edit streams in

This commit is contained in:
Andrew Pareles 2025-04-11 13:17:31 -07:00
parent 4efc5209ab
commit e5a40e3d35
3 changed files with 57 additions and 20 deletions

View file

@ -29,6 +29,7 @@ import { acceptAllBg, acceptBorder, buttonFontSize, buttonTextColor, rejectAllBg
import { PlacesType } from 'react-tooltip';
import { ToolName, toolNames } from '../../../../common/prompt/prompts.js';
import { error } from 'console';
import { RawToolCallObj } from '../../../../common/sendLLMMessageTypes.js';
@ -1333,7 +1334,7 @@ export const ListableToolItem = ({ name, onClick, isSmall, className, showDot }:
const EditToolChildren = ({ uri, changeDescription }: { uri: URI, changeDescription: string }) => {
const EditToolChildren = ({ uri, changeDescription }: { uri: URI | undefined, changeDescription: string }) => {
return <div className='!select-text cursor-auto'>
<SmallProseWrapper>
<ChatMarkdownRender string={changeDescription} codeURI={uri} chatMessageLocation={undefined} />
@ -2285,6 +2286,37 @@ const CommandBarInChat = () => {
}
const EditToolSoFar = ({ toolCallSoFar, }: { toolCallSoFar: RawToolCallObj }) => {
const uri = URI.file(toolCallSoFar.rawParams.uri ?? 'unknown')
const title = titleOfToolName['edit_file'].proposed
const uriDone = toolCallSoFar.doneParams.includes('uri')
const desc1 = <span className='flex items-center'>
{uriDone ?
getBasename(toolCallSoFar.rawParams['uri'] ?? 'unknown')
: `Generating`}
<IconLoading />
</span>
// If URI has not been specified
return <ToolHeaderWrapper
title={title}
desc1={desc1}
desc2={<JumpToFileButton uri={uri} />}
>
<EditToolChildren
uri={uri}
changeDescription={toolCallSoFar.rawParams.change_description ?? ''}
/>
<IconLoading />
</ToolHeaderWrapper>
}
export const SidebarChat = () => {
const textAreaRef = useRef<HTMLTextAreaElement | null>(null)
const textAreaFnsRef = useRef<TextAreaFns | null>(null)
@ -2416,6 +2448,15 @@ export const SidebarChat = () => {
/> : null
// the tool currently being generated
const generatingTool = toolIsGenerating ?
toolCallSoFar.name === 'edit_file' ? <EditToolSoFar
key={getChatBubbleId(threadId, streamingChatIdx + 1)}
toolCallSoFar={toolCallSoFar}
/>
: null
: null
const messagesHTML = <ScrollToBottomContainer
key={'messages' + chatThreadsState.currentThreadId} // force rerender on all children if id changes
scrollContainerRef={scrollContainerRef}
@ -2432,17 +2473,11 @@ export const SidebarChat = () => {
{previousMessagesHTML}
{currStreamingMessageHTML}
{toolIsGenerating ?
<ToolHeaderWrapper key={getChatBubbleId(currentThread.id, streamingChatIdx + 1)}
title={toolCallSoFar && toolNames.includes(toolCallSoFar.name as ToolName) ?
titleOfToolName[toolCallSoFar.name as ToolName]?.proposed
: toolCallSoFar?.name}
desc1={<span className='flex items-center'>Generating<IconLoading /></span>}
/>
: null}
{/* Generating tool */}
{generatingTool}
{/* loading indicator */}
{isRunning === 'LLM' && !toolIsGenerating ? <ProseWrapper>
{/* loading indicator */}
{<IconLoading className='opacity-50 text-sm' />}
</ProseWrapper> : null}

View file

@ -47,6 +47,7 @@ import { IWorkspaceContextService } from '../../../../../../../platform/workspac
import { IVoidCommandBarService } from '../../../voidCommandBarService.js'
import { INativeHostService } from '../../../../../../../platform/native/common/native.js';
import { IEditCodeService } from '../../../editCodeServiceInterface.js'
import { IToolsService } from '../../../toolsService.js'
// normally to do this you'd use a useEffect that calls .onDidChangeState(), but useEffect mounts too late and misses initial state changes
@ -215,6 +216,7 @@ const getReactAccessor = (accessor: ServicesAccessor) => {
IVoidCommandBarService: accessor.get(IVoidCommandBarService),
INativeHostService: accessor.get(INativeHostService),
IToolsService: accessor.get(IToolsService),
} as const
return reactAccessor

View file

@ -26,7 +26,7 @@ import { IVoidSettingsService } from '../common/voidSettingsService.js'
type ValidateParams = { [T in ToolName]: (p: RawToolParamsObj) => Promise<ToolCallParams[T]> }
type ValidateParams = { [T in ToolName]: (p: RawToolParamsObj) => ToolCallParams[T] }
type CallTool = { [T in ToolName]: (p: ToolCallParams[T]) => Promise<{ result: ToolResultType[T], interruptTool?: () => void }> }
type ToolResultToString = { [T in ToolName]: (p: ToolCallParams[T], result: Awaited<ToolResultType[T]>) => string }
@ -158,7 +158,7 @@ export class ToolsService implements IToolsService {
const queryBuilder = instantiationService.createInstance(QueryBuilder);
this.validateParams = {
read_file: async (params: RawToolParamsObj) => {
read_file: (params: RawToolParamsObj) => {
const { uri: uriStr, start_line: startLineUnknown, end_line: endLineUnknown, page_number: pageNumberUnknown } = params
const uri = validateURI(uriStr)
const pageNumber = validatePageNum(pageNumberUnknown)
@ -168,19 +168,19 @@ export class ToolsService implements IToolsService {
return { uri, startLine, endLine, pageNumber }
},
ls_dir: async (params: RawToolParamsObj) => {
ls_dir: (params: RawToolParamsObj) => {
const { uri: uriStr, page_number: pageNumberUnknown } = params
const uri = validateURI(uriStr)
const pageNumber = validatePageNum(pageNumberUnknown)
return { rootURI: uri, pageNumber }
},
get_dir_structure: async (params: RawToolParamsObj) => {
get_dir_structure: (params: RawToolParamsObj) => {
const { uri: uriStr, } = params
const uri = validateURI(uriStr)
return { rootURI: uri }
},
search_pathnames_only: async (params: RawToolParamsObj) => {
search_pathnames_only: (params: RawToolParamsObj) => {
const {
query: queryUnknown,
search_in_folder: includeUnknown,
@ -194,7 +194,7 @@ export class ToolsService implements IToolsService {
return { queryStr, searchInFolder, pageNumber }
},
search_files: async (params: RawToolParamsObj) => {
search_files: (params: RawToolParamsObj) => {
const {
query: queryUnknown,
search_in_folder: searchInFolderUnknown,
@ -213,7 +213,7 @@ export class ToolsService implements IToolsService {
// ---
create_file_or_folder: async (params: RawToolParamsObj) => {
create_file_or_folder: (params: RawToolParamsObj) => {
const { uri: uriUnknown } = params
const uri = validateURI(uriUnknown)
const uriStr = validateStr('uri', uriUnknown)
@ -221,7 +221,7 @@ export class ToolsService implements IToolsService {
return { uri, isFolder }
},
delete_file_or_folder: async (params: RawToolParamsObj) => {
delete_file_or_folder: (params: RawToolParamsObj) => {
const { uri: uriUnknown, params: paramsStr } = params
const uri = validateURI(uriUnknown)
const isRecursive = validateRecursiveParamStr(paramsStr)
@ -230,14 +230,14 @@ export class ToolsService implements IToolsService {
return { uri, isRecursive, isFolder }
},
edit_file: async (params: RawToolParamsObj) => {
edit_file: (params: RawToolParamsObj) => {
const { uri: uriStr, change_description: changeDescriptionUnknown } = params
const uri = validateURI(uriStr)
const changeDescription = validateStr('changeDescription', changeDescriptionUnknown)
return { uri, changeDescription }
},
run_terminal_command: async (params: RawToolParamsObj) => {
run_terminal_command: (params: RawToolParamsObj) => {
const { command: commandUnknown, terminal_id: terminalIdUnknown, wait_for_completion: waitForCompletionUnknown } = params
const command = validateStr('command', commandUnknown)
const proposedTerminalId = validateProposedTerminalId(terminalIdUnknown)