Files
diegosouzapw--omniroute/tests/unit/executor-default-base.test.ts
T
2026-07-13 13:39:12 +08:00

1523 lines
53 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import {
applyConfiguredUserAgent,
BaseExecutor,
getCustomUserAgent,
mergeAbortSignals,
mergeUpstreamExtraHeaders,
setUserAgentHeader,
} from "../../open-sse/executors/base.ts";
import { DefaultExecutor } from "../../open-sse/executors/default.ts";
import { PROVIDERS } from "../../open-sse/config/constants.ts";
import {
CLAUDE_CODE_COMPATIBLE_ANTHROPIC_VERSION,
CLAUDE_CODE_COMPATIBLE_DEFAULT_CHAT_PATH,
CLAUDE_CODE_COMPATIBLE_REDACT_THINKING_BETA,
CONTEXT_1M_BETA_HEADER,
} from "../../open-sse/services/claudeCodeCompatible.ts";
import { runWithCapture } from "../../open-sse/utils/providerRequestLogging.ts";
class TestExecutor extends BaseExecutor {
constructor(config = {}) {
super("test-provider", {
baseUrls: [
"https://primary.example/v1/chat/completions",
"https://fallback.example/v1/chat/completions",
],
headers: { "X-Test-Header": "base" },
...config,
});
}
async transformRequest(model, body, stream) {
return { ...body, transformed: true, model, stream };
}
}
test("BaseExecutor: openai-compatible buildUrl sanitizes custom chat paths", () => {
const executor = new BaseExecutor("openai-compatible-test", {});
const valid = executor.buildUrl("gpt-4.1", true, 0, {
providerSpecificData: {
baseUrl: "https://proxy.example/v1/",
chatPath: "/custom/chat/completions",
},
});
const invalid = executor.buildUrl("gpt-4.1", true, 0, {
providerSpecificData: {
baseUrl: "https://proxy.example/v1/",
chatPath: "../evil",
},
});
const invalidNullByte = executor.buildUrl("gpt-4.1", true, 0, {
providerSpecificData: {
baseUrl: "https://proxy.example/v1/",
chatPath: "/ok\0evil",
},
});
assert.equal(valid, "https://proxy.example/v1/custom/chat/completions");
assert.equal(invalid, "https://proxy.example/v1/chat/completions");
assert.equal(invalidNullByte, "https://proxy.example/v1/chat/completions");
});
test("BaseExecutor: legacy openai-compatible providers honor providerSpecificData.apiType", () => {
const executor = new BaseExecutor("openai-compatible-sp-openai", {});
const url = executor.buildUrl("gpt-5.4", true, 0, {
providerSpecificData: {
apiType: "responses",
baseUrl: "https://proxy.example/v1/",
},
});
assert.equal(url, "https://proxy.example/v1/responses");
});
test("DefaultExecutor.buildUrl handles Gemini, Claude and Qwen variants", () => {
const gemini = new DefaultExecutor("gemini");
const claude = new DefaultExecutor("claude");
const qwen = new DefaultExecutor("qwen");
assert.equal(
gemini.buildUrl("gemini-2.5-flash", false),
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent"
);
assert.equal(
gemini.buildUrl("gemini-2.5-flash", true),
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse"
);
assert.equal(claude.buildUrl("claude-sonnet-4", true), `${PROVIDERS.claude.baseUrl}?beta=true`);
assert.equal(qwen.buildUrl("qwen3-coder", true), "https://portal.qwen.ai/v1/chat/completions");
assert.equal(
qwen.buildUrl("qwen3-coder", true, 0, {
providerSpecificData: { resourceUrl: "custom.qwen.ai" },
}),
"https://custom.qwen.ai/v1/chat/completions"
);
});
test("DefaultExecutor.buildUrl uses full chat endpoints for hosted OpenAI-compatible providers", () => {
const bazaarlink = new DefaultExecutor("bazaarlink");
const crof = new DefaultExecutor("crof");
assert.equal(
bazaarlink.buildUrl("auto:free", true),
"https://bazaarlink.ai/api/v1/chat/completions"
);
assert.equal(crof.buildUrl("gpt-4.1", true), "https://crof.ai/v1/chat/completions");
});
test("DefaultExecutor.buildUrl honors a custom providerSpecificData.baseUrl for the built-in openai provider", () => {
const openai = new DefaultExecutor("openai");
// No override → hardcoded OpenAI endpoint (unchanged behavior).
assert.equal(openai.buildUrl("gpt-4o", true), "https://api.openai.com/v1/chat/completions");
// Custom base URL (e.g. a proxy/gateway) must be used instead of api.openai.com.
assert.equal(
openai.buildUrl("gpt-4o", true, 0, {
providerSpecificData: { baseUrl: "https://api.contactboxtools.me/v1" },
}),
"https://api.contactboxtools.me/v1/chat/completions"
);
// Trailing slash is normalized.
assert.equal(
openai.buildUrl("gpt-4o", true, 0, {
providerSpecificData: { baseUrl: "https://proxy.example/v1/" },
}),
"https://proxy.example/v1/chat/completions"
);
// A base URL already pointing at the chat endpoint is kept as-is.
assert.equal(
openai.buildUrl("gpt-4o", true, 0, {
providerSpecificData: { baseUrl: "https://proxy.example/v1/chat/completions" },
}),
"https://proxy.example/v1/chat/completions"
);
});
test("DefaultExecutor.buildUrl handles openai-compatible and anthropic-compatible providers", () => {
const openAICompat = new DefaultExecutor("openai-compatible-test");
const openAIResponsesCompat = new DefaultExecutor("openai-compatible-responses-test");
const openAILegacyResponsesCompat = new DefaultExecutor("openai-compatible-sp-openai");
const anthropicCompat = new DefaultExecutor("anthropic-compatible-test");
const anthropicCcCompat = new DefaultExecutor("anthropic-compatible-cc-test");
assert.equal(
openAICompat.buildUrl("gpt-4.1", true, 0, {
providerSpecificData: { baseUrl: "https://proxy.example/v1/" },
}),
"https://proxy.example/v1/chat/completions"
);
assert.equal(
openAICompat.buildUrl("gpt-4.1", true, 0, {
providerSpecificData: {
baseUrl: "https://proxy.example/v1/",
chatPath: "/custom/chat",
},
}),
"https://proxy.example/v1/custom/chat"
);
assert.equal(
openAIResponsesCompat.buildUrl("gpt-4.1", true, 0, {
providerSpecificData: { baseUrl: "https://proxy.example/v1/" },
}),
"https://proxy.example/v1/responses"
);
assert.equal(
openAICompat.buildUrl("gpt-4.1", true, 0, {
providerSpecificData: {
baseUrl: "https://proxy.example/v1/",
_omnirouteForceResponsesUpstream: true,
},
}),
"https://proxy.example/v1/responses"
);
assert.equal(
openAILegacyResponsesCompat.buildUrl("gpt-5.4", true, 0, {
providerSpecificData: {
apiType: "responses",
baseUrl: "https://proxy.example/v1/",
},
}),
"https://proxy.example/v1/responses"
);
assert.equal(
anthropicCompat.buildUrl("claude-sonnet-4", true, 0, {
providerSpecificData: { baseUrl: "https://anthropic.example/v1/" },
}),
"https://anthropic.example/v1/messages"
);
assert.equal(
anthropicCompat.buildUrl("claude-sonnet-4", true, 0, {
providerSpecificData: {
baseUrl: "https://anthropic.example/v1/",
chatPath: "/custom/messages",
},
}),
"https://anthropic.example/v1/custom/messages"
);
assert.equal(
anthropicCcCompat.buildUrl("claude-sonnet-4", true, 0, {
providerSpecificData: {
baseUrl: "https://cc.example/v1/messages",
},
}),
`https://cc.example${CLAUDE_CODE_COMPATIBLE_DEFAULT_CHAT_PATH}`
);
});
test("DefaultExecutor.buildUrl normalizes configurable chat-openai-compat base URLs", () => {
const bailian = new DefaultExecutor("bailian-coding-plan");
const heroku = new DefaultExecutor("heroku");
const databricks = new DefaultExecutor("databricks");
const azureAi = new DefaultExecutor("azure-ai");
const watsonx = new DefaultExecutor("watsonx");
const oci = new DefaultExecutor("oci");
const sap = new DefaultExecutor("sap");
const modal = new DefaultExecutor("modal");
const reka = new DefaultExecutor("reka");
const maritalk = new DefaultExecutor("maritalk");
const snowflake = new DefaultExecutor("snowflake");
const gigachat = new DefaultExecutor("gigachat");
const siliconflow = new DefaultExecutor("siliconflow");
assert.equal(
bailian.buildUrl("qwen3-coder-plus", true, 0, {
providerSpecificData: {
baseUrl: "https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1",
},
}),
"https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1/messages"
);
assert.equal(
heroku.buildUrl("claude-4-sonnet", true, 0, {
providerSpecificData: { baseUrl: "https://us.inference.heroku.com" },
}),
"https://us.inference.heroku.com/v1/chat/completions"
);
assert.equal(
databricks.buildUrl("databricks-gpt-5", true, 0, {
providerSpecificData: {
baseUrl: "https://adb-1234567890123456.7.azuredatabricks.net/serving-endpoints",
},
}),
"https://adb-1234567890123456.7.azuredatabricks.net/serving-endpoints/chat/completions"
);
assert.equal(
azureAi.buildUrl("DeepSeek-V3.1", true, 0, {
providerSpecificData: { baseUrl: "https://my-foundry.services.ai.azure.com" },
}),
"https://my-foundry.services.ai.azure.com/openai/v1/chat/completions"
);
assert.equal(
watsonx.buildUrl("ibm/granite-3-3-8b-instruct", true, 0, {
providerSpecificData: { baseUrl: "https://ca-tor.ml.cloud.ibm.com" },
}),
"https://ca-tor.ml.cloud.ibm.com/ml/gateway/v1/chat/completions"
);
assert.equal(
oci.buildUrl("openai.gpt-oss-20b", true, 0, {
providerSpecificData: {
baseUrl: "https://inference.generativeai.us-ashburn-1.oci.oraclecloud.com",
},
}),
"https://inference.generativeai.us-ashburn-1.oci.oraclecloud.com/openai/v1/chat/completions"
);
assert.equal(
sap.buildUrl("gpt-4o", true, 0, {
providerSpecificData: {
baseUrl: "https://sap.example.com/v2/lm/deployments/demo-deployment",
},
}),
"https://sap.example.com/v2/lm/deployments/demo-deployment/chat/completions"
);
assert.equal(
modal.buildUrl("Qwen/Qwen3-4B-Thinking-2507-FP8", true, 0, {
providerSpecificData: {
baseUrl: "https://alice--demo.modal.run/v1",
},
}),
"https://alice--demo.modal.run/v1/chat/completions"
);
assert.equal(
reka.buildUrl("reka-core", true, 0, {
providerSpecificData: {
baseUrl: "https://api.reka.ai/v1",
},
}),
"https://api.reka.ai/v1/chat/completions"
);
assert.equal(
maritalk.buildUrl("sabia-4", true, 0, {
providerSpecificData: {
baseUrl: "https://chat.maritaca.ai/api/chat/inference",
},
}),
"https://chat.maritaca.ai/api/chat/completions"
);
assert.equal(
snowflake.buildUrl("llama3.3-70b", true, 0, {
providerSpecificData: { baseUrl: "https://account.snowflakecomputing.com" },
}),
"https://account.snowflakecomputing.com/api/v2/cortex/inference:complete"
);
assert.equal(
gigachat.buildUrl("GigaChat-2-Pro", true, 0, {
providerSpecificData: { baseUrl: "https://gigachat.devices.sberbank.ru/api/v1" },
}),
"https://gigachat.devices.sberbank.ru/api/v1/chat/completions"
);
assert.equal(
siliconflow.buildUrl("deepseek-ai/DeepSeek-V3.2", true),
"https://api.siliconflow.com/v1/chat/completions"
);
assert.equal(
siliconflow.buildUrl("deepseek-ai/DeepSeek-V3.2", true, 0, {
providerSpecificData: { baseUrl: "https://api.siliconflow.cn/v1" },
}),
"https://api.siliconflow.cn/v1/chat/completions"
);
});
test("DefaultExecutor.buildUrl falls back to OpenAI config for unknown providers", () => {
const executor = new DefaultExecutor("unknown-provider");
assert.equal(executor.config.baseUrl, PROVIDERS.openai.baseUrl);
assert.equal(executor.buildUrl("gpt-4.1", true), PROVIDERS.openai.baseUrl);
});
test("DefaultExecutor.buildUrl applies urlSuffix for zai and glm-coding-apikey", () => {
const zai = new DefaultExecutor("zai");
const glmCodingApikey = new DefaultExecutor("glm-coding-apikey");
assert.equal(
zai.buildUrl("glm-5", true, 0, {
providerSpecificData: { baseUrl: "https://api.z.ai/api/anthropic/v1/messages" },
}),
"https://api.z.ai/api/anthropic/v1/messages?beta=true"
);
assert.equal(
glmCodingApikey.buildUrl("glm-4.7", true, 0, {
providerSpecificData: { baseUrl: "https://api.z.ai/api/anthropic/v1/messages" },
}),
"https://api.z.ai/api/anthropic/v1/messages?beta=true"
);
assert.equal(zai.buildUrl("glm-5", true), "https://api.z.ai/api/anthropic/v1/messages?beta=true");
});
test("DefaultExecutor.buildUrl applies urlSuffix from registry for unknown providers with suffix", () => {
const executor = new DefaultExecutor("unknown-provider");
assert.equal(executor.buildUrl("gpt-4.1", true), PROVIDERS.openai.baseUrl);
});
test("DefaultExecutor.buildHeaders uses x-api-key for zai and glm-coding-apikey", () => {
const zai = new DefaultExecutor("zai");
const glmCodingApikey = new DefaultExecutor("glm-coding-apikey");
const zaiHeaders = zai.buildHeaders({ apiKey: "zai-key" }, true);
const glmHeaders = glmCodingApikey.buildHeaders({ apiKey: "glm-key" }, true);
assert.equal(zaiHeaders["x-api-key"], "zai-key");
assert.equal(glmHeaders["x-api-key"], "glm-key");
assert.equal(zaiHeaders["Authorization"], undefined);
assert.equal(glmHeaders["Authorization"], undefined);
});
test("DefaultExecutor.buildHeaders handles Gemini and Claude auth modes", () => {
const gemini = new DefaultExecutor("gemini");
const claude = new DefaultExecutor("claude");
const azureAi = new DefaultExecutor("azure-ai");
const oci = new DefaultExecutor("oci");
const sap = new DefaultExecutor("sap");
const modal = new DefaultExecutor("modal");
const maritalk = new DefaultExecutor("maritalk");
const geminiApiKeyHeaders = gemini.buildHeaders({ apiKey: "gem-key" }, true);
const geminiOAuthHeaders = gemini.buildHeaders({ accessToken: "gem-token" }, false);
const claudeApiKeyHeaders = claude.buildHeaders({ apiKey: "claude-key" }, true);
const claudeOAuthHeaders = claude.buildHeaders({ accessToken: "claude-token" }, false);
const azureAiHeaders = azureAi.buildHeaders({ apiKey: "azure-ai-key" }, true);
const ociHeaders = oci.buildHeaders(
{
apiKey: "oci-key",
projectId: "ocid1.generativeaiproject.oc1.us-chicago-1.example",
},
true
);
const sapHeaders = sap.buildHeaders(
{
apiKey: "sap-key",
providerSpecificData: {
resourceGroup: "shared",
},
},
true
);
const modalHeaders = modal.buildHeaders(
{
apiKey: "modal-key",
},
true
);
const maritalkHeaders = maritalk.buildHeaders({ apiKey: "maritalk-key" }, true);
assert.equal(geminiApiKeyHeaders["x-goog-api-key"], "gem-key");
assert.equal(geminiApiKeyHeaders.Accept, "text/event-stream");
assert.equal(geminiApiKeyHeaders.Authorization, undefined);
assert.equal(geminiOAuthHeaders.Authorization, "Bearer gem-token");
assert.equal(claudeApiKeyHeaders["x-api-key"], "claude-key");
assert.equal(claudeApiKeyHeaders.Accept, "text/event-stream");
assert.equal(claudeOAuthHeaders.Authorization, "Bearer claude-token");
assert.equal(claudeOAuthHeaders["x-api-key"], undefined);
assert.equal(azureAiHeaders["api-key"], "azure-ai-key");
assert.equal(azureAiHeaders.Authorization, undefined);
assert.equal(ociHeaders.Authorization, "Bearer oci-key");
assert.equal(ociHeaders["OpenAI-Project"], "ocid1.generativeaiproject.oc1.us-chicago-1.example");
assert.equal(sapHeaders.Authorization, "Bearer sap-key");
assert.equal(sapHeaders["AI-Resource-Group"], "shared");
assert.equal(modalHeaders.Authorization, "Bearer modal-key");
assert.equal(maritalkHeaders.Authorization, "Key maritalk-key");
});
test("DefaultExecutor.buildHeaders handles GLM, default auth and anthropic-compatible headers", () => {
const glm = new DefaultExecutor("glm");
const glmt = new DefaultExecutor("glmt");
const openai = new DefaultExecutor("openai");
const anthropicCompat = new DefaultExecutor("anthropic-compatible-test");
const glmHeaders = glm.buildHeaders({ accessToken: "glm-token" }, false);
const glmtHeaders = glmt.buildHeaders({ apiKey: "glmt-key" }, false);
const openaiHeaders = openai.buildHeaders({ apiKey: "sk-openai" }, true);
const anthropicHeaders = anthropicCompat.buildHeaders({ apiKey: "anth-key" }, true);
assert.equal(glmHeaders["x-api-key"], "glm-token");
assert.equal(glmtHeaders["x-api-key"], "glmt-key");
assert.equal(openaiHeaders.Authorization, "Bearer sk-openai");
assert.equal(openaiHeaders.Accept, "text/event-stream");
assert.equal(anthropicHeaders["x-api-key"], "anth-key");
assert.equal(anthropicHeaders["anthropic-version"], "2023-06-01");
assert.equal(anthropicHeaders.Accept, "text/event-stream");
});
test("DefaultExecutor.buildHeaders keeps a caller-supplied Anthropic-Version (case-insensitive guard) for anthropic-compatible providers", () => {
// An operator may configure a Title-Case "Anthropic-Version" via the provider
// config headers. The default-guard at the anthropic-compatible-* branch must
// detect it case-insensitively and NOT add a second lowercase
// "anthropic-version" key, which undici would otherwise combine into
// "2025-01-01, 2023-06-01" and break the upstream request.
const anthropicCompat = new DefaultExecutor("anthropic-compatible-test");
// `config` is shared across instances via the provider registry, so snapshot
// and restore `config.headers` to avoid leaking the Title-Case override into
// other tests.
const originalConfigHeaders = anthropicCompat.config.headers;
anthropicCompat.config.headers = {
...originalConfigHeaders,
"Anthropic-Version": "2025-01-01",
};
try {
const headers = anthropicCompat.buildHeaders({ apiKey: "anth-key" }, true);
const versionKeys = Object.keys(headers).filter(
(key) => key.toLowerCase() === "anthropic-version"
);
assert.equal(versionKeys.length, 1, "Duplicate anthropic-version header keys found");
assert.equal(headers["Anthropic-Version"], "2025-01-01");
assert.equal(headers["anthropic-version"], undefined);
assert.equal(headers["x-api-key"], "anth-key");
} finally {
anthropicCompat.config.headers = originalConfigHeaders;
}
});
test("DefaultExecutor.buildHeaders still defaults anthropic-version when no variant is present", () => {
const anthropicCompat = new DefaultExecutor("anthropic-compatible-test");
const headers = anthropicCompat.buildHeaders({ apiKey: "anth-key" }, true);
assert.equal(headers["anthropic-version"], "2023-06-01");
});
test("DefaultExecutor local OpenAI-style providers honor custom base URLs and skip empty bearer headers", () => {
const lmStudio = new DefaultExecutor("lm-studio");
const vllm = new DefaultExecutor("vllm");
const lmStudioUrl = lmStudio.buildUrl("local-model", true, 0, {
providerSpecificData: { baseUrl: "http://127.0.0.1:4321/v1" },
});
const vllmHeaders = vllm.buildHeaders({}, false);
assert.equal(lmStudioUrl, "http://127.0.0.1:4321/v1/chat/completions");
assert.equal(vllmHeaders.Authorization, undefined);
assert.equal(vllmHeaders.Accept, "application/json");
});
test("DefaultExecutor local providers append /v1/chat/completions for bare hostname base URLs", () => {
const llamaCpp = new DefaultExecutor("llama-cpp");
const lmStudio = new DefaultExecutor("lm-studio");
const vllm = new DefaultExecutor("vllm");
const bareHost = llamaCpp.buildUrl("gemma-4", true, 0, {
providerSpecificData: { baseUrl: "https://foo.llama.example.com" },
});
const customPath = lmStudio.buildUrl("gemma-4", true, 0, {
providerSpecificData: { baseUrl: "https://bar.llama.ai/foo" },
});
const alreadyComplete = vllm.buildUrl("gemma-4", true, 0, {
providerSpecificData: { baseUrl: "https://baz.llama.ai/v1/chat/completions" },
});
assert.equal(bareHost, "https://foo.llama.example.com/v1/chat/completions");
assert.equal(customPath, "https://bar.llama.ai/foo/v1/chat/completions");
assert.equal(alreadyComplete, "https://baz.llama.ai/v1/chat/completions");
});
test("DefaultExecutor.buildHeaders handles Snowflake PATs and GigaChat access tokens", () => {
const snowflake = new DefaultExecutor("snowflake");
const gigachat = new DefaultExecutor("gigachat");
const snowflakePatHeaders = snowflake.buildHeaders({ apiKey: "pat/test-token" }, false);
const snowflakeJwtHeaders = snowflake.buildHeaders({ apiKey: "jwt-token" }, false);
const gigachatHeaders = gigachat.buildHeaders({ accessToken: "gigachat-token" }, false);
assert.equal(snowflakePatHeaders.Authorization, "Bearer test-token");
assert.equal(
snowflakePatHeaders["X-Snowflake-Authorization-Token-Type"],
"PROGRAMMATIC_ACCESS_TOKEN"
);
assert.equal(snowflakeJwtHeaders.Authorization, "Bearer jwt-token");
assert.equal(snowflakeJwtHeaders["X-Snowflake-Authorization-Token-Type"], "KEYPAIR_JWT");
assert.equal(gigachatHeaders.Authorization, "Bearer gigachat-token");
});
test("DefaultExecutor.buildHeaders strips DashScope headers for Qwen API keys and preserves them for OAuth", () => {
const executor = new DefaultExecutor("qwen");
const apiKeyHeaders = executor.buildHeaders({ apiKey: "dash-key" }, true);
const oauthHeaders = executor.buildHeaders({ accessToken: "oauth-token" }, true);
assert.equal(apiKeyHeaders.Authorization, "Bearer dash-key");
assert.equal(
Object.keys(apiKeyHeaders).some((key) => key.toLowerCase().startsWith("x-dashscope-")),
false
);
assert.equal(oauthHeaders.Authorization, "Bearer oauth-token");
assert.equal(oauthHeaders["X-Dashscope-AuthType"], "qwen-oauth");
assert.equal(oauthHeaders["X-Dashscope-CacheControl"], "enable");
});
test("DefaultExecutor.buildHeaders rotates extra API keys and builds Claude Code compatible headers", () => {
const openai = new DefaultExecutor("openai");
const cc = new DefaultExecutor("anthropic-compatible-cc-test");
const first = openai.buildHeaders(
{
apiKey: "primary",
connectionId: "conn-rotation",
providerSpecificData: { extraApiKeys: ["extra-1", "extra-2"] },
},
false
);
const second = openai.buildHeaders(
{
apiKey: "primary",
connectionId: "conn-rotation",
providerSpecificData: { extraApiKeys: ["extra-1", "extra-2"] },
},
false
);
const ccHeaders = cc.buildHeaders(
{
apiKey: "cc-key",
providerSpecificData: { ccSessionId: "session-1" },
},
true
);
const ccJsonHeaders = cc.buildHeaders(
{
apiKey: "cc-key",
providerSpecificData: { ccSessionId: "session-1" },
},
false
);
assert.equal(first.Authorization, "Bearer primary");
assert.equal(second.Authorization, "Bearer extra-1");
assert.equal(ccHeaders.Authorization, "Bearer cc-key");
assert.equal(ccHeaders["x-api-key"], undefined);
assert.equal(ccHeaders["anthropic-version"], CLAUDE_CODE_COMPATIBLE_ANTHROPIC_VERSION);
assert.equal(ccHeaders["X-Claude-Code-Session-Id"], "session-1");
assert.equal(ccHeaders.Accept, "text/event-stream");
assert.equal(ccJsonHeaders.Accept, "application/json");
});
test("DefaultExecutor.execute uses CC-compatible connection defaults to append 1M beta", async () => {
const originalFetch = globalThis.fetch;
const calls = [];
const toPlainHeaders = (headers) =>
headers instanceof Headers
? Object.fromEntries(headers.entries())
: Object.fromEntries(
Object.entries(headers || {}).map(([key, value]) => [
key,
value == null ? "" : String(value),
])
);
globalThis.fetch = async (_url, init = {}) => {
calls.push({ headers: toPlainHeaders(init.headers) });
return new Response(JSON.stringify({ ok: true }), {
status: 200,
headers: { "Content-Type": "application/json" },
});
};
try {
const cc = new DefaultExecutor("anthropic-compatible-cc-test");
await cc.execute({
model: "claude-sonnet-4-6",
body: {
model: "claude-sonnet-4-6",
messages: [{ role: "user", content: "hi" }],
max_tokens: 1,
},
stream: false,
credentials: {
apiKey: "cc-key",
providerSpecificData: {
ccSessionId: "session-1",
},
},
clientHeaders: {
"x-app": "cli",
"user-agent": "claude-cli/2.1.116 (external, cli)",
},
extendedContext: false,
});
await cc.execute({
model: "claude-sonnet-4-6",
body: {
model: "claude-sonnet-4-6",
messages: [{ role: "user", content: "hi" }],
max_tokens: 1,
},
stream: false,
credentials: {
apiKey: "cc-key",
providerSpecificData: {
ccSessionId: "session-1",
requestDefaults: { context1m: true, redactThinking: true },
},
},
extendedContext: false,
});
const anthropicCompat = new DefaultExecutor("anthropic-compatible-test");
await anthropicCompat.execute({
model: "claude-sonnet-4-6",
body: {
model: "claude-sonnet-4-6",
messages: [{ role: "user", content: "hi" }],
max_tokens: 1,
},
stream: false,
credentials: {
apiKey: "anth-key",
providerSpecificData: {
baseUrl: "https://anthropic.example.com/v1",
},
},
extendedContext: true,
});
} finally {
globalThis.fetch = originalFetch;
}
assert.equal(calls[0].headers["anthropic-beta"].includes(CONTEXT_1M_BETA_HEADER), false);
assert.equal(
calls[0].headers["anthropic-beta"].includes(CLAUDE_CODE_COMPATIBLE_REDACT_THINKING_BETA),
false
);
assert.equal(calls[1].headers["anthropic-beta"].includes(CONTEXT_1M_BETA_HEADER), true);
assert.equal(
calls[1].headers["anthropic-beta"].includes(CLAUDE_CODE_COMPATIBLE_REDACT_THINKING_BETA),
true
);
assert.equal(calls[2].headers["anthropic-beta"], undefined);
});
test("DefaultExecutor.execute reports the exact serialized provider request before fetch", async () => {
const originalFetch = globalThis.fetch;
let fetchStarted = false;
let fetchBody: any = null;
let prepared: any = null;
let preparedBeforeFetch = false;
globalThis.fetch = async (_url, init = {}) => {
fetchStarted = true;
fetchBody = JSON.parse(String(init.body || "{}"));
return new Response(JSON.stringify({ ok: true }), {
status: 200,
headers: { "Content-Type": "application/json" },
});
};
try {
const cc = new DefaultExecutor("anthropic-compatible-cc-test");
const requestCapture = {
capture(request) {
preparedBeforeFetch = !fetchStarted;
prepared = request;
},
body(fallback) {
return prepared?.body ?? fallback;
},
latest() {
return prepared;
},
};
const result = await runWithCapture(requestCapture, () =>
cc.execute({
model: "claude-sonnet-4-6",
body: {
model: "claude-sonnet-4-6",
system: [
{
type: "text",
text: "x-anthropic-billing-header: cc_version=1.0.0; cc_entrypoint=sdk-cli; cch=00000;",
},
],
messages: [{ role: "user", content: "hi" }],
max_tokens: 1,
reasoning_effort: "xhigh",
},
stream: false,
credentials: {
apiKey: "cc-key",
providerSpecificData: {
ccSessionId: "session-1",
},
},
})
);
assert.ok(prepared, "prepared request hook should fire before fetch");
assert.equal(preparedBeforeFetch, true);
assert.deepEqual(prepared.body, fetchBody);
assert.deepEqual(result.transformedBody, fetchBody);
assert.equal(prepared.body.reasoning_effort, "high");
assert.equal(fetchBody.reasoning_effort, "high");
assert.match(JSON.stringify(fetchBody), /\bcch=(?!00000)[0-9a-f]{5};/);
} finally {
globalThis.fetch = originalFetch;
}
});
test("DefaultExecutor.execute only injects adaptive thinking defaults for Claude models that support x-high effort", async () => {
const originalFetch = globalThis.fetch;
const requestBodies = [];
globalThis.fetch = async (_url, init = {}) => {
requestBodies.push(JSON.parse(String(init.body)));
return new Response(JSON.stringify({ ok: true }), {
status: 200,
headers: { "Content-Type": "application/json" },
});
};
try {
const claude = new DefaultExecutor("claude");
await claude.execute({
model: "claude-opus-4-7",
body: {
model: "claude-opus-4-7",
messages: [{ role: "user", content: "hi" }],
max_tokens: 1,
},
stream: false,
credentials: {
apiKey: "cc-key",
providerSpecificData: {
ccSessionId: "session-1",
},
},
clientHeaders: {
"x-app": "cli",
"user-agent": "claude-cli/2.1.116 (external, cli)",
},
extendedContext: false,
});
await claude.execute({
model: "claude-haiku-4-5-20251001",
body: {
model: "claude-haiku-4-5-20251001",
messages: [{ role: "user", content: "hi" }],
max_tokens: 1,
},
stream: false,
credentials: {
apiKey: "cc-key",
providerSpecificData: {
ccSessionId: "session-1",
},
},
clientHeaders: {
"x-app": "cli",
"user-agent": "claude-cli/2.1.116 (external, cli)",
},
extendedContext: false,
});
await claude.execute({
model: "claude-sonnet-4-6",
body: {
model: "claude-sonnet-4-6",
messages: [{ role: "user", content: "hi" }],
max_tokens: 1,
thinking: { type: "disabled" },
},
stream: false,
credentials: {
apiKey: "cc-key",
providerSpecificData: {
ccSessionId: "session-1",
},
},
clientHeaders: {
"x-app": "cli",
"user-agent": "claude-cli/2.1.116 (external, cli)",
},
extendedContext: false,
});
} finally {
globalThis.fetch = originalFetch;
}
assert.deepEqual((requestBodies[0] as any).thinking, { type: "adaptive" });
assert.deepEqual((requestBodies[0] as any).context_management, {
edits: [{ type: "clear_thinking_20251015", keep: "all" }],
});
assert.deepEqual((requestBodies[0] as any).output_config, { effort: "high" });
assert.equal((requestBodies[1] as any).thinking, undefined);
assert.equal((requestBodies[1] as any).context_management, undefined);
assert.equal((requestBodies[1] as any).output_config, undefined);
assert.deepEqual((requestBodies[2] as any).thinking, { type: "disabled" });
assert.equal((requestBodies[2] as any).context_management, undefined);
});
test("DefaultExecutor.transformRequest injects OpenAI stream usage and preserves model ids with slashes", () => {
const executor = new DefaultExecutor("openai");
const body = { model: "zai-org/GLM-5-FP8", messages: [{ role: "user", content: "hi" }] };
const result = executor.transformRequest("zai-org/GLM-5-FP8", body, true, {});
assert.notEqual(result, body);
assert.equal(result.model, "zai-org/GLM-5-FP8");
assert.deepEqual((result as any).stream_options, { include_usage: true });
assert.equal((body as any).stream_options, undefined);
});
test("DefaultExecutor.transformRequest only injects stream usage for OpenAI chat targets", () => {
const openAICompat = new DefaultExecutor("openai-compatible-test");
const openAIResponsesCompat = new DefaultExecutor("openai-compatible-responses-test");
const chatBody = { model: "gpt-4.1", messages: [{ role: "user", content: "hi" }] };
const responsesBody = { model: "gpt-4.1", input: "hi" };
const chatResult = openAICompat.transformRequest("gpt-4.1", chatBody, true, {
providerSpecificData: { baseUrl: "https://proxy.example/v1" },
});
const responsesResult = openAIResponsesCompat.transformRequest("gpt-4.1", responsesBody, true, {
providerSpecificData: { baseUrl: "https://proxy.example/v1" },
});
assert.deepEqual((chatResult as any).stream_options, { include_usage: true });
assert.equal((responsesResult as any).stream_options, undefined);
});
test("DefaultExecutor.execute routes Responses-shaped MCP requests to /responses for OpenAI-compatible providers", async () => {
const originalFetch = globalThis.fetch;
const calls: Array<{ url: string; body: any }> = [];
globalThis.fetch = async (url, init = {}) => {
calls.push({
url: String(url),
body: JSON.parse(String(init.body)),
});
return new Response(JSON.stringify({ ok: true }), {
status: 200,
headers: { "Content-Type": "application/json" },
});
};
try {
const executor = new DefaultExecutor("openai-compatible-test");
await executor.execute({
model: "gpt-4.1",
body: {
model: "gpt-4.1",
input: "find tools",
tools: [{ type: "tool_search" }],
},
stream: false,
credentials: {
apiKey: "test-key",
providerSpecificData: { baseUrl: "https://proxy.example/v1/" },
},
});
} finally {
globalThis.fetch = originalFetch;
}
assert.equal(calls.length, 1);
assert.equal(calls[0].url, "https://proxy.example/v1/responses");
assert.equal(calls[0].body.stream_options, undefined);
assert.deepEqual(calls[0].body.tools, [{ type: "tool_search" }]);
});
test("DefaultExecutor.transformRequest respects disableStreamOptions for OpenAI chat targets", () => {
const openAICompat = new DefaultExecutor("openai-compatible-test");
const chatBody = { model: "gpt-4.1", messages: [{ role: "user", content: "hi" }] };
const chatResultDisabled = openAICompat.transformRequest("gpt-4.1", chatBody, true, {
providerSpecificData: { baseUrl: "https://proxy.example/v1", disableStreamOptions: true },
});
const chatResultEnabled = openAICompat.transformRequest("gpt-4.1", chatBody, true, {
providerSpecificData: { baseUrl: "https://proxy.example/v1", disableStreamOptions: false },
});
assert.equal((chatResultDisabled as any).stream_options, undefined);
assert.deepEqual((chatResultEnabled as any).stream_options, { include_usage: true });
});
test("DefaultExecutor.transformRequest injects OpenRouter connection preset", () => {
const executor = new DefaultExecutor("openrouter");
const body = { model: "openai/gpt-4", messages: [{ role: "user", content: "hi" }] };
const result = executor.transformRequest("openai/gpt-4", body, true, {
providerSpecificData: { preset: " email-copywriter " },
});
assert.equal((result as any).preset, "email-copywriter");
assert.deepEqual((result as any).stream_options, { include_usage: true });
assert.equal((body as any).preset, undefined);
const explicit = executor.transformRequest(
"openai/gpt-4",
{ ...body, preset: "client-preset" },
true,
{ providerSpecificData: { preset: "connection-preset" } }
);
assert.equal((explicit as any).preset, "client-preset");
const explicitNull = executor.transformRequest("openai/gpt-4", { ...body, preset: null }, true, {
providerSpecificData: { preset: "connection-preset" },
});
assert.equal((explicitNull as any).preset, null);
const explicitEmpty = executor.transformRequest("openai/gpt-4", { ...body, preset: "" }, true, {
providerSpecificData: { preset: "connection-preset" },
});
assert.equal((explicitEmpty as any).preset, "");
const blank = executor.transformRequest("openai/gpt-4", body, true, {
providerSpecificData: { preset: " " },
});
assert.equal((blank as any).preset, undefined);
});
test("DefaultExecutor.transformRequest strips stream_options from Anthropic-compatible targets", () => {
const anthropicCompat = new DefaultExecutor("anthropic-compatible-test");
const anthropicCcCompat = new DefaultExecutor("anthropic-compatible-cc-test");
const anthropicBody = {
model: "claude-sonnet-4-6",
messages: [{ role: "user", content: "hi" }],
max_tokens: 1,
stream_options: { include_usage: true },
};
const ccBody = {
model: "claude-sonnet-4-6",
messages: [{ role: "user", content: "hi" }],
max_tokens: 1,
};
const anthropicResult = anthropicCompat.transformRequest(
"claude-sonnet-4-6",
anthropicBody,
true,
{}
);
const ccResult = anthropicCcCompat.transformRequest("claude-sonnet-4-6", ccBody, true, {});
assert.notEqual(anthropicResult, anthropicBody);
assert.equal((anthropicResult as any).stream_options, undefined);
assert.equal((ccResult as any).stream_options, undefined);
});
test("DefaultExecutor.transformRequest neutralizes incompatible tool_choice for Qwen thinking", () => {
const executor = new DefaultExecutor("qwen");
const body = {
messages: [{ role: "user", content: "hi" }],
thinking: { type: "enabled" },
tool_choice: { type: "function", function: { name: "pwd" } },
};
const result = executor.transformRequest("qwen3-coder-plus", body, true, {});
assert.notEqual(result, body);
assert.equal((result as any).tool_choice, "auto");
});
// Port of decolua/9router#1343: openai-compatible-* providers (DeepSeek / Ollama /
// local OpenAI-compatible models) often lack native Structured Output, so a
// `json_schema` response_format is downgraded to `json_object` with the schema
// injected into the system prompt instead.
test("DefaultExecutor.transformRequest downgrades json_schema to json_object for openai-compatible providers and injects the schema into a fresh system prompt", () => {
const executor = new DefaultExecutor("openai-compatible-deepseek");
const schema = {
type: "object",
properties: { answer: { type: "string" } },
required: ["answer"],
};
const body = {
model: "deepseek-chat",
messages: [{ role: "user", content: "give me JSON" }],
response_format: {
type: "json_schema",
json_schema: { name: "answer_schema", schema },
},
};
const result = executor.transformRequest("deepseek-chat", body, true, {
providerSpecificData: { baseUrl: "https://proxy.example/v1" },
}) as any;
// response_format is downgraded to json_object.
assert.deepEqual(result.response_format, { type: "json_object" });
// A system message carrying the schema is injected at the front.
assert.equal(result.messages[0].role, "system");
assert.match(result.messages[0].content, /strictly follows this JSON schema/);
assert.ok(result.messages[0].content.includes('"answer"'));
// The original user message is preserved.
assert.equal(result.messages[1].role, "user");
assert.equal(result.messages[1].content, "give me JSON");
// Original body is not mutated.
assert.equal((body as any).response_format.type, "json_schema");
assert.equal(body.messages.length, 1);
});
test("DefaultExecutor.transformRequest appends the json_schema prompt to an existing system message", () => {
const executor = new DefaultExecutor("openai-compatible-ollama");
const body = {
model: "llama3.1",
messages: [
{ role: "system", content: "You are concise." },
{ role: "user", content: "give me JSON" },
],
response_format: {
type: "json_schema",
json_schema: { name: "s", schema: { type: "object" } },
},
};
const result = executor.transformRequest("llama3.1", body, true, {
providerSpecificData: { baseUrl: "https://proxy.example/v1" },
}) as any;
assert.deepEqual(result.response_format, { type: "json_object" });
assert.equal(result.messages[0].role, "system");
assert.match(result.messages[0].content, /^You are concise\./);
assert.match(result.messages[0].content, /strictly follows this JSON schema/);
// Existing system message object is not mutated in place.
assert.equal(body.messages[0].content, "You are concise.");
});
test("DefaultExecutor.transformRequest leaves json_schema response_format untouched for native providers", () => {
const executor = new DefaultExecutor("openai");
const responseFormat = {
type: "json_schema",
json_schema: { name: "s", schema: { type: "object" } },
};
const body = {
model: "gpt-4.1",
messages: [{ role: "user", content: "give me JSON" }],
response_format: responseFormat,
};
const result = executor.transformRequest("gpt-4.1", body, true, {}) as any;
// Native OpenAI keeps the json_schema response_format; no system prompt injected.
assert.deepEqual(result.response_format, responseFormat);
assert.equal(result.messages.length, 1);
assert.equal(result.messages[0].role, "user");
});
test("DefaultExecutor.transformRequest ignores non-json_schema response_format for openai-compatible providers", () => {
const executor = new DefaultExecutor("openai-compatible-deepseek");
const body = {
model: "deepseek-chat",
messages: [{ role: "user", content: "hi" }],
response_format: { type: "json_object" },
};
const result = executor.transformRequest("deepseek-chat", body, true, {
providerSpecificData: { baseUrl: "https://proxy.example/v1" },
}) as any;
assert.deepEqual(result.response_format, { type: "json_object" });
assert.equal(result.messages.length, 1);
assert.equal(result.messages[0].role, "user");
});
test("DefaultExecutor.transformRequest applies GLMT preset defaults without overriding explicit values", () => {
const executor = new DefaultExecutor("glmt");
const autoBody = {
messages: [{ role: "user", content: "hi" }],
};
const autoResult = executor.transformRequest("glm-5.1", autoBody, true, {});
assert.notEqual(autoResult, autoBody);
assert.equal((autoResult as any).max_tokens, 65536);
(assert as any).equal((autoResult as any).temperature, 0.2);
(assert as any).deepEqual((autoResult as any).thinking, {
type: "enabled",
budget_tokens: 24576,
});
const explicitBody = {
messages: [{ role: "user", content: "hi" }],
max_tokens: 4096,
temperature: 0.7,
thinking: { type: "enabled" },
};
const explicitResult = executor.transformRequest("glm-5.1", explicitBody, true, {});
assert.notEqual(explicitResult, explicitBody);
assert.equal((explicitResult as any).max_tokens, 4096);
assert.equal((explicitResult as any).temperature, 0.7);
assert.deepEqual((explicitResult as any).thinking, {
type: "enabled",
budget_tokens: 4095,
});
});
test("BaseExecutor helpers manage custom user agents and upstream extra headers", () => {
const headers = { "user-agent": "old", Authorization: "Bearer old" };
assert.equal(getCustomUserAgent({ customUserAgent: " MyAgent/1.0 " }), "MyAgent/1.0");
assert.equal(getCustomUserAgent({ customUserAgent: " " }), null);
setUserAgentHeader(headers, "MyAgent/2.0");
assert.equal(headers["User-Agent"], "MyAgent/2.0");
assert.equal(headers["user-agent"], "MyAgent/2.0");
applyConfiguredUserAgent(headers, { customUserAgent: "MyAgent/3.0" });
assert.equal(headers["User-Agent"], "MyAgent/3.0");
mergeUpstreamExtraHeaders(headers, {
Authorization: "Bearer override",
"user-agent": "Merged/4.0",
"X-Upstream": "1",
});
assert.equal(headers.Authorization, "Bearer override");
assert.equal(headers["User-Agent"], "Merged/4.0");
assert.equal(headers["user-agent"], "Merged/4.0");
assert.equal(headers["X-Upstream"], "1");
});
test("BaseExecutor.mergeAbortSignals aborts when either source signal aborts", () => {
const primary = new AbortController();
const secondary = new AbortController();
const merged = mergeAbortSignals(primary.signal, secondary.signal);
assert.equal(merged.aborted, false);
const primaryReason = new Error("primary timeout");
primaryReason.name = "TimeoutError";
primary.abort(primaryReason);
assert.equal(merged.aborted, true);
assert.equal(merged.reason, primaryReason);
const otherPrimary = new AbortController();
const otherSecondary = new AbortController();
const merged2 = mergeAbortSignals(otherPrimary.signal, otherSecondary.signal);
const secondaryReason = new Error("client closed");
otherSecondary.abort(secondaryReason);
assert.equal(merged2.aborted, true);
assert.equal(merged2.reason, secondaryReason);
});
test("BaseExecutor.needsRefresh returns true only when expiry is near", () => {
const executor = new TestExecutor();
const soon = new Date(Date.now() + 60_000).toISOString();
const later = new Date(Date.now() + 60 * 60 * 1000).toISOString();
assert.equal(executor.needsRefresh({ expiresAt: soon }), true);
assert.equal(executor.needsRefresh({ expiresAt: later }), false);
assert.equal(executor.needsRefresh({}), false);
});
test("DefaultExecutor.refreshCredentials returns null without refresh token", async () => {
const executor = new DefaultExecutor("gemini");
const result = await executor.refreshCredentials({}, null);
assert.equal(result, null);
});
test("DefaultExecutor.needsRefresh requests a proactive token for GigaChat", () => {
const executor = new DefaultExecutor("gigachat");
assert.equal(executor.needsRefresh({ apiKey: "base64-basic-credentials" }), true);
assert.equal(
executor.needsRefresh({
apiKey: "base64-basic-credentials",
accessToken: "existing-token",
expiresAt: new Date(Date.now() + 60 * 60 * 1000).toISOString(),
}),
false
);
});
test("DefaultExecutor.refreshCredentials delegates to OAuth refresh and returns new tokens", async () => {
const executor = new DefaultExecutor("gemini");
const originalFetch = globalThis.fetch;
globalThis.fetch = async (url, options) => {
assert.match(String(url), /oauth2\.googleapis\.com/);
assert.equal(options.method, "POST");
return new Response(
JSON.stringify({
access_token: "new-access-token",
refresh_token: "new-refresh-token",
expires_in: 3600,
}),
{
status: 200,
headers: { "Content-Type": "application/json" },
}
);
};
try {
const result = await executor.refreshCredentials({ refreshToken: "refresh-me" }, null);
assert.deepEqual(result, {
accessToken: "new-access-token",
refreshToken: "new-refresh-token",
expiresIn: 3600,
});
} finally {
globalThis.fetch = originalFetch;
}
});
test("DefaultExecutor.refreshCredentials swallows refresh errors and logs them", async () => {
const executor = new DefaultExecutor("gemini");
const originalFetch = globalThis.fetch;
const messages = [];
globalThis.fetch = async () => {
throw new Error("network down");
};
try {
const result = await executor.refreshCredentials(
{ refreshToken: "refresh-me" },
{ error: (tag, message) => messages.push({ tag, message }) }
);
assert.equal(result, null);
assert.equal(messages.length, 1);
assert.match(messages[0].message, /refresh error: network down/);
} finally {
globalThis.fetch = originalFetch;
}
});
test("BaseExecutor.execute returns response metadata and merges headers", async () => {
const executor = new TestExecutor();
const originalFetch = globalThis.fetch;
let captured;
globalThis.fetch = async (url, options) => {
captured = { url, options };
return new Response(JSON.stringify({ ok: true }), {
status: 200,
headers: { "Content-Type": "application/json" },
});
};
try {
const result = await executor.execute({
model: "gpt-4.1",
body: { messages: [{ role: "user", content: "hi" }] },
stream: true,
credentials: {
apiKey: "base-key",
providerSpecificData: { customUserAgent: "CredsAgent/1.0" },
},
upstreamExtraHeaders: {
Authorization: "Bearer override",
"user-agent": "UpstreamAgent/2.0",
"X-Trace-Id": "trace-1",
},
});
assert.equal(result.url, "https://primary.example/v1/chat/completions");
assert.equal(result.response.status, 200);
(assert as any).equal((result.transformedBody as any).transformed, true);
assert.equal((result.transformedBody as any).model, "gpt-4.1");
assert.equal(result.headers.Authorization, "Bearer override");
assert.equal(result.headers["User-Agent"], "UpstreamAgent/2.0");
assert.equal(result.headers["user-agent"], undefined);
assert.equal(result.headers["X-Trace-Id"], "trace-1");
assert.equal(result.headers.Accept, "text/event-stream");
assert.equal(captured.options.body.includes('"transformed":true'), true);
} finally {
globalThis.fetch = originalFetch;
}
});
test("BaseExecutor.execute refreshes credentials before the request when needed", async () => {
class RefreshingExecutor extends BaseExecutor {
constructor() {
super("refreshing-provider", {
baseUrl: "https://refresh.example/v1/chat/completions",
});
}
needsRefresh() {
return true;
}
async refreshCredentials() {
return {
accessToken: "fresh-token",
expiresAt: new Date(Date.now() + 60 * 60 * 1000).toISOString(),
};
}
}
const executor = new RefreshingExecutor();
const originalFetch = globalThis.fetch;
let capturedHeaders;
globalThis.fetch = async (url, options) => {
assert.equal(String(url), "https://refresh.example/v1/chat/completions");
capturedHeaders = options.headers;
return new Response(JSON.stringify({ ok: true }), { status: 200 });
};
try {
await executor.execute({
model: "gpt-4.1",
body: {},
stream: false,
credentials: { apiKey: "stale-token" },
});
assert.equal(capturedHeaders.Authorization, "Bearer fresh-token");
} finally {
globalThis.fetch = originalFetch;
}
});
test("BaseExecutor.execute falls back to the next base URL after a transport error", async () => {
const executor = new TestExecutor();
const originalFetch = globalThis.fetch;
const calls = [];
globalThis.fetch = async (url) => {
calls.push(String(url));
if (calls.length === 1) {
throw new Error("first node down");
}
return new Response("ok", { status: 200 });
};
try {
const result = await executor.execute({
model: "gpt-4.1",
body: { hello: "world" },
stream: false,
credentials: {},
});
assert.deepEqual(calls, [
"https://primary.example/v1/chat/completions",
"https://fallback.example/v1/chat/completions",
]);
assert.equal(result.url, "https://fallback.example/v1/chat/completions");
} finally {
globalThis.fetch = originalFetch;
}
});
test("BaseExecutor.execute throws the last error when all URLs fail", async () => {
const executor = new TestExecutor();
const originalFetch = globalThis.fetch;
globalThis.fetch = async () => {
throw new Error("still down");
};
try {
await assert.rejects(
executor.execute({
model: "gpt-4.1",
body: {},
stream: false,
credentials: {},
}),
/still down/
);
} finally {
globalThis.fetch = originalFetch;
}
});
test("BaseExecutor.execute propagates aborted requests through the merged signal", async () => {
const executor = new TestExecutor({ baseUrls: ["https://single.example/v1/chat/completions"] });
const controller = new AbortController();
controller.abort();
const originalFetch = globalThis.fetch;
globalThis.fetch = async (url, options) => {
assert.equal(options.signal.aborted, true);
const error = new Error(`aborted ${url}`);
error.name = "AbortError";
throw error;
};
try {
await assert.rejects(
executor.execute({
model: "gpt-4.1",
body: {},
stream: false,
credentials: {},
signal: controller.signal,
}),
/aborted/
);
} finally {
globalThis.fetch = originalFetch;
}
});
test("BaseExecutor.execute clears the startup timeout after headers arrive", async () => {
const executor = new TestExecutor({ baseUrls: ["https://single.example/v1/chat/completions"] });
const originalFetch = globalThis.fetch;
const originalFetchStartTimeoutMs = BaseExecutor.FETCH_START_TIMEOUT_MS;
let capturedSignal;
BaseExecutor.FETCH_START_TIMEOUT_MS = 20;
globalThis.fetch = async (_url, options) => {
capturedSignal = options.signal;
return new Response("ok", {
status: 200,
headers: { "Content-Type": "application/json" },
});
};
try {
await executor.execute({
model: "gpt-4.1",
body: {},
stream: true,
credentials: {},
});
assert.equal(capturedSignal?.aborted, false);
await new Promise((resolve) => setTimeout(resolve, 40));
assert.equal(capturedSignal?.aborted, false);
} finally {
BaseExecutor.FETCH_START_TIMEOUT_MS = originalFetchStartTimeoutMs;
globalThis.fetch = originalFetch;
}
});
// Regression test for issue #1454: duplicate anthropic-version header when
// Claude Code CLI headers are detected on the native `claude` provider.
// The provider config seeds headers with Title-Case "Anthropic-Version" while
// the Claude-Code patch injects lowercase "anthropic-version". Before the fix,
// both keys coexisted in the JS object and undici combined their values into
// "2023-06-01, 2023-06-01", causing a 400 from Anthropic.
test("DefaultExecutor.execute does not produce duplicate anthropic-version header when Claude Code CLI headers are present", async () => {
const executor = new DefaultExecutor("claude");
const originalFetch = globalThis.fetch;
let capturedHeaders: Record<string, string> = {};
globalThis.fetch = async (_url, init = {}) => {
// Capture raw headers without normalisation so case-variant duplicate keys are visible.
capturedHeaders = (init.headers as Record<string, string>) || {};
return new Response(JSON.stringify({ ok: true }), {
status: 200,
headers: { "Content-Type": "application/json" },
});
};
try {
await executor.execute({
model: "claude-sonnet-4-6",
body: {
model: "claude-sonnet-4-6",
messages: [{ role: "user", content: "hi" }],
max_tokens: 1,
},
stream: false,
credentials: { accessToken: "oauth-token" },
clientHeaders: {
"x-app": "cli",
"user-agent": "claude-cli/2.1.116 (external, cli)",
"anthropic-beta": "oauth-2025-04-20",
},
});
} finally {
globalThis.fetch = originalFetch;
}
// Must be exactly one key — not multiple case variants that undici would combine
const versionKeys = Object.keys(capturedHeaders).filter(
(k) => k.toLowerCase() === "anthropic-version"
);
assert.equal(versionKeys.length, 1, "Duplicate anthropic-version header keys found");
assert.equal(capturedHeaders[versionKeys[0]], "2023-06-01");
});