Skip to content

Commit 09d2682

Browse files
committed
fix(openai): resolve gpt-5.5 without cached catalog
1 parent 00004ca commit 09d2682

6 files changed

Lines changed: 76 additions & 6 deletions

File tree

extensions/openai/openai-provider.live.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ function resolveLiveModelCase(modelId: string): LiveModelCase {
3939
templateId: "gpt-5.5",
4040
templateName: "GPT-5.5",
4141
cost: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0 },
42-
contextWindow: 272_000,
42+
contextWindow: 1_000_000,
4343
maxTokens: 128_000,
4444
reasoning: true,
4545
textVerbosity: "low",

extensions/openai/openai-provider.test.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ describe("buildOpenAIProvider", () => {
356356
});
357357
});
358358

359-
it("leaves gpt-5.5 to OpenClaw and resolves gpt-5.5-pro locally", () => {
359+
it("resolves gpt-5.5 locally without cached catalog metadata", () => {
360360
const provider = buildOpenAIProvider();
361361

362362
const model = provider.resolveDynamicModel?.({
@@ -380,6 +380,25 @@ describe("buildOpenAIProvider", () => {
380380
: null,
381381
} as never,
382382
});
383+
384+
expectFields(model, {
385+
provider: "openai",
386+
id: "gpt-5.5",
387+
api: "openai-responses",
388+
baseUrl: "https://api.openai.com/v1",
389+
contextWindow: 1_000_000,
390+
contextTokens: 272_000,
391+
maxTokens: 128_000,
392+
mediaInput: {
393+
image: { maxSidePx: 6000, preferredSidePx: 2048, tokenMode: "detail" },
394+
},
395+
cost: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0 },
396+
});
397+
});
398+
399+
it("resolves gpt-5.5-pro locally", () => {
400+
const provider = buildOpenAIProvider();
401+
383402
const pro = provider.resolveDynamicModel?.({
384403
provider: "openai",
385404
modelId: "gpt-5.5-pro",
@@ -402,7 +421,6 @@ describe("buildOpenAIProvider", () => {
402421
} as never,
403422
});
404423

405-
expect(model).toBeUndefined();
406424
expectFields(pro, {
407425
provider: "openai",
408426
id: "gpt-5.5-pro",

extensions/openai/openai-provider.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,16 @@ const OPENAI_GPT_54_MODEL_ID = "gpt-5.4";
3030
const OPENAI_GPT_54_PRO_MODEL_ID = "gpt-5.4-pro";
3131
const OPENAI_GPT_54_MINI_MODEL_ID = "gpt-5.4-mini";
3232
const OPENAI_GPT_54_NANO_MODEL_ID = "gpt-5.4-nano";
33+
const OPENAI_GPT_55_CONTEXT_WINDOW = 1_000_000;
34+
const OPENAI_GPT_55_CONTEXT_TOKENS = 272_000;
3335
const OPENAI_GPT_55_PRO_CONTEXT_TOKENS = 1_000_000;
3436
const OPENAI_GPT_54_CONTEXT_TOKENS = 1_050_000;
3537
const OPENAI_GPT_54_PRO_CONTEXT_TOKENS = 1_050_000;
3638
const OPENAI_GPT_54_MINI_CONTEXT_TOKENS = 400_000;
3739
const OPENAI_GPT_54_NANO_CONTEXT_TOKENS = 400_000;
3840
const OPENAI_GPT_54_MAX_TOKENS = 128_000;
3941
const OPENAI_CHAT_LATEST_COST = { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0 } as const;
42+
const OPENAI_GPT_55_COST = { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0 } as const;
4043
const OPENAI_GPT_55_PRO_COST = { input: 30, output: 180, cacheRead: 0, cacheWrite: 0 } as const;
4144
const OPENAI_GPT_54_COST = { input: 2.5, output: 15, cacheRead: 0.25, cacheWrite: 0 } as const;
4245
const OPENAI_GPT_54_PRO_COST = { input: 30, output: 180, cacheRead: 0, cacheWrite: 0 } as const;
@@ -56,6 +59,9 @@ const OPENAI_GPT_55_PRO_TEMPLATE_MODEL_IDS = [
5659
OPENAI_GPT_54_PRO_MODEL_ID,
5760
OPENAI_GPT_54_MODEL_ID,
5861
] as const;
62+
const OPENAI_GPT_55_MEDIA_INPUT = {
63+
image: { maxSidePx: 6000, preferredSidePx: 2048, tokenMode: "detail" },
64+
} as const satisfies ProviderRuntimeModel["mediaInput"];
5965
const OPENAI_GPT_54_TEMPLATE_MODEL_IDS = [OPENAI_GPT_55_MODEL_ID] as const;
6066
const OPENAI_GPT_54_PRO_TEMPLATE_MODEL_IDS = [OPENAI_GPT_55_PRO_MODEL_ID] as const;
6167
const OPENAI_GPT_54_MINI_TEMPLATE_MODEL_IDS = ["gpt-5-mini"] as const;
@@ -123,6 +129,20 @@ function resolveOpenAIGptForwardCompatModel(ctx: ProviderResolveDynamicModelCont
123129
contextWindow: 400_000,
124130
maxTokens: OPENAI_GPT_54_MAX_TOKENS,
125131
};
132+
} else if (lower === OPENAI_GPT_55_MODEL_ID) {
133+
templateIds = [OPENAI_GPT_55_MODEL_ID, OPENAI_GPT_54_MODEL_ID];
134+
patch = {
135+
api: "openai-responses",
136+
provider: PROVIDER_ID,
137+
baseUrl: "https://api.openai.com/v1",
138+
reasoning: true,
139+
input: ["text", "image"],
140+
mediaInput: OPENAI_GPT_55_MEDIA_INPUT,
141+
cost: OPENAI_GPT_55_COST,
142+
contextWindow: OPENAI_GPT_55_CONTEXT_WINDOW,
143+
contextTokens: OPENAI_GPT_55_CONTEXT_TOKENS,
144+
maxTokens: OPENAI_GPT_54_MAX_TOKENS,
145+
};
126146
} else if (lower === OPENAI_GPT_55_PRO_MODEL_ID) {
127147
templateIds = OPENAI_GPT_55_PRO_TEMPLATE_MODEL_IDS;
128148
patch = {

extensions/openai/openclaw.plugin.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@
124124
"mediaInput": {
125125
"image": { "maxSidePx": 6000, "preferredSidePx": 2048, "tokenMode": "detail" }
126126
},
127-
"contextWindow": 272000,
127+
"contextWindow": 1000000,
128+
"contextTokens": 272000,
128129
"maxTokens": 128000,
129130
"cost": { "input": 5, "output": 30, "cacheRead": 0.5, "cacheWrite": 0 }
130131
},

src/agents/embedded-agent-runner/model.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2967,6 +2967,26 @@ describe("resolveModel", () => {
29672967
});
29682968
});
29692969

2970+
it("builds an openai fallback for gpt-5.5 when the live catalog cache is cold", () => {
2971+
const result = resolveModelForTest("openai", "gpt-5.5", "/tmp/agent");
2972+
2973+
expect(result.error).toBeUndefined();
2974+
expectRecordFields(result.model, {
2975+
provider: "openai",
2976+
id: "gpt-5.5",
2977+
api: "openai-responses",
2978+
baseUrl: "https://api.openai.com/v1",
2979+
reasoning: true,
2980+
input: ["text", "image"],
2981+
contextWindow: 1_000_000,
2982+
contextTokens: 272_000,
2983+
maxTokens: 128_000,
2984+
mediaInput: {
2985+
image: { maxSidePx: 6000, preferredSidePx: 2048, tokenMode: "detail" },
2986+
},
2987+
});
2988+
});
2989+
29702990
it("builds an openai fallback for gpt-5.4 mini from the gpt-5.4-mini template", () => {
29712991
mockDiscoveredModel(discoverModels, {
29722992
provider: "openai",

src/plugin-sdk/test-helpers/provider-runtime-contract.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ export function describeOpenAIProviderRuntimeContract(load: ProviderRuntimeContr
447447
});
448448
});
449449

450-
it("leaves openai gpt-5.5 forward-compat resolution to OpenClaw", () => {
450+
it("owns openai gpt-5.5 forward-compat resolution", () => {
451451
const provider = requireProviderContractProvider("openai");
452452
const model = provider.resolveDynamicModel?.({
453453
provider: "openai",
@@ -465,7 +465,18 @@ export function describeOpenAIProviderRuntimeContract(load: ProviderRuntimeContr
465465
} as never,
466466
});
467467

468-
expect(model).toBeUndefined();
468+
expectFields(model, {
469+
id: "gpt-5.5",
470+
provider: "openai",
471+
api: "openai-responses",
472+
baseUrl: "https://api.openai.com/v1",
473+
contextWindow: 1_000_000,
474+
contextTokens: 272_000,
475+
maxTokens: 128_000,
476+
mediaInput: {
477+
image: { maxSidePx: 6000, preferredSidePx: 2048, tokenMode: "detail" },
478+
},
479+
});
469480
});
470481

471482
it("owns openai gpt-5.4 mini forward-compat resolution", () => {

0 commit comments

Comments
 (0)