diff --git a/backend/src/bridge/session-bridge.ts b/backend/src/bridge/session-bridge.ts index 80a13e70..cd7cd658 100644 --- a/backend/src/bridge/session-bridge.ts +++ b/backend/src/bridge/session-bridge.ts @@ -19,6 +19,11 @@ export class SessionBridge { this.fan({ type: "ui_request", ui_request: descriptor }); } else if (m.type === "extension_ui_request" && m.method === "notify") { this.fan({ type: "info", level: m.notifyType ?? "info", text: m.message ?? "" }); + } else if (m.type === "message_update" && m.assistantMessageEvent?.type === "text_delta") { + // Real Pi streams assistant text as message_update events whose nested + // assistantMessageEvent carries the incremental `delta`. Map it to the FE's + // text_delta contract. (Top-level text_delta below is what the fake-pi-rpc emits.) + this.fan({ type: "text_delta", text: m.assistantMessageEvent.delta ?? "" }); } else if (m.type === "text_delta") { this.fan({ type: "text_delta", text: m.text ?? "" }); } else if (m.type === "system_event") { diff --git a/backend/test/session-bridge.test.ts b/backend/test/session-bridge.test.ts index 2957c855..76324d92 100644 --- a/backend/test/session-bridge.test.ts +++ b/backend/test/session-bridge.test.ts @@ -15,6 +15,19 @@ function fakeRpc() { }; } +test("real Pi message_update (assistantMessageEvent text_delta) becomes a text_delta to the FE", () => { + const { rpc, fire } = fakeRpc(); + const b = new SessionBridge(rpc); + const seen: any[] = []; + b.onClientEvent((e) => seen.push(e)); + // Shape emitted by real `pi --mode rpc`: text streams inside message_update.assistantMessageEvent.delta + fire({ type: "message_update", assistantMessageEvent: { type: "text_delta", contentIndex: 0, delta: "Avvio" } }); + expect(seen[0]).toEqual({ type: "text_delta", text: "Avvio" }); + // Non-text message_update events (e.g. text_start) are ignored. + fire({ type: "message_update", assistantMessageEvent: { type: "text_start", contentIndex: 0 } }); + expect(seen).toHaveLength(1); +}); + test("extension_ui_request nativo (method:input, title=json) diventa ui_request ed รจ il pendente", () => { const { rpc, fire } = fakeRpc(); const b = new SessionBridge(rpc);