refactor(tools): tagged render-intent union for tool-call presentation
Replace the "bag of optional fields" tool-presentation types
(ToolCallPresentation / ToolResultPresentation / ToolTerminal) with a
card-tagged discriminated union — the standing FIXME(tool-presentation).
A tool declares one render intent per call/result and the ACP bridge
switches on `card`:
ToolCallView = generic | terminal | diff
ToolResultView = generic | terminal
The `diff` card is new: fs write/edit now emit an ACP {type:'diff'}
content block (an editor's inline diff), which the old shapes could not
express. The bridge also relativizes a file card's title against the
session cwd (mirroring claude-agent-acp's toDisplayPath) while keeping
locations/diff paths raw, and derives the no-capability fenced console
fallback from a terminal result's output. read gains the window-in-title
(`Read foo.txt (5 - 8)`) and an always-set location line, matching the
reference adapter field-for-field.
Migrates all three producer families (tool-fs, tool-bash, tool-todo) and
the sole consumer (the ACP bridge) together — the source does not compile
piecewise. Adds snapshot coverage for the terminal _meta path (a new
capability-advertising scenario) and re-records the fs goldens to show the
diff cards. Applied-hunk (result-time, context-line) diffs need a new
result/event shape and are a follow-up.
RFC: docs/rfc/implemented/architecture/2026-07-02-tool-render-intent-union.md
This commit is contained in:
@@ -118,6 +118,6 @@ export function apply(ctx: Context): void {
|
||||
text: `Updated todo list: ${count('pending')} pending, ${count('in_progress')} in progress, ${count('completed')} completed.`,
|
||||
}])
|
||||
},
|
||||
presentCall: args => ({ title: 'Update todo list', kind: 'other', rawInput: args.todos }),
|
||||
presentCall: args => ({ card: 'generic', title: 'Update todo list', kind: 'other', rawInput: args.todos }),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ describe('dsh-tool-todo', () => {
|
||||
const ctx = await setup()
|
||||
const def = ctx.tools.get('todo_write')!
|
||||
const todos = [{ content: 'a', status: 'pending' }]
|
||||
expect(def.presentCall?.({ todos })).toEqual({ title: 'Update todo list', kind: 'other', rawInput: todos })
|
||||
expect(def.presentCall?.({ todos })).toEqual({ card: 'generic', title: 'Update todo list', kind: 'other', rawInput: todos })
|
||||
})
|
||||
|
||||
it('unregisters the tool when its contributing fiber is disposed (HMR-safety)', async () => {
|
||||
|
||||
Reference in New Issue
Block a user