feat(openai): default new setups to GPT-5.6 (#103581)

* feat(openai): default fresh setup to GPT-5.6

* test(crestodian): expect GPT-5.6 Codex defaults

* test(crestodian): expect GPT-5.6 bootstrap default
This commit is contained in:
Peter Steinberger
2026-07-10 10:22:58 +01:00
committed by GitHub
parent fc60a8e66b
commit ab5d143d59
39 changed files with 652 additions and 179 deletions

View File

@@ -2,6 +2,7 @@
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
import { normalizeUniqueStringEntries } from "@openclaw/normalization-core/string-normalization";
import { upsertAuthProfileWithLock } from "../agents/auth-profiles/profiles.js";
import { resolveAgentModelPrimaryValue } from "../config/model-input.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import type { SecretInput } from "../config/types.secrets.js";
import { createLazyRuntimeSurface } from "../shared/lazy-runtime.js";
@@ -26,6 +27,7 @@ type ProviderApiKeyAuthMethodOptions = {
profileIds?: string[];
allowProfile?: boolean;
defaultModel?: string;
preserveExistingPrimary?: boolean;
expectedProviders?: string[];
metadata?: Record<string, string>;
noteMessage?: string;
@@ -74,6 +76,7 @@ async function applyApiKeyConfig(params: {
providerId: string;
profileIds: string[];
defaultModel?: string;
preserveExistingPrimary?: boolean;
applyConfig?: (cfg: OpenClawConfig) => OpenClawConfig;
}) {
const { applyAuthProfileConfig, applyPrimaryModel } = await loadProviderApiKeyAuthRuntime();
@@ -88,7 +91,16 @@ async function applyApiKeyConfig(params: {
if (params.applyConfig) {
next = params.applyConfig(next);
}
return params.defaultModel ? applyPrimaryModel(next, params.defaultModel) : next;
if (!params.defaultModel) {
return next;
}
if (
params.preserveExistingPrimary === true &&
resolveAgentModelPrimaryValue(next.agents?.defaults?.model) !== undefined
) {
return next;
}
return applyPrimaryModel(next, params.defaultModel);
}
/** Creates a provider auth method that captures, stores, and configures API-key credentials. */
@@ -204,6 +216,7 @@ export function createProviderApiKeyAuthMethod(
providerId: params.providerId,
profileIds,
defaultModel: params.defaultModel,
preserveExistingPrimary: params.preserveExistingPrimary,
applyConfig: params.applyConfig,
});
},

View File

@@ -31,6 +31,28 @@ describe("applyProviderAuthConfigPatch", () => {
expect(next.agents?.defaults?.model).toEqual(base.agents.defaults.model);
});
it("keeps configured primary and fallback refs in a newly introduced allowlist", () => {
const next = applyProviderAuthConfigPatch(
{
agents: {
defaults: {
model: {
primary: "openai/gpt-5.5",
fallbacks: ["anthropic/claude-opus-4-6"],
},
},
},
},
{ agents: { defaults: { models: { "openai/gpt-5.6-sol": {} } } } },
);
expect(next.agents?.defaults?.models).toEqual({
"openai/gpt-5.6-sol": {},
"openai/gpt-5.5": {},
"anthropic/claude-opus-4-6": {},
});
});
it("replaces the allowlist only when replaceDefaultModels is set", () => {
const patch = {
agents: {
@@ -176,6 +198,7 @@ describe("applyProviderAuthConfigPatch", () => {
alias: "gemini",
params: { thinking: "high", maxTokens: 12_000 },
},
"openai/gpt-5.5": {},
});
});
@@ -327,6 +350,10 @@ describe("applyDefaultModel", () => {
expect(next.agents?.defaults?.model).toEqual({
primary: "anthropic/claude-opus-4-6",
});
expect(next.agents?.defaults?.models).toEqual({
"openrouter/auto": {},
"anthropic/claude-opus-4-6": {},
});
});
it("normalizes a preserved retired Google Gemini primary", () => {
@@ -363,6 +390,11 @@ describe("applyDefaultModel", () => {
primary: "anthropic/claude-opus-4-6",
fallbacks: ["openai/gpt-5.4"],
});
expect(next.agents?.defaults?.models).toEqual({
"openrouter/auto": {},
"anthropic/claude-opus-4-6": {},
"openai/gpt-5.4": {},
});
});
it("adds the model to the allowlist", () => {

View File

@@ -276,6 +276,38 @@ function normalizeConfigModelRefsForWrite(
};
}
/** Keep a restrictive model allowlist consistent with the configured primary and fallbacks. */
function ensureConfiguredDefaultModelsAllowed(cfg: OpenClawConfig): OpenClawConfig {
const defaults = cfg.agents?.defaults;
if (!defaults?.models) {
return cfg;
}
const model = defaults.model;
const refs = [
typeof model === "string" ? model : model?.primary,
...(typeof model === "object" ? (model.fallbacks ?? []) : []),
].filter((ref): ref is string => typeof ref === "string" && ref.trim().length > 0);
const models = normalizeAgentModelMapForConfig(defaults.models);
let changed = false;
for (const ref of refs) {
const normalizedRef = normalizeAgentModelRefForConfig(ref);
if (!models[normalizedRef]) {
models[normalizedRef] = {};
changed = true;
}
}
if (!changed) {
return cfg;
}
return {
...cfg,
agents: {
...cfg.agents,
defaults: { ...defaults, models },
},
};
}
export function applyProviderAuthConfigPatch(
cfg: OpenClawConfig,
patch: unknown,
@@ -291,7 +323,7 @@ export function applyProviderAuthConfigPatch(
providerConfigNormalizer,
);
if (!options?.replaceDefaultModels || !isPlainRecord(patch)) {
return merged;
return ensureConfiguredDefaultModelsAllowed(merged);
}
const patchModels = (patch.agents as { defaults?: { models?: unknown } } | undefined)?.defaults
@@ -369,7 +401,7 @@ export function applyDefaultModel(
normalizeAgentModelRefForConfig(fallback),
)
: undefined;
return {
return ensureConfiguredDefaultModelsAllowed({
...cfg,
agents: {
...cfg.agents,
@@ -385,5 +417,5 @@ export function applyDefaultModel(
},
},
},
};
});
}