Render agent tool call messages in the Wind chat on the apollo-wind
ToolCall primitive (status line, input, traces, escalation task links,
errors and output per display mode) and tree messages as a disclosure
tree, both registered as Wind built-ins behind injected renderers.
Hoist the renderer-agnostic reading of tool calls and trees into
src/chat/headless and switch Material to it: status from input, output
and the span tree, tool name and duration, task URLs, section values,
the span icon lookup and its SVG set, and the tree row model. Task
links are only rendered for http(s) or relative URLs in both renderers.
MST-16565
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Summary
Fourth PR of the Wind chat renderer stack (MST-16565): agent tool call messages (
AGENTS_TOOL_CALL_RENDERER) and tree messages (APOLLO_CHAT_TREE_RENDERER) render in Wind. Both are registered as Wind built-ins, and a renderer injected on the service still wins (tested).Tool call: apollo-wind
ToolCallStatus: Material's state maps to the primitive's status.
executing;failed;completed;completed, because Material's line then reads "Ran".The line reads "Running 'x'" or "Ran 'x' for 1.23 seconds", as Material's does, and is localized.
Display modes:
ToolNameOnlyomitsToolCallContent, so only the status line shows.InputsAndOutputsandFullTraceget the body.Sections:
CodeBlock(renderValue) and objects through the primitive's JSON tree.FullTraceadds a Traces section: nested trace items with Material's span icons, model calls and agent output left out.Stable state: which parts are open (the card, Input, Output, Errors, Traces, Escalation and each trace row) is held by the renderer, as in Material, so it survives the finished call being re-sent under the same id and closing and reopening the card. The ported "stays expanded when the tool result replaces the message" test covers it, including an open Input section. Auto-opening for escalation happens once, so a re-send does not reopen a card the reader closed. A failure without input shows as failed. Trace rows and their icons are built level by level, only while the Traces section and the row are open.
Tree: disclosure tree, not apollo-wind
TreeViewThe tree message renders as a nested disclosure list built from apollo-wind
Tooltipand Tailwind. The same component is shared with the tool call's Traces section.expanded: false, as in Material.titleColor), a lucide icon viaServiceIcon, andadditionalInfoon the right. It gets a tooltip only when the span has a description; a described leaf row is focusable, so keyboard users get the tooltip too. Rows use the tool call section's styling (text-emphasis hover, chevron, indentation), so a trace inside a tool call and a tree message read alike. The tree model no longer supplies a "No description" placeholder, which also removes it from Material.apollo-wind's
TreeView(FileTreeView) is a file-manager component and does not fit here (see the open decision):Hoisted into
src/chat/headlesstool-call/tool-call-model.tsgetToolCallState(from input, output and the span tree, including child errors);getToolCallName;getToolCallDurationSeconds;getTaskUrls;getToolCallValues(input, error and output as Material picks them);getVisibleTraceChildren;getSpanAttributesApToolCall.tsxuses all of themtool-call/span-icon.ts,tool-call/span-icons.tsap-tool-call/utilsandap-tool-call/assetsApToolCall.tsximports them from heretree/chat-tree.ts:toChatTreeItem,getExpandedTreeIdstree-renderer.tsxdefault transform and expanded idsutils/openable-url.ts:isOpenableUrlToolCallSection.tsxtask links (see below)Security: escalation task links come from the backend. Both renderers now render them as links only when they are http(s) or relative; anything else shows as plain text. This also changes Material, which previously linked any scheme.
Storybook
pnpm storybook:design, Apollo React / Chat / Playground, then Compare renderers withscenario:FullTracecall waiting on two escalation task links, which opens by itself.Tests
vitest --run src/chat src/material/components/ap-chat src/material/components/ap-tool-call: 43 files, 237 tests pass. New tests cover:ToolNameOnlywithout a toggle;FullTrace, without model calls;javascript:URL;expanded: falseclosed.tsc --noEmit: clean.biome checkon touched files: no errors; two warnings already present in Material (its trace icondangerouslySetInnerHTMLand ananyinToolCallSection.tsx). The first push had a format error inheadless/tree/chat-tree.ts, now fixed.New strings, in
en.jsononly:The running and ran lines double their apostrophes, since a single
'starts a quoted literal in ICU.Stack
Jira: MST-16565
🤖 Generated with Claude Code