Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/claude-opus-5-5.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@upstash/box": patch
"@upstash/box-cli": patch
---

Add Claude Opus 5.5 model constants and CLI options for Claude Code, OpenRouter,
Vercel AI Gateway, OpenCode/Zen, and Cursor.
7 changes: 7 additions & 0 deletions .changeset/gpt-6-sol-luna.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@upstash/box": patch
"@upstash/box-cli": patch
---

Add GPT-6 Sol and GPT-6 Luna model constants and CLI options for Codex,
OpenRouter, and OpenCode/Zen.
9 changes: 9 additions & 0 deletions .changeset/vercel-gateway-models.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@upstash/box": patch
"@upstash/box-cli": patch
---

Fix Vercel AI Gateway Grok model identifiers: the gateway moved xAI models from
the `xai/` to the `spacexai/` namespace, so `VercelModel.Grok_*` now resolve
again. Add `VercelModel.Grok_4_7`, `GPT_6_Sol`, `GPT_6_Luna`, and
`Gemini_3_8_Flash`, with matching CLI picker options.
48 changes: 48 additions & 0 deletions packages/cli/src/__tests__/models.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,36 @@ import {
Agent,
ClaudeCode,
CursorModel,
OpenAICodex,
OpenCodeModel,
OpenRouterModel,
VercelModel,
} from "@upstash/box";
import { MODEL_OPTIONS_BY_AGENT } from "../models.js";

