Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion scripts/generate-model-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ for (const provider of allowedProviders) {
lines.push("};");
lines.push("");
lines.push("export function resolveMetadataProvider(provider: string): string | undefined {");
lines.push(" return PROVIDER_ALIASES[provider];");
lines.push(" return PROVIDER_ALIASES[provider] ?? PROVIDER_ALIASES[provider.toLowerCase()];");
lines.push("}");
lines.push("");
lines.push("export function getModelMetadata(provider: string, modelId: string): ModelMetadata | undefined {");
Expand Down
6 changes: 3 additions & 3 deletions scripts/model-metadata.source.json
Original file line number Diff line number Diff line change
Expand Up @@ -9439,7 +9439,7 @@
"cacheRead": 0.0028,
"cacheWrite": 0
},
"contextWindow": 1000000,
"contextWindow": 1048576,
"maxTokens": 384000,
"compat": {
"supportsDeveloperRole": false,
Expand Down Expand Up @@ -9485,7 +9485,7 @@
"cacheRead": 0.003625,
"cacheWrite": 0
},
"contextWindow": 1000000,
"contextWindow": 1048576,
"maxTokens": 384000,
"compat": {
"supportsDeveloperRole": false,
Expand Down Expand Up @@ -85724,4 +85724,4 @@
}
}
}
}
}
2 changes: 1 addition & 1 deletion src/codex/catalog/parsing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export type RawEntry = Record<string, unknown>;

export type RawCatalog = { models?: RawEntry[]; [k: string]: unknown };

export const JAWCODE_CATALOG_AUGMENT_PROVIDERS = new Set(["opencode-go"]);
export const JAWCODE_CATALOG_AUGMENT_PROVIDERS = new Set(["opencode-go", "deepseek"]);

