mirror of
https://github.com/voideditor/void
synced 2026-05-24 09:58:23 +00:00
misc bug fixes with oai-compat and agent
This commit is contained in:
parent
8dab3ac854
commit
b86356d2af
7 changed files with 35 additions and 27 deletions
|
|
@ -761,7 +761,7 @@ class ChatThreadService extends Disposable implements IChatThreadService {
|
|||
const handleToolCall = async (
|
||||
tool: ToolCallType,
|
||||
opts?: { preapproved: true, toolParams: ToolCallParams[ToolName] },
|
||||
): Promise<{ awaitingUserApproval: boolean, canceled: boolean }> => {
|
||||
): Promise<{ awaitingUserApproval?: boolean, canceled?: boolean }> => {
|
||||
const toolName: ToolName = tool.name
|
||||
const toolParamsStr = tool.paramsStr
|
||||
const toolId = tool.id
|
||||
|
|
@ -779,14 +779,14 @@ class ChatThreadService extends Disposable implements IChatThreadService {
|
|||
} catch (error) {
|
||||
const errorMessage = getErrorMessage(error)
|
||||
this._addMessageToThread(threadId, { role: 'tool', name: toolName, paramsStr: toolParamsStr, id: toolId, content: errorMessage, result: { type: 'error', params: undefined, value: errorMessage }, })
|
||||
return { awaitingUserApproval: false, canceled: false }
|
||||
return {}
|
||||
}
|
||||
|
||||
// 2. if tool requires approval, break from the loop, awaiting approval
|
||||
const requiresApproval = !this._settingsService.state.globalSettings.autoApprove
|
||||
if (requiresApproval && toolNamesThatRequireApproval.has(toolName)) {
|
||||
this._addMessageToThread(threadId, { role: 'tool_request', name: toolName, paramsStr: toolParamsStr, params: toolParams, id: toolId })
|
||||
return { awaitingUserApproval: true, canceled: false }
|
||||
return { awaitingUserApproval: true }
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -805,10 +805,10 @@ class ChatThreadService extends Disposable implements IChatThreadService {
|
|||
toolResult = await Promise.race([result, resolveIfCancel]) // this await is needed, typescript is bad...
|
||||
}
|
||||
catch (error) {
|
||||
if (canceled) return { awaitingUserApproval: false, canceled: true }
|
||||
if (canceled) return { canceled: true }
|
||||
const errorMessage = getErrorMessage(error)
|
||||
this._addMessageToThread(threadId, { role: 'tool', name: toolName, paramsStr: toolParamsStr, id: toolId, content: errorMessage, result: { type: 'error', params: toolParams, value: errorMessage }, })
|
||||
return { awaitingUserApproval: true, canceled: false }
|
||||
return {}
|
||||
}
|
||||
|
||||
// 4. stringify the result to give to the LLM
|
||||
|
|
@ -817,12 +817,12 @@ class ChatThreadService extends Disposable implements IChatThreadService {
|
|||
} catch (error) {
|
||||
const errorMessage = this.errMsgs.errWhenStringifying(error)
|
||||
this._addMessageToThread(threadId, { role: 'tool', name: toolName, paramsStr: toolParamsStr, id: toolId, content: errorMessage, result: { type: 'error', params: toolParams, value: errorMessage }, })
|
||||
return { awaitingUserApproval: false, canceled: false }
|
||||
return {}
|
||||
}
|
||||
|
||||
// 5. add to history and keep going
|
||||
this._addMessageToThread(threadId, { role: 'tool', name: toolName, paramsStr: toolParamsStr, id: toolId, content: toolResultStr, result: { type: 'success', params: toolParams, value: toolResult }, })
|
||||
return { awaitingUserApproval: false, canceled: false }
|
||||
return {}
|
||||
};
|
||||
|
||||
// above just defines helpers, below starts the actual function
|
||||
|
|
|
|||
|
|
@ -1244,11 +1244,11 @@ class EditCodeService extends Disposable implements IEditCodeService {
|
|||
// ctrlkzone should never have any conflicts
|
||||
}
|
||||
else {
|
||||
// keep conflict on whole file - to keep conflict, revert the change and use those contents as original, then un-revert the change
|
||||
// keep conflict on whole file - to keep conflict, revert the change and use those contents as original, then un-revert the file
|
||||
const currentFileStr = originalFileStr
|
||||
this.acceptOrRejectAllDiffAreas({ uri, removeCtrlKs: true, behavior: 'reject', _addToHistory: false })
|
||||
const oldFileStr = model.getValue(EndOfLinePreference.LF) // use this as original code
|
||||
this._writeURIText(uri, currentFileStr, 'wholeFileRange', { shouldRealignDiffAreas: false }) // un-revert
|
||||
this._writeURIText(uri, currentFileStr, 'wholeFileRange', { shouldRealignDiffAreas: true }) // un-revert
|
||||
originalCode = oldFileStr
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -224,6 +224,7 @@ const ChatModeDropdown = ({ className }: { className: string }) => {
|
|||
const accessor = useAccessor()
|
||||
|
||||
const voidSettingsService = accessor.get('IVoidSettingsService')
|
||||
const settingsState = useSettingsState()
|
||||
|
||||
const options: ChatMode[] = useMemo(() => ['normal', 'gather', 'agent'], [])
|
||||
|
||||
|
|
@ -234,7 +235,7 @@ const ChatModeDropdown = ({ className }: { className: string }) => {
|
|||
return <VoidCustomDropdownBox
|
||||
className={className}
|
||||
options={options}
|
||||
selectedOption={voidSettingsService.state.globalSettings.chatMode}
|
||||
selectedOption={settingsState.globalSettings.chatMode}
|
||||
onChangeOption={onChangeOption}
|
||||
getOptionDisplayName={(val) => nameOfChatMode[val]}
|
||||
getOptionDropdownName={(val) => nameOfChatMode[val]}
|
||||
|
|
@ -674,7 +675,7 @@ export const SelectedFiles = (
|
|||
|
||||
type ToolHeaderParams = {
|
||||
icon?: React.ReactNode;
|
||||
title: string;
|
||||
title: React.ReactNode;
|
||||
desc1: React.ReactNode;
|
||||
desc2?: React.ReactNode;
|
||||
isError?: boolean;
|
||||
|
|
@ -1109,24 +1110,30 @@ const ReasoningWrapper = ({ isDoneReasoning, isStreaming, children }: { isDoneRe
|
|||
|
||||
// should either be past or "-ing" tense, not present tense. Eg. when the LLM searches for something, the user expects it to say "I searched for X" or "I am searching for X". Not "I search X".
|
||||
|
||||
const loadingTitleWrapper = (item: React.ReactNode) => {
|
||||
return <span className='flex items-center flex-nowrap'>
|
||||
{item}
|
||||
<IconLoading className='w-4'/>
|
||||
</span>
|
||||
}
|
||||
const folderFileStr = (isFolder: boolean) => isFolder ? 'folder' : 'file'
|
||||
const toolNameToTitle = {
|
||||
'read_file': { done: 'Read file', proposed: 'Read file', running: 'Reading file...' },
|
||||
'list_dir': { done: 'Inspected folder', proposed: 'Inspect folder', running: 'Inspecting folder...' },
|
||||
'pathname_search': { done: 'Searched by file name', proposed: 'Search by file name', running: 'Searching by file name...' },
|
||||
'text_search': { done: 'Searched', proposed: 'Search text', running: 'Searching...' },
|
||||
'read_file': { done: 'Read file', proposed: 'Read file', running: loadingTitleWrapper('Reading file') },
|
||||
'list_dir': { done: 'Inspected folder', proposed: 'Inspect folder', running: loadingTitleWrapper('Inspecting folder') },
|
||||
'pathname_search': { done: 'Searched by file name', proposed: 'Search by file name', running: loadingTitleWrapper('Searching by file name') },
|
||||
'text_search': { done: 'Searched', proposed: 'Search text', running: loadingTitleWrapper('Searching') },
|
||||
'create_uri': {
|
||||
done: (isFolder: boolean) => `Created ${folderFileStr(isFolder)}`,
|
||||
proposed: (isFolder: boolean) => `Create ${folderFileStr(isFolder)}`,
|
||||
running: (isFolder: boolean) => `Creating ${folderFileStr(isFolder)}...`
|
||||
running: (isFolder: boolean) => loadingTitleWrapper(`Creating ${folderFileStr(isFolder)}`)
|
||||
},
|
||||
'delete_uri': {
|
||||
done: (isFolder: boolean) => `Deleted ${folderFileStr(isFolder)}`,
|
||||
proposed: (isFolder: boolean) => `Delete ${folderFileStr(isFolder)}`,
|
||||
running: (isFolder: boolean) => `Deleting ${folderFileStr(isFolder)}...`
|
||||
running: (isFolder: boolean) => loadingTitleWrapper(`Deleting ${folderFileStr(isFolder)}`)
|
||||
},
|
||||
'edit': { done: 'Edited file', proposed: 'Edit file', running: 'Editing file...' },
|
||||
'terminal_command': { done: 'Ran terminal command', proposed: 'Run terminal command', running: 'Running terminal command...' }
|
||||
'edit': { done: `Edited file`, proposed: 'Edit file', running: loadingTitleWrapper('Editing file') },
|
||||
'terminal_command': { done: `Ran terminal command`, proposed: 'Run terminal command', running: loadingTitleWrapper('Running terminal command') }
|
||||
} as const satisfies Record<ToolName, { done: any, proposed: any, running: any }>
|
||||
|
||||
|
||||
|
|
@ -1778,7 +1785,9 @@ const ChatBubble = ({ chatMessage, isCommitted, messageIdx, isLast, chatIsRunnin
|
|||
}
|
||||
else if (role === 'tool') {
|
||||
const ToolResultWrapper = toolNameToComponent[chatMessage.name].resultWrapper as ResultWrapper<ToolName>
|
||||
return <ToolResultWrapper toolMessage={chatMessage} messageIdx={messageIdx} threadId={threadId} />
|
||||
if (ToolResultWrapper)
|
||||
return <ToolResultWrapper toolMessage={chatMessage} messageIdx={messageIdx} threadId={threadId} />
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ export type VoidCommandBarProps = {
|
|||
export const VoidCommandBarMain = ({ uri, editor }: VoidCommandBarProps) => {
|
||||
const isDark = useIsDark()
|
||||
|
||||
console.log('VoidCommandBarMain', uri?.fsPath)
|
||||
return <div
|
||||
className={`@@void-scope ${isDark ? 'dark' : ''}`}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ const directoryResultToString = (params: ToolCallParams['list_dir'], result: Too
|
|||
const entries = result.children;
|
||||
|
||||
if (!result.hasPrevPage) { // is first page
|
||||
output += `${params.rootURI}\n`;
|
||||
output += `${params.rootURI.fsPath}\n`;
|
||||
}
|
||||
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@ import { EndOfLinePreference } from '../../../../../editor/common/model.js';
|
|||
export const tripleTick = ['```', '```']
|
||||
|
||||
export const editToolDesc_toolDescription = `\
|
||||
A high level description of the change you'd like to make in the file. This description will be handed to a dumber, faster model that will quickly apply the change.\
|
||||
Make sure to include all necessary information to make the change in this description, since it is the only context given to the fast-apply model that will actually write the change.\
|
||||
The best description you can give is a single code block of the form:\n${tripleTick[0]}\n// ... existing code ...\n{{change 1}}\n// ... existing code ...\n{{change2}}\n// ... existing code ...\n{{change 3}}\n...\n${tripleTick[1]}. \
|
||||
Wrap all code in triple backticks. Do NOT output the whole file here if possible, and try to write as LITTLE code as needed to describe the change.`
|
||||
A high level description of the change you'd like to make in the file. \
|
||||
Your output should be of the form:\n${tripleTick[0]}\n// ... existing code ...\n{{change 1}}\n// ... existing code ...\n{{change2}}\n// ... existing code ...\n{{change 3}}\n...\n${tripleTick[1]}. \
|
||||
(wrap your output in triple backticks). Do NOT output the whole file here, and write as little as possible. If a change seems big, break it up into smaller edits. \
|
||||
Your description will be handed to a dumber, faster model that will quickly apply the change, so try to be brief, but also make sure to include enough information to accurately describe the change.`
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ const _sendOpenAICompatibleChat = ({ messages: messages_, onText, onFinalMessage
|
|||
if (!toolCallOfIndex[index]) toolCallOfIndex[index] = { name: '', paramsStr: '', id: '' }
|
||||
toolCallOfIndex[index].name += tool.function?.name ?? ''
|
||||
toolCallOfIndex[index].paramsStr += tool.function?.arguments ?? '';
|
||||
toolCallOfIndex[index].id = tool.id ?? ''
|
||||
toolCallOfIndex[index].id += tool.id ?? ''
|
||||
}
|
||||
// message
|
||||
const newText = chunk.choices[0]?.delta?.content ?? ''
|
||||
|
|
|
|||
Loading…
Reference in a new issue