summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorFrank <[email protected]>2025-07-22 15:28:09 -0400
committerFrank <[email protected]>2025-07-22 15:28:09 -0400
commit26a40610ddbb9eaf77c8df4eaf4466a3e04bfa0e (patch)
tree06eb914c34184b55c3de5d68db3f0f399993e216
parentdb2fbed691f3b69dc3cbc1c94c68309e8755ead2 (diff)
downloadopencode-26a40610ddbb9eaf77c8df4eaf4466a3e04bfa0e.tar.gz
opencode-26a40610ddbb9eaf77c8df4eaf4466a3e04bfa0e.zip
wip: vscode extension
-rw-r--r--sdks/vscode/src/extension.ts130
1 files changed, 85 insertions, 45 deletions
diff --git a/sdks/vscode/src/extension.ts b/sdks/vscode/src/extension.ts
index f4daeb10b..de10db54d 100644
--- a/sdks/vscode/src/extension.ts
+++ b/sdks/vscode/src/extension.ts
@@ -1,70 +1,110 @@
// This method is called when your extension is deactivated
export function deactivate() {}
-import * as vscode from "vscode";
+import * as vscode from "vscode"
export function activate(context: vscode.ExtensionContext) {
- const TERMINAL_NAME = "opencode Terminal";
-
// Register command to open terminal in split screen and run opencode
let openTerminalDisposable = vscode.commands.registerCommand("opencode.openTerminal", async () => {
// Create a new terminal in split screen
+ const port = Math.floor(Math.random() * (65535 - 16384 + 1)) + 16384
const terminal = vscode.window.createTerminal({
- name: TERMINAL_NAME,
+ name: "opencode",
+ iconPath: {
+ light: vscode.Uri.file(context.asAbsolutePath("images/button-dark.svg")),
+ dark: vscode.Uri.file(context.asAbsolutePath("images/button-light.svg")),
+ },
location: {
viewColumn: vscode.ViewColumn.Beside,
preserveFocus: false,
},
- });
+ env: {
+ _EXTENSION_OPENCODE_PORT: port.toString(),
+ },
+ })
+
+ terminal.show(false)
+ terminal.sendText(`OPENCODE_THEME=system OPENCODE_CALLER=vscode opencode --port ${port}`)
+
+ const fileRef = getActiveFile()
+ if (!fileRef) return
- terminal.show();
- terminal.sendText("OPENCODE_THEME=system OPENCODE_CALLER=vscode opencode");
- });
+ // Wait for the terminal to be ready
+ let tries = 10
+ let connected = false
+ do {
+ await new Promise((resolve) => setTimeout(resolve, 200))
+ try {
+ await fetch(`http://localhost:${port}/app`)
+ connected = true
+ break
+ } catch (e) {}
+
+ tries--
+ } while (tries > 0)
+
+ // If connected, append the prompt to the terminal
+ if (connected) {
+ await appendPrompt(port, `In ${fileRef}`)
+ }
+ })
// Register command to add filepath to terminal
let addFilepathDisposable = vscode.commands.registerCommand("opencode.addFilepathToTerminal", async () => {
- const activeEditor = vscode.window.activeTextEditor;
+ const fileRef = getActiveFile()
+ if (!fileRef) return
- if (!activeEditor) {
- vscode.window.showInformationMessage("No active file to get path from");
- return;
- }
+ const terminal = vscode.window.activeTerminal
+ if (!terminal) return
- const document = activeEditor.document;
- const workspaceFolder = vscode.workspace.getWorkspaceFolder(document.uri);
+ // @ts-ignore
+ const port = terminal.creationOptions.env?.["_EXTENSION_OPENCODE_PORT"]
+ if (!port) return
- if (!workspaceFolder) {
- vscode.window.showInformationMessage("File is not in a workspace");
- return;
- }
+ await appendPrompt(parseInt(port), fileRef)
+ terminal.show()
+ })
- // Get the relative path from workspace root
- const relativePath = vscode.workspace.asRelativePath(document.uri);
- let filepathWithAt = `@${relativePath}`;
-
- // Check if there's a selection and add line numbers
- const selection = activeEditor.selection;
- if (!selection.isEmpty) {
- // Convert to 1-based line numbers
- const startLine = selection.start.line + 1;
- const endLine = selection.end.line + 1;
-
- if (startLine === endLine) {
- // Single line selection
- filepathWithAt += `#L${startLine}`;
- } else {
- // Multi-line selection
- filepathWithAt += `#L${startLine}-${endLine}`;
- }
- }
+ context.subscriptions.push(openTerminalDisposable, addFilepathDisposable)
+}
+
+async function appendPrompt(port: number, text: string) {
+ await fetch(`http://localhost:${port}/tui/append-prompt`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({ text }),
+ })
+}
+
+function getActiveFile() {
+ const activeEditor = vscode.window.activeTextEditor
+ if (!activeEditor) return
+
+ const document = activeEditor.document
+ const workspaceFolder = vscode.workspace.getWorkspaceFolder(document.uri)
+ if (!workspaceFolder) return
+
+ // Get the relative path from workspace root
+ const relativePath = vscode.workspace.asRelativePath(document.uri)
+ let filepathWithAt = `@${relativePath}`
+
+ // Check if there's a selection and add line numbers
+ const selection = activeEditor.selection
+ if (!selection.isEmpty) {
+ // Convert to 1-based line numbers
+ const startLine = selection.start.line + 1
+ const endLine = selection.end.line + 1
- // Get or create terminal
- let terminal = vscode.window.activeTerminal;
- if (terminal?.name === TERMINAL_NAME) {
- terminal.sendText(filepathWithAt);
- terminal.show();
+ if (startLine === endLine) {
+ // Single line selection
+ filepathWithAt += `#L${startLine}`
+ } else {
+ // Multi-line selection
+ filepathWithAt += `#L${startLine}-${endLine}`
}
- });
+ }
- context.subscriptions.push(openTerminalDisposable, addFilepathDisposable);
+ return filepathWithAt
}