fix(a2a): conductor bridge parses the hub's real SSE wire format (id/type in frame, data={ts,payload})

This commit is contained in:
diegosouzapw
2026-07-22 00:25:35 -03:00
parent 00e15af622
commit a75295f359
2 changed files with 12 additions and 10 deletions

View File

@@ -145,10 +145,9 @@ export class SseParser {
// ============ Connection loop ============
/** Wire shape of one hub event (the SSE `data:` payload) — untrusted input, Zod-validated. */
const hubEventSchema = z.object({
id: z.string(),
type: z.string(),
/** Wire shape of the hub's SSE `data:` field — {ts, payload}; id/type live in the
* SSE frame fields (verified against the live hub, 2026-07-22). Untrusted input → Zod. */
const hubDataSchema = z.object({
payload: z.record(z.string(), z.unknown()),
});
@@ -194,15 +193,16 @@ export function createConductorBridge(opts: ConductorBridgeOptions): ConductorBr
const { value, done } = await reader.read();
if (done) return;
for (const frame of parser.push(decoder.decode(value, { stream: true }))) {
let parsed: z.infer<typeof hubEventSchema>;
if (!frame.id || !frame.event) continue; // keepalive/partial frame — nada a espelhar
let payload: Record<string, unknown>;
try {
parsed = hubEventSchema.parse(JSON.parse(frame.data));
payload = hubDataSchema.parse(JSON.parse(frame.data)).payload;
} catch {
log(`evento SSE malformado ignorado (id=${frame.id ?? "?"})`);
log(`evento SSE malformado ignorado (id=${frame.id})`);
continue;
}
applyConductorEvent(opts.tm, index, parsed);
opts.cursor.set(parsed.id); // persisted per event — replay covers any gap on reconnect
applyConductorEvent(opts.tm, index, { id: frame.id, type: frame.event, payload });
opts.cursor.set(frame.id); // persisted per event — replay covers any gap on reconnect
}
}
}

View File

@@ -24,8 +24,10 @@ test.afterEach(async () => {
}
});
// Formato REAL do SSE do hub (verificado ao vivo 2026-07-22): id/type nos campos do
// frame; o `data:` carrega só {ts, payload}.
const sse = (id: number, type: string, payload: Record<string, unknown>) =>
`id: ${id}\nevent: ${type}\ndata: ${JSON.stringify({ id: String(id), type, ts: "2026-07-22T00:00:00Z", payload })}\n\n`;
`id: ${id}\nevent: ${type}\ndata: ${JSON.stringify({ ts: "2026-07-22T00:00:00Z", payload })}\n\n`;
interface FakeHub {
url: string;