| ... | @@ -48,50 +48,42 @@ const CLAUDE_PRESENTATION = { | ... | @@ -48,50 +48,42 @@ const CLAUDE_PRESENTATION = { |
| 48 | displayName: "Claude", | 48 | displayName: "Claude", |
| 49 | showInteractionModeToggle: true, | 49 | showInteractionModeToggle: true, |
| 50 | } as const; | 50 | } as const; |
| | 51 | const MINIMUM_CLAUDE_FABLE_5_VERSION = "2.1.169"; |
| 51 | const MINIMUM_CLAUDE_OPUS_4_8_VERSION = "2.1.154"; | 52 | const MINIMUM_CLAUDE_OPUS_4_8_VERSION = "2.1.154"; |
| 52 | const MINIMUM_CLAUDE_OPUS_4_7_VERSION = "2.1.111"; | 53 | const MINIMUM_CLAUDE_OPUS_4_7_VERSION = "2.1.111"; |
| 53 | | 54 | |
| 54 | const CLAUDE_EFFORT_OPTIONS = { | | |
| 55 | opus48: [ | | |
| 56 | { value: "low", label: "Low" }, | | |
| 57 | { value: "medium", label: "Medium" }, | | |
| 58 | { value: "high", label: "High", isDefault: true }, | | |
| 59 | { value: "xhigh", label: "Extra High" }, | | |
| 60 | { value: "max", label: "Max" }, | | |
| 61 | { value: "ultracode", label: "Ultracode" }, | | |
| 62 | { value: "ultrathink", label: "Ultrathink" }, | | |
| 63 | ], | | |
| 64 | opus47: [ | | |
| 65 | { value: "low", label: "Low" }, | | |
| 66 | { value: "medium", label: "Medium" }, | | |
| 67 | { value: "high", label: "High" }, | | |
| 68 | { value: "xhigh", label: "Extra High", isDefault: true }, | | |
| 69 | { value: "max", label: "Max" }, | | |
| 70 | { value: "ultrathink", label: "Ultrathink" }, | | |
| 71 | ], | | |
| 72 | opus46: [ | | |
| 73 | { value: "low", label: "Low" }, | | |
| 74 | { value: "medium", label: "Medium" }, | | |
| 75 | { value: "high", label: "High", isDefault: true }, | | |
| 76 | { value: "max", label: "Max" }, | | |
| 77 | { value: "ultrathink", label: "Ultrathink" }, | | |
| 78 | ], | | |
| 79 | sonnet46: [ | | |
| 80 | { value: "low", label: "Low" }, | | |
| 81 | { value: "medium", label: "Medium" }, | | |
| 82 | { value: "high", label: "High", isDefault: true }, | | |
| 83 | { value: "max", label: "Max" }, | | |
| 84 | { value: "ultrathink", label: "Ultrathink" }, | | |
| 85 | ], | | |
| 86 | opus45: [ | | |
| 87 | { value: "low", label: "Low" }, | | |
| 88 | { value: "medium", label: "Medium" }, | | |
| 89 | { value: "high", label: "High", isDefault: true }, | | |
| 90 | { value: "max", label: "Max" }, | | |
| 91 | ], | | |
| 92 | } as const; | | |
| 93 | | | |
| 94 | const BUILT_IN_MODELS: ReadonlyArray<ServerProviderModel> = [ | 55 | const BUILT_IN_MODELS: ReadonlyArray<ServerProviderModel> = [ |
| | 56 | { |
| | 57 | slug: "claude-fable-5", |
| | 58 | name: "Claude Fable 5", |
| | 59 | isCustom: false, |
| | 60 | capabilities: createModelCapabilities({ |
| | 61 | optionDescriptors: [ |
| | 62 | buildSelectOptionDescriptor({ |
| | 63 | id: "effort", |
| | 64 | label: "Reasoning", |
| | 65 | options: [ |
| | 66 | { value: "low", label: "Low" }, |
| | 67 | { value: "medium", label: "Medium" }, |
| | 68 | { value: "high", label: "High", isDefault: true }, |
| | 69 | { value: "xhigh", label: "Extra High" }, |
| | 70 | { value: "max", label: "Max" }, |
| | 71 | { value: "ultracode", label: "Ultracode" }, |
| | 72 | { value: "ultrathink", label: "Ultrathink" }, |
| | 73 | ], |
| | 74 | promptInjectedValues: ["ultrathink"], |
| | 75 | }), |
| | 76 | buildSelectOptionDescriptor({ |
| | 77 | id: "contextWindow", |
| | 78 | label: "Context Window", |
| | 79 | options: [ |
| | 80 | { value: "200k", label: "200k", isDefault: true }, |
| | 81 | { value: "1m", label: "1M" }, |
| | 82 | ], |
| | 83 | }), |
| | 84 | ], |
| | 85 | }), |
| | 86 | }, |
| 95 | { | 87 | { |
| 96 | slug: "claude-opus-4-8", | 88 | slug: "claude-opus-4-8", |
| 97 | name: "Claude Opus 4.8", | 89 | name: "Claude Opus 4.8", |
| ... | @@ -101,9 +93,21 @@ const BUILT_IN_MODELS: ReadonlyArray<ServerProviderModel> = [ | ... | @@ -101,9 +93,21 @@ const BUILT_IN_MODELS: ReadonlyArray<ServerProviderModel> = [ |
| 101 | buildSelectOptionDescriptor({ | 93 | buildSelectOptionDescriptor({ |
| 102 | id: "effort", | 94 | id: "effort", |
| 103 | label: "Reasoning", | 95 | label: "Reasoning", |
| 104 | options: CLAUDE_EFFORT_OPTIONS.opus48, | 96 | options: [ |
| | 97 | { value: "low", label: "Low" }, |
| | 98 | { value: "medium", label: "Medium" }, |
| | 99 | { value: "high", label: "High", isDefault: true }, |
| | 100 | { value: "xhigh", label: "Extra High" }, |
| | 101 | { value: "max", label: "Max" }, |
| | 102 | { value: "ultracode", label: "Ultracode" }, |
| | 103 | { value: "ultrathink", label: "Ultrathink" }, |
| | 104 | ], |
| 105 | promptInjectedValues: ["ultrathink"], | 105 | promptInjectedValues: ["ultrathink"], |
| 106 | }), | 106 | }), |
| | 107 | buildBooleanOptionDescriptor({ |
| | 108 | id: "fastMode", |
| | 109 | label: "Fast Mode", |
| | 110 | }), |
| 107 | buildSelectOptionDescriptor({ | 111 | buildSelectOptionDescriptor({ |
| 108 | id: "contextWindow", | 112 | id: "contextWindow", |
| 109 | label: "Context Window", | 113 | label: "Context Window", |
| ... | @@ -124,9 +128,20 @@ const BUILT_IN_MODELS: ReadonlyArray<ServerProviderModel> = [ | ... | @@ -124,9 +128,20 @@ const BUILT_IN_MODELS: ReadonlyArray<ServerProviderModel> = [ |
| 124 | buildSelectOptionDescriptor({ | 128 | buildSelectOptionDescriptor({ |
| 125 | id: "effort", | 129 | id: "effort", |
| 126 | label: "Reasoning", | 130 | label: "Reasoning", |
| 127 | options: CLAUDE_EFFORT_OPTIONS.opus47, | 131 | options: [ |
| | 132 | { value: "low", label: "Low" }, |
| | 133 | { value: "medium", label: "Medium" }, |
| | 134 | { value: "high", label: "High" }, |
| | 135 | { value: "xhigh", label: "Extra High", isDefault: true }, |
| | 136 | { value: "max", label: "Max" }, |
| | 137 | { value: "ultrathink", label: "Ultrathink" }, |
| | 138 | ], |
| 128 | promptInjectedValues: ["ultrathink"], | 139 | promptInjectedValues: ["ultrathink"], |
| 129 | }), | 140 | }), |
| | 141 | buildBooleanOptionDescriptor({ |
| | 142 | id: "fastMode", |
| | 143 | label: "Fast Mode", |
| | 144 | }), |
| 130 | buildSelectOptionDescriptor({ | 145 | buildSelectOptionDescriptor({ |
| 131 | id: "contextWindow", | 146 | id: "contextWindow", |
| 132 | label: "Context Window", | 147 | label: "Context Window", |
| ... | @@ -147,7 +162,13 @@ const BUILT_IN_MODELS: ReadonlyArray<ServerProviderModel> = [ | ... | @@ -147,7 +162,13 @@ const BUILT_IN_MODELS: ReadonlyArray<ServerProviderModel> = [ |
| 147 | buildSelectOptionDescriptor({ | 162 | buildSelectOptionDescriptor({ |
| 148 | id: "effort", | 163 | id: "effort", |
| 149 | label: "Reasoning", | 164 | label: "Reasoning", |
| 150 | options: CLAUDE_EFFORT_OPTIONS.opus46, | 165 | options: [ |
| | 166 | { value: "low", label: "Low" }, |
| | 167 | { value: "medium", label: "Medium" }, |
| | 168 | { value: "high", label: "High", isDefault: true }, |
| | 169 | { value: "max", label: "Max" }, |
| | 170 | { value: "ultrathink", label: "Ultrathink" }, |
| | 171 | ], |
| 151 | promptInjectedValues: ["ultrathink"], | 172 | promptInjectedValues: ["ultrathink"], |
| 152 | }), | 173 | }), |
| 153 | buildBooleanOptionDescriptor({ | 174 | buildBooleanOptionDescriptor({ |
| ... | @@ -174,7 +195,12 @@ const BUILT_IN_MODELS: ReadonlyArray<ServerProviderModel> = [ | ... | @@ -174,7 +195,12 @@ const BUILT_IN_MODELS: ReadonlyArray<ServerProviderModel> = [ |
| 174 | buildSelectOptionDescriptor({ | 195 | buildSelectOptionDescriptor({ |
| 175 | id: "effort", | 196 | id: "effort", |
| 176 | label: "Reasoning", | 197 | label: "Reasoning", |
| 177 | options: CLAUDE_EFFORT_OPTIONS.opus45, | 198 | options: [ |
| | 199 | { value: "low", label: "Low" }, |
| | 200 | { value: "medium", label: "Medium" }, |
| | 201 | { value: "high", label: "High", isDefault: true }, |
| | 202 | { value: "max", label: "Max" }, |
| | 203 | ], |
| 178 | }), | 204 | }), |
| 179 | buildBooleanOptionDescriptor({ | 205 | buildBooleanOptionDescriptor({ |
| 180 | id: "fastMode", | 206 | id: "fastMode", |
| ... | @@ -192,7 +218,13 @@ const BUILT_IN_MODELS: ReadonlyArray<ServerProviderModel> = [ | ... | @@ -192,7 +218,13 @@ const BUILT_IN_MODELS: ReadonlyArray<ServerProviderModel> = [ |
| 192 | buildSelectOptionDescriptor({ | 218 | buildSelectOptionDescriptor({ |
| 193 | id: "effort", | 219 | id: "effort", |
| 194 | label: "Reasoning", | 220 | label: "Reasoning", |
| 195 | options: CLAUDE_EFFORT_OPTIONS.sonnet46, | 221 | options: [ |
| | 222 | { value: "low", label: "Low" }, |
| | 223 | { value: "medium", label: "Medium" }, |
| | 224 | { value: "high", label: "High", isDefault: true }, |
| | 225 | { value: "max", label: "Max" }, |
| | 226 | { value: "ultrathink", label: "Ultrathink" }, |
| | 227 | ], |
| 196 | promptInjectedValues: ["ultrathink"], | 228 | promptInjectedValues: ["ultrathink"], |
| 197 | }), | 229 | }), |
| 198 | buildSelectOptionDescriptor({ | 230 | buildSelectOptionDescriptor({ |
| ... | @@ -221,6 +253,10 @@ const BUILT_IN_MODELS: ReadonlyArray<ServerProviderModel> = [ | ... | @@ -221,6 +253,10 @@ const BUILT_IN_MODELS: ReadonlyArray<ServerProviderModel> = [ |
| 221 | }, | 253 | }, |
| 222 | ]; | 254 | ]; |
| 223 | | 255 | |
| | 256 | function supportsClaudeFable5(version: string | null | undefined): boolean { |
| | 257 | return version ? compareSemverVersions(version, MINIMUM_CLAUDE_FABLE_5_VERSION) >= 0 : false; |
| | 258 | } |
| | 259 | |
| 224 | function supportsClaudeOpus48(version: string | null | undefined): boolean { | 260 | function supportsClaudeOpus48(version: string | null | undefined): boolean { |
| 225 | return version ? compareSemverVersions(version, MINIMUM_CLAUDE_OPUS_4_8_VERSION) >= 0 : false; | 261 | return version ? compareSemverVersions(version, MINIMUM_CLAUDE_OPUS_4_8_VERSION) >= 0 : false; |
| 226 | } | 262 | } |
| ... | @@ -233,6 +269,9 @@ function getBuiltInClaudeModelsForVersion( | ... | @@ -233,6 +269,9 @@ function getBuiltInClaudeModelsForVersion( |
| 233 | version: string | null | undefined, | 269 | version: string | null | undefined, |
| 234 | ): ReadonlyArray<ServerProviderModel> { | 270 | ): ReadonlyArray<ServerProviderModel> { |
| 235 | return BUILT_IN_MODELS.filter((model) => { | 271 | return BUILT_IN_MODELS.filter((model) => { |
| | 272 | if (model.slug === "claude-fable-5") { |
| | 273 | return supportsClaudeFable5(version); |
| | 274 | } |
| 236 | if (model.slug === "claude-opus-4-8") { | 275 | if (model.slug === "claude-opus-4-8") { |
| 237 | return supportsClaudeOpus48(version); | 276 | return supportsClaudeOpus48(version); |
| 238 | } | 277 | } |
| ... | @@ -243,6 +282,11 @@ function getBuiltInClaudeModelsForVersion( | ... | @@ -243,6 +282,11 @@ function getBuiltInClaudeModelsForVersion( |
| 243 | }); | 282 | }); |
| 244 | } | 283 | } |
| 245 | | 284 | |
| | 285 | function formatClaudeFable5UpgradeMessage(version: string | null): string { |
| | 286 | const versionLabel = version ? `v${version}` : "the installed version"; |
| | 287 | return `Claude Code ${versionLabel} is too old for Claude Fable 5. Upgrade to v${MINIMUM_CLAUDE_FABLE_5_VERSION} or newer to access it.`; |
| | 288 | } |
| | 289 | |
| 246 | function formatClaudeOpus48UpgradeMessage(version: string | null): string { | 290 | function formatClaudeOpus48UpgradeMessage(version: string | null): string { |
| 247 | const versionLabel = version ? `v${version}` : "the installed version"; | 291 | const versionLabel = version ? `v${version}` : "the installed version"; |
| 248 | return `Claude Code ${versionLabel} is too old for Claude Opus 4.8. Upgrade to v${MINIMUM_CLAUDE_OPUS_4_8_VERSION} or newer to access it.`; | 292 | return `Claude Code ${versionLabel} is too old for Claude Opus 4.8. Upgrade to v${MINIMUM_CLAUDE_OPUS_4_8_VERSION} or newer to access it.`; |
| ... | @@ -294,7 +338,7 @@ export function normalizeClaudeCliEffort( | ... | @@ -294,7 +338,7 @@ export function normalizeClaudeCliEffort( |
| 294 | if (effort === "ultracode") { | 338 | if (effort === "ultracode") { |
| 295 | return "xhigh"; | 339 | return "xhigh"; |
| 296 | } | 340 | } |
| 297 | if (effort === "xhigh" && model !== "claude-opus-4-8") { | 341 | if (effort === "xhigh" && model !== "claude-fable-5" && model !== "claude-opus-4-8") { |
| 298 | return "max"; | 342 | return "max"; |
| 299 | } | 343 | } |
| 300 | if (effort === "max" && model === "claude-sonnet-4-6") { | 344 | if (effort === "max" && model === "claude-sonnet-4-6") { |
| ... | @@ -688,11 +732,13 @@ export const checkClaudeProviderStatus = Effect.fn("checkClaudeProviderStatus")( | ... | @@ -688,11 +732,13 @@ export const checkClaudeProviderStatus = Effect.fn("checkClaudeProviderStatus")( |
| 688 | claudeSettings.customModels, | 732 | claudeSettings.customModels, |
| 689 | DEFAULT_CLAUDE_MODEL_CAPABILITIES, | 733 | DEFAULT_CLAUDE_MODEL_CAPABILITIES, |
| 690 | ); | 734 | ); |
| 691 | const versionUpgradeMessage = supportsClaudeOpus48(parsedVersion) | 735 | const versionUpgradeMessage = supportsClaudeFable5(parsedVersion) |
| 692 | ? undefined | 736 | ? undefined |
| 693 | : supportsClaudeOpus47(parsedVersion) | 737 | : supportsClaudeOpus48(parsedVersion) |
| 694 | ? formatClaudeOpus48UpgradeMessage(parsedVersion) | 738 | ? formatClaudeFable5UpgradeMessage(parsedVersion) |
| 695 | : formatClaudeOpus47UpgradeMessage(parsedVersion); | 739 | : supportsClaudeOpus47(parsedVersion) |
| | 740 | ? formatClaudeOpus48UpgradeMessage(parsedVersion) |
| | 741 | : formatClaudeOpus47UpgradeMessage(parsedVersion); |
| 696 | | 742 | |
| 697 | const capabilities = resolveCapabilities | 743 | const capabilities = resolveCapabilities |
| 698 | ? yield* resolveCapabilities(claudeSettings).pipe(Effect.orElseSucceed(() => undefined)) | 744 | ? yield* resolveCapabilities(claudeSettings).pipe(Effect.orElseSucceed(() => undefined)) |