refactor(chat): route browser chat through one runtime

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01ESFAnh2t9HmLwng8oW95St
This commit is contained in:
2026-08-12 14:43:59 -05:00
co-authored by Claude Opus 4.8
parent bd69eca555
commit f4e7a4ddb7
14 changed files with 1399 additions and 80 deletions
+20
View File
@@ -150,8 +150,28 @@ export type HarnessTurnAckPayload =
readonly selection?: HarnessSelection;
};
/**
* The frozen browser send-protocol advertisement (Task Five; server → client only).
*
* A conversation id or a harness selection never proves that the connected Gateway actually
* handles a given wire event, so after BetterAuth authenticates a browser Socket connection the
* Gateway advertises — exactly once, targeted to that socket — which send event the client may
* use. `legacy-message` in legacy mode, `unavailable` in `pi-rpc` (including test-ready Pi
* graphs); Task Five never advertises `turn-send` (its authenticated handler lands in Task 15).
* Capability is routing information, never authorization: every server handler still enforces
* authentication, ownership, DTO, mode, and runtime checks.
*/
export type ChatSendProtocol = 'legacy-message' | 'turn-send' | 'unavailable';
export interface ChatSendCapabilityPayload {
readonly protocol: ChatSendProtocol;
/** Exact Socket.IO id for the authenticated browser connection this advertisement is bound to. */
readonly connectionId: string;
}
/** Socket.IO typed event map: server → client */
export interface ServerToClientEvents {
'chat:send-capability': (payload: ChatSendCapabilityPayload) => void;
'message:ack': (payload: MessageAckPayload) => void;
'agent:start': (payload: AgentStartPayload) => void;
'agent:end': (payload: AgentEndPayload) => void;
+2
View File
@@ -16,6 +16,8 @@ export type {
ChatMessagePayload,
HarnessTurnSendPayload,
HarnessTurnAckPayload,
ChatSendProtocol,
ChatSendCapabilityPayload,
ServerToClientEvents,
ClientToServerEvents,
} from './events.js';