feat(cli): show reasoning + activity journal in the TUI#48
Merged
Conversation
The Ink TUI dropped say:reasoning at two points (useChatMessages filter + a ChatMessage early return), so the model's chain-of-thought was never visible interactively — even though the core streams it and the ACP path already surfaces it as agent_thought_chunk. Render reasoning dimmed + italic (distinct from the answer), streamed live in the dynamic zone and kept in scroll history. Also show full command output once a command completes (was truncated to 8 lines), keeping a bounded tail while it runs. Adds ChatMessage reasoning render tests.
Stop filtering api_req_started, checkpoint_created and api_req_retried in the TUI and render them as compact dim markers (→ querying <model>, ✓ checkpoint saved, ⟳ retrying) so the user sees what the agent is doing between answers. Replaces the old api_req_started null-return that hid the request entirely. Adds render tests.
There was a problem hiding this comment.
Pull request overview
This PR improves the interactive CLI TUI’s visibility into what the agent is doing by rendering previously-hidden “reasoning” (say: "reasoning") and adding compact “activity journal” rows for key operational events (API request started, checkpoint created, request retried). It also changes command output rendering to show more output while executing and (intended) full output once completed.
Changes:
- Stop filtering out
reasoning,api_req_started,checkpoint_created, andapi_req_retriedinuseChatMessages, allowing them into the TUI message stream. - Render activity journal markers and streamed reasoning in
ChatMessagewith distinct styling. - Add render tests covering reasoning and activity journal markers.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| cli/src/hooks/useChatMessages.ts | Removes message filtering that previously suppressed reasoning and activity markers from the TUI stream. |
| cli/src/components/ChatMessage.tsx | Adds activity journal + reasoning rendering and adjusts command output line limiting behavior. |
| cli/src/components/ChatMessage.test.tsx | Adds tests to validate reasoning and activity journal rendering. |
Comments suppressed due to low confidence (2)
cli/src/components/ChatMessage.tsx:503
- While a command is running, this currently shows the first 20 lines of output (because
formatToolResulttakes a head slice). For long-running commands that stream progress at the end (common for build tools), this hides the most relevant recent output. If the intent is a “bounded tail while running”, render the last N lines instead (and optionally add an “... X more lines above” marker).
{output && (
<Box flexDirection="column" marginLeft={2} width="100%">
{formatToolResult(output, isExecuting ? 20 : Number.MAX_SAFE_INTEGER).map((line, idx) => (
<ResultRow isFirst={idx === 0} key={idx}>
<Text color="gray">{line}</Text>
</ResultRow>
))}
</Box>
cli/src/components/ChatMessage.tsx:503
- While a command is running, this currently shows the first 20 lines of output (because
formatToolResulttakes a head slice). For long-running commands that stream progress at the end (common for build tools), this hides the most relevant recent output. If the intent is a “bounded tail while running”, render the last N lines instead (and optionally add an “... X more lines above” marker).
{output && (
<Box flexDirection="column" marginLeft={2} width="100%">
{formatToolResult(output, isExecuting ? 20 : Number.MAX_SAFE_INTEGER).map((line, idx) => (
<ResultRow isFirst={idx === 0} key={idx}>
<Text color="gray">{line}</Text>
</ResultRow>
))}
</Box>
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+316
to
+318
| if (say === "api_req_started") { | ||
| const modelId = (message as { modelInfo?: { modelId?: string } }).modelInfo?.modelId | ||
| return ( |
Comment on lines
+316
to
+318
| if (say === "api_req_started") { | ||
| const modelId = (message as { modelInfo?: { modelId?: string } }).modelInfo?.modelId | ||
| return ( |
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.
Make agent activity visible in the TUI
Two related TUI improvements so the user sees what the agent is doing.
Show the reasoning stream
The Ink TUI dropped
say:reasoningat two points (auseChatMessagesfilter and aChatMessageearly-return), so the model's chain-of-thought was never visible interactively — even though the core streams it (AgentLoopRunner→say("reasoning", partial)) and the ACP path already surfaces it asagent_thought_chunk. Now rendered dimmed + italic (distinct from the answer), streamed live in the dynamic zone and kept in scroll history.Surface an activity journal
api_req_started,checkpoint_createdandapi_req_retriedwere filtered out (only a generic spinner showed). Now rendered as compact dim markers:→ querying <model>,✓ checkpoint saved,⟳ retrying request…. Replaces the oldapi_req_startednull-return.Also: command output is shown in full once a command completes (was truncated to 8 lines), with a bounded tail while running.
Verification
typecheck·cli test(6 new render tests) ·lint— all green under Node 22.Note (separate issue, not this PR)
isaac task -m <reasoning-model>headless currently 401s — runtime instrumentation proved the CLI sends the correct gateway baseUrl + key and the gateway accepts the equivalent curl, so the 401 originates gateway-side and needs gateway-log investigation. It does not affect interactive mode (the path this PR improves), where reasoning displays correctly when the routed model emits it.