diff --git a/tests/unit/chatcore-translation-paths.test.ts b/tests/unit/chatcore-translation-paths.test.ts index 5d4b288946..30d31c0d3b 100644 --- a/tests/unit/chatcore-translation-paths.test.ts +++ b/tests/unit/chatcore-translation-paths.test.ts @@ -2329,6 +2329,12 @@ test("chatCore propagates budget errors without an executor-level emergency hop" assert.equal(result.success, false); assert.equal(result.status, 402); assert.equal(calls.length, 1, "no executor-level emergency hop may fire"); + const body = (await result.response.json()) as any; + assert.match(String(body?.error?.message ?? ""), /insufficient funds/); + assert.ok( + !calls.some((c: any) => String(c.body?.model ?? "").includes("gpt-oss-120b")), + "emergency fallback model must not be called at executor level" + ); }); test("chatCore injects progress events into streaming responses when requested", async () => { diff --git a/tests/unit/executor-vertex-extended.test.ts b/tests/unit/executor-vertex-extended.test.ts index 6318195c40..f7ac599518 100644 --- a/tests/unit/executor-vertex-extended.test.ts +++ b/tests/unit/executor-vertex-extended.test.ts @@ -68,6 +68,7 @@ test("VertexExecutor.buildUrl routes a non-JSON Express API key to the project-l expressUrl, "https://aiplatform.googleapis.com/v1/publishers/google/models/gemini-2.5-flash:generateContent?key=express-key-abc" ); + assert.ok(!expressUrl.includes("/projects/"), "Express key URL must not route through a project path"); }); test("VertexExecutor.buildUrl routes partner and org-prefixed models to the global partner endpoint", () => { diff --git a/tests/unit/stream-utils.test.ts b/tests/unit/stream-utils.test.ts index 933bc549d5..a955759ec1 100644 --- a/tests/unit/stream-utils.test.ts +++ b/tests/unit/stream-utils.test.ts @@ -1053,6 +1053,7 @@ test("createSSEStream passthrough merges Claude usage chunks and restores mapped test("#3685 createSSEStream passthrough emits SSE error (not synthetic text) for empty Claude assistant SSE", async () => { let failurePayload = null; + let completePayload = null; await assert.rejects( readTransformed( [ @@ -1084,6 +1085,9 @@ test("#3685 createSSEStream passthrough emits SSE error (not synthetic text) for onFailure(payload) { failurePayload = payload; }, + onComplete(payload) { + completePayload = payload; + }, } ), /empty response/i @@ -1091,6 +1095,11 @@ test("#3685 createSSEStream passthrough emits SSE error (not synthetic text) for assert.ok(failurePayload, "onFailure should be called"); assert.equal(failurePayload.status, 502); assert.match(failurePayload.message, /empty response/i); + assert.equal(failurePayload.code, "empty_response", "code must identify the failure kind"); + assert.equal(typeof failurePayload.code, "string", "code must be a string"); + assert.ok(failurePayload.message.length > 0, "message must be non-empty"); + assert.ok(failurePayload.status >= 500, "status must be a server error (5xx)"); + assert.equal(completePayload, null, "onComplete must not fire when stream is empty"); }); test("createSSEStream passthrough does not emit [DONE] for Claude SSE clients", async () => { @@ -1151,6 +1160,7 @@ test("createSSEStream passthrough does not emit [DONE] for Claude SSE clients", test("#3685 createSSEStream translate mode emits SSE error (not synthetic text) when OpenAI upstream finishes empty for Claude client", async () => { let failurePayload = null; + let completePayload = null; await assert.rejects( readTransformed( [ @@ -1182,6 +1192,9 @@ test("#3685 createSSEStream translate mode emits SSE error (not synthetic text) onFailure(payload) { failurePayload = payload; }, + onComplete(payload) { + completePayload = payload; + }, } ), /empty response/i @@ -1189,6 +1202,10 @@ test("#3685 createSSEStream translate mode emits SSE error (not synthetic text) assert.ok(failurePayload, "onFailure should be called"); assert.equal(failurePayload.status, 502); assert.match(failurePayload.message, /empty response/i); + assert.equal(failurePayload.code, "empty_response", "code must identify the failure kind"); + assert.ok(failurePayload.message.length > 0, "message must be non-empty"); + assert.ok(failurePayload.status >= 500, "status must be a server error (5xx)"); + assert.equal(completePayload, null, "onComplete must not fire when stream is empty"); }); test("createSSETransformStreamWithLogger flushes a trailing Claude usage event without a newline", async () => {