feat(catalog): updated model definitions and provider constraints

- Added `gpt-5.6-luna`, `gpt-5.6-sol`, and `gpt-5.6-terra` variants for the `opencode-zen` provider.
- Removed deprecated `*-pro` model aliases from the `openai-codex` provider in `models.json`.
- Updated `openai-compat.ts` to restrict pro-reasoning alias generation to the `openai` provider only.
- Adjusted various model `contextWindow`, `maxTokens`, and `cost` parameters to reflect latest upstream metadata.
- Added `perplexity-academic-researcher` model definition.
This commit is contained in:
can1357
2026-07-10 20:21:05 +02:00
parent c30bdc54ce
commit d9854ade76
3 changed files with 260 additions and 150 deletions
+16
View File
@@ -2,6 +2,22 @@
## [Unreleased]
### Added
- Added GPT-5.6 Luna, Sol, and Terra models
- Added perplexity-academic-researcher model
### Changed
- Updated context windows for multiple GPT-5.6 models
- Increased max tokens for several models
- Updated cache write costs for GPT-5.6 variants
- Reduced pricing for select models
### Removed
- Removed pro-reasoning aliases for GPT-5.6 variants
## [16.4.0] - 2026-07-10
### Breaking Changes
+227 -139
View File
@@ -18667,7 +18667,7 @@
"cacheRead": 0.2,
"cacheWrite": 0
},
"contextWindow": 200000,
"contextWindow": 1000000,
"maxTokens": 64000,
"headers": {
"User-Agent": "opencode/1.3.15",
@@ -19190,7 +19190,7 @@
"cacheRead": 0.5,
"cacheWrite": 0
},
"contextWindow": 400000,
"contextWindow": 1050000,
"maxTokens": 128000,
"headers": {
"User-Agent": "opencode/1.3.15",
@@ -19207,6 +19207,108 @@
},
"contextPromotionTarget": "github-copilot/gpt-5.4"
},
"gpt-5.6-luna": {
"id": "gpt-5.6-luna",
"name": "GPT-5.6 Luna",
"api": "openai-responses",
"provider": "github-copilot",
"baseUrl": "https://api.githubcopilot.com",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 1,
"output": 6,
"cacheRead": 0.1,
"cacheWrite": 0
},
"contextWindow": 1050000,
"maxTokens": 128000,
"headers": {
"User-Agent": "opencode/1.3.15",
"X-GitHub-Api-Version": "2026-06-01"
},
"thinking": {
"mode": "effort",
"efforts": [
"low",
"medium",
"high",
"xhigh",
"max"
]
}
},
"gpt-5.6-sol": {
"id": "gpt-5.6-sol",
"name": "GPT-5.6 Sol",
"api": "openai-responses",
"provider": "github-copilot",
"baseUrl": "https://api.githubcopilot.com",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 5,
"output": 30,
"cacheRead": 0.5,
"cacheWrite": 0
},
"contextWindow": 1050000,
"maxTokens": 128000,
"headers": {
"User-Agent": "opencode/1.3.15",
"X-GitHub-Api-Version": "2026-06-01"
},
"thinking": {
"mode": "effort",
"efforts": [
"low",
"medium",
"high",
"xhigh",
"max"
]
}
},
"gpt-5.6-terra": {
"id": "gpt-5.6-terra",
"name": "GPT-5.6 Terra",
"api": "openai-responses",
"provider": "github-copilot",
"baseUrl": "https://api.githubcopilot.com",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 2.5,
"output": 15,
"cacheRead": 0.25,
"cacheWrite": 0
},
"contextWindow": 1050000,
"maxTokens": 128000,
"headers": {
"User-Agent": "opencode/1.3.15",
"X-GitHub-Api-Version": "2026-06-01"
},
"thinking": {
"mode": "effort",
"efforts": [
"low",
"medium",
"high",
"xhigh",
"max"
]
}
},
"grok-code-fast-1": {
"id": "grok-code-fast-1",
"name": "Grok Code Fast 1",
@@ -48660,6 +48762,25 @@
"contextWindow": null,
"maxTokens": null
},
"perplexity-academic-researcher": {
"id": "perplexity-academic-researcher",
"name": "perplexity-academic-researcher",
"api": "openai-completions",
"provider": "nanogpt",
"baseUrl": "https://nano-gpt.com/api/v1",
"reasoning": false,
"input": [
"text"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": null,
"maxTokens": null
},
"phi-4-mini-instruct": {
"id": "phi-4-mini-instruct",
"name": "phi-4-mini-instruct",
@@ -63390,47 +63511,6 @@
]
}
},
"gpt-5.6-luna-pro": {
"id": "gpt-5.6-luna-pro",
"name": "GPT-5.6 Luna Pro",
"api": "openai-codex-responses",
"provider": "openai-codex",
"baseUrl": "https://chatgpt.com/backend-api",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 1,
"output": 6,
"cacheRead": 0.1,
"cacheWrite": 1.25
},
"remoteCompaction": {
"enabled": true,
"api": "openai-codex-responses",
"v2StreamingEnabled": true
},
"contextWindow": 372000,
"maxTokens": 128000,
"preferWebsockets": true,
"useResponsesLite": true,
"priority": 3,
"requestModelId": "gpt-5.6-luna",
"reasoningMode": "pro",
"applyPatchToolType": "freeform",
"thinking": {
"mode": "effort",
"efforts": [
"low",
"medium",
"high",
"xhigh",
"max"
]
}
},
"gpt-5.6-sol": {
"id": "gpt-5.6-sol",
"name": "GPT-5.6 Sol",
@@ -63470,47 +63550,6 @@
]
}
},
"gpt-5.6-sol-pro": {
"id": "gpt-5.6-sol-pro",
"name": "GPT-5.6 Sol Pro",
"api": "openai-codex-responses",
"provider": "openai-codex",
"baseUrl": "https://chatgpt.com/backend-api",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 5,
"output": 30,
"cacheRead": 0.5,
"cacheWrite": 6.25
},
"remoteCompaction": {
"enabled": true,
"api": "openai-codex-responses",
"v2StreamingEnabled": true
},
"contextWindow": 372000,
"maxTokens": 128000,
"preferWebsockets": true,
"useResponsesLite": true,
"priority": 1,
"requestModelId": "gpt-5.6-sol",
"reasoningMode": "pro",
"applyPatchToolType": "freeform",
"thinking": {
"mode": "effort",
"efforts": [
"low",
"medium",
"high",
"xhigh",
"max"
]
}
},
"gpt-5.6-terra": {
"id": "gpt-5.6-terra",
"name": "GPT-5.6 Terra",
@@ -63549,47 +63588,6 @@
"max"
]
}
},
"gpt-5.6-terra-pro": {
"id": "gpt-5.6-terra-pro",
"name": "GPT-5.6 Terra Pro",
"api": "openai-codex-responses",
"provider": "openai-codex",
"baseUrl": "https://chatgpt.com/backend-api",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 2.5,
"output": 15,
"cacheRead": 0.25,
"cacheWrite": 3.125
},
"remoteCompaction": {
"enabled": true,
"api": "openai-codex-responses",
"v2StreamingEnabled": true
},
"contextWindow": 372000,
"maxTokens": 128000,
"preferWebsockets": true,
"useResponsesLite": true,
"priority": 2,
"requestModelId": "gpt-5.6-terra",
"reasoningMode": "pro",
"applyPatchToolType": "freeform",
"thinking": {
"mode": "effort",
"efforts": [
"low",
"medium",
"high",
"xhigh",
"max"
]
}
}
},
"opencode": {
@@ -65525,6 +65523,96 @@
},
"contextPromotionTarget": "opencode-zen/gpt-5.4"
},
"gpt-5.6-luna": {
"id": "gpt-5.6-luna",
"name": "GPT-5.6 Luna",
"api": "openai-responses",
"provider": "opencode-zen",
"baseUrl": "https://opencode.ai/zen/v1",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 1,
"output": 6,
"cacheRead": 0.1,
"cacheWrite": 1.25
},
"contextWindow": 1050000,
"maxTokens": 128000,
"thinking": {
"mode": "effort",
"efforts": [
"low",
"medium",
"high",
"xhigh",
"max"
]
}
},
"gpt-5.6-sol": {
"id": "gpt-5.6-sol",
"name": "GPT-5.6 Sol",
"api": "openai-responses",
"provider": "opencode-zen",
"baseUrl": "https://opencode.ai/zen/v1",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 5,
"output": 30,
"cacheRead": 0.5,
"cacheWrite": 6.25
},
"contextWindow": 1050000,
"maxTokens": 128000,
"thinking": {
"mode": "effort",
"efforts": [
"low",
"medium",
"high",
"xhigh",
"max"
]
}
},
"gpt-5.6-terra": {
"id": "gpt-5.6-terra",
"name": "GPT-5.6 Terra",
"api": "openai-responses",
"provider": "opencode-zen",
"baseUrl": "https://opencode.ai/zen/v1",
"reasoning": true,
"input": [
"text",
"image"
],
"cost": {
"input": 2.5,
"output": 15,
"cacheRead": 0.25,
"cacheWrite": 3.125
},
"contextWindow": 1050000,
"maxTokens": 128000,
"thinking": {
"mode": "effort",
"efforts": [
"low",
"medium",
"high",
"xhigh",
"max"
]
}
},
"grok-4.5": {
"id": "grok-4.5",
"name": "Grok 4.5",
@@ -65601,7 +65689,7 @@
"cacheRead": 0,
"cacheWrite": 0
},
"contextWindow": 256000,
"contextWindow": 190000,
"maxTokens": 64000,
"thinking": {
"mode": "effort",
@@ -68111,13 +68199,13 @@
"text"
],
"cost": {
"input": 0.09,
"output": 0.18,
"cacheRead": 0.018,
"input": 0.08399999999999999,
"output": 0.16799999999999998,
"cacheRead": 0.016800000000000002,
"cacheWrite": 0
},
"contextWindow": 1048576,
"maxTokens": 65536,
"maxTokens": 384000,
"thinking": {
"mode": "effort",
"efforts": [
@@ -75529,9 +75617,9 @@
"text"
],
"cost": {
"input": 0.77,
"output": 2.42,
"cacheRead": 0.143,
"input": 0.42,
"output": 1.32,
"cacheRead": 0.078,
"cacheWrite": 0
},
"contextWindow": 1048576,
@@ -79347,7 +79435,7 @@
"input": 1.25,
"output": 7.5,
"cacheRead": 0.125,
"cacheWrite": 0
"cacheWrite": 1.5625
},
"contextWindow": 1000000,
"maxTokens": 128000,
@@ -79377,7 +79465,7 @@
"input": 1.25,
"output": 7.5,
"cacheRead": 0.125,
"cacheWrite": 0
"cacheWrite": 1.5625
},
"contextWindow": 1000000,
"maxTokens": 128000,
@@ -79407,7 +79495,7 @@
"input": 6.25,
"output": 37.5,
"cacheRead": 0.625,
"cacheWrite": 0
"cacheWrite": 7.8125
},
"contextWindow": 1000000,
"maxTokens": 128000,
@@ -79437,7 +79525,7 @@
"input": 6.25,
"output": 37.5,
"cacheRead": 0.625,
"cacheWrite": 0
"cacheWrite": 7.8125
},
"contextWindow": 1000000,
"maxTokens": 128000,
@@ -79467,7 +79555,7 @@
"input": 3.125,
"output": 18.75,
"cacheRead": 0.3125,
"cacheWrite": 0
"cacheWrite": 3.90625
},
"contextWindow": 1000000,
"maxTokens": 128000,
@@ -79497,7 +79585,7 @@
"input": 3.125,
"output": 18.75,
"cacheRead": 0.3125,
"cacheWrite": 0
"cacheWrite": 3.90625
},
"contextWindow": 1000000,
"maxTokens": 128000,
@@ -823,17 +823,23 @@ const OPENAI_PRO_REASONING_BASE_IDS: Record<string, true> = {
"gpt-5.6-sol": true,
"gpt-5.6-terra": true,
};
const OPENAI_PRO_REASONING_PROVIDERS: Record<string, true> = { openai: true, "openai-codex": true };
/**
* Providers whose generated pro aliases this pass owns. `openai-codex` stays in
* the sweep so stale aliases from earlier snapshots are dropped on regen, but
* projection is `openai`-only — subscription (Codex) auth does not offer pro
* reasoning.
*/
const OPENAI_PRO_REASONING_SWEEP_PROVIDERS: Record<string, true> = { openai: true, "openai-codex": true };
/**
* A row this generator pass owns: one of the derived `gpt-5.6-*-pro` alias ids
* on `openai`/`openai-codex` that carries the generated `reasoningMode` marker.
* on a swept provider that carries the generated `reasoningMode` marker.
* A real upstream model occupying the same id has no `reasoningMode` and is
* never touched.
*/
function isGeneratedOpenAIProReasoningAlias(model: ModelSpec<Api>): boolean {
return (
OPENAI_PRO_REASONING_PROVIDERS[model.provider] === true &&
OPENAI_PRO_REASONING_SWEEP_PROVIDERS[model.provider] === true &&
model.reasoningMode !== undefined &&
model.id.endsWith("-pro") &&
OPENAI_PRO_REASONING_BASE_IDS[model.id.slice(0, -"-pro".length)] === true
@@ -842,21 +848,21 @@ function isGeneratedOpenAIProReasoningAlias(model: ModelSpec<Api>): boolean {
/**
* Re-derive the generated pro-reasoning aliases (`gpt-5.6-*-pro`) for the
* first-party `openai`/`openai-codex` gpt-5.6 rows. Each alias inherits the
* base row's metadata, requests the base wire id via `requestModelId`, and
* sets `reasoningMode: "pro"` so Responses-family request builders emit
* first-party `openai` gpt-5.6 rows. Each alias inherits the base row's
* metadata, requests the base wire id via `requestModelId`, and sets
* `reasoningMode: "pro"` so Responses-family request builders emit
* `reasoning: { mode: "pro" }`. Called by the models.json generator after all
* sources merge: stale copies of the owned aliases (previous snapshot) are
* dropped and re-projected from the current base rows so alias metadata always
* tracks the base, while a real upstream model that occupies an alias id wins
* and suppresses the projection.
* sources merge: stale copies of the owned aliases (previous snapshot,
* including retired `openai-codex` rows) are dropped and re-projected from the
* current base rows so alias metadata always tracks the base, while a real
* upstream model that occupies an alias id wins and suppresses the projection.
*/
export function projectOpenAIProReasoningAliases(models: readonly ModelSpec<Api>[]): ModelSpec<Api>[] {
const kept = models.filter(model => !isGeneratedOpenAIProReasoningAlias(model));
const ids = new Set(kept.map(model => `${model.provider}/${model.id}`));
const out = [...kept];
for (const model of kept) {
if (!OPENAI_PRO_REASONING_PROVIDERS[model.provider]) continue;
if (model.provider !== "openai") continue;
if (!OPENAI_PRO_REASONING_BASE_IDS[model.id]) continue;
const aliasId = `${model.id}-pro`;
const aliasKey = `${model.provider}/${aliasId}`;