Skip to content

Multi-bot thinking indicator for chat channels#5928

Open
wca4a wants to merge 7 commits into
developfrom
wsa/multibot-thinking
Open

Multi-bot thinking indicator for chat channels#5928
wca4a wants to merge 7 commits into
developfrom
wsa/multibot-thinking

Conversation

@wca4a

@wca4a wca4a commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Reworks useConversationComputingState to return per-ship computing states with a combined label ("X and Y are thinking...", "N bots are thinking..."), sorted by ship so heartbeat re-publishes don't reorder.
  • Rewrites ThinkingState as an animated avatar stack (max 3 avatars + "+N" overflow) and enables it in group chat channels (dm + chat), gated on read permission.
  • Shows the thinking indicator in thread views (DetailView), above the reply composer.
  • Fixes two %presence agent bugs:
    • Host blind spot: a %set with empty disclose (= public) was fanned out to subscribers but never stored on the context host itself, so the host's own client never saw presence for channels it hosts.
    • Bounded nack retry: a nacked context watch previously dropped the desire permanently (one transient nack = no presence until next full setup). Now retries with linear backoff (try × 5min) via a new tries map in %1 state, giving up after 5 consecutive nacks so a permanently-failing host doesn't become an eternal timer.

Known limitation: thread indicator is channel-scoped

Computing presence contexts are keyed by channel/DM only (/channel/chat/~host/name), so the indicator in a thread reflects bots thinking anywhere in that channel, not specifically in that thread. The ideal end state is thread-scoped presence contexts (e.g. /channel/chat/~host/name/thread/<parent-post-id>) published by the gateway, with the channel view aggregating thread contexts by prefix. That requires changes across the presence agent, the gateway publisher, and the client presence API, so it's deferred to a follow-up.

Test plan

  • tsc --noEmit clean on packages/app
  • Hoon build check on a live ship (incl. %0%1 state migration)
  • iOS sim, live ships: DM single-bot indicator; group channel two-ship avatar stack + combined label; remote-channel presence mirror populates during a run and clears at run end
  • 3-ship and 4-ship (+1 overflow) states verified via mocked presence
  • Thread view indicator verified via mocked presence (iOS sim)
  • Gallery/notebook channels show no indicator
  • Desktop web spot-check
  • Android pass

🤖 Generated with Claude Code

wca4a and others added 7 commits June 12, 2026 06:37
…tionComputingState

Drop the activeStates[0] truncation so every thinking ship in a
conversation is surfaced, sorted by ship (not timing.since, which
heartbeat re-publishes would reorder). Combined label resolves
display names for two ships and counts for three or more.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Overlapping ContactAvatars pop in/out via ship-keyed AnimatePresence
(capped at 3 visible plus +N). Avatars show in group channels always
and in DMs only when two or more ships report, so 1:1 DMs keep the
avatar-less spinner+text.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The presence pipeline already aggregates group-channel contexts;
only the UI gate was DM-only. Notebooks, galleries, and group DMs
stay excluded.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two bugs blocked bot presence in group channels:
- a %set with empty disclose fanned out to subscribers but was never
  stored on the host itself, so the host's own client saw nothing for
  channels it hosts. Treat empty disclose as public, including us.
- a nacked context watch permanently dropped the desire, killing
  presence for that context until the next full setup. Keep the desire
  and retry after ~m5, skipping if the context is no longer wanted.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
A nacked context watch previously rescheduled itself every ~m5
forever, so a permanently-failing host (e.g. nuked presence agent)
meant an eternal timer per context. Track consecutive nacks per
[ship context] in a new state-1 tries map, back off linearly
(try * ~m5), and give up after 5 attempts by dropping the desire;
the next full setup starts a fresh cycle if the context is still
relevant. Tries are pruned on ack, context removal, and full setup.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Computing presence is channel-scoped, so the indicator reflects bots
thinking anywhere in the channel; thread-scoped presence contexts are
the ideal end state.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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