feat: migrate to scoped bus API (forService/forSession)#145
Conversation
WalkthroughWalkthrough
ChangesSession-scoped status publishing and variant-driven TUI
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Possibly related PRs
Pre-merge checks | ✅ 3 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (3 passed)
Tip: You can configure your own custom pre-merge checks in the settings. Finishing TouchesGenerate docstrings
Generate unit tests (beta)
Simplify code
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
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/status.ts`:
- Line 135: The `BrainStatusEvent` interface does not include a `sessionId`
field, but the payload construction in the status module is attempting to add
`sessionId` and casting it to `BrainStatusEvent`, which violates type safety.
Update the `BrainStatusEvent` interface definition to include the `sessionId`
field with an appropriate type (likely `string | undefined` based on the usage
pattern), so that the `sessionId` property is properly declared and the type
cast on line 135 becomes type-safe without needing to bypass TypeScript's type
checking.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 9e536bff-6486-4e74-be02-ac121c475178
Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
Files selected for processing (3)
package.jsonsrc/status.tssrc/tui.tsx
| // ALS-stored session ID wins over global (prevents cross-session channel overwrite). | ||
| // If no ALS context (startup, auto-ingest fire-and-forget), use the unscoped "brain" service. | ||
| const sid = _sessionAls.getStore() ?? ""; | ||
| const payload = { ..._state.current, version: _version, sessionId: sid || undefined } as BrainStatusEvent; |
There was a problem hiding this comment.
Type safety violation: sessionId is not in BrainStatusEvent interface.
Line 135 adds sessionId to the payload and casts it to BrainStatusEvent, but the interface (defined in src/event-bus.ts:5-12) does not include a sessionId field. This bypasses TypeScript's type checking and could cause runtime issues if consumers expect only the declared fields.
Proposed fix: Add sessionId to BrainStatusEvent interface
Update src/event-bus.ts to include the sessionId field:
export interface BrainStatusEvent {
status?: "init" | "busy" | "ready" | "error";
statusText?: string;
current?: number;
total?: number;
version?: string;
error?: string;
+ sessionId?: string;
}Then the cast on line 135 will be type-safe.
Prompt for 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.
In `@src/status.ts` at line 135, The `BrainStatusEvent` interface does not include
a `sessionId` field, but the payload construction in the status module is
attempting to add `sessionId` and casting it to `BrainStatusEvent`, which
violates type safety. Update the `BrainStatusEvent` interface definition to
include the `sessionId` field with an appropriate type (likely `string |
undefined` based on the usage pattern), so that the `sessionId` property is
properly declared and the type cast on line 135 becomes type-safe without
needing to bypass TypeScript's type checking.
There was a problem hiding this comment.
1 issue found across 4 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/tui.tsx">
<violation number="1" location="src/tui.tsx:82">
P1: Subscription scope is fixed at mount and does not track later `sessionId` updates. Sidebar can miss status updates after session creation because publisher switches to session-scoped channel.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| // the old brain/{sid} channel. No sessionId filter needed — the bus | ||
| // only delivers events for the scoped session (or unscoped when sid missing). | ||
| const scoped = b.forService("brain"); | ||
| const brainBus = props.sessionId ? scoped.forSession(props.sessionId) : scoped; |
There was a problem hiding this comment.
P1: Subscription scope is fixed at mount and does not track later sessionId updates. Sidebar can miss status updates after session creation because publisher switches to session-scoped channel.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/tui.tsx, line 82:
<comment>Subscription scope is fixed at mount and does not track later `sessionId` updates. Sidebar can miss status updates after session creation because publisher switches to session-scoped channel.</comment>
<file context>
@@ -1,161 +1,134 @@
+ // the old brain/{sid} channel. No sessionId filter needed — the bus
+ // only delivers events for the scoped session (or unscoped when sid missing).
+ const scoped = b.forService("brain");
+ const brainBus = props.sessionId ? scoped.forSession(props.sessionId) : scoped;
+ unsub = brainBus.subscribe("status", (envelope) => {
+ handleStatus(envelope.payload as BrainStatusEvent);
</file context>
Replaces manual channel string building with scoped bus API. Removes session ID filter — no longer needed.
Summary by cubic
Migrated brain status publishing and TUI subscriptions to the scoped bus API (
forService/forSession), removing manual channel strings and cross-session filtering. This improves session isolation and simplifies event routing.Refactors
AsyncLocalStorageto bind session IDs per tool run and publish viabus.forService("brain").forSession(sid).publish("status")(unscoped when no session); removed_channeland session filter.BusTui.forService("brain")and optional.forSession(sessionId)onstatus; removed duplicate subscriptions and filters; addedvariantprop for sidebar/home, with cleaner indicators and compact progress.Dependencies
@four-bytes/opencode-plugin-libtov0.6.0for scoped bus support.Written for commit cf51a8f. Summary will update on new commits.
Summary by CodeRabbit
New Features
Improvements
Chores