feat(web): show subagent task trace in tool dialog#539
Merged
tiann merged 3 commits intotiann:mainfrom Apr 28, 2026
Merged
Conversation
Task tool modals previously showed only Input and Result. This adds a Trace section between them that surfaces the child tool calls already wired through the reducer into block.children. - TraceSection collapses by default when completed, expands when running or error so the relevant state is visible on open - Each child row toggles an inline expand (Input/Result) to avoid nested Dialogs - Header summarises call count, token total and duration via readSummaryFields() typed parser, falling back gracefully when any value is absent - formatTaskChildLabel / TaskStateIcon imported from shared helpers.tsx (extracted in prior refactor commit) — no local duplicates - Task name guard: getTaskTraceChildren returns null for non-Task blocks - children prop renamed to items in TraceSectionInner / TraceChildList (react/no-children-prop anti-pattern removed) - i18n: tool.trace and tool.trace.callsSuffix keys added for en and zh-CN; useTranslation hooked up to header label and calls suffix - 15 unit tests: getTaskTraceChildren (guard, filter, non-Task null), getTraceSummaryText (3 branches), TraceSection (open/close/toggle/ summary/empty)
There was a problem hiding this comment.
Findings
- [Minor] Expanded trace rows omit child input — expanding a child call currently renders only the result, so calls whose important details live in
input(for exampleBash.command,Edit.old_string/new_string, orWrite.content) still cannot be inspected from the Task trace. Evidence:web/src/components/ToolCard/trace.tsx:216.
Suggested fix:const FullInputView = getToolFullViewComponent(child.tool.name) const { t } = useTranslation() {expanded && ( <div className="ml-8 flex flex-col gap-2 rounded border border-[var(--app-border)] p-2"> <div> <div className="mb-1 text-xs font-medium text-[var(--app-hint)]">{t('tool.input')}</div> {FullInputView ? ( <FullInputView block={child} metadata={metadata} /> ) : ( <CodeBlock code={safeStringify(child.tool.input)} language="json" /> )} </div> <div> <div className="mb-1 text-xs font-medium text-[var(--app-hint)]">{t('tool.result')}</div> <ResultView block={child} metadata={metadata} /> </div> </div> )}
Questions
- None.
Summary
- Review mode: initial
- One functional gap found in the new trace UI. Residual risk: I could not execute the test suite in this runner.
Testing
- Not run (automation):
bunis not installed in the runner (bun: command not found).
HAPI Bot
|
|
||
| {expanded && ( | ||
| <div className="ml-8 flex flex-col gap-2 rounded border border-[var(--app-border)] p-2"> | ||
| <ResultView block={child} metadata={metadata} /> |
There was a problem hiding this comment.
[MINOR] Expanded trace rows omit child input
TraceChildRow only renders <ResultView block={child} ... /> when a child is expanded. That leaves important call details hidden for tools where the meaningful data is in child.tool.input, such as Bash.command, Edit.old_string/new_string, or Write.content, so the trace still does not let users inspect what the subagent actually invoked.
Suggested fix:
const FullInputView = getToolFullViewComponent(child.tool.name)
const { t } = useTranslation()
{expanded && (
<div className="ml-8 flex flex-col gap-2 rounded border border-[var(--app-border)] p-2">
<div>
<div className="mb-1 text-xs font-medium text-[var(--app-hint)]">{t('tool.input')}</div>
{FullInputView ? (
<FullInputView block={child} metadata={metadata} />
) : (
<CodeBlock code={safeStringify(child.tool.input)} language="json" />
)}
</div>
<div>
<div className="mb-1 text-xs font-medium text-[var(--app-hint)]">{t('tool.result')}</div>
<ResultView block={child} metadata={metadata} />
</div>
</div>
)}Expanded child rows in the Task trace section now render both an Input section and a Result section, matching the pattern used in the parent ToolCard dialog. Tools with a registered FullInputView use it; all others fall back to a JSON CodeBlock. Closes bot review on PR tiann#539.
There was a problem hiding this comment.
Findings
- None.
Questions
- None.
Summary
- Review mode: follow-up after new commits
- No blocking correctness, security, regression, data loss, performance, or maintainability issues found in the latest diff. The follow-up commit addresses the prior bot finding by rendering expanded child input along with result output. Residual risk: validation is based on static review only.
Testing
- Not run (automation; PR code not executed during review)
HAPI Bot
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When a session uses the Task (subagent) tool, the tool dialog currently
shows only Input and Result. The child tool calls that run inside the
subagent (Glob, Grep, Read, …) are already wired through the reducer into
block.children, but the modal never renders them, leaving the user withno visibility into what the subagent actually did.
Solution
Adds a Trace section between Input and Result in the Task tool dialog.
The section surfaces the existing
block.childrenarray without any newdata plumbing.
runninganderrorexpand (user opened the dialog to see progress or diagnose a failure);
completedcollapses (Result is the primary content, Trace is secondary).(N calls · M.Mk tok · S.Ss), readingresult.totalToolUseCount / totalTokens / totalDurationMswithgraceful fallback when any field is absent.
without opening a nested Dialog.
result.*fields — the field is typedunknownat the call site, so all numeric reads go through
isObjectguards.child tool calls, so non-Task tools are unaffected.
Screenshots
Tests
14 new unit tests in
web/src/components/ToolCard/trace.test.tsx:getTaskTraceChildren— null for empty children, filters non-tool-call nodesgetTraceSummaryText— all three fallback branchesTraceSection— empty renders nothing; children render header; running/errordefault to expanded; completed defaults to collapsed; toggle inverts state;
summary text visible in header
All existing tests continue to pass (
bun run test, 187 total).i18n
tool.tracekey added forenandzh-CN.