mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-14 02:42:24 +03:00
Three related things that genuinely belong together: the registry and suffix splitter not knowing Astra while the live catalog serves it, the Codex client pin Astra requires, and dropping `next/font/google` so a production image build does not reach fonts.googleapis.com. --- Validated in one consolidated worktree cut from `release/v3.8.51`, boarded with the other 19 PRs of this batch. Two in-batch conflicts, both additive and resolved by keeping each side: the `ENVIRONMENT.md` table (#13035 + #13011) and the `chatHelpers.ts` import block (#12975 on the tip + #13017). - `typecheck:core` clean; `check:dashboard-typecheck` OK (206 pre-existing, within baseline); `check:changelog-integrity` OK; `check:docs-counts` migrations ✓ - complexity 2816 / baseline 3218 and cognitive-complexity 1271 / baseline 1437 — both under baseline - 531 of 532 focused assertions green across the batch's 46 test files - `check-file-size` rebaselined for the batch's real growth (annotation `_rebaseline_2026_09_11_mergebatch_v3851_houminxi`, landed on #13038), attributed per PR The single red is **not this batch**: `tests/unit/combo/quota-weighted-strategy.test.ts` → "A/B isolation: 7 hard-empty + 2 at 0.5% + 1 at 40%, floor=1" asserts an order between two connections of identical weight and flakes on the pure tip too — 2 failures in 4 runs at `origin/release/v3.8.51` with nothing from this batch applied. ⚠️ base-red inherited: #12732 — `Docs Gates`, `Merge integrity`, `No new ESLint warnings`, `Unit Tests fast-path` and `Fast Quality Gates` reproduce on the pure tip (provider count 356 vs the 358 the modules define, SKILL.md drift, and `open-sse/utils/stream.ts` at 3115 > frozen 3098, untouched here). Thanks @HouMinXi — the live evidence on these (X500 logs, `storage.sqlite` state, real `/v1/models` probes, the 36-minute outage write-up) is what let a 20-PR batch be reviewed as a unit.
166 lines
6.9 KiB
TypeScript
166 lines
6.9 KiB
TypeScript
/**
|
|
* tests/unit/claude-codex-identity-version-sync.test.ts
|
|
*
|
|
* Guards the pinned CLI identity versions against drift. The Claude Code version
|
|
* lives in FOUR places (claudeIdentity, anthropicHeaders, claudeCodeCompatible,
|
|
* ccBridgeTransforms) and MUST stay in lockstep — a partial bump produces an
|
|
* inconsistent wire fingerprint. The Codex client version lives in codexClient.
|
|
*
|
|
* When you capture a newer claude-cli / codex release, bump ALL constants and
|
|
* update the pinned values below in the same change.
|
|
*/
|
|
|
|
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
|
|
const id = await import("../../open-sse/executors/claudeIdentity.ts");
|
|
const hdr = await import("../../open-sse/config/anthropicHeaders.ts");
|
|
const compat = await import("../../open-sse/services/claudeCodeCompatible.ts");
|
|
const bridge = await import("../../open-sse/services/ccBridgeTransforms.ts");
|
|
const codexCfg = await import("../../open-sse/config/codexClient.ts");
|
|
const canonical = await import("../../src/shared/constants/claudeCodeClient.ts");
|
|
|
|
test("Claude CLI version constants are in lockstep across all 4 sources", () => {
|
|
const V = canonical.CLAUDE_CODE_CLIENT_VERSION;
|
|
assert.equal(id.CLAUDE_CODE_VERSION, V, "claudeIdentity.CLAUDE_CODE_VERSION drift");
|
|
assert.equal(hdr.CLAUDE_CLI_VERSION, V, "anthropicHeaders.CLAUDE_CLI_VERSION drift");
|
|
assert.equal(compat.CLAUDE_CODE_COMPATIBLE_VERSION, V, "claudeCodeCompatible version drift");
|
|
assert.equal(bridge.DEFAULT_CLAUDE_CODE_VERSION, V, "ccBridgeTransforms version drift");
|
|
assert.equal(
|
|
hdr.CLAUDE_CLI_USER_AGENT,
|
|
`claude-cli/${V} (external, cli)`,
|
|
"CLAUDE_CLI_USER_AGENT drift"
|
|
);
|
|
assert.equal(
|
|
compat.CLAUDE_CODE_COMPATIBLE_USER_AGENT,
|
|
`claude-cli/${V} (external, sdk-cli)`,
|
|
"CLAUDE_CODE_COMPATIBLE_USER_AGENT drift"
|
|
);
|
|
});
|
|
|
|
test("Claude CLI wire versions match the captured 2.1.258 binary", () => {
|
|
assert.equal(canonical.CLAUDE_CODE_CLIENT_VERSION, "2.1.258");
|
|
assert.equal(canonical.CLAUDE_CODE_CLIENT_BUILD_REVISION, "1e2");
|
|
assert.equal(canonical.CLAUDE_CODE_CLIENT_BILLING_VERSION, "2.1.258.1e2");
|
|
assert.equal(canonical.CLAUDE_CODE_SDK_PACKAGE_VERSION, "0.112.1");
|
|
assert.equal(canonical.CLAUDE_CODE_RUNTIME_VERSION, "v26.3.0");
|
|
assert.equal(
|
|
compat.CLAUDE_CODE_COMPATIBLE_STAINLESS_PACKAGE_VERSION,
|
|
canonical.CLAUDE_CODE_SDK_PACKAGE_VERSION
|
|
);
|
|
assert.equal(
|
|
compat.CLAUDE_CODE_COMPATIBLE_STAINLESS_RUNTIME_VERSION,
|
|
canonical.CLAUDE_CODE_RUNTIME_VERSION
|
|
);
|
|
assert.equal(hdr.CLAUDE_CLI_STAINLESS_PACKAGE_VERSION, canonical.CLAUDE_CODE_SDK_PACKAGE_VERSION);
|
|
assert.equal(hdr.CLAUDE_CLI_STAINLESS_RUNTIME_VERSION, canonical.CLAUDE_CODE_RUNTIME_VERSION);
|
|
assert.equal(hdr.CLAUDE_CLI_BILLING_VERSION, canonical.CLAUDE_CODE_CLIENT_BILLING_VERSION);
|
|
});
|
|
|
|
async function withEnv<T>(
|
|
entries: Record<string, string | undefined>,
|
|
fn: () => T | Promise<T>
|
|
): Promise<T> {
|
|
const previous = new Map<string, string | undefined>();
|
|
for (const [key, value] of Object.entries(entries)) {
|
|
previous.set(key, process.env[key]);
|
|
if (value === undefined) {
|
|
delete process.env[key];
|
|
} else {
|
|
process.env[key] = value;
|
|
}
|
|
}
|
|
try {
|
|
return await fn();
|
|
} finally {
|
|
for (const [key, value] of previous.entries()) {
|
|
if (value === undefined) {
|
|
delete process.env[key];
|
|
} else {
|
|
process.env[key] = value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
test("Codex client version locksteps Dockerfile @openai/codex", () => {
|
|
const dockerfile = fs.readFileSync(path.join(process.cwd(), "Dockerfile"), "utf8");
|
|
const match = dockerfile.match(/@openai\/codex@([0-9]+\.[0-9]+\.[0-9]+)/);
|
|
assert.ok(match, "Dockerfile must pin @openai/codex@x.y.z");
|
|
const pinned = match[1];
|
|
assert.notEqual(pinned, "0.149.0");
|
|
assert.equal(codexCfg.DEFAULT_CODEX_CLIENT_VERSION, pinned);
|
|
assert.equal(codexCfg.getCodexClientVersion(), pinned);
|
|
assert.equal(codexCfg.getCodexDefaultHeaders().Version, pinned);
|
|
assert.equal(
|
|
codexCfg.getCodexCliRsHeaders()["User-Agent"],
|
|
`codex_cli_rs/${pinned}`,
|
|
);
|
|
});
|
|
|
|
test("Codex client version env override still wins", async () => {
|
|
await withEnv({ CODEX_CLIENT_VERSION: "0.99.0" }, () => {
|
|
assert.equal(codexCfg.getCodexClientVersion(), "0.99.0");
|
|
assert.equal(codexCfg.getCodexDefaultHeaders().Version, "0.99.0");
|
|
});
|
|
});
|
|
|
|
test("test 7: live-empty GitHub catalog path does not call persist", () => {
|
|
const src = fs.readFileSync(
|
|
path.join(process.cwd(), "src/app/api/providers/[id]/models/route.ts"),
|
|
"utf8",
|
|
);
|
|
// The githubCatalogModels fallback must use buildResponse, not buildApiDiscoveryResponse.
|
|
const idx = src.indexOf("Codex live catalog unavailable — using GitHub model catalog");
|
|
assert.ok(idx > 0);
|
|
const start = src.lastIndexOf("if (githubCatalogModels", idx);
|
|
const end = src.indexOf("if (cachedDiscoveryModels", idx);
|
|
assert.ok(start > 0 && end > start);
|
|
const window = src.slice(start, end);
|
|
assert.match(window, /buildResponse\s*\(/);
|
|
assert.doesNotMatch(window, /buildApiDiscoveryResponse\s*\(/);
|
|
|
|
const liveIdx = src.lastIndexOf("if (liveModels && liveModels.length > 0)");
|
|
assert.ok(liveIdx > 0 && liveIdx < start);
|
|
const liveWindow = src.slice(liveIdx, start);
|
|
assert.match(liveWindow, /buildApiDiscoveryResponse\s*\(/);
|
|
});
|
|
|
|
test("Codex client version locksteps Dockerfile @openai/codex and env override", () => {
|
|
const dockerfile = fs.readFileSync(path.join(process.cwd(), "Dockerfile"), "utf8");
|
|
const match = dockerfile.match(/@openai\/codex@([0-9]+\.[0-9]+\.[0-9]+)/);
|
|
assert.ok(match, "Dockerfile must pin @openai/codex@x.y.z");
|
|
const pinned = match[1];
|
|
assert.notEqual(pinned, "0.149.0");
|
|
assert.equal(codexCfg.DEFAULT_CODEX_CLIENT_VERSION, pinned);
|
|
assert.equal(codexCfg.getCodexClientVersion(), pinned);
|
|
assert.equal(codexCfg.getCodexDefaultHeaders().Version, pinned);
|
|
assert.equal(
|
|
codexCfg.getCodexCliRsHeaders()["User-Agent"],
|
|
`codex_cli_rs/${pinned}`,
|
|
);
|
|
});
|
|
|
|
test("test 7: live-empty GitHub catalog path does not call persist", () => {
|
|
const src = fs.readFileSync(
|
|
path.join(process.cwd(), "src/app/api/providers/[id]/models/route.ts"),
|
|
"utf8",
|
|
);
|
|
// The githubCatalogModels fallback must use buildResponse, not buildApiDiscoveryResponse.
|
|
const idx = src.indexOf("Codex live catalog unavailable — using GitHub model catalog");
|
|
assert.ok(idx > 0);
|
|
const start = src.lastIndexOf("if (githubCatalogModels", idx);
|
|
const end = src.indexOf("if (cachedDiscoveryModels", idx);
|
|
assert.ok(start > 0 && end > start);
|
|
const window = src.slice(start, end);
|
|
assert.match(window, /buildResponse\s*\(/);
|
|
assert.doesNotMatch(window, /buildApiDiscoveryResponse\s*\(/);
|
|
|
|
const liveIdx = src.lastIndexOf("if (liveModels && liveModels.length > 0)");
|
|
assert.ok(liveIdx > 0 && liveIdx < start);
|
|
const liveWindow = src.slice(liveIdx, start);
|
|
assert.match(liveWindow, /buildApiDiscoveryResponse\s*\(/);
|
|
});
|