Feat/watch running summary#3962
Draft
pedrofrxncx wants to merge 10 commits into
Draft
Conversation
The /watch SSE stream emits a decopilot.running.summary snapshot on connect (DB-backed, authoritative, cross-pod) and the run reactor broadcasts a fresh summary through the SSE hub on every thread transition. A NATS JetStream KV store (DB fallback when NATS is absent) materializes the cross-pod running set, keyed by org with a per-entry progress timestamp so orphaned runs self-heal via read-time pruning. The home page renders "X agents working on N tasks".
The shared decopilot SSE pool is opened once and ref-counted; a late subscriber (RunningSummaryLine mounting after the pool was already open) never receives the one-shot connect snapshot, so the badge stays at 0 until the next transition. Give the running summary its own dedicated, ref-counted /watch connection so every mount/reconnect gets a fresh snapshot.
Hovering the "X agents working on N tasks" badge reveals the running threads: each row shows the agent avatar + name, the thread title, and the latest assistant snippet (fetched lazily when the popover opens). Clicking a row opens that thread. Also fixes a title inconsistency: RunningThread.title is now consistently the THREAD title (snapshot previously used the agent/connection title while the reactor broadcast used the thread title). The agent is resolved client-side from virtual_mcp_id, so the summarizeRunning join is dropped and the unused per-agent breakdown removed from RunningSummary.
Adds an "All my work" scope alongside "This org": your in_progress threads across every org you belong to, on the home badge + hover list, each row linking to the right org+thread. - RunningThread gains organization_id (cross-org nav) and agent_title (server-resolved; the client cannot resolve a cross-org agent). - New summarizeRunningForUser(userId): membership-gated cross-org query. - New authenticated, non-org GET /api/me/watch — snapshots the user set and registers on the synthetic SSE channel user:<id> (the hub keys channels by opaque string, so no hub/NATS changes). The reactor fire-and-forgets a per-user summary to that channel on each transition. - Home: a persisted scope toggle; subscribes to both feeds so the badge stays visible and the toggle reachable; cross-org rows resolve org slug from the user org list, fetch the snippet with that org\047s client, and navigate via useNavigate. Per-user broadcast computes from DB per transition (the org channel uses KV); fine for an opt-in lower-traffic feed, optimizable to per-user KV later.
Defaults the scope to the per-user cross-org feed; only switches to "This org" when explicitly chosen (persisted). The toggle is local state over two always-subscribed feeds, so switching never reconnects or reloads.
…dentity Connection exhaustion: the badge held two dedicated SSE streams (org + user) per tab, so a few tabs blew past the browser per-domain limit and hung the app (and the churn flickered the badge). Collapse to ONE thin /watch connection per tab that carries both scopes: the server also listens on the user:<id> channel and sends both snapshots on connect, distinguished by event type (decopilot.running.summary[.user]). Drops /api/me/watch. The client caches both scopes and no longer clears on unmount, so a re-render never flashes empty. Cross-org agent identity: rows in "All my work" showed a generic "Agent" + icon because useVirtualMCP only resolves current-org agents and the well-known Decopilot agent has no connections row (server agent_title was null). Resolve Decopilot client-side from the thread org id (name + capybara icon); custom cross-org agents still use the server agent_title.
In "All my work", each row now shows the org icon + name (reusing OrgIcon from account-popover) so cross-org tasks are disambiguated. Org scope is unchanged (single org, no need to repeat it).
…flows Consolidates the handling of running summaries and workflow events into a single, shared `/watch` connection per organization. This change optimizes resource usage by reducing the number of SSE connections, preventing browser connection limits from being exceeded. The new structure allows both running summary and workflow events to be streamed together, enhancing performance and simplifying the event handling logic. Updates include the introduction of a unified SSE pool and adjustments to the relevant hooks and components to utilize this new architecture.
Updated integration tests to include handling for both DECOPILOT_RUNNING_SUMMARY_EVENT and DECOPILOT_USER_RUNNING_SUMMARY_EVENT. This change ensures that the tests correctly drop these summary broadcasts during the run-lifecycle sequence assertions, improving clarity and accuracy in event processing. Additionally, refactored the export statements in the relevant test files for consistency.
…te state updates Updated the emitUserRunningSummary function to be asynchronous, ensuring that the cross-org query completes within the reactor's flow. This change prevents stale state issues by awaiting the summary emission, and errors are now logged instead of thrown. Additionally, adjusted calls to emitUserRunningSummary to await its completion in relevant functions. Improved the user state handling in the home page layout to filter out duplicate threads from the current organization.
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.
What is this contribution about?
Screenshots/Demonstration
How to Test
Migration Notes
Review Checklist
Summary by cubic
Adds a live running summary to the home page: “X agents working on N tasks,” with a hover list and a scope toggle between “This org” and “All my work.” The
/watchSSE sends org and per‑user snapshots on connect and broadcasts on every run transition, backed by a cross‑pod running set.New Features
/watchstreamsdecopilot.running.summary(org) anddecopilot.running.summary.user(per‑user) snapshots on connect when requested; the reactor broadcasts fresh summaries on start/step/finish to org anduser:<id>channels.RunningThreadsStorewith a JetStream KV backend (per‑org key, idle‑entry pruning, TTL) and a DB fallback when NATS is absent; storage addssummarizeRunningandsummarizeRunningForUser;@decocms/mesh-sdkaddsDECOPILOT_RUNNING_SUMMARY_EVENT,DECOPILOT_USER_RUNNING_SUMMARY_EVENT,buildRunningSummary, andcreateDecopilotRunningSummaryEvent.Refactors
/watchSSE pool shared by decopilot, workflows, and the running summary; one cross‑tab connection per org (Web Locks +BroadcastChannel), with view filters per consumer.?typesand can include both org and per‑user scopes.Written for commit 791b47a. Summary will update on new commits.