export const ROUTED_MODEL_COMPATIBILITY_EXCLUSIONS = new Set([
// Issue #82: Zen Go /models advertises HY3, but Console Go rejects it as outside the lite list.
Expand Down
5 changes: 3 additions & 2 deletions src/generated/model-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const PROVIDER_ALIASES: Record<string, string> = {
"google-antigravity": "google",
"antigravity": "google",
"gemini-antigravity": "google",
"deepseek": "deepseek",
"moonshot": "moonshot",
"zhipu-bigmodel": "zai",
"zhipu-bigmodel-coding": "zai",
Expand All @@ -40,7 +41,7 @@ const DATA: Record<string, readonly Row[]> = {
"anthropic": [["claude-3-5-sonnet-20240620",200000,8192,"text,image",0,null,3,15,0.3,3.75],["claude-3-5-sonnet-20241022",200000,8192,"text,image",0,null,3,15,0.3,3.75],["claude-3-haiku-20240307",200000,4096,"text,image",0,null,0.25,1.25,0.03,0.3],["claude-fable-5",1000000,128000,"text,image",1,null,10,50,1,12.5],["claude-haiku-4-5",200000,64000,"text,image",1,null,1,5,0.1,1.25],["claude-haiku-4-5-20251001",200000,64000,"text,image",1,null,1,5,0.1,1.25],["claude-opus-4-0",200000,32000,"text,image",1,null,15,75,1.5,18.75],["claude-opus-4-1",200000,32000,"text,image",1,null,15,75,1.5,18.75],["claude-opus-4-1-20250805",200000,32000,"text,image",1,null,15,75,1.5,18.75],["claude-opus-4-20250514",200000,32000,"text,image",1,null,15,75,1.5,18.75],["claude-opus-4-5",200000,64000,"text,image",1,null,5,25,0.5,6.25],["claude-opus-4-5-20251101",200000,64000,"text,image",1,null,5,25,0.5,6.25],["claude-opus-4-6",1000000,128000,"text,image",1,null,5,25,0.5,6.25],["claude-opus-4-6[1m]",1000000,128000,"text,image",1,"claude-opus-4-6",5,25,0.5,6.25],["claude-opus-4-7",1000000,128000,"text,image",1,null,5,25,0.5,6.25],["claude-opus-4-7[1m]",1000000,128000,"text,image",1,"claude-opus-4-7",5,25,0.5,6.25],["claude-opus-4-8",1000000,128000,"text,image",1,null,5,25,0.5,6.25],["claude-opus-4-8[1m]",1000000,128000,"text,image",1,"claude-opus-4-8",5,25,0.5,6.25],["claude-opus-5",1000000,128000,"text,image",1,null,5,25,0.5,6.25],["claude-sonnet-4-0",200000,64000,"text,image",1,null,3,15,0.3,3.75],["claude-sonnet-4-20250514",200000,64000,"text,image",1,null,3,15,0.3,3.75],["claude-sonnet-4-5",1000000,64000,"text,image",1,null,3,15,0.3,3.75],["claude-sonnet-4-5-20250929",1000000,64000,"text,image",1,null,3,15,0.3,3.75],["claude-sonnet-4-6",1000000,128000,"text,image",1,null,3,15,0.3,3.75],["claude-sonnet-4-6[1m]",1000000,64000,"text,image",1,"claude-sonnet-4-6",3,15,0.3,3.75],["claude-sonnet-5",1000000,128000,"text,image",1,null,2,10,0.2,2.5]],
"azure-openai": [["gpt-4.1",1047576,32768,"text,image",0,null,2,8,0.5,0],["gpt-4o",128000,16384,"text,image",0,null,2.5,10,1.25,0],["gpt-4o-mini",128000,16384,"text,image",0,null,0.15,0.6,0.075,0],["o3",200000,100000,"text,image",1,null,2,8,0.5,0],["o3-mini",200000,100000,"text",1,null,1.1,4.4,0.55,0]],
"cerebras": [["gemma-4-31b",131072,40960,"text,image",1,null,0.99,1.49,0,0],["gpt-oss-120b",131072,40960,"text",1,null,0.35,0.75,0,0],["llama3.1-8b",32000,8000,"text",0,null,0.1,0.1,0,0],["qwen-3-235b-a22b-instruct-2507",131000,32000,"text",0,null,0.6,1.2,0,0],["qwen-3-coder-480b",131072,32768,"text",0,null,0,0,0,0],["zai-glm-4.6",131072,32768,"text",0,null,0,0,0,0],["zai-glm-4.7",131072,40960,"text",1,null,2.25,2.75,2.25,0]],
"deepseek": [["deepseek-v4-flash",1000000,384000,"text",1,null,0.14,0.28,0.0028,0],["deepseek-v4-pro",1000000,384000,"text",1,null,0.435,0.87,0.003625,0]],
"deepseek": [["deepseek-v4-flash",1048576,384000,"text",1,null,0.14,0.28,0.0028,0],["deepseek-v4-pro",1048576,384000,"text",1,null,0.435,0.87,0.003625,0]],
"google": [["deep-research-max-preview-04-2026",131072,65536,"text,image",1,null,2,12,0.2,0],["deep-research-preview-04-2026",131072,65536,"text,image",1,null,2,12,0.2,0],["gemini-1.5-flash",1000000,8192,"text,image",0,null,0.075,0.3,0.01875,0],["gemini-1.5-flash-8b",1000000,8192,"text,image",0,null,0.0375,0.15,0.01,0],["gemini-1.5-pro",1000000,8192,"text,image",0,null,1.25,5,0.3125,0],["gemini-2.0-flash",1048576,8192,"text,image",0,null,0.1,0.4,0.025,0],["gemini-2.0-flash-lite",1048576,8192,"text,image",0,null,0.075,0.3,0,0],["gemini-2.5-computer-use-preview-10-2025",131072,65536,"text,image",1,null,1.25,10,0,0],["gemini-2.5-flash",1048576,65536,"text,image",1,null,0.3,2.5,0.03,0],["gemini-2.5-flash-lite",1048576,65536,"text,image",1,null,0.1,0.4,0.01,0],["gemini-2.5-flash-lite-preview-06-17",1048576,65536,"text,image",1,null,0.1,0.4,0.025,0],["gemini-2.5-flash-lite-preview-09-2025",1048576,65536,"text,image",1,null,0.1,0.4,0.025,0],["gemini-2.5-flash-preview-04-17",1048576,65536,"text,image",1,null,0.15,0.6,0.0375,0],["gemini-2.5-flash-preview-05-20",1048576,65536,"text,image",1,null,0.15,0.6,0.0375,0],["gemini-2.5-flash-preview-09-2025",1048576,65536,"text,image",1,null,0.3,2.5,0.075,0],["gemini-2.5-pro",1048576,65536,"text,image",1,null,1.25,10,0.125,0],["gemini-2.5-pro-preview-05-06",1048576,65536,"text,image",1,null,1.25,10,0.31,0],["gemini-2.5-pro-preview-06-05",1048576,65536,"text,image",1,null,1.25,10,0.31,0],["gemini-3-flash-preview",1048576,65536,"text,image",1,null,0.5,3,0.05,0],["gemini-3-pro-preview",1048576,65536,"text,image",1,null,2,12,0.2,0],["gemini-3.1-flash-lite",1048576,65536,"text,image",1,null,0.25,1.5,0.025,0],["gemini-3.1-flash-lite-image",65536,65536,"text,image",1,null,0.25,30,0,0],["gemini-3.1-flash-lite-preview",1048576,65536,"text,image",1,null,0.25,1.5,0.025,0],["gemini-3.1-flash-live-preview",131072,65536,"text,image",1,null,0.75,4.5,0,0],["gemini-3.1-pro-preview",1048576,65536,"text,image",1,null,2,12,0.2,0],["gemini-3.1-pro-preview-customtools",1048576,65536,"text,image",1,null,2,12,0.2,0],["gemini-3.5-flash",1048576,65536,"text,image",1,null,1.5,9,0.15,0],["gemini-3.5-flash-lite",1048576,65536,"text,image",1,null,0.3,2.5,0.03,0],["gemini-3.6-flash",1048576,65536,"text,image",1,null,1.5,7.5,0.15,0],["gemini-flash-latest",1048576,65536,"text,image",1,null,1.5,9,0.15,0],["gemini-flash-lite-latest",1048576,65536,"text,image",1,null,0.25,1.5,0.025,0],["gemini-live-2.5-flash",128000,8000,"text,image",1,null,0.5,2,0,0],["gemini-live-2.5-flash-preview-native-audio",131072,65536,"text",1,null,0.5,2,0,0],["gemini-robotics-er-1.6-preview",131072,65536,"text,image",1,null,1,5,0,0],["gemma-3-27b-it",131072,8192,"text,image",0,null,0,0,0,0],["gemma-4-26b",256000,8192,"text,image",1,null,0,0,0,0],["gemma-4-26b-a4b-it",262144,32768,"text,image",1,null,0,0,0,0],["gemma-4-26b-it",256000,8192,"text,image",1,null,0,0,0,0],["gemma-4-31b",256000,8192,"text,image",1,null,0,0,0,0],["gemma-4-31b-it",262144,32768,"text,image",1,null,0,0,0,0],["gemma-4-E2B-it",131072,8192,"text,image",1,null,0,0,0,0],["gemma-4-E4B-it",131072,8192,"text,image",1,null,0,0,0,0]],
"minimax": [["MiniMax-M2",196608,128000,"text",1,null,0.3,1.2,0,0],["MiniMax-M2.1",204800,131072,"text",1,null,0.3,1.2,0,0],["MiniMax-M2.5",204800,131072,"text",1,null,0.3,1.2,0.03,0.375],["MiniMax-M2.5-highspeed",204800,131072,"text",1,null,0.6,2.4,0.06,0.375],["MiniMax-M2.5-lightning",204800,32000,"text",1,null,0.3,2.4,0,0],["MiniMax-M2.7",204800,131072,"text",1,null,0.3,1.2,0.06,0.375],["MiniMax-M2.7-highspeed",204800,131072,"text",1,null,0.6,2.4,0.06,0.375],["minimax-m3",512000,128000,"text,image",1,null,0.6,2.4,0.12,0],["MiniMax-M3",1000000,128000,"text,image,video",1,null,0.3,1.2,0.06,0]],
"mistral": [["codestral-latest",256000,4096,"text",0,null,0.3,0.9,0,0],["devstral-2512",262144,262144,"text",0,null,0.4,2,0,0],["devstral-latest",262144,262144,"text",0,null,0.4,2,0,0],["devstral-medium-2507",128000,128000,"text",0,null,0.4,2,0,0],["devstral-medium-latest",262144,262144,"text",0,null,0.4,2,0,0],["devstral-small-2505",128000,128000,"text",0,null,0.1,0.3,0,0],["devstral-small-2507",128000,128000,"text",0,null,0.1,0.3,0,0],["labs-devstral-small-2512",256000,256000,"text,image",0,null,0,0,0,0],["magistral-medium-latest",128000,16384,"text",1,null,2,5,0,0],["magistral-small",128000,128000,"text",1,null,0.5,1.5,0,0],["ministral-3b-latest",128000,128000,"text",0,null,0.04,0.04,0,0],["ministral-8b-latest",128000,128000,"text",0,null,0.1,0.1,0,0],["mistral-large-2411",131072,16384,"text",0,null,2,6,0,0],["mistral-large-2512",262144,262144,"text,image",0,null,0.5,1.5,0,0],["mistral-large-latest",262144,262144,"text,image",0,null,0.5,1.5,0,0],["mistral-medium-2505",131072,131072,"text,image",0,null,0.4,2,0,0],["mistral-medium-2508",262144,262144,"text,image",0,null,0.4,2,0,0],["mistral-medium-2604",262144,262144,"text,image",1,null,1.5,7.5,0,0],["mistral-medium-latest",262144,262144,"text,image",1,null,1.5,7.5,0,0],["mistral-nemo",128000,128000,"text",0,null,0.15,0.15,0,0],["mistral-small-2506",128000,16384,"text,image",0,null,0.1,0.3,0,0],["mistral-small-2603",256000,256000,"text,image",1,null,0.15,0.6,0,0],["mistral-small-latest",256000,256000,"text,image",1,null,0.15,0.6,0,0],["open-mistral-7b",8000,8000,"text",0,null,0.25,0.25,0,0],["open-mistral-nemo",128000,128000,"text",0,null,0.15,0.15,0,0],["open-mixtral-8x22b",64000,64000,"text",0,null,2,6,0,0],["open-mixtral-8x7b",32000,32000,"text",0,null,0.7,0.7,0,0],["pixtral-12b",128000,128000,"text,image",0,null,0.15,0.15,0,0],["pixtral-large-latest",128000,128000,"text,image",0,null,2,6,0,0]],
Expand All @@ -54,7 +55,7 @@ const DATA: Record<string, readonly Row[]> = {
};

export function resolveMetadataProvider(provider: string): string | undefined {
return PROVIDER_ALIASES[provider];
return PROVIDER_ALIASES[provider] ?? PROVIDER_ALIASES[provider.toLowerCase()];
}

export function getModelMetadata(provider: string, modelId: string): ModelMetadata | undefined {
Expand Down
17 changes: 14 additions & 3 deletions src/providers/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1299,11 +1299,22 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
adapter: "openai-chat",
authKind: "key",
dashboardUrl: "https://platform.deepseek.com/api_keys",
// deepseek-chat/deepseek-reasoner are upstream-deprecated at 2026-07-24 15:59 UTC;
// kept until then. Evidence: devlog/_plan/260710_provider_hardening/002_research_cn.md.
// Route DeepSeek's own catalog bundle so routed rebuilds restore the official
// context window from the vendored model-metadata bundle instead of falling
// back to the 128k strict-fields default (scripts/model-metadata.source.json,
// verified 2026-08-08).
jawcodeBundle: "deepseek",
// deepseek-chat/deepseek-reasoner were deprecated upstream on 2026-07-24 15:59 UTC;
// official identifiers are now deepseek-v4-flash / deepseek-v4-pro. They stay in
// the list only as compatibility aliases so existing saved configs and requests
// keep validating and routing (they previously mapped to v4-flash; devlog
// _fin/260710_provider_hardening/002_research_cn.md). The current offerings are
// the V4 ids — defaultModel and the model-specific wiring above use them.
models: ["deepseek-chat", "deepseek-reasoner", ...DEEPSEEK_THINKING_MODELS],
defaultModel: "deepseek-v4-flash",
modelContextWindows: { "deepseek-v4-flash": 1_000_000, "deepseek-v4-pro": 1_000_000 },
// Official DeepSeek Codex setup (codex-deepseek-setup.sh) advertises 1,048,576
// for both V4 models; the older 1,000,000 figure was a rounded approximation.
modelContextWindows: { "deepseek-v4-flash": 1_048_576, "deepseek-v4-pro": 1_048_576 },
// DeepSeek documents V4-Flash as a native Responses API model adapted for Codex. The
// API id is `deepseek-v4-flash`; `DeepSeek-V4-Flash-0731` is a release/version label.
modelWireDefaults: {
Expand Down
41 changes: 41 additions & 0 deletions tests/codex-catalog.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2826,6 +2826,47 @@ describe("Codex catalog routed normalization", () => {
expect(routed?.input_modalities).toEqual(["text"]);
});

test("DeepSeek routed entries restore the official context window from jawcode metadata", () => {
const entries = buildCatalogEntries(nativeTemplate(), [], [
{ provider: "deepseek", id: "deepseek-v4-flash" },
{ provider: "deepseek", id: "deepseek-v4-pro" },
]);
const flash = entries.find(e => e.slug === "deepseek/deepseek-v4-flash");
const pro = entries.find(e => e.slug === "deepseek/deepseek-v4-pro");

for (const routed of [flash, pro]) {
expect(routed?.context_window).toBe(1_048_576);
expect(routed?.max_context_window).toBe(1_048_576);
expect(routed?.auto_compact_token_limit).toBe(943_718); // floor(1048576 * 0.9)
expect(routed?.input_modalities).toEqual(["text"]);
}
// The catalog rebuild falls back to the strict 128k default when metadata is missing,
// so this assertion proves the jawcode bundle lookup actually ran.
expect(resolveMetadataProvider("deepseek")).toBe("deepseek");
expect(getModelMetadata("deepseek", "deepseek-v4-flash")?.contextWindow).toBe(1_048_576);
});
Comment thread
iF2007 marked this conversation as resolved.

test("DeepSeek catalog sync appends V4 rows missing from /v1/models", () => {
const models = augmentRoutedModelsWithMetadata([], ["deepseek"]);
const slugs = new Set(models.map(m => `${m.provider}/${m.id}`));

expect(slugs.has("deepseek/deepseek-v4-flash")).toBe(true);
expect(slugs.has("deepseek/deepseek-v4-pro")).toBe(true);
for (const model of models) {
expect(model.contextWindow).toBe(1_048_576);
expect(model.inputModalities).toEqual(["text"]);
}

const entries = buildCatalogEntries(nativeTemplate(), [], models);
for (const id of ["deepseek-v4-flash", "deepseek-v4-pro"]) {
const routed = entries.find(e => e.slug === `deepseek/${id}`);
expect(routed?.context_window).toBe(1_048_576);
expect(routed?.max_context_window).toBe(1_048_576);
expect(routed?.auto_compact_token_limit).toBe(943_718); // floor(1048576 * 0.9)
expect(routed?.input_modalities).toEqual(["text"]);
}
});

test("provider context-cap applies before jawcode catalog metadata reaches Codex", () => {
const entries = buildCatalogEntries(nativeTemplate(), [], [
{ provider: "opencode-go", id: "deepseek-v4-pro", contextCap: 350_000, contextCapped: false },
Expand Down
8 changes: 6 additions & 2 deletions tests/provider-registry-parity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,8 @@ describe("provider registry parity", () => {
baseUrl: "https://api.deepseek.com",
defaultModel: "deepseek-v4-flash",
modelContextWindows: {
"deepseek-v4-flash": 1_000_000,
"deepseek-v4-pro": 1_000_000,
"deepseek-v4-flash": 1_048_576,
"deepseek-v4-pro": 1_048_576,
},
});

Expand Down Expand Up @@ -761,6 +761,7 @@ describe("provider registry parity", () => {
"google-antigravity": "google",
"antigravity": "google",
"gemini-antigravity": "google",
deepseek: "deepseek",
moonshot: "moonshot",
minimax: "minimax",
"minimax-cn": "minimax",
Expand All @@ -769,6 +770,9 @@ describe("provider registry parity", () => {
});
expect(resolveMetadataProvider("gemini")).toBe("google");
expect(resolveMetadataProvider("minimax-cn")).toBe("minimax");
expect(resolveMetadataProvider("deepseek")).toBe("deepseek");
// User-saved provider keys can be title-cased ("DeepSeek"); alias lookup folds case.
expect(resolveMetadataProvider("DeepSeek")).toBe("deepseek");
});

test("legacy azure adapter spelling remains accepted", () => {
Expand Down
Loading