fix: wait for Workbench event semantics
Co-Authored-By: Codex <noreply@openai.com>
This commit is contained in:
@@ -125,6 +125,94 @@ describe("Workbench native HTTP adapter", () => {
|
||||
}
|
||||
});
|
||||
|
||||
test("L0 CLI waits for explicit Kafka event semantics in one SSE window", async () => {
|
||||
const subscribers = new Set<(envelope: any) => void>();
|
||||
const bridge = {
|
||||
capabilities: { liveKafkaSse: true },
|
||||
ready: Promise.resolve(),
|
||||
subscribeLiveHwlabEvents(listener: (envelope: any) => void) { subscribers.add(listener); return () => subscribers.delete(listener); }
|
||||
};
|
||||
const app = createWorkbenchHttpApp({
|
||||
mode: "agentrun-native",
|
||||
kafkaEventBridge: bridge,
|
||||
async dispatch() { return { ok: true }; },
|
||||
async snapshot() { return { sessions: {}, turns: {} }; }
|
||||
});
|
||||
const server = Bun.serve({ port: 0, fetch: (request) => app.fetch(request) });
|
||||
try {
|
||||
const pending = runWorkbenchCli([
|
||||
"events", "inspect",
|
||||
"--session-id", "ses_l0_semantics",
|
||||
"--trace-id", "trc_l0_semantics",
|
||||
"--over-api",
|
||||
"--api-url", `http://127.0.0.1:${server.port}`,
|
||||
"--timeout-ms", "1000",
|
||||
"--wait-for", "user,backend,assistant,terminal,final"
|
||||
], {});
|
||||
for (let index = 0; index < 20 && subscribers.size === 0; index += 1) await Bun.sleep(5);
|
||||
const events = [
|
||||
{ type: "user", eventType: "user" },
|
||||
{ type: "backend", eventType: "backend" },
|
||||
{ type: "assistant", eventType: "assistant", final: true, replyAuthority: true, finalResponse: { text: "done" } },
|
||||
{ type: "result", eventType: "terminal", terminal: true, terminalStatus: "completed", status: "completed" }
|
||||
];
|
||||
for (const event of events) {
|
||||
for (const listener of subscribers) listener({ schema: "hwlab.event.v1", sessionId: "ses_l0_semantics", traceId: "trc_l0_semantics", event });
|
||||
}
|
||||
expect(await pending).toMatchObject({
|
||||
ok: true,
|
||||
eventCount: 4,
|
||||
eventTypes: ["user", "backend", "assistant", "terminal"],
|
||||
waitFor: ["user", "backend", "assistant", "terminal", "final"],
|
||||
observedSemantics: ["user", "backend", "assistant", "terminal", "final"],
|
||||
missingSemantics: [],
|
||||
semanticCounts: { user: 1, backend: 1, assistant: 1, terminal: 1, final: 1 },
|
||||
terminalStatuses: ["completed"]
|
||||
});
|
||||
} finally {
|
||||
server.stop(true);
|
||||
await app.close();
|
||||
}
|
||||
});
|
||||
|
||||
test("L0 CLI reports missing Kafka event semantics on timeout", async () => {
|
||||
const subscribers = new Set<(envelope: any) => void>();
|
||||
const app = createWorkbenchHttpApp({
|
||||
mode: "agentrun-native",
|
||||
kafkaEventBridge: {
|
||||
capabilities: { liveKafkaSse: true },
|
||||
ready: Promise.resolve(),
|
||||
subscribeLiveHwlabEvents(listener: (envelope: any) => void) { subscribers.add(listener); return () => subscribers.delete(listener); }
|
||||
},
|
||||
async dispatch() { return { ok: true }; },
|
||||
async snapshot() { return { sessions: {}, turns: {} }; }
|
||||
});
|
||||
const server = Bun.serve({ port: 0, fetch: (request) => app.fetch(request) });
|
||||
try {
|
||||
const pending = runWorkbenchCli([
|
||||
"events", "inspect",
|
||||
"--trace-id", "trc_l0_missing_terminal",
|
||||
"--over-api",
|
||||
"--api-url", `http://127.0.0.1:${server.port}`,
|
||||
"--timeout-ms", "50",
|
||||
"--wait-for", "assistant,terminal"
|
||||
], {});
|
||||
for (let index = 0; index < 20 && subscribers.size === 0; index += 1) await Bun.sleep(2);
|
||||
for (const listener of subscribers) listener({ schema: "hwlab.event.v1", traceId: "trc_l0_missing_terminal", event: { type: "assistant", eventType: "assistant" } });
|
||||
expect(await pending).toMatchObject({
|
||||
ok: false,
|
||||
status: "event-timeout",
|
||||
observedSemantics: ["assistant"],
|
||||
missingSemantics: ["terminal"],
|
||||
terminalStatuses: [],
|
||||
error: { code: "workbench_kafka_sse_event_missing" }
|
||||
});
|
||||
} finally {
|
||||
server.stop(true);
|
||||
await app.close();
|
||||
}
|
||||
});
|
||||
|
||||
test("L0 SSE exposes Kafka startup failure without waiting for a read model", async () => {
|
||||
const startupError = Object.assign(new Error("Kafka broker unavailable"), { code: "kafka_broker_unavailable" });
|
||||
const response = await createWorkbenchHttpApp({
|
||||
|
||||
Reference in New Issue
Block a user