diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 481d0899..7ca1f64d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,6 +11,9 @@ on: lsp_branch: description: "Branch name of lsp" default: "main" + chat_js_branch: + description: "Branch name of chat-js" + default: "main" jobs: dist: @@ -57,23 +60,44 @@ jobs: with: fetch-depth: ${{ env.FETCH_DEPTH }} - - name: Download artifact - id: download-artifact + - name: Download lsp artifacts + id: download-artifact-lsp uses: dawidd6/action-download-artifact@v3 with: github_token: ${{secrets.GITHUB_TOKEN}} - workflow: build.yml - repo: smallcloudai/refact-lsp + workflow: agent_engine_build.yml + repo: smallcloudai/refact branch: ${{ inputs.lsp_branch }} path: ./assets name: dist-${{ matrix.target }} + + - name: Download chat artifacts + id: download-artifact-chat + uses: dawidd6/action-download-artifact@v9 + with: + github_token: ${{secrets.GITHUB_TOKEN}} + workflow: agent_gui_build.yml + repo: smallcloudai/refact + branch: ${{ inputs.chat_js_branch }} + path: ./chat_package + name: lts-refact-chat-js-.*\.tgz + name_is_regexp: true + + - name: Prepare chat package + shell: bash + run: | + mkdir -p ./chat_package_fixed + find ./chat_package -name "*.tgz" -type f -exec cp {} ./chat_package_fixed/ \; + ls -la ./chat_package_fixed - name: Install VSCE + shell: bash run: | - npm install + npm install ./chat_package_fixed/*.tgz npm install -g @vscode/vsce + rm -rf ./chat_package ./chat_package_fixed - - name: Pakckage VSCE extension + - name: Package VSCE extension run: | chmod +x ./assets/refact-lsp* vsce package --target ${{ matrix.code-target }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index e6292d17..a487334f 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -6,6 +6,9 @@ on: lsp_branch: description: "Branch name of lsp" default: "main" + chat_js_branch: + description: "Branch name of chat-js" + default: "main" stable_release: description: "Publish stable release version" default: false @@ -56,21 +59,42 @@ jobs: with: fetch-depth: ${{ env.FETCH_DEPTH }} - - name: Install VSCE - run: | - npm install - npm install -g @vscode/vsce - - - name: Download artifact - id: download-artifact + - name: Download lsp artifacts + id: download-artifact-lsp uses: dawidd6/action-download-artifact@v3 with: github_token: ${{secrets.GITHUB_TOKEN}} - workflow: build.yml - repo: smallcloudai/refact-lsp + workflow: agent_engine_build.yml + repo: smallcloudai/refact branch: ${{ inputs.lsp_branch }} path: ./assets name: dist-${{ matrix.target }} + + - name: Download chat artifacts + id: download-artifact-chat + uses: dawidd6/action-download-artifact@v9 + with: + github_token: ${{secrets.GITHUB_TOKEN}} + workflow: agent_gui_build.yml + repo: smallcloudai/refact + branch: ${{ inputs.chat_js_branch }} + path: ./chat_package + name: lts-refact-chat-js-.*\.tgz + name_is_regexp: true + + - name: Prepare chat package + shell: bash + run: | + mkdir -p ./chat_package_fixed + find ./chat_package -name "*.tgz" -type f -exec cp {} ./chat_package_fixed/ \; + ls -la ./chat_package_fixed + + - name: Install VSCE + shell: bash + run: | + npm install ./chat_package_fixed/*.tgz + npm install -g @vscode/vsce + rm -rf ./chat_package ./chat_package_fixed - name: Package VSCE extension shell: bash @@ -97,6 +121,7 @@ jobs: prerelease: ${{ !inputs.stable_release }} tag: v${{ steps.get_version.outputs.version }} # Use the version from previous step with 'v' prefix overwrite: true + target_commit: ${{ github.sha }} file_glob: true - name: Publish VSCE extension diff --git a/README.md b/README.md index d10975c9..3c6c1bc8 100644 --- a/README.md +++ b/README.md @@ -8,47 +8,91 @@ [![Twitter Follow](https://img.shields.io/twitter/follow/refact_ai)](https://twitter.com/intent/follow?screen_name=refact_ai) ![License](https://img.shields.io/github/license/smallcloudai/refact-vscode) -## Refact.ai Open Source, Customizable AI Coding Assistant -Refact.ai is an open-source AI coding assistant that boosts developer's productivity. It's suitable for both individual and enterprise use, supporting 25+ programming languages including Python, Javascript, Java, Rust, Typescript, PHP, Java, C++, C#, Go and more. - -Download the extension for VS Code from [here](https://marketplace.visualstudio.com/items?itemName=smallcloud.codify). - -Simplify your coding experience with Refact.ai's functions: - -- **Code-completion:** helps you write code faster. It looks up and down from the cursor position in the current file, as well as other files in your project for context. After fine-tuning (available in Self-Hosting and Enterprise versions) a code completion model will provide you with more relevant suggestions: it can memorize your coding style, the right way to use your internal APIs, and the tech stack you use. -- **AI Toolbox:** helps explain, refactor your code, write documentation, find bugs, you can ask in natural language to generate new code for you. The Toolbox is customizable, you can create your own commands. -- **Integrated in-IDE Chat:** It's better than switching between IDE and a browser: select a piece of code in the editor, ask a question without the need to copy-paste anything, and apply changes back as a diff. Chat can either automatically include the relevant files within the project for context, or you can use @-commands to control what context to use to answer your question. -- **Self-hosting or cloud version:** enables you to host code completion and chat models yourself. The Refact.ai self-hosting server supports many recent models, offers efficient inference, and facilitates fine-tuning. - -## Refact.ai For Enterprise -Are you part of an Enterprise and want to **boost developers' efficiency by 45%**? The Refact.ai Enterprise plan offers: -- **Knows Your Code:** Refact.ai focuses on automated customization for internal codebases and improving over time. -- **Ultimate Security:** Deploy Refact.ai on-premise: on your own servers or private cloud. Your data never leaves your control. Telemetry from the plugins goes to your server and nowhere else. You can verify what the code does, it's open source. -- **Fine-Tuning:** We've solved all the complexity for you, no data engineer required. A fine-tuned code completion model will provide you with more relevant suggestions: it can memorize your coding style, the right way to use your internal APIs, and the tech stack you use. After fine-tuning, auto-completion helps our clients to write around 45% of their code. -- **User Statistics:** Keep track of how much code Refact.ai helps to write for each team member. Measure productivity gains with real numbers. -- **Efficient Inference:** The Enterprise version supports paged attention and continuous batching, supporting up to 50 engineers per GPU for code completion. +## Refact.ai - Your Customizable Open-Source AI Software Engineering Agent + +Refact.ai is a free, **open-source** AI Agent that handles engineering tasks end-to-end. It deeply understands your codebases and integrates with your tools, databases, and browsers to automate complex, multi-step tasks. + +- Integrate AI Agent with the tools you already use, allowing it to complete tasks for you end-to-end. +- Deploy Refact.ai on-premise and maintain **100% control over your codebase**. +- Access State-of-the-Art Models (Claude 3.5 Sonnet, GPT-4o, o3-mini, etc.) +- Bring your own key (BYOK) - Use your own API keys for external LLMs. +- Stop switching between your IDE and chat—Refact.ai has an integrated chat right in your IDE. +- Get free, unlimited, context-aware auto-completion. + +Suitable for both individual and enterprise use, supporting 25+ programming languages, including Python, JavaScript, Java, Rust, TypeScript, PHP, C++, C#, Go, and more. + +We can't say it better than our users: *'Refact.ai understands me better than my human coworkers. It's like working in perfect sync with an ideal partner.'* + +## How does Refact.ai Agent empower developers? + +- **Unlimited accurate auto-completion with context awareness for free** - Powered by Qwen2.5-Coder-1.5B, Refact.ai uses Retrieval-Augmented Generation (RAG) to provide precise, context-aware code suggestions. By retrieving relevant snippets and project-specific insights, it ensures completions that align with your coding style and architecture.![auto-completion](https://github.com/user-attachments/assets/0ffab638-c807-4863-8d62-a663b1459805) +- **Integrated in-IDE Chat** - By deeply understanding your codebases, Refact.ai provides relevant, intelligent answers to your questions—right inside your development environment.![refactor](https://github.com/user-attachments/assets/e7b2e779-85c5-46a0-99ad-ea909a69ddc7) +- **Integrated with the tools** - Refact.ai goes beyond codebases, connecting with GitHub, GitLab, databases (PostgreSQL, MySQL), Pdb, Docker, and any shell command, so AI Agent can autonomously complete tasks—from code generation to deployment.![integrations](https://github.com/user-attachments/assets/daf8d0ee-0a54-4aa8-82e5-f968fded0c7a) +- **State-of-the-Art Models** - Refact.ai supports **Claude 3.5 Sonnet, GPT-4o, and o3-mini**, allowing you to choose the best model for each task based on its complexity. +- **Bring your own key (BYOK)** - Use your own API keys for external LLMs, ensuring flexibility and control over your AI infrastructure.![BYOK](https://github.com/user-attachments/assets/44e416f7-fb4d-4846-a1e0-1b7da32c2c75) +- **Upload images**: Click the image button to add visual context to your chat. +- **Use @-commands** to control what context to use to answer your question: + - **@web** - define a webpage. + - **@file** - upload and attach a single file. + - **@definition** - find and attach a definition. + - **@references** - locate all references and attach them. + - **@tree** - display the workspace directory and files tree. + - Create your own **custom system prompt** for a more personalized workflow.![@-commands](https://github.com/user-attachments/assets/28e1db76-3490-4195-a3e0-de30496239a9) + +## Refact.ai Agent For Enterprise +Deploying Refact.ai Agent is like adding a 24/7 engineer to your team—one that instantly understands your codebase, adapts to your workflows, accelerates development from day one, and becomes a shared knowledge base for your entire team. + +1. **Refact.ai already understands your company's context:** AI Agent captures the unique structure, tools, and workflows of your organization, using your company's databases, documentation, and code architecture to deliver customized solutions. +2. **Gets smarter over time:** With each interaction and feedback, Refact.ai Agent adapts to your organization's needs, becoming more accurate and powerful. +3. **Organizes experience into the knowledge base:** Refact.ai Agent captures and shares knowledge from interactions with each team member. It not only streamlines workflows but also supports faster onboarding and smoother cross-functional collaboration across projects. + +### Take full control of your AI Agent, tailored to your company: +- **Deploy Refact.ai on-premise:** on your own servers or private cloud. Your data never leaves your control. Telemetry from the plugins goes to your server and nowhere else. You can verify what the code does, it's open source. +- **Fine-tune a model on your codebase:** A fine-tuned code completion model will provide you with more relevant suggestions: it can memorize your coding style, the right way to use your internal APIs, and the tech stack you use. - **Priority Support:** Our engineers are always available to assist you at every stage, from setup to fine-tuning and beyond. -- **Access to 20+ LLMs:** (including Refact/1.6B, GPT-4, Code Llama, StarCoder2, Mistral, Mixtral, etc.) some of them with the opportunity to fine-tune. - -**To get a 2-Week free trial** for your team, just fill out the form on [our website](https://refact.ai/enterprise/?utm_source=vscode&utm_medium=marketplace&utm_campaign=enterprise). We'll reach out with more details! - -## Check Out How Easy Refact.ai Is to Use -### Boost coding productivity with fine-tuned auto-completions -![Comp_brand](https://github.com/smallcloudai/refact-vscode/assets/15157041/59bd60e2-4680-4bf5-87c5-6f57dc96cef7) - - -### Get the answer to your question in the embedded Chat -![Chat_brand](https://github.com/smallcloudai/refact-vscode/assets/15157041/7e10a353-bb6f-4c79-b65e-c01a7ab6aece) - -### Just highlight part of the code and ask Toolbox to explain it -![Explain_brand](https://github.com/smallcloudai/refact-vscode/assets/15157041/a5f8519f-284f-43c7-9cce-163dbac86ef7) - -### Ask Toolbox to shorten your code -![Shorter_brand](https://github.com/smallcloudai/refact-vscode/assets/15157041/d3724ac7-076c-43d6-a300-2617952ebc8e) +**To get a 2-week free trial** for your team, just fill out the form on [our website](https://refact.ai/contact/?utm_source=vscode&utm_medium=marketplace&utm_campaign=enterprise). We'll reach out with more details! +\ +  +\ +  +## Which tasks can Refact.ai help me with? + +- **Generate code from natural language prompts (even if you make typos)** - Instantly turn ideas into functional code, accelerating development and eliminating the blank-screen problem. +\ +  + ![gen](https://github.com/user-attachments/assets/ef4acec7-4967-400a-900e-9d3382d05b1b) +\ +  +- **Refactor code** - Improve code quality, readability, and efficiency with automated refactoring that aligns with best practices. +\ +  + ![refactor](https://github.com/user-attachments/assets/2cae4467-f363-4033-8ecf-2854dcc74aaa) +\ +  +- **Explain code** - Quickly understand complex or unfamiliar code with AI-generated explanations, making collaboration and onboarding faster. +\ +  +![explain](https://github.com/user-attachments/assets/bd43d9aa-15c9-49dc-9fa9-b5ab5c4ecdfe) +\ +  +- **Debug code** - Detect and fix errors faster with intelligent debugging, reducing time spent troubleshooting issues. +\ +  +![ddbg](https://github.com/user-attachments/assets/45e917b5-f47b-4b84-b1f4-f4918c8a00c7) +\ +  +- **Generate unit tests** - Ensure code reliability by automatically creating comprehensive unit tests. +\ +  + ![unit](https://github.com/user-attachments/assets/5168ee57-e35b-4484-bf19-70cc0f3a6299) +\ +  + +- **Code Review** - Get AI-assisted code reviews for cleaner, more secure, and more efficient code, addressing developers' top concern: accuracy. +- **Create Documentation** - Automate documentation generation to keep knowledge accessible and up to date. +- **Generate Docstrings** - Enhance maintainability with clear, structured documentation generated for functions and classes in seconds. ## Join Our Discord Community -Connect with other developers who care about AI tools in our [**Discord community**](https://www.smallcloud.ai/discord). Ask questions, share your opinion, propose new features. - -Implement a feature you want, and contribute to the future of programming! +Connect with other developers in our [Discord community](https://www.smallcloud.ai/discord). Ask questions, share your opinion, propose new features. diff --git a/package.json b/package.json index f5836ec3..9b283451 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "codify", - "displayName": "Refact", - "description": "Refact AI Assistant for Code Writing and Refactoring", + "displayName": "Refact – Open-Source AI Agent, Code Generator & Chat for JavaScript, Python, TypeScript, Java, PHP, Go, and more.", + "description": "Refact.ai is a free, open-source AI Agent that adapts to your workflow. It tracks your cursor to provide instant assistance, connects with tools, databases and browsers, works with debuggers, and runs shell commands. As your AI copilot, it handles code generation, testing, review, and refactoring.", "publisher": "smallcloud", "icon": "logo-small.png", "galleryBanner": { @@ -18,7 +18,7 @@ "url": "https://github.com/smallcloudai/refact-vscode/issues", "email": "support@smallcloud.tech" }, - "version": "6.1.0", + "version": "6.2.1", "dependencies": { "@types/marked": "^4.0.8", "@types/vscode": "^1.69.0", @@ -27,7 +27,7 @@ "fetch-h2": "^3.0.2", "json5": "^2.2.3", "marked": "^4.0.8", - "refact-chat-js": "~v2.0.5", + "refact-chat-js": "^2.0.10-alpha.2", "uuid": "^9.0.1", "vscode-languageclient": "^7.0.0" }, @@ -57,7 +57,9 @@ "Machine Learning", "Education", "Testing", - "Data Science" + "Data Science", + "AI", + "Chat" ], "keywords": [ "refact", @@ -95,14 +97,12 @@ "react", "swift", "objective-c", - "objectivec", "ai", "method completion", "intellicode", "intellisense", "snippets", "kite", - "nodejs", "node", "node.js", "jupyter", @@ -114,7 +114,9 @@ "llm", "test", "security", - "coding" + "coding", + "copilot", + "cursor" ], "activationEvents": [ "onStartupFinished" diff --git a/src/extension.ts b/src/extension.ts index bf502db6..185f8a49 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -89,6 +89,7 @@ async function pressed_escape() } if (editor) { let state = estate.state_of_editor(editor, "pressed_escape"); + global.side_panel?.toolEditChange(editor.document.uri.fsPath, false); if (state) { state.diff_lens_pos = Number.MAX_SAFE_INTEGER; state.completion_lens_pos = Number.MAX_SAFE_INTEGER; diff --git a/src/interactiveDiff.ts b/src/interactiveDiff.ts index f8e0d7f0..884529d8 100644 --- a/src/interactiveDiff.ts +++ b/src/interactiveDiff.ts @@ -589,6 +589,8 @@ export async function like_and_accept(editor: vscode.TextEditor) // dataCollection.data_feedback_candidate_reset(state); }); await thenable; + global.side_panel?.toolEditChange(editor.document.uri.fsPath, true); + await editor.document.save(); } diff --git a/src/sidebar.ts b/src/sidebar.ts index 804ad0af..b90b1ffd 100644 --- a/src/sidebar.ts +++ b/src/sidebar.ts @@ -23,17 +23,17 @@ import { ideNewFileAction, ideOpenSettingsAction, ideDiffPasteBackAction, - ideDiffPreviewAction, type ChatThread, - type DiffPreviewResponse, - resetDiffApi, ideAnimateFileStart, ideAnimateFileStop, - ideWriteResultsToFile, - type PatchResult, ideChatPageChange, ideEscapeKeyPressed, ideIsChatStreaming, + setCurrentProjectInfo, + ideToolCall, + ToolEditResult, + ideToolCallResponse, + TextDocToolCall, } from "refact-chat-js/dist/events"; import { basename, join } from "path"; import { diff_paste_back } from "./chatTab"; @@ -68,6 +68,9 @@ export async function open_chat_tab( {role: "user", content: question}, ] : [], model: model, + new_chat_suggested: { + wasSuggested: false, + } }; global.side_panel.goto_chat(chat); // changes html @@ -85,6 +88,7 @@ export class PanelWebview implements vscode.WebviewViewProvider { public chat: chatTab.ChatTab | null = null; public statistic: statisticTab.StatisticTab | null = null; + public tool_edit_in_progress: null | {chatId: string, toolCallId?: string} = null; // public fim_debug: fimDebug.FimDebug | null = null; // public chatHistoryProvider: ChatHistoryProvider|undefined; @@ -119,6 +123,10 @@ export class PanelWebview implements vscode.WebviewViewProvider { } })); + this._disposables.push(vscode.workspace.onDidChangeWorkspaceFolders((event) => { + this.sendCurrentProjectInfo(); + })); + // this._disposables.push(vscode.workspace.onDidOpenTextDocument((event) => { // console.log("onDidOpenTextDocument"); @@ -176,10 +184,8 @@ export class PanelWebview implements vscode.WebviewViewProvider { const fileName = basename(filePath); - const indentedCode = this.trimIndent(code); - return { - code: indentedCode, + code: code, language, path: filePath, basename: fileName @@ -262,10 +268,7 @@ export class PanelWebview implements vscode.WebviewViewProvider { this._view?.webview.postMessage(message); } - sendClearDiffCacheMessage() { - const message = resetDiffApi(); - this._view?.webview.postMessage(message); - } + public new_statistic(view: vscode.WebviewView) @@ -537,12 +540,10 @@ export class PanelWebview implements vscode.WebviewViewProvider { } if(ideDiffPasteBackAction.match(e)) { - return this.handleDiffPasteBack(e.payload); + this.tool_edit_in_progress = e.payload.chatId ? {chatId: e.payload.chatId, toolCallId: e.payload.toolCallId} : null; + return this.handleDiffPasteBack(e.payload.content); } - if (ideDiffPreviewAction.match(e)) { - return this.handleDiffPreview(e.payload); - } if(ideAnimateFileStart.match(e)) { return this.startFileAnimation(e.payload); @@ -552,10 +553,6 @@ export class PanelWebview implements vscode.WebviewViewProvider { return this.stopFileAnimation(e.payload); } - if(ideWriteResultsToFile.match(e)) { - return this.writeResultsToFile(e.payload); - } - if(ideChatPageChange.match(e)) { return this.handleCurrentChatPage(e.payload); } @@ -568,6 +565,10 @@ export class PanelWebview implements vscode.WebviewViewProvider { return this.handleEscapePressed(e.payload); } + if(ideToolCall.match(e)) { + this.tool_edit_in_progress = {chatId: e.payload.chatId, toolCallId: e.payload.toolCall.id}; + return this.handleToolEdit(e.payload.toolCall, e.payload.edit); + } // if(ideOpenChatInNewTab.match(e)) { // return this.handleOpenInTab(e.payload); // } @@ -600,6 +601,16 @@ export class PanelWebview implements vscode.WebviewViewProvider { // } + async handleToolEdit(toolCall: TextDocToolCall, toolEdit: ToolEditResult) { + if(!toolEdit.file_before && toolEdit.file_after) { + return this.createNewFileWithContent(toolCall.function.arguments.path, toolEdit.file_after); + } + + return this.addDiffToFile(toolCall.function.arguments.path, toolEdit.file_after); + } + + + // This isn't called async deleteFile(fileName: string) { const uri = this.filePathToUri(fileName); const edit = new vscode.WorkspaceEdit(); @@ -619,8 +630,9 @@ export class PanelWebview implements vscode.WebviewViewProvider { edit.insert(newFile, new vscode.Position(0, 0), content); return vscode.workspace.applyEdit(edit).then(success => { if (success) { + this.watchFileForSaveOrClose(document); vscode.window.showTextDocument(document); - this.refetchDiffsOnSave(document); + // TOOD: send message to ide when file is saved, or closed } else { vscode.window.showInformationMessage('Error: creating file ' + fileName); } @@ -628,6 +640,41 @@ export class PanelWebview implements vscode.WebviewViewProvider { }); } + watchFileForSaveOrClose(document: vscode.TextDocument) { + const disposables: vscode.Disposable[] = []; + const saveDisposable = vscode.workspace.onDidSaveTextDocument((savedDoc) => { + if (savedDoc.uri.toString() === document.uri.toString()) { + // Send message to webview that file was saved + this.toolEditChange(document.uri.fsPath, true); + disposables.forEach(d => d.dispose()); + } + }); + disposables.push(saveDisposable); + + const closeDisposable = vscode.workspace.onDidCloseTextDocument((closedDoc) => { + if (closedDoc.uri.toString() === document.uri.toString()) { + // Send message to webview that file was closed + this.toolEditChange(document.uri.fsPath, false); + disposables.forEach(d => d.dispose()); + } + }); + disposables.push(closeDisposable); + + this._disposables.push(...disposables); + } + + toolEditChange(path: string, accepted: boolean | "indeterminate") { + if(this.tool_edit_in_progress) { + const action = ideToolCallResponse({ + chatId: this.tool_edit_in_progress.chatId, + toolCallId: this.tool_edit_in_progress.toolCallId ?? "", + accepted + }); + this._view?.webview.postMessage(action); + this.tool_edit_in_progress = null; + } + } + async addDiffToFile(fileName: string, content: string) { const uri = this.filePathToUri(fileName); const document = await vscode.workspace.openTextDocument(uri); @@ -638,15 +685,14 @@ export class PanelWebview implements vscode.WebviewViewProvider { const range = new vscode.Range(start, end); - diff_paste_back( + return diff_paste_back( document, range, content ); - // TODO: can remove this when diff api is removed. - this.refetchDiffsOnSave(document); } + // this isn't called async editFileWithContent(fileName: string, content: string) { const uri = this.filePathToUri(fileName); const document = await vscode.workspace.openTextDocument(uri); @@ -668,17 +714,6 @@ export class PanelWebview implements vscode.WebviewViewProvider { } - async writeResultsToFile(results: PatchResult[]) { - for(const result of results) { - if(result.file_name_add) { - this.createNewFileWithContent(result.file_name_add, result.file_text); - } else if(result.file_name_edit) { - this.editFileWithContent(result.file_name_edit, result.file_text); - } else if (result.file_name_delete) { - this.deleteFile(result.file_name_delete); - } - } - } async handleCurrentChatPage(page: string) { this.context.globalState.update("chat_page", JSON.stringify(page)); @@ -737,107 +772,42 @@ export class PanelWebview implements vscode.WebviewViewProvider { } - private getTrimmedSelectedRange(editor: vscode.TextEditor): vscode.Range { - - const selection = editor.selection; - const document = editor.document; - let start = selection.start; - let end = selection.end; - - // Get the text of the selected range - let selectedText = document.getText(selection); - - // Trim leading and trailing whitespace and new lines - const trimmedText = selectedText.trim(); - - // If the trimmed text is empty, return the original selection - if (trimmedText.length === 0) { - return selection; - } - - // Find the start and end positions of the trimmed text within the selected range - const leadingWhitespaceLength = selectedText.length - selectedText.trimStart().length; - const trailingWhitespaceLength = selectedText.length - selectedText.trimEnd().length; - - start = document.positionAt(document.offsetAt(start) + leadingWhitespaceLength); - end = document.positionAt(document.offsetAt(end) - trailingWhitespaceLength); - - return new vscode.Range(start, end); - } - - private async handleDiffPasteBack(code_block: string) { const editor = vscode.window.activeTextEditor; if(!editor) { return; } - const trimmedRange = this.getTrimmedSelectedRange(editor); - const startOfLine = new vscode.Position(trimmedRange.start.line, 0); - const endOfLine = new vscode.Position(trimmedRange.start.line + 1, 0); + const range = editor.selection + const startOfLine = new vscode.Position(range.start.line, 0); + const endOfLine = new vscode.Position(range.start.line + 1, 0); const firstLineRange = new vscode.Range(startOfLine, endOfLine); - const spaceRegex = /^[ \t]+/; - const selectedLine = editor.document.getText( - firstLineRange - ); - const indent = selectedLine.match(spaceRegex)?.[0] ?? ""; - const indentedCode = code_block.replace(/\n/gm, "\n" + indent); - const rangeToReplace = new vscode.Range(trimmedRange.start, trimmedRange.end); - return diff_paste_back( editor.document, - rangeToReplace, - indentedCode, + firstLineRange, + code_block ); } - private refetchDiffsOnSave(document: vscode.TextDocument) { - const disposables: vscode.Disposable[] = []; - const dispose = () => disposables.forEach(d => d.dispose()); - disposables.push(vscode.workspace.onDidSaveTextDocument((savedDocument) => { - if(savedDocument.uri.fsPath === document.uri.fsPath) { - this.sendClearDiffCacheMessage(); - dispose(); - } - })); - disposables.push(vscode.workspace.onDidCloseTextDocument((closedDocument) => { - if(closedDocument.uri.fsPath === document.uri.fsPath) { - dispose(); - } - })); - } - - private async handleDiffPreview(response: DiffPreviewResponse) { - - const openFiles = this.getOpenFiles(); - - for (const change of response.results) { - if (change.file_name_edit !== null && change.file_text !== null) { - this.addDiffToFile(change.file_name_edit, change.file_text); - } else if(change.file_name_add !== null && change.file_text!== null && openFiles.includes(change.file_name_add) === false) { - this.createNewFileWithContent(change.file_name_add, change.file_text); - } else if(change.file_name_add !== null && change.file_text!== null && openFiles.includes(change.file_name_add)) { - this.addDiffToFile(change.file_name_add, change.file_text); - } else if(change.file_name_delete) { - this.deleteFile(change.file_name_delete); - } - } - } - async handleOpenFile(file: {file_name:string, line?: number}) { const uri = this.filePathToUri(file.file_name); - const document = await vscode.workspace.openTextDocument(uri); - - if(file.line !== undefined) { - const position = new vscode.Position(file.line ?? 0, 0); - const editor = await vscode.window.showTextDocument(document); - const range = new vscode.Range(position, position); - editor.revealRange(range); - } else { - await vscode.window.showTextDocument(document); + try { + const document = await vscode.workspace.openTextDocument(uri); + + if(file.line !== undefined) { + const position = new vscode.Position(file.line ?? 0, 0); + const editor = await vscode.window.showTextDocument(document); + const range = new vscode.Range(position, position); + editor.revealRange(range); + } else { + await vscode.window.showTextDocument(document); + } + + console.log(`opening document ${document.uri}`); + return document; + } catch (e) { + console.error(e); } - - return document; } getColorTheme(): "light" | "dark" { @@ -848,6 +818,11 @@ export class PanelWebview implements vscode.WebviewViewProvider { } } + sendCurrentProjectInfo() { + const action = setCurrentProjectInfo({name: vscode.workspace.name ?? ""}); + this._view?.webview.postMessage(action); + } + async createInitialState(thread?: ChatThread, tabbed = false): Promise> { const fontSize = vscode.workspace.getConfiguration().get("editor.fontSize") ?? 12; @@ -874,6 +849,8 @@ export class PanelWebview implements vscode.WebviewViewProvider { features: { vecdb, ast, + images: true, + statistics: true, }, keyBindings: { completeManual, @@ -884,6 +861,7 @@ export class PanelWebview implements vscode.WebviewViewProvider { }; const state: Partial = { + current_project: {name: vscode.workspace.name ?? ""}, config, };