feat(ai,coding-agent): add GPT-6.1 Sol and make it the Codex default

Add gpt-6.1-sol to the OpenAI, Azure OpenAI Responses, and OpenAI Codex
providers with official pricing ($2 input, $0.10 cached input, $2.50
cache writes, $10 output, long-context tier above 272k). The model
rejects reasoning.effort "none", so off is unsupported and clamps to
the lowest effort.
This commit is contained in:
Armin Ronacher 2026-09-29 19:43:27 +02:00
parent 312184edb6
commit 12c416e1a6
7 changed files with 63 additions and 5 deletions

View file

@ -2,6 +2,10 @@
## [Unreleased]
### Added
- Added GPT-6.1 Sol (`gpt-6.1-sol`) to the OpenAI, Azure OpenAI Responses, and OpenAI Codex providers.
## [0.99.0] - 2026-09-29
### Breaking Changes

View file

@ -369,6 +369,7 @@ const OPENAI_TOOL_SEARCH_MODEL_IDS = new Set([
"gpt-6-astra",
"gpt-6-sol",
"gpt-6-luna",
"gpt-6.1-sol",
]);
const OPENAI_ADDITIONAL_TOOLS_MODEL_IDS = OPENAI_TOOL_SEARCH_MODEL_IDS;
const OPENAI_MID_CONVO_SYSTEM_MESSAGE_MODEL_IDS = OPENAI_TOOL_SEARCH_MODEL_IDS;
@ -379,6 +380,7 @@ const OPENAI_CODEX_ADDITIONAL_TOOLS_MODEL_IDS = new Set([
"gpt-6-astra",
"gpt-6-sol",
"gpt-6-luna",
"gpt-6.1-sol",
]);
const OPENAI_LONG_CONTEXT_INPUT_THRESHOLD = 272000;
const OPENAI_SHORT_CONTEXT_CAPPED_MODEL_IDS = new Set([
@ -390,6 +392,7 @@ const OPENAI_SHORT_CONTEXT_CAPPED_MODEL_IDS = new Set([
"gpt-6-astra",
"gpt-6-sol",
"gpt-6-luna",
"gpt-6.1-sol",
]);
const OPENAI_LONG_CONTEXT_PRICING_MODEL_IDS = new Set([
"gpt-5.4",
@ -402,6 +405,7 @@ const OPENAI_LONG_CONTEXT_PRICING_MODEL_IDS = new Set([
"gpt-6-astra",
"gpt-6-sol",
"gpt-6-luna",
"gpt-6.1-sol",
]);
// Keep the generated default no less restrictive than coding-agent's historical
@ -439,6 +443,7 @@ const OPENAI_STANDARD_COSTS: Record<string, ModelCost> = {
"gpt-6-astra": { input: 10, output: 50, cacheRead: 1, cacheWrite: 12.5 },
"gpt-6-luna": { input: 0.1, output: 0.5, cacheRead: 0.01, cacheWrite: 0.125 },
"gpt-6-sol": { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 },
"gpt-6.1-sol": { input: 2, output: 10, cacheRead: 0.1, cacheWrite: 2.5 },
};
const OPENAI_RESPONSES_NONE_REASONING_MODELS = new Set([
@ -1028,13 +1033,17 @@ function applyThinkingLevelMetadata(model: Model<any>): void {
mergeThinkingLevelMap(model, { off: null });
}
if (
(model.id === "gpt-6-astra" || model.id === "gpt-6-sol" || model.id === "gpt-6-luna") &&
(model.id === "gpt-6-astra" ||
model.id === "gpt-6-sol" ||
model.id === "gpt-6-luna" ||
model.id === "gpt-6.1-sol") &&
(model.api === "openai-responses" ||
model.api === "azure-openai-responses" ||
model.api === "openai-codex-responses")
) {
mergeThinkingLevelMap(model, {
off: model.id === "gpt-6-astra" ? null : "none",
// GPT-6 Astra and GPT-6.1 Sol reject reasoning.effort "none".
off: model.id === "gpt-6-astra" || model.id === "gpt-6.1-sol" ? null : "none",
minimal: null,
low: "low",
medium: "medium",
@ -2951,6 +2960,18 @@ async function generateModels() {
// Add missing gpt models
const missingOpenAiModels: Model<"openai-responses">[] = [
{
id: "gpt-6.1-sol",
name: "GPT-6.1 Sol",
api: "openai-responses",
baseUrl: "https://api.openai.com/v1",
provider: "openai",
reasoning: true,
input: ["text", "image"],
cost: withOpenAiLongContextPricing(OPENAI_STANDARD_COSTS["gpt-6.1-sol"]),
contextWindow: OPENAI_LONG_CONTEXT_INPUT_THRESHOLD,
maxTokens: 128000,
},
{
id: "gpt-6-astra",
name: "GPT-6 Astra",
@ -3184,6 +3205,18 @@ async function generateModels() {
const CODEX_SPARK_CONTEXT = 128000;
const CODEX_MAX_TOKENS = 128000;
const codexModels: Model<"openai-codex-responses">[] = [
{
id: "gpt-6.1-sol",
name: "GPT-6.1 Sol",
api: "openai-codex-responses",
provider: "openai-codex",
baseUrl: CODEX_BASE_URL,
reasoning: true,
input: ["text", "image"],
cost: withOpenAiLongContextPricing(OPENAI_STANDARD_COSTS["gpt-6.1-sol"]),
contextWindow: CODEX_CONTEXT,
maxTokens: CODEX_MAX_TOKENS,
},
{
id: "gpt-6-astra",
name: "GPT-6 Astra",

View file

@ -67,7 +67,7 @@ describe("max thinking level", () => {
expect(clampThinkingLevel(model, "xhigh")).toBe("max");
});
it.each(["gpt-5.6-sol", "gpt-6-astra", "gpt-6-sol", "gpt-6-luna"] as const)(
it.each(["gpt-5.6-sol", "gpt-6-astra", "gpt-6-sol", "gpt-6-luna", "gpt-6.1-sol"] as const)(
"sends max to the Codex Responses API for %s",
async (modelId) => {
const model = getModel("openai-codex", modelId)!;

View file

@ -93,6 +93,7 @@ describe("getSupportedThinkingLevels", () => {
"gpt-6-astra",
"gpt-6-sol",
"gpt-6-luna",
"gpt-6.1-sol",
] as const)("includes xhigh for openai-codex %s models", (modelId) => {
const model = getModel("openai-codex", modelId);
expect(model).toBeDefined();
@ -108,9 +109,25 @@ describe("getSupportedThinkingLevels", () => {
},
);
// OpenAI and Codex reject reasoning.effort "none" for GPT-6.1 Sol.
it("does not support off for GPT-6.1 Sol", () => {
const expected = {
openai: ["low", "medium", "high", "xhigh", "max"],
"azure-openai-responses": ["low", "medium", "high", "xhigh", "max"],
"openai-codex": ["minimal", "low", "medium", "high", "xhigh", "max"],
} as const;
for (const [provider, levels] of Object.entries(expected)) {
const model = getModel(provider as keyof typeof expected, "gpt-6.1-sol");
expect(model).toBeDefined();
expect(getSupportedThinkingLevels(model!)).toEqual(levels);
expect(model!.thinkingLevelMap?.off).toBeNull();
}
});
it.each([
["gpt-6-sol", { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 }],
["gpt-6-luna", { input: 0.1, output: 0.5, cacheRead: 0.01, cacheWrite: 0.125 }],
["gpt-6.1-sol", { input: 2, output: 10, cacheRead: 0.1, cacheWrite: 2.5 }],
] as const)("includes official metadata for OpenAI and Codex %s", (modelId, cost) => {
for (const provider of ["openai", "openai-codex"] as const) {
const model = getModel(provider, modelId);

View file

@ -2,6 +2,10 @@
## [Unreleased]
### Changed
- Changed the default OpenAI Codex model to GPT-6.1 Sol (`gpt-6.1-sol`).
## [0.99.0] - 2026-09-29
### New Features

View file

@ -23,7 +23,7 @@ export const defaultModelPerProvider: Partial<Record<KnownProvider, string>> = {
anthropic: "claude-opus-4-8",
openai: "gpt-5.5",
"azure-openai-responses": "gpt-5.4",
"openai-codex": "gpt-5.5",
"openai-codex": "gpt-6.1-sol",
radius: "balanced",
nvidia: "nvidia/nemotron-3-super-120b-a12b",
deepseek: "deepseek-v4-pro",

View file

@ -708,7 +708,7 @@ describe("resolveCliModel", () => {
describe("default model selection", () => {
test("openai defaults track current models", () => {
expect(defaultModelPerProvider.openai).toBe("gpt-5.5");
expect(defaultModelPerProvider["openai-codex"]).toBe("gpt-5.5");
expect(defaultModelPerProvider["openai-codex"]).toBe("gpt-6.1-sol");
});
test("zai, minimax, cerebras, and ant-ling defaults track current models", () => {