|
5 | 5 | } from "../src/server/responses-snapshot-repair"; |
6 | 6 | import { handleResponses } from "../src/server/responses"; |
7 | 7 | import { createTranslatorBudget } from "../src/lib/translator-budget"; |
8 | | -import { isEagerRelaySseResponse } from "../src/server/relay"; |
| 8 | +import { isEagerRelaySseResponse, MAX_COMPLETED_OUTPUT_ITEMS } from "../src/server/relay"; |
9 | 9 | import type { OcxConfig } from "../src/types"; |
10 | 10 |
|
11 | 11 | function parsedSseEvents(text: string): Array<Record<string, unknown>> { |
@@ -112,7 +112,7 @@ describe("Responses passthrough sparse-snapshot repair", () => { |
112 | 112 |
|
113 | 113 | test("repairs output-item status and nested reasoning summary parts", () => { |
114 | 114 | const rewrite = createResponsesSnapshotPayloadRewrite(); |
115 | | - for (const invalidStatus of [undefined, null, 42]) { |
| 115 | + for (const invalidStatus of [undefined, null, 42, ""]) { |
116 | 116 | const added = JSON.parse(rewrite(JSON.stringify({ |
117 | 117 | type: "response.output_item.added", |
118 | 118 | output_index: 0, |
@@ -166,7 +166,7 @@ describe("Responses passthrough sparse-snapshot repair", () => { |
166 | 166 | }); |
167 | 167 |
|
168 | 168 | test("replaces structurally invalid response statuses with the event status", () => { |
169 | | - for (const invalidStatus of [null, 42]) { |
| 169 | + for (const invalidStatus of [null, 42, ""]) { |
170 | 170 | const rewrite = createResponsesSnapshotPayloadRewrite(); |
171 | 171 | const event = JSON.parse(rewrite(JSON.stringify({ |
172 | 172 | type: "response.completed", |
@@ -194,6 +194,16 @@ describe("Responses passthrough sparse-snapshot repair", () => { |
194 | 194 | expect(event.response.output[1]?.status).toBeUndefined(); |
195 | 195 | }); |
196 | 196 |
|
| 197 | + test("repairs non-assistant output message roles to the canonical Responses role", () => { |
| 198 | + const rewrite = createResponsesSnapshotPayloadRewrite(); |
| 199 | + const event = JSON.parse(rewrite(JSON.stringify({ |
| 200 | + type: "response.output_item.added", |
| 201 | + item: { id: "msg_role", type: "message", role: "user", content: [] }, |
| 202 | + }))) as { item: Record<string, unknown> }; |
| 203 | + |
| 204 | + expect(event.item.role).toBe("assistant"); |
| 205 | + }); |
| 206 | + |
197 | 207 | test("reconstructs a sparse completed output from prior done items", () => { |
198 | 208 | for (const sparseOutput of [undefined, null, [], "invalid"]) { |
199 | 209 | const rewrite = createResponsesSnapshotPayloadRewrite(); |
@@ -309,7 +319,7 @@ describe("Responses passthrough sparse-snapshot repair", () => { |
309 | 319 |
|
310 | 320 | test("does not reconstruct a partial terminal after the retained-item cap is exceeded", () => { |
311 | 321 | const rewrite = createResponsesSnapshotPayloadRewrite(); |
312 | | - for (let outputIndex = 0; outputIndex <= 256; outputIndex += 1) { |
| 322 | + for (let outputIndex = 0; outputIndex <= MAX_COMPLETED_OUTPUT_ITEMS; outputIndex += 1) { |
313 | 323 | rewrite(JSON.stringify({ |
314 | 324 | type: "response.output_item.done", |
315 | 325 | output_index: outputIndex, |
|
0 commit comments