Skip to content

Commit 0d2e01a

Browse files
fix: drop codex suffix from gpt-5.4 (#143)
* fix: drop codex suffix from gpt-5.4 * fix: tests * fix: tests * chore: changeset
1 parent 608f4de commit 0d2e01a

8 files changed

Lines changed: 46 additions & 24 deletions

File tree

.changeset/wet-ducks-cheer.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@upstash/box-cli": patch
3+
"@upstash/box": patch
4+
---
5+
6+
fixed gpt-5.4 support

packages/cli/src/models.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@ export const MODEL_OPTIONS_BY_AGENT: Record<
3737
{
3838
label: "OpenAI",
3939
options: [
40-
{ value: OpenAICodex.GPT_5_4_Codex, label: "GPT-5.4 Codex" },
40+
{ value: OpenAICodex.GPT_5_4, label: "GPT-5.4" },
41+
{ value: OpenAICodex.GPT_5_4_Mini, label: "GPT-5.4 Mini" },
4142
{ value: OpenAICodex.GPT_5_3_Codex, label: "GPT-5.3 Codex" },
43+
{ value: OpenAICodex.GPT_5_3_Codex_Spark, label: "GPT-5.3 Codex Spark" },
4244
{ value: OpenAICodex.GPT_5_2_Codex, label: "GPT-5.2 Codex" },
4345
{ value: OpenAICodex.GPT_5_1_Codex_Max, label: "GPT-5.1 Codex Max" },
4446
{ value: OpenAICodex.GPT_5_1_Codex_Mini, label: "GPT-5.1 Codex Mini" },
@@ -97,8 +99,12 @@ export const MODEL_OPTIONS_BY_AGENT: Record<
9799
{
98100
label: "OpenAI",
99101
options: [
100-
{ value: OpenCodeModel.GPT_5_4_Codex, label: "GPT-5.4 Codex" },
102+
{ value: OpenCodeModel.GPT_5_4_Pro, label: "GPT-5.4 Pro" },
103+
{ value: OpenCodeModel.GPT_5_4, label: "GPT-5.4" },
104+
{ value: OpenCodeModel.GPT_5_4_Mini, label: "GPT-5.4 Mini" },
105+
{ value: OpenCodeModel.GPT_5_4_Nano, label: "GPT-5.4 Nano" },
101106
{ value: OpenCodeModel.GPT_5_3_Codex, label: "GPT-5.3 Codex" },
107+
{ value: OpenCodeModel.GPT_5_3_Codex_Spark, label: "GPT-5.3 Codex Spark" },
102108
{ value: OpenCodeModel.GPT_5_2_Codex, label: "GPT-5.2 Codex" },
103109
{ value: OpenCodeModel.GPT_5_1_Codex_Max, label: "GPT-5.1 Codex Max" },
104110
{ value: OpenCodeModel.GPT_5_1_Codex_Mini, label: "GPT-5.1 Codex Mini" },

packages/sdk/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,8 @@ The preferred field in agent config is `harness`, and it is required. Deprecated
332332

333333
| Enum | Value |
334334
| --------------------------------- | ---------------------------- |
335-
| `OpenAICodex.GPT_5_4_Codex` | `openai/gpt-5.4-codex` |
335+
| `OpenAICodex.GPT_5_4` | `openai/gpt-5.4` |
336+
| `OpenAICodex.GPT_5_4_Mini` | `openai/gpt-5.4-mini` |
336337
| `OpenAICodex.GPT_5_3_Codex` | `openai/gpt-5.3-codex` |
337338
| `OpenAICodex.GPT_5_3_Codex_Spark` | `openai/gpt-5.3-codex-spark` |
338339
| `OpenAICodex.GPT_5_2_Codex` | `openai/gpt-5.2-codex` |

packages/sdk/src/__tests__/box-config-model.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ describe("Box.configureModel", () => {
2121
const { box, fetchMock } = await createTestBox();
2222
fetchMock.mockResolvedValueOnce(mockResponse({}));
2323

24-
await box.configureModel("openai/gpt_5_4_codex");
24+
await box.configureModel("openai/gpt_5_4");
2525

2626
const body = JSON.parse(fetchMock.mock.calls[1]![1]?.body as string);
27-
expect(body.model).toBe("openai/gpt_5_4_codex");
27+
expect(body.model).toBe("openai/gpt_5_4");
2828
});
2929

3030
it("updates local modelConfig after success", async () => {

packages/sdk/src/__tests__/box-create.test.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ describe("Box.create", () => {
3232

3333
await Box.create({
3434
...TEST_CONFIG,
35-
agent: { harness: Agent.Codex, model: OpenAICodex.GPT_5_4_Codex, apiKey: "k" },
35+
agent: { harness: Agent.Codex, model: OpenAICodex.GPT_5_4, apiKey: "k" },
3636
});
3737

3838
const body = JSON.parse(vi.mocked(fetch).mock.calls[0]![1]?.body as string);
3939
expect(body.agent).toBe(Agent.Codex);
40-
expect(body.model).toBe(OpenAICodex.GPT_5_4_Codex);
40+
expect(body.model).toBe(OpenAICodex.GPT_5_4);
4141
});
4242

4343
it("supports deprecated provider field", async () => {
@@ -46,12 +46,12 @@ describe("Box.create", () => {
4646

4747
await Box.create({
4848
...TEST_CONFIG,
49-
agent: { provider: Agent.Codex, model: OpenAICodex.GPT_5_4_Codex, apiKey: "k" },
49+
agent: { provider: Agent.Codex, model: OpenAICodex.GPT_5_4, apiKey: "k" },
5050
});
5151

5252
const body = JSON.parse(vi.mocked(fetch).mock.calls[0]![1]?.body as string);
5353
expect(body.agent).toBe(Agent.Codex);
54-
expect(body.model).toBe(OpenAICodex.GPT_5_4_Codex);
54+
expect(body.model).toBe(OpenAICodex.GPT_5_4);
5555
});
5656

5757
it("supports deprecated runner field", async () => {
@@ -63,9 +63,9 @@ describe("Box.create", () => {
6363
agent: {
6464
provider: Agent.Codex,
6565
runner: "ignored",
66-
model: OpenAICodex.GPT_5_4_Codex,
66+
model: OpenAICodex.GPT_5_4,
6767
apiKey: "k",
68-
},
68+
} as any,
6969
});
7070

7171
const body = JSON.parse(vi.mocked(fetch).mock.calls[0]![1]?.body as string);
@@ -97,7 +97,7 @@ describe("Box.create", () => {
9797

9898
await Box.create({
9999
...TEST_CONFIG,
100-
agent: { runner: "codex", model: "openai/gpt-5.4-codex", apiKey: "k" } as any,
100+
agent: { runner: "codex", model: "openai/gpt-5.4", apiKey: "k" } as any,
101101
});
102102

103103
const body = JSON.parse(vi.mocked(fetch).mock.calls[0]![1]?.body as string);
@@ -108,7 +108,7 @@ describe("Box.create", () => {
108108
await expect(
109109
Box.create({
110110
...TEST_CONFIG,
111-
agent: { model: "openai/gpt-5.4-codex", apiKey: "k" } as any,
111+
agent: { model: "openai/gpt-5.4", apiKey: "k" } as any,
112112
}),
113113
).rejects.toThrow(
114114
"agent.harness is required. Deprecated aliases agent.provider and agent.runner are still accepted.",

packages/sdk/src/__tests__/box-from-snapshot.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ describe("Box.fromSnapshot", () => {
3131

3232
await Box.fromSnapshot("snap-1", {
3333
...TEST_CONFIG,
34-
agent: { provider: Agent.Codex, model: OpenAICodex.GPT_5_4_Codex, apiKey: "k" },
34+
agent: { provider: Agent.Codex, model: OpenAICodex.GPT_5_4, apiKey: "k" },
3535
});
3636

3737
const body = JSON.parse(vi.mocked(fetch).mock.calls[0]![1]?.body as string);
3838
expect(body.agent).toBe(Agent.Codex);
39-
expect(body.model).toBe(OpenAICodex.GPT_5_4_Codex);
39+
expect(body.model).toBe(OpenAICodex.GPT_5_4);
4040
});
4141

4242
it("polls until box is ready", async () => {

packages/sdk/src/__tests__/integration/agent.integration.test.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { describe, it, expect, beforeAll, afterAll } from "vitest";
22
import { z } from "zod/v3";
3-
import { Agent, Box, ClaudeCode } from "../../index.js";
3+
import { Agent, Box, ClaudeCode, OpenAICodex } from "../../index.js";
44
import { UPSTASH_BOX_API_KEY } from "./setup.js";
55

66
describe.skipIf(!UPSTASH_BOX_API_KEY)("agent", () => {
@@ -67,13 +67,13 @@ describe.skipIf(!UPSTASH_BOX_API_KEY)("agent", () => {
6767
}, 120000);
6868
});
6969

70-
describe.skipIf(!UPSTASH_BOX_API_KEY)("agent (OpenAI)", () => {
71-
let box: Box;
70+
describe.skipIf(!UPSTASH_BOX_API_KEY)("agent (OpenAI GPT-5.4)", () => {
71+
let box: Box<Agent.Codex>;
7272

7373
beforeAll(async () => {
74-
box = await Box.create({
74+
box = await Box.create<Agent.Codex>({
7575
apiKey: UPSTASH_BOX_API_KEY!,
76-
agent: { provider: Agent.ClaudeCode, model: ClaudeCode.Opus_4_6 },
76+
agent: { harness: Agent.Codex, model: OpenAICodex.GPT_5_4 },
7777
});
7878
}, 120000);
7979

@@ -85,14 +85,16 @@ describe.skipIf(!UPSTASH_BOX_API_KEY)("agent (OpenAI)", () => {
8585
}
8686
}, 30000);
8787

88-
it("agent.run: returns result with OpenAI model", async () => {
88+
it("agent.run: returns non-empty result", async () => {
8989
const run = await box.agent.run({
9090
prompt: "Reply with exactly: OPENAI_OK",
9191
});
9292
expect(run.result).toBeTruthy();
93+
expect(run.result).toContain("OPENAI_OK");
94+
expect(run.status).toBe("completed");
9395
}, 120000);
9496

95-
it("agent.stream: yields Chunk objects with OpenAI model", async () => {
97+
it("agent.stream: yields text-delta chunks", async () => {
9698
let text = "";
9799
let chunkCount = 0;
98100
const run = await box.agent.stream({
@@ -106,5 +108,6 @@ describe.skipIf(!UPSTASH_BOX_API_KEY)("agent (OpenAI)", () => {
106108
}
107109
expect(chunkCount).toBeGreaterThan(0);
108110
expect(text).toBeTruthy();
111+
expect(run.status).toBe("completed");
109112
}, 120000);
110113
});

packages/sdk/src/types.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,10 @@ export enum ClaudeCode {
4242
* OpenAI Codex model identifiers
4343
*/
4444
export enum OpenAICodex {
45-
GPT_5_4_Codex = "openai/gpt-5.4-codex",
45+
GPT_5_4 = "openai/gpt-5.4",
46+
GPT_5_4_Mini = "openai/gpt-5.4-mini",
4647
GPT_5_3_Codex = "openai/gpt-5.3-codex",
48+
GPT_5_3_Codex_Spark = "openai/gpt-5.3-codex-spark",
4749
GPT_5_2_Codex = "openai/gpt-5.2-codex",
4850
GPT_5_1_Codex_Max = "openai/gpt-5.1-codex-max",
4951
GPT_5_1_Codex_Mini = "openai/gpt-5.1-codex-mini",
@@ -76,8 +78,12 @@ export enum OpenCodeModel {
7678
Claude_Sonnet_4_6 = "opencode/claude-sonnet-4-6",
7779
Claude_Haiku_4_5 = "opencode/claude-haiku-4-5",
7880
// OpenAI-backed OpenCode models
79-
GPT_5_4_Codex = "opencode/gpt-5.4-codex",
81+
GPT_5_4 = "opencode/gpt-5.4",
82+
GPT_5_4_Pro = "opencode/gpt-5.4-pro",
83+
GPT_5_4_Mini = "opencode/gpt-5.4-mini",
84+
GPT_5_4_Nano = "opencode/gpt-5.4-nano",
8085
GPT_5_3_Codex = "opencode/gpt-5.3-codex",
86+
GPT_5_3_Codex_Spark = "opencode/gpt-5.3-codex-spark",
8187
GPT_5_2_Codex = "opencode/gpt-5.2-codex",
8288
GPT_5_1_Codex_Max = "opencode/gpt-5.1-codex-max",
8389
GPT_5_1_Codex_Mini = "opencode/gpt-5.1-codex-mini",

0 commit comments

Comments
 (0)