Skip to content

fix(mission): thread messages, accurate unreads, state_change detail (by Wren) - #217

Merged
conoremclaughlin merged 8 commits into
mainfrom
wren/fix/mission-thread-messages
Mar 16, 2026
Merged

fix(mission): thread messages, accurate unreads, state_change detail (by Wren)#217
conoremclaughlin merged 8 commits into
mainfrom
wren/fix/mission-thread-messages

Conversation

@conoremclaughlin

@conoremclaughlin conoremclaughlin commented Mar 11, 2026

Copy link
Copy Markdown
Owner

Summary

  • Thread messages in feed: extractInboxMessages now parses threadsWithUnread[*].previewMessages so thread-based messages appear in the mission control feed alongside legacy inbox messages
  • Accurate per-agent unread counts: New get_agent_summaries MCP tool computes thread unreads with proper per-agent last_read_at — fixes the inflated 246-unread bug where all-agents mode counted ALL thread messages as unread for every participant
  • State change detail: Session update events now show actual values (Session b73acc8f → currentPhase: implementing, lifecycle: running) instead of just field names (Session b73acc8f updated (currentPhase, lifecycle))

Changes

Backend (packages/api/src/mcp/tools/inbox-handlers.ts)

  • New get_agent_summaries tool: returns per-agent summaries in one call
    • Auto-discovers agents from agent_identities table
    • Accurate unread counts: legacy agent_inbox + thread-aware with per-agent last_read_at
    • Active session count, latest session lifecycle/phase

CLI (packages/cli/src/commands/mission.ts)

  • extractInboxMessages: extracts from both messages and threadsWithUnread[*].previewMessages
  • extractUnreadCount: prefers totalUnreadCount over unreadCount
  • fetchMissionSnapshot: uses get_agent_summaries for the SB summary bar (falls back to per-agent get_inbox if server doesn't support it yet)
  • formatStateChange: parses payload.after to show actual changed values, skips long fields (>80 chars)

Tests (packages/cli/src/commands/mission.test.ts)

  • 11 new regression tests (62 → 66 total, all passing)
  • Covers: thread preview extraction, legacy+thread merging, totalUnreadCount preference, state_change value rendering

Test plan

  • npx vitest run packages/cli/src/commands/mission.test.ts — 66 tests passing
  • Type-check passes for both API and CLI packages
  • Manual testing with sb mission --watch confirms thread messages appear and unread counts are accurate
  • Restart PCP server to pick up new get_agent_summaries tool, verify SB summary bar shows correct counts

— Wren

conoremclaughlin and others added 7 commits March 11, 2026 22:20
Thread-backed messages (sent via send_to_inbox with threadKey) now live in
inbox_thread_messages, not agent_inbox. The mission feed was only reading
from the legacy messages array, so cross-agent thread messages were invisible.

Changes:
- extractInboxMessages: also extract preview messages from threadsWithUnread
- extractUnreadCount: prefer totalUnreadCount (includes thread unreads)
- All-agents path: count thread unreads per participant from threadsWithUnread

Co-Authored-By: Wren <noreply@anthropic.com>
…ion feed

Tests cover:
- Thread preview messages extracted from threadsWithUnread
- Merged legacy + thread messages
- Missing threadsWithUnread handled gracefully
- Preview messages without createdAt skipped
- Recipient derived from thread participants (excludes sender)
- totalUnreadCount preferred over legacy unreadCount
- Non-finite totalUnreadCount falls back correctly

Co-Authored-By: Wren <noreply@anthropic.com>
The all-agents get_inbox query lacks agent-specific thread read status,
so thread unreadCount was inflated (counted total messages, not per-agent
unreads). This caused wildly inflated numbers like 246 unread across 5 SBs.

Removed the all-agents optimization entirely — per-agent queries give
accurate totalUnreadCount (legacy + thread unreads) per agent. The extra
API calls are worth correct counts.

Co-Authored-By: Wren <noreply@anthropic.com>
New MCP tool that returns per-agent summaries in one call:
- Accurate unread counts (legacy inbox + thread-aware with per-agent last_read_at)
- Active session count and latest session lifecycle/phase
- Auto-discovers agents from agent_identities when agentIds omitted
- Replaces broken all-agents thread counting that inflated unread counts

Co-Authored-By: Wren <noreply@anthropic.com>
Replace broken all-agents inbox counting with dedicated backend tool.
Feed messages still fetched from get_inbox (all agents, all statuses).
Falls back to per-agent get_inbox if server doesn't support new tool yet.

Co-Authored-By: Wren <noreply@anthropic.com>
Instead of 'Session b73acc8f updated (currentPhase, lifecycle)',
now shows 'Session b73acc8f → currentPhase: implementing, lifecycle: running'.

Parses payload.after for the actual values. Skips long fields (>80 chars)
like context blobs. Falls back to field names if payload is missing.

Co-Authored-By: Wren <noreply@anthropic.com>
@conoremclaughlin conoremclaughlin changed the title fix(cli): show thread messages in mission control feed (by Wren) fix(mission): thread messages, accurate unreads, state_change detail (by Wren) Mar 16, 2026
get_agent_summaries now queries all non-ended sessions (no limit) and
returns sessionsByLifecycle counts per agent (e.g. { running: 2, idle: 1 }).

SB summary bar now shows '2 running, 1 idle' instead of '3 sessions'
with a single misleading lifecycle status. Running sessions shown first.

Co-Authored-By: Wren <noreply@anthropic.com>
@conoremclaughlin
conoremclaughlin merged commit 5658279 into main Mar 16, 2026
4 checks passed
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