import test from "node:test"; import assert from "node:assert/strict"; import { FORMATS } from "../../open-sse/translator/formats.ts"; import { getModelInfoCore } from "../../open-sse/services/model.ts"; import { detectFormat, detectFormatFromEndpoint } from "../../open-sse/services/provider.ts"; import { shouldUseNativeCodexPassthrough } from "../../open-sse/handlers/chatCore.ts"; import { translateRequest } from "../../open-sse/translator/index.ts"; import { GithubExecutor } from "../../open-sse/executors/github.ts"; import { DefaultExecutor } from "../../open-sse/executors/default.ts"; import { CodexExecutor } from "../../open-sse/executors/codex.ts"; import { translateNonStreamingResponse } from "../../open-sse/handlers/responseTranslator.ts"; import { extractUsageFromResponse } from "../../open-sse/handlers/usageExtractor.ts"; import { parseSSEToOpenAIResponse, parseSSEToResponsesOutput, } from "../../open-sse/handlers/sseParser.ts"; test("getModelInfoCore resolves unique non-openai unprefixed model", async () => { const info = await getModelInfoCore("claude-sonnet-4-5-20250929", {}); assert.equal(info.provider, "claude"); assert.equal(info.model, "claude-sonnet-4-5-20250929"); }); test("getModelInfoCore keeps openai fallback for gpt-4o", async () => { const info = await getModelInfoCore("gpt-4o", {}); assert.equal(info.provider, "openai"); assert.equal(info.model, "gpt-4o"); }); test("getModelInfoCore routes native codex-auto-review to codex", async () => { const info = await getModelInfoCore("codex-auto-review", {}); assert.equal(info.provider, "codex"); assert.equal(info.model, "codex-auto-review"); }); test("getModelInfoCore keeps unprefixed gpt-5.5 on the OpenAI fallback", async () => { const info = await getModelInfoCore("gpt-5.5", {}); assert.equal(info.provider, "openai"); assert.equal(info.model, "gpt-5.5"); }); test("getModelInfoCore keeps explicit cx/gpt-5.5-medium separate from gpt-5.5", async () => { const info = await getModelInfoCore("cx/gpt-5.5-medium", {}); assert.equal(info.provider, "codex"); assert.equal(info.model, "gpt-5.5-medium"); }); test("getModelInfoCore resolves explicit gpt-5.5 Codex model", async () => { const info = await getModelInfoCore("cx/gpt-5.5", {}); assert.equal(info.provider, "codex"); assert.equal(info.model, "gpt-5.5"); }); test("getModelInfoCore keeps duplicate unprefixed gpt-5.5 checks on OpenAI", async () => { const info = await getModelInfoCore("gpt-5.5", {}); assert.equal(info.provider, "openai"); assert.equal(info.model, "gpt-5.5"); }); test("getModelInfoCore keeps repeated unprefixed gpt-5.5 checks on OpenAI", async () => { const info = await getModelInfoCore("gpt-5.5", {}); assert.equal(info.provider, "openai"); assert.equal(info.model, "gpt-5.5"); }); test("getModelInfoCore resolves explicit gpt-5.5 Codex model", async () => { const info = await getModelInfoCore("cx/gpt-5.5", {}); assert.equal(info.provider, "codex"); assert.equal(info.model, "gpt-5.5"); }); test("getModelInfoCore returns explicit ambiguity metadata for ambiguous unprefixed model", async () => { const info = await getModelInfoCore("claude-haiku-4.5", {}); assert.equal(info.provider, null); assert.equal((info as any).errorType, "ambiguous_model"); assert.match((info as any).errorMessage, /Ambiguous model/i); assert.ok(Array.isArray((info as any).candidateProviders)); assert.ok((info as any).candidateProviders.length >= 2); }); test("getModelInfoCore canonicalizes github legacy alias with explicit provider prefix", async () => { const info = await getModelInfoCore("gh/claude-4.5-opus", {}); assert.equal(info.provider, "github"); assert.equal(info.model, "claude-opus-4-5-20251101"); }); test("GithubExecutor routes codex-family model to /responses", () => { const executor = new GithubExecutor(); const url = executor.buildUrl("gpt-5.3-codex", true); assert.match(url, /\/responses$/); }); test("GithubExecutor keeps non-codex model on /chat/completions", () => { const executor = new GithubExecutor(); const url = executor.buildUrl("gpt-5", true); assert.match(url, /\/chat\/completions$/); }); test("DefaultExecutor uses x-api-key for kimi-coding-apikey", () => { const executor = new DefaultExecutor("kimi-coding-apikey"); const headers = executor.buildHeaders({ apiKey: "sk-kimi-test" }, true); assert.equal((headers as any)["x-api-key"], "sk-kimi-test"); assert.equal((headers as any).Authorization, undefined); }); test("DefaultExecutor execute honors connection-level custom User-Agent", async () => { const executor = new DefaultExecutor("openai"); const originalFetch = globalThis.fetch; let capturedHeaders = null; globalThis.fetch = async (_url, init = {}) => { capturedHeaders = (init as any).headers || null; return new Response(JSON.stringify({ id: "chatcmpl-test" }), { status: 200 }); }; try { await executor.execute({ model: "gpt-4o", body: { model: "gpt-4o", messages: [{ role: "user", content: "hello" }], }, stream: false, credentials: { apiKey: "sk-openai-test", providerSpecificData: { customUserAgent: "OmniRouteCustomUA/2.0", }, }, }); } finally { globalThis.fetch = originalFetch; } assert.ok(capturedHeaders); assert.equal(capturedHeaders.Authorization, "Bearer sk-openai-test"); assert.equal(capturedHeaders["User-Agent"], "OmniRouteCustomUA/2.0"); }); test("CodexExecutor forces stream=true for upstream compatibility", () => { const executor = new CodexExecutor(); const transformed = executor.transformRequest( "gpt-5.1-codex", { model: "gpt-5.1-codex", input: [], stream: false }, false, {} ); assert.equal(transformed.stream, true); }); test("Claude native messages can be round-tripped through OpenAI into Claude OAuth format", () => { const normalizeOptions = { normalizeToolCallId: false, preserveDeveloperRole: undefined }; const openaiBody = translateRequest( FORMATS.CLAUDE, FORMATS.OPENAI, "claude-sonnet-4-6", { model: "claude-sonnet-4-6", max_tokens: 32, messages: [{ role: "user", content: "reply with OK only" }], }, false, null, "claude", null, normalizeOptions ); const translated = translateRequest( FORMATS.OPENAI, FORMATS.CLAUDE, "claude-sonnet-4-6", openaiBody, false, null, "claude", null, normalizeOptions ); assert.deepEqual(translated.messages, [ { role: "user", content: [{ type: "text", text: "reply with OK only" }], }, ]); assert.equal(translated.system, undefined); }); test("CodexExecutor maps fast service tier to priority", () => { const executor = new CodexExecutor(); const transformed = executor.transformRequest( "gpt-5.1-codex", { model: "gpt-5.1-codex", input: [], service_tier: "fast" }, true, {} ); assert.equal(transformed.service_tier, "priority"); }); test("shouldUseNativeCodexPassthrough only enables responses-native Codex requests", () => { assert.equal( shouldUseNativeCodexPassthrough({ provider: "codex", sourceFormat: FORMATS.OPENAI_RESPONSES, endpointPath: "/v1/responses", }), true ); assert.equal( shouldUseNativeCodexPassthrough({ provider: "codex", sourceFormat: FORMATS.OPENAI, endpointPath: "/v1/responses", }), false ); assert.equal( shouldUseNativeCodexPassthrough({ provider: "openai", sourceFormat: FORMATS.OPENAI_RESPONSES, endpointPath: "/v1/responses", }), false ); assert.equal( shouldUseNativeCodexPassthrough({ provider: "codex", sourceFormat: FORMATS.OPENAI_RESPONSES, endpointPath: "/v1/responses/compact", }), true ); assert.equal( shouldUseNativeCodexPassthrough({ provider: "codex", sourceFormat: FORMATS.OPENAI_RESPONSES, endpointPath: "/v1/responses/items/history", }), true ); assert.equal( shouldUseNativeCodexPassthrough({ provider: "codex", sourceFormat: FORMATS.OPENAI_RESPONSES, endpointPath: "/v1/chat/completions", }), false ); }); test("CodexExecutor can apply per-connection fast service tier defaults", () => { const executor = new CodexExecutor(); const transformed = executor.transformRequest( "gpt-5.1-codex", { model: "gpt-5.1-codex", input: [] }, true, { providerSpecificData: { requestDefaults: { serviceTier: "priority" }, }, } ); assert.equal(transformed.service_tier, "priority"); }); test("CodexExecutor always requests SSE accept header", () => { const executor = new CodexExecutor(); const headers = executor.buildHeaders({ accessToken: "test-token" }, false); assert.equal(headers.Accept, "text/event-stream"); }); test("CodexExecutor does not request SSE accept header for compact requests", () => { const executor = new CodexExecutor(); const headers = executor.buildHeaders( { accessToken: "test-token", requestEndpointPath: "/v1/responses/compact", }, false ); assert.equal(headers.Accept, "application/json"); }); test("CodexExecutor preserves native responses payloads for Codex passthrough", () => { const executor = new CodexExecutor(); const transformed = executor.transformRequest( "gpt-5.1-codex", { model: "gpt-5.1-codex", input: "ship it", instructions: "custom system prompt", store: true, metadata: { source: "codex-client" }, reasoning_effort: "high", service_tier: "fast", _nativeCodexPassthrough: true, stream: false, }, false, {} ); assert.equal(transformed.stream, true); assert.equal(transformed.service_tier, "priority"); assert.equal(transformed.instructions, "custom system prompt"); assert.equal(transformed.store, false); assert.deepEqual(transformed.metadata, { source: "codex-client" }); assert.equal(transformed.reasoning.effort, "high"); assert.equal(transformed.reasoning_effort, undefined); assert.ok(!("_nativeCodexPassthrough" in transformed)); }); test("CodexExecutor gives model reasoning suffix precedence over client defaults", () => { const executor = new CodexExecutor(); const transformed = executor.transformRequest( "gpt-5.5-xhigh", { model: "gpt-5.5-xhigh", input: [], reasoning: { effort: "medium", summary: "auto" }, reasoning_effort: "low", }, true, {} ); assert.equal(transformed.model, "gpt-5.5"); assert.deepEqual(transformed.reasoning, { effort: "xhigh", summary: "auto" }); assert.equal(transformed.reasoning_effort, undefined); }); test("CodexExecutor strips streaming fields for compact passthrough", () => { const executor = new CodexExecutor(); const transformed = executor.transformRequest( "gpt-5.1-codex", { model: "gpt-5.1-codex", input: "compact this session", stream: false, stream_options: { include_usage: true }, _nativeCodexPassthrough: true, }, false, { requestEndpointPath: "/v1/responses/compact", } ); assert.equal("stream" in transformed, false); assert.equal("stream_options" in transformed, false); assert.ok(!("_nativeCodexPassthrough" in transformed)); }); test("CodexExecutor routes responses subpaths to matching upstream paths", () => { const executor = new CodexExecutor(); const compactUrl = executor.buildUrl("gpt-5.1-codex", true, 0, { requestEndpointPath: "/v1/responses/compact", }); assert.match(compactUrl, /\/responses\/compact$/); const genericSubpathUrl = executor.buildUrl("gpt-5.1-codex", true, 0, { requestEndpointPath: "/v1/responses/items/history", }); assert.match(genericSubpathUrl, /\/responses\/items\/history$/); }); test("translateNonStreamingResponse converts Responses API payload to OpenAI chat.completion", () => { const responseBody = { id: "resp_123", object: "response", created_at: 1739370000, model: "gpt-5.1-codex", output: [ { type: "message", role: "assistant", content: [{ type: "output_text", text: "Hello from responses API." }], }, { type: "function_call", id: "fc_1", call_id: "call_1", name: "sum", arguments: '{"a":1,"b":2}', }, ], usage: { input_tokens: 11, output_tokens: 7, }, }; const translated = translateNonStreamingResponse( responseBody, FORMATS.OPENAI_RESPONSES, FORMATS.OPENAI ); assert.equal((translated as any).object, "chat.completion"); assert.equal((translated as any).model, "gpt-5.1-codex"); (assert as any).equal((translated as any).choices[0].message.role, "assistant"); (assert as any).equal( (translated as any).choices[0].message.content, "Hello from responses API." ); assert.equal((translated as any).choices[0].finish_reason, "tool_calls"); assert.equal(((translated as any).choices[0].message.tool_calls as any).length, 1); assert.equal(((translated as any).usage as any).prompt_tokens, 11); assert.equal((translated as any).usage.completion_tokens, 7); assert.equal((translated as any).usage.total_tokens, 18); }); test("extractUsageFromResponse reads usage from Responses API payload", () => { const responseBody = { object: "response", usage: { input_tokens: 20, output_tokens: 9, cache_read_input_tokens: 4, reasoning_tokens: 3, }, }; const usage = extractUsageFromResponse(responseBody, "github"); assert.equal(usage.prompt_tokens, 20); assert.equal(usage.completion_tokens, 9); assert.equal(usage.cached_tokens, 4); assert.equal(usage.reasoning_tokens, 3); }); test("detectFormat identifies OpenAI Responses when input is string", () => { const format = detectFormat({ model: "gpt-5.1-codex", input: "hello world", stream: true, }); assert.equal(format, FORMATS.OPENAI_RESPONSES); }); test("detectFormat identifies OpenAI Responses by max_output_tokens without input array", () => { const format = detectFormat({ model: "gpt-5.1-codex", max_output_tokens: 256, stream: false, }); assert.equal(format, FORMATS.OPENAI_RESPONSES); }); test("detectFormatFromEndpoint uses chat completions endpoint for OpenAI chat protocol", () => { const format = detectFormatFromEndpoint( { model: "test-model", messages: [{ role: "user", content: "hi" }], input: "ignored for endpoint protocol detection", max_output_tokens: 16, stream: false, }, "/v1/chat/completions" ); assert.equal(format, FORMATS.OPENAI); }); test("detectFormatFromEndpoint forces Claude for /v1/messages", () => { const format = detectFormatFromEndpoint( { model: "claude-opus-4-6", messages: [{ role: "user", content: "hi" }], max_tokens: 16, stream: false, }, "/v1/messages" ); assert.equal(format, FORMATS.CLAUDE); }); test("translateRequest normalizes openai-responses input string into list payload", () => { const translated = translateRequest( FORMATS.OPENAI_RESPONSES, FORMATS.OPENAI_RESPONSES, "gpt-5.1-codex", { model: "gpt-5.1-codex", input: "hello from responses", stream: false, }, false ); assert.ok(Array.isArray(translated.input)); assert.equal(translated.input.length, 1); assert.equal(translated.input[0].type, "message"); assert.equal(translated.input[0].role, "user"); assert.equal(translated.input[0].content[0].type, "input_text"); assert.equal(translated.input[0].content[0].text, "hello from responses"); }); test("translateRequest preserves service_tier when converting openai to openai-responses", () => { const translated = translateRequest( FORMATS.OPENAI, FORMATS.OPENAI_RESPONSES, "gpt-5.1-codex", { model: "gpt-5.1-codex", messages: [{ role: "user", content: "hello from chat completions" }], service_tier: "fast", stream: false, }, false ); assert.equal(translated.service_tier, "fast"); assert.ok(Array.isArray(translated.input)); }); test("parseSSEToResponsesOutput parses completed response from SSE payload", () => { const rawSSE = [ "event: response.created", 'data: {"type":"response.created","response":{"id":"resp_1","object":"response","model":"gpt-5.1-codex","status":"in_progress","output":[]}}', "", "event: response.completed", 'data: {"type":"response.completed","response":{"id":"resp_1","object":"response","model":"gpt-5.1-codex","status":"completed","output":[{"type":"message","role":"assistant","content":[{"type":"output_text","text":"ok"}]}],"usage":{"input_tokens":5,"output_tokens":3}}}', "", "data: [DONE]", "", ].join("\n"); const parsed = parseSSEToResponsesOutput(rawSSE, "fallback-model"); assert.equal(parsed.object, "response"); assert.equal(parsed.id, "resp_1"); assert.equal(parsed.model, "gpt-5.1-codex"); assert.equal(parsed.status, "completed"); assert.equal(parsed.output[0].type, "message"); assert.equal(parsed.usage.input_tokens, 5); assert.equal(parsed.usage.output_tokens, 3); }); test("parseSSEToResponsesOutput returns null for invalid payload", () => { const parsed = parseSSEToResponsesOutput("data: not-json\n\ndata: [DONE]\n", "fallback-model"); assert.equal(parsed, null); }); test("parseSSEToOpenAIResponse merges split tool call chunks by id without duplication", () => { const rawSSE = [ `data: ${JSON.stringify({ id: "chatcmpl_1", object: "chat.completion.chunk", choices: [ { index: 0, delta: { tool_calls: [ { id: "call_abc", index: 0, type: "function", function: { name: "sum", arguments: '{"a":' }, }, ], }, }, ], })}`, `data: ${JSON.stringify({ id: "chatcmpl_1", object: "chat.completion.chunk", choices: [ { index: 0, delta: { tool_calls: [ { id: "call_abc", index: 0, type: "function", function: { arguments: "1}" }, }, ], }, finish_reason: "tool_calls", }, ], })}`, "data: [DONE]", ].join("\n"); const parsed = parseSSEToOpenAIResponse(rawSSE, "gpt-5.1-codex"); assert.ok(parsed); assert.equal(parsed.choices[0].finish_reason, "tool_calls"); assert.equal(parsed.choices[0].message.tool_calls.length, 1); assert.equal(parsed.choices[0].message.tool_calls[0].id, "call_abc"); assert.equal(parsed.choices[0].message.tool_calls[0].function.name, "sum"); assert.equal(parsed.choices[0].message.tool_calls[0].function.arguments, '{"a":1}'); }); test("parseSSEToOpenAIResponse normalizes delta.reasoning alias to reasoning_content", () => { const rawSSE = [ `data: ${JSON.stringify({ id: "chatcmpl_2", object: "chat.completion.chunk", choices: [{ index: 0, delta: { reasoning: "Let me think..." } }], })}`, `data: ${JSON.stringify({ id: "chatcmpl_2", object: "chat.completion.chunk", choices: [{ index: 0, delta: { reasoning: " The answer is 4." } }], })}`, `data: ${JSON.stringify({ id: "chatcmpl_2", object: "chat.completion.chunk", choices: [{ index: 0, delta: { content: "2+2=4" }, finish_reason: "stop" }], })}`, "data: [DONE]", ].join("\n"); const parsed = parseSSEToOpenAIResponse(rawSSE, "moonshotai/kimi-k2.5"); assert.ok(parsed); assert.equal(parsed.choices[0].message.reasoning_content, "Let me think... The answer is 4."); assert.equal(parsed.choices[0].message.content, "2+2=4"); });