mirror of
https://github.com/voideditor/void
synced 2026-05-24 09:58:23 +00:00
edit state and apply state should work, edit UI
This commit is contained in:
parent
8a6b75b6bb
commit
bf2843b1bd
6 changed files with 336 additions and 306 deletions
|
|
@ -23,7 +23,7 @@ import { IToolsService } from './toolsService.js';
|
|||
import { CancellationToken } from '../../../../base/common/cancellation.js';
|
||||
import { ILanguageFeaturesService } from '../../../../editor/common/services/languageFeatures.js';
|
||||
import { ITextModelService } from '../../../../editor/common/services/resolverService.js';
|
||||
import { ChatMessage, CodespanLocationLink, StagingSelectionItem, ToolRequestApproval } from '../common/chatThreadServiceTypes.js';
|
||||
import { ChatMessage, CodespanLocationLink, StagingSelectionItem, ToolMessage, ToolRequestApproval } from '../common/chatThreadServiceTypes.js';
|
||||
import { Position } from '../../../../editor/common/core/position.js';
|
||||
import { ITerminalToolService } from './terminalToolService.js';
|
||||
|
||||
|
|
@ -239,224 +239,224 @@ class ChatThreadService extends Disposable implements IChatThreadService {
|
|||
}
|
||||
const threads = this._convertThreadDataFromStorage(threadsStr);
|
||||
|
||||
// threads['abc'] = {
|
||||
// id: 'abc',
|
||||
// createdAt: new Date().toISOString(),
|
||||
// lastModified: new Date().toISOString(),
|
||||
// messages: [
|
||||
// {
|
||||
// role: 'tool',
|
||||
// name: 'pathname_search',
|
||||
// id: 'tool-1',
|
||||
// paramsStr: '{"query": "hello", "pageNumber": 0}',
|
||||
// content: '/users/andrew/void/Desktop/etc/abc.txt',
|
||||
// result: { type: 'success', params: { queryStr: 'hello', pageNumber: 0 }, value: { uris: [URI.file('/Users/username/Downloads/helloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo.txt'), URI.file('/Users/username/Downloads/hello1.txt'), URI.file('/Users/username/Downloads/hello2.txt'), URI.file('/Users/username/Downloads/hello3.txt'), URI.file('/Users/username/hello.txt')], hasNextPage: true } },
|
||||
// } satisfies ToolMessage<'pathname_search'>,
|
||||
// {
|
||||
// role: 'tool',
|
||||
// name: 'pathname_search',
|
||||
// id: 'tool-1',
|
||||
// paramsStr: '{"query": "hello", "pageNumber": 0}',
|
||||
// content: '/users/andrew/void/Desktop/etc/abc.txt',
|
||||
// result: { type: 'success', params: { queryStr: 'hello', pageNumber: 0 }, value: { uris: [], hasNextPage: false } },
|
||||
// } satisfies ToolMessage<'pathname_search'>,
|
||||
threads['abc'] = {
|
||||
id: 'abc',
|
||||
createdAt: new Date().toISOString(),
|
||||
lastModified: new Date().toISOString(),
|
||||
messages: [
|
||||
{
|
||||
role: 'tool',
|
||||
name: 'pathname_search',
|
||||
id: 'tool-1',
|
||||
paramsStr: '{"query": "hello", "pageNumber": 0}',
|
||||
content: '/users/andrew/void/Desktop/etc/abc.txt',
|
||||
result: { type: 'success', params: { queryStr: 'hello', pageNumber: 0 }, value: { uris: [URI.file('/Users/username/Downloads/helloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo.txt'), URI.file('/Users/username/Downloads/hello1.txt'), URI.file('/Users/username/Downloads/hello2.txt'), URI.file('/Users/username/Downloads/hello3.txt'), URI.file('/Users/username/hello.txt')], hasNextPage: true } },
|
||||
} satisfies ToolMessage<'pathname_search'>,
|
||||
{
|
||||
role: 'tool',
|
||||
name: 'pathname_search',
|
||||
id: 'tool-1',
|
||||
paramsStr: '{"query": "hello", "pageNumber": 0}',
|
||||
content: '/users/andrew/void/Desktop/etc/abc.txt',
|
||||
result: { type: 'success', params: { queryStr: 'hello', pageNumber: 0 }, value: { uris: [], hasNextPage: false } },
|
||||
} satisfies ToolMessage<'pathname_search'>,
|
||||
|
||||
// // {
|
||||
// // role: 'tool_request',
|
||||
// // name: 'pathname_search',
|
||||
// // params: { queryStr: 'hello', pageNumber: 0 },
|
||||
// // paramsStr: '{"query": "hello", "pageNumber": 0}',
|
||||
// // voidToolId: 'request-1',
|
||||
// // } satisfies ToolRequestApproval<'pathname_search'>,
|
||||
// {
|
||||
// role: 'tool_request',
|
||||
// name: 'pathname_search',
|
||||
// params: { queryStr: 'hello', pageNumber: 0 },
|
||||
// paramsStr: '{"query": "hello", "pageNumber": 0}',
|
||||
// voidToolId: 'request-1',
|
||||
// } satisfies ToolRequestApproval<'pathname_search'>,
|
||||
|
||||
// {
|
||||
// role: 'tool',
|
||||
// name: 'list_dir',
|
||||
// id: 'tool-2',
|
||||
// paramsStr: '{"uri": "/Users/username/Documents"}',
|
||||
// content: 'Directory listing of /Users/username/Documents',
|
||||
// result: {
|
||||
// type: 'success',
|
||||
// params: { rootURI: URI.file('/Users/username/Documents'), pageNumber: 1, },
|
||||
// value: {
|
||||
// children: [
|
||||
// { uri: URI.file('/Users/username/Documents/file1.txt'), name: 'file1.txt', isDirectory: false, isSymbolicLink: false },
|
||||
// { uri: URI.file('/Users/username/Documents/folder1'), name: 'folder1', isDirectory: true, isSymbolicLink: false }
|
||||
// ],
|
||||
// hasNextPage: true,
|
||||
// hasPrevPage: true,
|
||||
// itemsRemaining: 5,
|
||||
// }
|
||||
// },
|
||||
// } satisfies ToolMessage<'list_dir'>,
|
||||
{
|
||||
role: 'tool',
|
||||
name: 'list_dir',
|
||||
id: 'tool-2',
|
||||
paramsStr: '{"uri": "/Users/username/Documents"}',
|
||||
content: 'Directory listing of /Users/username/Documents',
|
||||
result: {
|
||||
type: 'success',
|
||||
params: { rootURI: URI.file('/Users/username/Documents'), pageNumber: 1, },
|
||||
value: {
|
||||
children: [
|
||||
{ uri: URI.file('/Users/username/Documents/file1.txt'), name: 'file1.txt', isDirectory: false, isSymbolicLink: false },
|
||||
{ uri: URI.file('/Users/username/Documents/folder1'), name: 'folder1', isDirectory: true, isSymbolicLink: false }
|
||||
],
|
||||
hasNextPage: true,
|
||||
hasPrevPage: true,
|
||||
itemsRemaining: 5,
|
||||
}
|
||||
},
|
||||
} satisfies ToolMessage<'list_dir'>,
|
||||
|
||||
// // {
|
||||
// // role: 'tool_request',
|
||||
// // name: 'list_dir',
|
||||
// // params: { rootURI: URI.file('/Users/username/Documents'), pageNumber: 0 },
|
||||
// // paramsStr: '{"uri": "/Users/username/Documents"}',
|
||||
// // voidToolId: 'request-2',
|
||||
// // } satisfies ToolRequestApproval<'list_dir'>,
|
||||
// {
|
||||
// role: 'tool_request',
|
||||
// name: 'list_dir',
|
||||
// params: { rootURI: URI.file('/Users/username/Documents'), pageNumber: 0 },
|
||||
// paramsStr: '{"uri": "/Users/username/Documents"}',
|
||||
// voidToolId: 'request-2',
|
||||
// } satisfies ToolRequestApproval<'list_dir'>,
|
||||
|
||||
// {
|
||||
// role: 'tool',
|
||||
// name: 'read_file',
|
||||
// id: 'tool-3',
|
||||
// paramsStr: '{"uri": "/Users/username/Documents/file1.txt"}',
|
||||
// content: 'Content of file1.txt\nThis is a sample file.\nHello world!',
|
||||
// result: {
|
||||
// type: 'success',
|
||||
// params: { uri: URI.file('/Users/username/Documents/file1.txt'), pageNumber: 0 },
|
||||
// value: { fileContents: 'Content of file1.txt\nThis is a sample file.\nHello world!', hasNextPage: false }
|
||||
// },
|
||||
// } satisfies ToolMessage<'read_file'>,
|
||||
{
|
||||
role: 'tool',
|
||||
name: 'read_file',
|
||||
id: 'tool-3',
|
||||
paramsStr: '{"uri": "/Users/username/Documents/file1.txt"}',
|
||||
content: 'Content of file1.txt\nThis is a sample file.\nHello world!',
|
||||
result: {
|
||||
type: 'success',
|
||||
params: { uri: URI.file('/src/vs/workbench/hi'), pageNumber: 0 },
|
||||
value: { fileContents: 'Content of file1.txt\nThis is a sample file.\nHello world!', hasNextPage: false }
|
||||
},
|
||||
} satisfies ToolMessage<'read_file'>,
|
||||
|
||||
// // {
|
||||
// // role: 'tool_request',
|
||||
// // name: 'read_file',
|
||||
// // params: { uri: URI.file('/Users/username/Documents/file1.txt'), pageNumber: 0 },
|
||||
// // paramsStr: '{"uri": "/Users/username/Documents/file1.txt"}',
|
||||
// // voidToolId: 'request-3',
|
||||
// // } satisfies ToolRequestApproval<'read_file'>,
|
||||
// {
|
||||
// role: 'tool_request',
|
||||
// name: 'read_file',
|
||||
// params: { uri: URI.file('/Users/username/Documents/file1.txt'), pageNumber: 0 },
|
||||
// paramsStr: '{"uri": "/Users/username/Documents/file1.txt"}',
|
||||
// voidToolId: 'request-3',
|
||||
// } satisfies ToolRequestApproval<'read_file'>,
|
||||
|
||||
// {
|
||||
// role: 'tool',
|
||||
// name: 'search',
|
||||
// id: 'tool-4',
|
||||
// paramsStr: '{"query": "function main"}',
|
||||
// content: 'Found matches in 3 files',
|
||||
// result: {
|
||||
// type: 'success',
|
||||
// params: { queryStr: 'function main', pageNumber: 0 },
|
||||
// value: {
|
||||
// uris: [
|
||||
// URI.file('/Users/username/Project/main.js'),
|
||||
// URI.file('/Users/username/Project/src/app.js'),
|
||||
// URI.file('/Users/username/Project/test/test.js')
|
||||
// ],
|
||||
// hasNextPage: false
|
||||
// }
|
||||
// },
|
||||
// } satisfies ToolMessage<'search'>,
|
||||
{
|
||||
role: 'tool',
|
||||
name: 'search',
|
||||
id: 'tool-4',
|
||||
paramsStr: '{"query": "function main"}',
|
||||
content: 'Found matches in 3 files',
|
||||
result: {
|
||||
type: 'success',
|
||||
params: { queryStr: 'function main', pageNumber: 0 },
|
||||
value: {
|
||||
uris: [
|
||||
URI.file('/Users/username/Project/main.js'),
|
||||
URI.file('/Users/username/Project/src/app.js'),
|
||||
URI.file('/Users/username/Project/test/test.js')
|
||||
],
|
||||
hasNextPage: false
|
||||
}
|
||||
},
|
||||
} satisfies ToolMessage<'search'>,
|
||||
|
||||
// // {
|
||||
// // role: 'tool_request',
|
||||
// // name: 'search',
|
||||
// // params: { queryStr: 'function main', pageNumber: 0 },
|
||||
// // paramsStr: '{"query": "function main"}',
|
||||
// // voidToolId: 'request-4',
|
||||
// // } satisfies ToolRequestApproval<'search'>,
|
||||
// {
|
||||
// role: 'tool_request',
|
||||
// name: 'search',
|
||||
// params: { queryStr: 'function main', pageNumber: 0 },
|
||||
// paramsStr: '{"query": "function main"}',
|
||||
// voidToolId: 'request-4',
|
||||
// } satisfies ToolRequestApproval<'search'>,
|
||||
|
||||
// // ---
|
||||
// ---
|
||||
|
||||
// {
|
||||
// role: 'tool',
|
||||
// name: 'edit',
|
||||
// id: 'tool-5',
|
||||
// paramsStr: '{"uri": "/Users/username/Project/main.js", "changeDescription": "Add console.log statement"}',
|
||||
// content: 'Successfully edited the file at /Users/username/Project/main.js',
|
||||
// result: {
|
||||
// type: 'success',
|
||||
// params: { uri: URI.file('/Users/username/Project/main.js'), changeDescription: 'Add console.log statement' },
|
||||
// value: {}
|
||||
// },
|
||||
// } satisfies ToolMessage<'edit'>,
|
||||
// {
|
||||
// role: 'tool_request',
|
||||
// name: 'edit',
|
||||
// params: { uri: URI.file('/Users/username/Project/main.js'), changeDescription: 'Add console.log statement' },
|
||||
// paramsStr: '{"uri": "/Users/username/Project/main.js", "changeDescription": "Add console.log statement"}',
|
||||
// voidToolId: 'request-5',
|
||||
// } satisfies ToolRequestApproval<'edit'>,
|
||||
{
|
||||
role: 'tool',
|
||||
name: 'edit',
|
||||
id: 'tool-5',
|
||||
paramsStr: '{"uri": "/Users/username/Project/main.js", "changeDescription": "Add console.log statement"}',
|
||||
content: 'Successfully edited the file at /Users/username/Project/main.js',
|
||||
result: {
|
||||
type: 'success',
|
||||
params: { uri: URI.file('/Users/username/Project/main.js'), changeDescription: 'Add console.log statement' },
|
||||
value: {}
|
||||
},
|
||||
} satisfies ToolMessage<'edit'>,
|
||||
{
|
||||
role: 'tool_request',
|
||||
name: 'edit',
|
||||
params: { uri: URI.file('/Users/username/Project/main.js'), changeDescription: 'Add console.log statement' },
|
||||
paramsStr: '{"uri": "/Users/username/Project/main.js", "changeDescription": "Add console.log statement"}',
|
||||
voidToolId: 'request-5',
|
||||
} satisfies ToolRequestApproval<'edit'>,
|
||||
|
||||
// {
|
||||
// role: 'tool',
|
||||
// name: 'create_uri',
|
||||
// id: 'tool-6',
|
||||
// paramsStr: '{"uri": "/Users/username/Project/new-file.js"}',
|
||||
// content: 'Successfully created file at /Users/username/Project/new-file.js',
|
||||
// result: {
|
||||
// type: 'success',
|
||||
// params: { uri: URI.file('/Users/username/Project/new-file.js'), isFolder: false },
|
||||
// value: {}
|
||||
// },
|
||||
// } satisfies ToolMessage<'create_uri'>,
|
||||
// {
|
||||
// role: 'tool_request',
|
||||
// name: 'create_uri',
|
||||
// params: { uri: URI.file('/Users/username/Project/new-file.js'), isFolder: false },
|
||||
// paramsStr: '{"uri": "/Users/username/Project/new-file.js"}',
|
||||
// voidToolId: 'request-6',
|
||||
// } satisfies ToolRequestApproval<'create_uri'>,
|
||||
{
|
||||
role: 'tool',
|
||||
name: 'create_uri',
|
||||
id: 'tool-6',
|
||||
paramsStr: '{"uri": "/Users/username/Project/new-file.js"}',
|
||||
content: 'Successfully created file at /Users/username/Project/new-file.js',
|
||||
result: {
|
||||
type: 'success',
|
||||
params: { uri: URI.file('Users/andrew/Desktop/void/src/vs/workbench/hi'), isFolder: false },
|
||||
value: {}
|
||||
},
|
||||
} satisfies ToolMessage<'create_uri'>,
|
||||
{
|
||||
role: 'tool_request',
|
||||
name: 'create_uri',
|
||||
params: { uri: URI.file('/Users/username/Project/new-file.js'), isFolder: false },
|
||||
paramsStr: '{"uri": "/Users/username/Project/new-file.js"}',
|
||||
voidToolId: 'request-6',
|
||||
} satisfies ToolRequestApproval<'create_uri'>,
|
||||
|
||||
// {
|
||||
// role: 'tool',
|
||||
// name: 'delete_uri',
|
||||
// id: 'tool-7',
|
||||
// paramsStr: '{"uri": "/Users/username/Project/old-file.js", "params": ""}',
|
||||
// content: 'Successfully deleted file at /Users/username/Project/old-file.js',
|
||||
// result: {
|
||||
// type: 'success',
|
||||
// params: { uri: URI.file('/Users/username/Project/old-file.js'), isRecursive: false, isFolder: false },
|
||||
// value: {}
|
||||
// },
|
||||
// } satisfies ToolMessage<'delete_uri'>,
|
||||
// {
|
||||
// role: 'tool_request',
|
||||
// name: 'delete_uri',
|
||||
// params: { uri: URI.file('/Users/username/Project/old-file.js'), isRecursive: false, isFolder: false },
|
||||
// paramsStr: '{"uri": "/Users/username/Project/old-file.js", "params": ""}',
|
||||
// voidToolId: 'request-7',
|
||||
// } satisfies ToolRequestApproval<'delete_uri'>,
|
||||
{
|
||||
role: 'tool',
|
||||
name: 'delete_uri',
|
||||
id: 'tool-7',
|
||||
paramsStr: '{"uri": "/Users/username/Project/old-file.js", "params": ""}',
|
||||
content: 'Successfully deleted file at /Users/username/Project/old-file.js',
|
||||
result: {
|
||||
type: 'success',
|
||||
params: { uri: URI.file('/Users/username/Project/old-file.js'), isRecursive: false, isFolder: false },
|
||||
value: {}
|
||||
},
|
||||
} satisfies ToolMessage<'delete_uri'>,
|
||||
{
|
||||
role: 'tool_request',
|
||||
name: 'delete_uri',
|
||||
params: { uri: URI.file('/Users/username/Project/old-file.js'), isRecursive: false, isFolder: false },
|
||||
paramsStr: '{"uri": "/Users/username/Project/old-file.js", "params": ""}',
|
||||
voidToolId: 'request-7',
|
||||
} satisfies ToolRequestApproval<'delete_uri'>,
|
||||
|
||||
// {
|
||||
// role: 'tool',
|
||||
// name: 'terminal_command',
|
||||
// id: 'tool-8',
|
||||
// paramsStr: '{"command": "npm install", "waitForCompletion": "true"}',
|
||||
// content: 'Command executed: npm install\nAdded 123 packages in 3.5s',
|
||||
// result: {
|
||||
// type: 'success',
|
||||
// params: { command: 'npm install', proposedTerminalId: '1', waitForCompletion: true },
|
||||
// value: {
|
||||
// terminalId: '1',
|
||||
// didCreateTerminal: false,
|
||||
// result: 'Added 123 packages in 3.5s',
|
||||
// resolveReason: { type: 'done', exitCode: 0 }
|
||||
// }
|
||||
// },
|
||||
// } satisfies ToolMessage<'terminal_command'>,
|
||||
// {
|
||||
// role: 'tool_request',
|
||||
// name: 'terminal_command',
|
||||
// params: { command: 'npm install', proposedTerminalId: '1', waitForCompletion: true },
|
||||
// paramsStr: '{"command": "npm install", "waitForCompletion": "true"}',
|
||||
// voidToolId: 'request-8',
|
||||
// } satisfies ToolRequestApproval<'terminal_command'>,
|
||||
{
|
||||
role: 'tool',
|
||||
name: 'terminal_command',
|
||||
id: 'tool-8',
|
||||
paramsStr: '{"command": "npm install", "waitForCompletion": "true"}',
|
||||
content: 'Command executed: npm install\nAdded 123 packages in 3.5s',
|
||||
result: {
|
||||
type: 'success',
|
||||
params: { command: 'npm install', proposedTerminalId: '1', waitForCompletion: true },
|
||||
value: {
|
||||
terminalId: '1',
|
||||
didCreateTerminal: false,
|
||||
result: 'Added 123 packages in 3.5s',
|
||||
resolveReason: { type: 'done', exitCode: 0 }
|
||||
}
|
||||
},
|
||||
} satisfies ToolMessage<'terminal_command'>,
|
||||
{
|
||||
role: 'tool_request',
|
||||
name: 'terminal_command',
|
||||
params: { command: 'npm install', proposedTerminalId: '1', waitForCompletion: true },
|
||||
paramsStr: '{"command": "npm install", "waitForCompletion": "true"}',
|
||||
voidToolId: 'request-8',
|
||||
} satisfies ToolRequestApproval<'terminal_command'>,
|
||||
|
||||
|
||||
|
||||
// // Examples of error and rejected states
|
||||
// {
|
||||
// role: 'tool',
|
||||
// name: 'pathname_search',
|
||||
// id: 'tool-error',
|
||||
// paramsStr: '{"query": "invalid**query"}',
|
||||
// content: 'Error: Invalid search pattern',
|
||||
// result: { type: 'error', params: { queryStr: 'invalid**query', pageNumber: 0 }, value: 'Error: Invalid search pattern' },
|
||||
// } satisfies ToolMessage<'pathname_search'>,
|
||||
// Examples of error and rejected states
|
||||
{
|
||||
role: 'tool',
|
||||
name: 'pathname_search',
|
||||
id: 'tool-error',
|
||||
paramsStr: '{"query": "invalid**query"}',
|
||||
content: 'Error: Invalid search pattern',
|
||||
result: { type: 'error', params: { queryStr: 'invalid**query', pageNumber: 0 }, value: 'Error: Invalid search pattern' },
|
||||
} satisfies ToolMessage<'pathname_search'>,
|
||||
|
||||
// {
|
||||
// role: 'tool',
|
||||
// name: 'pathname_search',
|
||||
// id: 'tool-rejected',
|
||||
// paramsStr: '{"query": "sensitive-data"}',
|
||||
// content: 'Tool call was rejected by the user.',
|
||||
// result: { type: 'rejected', params: { queryStr: 'sensitive-data', pageNumber: 0 } },
|
||||
// } satisfies ToolMessage<'pathname_search'>,
|
||||
// ],
|
||||
// state: defaultThreadState,
|
||||
// }
|
||||
{
|
||||
role: 'tool',
|
||||
name: 'pathname_search',
|
||||
id: 'tool-rejected',
|
||||
paramsStr: '{"query": "sensitive-data"}',
|
||||
content: 'Tool call was rejected by the user.',
|
||||
result: { type: 'rejected', params: { queryStr: 'sensitive-data', pageNumber: 0 } },
|
||||
} satisfies ToolMessage<'pathname_search'>,
|
||||
],
|
||||
state: defaultThreadState,
|
||||
}
|
||||
|
||||
return threads
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ const CopyButton = ({ codeStr }: { codeStr: string }) => {
|
|||
const applyingURIOfApplyBoxIdRef: { current: { [applyBoxId: string]: URI | undefined } } = { current: {} }
|
||||
|
||||
|
||||
export const useApplyButtonHTML = ({ codeStr, applyBoxId }: { codeStr: string, applyBoxId: string }) => {
|
||||
export const useApplyButtonHTML = ({ codeStr, applyBoxId, uri }: { codeStr: string, applyBoxId: string, uri: URI | 'current' }) => {
|
||||
|
||||
const settingsState = useSettingsState()
|
||||
const isDisabled = !!isFeatureNameDisabled('Apply', settingsState) || !applyBoxId
|
||||
|
|
@ -112,13 +112,16 @@ export const useApplyButtonHTML = ({ codeStr, applyBoxId }: { codeStr: string, a
|
|||
const getUriBeingApplied = useCallback(() => applyingURIOfApplyBoxIdRef.current[applyBoxId] ?? null, [applyBoxId])
|
||||
const getStreamState = useCallback(() => editCodeService.getURIStreamState({ uri: getUriBeingApplied() }), [editCodeService, getUriBeingApplied])
|
||||
|
||||
// listen for stream updates
|
||||
// listen for stream updates on this box
|
||||
useURIStreamState(
|
||||
useCallback((uri, newStreamState) => {
|
||||
const shouldUpdate = getUriBeingApplied()?.fsPath === uri.fsPath
|
||||
useCallback((uri_, newStreamState) => {
|
||||
const shouldUpdate = (
|
||||
getUriBeingApplied()?.fsPath === uri_.fsPath
|
||||
|| (uri === 'current' ? false : uri.fsPath === uri_.fsPath)
|
||||
)
|
||||
if (!shouldUpdate) return
|
||||
rerender(c => c + 1)
|
||||
}, [applyBoxId, editCodeService, getUriBeingApplied])
|
||||
}, [applyBoxId, editCodeService, getUriBeingApplied, uri])
|
||||
)
|
||||
|
||||
const onClickSubmit = useCallback(async () => {
|
||||
|
|
@ -127,14 +130,14 @@ export const useApplyButtonHTML = ({ codeStr, applyBoxId }: { codeStr: string, a
|
|||
const [newApplyingUri, _] = await editCodeService.startApplying({
|
||||
from: 'ClickApply',
|
||||
applyStr: codeStr,
|
||||
uri: 'current',
|
||||
uri: uri,
|
||||
startBehavior: 'reject-conflicts',
|
||||
}) ?? []
|
||||
applyingURIOfApplyBoxIdRef.current[applyBoxId] = newApplyingUri ?? undefined
|
||||
|
||||
rerender(c => c + 1)
|
||||
metricsService.capture('Apply Code', { length: codeStr.length }) // capture the length only
|
||||
}, [isDisabled, getStreamState, editCodeService, codeStr, applyBoxId, metricsService])
|
||||
}, [isDisabled, getStreamState, editCodeService, codeStr, uri, applyBoxId, metricsService])
|
||||
|
||||
|
||||
const onInterrupt = useCallback(() => {
|
||||
|
|
@ -263,17 +266,18 @@ export const BlockCodeApplyWrapper = ({
|
|||
applyBoxId,
|
||||
language,
|
||||
canApply,
|
||||
|
||||
uri,
|
||||
}: {
|
||||
initValue: string;
|
||||
children: React.ReactNode;
|
||||
applyBoxId: string;
|
||||
canApply: boolean;
|
||||
language: string;
|
||||
uri: URI | 'current',
|
||||
}) => {
|
||||
|
||||
|
||||
const { statusIndicatorHTML, buttonsHTML } = useApplyButtonHTML({ codeStr: initValue, applyBoxId })
|
||||
const { statusIndicatorHTML, buttonsHTML } = useApplyButtonHTML({ codeStr: initValue, applyBoxId, uri })
|
||||
|
||||
return <div
|
||||
className='border border-void-border-3 rounded overflow-hidden bg-void-bg-3'
|
||||
|
|
@ -287,7 +291,7 @@ export const BlockCodeApplyWrapper = ({
|
|||
{language || 'text'}
|
||||
</span>
|
||||
</div>
|
||||
<div className={`${canApply ? '' : 'hidden'} flex gap-1`}>
|
||||
<div className={`${canApply ? '' : 'hidden'} flex items-center gap-1`}>
|
||||
{buttonsHTML}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
*--------------------------------------------------------------------------------------*/
|
||||
|
||||
import { VoidCodeEditor, VoidCodeEditorProps } from '../util/inputs.js';
|
||||
import { BlockCodeApplyWrapper, useApplyButtonHTML } from './ApplyBlockHoverButtons.js';
|
||||
|
||||
|
||||
export const BlockCode = ({ ...codeEditorProps }: VoidCodeEditorProps) => {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export type ChatMessageLocation = {
|
|||
|
||||
type ApplyBoxLocation = ChatMessageLocation & { tokenIdx: string }
|
||||
|
||||
const getApplyBoxId = ({ threadId, messageIdx, tokenIdx }: ApplyBoxLocation) => {
|
||||
export const getApplyBoxId = ({ threadId, messageIdx, tokenIdx }: ApplyBoxLocation) => {
|
||||
return `${threadId}-${messageIdx}-${tokenIdx}`
|
||||
}
|
||||
|
||||
|
|
@ -120,7 +120,7 @@ const RenderToken = ({ token, inPTag, codeURI, chatMessageLocation, tokenIdx, ..
|
|||
const firstLineIsURI = URI.isUri(firstLine)
|
||||
const contents = firstLineIsURI ? (remainingContents || '') : t.text // exclude first-line URI from contents
|
||||
|
||||
// figure out langauge
|
||||
// figure out langauge and URI
|
||||
let language: string | undefined = undefined
|
||||
let uri: URI | undefined = undefined
|
||||
if (t.lang) { // a language was provided. empty string is common so check truthy, not just undefined
|
||||
|
|
@ -151,6 +151,7 @@ const RenderToken = ({ token, inPTag, codeURI, chatMessageLocation, tokenIdx, ..
|
|||
applyBoxId={applyBoxId}
|
||||
initValue={contents}
|
||||
language={language}
|
||||
uri={uri || 'current'}
|
||||
>
|
||||
<BlockCode
|
||||
initValue={contents}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import React, { ButtonHTMLAttributes, FormEvent, FormHTMLAttributes, Fragment, K
|
|||
import { useAccessor, useSidebarState, useChatThreadsState, useChatThreadsStreamState, useUriState, useSettingsState } from '../util/services.js';
|
||||
|
||||
import { BlockCode } from '../markdown/BlockCode.js';
|
||||
import { ChatMarkdownRender, ChatMessageLocation } from '../markdown/ChatMarkdownRender.js';
|
||||
import { ChatMarkdownRender, ChatMessageLocation, getApplyBoxId } from '../markdown/ChatMarkdownRender.js';
|
||||
import { URI } from '../../../../../../../base/common/uri.js';
|
||||
import { IDisposable } from '../../../../../../../base/common/lifecycle.js';
|
||||
import { ErrorDisplay } from './ErrorDisplay.js';
|
||||
|
|
@ -30,6 +30,8 @@ import { AlertTriangle, ChevronRight, Dot, Pencil, X } from 'lucide-react';
|
|||
import { ChatMessage, StagingSelectionItem, ToolMessage, ToolRequestApproval } from '../../../../common/chatThreadServiceTypes.js';
|
||||
import { ToolCallParams, ToolName, ToolNameWithApproval } from '../../../../common/toolsServiceTypes.js';
|
||||
import { getLanguageFromModel } from '../../../../common/helpers/getLanguage.js';
|
||||
import { dirname } from '../../../../../../../base/common/resources.js';
|
||||
import { useApplyButtonHTML } from '../markdown/ApplyBlockHoverButtons.js';
|
||||
|
||||
|
||||
|
||||
|
|
@ -489,11 +491,11 @@ const ScrollToBottomContainer = ({ children, className, style, scrollContainerRe
|
|||
};
|
||||
|
||||
|
||||
|
||||
const getBasename = (pathStr: string) => {
|
||||
// 'unixify' path
|
||||
pathStr = pathStr.replace(/[/\\]+/g, '/') // replace any / or \ or \\ with /
|
||||
const parts = pathStr.split('/') // split on /
|
||||
if (parts.length === 0) return pathStr
|
||||
return parts[parts.length - 1]
|
||||
}
|
||||
|
||||
|
|
@ -679,7 +681,7 @@ type ToolHeaderParams = {
|
|||
onClick?: () => void;
|
||||
}
|
||||
|
||||
const ToolHeaderComponent = ({
|
||||
const ToolHeaderWrapper = ({
|
||||
icon,
|
||||
title,
|
||||
desc1,
|
||||
|
|
@ -696,7 +698,7 @@ const ToolHeaderComponent = ({
|
|||
const isClickable = !!(isDropdown || onClick)
|
||||
|
||||
return (<div className=''>
|
||||
<div className="w-full border border-void-border-3 rounded px-2 py-1 bg-void-bg-2-alt overflow-hidden">
|
||||
<div className="w-full border border-void-border-3 rounded px-2 py-1 bg-void-bg-3 overflow-hidden">
|
||||
{/* header */}
|
||||
<div
|
||||
className={`select-none flex items-center min-h-[24px] ${isClickable ? 'cursor-pointer hover:brightness-125 transition-all duration-150' : ''} ${!isDropdown ? 'mx-1' : ''}`}
|
||||
|
|
@ -710,13 +712,14 @@ const ToolHeaderComponent = ({
|
|||
className={`text-void-fg-3 mr-0.5 h-4 w-4 flex-shrink-0 transition-transform duration-100 ease-[cubic-bezier(0.4,0,0.2,1)] ${isExpanded ? 'rotate-90' : ''}`}
|
||||
/>
|
||||
)}
|
||||
<div className="flex items-center w-full gap-x-2 overflow-hidden">
|
||||
<div className="flex items-center w-full gap-x-2 overflow-hidden justify-between">
|
||||
{/* left */}
|
||||
<div className="flex items-center gap-x-2 min-w-0 overflow-hidden">
|
||||
<span className="text-void-fg-3 flex-shrink-0">{title}</span>
|
||||
|
||||
{/* Fixed description with proper ellipsis */}
|
||||
<span className="text-void-fg-4 text-xs italic truncate">{desc1}</span>
|
||||
</div>
|
||||
|
||||
{/* right */}
|
||||
<div className="flex items-center gap-x-2 flex-shrink-0">
|
||||
{desc2 && <span className="text-void-fg-4 text-xs">
|
||||
{desc2}
|
||||
|
|
@ -733,13 +736,13 @@ const ToolHeaderComponent = ({
|
|||
{/* children */}
|
||||
{<div
|
||||
className={`overflow-hidden transition-all duration-200 ease-in-out ${isExpanded ? 'opacity-100' : 'max-h-0 opacity-0'}
|
||||
text-void-fg-4 bg-black bg-opacity-20 border border-void-border-4 border-opacity-50 rounded-sm`}
|
||||
text-void-fg-4 rounded-sm`}
|
||||
// bg-black bg-opacity-10 border border-void-border-4 border-opacity-50
|
||||
>
|
||||
{children}
|
||||
</div>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
</div>);
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -939,28 +942,6 @@ const UserMessageComponent = ({ chatMessage, messageIdx, isLoading }: ChatBubble
|
|||
|
||||
|
||||
|
||||
export const ToolContentsWrapper = ({ children, className }: { children: React.ReactNode, className?: string }) => {
|
||||
return <div className={`${className ? className : ''} max-h-64 overflow-x-auto cursor-default select-none`}>
|
||||
<div className='px-2 py-1 min-w-full'>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
const ListableToolItem = ({ name, onClick, isSmall, className }: { name: string, onClick?: () => void, isSmall?: boolean, className?: string }) => {
|
||||
return <div
|
||||
className={`
|
||||
${onClick ? 'hover:brightness-125 hover:cursor-pointer transition-all duration-200 ' : ''}
|
||||
flex items-center flex-nowrap whitespace-nowrap
|
||||
${className ? className : ''}
|
||||
`}
|
||||
onClick={onClick}
|
||||
>
|
||||
<div className="flex-shrink-0"><svg className="w-1 h-1 opacity-60 mr-1.5 fill-current" viewBox="0 0 100 40"><rect x="0" y="15" width="100" height="10" /></svg></div>
|
||||
<div className={`${isSmall ? 'italic text-sm leading-4 flex items-center' : ''}`}>{name}</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
const AssistantMessageComponent = ({ chatMessage, isLoading, messageIdx, isLast }: ChatBubbleProps & { chatMessage: ChatMessage & { role: 'assistant' } }) => {
|
||||
|
||||
const accessor = useAccessor()
|
||||
|
|
@ -1141,9 +1122,54 @@ const ToolRequestAcceptRejectButtons = ({ voidToolId }: { voidToolId: string })
|
|||
</div>
|
||||
}
|
||||
|
||||
export const ToolContentsWrapper = ({ children, className }: { children: React.ReactNode, className?: string }) => {
|
||||
return <div className={`${className ? className : ''} overflow-x-auto cursor-default select-none`}>
|
||||
<div className='px-2 py-1 min-w-full'>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
const ListableToolItem = ({ name, onClick, isSmall, className, showDot }: { name: React.ReactNode, onClick?: () => void, isSmall?: boolean, className?: string, showDot?: boolean }) => {
|
||||
return <div
|
||||
className={`
|
||||
${onClick ? 'hover:brightness-125 hover:cursor-pointer transition-all duration-200 ' : ''}
|
||||
flex items-center flex-nowrap whitespace-nowrap
|
||||
${className ? className : ''}
|
||||
`}
|
||||
onClick={onClick}
|
||||
>
|
||||
{showDot === false ? null : <div className="flex-shrink-0"><svg className="w-1 h-1 opacity-60 mr-1.5 fill-current" viewBox="0 0 100 40"><rect x="0" y="15" width="100" height="10" /></svg></div>}
|
||||
<div className={`${isSmall ? 'italic text-void-fg-4 flex items-center' : ''}`}>{name}</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
const EditToolChildren = ({ uri, changeDescription }: { uri: URI, changeDescription: string }) => {
|
||||
const accessor = useAccessor()
|
||||
const commandService = accessor.get('ICommandService')
|
||||
return <ToolContentsWrapper className='bg-void-bg-3'>
|
||||
<ListableToolItem
|
||||
showDot={false}
|
||||
className='w-full overflow-auto mb-2'
|
||||
name={uri.fsPath}
|
||||
onClick={() => { commandService.executeCommand('vscode.open', uri, { preview: true }) }}
|
||||
/>
|
||||
<div className='select-auto cursor-auto'>
|
||||
<ChatMarkdownRender string={changeDescription} codeURI={uri} chatMessageLocation={undefined} />
|
||||
</div>
|
||||
</ToolContentsWrapper>
|
||||
}
|
||||
const EditToolApplyButton = ({ changeDescription, applyBoxId, uri }: { changeDescription: string, applyBoxId: string, uri: URI }) => {
|
||||
const { statusIndicatorHTML, buttonsHTML } = useApplyButtonHTML({ codeStr: changeDescription, applyBoxId, uri })
|
||||
return <div className='flex items-center gap-1'>
|
||||
{statusIndicatorHTML}
|
||||
{buttonsHTML}
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
const toolNameToComponent: { [T in ToolName]: {
|
||||
requestWrapper: T extends ToolNameWithApproval ? ((props: { toolRequest: ToolRequestApproval<T> }) => React.ReactNode) : null,
|
||||
resultWrapper: (props: { toolMessage: ToolMessage<T> }) => React.ReactNode,
|
||||
resultWrapper: (props: { toolMessage: ToolMessage<T>, messageIdx: number }) => React.ReactNode,
|
||||
} } = {
|
||||
'read_file': {
|
||||
requestWrapper: null,
|
||||
|
|
@ -1171,7 +1197,7 @@ const toolNameToComponent: { [T in ToolName]: {
|
|||
</>
|
||||
}
|
||||
|
||||
return <ToolHeaderComponent {...componentParams} />
|
||||
return <ToolHeaderWrapper {...componentParams} />
|
||||
},
|
||||
},
|
||||
'list_dir': {
|
||||
|
|
@ -1192,10 +1218,8 @@ const toolNameToComponent: { [T in ToolName]: {
|
|||
if (toolMessage.result.type === 'success') {
|
||||
const { value, params } = toolMessage.result
|
||||
componentParams.numResults = value.children?.length
|
||||
componentParams.children = <ToolContentsWrapper>
|
||||
{!value.children || (value.children.length ?? 0) === 0 ? <>
|
||||
<ListableToolItem name={'No results found.'} isSmall={true} />
|
||||
</> : <>
|
||||
componentParams.children = !value.children || (value.children.length ?? 0) === 0 ? undefined
|
||||
: <ToolContentsWrapper>
|
||||
{value.children.map((child, i) => (<ListableToolItem key={i}
|
||||
name={`${child.name}${child.isDirectory ? '/' : ''}`}
|
||||
onClick={() => {
|
||||
|
|
@ -1206,8 +1230,7 @@ const toolNameToComponent: { [T in ToolName]: {
|
|||
{value.hasNextPage &&
|
||||
<ListableToolItem name={`Results truncated (${value.itemsRemaining} remaining).`} isSmall={true} />
|
||||
}
|
||||
</>}
|
||||
</ToolContentsWrapper>
|
||||
</ToolContentsWrapper>
|
||||
}
|
||||
else {
|
||||
componentParams.children = <>
|
||||
|
|
@ -1215,7 +1238,7 @@ const toolNameToComponent: { [T in ToolName]: {
|
|||
</>
|
||||
}
|
||||
|
||||
return <ToolHeaderComponent {...componentParams} />
|
||||
return <ToolHeaderWrapper {...componentParams} />
|
||||
}
|
||||
},
|
||||
'pathname_search': {
|
||||
|
|
@ -1235,10 +1258,8 @@ const toolNameToComponent: { [T in ToolName]: {
|
|||
if (toolMessage.result.type === 'success') {
|
||||
const { value, params } = toolMessage.result
|
||||
componentParams.numResults = value.uris.length
|
||||
componentParams.children = <ToolContentsWrapper>
|
||||
{value.uris.length === 0 ? <>
|
||||
<ListableToolItem name={'No results found.'} isSmall={true} />
|
||||
</> : <>
|
||||
componentParams.children = value.uris.length === 0 ? undefined
|
||||
: <ToolContentsWrapper>
|
||||
{value.uris.map((uri, i) => (<ListableToolItem key={i}
|
||||
name={getBasename(uri.fsPath)}
|
||||
onClick={() => { commandService.executeCommand('vscode.open', uri, { preview: true }) }}
|
||||
|
|
@ -1246,8 +1267,8 @@ const toolNameToComponent: { [T in ToolName]: {
|
|||
{value.hasNextPage &&
|
||||
<ListableToolItem name={'Results truncated.'} isSmall={true} />
|
||||
}
|
||||
</>}
|
||||
</ToolContentsWrapper>
|
||||
|
||||
</ToolContentsWrapper>
|
||||
}
|
||||
else {
|
||||
componentParams.children = <>
|
||||
|
|
@ -1255,7 +1276,7 @@ const toolNameToComponent: { [T in ToolName]: {
|
|||
</>
|
||||
}
|
||||
|
||||
return <ToolHeaderComponent {...componentParams} />
|
||||
return <ToolHeaderWrapper {...componentParams} />
|
||||
}
|
||||
},
|
||||
'search': {
|
||||
|
|
@ -1275,10 +1296,8 @@ const toolNameToComponent: { [T in ToolName]: {
|
|||
if (toolMessage.result.type === 'success') {
|
||||
const { value, params } = toolMessage.result
|
||||
componentParams.numResults = value.uris.length
|
||||
componentParams.children = <ToolContentsWrapper>
|
||||
{value.uris.length === 0 ? <>
|
||||
<ListableToolItem name={'No results found.'} isSmall={true} />
|
||||
</> : <>
|
||||
componentParams.children = value.uris.length === 0 ? undefined
|
||||
: <ToolContentsWrapper>
|
||||
{value.uris.map((uri, i) => (<ListableToolItem key={i}
|
||||
name={getBasename(uri.fsPath)}
|
||||
onClick={() => { commandService.executeCommand('vscode.open', uri, { preview: true }) }}
|
||||
|
|
@ -1286,15 +1305,15 @@ const toolNameToComponent: { [T in ToolName]: {
|
|||
{value.hasNextPage &&
|
||||
<ListableToolItem name={`Results truncated.`} isSmall={true} />
|
||||
}
|
||||
</>}
|
||||
</ToolContentsWrapper>
|
||||
|
||||
</ToolContentsWrapper>
|
||||
}
|
||||
else {
|
||||
componentParams.children = <>
|
||||
{toolMessage.result.value}
|
||||
</>
|
||||
}
|
||||
return <ToolHeaderComponent {...componentParams} />
|
||||
return <ToolHeaderWrapper {...componentParams} />
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -1304,6 +1323,7 @@ const toolNameToComponent: { [T in ToolName]: {
|
|||
requestWrapper: ({ toolRequest }) => {
|
||||
const accessor = useAccessor()
|
||||
const commandService = accessor.get('ICommandService')
|
||||
const explorerService = accessor.get('IExplorerService')
|
||||
const title = toolNameToTitle[toolRequest.name].proposed
|
||||
const desc1 = toolNameToDesc(toolRequest.name, toolRequest.params)
|
||||
const icon = null
|
||||
|
|
@ -1312,9 +1332,13 @@ const toolNameToComponent: { [T in ToolName]: {
|
|||
const componentParams: ToolHeaderParams = { title, desc1, isError, icon, }
|
||||
|
||||
const { params } = toolRequest
|
||||
componentParams.onClick = () => { commandService.executeCommand('vscode.open', params.uri, { preview: true }) }
|
||||
|
||||
return <ToolHeaderComponent title={title} desc1={desc1} />
|
||||
// TODO!!! would be cool to open up the lowest parent that exists
|
||||
// componentParams.onClick = () => {
|
||||
// // open the parent
|
||||
// }
|
||||
|
||||
return <ToolHeaderWrapper {...componentParams} />
|
||||
},
|
||||
resultWrapper: ({ toolMessage }) => {
|
||||
const accessor = useAccessor()
|
||||
|
|
@ -1341,7 +1365,7 @@ const toolNameToComponent: { [T in ToolName]: {
|
|||
</>
|
||||
}
|
||||
|
||||
return <ToolHeaderComponent {...componentParams} />
|
||||
return <ToolHeaderWrapper {...componentParams} />
|
||||
}
|
||||
},
|
||||
'delete_uri': {
|
||||
|
|
@ -1358,7 +1382,7 @@ const toolNameToComponent: { [T in ToolName]: {
|
|||
const { params } = toolRequest
|
||||
componentParams.onClick = () => { commandService.executeCommand('vscode.open', params.uri, { preview: true }) }
|
||||
|
||||
return <ToolHeaderComponent {...componentParams} />
|
||||
return <ToolHeaderWrapper {...componentParams} />
|
||||
},
|
||||
resultWrapper: ({ toolMessage }) => {
|
||||
const accessor = useAccessor()
|
||||
|
|
@ -1384,7 +1408,7 @@ const toolNameToComponent: { [T in ToolName]: {
|
|||
</>
|
||||
}
|
||||
|
||||
return <ToolHeaderComponent {...componentParams} />
|
||||
return <ToolHeaderWrapper {...componentParams} />
|
||||
}
|
||||
},
|
||||
'edit': {
|
||||
|
|
@ -1399,21 +1423,16 @@ const toolNameToComponent: { [T in ToolName]: {
|
|||
const componentParams: ToolHeaderParams = { title, desc1, isError, icon, }
|
||||
|
||||
const { params } = toolRequest
|
||||
componentParams.children = <ToolContentsWrapper className='bg-void-bg-3'>
|
||||
<ListableToolItem
|
||||
name={getBasename(params.uri.fsPath)}
|
||||
onClick={() => { commandService.executeCommand('vscode.open', params.uri, { preview: true }) }}
|
||||
/>
|
||||
<div className='select-auto cursor-auto'>
|
||||
<ChatMarkdownRender string={params.changeDescription} codeURI={params.uri} chatMessageLocation={undefined} />
|
||||
</div>
|
||||
</ToolContentsWrapper>
|
||||
componentParams.children = <EditToolChildren
|
||||
uri={params.uri}
|
||||
changeDescription={params.changeDescription}
|
||||
/>
|
||||
|
||||
return <ToolHeaderComponent {...componentParams} />
|
||||
return <ToolHeaderWrapper {...componentParams} />
|
||||
},
|
||||
resultWrapper: ({ toolMessage }) => {
|
||||
resultWrapper: ({ toolMessage, messageIdx }) => {
|
||||
const accessor = useAccessor()
|
||||
const commandService = accessor.get('ICommandService')
|
||||
const chatThreadsService = accessor.get('IChatThreadService')
|
||||
const title = toolNameToTitle[toolMessage.name].past
|
||||
const desc1 = toolNameToDesc(toolMessage.name, toolMessage.result.params)
|
||||
const icon = null
|
||||
|
|
@ -1421,15 +1440,25 @@ const toolNameToComponent: { [T in ToolName]: {
|
|||
const isError = toolMessage.result.type === 'error'
|
||||
const componentParams: ToolHeaderParams = { title, desc1, isError, icon }
|
||||
|
||||
if (toolMessage.result.type === 'success') {
|
||||
if (toolMessage.result.type === 'success' || toolMessage.result.type === 'rejected') {
|
||||
const { params } = toolMessage.result
|
||||
componentParams.children = <ChatMarkdownRender string={params.changeDescription} codeURI={params.uri} chatMessageLocation={undefined} />
|
||||
componentParams.onClick = () => { commandService.executeCommand('vscode.open', params.uri, { preview: true }) }
|
||||
}
|
||||
else if (toolMessage.result.type === 'rejected') {
|
||||
const { params } = toolMessage.result
|
||||
componentParams.children = <ChatMarkdownRender string={params.changeDescription} codeURI={params.uri} chatMessageLocation={undefined} />
|
||||
componentParams.onClick = () => { commandService.executeCommand('vscode.open', params.uri, { preview: true }) }
|
||||
|
||||
const threadId = chatThreadsService.getCurrentThread().id
|
||||
const applyBoxId = getApplyBoxId({
|
||||
threadId: threadId,
|
||||
messageIdx: messageIdx,
|
||||
tokenIdx: 'N/A',
|
||||
})
|
||||
|
||||
componentParams.children = <EditToolChildren
|
||||
uri={params.uri}
|
||||
changeDescription={params.changeDescription}
|
||||
/>
|
||||
componentParams.desc2 = <EditToolApplyButton
|
||||
changeDescription={params.changeDescription}
|
||||
applyBoxId={applyBoxId}
|
||||
uri={params.uri}
|
||||
/>
|
||||
}
|
||||
else if (toolMessage.result.type === 'error') {
|
||||
componentParams.children = <>
|
||||
|
|
@ -1437,7 +1466,7 @@ const toolNameToComponent: { [T in ToolName]: {
|
|||
</>
|
||||
}
|
||||
|
||||
return <ToolHeaderComponent {...componentParams} />
|
||||
return <ToolHeaderWrapper {...componentParams} />
|
||||
}
|
||||
},
|
||||
'terminal_command': {
|
||||
|
|
@ -1458,8 +1487,7 @@ const toolNameToComponent: { [T in ToolName]: {
|
|||
if (!waitForCompletion)
|
||||
componentParams.desc2 = '(background task)'
|
||||
|
||||
// TODO!!! open terminal
|
||||
return <ToolHeaderComponent {...componentParams} />
|
||||
return <ToolHeaderWrapper {...componentParams} />
|
||||
},
|
||||
resultWrapper: ({ toolMessage }) => {
|
||||
const accessor = useAccessor()
|
||||
|
|
@ -1510,9 +1538,7 @@ const toolNameToComponent: { [T in ToolName]: {
|
|||
</>
|
||||
}
|
||||
|
||||
// TODO!!! open terminal
|
||||
|
||||
return <ToolHeaderComponent {...componentParams} />
|
||||
return <ToolHeaderWrapper {...componentParams} />
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -1551,8 +1577,8 @@ const ChatBubble = ({ chatMessage, isLoading, messageIdx, isLast }: ChatBubblePr
|
|||
</>
|
||||
}
|
||||
else if (role === 'tool') {
|
||||
const ToolResultWrapper = toolNameToComponent[chatMessage.name].resultWrapper as React.FC<{ toolMessage: any }> // ts isnt smart enough...
|
||||
return <ToolResultWrapper toolMessage={chatMessage} />
|
||||
const ToolResultWrapper = toolNameToComponent[chatMessage.name].resultWrapper as React.FC<{ toolMessage: any, messageIdx: number }> // ts isnt smart enough...
|
||||
return <ToolResultWrapper toolMessage={chatMessage} messageIdx={messageIdx} />
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,10 +67,10 @@ const markdownLangToVscodeLang: { [key: string]: string } = {
|
|||
'less': 'less',
|
||||
'javascript': 'typescript',
|
||||
'js': 'typescript', // use more general renderer
|
||||
'jsx': 'typescript',
|
||||
'jsx': 'typescriptreact',
|
||||
'typescript': 'typescript',
|
||||
'ts': 'typescript',
|
||||
'tsx': 'typescript',
|
||||
'tsx': 'typescriptreact',
|
||||
'json': 'json',
|
||||
'jsonc': 'json',
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue