mirror of
https://github.com/voideditor/void
synced 2026-05-23 17:38:23 +00:00
improve edit tool
This commit is contained in:
parent
991e6a9d5f
commit
0bb948ee2d
6 changed files with 56 additions and 27 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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<T>,
|
|||
return <ToolHeaderWrapper {...componentParams} />
|
||||
}
|
||||
},
|
||||
'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 = <span className='flex items-center'>
|
||||
|
|
@ -2649,7 +2649,7 @@ const EditToolSoFar = ({ toolCallSoFar, }: { toolCallSoFar: RawToolCallObj }) =>
|
|||
return <ToolHeaderWrapper
|
||||
title={title}
|
||||
desc1={desc1}
|
||||
desc2={<JumpToFileButton uri={uri} />}
|
||||
desc2={uri && <JumpToFileButton uri={uri} />}
|
||||
>
|
||||
<EditToolChildren
|
||||
uri={uri}
|
||||
|
|
@ -2703,7 +2703,7 @@ export const SidebarChat = () => {
|
|||
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' ? <EditToolSoFar
|
||||
toolCallSoFar.name === 'edit_file' ? <EditToolSoFar
|
||||
key={'curr-streaming-tool'}
|
||||
toolCallSoFar={toolCallSoFar}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -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.`
|
||||
|
|
|
|||
|
|
@ -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.' },
|
||||
|
|
|
|||
|
|
@ -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': {},
|
||||
// ---
|
||||
|
|
|
|||
Loading…
Reference in a new issue