feat(claude): add Opus 5 model

This commit is contained in:
Mohamed Boudra
2026-07-24 19:37:27 +02:00
parent d98c5e77f7
commit 7ef3376b62
3 changed files with 29 additions and 4 deletions

View File

@@ -414,6 +414,7 @@ describe("ClaudeAgentClient.fetchCatalog", () => {
}); });
expect(models.map((m) => m.id)).toEqual([ expect(models.map((m) => m.id)).toEqual([
"claude-opus-5",
"claude-fable-5", "claude-fable-5",
"claude-opus-4-8[1m]", "claude-opus-4-8[1m]",
"claude-opus-4-8", "claude-opus-4-8",
@@ -433,7 +434,7 @@ describe("ClaudeAgentClient.fetchCatalog", () => {
} }
const defaultModel = models.find((m) => m.isDefault); const defaultModel = models.find((m) => m.isDefault);
expect(defaultModel?.id).toBe("claude-opus-4-8"); expect(defaultModel?.id).toBe("claude-opus-5");
} finally { } finally {
await fs.rm(emptyConfigDir, { recursive: true, force: true }); await fs.rm(emptyConfigDir, { recursive: true, force: true });
} }
@@ -456,6 +457,7 @@ describe("ClaudeAgentClient.fetchCatalog", () => {
return models.find((model) => model.id === modelId)?.thinkingOptions?.map(({ id }) => id); return models.find((model) => model.id === modelId)?.thinkingOptions?.map(({ id }) => id);
}; };
expect(getThinkingIds("claude-opus-5")).toContain("ultracode");
expect(getThinkingIds("claude-fable-5")).toContain("ultracode"); expect(getThinkingIds("claude-fable-5")).toContain("ultracode");
expect(getThinkingIds("claude-opus-4-8[1m]")).toContain("ultracode"); expect(getThinkingIds("claude-opus-4-8[1m]")).toContain("ultracode");
expect(getThinkingIds("claude-opus-4-8")).toContain("ultracode"); expect(getThinkingIds("claude-opus-4-8")).toContain("ultracode");

View File

@@ -30,6 +30,15 @@ export const CLAUDE_DISABLED_THINKING_OPTION_ID = "off";
export const CLAUDE_ULTRACODE_THINKING_OPTION_ID = "ultracode"; export const CLAUDE_ULTRACODE_THINKING_OPTION_ID = "ultracode";
export const CLAUDE_MODEL_MANIFEST = [ export const CLAUDE_MODEL_MANIFEST = [
{
id: "claude-opus-5",
label: "Opus 5",
description: "Opus 5 · Latest release",
isDefault: true,
contextWindowMaxTokens: 1_000_000,
effortLevels: CLAUDE_EFFORT_LEVELS.xhigh,
supportsThinkingDisabled: true,
},
{ {
id: "claude-fable-5", id: "claude-fable-5",
label: "Fable 5", label: "Fable 5",
@@ -49,8 +58,7 @@ export const CLAUDE_MODEL_MANIFEST = [
{ {
id: "claude-opus-4-8", id: "claude-opus-4-8",
label: "Opus 4.8", label: "Opus 4.8",
description: "Opus 4.8 · Latest release", description: "Opus 4.8 · Previous release",
isDefault: true,
contextWindowMaxTokens: 200_000, contextWindowMaxTokens: 200_000,
effortLevels: CLAUDE_EFFORT_LEVELS.xhigh, effortLevels: CLAUDE_EFFORT_LEVELS.xhigh,
supportsThinkingDisabled: true, supportsThinkingDisabled: true,

View File

@@ -42,6 +42,7 @@ describe("getClaudeModels", () => {
it("returns all claude models", () => { it("returns all claude models", () => {
const models = getClaudeModels(); const models = getClaudeModels();
expect(models.map((m) => m.id)).toEqual([ expect(models.map((m) => m.id)).toEqual([
"claude-opus-5",
"claude-fable-5", "claude-fable-5",
"claude-opus-4-8[1m]", "claude-opus-4-8[1m]",
"claude-opus-4-8", "claude-opus-4-8",
@@ -60,7 +61,7 @@ describe("getClaudeModels", () => {
const models = getClaudeModels(); const models = getClaudeModels();
const defaults = models.filter((m) => m.isDefault); const defaults = models.filter((m) => m.isDefault);
expect(defaults).toHaveLength(1); expect(defaults).toHaveLength(1);
expect(defaults[0].id).toBe("claude-opus-4-8"); expect(defaults[0].id).toBe("claude-opus-5");
}); });
it("defines context window sizes in the catalog", () => { it("defines context window sizes in the catalog", () => {
@@ -70,6 +71,7 @@ describe("getClaudeModels", () => {
expect(contextWindows).toEqual( expect(contextWindows).toEqual(
new Map([ new Map([
["claude-opus-5", 1_000_000],
["claude-fable-5", 1_000_000], ["claude-fable-5", 1_000_000],
["claude-opus-4-8[1m]", 1_000_000], ["claude-opus-4-8[1m]", 1_000_000],
["claude-opus-4-8", 200_000], ["claude-opus-4-8", 200_000],
@@ -88,6 +90,15 @@ describe("getClaudeModels", () => {
it("derives thinking options from model effort capabilities", () => { it("derives thinking options from model effort capabilities", () => {
const models = new Map(getClaudeModels().map((model) => [model.id, model])); const models = new Map(getClaudeModels().map((model) => [model.id, model]));
expect(models.get("claude-opus-5")?.thinkingOptions?.map((option) => option.id)).toEqual([
CLAUDE_DISABLED_THINKING_OPTION_ID,
"low",
"medium",
"high",
"xhigh",
"max",
CLAUDE_ULTRACODE_THINKING_OPTION_ID,
]);
expect(models.get("claude-sonnet-5")?.thinkingOptions?.map((option) => option.id)).toEqual([ expect(models.get("claude-sonnet-5")?.thinkingOptions?.map((option) => option.id)).toEqual([
CLAUDE_DISABLED_THINKING_OPTION_ID, CLAUDE_DISABLED_THINKING_OPTION_ID,
"low", "low",
@@ -128,6 +139,8 @@ describe("getClaudeModels", () => {
}); });
it.each([ it.each([
["claude-opus-5", true, "low"],
["claude-opus-5-20260724", true, "low"],
["claude-sonnet-5", true, "low"], ["claude-sonnet-5", true, "low"],
["claude-sonnet-5-20260101", true, "low"], ["claude-sonnet-5-20260101", true, "low"],
["claude-fable-5", false, "low"], ["claude-fable-5", false, "low"],
@@ -286,6 +299,7 @@ describe("ClaudeAgentClient.fetchCatalog", () => {
describe("normalizeClaudeRuntimeModelId", () => { describe("normalizeClaudeRuntimeModelId", () => {
it("returns exact match for known model IDs", () => { it("returns exact match for known model IDs", () => {
expect(normalizeClaudeRuntimeModelId("claude-opus-5")).toBe("claude-opus-5");
expect(normalizeClaudeRuntimeModelId("claude-fable-5")).toBe("claude-fable-5"); expect(normalizeClaudeRuntimeModelId("claude-fable-5")).toBe("claude-fable-5");
expect(normalizeClaudeRuntimeModelId("claude-sonnet-5")).toBe("claude-sonnet-5"); expect(normalizeClaudeRuntimeModelId("claude-sonnet-5")).toBe("claude-sonnet-5");
expect(normalizeClaudeRuntimeModelId("claude-opus-4-6")).toBe("claude-opus-4-6"); expect(normalizeClaudeRuntimeModelId("claude-opus-4-6")).toBe("claude-opus-4-6");
@@ -295,6 +309,7 @@ describe("normalizeClaudeRuntimeModelId", () => {
}); });
it("normalizes dated model IDs to base model", () => { it("normalizes dated model IDs to base model", () => {
expect(normalizeClaudeRuntimeModelId("claude-opus-5-20260724")).toBe("claude-opus-5");
expect(normalizeClaudeRuntimeModelId("claude-fable-5-20260301")).toBe("claude-fable-5"); expect(normalizeClaudeRuntimeModelId("claude-fable-5-20260301")).toBe("claude-fable-5");
expect(normalizeClaudeRuntimeModelId("claude-sonnet-5-20260101")).toBe("claude-sonnet-5"); expect(normalizeClaudeRuntimeModelId("claude-sonnet-5-20260101")).toBe("claude-sonnet-5");
expect(normalizeClaudeRuntimeModelId("claude-opus-4-6-20260101")).toBe("claude-opus-4-6"); expect(normalizeClaudeRuntimeModelId("claude-opus-4-6-20260101")).toBe("claude-opus-4-6");