diff --git a/src/vs/workbench/contrib/void/browser/chatThreadService.ts b/src/vs/workbench/contrib/void/browser/chatThreadService.ts
index 4ee81654..0a033524 100644
--- a/src/vs/workbench/contrib/void/browser/chatThreadService.ts
+++ b/src/vs/workbench/contrib/void/browser/chatThreadService.ts
@@ -641,15 +641,16 @@ class ChatThreadService extends Disposable implements IChatThreadService {
resMessageIsDonePromise(toolCall) // resolve with tool calls
},
- onError: (error) => {
+ onError: async (error) => {
const messageSoFar = this.streamState[threadId]?.displayContentSoFar ?? ''
const reasoningSoFar = this.streamState[threadId]?.reasoningSoFar ?? ''
+ this._setStreamState(threadId, { displayContentSoFar: undefined, reasoningSoFar: undefined, streamingToken: undefined, toolCallSoFar: undefined }, 'merge')
if (nAttempts < CHAT_RETRIES) {
nAttempts += 1
shouldRetry = true
- this._setStreamState(threadId, { displayContentSoFar: undefined, reasoningSoFar: undefined, streamingToken: undefined, toolCallSoFar: undefined }, 'merge')
- timeout(RETRY_DELAY).then(() => { resMessageIsDonePromise() })
+ await timeout(RETRY_DELAY)
+ resMessageIsDonePromise()
}
else {
// const toolCallSoFar = this.streamState[threadId]?.toolCallSoFar
@@ -661,9 +662,9 @@ class ChatThreadService extends Disposable implements IChatThreadService {
},
onAbort: () => {
// stop the loop to free up the promise, but don't modify state (already handled by whatever stopped it)
+ aborted = true
resMessageIsDonePromise()
this._metricsService.capture('Agent Loop Done (Aborted)', { nMessagesSent, chatMode })
- aborted = true
},
})
@@ -678,12 +679,12 @@ class ChatThreadService extends Disposable implements IChatThreadService {
const toolCall = await messageIsDonePromise // wait for message to complete
this._setStreamState(threadId, { streamingToken: undefined }, 'merge') // streaming message is done
- if (shouldRetry) {
- continue
- }
- if (aborted) {
- return
- }
+ // this is a complete hack to make it so if an error loop was aborted, we stop (because onAbort does not get called if error happens instantly)
+ // maybe we should remove all the abort stuff and just make it so that we only go by state?
+ if (!this.streamState[threadId]?.isRunning) { return }
+
+ if (aborted) { return }
+ if (shouldRetry) { continue }
// call tool if there is one
const tool: RawToolCallObj | undefined = toolCall
@@ -692,8 +693,9 @@ class ChatThreadService extends Disposable implements IChatThreadService {
// stop if interrupted. we don't have to do this for llmMessage because we have a stream token for it and onAbort gets called, but we don't have the equivalent for tools.
// just detect tool interruption which is the same as chat interruption right now
- if (interrupted) { return }
+ if (!this.streamState[threadId]?.isRunning) { return }
if (aborted) { return }
+ if (interrupted) { return }
if (awaitingUserApproval) {
console.log('awaiting...')
@@ -1419,14 +1421,13 @@ We only need to do it for files that were edited since `from`, ie files between
openNewThread() {
// if a thread with 0 messages already exists, switch to it
const { allThreads: currentThreads } = this.state
- for (const threadId in currentThreads) {
- if (currentThreads[threadId]!.messages.length === 0) {
-
- // switch to the thread
- this.switchToThread(threadId)
-
- }
- }
+ for (const threadId in currentThreads) {
+ if (currentThreads[threadId]!.messages.length === 0) {
+ // switch to the existing empty thread and exit
+ this.switchToThread(threadId)
+ return
+ }
+ }
// otherwise, start a new thread
const newThread = newThreadObject()
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 5f8c84f6..2e3ec7b1 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
@@ -1447,10 +1447,10 @@ export const ListableToolItem = ({ name, onClick, isSmall, className, showDot }:
-const EditToolChildren = ({ uri, changeDescription }: { uri: URI | undefined, changeDescription: string }) => {
+const EditToolChildren = ({ uri, changeDiff }: { uri: URI | undefined, changeDiff: string }) => {
return
- { nativeHostService.showItemInFolder(environmentService.logsHome.fsPath) }}>
+ { nativeHostService.showItemInFolder(environmentService.logsHome.fsPath) }}>
Open Logs
diff --git a/src/vs/workbench/contrib/void/browser/toolsService.ts b/src/vs/workbench/contrib/void/browser/toolsService.ts
index b6dcf819..bdacb18e 100644
--- a/src/vs/workbench/contrib/void/browser/toolsService.ts
+++ b/src/vs/workbench/contrib/void/browser/toolsService.ts
@@ -242,10 +242,10 @@ export class ToolsService implements IToolsService {
},
edit_file: (params: RawToolParamsObj) => {
- const { uri: uriStr, change_description: changeDescriptionUnknown } = params
+ const { uri: uriStr, change_diff: changeDiffUnknown } = params
const uri = validateURI(uriStr)
- const changeDescription = validateStr('changeDescription', changeDescriptionUnknown)
- return { uri, changeDescription }
+ const changeDiff = validateStr('changeDiff', changeDiffUnknown)
+ return { uri, changeDiff }
},
// ---
@@ -383,14 +383,14 @@ export class ToolsService implements IToolsService {
return { result: {} }
},
- edit_file: async ({ uri, changeDescription }) => {
+ edit_file: async ({ uri, changeDiff }) => {
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 resume later.`)
+ throw new Error(`Another LLM is currently making changes to this file. Please stop streaming for now and ask the user to resume later.`)
}
const opts = {
uri,
- applyStr: changeDescription,
+ applyStr: changeDiff,
from: 'ClickApply',
startBehavior: 'keep-conflicts',
} as const
diff --git a/src/vs/workbench/contrib/void/common/prompt/prompts.ts b/src/vs/workbench/contrib/void/common/prompt/prompts.ts
index ab88d57b..7ce1292b 100644
--- a/src/vs/workbench/contrib/void/common/prompt/prompts.ts
+++ b/src/vs/workbench/contrib/void/common/prompt/prompts.ts
@@ -204,12 +204,14 @@ export const voidTools = {
description: `Edits the contents of a file given the file's URI and a description.`,
params: {
...uriParam('file'),
- change_description: {
+ change_diff: {
description: `\
-Your description MUST be wrapped in triple backticks. \
-A code description of the change you want to make, with comments like "// ... existing code ..." to condense your writing. \
-NEVER re-write the whole file. Bias towards writing as little as possible. \
-Here's an example of a good description:\n${editToolDescriptionExample}`
+A code diff describing the change to make to the file. \
+Your DIFF is the only context that will be given to another LLM to apply the change, so it must be accurate and complete. \
+Your DIFF MUST be wrapped in triple backticks. \
+NEVER re-write the whole file. Always bias towards writing as little as possible. \
+Use comments like "// ... existing code ..." to condense your writing. \
+Here's an example of a good output:\n${editToolDescriptionExample}`
}
},
},
@@ -506,7 +508,7 @@ export const DIVIDER = `=======`
export const FINAL = `>>>>>>> UPDATED`
export const searchReplace_systemMessage = `\
-You are a coding assistant that takes in a diff describing of a change to make, and outputs SEARCH/REPLACE code blocks which implement the change.
+You are a coding assistant that takes in a diff, and outputs SEARCH/REPLACE code blocks to implement the change(s) in the diff.
The diff will be labeled \`DIFF\` and the original file will be labeled \`ORIGINAL_FILE\`.
Format your SEARCH/REPLACE blocks as follows:
@@ -518,11 +520,11 @@ ${DIVIDER}
${FINAL}
${tripleTick[1]}
-1. Your SEARCH/REPLACE block(s) must implement the change EXACTLY.
+1. Your SEARCH/REPLACE block(s) must implement the diff EXACTLY. Do NOT leave anything out.
-2. Assume any comments in the diff are PART OF THE CHANGE. Include them in the output.
+2. You are allowed to output multiple SEARCH/REPLACE blocks to implement the change.
-3. You are allowed to output multiple SEARCH/REPLACE blocks.
+3. Assume any comments in the diff are PART OF THE CHANGE. Include them in the output.
4. Your output should consist ONLY of SEARCH/REPLACE blocks. Do NOT output any text or explanations before or after this.
diff --git a/src/vs/workbench/contrib/void/common/toolsServiceTypes.ts b/src/vs/workbench/contrib/void/common/toolsServiceTypes.ts
index 56bbf6fa..b234689c 100644
--- a/src/vs/workbench/contrib/void/common/toolsServiceTypes.ts
+++ b/src/vs/workbench/contrib/void/common/toolsServiceTypes.ts
@@ -42,7 +42,7 @@ export type ToolCallParams = {
'search_in_file': { uri: URI, query: string, isRegex: boolean },
'read_lint_errors': { uri: URI },
// ---
- 'edit_file': { uri: URI, changeDescription: string },
+ 'edit_file': { uri: URI, changeDiff: string },
'create_file_or_folder': { uri: URI, isFolder: boolean },
'delete_file_or_folder': { uri: URI, isRecursive: boolean, isFolder: boolean },
// ---