mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-07-12 21:02:17 +02:00
refactor(x): one delivery path for turn events — chat, channels, deltas
Completes the turn-spine unification. Chat's SessionChatStore now consumes turns:events like every other surface, joining live turns by file offset (drop covered, append contiguous, refetch on gap) instead of blind-appending session-bus events. Text/reasoning deltas cross IPC only for turns a window subscribed to (turns:subscribe/unsubscribe, a per-webContents registry that also survives window teardown), so headless pipeline chatter never reaches windows that aren't watching. The channels bridge settles turns off the turn event bus instead of filtering the session broadcast. With no turn-event consumers left, SessionsImpl stops forwarding entirely (it drains its execution streams and keeps outcome/index handling) and sessions:events shrinks to index-changed entries — one channel for turn events, one for session metadata. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
f916cb1d70
commit
876bc35e9e
15 changed files with 284 additions and 115 deletions
|
|
@ -461,7 +461,7 @@ const ipcSchemas = {
|
|||
},
|
||||
// ── New runtime: sessions + turns (session-design.md) ────────────────────
|
||||
// Turn-mutating calls return quickly; the renderer follows progress through
|
||||
// the sessions:events feed and the shared reduceTurn reducer.
|
||||
// the turns:events feed and the shared reduceTurn reducer.
|
||||
'sessions:create': {
|
||||
req: z.object({ title: z.string().optional() }),
|
||||
res: z.object({ sessionId: z.string() }),
|
||||
|
|
@ -545,12 +545,24 @@ const ipcSchemas = {
|
|||
},
|
||||
// Process-wide turn event spine: every turn's durable events (with file
|
||||
// offsets), regardless of who started the turn — session chat, headless
|
||||
// background/knowledge runners, spawned sub-agents. Deltas are not
|
||||
// broadcast here in v1; session chat streams them via sessions:events.
|
||||
// background/knowledge runners, spawned sub-agents. Text/reasoning deltas
|
||||
// ride the same channel but only reach windows that subscribed to that
|
||||
// turn via turns:subscribe.
|
||||
'turns:events': {
|
||||
req: z.custom<TurnBusEvent>(),
|
||||
res: z.null(),
|
||||
},
|
||||
// Per-window delta subscription: deltas are high-volume and ephemeral, so
|
||||
// they cross IPC only for turns this window declared it is watching.
|
||||
// Durable events are always broadcast regardless.
|
||||
'turns:subscribe': {
|
||||
req: z.object({ turnId: z.string() }),
|
||||
res: z.object({ success: z.literal(true) }),
|
||||
},
|
||||
'turns:unsubscribe': {
|
||||
req: z.object({ turnId: z.string() }),
|
||||
res: z.object({ success: z.literal(true) }),
|
||||
},
|
||||
'services:events': {
|
||||
req: ServiceEvent,
|
||||
res: z.null(),
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
import { z } from "zod";
|
||||
import {
|
||||
ModelDescriptor,
|
||||
type TurnStatus,
|
||||
type TurnStreamEvent,
|
||||
} from "./turns.js";
|
||||
import { ModelDescriptor, type TurnStatus } from "./turns.js";
|
||||
|
||||
// Durable session contract for the session layer (see
|
||||
// packages/core/docs/session-design.md). A session is an append-only chain
|
||||
|
|
@ -171,21 +167,14 @@ export interface SessionIndexEntry {
|
|||
error?: string;
|
||||
}
|
||||
|
||||
// What the renderer's single feed consumer receives over IPC: live turn
|
||||
// stream events (durable events + ephemeral deltas) and index updates.
|
||||
// entry: null signals deletion.
|
||||
export type SessionBusEvent =
|
||||
| {
|
||||
kind: "turn-event";
|
||||
sessionId: string;
|
||||
turnId: string;
|
||||
event: TurnStreamEvent;
|
||||
}
|
||||
| {
|
||||
kind: "index-changed";
|
||||
sessionId: string;
|
||||
entry: SessionIndexEntry | null;
|
||||
};
|
||||
// What the renderer's session-feed consumer receives over IPC: session index
|
||||
// updates only. Turn events (durable + deltas) travel on the turns:events
|
||||
// spine (TurnBusEvent in turns.ts). entry: null signals deletion.
|
||||
export type SessionBusEvent = {
|
||||
kind: "index-changed";
|
||||
sessionId: string;
|
||||
entry: SessionIndexEntry | null;
|
||||
};
|
||||
|
||||
export function sessionIndexEntry(
|
||||
state: SessionState,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue