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
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Future built-in tool candidates (`apply_patch`, `request_user_input`, `webfetch`
Native Z.ai GLM-5.2 provider behavior is specified in `dev-docs/specs/zai-provider.md` and implemented through core `ChatZai` plus runtime `model.provider=zai`.
Native Moonshot Kimi K3 provider behavior is specified in `dev-docs/specs/moonshot-provider.md` and implemented through core `ChatMoonshot` plus runtime `model.provider=moonshot`.
Native xAI Grok 4.5 provider behavior is specified in `dev-docs/specs/xai-provider.md` and implemented through core `ChatXai` plus runtime `model.provider=xai`.
Anthropic Claude Opus 5 uses the existing native `ChatAnthropic` path with model ID `claude-opus-5`, adaptive thinking across `low|medium|high|xhigh|max`, and Claude API fast mode; its static model contract lives in `packages/core/src/models/anthropic.ts`.

## Implementation plan

Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/models/anthropic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ export const ANTHROPIC_MODELS: ModelSpec[] = [
maxInputTokens: 1_000_000,
maxOutputTokens: 128_000,
},
{
id: "claude-opus-5",
provider: "anthropic",
contextWindow: 1_000_000,
maxInputTokens: 1_000_000,
maxOutputTokens: 128_000,
supportsFast: true,
},
{
id: "claude-opus-4-8",
provider: "anthropic",
Expand Down
14 changes: 14 additions & 0 deletions packages/core/tests/model-registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,20 @@ describe("resolveProviderModelId", () => {
});
});

test("registers Claude Opus 5 with published limits and fast mode", () => {
const registry = createModelRegistry(ANTHROPIC_MODELS);

expect(resolveModel(registry, "claude-opus-5", "anthropic")).toEqual({
id: "claude-opus-5",
provider: "anthropic",
contextWindow: 1_000_000,
maxInputTokens: 1_000_000,
maxOutputTokens: 128_000,
supportsFast: true,
});
expect(supportsFastMode(registry, "claude-opus-5", "anthropic")).toBe(true);
});

test("uses GPT-5.6 as the OpenAI default without a registry alias", () => {
const registry = createModelRegistry(OPENAI_MODELS);

Expand Down
12 changes: 12 additions & 0 deletions packages/runtime/src/model-reasoning.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,17 @@ const ANTHROPIC_REASONING_MODEL_TABLE: Readonly<
},
outputEffortByLevel: ANTHROPIC_OUTPUT_EFFORT_ALL,
},
"claude-opus-5": {
supportedLevels: ["low", "medium", "high", "xhigh", "max"],
budgetPresetByLevel: {
low: "reasoning_low",
medium: "reasoning_medium",
high: "reasoning_high",
xhigh: "reasoning_xhigh",
max: "reasoning_xhigh",
},
outputEffortByLevel: ANTHROPIC_OUTPUT_EFFORT_ALL,
},
"claude-opus-4-8": {
supportedLevels: ["low", "medium", "high", "xhigh", "max"],
budgetPresetByLevel: {
Expand Down Expand Up @@ -238,6 +249,7 @@ const ANTHROPIC_REASONING_MODEL_TABLE: Readonly<

const ANTHROPIC_ADAPTIVE_THINKING_MODELS = new Set<string>([
"claude-fable-5",
"claude-opus-5",
"claude-opus-4-8",
"claude-opus-4-7",
"claude-opus-4-6",
Expand Down
7 changes: 7 additions & 0 deletions packages/runtime/tests/model-fast.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ describe("model fast mode resolution", () => {
});

test("enables Anthropic fast mode for supported models only", () => {
expect(
resolveFastMode({
provider: "anthropic",
model: "claude-opus-5",
requested: true,
}),
).toEqual({ enabled: true, provider: "anthropic", fastMode: true });
expect(
resolveFastMode({
provider: "anthropic",
Expand Down
16 changes: 16 additions & 0 deletions packages/runtime/tests/model-list-static.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,22 @@ describe("model.list static providers", () => {
});
});

test("lists Claude Opus 5 from static metadata", async () => {
const result = await buildProviderModelList({
provider: "anthropic",
includeDetails: true,
log: () => {},
providerEntriesOverride: {},
});

expect(result.models).toContain("claude-opus-5");
expect(result.details?.["claude-opus-5"]).toEqual({
context_window: 1_000_000,
max_input_tokens: 1_000_000,
max_output_tokens: 128_000,
});
});

test("details follow merged runtime registry for static providers", async () => {
const providerEntries: Record<string, ModelEntry> = {
"gpt-5.6": {
Expand Down
15 changes: 15 additions & 0 deletions packages/runtime/tests/model-reasoning.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,21 @@ describe("model reasoning mapping", () => {
expect(mapped.usedFallbackModelProfile).toBe(false);
});

test.each(["low", "medium", "high", "xhigh", "max"] as const)(
"maps Claude Opus 5 %s to native adaptive effort",
(requested) => {
const mapped = resolveAnthropicReasoning({
model: "claude-opus-5",
requested,
});
expect(mapped.applied).toBe(requested);
expect(mapped.thinking).toEqual({ type: "adaptive" });
expect(mapped.outputConfig).toEqual({ effort: requested });
expect(mapped.fallbackApplied).toBe(false);
expect(mapped.usedFallbackModelProfile).toBe(false);
},
);

test("uses conservative fallback profile for unknown anthropic model", () => {
const missing: string[] = [];
const mapped = resolveAnthropicReasoning({
Expand Down
Loading