diff --git a/src/vs/workbench/contrib/void/browser/chatThreadService.ts b/src/vs/workbench/contrib/void/browser/chatThreadService.ts index a4444838..baae23e4 100644 --- a/src/vs/workbench/contrib/void/browser/chatThreadService.ts +++ b/src/vs/workbench/contrib/void/browser/chatThreadService.ts @@ -506,7 +506,7 @@ class ChatThreadService extends Disposable implements IChatThreadService { return {} } // once validated, add checkpoint for edit - if (toolName === 'replace_in_file') { this._addToolEditCheckpoint({ threadId, uri: (toolParams as ToolCallParams['replace_in_file']).uri }) } + if (toolName === 'edit_file') { this._addToolEditCheckpoint({ threadId, uri: (toolParams as ToolCallParams['edit_file']).uri }) } // 2. if tool requires approval, break from the loop, awaiting approval diff --git a/src/vs/workbench/contrib/void/browser/editCodeService.ts b/src/vs/workbench/contrib/void/browser/editCodeService.ts index e21b1776..d9d0d9f3 100644 --- a/src/vs/workbench/contrib/void/browser/editCodeService.ts +++ b/src/vs/workbench/contrib/void/browser/editCodeService.ts @@ -1165,7 +1165,30 @@ class EditCodeService extends Disposable implements IEditCodeService { public instantlyApplySearchReplaceBlocks({ uri, searchReplaceBlocks }: { uri: URI, searchReplaceBlocks: string }) { + // start diffzone + const res = this._startStreamingDiffZone({ + uri, + streamRequestIdRef: { current: null }, + startBehavior: 'keep-conflicts', + linkedCtrlKZone: null, + onWillUndo: () => { }, + }) + if (!res) return + const { diffZone, onFinishEdit } = res + + + const onDone = () => { + diffZone._streamState = { isStreaming: false, } + this._onDidChangeStreamingInDiffZone.fire({ uri, diffareaid: diffZone.diffareaid }) + this._refreshStylesAndDiffsInURI(uri) + onFinishEdit() + } + + this._instantlyApplySRBlocks(uri, searchReplaceBlocks) + + + onDone() } diff --git a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx index b44a46c4..7e34f9fd 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx @@ -1243,7 +1243,7 @@ const titleOfToolName = { 'search_for_files': { done: 'Searched', proposed: 'Search', running: loadingTitleWrapper('Searching') }, 'create_file_or_folder': { done: `Created`, proposed: `Create`, running: loadingTitleWrapper(`Creating`) }, 'delete_file_or_folder': { done: `Deleted`, proposed: `Delete`, running: loadingTitleWrapper(`Deleting`) }, - 'replace_in_file': { done: `Edited file`, proposed: 'Edit file', running: loadingTitleWrapper('Editing file') }, + 'edit_file': { done: `Edited file`, proposed: 'Edit file', running: loadingTitleWrapper('Editing file') }, 'run_command': { done: `Ran terminal`, proposed: 'Run terminal', running: loadingTitleWrapper('Running terminal') }, 'open_persistent_terminal': { done: `Opened terminal`, proposed: 'Open terminal', running: loadingTitleWrapper('Opening terminal') }, 'kill_persistent_terminal': { done: `Killed terminal`, proposed: 'Kill terminal', running: loadingTitleWrapper('Killing terminal') }, @@ -1319,8 +1319,8 @@ const toolNameToDesc = (toolName: ToolName, _toolParams: ToolCallParams[ToolName desc1Info: getRelative(toolParams.uri, accessor), } }, - 'replace_in_file': () => { - const toolParams = _toolParams as ToolCallParams['replace_in_file'] + 'edit_file': () => { + const toolParams = _toolParams as ToolCallParams['edit_file'] return { desc1: getBasename(toolParams.uri.fsPath), desc1Info: getRelative(toolParams.uri, accessor), @@ -1977,7 +1977,7 @@ const toolNameToComponent: { [T in ToolName]: { resultWrapper: ResultWrapper, return } }, - 'replace_in_file': { + 'edit_file': { resultWrapper: ({ toolMessage, messageIdx, threadId }) => { const accessor = useAccessor() const isError = toolMessage.type === 'tool_error' @@ -2633,9 +2633,9 @@ const CommandBarInChat = () => { const EditToolSoFar = ({ toolCallSoFar, }: { toolCallSoFar: RawToolCallObj }) => { - const uri = URI.file(toolCallSoFar.rawParams.uri ?? 'unknown') + const uri = toolCallSoFar.rawParams.uri ? URI.file(toolCallSoFar.rawParams.uri) : undefined - const title = titleOfToolName['replace_in_file'].proposed + const title = titleOfToolName['edit_file'].proposed const uriDone = toolCallSoFar.doneParams.includes('uri') const desc1 = @@ -2649,7 +2649,7 @@ const EditToolSoFar = ({ toolCallSoFar, }: { toolCallSoFar: RawToolCallObj }) => return } + desc2={uri && } > { const reasoningSoFar = currThreadStreamState?.reasoningSoFar // this is just if it's currently being generated, NOT if it's currently running - const toolIsGenerating = toolCallSoFar && !toolCallSoFar.isDone && toolCallSoFar.name === 'replace_in_file' // show loading for slow tools (right now just edit) + const toolIsGenerating = toolCallSoFar && !toolCallSoFar.isDone && toolCallSoFar.name === 'edit_file' // show loading for slow tools (right now just edit) // ----- SIDEBAR CHAT state (local) ----- @@ -2794,7 +2794,7 @@ export const SidebarChat = () => { // the tool currently being generated const generatingTool = toolIsGenerating ? - toolCallSoFar.name === 'replace_in_file' ? diff --git a/src/vs/workbench/contrib/void/browser/toolsService.ts b/src/vs/workbench/contrib/void/browser/toolsService.ts index e3773f1e..9a55d134 100644 --- a/src/vs/workbench/contrib/void/browser/toolsService.ts +++ b/src/vs/workbench/contrib/void/browser/toolsService.ts @@ -241,11 +241,10 @@ export class ToolsService implements IToolsService { return { uri, isRecursive, isFolder } }, - replace_in_file: (params: RawToolParamsObj) => { + edit_file: (params: RawToolParamsObj) => { const { uri: uriStr, search_replace_blocks: searchReplaceBlocksUnknown } = params const uri = validateURI(uriStr) const searchReplaceBlocks = validateStr('searchReplaceBlocks', searchReplaceBlocksUnknown) - console.log('params!!!', uri, searchReplaceBlocks, 'nnnnn', searchReplaceBlocksUnknown) return { uri, searchReplaceBlocks } }, @@ -384,7 +383,7 @@ export class ToolsService implements IToolsService { await fileService.del(uri, { recursive: isRecursive }) return { result: {} } }, - replace_in_file: async ({ uri, searchReplaceBlocks }) => { + edit_file: async ({ uri, searchReplaceBlocks }) => { await voidModelService.initializeModel(uri) if (this.commandBarService.getStreamState(uri) === 'streaming') { throw new Error(`Another LLM is currently making changes to this file. Please stop streaming for now and ask the user to resume later.`) @@ -471,7 +470,7 @@ export class ToolsService implements IToolsService { delete_file_or_folder: (params, result) => { return `URI ${params.uri.fsPath} successfully deleted.` }, - replace_in_file: (params, result) => { + edit_file: (params, result) => { const lintErrsString = ( this.voidSettingsService.state.globalSettings.includeToolLintErrors ? (result.lintErrors ? ` Lint errors found after change:\n${stringifyLintErrors(result.lintErrors)}.\nIf this is related to a change made while calling this tool, you might want to fix the error.` diff --git a/src/vs/workbench/contrib/void/common/prompt/prompts.ts b/src/vs/workbench/contrib/void/common/prompt/prompts.ts index 3a4b8ea0..acc8ecb1 100644 --- a/src/vs/workbench/contrib/void/common/prompt/prompts.ts +++ b/src/vs/workbench/contrib/void/common/prompt/prompts.ts @@ -43,10 +43,16 @@ export const FINAL = `>>>>>>> UPDATED` const searchReplaceBlockTemplate = `\ ${tripleTick[0]} ${ORIGINAL} -// ... original code goes here +// ... original code 1 goes here ${DIVIDER} -// ... final code goes here +// ... final code 1 goes here ${FINAL} +${ORIGINAL} +// ... original code 2 goes here +${DIVIDER} +// ... final code 2 goes here +${FINAL} +... ${tripleTick[1]}` @@ -69,7 +75,7 @@ ${searchReplaceBlockTemplate} 5. The ORIGINAL code in each SEARCH/REPLACE block must EXACTLY match lines in the original file. Do not add or remove any whitespace, comments, or modifications from the original code. -6. Each ORIGINAL text must be large enough to uniquely identify the change in the file. However; bias towards writing as little as possible. +6. Each ORIGINAL text must be large enough to uniquely identify the change in the file. However, bias towards writing as little as possible. 7. Each ORIGINAL text must be DISJOINT from all other ORIGINAL text. @@ -100,14 +106,15 @@ ${tripleTick[1]}` const replaceTool_description = `\ -Output a single string of SEARCH/REPLACE block(s) here. Your string should be wrapped in triple backticks. Here's how to format your SEARCH/REPLACE blocks: +Output a string of SEARCH/REPLACE block(s) to implement your desired change. +You are encouraged to output multiple changes at once. Here's how to format your blocks: ${searchReplaceBlockTemplate} -1. You are allowed to output multiple SEARCH/REPLACE blocks to implement your desired change. Just write them sequentially. +1. Don't forget to wrap your output in triple backticks. -2. The ORIGINAL code in each SEARCH/REPLACE block must EXACTLY match lines in the original file. Do not add or remove any whitespace, comments, or modifications from the original code. +2. The ORIGINAL code in each SEARCH/REPLACE block must EXACTLY match lines in the original file. Do not add or remove any whitespace or comments from the original code. -3. Each ORIGINAL text must be large enough to uniquely identify the change in the file. However; bias towards writing as little as possible. +3. Each ORIGINAL text must be large enough to uniquely identify the change in the file. However, bias towards writing as little as possible. 4. Each ORIGINAL text must be DISJOINT from all other ORIGINAL text.` @@ -278,8 +285,8 @@ export const voidTools = { }, }, - replace_in_file: { // APPLY TOOL - name: 'replace_in_file', + edit_file: { // APPLY TOOL + name: 'edit_file', description: `Edit the contents of a file. You must provide the file's URI as well as SEARCH/REPLACE block(s) that will be used to apply the edit.`, params: { ...uriParam('file'), @@ -289,7 +296,7 @@ export const voidTools = { run_command: { name: 'run_command', - description: `Runs a terminal command and waits for the result (times out after ${MAX_TERMINAL_INACTIVE_TIME}s of inactivity). You can use this tool to run any command: sed, grep, etc. Do not edit any files with this tool; use replace_in_file instead. When working with git and other tools that open an editor (e.g. git diff), you should pipe to cat to get all results and not get stuck in vim.`, + description: `Runs a terminal command and waits for the result (times out after ${MAX_TERMINAL_INACTIVE_TIME}s of inactivity). You can use this tool to run any command: sed, grep, etc. Do not edit any files with this tool; use edit_file instead. When working with git and other tools that open an editor (e.g. git diff), you should pipe to cat to get all results and not get stuck in vim.`, params: { command: { description: 'The terminal command to run.' }, bg_terminal_id: { description: 'Optional. This only applies to terminals that have been opened with open_persistent_terminal. Runs the command in the terminal with the specified ID.' }, diff --git a/src/vs/workbench/contrib/void/common/toolsServiceTypes.ts b/src/vs/workbench/contrib/void/common/toolsServiceTypes.ts index 8972c4ff..016344da 100644 --- a/src/vs/workbench/contrib/void/common/toolsServiceTypes.ts +++ b/src/vs/workbench/contrib/void/common/toolsServiceTypes.ts @@ -19,7 +19,7 @@ export type ShallowDirectoryItem = { export const approvalTypeOfToolName: Partial<{ [T in ToolName]?: 'edits' | 'terminal' }> = { 'create_file_or_folder': 'edits', 'delete_file_or_folder': 'edits', - 'replace_in_file': 'edits', + 'edit_file': 'edits', 'run_command': 'terminal', } @@ -42,7 +42,7 @@ export type ToolCallParams = { 'search_in_file': { uri: URI, query: string, isRegex: boolean }, 'read_lint_errors': { uri: URI }, // --- - 'replace_in_file': { uri: URI, searchReplaceBlocks: string }, + 'edit_file': { uri: URI, searchReplaceBlocks: string }, 'create_file_or_folder': { uri: URI, isFolder: boolean }, 'delete_file_or_folder': { uri: URI, isRecursive: boolean, isFolder: boolean }, // --- @@ -61,7 +61,7 @@ export type ToolResultType = { 'search_in_file': { lines: number[]; }, 'read_lint_errors': { lintErrors: LintErrorItem[] | null }, // --- - 'replace_in_file': Promise<{ lintErrors: LintErrorItem[] | null }>, + 'edit_file': Promise<{ lintErrors: LintErrorItem[] | null }>, 'create_file_or_folder': {}, 'delete_file_or_folder': {}, // ---