fix(mobile-chat): render tool-call chain + suppress false 'unreachable' banner while agent works #2789
Reference in New Issue
Block a user
Delete Branch "fix/mobile-chat-tooltrace-and-banner"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Two mobile-chat gaps, both reported from a live SEO-agent screenshot during a long (1100-file download) turn.
1. Mobile was missing the tool-call chain
MobileChatrendered only message text + attachments, dropping agent messages'toolTraceentirely — so a long tool-using turn showed as a bare reply with no visible work. DesktopChatTabrenders it viaToolTraceChips. Mobile now reuses that same renderer under the agent bubble (collapsed-by-default chip list), consistent with how mobile already reusesAgentCommsPanel/AttachmentPreview(#231 parity). The trace data already rides on the shareduseChatHistory/useChatSocketmessages — mobile just never rendered it.2. False "Failed to send — agent may be unreachable" banner under the live "●●● 148s" timer
Root cause: the clear-on-thinking effect only fires on the thinking transition. A non-524 send error that lands mid-turn — a long poll-mode turn whose POST times out at the Cloudflare edge (504/522) while the workspace still reports
currentTask— setssendErrorwithout re-triggering the effect, so the banner shows under the live thinking timer. Self-contradictory: the agent is provably working.Fix: gate the banner at render-time on
!thinking(sending in flight ORcurrentTaskset). Applied to bothMobileChatand desktopChatTab— same latent bug, keeps parity. A still-unresolved error resurfaces normally once the turn ends. (Complements the existing 524-swallow inuseChatSend: 524 = accepted+slow → no error; 504/522 = genuinely unreachable → error, but now suppressed while the agent is demonstrably working.)Tests
MobileChat.test.tsx(+4): tool-chain renders + expands; no affordance whentool_traceabsent; banner suppressed whilecurrentTaskset (with the thinking indicator still present — the exact contradiction); banner still shown when a send fails and the agent is NOT working.Co-Authored-By: Claude Fable 5 noreply@anthropic.com
COMMENT on head
0b11e99d.Code review: clean. Rendering
ToolTraceChipsunder non-user mobile bubbles correctly reuses the desktop renderer on the same sharedtoolTracedata fromuseChatHistory/useChatSocket, and the component uses existing tokenized Tailwind classes (border-line,text-ink-mid, dark border), so I do not see a mobile theme/styling regression.The
!thinkingbanner gate is the right behavior on both MobileChat and desktop ChatTab.thinking = sending || currentTask, so it suppresses the contradictory 'agent unreachable' banner only while there is positive evidence of active work. If the error remains unresolved after the send/currentTask clears, the banner resurfaces normally. A genuinely offline workspace should not have a live currentTask+sending state, and ChatErrorBanner still receivesisOnlinefor the restart affordance when the banner is shown.The tests cover the important surfaces: tool-chain collapsed render + expand, absent tool_trace, suppressing a non-524 error while currentTask drives the thinking indicator, and showing the banner when no work is active. Holding approval only because required CI is not green yet: Canvas remained pending through a bounded poll and review/checklist gates were red. Once required CI/all-required is green, this is approvable from my code review.
REQUEST_CHANGES on head
0b11e99d1d.The mobile chat rendering pieces look directionally reasonable, but this PR is not safe to merge because it carries stale E2E chat fixture changes that would regress the just-fixed #2786/#2788 main-red class.
Blocking finding:
canvas/e2e/fixtures/chat-seed.tsreverts the chat harness back onto the obsoletechat_messagestable and shell-builtpsqlstrings. In this head,seedChatHistory()inserts intochat_messages, while the real chat history path is backed byactivity_logs/MessageStore; this was the false-green/stuck E2E Chat root fixed in #2788. The same file also removesdelivery_mode = 'push'from the external echo workspace setup, which reintroduces the poll-mode echo fixture problem where desktop waits for a push response that never dispatches. The companion spec also switches API defaulting back towardE2E_API_URLand drops the quote-preservation regression content.This is outside the stated mobile-tool-call scope but would regress the E2E Chat harness and main-red durability if merged after #2788. Please rebase/drop the stale
canvas/e2e/chat-separation.spec.tsandcanvas/e2e/fixtures/chat-seed.tshunks so the PR only carries the intended MobileChat/ChatTab/test changes, then rerun CI.0b11e99d1dto14ba40e47c14ba40e47ctoc4a5e757b9COMMENT on head
c4a5e757b9.Code re-review is clean and my stale RC is resolved: the old E2E chat fixture/spec hunks are gone, and the live diff is scoped to
MobileChat.tsx,MobileChat.test.tsx, andChatTab.tsx.The MobileChat/ChatTab changes compose with merged #2795: the attach-button
sendinggate remains removed, tool-call chains render via the sharedToolTraceChipsfor agent messages withtoolTrace, and the falseunreachablebanner is suppressed only whilethinkingis true, so idle/offline errors still surface. The added tests cover tool-chain render/no-render plus banner hidden while currentTask drives thinking and visible when no work is active.Holding formal APPROVAL only because
CI / Canvas (Next.js)is still pending on this head after a bounded poll; approval condition requested CI green. Once Canvas/all-required is green, this is approvable from my review.APPROVED on head
c4a5e757b9.This clears my stale RC on
0b11e99d. The rebased live diff is scoped toMobileChat.tsx,MobileChat.test.tsx, andChatTab.tsx; the stale E2E chat fixture/spec hunks that would have reverted #2788 are gone.Review summary:
ToolTraceChipsrenderer for agent messages withtoolTrace, and remains absent for plain agent messages.unreachablebanner is suppressed only whilethinkingis true (sending || currentTask), so live long-turn work no longer displays a contradictory failure banner, while idle/offline errors still surface.CI / Canvas (Next.js)andCI / all-requiredsucceeded.No remaining blockers.
APPROVED on head
c4a5e757.5-axis review + overlap check:
No findings.