describe("MODEL_OPTIONS_BY_AGENT", () => {
it.each([
[Agent.ClaudeCode, "Anthropic", ClaudeCode.Opus_5_5, "Claude Opus 5.5"],
[Agent.ClaudeCode, "OpenRouter", OpenRouterModel.Claude_Opus_5_5, "Claude Opus 5.5 (OR)"],
[
Agent.ClaudeCode,
"Vercel AI Gateway",
VercelModel.Claude_Opus_5_5,
"Claude Opus 5.5 (Vercel)",
],
[Agent.Codex, "OpenRouter", OpenRouterModel.Claude_Opus_5_5, "Claude Opus 5.5 (OR)"],
[Agent.Codex, "Vercel AI Gateway", VercelModel.Claude_Opus_5_5, "Claude Opus 5.5 (Vercel)"],
[Agent.OpenCode, "OpenCode — Paid", OpenCodeModel.Zen_Claude_Opus_5_5, "Claude Opus 5.5"],
[Agent.OpenCode, "Anthropic", OpenCodeModel.Claude_Opus_5_5, "Claude Opus 5.5"],
[Agent.OpenCode, "OpenRouter", OpenRouterModel.Claude_Opus_5_5, "Claude Opus 5.5 (OR)"],
[Agent.OpenCode, "Vercel AI Gateway", VercelModel.Claude_Opus_5_5, "Claude Opus 5.5 (Vercel)"],
[Agent.Cursor, "Cursor", CursorModel.Claude_Opus_5_5, "Claude Opus 5.5"],
])("includes Claude Opus 5.5 for %s via %s", (agent, groupLabel, value, label) => {
const group = MODEL_OPTIONS_BY_AGENT[agent].find(({ label }) => label === groupLabel);

expect(group?.options).toContainEqual({ value, label });
});

it.each([
[Agent.ClaudeCode, "Anthropic", ClaudeCode.Opus_5, "Claude Opus 5"],
[Agent.ClaudeCode, "OpenRouter", OpenRouterModel.Claude_Opus_5, "Claude Opus 5 (OR)"],
Expand All @@ -27,6 +50,31 @@ describe("MODEL_OPTIONS_BY_AGENT", () => {
expect(group?.options).toContainEqual({ value, label });
});

it.each([
[Agent.ClaudeCode, VercelModel.Grok_4_7, "Grok 4.7 (Vercel)"],
[Agent.ClaudeCode, VercelModel.Gemini_3_8_Flash, "Gemini 3.8 Flash (Vercel)"],
[Agent.Codex, VercelModel.GPT_6_Sol, "GPT-6 Sol (Vercel)"],
[Agent.Codex, VercelModel.GPT_6_Luna, "GPT-6 Luna (Vercel)"],
[Agent.OpenCode, VercelModel.GPT_6_Sol, "GPT-6 Sol (Vercel)"],
[Agent.OpenCode, VercelModel.Grok_4_7, "Grok 4.7 (Vercel)"],
])("includes current Vercel AI Gateway models for %s", (agent, value, label) => {
const group = MODEL_OPTIONS_BY_AGENT[agent].find(({ label }) => label === "Vercel AI Gateway");

expect(group?.options).toContainEqual({ value, label });
});

it.each([
[Agent.Codex, "OpenAI", OpenAICodex.GPT_6_Sol, "GPT-6 Sol"],
[Agent.Codex, "OpenAI", OpenAICodex.GPT_6_Luna, "GPT-6 Luna"],
[Agent.Codex, "OpenRouter", OpenRouterModel.GPT_6_Sol, "GPT-6 Sol (OR)"],
[Agent.OpenCode, "OpenAI", OpenCodeModel.GPT_6_Sol, "GPT-6 Sol"],
[Agent.OpenCode, "OpenAI", OpenCodeModel.GPT_6_Luna, "GPT-6 Luna"],
])("includes GPT-6 Sol and Luna for %s via %s", (agent, groupLabel, value, label) => {
const group = MODEL_OPTIONS_BY_AGENT[agent].find(({ label }) => label === groupLabel);

expect(group?.options).toContainEqual({ value, label });
});

it("includes Cursor models", () => {
const cursorModels = MODEL_OPTIONS_BY_AGENT[Agent.Cursor].flatMap((group) => group.options);

Expand Down
27 changes: 27 additions & 0 deletions packages/cli/src/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const MODEL_OPTIONS_BY_AGENT: Record<
options: [
{ value: ClaudeCode.Fable_5_1, label: "Claude Fable 5.1" },
{ value: ClaudeCode.Fable_5, label: "Claude Fable 5" },
{ value: ClaudeCode.Opus_5_5, label: "Claude Opus 5.5" },
{ value: ClaudeCode.Opus_5, label: "Claude Opus 5" },
{ value: ClaudeCode.Opus_4_8, label: "Claude Opus 4.8" },
{ value: ClaudeCode.Opus_4_7, label: "Claude Opus 4.7" },
Expand All @@ -36,6 +37,7 @@ export const MODEL_OPTIONS_BY_AGENT: Record<
options: [
{ value: OpenRouterModel.Claude_Fable_5_1, label: "Claude Fable 5.1 (OR)" },
{ value: OpenRouterModel.Claude_Fable_5, label: "Claude Fable 5 (OR)" },
{ value: OpenRouterModel.Claude_Opus_5_5, label: "Claude Opus 5.5 (OR)" },
{ value: OpenRouterModel.Claude_Opus_5, label: "Claude Opus 5 (OR)" },
{ value: OpenRouterModel.Claude_Opus_4_5, label: "Claude Opus 4.5 (OR)" },
{ value: OpenRouterModel.Claude_Sonnet_5, label: "Claude Sonnet 5 (OR)" },
Expand All @@ -45,6 +47,8 @@ export const MODEL_OPTIONS_BY_AGENT: Record<
{ value: OpenRouterModel.Gemini_2_5_Pro, label: "Gemini 2.5 Pro (OR)" },
{ value: OpenRouterModel.Gemini_2_5_Flash, label: "Gemini 2.5 Flash (OR)" },
{ value: OpenRouterModel.GPT_6_Astra, label: "GPT-6 Astra (OR)" },
{ value: OpenRouterModel.GPT_6_Sol, label: "GPT-6 Sol (OR)" },
{ value: OpenRouterModel.GPT_6_Luna, label: "GPT-6 Luna (OR)" },
{ value: OpenRouterModel.GPT_5_6_Sol, label: "GPT-5.6 Sol (OR)" },
{ value: OpenRouterModel.GPT_5_6_Terra, label: "GPT-5.6 Terra (OR)" },
{ value: OpenRouterModel.GPT_5_6_Luna, label: "GPT-5.6 Luna (OR)" },
Expand All @@ -58,14 +62,17 @@ export const MODEL_OPTIONS_BY_AGENT: Record<
options: [
{ value: VercelModel.Claude_Fable_5_1, label: "Claude Fable 5.1 (Vercel)" },
{ value: VercelModel.Claude_Fable_5, label: "Claude Fable 5 (Vercel)" },
{ value: VercelModel.Claude_Opus_5_5, label: "Claude Opus 5.5 (Vercel)" },
{ value: VercelModel.Claude_Opus_5, label: "Claude Opus 5 (Vercel)" },
{ value: VercelModel.Claude_Sonnet_5, label: "Claude Sonnet 5 (Vercel)" },
{ value: VercelModel.Claude_Opus_4_7, label: "Claude Opus 4.7 (Vercel)" },
{ value: VercelModel.Claude_Sonnet_4_6, label: "Claude Sonnet 4.6 (Vercel)" },
{ value: VercelModel.Claude_Opus_4_6, label: "Claude Opus 4.6 (Vercel)" },
{ value: VercelModel.Claude_Haiku_4_5, label: "Claude Haiku 4.5 (Vercel)" },
{ value: VercelModel.Gemini_3_8_Flash, label: "Gemini 3.8 Flash (Vercel)" },
{ value: VercelModel.Gemini_3_5_Flash, label: "Gemini 3.5 Flash (Vercel)" },
{ value: VercelModel.Grok_Build_0_1, label: "Grok Build 0.1 (Vercel)" },
{ value: VercelModel.Grok_4_7, label: "Grok 4.7 (Vercel)" },
{ value: VercelModel.Grok_4_3, label: "Grok 4.3 (Vercel)" },
],
},
Expand All @@ -75,6 +82,8 @@ export const MODEL_OPTIONS_BY_AGENT: Record<
label: "OpenAI",
options: [
{ value: OpenAICodex.GPT_6_Astra, label: "GPT-6 Astra" },
{ value: OpenAICodex.GPT_6_Sol, label: "GPT-6 Sol" },
{ value: OpenAICodex.GPT_6_Luna, label: "GPT-6 Luna" },
{ value: OpenAICodex.GPT_5_6_Sol, label: "GPT-5.6 Sol" },
{ value: OpenAICodex.GPT_5_6_Terra, label: "GPT-5.6 Terra" },
{ value: OpenAICodex.GPT_5_6_Luna, label: "GPT-5.6 Luna" },
Expand All @@ -92,6 +101,7 @@ export const MODEL_OPTIONS_BY_AGENT: Record<
options: [
{ value: OpenRouterModel.Claude_Fable_5_1, label: "Claude Fable 5.1 (OR)" },
{ value: OpenRouterModel.Claude_Fable_5, label: "Claude Fable 5 (OR)" },
{ value: OpenRouterModel.Claude_Opus_5_5, label: "Claude Opus 5.5 (OR)" },
{ value: OpenRouterModel.Claude_Opus_5, label: "Claude Opus 5 (OR)" },
{ value: OpenRouterModel.Claude_Opus_4_5, label: "Claude Opus 4.5 (OR)" },
{ value: OpenRouterModel.Claude_Sonnet_5, label: "Claude Sonnet 5 (OR)" },
Expand All @@ -101,6 +111,8 @@ export const MODEL_OPTIONS_BY_AGENT: Record<
{ value: OpenRouterModel.Gemini_2_5_Pro, label: "Gemini 2.5 Pro (OR)" },
{ value: OpenRouterModel.Gemini_2_5_Flash, label: "Gemini 2.5 Flash (OR)" },
{ value: OpenRouterModel.GPT_6_Astra, label: "GPT-6 Astra (OR)" },
{ value: OpenRouterModel.GPT_6_Sol, label: "GPT-6 Sol (OR)" },
{ value: OpenRouterModel.GPT_6_Luna, label: "GPT-6 Luna (OR)" },
{ value: OpenRouterModel.GPT_5_6_Sol, label: "GPT-5.6 Sol (OR)" },
{ value: OpenRouterModel.GPT_5_6_Terra, label: "GPT-5.6 Terra (OR)" },
{ value: OpenRouterModel.GPT_5_6_Luna, label: "GPT-5.6 Luna (OR)" },
Expand All @@ -113,13 +125,16 @@ export const MODEL_OPTIONS_BY_AGENT: Record<
label: "Vercel AI Gateway",
options: [
{ value: VercelModel.GPT_6_Astra, label: "GPT-6 Astra (Vercel)" },
{ value: VercelModel.GPT_6_Sol, label: "GPT-6 Sol (Vercel)" },
{ value: VercelModel.GPT_6_Luna, label: "GPT-6 Luna (Vercel)" },
{ value: VercelModel.GPT_5_6_Sol, label: "GPT-5.6 Sol (Vercel)" },
{ value: VercelModel.GPT_5_6_Terra, label: "GPT-5.6 Terra (Vercel)" },
{ value: VercelModel.GPT_5_6_Luna, label: "GPT-5.6 Luna (Vercel)" },
{ value: VercelModel.GPT_5_5, label: "GPT-5.5 (Vercel)" },
{ value: VercelModel.GPT_5_5_Pro, label: "GPT-5.5 Pro (Vercel)" },
{ value: VercelModel.GPT_5_4, label: "GPT-5.4 (Vercel)" },
{ value: VercelModel.GPT_5_4_Mini, label: "GPT-5.4 Mini (Vercel)" },
{ value: VercelModel.Claude_Opus_5_5, label: "Claude Opus 5.5 (Vercel)" },
{ value: VercelModel.Claude_Opus_5, label: "Claude Opus 5 (Vercel)" },
{ value: VercelModel.Claude_Opus_4_7, label: "Claude Opus 4.7 (Vercel)" },
{ value: VercelModel.Claude_Sonnet_4_6, label: "Claude Sonnet 4.6 (Vercel)" },
Expand All @@ -138,6 +153,7 @@ export const MODEL_OPTIONS_BY_AGENT: Record<
{ value: OpenCodeModel.Zen_MiniMax_M2_7, label: "MiniMax M2.7" },
{ value: OpenCodeModel.Zen_Claude_Fable_5_1, label: "Claude Fable 5.1" },
{ value: OpenCodeModel.Zen_Claude_Fable_5, label: "Claude Fable 5" },
{ value: OpenCodeModel.Zen_Claude_Opus_5_5, label: "Claude Opus 5.5" },
{ value: OpenCodeModel.Zen_Claude_Opus_5, label: "Claude Opus 5" },
{ value: OpenCodeModel.Zen_Claude_Sonnet_5, label: "Claude Sonnet 5" },
{ value: OpenCodeModel.Zen_Claude_Sonnet_4_6, label: "Claude Sonnet 4.6" },
Expand All @@ -159,6 +175,7 @@ export const MODEL_OPTIONS_BY_AGENT: Record<
options: [
{ value: OpenCodeModel.Claude_Fable_5_1, label: "Claude Fable 5.1" },
{ value: OpenCodeModel.Claude_Fable_5, label: "Claude Fable 5" },
{ value: OpenCodeModel.Claude_Opus_5_5, label: "Claude Opus 5.5" },
{ value: OpenCodeModel.Claude_Opus_5, label: "Claude Opus 5" },
{ value: OpenCodeModel.Claude_Opus_4_8, label: "Claude Opus 4.8" },
{ value: OpenCodeModel.Claude_Opus_4_7, label: "Claude Opus 4.7" },
Expand All @@ -175,6 +192,8 @@ export const MODEL_OPTIONS_BY_AGENT: Record<
label: "OpenAI",
options: [
{ value: OpenCodeModel.GPT_6_Astra, label: "GPT-6 Astra" },
{ value: OpenCodeModel.GPT_6_Sol, label: "GPT-6 Sol" },
{ value: OpenCodeModel.GPT_6_Luna, label: "GPT-6 Luna" },
{ value: OpenCodeModel.GPT_5_5, label: "GPT-5.5" },
{ value: OpenCodeModel.GPT_5_4_Pro, label: "GPT-5.4 Pro" },
{ value: OpenCodeModel.GPT_5_4, label: "GPT-5.4" },
Expand All @@ -195,6 +214,7 @@ export const MODEL_OPTIONS_BY_AGENT: Record<
options: [
{ value: OpenRouterModel.Claude_Fable_5_1, label: "Claude Fable 5.1 (OR)" },
{ value: OpenRouterModel.Claude_Fable_5, label: "Claude Fable 5 (OR)" },
{ value: OpenRouterModel.Claude_Opus_5_5, label: "Claude Opus 5.5 (OR)" },
{ value: OpenRouterModel.Claude_Opus_5, label: "Claude Opus 5 (OR)" },
{ value: OpenRouterModel.Claude_Opus_4_5, label: "Claude Opus 4.5 (OR)" },
{ value: OpenRouterModel.Claude_Sonnet_5, label: "Claude Sonnet 5 (OR)" },
Expand All @@ -204,6 +224,8 @@ export const MODEL_OPTIONS_BY_AGENT: Record<
{ value: OpenRouterModel.Gemini_2_5_Pro, label: "Gemini 2.5 Pro (OR)" },
{ value: OpenRouterModel.Gemini_2_5_Flash, label: "Gemini 2.5 Flash (OR)" },
{ value: OpenRouterModel.GPT_6_Astra, label: "GPT-6 Astra (OR)" },
{ value: OpenRouterModel.GPT_6_Sol, label: "GPT-6 Sol (OR)" },
{ value: OpenRouterModel.GPT_6_Luna, label: "GPT-6 Luna (OR)" },
{ value: OpenRouterModel.GPT_5_6_Sol, label: "GPT-5.6 Sol (OR)" },
{ value: OpenRouterModel.GPT_5_6_Terra, label: "GPT-5.6 Terra (OR)" },
{ value: OpenRouterModel.GPT_5_6_Luna, label: "GPT-5.6 Luna (OR)" },
Expand All @@ -217,12 +239,16 @@ export const MODEL_OPTIONS_BY_AGENT: Record<
options: [
{ value: VercelModel.Claude_Fable_5_1, label: "Claude Fable 5.1 (Vercel)" },
{ value: VercelModel.Claude_Fable_5, label: "Claude Fable 5 (Vercel)" },
{ value: VercelModel.Claude_Opus_5_5, label: "Claude Opus 5.5 (Vercel)" },
{ value: VercelModel.Claude_Opus_5, label: "Claude Opus 5 (Vercel)" },
{ value: VercelModel.Claude_Sonnet_5, label: "Claude Sonnet 5 (Vercel)" },
{ value: VercelModel.Claude_Opus_4_7, label: "Claude Opus 4.7 (Vercel)" },
{ value: VercelModel.Claude_Sonnet_4_6, label: "Claude Sonnet 4.6 (Vercel)" },
{ value: VercelModel.GPT_6_Sol, label: "GPT-6 Sol (Vercel)" },
{ value: VercelModel.GPT_5_5, label: "GPT-5.5 (Vercel)" },
{ value: VercelModel.Gemini_3_8_Flash, label: "Gemini 3.8 Flash (Vercel)" },
{ value: VercelModel.Gemini_3_5_Flash, label: "Gemini 3.5 Flash (Vercel)" },
{ value: VercelModel.Grok_4_7, label: "Grok 4.7 (Vercel)" },
{ value: VercelModel.Grok_4_3, label: "Grok 4.3 (Vercel)" },
],
},
Expand All @@ -238,6 +264,7 @@ export const MODEL_OPTIONS_BY_AGENT: Record<
{ value: CursorModel.GPT_5_4_Mini, label: "GPT-5.4 Mini" },
{ value: CursorModel.GPT_5_3_Codex, label: "GPT-5.3 Codex" },
{ value: CursorModel.Claude_Fable_5, label: "Claude Fable 5" },
{ value: CursorModel.Claude_Opus_5_5, label: "Claude Opus 5.5" },
{ value: CursorModel.Claude_Opus_5, label: "Claude Opus 5" },
{ value: CursorModel.Claude_Opus_4_8, label: "Claude Opus 4.8" },
{ value: CursorModel.Claude_Opus_4_7, label: "Claude Opus 4.7" },
Expand Down
7 changes: 7 additions & 0 deletions packages/python-sdk/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ All notable changes to `upstash-box` (Python) are documented here.

## Unreleased

- Add Claude Opus 5.5 model constants for Claude Code, OpenRouter, Vercel AI
Gateway, OpenCode/Zen, and Cursor, mirroring `@upstash/box`.
- Fix Vercel AI Gateway Grok identifiers: the gateway moved xAI models from the
`xai/` to the `spacexai/` namespace, so `VercelModel.GROK_*` now resolve again.
Add `VercelModel.GROK_4_7`, `GPT_6_SOL`, `GPT_6_LUNA`, and `GEMINI_3_8_FLASH`.
- Add GPT-6 Sol and GPT-6 Luna to `OpenAICodex`, `OpenRouterModel`, and
`OpenCodeModel`.
- Fix `delete_boxes(box_ids=[])` deleting every box on the account. The API read
an empty id list as "no filter". `delete_boxes` and `delete_snapshots` now raise
`BoxError` before any request is made when the list is empty or contains a
Expand Down
39 changes: 39 additions & 0 deletions packages/python-sdk/tests/_async/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
CursorModel,
FinishChunk,
FinishUsage,
OpenAICodex,
OpenCodeModel,
OpenRouterModel,
PublicURL,
Expand All @@ -20,6 +21,44 @@
)


def test_claude_opus_5_5_model_identifier():
assert {
ClaudeCode.OPUS_5_5.value,
CursorModel.CLAUDE_OPUS_5_5.value,
OpenCodeModel.CLAUDE_OPUS_5_5.value,
OpenCodeModel.ZEN_CLAUDE_OPUS_5_5.value,
OpenRouterModel.CLAUDE_OPUS_5_5.value,
VercelModel.CLAUDE_OPUS_5_5.value,
} == {
"anthropic/claude-opus-5-5",
"cursor/claude-opus-5-5",
"opencode/claude-opus-5-5",
"openrouter/anthropic/claude-opus-5.5",
"vercel/anthropic/claude-opus-5.5",
}


def test_gpt_6_sol_and_luna_model_identifiers():
assert OpenAICodex.GPT_6_SOL.value == "openai/gpt-6-sol"
assert OpenAICodex.GPT_6_LUNA.value == "openai/gpt-6-luna"
assert OpenRouterModel.GPT_6_SOL.value == "openrouter/openai/gpt-6-sol"
assert OpenRouterModel.GPT_6_LUNA.value == "openrouter/openai/gpt-6-luna"
assert OpenCodeModel.GPT_6_SOL.value == "opencode/gpt-6-sol"
assert OpenCodeModel.GPT_6_LUNA.value == "opencode/gpt-6-luna"


def test_vercel_gateway_model_identifiers():
# xAI models moved from the xai/ to the spacexai/ namespace on the gateway.
assert VercelModel.GROK_BUILD_0_1.value == "vercel/spacexai/grok-build-0.1"
assert VercelModel.GROK_4_7.value == "vercel/spacexai/grok-4.7"
assert VercelModel.GROK_4_3.value == "vercel/spacexai/grok-4.3"
assert VercelModel.GROK_4_20_REASONING.value == "vercel/spacexai/grok-4.20-reasoning"
assert VercelModel.GPT_6_SOL.value == "vercel/openai/gpt-6-sol"
assert VercelModel.GPT_6_LUNA.value == "vercel/openai/gpt-6-luna"
assert VercelModel.GEMINI_3_8_FLASH.value == "vercel/google/gemini-3.8-flash"
assert not any(m.value.startswith("vercel/xai/") for m in VercelModel)


def test_claude_opus_5_model_identifier():
assert {
ClaudeCode.OPUS_5.value,
Expand Down
Loading
Loading