From e4a2e873485c38d8a6150acf4f6aa6cd722f1540 Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Tue, 10 Nov 2026 01:42:38 +0100 Subject: [PATCH] fix(claude): default Fable and Mythos 5.2 to medium effort Claude Code 2.1.321's model catalog declares default_effort "medium" for both models, so Paseo's inherited "high" would start sessions above Claude Code's own default and cost more. Gate Mythos 5.2 on 2.1.321 as well: older Claude Code can advertise the mythos alias without Paseo knowing its capabilities there. The Fast control now applies beyond Opus, so its description no longer names a model family. Co-authored-by: gudcks <84506708+gudcks@users.noreply.github.com> --- .../agent/providers/claude/agent.test.ts | 3 +- .../providers/claude/feature-definitions.ts | 2 +- .../agent/providers/claude/model-manifest.ts | 3 ++ .../agent/providers/claude/models.test.ts | 37 ++++++++++++++++--- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/packages/server/src/server/agent/providers/claude/agent.test.ts b/packages/server/src/server/agent/providers/claude/agent.test.ts index b654745519..3aa96635fc 100644 --- a/packages/server/src/server/agent/providers/claude/agent.test.ts +++ b/packages/server/src/server/agent/providers/claude/agent.test.ts @@ -1614,7 +1614,8 @@ describe("ClaudeAgentSession features", () => { test.each([ ["supported model", "claude-opus-4-8", { type: "disabled" }, undefined], ["Mythos 5.1", "claude-mythos-5-1", { type: "adaptive", display: "summarized" }, "high"], - ["Fable 5.2", "claude-fable-5-2", { type: "adaptive", display: "summarized" }, "high"], + ["Fable 5.2", "claude-fable-5-2", { type: "adaptive", display: "summarized" }, "medium"], + ["Mythos 5.2", "claude-mythos-5-2", { type: "adaptive", display: "summarized" }, "medium"], ["Haiku 5.5", "claude-haiku-5-5", { type: "disabled" }, undefined], ["unsupported model", "claude-fable-5", { type: "adaptive", display: "summarized" }, "high"], ["custom model", "openrouter/anthropic/claude-opus-4-8", undefined, undefined], diff --git a/packages/server/src/server/agent/providers/claude/feature-definitions.ts b/packages/server/src/server/agent/providers/claude/feature-definitions.ts index 0606860745..46df4d94bb 100644 --- a/packages/server/src/server/agent/providers/claude/feature-definitions.ts +++ b/packages/server/src/server/agent/providers/claude/feature-definitions.ts @@ -5,7 +5,7 @@ export const CLAUDE_FAST_MODE_CONTROL: AgentOptionToggleControl = { type: "toggle", key: "fast_mode", label: "Fast", - description: "Lower latency Opus responses at higher token cost", + description: "Lower latency responses at higher token cost", tooltip: "Toggle fast mode", icon: "zap", }; diff --git a/packages/server/src/server/agent/providers/claude/model-manifest.ts b/packages/server/src/server/agent/providers/claude/model-manifest.ts index 686be00258..d73ae34f7d 100644 --- a/packages/server/src/server/agent/providers/claude/model-manifest.ts +++ b/packages/server/src/server/agent/providers/claude/model-manifest.ts @@ -63,6 +63,8 @@ export const CLAUDE_MODEL_MANIFEST = [ label: "Mythos 5.2", requiresDiscovery: true, description: "Mythos 5.2 · Requires verified access", + minimumClaudeCodeVersion: "2.1.321", + defaultThinkingOptionId: "medium", contextWindowMaxTokens: 1_000_000, effortLevels: CLAUDE_EFFORT_LEVELS.xhigh, supportsFastMode: true, @@ -80,6 +82,7 @@ export const CLAUDE_MODEL_MANIFEST = [ label: "Fable 5.2", description: "Fable 5.2 · Most powerful model", minimumClaudeCodeVersion: "2.1.321", + defaultThinkingOptionId: "medium", contextWindowMaxTokens: 1_000_000, effortLevels: CLAUDE_EFFORT_LEVELS.xhigh, supportsFastMode: true, diff --git a/packages/server/src/server/agent/providers/claude/models.test.ts b/packages/server/src/server/agent/providers/claude/models.test.ts index d7c57bdd98..1287fd6335 100644 --- a/packages/server/src/server/agent/providers/claude/models.test.ts +++ b/packages/server/src/server/agent/providers/claude/models.test.ts @@ -248,8 +248,8 @@ describe("getClaudeModels", () => { ["claude-sonnet-5-20260101", true, "high"], ["claude-fable-5", false, "high"], ["claude-fable-5-1", false, "high"], - ["claude-fable-5-2", false, "high"], - ["claude-mythos-5-2", false, "high"], + ["claude-fable-5-2", false, "medium"], + ["claude-mythos-5-2", false, "medium"], ["claude-haiku-5-5", true, "medium"], ["claude-haiku-5-5-20261007", true, "medium"], ["claude-haiku-4-5", false, undefined], @@ -829,14 +829,14 @@ describe("Claude Fable 5.1 catalog", () => { }); describe("Claude Fable 5.2 catalog", () => { - it("offers one 1M model with high default effort, always-on thinking, and fast mode", () => { + it("offers one 1M model with medium default effort, always-on thinking, and fast mode", () => { const models = getClaudeModels().filter((model) => model.id.startsWith("claude-fable-5-2")); expect(models).toHaveLength(1); expect(models[0]).toMatchObject({ id: "claude-fable-5-2", label: "Fable 5.2", contextWindowMaxTokens: 1_000_000, - defaultThinkingOptionId: "high", + defaultThinkingOptionId: "medium", }); expect(models[0].thinkingOptions?.map((option) => option.id)).toEqual([ "low", @@ -1047,14 +1047,39 @@ describe("Claude Mythos 5.1 catalog", () => { }); describe("Claude Mythos 5.2 catalog", () => { - it("offers one 1M model with high default effort, always-on thinking, and fast mode", () => { + it("stays hidden on Claude Code older than 2.1.321 even when advertised", async () => { + const configDir = await createClaudeConfigDir({}); + const client = new ClaudeAgentClient({ + logger: createTestLogger(), + resolveVersion: async () => "2.1.320", + runtimeSettings: { env: { CLAUDE_CONFIG_DIR: configDir } }, + discoverModels: async () => [ + { + value: "mythos", + resolvedModel: "claude-mythos-5-2", + displayName: "Mythos", + description: "", + }, + ], + }); + + const { models } = await client.fetchCatalog({ + scope: "workspace", + cwd: configDir, + force: false, + }); + + expect(models.some((model) => model.id === "claude-mythos-5-2")).toBe(false); + }); + + it("offers one 1M model with medium default effort, always-on thinking, and fast mode", () => { const models = getClaudeModels().filter((model) => model.id.startsWith("claude-mythos-5-2")); expect(models).toHaveLength(1); expect(models[0]).toMatchObject({ id: "claude-mythos-5-2", label: "Mythos 5.2", contextWindowMaxTokens: 1_000_000, - defaultThinkingOptionId: "high", + defaultThinkingOptionId: "medium", }); expect(models[0].thinkingOptions?.map((option) => option.id)).toEqual([ "low",