Skip to content
5 changes: 4 additions & 1 deletion docs/config/models.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ Mux ships with curated models kept up to date with the frontier. Use any custom
| Opus 4.8 | anthropic:claude-opus-4-8 | `opus` | ✓ |
| Sonnet 5 | anthropic:claude-sonnet-5 | `sonnet` | |
| Haiku 4.5 | anthropic:claude-haiku-4-5 | `haiku` | |
| GPT-5.5 | openai:gpt-5.5 | `gpt`, `gpt-5.5` | |
| GPT-5.5 | openai:gpt-5.5 | `gpt-5.5` | |
| GPT-5.5 Pro | openai:gpt-5.5-pro | `gpt-pro`, `gpt-5.5-pro` | |
| GPT-5.6 Sol | openai:gpt-5.6-sol | `gpt`, `sol`, `gpt-5.6-sol` | |
| GPT-5.6 Terra | openai:gpt-5.6-terra | `terra`, `gpt-5.6-terra` | |
| GPT-5.6 Luna | openai:gpt-5.6-luna | `luna`, `gpt-5.6-luna` | |
| GPT-5.4 Mini | openai:gpt-5.4-mini | `gpt-mini` | |
| GPT-5.4 Nano | openai:gpt-5.4-nano | `gpt-nano` | |
| Codex 5.3 | openai:gpt-5.3-codex | `codex`, `codex-5.3` | |
Expand Down
4 changes: 4 additions & 0 deletions src/common/constants/codexOAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ export const CODEX_OAUTH_ALLOWED_MODELS = new Set<string>([
"gpt-5.2",
"gpt-5.4-mini",
"gpt-5.5",
// GPT-5.6 tiers ship in both Codex and the public API (GA July 9, 2026).
"gpt-5.6-sol",
"gpt-5.6-terra",
"gpt-5.6-luna",
"gpt-5.2-codex",
"gpt-5.3-codex",
"gpt-5.3-codex-spark",
Expand Down
36 changes: 34 additions & 2 deletions src/common/constants/knownModels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,12 @@ const MODEL_DEFINITIONS = {
aliases: ["haiku"],
tokenizerOverride: "anthropic/claude-3.5-haiku",
},
// GPT alias tracks the latest stable GPT-5 tier.
// Previous flagship tier; kept selectable via its explicit id alias.
// The bare `gpt` alias moved to GPT_56_SOL when GPT-5.6 went GA (July 9, 2026).
GPT: {
provider: "openai",
providerModelId: "gpt-5.5",
aliases: ["gpt", "gpt-5.5"],
aliases: ["gpt-5.5"],
warm: true,
tokenizerOverride: "openai/gpt-5",
},
Expand All @@ -101,6 +102,37 @@ const MODEL_DEFINITIONS = {
warm: true,
tokenizerOverride: "openai/gpt-5",
},
// GPT-5.6 family - previewed June 26, 2026; generally available July 9, 2026 across
// ChatGPT, Codex, and the API (verified callable via plain API keys). New naming
// system: the number is the generation, while Sol/Terra/Luna are durable capability
// tiers. Cache writes bill at 1.25x input; cache reads keep the 90% discount.
// All tiers support a native "max" reasoning effort (see the thinking policy).
// The API also offers `reasoning.mode: "pro"`, not yet implemented in Mux (planned
// as a thinking-slider toggle; tracked in issue #3704).
// GPT-5.6 Sol - flagship tier. $5/M input, $30/M output. Bare `gpt` alias lives here:
// Sol succeeds gpt-5.5 as the flagship at the same list price.
GPT_56_SOL: {
provider: "openai",
providerModelId: "gpt-5.6-sol",
aliases: ["gpt", "sol", "gpt-5.6-sol"],
warm: true,
tokenizerOverride: "openai/gpt-5",
},
// GPT-5.6 Terra - balanced tier; GPT-5.5-competitive at half the cost.
// $2.50/M input, $15/M output.
GPT_56_TERRA: {
provider: "openai",
providerModelId: "gpt-5.6-terra",
aliases: ["terra", "gpt-5.6-terra"],
tokenizerOverride: "openai/gpt-5",
},
// GPT-5.6 Luna - fastest/cheapest tier. $1/M input, $6/M output.
GPT_56_LUNA: {
provider: "openai",
providerModelId: "gpt-5.6-luna",
aliases: ["luna", "gpt-5.6-luna"],
tokenizerOverride: "openai/gpt-5",
},
// GPT Mini alias tracks the latest stable GPT-5 mini tier.
GPT_54_MINI: {
provider: "openai",
Expand Down
10 changes: 10 additions & 0 deletions src/common/types/thinking.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ describe("getThinkingDisplayLabel", () => {
expect(getThinkingDisplayLabel("max", "mux-gateway:openai/gpt-5.2")).toBe("XHIGH");
});

test("keeps xhigh and max distinguishable on GPT-5.6 (native max effort)", () => {
expect(getThinkingDisplayLabel("xhigh", "openai:gpt-5.6-sol")).toBe("XHIGH");
expect(getThinkingDisplayLabel("max", "openai:gpt-5.6-sol")).toBe("MAX");
expect(getThinkingDisplayLabel("max", "openai:gpt-5.6-terra")).toBe("MAX");
expect(getThinkingDisplayLabel("max", "mux-gateway:openai/gpt-5.6-luna")).toBe("MAX");
// Option labels (settings dropdowns) must diverge too
expect(getThinkingOptionLabel("xhigh", "openai:gpt-5.6-sol")).toBe("xhigh");
expect(getThinkingOptionLabel("max", "openai:gpt-5.6-sol")).toBe("max");
});

test("returns MAX for xhigh/max when no model specified (default)", () => {
expect(getThinkingDisplayLabel("xhigh")).toBe("MAX");
expect(getThinkingDisplayLabel("max")).toBe("MAX");
Expand Down
30 changes: 28 additions & 2 deletions src/common/types/thinking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,13 @@ export function getThinkingDisplayLabel(level: ThinkingLevel, modelString?: stri
const normalized = modelString.trim().toLowerCase();
const withoutPrefix = normalized.replace(/^[a-z0-9_-]+:\s*/, "");

// OpenAI: both xhigh and max resolve to "xhigh" reasoning effort
if (normalized.startsWith("openai:") || withoutPrefix.startsWith("openai/")) return "XHIGH";
if (normalized.startsWith("openai:") || withoutPrefix.startsWith("openai/")) {
// GPT-5.6 has a native "max" reasoning effort distinct from xhigh, so both
// labels must stay distinguishable in settings dropdowns and the slider.
if (level === "max" && openaiSupportsNativeMaxEffort(modelString)) return "MAX";
// Other OpenAI models: both xhigh and max resolve to "xhigh" reasoning effort
return "XHIGH";
}

// Anthropic Opus 4.7+: xhigh is a distinct effort level from max
if (level === "xhigh" && anthropicSupportsNativeXhigh(modelString)) return "XHIGH";
Expand Down Expand Up @@ -237,6 +242,24 @@ export function anthropicSupportsNativeXhigh(modelString: string): boolean {
);
}

/**
* Whether the given OpenAI model supports the native "max" reasoning effort
* (GPT-5.6 family — Sol/Terra/Luna, GA July 9, 2026 — including version-suffixed
* ids like `gpt-5.6-sol-2026-07-09`). OpenAI recommends max effort "for demanding
* tasks that need more exploration and verification".
*
* Only valid on the Responses API path: the @ai-sdk/openai Responses schema
* accepts arbitrary effort strings, but the Chat Completions schema rejects
* anything outside its enum — callers must clamp to "xhigh" there.
*
* Note: GPT-5.6 also supports `reasoning.mode: "pro"` (more model work for
* reliability, single final answer). Mux does not implement it yet — planned as
* a toggle inside the thinking slider; tracked in issue #3704.
*/
export function openaiSupportsNativeMaxEffort(modelString: string): boolean {
return /^gpt-5\.6-(?:sol|terra|luna)(?!-[a-z])/.test(stripModelProviderPrefixes(modelString));
}

/**
* Whether the given Anthropic model rejects `thinking: { type: "disabled" }`.
*
Expand Down Expand Up @@ -276,6 +299,9 @@ export const OPENAI_REASONING_EFFORT: Record<ThinkingLevel, string | undefined>
medium: "medium",
high: "high",
xhigh: "xhigh", // Maps 1:1 to OpenAI's reasoning effort value
// Shared clamp for models without a native max effort. GPT-5.6 (see
// openaiSupportsNativeMaxEffort) overrides this to "max" in buildProviderOptions
// on the Responses API path.
max: "xhigh",
};

Expand Down
39 changes: 39 additions & 0 deletions src/common/utils/ai/providerOptions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,45 @@ describe("buildProviderOptions - OpenAI", () => {
expect(openai!.parallelToolCalls).toBe(true);
});

describe("GPT-5.6 native max reasoning effort", () => {
test.each(["gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"])(
"sends native max effort for %s on the Responses API",
(modelId) => {
const result = buildProviderOptions(`openai:${modelId}`, "max");
const openai = getOpenAIOptions(result);

expect(openai).toBeDefined();
expect(openai!.reasoningEffort).toBe("max");
}
);

test("clamps max to xhigh on the Chat Completions wire format", () => {
const result = buildProviderOptions("openai:gpt-5.6-sol", "max", undefined, undefined, {
openai: { wireFormat: "chatCompletions" },
});
const openai = getOpenAIOptions(result);

expect(openai).toBeDefined();
expect(openai!.reasoningEffort).toBe("xhigh");
});

test("keeps the max→xhigh clamp for non-GPT-5.6 models", () => {
const result = buildProviderOptions("openai:gpt-5.5", "max");
const openai = getOpenAIOptions(result);

expect(openai).toBeDefined();
expect(openai!.reasoningEffort).toBe("xhigh");
});

test("non-max levels stay on the shared mapping for GPT-5.6", () => {
const result = buildProviderOptions("openai:gpt-5.6-sol", "high");
const openai = getOpenAIOptions(result);

expect(openai).toBeDefined();
expect(openai!.reasoningEffort).toBe("high");
});
});

describe("store option", () => {
test("should include store: false when muxProviderOptions sets store to false", () => {
const result = buildProviderOptions("openai:gpt-5", "medium", undefined, undefined, {
Expand Down
12 changes: 10 additions & 2 deletions src/common/utils/ai/providerOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
GEMINI_THINKING_BUDGETS,
OPENAI_REASONING_EFFORT,
OPENROUTER_REASONING_EFFORT,
openaiSupportsNativeMaxEffort,
} from "@/common/types/thinking";
import { isGeminiFlashThinkingLevelModelName } from "@/common/utils/thinking/policy";
import { resolveModelForMetadata } from "@/common/utils/providers/modelEntries";
Expand Down Expand Up @@ -353,8 +354,6 @@ export function buildProviderOptions(

// Build OpenAI-specific options
if (formatProvider === "openai") {
const reasoningEffort = OPENAI_REASONING_EFFORT[effectiveThinking];

// Mux always sends the latest conversation history explicitly. OpenAI's
// previous_response_id is an alternative state-management path, not an additive one.
// Chaining it on top of explicit history double-counts prior turns and caused GPT-5.4
Expand All @@ -374,6 +373,15 @@ export function buildProviderOptions(
const truncationMode = openaiTruncationMode ?? "disabled";
const shouldSendReasoningSummary = supportsOpenAIReasoningSummary(capModelName);

// GPT-5.6 supports a native "max" reasoning effort for demanding tasks that need
// more exploration and verification. The Responses schema in @ai-sdk/openai accepts
// arbitrary effort strings, so "max" passes through unchanged; the Chat Completions
// schema enum rejects it, so that path keeps the shared max→"xhigh" clamp.
const reasoningEffort =
effectiveThinking === "max" && isResponses && openaiSupportsNativeMaxEffort(capModelName)
? "max"
: OPENAI_REASONING_EFFORT[effectiveThinking];

log.debug("buildProviderOptions: OpenAI config", {
reasoningEffort,
shouldSendReasoningSummary,
Expand Down
25 changes: 25 additions & 0 deletions src/common/utils/thinking/policy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,31 @@ describe("getThinkingPolicyForModel", () => {
]);
});

test.each(["gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"])(
"returns all 6 levels including native max for %s",
(modelId) => {
expect(getThinkingPolicyForModel(`openai:${modelId}`)).toEqual([
"off",
"low",
"medium",
"high",
"xhigh",
"max",
]);
}
);

test("returns all 6 levels for gpt-5.6-sol behind mux-gateway with version suffix", () => {
expect(getThinkingPolicyForModel("mux-gateway:openai/gpt-5.6-sol-2026-06-26")).toEqual([
"off",
"low",
"medium",
"high",
"xhigh",
"max",
]);
});

test("returns 5 levels including xhigh for gpt-5.5", () => {
expect(getThinkingPolicyForModel("openai:gpt-5.5")).toEqual([
"off",
Expand Down
13 changes: 12 additions & 1 deletion src/common/utils/thinking/policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
THINKING_LEVEL_OFF,
anthropicRejectsDisabledThinking,
anthropicSupportsNativeXhigh,
openaiSupportsNativeMaxEffort,
stripModelProviderPrefixes,
type ThinkingLevel,
type ParsedThinkingInput,
Expand Down Expand Up @@ -54,6 +55,7 @@ export function isGeminiFlashThinkingLevelModelName(modelName: string): boolean
* - openai:gpt-5.3-codex / Spark variants →
* ["off", "low", "medium", "high", "xhigh"] (5 levels including xhigh)
* - openai:gpt-5.2 / openai:gpt-5.5 → ["off", "low", "medium", "high", "xhigh"]
* - gpt-5.6 tiers (sol/terra/luna) → all 6 levels including native "max"
* - openai:gpt-5.2-pro / openai:gpt-5.5-pro → ["medium", "high", "xhigh"] (3 levels)
* - openai:gpt-5-pro → ["high"] (only supported level, legacy)
* - Gemini Flash chat variants → ["off", "low", "medium", "high"]
Expand Down Expand Up @@ -125,7 +127,16 @@ function getExplicitThinkingPolicy(modelString: string): ThinkingPolicy | null {
return ["medium", "high", "xhigh"];
}

// gpt-5.2, gpt-5.5 and the gpt-5.4-mini / gpt-5.4-nano variants support 5 reasoning levels including xhigh.
// GPT-5.6 tiers (sol/terra/luna) support all 6 levels: OpenAI documents a native
// "max" reasoning effort for demanding tasks that need more exploration and
// verification. On the Responses API we send "max" through as-is; the Chat
// Completions path clamps to "xhigh" (see buildProviderOptions).
if (openaiSupportsNativeMaxEffort(withoutProviderNamespace)) {
return ["off", "low", "medium", "high", "xhigh", "max"];
Comment thread
ammar-agent marked this conversation as resolved.
Outdated
Comment thread
ammar-agent marked this conversation as resolved.
Outdated
}

// gpt-5.2, gpt-5.5 and the gpt-5.4-mini / gpt-5.4-nano variants support 5 reasoning
// levels including xhigh.
if (
/^gpt-5\.2(?!-[a-z])/.test(withoutProviderNamespace) ||
/^gpt-5\.(?:4|5)(?:-(?:mini|nano))?(?!-[a-z])/.test(withoutProviderNamespace)
Expand Down
53 changes: 53 additions & 0 deletions src/common/utils/tokens/models-extra.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,59 @@ export const modelsExtra: Record<string, ModelData> = {
supported_endpoints: ["/v1/responses"],
},

// GPT-5.6 family (Sol / Terra / Luna) - Previewed June 26, 2026; GA July 9, 2026.
// Published pricing per 1M tokens: Sol $5/$30, Terra $2.50/$15, Luna $1/$6.
// Prompt caching: cache reads keep the 90% discount; cache writes for GPT-5.6+ bill
// at 1.25x the uncached input rate (with explicit breakpoints and a 30-min minimum
// cache life). No long-context tiered pricing has been published for this family.
// OpenAI has not published official context specs in the GA announcement; we mirror
// GPT-5.5's window (1.05M in / 128K out) as a provisional value until the model card
// lands. (Preview reports suggest Sol may be larger, ~1.5M, but that's unconfirmed.)
"gpt-5.6-sol": {
max_input_tokens: 1050000,
max_output_tokens: 128000,
input_cost_per_token: 0.000005, // $5 per million input tokens
output_cost_per_token: 0.00003, // $30 per million output tokens
cache_read_input_token_cost: 0.0000005, // $0.50 per million cached input tokens (90% off)
cache_creation_input_token_cost: 0.00000625, // $6.25 per million tokens (1.25x input)
Comment thread
ammar-agent marked this conversation as resolved.
litellm_provider: "openai",
mode: "chat",
supports_function_calling: true,
supports_vision: true,
supports_reasoning: true,
supports_response_schema: true,
},

"gpt-5.6-terra": {
max_input_tokens: 1050000,
max_output_tokens: 128000,
input_cost_per_token: 0.0000025, // $2.50 per million input tokens
output_cost_per_token: 0.000015, // $15 per million output tokens
cache_read_input_token_cost: 0.00000025, // $0.25 per million cached input tokens (90% off)
cache_creation_input_token_cost: 0.000003125, // $3.125 per million tokens (1.25x input)
litellm_provider: "openai",
mode: "chat",
supports_function_calling: true,
supports_vision: true,
supports_reasoning: true,
supports_response_schema: true,
},

"gpt-5.6-luna": {
max_input_tokens: 1050000,
max_output_tokens: 128000,
input_cost_per_token: 0.000001, // $1 per million input tokens
output_cost_per_token: 0.000006, // $6 per million output tokens
cache_read_input_token_cost: 0.0000001, // $0.10 per million cached input tokens (90% off)
cache_creation_input_token_cost: 0.00000125, // $1.25 per million tokens (1.25x input)
litellm_provider: "openai",
mode: "chat",
supports_function_calling: true,
supports_vision: true,
supports_reasoning: true,
supports_response_schema: true,
},

// GPT-5.4 mini - Released March 11, 2026
// Smaller/faster gpt-5.4-mini tier with 400K context, 128K max output, and published
// pricing of $0.75/M input, $4.50/M output, and $0.075/M cached input.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3097,8 +3097,11 @@ export const BUILTIN_SKILL_FILES: Record<string, Record<string, string>> = {
"| Opus 4.8 | anthropic:claude-opus-4-8 | `opus` | ✓ |",
"| Sonnet 5 | anthropic:claude-sonnet-5 | `sonnet` | |",
"| Haiku 4.5 | anthropic:claude-haiku-4-5 | `haiku` | |",
"| GPT-5.5 | openai:gpt-5.5 | `gpt`, `gpt-5.5` | |",
"| GPT-5.5 | openai:gpt-5.5 | `gpt-5.5` | |",
"| GPT-5.5 Pro | openai:gpt-5.5-pro | `gpt-pro`, `gpt-5.5-pro` | |",
"| GPT-5.6 Sol | openai:gpt-5.6-sol | `gpt`, `sol`, `gpt-5.6-sol` | |",
"| GPT-5.6 Terra | openai:gpt-5.6-terra | `terra`, `gpt-5.6-terra` | |",
"| GPT-5.6 Luna | openai:gpt-5.6-luna | `luna`, `gpt-5.6-luna` | |",
"| GPT-5.4 Mini | openai:gpt-5.4-mini | `gpt-mini` | |",
"| GPT-5.4 Nano | openai:gpt-5.4-nano | `gpt-nano` | |",
"| Codex 5.3 | openai:gpt-5.3-codex | `codex`, `codex-5.3` | |",
Expand Down
Loading