From ba8644fbb6d4427c93b9b99512d4e444881d5937 Mon Sep 17 00:00:00 2001 From: Andrew Pareles Date: Mon, 14 Apr 2025 23:12:10 -0700 Subject: [PATCH] read_file improvements --- .../void/browser/react/src/sidebar-tsx/SidebarChat.tsx | 7 ++++--- src/vs/workbench/contrib/void/browser/toolsService.ts | 6 +++--- .../workbench/contrib/void/common/toolsServiceTypes.ts | 2 +- .../electron-main/llmMessage/sendLLMMessage.impl.ts | 10 ++++++---- 4 files changed, 14 insertions(+), 11 deletions(-) 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 2f1c7ae6..4892feff 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 @@ -29,6 +29,7 @@ import { acceptAllBg, acceptBorder, buttonFontSize, buttonTextColor, rejectAllBg import { ToolName, toolNames } from '../../../../common/prompt/prompts.js'; import { error } from 'console'; import { RawToolCallObj } from '../../../../common/sendLLMMessageTypes.js'; +import { MAX_FILE_CHARS_PAGE } from '../../../toolsService.js'; @@ -1434,8 +1435,8 @@ const toolNameToComponent: { [T in ToolName]: { resultWrapper: ResultWrapper, const componentParams: ToolHeaderParams = { title, desc1, isError, icon } if (toolMessage.params.startLine !== null || toolMessage.params.endLine !== null) { - const start = toolMessage.params.startLine === null ? `start` : `${toolMessage.params.startLine}` - const end = toolMessage.params.endLine === null ? `end` : `${toolMessage.params.endLine}` + const start = toolMessage.params.startLine === null ? `1` : `${toolMessage.params.startLine}` + const end = toolMessage.params.endLine === null ? `` : `${toolMessage.params.endLine}` const addStr = `(${start}-${end})` componentParams.desc1 += ` ${addStr}` } @@ -1444,7 +1445,7 @@ const toolNameToComponent: { [T in ToolName]: { resultWrapper: ResultWrapper, const { params, result } = toolMessage componentParams.onClick = () => { commandService.executeCommand('vscode.open', params.uri, { preview: true }) } if (result.hasNextPage && params.pageNumber === 1) // first page - componentParams.desc2 = '(truncated)' + componentParams.desc2 = `(first ${Math.round(MAX_FILE_CHARS_PAGE) / 1000}k)` else if (params.pageNumber > 1) // subsequent pages componentParams.desc2 = `(part ${params.pageNumber})` } diff --git a/src/vs/workbench/contrib/void/browser/toolsService.ts b/src/vs/workbench/contrib/void/browser/toolsService.ts index 53a33daf..cc37f836 100644 --- a/src/vs/workbench/contrib/void/browser/toolsService.ts +++ b/src/vs/workbench/contrib/void/browser/toolsService.ts @@ -276,8 +276,8 @@ export class ToolsService implements IToolsService { const toIdx = MAX_FILE_CHARS_PAGE * pageNumber - 1 const fileContents = contents.slice(fromIdx, toIdx + 1) // paginate const hasNextPage = (contents.length - 1) - toIdx >= 1 - - return { result: { fileContents, hasNextPage } } + const totalFileLen = contents.length + return { result: { fileContents, totalFileLen, hasNextPage } } }, ls_dir: async ({ rootURI, pageNumber }) => { @@ -400,7 +400,7 @@ export class ToolsService implements IToolsService { // given to the LLM after the call this.stringOfResult = { read_file: (params, result) => { - return result.fileContents + nextPageStr(result.hasNextPage) + return `${result.fileContents}${nextPageStr(result.hasNextPage)}${result.hasNextPage ? `This file has ${result.totalFileLen} characters, paginated ${MAX_FILE_CHARS_PAGE} at a time.` : ''}` }, ls_dir: (params, result) => { const dirTreeStr = stringifyDirectoryTree1Deep(params, result) diff --git a/src/vs/workbench/contrib/void/common/toolsServiceTypes.ts b/src/vs/workbench/contrib/void/common/toolsServiceTypes.ts index 891db752..a8589e0f 100644 --- a/src/vs/workbench/contrib/void/common/toolsServiceTypes.ts +++ b/src/vs/workbench/contrib/void/common/toolsServiceTypes.ts @@ -39,7 +39,7 @@ export type ToolCallParams = { // RESULT OF TOOL CALL export type ToolResultType = { - 'read_file': { fileContents: string, hasNextPage: boolean }, + 'read_file': { fileContents: string, totalFileLen: number, hasNextPage: boolean }, 'ls_dir': { children: ShallowDirectoryItem[] | null, hasNextPage: boolean, hasPrevPage: boolean, itemsRemaining: number }, 'get_dir_structure': { str: string, }, 'search_pathnames_only': { uris: URI[], hasNextPage: boolean }, diff --git a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts index 5f7f0474..687497d0 100644 --- a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts +++ b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts @@ -263,8 +263,9 @@ const _sendOpenAICompatibleChat = ({ messages, onText, onFinalMessage, onError, onError({ message: 'Void: Response from model was empty.', fullError: null }) } else { - const toolCall = openAIToolToRawToolCallObj(toolName, toolParamsStr, toolId) ?? undefined - onFinalMessage({ fullText: fullTextSoFar, fullReasoning: fullReasoningSoFar, anthropicReasoning: null, toolCall: toolCall }); + const toolCall = openAIToolToRawToolCallObj(toolName, toolParamsStr, toolId) + const toolCallObj = toolCall ? { toolCall } : {} + onFinalMessage({ fullText: fullTextSoFar, fullReasoning: fullReasoningSoFar, anthropicReasoning: null, ...toolCallObj }); } }) // when error/fail - this catches errors of both .create() and .then(for await) @@ -448,8 +449,9 @@ const sendAnthropicChat = ({ messages, providerName, onText, onFinalMessage, onE stream.on('finalMessage', (response) => { const anthropicReasoning = response.content.filter(c => c.type === 'thinking' || c.type === 'redacted_thinking') const tools = response.content.filter(c => c.type === 'tool_use') - const toolCall = tools[0] ? anthropicToolToRawToolCallObj(tools[0]) ?? undefined : undefined - onFinalMessage({ fullText, fullReasoning, anthropicReasoning, toolCall, }) + const toolCall = tools[0] && anthropicToolToRawToolCallObj(tools[0]) + const toolCallObj = toolCall ? { toolCall } : {} + onFinalMessage({ fullText, fullReasoning, anthropicReasoning, ...toolCallObj }) }) // on error stream.on('error', (error) => {