mirror of
https://github.com/voideditor/void
synced 2026-05-23 17:38:23 +00:00
better terminal context and search/replace fix
This commit is contained in:
parent
7605931abe
commit
6b4142e9b1
7 changed files with 43 additions and 35 deletions
|
|
@ -483,8 +483,8 @@ class ConvertToLLMMessageService extends Disposable implements IConvertToLLMMess
|
|||
})
|
||||
const includeXMLToolDefinitions = !specialToolFormat
|
||||
|
||||
const runningTerminalIds = this.terminalToolService.listTerminalIds()
|
||||
const systemMessage = chat_systemMessage({ workspaceFolders, openedURIs, directoryStr, activeURI, runningTerminalIds, chatMode, includeXMLToolDefinitions })
|
||||
const persistentTerminalIDs = this.terminalToolService.listTerminalIds()
|
||||
const systemMessage = chat_systemMessage({ workspaceFolders, openedURIs, directoryStr, activeURI, persistentTerminalIDs, chatMode, includeXMLToolDefinitions })
|
||||
return systemMessage
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1594,10 +1594,10 @@ class EditCodeService extends Disposable implements IEditCodeService {
|
|||
for (const b of blocks) {
|
||||
const i = modelStr.indexOf(b.orig)
|
||||
if (i === -1)
|
||||
throw new Error(this._errContentOfInvalidStr('Not found', replacements[i].block.orig))
|
||||
throw new Error(this._errContentOfInvalidStr('Not found', b.orig))
|
||||
const j = modelStr.lastIndexOf(b.orig)
|
||||
if (i !== j)
|
||||
throw new Error(this._errContentOfInvalidStr('Not unique', replacements[i].block.orig))
|
||||
throw new Error(this._errContentOfInvalidStr('Not unique', b.orig))
|
||||
|
||||
replacements.push({
|
||||
origStart: i,
|
||||
|
|
@ -1611,9 +1611,8 @@ class EditCodeService extends Disposable implements IEditCodeService {
|
|||
|
||||
// ensure no overlap
|
||||
for (let i = 1; i < replacements.length; i++) {
|
||||
if (replacements[i].origStart < replacements[i - 1].origEnd) {
|
||||
// There's an overlap
|
||||
throw new Error(this._errContentOfInvalidStr('Has overlap', replacements[i].block.orig))
|
||||
if (replacements[i].origStart <= replacements[i - 1].origEnd) {
|
||||
throw new Error(this._errContentOfInvalidStr('Has overlap', replacements[i]?.block?.orig))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1321,8 +1321,8 @@ 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`) },
|
||||
'rewrite_file': { done: `Rewrote file`, proposed: 'Rewrite file', running: loadingTitleWrapper('Rewriting file') },
|
||||
'edit_file': { done: `Edited file`, proposed: 'Edit file', running: loadingTitleWrapper('Editing file') },
|
||||
'rewrite_file': { done: `Wrote file`, proposed: 'Write file', running: loadingTitleWrapper('Writing 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') },
|
||||
|
|
@ -2065,12 +2065,12 @@ const toolNameToComponent: { [T in ToolName]: { resultWrapper: ResultWrapper<T>,
|
|||
},
|
||||
'rewrite_file': {
|
||||
resultWrapper: (params) => {
|
||||
return <EditTool {...params} content={params.toolMessage.params.newContent} />
|
||||
return <EditTool {...params} content={`${'```\n'}${params.toolMessage.params.newContent}${'\n```'}`} />
|
||||
}
|
||||
},
|
||||
'edit_file': {
|
||||
resultWrapper: (params) => {
|
||||
return <EditTool {...params} content={params.toolMessage.params.searchReplaceBlocks} />
|
||||
return <EditTool {...params} content={`${'```\n'}${params.toolMessage.params.searchReplaceBlocks}${'\n```'}`} />
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ export class TerminalToolService extends Disposable implements ITerminalToolServ
|
|||
|
||||
async killTerminal(terminalId: string) {
|
||||
const terminal = this.terminalInstanceOfId[terminalId]
|
||||
if (!terminal) throw new Error(`Kill Terminal: Terminal with ID ${terminalId} did not exist.`);
|
||||
if (!terminal) throw new Error(`Kill Terminal: Terminal with ID ${terminalId} does not exist.`);
|
||||
terminal.dispose(TerminalExitReason.Extension)
|
||||
delete this.terminalInstanceOfId[terminalId]
|
||||
return
|
||||
|
|
@ -168,7 +168,7 @@ export class TerminalToolService extends Disposable implements ITerminalToolServ
|
|||
let terminalId: string
|
||||
if (isBG) { // BG process
|
||||
terminal = this.terminalInstanceOfId[bgTerminalId];
|
||||
if (!terminal) throw new Error(`Unexpected internal error: Terminal with ID ${bgTerminalId} did not exist.`);
|
||||
if (!terminal) throw new Error(`Unexpected internal error: Terminal with ID ${bgTerminalId} does not exist.`);
|
||||
terminalId = bgTerminalId
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ const isFalsy = (u: unknown) => {
|
|||
|
||||
const validateStr = (argName: string, value: unknown) => {
|
||||
if (value === null) throw new Error(`Invalid LLM output: ${argName} was null.`)
|
||||
if (typeof value !== 'string') throw new Error(`Invalid LLM output format: ${argName} must be a string, but it's a(n) ${typeof value}. Value: ${JSON.stringify(value)}.`)
|
||||
if (typeof value !== 'string') throw new Error(`Invalid LLM output format: ${argName} must be a string, but its type is "${typeof value}". Full value: ${JSON.stringify(value)}.`)
|
||||
return value
|
||||
}
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ const validateStr = (argName: string, value: unknown) => {
|
|||
// TODO!!!! check to make sure folder/file exists
|
||||
const validateURI = (uriStr: unknown) => {
|
||||
if (uriStr === null) throw new Error(`Invalid LLM output: uri was null.`)
|
||||
if (typeof uriStr !== 'string') throw new Error(`Invalid LLM output format: Provided uri must be a string, but it's a(n) ${typeof uriStr}. Value: ${uriStr}.`)
|
||||
if (typeof uriStr !== 'string') throw new Error(`Invalid LLM output format: Provided uri must be a string, but it's a(n) ${typeof uriStr}. Full value: ${JSON.stringify(uriStr)}.`)
|
||||
const uri = URI.file(uriStr)
|
||||
return uri
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,19 +41,17 @@ export const FINAL = `>>>>>>> UPDATED`
|
|||
|
||||
|
||||
const searchReplaceBlockTemplate = `\
|
||||
${tripleTick[0]}
|
||||
${ORIGINAL}
|
||||
// ... original code 1 goes here
|
||||
// ... original code goes here
|
||||
${DIVIDER}
|
||||
// ... final code 1 goes here
|
||||
// ... final code goes here
|
||||
${FINAL}
|
||||
|
||||
${ORIGINAL}
|
||||
// ... original code 2 goes here
|
||||
// ... original code goes here
|
||||
${DIVIDER}
|
||||
// ... final code 2 goes here
|
||||
${FINAL}
|
||||
...
|
||||
${tripleTick[1]}`
|
||||
// ... final code goes here
|
||||
${FINAL}`
|
||||
|
||||
|
||||
|
||||
|
|
@ -63,7 +61,9 @@ You are a coding assistant that takes in a diff, and outputs SEARCH/REPLACE code
|
|||
The diff will be labeled \`DIFF\` and the original file will be labeled \`ORIGINAL_FILE\`.
|
||||
|
||||
Format your SEARCH/REPLACE blocks as follows:
|
||||
${tripleTick[0]}
|
||||
${searchReplaceBlockTemplate}
|
||||
${tripleTick[1]}
|
||||
|
||||
1. Your SEARCH/REPLACE block(s) must implement the diff EXACTLY. Do NOT leave anything out.
|
||||
|
||||
|
|
@ -106,18 +106,21 @@ ${tripleTick[1]}`
|
|||
|
||||
|
||||
const replaceTool_description = `\
|
||||
A string of SEARCH/REPLACE block(s) to apply to the given file.
|
||||
You are encouraged to output multiple changes in this string when possible. For example:
|
||||
A string of SEARCH/REPLACE block(s) which will be applied to the given file.
|
||||
Your SEARCH/REPLACE blocks string must be formatted as follows:
|
||||
${searchReplaceBlockTemplate}
|
||||
|
||||
Guidelines:
|
||||
1. 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.
|
||||
## Guidelines:
|
||||
|
||||
2. Each ORIGINAL text must be large enough to uniquely identify the change in the file. However, bias towards writing as little as possible.
|
||||
1. You are encouraged to output multiple changes whenever possible.
|
||||
|
||||
3. Each ORIGINAL text must be DISJOINT from all other ORIGINAL text.
|
||||
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.
|
||||
|
||||
4. This field is a STRING (not an array). You should wrap the string in triple backticks.`
|
||||
3. Each ORIGINAL text must be large enough to uniquely identify the change. However, bias towards writing as little as possible.
|
||||
|
||||
4. Each ORIGINAL text must be DISJOINT from all other ORIGINAL text.
|
||||
|
||||
5. This field is a STRING (not an array).`
|
||||
|
||||
|
||||
// ======================================================== tools ========================================================
|
||||
|
|
@ -300,7 +303,7 @@ export const voidTools = {
|
|||
description: `Edits a file, deleting all the old contents and replacing them with your new contents. Use this tool if you want to edit a file you just created.`,
|
||||
params: {
|
||||
...uriParam('file'),
|
||||
new_content: { description: `The new contents of the file.` }
|
||||
new_content: { description: `The new contents of the file. Must be a string.` }
|
||||
},
|
||||
},
|
||||
|
||||
|
|
@ -403,7 +406,7 @@ ${toolCallXMLGuidelines}`
|
|||
// ======================================================== chat (normal, gather, agent) ========================================================
|
||||
|
||||
|
||||
export const chat_systemMessage = ({ workspaceFolders, openedURIs, activeURI, runningTerminalIds, directoryStr, chatMode: mode, includeXMLToolDefinitions }: { workspaceFolders: string[], directoryStr: string, openedURIs: string[], activeURI: string | undefined, runningTerminalIds: string[], chatMode: ChatMode, includeXMLToolDefinitions: boolean }) => {
|
||||
export const chat_systemMessage = ({ workspaceFolders, openedURIs, activeURI, persistentTerminalIDs, directoryStr, chatMode: mode, includeXMLToolDefinitions }: { workspaceFolders: string[], directoryStr: string, openedURIs: string[], activeURI: string | undefined, persistentTerminalIDs: string[], chatMode: ChatMode, includeXMLToolDefinitions: boolean }) => {
|
||||
const header = (`You are an expert coding ${mode === 'agent' ? 'agent' : 'assistant'} whose job is \
|
||||
${mode === 'agent' ? `to help the user develop, run, and make changes to their codebase.`
|
||||
: mode === 'gather' ? `to search, understand, and reference files in the user's codebase.`
|
||||
|
|
@ -425,9 +428,9 @@ ${workspaceFolders.join('\n') || 'NO WORKSPACE OPEN'}
|
|||
${activeURI}
|
||||
|
||||
- Open files:
|
||||
${openedURIs.join('\n') || 'NO OPENED EDITORS'}${''/* separator */}${mode === 'agent' && runningTerminalIds.length !== 0 ? `
|
||||
${openedURIs.join('\n') || 'NO OPENED EDITORS'}${''/* separator */}${mode === 'agent' && persistentTerminalIDs.length !== 0 ? `
|
||||
|
||||
- Existing terminal IDs: ${runningTerminalIds.join(', ')}` : ''}
|
||||
- Persistent terminal IDs available for you to run commands in: ${persistentTerminalIDs.join(', ')}` : ''}
|
||||
</system_info>`)
|
||||
|
||||
|
||||
|
|
@ -510,7 +513,7 @@ ${details.map((d, i) => `${i + 1}. ${d}`).join('\n\n')}`)
|
|||
// // log all prompts
|
||||
// for (const chatMode of ['agent', 'gather', 'normal'] satisfies ChatMode[]) {
|
||||
// console.log(`========================================= SYSTEM MESSAGE FOR ${chatMode} ===================================\n`,
|
||||
// chat_systemMessage({ chatMode, workspaceFolders: [], openedURIs: [], activeURI: 'pee', runningTerminalIds: [], directoryStr: 'lol', }))
|
||||
// chat_systemMessage({ chatMode, workspaceFolders: [], openedURIs: [], activeURI: 'pee', persistentTerminalIDs: [], directoryStr: 'lol', }))
|
||||
// }
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -162,6 +162,10 @@ const _sendOpenAICompatibleFIM = async ({ messages: { prefix, suffix, stopTokens
|
|||
|
||||
const toOpenAICompatibleTool = (toolInfo: InternalToolInfo) => {
|
||||
const { name, description, params } = toolInfo
|
||||
|
||||
const paramsWithType: { [s: string]: { description: string; type: 'string' } } = {}
|
||||
for (const key in params) { paramsWithType[key] = { ...params[key], type: 'string' } }
|
||||
|
||||
return {
|
||||
type: 'function',
|
||||
function: {
|
||||
|
|
@ -358,12 +362,14 @@ const _openaiCompatibleList = async ({ onSuccess: onSuccess_, onError: onError_,
|
|||
// ------------ ANTHROPIC (HELPERS) ------------
|
||||
const toAnthropicTool = (toolInfo: InternalToolInfo) => {
|
||||
const { name, description, params } = toolInfo
|
||||
const paramsWithType: { [s: string]: { description: string; type: 'string' } } = {}
|
||||
for (const key in params) { paramsWithType[key] = { ...params[key], type: 'string' } }
|
||||
return {
|
||||
name: name,
|
||||
description: description,
|
||||
input_schema: {
|
||||
type: 'object',
|
||||
properties: params,
|
||||
properties: paramsWithType,
|
||||
// required: Object.keys(params),
|
||||
},
|
||||
} satisfies Anthropic.Messages.Tool
|
||||
|
|
|
|||
Loading…
Reference in a new issue