feat(ui): single-line tool indicator on Feishu/Telegram, heartbeat on WeChat#268
Merged
Conversation
… WeChat
Users repeatedly told us the running tool-call list is noise — they only
care about the final answer. Replace the ever-growing per-tool list with
one summary line, and hide the section entirely once the turn finishes.
Feishu card builders (v1 + v2)
- One line during in-flight states: `⏳ <latest tool> · N tools`.
- Section disappears on `complete` / `error`; card shows only the user
prompt, the final response, and the grey footer stats.
- No new `CardState` fields — derive the indicator from
`state.toolCalls[last]` + `.length`, so web UI's collapsible per-tool
view (already the preferred surface for users who want detail)
keeps working unchanged.
Telegram sender
- Same single-line treatment + hide-on-complete; matches Feishu cards.
WeChat sender
- Per-batch progress text is the noisiest surface (WeChat can't edit
messages, so each tool batch lands as a new chat message every 5s).
Replaced with a single-line heartbeat throttled to 30s:
`🔧 运行中:<tool> · N tools`. Long runs still show signs of life
without flooding the thread.
- Drops the unused `CardStatus` import while we're here.
Tests
- card-builder + card-builder-v2: assert single-line render during
`running`, and zero tool-related element on `complete`.
288 / 288 vitest pass. Lint clean (2 pre-existing warnings, untouched).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
floodsung
added a commit
that referenced
this pull request
May 14, 2026
…se, show only final result (#269) PR #268 hid the running tool list from the main card. The "Agent activity between turns" spontaneous card had the same problem one layer deeper — it accumulated every assistant message (including bare `tool_use` blocks that rendered as `🔧 Bash`/`🔧 Read` lines) into a numbered list, exactly the play-by-play we just hid from the main card. Apply the same UX bet here: - `extractSpontaneousSnippet`: tool_use-only assistant messages now return null. Text snippets (the agent's actual conclusion) still survive. Mixed messages still surface the text and ignore the adjacent tool_use, same as before. - `formatSpontaneousCardBody`: render only the LATEST snippet (the conclusion of the burst), not a numbered list of all snippets. When N>1 were coalesced, append a small `_(N events coalesced; showing latest)_` footer so the user knows there was more activity if they want to dig into pm2 logs or the web UI. Side effects: - A between-turn burst that produced ONLY tool calls (no agent text) no longer triggers a card at all — the buffer stays empty, the 30 s flush is a no-op. This is the correct outcome: nothing user-meaningful to report. - The continuation-turn render path (handleContinuationTurn) was already covered by PR #268 since it goes through the same card-builder.ts surface. No change needed there. Tests: - extractSpontaneousSnippet: assert tool_use-only returns null, text+tool_use still returns the text, multi-tool_use returns null. - formatSpontaneousCardBody: assert single-snippet renders without a numbered prefix; N>1 renders the latest snippet plus the coalesced-count footer, and the earlier snippets are NOT in the body. 290/290 vitest pass. Build + lint clean (2 pre-existing warnings). Co-authored-by: Flood Sung <floodsung@xvirobotics.ai> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
SimonYeyi
pushed a commit
to SimonYeyi/metabot
that referenced
this pull request
May 26, 2026
… WeChat (xvirobotics#268) Users repeatedly told us the running tool-call list is noise — they only care about the final answer. Replace the ever-growing per-tool list with one summary line, and hide the section entirely once the turn finishes. Feishu card builders (v1 + v2) - One line during in-flight states: `⏳ <latest tool> · N tools`. - Section disappears on `complete` / `error`; card shows only the user prompt, the final response, and the grey footer stats. - No new `CardState` fields — derive the indicator from `state.toolCalls[last]` + `.length`, so web UI's collapsible per-tool view (already the preferred surface for users who want detail) keeps working unchanged. Telegram sender - Same single-line treatment + hide-on-complete; matches Feishu cards. WeChat sender - Per-batch progress text is the noisiest surface (WeChat can't edit messages, so each tool batch lands as a new chat message every 5s). Replaced with a single-line heartbeat throttled to 30s: `🔧 运行中:<tool> · N tools`. Long runs still show signs of life without flooding the thread. - Drops the unused `CardStatus` import while we're here. Tests - card-builder + card-builder-v2: assert single-line render during `running`, and zero tool-related element on `complete`. 288 / 288 vitest pass. Lint clean (2 pre-existing warnings, untouched). Co-authored-by: Flood Sung <floodsung@xvirobotics.ai> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
SimonYeyi
pushed a commit
to SimonYeyi/metabot
that referenced
this pull request
May 26, 2026
…se, show only final result (xvirobotics#269) PR xvirobotics#268 hid the running tool list from the main card. The "Agent activity between turns" spontaneous card had the same problem one layer deeper — it accumulated every assistant message (including bare `tool_use` blocks that rendered as `🔧 Bash`/`🔧 Read` lines) into a numbered list, exactly the play-by-play we just hid from the main card. Apply the same UX bet here: - `extractSpontaneousSnippet`: tool_use-only assistant messages now return null. Text snippets (the agent's actual conclusion) still survive. Mixed messages still surface the text and ignore the adjacent tool_use, same as before. - `formatSpontaneousCardBody`: render only the LATEST snippet (the conclusion of the burst), not a numbered list of all snippets. When N>1 were coalesced, append a small `_(N events coalesced; showing latest)_` footer so the user knows there was more activity if they want to dig into pm2 logs or the web UI. Side effects: - A between-turn burst that produced ONLY tool calls (no agent text) no longer triggers a card at all — the buffer stays empty, the 30 s flush is a no-op. This is the correct outcome: nothing user-meaningful to report. - The continuation-turn render path (handleContinuationTurn) was already covered by PR xvirobotics#268 since it goes through the same card-builder.ts surface. No change needed there. Tests: - extractSpontaneousSnippet: assert tool_use-only returns null, text+tool_use still returns the text, multi-tool_use returns null. - formatSpontaneousCardBody: assert single-snippet renders without a numbered prefix; N>1 renders the latest snippet plus the coalesced-count footer, and the earlier snippets are NOT in the body. 290/290 vitest pass. Build + lint clean (2 pre-existing warnings). Co-authored-by: Flood Sung <floodsung@xvirobotics.ai> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
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.
Summary
Users repeatedly told us the per-tool list inside the running card is noise — they read the final response, not the intermediate Read/Edit/Bash trail. This PR replaces the ever-growing tool list with one summary line and hides the section entirely once the turn finishes.
What changes
Why now
User asked for it after consistent feedback that "现在已经没人看中间的工具调用了". The hung-run signal still has a home: while the turn is in flight, the one-line indicator keeps updating, so users can tell whether the card is alive or frozen.
Test plan
🤖 Generated with Claude Code