Files
oh-my-pi/packages/coding-agent/test/debug/raw-sse-buffer.test.ts
T
can1357 00e6e14cb4 feat: added reconstructed raw SSE capture for stream provider SDKs
- Added reconstructed SSE event emission for OpenAI, Azure, and Anthropic streams.
- Added raw SSE text to debug report bundles, including raw-sse.txt output.
- Included dropped-record metadata in raw SSE text when events were trimmed.
- Updated raw SSE and sse-debug tests for observer-based capture and safety checks.
2026-06-08 02:35:14 +02:00

95 lines
3.1 KiB
TypeScript

import { describe, expect, it } from "bun:test";
import type { Model } from "@oh-my-pi/pi-ai";
import { RawSseDebugBuffer, rawSseRecordLines, resolveRawSseDebugBuffer } from "../../src/debug/raw-sse-buffer";
const model: Model<"anthropic-messages"> = {
id: "claude-test",
name: "Claude Test",
api: "anthropic-messages",
provider: "anthropic",
baseUrl: "https://api.anthropic.com",
reasoning: true,
input: ["text"],
cost: { input: 1, output: 1, cacheRead: 0, cacheWrite: 0 },
contextWindow: 200_000,
maxTokens: 8_192,
};
describe("RawSseDebugBuffer", () => {
it("records response metadata and raw SSE frame lines for diagnostics", () => {
const buffer = new RawSseDebugBuffer();
buffer.recordResponse(
{ status: 200, requestId: "req_123", headers: {}, metadata: { lastTransport: "sse" } },
model,
);
buffer.recordEvent(
{
event: "content_block_delta",
data: '{"type":"content_block_delta"}',
raw: ["event: content_block_delta", 'data: {"type":"content_block_delta"}'],
},
model,
);
const snapshot = buffer.snapshot();
expect(snapshot.totalEvents).toBe(1);
expect(snapshot.records).toHaveLength(2);
const [responseLine] = rawSseRecordLines(snapshot.records[0]);
expect(responseLine).toContain("provider=anthropic model=claude-test");
expect(rawSseRecordLines(snapshot.records[1])).toEqual([
"event: content_block_delta",
'data: {"type":"content_block_delta"}',
]);
expect(buffer.toRawText()).toContain("event: content_block_delta");
});
it("notifies subscribers when new frames arrive", () => {
const buffer = new RawSseDebugBuffer();
let updates = 0;
const unsubscribe = buffer.subscribe(() => {
updates += 1;
});
buffer.recordEvent({ event: null, data: "{}", raw: ["data: {}"] }, model);
unsubscribe();
buffer.recordEvent({ event: null, data: "{}", raw: ["data: {}"] }, model);
expect(updates).toBe(1);
expect(buffer.snapshot().totalEvents).toBe(2);
});
it("creates a fallback buffer for session objects without a preinstalled buffer", () => {
const owner = {};
const buffer = resolveRawSseDebugBuffer(owner);
buffer.recordEvent({ event: "message", data: "{}", raw: ["event: message", "data: {}"] }, model);
expect(resolveRawSseDebugBuffer(owner)).toBe(buffer);
expect(buffer.snapshot().totalEvents).toBe(1);
});
it("keeps session-owned records captured before the viewer resolves the buffer", () => {
const session = { rawSseDebugBuffer: new RawSseDebugBuffer() };
session.rawSseDebugBuffer.recordResponse(
{ status: 200, requestId: "req_pre_viewer", headers: {}, metadata: { lastTransport: "sse" } },
model,
);
session.rawSseDebugBuffer.recordEvent(
{ event: "message_start", data: "{}", raw: ["event: message_start", "data: {}"] },
model,
);
session.rawSseDebugBuffer.recordEvent(
{ event: "message_stop", data: "{}", raw: ["event: message_stop", "data: {}"] },
model,
);
const buffer = resolveRawSseDebugBuffer(session);
expect(buffer).toBe(session.rawSseDebugBuffer);
expect(buffer.snapshot().totalEvents).toBe(2);
expect(buffer.toRawText()).toContain("requestId=req_pre_viewer");
expect(buffer.toRawText()).toContain("event: message_stop");
});
});