authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-06-30 11:40:35-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-06-30 11:40:35-07:00
log9d66b104feb761cff07c305d570610112bb5c8dc
treef0a02f1c5e8d5215656a78c1170294513cfc4a3f
parent51ea084c870457f22090e57b5c180144759cb993
signature Signed by PGP key B5690EEEBB952194

Add Claude Sonnet 5 as the default Claude model (#3620)


4 files changed, 43 insertions(+), 92 deletions(-)

apps/server/src/provider/Layers/ClaudeProvider.ts+36-1
...@@ -193,6 +193,36 @@ const BUILT_IN_MODELS: ReadonlyArray<ServerProviderModel> = [...@@ -193,6 +193,36 @@ const BUILT_IN_MODELS: ReadonlyArray<ServerProviderModel> = [
193 ],193 ],
194 }),194 }),
195 },195 },
196 {
197 slug: "claude-sonnet-5",
198 name: "Claude Sonnet 5",
199 isCustom: false,
200 capabilities: createModelCapabilities({
201 optionDescriptors: [
202 buildSelectOptionDescriptor({
203 id: "effort",
204 label: "Reasoning",
205 options: [
206 { value: "low", label: "Low" },
207 { value: "medium", label: "Medium" },
208 { value: "high", label: "High", isDefault: true },
209 { value: "xhigh", label: "Extra High" },
210 { value: "max", label: "Max" },
211 { value: "ultrathink", label: "Ultrathink" },
212 ],
213 promptInjectedValues: ["ultrathink"],
214 }),
215 buildSelectOptionDescriptor({
216 id: "contextWindow",
217 label: "Context Window",
218 options: [
219 { value: "200k", label: "200k", isDefault: true },
220 { value: "1m", label: "1M" },
221 ],
222 }),
223 ],
224 }),
225 },
196 {226 {
197 slug: "claude-sonnet-4-6",227 slug: "claude-sonnet-4-6",
198 name: "Claude Sonnet 4.6",228 name: "Claude Sonnet 4.6",
...@@ -322,7 +352,12 @@ export function normalizeClaudeCliEffort(...@@ -322,7 +352,12 @@ export function normalizeClaudeCliEffort(
322 if (effort === "ultracode") {352 if (effort === "ultracode") {
323 return "xhigh";353 return "xhigh";
324 }354 }
325 if (effort === "xhigh" && model !== "claude-fable-5" && model !== "claude-opus-4-8") {355 if (
356 effort === "xhigh" &&
357 model !== "claude-fable-5" &&
358 model !== "claude-opus-4-8" &&
359 model !== "claude-sonnet-5"
360 ) {
326 return "max";361 return "max";
327 }362 }
328 if (effort === "max" && model === "claude-sonnet-4-6") {363 if (effort === "max" && model === "claude-sonnet-4-6") {
apps/web/src/components/settings/ProviderModelsSection.tsx+1-1
...@@ -32,7 +32,7 @@ import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip";...@@ -32,7 +32,7 @@ import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip";
32 */32 */
33const CUSTOM_MODEL_PLACEHOLDER_BY_KIND: Partial<Record<ProviderDriverKind, string>> = {33const CUSTOM_MODEL_PLACEHOLDER_BY_KIND: Partial<Record<ProviderDriverKind, string>> = {
34 [ProviderDriverKind.make("codex")]: "gpt-6.7-codex-ultra-preview",34 [ProviderDriverKind.make("codex")]: "gpt-6.7-codex-ultra-preview",
35 [ProviderDriverKind.make("claudeAgent")]: "claude-sonnet-5-0",35 [ProviderDriverKind.make("claudeAgent")]: "claude-sonnet-5",
36 [ProviderDriverKind.make("cursor")]: "claude-sonnet-4-6",36 [ProviderDriverKind.make("cursor")]: "claude-sonnet-4-6",
37 [ProviderDriverKind.make("opencode")]: "openai/gpt-5",37 [ProviderDriverKind.make("opencode")]: "openai/gpt-5",
38};38};
packages/contracts/src/model.ts+5-2
...@@ -138,7 +138,7 @@ export const DEFAULT_GIT_TEXT_GENERATION_MODEL = "gpt-5.4-mini";...@@ -138,7 +138,7 @@ export const DEFAULT_GIT_TEXT_GENERATION_MODEL = "gpt-5.4-mini";
138138
139export const DEFAULT_MODEL_BY_PROVIDER: Partial<Record<ProviderDriverKind, string>> = {139export const DEFAULT_MODEL_BY_PROVIDER: Partial<Record<ProviderDriverKind, string>> = {
140 [CODEX_DRIVER_KIND]: DEFAULT_MODEL,140 [CODEX_DRIVER_KIND]: DEFAULT_MODEL,
141 [CLAUDE_DRIVER_KIND]: "claude-sonnet-4-6",141 [CLAUDE_DRIVER_KIND]: "claude-sonnet-5",
142 [CURSOR_DRIVER_KIND]: "auto",142 [CURSOR_DRIVER_KIND]: "auto",
143 [GROK_DRIVER_KIND]: "grok-build",143 [GROK_DRIVER_KIND]: "grok-build",
144 [OPENCODE_DRIVER_KIND]: "openai/gpt-5",144 [OPENCODE_DRIVER_KIND]: "openai/gpt-5",
...@@ -174,7 +174,10 @@ export const MODEL_SLUG_ALIASES_BY_PROVIDER: Partial<...@@ -174,7 +174,10 @@ export const MODEL_SLUG_ALIASES_BY_PROVIDER: Partial<
174 "opus-4.6": "claude-opus-4-6",174 "opus-4.6": "claude-opus-4-6",
175 "claude-opus-4.6": "claude-opus-4-6",175 "claude-opus-4.6": "claude-opus-4-6",
176 "claude-opus-4-6-20251117": "claude-opus-4-6",176 "claude-opus-4-6-20251117": "claude-opus-4-6",
177 sonnet: "claude-sonnet-4-6",177 sonnet: "claude-sonnet-5",
178 "sonnet-5": "claude-sonnet-5",
179 "claude-sonnet-5.0": "claude-sonnet-5",
180 "claude-sonnet-5-0": "claude-sonnet-5",
178 "sonnet-4.6": "claude-sonnet-4-6",181 "sonnet-4.6": "claude-sonnet-4-6",
179 "claude-sonnet-4.6": "claude-sonnet-4-6",182 "claude-sonnet-4.6": "claude-sonnet-4-6",
180 "claude-sonnet-4-6-20251117": "claude-sonnet-4-6",183 "claude-sonnet-4-6-20251117": "claude-sonnet-4-6",
packages/shared/src/model.test.ts+1-88
...@@ -1,13 +1,7 @@...@@ -1,13 +1,7 @@
1import { describe, expect, it } from "vite-plus/test";1import { describe, expect, it } from "vite-plus/test";
2import {2import { ProviderInstanceId, type ModelCapabilities } from "@t3tools/contracts";
3 DEFAULT_MODEL,
4 ProviderDriverKind,
5 ProviderInstanceId,
6 type ModelCapabilities,
7} from "@t3tools/contracts";
83
9import {4import {
10 applyClaudePromptEffortPrefix,
11 buildProviderOptionSelectionsFromDescriptors,5 buildProviderOptionSelectionsFromDescriptors,
12 createModelCapabilities,6 createModelCapabilities,
13 createModelSelection,7 createModelSelection,
...@@ -16,11 +10,6 @@ import {...@@ -16,11 +10,6 @@ import {
16 getProviderOptionDescriptors,10 getProviderOptionDescriptors,
17 getProviderOptionBooleanSelectionValue,11 getProviderOptionBooleanSelectionValue,
18 getProviderOptionStringSelectionValue,12 getProviderOptionStringSelectionValue,
19 isClaudeUltrathinkPrompt,
20 normalizeModelSlug,
21 resolveModelSlugForProvider,
22 resolveSelectableModel,
23 trimOrNull,
24} from "./model.ts";13} from "./model.ts";
2514
26const codexCaps: ModelCapabilities = createModelCapabilities({15const codexCaps: ModelCapabilities = createModelCapabilities({
...@@ -70,82 +59,6 @@ const claudeCaps: ModelCapabilities = createModelCapabilities({...@@ -70,82 +59,6 @@ const claudeCaps: ModelCapabilities = createModelCapabilities({
70 ],59 ],
71});60});
7261
73describe("normalizeModelSlug", () => {
74 it("maps known aliases to canonical slugs", () => {
75 const claude = ProviderDriverKind.make("claudeAgent");
76 expect(normalizeModelSlug("gpt-5-codex")).toBe("gpt-5.4");
77 expect(normalizeModelSlug("5.3")).toBe("gpt-5.3-codex");
78 expect(normalizeModelSlug("sonnet", claude)).toBe("claude-sonnet-4-6");
79 });
80
81 it("returns null for empty or missing values", () => {
82 expect(normalizeModelSlug("")).toBeNull();
83 expect(normalizeModelSlug(" ")).toBeNull();
84 expect(normalizeModelSlug(null)).toBeNull();
85 expect(normalizeModelSlug(undefined)).toBeNull();
86 });
87});
88
89describe("resolveModelSlugForProvider", () => {
90 it("returns defaults when the model is missing", () => {
91 expect(resolveModelSlugForProvider(ProviderDriverKind.make("codex"), undefined)).toBe(
92 DEFAULT_MODEL,
93 );
94 expect(resolveModelSlugForProvider(ProviderDriverKind.make("ollama"), undefined)).toBe(
95 DEFAULT_MODEL,
96 );
97 expect(resolveModelSlugForProvider(ProviderDriverKind.make("grok"), undefined)).toBe(
98 "grok-build",
99 );
100 });
101
102 it("preserves normalized unknown models", () => {
103 expect(
104 resolveModelSlugForProvider(ProviderDriverKind.make("codex"), "custom/internal-model"),
105 ).toBe("custom/internal-model");
106 });
107});
108
109describe("resolveSelectableModel", () => {
110 it("resolves exact slugs, labels, and aliases", () => {
111 const options = [
112 { slug: "gpt-5.3-codex", name: "GPT-5.3 Codex" },
113 { slug: "claude-sonnet-4-6", name: "Claude Sonnet 4.6" },
114 ];
115 expect(resolveSelectableModel(ProviderDriverKind.make("codex"), "gpt-5.3-codex", options)).toBe(
116 "gpt-5.3-codex",
117 );
118 expect(resolveSelectableModel(ProviderDriverKind.make("codex"), "gpt-5.3 codex", options)).toBe(
119 "gpt-5.3-codex",
120 );
121 expect(resolveSelectableModel(ProviderDriverKind.make("claudeAgent"), "sonnet", options)).toBe(
122 "claude-sonnet-4-6",
123 );
124 });
125});
126
127describe("misc helpers", () => {
128 it("detects ultrathink prompts", () => {
129 expect(isClaudeUltrathinkPrompt("Please ultrathink about this")).toBe(true);
130 expect(isClaudeUltrathinkPrompt("Ultrathink:\nInvestigate")).toBe(true);
131 expect(isClaudeUltrathinkPrompt("Investigate")).toBe(false);
132 });
133
134 it("prefixes ultrathink prompts once", () => {
135 expect(applyClaudePromptEffortPrefix("Investigate", "ultrathink")).toBe(
136 "Ultrathink:\nInvestigate",
137 );
138 expect(applyClaudePromptEffortPrefix("Ultrathink:\nInvestigate", "ultrathink")).toBe(
139 "Ultrathink:\nInvestigate",
140 );
141 });
142
143 it("trims strings to null", () => {
144 expect(trimOrNull(" hi ")).toBe("hi");
145 expect(trimOrNull(" ")).toBeNull();
146 });
147});
148
149describe("descriptor helpers", () => {62describe("descriptor helpers", () => {
150 it("applies selection values to capability descriptors", () => {63 it("applies selection values to capability descriptors", () => {
151 expect(64 expect(