Skip to content

Make TUI consume project-service API events#196

Merged
TraderSamwise merged 3 commits into
masterfrom
feat/tui-api-client-parity
Jun 20, 2026
Merged

Make TUI consume project-service API events#196
TraderSamwise merged 3 commits into
masterfrom
feat/tui-api-client-parity

Conversation

@TraderSamwise

@TraderSamwise TraderSamwise commented Jun 20, 2026

Copy link
Copy Markdown
Owner

Summary

  • add a dashboard /events SSE client for project_update and alert refreshes, and remove the old in-process TUI event-bus subscriber
  • route dashboard open/focus and orchestration route discovery through project-service APIs
  • make notification panel and Coordination reads service-backed without local read fallbacks

Verification

  • yarn typecheck
  • yarn lint
  • yarn vitest run
  • yarn build

Summary by CodeRabbit

Release Notes

  • New Features

    • Orchestration route picker enables flexible message and task recipient selection
    • Real-time project updates stream for live dashboard synchronization
    • Service-provided orchestration route options with tool and session routing
  • Improvements

    • Notifications and coordination state sourced from service for consistency and accuracy
    • Enhanced live agent window opening with improved availability feedback
    • Session-level tool configuration tracking

@vercel

vercel Bot commented Jun 20, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
app Ready Ready Preview, Comment Jun 20, 2026 9:18am

@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@TraderSamwise, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 25 minutes and 34 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a3ba7913-2d55-44cf-92d6-7329a8a09a01

📥 Commits

Reviewing files that changed from the base of the PR and between 963c495 and 4a98d48.

📒 Files selected for processing (6)
  • src/multiplexer/dashboard-control.test.ts
  • src/multiplexer/dashboard-control.ts
  • src/multiplexer/notifications.test.ts
  • src/multiplexer/notifications.ts
  • src/multiplexer/project-event-stream.test.ts
  • src/multiplexer/project-event-stream.ts
📝 Walkthrough

Walkthrough

This PR migrates the dashboard to service-authoritative data flows by introducing an SSE-based project event stream (project-event-stream.ts) that replaces the old eventBus.subscribe coordination push. It adds an orchestration route API contract with a metadata-server handler and client wrapper, updates dashboard-mode live tmux-window opening and orchestration route picking to use the project service, and converts notification/coordination refresh throughout to service calls instead of local rebuilds. A toolConfigKey field is also propagated across session types.

Changes

Service-Driven Dashboard Refresh and Orchestration Routes

