1 line
116 KiB
JSON
1 line
116 KiB
JSON
{"repo": "ariangibson/understudy", "files": {"test/front-doors.test.ts": {"8d42a24dd9538079a422fa522e639c9df6dc6a1b": {"t": 1785746537.0720115, "n": 20929, "h": "09522e2d801eac57", "c": "import { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\n\n/**\n * App-level tests for the Anthropic Messages and OpenAI Responses front\n * doors — the endpoints that let unmodified Claude Code and Codex sessions\n * fail over across providers. Provider HTTP is stubbed via global fetch.\n */\n\nasync function freshApp(env: Record<string, string> = {}) {\n vi.resetModules();\n // Neutralize upstream overrides a dev shell may have exported (e.g. after\n // a rehearsal/ run) so provider URLs are deterministic under test.\n vi.stubEnv(\"UNDERSTUDY_OPENAI_UPSTREAM\", \"\");\n vi.stubEnv(\"UNDERSTUDY_ANTHROPIC_UPSTREAM\", \"\");\n for (const [k, v] of Object.entries(env)) vi.stubEnv(k, v);\n vi.stubEnv(\"USAGE_LOG\", `/tmp/llm-proxy-test-${Date.now()}-${Math.random()}.jsonl`);\n const { createApp } = await import(\"../src/app.js\");\n return createApp();\n}\n\nbeforeEach(() => {\n vi.unstubAllEnvs();\n});\n\nafterEach(() => {\n vi.unstubAllGlobals();\n vi.unstubAllEnvs();\n});\n\nconst messagesBody = (model: string, extra: object = {}) =>\n JSON.stringify({\n model,\n max_tokens: 1024,\n messages: [{ role: \"user\", content: [{ type: \"text\", text: \"hi\" }] }],\n ...extra,\n });\n\nfunction anthropicMessage(content = \"hello from claude\") {\n return {\n id: \"msg_01\",\n type: \"message\",\n role: \"assistant\",\n model: \"claude-sonnet-4-6\",\n content: [{ type: \"text\", text: content }],\n stop_reason: \"end_turn\",\n stop_sequence: null,\n usage: { input_tokens: 3, output_tokens: 5 },\n };\n}\n\nfunction openaiCompletion(model: string, content = \"hello from fallback\") {\n return {\n id: \"chatcmpl-x\",\n object: \"chat.completion\",\n created: 1,\n model,\n choices: [\n { index: 0, message: { role: \"assistant\", content }, finish_reason: \"stop\" },\n ],\n usage: { prompt_tokens: 1, completion_tokens: 2, total_tokens: 3 },\n };\n}\n\ndescribe(\"/v1/messages — Anthropic passthrough\", () => {\n it(\"forwards to api.anthropic.com with the server key and strips oauth betas\", async () => {\n const app = await freshApp({ ANTHROPIC_API_KEY: \"sk-ant-key\" });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.anthropic.com/v1/messages?beta=true\");\n const headers = init?.headers as Record<string, string>;\n expect(headers[\"x-api-key\"]).toBe(\"sk-ant-key\");\n expect(headers.authorization).toBeUndefined();\n expect(headers[\"anthropic-beta\"]).toBe(\"interleaved-thinking-2025-05-14\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"claude-sonnet-4-6\");\n expect(sent.fallbacks).toBeUndefined();\n return new Response(JSON.stringify(anthropicMessage()), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/messages?beta=true\", {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"anthropic-beta\": \"oauth-2025-04-20,interleaved-thinking-2025-05-14\",\n },\n body: messagesBody(\"claude-sonnet-4-6\", { fallbacks: [] }),\n });\n expect(res.status).toBe(200);\n const json = (await res.json()) as { content: Array<{ text: string }> };\n expect(json.content[0]?.text).toBe(\"hello from claude\");\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"anthropic\");\n });\n\n it(\"forwards a client OAuth token untouched, even with no server key\", async () => {\n const app = await freshApp({ GATEWAY_API_KEYS: \"gw-secret\" }); // no ANTHROPIC_API_KEY\n const fetchMock = vi.fn(async (_url: RequestInfo | URL, init?: RequestInit) => {\n const headers = init?.headers as Record<string, string>;\n expect(headers.authorization).toBe(\"Bearer sk-ant-oat01-token\");\n expect(headers[\"anthropic-beta\"]).toBe(\"oauth-2025-04-20,claude-code-20250219\");\n expect(headers[\"x-api-key\"]).toBeUndefined();\n return new Response(JSON.stringify(anthropicMessage()), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n // Note: the OAuth bearer also passes gateway auth — it is its own credential.\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n authorization: \"Bearer sk-ant-oat01-token\",\n \"anthropic-beta\": \"oauth-2025-04-20,claude-code-20250219\",\n },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n });\n\n it(\"pipes streaming SSE bytes through untouched\", async () => {\n const app = await freshApp({ ANTHROPIC_API_KEY: \"sk-ant-key\" });\n const sse = [\n `event: message_start`,\n `data: {\"type\":\"message_start\",\"message\":{\"id\":\"msg_01\",\"usage\":{\"input_tokens\":3}}}`,\n ``,\n `event: content_block_delta`,\n `data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"hi\"}}`,\n ``,\n `event: message_delta`,\n `data: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\"},\"usage\":{\"output_tokens\":2}}`,\n ``,\n `event: message_stop`,\n `data: {\"type\":\"message_stop\"}`,\n ``,\n ``,\n ].join(\"\\n\");\n vi.stubGlobal(\n \"fetch\",\n vi.fn(\n async () =>\n new Response(sse, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n }),\n ),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\", { stream: true }),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"content-type\")).toContain(\"text/event-stream\");\n expect(await res.text()).toBe(sse);\n });\n});\n\ndescribe(\"/v1/messages — cross-provider failover\", () => {\n it(\"fails over to an OpenAI-compatible provider and answers in Anthropic shape\", async () => {\n const app = await freshApp({\n ANTHROPIC_API_KEY: \"sk-ant-key\",\n DEEPSEEK_API_KEY: \"dk-test\",\n FALLBACK_CHAIN: \"deepseek/deepseek-chat\",\n });\n const calls: string[] = [];\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n calls.push(new URL(String(url)).hostname);\n if (String(url).includes(\"anthropic.com\")) {\n return new Response(\n JSON.stringify({ type: \"error\", error: { type: \"rate_limit_error\", message: \"slow down\" } }),\n { status: 429, headers: { \"retry-after\": \"30\" } },\n );\n }\n // DeepSeek receives the *translated* chat-completions request.\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"deepseek-chat\");\n expect(sent.messages.at(-1)).toEqual({ role: \"user\", content: \"hi\" });\n return new Response(JSON.stringify(openaiCompletion(\"deepseek-chat\", \"rescued\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n }),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n expect(calls).toEqual([\"api.anthropic.com\", \"api.deepseek.com\"]);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"deepseek\");\n expect(res.headers.get(\"x-understudy-fallback\")).toBe(\"from anthropic/claude-sonnet-4-6\");\n\n const json = (await res.json()) as {\n type: string;\n model: string;\n content: Array<{ type: string; text: string }>;\n stop_reason: string;\n };\n expect(json.type).toBe(\"message\"); // Anthropic shape, not chat.completion\n expect(json.model).toBe(\"claude-sonnet-4-6\"); // echoes the requested model\n expect(json.content).toEqual([{ type: \"text\", text: \"rescued\" }]);\n expect(json.stop_reason).toBe(\"end_turn\");\n });\n\n it(\"re-dialects a fallback SSE stream as Anthropic events\", async () => {\n const app = await freshApp({\n ANTHROPIC_API_KEY: \"sk-ant-key\",\n DEEPSEEK_API_KEY: \"dk-test\",\n FALLBACK_CHAIN: \"deepseek/deepseek-chat\",\n });\n const openaiSSE = [\n `data: {\"id\":\"c\",\"object\":\"chat.completion.chunk\",\"created\":1,\"model\":\"deepseek-chat\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"res\"},\"finish_reason\":null}]}`,\n `data: {\"id\":\"c\",\"object\":\"chat.completion.chunk\",\"created\":1,\"model\":\"deepseek-chat\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"cued\"},\"finish_reason\":null}]}`,\n `data: {\"id\":\"c\",\"object\":\"chat.completion.chunk\",\"created\":1,\"model\":\"deepseek-chat\",\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"stop\"}],\"usage\":{\"prompt_tokens\":3,\"completion_tokens\":2,\"total_tokens\":5}}`,\n \"data: [DONE]\",\n \"\",\n ].join(\"\\n\\n\");\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async (url: RequestInfo | URL) => {\n if (String(url).includes(\"anthropic.com\")) {\n return new Response(\"overloaded\", { status: 529 });\n }\n return new Response(openaiSSE, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n });\n }),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\", { stream: true }),\n });\n expect(res.status).toBe(200);\n const text = await res.text();\n expect(text).toContain(\"event: message_start\");\n expect(text).toContain('\"text_delta\",\"text\":\"res\"');\n expect(text).toContain('\"text_delta\",\"text\":\"cued\"');\n expect(text).toContain('\"stop_reason\":\"end_turn\"');\n expect(text).toContain(\"event: message_stop\");\n // The client asked for a Claude model and must see one in message_start.\n expect(text).toContain('\"model\":\"claude-sonnet-4-6\"');\n });\n});\n\ndescribe(\"/v1/messages — OAuth bearer cannot reach server-key providers\", () => {\n // An sk-ant-oat bearer clears gateway auth (it is the caller's own Anthropic\n // credential). It must NOT become a skeleton key to the server's other\n // provider keys — neither by requesting a non-Anthropic model directly nor\n // by failing over onto one.\n const OAT = \"Bearer sk-ant-oat01-fake-token\";\n\n it(\"rejects a non-Anthropic model requested with only an OAuth bearer\", async () => {\n const app = await freshApp({\n GATEWAY_API_KEYS: \"gw-secret\",\n OPENAI_API_KEY: \"sk-openai-server-key\",\n });\n const fetchMock = vi.fn(async () => new Response(\"{}\", { status: 200 }));\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", authorization: OAT },\n body: messagesBody(\"openai/gpt-5.5\"),\n });\n\n expect(res.status).toBe(401);\n // The server key was never spent — no upstream call was made at all.\n expect(fetchMock).not.toHaveBeenCalled();\n });\n\n it(\"does not fail an OAuth-only request over onto a server-key provider\", async () => {\n const app = await freshApp({\n GATEWAY_API_KEYS: \"gw-secret\",\n OPENAI_API_KEY: \"sk-openai-server-key\",\n FALLBACK_CHAIN: \"openai/gpt-5.5\",\n });\n const hosts: string[] = [];\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async (url: RequestInfo | URL) => {\n hosts.push(new URL(String(url)).hostname);\n // Anthropic (the caller's own token) is rate-limited; the only\n // configured fallback is a server-key OpenAI route.\n return new Response(\n JSON.stringify({ type: \"error\", error: { type: \"rate_limit_error\", message: \"slow down\" } }),\n { status: 429, headers: { \"retry-after\": \"30\" } },\n );\n }),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", authorization: OAT },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n\n // The Anthropic attempt is made with the caller's token and 429s, but the\n // chain must NOT roll onto OpenAI's server key — so the client sees the\n // upstream error, and OpenAI is never contacted.\n expect(hosts).toEqual([\"api.anthropic.com\"]);\n expect(hosts).not.toContain(\"api.openai.com\");\n expect(res.status).toBe(429);\n });\n\n it(\"still lets a valid gateway key use other providers\", async () => {\n const app = await freshApp({\n GATEWAY_API_KEYS: \"gw-secret\",\n OPENAI_API_KEY: \"sk-openai-server-key\",\n });\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async () =>\n new Response(JSON.stringify(openaiCompletion(\"gpt-5.5\", \"allowed\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n }),\n ),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", authorization: \"Bearer gw-secret\" },\n body: messagesBody(\"openai/gpt-5.5\"),\n });\n\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"openai\");\n });\n});\n\ndescribe(\"/v1/responses — Codex front door\", () => {\n const responsesBody = (model: string, extra: object = {}) =>\n JSON.stringify({\n model,\n instructions: \"You are Codex.\",\n input: [\n {\n type: \"message\",\n role: \"user\",\n content: [{ type: \"input_text\", text: \"hi\" }],\n },\n ],\n tools: [],\n tool_choice: \"auto\",\n store: false,\n stream: false,\n ...extra,\n });\n\n it(\"translates to chat completions and back to a Responses object\", async () => {\n const app = await freshApp({ OPENAI_API_KEY: \"sk-test\" });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.openai.com/v1/chat/completions\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.messages[0]).toEqual({ role: \"system\", content: \"You are Codex.\" });\n expect(sent.messages[1]).toEqual({ role: \"user\", content: \"hi\" });\n return new Response(JSON.stringify(openaiCompletion(\"gpt-5-mini\", \"hi there\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/responses\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: responsesBody(\"gpt-5-mini\"),\n });\n expect(res.status).toBe(200);\n const json = (await res.json()) as {\n object: string;\n status: string;\n output: Array<{ type: string; content: Array<{ text: string }> }>;\n };\n expect(json.object).toBe(\"response\");\n expect(json.status).toBe(\"completed\");\n expect(json.output[0]?.content[0]?.text).toBe(\"hi there\");\n });\n\n it(\"serves Codex from a chat-completions-only host (synthetic.new)\", async () => {\n const app = await freshApp({ SYNTHETIC_API_KEY: \"syn-test\" });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.synthetic.new/openai/v1/chat/completions\");\n const headers = init?.headers as Record<string, string>;\n expect(headers.authorization).toBe(\"Bearer syn-test\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"syn:large:vision\");\n return new Response(\n JSON.stringify(openaiCompletion(\"syn:large:vision\", \"open model here\")),\n { status: 200, headers: { \"content-type\": \"application/json\" } },\n );\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/responses\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: responsesBody(\"syn:large:vision\"),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"synthetic\");\n const json = (await res.json()) as {\n object: string;\n output: Array<{ content: Array<{ text: string }> }>;\n };\n expect(json.object).toBe(\"response\");\n expect(json.output[0]?.content[0]?.text).toBe(\"open model here\");\n });\n\n it(\"streams Responses events and fails over across providers\", async () => {\n const app = await freshApp({\n OPENAI_API_KEY: \"sk-test\",\n ANTHROPIC_API_KEY: \"sk-ant-key\",\n FALLBACK_CHAIN: \"anthropic/claude-sonnet-4-6\",\n });\n const anthropicSSE = [\n `event: message_start`,\n `data: {\"type\":\"message_start\",\"message\":{\"id\":\"msg_01\",\"usage\":{\"input_tokens\":3}}}`,\n ``,\n `event: content_block_start`,\n `data: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}`,\n ``,\n `event: content_block_delta`,\n `data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"claude to the rescue\"}}`,\n ``,\n `event: message_delta`,\n `data: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\"},\"usage\":{\"output_tokens\":4}}`,\n ``,\n `event: message_stop`,\n `data: {\"type\":\"message_stop\"}`,\n ``,\n ``,\n ].join(\"\\n\");\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async (url: RequestInfo | URL) => {\n if (String(url).includes(\"openai.com\")) {\n return new Response(JSON.stringify({ error: { message: \"rate limited\" } }), {\n status: 429,\n });\n }\n expect(String(url)).toContain(\"api.anthropic.com/v1/messages\");\n return new Response(anthropicSSE, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n });\n }),\n );\n\n const res = await app.request(\"/v1/responses\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: responsesBody(\"gpt-5-mini\", { stream: true }),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"anthropic\");\n expect(res.headers.get(\"x-understudy-fallback\")).toBe(\"from openai/gpt-5-mini\");\n\n const text = await res.text();\n expect(text).toContain(\"event: response.created\");\n expect(text).toContain(\"event: response.output_text.delta\");\n expect(text).toContain('\"delta\":\"claude to the rescue\"');\n expect(text).toContain(\"event: response.completed\");\n });\n});\n\ndescribe(\"MODEL_OVERRIDES\", () => {\n it(\"rewrites the requested model before routing\", async () => {\n const app = await freshApp({\n GROQ_API_KEY: \"gk-test\",\n MODEL_OVERRIDES: \"claude-3-5-haiku*=groq/llama-3.3-70b\",\n });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.groq.com/openai/v1/chat/completions\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"llama-3.3-70b\");\n return new Response(JSON.stringify(openaiCompletion(\"llama-3.3-70b\", \"overridden\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/chat/completions\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n model: \"claude-3-5-haiku-20241022\",\n messages: [{ role: \"user\", content: \"hi\" }],\n }),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"groq\");\n });\n\n it(\"applies on the Messages front door too, answering in Anthropic shape\", async () => {\n const app = await freshApp({\n DEEPSEEK_API_KEY: \"dk-test\",\n MODEL_OVERRIDES: \"claude-*=deepseek/deepseek-chat\",\n });\n vi.stubGlobal(\n \"fetch\",\n vi.fn(\n async () =>\n new Response(JSON.stringify(openaiCompletion(\"deepseek-chat\", \"ds answer\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n }),\n ),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"deepseek\");\n const json = (await res.json()) as { type: string; content: Array<{ text: string }> };\n expect(json.type).toBe(\"message\");\n expect(json.content[0]?.text).toBe(\"ds answer\");\n });\n});\n\ndescribe(\"/v1/messages/count_tokens\", () => {\n it(\"estimates locally when no upstream key is configured\", async () => {\n const app = await freshApp();\n const res = await app.request(\"/v1/messages/count_tokens\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n const json = (await res.json()) as { input_tokens: number };\n expect(json.input_tokens).toBeGreaterThan(0);\n });\n});\n"}, "bc4ce7c85a1a44964d7fb956c5f2dbcd811e8e43": {"t": 1785765438.1845603, "n": 20929, "h": "09522e2d801eac57", "c": "import { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\n\n/**\n * App-level tests for the Anthropic Messages and OpenAI Responses front\n * doors — the endpoints that let unmodified Claude Code and Codex sessions\n * fail over across providers. Provider HTTP is stubbed via global fetch.\n */\n\nasync function freshApp(env: Record<string, string> = {}) {\n vi.resetModules();\n // Neutralize upstream overrides a dev shell may have exported (e.g. after\n // a rehearsal/ run) so provider URLs are deterministic under test.\n vi.stubEnv(\"UNDERSTUDY_OPENAI_UPSTREAM\", \"\");\n vi.stubEnv(\"UNDERSTUDY_ANTHROPIC_UPSTREAM\", \"\");\n for (const [k, v] of Object.entries(env)) vi.stubEnv(k, v);\n vi.stubEnv(\"USAGE_LOG\", `/tmp/llm-proxy-test-${Date.now()}-${Math.random()}.jsonl`);\n const { createApp } = await import(\"../src/app.js\");\n return createApp();\n}\n\nbeforeEach(() => {\n vi.unstubAllEnvs();\n});\n\nafterEach(() => {\n vi.unstubAllGlobals();\n vi.unstubAllEnvs();\n});\n\nconst messagesBody = (model: string, extra: object = {}) =>\n JSON.stringify({\n model,\n max_tokens: 1024,\n messages: [{ role: \"user\", content: [{ type: \"text\", text: \"hi\" }] }],\n ...extra,\n });\n\nfunction anthropicMessage(content = \"hello from claude\") {\n return {\n id: \"msg_01\",\n type: \"message\",\n role: \"assistant\",\n model: \"claude-sonnet-4-6\",\n content: [{ type: \"text\", text: content }],\n stop_reason: \"end_turn\",\n stop_sequence: null,\n usage: { input_tokens: 3, output_tokens: 5 },\n };\n}\n\nfunction openaiCompletion(model: string, content = \"hello from fallback\") {\n return {\n id: \"chatcmpl-x\",\n object: \"chat.completion\",\n created: 1,\n model,\n choices: [\n { index: 0, message: { role: \"assistant\", content }, finish_reason: \"stop\" },\n ],\n usage: { prompt_tokens: 1, completion_tokens: 2, total_tokens: 3 },\n };\n}\n\ndescribe(\"/v1/messages — Anthropic passthrough\", () => {\n it(\"forwards to api.anthropic.com with the server key and strips oauth betas\", async () => {\n const app = await freshApp({ ANTHROPIC_API_KEY: \"sk-ant-key\" });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.anthropic.com/v1/messages?beta=true\");\n const headers = init?.headers as Record<string, string>;\n expect(headers[\"x-api-key\"]).toBe(\"sk-ant-key\");\n expect(headers.authorization).toBeUndefined();\n expect(headers[\"anthropic-beta\"]).toBe(\"interleaved-thinking-2025-05-14\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"claude-sonnet-4-6\");\n expect(sent.fallbacks).toBeUndefined();\n return new Response(JSON.stringify(anthropicMessage()), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/messages?beta=true\", {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"anthropic-beta\": \"oauth-2025-04-20,interleaved-thinking-2025-05-14\",\n },\n body: messagesBody(\"claude-sonnet-4-6\", { fallbacks: [] }),\n });\n expect(res.status).toBe(200);\n const json = (await res.json()) as { content: Array<{ text: string }> };\n expect(json.content[0]?.text).toBe(\"hello from claude\");\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"anthropic\");\n });\n\n it(\"forwards a client OAuth token untouched, even with no server key\", async () => {\n const app = await freshApp({ GATEWAY_API_KEYS: \"gw-secret\" }); // no ANTHROPIC_API_KEY\n const fetchMock = vi.fn(async (_url: RequestInfo | URL, init?: RequestInit) => {\n const headers = init?.headers as Record<string, string>;\n expect(headers.authorization).toBe(\"Bearer sk-ant-oat01-token\");\n expect(headers[\"anthropic-beta\"]).toBe(\"oauth-2025-04-20,claude-code-20250219\");\n expect(headers[\"x-api-key\"]).toBeUndefined();\n return new Response(JSON.stringify(anthropicMessage()), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n // Note: the OAuth bearer also passes gateway auth — it is its own credential.\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n authorization: \"Bearer sk-ant-oat01-token\",\n \"anthropic-beta\": \"oauth-2025-04-20,claude-code-20250219\",\n },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n });\n\n it(\"pipes streaming SSE bytes through untouched\", async () => {\n const app = await freshApp({ ANTHROPIC_API_KEY: \"sk-ant-key\" });\n const sse = [\n `event: message_start`,\n `data: {\"type\":\"message_start\",\"message\":{\"id\":\"msg_01\",\"usage\":{\"input_tokens\":3}}}`,\n ``,\n `event: content_block_delta`,\n `data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"hi\"}}`,\n ``,\n `event: message_delta`,\n `data: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\"},\"usage\":{\"output_tokens\":2}}`,\n ``,\n `event: message_stop`,\n `data: {\"type\":\"message_stop\"}`,\n ``,\n ``,\n ].join(\"\\n\");\n vi.stubGlobal(\n \"fetch\",\n vi.fn(\n async () =>\n new Response(sse, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n }),\n ),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\", { stream: true }),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"content-type\")).toContain(\"text/event-stream\");\n expect(await res.text()).toBe(sse);\n });\n});\n\ndescribe(\"/v1/messages — cross-provider failover\", () => {\n it(\"fails over to an OpenAI-compatible provider and answers in Anthropic shape\", async () => {\n const app = await freshApp({\n ANTHROPIC_API_KEY: \"sk-ant-key\",\n DEEPSEEK_API_KEY: \"dk-test\",\n FALLBACK_CHAIN: \"deepseek/deepseek-chat\",\n });\n const calls: string[] = [];\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n calls.push(new URL(String(url)).hostname);\n if (String(url).includes(\"anthropic.com\")) {\n return new Response(\n JSON.stringify({ type: \"error\", error: { type: \"rate_limit_error\", message: \"slow down\" } }),\n { status: 429, headers: { \"retry-after\": \"30\" } },\n );\n }\n // DeepSeek receives the *translated* chat-completions request.\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"deepseek-chat\");\n expect(sent.messages.at(-1)).toEqual({ role: \"user\", content: \"hi\" });\n return new Response(JSON.stringify(openaiCompletion(\"deepseek-chat\", \"rescued\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n }),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n expect(calls).toEqual([\"api.anthropic.com\", \"api.deepseek.com\"]);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"deepseek\");\n expect(res.headers.get(\"x-understudy-fallback\")).toBe(\"from anthropic/claude-sonnet-4-6\");\n\n const json = (await res.json()) as {\n type: string;\n model: string;\n content: Array<{ type: string; text: string }>;\n stop_reason: string;\n };\n expect(json.type).toBe(\"message\"); // Anthropic shape, not chat.completion\n expect(json.model).toBe(\"claude-sonnet-4-6\"); // echoes the requested model\n expect(json.content).toEqual([{ type: \"text\", text: \"rescued\" }]);\n expect(json.stop_reason).toBe(\"end_turn\");\n });\n\n it(\"re-dialects a fallback SSE stream as Anthropic events\", async () => {\n const app = await freshApp({\n ANTHROPIC_API_KEY: \"sk-ant-key\",\n DEEPSEEK_API_KEY: \"dk-test\",\n FALLBACK_CHAIN: \"deepseek/deepseek-chat\",\n });\n const openaiSSE = [\n `data: {\"id\":\"c\",\"object\":\"chat.completion.chunk\",\"created\":1,\"model\":\"deepseek-chat\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"res\"},\"finish_reason\":null}]}`,\n `data: {\"id\":\"c\",\"object\":\"chat.completion.chunk\",\"created\":1,\"model\":\"deepseek-chat\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"cued\"},\"finish_reason\":null}]}`,\n `data: {\"id\":\"c\",\"object\":\"chat.completion.chunk\",\"created\":1,\"model\":\"deepseek-chat\",\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"stop\"}],\"usage\":{\"prompt_tokens\":3,\"completion_tokens\":2,\"total_tokens\":5}}`,\n \"data: [DONE]\",\n \"\",\n ].join(\"\\n\\n\");\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async (url: RequestInfo | URL) => {\n if (String(url).includes(\"anthropic.com\")) {\n return new Response(\"overloaded\", { status: 529 });\n }\n return new Response(openaiSSE, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n });\n }),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\", { stream: true }),\n });\n expect(res.status).toBe(200);\n const text = await res.text();\n expect(text).toContain(\"event: message_start\");\n expect(text).toContain('\"text_delta\",\"text\":\"res\"');\n expect(text).toContain('\"text_delta\",\"text\":\"cued\"');\n expect(text).toContain('\"stop_reason\":\"end_turn\"');\n expect(text).toContain(\"event: message_stop\");\n // The client asked for a Claude model and must see one in message_start.\n expect(text).toContain('\"model\":\"claude-sonnet-4-6\"');\n });\n});\n\ndescribe(\"/v1/messages — OAuth bearer cannot reach server-key providers\", () => {\n // An sk-ant-oat bearer clears gateway auth (it is the caller's own Anthropic\n // credential). It must NOT become a skeleton key to the server's other\n // provider keys — neither by requesting a non-Anthropic model directly nor\n // by failing over onto one.\n const OAT = \"Bearer sk-ant-oat01-fake-token\";\n\n it(\"rejects a non-Anthropic model requested with only an OAuth bearer\", async () => {\n const app = await freshApp({\n GATEWAY_API_KEYS: \"gw-secret\",\n OPENAI_API_KEY: \"sk-openai-server-key\",\n });\n const fetchMock = vi.fn(async () => new Response(\"{}\", { status: 200 }));\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", authorization: OAT },\n body: messagesBody(\"openai/gpt-5.5\"),\n });\n\n expect(res.status).toBe(401);\n // The server key was never spent — no upstream call was made at all.\n expect(fetchMock).not.toHaveBeenCalled();\n });\n\n it(\"does not fail an OAuth-only request over onto a server-key provider\", async () => {\n const app = await freshApp({\n GATEWAY_API_KEYS: \"gw-secret\",\n OPENAI_API_KEY: \"sk-openai-server-key\",\n FALLBACK_CHAIN: \"openai/gpt-5.5\",\n });\n const hosts: string[] = [];\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async (url: RequestInfo | URL) => {\n hosts.push(new URL(String(url)).hostname);\n // Anthropic (the caller's own token) is rate-limited; the only\n // configured fallback is a server-key OpenAI route.\n return new Response(\n JSON.stringify({ type: \"error\", error: { type: \"rate_limit_error\", message: \"slow down\" } }),\n { status: 429, headers: { \"retry-after\": \"30\" } },\n );\n }),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", authorization: OAT },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n\n // The Anthropic attempt is made with the caller's token and 429s, but the\n // chain must NOT roll onto OpenAI's server key — so the client sees the\n // upstream error, and OpenAI is never contacted.\n expect(hosts).toEqual([\"api.anthropic.com\"]);\n expect(hosts).not.toContain(\"api.openai.com\");\n expect(res.status).toBe(429);\n });\n\n it(\"still lets a valid gateway key use other providers\", async () => {\n const app = await freshApp({\n GATEWAY_API_KEYS: \"gw-secret\",\n OPENAI_API_KEY: \"sk-openai-server-key\",\n });\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async () =>\n new Response(JSON.stringify(openaiCompletion(\"gpt-5.5\", \"allowed\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n }),\n ),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", authorization: \"Bearer gw-secret\" },\n body: messagesBody(\"openai/gpt-5.5\"),\n });\n\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"openai\");\n });\n});\n\ndescribe(\"/v1/responses — Codex front door\", () => {\n const responsesBody = (model: string, extra: object = {}) =>\n JSON.stringify({\n model,\n instructions: \"You are Codex.\",\n input: [\n {\n type: \"message\",\n role: \"user\",\n content: [{ type: \"input_text\", text: \"hi\" }],\n },\n ],\n tools: [],\n tool_choice: \"auto\",\n store: false,\n stream: false,\n ...extra,\n });\n\n it(\"translates to chat completions and back to a Responses object\", async () => {\n const app = await freshApp({ OPENAI_API_KEY: \"sk-test\" });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.openai.com/v1/chat/completions\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.messages[0]).toEqual({ role: \"system\", content: \"You are Codex.\" });\n expect(sent.messages[1]).toEqual({ role: \"user\", content: \"hi\" });\n return new Response(JSON.stringify(openaiCompletion(\"gpt-5-mini\", \"hi there\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/responses\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: responsesBody(\"gpt-5-mini\"),\n });\n expect(res.status).toBe(200);\n const json = (await res.json()) as {\n object: string;\n status: string;\n output: Array<{ type: string; content: Array<{ text: string }> }>;\n };\n expect(json.object).toBe(\"response\");\n expect(json.status).toBe(\"completed\");\n expect(json.output[0]?.content[0]?.text).toBe(\"hi there\");\n });\n\n it(\"serves Codex from a chat-completions-only host (synthetic.new)\", async () => {\n const app = await freshApp({ SYNTHETIC_API_KEY: \"syn-test\" });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.synthetic.new/openai/v1/chat/completions\");\n const headers = init?.headers as Record<string, string>;\n expect(headers.authorization).toBe(\"Bearer syn-test\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"syn:large:vision\");\n return new Response(\n JSON.stringify(openaiCompletion(\"syn:large:vision\", \"open model here\")),\n { status: 200, headers: { \"content-type\": \"application/json\" } },\n );\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/responses\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: responsesBody(\"syn:large:vision\"),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"synthetic\");\n const json = (await res.json()) as {\n object: string;\n output: Array<{ content: Array<{ text: string }> }>;\n };\n expect(json.object).toBe(\"response\");\n expect(json.output[0]?.content[0]?.text).toBe(\"open model here\");\n });\n\n it(\"streams Responses events and fails over across providers\", async () => {\n const app = await freshApp({\n OPENAI_API_KEY: \"sk-test\",\n ANTHROPIC_API_KEY: \"sk-ant-key\",\n FALLBACK_CHAIN: \"anthropic/claude-sonnet-4-6\",\n });\n const anthropicSSE = [\n `event: message_start`,\n `data: {\"type\":\"message_start\",\"message\":{\"id\":\"msg_01\",\"usage\":{\"input_tokens\":3}}}`,\n ``,\n `event: content_block_start`,\n `data: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}`,\n ``,\n `event: content_block_delta`,\n `data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"claude to the rescue\"}}`,\n ``,\n `event: message_delta`,\n `data: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\"},\"usage\":{\"output_tokens\":4}}`,\n ``,\n `event: message_stop`,\n `data: {\"type\":\"message_stop\"}`,\n ``,\n ``,\n ].join(\"\\n\");\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async (url: RequestInfo | URL) => {\n if (String(url).includes(\"openai.com\")) {\n return new Response(JSON.stringify({ error: { message: \"rate limited\" } }), {\n status: 429,\n });\n }\n expect(String(url)).toContain(\"api.anthropic.com/v1/messages\");\n return new Response(anthropicSSE, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n });\n }),\n );\n\n const res = await app.request(\"/v1/responses\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: responsesBody(\"gpt-5-mini\", { stream: true }),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"anthropic\");\n expect(res.headers.get(\"x-understudy-fallback\")).toBe(\"from openai/gpt-5-mini\");\n\n const text = await res.text();\n expect(text).toContain(\"event: response.created\");\n expect(text).toContain(\"event: response.output_text.delta\");\n expect(text).toContain('\"delta\":\"claude to the rescue\"');\n expect(text).toContain(\"event: response.completed\");\n });\n});\n\ndescribe(\"MODEL_OVERRIDES\", () => {\n it(\"rewrites the requested model before routing\", async () => {\n const app = await freshApp({\n GROQ_API_KEY: \"gk-test\",\n MODEL_OVERRIDES: \"claude-3-5-haiku*=groq/llama-3.3-70b\",\n });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.groq.com/openai/v1/chat/completions\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"llama-3.3-70b\");\n return new Response(JSON.stringify(openaiCompletion(\"llama-3.3-70b\", \"overridden\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/chat/completions\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n model: \"claude-3-5-haiku-20241022\",\n messages: [{ role: \"user\", content: \"hi\" }],\n }),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"groq\");\n });\n\n it(\"applies on the Messages front door too, answering in Anthropic shape\", async () => {\n const app = await freshApp({\n DEEPSEEK_API_KEY: \"dk-test\",\n MODEL_OVERRIDES: \"claude-*=deepseek/deepseek-chat\",\n });\n vi.stubGlobal(\n \"fetch\",\n vi.fn(\n async () =>\n new Response(JSON.stringify(openaiCompletion(\"deepseek-chat\", \"ds answer\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n }),\n ),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"deepseek\");\n const json = (await res.json()) as { type: string; content: Array<{ text: string }> };\n expect(json.type).toBe(\"message\");\n expect(json.content[0]?.text).toBe(\"ds answer\");\n });\n});\n\ndescribe(\"/v1/messages/count_tokens\", () => {\n it(\"estimates locally when no upstream key is configured\", async () => {\n const app = await freshApp();\n const res = await app.request(\"/v1/messages/count_tokens\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n const json = (await res.json()) as { input_tokens: number };\n expect(json.input_tokens).toBeGreaterThan(0);\n });\n});\n"}, "8b955380f23a542a0ac3c61c3bdedbabeaf3ce22": {"t": 1785765439.6191978, "n": 17734, "h": "91a03d522cfd9e8c", "c": "import { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\n\n/**\n * App-level tests for the Anthropic Messages and OpenAI Responses front\n * doors — the endpoints that let unmodified Claude Code and Codex sessions\n * fail over across providers. Provider HTTP is stubbed via global fetch.\n */\n\nasync function freshApp(env: Record<string, string> = {}) {\n vi.resetModules();\n // Neutralize upstream overrides a dev shell may have exported (e.g. after\n // a rehearsal/ run) so provider URLs are deterministic under test.\n vi.stubEnv(\"UNDERSTUDY_OPENAI_UPSTREAM\", \"\");\n vi.stubEnv(\"UNDERSTUDY_ANTHROPIC_UPSTREAM\", \"\");\n for (const [k, v] of Object.entries(env)) vi.stubEnv(k, v);\n vi.stubEnv(\"USAGE_LOG\", `/tmp/llm-proxy-test-${Date.now()}-${Math.random()}.jsonl`);\n const { createApp } = await import(\"../src/app.js\");\n return createApp();\n}\n\nbeforeEach(() => {\n vi.unstubAllEnvs();\n});\n\nafterEach(() => {\n vi.unstubAllGlobals();\n vi.unstubAllEnvs();\n});\n\nconst messagesBody = (model: string, extra: object = {}) =>\n JSON.stringify({\n model,\n max_tokens: 1024,\n messages: [{ role: \"user\", content: [{ type: \"text\", text: \"hi\" }] }],\n ...extra,\n });\n\nfunction anthropicMessage(content = \"hello from claude\") {\n return {\n id: \"msg_01\",\n type: \"message\",\n role: \"assistant\",\n model: \"claude-sonnet-4-6\",\n content: [{ type: \"text\", text: content }],\n stop_reason: \"end_turn\",\n stop_sequence: null,\n usage: { input_tokens: 3, output_tokens: 5 },\n };\n}\n\nfunction openaiCompletion(model: string, content = \"hello from fallback\") {\n return {\n id: \"chatcmpl-x\",\n object: \"chat.completion\",\n created: 1,\n model,\n choices: [\n { index: 0, message: { role: \"assistant\", content }, finish_reason: \"stop\" },\n ],\n usage: { prompt_tokens: 1, completion_tokens: 2, total_tokens: 3 },\n };\n}\n\ndescribe(\"/v1/messages — Anthropic passthrough\", () => {\n it(\"forwards to api.anthropic.com with the server key and strips oauth betas\", async () => {\n const app = await freshApp({ ANTHROPIC_API_KEY: \"sk-ant-key\" });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.anthropic.com/v1/messages?beta=true\");\n const headers = init?.headers as Record<string, string>;\n expect(headers[\"x-api-key\"]).toBe(\"sk-ant-key\");\n expect(headers.authorization).toBeUndefined();\n expect(headers[\"anthropic-beta\"]).toBe(\"interleaved-thinking-2025-05-14\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"claude-sonnet-4-6\");\n expect(sent.fallbacks).toBeUndefined();\n return new Response(JSON.stringify(anthropicMessage()), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/messages?beta=true\", {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"anthropic-beta\": \"oauth-2025-04-20,interleaved-thinking-2025-05-14\",\n },\n body: messagesBody(\"claude-sonnet-4-6\", { fallbacks: [] }),\n });\n expect(res.status).toBe(200);\n const json = (await res.json()) as { content: Array<{ text: string }> };\n expect(json.content[0]?.text).toBe(\"hello from claude\");\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"anthropic\");\n });\n\n it(\"forwards a client OAuth token untouched, even with no server key\", async () => {\n const app = await freshApp({ GATEWAY_API_KEYS: \"gw-secret\" }); // no ANTHROPIC_API_KEY\n const fetchMock = vi.fn(async (_url: RequestInfo | URL, init?: RequestInit) => {\n const headers = init?.headers as Record<string, string>;\n expect(headers.authorization).toBe(\"Bearer sk-ant-oat01-token\");\n expect(headers[\"anthropic-beta\"]).toBe(\"oauth-2025-04-20,claude-code-20250219\");\n expect(headers[\"x-api-key\"]).toBeUndefined();\n return new Response(JSON.stringify(anthropicMessage()), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n // Note: the OAuth bearer also passes gateway auth — it is its own credential.\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n authorization: \"Bearer sk-ant-oat01-token\",\n \"anthropic-beta\": \"oauth-2025-04-20,claude-code-20250219\",\n },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n });\n\n it(\"pipes streaming SSE bytes through untouched\", async () => {\n const app = await freshApp({ ANTHROPIC_API_KEY: \"sk-ant-key\" });\n const sse = [\n `event: message_start`,\n `data: {\"type\":\"message_start\",\"message\":{\"id\":\"msg_01\",\"usage\":{\"input_tokens\":3}}}`,\n ``,\n `event: content_block_delta`,\n `data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"hi\"}}`,\n ``,\n `event: message_delta`,\n `data: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\"},\"usage\":{\"output_tokens\":2}}`,\n ``,\n `event: message_stop`,\n `data: {\"type\":\"message_stop\"}`,\n ``,\n ``,\n ].join(\"\\n\");\n vi.stubGlobal(\n \"fetch\",\n vi.fn(\n async () =>\n new Response(sse, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n }),\n ),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\", { stream: true }),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"content-type\")).toContain(\"text/event-stream\");\n expect(await res.text()).toBe(sse);\n });\n});\n\ndescribe(\"/v1/messages — cross-provider failover\", () => {\n it(\"fails over to an OpenAI-compatible provider and answers in Anthropic shape\", async () => {\n const app = await freshApp({\n ANTHROPIC_API_KEY: \"sk-ant-key\",\n DEEPSEEK_API_KEY: \"dk-test\",\n FALLBACK_CHAIN: \"deepseek/deepseek-chat\",\n });\n const calls: string[] = [];\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n calls.push(new URL(String(url)).hostname);\n if (String(url).includes(\"anthropic.com\")) {\n return new Response(\n JSON.stringify({ type: \"error\", error: { type: \"rate_limit_error\", message: \"slow down\" } }),\n { status: 429, headers: { \"retry-after\": \"30\" } },\n );\n }\n // DeepSeek receives the *translated* chat-completions request.\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"deepseek-chat\");\n expect(sent.messages.at(-1)).toEqual({ role: \"user\", content: \"hi\" });\n return new Response(JSON.stringify(openaiCompletion(\"deepseek-chat\", \"rescued\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n }),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n expect(calls).toEqual([\"api.anthropic.com\", \"api.deepseek.com\"]);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"deepseek\");\n expect(res.headers.get(\"x-understudy-fallback\")).toBe(\"from anthropic/claude-sonnet-4-6\");\n\n const json = (await res.json()) as {\n type: string;\n model: string;\n content: Array<{ type: string; text: string }>;\n stop_reason: string;\n };\n expect(json.type).toBe(\"message\"); // Anthropic shape, not chat.completion\n expect(json.model).toBe(\"claude-sonnet-4-6\"); // echoes the requested model\n expect(json.content).toEqual([{ type: \"text\", text: \"rescued\" }]);\n expect(json.stop_reason).toBe(\"end_turn\");\n });\n\n it(\"re-dialects a fallback SSE stream as Anthropic events\", async () => {\n const app = await freshApp({\n ANTHROPIC_API_KEY: \"sk-ant-key\",\n DEEPSEEK_API_KEY: \"dk-test\",\n FALLBACK_CHAIN: \"deepseek/deepseek-chat\",\n });\n const openaiSSE = [\n `data: {\"id\":\"c\",\"object\":\"chat.completion.chunk\",\"created\":1,\"model\":\"deepseek-chat\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"res\"},\"finish_reason\":null}]}`,\n `data: {\"id\":\"c\",\"object\":\"chat.completion.chunk\",\"created\":1,\"model\":\"deepseek-chat\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"cued\"},\"finish_reason\":null}]}`,\n `data: {\"id\":\"c\",\"object\":\"chat.completion.chunk\",\"created\":1,\"model\":\"deepseek-chat\",\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"stop\"}],\"usage\":{\"prompt_tokens\":3,\"completion_tokens\":2,\"total_tokens\":5}}`,\n \"data: [DONE]\",\n \"\",\n ].join(\"\\n\\n\");\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async (url: RequestInfo | URL) => {\n if (String(url).includes(\"anthropic.com\")) {\n return new Response(\"overloaded\", { status: 529 });\n }\n return new Response(openaiSSE, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n });\n }),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\", { stream: true }),\n });\n expect(res.status).toBe(200);\n const text = await res.text();\n expect(text).toContain(\"event: message_start\");\n expect(text).toContain('\"text_delta\",\"text\":\"res\"');\n expect(text).toContain('\"text_delta\",\"text\":\"cued\"');\n expect(text).toContain('\"stop_reason\":\"end_turn\"');\n expect(text).toContain(\"event: message_stop\");\n // The client asked for a Claude model and must see one in message_start.\n expect(text).toContain('\"model\":\"claude-sonnet-4-6\"');\n });\n});\n\ndescribe(\"/v1/responses — Codex front door\", () => {\n const responsesBody = (model: string, extra: object = {}) =>\n JSON.stringify({\n model,\n instructions: \"You are Codex.\",\n input: [\n {\n type: \"message\",\n role: \"user\",\n content: [{ type: \"input_text\", text: \"hi\" }],\n },\n ],\n tools: [],\n tool_choice: \"auto\",\n store: false,\n stream: false,\n ...extra,\n });\n\n it(\"translates to chat completions and back to a Responses object\", async () => {\n const app = await freshApp({ OPENAI_API_KEY: \"sk-test\" });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.openai.com/v1/chat/completions\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.messages[0]).toEqual({ role: \"system\", content: \"You are Codex.\" });\n expect(sent.messages[1]).toEqual({ role: \"user\", content: \"hi\" });\n return new Response(JSON.stringify(openaiCompletion(\"gpt-5-mini\", \"hi there\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/responses\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: responsesBody(\"gpt-5-mini\"),\n });\n expect(res.status).toBe(200);\n const json = (await res.json()) as {\n object: string;\n status: string;\n output: Array<{ type: string; content: Array<{ text: string }> }>;\n };\n expect(json.object).toBe(\"response\");\n expect(json.status).toBe(\"completed\");\n expect(json.output[0]?.content[0]?.text).toBe(\"hi there\");\n });\n\n it(\"serves Codex from a chat-completions-only host (synthetic.new)\", async () => {\n const app = await freshApp({ SYNTHETIC_API_KEY: \"syn-test\" });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.synthetic.new/openai/v1/chat/completions\");\n const headers = init?.headers as Record<string, string>;\n expect(headers.authorization).toBe(\"Bearer syn-test\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"syn:large:vision\");\n return new Response(\n JSON.stringify(openaiCompletion(\"syn:large:vision\", \"open model here\")),\n { status: 200, headers: { \"content-type\": \"application/json\" } },\n );\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/responses\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: responsesBody(\"syn:large:vision\"),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"synthetic\");\n const json = (await res.json()) as {\n object: string;\n output: Array<{ content: Array<{ text: string }> }>;\n };\n expect(json.object).toBe(\"response\");\n expect(json.output[0]?.content[0]?.text).toBe(\"open model here\");\n });\n\n it(\"streams Responses events and fails over across providers\", async () => {\n const app = await freshApp({\n OPENAI_API_KEY: \"sk-test\",\n ANTHROPIC_API_KEY: \"sk-ant-key\",\n FALLBACK_CHAIN: \"anthropic/claude-sonnet-4-6\",\n });\n const anthropicSSE = [\n `event: message_start`,\n `data: {\"type\":\"message_start\",\"message\":{\"id\":\"msg_01\",\"usage\":{\"input_tokens\":3}}}`,\n ``,\n `event: content_block_start`,\n `data: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}`,\n ``,\n `event: content_block_delta`,\n `data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"claude to the rescue\"}}`,\n ``,\n `event: message_delta`,\n `data: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\"},\"usage\":{\"output_tokens\":4}}`,\n ``,\n `event: message_stop`,\n `data: {\"type\":\"message_stop\"}`,\n ``,\n ``,\n ].join(\"\\n\");\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async (url: RequestInfo | URL) => {\n if (String(url).includes(\"openai.com\")) {\n return new Response(JSON.stringify({ error: { message: \"rate limited\" } }), {\n status: 429,\n });\n }\n expect(String(url)).toContain(\"api.anthropic.com/v1/messages\");\n return new Response(anthropicSSE, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n });\n }),\n );\n\n const res = await app.request(\"/v1/responses\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: responsesBody(\"gpt-5-mini\", { stream: true }),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"anthropic\");\n expect(res.headers.get(\"x-understudy-fallback\")).toBe(\"from openai/gpt-5-mini\");\n\n const text = await res.text();\n expect(text).toContain(\"event: response.created\");\n expect(text).toContain(\"event: response.output_text.delta\");\n expect(text).toContain('\"delta\":\"claude to the rescue\"');\n expect(text).toContain(\"event: response.completed\");\n });\n});\n\ndescribe(\"MODEL_OVERRIDES\", () => {\n it(\"rewrites the requested model before routing\", async () => {\n const app = await freshApp({\n GROQ_API_KEY: \"gk-test\",\n MODEL_OVERRIDES: \"claude-3-5-haiku*=groq/llama-3.3-70b\",\n });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.groq.com/openai/v1/chat/completions\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"llama-3.3-70b\");\n return new Response(JSON.stringify(openaiCompletion(\"llama-3.3-70b\", \"overridden\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/chat/completions\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n model: \"claude-3-5-haiku-20241022\",\n messages: [{ role: \"user\", content: \"hi\" }],\n }),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"groq\");\n });\n\n it(\"applies on the Messages front door too, answering in Anthropic shape\", async () => {\n const app = await freshApp({\n DEEPSEEK_API_KEY: \"dk-test\",\n MODEL_OVERRIDES: \"claude-*=deepseek/deepseek-chat\",\n });\n vi.stubGlobal(\n \"fetch\",\n vi.fn(\n async () =>\n new Response(JSON.stringify(openaiCompletion(\"deepseek-chat\", \"ds answer\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n }),\n ),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"deepseek\");\n const json = (await res.json()) as { type: string; content: Array<{ text: string }> };\n expect(json.type).toBe(\"message\");\n expect(json.content[0]?.text).toBe(\"ds answer\");\n });\n});\n\ndescribe(\"/v1/messages/count_tokens\", () => {\n it(\"estimates locally when no upstream key is configured\", async () => {\n const app = await freshApp();\n const res = await app.request(\"/v1/messages/count_tokens\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n const json = (await res.json()) as { input_tokens: number };\n expect(json.input_tokens).toBeGreaterThan(0);\n });\n});\n"}, "c20c27b01d29a4d60f477128a02708b0d2ce4420": {"t": 1785765441.193825, "n": 17488, "h": "9d66ba6c48f5a8c9", "c": "import { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\n\n/**\n * App-level tests for the Anthropic Messages and OpenAI Responses front\n * doors — the endpoints that let unmodified Claude Code and Codex sessions\n * fail over across providers. Provider HTTP is stubbed via global fetch.\n */\n\nasync function freshApp(env: Record<string, string> = {}) {\n vi.resetModules();\n for (const [k, v] of Object.entries(env)) vi.stubEnv(k, v);\n vi.stubEnv(\"USAGE_LOG\", `/tmp/llm-proxy-test-${Date.now()}-${Math.random()}.jsonl`);\n const { createApp } = await import(\"../src/app.js\");\n return createApp();\n}\n\nbeforeEach(() => {\n vi.unstubAllEnvs();\n});\n\nafterEach(() => {\n vi.unstubAllGlobals();\n vi.unstubAllEnvs();\n});\n\nconst messagesBody = (model: string, extra: object = {}) =>\n JSON.stringify({\n model,\n max_tokens: 1024,\n messages: [{ role: \"user\", content: [{ type: \"text\", text: \"hi\" }] }],\n ...extra,\n });\n\nfunction anthropicMessage(content = \"hello from claude\") {\n return {\n id: \"msg_01\",\n type: \"message\",\n role: \"assistant\",\n model: \"claude-sonnet-4-6\",\n content: [{ type: \"text\", text: content }],\n stop_reason: \"end_turn\",\n stop_sequence: null,\n usage: { input_tokens: 3, output_tokens: 5 },\n };\n}\n\nfunction openaiCompletion(model: string, content = \"hello from fallback\") {\n return {\n id: \"chatcmpl-x\",\n object: \"chat.completion\",\n created: 1,\n model,\n choices: [\n { index: 0, message: { role: \"assistant\", content }, finish_reason: \"stop\" },\n ],\n usage: { prompt_tokens: 1, completion_tokens: 2, total_tokens: 3 },\n };\n}\n\ndescribe(\"/v1/messages — Anthropic passthrough\", () => {\n it(\"forwards to api.anthropic.com with the server key and strips oauth betas\", async () => {\n const app = await freshApp({ ANTHROPIC_API_KEY: \"sk-ant-key\" });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.anthropic.com/v1/messages?beta=true\");\n const headers = init?.headers as Record<string, string>;\n expect(headers[\"x-api-key\"]).toBe(\"sk-ant-key\");\n expect(headers.authorization).toBeUndefined();\n expect(headers[\"anthropic-beta\"]).toBe(\"interleaved-thinking-2025-05-14\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"claude-sonnet-4-6\");\n expect(sent.fallbacks).toBeUndefined();\n return new Response(JSON.stringify(anthropicMessage()), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/messages?beta=true\", {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"anthropic-beta\": \"oauth-2025-04-20,interleaved-thinking-2025-05-14\",\n },\n body: messagesBody(\"claude-sonnet-4-6\", { fallbacks: [] }),\n });\n expect(res.status).toBe(200);\n const json = (await res.json()) as { content: Array<{ text: string }> };\n expect(json.content[0]?.text).toBe(\"hello from claude\");\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"anthropic\");\n });\n\n it(\"forwards a client OAuth token untouched, even with no server key\", async () => {\n const app = await freshApp({ GATEWAY_API_KEYS: \"gw-secret\" }); // no ANTHROPIC_API_KEY\n const fetchMock = vi.fn(async (_url: RequestInfo | URL, init?: RequestInit) => {\n const headers = init?.headers as Record<string, string>;\n expect(headers.authorization).toBe(\"Bearer sk-ant-oat01-token\");\n expect(headers[\"anthropic-beta\"]).toBe(\"oauth-2025-04-20,claude-code-20250219\");\n expect(headers[\"x-api-key\"]).toBeUndefined();\n return new Response(JSON.stringify(anthropicMessage()), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n // Note: the OAuth bearer also passes gateway auth — it is its own credential.\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n authorization: \"Bearer sk-ant-oat01-token\",\n \"anthropic-beta\": \"oauth-2025-04-20,claude-code-20250219\",\n },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n });\n\n it(\"pipes streaming SSE bytes through untouched\", async () => {\n const app = await freshApp({ ANTHROPIC_API_KEY: \"sk-ant-key\" });\n const sse = [\n `event: message_start`,\n `data: {\"type\":\"message_start\",\"message\":{\"id\":\"msg_01\",\"usage\":{\"input_tokens\":3}}}`,\n ``,\n `event: content_block_delta`,\n `data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"hi\"}}`,\n ``,\n `event: message_delta`,\n `data: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\"},\"usage\":{\"output_tokens\":2}}`,\n ``,\n `event: message_stop`,\n `data: {\"type\":\"message_stop\"}`,\n ``,\n ``,\n ].join(\"\\n\");\n vi.stubGlobal(\n \"fetch\",\n vi.fn(\n async () =>\n new Response(sse, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n }),\n ),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\", { stream: true }),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"content-type\")).toContain(\"text/event-stream\");\n expect(await res.text()).toBe(sse);\n });\n});\n\ndescribe(\"/v1/messages — cross-provider failover\", () => {\n it(\"fails over to an OpenAI-compatible provider and answers in Anthropic shape\", async () => {\n const app = await freshApp({\n ANTHROPIC_API_KEY: \"sk-ant-key\",\n DEEPSEEK_API_KEY: \"dk-test\",\n FALLBACK_CHAIN: \"deepseek/deepseek-chat\",\n });\n const calls: string[] = [];\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n calls.push(new URL(String(url)).hostname);\n if (String(url).includes(\"anthropic.com\")) {\n return new Response(\n JSON.stringify({ type: \"error\", error: { type: \"rate_limit_error\", message: \"slow down\" } }),\n { status: 429, headers: { \"retry-after\": \"30\" } },\n );\n }\n // DeepSeek receives the *translated* chat-completions request.\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"deepseek-chat\");\n expect(sent.messages.at(-1)).toEqual({ role: \"user\", content: \"hi\" });\n return new Response(JSON.stringify(openaiCompletion(\"deepseek-chat\", \"rescued\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n }),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n expect(calls).toEqual([\"api.anthropic.com\", \"api.deepseek.com\"]);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"deepseek\");\n expect(res.headers.get(\"x-understudy-fallback\")).toBe(\"from anthropic/claude-sonnet-4-6\");\n\n const json = (await res.json()) as {\n type: string;\n model: string;\n content: Array<{ type: string; text: string }>;\n stop_reason: string;\n };\n expect(json.type).toBe(\"message\"); // Anthropic shape, not chat.completion\n expect(json.model).toBe(\"claude-sonnet-4-6\"); // echoes the requested model\n expect(json.content).toEqual([{ type: \"text\", text: \"rescued\" }]);\n expect(json.stop_reason).toBe(\"end_turn\");\n });\n\n it(\"re-dialects a fallback SSE stream as Anthropic events\", async () => {\n const app = await freshApp({\n ANTHROPIC_API_KEY: \"sk-ant-key\",\n DEEPSEEK_API_KEY: \"dk-test\",\n FALLBACK_CHAIN: \"deepseek/deepseek-chat\",\n });\n const openaiSSE = [\n `data: {\"id\":\"c\",\"object\":\"chat.completion.chunk\",\"created\":1,\"model\":\"deepseek-chat\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"res\"},\"finish_reason\":null}]}`,\n `data: {\"id\":\"c\",\"object\":\"chat.completion.chunk\",\"created\":1,\"model\":\"deepseek-chat\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"cued\"},\"finish_reason\":null}]}`,\n `data: {\"id\":\"c\",\"object\":\"chat.completion.chunk\",\"created\":1,\"model\":\"deepseek-chat\",\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"stop\"}],\"usage\":{\"prompt_tokens\":3,\"completion_tokens\":2,\"total_tokens\":5}}`,\n \"data: [DONE]\",\n \"\",\n ].join(\"\\n\\n\");\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async (url: RequestInfo | URL) => {\n if (String(url).includes(\"anthropic.com\")) {\n return new Response(\"overloaded\", { status: 529 });\n }\n return new Response(openaiSSE, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n });\n }),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\", { stream: true }),\n });\n expect(res.status).toBe(200);\n const text = await res.text();\n expect(text).toContain(\"event: message_start\");\n expect(text).toContain('\"text_delta\",\"text\":\"res\"');\n expect(text).toContain('\"text_delta\",\"text\":\"cued\"');\n expect(text).toContain('\"stop_reason\":\"end_turn\"');\n expect(text).toContain(\"event: message_stop\");\n // The client asked for a Claude model and must see one in message_start.\n expect(text).toContain('\"model\":\"claude-sonnet-4-6\"');\n });\n});\n\ndescribe(\"/v1/responses — Codex front door\", () => {\n const responsesBody = (model: string, extra: object = {}) =>\n JSON.stringify({\n model,\n instructions: \"You are Codex.\",\n input: [\n {\n type: \"message\",\n role: \"user\",\n content: [{ type: \"input_text\", text: \"hi\" }],\n },\n ],\n tools: [],\n tool_choice: \"auto\",\n store: false,\n stream: false,\n ...extra,\n });\n\n it(\"translates to chat completions and back to a Responses object\", async () => {\n const app = await freshApp({ OPENAI_API_KEY: \"sk-test\" });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.openai.com/v1/chat/completions\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.messages[0]).toEqual({ role: \"system\", content: \"You are Codex.\" });\n expect(sent.messages[1]).toEqual({ role: \"user\", content: \"hi\" });\n return new Response(JSON.stringify(openaiCompletion(\"gpt-5-mini\", \"hi there\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/responses\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: responsesBody(\"gpt-5-mini\"),\n });\n expect(res.status).toBe(200);\n const json = (await res.json()) as {\n object: string;\n status: string;\n output: Array<{ type: string; content: Array<{ text: string }> }>;\n };\n expect(json.object).toBe(\"response\");\n expect(json.status).toBe(\"completed\");\n expect(json.output[0]?.content[0]?.text).toBe(\"hi there\");\n });\n\n it(\"serves Codex from a chat-completions-only host (synthetic.new)\", async () => {\n const app = await freshApp({ SYNTHETIC_API_KEY: \"syn-test\" });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.synthetic.new/openai/v1/chat/completions\");\n const headers = init?.headers as Record<string, string>;\n expect(headers.authorization).toBe(\"Bearer syn-test\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"syn:large:vision\");\n return new Response(\n JSON.stringify(openaiCompletion(\"syn:large:vision\", \"open model here\")),\n { status: 200, headers: { \"content-type\": \"application/json\" } },\n );\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/responses\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: responsesBody(\"syn:large:vision\"),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"synthetic\");\n const json = (await res.json()) as {\n object: string;\n output: Array<{ content: Array<{ text: string }> }>;\n };\n expect(json.object).toBe(\"response\");\n expect(json.output[0]?.content[0]?.text).toBe(\"open model here\");\n });\n\n it(\"streams Responses events and fails over across providers\", async () => {\n const app = await freshApp({\n OPENAI_API_KEY: \"sk-test\",\n ANTHROPIC_API_KEY: \"sk-ant-key\",\n FALLBACK_CHAIN: \"anthropic/claude-sonnet-4-6\",\n });\n const anthropicSSE = [\n `event: message_start`,\n `data: {\"type\":\"message_start\",\"message\":{\"id\":\"msg_01\",\"usage\":{\"input_tokens\":3}}}`,\n ``,\n `event: content_block_start`,\n `data: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}`,\n ``,\n `event: content_block_delta`,\n `data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"claude to the rescue\"}}`,\n ``,\n `event: message_delta`,\n `data: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\"},\"usage\":{\"output_tokens\":4}}`,\n ``,\n `event: message_stop`,\n `data: {\"type\":\"message_stop\"}`,\n ``,\n ``,\n ].join(\"\\n\");\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async (url: RequestInfo | URL) => {\n if (String(url).includes(\"openai.com\")) {\n return new Response(JSON.stringify({ error: { message: \"rate limited\" } }), {\n status: 429,\n });\n }\n expect(String(url)).toContain(\"api.anthropic.com/v1/messages\");\n return new Response(anthropicSSE, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n });\n }),\n );\n\n const res = await app.request(\"/v1/responses\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: responsesBody(\"gpt-5-mini\", { stream: true }),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"anthropic\");\n expect(res.headers.get(\"x-understudy-fallback\")).toBe(\"from openai/gpt-5-mini\");\n\n const text = await res.text();\n expect(text).toContain(\"event: response.created\");\n expect(text).toContain(\"event: response.output_text.delta\");\n expect(text).toContain('\"delta\":\"claude to the rescue\"');\n expect(text).toContain(\"event: response.completed\");\n });\n});\n\ndescribe(\"MODEL_OVERRIDES\", () => {\n it(\"rewrites the requested model before routing\", async () => {\n const app = await freshApp({\n GROQ_API_KEY: \"gk-test\",\n MODEL_OVERRIDES: \"claude-3-5-haiku*=groq/llama-3.3-70b\",\n });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.groq.com/openai/v1/chat/completions\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"llama-3.3-70b\");\n return new Response(JSON.stringify(openaiCompletion(\"llama-3.3-70b\", \"overridden\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/chat/completions\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n model: \"claude-3-5-haiku-20241022\",\n messages: [{ role: \"user\", content: \"hi\" }],\n }),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"groq\");\n });\n\n it(\"applies on the Messages front door too, answering in Anthropic shape\", async () => {\n const app = await freshApp({\n DEEPSEEK_API_KEY: \"dk-test\",\n MODEL_OVERRIDES: \"claude-*=deepseek/deepseek-chat\",\n });\n vi.stubGlobal(\n \"fetch\",\n vi.fn(\n async () =>\n new Response(JSON.stringify(openaiCompletion(\"deepseek-chat\", \"ds answer\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n }),\n ),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"deepseek\");\n const json = (await res.json()) as { type: string; content: Array<{ text: string }> };\n expect(json.type).toBe(\"message\");\n expect(json.content[0]?.text).toBe(\"ds answer\");\n });\n});\n\ndescribe(\"/v1/messages/count_tokens\", () => {\n it(\"estimates locally when no upstream key is configured\", async () => {\n const app = await freshApp();\n const res = await app.request(\"/v1/messages/count_tokens\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n const json = (await res.json()) as { input_tokens: number };\n expect(json.input_tokens).toBeGreaterThan(0);\n });\n});\n"}, "9f41854cdc156fe4f8afca3c114d5beaf888a47e": {"t": 1785765442.7125475, "n": 17497, "h": "3af8663e58229482", "c": "import { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\n\n/**\n * App-level tests for the Anthropic Messages and OpenAI Responses front\n * doors — the endpoints that let unmodified Claude Code and Codex sessions\n * fail over across providers. Provider HTTP is stubbed via global fetch.\n */\n\nasync function freshApp(env: Record<string, string> = {}) {\n vi.resetModules();\n for (const [k, v] of Object.entries(env)) vi.stubEnv(k, v);\n vi.stubEnv(\"USAGE_LOG\", `/tmp/llm-proxy-test-${Date.now()}-${Math.random()}.jsonl`);\n const { createApp } = await import(\"../src/app.js\");\n return createApp();\n}\n\nbeforeEach(() => {\n vi.unstubAllEnvs();\n});\n\nafterEach(() => {\n vi.unstubAllGlobals();\n vi.unstubAllEnvs();\n});\n\nconst messagesBody = (model: string, extra: object = {}) =>\n JSON.stringify({\n model,\n max_tokens: 1024,\n messages: [{ role: \"user\", content: [{ type: \"text\", text: \"hi\" }] }],\n ...extra,\n });\n\nfunction anthropicMessage(content = \"hello from claude\") {\n return {\n id: \"msg_01\",\n type: \"message\",\n role: \"assistant\",\n model: \"claude-sonnet-4-6\",\n content: [{ type: \"text\", text: content }],\n stop_reason: \"end_turn\",\n stop_sequence: null,\n usage: { input_tokens: 3, output_tokens: 5 },\n };\n}\n\nfunction openaiCompletion(model: string, content = \"hello from fallback\") {\n return {\n id: \"chatcmpl-x\",\n object: \"chat.completion\",\n created: 1,\n model,\n choices: [\n { index: 0, message: { role: \"assistant\", content }, finish_reason: \"stop\" },\n ],\n usage: { prompt_tokens: 1, completion_tokens: 2, total_tokens: 3 },\n };\n}\n\ndescribe(\"/v1/messages — Anthropic passthrough\", () => {\n it(\"forwards to api.anthropic.com with the server key and strips oauth betas\", async () => {\n const app = await freshApp({ ANTHROPIC_API_KEY: \"sk-ant-key\" });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.anthropic.com/v1/messages?beta=true\");\n const headers = init?.headers as Record<string, string>;\n expect(headers[\"x-api-key\"]).toBe(\"sk-ant-key\");\n expect(headers.authorization).toBeUndefined();\n expect(headers[\"anthropic-beta\"]).toBe(\"interleaved-thinking-2025-05-14\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"claude-sonnet-4-6\");\n expect(sent.fallbacks).toBeUndefined();\n return new Response(JSON.stringify(anthropicMessage()), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/messages?beta=true\", {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"anthropic-beta\": \"oauth-2025-04-20,interleaved-thinking-2025-05-14\",\n },\n body: messagesBody(\"claude-sonnet-4-6\", { fallbacks: [] }),\n });\n expect(res.status).toBe(200);\n const json = (await res.json()) as { content: Array<{ text: string }> };\n expect(json.content[0]?.text).toBe(\"hello from claude\");\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"anthropic\");\n });\n\n it(\"forwards a client OAuth token untouched, even with no server key\", async () => {\n const app = await freshApp({ GATEWAY_API_KEYS: \"gw-secret\" }); // no ANTHROPIC_API_KEY\n const fetchMock = vi.fn(async (_url: RequestInfo | URL, init?: RequestInit) => {\n const headers = init?.headers as Record<string, string>;\n expect(headers.authorization).toBe(\"Bearer sk-ant-oat01-token\");\n expect(headers[\"anthropic-beta\"]).toBe(\"oauth-2025-04-20,claude-code-20250219\");\n expect(headers[\"x-api-key\"]).toBeUndefined();\n return new Response(JSON.stringify(anthropicMessage()), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n // Note: the OAuth bearer also passes gateway auth — it is its own credential.\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n authorization: \"Bearer sk-ant-oat01-token\",\n \"anthropic-beta\": \"oauth-2025-04-20,claude-code-20250219\",\n },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n });\n\n it(\"pipes streaming SSE bytes through untouched\", async () => {\n const app = await freshApp({ ANTHROPIC_API_KEY: \"sk-ant-key\" });\n const sse = [\n `event: message_start`,\n `data: {\"type\":\"message_start\",\"message\":{\"id\":\"msg_01\",\"usage\":{\"input_tokens\":3}}}`,\n ``,\n `event: content_block_delta`,\n `data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"hi\"}}`,\n ``,\n `event: message_delta`,\n `data: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\"},\"usage\":{\"output_tokens\":2}}`,\n ``,\n `event: message_stop`,\n `data: {\"type\":\"message_stop\"}`,\n ``,\n ``,\n ].join(\"\\n\");\n vi.stubGlobal(\n \"fetch\",\n vi.fn(\n async () =>\n new Response(sse, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n }),\n ),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\", { stream: true }),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"content-type\")).toContain(\"text/event-stream\");\n expect(await res.text()).toBe(sse);\n });\n});\n\ndescribe(\"/v1/messages — cross-provider failover\", () => {\n it(\"fails over to an OpenAI-compatible provider and answers in Anthropic shape\", async () => {\n const app = await freshApp({\n ANTHROPIC_API_KEY: \"sk-ant-key\",\n DEEPSEEK_API_KEY: \"dk-test\",\n FALLBACK_CHAIN: \"deepseek/deepseek-chat\",\n });\n const calls: string[] = [];\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n calls.push(new URL(String(url)).hostname);\n if (String(url).includes(\"anthropic.com\")) {\n return new Response(\n JSON.stringify({ type: \"error\", error: { type: \"rate_limit_error\", message: \"slow down\" } }),\n { status: 429, headers: { \"retry-after\": \"30\" } },\n );\n }\n // DeepSeek receives the *translated* chat-completions request.\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"deepseek-chat\");\n expect(sent.messages.at(-1)).toEqual({ role: \"user\", content: \"hi\" });\n return new Response(JSON.stringify(openaiCompletion(\"deepseek-chat\", \"rescued\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n }),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n expect(calls).toEqual([\"api.anthropic.com\", \"api.deepseek.com\"]);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"deepseek\");\n expect(res.headers.get(\"x-understudy-fallback\")).toBe(\"from anthropic/claude-sonnet-4-6\");\n\n const json = (await res.json()) as {\n type: string;\n model: string;\n content: Array<{ type: string; text: string }>;\n stop_reason: string;\n };\n expect(json.type).toBe(\"message\"); // Anthropic shape, not chat.completion\n expect(json.model).toBe(\"claude-sonnet-4-6\"); // echoes the requested model\n expect(json.content).toEqual([{ type: \"text\", text: \"rescued\" }]);\n expect(json.stop_reason).toBe(\"end_turn\");\n });\n\n it(\"re-dialects a fallback SSE stream as Anthropic events\", async () => {\n const app = await freshApp({\n ANTHROPIC_API_KEY: \"sk-ant-key\",\n DEEPSEEK_API_KEY: \"dk-test\",\n FALLBACK_CHAIN: \"deepseek/deepseek-chat\",\n });\n const openaiSSE = [\n `data: {\"id\":\"c\",\"object\":\"chat.completion.chunk\",\"created\":1,\"model\":\"deepseek-chat\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"res\"},\"finish_reason\":null}]}`,\n `data: {\"id\":\"c\",\"object\":\"chat.completion.chunk\",\"created\":1,\"model\":\"deepseek-chat\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"cued\"},\"finish_reason\":null}]}`,\n `data: {\"id\":\"c\",\"object\":\"chat.completion.chunk\",\"created\":1,\"model\":\"deepseek-chat\",\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"stop\"}],\"usage\":{\"prompt_tokens\":3,\"completion_tokens\":2,\"total_tokens\":5}}`,\n \"data: [DONE]\",\n \"\",\n ].join(\"\\n\\n\");\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async (url: RequestInfo | URL) => {\n if (String(url).includes(\"anthropic.com\")) {\n return new Response(\"overloaded\", { status: 529 });\n }\n return new Response(openaiSSE, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n });\n }),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\", { stream: true }),\n });\n expect(res.status).toBe(200);\n const text = await res.text();\n expect(text).toContain(\"event: message_start\");\n expect(text).toContain('\"text_delta\",\"text\":\"res\"');\n expect(text).toContain('\"text_delta\",\"text\":\"cued\"');\n expect(text).toContain('\"stop_reason\":\"end_turn\"');\n expect(text).toContain(\"event: message_stop\");\n // The client asked for a Claude model and must see one in message_start.\n expect(text).toContain('\"model\":\"claude-sonnet-4-6\"');\n });\n});\n\ndescribe(\"/v1/responses — Codex front door\", () => {\n const responsesBody = (model: string, extra: object = {}) =>\n JSON.stringify({\n model,\n instructions: \"You are Codex.\",\n input: [\n {\n type: \"message\",\n role: \"user\",\n content: [{ type: \"input_text\", text: \"hi\" }],\n },\n ],\n tools: [],\n tool_choice: \"auto\",\n store: false,\n stream: false,\n ...extra,\n });\n\n it(\"translates to chat completions and back to a Responses object\", async () => {\n const app = await freshApp({ OPENAI_API_KEY: \"sk-test\" });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.openai.com/v1/chat/completions\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.messages[0]).toEqual({ role: \"system\", content: \"You are Codex.\" });\n expect(sent.messages[1]).toEqual({ role: \"user\", content: \"hi\" });\n return new Response(JSON.stringify(openaiCompletion(\"gpt-5-mini\", \"hi there\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/responses\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: responsesBody(\"gpt-5-mini\"),\n });\n expect(res.status).toBe(200);\n const json = (await res.json()) as {\n object: string;\n status: string;\n output: Array<{ type: string; content: Array<{ text: string }> }>;\n };\n expect(json.object).toBe(\"response\");\n expect(json.status).toBe(\"completed\");\n expect(json.output[0]?.content[0]?.text).toBe(\"hi there\");\n });\n\n it(\"serves Codex from a chat-completions-only host (synthetic.new)\", async () => {\n const app = await freshApp({ SYNTHETIC_API_KEY: \"syn-test\" });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.synthetic.new/openai/v1/chat/completions\");\n const headers = init?.headers as Record<string, string>;\n expect(headers.authorization).toBe(\"Bearer syn-test\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"hf:moonshotai/Kimi-K2.6\");\n return new Response(\n JSON.stringify(openaiCompletion(\"hf:moonshotai/Kimi-K2.6\", \"kimi here\")),\n { status: 200, headers: { \"content-type\": \"application/json\" } },\n );\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/responses\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: responsesBody(\"hf:moonshotai/Kimi-K2.6\"),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"synthetic\");\n const json = (await res.json()) as {\n object: string;\n output: Array<{ content: Array<{ text: string }> }>;\n };\n expect(json.object).toBe(\"response\");\n expect(json.output[0]?.content[0]?.text).toBe(\"kimi here\");\n });\n\n it(\"streams Responses events and fails over across providers\", async () => {\n const app = await freshApp({\n OPENAI_API_KEY: \"sk-test\",\n ANTHROPIC_API_KEY: \"sk-ant-key\",\n FALLBACK_CHAIN: \"anthropic/claude-sonnet-4-6\",\n });\n const anthropicSSE = [\n `event: message_start`,\n `data: {\"type\":\"message_start\",\"message\":{\"id\":\"msg_01\",\"usage\":{\"input_tokens\":3}}}`,\n ``,\n `event: content_block_start`,\n `data: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}`,\n ``,\n `event: content_block_delta`,\n `data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"claude to the rescue\"}}`,\n ``,\n `event: message_delta`,\n `data: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\"},\"usage\":{\"output_tokens\":4}}`,\n ``,\n `event: message_stop`,\n `data: {\"type\":\"message_stop\"}`,\n ``,\n ``,\n ].join(\"\\n\");\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async (url: RequestInfo | URL) => {\n if (String(url).includes(\"openai.com\")) {\n return new Response(JSON.stringify({ error: { message: \"rate limited\" } }), {\n status: 429,\n });\n }\n expect(String(url)).toContain(\"api.anthropic.com/v1/messages\");\n return new Response(anthropicSSE, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n });\n }),\n );\n\n const res = await app.request(\"/v1/responses\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: responsesBody(\"gpt-5-mini\", { stream: true }),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"anthropic\");\n expect(res.headers.get(\"x-understudy-fallback\")).toBe(\"from openai/gpt-5-mini\");\n\n const text = await res.text();\n expect(text).toContain(\"event: response.created\");\n expect(text).toContain(\"event: response.output_text.delta\");\n expect(text).toContain('\"delta\":\"claude to the rescue\"');\n expect(text).toContain(\"event: response.completed\");\n });\n});\n\ndescribe(\"MODEL_OVERRIDES\", () => {\n it(\"rewrites the requested model before routing\", async () => {\n const app = await freshApp({\n GROQ_API_KEY: \"gk-test\",\n MODEL_OVERRIDES: \"claude-3-5-haiku*=groq/llama-3.3-70b\",\n });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.groq.com/openai/v1/chat/completions\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"llama-3.3-70b\");\n return new Response(JSON.stringify(openaiCompletion(\"llama-3.3-70b\", \"overridden\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/chat/completions\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n model: \"claude-3-5-haiku-20241022\",\n messages: [{ role: \"user\", content: \"hi\" }],\n }),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"groq\");\n });\n\n it(\"applies on the Messages front door too, answering in Anthropic shape\", async () => {\n const app = await freshApp({\n DEEPSEEK_API_KEY: \"dk-test\",\n MODEL_OVERRIDES: \"claude-*=deepseek/deepseek-chat\",\n });\n vi.stubGlobal(\n \"fetch\",\n vi.fn(\n async () =>\n new Response(JSON.stringify(openaiCompletion(\"deepseek-chat\", \"ds answer\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n }),\n ),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"deepseek\");\n const json = (await res.json()) as { type: string; content: Array<{ text: string }> };\n expect(json.type).toBe(\"message\");\n expect(json.content[0]?.text).toBe(\"ds answer\");\n });\n});\n\ndescribe(\"/v1/messages/count_tokens\", () => {\n it(\"estimates locally when no upstream key is configured\", async () => {\n const app = await freshApp();\n const res = await app.request(\"/v1/messages/count_tokens\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n const json = (await res.json()) as { input_tokens: number };\n expect(json.input_tokens).toBeGreaterThan(0);\n });\n});\n"}, "14a9627f3baf2485db176d35d1ce17d04de90014": {"t": 1785765444.070743, "n": 16160, "h": "0a962cdd3c965233", "c": "import { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\n\n/**\n * App-level tests for the Anthropic Messages and OpenAI Responses front\n * doors — the endpoints that let unmodified Claude Code and Codex sessions\n * fail over across providers. Provider HTTP is stubbed via global fetch.\n */\n\nasync function freshApp(env: Record<string, string> = {}) {\n vi.resetModules();\n for (const [k, v] of Object.entries(env)) vi.stubEnv(k, v);\n vi.stubEnv(\"USAGE_LOG\", `/tmp/llm-proxy-test-${Date.now()}-${Math.random()}.jsonl`);\n const { createApp } = await import(\"../src/app.js\");\n return createApp();\n}\n\nbeforeEach(() => {\n vi.unstubAllEnvs();\n});\n\nafterEach(() => {\n vi.unstubAllGlobals();\n vi.unstubAllEnvs();\n});\n\nconst messagesBody = (model: string, extra: object = {}) =>\n JSON.stringify({\n model,\n max_tokens: 1024,\n messages: [{ role: \"user\", content: [{ type: \"text\", text: \"hi\" }] }],\n ...extra,\n });\n\nfunction anthropicMessage(content = \"hello from claude\") {\n return {\n id: \"msg_01\",\n type: \"message\",\n role: \"assistant\",\n model: \"claude-sonnet-4-6\",\n content: [{ type: \"text\", text: content }],\n stop_reason: \"end_turn\",\n stop_sequence: null,\n usage: { input_tokens: 3, output_tokens: 5 },\n };\n}\n\nfunction openaiCompletion(model: string, content = \"hello from fallback\") {\n return {\n id: \"chatcmpl-x\",\n object: \"chat.completion\",\n created: 1,\n model,\n choices: [\n { index: 0, message: { role: \"assistant\", content }, finish_reason: \"stop\" },\n ],\n usage: { prompt_tokens: 1, completion_tokens: 2, total_tokens: 3 },\n };\n}\n\ndescribe(\"/v1/messages — Anthropic passthrough\", () => {\n it(\"forwards to api.anthropic.com with the server key and strips oauth betas\", async () => {\n const app = await freshApp({ ANTHROPIC_API_KEY: \"sk-ant-key\" });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.anthropic.com/v1/messages?beta=true\");\n const headers = init?.headers as Record<string, string>;\n expect(headers[\"x-api-key\"]).toBe(\"sk-ant-key\");\n expect(headers.authorization).toBeUndefined();\n expect(headers[\"anthropic-beta\"]).toBe(\"interleaved-thinking-2025-05-14\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"claude-sonnet-4-6\");\n expect(sent.fallbacks).toBeUndefined();\n return new Response(JSON.stringify(anthropicMessage()), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/messages?beta=true\", {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"anthropic-beta\": \"oauth-2025-04-20,interleaved-thinking-2025-05-14\",\n },\n body: messagesBody(\"claude-sonnet-4-6\", { fallbacks: [] }),\n });\n expect(res.status).toBe(200);\n const json = (await res.json()) as { content: Array<{ text: string }> };\n expect(json.content[0]?.text).toBe(\"hello from claude\");\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"anthropic\");\n });\n\n it(\"forwards a client OAuth token untouched, even with no server key\", async () => {\n const app = await freshApp({ GATEWAY_API_KEYS: \"gw-secret\" }); // no ANTHROPIC_API_KEY\n const fetchMock = vi.fn(async (_url: RequestInfo | URL, init?: RequestInit) => {\n const headers = init?.headers as Record<string, string>;\n expect(headers.authorization).toBe(\"Bearer sk-ant-oat01-token\");\n expect(headers[\"anthropic-beta\"]).toBe(\"oauth-2025-04-20,claude-code-20250219\");\n expect(headers[\"x-api-key\"]).toBeUndefined();\n return new Response(JSON.stringify(anthropicMessage()), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n // Note: the OAuth bearer also passes gateway auth — it is its own credential.\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n authorization: \"Bearer sk-ant-oat01-token\",\n \"anthropic-beta\": \"oauth-2025-04-20,claude-code-20250219\",\n },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n });\n\n it(\"pipes streaming SSE bytes through untouched\", async () => {\n const app = await freshApp({ ANTHROPIC_API_KEY: \"sk-ant-key\" });\n const sse = [\n `event: message_start`,\n `data: {\"type\":\"message_start\",\"message\":{\"id\":\"msg_01\",\"usage\":{\"input_tokens\":3}}}`,\n ``,\n `event: content_block_delta`,\n `data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"hi\"}}`,\n ``,\n `event: message_delta`,\n `data: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\"},\"usage\":{\"output_tokens\":2}}`,\n ``,\n `event: message_stop`,\n `data: {\"type\":\"message_stop\"}`,\n ``,\n ``,\n ].join(\"\\n\");\n vi.stubGlobal(\n \"fetch\",\n vi.fn(\n async () =>\n new Response(sse, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n }),\n ),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\", { stream: true }),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"content-type\")).toContain(\"text/event-stream\");\n expect(await res.text()).toBe(sse);\n });\n});\n\ndescribe(\"/v1/messages — cross-provider failover\", () => {\n it(\"fails over to an OpenAI-compatible provider and answers in Anthropic shape\", async () => {\n const app = await freshApp({\n ANTHROPIC_API_KEY: \"sk-ant-key\",\n DEEPSEEK_API_KEY: \"dk-test\",\n FALLBACK_CHAIN: \"deepseek/deepseek-chat\",\n });\n const calls: string[] = [];\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n calls.push(new URL(String(url)).hostname);\n if (String(url).includes(\"anthropic.com\")) {\n return new Response(\n JSON.stringify({ type: \"error\", error: { type: \"rate_limit_error\", message: \"slow down\" } }),\n { status: 429, headers: { \"retry-after\": \"30\" } },\n );\n }\n // DeepSeek receives the *translated* chat-completions request.\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"deepseek-chat\");\n expect(sent.messages.at(-1)).toEqual({ role: \"user\", content: \"hi\" });\n return new Response(JSON.stringify(openaiCompletion(\"deepseek-chat\", \"rescued\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n }),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n expect(calls).toEqual([\"api.anthropic.com\", \"api.deepseek.com\"]);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"deepseek\");\n expect(res.headers.get(\"x-understudy-fallback\")).toBe(\"from anthropic/claude-sonnet-4-6\");\n\n const json = (await res.json()) as {\n type: string;\n model: string;\n content: Array<{ type: string; text: string }>;\n stop_reason: string;\n };\n expect(json.type).toBe(\"message\"); // Anthropic shape, not chat.completion\n expect(json.model).toBe(\"claude-sonnet-4-6\"); // echoes the requested model\n expect(json.content).toEqual([{ type: \"text\", text: \"rescued\" }]);\n expect(json.stop_reason).toBe(\"end_turn\");\n });\n\n it(\"re-dialects a fallback SSE stream as Anthropic events\", async () => {\n const app = await freshApp({\n ANTHROPIC_API_KEY: \"sk-ant-key\",\n DEEPSEEK_API_KEY: \"dk-test\",\n FALLBACK_CHAIN: \"deepseek/deepseek-chat\",\n });\n const openaiSSE = [\n `data: {\"id\":\"c\",\"object\":\"chat.completion.chunk\",\"created\":1,\"model\":\"deepseek-chat\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"res\"},\"finish_reason\":null}]}`,\n `data: {\"id\":\"c\",\"object\":\"chat.completion.chunk\",\"created\":1,\"model\":\"deepseek-chat\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"cued\"},\"finish_reason\":null}]}`,\n `data: {\"id\":\"c\",\"object\":\"chat.completion.chunk\",\"created\":1,\"model\":\"deepseek-chat\",\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"stop\"}],\"usage\":{\"prompt_tokens\":3,\"completion_tokens\":2,\"total_tokens\":5}}`,\n \"data: [DONE]\",\n \"\",\n ].join(\"\\n\\n\");\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async (url: RequestInfo | URL) => {\n if (String(url).includes(\"anthropic.com\")) {\n return new Response(\"overloaded\", { status: 529 });\n }\n return new Response(openaiSSE, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n });\n }),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\", { stream: true }),\n });\n expect(res.status).toBe(200);\n const text = await res.text();\n expect(text).toContain(\"event: message_start\");\n expect(text).toContain('\"text_delta\",\"text\":\"res\"');\n expect(text).toContain('\"text_delta\",\"text\":\"cued\"');\n expect(text).toContain('\"stop_reason\":\"end_turn\"');\n expect(text).toContain(\"event: message_stop\");\n // The client asked for a Claude model and must see one in message_start.\n expect(text).toContain('\"model\":\"claude-sonnet-4-6\"');\n });\n});\n\ndescribe(\"/v1/responses — Codex front door\", () => {\n const responsesBody = (model: string, extra: object = {}) =>\n JSON.stringify({\n model,\n instructions: \"You are Codex.\",\n input: [\n {\n type: \"message\",\n role: \"user\",\n content: [{ type: \"input_text\", text: \"hi\" }],\n },\n ],\n tools: [],\n tool_choice: \"auto\",\n store: false,\n stream: false,\n ...extra,\n });\n\n it(\"translates to chat completions and back to a Responses object\", async () => {\n const app = await freshApp({ OPENAI_API_KEY: \"sk-test\" });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.openai.com/v1/chat/completions\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.messages[0]).toEqual({ role: \"system\", content: \"You are Codex.\" });\n expect(sent.messages[1]).toEqual({ role: \"user\", content: \"hi\" });\n return new Response(JSON.stringify(openaiCompletion(\"gpt-5-mini\", \"hi there\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/responses\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: responsesBody(\"gpt-5-mini\"),\n });\n expect(res.status).toBe(200);\n const json = (await res.json()) as {\n object: string;\n status: string;\n output: Array<{ type: string; content: Array<{ text: string }> }>;\n };\n expect(json.object).toBe(\"response\");\n expect(json.status).toBe(\"completed\");\n expect(json.output[0]?.content[0]?.text).toBe(\"hi there\");\n });\n\n it(\"streams Responses events and fails over across providers\", async () => {\n const app = await freshApp({\n OPENAI_API_KEY: \"sk-test\",\n ANTHROPIC_API_KEY: \"sk-ant-key\",\n FALLBACK_CHAIN: \"anthropic/claude-sonnet-4-6\",\n });\n const anthropicSSE = [\n `event: message_start`,\n `data: {\"type\":\"message_start\",\"message\":{\"id\":\"msg_01\",\"usage\":{\"input_tokens\":3}}}`,\n ``,\n `event: content_block_start`,\n `data: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"text\",\"text\":\"\"}}`,\n ``,\n `event: content_block_delta`,\n `data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"claude to the rescue\"}}`,\n ``,\n `event: message_delta`,\n `data: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\"},\"usage\":{\"output_tokens\":4}}`,\n ``,\n `event: message_stop`,\n `data: {\"type\":\"message_stop\"}`,\n ``,\n ``,\n ].join(\"\\n\");\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async (url: RequestInfo | URL) => {\n if (String(url).includes(\"openai.com\")) {\n return new Response(JSON.stringify({ error: { message: \"rate limited\" } }), {\n status: 429,\n });\n }\n expect(String(url)).toContain(\"api.anthropic.com/v1/messages\");\n return new Response(anthropicSSE, {\n status: 200,\n headers: { \"content-type\": \"text/event-stream\" },\n });\n }),\n );\n\n const res = await app.request(\"/v1/responses\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: responsesBody(\"gpt-5-mini\", { stream: true }),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"anthropic\");\n expect(res.headers.get(\"x-understudy-fallback\")).toBe(\"from openai/gpt-5-mini\");\n\n const text = await res.text();\n expect(text).toContain(\"event: response.created\");\n expect(text).toContain(\"event: response.output_text.delta\");\n expect(text).toContain('\"delta\":\"claude to the rescue\"');\n expect(text).toContain(\"event: response.completed\");\n });\n});\n\ndescribe(\"MODEL_OVERRIDES\", () => {\n it(\"rewrites the requested model before routing\", async () => {\n const app = await freshApp({\n GROQ_API_KEY: \"gk-test\",\n MODEL_OVERRIDES: \"claude-3-5-haiku*=groq/llama-3.3-70b\",\n });\n const fetchMock = vi.fn(async (url: RequestInfo | URL, init?: RequestInit) => {\n expect(String(url)).toBe(\"https://api.groq.com/openai/v1/chat/completions\");\n const sent = JSON.parse(String(init?.body));\n expect(sent.model).toBe(\"llama-3.3-70b\");\n return new Response(JSON.stringify(openaiCompletion(\"llama-3.3-70b\", \"overridden\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n });\n });\n vi.stubGlobal(\"fetch\", fetchMock);\n\n const res = await app.request(\"/v1/chat/completions\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n model: \"claude-3-5-haiku-20241022\",\n messages: [{ role: \"user\", content: \"hi\" }],\n }),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"groq\");\n });\n\n it(\"applies on the Messages front door too, answering in Anthropic shape\", async () => {\n const app = await freshApp({\n DEEPSEEK_API_KEY: \"dk-test\",\n MODEL_OVERRIDES: \"claude-*=deepseek/deepseek-chat\",\n });\n vi.stubGlobal(\n \"fetch\",\n vi.fn(\n async () =>\n new Response(JSON.stringify(openaiCompletion(\"deepseek-chat\", \"ds answer\")), {\n status: 200,\n headers: { \"content-type\": \"application/json\" },\n }),\n ),\n );\n\n const res = await app.request(\"/v1/messages\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n expect(res.headers.get(\"x-understudy-provider\")).toBe(\"deepseek\");\n const json = (await res.json()) as { type: string; content: Array<{ text: string }> };\n expect(json.type).toBe(\"message\");\n expect(json.content[0]?.text).toBe(\"ds answer\");\n });\n});\n\ndescribe(\"/v1/messages/count_tokens\", () => {\n it(\"estimates locally when no upstream key is configured\", async () => {\n const app = await freshApp();\n const res = await app.request(\"/v1/messages/count_tokens\", {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: messagesBody(\"claude-sonnet-4-6\"),\n });\n expect(res.status).toBe(200);\n const json = (await res.json()) as { input_tokens: number };\n expect(json.input_tokens).toBeGreaterThan(0);\n });\n});\n"}}}} |