Files
can1357 df0bb6e31a feat: implemented provider wire codecs and optimized telemetry and parsing
- Added internal protobuf wire codecs, message builders, and protocol definitions for Cursor and Devin providers.
- Deferred loading of OTel SDK and OTLP exporters and added bounded caches to optimize startup and lookup performance.
- Added SQLite-backed parse caching for legacy extension source analysis and streaming file chunk parsing for changelogs.
- Added support for rendering context usage overflow above 100% in the status line component.
2026-08-20 07:54:06 +02:00

1343 lines
50 KiB
TypeScript

import { Database } from "bun:sqlite";
import { describe, expect, it } from "bun:test";
import * as fs from "node:fs/promises";
import * as os from "node:os";
import * as path from "node:path";
import { buildModel } from "@oh-my-pi/pi-catalog/build";
import { isOfficialAnthropicApiUrl } from "@oh-my-pi/pi-catalog/compat/anthropic";
import { buildOpenAICompat, buildOpenAIResponsesCompat } from "@oh-my-pi/pi-catalog/compat/openai";
import { Effort } from "@oh-my-pi/pi-catalog/effort";
import { readModelCache, writeModelCache } from "@oh-my-pi/pi-catalog/model-cache";
import { resolveProviderModels } from "@oh-my-pi/pi-catalog/model-manager";
import { getBundledModel } from "@oh-my-pi/pi-catalog/models";
import { openrouterModelManagerOptions } from "@oh-my-pi/pi-catalog/provider-models/openai-compat";
import type { Api, Model, ModelSpec } from "@oh-my-pi/pi-catalog/types";
function completionsSpec(overrides: Partial<ModelSpec<"openai-completions">> = {}): ModelSpec<"openai-completions"> {
return {
id: "some-model",
name: "Some Model",
api: "openai-completions",
provider: "custom",
baseUrl: "https://api.example.com/v1",
reasoning: false,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 128_000,
maxTokens: 8_192,
...overrides,
};
}
function openrouterSpec(overrides: Partial<ModelSpec<"openrouter">> = {}): ModelSpec<"openrouter"> {
return {
id: "anthropic/claude-sonnet-4",
name: "Claude Sonnet 4",
api: "openrouter",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: true,
input: ["text", "image"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 200_000,
maxTokens: 64_000,
...overrides,
};
}
describe("buildModel", () => {
it("resolves a complete compat record for an openai-completions spec with no compat", () => {
const model = buildModel(completionsSpec());
expect(model.compat).toBeDefined();
expect(typeof model.compat.supportsStore).toBe("boolean");
expect(model.compat.maxTokensField).toBe("max_completion_tokens");
expect(model.compat.thinkingFormat).toBe("openai");
expect(typeof model.compat.isOpenRouterHost).toBe("boolean");
expect(model.compat.isOpenRouterHost).toBe(false);
expect(model.compatConfig).toBeUndefined();
});
it("built models survive a JSON roundtrip, so generator-materialized rows need no rebuild", () => {
// models.ts consumes models.json rows verbatim as complete Models; this
// holds only if buildModel output is pure JSON (no functions, no
// undefined-valued fields that JSON would drop).
const generated = [buildModel(completionsSpec({ reasoning: true })), buildModel(openrouterSpec())];
for (const model of generated) {
expect(JSON.parse(JSON.stringify(model)) as Model<Api>).toEqual(model);
}
});
it("lets sparse overrides win over detection and keeps the verbatim config", () => {
const sparse = { supportsDeveloperRole: true } as const;
const model = buildModel(
completionsSpec({
provider: "groq",
baseUrl: "https://api.groq.com/openai/v1",
compat: sparse,
}),
);
// Detection would say false for a non-OpenAI host; the override wins.
expect(model.compat.supportsDeveloperRole).toBe(true);
// The verbatim sparse object is preserved by reference.
expect(model.compatConfig).toBe(sparse);
});
it("materializes the opencode whenThinking variant without mutating the base view", () => {
const model = buildModel(
completionsSpec({
provider: "opencode-zen",
baseUrl: "https://opencode.ai/zen/v1",
reasoning: true,
}),
);
expect(model.compat.whenThinking).toBeDefined();
expect(model.compat.whenThinking?.requiresReasoningContentForToolCalls).toBe(true);
expect(model.compat.whenThinking?.allowsSyntheticReasoningContentForToolCalls).toBe(false);
// Base compat stays on the thinking-off defaults.
expect(model.compat.requiresReasoningContentForToolCalls).toBe(false);
expect(model.compat.allowsSyntheticReasoningContentForToolCalls).toBe(true);
});
it("leaves whenThinking undefined for non-opencode reasoning specs", () => {
const model = buildModel(completionsSpec({ reasoning: true }));
expect(model.compat.whenThinking).toBeUndefined();
});
it("builds OpenRouter pseudo-API models with shared chat and Responses compat", () => {
const model = buildModel(
openrouterSpec({
compat: { openRouterRouting: { only: ["anthropic"], order: ["anthropic"] } },
}),
);
expect(model.compat).toBeDefined();
expect(model.compat.isOpenRouterHost).toBe(true);
expect(model.compat.thinkingFormat).toBe("openrouter");
expect(model.compat.supportsStrictMode).toBe(true);
expect(model.compat.strictResponsesPairing).toBe(false);
expect(model.compat.openRouterRouting).toEqual({ only: ["anthropic"], order: ["anthropic"] });
});
it("loads bundled OpenRouter models with resolved compat", () => {
const model = getBundledModel<"openrouter">("openrouter", "anthropic/claude-sonnet-4");
expect(model.compat).toBeDefined();
expect(model.compat?.isOpenRouterHost).toBe(true);
expect(model.compat?.supportsStrictMode).toBe(true);
});
it("strips gateway author prefixes and extrinsic tags from display names", () => {
const cases: [string, string][] = [
["Anthropic: Claude Opus 4.6 (Fast) ($$$$)", "Claude Opus 4.6 (Fast)"],
["Claude Opus 4.5 (latest)", "Claude Opus 4.5"],
["Gemini 2.5 Flash (Thinking) (Antigravity)", "Gemini 2.5 Flash (Thinking)"],
["Stealth: Claude Opus 4.6 (20% off)", "Claude Opus 4.6"],
["NousResearch: Hermes 2 Pro (retires Jun 5)", "Hermes 2 Pro"],
["Z.ai: GLM 5", "GLM 5"],
];
for (const [raw, cleaned] of cases) {
expect(buildModel(completionsSpec({ name: raw })).name).toBe(cleaned);
}
});
it("keeps variant tags that map to distinct wire ids", () => {
const keep = [
"Trinity Large Preview (free)",
"Grok 4.1 Fast (Non-Reasoning)",
"GPT-4o (2024-08-06)",
"Claude Haiku 3.5 (EU)",
"Llama-3.3+(3.1v3.3)-70B-Hanami-x1",
];
for (const name of keep) {
expect(buildModel(completionsSpec({ name })).name).toBe(name);
}
});
it("limits inferred GA computer capability to first-party Responses transports", () => {
const common = {
id: "gpt-5.6-terra",
name: "GPT-5.6 Terra",
reasoning: true,
input: ["text", "image"] as Array<"text" | "image">,
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 400_000,
maxTokens: 128_000,
};
const direct = {
...common,
api: "openai-responses" as const,
provider: "openai",
baseUrl: "https://api.openai.com/v1",
} satisfies ModelSpec<"openai-responses">;
expect(buildModel(direct).supportsComputerUse).toBe(true);
expect(buildModel({ ...direct, baseUrl: "https://gateway.example/v1" }).supportsComputerUse).toBe(false);
expect(buildModel({ ...direct, provider: "gpt-proxy" }).supportsComputerUse).toBe(false);
const subscription = {
...common,
api: "openai-codex-responses" as const,
provider: "openai-codex",
baseUrl: "https://chatgpt.com/backend-api",
} satisfies ModelSpec<"openai-codex-responses">;
for (const id of ["gpt-5.3-codex-spark", "gpt-5.6-luna", "gpt-5.6-terra", "gpt-5.6-sol"]) {
expect(buildModel({ ...subscription, id, name: id }).supportsComputerUse).toBe(false);
}
expect(buildModel({ ...subscription, supportsComputerUse: true }).supportsComputerUse).toBe(true);
const azure = {
...common,
api: "azure-openai-responses" as const,
provider: "azure",
baseUrl: "",
} satisfies ModelSpec<"azure-openai-responses">;
expect(buildModel(azure).supportsComputerUse).toBe(true);
expect(buildModel({ ...azure, provider: "azure-openai" }).supportsComputerUse).toBe(true);
expect(buildModel({ ...azure, provider: "custom-azure-proxy" }).supportsComputerUse).toBe(false);
expect(buildModel({ ...azure, baseUrl: "https://gateway.example/openai/v1" }).supportsComputerUse).toBe(false);
});
it("recomputes inferred computer capability when a built model is rerouted while preserving explicit metadata", () => {
const direct = {
id: "gpt-5.4",
name: "GPT-5.4",
api: "openai-responses" as const,
provider: "openai",
baseUrl: "https://api.openai.com/v1",
reasoning: true,
input: ["text", "image"] as Array<"text" | "image">,
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 400_000,
maxTokens: 128_000,
} satisfies ModelSpec<"openai-responses">;
const reroute = (model: Model<"openai-responses">, baseUrl: string) =>
buildModel({ ...model, baseUrl, compat: model.compatConfig } as ModelSpec<"openai-responses">);
expect(reroute(buildModel(direct), "https://gateway.example/v1").supportsComputerUse).toBe(false);
const inferred = buildModel(direct);
expect(
buildModel({
...inferred,
provider: "gpt-proxy",
compat: inferred.compatConfig,
} as ModelSpec<"openai-responses">).supportsComputerUse,
).toBe(false);
expect(
reroute(buildModel({ ...direct, supportsComputerUse: true }), "https://gateway.example/v1")
.supportsComputerUse,
).toBe(true);
expect(reroute(buildModel({ ...direct, supportsComputerUse: false }), direct.baseUrl).supportsComputerUse).toBe(
false,
);
});
});
describe("xAI Responses reasoning-effort suppression", () => {
const grokResponsesSpec = (
id: string,
provider: "xai" | "xai-oauth" = "xai-oauth",
): ModelSpec<"openai-responses"> => ({
id,
name: id,
api: "openai-responses",
provider,
baseUrl: "https://api.x.ai/v1",
reasoning: true,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 512_000,
maxTokens: 512_000,
});
it("omits the effort dial for a custom grok-build spec (off the allowlist)", () => {
const compat = buildOpenAIResponsesCompat(grokResponsesSpec("grok-build"));
expect(compat.supportsReasoningEffort).toBe(false);
expect(compat.omitReasoningEffort).toBe(true);
expect(buildModel(grokResponsesSpec("grok-build")).thinking).toBeUndefined();
});
it("keeps the effort dial for a custom grok-4.3 spec (on the allowlist)", () => {
expect(buildOpenAIResponsesCompat(grokResponsesSpec("grok-4.3")).supportsReasoningEffort).toBe(true);
});
it("applies the same Responses dialect to paid xai and xai-oauth", () => {
const paid = buildOpenAIResponsesCompat(grokResponsesSpec("grok-4.3", "xai"));
const oauth = buildOpenAIResponsesCompat(grokResponsesSpec("grok-4.3", "xai-oauth"));
expect(paid.promptCacheSessionHeader).toBe("x-grok-conv-id");
expect(oauth.promptCacheSessionHeader).toBe("x-grok-conv-id");
expect(paid.includeEncryptedReasoning).toBe(true);
expect(oauth.includeEncryptedReasoning).toBe(true);
expect(paid.filterReasoningHistory).toBe(false);
expect(oauth.filterReasoningHistory).toBe(false);
expect(paid.supportsImageDetailOriginal).toBe(false);
expect(oauth.supportsImageDetailOriginal).toBe(false);
expect(paid.supportsReasoningEffort).toBe(true);
expect(oauth.supportsReasoningEffort).toBe(true);
expect(paid.reasoningEffortMap).toEqual({ minimal: "low", xhigh: "high", max: "high" });
expect(oauth.reasoningEffortMap).toEqual({ minimal: "low", xhigh: "high", max: "high" });
expect(
buildOpenAIResponsesCompat(grokResponsesSpec("grok-4.20-multi-agent-0309", "xai")).reasoningEffortMap,
).toEqual({ minimal: "low" });
expect(paid.supportsPenaltyAndStopParams).toBe(false);
expect(oauth.supportsPenaltyAndStopParams).toBe(false);
expect(paid.supportsReasoningSummary).toBe(false);
expect(oauth.supportsReasoningSummary).toBe(false);
});
it("suppresses penalty params on every first-party xAI Responses model", () => {
const reasoning = buildOpenAIResponsesCompat(grokResponsesSpec("grok-4.5", "xai"));
const nonReasoning = buildOpenAIResponsesCompat({
...grokResponsesSpec("grok-2", "xai"),
reasoning: false,
});
expect(reasoning.supportsPenaltyAndStopParams).toBe(false);
expect(nonReasoning.supportsPenaltyAndStopParams).toBe(false);
});
it("omits effort for paid xai models off the Grok allowlist", () => {
const compat = buildOpenAIResponsesCompat(grokResponsesSpec("grok-code-fast-1", "xai"));
expect(compat.supportsReasoningEffort).toBe(false);
expect(compat.omitReasoningEffort).toBe(true);
expect(buildModel(grokResponsesSpec("grok-code-fast-1", "xai")).thinking).toBeUndefined();
});
it("exposes the grok-4.6 low..xhigh ladder and rejects max", () => {
const model = buildModel(grokResponsesSpec("grok-4.6"));
expect(model.compat.supportsReasoningEffort).toBe(true);
expect(model.compat.omitReasoningEffort).toBe(false);
expect(model.thinking?.efforts).toEqual([Effort.Minimal, Effort.Low, Effort.Medium, Effort.High, Effort.XHigh]);
expect(model.thinking?.efforts).not.toContain(Effort.Max);
});
it("lets the grok-4.6 allowlist beat a stale cached omitReasoningEffort flag", () => {
const model = buildModel({
...grokResponsesSpec("grok-4.6"),
compat: { omitReasoningEffort: true },
});
expect(model.compat.supportsReasoningEffort).toBe(true);
expect(model.compat.omitReasoningEffort).toBe(false);
expect(model.thinking?.efforts).toContain(Effort.XHigh);
expect(model.thinking?.efforts).not.toContain(Effort.Max);
});
it("lets an explicit compat.supportsReasoningEffort override the allowlist default", () => {
const compat = buildOpenAIResponsesCompat({
...grokResponsesSpec("grok-build"),
compat: { supportsReasoningEffort: true },
});
expect(compat.supportsReasoningEffort).toBe(true);
});
it("does not suppress effort for a non-xAI provider with a grok-like id", () => {
const compat = buildOpenAIResponsesCompat({
...grokResponsesSpec("grok-build"),
provider: "openai",
baseUrl: "https://api.openai.com/v1",
});
expect(compat.supportsReasoningEffort).toBe(true);
});
});
describe("openai-completions wire-quirk compat detection", () => {
it("derives wireModelIdMode from provider/host", () => {
expect(buildOpenAICompat(completionsSpec({ provider: "firepass" })).wireModelIdMode).toBe("firepass");
expect(
buildOpenAICompat(completionsSpec({ provider: "fireworks", baseUrl: "https://api.fireworks.ai/inference/v1" }))
.wireModelIdMode,
).toBe("fireworks");
// Fireworks "Fast" variants route through the router namespace (like Fire Pass).
expect(
buildOpenAICompat(
completionsSpec({
provider: "fireworks",
id: "kimi-k2.6-fast",
baseUrl: "https://api.fireworks.ai/inference/v1",
}),
).wireModelIdMode,
).toBe("firepass");
expect(
buildOpenAICompat(completionsSpec({ provider: "openrouter", baseUrl: "https://openrouter.ai/api/v1" }))
.wireModelIdMode,
).toBe("openrouter");
expect(buildOpenAICompat(completionsSpec()).wireModelIdMode).toBe("raw");
});
it("strips DeepSeek special tokens only for deepseek ids on nvidia/deepseek providers", () => {
expect(
buildOpenAICompat(
completionsSpec({
provider: "nvidia",
id: "deepseek-ai/deepseek-v3.1",
baseUrl: "https://integrate.api.nvidia.com/v1",
}),
).stripDeepseekSpecialTokens,
).toBe(true);
expect(
buildOpenAICompat(
completionsSpec({ provider: "deepseek", id: "deepseek-chat", baseUrl: "https://api.deepseek.com/v1" }),
).stripDeepseekSpecialTokens,
).toBe(true);
// DeepSeek id behind another host must NOT strip (only nvidia/deepseek hosts emit the raw tokens).
expect(
buildOpenAICompat(
completionsSpec({
provider: "openrouter",
id: "deepseek/deepseek-v3.1",
baseUrl: "https://openrouter.ai/api/v1",
}),
).stripDeepseekSpecialTokens,
).toBe(false);
// Non-deepseek id on nvidia must NOT strip.
expect(
buildOpenAICompat(
completionsSpec({
provider: "nvidia",
id: "meta/llama-3.1",
baseUrl: "https://integrate.api.nvidia.com/v1",
}),
).stripDeepseekSpecialTokens,
).toBe(false);
});
it("downgrades forced tool choice only for DeepSeek reasoning models on OpenCode gateways", () => {
const deepseekReasoning = {
id: "deepseek-v4-flash",
name: "DeepSeek V4 Flash",
reasoning: true,
} as const;
expect(
buildOpenAICompat(
completionsSpec({
...deepseekReasoning,
provider: "opencode-zen",
baseUrl: "https://opencode.ai/zen/v1",
}),
).supportsForcedToolChoice,
).toBe(false);
expect(
buildOpenAICompat(
completionsSpec({
...deepseekReasoning,
provider: "custom",
baseUrl: "https://opencode.ai/zen/go/v1",
}),
).supportsForcedToolChoice,
).toBe(false);
expect(
buildOpenAICompat(
completionsSpec({
...deepseekReasoning,
provider: "nvidia",
baseUrl: "https://integrate.api.nvidia.com/v1",
}),
).supportsForcedToolChoice,
).toBe(true);
expect(
buildOpenAICompat(
completionsSpec({
...deepseekReasoning,
provider: "opencode-zen",
baseUrl: "https://opencode.ai/zen/v1",
reasoning: false,
}),
).supportsForcedToolChoice,
).toBe(true);
});
it("requires a synthetic assistant bridge after tool results only for Mistral hosts", () => {
// Mistral/Devstral reject a user message directly after a tool result; the chat
// builder bridges it with a synthetic assistant turn, keyed on the Mistral host.
expect(
buildOpenAICompat(
completionsSpec({ provider: "mistral", id: "devstral-latest", baseUrl: "https://api.mistral.ai/v1" }),
).requiresAssistantAfterToolResult,
).toBe(true);
// URL-only match (custom provider fronting Mistral).
expect(
buildOpenAICompat(
completionsSpec({
provider: "custom",
id: "mistral-large",
baseUrl: "https://proxy.example/mistral.ai/v1",
}),
).requiresAssistantAfterToolResult,
).toBe(true);
// Non-Mistral hosts must not insert the bridge.
expect(buildOpenAICompat(completionsSpec()).requiresAssistantAfterToolResult).toBe(false);
expect(
buildOpenAICompat(completionsSpec({ provider: "openai", id: "gpt-5", baseUrl: "https://api.openai.com/v1" }))
.requiresAssistantAfterToolResult,
).toBe(false);
});
it("flags cumulative reasoning deltas for MiniMax provider or id", () => {
expect(buildOpenAICompat(completionsSpec({ provider: "minimax" })).reasoningDeltasMayBeCumulative).toBe(true);
expect(buildOpenAICompat(completionsSpec({ id: "MiniMax-M2" })).reasoningDeltasMayBeCumulative).toBe(true);
expect(buildOpenAICompat(completionsSpec()).reasoningDeltasMayBeCumulative).toBe(false);
});
it("extends the reasoning stream idle floor to Kimi K2.6 and K2.7 Code, not other reasoning models", () => {
const kimiOverrides = {
provider: "moonshot",
baseUrl: "https://api.moonshot.ai/v1",
reasoning: true,
} as const;
expect(buildOpenAICompat(completionsSpec({ ...kimiOverrides, id: "kimi-k2.6" })).streamIdleTimeoutMs).toBe(
300_000,
);
expect(buildOpenAICompat(completionsSpec({ ...kimiOverrides, id: "kimi-k2.7-code" })).streamIdleTimeoutMs).toBe(
300_000,
);
expect(
buildOpenAICompat(completionsSpec({ ...kimiOverrides, id: "kimi-k2.7-code-highspeed" })).streamIdleTimeoutMs,
).toBe(300_000);
// K2.7 Code on non-native OpenAI-compatible hosts keeps their default.
expect(
buildOpenAICompat(completionsSpec({ id: "kimi-k2.7-code", reasoning: true })).streamIdleTimeoutMs,
).toBeUndefined();
// A non-Kimi reasoning model on a generic host keeps the runtime default.
expect(
buildOpenAICompat(completionsSpec({ id: "some-reasoner", reasoning: true })).streamIdleTimeoutMs,
).toBeUndefined();
});
it("maps the remaining provider-keyed wire quirks", () => {
expect(buildOpenAICompat(completionsSpec({ provider: "ollama" })).emptyLengthFinishIsContextError).toBe(true);
expect(buildOpenAICompat(completionsSpec()).emptyLengthFinishIsContextError).toBe(false);
expect(
buildOpenAICompat(completionsSpec({ provider: "openai", baseUrl: "https://api.openai.com/v1" }))
.usesOpenAIToolCallIdLimit,
).toBe(true);
expect(buildOpenAICompat(completionsSpec()).usesOpenAIToolCallIdLimit).toBe(false);
expect(
buildOpenAICompat(completionsSpec({ provider: "fireworks", baseUrl: "https://api.fireworks.ai/inference/v1" }))
.dropThinkingWhenReasoningEffort,
).toBe(true);
expect(buildOpenAICompat(completionsSpec()).dropThinkingWhenReasoningEffort).toBe(false);
});
it("floors the stream timeout for a loopback litellm proxy without enabling reasoning replay (#4786)", () => {
// A litellm proxy on a loopback baseUrl fronts a local llama-server whose
// prefill can exceed the 100s default first-event budget on large prompts.
// The proxy carve-out (which keeps `replayReasoningContent` off so the
// field is never forwarded to an unrelated cloud upstream) must NOT also
// strip the widened stream-timeout floor, or the turn aborts and
// retry-loops during a slow reprocess.
const loopback = buildOpenAICompat(
completionsSpec({ provider: "litellm", id: "qwen3", baseUrl: "http://127.0.0.1:4000/v1" }),
);
expect(loopback.streamIdleTimeoutMs).toBe(300_000);
expect(loopback.replayReasoningContent).toBe(false);
// A litellm proxy on a remote baseUrl gets neither: no local upstream to
// wait on, and replay would risk a 400 on the cloud upstream.
const remote = buildOpenAICompat(
completionsSpec({ provider: "litellm", id: "qwen3", baseUrl: "https://litellm.example.com/v1" }),
);
expect(remote.streamIdleTimeoutMs).toBeUndefined();
expect(remote.replayReasoningContent).toBe(false);
// A first-party local backend (llama.cpp) still gets both the floor and
// the reasoning replay it needs for KV-cache reuse.
const native = buildOpenAICompat(
completionsSpec({ provider: "llama.cpp", id: "qwen3", baseUrl: "http://127.0.0.1:8080/v1" }),
);
expect(native.streamIdleTimeoutMs).toBe(300_000);
expect(native.replayReasoningContent).toBe(true);
});
it("disables the leaked-markup healer for the official OpenAI endpoint only", () => {
// Official OpenAI returns structured reasoning and never leaks fences, so
// the provider-local healer stays off; every other OpenAI-compatible host
// keeps the default "thinking" healer, and Kimi/DSML keep their grammars.
expect(
buildOpenAICompat(completionsSpec({ provider: "openai", baseUrl: "https://api.openai.com/v1" }))
.streamMarkupHealingPattern,
).toBeUndefined();
expect(
buildOpenAICompat(completionsSpec({ provider: "openrouter", baseUrl: "https://openrouter.ai/api/v1" }))
.streamMarkupHealingPattern,
).toBe("thinking");
// A lookalike host under the openai provider id is NOT the official endpoint.
expect(
buildOpenAICompat(completionsSpec({ provider: "openai", baseUrl: "https://api.openai.com.evil/v1" }))
.streamMarkupHealingPattern,
).toBe("thinking");
expect(
buildOpenAICompat(
completionsSpec({ provider: "moonshot", id: "kimi-k2", baseUrl: "https://api.moonshot.ai/v1" }),
).streamMarkupHealingPattern,
).toBe("kimi");
});
it("derives Responses obfuscation opt-out and wire mode per surface", () => {
expect(
buildOpenAIResponsesCompat({
id: "gpt-5",
provider: "openai",
name: "GPT 5",
baseUrl: "https://api.openai.com/v1",
}).supportsObfuscationOptOut,
).toBe(true);
// Azure mirrors the schema but is NOT the OpenAI host: no obfuscation opt-out.
expect(
buildOpenAIResponsesCompat({ id: "gpt-5", provider: "azure", name: "gpt-5", baseUrl: "" })
.supportsObfuscationOptOut,
).toBe(false);
const openrouterResponses = buildOpenAIResponsesCompat({
id: "anthropic/claude-sonnet-4",
provider: "openrouter",
name: "Claude Sonnet 4",
baseUrl: "https://openrouter.ai/api/v1",
});
expect(openrouterResponses.supportsObfuscationOptOut).toBe(false);
expect(openrouterResponses.wireModelIdMode).toBe("openrouter");
});
});
describe("OpenAI explicit prompt-cache breakpoint compat", () => {
it("enables the 30-minute breakpoint contract for GPT-5.6+ on the official API", () => {
const completions = buildOpenAICompat(
completionsSpec({ id: "gpt-5.6", provider: "openai", baseUrl: "https://api.openai.com/v1" }),
);
const responses = buildOpenAIResponsesCompat({
id: "gpt-5.6-mini",
provider: "openai",
name: "GPT 5.6 Mini",
baseUrl: "https://api.openai.com/v1",
});
expect(completions.supportsPromptCacheBreakpoints).toBe(true);
expect(completions.promptCacheBreakpointTtl).toBe("30m");
expect(responses.supportsPromptCacheBreakpoints).toBe(true);
expect(responses.promptCacheBreakpointTtl).toBe("30m");
expect(
buildOpenAICompat(
completionsSpec({ id: "gpt-5.6-preview", provider: "openai", baseUrl: "https://api.openai.com/v1" }),
).supportsPromptCacheBreakpoints,
).toBe(true);
expect(
buildOpenAICompat(completionsSpec({ id: "gpt-5.7", provider: "openai", baseUrl: "https://api.openai.com/v1" }))
.supportsPromptCacheBreakpoints,
).toBe(true);
expect(
buildOpenAIResponsesCompat({
id: "gpt-6.1-mini",
provider: "openai",
name: "GPT 6.1 Mini",
baseUrl: "https://api.openai.com/v1",
}).supportsPromptCacheBreakpoints,
).toBe(true);
expect(
buildOpenAICompat(completionsSpec({ id: "gpt-5.5", provider: "openai", baseUrl: "https://api.openai.com/v1" }))
.supportsPromptCacheBreakpoints,
).toBe(false);
expect(
buildOpenAIResponsesCompat({
id: "gpt-5.6",
provider: "openrouter",
name: "GPT 5.6 through OpenRouter",
baseUrl: "https://openrouter.ai/api/v1",
}).supportsPromptCacheBreakpoints,
).toBe(false);
expect(
buildOpenAIResponsesCompat({
id: "gpt-4.1",
provider: "openai",
name: "GPT 4.1",
baseUrl: "https://api.openai.com/v1",
}).supportsPromptCacheBreakpoints,
).toBe(false);
expect(
buildOpenAIResponsesCompat({
id: "gpt-5.6",
provider: "openai",
name: "GPT 5.6",
baseUrl: "https://api.openai.com.evil/v1",
}).supportsPromptCacheBreakpoints,
).toBe(false);
});
it("keeps custom endpoint support opt-in", () => {
const compat = buildOpenAICompat(
completionsSpec({
id: "gpt-5.6",
compat: { supportsPromptCacheBreakpoints: true, promptCacheBreakpointTtl: "30m" },
}),
);
expect(compat.supportsPromptCacheBreakpoints).toBe(true);
expect(compat.promptCacheBreakpointTtl).toBe("30m");
});
});
describe("OpenRouter model discovery", () => {
it("keeps refreshed OpenRouter models on the OpenRouter pseudo API", async () => {
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "pi-catalog-openrouter-refresh-"));
const dbPath = path.join(tempDir, "models.db");
const routing = { only: ["anthropic"], order: ["anthropic"] };
const staticModel = openrouterSpec({ compat: { openRouterRouting: routing } });
const options = openrouterModelManagerOptions({
fetch: async () =>
new Response(
JSON.stringify({
data: [
{
id: staticModel.id,
name: "Anthropic: Claude Sonnet 4",
supported_parameters: ["tools", "tool_choice", "reasoning"],
architecture: { modality: "text+image" },
pricing: {
prompt: "0.000003",
completion: "0.000015",
input_cache_read: "0.0000003",
input_cache_write: "0.00000375",
},
top_provider: { max_completion_tokens: 32_000 },
context_length: 180_000,
},
],
}),
{ status: 200, headers: { "content-type": "application/json" } },
),
});
try {
const dynamicModels = await options.fetchDynamicModels?.();
expect(dynamicModels?.[0]?.api).toBe("openrouter");
const online = await resolveProviderModels<"openrouter">(
{
...options,
staticModels: [staticModel],
cacheDbPath: dbPath,
},
"online",
);
const model = online.models.find(candidate => candidate.id === staticModel.id);
expect(model?.api).toBe("openrouter");
expect(model?.provider).toBe("openrouter");
expect(model?.compat.isOpenRouterHost).toBe(true);
expect(model?.compat.openRouterRouting).toEqual(routing);
expect(model?.input).toEqual(["text", "image"]);
} finally {
await fs.rm(tempDir, { recursive: true, force: true });
}
});
it("maps OpenRouter's advertised reasoning effort ladder and default", async () => {
const options = openrouterModelManagerOptions({
fetch: async () =>
Response.json({
data: [
{
id: "deepseek/deepseek-v4-flash-0731",
name: "DeepSeek V4 Flash 0731",
supported_parameters: ["tools", "reasoning", "reasoning_effort"],
reasoning: {
supported_efforts: ["max", "high", "low"],
default_effort: "high",
},
},
],
}),
});
const specs = await options.fetchDynamicModels?.();
const spec = specs?.find(model => model.id === "deepseek/deepseek-v4-flash-0731");
if (!spec) throw new Error("Expected discovered DeepSeek V4 Flash 0731 model");
expect(buildModel(spec).thinking).toEqual({
mode: "effort",
efforts: [Effort.Low, Effort.High, Effort.Max],
defaultLevel: Effort.High,
});
});
it("ignores legacy OpenRouter chat-completions cache rows", async () => {
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "pi-catalog-openrouter-legacy-cache-"));
const dbPath = path.join(tempDir, "models.db");
const legacyModel = buildModel(
completionsSpec({
id: "anthropic/claude-sonnet-4",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: true,
}),
);
try {
writeModelCache("openrouter", Date.now(), [legacyModel], true, "", dbPath);
const offline = await resolveProviderModels<"openrouter">(
{
...openrouterModelManagerOptions(),
staticModels: [],
cacheDbPath: dbPath,
},
"offline",
);
expect(offline.models).toEqual([]);
} finally {
await fs.rm(tempDir, { recursive: true, force: true });
}
});
});
describe("model cache spec round trip", () => {
it("persists sparse specs and rebuilds resolved models on cache reads", async () => {
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "pi-catalog-model-cache-"));
const dbPath = path.join(tempDir, "models.db");
const sparse = { supportsDeveloperRole: true } as const;
const spec = completionsSpec({ provider: "spec-cache-test", compat: sparse });
try {
const online = await resolveProviderModels<"openai-completions">(
{
providerId: "spec-cache-test",
staticModels: [],
cacheDbPath: dbPath,
fetchDynamicModels: async () => [spec],
},
"online",
);
expect(online.models[0]?.compat.supportsDeveloperRole).toBe(true);
// The persisted row carries the sparse spec, never the resolved record.
const db = new Database(dbPath, { readonly: true });
const row = db
.query<{ models: string }, [string]>("SELECT models FROM model_cache WHERE provider_id = ?")
.get("spec-cache-test");
db.close();
expect(row).toBeDefined();
const persisted = JSON.parse(row?.models ?? "[]") as ModelSpec<"openai-completions">[];
expect(persisted[0]?.compat).toEqual(sparse);
expect(persisted[0]).not.toHaveProperty("compatConfig");
expect(persisted[0]?.compat).not.toHaveProperty("isOpenRouterHost");
// Offline reads rebuild the row into a fully-resolved model.
const offline = await resolveProviderModels<"openai-completions">(
{
providerId: "spec-cache-test",
staticModels: [],
cacheDbPath: dbPath,
},
"offline",
);
const model = offline.models.find(candidate => candidate.id === spec.id);
expect(model?.compat.supportsDeveloperRole).toBe(true);
expect(model?.compat.isOpenRouterHost).toBe(false);
expect(model?.compatConfig).toEqual(sparse);
} finally {
await fs.rm(tempDir, { recursive: true, force: true });
}
});
it("preserves static long-context pricing through dynamic refresh and cache restore", async () => {
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "pi-catalog-tiered-cost-"));
const dbPath = path.join(tempDir, "models.db");
const staticModel = completionsSpec({
id: "tiered-model",
provider: "tiered-cost-test",
cost: {
input: 1,
output: 2,
cacheRead: 0.1,
cacheWrite: 1.25,
longContext: {
inputThreshold: 272_000,
input: 2,
output: 3,
cacheRead: 0.2,
cacheWrite: 2.5,
},
},
});
const dynamicModel = completionsSpec({
...staticModel,
cost: { input: 3, output: 4, cacheRead: 0.3, cacheWrite: 3.75 },
});
const options = {
providerId: "tiered-cost-test",
staticModels: [staticModel],
cacheDbPath: dbPath,
};
try {
const online = await resolveProviderModels<"openai-completions">(
{ ...options, fetchDynamicModels: async () => [dynamicModel] },
"online",
);
expect(online.models[0]?.cost).toEqual({
...dynamicModel.cost,
longContext: staticModel.cost.longContext,
});
const offline = await resolveProviderModels<"openai-completions">(options, "offline");
expect(offline.models[0]?.cost.longContext).toEqual(staticModel.cost.longContext);
} finally {
await fs.rm(tempDir, { recursive: true, force: true });
}
});
it("invalidates schema-v10 rows that predate computer-use capability provenance", async () => {
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "pi-catalog-legacy-computer-cache-"));
const dbPath = path.join(tempDir, "models.db");
const model = buildModel({
id: "legacy-inferred-computer",
name: "Legacy inferred computer",
api: "openai-responses",
provider: "openai",
baseUrl: "https://api.openai.com/v1",
reasoning: true,
input: ["text", "image"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 400_000,
maxTokens: 128_000,
} satisfies ModelSpec<"openai-responses">);
try {
writeModelCache("legacy-computer-cache-test", Date.now(), [model], true, "", dbPath);
const db = new Database(dbPath);
db.run("UPDATE model_cache SET version = 10 WHERE provider_id = ?", ["legacy-computer-cache-test"]);
db.close();
expect(readModelCache("legacy-computer-cache-test", Infinity, Date.now, dbPath)).toBeNull();
const verified = new Database(dbPath, { readonly: true });
const row = verified.query<{ count: number }, []>("SELECT COUNT(*) AS count FROM model_cache").get();
verified.close();
expect(row?.count).toBe(0);
} finally {
await fs.rm(tempDir, { recursive: true, force: true });
}
});
it("preserves computer-use provenance across cache restarts and endpoint reroutes", async () => {
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "pi-catalog-computer-use-cache-"));
const dbPath = path.join(tempDir, "models.db");
const common = {
name: "GPT-5.4",
requestModelId: "gpt-5.4",
api: "openai-responses" as const,
reasoning: true,
input: ["text", "image"] as Array<"text" | "image">,
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 400_000,
maxTokens: 128_000,
};
const direct = {
...common,
id: "inferred-direct",
provider: "openai",
baseUrl: "https://api.openai.com/v1",
} satisfies ModelSpec<"openai-responses">;
const proxy = {
...common,
id: "inferred-proxy",
provider: "gpt-proxy",
baseUrl: "https://gateway.example/v1",
} satisfies ModelSpec<"openai-responses">;
const explicitTrue = { ...direct, id: "explicit-true", supportsComputerUse: true };
const explicitFalse = { ...proxy, id: "explicit-false", supportsComputerUse: false };
const reroute = (model: Model<"openai-responses">, provider: string, baseUrl: string) =>
buildModel({ ...model, provider, baseUrl, compat: model.compatConfig } as ModelSpec<"openai-responses">);
try {
await resolveProviderModels<"openai-responses">(
{
providerId: "computer-use-cache-test",
staticModels: [],
cacheDbPath: dbPath,
fetchDynamicModels: async () => [direct, proxy, explicitTrue, explicitFalse],
},
"online",
);
const db = new Database(dbPath, { readonly: true });
const row = db
.query<{ models: string }, [string]>("SELECT models FROM model_cache WHERE provider_id = ?")
.get("computer-use-cache-test");
db.close();
const persisted = JSON.parse(row?.models ?? "[]") as Array<Record<string, unknown>>;
expect(persisted.find(model => model.id === direct.id)).not.toHaveProperty("supportsComputerUse");
expect(persisted.find(model => model.id === proxy.id)).not.toHaveProperty("supportsComputerUse");
expect(persisted.find(model => model.id === explicitTrue.id)?.supportsComputerUse).toBe(true);
expect(persisted.find(model => model.id === explicitFalse.id)?.supportsComputerUse).toBe(false);
const offline = await resolveProviderModels<"openai-responses">(
{ providerId: "computer-use-cache-test", staticModels: [], cacheDbPath: dbPath },
"offline",
);
const byId = new Map(offline.models.map(model => [model.id, model]));
const cachedDirect = byId.get(direct.id);
const cachedProxy = byId.get(proxy.id);
const cachedExplicitTrue = byId.get(explicitTrue.id);
const cachedExplicitFalse = byId.get(explicitFalse.id);
expect(cachedDirect?.supportsComputerUseConfig).toBeUndefined();
expect(cachedProxy?.supportsComputerUseConfig).toBeUndefined();
expect(reroute(cachedDirect!, "gpt-proxy", proxy.baseUrl).supportsComputerUse).toBe(false);
expect(reroute(cachedProxy!, "openai", direct.baseUrl).supportsComputerUse).toBe(true);
expect(cachedExplicitTrue?.supportsComputerUseConfig).toBe(true);
expect(cachedExplicitFalse?.supportsComputerUseConfig).toBe(false);
expect(reroute(cachedExplicitTrue!, "gpt-proxy", proxy.baseUrl).supportsComputerUse).toBe(true);
expect(reroute(cachedExplicitFalse!, "openai", direct.baseUrl).supportsComputerUse).toBe(false);
} finally {
await fs.rm(tempDir, { recursive: true, force: true });
}
});
it("uses current static limits for same-id cache rows when the static fingerprint changed", async () => {
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "pi-catalog-static-fingerprint-"));
const dbPath = path.join(tempDir, "models.db");
const staleSameId = buildModel(
completionsSpec({
id: "catalog-updated-model",
name: "Catalog Updated Model (cached)",
provider: "spec-cache-test",
contextWindow: 64_000,
maxTokens: 4_000,
}),
);
const cachedOnly = buildModel(
completionsSpec({
id: "cache-only-model",
name: "Cache Only Model",
provider: "spec-cache-test",
contextWindow: 96_000,
maxTokens: 6_000,
}),
);
const updatedStatic = completionsSpec({
id: staleSameId.id,
name: "Catalog Updated Model",
provider: "spec-cache-test",
contextWindow: 256_000,
maxTokens: 32_000,
});
try {
writeModelCache(
"spec-cache-test",
Date.now(),
[staleSameId, cachedOnly],
true,
"merge-v3:stale-static-catalog",
dbPath,
);
const offline = await resolveProviderModels<"openai-completions">(
{
providerId: "spec-cache-test",
staticModels: [updatedStatic],
cacheDbPath: dbPath,
},
"offline",
);
const sameId = offline.models.find(candidate => candidate.id === updatedStatic.id);
expect(sameId?.contextWindow).toBe(256_000);
expect(sameId?.maxTokens).toBe(32_000);
const cacheOnly = offline.models.find(candidate => candidate.id === cachedOnly.id);
expect(cacheOnly?.contextWindow).toBe(96_000);
expect(cacheOnly?.maxTokens).toBe(6_000);
} finally {
await fs.rm(tempDir, { recursive: true, force: true });
}
});
it("retries an empty discovery result after the short interval and caches recovery", async () => {
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "pi-catalog-empty-discovery-"));
const dbPath = path.join(tempDir, "models.db");
const recoveredModel = completionsSpec({ id: "recovered-model", provider: "empty-discovery-test" });
let discoveredModels: readonly ModelSpec<"openai-completions">[] = [];
let fetches = 0;
let currentTime = 1_000_000;
const options = {
providerId: "empty-discovery-test",
staticModels: [],
dynamicModelsAuthoritative: true,
cacheDbPath: dbPath,
now: () => currentTime,
fetchDynamicModels: async () => {
fetches++;
return discoveredModels;
},
};
try {
const empty = await resolveProviderModels(options, "online");
expect(empty.models).toEqual([]);
// Authoritative for the cycle (drives downstream pruning) yet not pinned
// into the cache as authoritative (keeps the short retry interval).
expect(empty.stale).toBe(false);
expect(fetches).toBe(1);
const db = new Database(dbPath, { readonly: true });
const row = db
.query<{ authoritative: number }, [string]>("SELECT authoritative FROM model_cache WHERE provider_id = ?")
.get(options.providerId);
db.close();
expect(row?.authoritative).toBe(0);
discoveredModels = [recoveredModel];
currentTime += 5 * 60 * 1_000 - 1;
const beforeRetry = await resolveProviderModels(options, "online-if-uncached");
expect(beforeRetry.models).toEqual([]);
expect(fetches).toBe(1);
currentTime++;
const recovered = await resolveProviderModels(options, "online-if-uncached");
expect(recovered.models.map(model => model.id)).toEqual([recoveredModel.id]);
expect(recovered.stale).toBe(false);
expect(fetches).toBe(2);
currentTime++;
const cached = await resolveProviderModels(options, "online-if-uncached");
expect(cached.models.map(model => model.id)).toEqual([recoveredModel.id]);
expect(cached.stale).toBe(false);
expect(fetches).toBe(2);
} finally {
await fs.rm(tempDir, { recursive: true, force: true });
}
});
it("reports an authoritative catalog emptying as non-stale so removed models prune", async () => {
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "pi-catalog-empty-transition-"));
const dbPath = path.join(tempDir, "models.db");
const model = completionsSpec({ id: "going-away", provider: "empty-transition-test" });
let discoveredModels: readonly ModelSpec<"openai-completions">[] = [model];
const options = {
providerId: "empty-transition-test",
staticModels: [],
dynamicModelsAuthoritative: true,
cacheDbPath: dbPath,
fetchDynamicModels: async () => discoveredModels,
};
try {
const populated = await resolveProviderModels(options, "online");
expect(populated.models.map(candidate => candidate.id)).toEqual([model.id]);
expect(populated.stale).toBe(false);
discoveredModels = [];
const emptied = await resolveProviderModels(options, "online");
expect(emptied.models).toEqual([]);
// The successful empty fetch must stay authoritative so ModelRegistry
// prunes the removed model instead of leaving it selectable forever.
expect(emptied.stale).toBe(false);
const db = new Database(dbPath, { readonly: true });
const row = db
.query<{ authoritative: number }, [string]>("SELECT authoritative FROM model_cache WHERE provider_id = ?")
.get(options.providerId);
db.close();
expect(row?.authoritative).toBe(0);
} finally {
await fs.rm(tempDir, { recursive: true, force: true });
}
});
it("restores static model headers on fresh cache reads", async () => {
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "pi-catalog-static-headers-"));
const dbPath = path.join(tempDir, "models.db");
const staticModel = completionsSpec({
id: "header-static-model",
provider: "header-cache-test",
headers: { "X-Project-Id": "project-42" },
});
let fetches = 0;
const options = {
providerId: "header-cache-test",
staticModels: [staticModel],
cacheDbPath: dbPath,
fetchDynamicModels: async () => {
fetches++;
return [];
},
};
try {
const online = await resolveProviderModels(options, "online");
expect(online.models[0]?.headers).toEqual({ "X-Project-Id": "project-42" });
expect(fetches).toBe(1);
const offline = await resolveProviderModels(options, "offline");
expect(offline.models[0]?.headers).toEqual({ "X-Project-Id": "project-42" });
expect(fetches).toBe(1);
const fresh = await resolveProviderModels(options, "online-if-uncached");
expect(fresh.models[0]?.headers).toEqual({ "X-Project-Id": "project-42" });
expect(fetches).toBe(1);
} finally {
await fs.rm(tempDir, { recursive: true, force: true });
}
});
it("refetches dynamic-only models whose headers cannot be restored", async () => {
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "pi-catalog-dynamic-headers-"));
const dbPath = path.join(tempDir, "models.db");
const dynamicModel = completionsSpec({
id: "header-dynamic-model",
provider: "header-cache-test",
headers: { "X-Required-Route": "route-42" },
});
let fetches = 0;
const options = {
providerId: "header-cache-test",
staticModels: [],
dynamicModelsAuthoritative: true,
cacheDbPath: dbPath,
fetchDynamicModels: async () => {
fetches++;
return [dynamicModel];
},
};
try {
const online = await resolveProviderModels(options, "online");
expect(online.models[0]?.headers).toEqual({ "X-Required-Route": "route-42" });
expect(fetches).toBe(1);
const fresh = await resolveProviderModels(options, "online-if-uncached");
expect(fresh.models[0]?.headers).toEqual({ "X-Required-Route": "route-42" });
expect(fetches).toBe(2);
const offline = await resolveProviderModels(options, "offline");
expect(offline.models).toEqual([]);
expect(offline.stale).toBe(true);
expect(fetches).toBe(2);
} finally {
await fs.rm(tempDir, { recursive: true, force: true });
}
});
it("keeps a synthesized request-model variant across an offline restart", async () => {
// Regression for #6037/#6284: Copilot `-1m` long-context variants are
// synthesized dynamically with transport headers and a `requestModelId`
// pointing at a same-provider base. Their headers are omitted from the
// cache but recoverable from the base's static headers, so they must NOT
// be flagged unrestorable and dropped on the next offline read.
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "pi-catalog-request-model-variant-"));
const dbPath = path.join(tempDir, "models.db");
const headers = { "X-GitHub-Api-Version": "2026-06-01" };
const base = completionsSpec({ id: "sol", provider: "variant-cache-test", headers });
const variant = completionsSpec({
id: "sol-1m",
provider: "variant-cache-test",
requestModelId: "sol",
headers,
contextWindow: 1_000_000,
});
const options = {
providerId: "variant-cache-test",
staticModels: [base],
cacheDbPath: dbPath,
};
try {
const online = await resolveProviderModels<"openai-completions">(
{ ...options, fetchDynamicModels: async () => [base, variant] },
"online",
);
expect(online.models.find(candidate => candidate.id === "sol-1m")).toBeDefined();
const offline = await resolveProviderModels<"openai-completions">(
{ ...options, fetchDynamicModels: async () => null },
"offline",
);
const restored = offline.models.find(candidate => candidate.id === "sol-1m");
expect(restored).toBeDefined();
expect(restored?.headers).toEqual(headers);
expect(offline.models.find(candidate => candidate.id === "sol")?.headers).toEqual(headers);
} finally {
await fs.rm(tempDir, { recursive: true, force: true });
}
});
it("refetches a current request-model alias whose headers differ from its static base", async () => {
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "pi-catalog-custom-alias-"));
const dbPath = path.join(tempDir, "models.db");
const baseHeaders = { "X-Route": "static" };
const customHeaders = { "X-Route": "tenant-specific" };
const base = completionsSpec({ id: "base", provider: "alias-cache-test", headers: baseHeaders });
const aliasSpec = completionsSpec({
id: "custom-alias",
provider: "alias-cache-test",
requestModelId: "base",
headers: customHeaders,
});
const alias = buildModel(aliasSpec);
let fetches = 0;
const options = {
providerId: "alias-cache-test",
staticModels: [base],
cacheDbPath: dbPath,
fetchDynamicModels: async () => {
fetches++;
return [aliasSpec];
},
};
try {
writeModelCache("alias-cache-test", Date.now(), [alias], true, "", dbPath, [buildModel(base)]);
const refreshed = await resolveProviderModels<"openai-completions">(options, "online-if-uncached");
expect(fetches).toBe(1);
expect(refreshed.models.find(candidate => candidate.id === alias.id)?.headers).toEqual(customHeaders);
const offline = await resolveProviderModels<"openai-completions">(options, "offline");
expect(offline.models.find(candidate => candidate.id === alias.id)).toBeUndefined();
} finally {
await fs.rm(tempDir, { recursive: true, force: true });
}
});
it("recovers a legacy stale-marked request-model variant via requestModelId", async () => {
// Legacy cache rows (written by the old id-only writer) flag `-1m`
// variants unrestorable because it never matched their base's headers.
// The restore path must still recover them through `requestModelId`.
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "pi-catalog-legacy-variant-"));
const dbPath = path.join(tempDir, "models.db");
const headers = { "X-GitHub-Api-Version": "2026-06-01" };
const base = completionsSpec({ id: "sol", provider: "variant-cache-test", headers });
const variant = buildModel(
completionsSpec({
id: "sol-1m",
provider: "variant-cache-test",
requestModelId: "sol",
headers,
contextWindow: 1_000_000,
}),
);
try {
// Emulate a legacy write: no static header source, so the variant is
// flagged unrestorable even though its base carries the headers.
writeModelCache("variant-cache-test", Date.now(), [variant], true, "", dbPath);
const db = new Database(dbPath);
db.run("UPDATE model_cache SET header_restore_version = 0 WHERE provider_id = ?", ["variant-cache-test"]);
db.close();
const offline = await resolveProviderModels<"openai-completions">(
{ providerId: "variant-cache-test", staticModels: [base], cacheDbPath: dbPath },
"offline",
);
const restored = offline.models.find(candidate => candidate.id === "sol-1m");
expect(restored).toBeDefined();
expect(restored?.headers).toEqual(headers);
} finally {
await fs.rm(tempDir, { recursive: true, force: true });
}
});
});
describe("isOfficialAnthropicApiUrl", () => {
it("treats a missing baseUrl as official", () => {
expect(isOfficialAnthropicApiUrl(undefined)).toBe(true);
});
it("accepts the https first-party host", () => {
expect(isOfficialAnthropicApiUrl("https://api.anthropic.com/v1")).toBe(true);
});
it("rejects non-https schemes", () => {
expect(isOfficialAnthropicApiUrl("http://api.anthropic.com")).toBe(false);
});
it("rejects lookalike hostnames", () => {
expect(isOfficialAnthropicApiUrl("https://api.anthropic.com.evil.com")).toBe(false);
});
});