diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index 8a128b37..74efa352 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -20,6 +20,7 @@ ### Added +- Added OpenAI GPT-5.6 model metadata for `gpt-5.6`, `gpt-5.6-sol`, `gpt-5.6-terra`, and `gpt-5.6-luna`, plus verified `openai-codex` support for `gpt-5.6-sol`, `gpt-5.6-terra`, and `gpt-5.6-luna`. - Refreshed generated model catalogs from models.dev, adding newly listed models including Kimi K2.7 Code for GitHub Copilot and Fable 5 to several providers ([#6256](https://github.com/earendil-works/pi/issues/6256)). - Added Claude Sonnet 5 to the GitHub Copilot model catalog ([#6200](https://github.com/earendil-works/pi/issues/6200)). - Added zstd request-body compression for the OpenAI Codex Responses SSE transport. Requests are sent with `Content-Encoding: zstd` when Node/Bun zstd support is available; the WebSocket transport is unchanged. diff --git a/packages/ai/scripts/generate-models.ts b/packages/ai/scripts/generate-models.ts index 08de7546..20c78a44 100644 --- a/packages/ai/scripts/generate-models.ts +++ b/packages/ai/scripts/generate-models.ts @@ -201,6 +201,10 @@ const OPENAI_RESPONSES_NONE_REASONING_MODELS = new Set([ "gpt-5.4-mini", "gpt-5.4-nano", "gpt-5.5", + "gpt-5.6", + "gpt-5.6-sol", + "gpt-5.6-terra", + "gpt-5.6-luna", ]); const OPENCODE_OPENAI_COMPLETIONS_LONG_CACHE_RETENTION_UNSUPPORTED_MODELS = new Set([ @@ -262,7 +266,8 @@ function supportsOpenAiXhigh(modelId: string): boolean { modelId.includes("gpt-5.2") || modelId.includes("gpt-5.3") || modelId.includes("gpt-5.4") || - modelId.includes("gpt-5.5") + modelId.includes("gpt-5.5") || + modelId.includes("gpt-5.6") ); } @@ -1684,8 +1689,56 @@ async function generateModels() { // Add missing gpt models - if (!allModels.some(m => m.provider === "openai" && m.id === "gpt-5-chat-latest")) { - allModels.push({ + const missingOpenAiModels: Model<"openai-responses">[] = [ + { + id: "gpt-5.6", + name: "GPT-5.6", + api: "openai-responses", + baseUrl: "https://api.openai.com/v1", + provider: "openai", + reasoning: true, + input: ["text", "image"], + cost: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0 }, + contextWindow: 1050000, + maxTokens: 128000, + }, + { + id: "gpt-5.6-sol", + name: "GPT-5.6 Sol", + api: "openai-responses", + baseUrl: "https://api.openai.com/v1", + provider: "openai", + reasoning: true, + input: ["text", "image"], + cost: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0 }, + contextWindow: 1050000, + maxTokens: 128000, + }, + { + id: "gpt-5.6-terra", + name: "GPT-5.6 Terra", + api: "openai-responses", + baseUrl: "https://api.openai.com/v1", + provider: "openai", + reasoning: true, + input: ["text", "image"], + cost: { input: 2.5, output: 15, cacheRead: 0.25, cacheWrite: 0 }, + contextWindow: 1050000, + maxTokens: 128000, + }, + { + id: "gpt-5.6-luna", + name: "GPT-5.6 Luna", + api: "openai-responses", + baseUrl: "https://api.openai.com/v1", + provider: "openai", + reasoning: true, + input: ["text", "image"], + cost: { input: 1, output: 6, cacheRead: 0.1, cacheWrite: 0 }, + contextWindow: 1050000, + maxTokens: 128000, + }, + { id: "gpt-5-chat-latest", name: "GPT-5 Chat Latest", api: "openai-responses", @@ -1701,7 +1754,12 @@ async function generateModels() { }, contextWindow: 128000, maxTokens: 16384, - }); + }, + ]; + for (const model of missingOpenAiModels) { + if (!allModels.some((m) => m.provider === model.provider && m.id === model.id)) { + allModels.push(model); + } } const deepseekCompat: OpenAICompletionsCompat = { @@ -1881,6 +1939,42 @@ async function generateModels() { contextWindow: CODEX_CONTEXT, maxTokens: CODEX_MAX_TOKENS, }, + { + id: "gpt-5.6-luna", + name: "GPT-5.6 Luna", + api: "openai-codex-responses", + provider: "openai-codex", + baseUrl: CODEX_BASE_URL, + reasoning: true, + input: ["text", "image"], + cost: { input: 1, output: 6, cacheRead: 0.1, cacheWrite: 0 }, + contextWindow: CODEX_CONTEXT, + maxTokens: CODEX_MAX_TOKENS, + }, + { + id: "gpt-5.6-sol", + name: "GPT-5.6 Sol", + api: "openai-codex-responses", + provider: "openai-codex", + baseUrl: CODEX_BASE_URL, + reasoning: true, + input: ["text", "image"], + cost: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0 }, + contextWindow: CODEX_CONTEXT, + maxTokens: CODEX_MAX_TOKENS, + }, + { + id: "gpt-5.6-terra", + name: "GPT-5.6 Terra", + api: "openai-codex-responses", + provider: "openai-codex", + baseUrl: CODEX_BASE_URL, + reasoning: true, + input: ["text", "image"], + cost: { input: 2.5, output: 15, cacheRead: 0.25, cacheWrite: 0 }, + contextWindow: CODEX_CONTEXT, + maxTokens: CODEX_MAX_TOKENS, + }, ]; allModels.push(...codexModels); diff --git a/packages/ai/src/providers/azure-openai-responses.models.ts b/packages/ai/src/providers/azure-openai-responses.models.ts index b35eec5c..3f89cd9e 100644 --- a/packages/ai/src/providers/azure-openai-responses.models.ts +++ b/packages/ai/src/providers/azure-openai-responses.models.ts @@ -606,6 +606,78 @@ export const AZURE_OPENAI_RESPONSES_MODELS = { contextWindow: 1050000, maxTokens: 128000, } satisfies Model<"azure-openai-responses">, + "gpt-5.6": { + id: "gpt-5.6", + name: "GPT-5.6 Sol", + api: "azure-openai-responses", + provider: "azure-openai-responses", + baseUrl: "", + reasoning: true, + thinkingLevelMap: {"off":null,"xhigh":"xhigh"}, + input: ["text", "image"], + cost: { + input: 5, + output: 30, + cacheRead: 0.5, + cacheWrite: 6.25, + }, + contextWindow: 1050000, + maxTokens: 128000, + } satisfies Model<"azure-openai-responses">, + "gpt-5.6-luna": { + id: "gpt-5.6-luna", + name: "GPT-5.6 Luna", + api: "azure-openai-responses", + provider: "azure-openai-responses", + baseUrl: "", + reasoning: true, + thinkingLevelMap: {"off":null,"xhigh":"xhigh"}, + input: ["text", "image"], + cost: { + input: 1, + output: 6, + cacheRead: 0.1, + cacheWrite: 1.25, + }, + contextWindow: 1050000, + maxTokens: 128000, + } satisfies Model<"azure-openai-responses">, + "gpt-5.6-sol": { + id: "gpt-5.6-sol", + name: "GPT-5.6 Sol", + api: "azure-openai-responses", + provider: "azure-openai-responses", + baseUrl: "", + reasoning: true, + thinkingLevelMap: {"off":null,"xhigh":"xhigh"}, + input: ["text", "image"], + cost: { + input: 5, + output: 30, + cacheRead: 0.5, + cacheWrite: 6.25, + }, + contextWindow: 1050000, + maxTokens: 128000, + } satisfies Model<"azure-openai-responses">, + "gpt-5.6-terra": { + id: "gpt-5.6-terra", + name: "GPT-5.6 Terra", + api: "azure-openai-responses", + provider: "azure-openai-responses", + baseUrl: "", + reasoning: true, + thinkingLevelMap: {"off":null,"xhigh":"xhigh"}, + input: ["text", "image"], + cost: { + input: 2.5, + output: 15, + cacheRead: 0.25, + cacheWrite: 3.125, + }, + contextWindow: 1050000, + maxTokens: 128000, + } satisfies Model<"azure-openai-responses">, "o1": { id: "o1", name: "o1", diff --git a/packages/ai/src/providers/openai-codex.models.ts b/packages/ai/src/providers/openai-codex.models.ts index c849c24c..bccd7077 100644 --- a/packages/ai/src/providers/openai-codex.models.ts +++ b/packages/ai/src/providers/openai-codex.models.ts @@ -76,4 +76,58 @@ export const OPENAI_CODEX_MODELS = { contextWindow: 272000, maxTokens: 128000, } satisfies Model<"openai-codex-responses">, + "gpt-5.6-luna": { + id: "gpt-5.6-luna", + name: "GPT-5.6 Luna", + api: "openai-codex-responses", + provider: "openai-codex", + baseUrl: "https://chatgpt.com/backend-api", + reasoning: true, + thinkingLevelMap: {"xhigh":"xhigh","minimal":"low"}, + input: ["text", "image"], + cost: { + input: 1, + output: 6, + cacheRead: 0.1, + cacheWrite: 0, + }, + contextWindow: 272000, + maxTokens: 128000, + } satisfies Model<"openai-codex-responses">, + "gpt-5.6-sol": { + id: "gpt-5.6-sol", + name: "GPT-5.6 Sol", + api: "openai-codex-responses", + provider: "openai-codex", + baseUrl: "https://chatgpt.com/backend-api", + reasoning: true, + thinkingLevelMap: {"xhigh":"xhigh","minimal":"low"}, + input: ["text", "image"], + cost: { + input: 5, + output: 30, + cacheRead: 0.5, + cacheWrite: 0, + }, + contextWindow: 272000, + maxTokens: 128000, + } satisfies Model<"openai-codex-responses">, + "gpt-5.6-terra": { + id: "gpt-5.6-terra", + name: "GPT-5.6 Terra", + api: "openai-codex-responses", + provider: "openai-codex", + baseUrl: "https://chatgpt.com/backend-api", + reasoning: true, + thinkingLevelMap: {"xhigh":"xhigh","minimal":"low"}, + input: ["text", "image"], + cost: { + input: 2.5, + output: 15, + cacheRead: 0.25, + cacheWrite: 0, + }, + contextWindow: 272000, + maxTokens: 128000, + } satisfies Model<"openai-codex-responses">, } as const; diff --git a/packages/ai/src/providers/openai.models.ts b/packages/ai/src/providers/openai.models.ts index fcf9a76c..4da421b9 100644 --- a/packages/ai/src/providers/openai.models.ts +++ b/packages/ai/src/providers/openai.models.ts @@ -606,6 +606,78 @@ export const OPENAI_MODELS = { contextWindow: 1050000, maxTokens: 128000, } satisfies Model<"openai-responses">, + "gpt-5.6": { + id: "gpt-5.6", + name: "GPT-5.6 Sol", + api: "openai-responses", + provider: "openai", + baseUrl: "https://api.openai.com/v1", + reasoning: true, + thinkingLevelMap: {"off":"none","xhigh":"xhigh"}, + input: ["text", "image"], + cost: { + input: 5, + output: 30, + cacheRead: 0.5, + cacheWrite: 6.25, + }, + contextWindow: 1050000, + maxTokens: 128000, + } satisfies Model<"openai-responses">, + "gpt-5.6-luna": { + id: "gpt-5.6-luna", + name: "GPT-5.6 Luna", + api: "openai-responses", + provider: "openai", + baseUrl: "https://api.openai.com/v1", + reasoning: true, + thinkingLevelMap: {"off":"none","xhigh":"xhigh"}, + input: ["text", "image"], + cost: { + input: 1, + output: 6, + cacheRead: 0.1, + cacheWrite: 1.25, + }, + contextWindow: 1050000, + maxTokens: 128000, + } satisfies Model<"openai-responses">, + "gpt-5.6-sol": { + id: "gpt-5.6-sol", + name: "GPT-5.6 Sol", + api: "openai-responses", + provider: "openai", + baseUrl: "https://api.openai.com/v1", + reasoning: true, + thinkingLevelMap: {"off":"none","xhigh":"xhigh"}, + input: ["text", "image"], + cost: { + input: 5, + output: 30, + cacheRead: 0.5, + cacheWrite: 6.25, + }, + contextWindow: 1050000, + maxTokens: 128000, + } satisfies Model<"openai-responses">, + "gpt-5.6-terra": { + id: "gpt-5.6-terra", + name: "GPT-5.6 Terra", + api: "openai-responses", + provider: "openai", + baseUrl: "https://api.openai.com/v1", + reasoning: true, + thinkingLevelMap: {"off":"none","xhigh":"xhigh"}, + input: ["text", "image"], + cost: { + input: 2.5, + output: 15, + cacheRead: 0.25, + cacheWrite: 3.125, + }, + contextWindow: 1050000, + maxTokens: 128000, + } satisfies Model<"openai-responses">, "o1": { id: "o1", name: "o1", diff --git a/packages/ai/src/providers/openrouter.models.ts b/packages/ai/src/providers/openrouter.models.ts index 5af57bc8..087f1deb 100644 --- a/packages/ai/src/providers/openrouter.models.ts +++ b/packages/ai/src/providers/openrouter.models.ts @@ -857,24 +857,6 @@ export const OPENROUTER_MODELS = { contextWindow: 1048576, maxTokens: 65535, } satisfies Model<"openai-completions">, - "google/gemini-2.5-flash-lite-preview-09-2025": { - id: "google/gemini-2.5-flash-lite-preview-09-2025", - name: "Google: Gemini 2.5 Flash Lite Preview 09-2025", - api: "openai-completions", - provider: "openrouter", - baseUrl: "https://openrouter.ai/api/v1", - compat: {"supportsDeveloperRole":false,"thinkingFormat":"openrouter"}, - reasoning: true, - input: ["text", "image"], - cost: { - input: 0.1, - output: 0.4, - cacheRead: 0.01, - cacheWrite: 0.083333, - }, - contextWindow: 1048576, - maxTokens: 65535, - } satisfies Model<"openai-completions">, "google/gemini-2.5-pro": { id: "google/gemini-2.5-pro", name: "Google: Gemini 2.5 Pro", @@ -1462,9 +1444,9 @@ export const OPENROUTER_MODELS = { reasoning: true, input: ["text"], cost: { - input: 0.12, - output: 0.48, - cacheRead: 0, + input: 0.15, + output: 0.9, + cacheRead: 0.05, cacheWrite: 0, }, contextWindow: 204800, @@ -1480,8 +1462,8 @@ export const OPENROUTER_MODELS = { reasoning: true, input: ["text"], cost: { - input: 0.18, - output: 0.72, + input: 0.24, + output: 0.96, cacheRead: 0, cacheWrite: 0, }, @@ -1912,13 +1894,13 @@ export const OPENROUTER_MODELS = { reasoning: true, input: ["text", "image"], cost: { - input: 0.74, + input: 0.72, output: 3.5, cacheRead: 0.15, cacheWrite: 0, }, contextWindow: 262144, - maxTokens: 16384, + maxTokens: 262144, } satisfies Model<"openai-completions">, "nex-agi/nex-n2-mini": { id: "nex-agi/nex-n2-mini", @@ -2814,6 +2796,120 @@ export const OPENROUTER_MODELS = { contextWindow: 1050000, maxTokens: 128000, } satisfies Model<"openai-completions">, + "openai/gpt-5.6-luna": { + id: "openai/gpt-5.6-luna", + name: "OpenAI: GPT-5.6 Luna", + api: "openai-completions", + provider: "openrouter", + baseUrl: "https://openrouter.ai/api/v1", + compat: {"thinkingFormat":"openrouter"}, + reasoning: true, + thinkingLevelMap: {"xhigh":"xhigh"}, + input: ["text", "image"], + cost: { + input: 1, + output: 6, + cacheRead: 0.1, + cacheWrite: 0, + }, + contextWindow: 1050000, + maxTokens: 128000, + } satisfies Model<"openai-completions">, + "openai/gpt-5.6-luna-pro": { + id: "openai/gpt-5.6-luna-pro", + name: "OpenAI: GPT-5.6 Luna Pro", + api: "openai-completions", + provider: "openrouter", + baseUrl: "https://openrouter.ai/api/v1", + compat: {"thinkingFormat":"openrouter"}, + reasoning: true, + thinkingLevelMap: {"xhigh":"xhigh"}, + input: ["text", "image"], + cost: { + input: 1, + output: 6, + cacheRead: 0.1, + cacheWrite: 0, + }, + contextWindow: 1050000, + maxTokens: 128000, + } satisfies Model<"openai-completions">, + "openai/gpt-5.6-sol": { + id: "openai/gpt-5.6-sol", + name: "OpenAI: GPT-5.6 Sol", + api: "openai-completions", + provider: "openrouter", + baseUrl: "https://openrouter.ai/api/v1", + compat: {"thinkingFormat":"openrouter"}, + reasoning: true, + thinkingLevelMap: {"xhigh":"xhigh"}, + input: ["text", "image"], + cost: { + input: 5, + output: 30, + cacheRead: 0.5, + cacheWrite: 0, + }, + contextWindow: 1050000, + maxTokens: 128000, + } satisfies Model<"openai-completions">, + "openai/gpt-5.6-sol-pro": { + id: "openai/gpt-5.6-sol-pro", + name: "OpenAI: GPT-5.6 Sol Pro", + api: "openai-completions", + provider: "openrouter", + baseUrl: "https://openrouter.ai/api/v1", + compat: {"thinkingFormat":"openrouter"}, + reasoning: true, + thinkingLevelMap: {"xhigh":"xhigh"}, + input: ["text", "image"], + cost: { + input: 5, + output: 30, + cacheRead: 0.5, + cacheWrite: 0, + }, + contextWindow: 1050000, + maxTokens: 128000, + } satisfies Model<"openai-completions">, + "openai/gpt-5.6-terra": { + id: "openai/gpt-5.6-terra", + name: "OpenAI: GPT-5.6 Terra", + api: "openai-completions", + provider: "openrouter", + baseUrl: "https://openrouter.ai/api/v1", + compat: {"thinkingFormat":"openrouter"}, + reasoning: true, + thinkingLevelMap: {"xhigh":"xhigh"}, + input: ["text", "image"], + cost: { + input: 2.5, + output: 15, + cacheRead: 0.25, + cacheWrite: 0, + }, + contextWindow: 1050000, + maxTokens: 128000, + } satisfies Model<"openai-completions">, + "openai/gpt-5.6-terra-pro": { + id: "openai/gpt-5.6-terra-pro", + name: "OpenAI: GPT-5.6 Terra Pro", + api: "openai-completions", + provider: "openrouter", + baseUrl: "https://openrouter.ai/api/v1", + compat: {"thinkingFormat":"openrouter"}, + reasoning: true, + thinkingLevelMap: {"xhigh":"xhigh"}, + input: ["text", "image"], + cost: { + input: 2.5, + output: 15, + cacheRead: 0.25, + cacheWrite: 0, + }, + contextWindow: 1050000, + maxTokens: 128000, + } satisfies Model<"openai-completions">, "openai/gpt-audio": { id: "openai/gpt-audio", name: "OpenAI: GPT Audio", @@ -2878,13 +2974,13 @@ export const OPENROUTER_MODELS = { reasoning: true, input: ["text"], cost: { - input: 0.03, - output: 0.15, + input: 0.036, + output: 0.18, cacheRead: 0, cacheWrite: 0, }, contextWindow: 131072, - maxTokens: 131072, + maxTokens: 4096, } satisfies Model<"openai-completions">, "openai/gpt-oss-120b:free": { id: "openai/gpt-oss-120b:free", @@ -3246,42 +3342,6 @@ export const OPENROUTER_MODELS = { contextWindow: 262144, maxTokens: 32768, } satisfies Model<"openai-completions">, - "poolside/laguna-xs.2": { - id: "poolside/laguna-xs.2", - name: "Poolside: Laguna XS.2", - api: "openai-completions", - provider: "openrouter", - baseUrl: "https://openrouter.ai/api/v1", - compat: {"supportsDeveloperRole":false,"thinkingFormat":"openrouter"}, - reasoning: true, - input: ["text"], - cost: { - input: 0.1, - output: 0.2, - cacheRead: 0.05, - cacheWrite: 0, - }, - contextWindow: 262144, - maxTokens: 32768, - } satisfies Model<"openai-completions">, - "poolside/laguna-xs.2:free": { - id: "poolside/laguna-xs.2:free", - name: "Poolside: Laguna XS.2 (free)", - api: "openai-completions", - provider: "openrouter", - baseUrl: "https://openrouter.ai/api/v1", - compat: {"supportsDeveloperRole":false,"thinkingFormat":"openrouter"}, - reasoning: true, - input: ["text"], - cost: { - input: 0, - output: 0, - cacheRead: 0, - cacheWrite: 0, - }, - contextWindow: 262144, - maxTokens: 32768, - } satisfies Model<"openai-completions">, "qwen/qwen-2.5-72b-instruct": { id: "qwen/qwen-2.5-72b-instruct", name: "Qwen2.5 72B Instruct", @@ -4625,13 +4685,13 @@ export const OPENROUTER_MODELS = { thinkingLevelMap: {"xhigh":"xhigh"}, input: ["text"], cost: { - input: 0.9, - output: 3.08, - cacheRead: 0.18, + input: 0.54, + output: 1.76, + cacheRead: 0.1, cacheWrite: 0, }, contextWindow: 1048576, - maxTokens: 1048576, + maxTokens: 101376, } satisfies Model<"openai-completions">, "z-ai/glm-5v-turbo": { id: "z-ai/glm-5v-turbo", diff --git a/packages/ai/src/providers/vercel-ai-gateway.models.ts b/packages/ai/src/providers/vercel-ai-gateway.models.ts index b376bca8..997265cd 100644 --- a/packages/ai/src/providers/vercel-ai-gateway.models.ts +++ b/packages/ai/src/providers/vercel-ai-gateway.models.ts @@ -2508,6 +2508,60 @@ export const VERCEL_AI_GATEWAY_MODELS = { contextWindow: 1000000, maxTokens: 128000, } satisfies Model<"anthropic-messages">, + "openai/gpt-5.6-luna": { + id: "openai/gpt-5.6-luna", + name: "GPT 5.6 Luna", + api: "anthropic-messages", + provider: "vercel-ai-gateway", + baseUrl: "https://ai-gateway.vercel.sh", + reasoning: true, + thinkingLevelMap: {"xhigh":"xhigh"}, + input: ["text", "image"], + cost: { + input: 1, + output: 6, + cacheRead: 0.1, + cacheWrite: 1.25, + }, + contextWindow: 1050000, + maxTokens: 128000, + } satisfies Model<"anthropic-messages">, + "openai/gpt-5.6-sol": { + id: "openai/gpt-5.6-sol", + name: "GPT 5.6 Sol", + api: "anthropic-messages", + provider: "vercel-ai-gateway", + baseUrl: "https://ai-gateway.vercel.sh", + reasoning: true, + thinkingLevelMap: {"xhigh":"xhigh"}, + input: ["text", "image"], + cost: { + input: 5, + output: 30, + cacheRead: 0.5, + cacheWrite: 6.25, + }, + contextWindow: 1050000, + maxTokens: 128000, + } satisfies Model<"anthropic-messages">, + "openai/gpt-5.6-terra": { + id: "openai/gpt-5.6-terra", + name: "GPT 5.6 Terra", + api: "anthropic-messages", + provider: "vercel-ai-gateway", + baseUrl: "https://ai-gateway.vercel.sh", + reasoning: true, + thinkingLevelMap: {"xhigh":"xhigh"}, + input: ["text", "image"], + cost: { + input: 2.5, + output: 15, + cacheRead: 0.25, + cacheWrite: 3.125, + }, + contextWindow: 1050000, + maxTokens: 128000, + } satisfies Model<"anthropic-messages">, "openai/gpt-oss-120b": { id: "openai/gpt-oss-120b", name: "GPT OSS 120B", diff --git a/packages/ai/test/openai-responses-copilot-provider.test.ts b/packages/ai/test/openai-responses-copilot-provider.test.ts index 57c319f2..0f925c8b 100644 --- a/packages/ai/test/openai-responses-copilot-provider.test.ts +++ b/packages/ai/test/openai-responses-copilot-provider.test.ts @@ -91,42 +91,51 @@ describe("openai-responses provider defaults", () => { }); }); - it.each(["gpt-5.1", "gpt-5.2", "gpt-5.3-codex", "gpt-5.4", "gpt-5.4-mini", "gpt-5.4-nano", "gpt-5.5"] as const)( - "sends none reasoning effort for OpenAI %s when no reasoning is requested", - async (modelId) => { - const model = getModel("openai", modelId); - let capturedPayload: unknown; + it.each([ + "gpt-5.1", + "gpt-5.2", + "gpt-5.3-codex", + "gpt-5.4", + "gpt-5.4-mini", + "gpt-5.4-nano", + "gpt-5.5", + "gpt-5.6", + "gpt-5.6-sol", + "gpt-5.6-terra", + "gpt-5.6-luna", + ] as const)("sends none reasoning effort for OpenAI %s when no reasoning is requested", async (modelId) => { + const model = getModel("openai", modelId); + let capturedPayload: unknown; - vi.spyOn(globalThis, "fetch").mockResolvedValue( - new Response("data: [DONE]\n\n", { - status: 200, - headers: { "content-type": "text/event-stream" }, - }), - ); + vi.spyOn(globalThis, "fetch").mockResolvedValue( + new Response("data: [DONE]\n\n", { + status: 200, + headers: { "content-type": "text/event-stream" }, + }), + ); - const stream = streamOpenAIResponses( - model, - { - systemPrompt: "sys", - messages: [{ role: "user", content: "hi", timestamp: Date.now() }], + const stream = streamOpenAIResponses( + model, + { + systemPrompt: "sys", + messages: [{ role: "user", content: "hi", timestamp: Date.now() }], + }, + { + apiKey: "test-key", + onPayload: (payload) => { + capturedPayload = payload; }, - { - apiKey: "test-key", - onPayload: (payload) => { - capturedPayload = payload; - }, - }, - ); + }, + ); - for await (const event of stream) { - if (event.type === "done" || event.type === "error") break; - } + for await (const event of stream) { + if (event.type === "done" || event.type === "error") break; + } - expect(capturedPayload).toMatchObject({ - reasoning: { effort: "none" }, - }); - }, - ); + expect(capturedPayload).toMatchObject({ + reasoning: { effort: "none" }, + }); + }); it.each(["gpt-5", "gpt-5-mini", "gpt-5-nano", "gpt-5-pro", "gpt-5.2-pro", "gpt-5.4-pro", "gpt-5.5-pro"] as const)( "omits reasoning effort for OpenAI %s when off is unsupported", diff --git a/packages/ai/test/supports-xhigh.test.ts b/packages/ai/test/supports-xhigh.test.ts index 257758dc..d52575e8 100644 --- a/packages/ai/test/supports-xhigh.test.ts +++ b/packages/ai/test/supports-xhigh.test.ts @@ -33,11 +33,23 @@ describe("getSupportedThinkingLevels", () => { expect(getSupportedThinkingLevels(model!)).not.toContain("xhigh"); }); - it.each(["gpt-5.4", "gpt-5.5"] as const)("includes xhigh for %s models", (modelId) => { - const model = getModel("openai-codex", modelId); - expect(model).toBeDefined(); - expect(getSupportedThinkingLevels(model!)).toContain("xhigh"); - }); + it.each(["gpt-5.4", "gpt-5.5", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"] as const)( + "includes xhigh for openai-codex %s models", + (modelId) => { + const model = getModel("openai-codex", modelId); + expect(model).toBeDefined(); + expect(getSupportedThinkingLevels(model!)).toContain("xhigh"); + }, + ); + + it.each(["gpt-5.6", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"] as const)( + "includes xhigh for OpenAI %s models", + (modelId) => { + const model = getModel("openai", modelId); + expect(model).toBeDefined(); + expect(getSupportedThinkingLevels(model!)).toContain("xhigh"); + }, + ); it("includes only medium/high/xhigh for OpenAI GPT-5.5 Pro", () => { const model = getModel("openai", "gpt-5.5-pro"); diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index bd6c5289..def72907 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -4,6 +4,7 @@ ### Added +- Added inherited OpenAI GPT-5.6 model metadata for `gpt-5.6`, `gpt-5.6-sol`, `gpt-5.6-terra`, and `gpt-5.6-luna`, plus verified `openai-codex` support for `gpt-5.6-sol`, `gpt-5.6-terra`, and `gpt-5.6-luna`. - Added `/login ` support with provider autocomplete. - Added public SDK exports for CLI-equivalent model and scoped-model resolution ([#6201](https://github.com/earendil-works/pi/issues/6201)). - Added extension and RPC `agent_settled` events plus session-level idle waiting for fully settled agent runs ([#6363](https://github.com/earendil-works/pi/issues/6363)).