Layer / File(s) Summary
Orchestration route API contract and session toolConfigKey shape
src/project-api-contract.ts, app/lib/desktop-state.ts, src/dashboard/index.ts, src/dashboard/session-registry.ts
Adds OrchestrationRouteMode, OrchestrationRouteOption, OrchestrationRouteOptionsResponse types and the /orchestration/routes endpoint to PROJECT_API_ROUTES; adds optional toolConfigKey to DesktopSession, DashboardSession, DashboardLocalSession, and the two session-registry mapping paths.
SSE project event stream implementation and lifecycle wiring
src/multiplexer/project-event-stream.ts, src/multiplexer/project-event-stream.test.ts, src/multiplexer/session-launch.ts, src/multiplexer/runtime-lifecycle-methods.ts, src/multiplexer/index.ts
Adds project-event-stream.ts with reconnecting SSE client, line-by-line parser, debounced view refresh scheduling (scheduleProjectViewRefresh), alert application (applyDashboardAlert), and start/stop lifecycle functions; starts the stream in runDashboard, stops it in teardown, and removes the old eventBus.subscribe coordination-push handler from the multiplexer constructor.
Service-authoritative notification and coordination refresh
src/multiplexer/notifications.ts, src/multiplexer/notifications.test.ts, src/multiplexer/coordination.ts, src/multiplexer/subscreens.ts
Exports refreshNotificationPanelFromService; changes showNotificationPanel and mutateNotificationsViaService to use it; removes local refreshNotificationEntries fallback from refreshCoordinationFromService; removes scheduleCoordinationPush; converts openRelevantThreadForSession and refreshCoordinationThreads to async with service-backed refresh; updates post-action refreshes to fire async with .catch(()=>{}).
Metadata-server orchestration route endpoint
src/metadata-server.ts, src/metadata-server.test.ts, app/lib/api.ts
Adds GET /orchestration/routes HTTP handler returning buildOrchestrationRouteOptions output; introduces orchestrationCandidateFromSession and formatRoutePreview helpers; adds getOrchestrationRouteOptions client wrapper in app/lib/api.ts; adds an end-to-end test verifying expected option labels and recipient metadata.
Dashboard control: project-service live-target opening and orchestration picker
src/multiplexer/dashboard-control.ts, src/multiplexer/dashboard-control.test.ts, src/multiplexer/dashboard-actions-methods.ts, src/multiplexer/dashboard-model.ts
Routes waitAndOpenLiveTmuxWindowForEntry/waitAndOpenLiveTmuxWindowForService through openProjectServiceNotificationTarget in dashboard mode; adds showOrchestrationRoutePickerFromService, applyOrchestrationRouteOptions, validOrchestrationRouteOption; adds dashboardActionMethods.refreshNotificationPanelFromService; propagates toolConfigKey in session seed/compute paths; tests cover service POST shape, URL construction, payload validation, and error path.
Dashboard interaction: missing-agent branch, 'o' key, async thread opening
src/multiplexer/dashboard-interaction.ts, src/multiplexer/dashboard-interaction.test.ts
Adds early-return in activateDashboardEntry when live-target is "missing" in dashboard mode (refresh model, flash footer, skip local focus/offline logic); adds "o" key handler calling openRelevantThreadForSession; test asserts no local focus when agent is unavailable.

Sequence Diagram(s)

sequenceDiagram
  participant Dashboard as Dashboard (runDashboard)
  participant SSEStream as project-event-stream
  participant ProjectService as ProjectService (SSE endpoint)
  participant scheduleRefresh as scheduleProjectViewRefresh
  participant Notifications as notifications.ts
  participant MetadataServer as MetadataServer (/orchestration/routes)
  participant DashboardControl as dashboard-control.ts

  rect rgba(70, 130, 180, 0.5)
    Note over Dashboard, SSEStream: Stream startup
    Dashboard->>SSEStream: startDashboardProjectEventStream(host)
    SSEStream->>ProjectService: GET SSE endpoint (text/event-stream)
    ProjectService-->>SSEStream: event: projectUpdate / alert
  end

  rect rgba(80, 160, 80, 0.5)
    Note over SSEStream, Notifications: Debounced refresh on projectUpdate
    SSEStream->>scheduleRefresh: views[] from projectUpdate event
    scheduleRefresh->>scheduleRefresh: accumulate Set, 25ms debounce
    scheduleRefresh->>Notifications: refreshCoordinationFromService()
    Notifications->>ProjectService: GET coordination data
    ProjectService-->>Notifications: updated state (no local fallback on failure)
  end

  rect rgba(180, 100, 60, 0.5)
    Note over Dashboard, MetadataServer: Orchestration route picker
    Dashboard->>DashboardControl: showOrchestrationRoutePicker()
    DashboardControl->>MetadataServer: GET /orchestration/routes?selectedSessionId=...
    MetadataServer->>MetadataServer: buildOrchestrationRouteOptions(sessions, teammates)
    MetadataServer-->>DashboardControl: OrchestrationRouteOptionsResponse
    DashboardControl->>DashboardControl: applyOrchestrationRouteOptions (open overlay or show error)
  end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • TraderSamwise/aimux#173: Overlaps at the coordination screen refresh and selection logic in src/multiplexer/coordination.ts, which this PR significantly rewrites.
  • TraderSamwise/aimux#178: Both PRs change the coordination-push and notification-refresh flow in the coordination subsystem; this PR removes scheduleCoordinationPush that the earlier PR introduced.
  • TraderSamwise/aimux#184: Both extend PROJECT_API_ROUTES and wire up new route-constant consumers; this PR adds PROJECT_API_ROUTES.orchestration.routes alongside the pattern the earlier PR established.

Poem

