mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-20 22:22:57 +03:00
fix(command-code): align CLI version header (#3462)
Integrated into release/v3.8.17
This commit is contained in:
committed by
GitHub
parent
49c11f0cea
commit
1cc2313a4f
@@ -5,7 +5,7 @@ import { BaseExecutor, mergeUpstreamExtraHeaders, type ExecuteInput } from "./ba
|
||||
|
||||
type JsonRecord = Record<string, unknown>;
|
||||
|
||||
const COMMAND_CODE_VERSION = "0.24.1";
|
||||
export const COMMAND_CODE_VERSION = process.env.COMMAND_CODE_VERSION?.trim() || "0.33.2";
|
||||
const MAX_COMMAND_CODE_TOKENS = 200_000;
|
||||
const encoder = new TextEncoder();
|
||||
|
||||
|
||||
@@ -320,8 +320,7 @@ async function fetchWithProxyFallback(
|
||||
// Only attempt proxy fallback for retryable errors (network / timeout)
|
||||
// and only when the target is not a local / LAN address.
|
||||
const fetchErr = err as SafeOutboundFetchError;
|
||||
const isNetworkIssue =
|
||||
fetchErr?.code === "NETWORK_ERROR" || fetchErr?.code === "TIMEOUT";
|
||||
const isNetworkIssue = fetchErr?.code === "NETWORK_ERROR" || fetchErr?.code === "TIMEOUT";
|
||||
const isRetryable = fetchErr?.isRetryable !== false;
|
||||
const isValidTarget = !isLocal && isRetryableProxyTarget(url);
|
||||
|
||||
@@ -574,6 +573,7 @@ export async function validateCommandCodeProvider({ apiKey, providerSpecificData
|
||||
providerSpecificData?.validationModelId ||
|
||||
entry?.models?.find((model) => model.id === "deepseek/deepseek-v4-flash")?.id ||
|
||||
"deepseek/deepseek-v4-flash";
|
||||
const { COMMAND_CODE_VERSION } = await import("@omniroute/open-sse/executors/commandCode.ts");
|
||||
|
||||
return validateDirectChatProvider({
|
||||
url,
|
||||
@@ -581,7 +581,7 @@ export async function validateCommandCodeProvider({ apiKey, providerSpecificData
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${apiKey}`,
|
||||
"x-command-code-version": "0.24.1",
|
||||
"x-command-code-version": COMMAND_CODE_VERSION,
|
||||
"x-cli-environment": "external",
|
||||
"x-project-slug": "pi-cc",
|
||||
"x-taste-learning": "false",
|
||||
@@ -2914,8 +2914,7 @@ async function validateGrokWebProvider({ apiKey, providerSpecificData = {} }: an
|
||||
if (isCloudflareChallenge(errorDetail)) {
|
||||
return {
|
||||
valid: false,
|
||||
error:
|
||||
"Grok validation blocked by Cloudflare anti-bot. Try a residential IP or proxy.",
|
||||
error: "Grok validation blocked by Cloudflare anti-bot. Try a residential IP or proxy.",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3410,9 +3409,8 @@ async function validateClaudeWebProvider({ apiKey, providerSpecificData = {} }:
|
||||
return { valid: false, error: "Paste your sessionKey cookie from claude.ai" };
|
||||
}
|
||||
|
||||
const { tlsFetchClaude, TlsClientUnavailableError } = await import(
|
||||
"@omniroute/open-sse/services/claudeTlsClient.ts"
|
||||
);
|
||||
const { tlsFetchClaude, TlsClientUnavailableError } =
|
||||
await import("@omniroute/open-sse/services/claudeTlsClient.ts");
|
||||
|
||||
let response: { status: number; text: string | null };
|
||||
try {
|
||||
@@ -3455,7 +3453,8 @@ async function validateClaudeWebProvider({ apiKey, providerSpecificData = {} }:
|
||||
if (response.status === 401 || response.status === 403) {
|
||||
return {
|
||||
valid: false,
|
||||
error: "Invalid or expired session cookie — re-paste sessionKey from claude.ai DevTools → Cookies",
|
||||
error:
|
||||
"Invalid or expired session cookie — re-paste sessionKey from claude.ai DevTools → Cookies",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3502,7 +3501,8 @@ async function validateGeminiWebProvider({ apiKey, providerSpecificData = {} }:
|
||||
if (response.status === 401 || response.status === 403) {
|
||||
return {
|
||||
valid: false,
|
||||
error: "Invalid or expired __Secure-1PSID cookie — re-paste from gemini.google.com DevTools → Cookies",
|
||||
error:
|
||||
"Invalid or expired __Secure-1PSID cookie — re-paste from gemini.google.com DevTools → Cookies",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3555,7 +3555,8 @@ async function validateCopilotWebProvider({ apiKey, providerSpecificData = {} }:
|
||||
if (response.status === 401 || response.status === 403) {
|
||||
return {
|
||||
valid: false,
|
||||
error: "Invalid or expired access_token — re-paste from copilot.microsoft.com DevTools → Cookies",
|
||||
error:
|
||||
"Invalid or expired access_token — re-paste from copilot.microsoft.com DevTools → Cookies",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3774,15 +3775,10 @@ export async function validateProviderApiKey({ provider, apiKey, providerSpecifi
|
||||
* These providers share a POST /chat/completions auth check pattern and differ
|
||||
* only in default baseUrl and test model name.
|
||||
*/
|
||||
function buildOpengatewayValidator(
|
||||
defaultBaseUrl: string,
|
||||
model: string
|
||||
) {
|
||||
function buildOpengatewayValidator(defaultBaseUrl: string, model: string) {
|
||||
return async ({ apiKey, providerSpecificData }: any) => {
|
||||
try {
|
||||
const baseUrl = normalizeBaseUrl(
|
||||
providerSpecificData?.baseUrl || defaultBaseUrl
|
||||
);
|
||||
const baseUrl = normalizeBaseUrl(providerSpecificData?.baseUrl || defaultBaseUrl);
|
||||
const chatUrl = `${baseUrl.replace(/\/chat\/completions$/, "")}/chat/completions`;
|
||||
const res = await validationWrite(
|
||||
chatUrl,
|
||||
@@ -3832,8 +3828,7 @@ export async function validateProviderApiKey({ provider, apiKey, providerSpecifi
|
||||
// The executor routes these tokens to dashscope.aliyuncs.com, so the
|
||||
// validation must test against dashscope, NOT the Cosy PAT endpoint.
|
||||
try {
|
||||
const dashscopeUrl =
|
||||
"https://dashscope.aliyuncs.com/compatible-mode/v1/models";
|
||||
const dashscopeUrl = "https://dashscope.aliyuncs.com/compatible-mode/v1/models";
|
||||
const res = await validationRead(
|
||||
dashscopeUrl,
|
||||
{
|
||||
@@ -3994,7 +3989,7 @@ export async function validateProviderApiKey({ provider, apiKey, providerSpecifi
|
||||
max_tokens: 1,
|
||||
}),
|
||||
},
|
||||
isLocal,
|
||||
isLocal
|
||||
);
|
||||
if (res.status === 401 || res.status === 403) {
|
||||
return { valid: false, error: "Invalid API key" };
|
||||
@@ -4067,7 +4062,7 @@ export async function validateProviderApiKey({ provider, apiKey, providerSpecifi
|
||||
max_tokens: 1,
|
||||
}),
|
||||
},
|
||||
isLocal,
|
||||
isLocal
|
||||
);
|
||||
if (res.status === 401 || res.status === 403) {
|
||||
return { valid: false, error: "Invalid API key" };
|
||||
|
||||
@@ -8,7 +8,8 @@ const TEST_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-command-c
|
||||
process.env.DATA_DIR = TEST_DATA_DIR;
|
||||
|
||||
const { REGISTRY, getRegistryEntry } = await import("../../open-sse/config/providerRegistry.ts");
|
||||
const { CommandCodeExecutor } = await import("../../open-sse/executors/commandCode.ts");
|
||||
const { CommandCodeExecutor, COMMAND_CODE_VERSION } =
|
||||
await import("../../open-sse/executors/commandCode.ts");
|
||||
const { getExecutor, hasSpecializedExecutor } = await import("../../open-sse/executors/index.ts");
|
||||
const core = await import("../../src/lib/db/core.ts");
|
||||
|
||||
@@ -117,7 +118,7 @@ test("Command Code executor posts wrapped body and required headers to /alpha/ge
|
||||
assert.equal(calls[0].url, "https://api.commandcode.ai/alpha/generate");
|
||||
assert.equal(calls[0].init.method, "POST");
|
||||
assert.equal(headers.Authorization, "Bearer cc_test_key");
|
||||
assert.equal(headers["x-command-code-version"], "0.24.1");
|
||||
assert.equal(headers["x-command-code-version"], COMMAND_CODE_VERSION);
|
||||
assert.equal(headers["x-cli-environment"], "external");
|
||||
assert.equal(headers["x-project-slug"], "pi-cc");
|
||||
assert.equal(headers["x-taste-learning"], "false");
|
||||
|
||||
@@ -13,6 +13,8 @@ const { __setTlsFetchOverrideForTesting: __setPplxTlsFetchOverride } =
|
||||
const { __setTlsFetchOverrideForTesting: __setGrokTlsFetchOverride } =
|
||||
await import("../../open-sse/services/grokTlsClient.ts");
|
||||
|
||||
const { COMMAND_CODE_VERSION } = await import("../../open-sse/executors/commandCode.ts");
|
||||
|
||||
const originalFetch = globalThis.fetch;
|
||||
|
||||
test.afterEach(() => {
|
||||
@@ -506,9 +508,7 @@ test("grok-web validator: 403 with credential-rejection body is treated as auth-
|
||||
|
||||
test("grok-web validator: TLS client unavailable surfaces actionable error", async () => {
|
||||
__setGrokTlsFetchOverride(async () => {
|
||||
const { TlsClientUnavailableError } = await import(
|
||||
"../../open-sse/services/grokTlsClient.ts"
|
||||
);
|
||||
const { TlsClientUnavailableError } = await import("../../open-sse/services/grokTlsClient.ts");
|
||||
throw new TlsClientUnavailableError("native binary not found");
|
||||
});
|
||||
|
||||
@@ -1960,7 +1960,7 @@ test("validateCommandCodeProvider sends Command Code probe URL, headers, and wra
|
||||
assert.equal(calls[0].method, "POST");
|
||||
assert.equal(calls[0].headers.Authorization, "Bearer cc_test_key");
|
||||
assert.equal(calls[0].headers["Content-Type"], "application/json");
|
||||
assert.equal(calls[0].headers["x-command-code-version"], "0.24.1");
|
||||
assert.equal(calls[0].headers["x-command-code-version"], COMMAND_CODE_VERSION);
|
||||
assert.equal(calls[0].headers["x-cli-environment"], "external");
|
||||
assert.equal(calls[0].headers["x-project-slug"], "pi-cc");
|
||||
assert.equal(calls[0].headers["x-taste-learning"], "false");
|
||||
@@ -2003,7 +2003,11 @@ test("validateCommandCodeProvider rejects auth failures and provider outages", a
|
||||
const { __setTlsFetchOverrideForTesting: __setClaudeTlsFetchOverride } =
|
||||
await import("../../open-sse/services/claudeTlsClient.ts");
|
||||
|
||||
function makeClaudeTlsResponse(status: number, body: string, headers: Record<string, string> = {}): any {
|
||||
function makeClaudeTlsResponse(
|
||||
status: number,
|
||||
body: string,
|
||||
headers: Record<string, string> = {}
|
||||
): any {
|
||||
const h = new Headers();
|
||||
for (const [k, v] of Object.entries(headers)) h.set(k, v);
|
||||
return { status, ok: status >= 200 && status < 300, headers: h, text: body, body: null };
|
||||
@@ -2024,7 +2028,10 @@ test("claude-web validator: 200 from /api/organizations → valid", async () =>
|
||||
assert.equal(result.valid, true);
|
||||
assert.equal(result.error, null);
|
||||
assert.equal(captured?.url, "https://claude.ai/api/organizations");
|
||||
assert.match((captured?.opts.headers as Record<string, string>).Cookie || "", /sessionKey=sk-ant-sid02-test-session-key/);
|
||||
assert.match(
|
||||
(captured?.opts.headers as Record<string, string>).Cookie || "",
|
||||
/sessionKey=sk-ant-sid02-test-session-key/
|
||||
);
|
||||
__setClaudeTlsFetchOverride(null);
|
||||
});
|
||||
|
||||
@@ -2072,9 +2079,7 @@ test("claude-web validator: 429 → valid (rate limited means auth passed)", asy
|
||||
});
|
||||
|
||||
test("claude-web validator: 500 → Claude.ai unavailable", async () => {
|
||||
__setClaudeTlsFetchOverride(async () =>
|
||||
makeClaudeTlsResponse(500, "internal server error")
|
||||
);
|
||||
__setClaudeTlsFetchOverride(async () => makeClaudeTlsResponse(500, "internal server error"));
|
||||
|
||||
const result = await validateProviderApiKey({
|
||||
provider: "claude-web",
|
||||
@@ -2335,10 +2340,7 @@ test("gitlawb validator: accepts valid API key via chat/completions probe", asyn
|
||||
test("gitlawb validator: 400/422/429 treated as auth success", async () => {
|
||||
for (const status of [400, 422, 429]) {
|
||||
globalThis.fetch = async (url) => {
|
||||
assert.equal(
|
||||
String(url),
|
||||
"https://opengateway.gitlawb.com/v1/xiaomi-mimo/chat/completions"
|
||||
);
|
||||
assert.equal(String(url), "https://opengateway.gitlawb.com/v1/xiaomi-mimo/chat/completions");
|
||||
return new Response(JSON.stringify({ error: "bad request" }), { status });
|
||||
};
|
||||
const result = await validateProviderApiKey({ provider: "gitlawb", apiKey: "glb-key" });
|
||||
@@ -2349,10 +2351,7 @@ test("gitlawb validator: 400/422/429 treated as auth success", async () => {
|
||||
|
||||
test("gitlawb validator: rejects invalid API key (401)", async () => {
|
||||
globalThis.fetch = async (url) => {
|
||||
assert.equal(
|
||||
String(url),
|
||||
"https://opengateway.gitlawb.com/v1/xiaomi-mimo/chat/completions"
|
||||
);
|
||||
assert.equal(String(url), "https://opengateway.gitlawb.com/v1/xiaomi-mimo/chat/completions");
|
||||
return new Response(JSON.stringify({ error: "unauthorized" }), { status: 401 });
|
||||
};
|
||||
|
||||
@@ -2363,10 +2362,7 @@ test("gitlawb validator: rejects invalid API key (401)", async () => {
|
||||
|
||||
test("gitlawb validator: rejects invalid API key (403)", async () => {
|
||||
globalThis.fetch = async (url) => {
|
||||
assert.equal(
|
||||
String(url),
|
||||
"https://opengateway.gitlawb.com/v1/xiaomi-mimo/chat/completions"
|
||||
);
|
||||
assert.equal(String(url), "https://opengateway.gitlawb.com/v1/xiaomi-mimo/chat/completions");
|
||||
return new Response(JSON.stringify({ error: "forbidden" }), { status: 403 });
|
||||
};
|
||||
|
||||
@@ -2387,10 +2383,7 @@ test("gitlawb validator: surfaces network failures", async () => {
|
||||
|
||||
test("gitlawb validator: accepts custom baseUrl override", async () => {
|
||||
globalThis.fetch = async (url, init = {}) => {
|
||||
assert.equal(
|
||||
String(url),
|
||||
"https://custom-gateway.example.com/v1/xiaomi-mimo/chat/completions"
|
||||
);
|
||||
assert.equal(String(url), "https://custom-gateway.example.com/v1/xiaomi-mimo/chat/completions");
|
||||
assert.equal((init.headers as Record<string, string>).Authorization, "Bearer glb-key");
|
||||
return new Response(JSON.stringify({ choices: [{ message: { content: "ok" } }] }), {
|
||||
status: 200,
|
||||
@@ -2414,7 +2407,10 @@ test("gitlawb-gmi validator: accepts valid API key via chat/completions probe",
|
||||
globalThis.fetch = async (url, init = {}) => {
|
||||
calls.push({ url: String(url), headers: init.headers || {} });
|
||||
assert.equal(String(url), "https://opengateway.gitlawb.com/v1/gmi-cloud/chat/completions");
|
||||
assert.equal((init.headers as Record<string, string>).Authorization, "Bearer glb-gmi-valid-key");
|
||||
assert.equal(
|
||||
(init.headers as Record<string, string>).Authorization,
|
||||
"Bearer glb-gmi-valid-key"
|
||||
);
|
||||
const body = JSON.parse(String(init.body));
|
||||
assert.equal(body.model, "XiaomiMiMo/MiMo-V2.5-Pro");
|
||||
assert.equal(body.messages[0].content, "test");
|
||||
@@ -2435,10 +2431,7 @@ test("gitlawb-gmi validator: accepts valid API key via chat/completions probe",
|
||||
test("gitlawb-gmi validator: accepts 400/422/429 as auth success", async () => {
|
||||
for (const status of [400, 422, 429]) {
|
||||
globalThis.fetch = async (url) => {
|
||||
assert.equal(
|
||||
String(url),
|
||||
"https://opengateway.gitlawb.com/v1/gmi-cloud/chat/completions"
|
||||
);
|
||||
assert.equal(String(url), "https://opengateway.gitlawb.com/v1/gmi-cloud/chat/completions");
|
||||
return new Response(JSON.stringify({ error: "bad request" }), { status });
|
||||
};
|
||||
const result = await validateProviderApiKey({
|
||||
@@ -2451,10 +2444,7 @@ test("gitlawb-gmi validator: accepts 400/422/429 as auth success", async () => {
|
||||
|
||||
test("gitlawb-gmi validator: rejects invalid API key (401)", async () => {
|
||||
globalThis.fetch = async (url) => {
|
||||
assert.equal(
|
||||
String(url),
|
||||
"https://opengateway.gitlawb.com/v1/gmi-cloud/chat/completions"
|
||||
);
|
||||
assert.equal(String(url), "https://opengateway.gitlawb.com/v1/gmi-cloud/chat/completions");
|
||||
return new Response(JSON.stringify({ error: "unauthorized" }), { status: 401 });
|
||||
};
|
||||
|
||||
@@ -2468,10 +2458,7 @@ test("gitlawb-gmi validator: rejects invalid API key (401)", async () => {
|
||||
|
||||
test("gitlawb-gmi validator: rejects invalid API key (403)", async () => {
|
||||
globalThis.fetch = async (url) => {
|
||||
assert.equal(
|
||||
String(url),
|
||||
"https://opengateway.gitlawb.com/v1/gmi-cloud/chat/completions"
|
||||
);
|
||||
assert.equal(String(url), "https://opengateway.gitlawb.com/v1/gmi-cloud/chat/completions");
|
||||
return new Response(JSON.stringify({ error: "forbidden" }), { status: 403 });
|
||||
};
|
||||
|
||||
@@ -2498,10 +2485,7 @@ test("gitlawb-gmi validator: surfaces network failures", async () => {
|
||||
|
||||
test("gitlawb-gmi validator: accepts custom baseUrl override", async () => {
|
||||
globalThis.fetch = async (url, init = {}) => {
|
||||
assert.equal(
|
||||
String(url),
|
||||
"https://custom-gateway.example.com/v1/gmi-cloud/chat/completions"
|
||||
);
|
||||
assert.equal(String(url), "https://custom-gateway.example.com/v1/gmi-cloud/chat/completions");
|
||||
assert.equal((init.headers as Record<string, string>).Authorization, "Bearer glb-gmi-key");
|
||||
return new Response(JSON.stringify({ choices: [{ message: { content: "ok" } }] }), {
|
||||
status: 200,
|
||||
|
||||
@@ -9,6 +9,7 @@ process.env.DATA_DIR = TEST_DATA_DIR;
|
||||
|
||||
const core = await import("../../src/lib/db/core.ts");
|
||||
const { handleResponsesCore } = await import("../../open-sse/handlers/responsesHandler.ts");
|
||||
const { COMMAND_CODE_VERSION } = await import("../../open-sse/executors/commandCode.ts");
|
||||
|
||||
const originalFetch = globalThis.fetch;
|
||||
|
||||
@@ -253,7 +254,7 @@ test("handleResponsesCore transforms Command Code executor SSE through Responses
|
||||
assert.equal(result.success, true);
|
||||
assert.equal(call.url, "https://api.commandcode.ai/alpha/generate");
|
||||
assert.equal(call.headers.Authorization, "Bearer cc_test_key");
|
||||
assert.equal(call.headers["x-command-code-version"], "0.24.1");
|
||||
assert.equal(call.headers["x-command-code-version"], COMMAND_CODE_VERSION);
|
||||
assert.equal(call.body.params.model, "gpt-5.4-mini");
|
||||
assert.equal(call.body.params.stream, true);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user