diff --git a/extensions/void/package-lock.json b/extensions/void/package-lock.json index a7f8924e..cef3eea9 100644 --- a/extensions/void/package-lock.json +++ b/extensions/void/package-lock.json @@ -7,12 +7,10 @@ "": { "name": "void", "version": "0.0.1", - "dependencies": { - "@anthropic-ai/sdk": "^0.27.1", - "openai": "^4.57.0" - }, "devDependencies": { + "@anthropic-ai/sdk": "^0.29.2", "@eslint/js": "^9.9.1", + "@monaco-editor/react": "^4.6.0", "@types/diff": "^5.2.2", "@types/diff-match-patch": "^1.0.36", "@types/jest": "^29.5.12", @@ -36,6 +34,7 @@ "globals": "^15.9.0", "marked": "^14.1.0", "ollama": "^0.5.9", + "openai": "^4.68.1", "postcss": "^8.4.41", "posthog-js": "^1.174.0", "react": "^18.3.1", @@ -66,9 +65,10 @@ } }, "node_modules/@anthropic-ai/sdk": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.27.3.tgz", - "integrity": "sha512-IjLt0gd3L4jlOfilxVXTifn42FnVffMgDC04RJK1KDZpmkBWLv0XC92MVVmkxrFZNS/7l3xWgP/I3nqtX1sQHw==", + "version": "0.29.2", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.29.2.tgz", + "integrity": "sha512-5dwiOPO/AZvhY4bJIG9vjFKU9Kza3hA6VEsbIQg6L9vny2RQIpCFhV50nB9IrG2edZaHZb4HuQ9Wmsn5zgWyZg==", + "dev": true, "license": "MIT", "dependencies": { "@types/node": "^18.11.18", @@ -84,6 +84,7 @@ "version": "18.19.50", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.50.tgz", "integrity": "sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==", + "dev": true, "license": "MIT", "dependencies": { "undici-types": "~5.26.4" @@ -93,6 +94,7 @@ "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, "license": "MIT" }, "node_modules/@babel/code-frame": { @@ -556,6 +558,34 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@monaco-editor/loader": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.4.0.tgz", + "integrity": "sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==", + "dev": true, + "license": "MIT", + "dependencies": { + "state-local": "^1.0.6" + }, + "peerDependencies": { + "monaco-editor": ">= 0.21.0 < 1" + } + }, + "node_modules/@monaco-editor/react": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.6.0.tgz", + "integrity": "sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@monaco-editor/loader": "^1.4.0" + }, + "peerDependencies": { + "monaco-editor": ">= 0.25.0 < 1", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -728,6 +758,7 @@ "version": "22.6.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.6.1.tgz", "integrity": "sha512-V48tCfcKb/e6cVUigLAaJDAILdMP0fUW6BidkPK4GpGjXcfbnoHasCZDwz3N3yVt5we2RHm4XTQCpv0KJz9zqw==", + "dev": true, "license": "MIT", "dependencies": { "undici-types": "~6.19.2" @@ -737,6 +768,7 @@ "version": "2.6.11", "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", + "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", @@ -1068,6 +1100,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, "license": "MIT", "dependencies": { "event-target-shim": "^5.0.0" @@ -1116,6 +1149,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "dev": true, "license": "MIT", "dependencies": { "humanize-ms": "^1.2.1" @@ -1353,6 +1387,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, "license": "MIT" }, "node_modules/autoprefixer": { @@ -1920,6 +1955,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -2163,6 +2199,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -2821,6 +2858,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -3088,6 +3126,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -3102,6 +3141,7 @@ "version": "1.7.2", "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==", + "dev": true, "license": "MIT" }, "node_modules/format": { @@ -3117,6 +3157,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", + "dev": true, "license": "MIT", "dependencies": { "node-domexception": "1.0.0", @@ -3614,6 +3655,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, "license": "MIT", "dependencies": { "ms": "^2.0.0" @@ -5292,6 +5334,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -5301,6 +5344,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -5532,10 +5576,19 @@ "node": ">=10" } }, + "node_modules/monaco-editor": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.0.tgz", + "integrity": "sha512-OeWhNpABLCeTqubfqLMXGsqf6OmPU6pHM85kF3dhy6kq5hnhuVS1p3VrEW/XhWHc71P2tHyS5JFySD8mgs1crw==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, "license": "MIT" }, "node_modules/mz": { @@ -5580,6 +5633,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "dev": true, "funding": [ { "type": "github", @@ -5599,6 +5653,7 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" @@ -5793,9 +5848,10 @@ } }, "node_modules/openai": { - "version": "4.63.0", - "resolved": "https://registry.npmjs.org/openai/-/openai-4.63.0.tgz", - "integrity": "sha512-Y9V4KODbmrOpqiOmCDVnPfMxMqKLOx8Hwcdn/r8mePq4yv7FSXGnxCs8/jZKO7zCB/IVPWihpJXwJNAIOEiZ2g==", + "version": "4.68.1", + "resolved": "https://registry.npmjs.org/openai/-/openai-4.68.1.tgz", + "integrity": "sha512-C9XmYRHgra1U1G4GGFNqRHQEjxhoOWbQYR85IibfJ0jpHUhOm4/lARiKaC/h3zThvikwH9Dx/XOKWPNVygIS3g==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@types/node": "^18.11.18", @@ -5822,6 +5878,7 @@ "version": "18.19.50", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.50.tgz", "integrity": "sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==", + "dev": true, "license": "MIT", "dependencies": { "undici-types": "~5.26.4" @@ -5831,6 +5888,7 @@ "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, "license": "MIT" }, "node_modules/optionator": { @@ -7254,6 +7312,13 @@ "node": ">=8" } }, + "node_modules/state-local": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", + "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==", + "dev": true, + "license": "MIT" + }, "node_modules/stdin-discarder": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.1.0.tgz", @@ -7741,6 +7806,7 @@ "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, "license": "MIT" }, "node_modules/trim-lines": { @@ -7946,6 +8012,7 @@ "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, "license": "MIT" }, "node_modules/unified": { @@ -8152,6 +8219,7 @@ "version": "4.0.0-beta.3", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", + "dev": true, "license": "MIT", "engines": { "node": ">= 14" @@ -8168,6 +8236,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, "license": "BSD-2-Clause" }, "node_modules/whatwg-fetch": { @@ -8181,6 +8250,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, "license": "MIT", "dependencies": { "tr46": "~0.0.3", diff --git a/extensions/void/package.json b/extensions/void/package.json index 32d9b22e..acbf0266 100644 --- a/extensions/void/package.json +++ b/extensions/void/package.json @@ -24,7 +24,7 @@ }, { "command": "void.ctrl+k", - "title": "Show Selection Lens" + "title": "Make Inline Edit" }, { "command": "void.acceptDiff", @@ -101,14 +101,16 @@ } }, "scripts": { - "vscode:prepublish": "npm run compile", + "vscode:prepublish": "echo \"running prepublish\"", "watch": "tsc -watch -p ./", "build": "rimraf dist && node build-tsx.js && node build-css.js", "pretest": "tsc -p ./ && eslint src --ext ts", "test": "vscode-test" }, "devDependencies": { + "@anthropic-ai/sdk": "^0.29.2", "@eslint/js": "^9.9.1", + "@monaco-editor/react": "^4.6.0", "@types/diff": "^5.2.2", "@types/diff-match-patch": "^1.0.36", "@types/jest": "^29.5.12", @@ -132,6 +134,7 @@ "globals": "^15.9.0", "marked": "^14.1.0", "ollama": "^0.5.9", + "openai": "^4.68.1", "postcss": "^8.4.41", "posthog-js": "^1.174.0", "react": "^18.3.1", @@ -143,9 +146,5 @@ "typescript": "5.5.4", "typescript-eslint": "^8.3.0", "uuid": "^10.0.0" - }, - "dependencies": { - "@anthropic-ai/sdk": "^0.27.1", - "openai": "^4.57.0" } } diff --git a/extensions/void/src/SidebarWebviewProvider.ts b/extensions/void/src/SidebarWebviewProvider.ts index c8aaffba..0c2ed5a5 100644 --- a/extensions/void/src/SidebarWebviewProvider.ts +++ b/extensions/void/src/SidebarWebviewProvider.ts @@ -2,7 +2,7 @@ import * as vscode from 'vscode'; -function getNonce() { +function generateNonce() { let text = ""; const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; for (let i = 0; i < 32; i++) { @@ -39,7 +39,7 @@ export class SidebarWebviewProvider implements vscode.WebviewViewProvider { const scriptUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri, 'dist/sidebar/index.js')); const stylesUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri, 'dist/sidebar/styles.css')); const rootUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri)); - const nonce = getNonce(); + const nonce = generateNonce(); const webviewHTML = ` @@ -53,6 +53,7 @@ export class SidebarWebviewProvider implements vscode.WebviewViewProvider {
+
`; diff --git a/extensions/void/src/common/shared_types.ts b/extensions/void/src/common/shared_types.ts index 3c59f888..e7373266 100644 --- a/extensions/void/src/common/shared_types.ts +++ b/extensions/void/src/common/shared_types.ts @@ -41,6 +41,7 @@ type Diff = { // editor -> sidebar type MessageToSidebar = ( | { type: 'ctrl+l', selection: CodeSelection } // user presses ctrl+l in the editor + | { type: 'ctrl+k', selection: CodeSelection } | { type: 'files', files: { filepath: vscode.Uri, content: string }[] } | { type: 'partialVoidConfig', partialVoidConfig: PartialVoidConfig } | { type: 'allThreads', threads: ChatThreads } @@ -65,7 +66,8 @@ type MessageFromSidebar = ( type ChatThreads = { [id: string]: { id: string; // store the id here too - createdAt: string; + createdAt: string; // ISO string + lastModified: string; // ISO string messages: ChatMessage[]; } } diff --git a/extensions/void/src/extension.ts b/extensions/void/src/extension.ts index 961d585c..edd2f993 100644 --- a/extensions/void/src/extension.ts +++ b/extensions/void/src/extension.ts @@ -9,37 +9,60 @@ const readFileContentOfUri = async (uri: vscode.Uri) => { .replace(/\r\n/g, '\n') // replace windows \r\n with \n } +const roundRangeToLines = (selection: vscode.Selection) => { + return new vscode.Range(selection.start.line, 0, selection.end.line, Number.MAX_SAFE_INTEGER) +} + export function activate(context: vscode.ExtensionContext) { // 1. Mount the chat sidebar - const webviewProvider = new SidebarWebviewProvider(context); + const sidebarWebviewProvider = new SidebarWebviewProvider(context); context.subscriptions.push( - vscode.window.registerWebviewViewProvider(SidebarWebviewProvider.viewId, webviewProvider, { webviewOptions: { retainContextWhenHidden: true } }) + vscode.window.registerWebviewViewProvider(SidebarWebviewProvider.viewId, sidebarWebviewProvider, { webviewOptions: { retainContextWhenHidden: true } }) ); - // 2. Activate the sidebar on ctrl+l + // 2. ctrl+l context.subscriptions.push( vscode.commands.registerCommand('void.ctrl+l', () => { - const editor = vscode.window.activeTextEditor - if (!editor) - return + if (!editor) return // show the sidebar vscode.commands.executeCommand('workbench.view.extension.voidViewContainer'); // vscode.commands.executeCommand('vscode.moveViewToPanel', CustomViewProvider.viewId); // move to aux bar - // get the text the user is selecting - const selectionStr = editor.document.getText(editor.selection); - // get the range of the selection - const selectionRange = editor.selection; + const selectionRange = roundRangeToLines(editor.selection); + + // get the text the user is selecting + const selectionStr = editor.document.getText(selectionRange); // get the file the user is in const filePath = editor.document.uri; // send message to the webview (Sidebar.tsx) - webviewProvider.webview.then(webview => webview.postMessage({ type: 'ctrl+l', selection: { selectionStr, selectionRange, filePath } } satisfies MessageToSidebar)); + sidebarWebviewProvider.webview.then(webview => webview.postMessage({ type: 'ctrl+l', selection: { selectionStr, selectionRange, filePath } } satisfies MessageToSidebar)); + }) + ); + + // 2.5: ctrl+k + context.subscriptions.push( + vscode.commands.registerCommand('void.ctrl+k', () => { + console.log('CTRLK PRESSED') + const editor = vscode.window.activeTextEditor + if (!editor) return + + // get the range of the selection + const selectionRange = roundRangeToLines(editor.selection); + + // get the text the user is selecting + const selectionStr = editor.document.getText(selectionRange); + + // get the file the user is in + const filePath = editor.document.uri; + + // send message to the webview (Sidebar.tsx) + sidebarWebviewProvider.webview.then(webview => webview.postMessage({ type: 'ctrl+k', selection: { selectionStr, selectionRange, filePath } } satisfies MessageToSidebar)); }) ); @@ -56,7 +79,7 @@ export function activate(context: vscode.ExtensionContext) { })); // 5. Receive messages from sidebar - webviewProvider.webview.then( + sidebarWebviewProvider.webview.then( webview => { // top navigation bar commands @@ -83,7 +106,8 @@ export function activate(context: vscode.ExtensionContext) { // send contents to webview webview.postMessage({ type: 'files', files, } satisfies MessageToSidebar) - } else if (m.type === 'applyChanges') { + } + else if (m.type === 'applyChanges') { const editor = vscode.window.activeTextEditor if (!editor) { diff --git a/extensions/void/src/sidebar/CtrlK.tsx b/extensions/void/src/sidebar/CtrlK.tsx new file mode 100644 index 00000000..89797e3e --- /dev/null +++ b/extensions/void/src/sidebar/CtrlK.tsx @@ -0,0 +1,20 @@ +import React, { useState } from 'react'; +import { useOnVSCodeMessage } from './getVscodeApi'; + + +export const CtrlK = () => { + + const [x, sx] = useState('abc') + + useOnVSCodeMessage('ctrl+k', () => { + console.log('Ctrl+K pressed') + sx('Pressed ctrl+k') + }) + + return <> +
+ {x} +
+ +}; + diff --git a/extensions/void/src/sidebar/Sidebar.tsx b/extensions/void/src/sidebar/Sidebar.tsx index d27283c8..e0ed5906 100644 --- a/extensions/void/src/sidebar/Sidebar.tsx +++ b/extensions/void/src/sidebar/Sidebar.tsx @@ -5,58 +5,45 @@ import { awaitVSCodeResponse, getVSCodeAPI, onMessageFromVSCode, useOnVSCodeMess import { SidebarThreadSelector } from "./SidebarThreadSelector"; import { SidebarChat } from "./SidebarChat"; import { SidebarSettings } from './SidebarSettings'; -import { identifyUser, useMetrics } from "./metrics/posthog"; +import { identifyUser } from "./metrics/posthog"; const Sidebar = () => { - useMetrics() - - // when we get the deviceid, identify the user - useEffect(() => { - getVSCodeAPI().postMessage({ type: 'getDeviceId' }); - awaitVSCodeResponse('deviceId').then((m => { - identifyUser(m.deviceId) - })) - }, []) - + const chatInputRef = useRef(null) const [tab, setTab] = useState<'threadSelector' | 'chat' | 'settings'>('chat') // if they pressed the + to add a new chat - useOnVSCodeMessage('startNewThread', (m) => { setTab('chat') }) + useOnVSCodeMessage('startNewThread', (m) => { + setTab('chat'); + chatInputRef.current?.focus(); + }) // ctrl+l should switch back to chat - useOnVSCodeMessage('ctrl+l', (m) => { setTab('chat') }) + useOnVSCodeMessage('ctrl+l', (m) => { + setTab('chat'); + chatInputRef.current?.focus(); + }) // if they toggled thread selector useOnVSCodeMessage('toggleThreadSelector', (m) => { - if (tab === 'threadSelector') + if (tab === 'threadSelector') { setTab('chat') - else + chatInputRef.current?.blur(); + } else setTab('threadSelector') }) // if they toggled settings useOnVSCodeMessage('toggleSettings', (m) => { - if (tab === 'settings') + if (tab === 'settings') { setTab('chat') - else + chatInputRef.current?.blur(); + } else setTab('settings') }) - // Receive messages from the VSCode extension - useEffect(() => { - const listener = (event: MessageEvent) => { - const m = event.data as MessageToSidebar; - onMessageFromVSCode(m) - } - window.addEventListener('message', listener); - return () => { window.removeEventListener('message', listener) } - }, []) - - - return <>
@@ -65,7 +52,7 @@ const Sidebar = () => {
- +
diff --git a/extensions/void/src/sidebar/SidebarChat.tsx b/extensions/void/src/sidebar/SidebarChat.tsx index cdb8ae91..b7280b33 100644 --- a/extensions/void/src/sidebar/SidebarChat.tsx +++ b/extensions/void/src/sidebar/SidebarChat.tsx @@ -4,7 +4,6 @@ import React, { FormEvent, useCallback, useEffect, useRef, useState } from "reac import { marked } from 'marked'; import MarkdownRender from "./markdown/MarkdownRender"; import BlockCode from "./markdown/BlockCode"; -import { SelectedFiles } from "./components/SelectedFiles"; import { File, ChatMessage, CodeSelection } from "../common/shared_types"; import * as vscode from 'vscode' import { awaitVSCodeResponse, getVSCodeAPI, onMessageFromVSCode, useOnVSCodeMessage } from "./getVscodeApi"; @@ -63,6 +62,55 @@ Please edit the selected code following these instructions: return str; }; + + + + +const getBasename = (pathStr: string) => { + // "unixify" path + pathStr = pathStr.replace(/[/\\]+/g, "/") // replace any / or \ or \\ with / + const parts = pathStr.split("/") // split on / + return parts[parts.length - 1] +} + +export const SelectedFiles = ({ files, setFiles, }: { files: vscode.Uri[], setFiles: null | ((files: vscode.Uri[]) => void) }) => { + return ( + files.length !== 0 && ( +
+ {files.map((filename, i) => ( + + ))} +
+ ) + ) +} + + const ChatBubble = ({ chatMessage }: { chatMessage: ChatMessage }) => { const role = chatMessage.role @@ -76,16 +124,17 @@ const ChatBubble = ({ chatMessage }: { chatMessage: ChatMessage }) => { if (role === 'user') { chatbubbleContents = <> - {chatMessage.selection?.selectionStr && } + {chatMessage.selection?.selectionStr && } {children} } else if (role === 'assistant') { - chatbubbleContents = // sectionsHTML } - return
{chatbubbleContents} @@ -95,7 +144,7 @@ const ChatBubble = ({ chatMessage }: { chatMessage: ChatMessage }) => { -export const SidebarChat = () => { +export const SidebarChat = ({ chatInputRef }: { chatInputRef: React.RefObject }) => { // state of current message @@ -224,8 +273,8 @@ export const SidebarChat = () => { abortFnRef.current?.() // if messageStream was not empty, add it to the history - const llmContent = messageStream || '(canceled)' - const newHistoryElt: ChatMessage = { role: 'assistant', displayContent: messageStream, content: llmContent } + const llmContent = messageStream || '(null)' + const newHistoryElt: ChatMessage = { role: 'assistant', content: llmContent, displayContent: messageStream, } addMessageToHistory(newHistoryElt) setMessageStream('') @@ -233,14 +282,9 @@ export const SidebarChat = () => { }, [captureChatEvent, messageStream, addMessageToHistory]) - //Clear code selection - const clearSelection = () => { - setSelection(null); - }; - return <> -
+
{/* previous messages */} {currentThread !== null && currentThread.messages.map((message, i) => @@ -261,14 +305,15 @@ export const SidebarChat = () => { {/* selected code */} {!!selection?.selectionStr && ( - - Remove - - )} /> + setSelection(null)} + className="btn btn-secondary btn-sm border border-vscode-input-border rounded" + > + Remove + + )} /> )}
} @@ -284,6 +329,7 @@ export const SidebarChat = () => { {/* input */}