🐇 Hop hop, the SSE stream arrives,
No more old event-bus, the dashboard thrives!
Orchestration routes now bloom from the server's lair,
toolConfigKey hops through sessions everywhere.
Local rebuilds banished, service calls ring true —
This rabbit ships real-time updates, fresh as morning dew! 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Make TUI consume project-service API events' accurately and concisely summarizes the main change: integrating TUI with project-service API events for dashboard integration.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/tui-api-client-parity

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/multiplexer/dashboard-control.ts`:
- Around line 411-414: The hardcoded 10 second request timeout in the service
call handling (around lines 448-472, particularly in
openProjectServiceNotificationTarget) exceeds the 3 second total deadline
imposed by the enclosing polling helpers. Replace the hardcoded timeout value
with one that respects the caller's deadline constraint, ensuring that
individual request timeouts do not exceed the overall polling deadline to
prevent UI blocking and maintain the intended wait budget.

In `@src/multiplexer/notifications.ts`:
- Around line 190-195: The validation guard before calling
applyCoordinationModel checks the shape of res.model and res.worklist but does
not validate res.threads, allowing invalid non-array thread shapes to reach
applyCoordinationModel and corrupt host.threadEntries. Add a condition to the
existing guard's if statement to ensure res.threads is either falsy (allowing
the ?? [] fallback) or is an Array before proceeding with the
applyCoordinationModel call.

In `@src/multiplexer/project-event-stream.ts`:
- Line 59: The SSE stream reconnection logic in the project-event-stream.ts file
does not implement backoff when readEventStream completes successfully on a
clean close. Currently, when the stream closes with a successful response, the
loop immediately re-fetches without waiting, which can cause rapid reconnect
attempts if the server closes 200 status streams quickly. Add a delay using
RETRY_MS after the readEventStream call completes successfully (on normal
return, not just on error) before the next iteration attempts to fetch the
stream again. This ensures proper backoff behavior for both error and
clean-close scenarios.
- Around line 212-223: The abort listener added to the signal in the sleep
function is not being removed when the timeout completes normally, causing
listener accumulation on the long-lived signal. Store a reference to the abort
event handler function, then after the Promise resolves (when the setTimeout
callback fires), manually remove the listener from the signal using
removeEventListener. This ensures the listener is cleaned up regardless of
whether the abort signal fires or the timeout completes naturally, preventing
listener leaks during repeated reconnect delays.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e5029cd6-a60c-49c1-9afb-ec6fef7394f6

📥 Commits

Reviewing files that changed from the base of the PR and between e40ebbc and 963c495.

📒 Files selected for processing (23)
  • app/lib/api.ts
  • app/lib/desktop-state.ts
  • src/dashboard/index.ts
  • src/dashboard/session-registry.ts
  • src/metadata-server.test.ts
  • src/metadata-server.ts
  • src/multiplexer/coordination.test.ts
  • src/multiplexer/coordination.ts
  • src/multiplexer/dashboard-actions-methods.ts
  • src/multiplexer/dashboard-control.test.ts
  • src/multiplexer/dashboard-control.ts
  • src/multiplexer/dashboard-interaction.test.ts
  • src/multiplexer/dashboard-interaction.ts
  • src/multiplexer/dashboard-model.ts
  • src/multiplexer/index.ts
  • src/multiplexer/notifications.test.ts
  • src/multiplexer/notifications.ts
  • src/multiplexer/project-event-stream.test.ts
  • src/multiplexer/project-event-stream.ts
  • src/multiplexer/runtime-lifecycle-methods.ts
  • src/multiplexer/session-launch.ts
  • src/multiplexer/subscreens.ts
  • src/project-api-contract.ts
💤 Files with no reviewable changes (2)
  • src/multiplexer/coordination.test.ts
  • src/multiplexer/index.ts

Comment thread src/multiplexer/dashboard-control.ts
Comment thread src/multiplexer/notifications.ts Outdated
Comment thread src/multiplexer/project-event-stream.ts
Comment thread src/multiplexer/project-event-stream.ts
@TraderSamwise
TraderSamwise merged commit 1f5b78c into master Jun 20, 2026
3 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