diff --git a/src/vs/workbench/contrib/void/browser/chatThreadService.ts b/src/vs/workbench/contrib/void/browser/chatThreadService.ts index 158c7eb8..b60563b0 100644 --- a/src/vs/workbench/contrib/void/browser/chatThreadService.ts +++ b/src/vs/workbench/contrib/void/browser/chatThreadService.ts @@ -661,7 +661,6 @@ class ChatThreadService extends Disposable implements IChatThreadService { // above just defines helpers, below starts the actual function const { chatMode } = this._settingsService.state.globalSettings // should not change as we loop even if user changes it, so it goes here - console.log('a', chatMode) // clear any previous error this._setStreamState(threadId, { error: undefined }, 'set') @@ -670,13 +669,11 @@ class ChatThreadService extends Disposable implements IChatThreadService { let isRunningWhenEnd: IsRunningType = undefined let aborted = false - console.log('b') // before enter loop, call tool if (callThisToolFirst) { const { interrupted } = await this._runToolCall(threadId, callThisToolFirst.name, { preapproved: true, validatedParams: callThisToolFirst.params }) if (interrupted) return } - console.log('c') // tool use loop while (shouldSendAnotherMessage) { @@ -688,17 +685,14 @@ class ChatThreadService extends Disposable implements IChatThreadService { let resMessageIsDonePromise: (toolCall?: RawToolCallObj | undefined) => void // resolves when user approves this tool use (or if tool doesn't require approval) const messageIsDonePromise = new Promise((res, rej) => { resMessageIsDonePromise = res }) - console.log('d') // send llm message this._setStreamState(threadId, { isRunning: 'LLM' }, 'merge') const systemMessage = await this._generateSystemMessage(chatMode) - console.log('e0') const llmMessages = await this._generateLLMMessages(threadId) const messages: LLMChatMessage[] = [ { role: 'system', content: systemMessage }, ...llmMessages ] - console.log('e') const llmCancelToken = this._llmMessageService.sendLLMMessage({ messagesType: 'chatMessages', @@ -740,20 +734,14 @@ class ChatThreadService extends Disposable implements IChatThreadService { break } this._setStreamState(threadId, { streamingToken: llmCancelToken }, 'merge') // new stream token for the new message - console.log('waiting...') const toolCall = await messageIsDonePromise // wait for message to complete - console.log('done!') if (aborted) { return } - console.log('H') this._setStreamState(threadId, { streamingToken: undefined }, 'merge') // streaming message is done - console.log('I') // call tool if there is one const tool: RawToolCallObj | undefined = toolCall if (tool) { - console.log('J') const { awaitingUserApproval, interrupted } = await this._runToolCall(threadId, tool.name, { preapproved: false, unvalidatedToolParams: tool.rawParams }) - console.log('K') // 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 @@ -768,17 +756,14 @@ class ChatThreadService extends Disposable implements IChatThreadService { } } // end while - console.log('L') // if awaiting user approval, keep isRunning true, else end isRunning this._setStreamState(threadId, { isRunning: isRunningWhenEnd }, 'merge') - console.log('M') // add checkpoint before the next user message if (!isRunningWhenEnd) this._addUserCheckpoint({ threadId }) - console.log('N') // capture number of messages sent this._metricsService.capture('Agent Loop Done', { nMessagesSent, chatMode }) @@ -969,7 +954,7 @@ class ChatThreadService extends Disposable implements IChatThreadService { const [_, toIdx] = c if (toIdx === fromIdx) return - console.log(`going from ${fromIdx} to ${toIdx}`) + // console.log(`going from ${fromIdx} to ${toIdx}`) // update the user's checkpoint this._addUserModificationsToCurrCheckpoint({ threadId }) @@ -1064,6 +1049,7 @@ We only need to do it for files that were edited since `from`, ie files between severity: error ? Severity.Warning : Severity.Info, message: error ? `Error: ${error} ` : `A new Chat result is ready.`, source: messageContent, + sticky: true, actions: { primary: [{ id: 'void.goToChat', diff --git a/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/Settings.tsx b/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/Settings.tsx index 59d8592f..8452291f 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/Settings.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/void-settings-tsx/Settings.tsx @@ -638,6 +638,16 @@ export const FeaturesTab = () => { /> {voidSettingsState.globalSettings.autoApprove ? 'Auto-approve' : 'Auto-approve'} + + {/* Tool Lint Errors Switch */} +
+ voidSettingsService.setGlobalSetting('includeToolLintErrors', newVal)} + /> + {voidSettingsState.globalSettings.includeToolLintErrors ? 'Include after-edit lint errors' : `Don't include lint errors`} +
diff --git a/src/vs/workbench/contrib/void/browser/toolsService.ts b/src/vs/workbench/contrib/void/browser/toolsService.ts index 83249778..8dec053d 100644 --- a/src/vs/workbench/contrib/void/browser/toolsService.ts +++ b/src/vs/workbench/contrib/void/browser/toolsService.ts @@ -18,6 +18,7 @@ import { IMarkerService } from '../../../../platform/markers/common/markers.js' import { timeout } from '../../../../base/common/async.js' import { RawToolParamsObj } from '../common/sendLLMMessageTypes.js' import { ToolName } from '../common/prompt/prompts.js' +import { IVoidSettingsService } from '../common/voidSettingsService.js' // tool use for AI @@ -151,6 +152,7 @@ export class ToolsService implements IToolsService { @IVoidCommandBarService private readonly commandBarService: IVoidCommandBarService, @IDirectoryStrService private readonly directoryStrService: IDirectoryStrService, @IMarkerService private readonly markerService: IMarkerService, + @IVoidSettingsService private readonly voidSettingsService: IVoidSettingsService, ) { const queryBuilder = instantiationService.createInstance(QueryBuilder); @@ -412,10 +414,13 @@ export class ToolsService implements IToolsService { return `URI ${params.uri.fsPath} successfully deleted.` }, edit_file: (params, result) => { + const lintErrsString = ( + this.voidSettingsService.state.globalSettings.includeToolLintErrors ? + (result.lintErrors ? ` Lint errors found after change:\n${lintErrorsStr(result.lintErrors)}.\nIf this is related to a change made while calling this tool, you might want to fix the error.` + : ` No lint errors found.`) + : '') - const additionalStr = result.lintErrors ? `Lint errors found after change:\n${lintErrorsStr(result.lintErrors)}.\nIf this is related to a change made while calling this tool, you might want to fix the error.` : `No lint errors found.` - - return `Change successfully made to ${params.uri.fsPath}.${additionalStr}` + return `Change successfully made to ${params.uri.fsPath}.${lintErrsString}` }, run_terminal_command: (params, result) => { const { diff --git a/src/vs/workbench/contrib/void/common/prompt/prompts.ts b/src/vs/workbench/contrib/void/common/prompt/prompts.ts index 1301cdbc..100c01c0 100644 --- a/src/vs/workbench/contrib/void/common/prompt/prompts.ts +++ b/src/vs/workbench/contrib/void/common/prompt/prompts.ts @@ -16,6 +16,10 @@ export const tripleTick = ['```', '```'] export const MAX_DIRSTR_CHARS_TOTAL_BEGINNING = 20_000 export const MAX_DIRSTR_CHARS_TOTAL_TOOL = 20_000 +export const MAX_DIRSTR_RESULTS_TOTAL_BEGINNING = 100 +export const MAX_DIRSTR_RESULTS_TOTAL_TOOL = 100 + + export const MAX_PREFIX_SUFFIX_CHARS = 20_000 @@ -300,8 +304,8 @@ ${directoryStr} } if (mode === 'gather') { - details.push(`Your primary use of tools should be to gather information to help the user understand the codebase and answer their query.`) - details.push(`You should extensively read files, types, content, etc and gather relevant context.`) + details.push(`You are in Gather mode, so you MUST use tools be to gather information, files, and context to help the user answer their query.`) + details.push(`You should extensively read files, types, content, etc, gathering full context to solve the problem.`) } diff --git a/src/vs/workbench/contrib/void/common/voidSettingsService.ts b/src/vs/workbench/contrib/void/common/voidSettingsService.ts index b4ddb7ab..ad237922 100644 --- a/src/vs/workbench/contrib/void/common/voidSettingsService.ts +++ b/src/vs/workbench/contrib/void/common/voidSettingsService.ts @@ -211,7 +211,15 @@ class VoidSettingsService extends Disposable implements IVoidSettingsService { } async readAndInitializeState() { - const readS = await this._readState(); + let readS: VoidSettingsState + try { + readS = await this._readState(); + // 1.0.3 addition, remove when enough users have had this code run + if (readS.globalSettings.includeToolLintErrors === undefined) readS.globalSettings.includeToolLintErrors = true + } + catch (e) { + readS = defaultState() + } // the stored data structure might be outdated, so we need to update it here const finalState = readS diff --git a/src/vs/workbench/contrib/void/common/voidSettingsTypes.ts b/src/vs/workbench/contrib/void/common/voidSettingsTypes.ts index 47c1f515..bf54f61a 100644 --- a/src/vs/workbench/contrib/void/common/voidSettingsTypes.ts +++ b/src/vs/workbench/contrib/void/common/voidSettingsTypes.ts @@ -356,6 +356,7 @@ export type GlobalSettings = { chatMode: ChatMode; autoApprove: boolean; showInlineSuggestions: boolean; + includeToolLintErrors: boolean; } export const defaultGlobalSettings: GlobalSettings = { @@ -367,6 +368,7 @@ export const defaultGlobalSettings: GlobalSettings = { chatMode: 'agent', autoApprove: false, showInlineSuggestions: true, + includeToolLintErrors: true, } export type GlobalSettingName = keyof GlobalSettings diff --git a/src/vs/workbench/contrib/void/electron-main/llmMessage/extractGrammar.ts b/src/vs/workbench/contrib/void/electron-main/llmMessage/extractGrammar.ts index 4b589636..463d0c06 100644 --- a/src/vs/workbench/contrib/void/electron-main/llmMessage/extractGrammar.ts +++ b/src/vs/workbench/contrib/void/electron-main/llmMessage/extractGrammar.ts @@ -166,6 +166,15 @@ const parseXMLPrefixToToolCall = (toolName: ToolName, str: string, toolOfToolNam let isDone = false const getAnswer = (): RawToolCallObj => { + // trim off all whitespace at and before first \n and after last \n for each param + for (const p in paramsObj) { + const paramName = p as ToolParamName + const orig = paramsObj[paramName] + if (orig === undefined) continue + paramsObj[paramName] = trimBeforeAndAfterNewLines(orig) + } + + // return tool call const ans: RawToolCallObj = { name: toolName, rawParams: paramsObj, @@ -260,7 +269,6 @@ export const extractToolsWrapper = ( let trueFullText = '' let latestToolCall: RawToolCallObj | undefined = undefined - let foundOpenTag: { idx: number, toolName: ToolName } | null = null let openToolTagBuffer = '' // the characters we've seen so far that come after a < with no space afterwards, not yet added to fullText @@ -270,7 +278,7 @@ export const extractToolsWrapper = ( prevFullTextLen = params.fullText.length trueFullText = params.fullText - console.log('NEWTEXT', JSON.stringify(newText)) + // console.log('NEWTEXT', JSON.stringify(newText)) if (foundOpenTag === null) { @@ -278,7 +286,7 @@ export const extractToolsWrapper = ( // ensure the code below doesn't run if only half a tag has been written const isPartial = findPartiallyWrittenToolTagAtEnd(newFullText, toolOpenTags) if (isPartial) { - console.log('--- partial!!!') + // console.log('--- partial!!!') openToolTagBuffer += newText } // if no tooltag is partially written at the end, attempt to get the index @@ -292,7 +300,7 @@ export const extractToolsWrapper = ( if (i !== null) { const [idx, toolTag] = i const toolName = toolTag.substring(1, toolTag.length - 1) as ToolName - console.log('found ', toolName) + // console.log('found ', toolName) foundOpenTag = { idx, toolName } // do not count anything at or after i in fullText @@ -329,15 +337,6 @@ export const extractToolsWrapper = ( fullText = fullText.trimEnd() const toolCall = latestToolCall - if (toolCall) { - // trim off all whitespace at and before first \n and after last \n for each param - for (const p in toolCall.rawParams) { - const paramName = p as ToolParamName - const orig = toolCall.rawParams[paramName] - if (orig === undefined) continue - toolCall.rawParams[paramName] = trimBeforeAndAfterNewLines(orig) - } - } // console.log('final message!!!', trueFullText) // console.log('----- returning ----\n', fullText) @@ -351,7 +350,7 @@ export const extractToolsWrapper = ( -// trim all whitespace up until the first newline, and all whitespace after the last newline +// trim all whitespace up until the first newline, and all whitespace up until the last newline const trimBeforeAndAfterNewLines = (s: string) => { if (!s) return s;