Skip to content

improvement(mothership): show elapsed time on the chat's Thinking indicator during long silent waits - #8734

Draft
waleedlatif1 wants to merge 2 commits into
stagingfrom
feat/mothership-thinking-indicator
Draft

waleedlatif1 wants to merge 2 commits into
stagingfrom
feat/mothership-thinking-indicator

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • After a send, the model can reason silently for 15–40s before its first output (hidden reasoning streams no visible bytes), and follow-up turns tend to wait longer. Today the chat shows the turn-level "Thinking" shimmer for that whole stretch, but nothing about it changes, so a long wait looks like a hang.
  • The Thinking shimmer now shows the wait's elapsed time ("Thinking 12s") once a wait passes 5s. Short waits look the same as before.
  • A "wait" restarts on every piece of visible output (the same activity key that already drives the shimmer's quiet-period clock), so the count also covers long mid-turn gaps, not only time-to-first-output. Hidden reasoning is not visible output, so it does not reset the count.
  • The count runs only while the shimmer is actually shown. When a tool or agent row owns the wait, or when output arrives, the turn ends, or the user stops it, the count disappears and its timer is cleared.
  • The Wait tool's private useElapsedMs moved into the shared home/hooks/use-elapsed-ms.ts, so one clock serves both the Wait countdown and the turn wait.

Design

  • Built from existing pieces. The indicator is the same PendingTagIndicator / ThinkingLoader shimmer. The count is a muted text-[var(--text-muted)] 14px span with tabular-nums, placed after the "Thinking" label, and it is formatted with the shared formatDuration ("12s", "1m 5s").
  • No layout jank. The count sits inside the existing fixed 36px tail slot, so the row's height never changes. tabular-nums keeps the width steady as the digits tick.
  • Accessible. The loader's <output> already announces "Thinking". The count is aria-hidden because a live region that changed every second would be noise for screen readers.
  • Reduced motion. The count is only a text change. It fades in with animate-stream-fade-in, which the global reduced-motion rule already turns off.
  • Cheap. The count ticks in its own ElapsedCount leaf, so neither the loader SVG nor MessageContent re-renders on the clock. The wait's start time is a ref that the existing layout effect updates, so stream chunks cause no extra MessageContent render.
  • Not shown on purpose: the reasoning itself. The transcript hides thinking blocks by design, and with hidden reasoning there is no text to show anyway. Elapsed time is the signal that works for every provider.

Type of Change

  • Improvement (UX)

Testing

  • New message-content.dom.test.tsx (jsdom, fake timers, reduced-motion stub) covers these cases:
    • Thinking shows from send.
    • The count appears at 5s and keeps ticking.
    • The count keeps going through hidden reasoning.
    • The indicator and count are hidden on first output.
    • The indicator is removed and its timer cleared when the turn ends.
    • The indicator is removed on user stop.
    • No count runs while a running tool row owns the wait.
    • The timer is cleared on unmount.
  • bunx vitest run app/workspace/[workspaceId]/home/components/message-content: 17 files, 161 tests passed.
  • bun run lint, bun run type-check, bun run check:audits (58 audits) and docs-manifest:check all pass.
  • Root bun run test: everything passes except copilot-route-inventory.test.ts, which hits its 60s timeout on my machine. That test imports every v2 route and touches nothing in this diff.
  • Screenshots: not captured, because the dev server needs credentials. In words: the row looks like before, the shape loader plus a shimmering "Thinking". From 5s on, a grey "5s", "6s" and so on appears right after the label.

Manual check: send a prompt that makes the model reason for a while, such as a multi-step planning question on a reasoning model.

  • Thinking shows right away, and after 5s a grey seconds count ticks next to it.
  • The count disappears the moment text or a tool row shows up.
  • Pressing stop replaces the row with "Stopped by user", and no count remains.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel

vercel Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
docs Skipped Skipped Oct 7, 2026 7:56am UTC

Request Review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 5 files

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Turn on auto-fix | Re-trigger cubic

@greptile-apps

greptile-apps Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

[Medium risk] Adds elapsed time display to the chat thinking indicator.

The PR appears safe to merge; no blocking issues remain.

What we checked:

  • Shared clock callers still match: Both callers use the new object argument. They pass the same values as before, and the default for resetKey is unchanged.

Summary

Adds elapsed time beside the chat’s Thinking indicator after five seconds of silence. Shares the clock with the Wait tool’s countdown.

  • The latest changes add props interfaces, use text-sm, and explicitly type the wait-start ref.
  • Tests now check indicator state and timer cleanup without reading rendered text.
  • All six previous, unnumbered findings are addressed. No new actionable issues were found.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Visible output or turn start] --> B[Record wait start]
  B --> C{Thinking indicator shown?}
  C -->|Yes| D[Read elapsed time]
  D --> E{At least five seconds?}
  E -->|Yes| F[Show elapsed count]
  E -->|No| G[Show Thinking only]
  C -->|No| H[Hide count and clear timer]
Loading

Reviews (2) · Last reviewed commit: "improvement(mothership): address review ..." · Reviewed by Greptile

Comment thread apps/sim/app/workspace/[workspaceId]/home/hooks/use-elapsed-ms.ts Outdated
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

This branch was previously deployed

1 inactive deployment
Preview — 8bb6d309 Deployed Oct 7, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant