From 0e013978a93579f265b91d1b70f67602a7d68279 Mon Sep 17 00:00:00 2001 From: Bulat Yapparov Date: Thu, 20 Aug 2026 11:56:22 +0100 Subject: [PATCH] feat: add GPT-5.6 OpenAI models --- CHANGELOG.md | 1 + packages/cli/package.json | 2 +- packages/cli/src/plugin/codex.ts | 11 +++ packages/cli/src/provider/transform.ts | 35 +++++++--- packages/cli/test/plugin/codex.test.ts | 67 +++++++++++++++++++ packages/cli/test/provider/transform.test.ts | 49 ++++++++++++++ .../cli/test/tool/fixtures/models-api.json | 57 ++++++++++++++++ 7 files changed, 211 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee5be54..8cc2381 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Features +- **GPT-5.6 Codex models** — Added OpenAI's Sol, Terra, and Luna models with API and subscription-backed reasoning effort variants, including the Codex-only `ultra` alias for Sol and Terra. - **GLM-5.3 model support** — Added the latest Z.AI Coding Plan model with its 1M-token context window and native `low`, `high`, and `max` reasoning efforts. ### Compatibility diff --git a/packages/cli/package.json b/packages/cli/package.json index eca491f..7fe81d0 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "0.4.2", + "version": "0.4.3", "name": "@aictrl/cli", "description": "Headless execution engine for AI agent skills", "type": "module", diff --git a/packages/cli/src/plugin/codex.ts b/packages/cli/src/plugin/codex.ts index d815d54..3552377 100644 --- a/packages/cli/src/plugin/codex.ts +++ b/packages/cli/src/plugin/codex.ts @@ -4,6 +4,7 @@ import { Installation } from "../installation" import { Auth, OAUTH_DUMMY_KEY } from "../auth" import os from "os" import { ProviderTransform } from "@/provider/transform" +import type { Provider } from "@/provider/provider" const log = Log.create({ service: "plugin.codex" }) @@ -357,6 +358,7 @@ export async function CodexAuthPlugin(input: PluginInput): Promise { if (auth.type !== "oauth") return {} // Filter models to only allowed Codex models for OAuth + const models = ["gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"] const allowedModels = new Set([ "gpt-5.1-codex-max", "gpt-5.1-codex-mini", @@ -364,6 +366,7 @@ export async function CodexAuthPlugin(input: PluginInput): Promise { "gpt-5.2-codex", "gpt-5.3-codex", "gpt-5.1-codex", + ...models, ]) for (const modelId of Object.keys(provider.models)) { if (modelId.includes("codex")) continue @@ -403,6 +406,14 @@ export async function CodexAuthPlugin(input: PluginInput): Promise { provider.models["gpt-5.3-codex"] = model } + for (const id of models) { + const model = provider.models[id] as Provider.Model | undefined + if (!model) continue + model.family = "gpt-codex" + model.limit = { context: 400_000, input: 272_000, output: 128_000 } + model.variants = ProviderTransform.variants(model) + } + // Zero out costs for Codex (included with ChatGPT subscription) for (const model of Object.values(provider.models)) { model.cost = { diff --git a/packages/cli/src/provider/transform.ts b/packages/cli/src/provider/transform.ts index 98b2a29..67481d3 100644 --- a/packages/cli/src/provider/transform.ts +++ b/packages/cli/src/provider/transform.ts @@ -329,6 +329,8 @@ export namespace ProviderTransform { const WIDELY_SUPPORTED_EFFORTS = ["low", "medium", "high"] const OPENAI_EFFORTS = ["none", "minimal", ...WIDELY_SUPPORTED_EFFORTS, "xhigh"] + const OPENAI_GPT_5_6_EFFORTS = ["none", ...WIDELY_SUPPORTED_EFFORTS, "xhigh", "max"] + const OPENAI_GPT_5_6_CODEX_EFFORTS = [...WIDELY_SUPPORTED_EFFORTS, "xhigh", "max"] export function variants(model: Provider.Model): Record> { if (!model.capabilities.reasoning) { @@ -486,7 +488,7 @@ export namespace ProviderTransform { case "@ai-sdk/deepinfra": // https://v5.ai-sdk.dev/providers/ai-sdk-providers/deepinfra case "venice-ai-sdk-provider": - // https://docs.venice.ai/overview/guides/reasoning-models#reasoning-effort + // https://docs.venice.ai/overview/guides/reasoning-models#reasoning-effort return Object.fromEntries(WIDELY_SUPPORTED_EFFORTS.map((effort) => [effort, { reasoningEffort: effort }])) case "@ai-sdk/openai-compatible": @@ -513,6 +515,13 @@ export namespace ProviderTransform { // https://v5.ai-sdk.dev/providers/ai-sdk-providers/openai if (id === "gpt-5-pro") return {} const openaiEfforts = iife(() => { + if (["gpt-5.6", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"].includes(model.api.id)) { + if (model.family === "gpt-codex" && model.api.id !== "gpt-5.6-luna") { + return [...OPENAI_GPT_5_6_CODEX_EFFORTS, "ultra"] + } + if (model.family === "gpt-codex") return OPENAI_GPT_5_6_CODEX_EFFORTS + return OPENAI_GPT_5_6_EFFORTS + } if (id.includes("codex")) { if (id.includes("5.2") || id.includes("5.3")) return [...WIDELY_SUPPORTED_EFFORTS, "xhigh"] return WIDELY_SUPPORTED_EFFORTS @@ -530,14 +539,17 @@ export namespace ProviderTransform { return arr }) return Object.fromEntries( - openaiEfforts.map((effort) => [ - effort, - { - reasoningEffort: effort, - reasoningSummary: "auto", - include: ["reasoning.encrypted_content"], - }, - ]), + openaiEfforts.map((effort) => { + const value = effort === "ultra" ? "max" : effort + return [ + effort, + { + reasoningEffort: value, + reasoningSummary: "auto", + include: ["reasoning.encrypted_content"], + }, + ] + }), ) case "@ai-sdk/anthropic": @@ -736,7 +748,10 @@ export namespace ProviderTransform { result["chat_template_args"] = { enable_thinking: true } } - if (["zai", "zai-coding-plan", "zhipuai"].includes(input.model.providerID) && input.model.api.npm === "@ai-sdk/openai-compatible") { + if ( + ["zai", "zai-coding-plan", "zhipuai"].includes(input.model.providerID) && + input.model.api.npm === "@ai-sdk/openai-compatible" + ) { result["thinking"] = { type: "enabled", clear_thinking: false, diff --git a/packages/cli/test/plugin/codex.test.ts b/packages/cli/test/plugin/codex.test.ts index 74d28ac..4c8fde0 100644 --- a/packages/cli/test/plugin/codex.test.ts +++ b/packages/cli/test/plugin/codex.test.ts @@ -1,5 +1,6 @@ import { describe, expect, test } from "bun:test" import { + CodexAuthPlugin, parseJwtClaims, extractAccountIdFromClaims, extractAccountId, @@ -120,4 +121,70 @@ describe("plugin.codex", () => { ).toBe("acc-123") }) }) + + test("exposes GPT-5.6 Codex models with their supported effort levels", async () => { + const hooks = await CodexAuthPlugin({} as never) + if (!hooks.auth?.loader) throw new Error("Codex auth loader is missing") + const provider = { + models: Object.fromEntries( + ["gpt-4o", "gpt-5.3-codex", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"].map((id) => [ + id, + { + id, + providerID: "openai", + api: { id, url: "https://api.openai.com", npm: "@ai-sdk/openai" }, + name: id, + family: "gpt", + capabilities: { + temperature: false, + reasoning: true, + attachment: true, + toolcall: true, + input: { text: true, audio: false, image: true, video: false, pdf: true }, + output: { text: true, audio: false, image: false, video: false, pdf: false }, + interleaved: false, + }, + cost: { input: 1, output: 1, cache: { read: 1, write: 1 } }, + limit: { context: 1_050_000, input: 922_000, output: 128_000 }, + status: "active", + options: {}, + headers: {}, + release_date: "2026-07-09", + variants: {} as Record>, + }, + ]), + ), + } + + await hooks.auth.loader( + async () => ({ type: "oauth", refresh: "refresh", access: "access", expires: Date.now() + 60_000 }), + provider as never, + ) + + expect(provider.models["gpt-4o"]).toBeUndefined() + expect(provider.models["gpt-5.6-sol"].limit).toEqual({ context: 400_000, input: 272_000, output: 128_000 }) + expect(Object.keys(provider.models["gpt-5.6-sol"].variants)).toEqual([ + "low", + "medium", + "high", + "xhigh", + "max", + "ultra", + ]) + expect(Object.keys(provider.models["gpt-5.6-terra"].variants)).toEqual([ + "low", + "medium", + "high", + "xhigh", + "max", + "ultra", + ]) + expect(Object.keys(provider.models["gpt-5.6-luna"].variants)).toEqual(["low", "medium", "high", "xhigh", "max"]) + expect(provider.models["gpt-5.6-sol"].variants.ultra).toEqual({ + reasoningEffort: "max", + reasoningSummary: "auto", + include: ["reasoning.encrypted_content"], + }) + expect(provider.models["gpt-5.6-luna"].variants.ultra).toBeUndefined() + }) }) diff --git a/packages/cli/test/provider/transform.test.ts b/packages/cli/test/provider/transform.test.ts index 68dd026..c758136 100644 --- a/packages/cli/test/provider/transform.test.ts +++ b/packages/cli/test/provider/transform.test.ts @@ -2178,6 +2178,55 @@ describe("ProviderTransform.variants", () => { const result = ProviderTransform.variants(model) expect(Object.keys(result)).toEqual(["none", "minimal", "low", "medium", "high", "xhigh"]) }) + + test.each(["gpt-5.6", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"])( + "%s exposes every supported API reasoning effort", + (id) => { + const model = createMockModel({ + id, + providerID: "openai", + api: { + id, + url: "https://api.openai.com", + npm: "@ai-sdk/openai", + }, + release_date: "2026-07-09", + }) + const result = ProviderTransform.variants(model) + expect(Object.keys(result)).toEqual(["none", "low", "medium", "high", "xhigh", "max"]) + expect(result.max).toEqual({ + reasoningEffort: "max", + reasoningSummary: "auto", + include: ["reasoning.encrypted_content"], + }) + }, + ) + + test.each([ + { id: "gpt-5.6-sol", efforts: ["low", "medium", "high", "xhigh", "max", "ultra"] }, + { id: "gpt-5.6-terra", efforts: ["low", "medium", "high", "xhigh", "max", "ultra"] }, + { id: "gpt-5.6-luna", efforts: ["low", "medium", "high", "xhigh", "max"] }, + ])("$id exposes its Codex reasoning efforts", ({ id, efforts }) => { + const model = createMockModel({ + id, + providerID: "openai", + family: "gpt-codex", + api: { + id, + url: "https://chatgpt.com/backend-api/codex", + npm: "@ai-sdk/openai", + }, + release_date: "2026-07-09", + }) + const result = ProviderTransform.variants(model) + expect(Object.keys(result)).toEqual([...efforts]) + if (id === "gpt-5.6-luna") return + expect(result.ultra).toEqual({ + reasoningEffort: "max", + reasoningSummary: "auto", + include: ["reasoning.encrypted_content"], + }) + }) }) describe("@ai-sdk/anthropic", () => { diff --git a/packages/cli/test/tool/fixtures/models-api.json b/packages/cli/test/tool/fixtures/models-api.json index c933ae5..0364401 100644 --- a/packages/cli/test/tool/fixtures/models-api.json +++ b/packages/cli/test/tool/fixtures/models-api.json @@ -24977,6 +24977,63 @@ "name": "OpenAI", "doc": "https://platform.openai.com/docs/models", "models": { + "gpt-5.6-sol": { + "id": "gpt-5.6-sol", + "name": "GPT-5.6 Sol", + "description": "Frontier GPT-5.6 model for complex professional work, coding, and agentic workflows", + "family": "gpt-sol", + "attachment": true, + "reasoning": true, + "reasoning_options": [{ "type": "effort", "values": ["none", "low", "medium", "high", "xhigh", "max"] }], + "tool_call": true, + "structured_output": true, + "temperature": false, + "knowledge": "2026-02-16", + "release_date": "2026-07-09", + "last_updated": "2026-07-09", + "modalities": { "input": ["text", "image", "pdf"], "output": ["text"] }, + "open_weights": false, + "cost": { "input": 5, "output": 30, "cache_read": 0.5, "cache_write": 6.25 }, + "limit": { "context": 1050000, "input": 922000, "output": 128000 } + }, + "gpt-5.6-terra": { + "id": "gpt-5.6-terra", + "name": "GPT-5.6 Terra", + "description": "Balanced GPT-5.6 model for capable, cost-efficient everyday work", + "family": "gpt-terra", + "attachment": true, + "reasoning": true, + "reasoning_options": [{ "type": "effort", "values": ["none", "low", "medium", "high", "xhigh", "max"] }], + "tool_call": true, + "structured_output": true, + "temperature": false, + "knowledge": "2026-02-16", + "release_date": "2026-07-09", + "last_updated": "2026-07-09", + "modalities": { "input": ["text", "image", "pdf"], "output": ["text"] }, + "open_weights": false, + "cost": { "input": 2, "output": 12, "cache_read": 0.2, "cache_write": 2.5 }, + "limit": { "context": 1050000, "input": 922000, "output": 128000 } + }, + "gpt-5.6-luna": { + "id": "gpt-5.6-luna", + "name": "GPT-5.6 Luna", + "description": "Cost-efficient GPT-5.6 model for fast, high-volume workloads", + "family": "gpt-luna", + "attachment": true, + "reasoning": true, + "reasoning_options": [{ "type": "effort", "values": ["none", "low", "medium", "high", "xhigh", "max"] }], + "tool_call": true, + "structured_output": true, + "temperature": false, + "knowledge": "2026-02-16", + "release_date": "2026-07-09", + "last_updated": "2026-07-09", + "modalities": { "input": ["text", "image", "pdf"], "output": ["text"] }, + "open_weights": false, + "cost": { "input": 0.2, "output": 1.2, "cache_read": 0.02, "cache_write": 0.25 }, + "limit": { "context": 1050000, "input": 922000, "output": 128000 } + }, "gpt-4.1-nano": { "id": "gpt-4.1-nano", "name": "GPT-4.1 nano",