-
Notifications
You must be signed in to change notification settings - Fork 7
feat(staged): forward tool call raw_input params through ACP driver to DB #495
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -64,12 +64,46 @@ const TOOL_VERBS: Record<string, [past: string, present: string]> = { | |
| Grep: ['Searched', 'Searching'], | ||
| Search: ['Searched', 'Searching'], | ||
| Glob: ['Listed', 'Listing'], | ||
| Edit: ['Edited', 'Editing'], | ||
| StrReplace: ['Edited', 'Editing'], | ||
| Delete: ['Deleted', 'Deleting'], | ||
| EditNotebook: ['Edited', 'Editing'], | ||
| SemanticSearch: ['Searched', 'Searching'], | ||
| }; | ||
|
|
||
| /** Pick the single most useful display value from structured tool args. */ | ||
| function primaryArg(toolName: string, args: Record<string, unknown>): string { | ||
| const str = (key: string) => { | ||
| const v = args[key]; | ||
| return typeof v === 'string' ? v : undefined; | ||
| }; | ||
| switch (toolName) { | ||
| case 'Read': | ||
| case 'ReadFile': | ||
| case 'Write': | ||
| case 'WriteFile': | ||
| case 'Edit': | ||
| case 'Delete': | ||
| case 'EditNotebook': | ||
| case 'StrReplace': | ||
| return str('file_path') || str('path') || ''; | ||
| case 'Run': | ||
| case 'Shell': | ||
| case 'Bash': | ||
| return str('command') || str('cmd') || ''; | ||
| case 'Grep': | ||
| case 'Search': | ||
| case 'SemanticSearch': | ||
| return str('pattern') || str('query') || ''; | ||
| case 'Glob': | ||
| return str('pattern') || str('glob') || ''; | ||
| default: { | ||
| const formatted = formatArgs(args); | ||
| return formatted.length > 200 ? formatted.slice(0, 200) + '…' : formatted; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| const TITLE_VERBS = new Set([ | ||
| 'Add', | ||
| 'Analyze', | ||
|
|
@@ -211,19 +245,51 @@ export function formatToolDisplay( | |
| const tenseIdx = pending ? 1 : 0; | ||
| const parsed = parseToolCall(content); | ||
| if (parsed) { | ||
| const entry = TOOL_VERBS[parsed.name]; | ||
| const verb = entry ? entry[tenseIdx] : parsed.name; | ||
| return { verb, detail: makePathsRelative(formatArgs(parsed.args), repoDir) }; | ||
| // parsed.name may be a bare tool name ("Read") or a full ACP title | ||
| // ("Read /path/to/file"). Try exact match first, then first-word match. | ||
| let toolName = parsed.name; | ||
| let entry = TOOL_VERBS[toolName]; | ||
| if (!entry) { | ||
| const spaceIdx = parsed.name.indexOf(' '); | ||
| if (spaceIdx > 0) { | ||
| const firstWord = parsed.name.slice(0, spaceIdx); | ||
| if (TOOL_VERBS[firstWord]) { | ||
| toolName = firstWord; | ||
| entry = TOOL_VERBS[firstWord]; | ||
| } | ||
| } | ||
| } | ||
| if (entry) { | ||
| const verb = entry[tenseIdx]; | ||
| const detail = makePathsRelative(primaryArg(toolName, parsed.args), repoDir); | ||
| return { verb, detail }; | ||
| } | ||
| // Unrecognized tool name — fall through to treat parsed.name as plain text | ||
| content = parsed.name; | ||
|
Comment on lines
+267
to
+268
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For parsed JSON tool calls whose Useful? React with 👍 / 👎. |
||
| } | ||
|
|
||
| // Plain-text content: check TOOL_VERBS first (handles "Shell", "Bash ls", etc.) | ||
| const spaceIdx = content.indexOf(' '); | ||
| if (spaceIdx > 0) { | ||
| const firstWord = content.slice(0, spaceIdx); | ||
| const tvEntry = TOOL_VERBS[firstWord]; | ||
| if (tvEntry) { | ||
| return { | ||
| verb: tvEntry[tenseIdx], | ||
| detail: makePathsRelative(content.slice(spaceIdx + 1), repoDir), | ||
| }; | ||
| } | ||
| if (TITLE_VERBS.has(firstWord)) { | ||
| return { verb: firstWord, detail: makePathsRelative(content.slice(spaceIdx + 1), repoDir) }; | ||
| } | ||
| } else if (TITLE_VERBS.has(content)) { | ||
| return { verb: content, detail: '' }; | ||
| } else { | ||
| const tvEntry = TOOL_VERBS[content]; | ||
| if (tvEntry) { | ||
| return { verb: tvEntry[tenseIdx], detail: '' }; | ||
| } | ||
| if (TITLE_VERBS.has(content)) { | ||
| return { verb: content, detail: '' }; | ||
| } | ||
| } | ||
|
|
||
| return { verb: pending ? 'Running' : 'Ran', detail: makePathsRelative(content, repoDir) }; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a tool call is first stored with
raw_input, a laterToolCallUpdatethat only changestitlereaches this code withraw_input: None, andformat_tool_call_contentrewrites the DB row as plain text. That silently drops the previously persisted input JSON, so the UI loses structured parameters after a title change. This is a regression in the new raw-input flow and will appear whenever ACP emits title updates without re-sendingraw_input.Useful? React with 👍 / 👎.