mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-24 18:22:38 +00:00
feat(providers): add Claude Sonnet 5
This commit is contained in:
@@ -60,6 +60,11 @@ const EXPECTED_CLAUDE_MODELS = [
|
||||
model: "Opus 4.8",
|
||||
descriptionFragment: "Latest release",
|
||||
},
|
||||
{
|
||||
id: "claude-sonnet-5",
|
||||
model: "Sonnet 5",
|
||||
descriptionFragment: "Efficient for routine tasks",
|
||||
},
|
||||
{
|
||||
id: "claude-opus-4-7[1m]",
|
||||
model: "Opus 4.7 1M",
|
||||
@@ -392,7 +397,7 @@ try {
|
||||
"--quiet should print the current Claude catalog IDs",
|
||||
);
|
||||
assert(
|
||||
claudeModelsFromJson.some((m) => m.id === "claude-sonnet-4-6"),
|
||||
claudeModelsFromJson.some((m) => m.id === "claude-sonnet-5"),
|
||||
"captured --json output should include the current Claude everyday model id",
|
||||
);
|
||||
console.log("✓ provider models --quiet outputs model IDs only\n");
|
||||
|
||||
@@ -416,6 +416,7 @@ describe("ClaudeAgentClient.fetchCatalog", () => {
|
||||
"claude-fable-5",
|
||||
"claude-opus-4-8[1m]",
|
||||
"claude-opus-4-8",
|
||||
"claude-sonnet-5",
|
||||
"claude-opus-4-7[1m]",
|
||||
"claude-opus-4-7",
|
||||
"claude-opus-4-6[1m]",
|
||||
@@ -457,6 +458,8 @@ describe("ClaudeAgentClient.fetchCatalog", () => {
|
||||
expect(getThinkingIds("claude-fable-5")).toContain("ultracode");
|
||||
expect(getThinkingIds("claude-opus-4-8[1m]")).toContain("ultracode");
|
||||
expect(getThinkingIds("claude-opus-4-8")).toContain("ultracode");
|
||||
expect(getThinkingIds("claude-sonnet-5")).toContain("xhigh");
|
||||
expect(getThinkingIds("claude-sonnet-5")).not.toContain("ultracode");
|
||||
expect(getThinkingIds("claude-opus-4-7")).not.toContain("ultracode");
|
||||
expect(getThinkingIds("claude-sonnet-4-6")).not.toContain("ultracode");
|
||||
} finally {
|
||||
|
||||
@@ -38,6 +38,7 @@ describe("getClaudeModels", () => {
|
||||
"claude-fable-5",
|
||||
"claude-opus-4-8[1m]",
|
||||
"claude-opus-4-8",
|
||||
"claude-sonnet-5",
|
||||
"claude-opus-4-7[1m]",
|
||||
"claude-opus-4-7",
|
||||
"claude-opus-4-6[1m]",
|
||||
@@ -203,12 +204,14 @@ describe("normalizeClaudeRuntimeModelId", () => {
|
||||
expect(normalizeClaudeRuntimeModelId("claude-fable-5")).toBe("claude-fable-5");
|
||||
expect(normalizeClaudeRuntimeModelId("claude-opus-4-6")).toBe("claude-opus-4-6");
|
||||
expect(normalizeClaudeRuntimeModelId("claude-opus-4-6[1m]")).toBe("claude-opus-4-6[1m]");
|
||||
expect(normalizeClaudeRuntimeModelId("claude-sonnet-5")).toBe("claude-sonnet-5");
|
||||
expect(normalizeClaudeRuntimeModelId("claude-sonnet-4-6")).toBe("claude-sonnet-4-6");
|
||||
expect(normalizeClaudeRuntimeModelId("claude-haiku-4-5")).toBe("claude-haiku-4-5");
|
||||
});
|
||||
|
||||
it("normalizes dated model IDs to base model", () => {
|
||||
expect(normalizeClaudeRuntimeModelId("claude-fable-5-20260301")).toBe("claude-fable-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-sonnet-4-6-20260101")).toBe("claude-sonnet-4-6");
|
||||
expect(normalizeClaudeRuntimeModelId("claude-haiku-4-5-20251001")).toBe("claude-haiku-4-5");
|
||||
@@ -216,6 +219,7 @@ describe("normalizeClaudeRuntimeModelId", () => {
|
||||
|
||||
it("preserves [1m] suffix from runtime model strings", () => {
|
||||
expect(normalizeClaudeRuntimeModelId("claude-opus-4-6[1m]")).toBe("claude-opus-4-6[1m]");
|
||||
expect(normalizeClaudeRuntimeModelId("claude-sonnet-5[1m]")).toBe("claude-sonnet-5");
|
||||
});
|
||||
|
||||
it("returns null for empty/null/undefined", () => {
|
||||
|
||||
@@ -12,7 +12,7 @@ const CLAUDE_THINKING_OPTIONS = [
|
||||
{ id: "max", label: "Max" },
|
||||
] as const;
|
||||
|
||||
const CLAUDE_OPUS_EXTENDED_THINKING_OPTIONS = [
|
||||
const CLAUDE_EXTENDED_THINKING_OPTIONS = [
|
||||
{ id: "low", label: "Low" },
|
||||
{ id: "medium", label: "Medium" },
|
||||
{ id: "high", label: "High" },
|
||||
@@ -21,7 +21,7 @@ const CLAUDE_OPUS_EXTENDED_THINKING_OPTIONS = [
|
||||
] as const;
|
||||
|
||||
const CLAUDE_ULTRACODE_THINKING_OPTIONS = [
|
||||
...CLAUDE_OPUS_EXTENDED_THINKING_OPTIONS,
|
||||
...CLAUDE_EXTENDED_THINKING_OPTIONS,
|
||||
{ id: "ultracode", label: "Ultracode" },
|
||||
] as const;
|
||||
|
||||
@@ -48,19 +48,26 @@ const CLAUDE_MODELS: AgentModelDefinition[] = [
|
||||
isDefault: true,
|
||||
thinkingOptions: [...CLAUDE_ULTRACODE_THINKING_OPTIONS],
|
||||
},
|
||||
{
|
||||
provider: "claude",
|
||||
id: "claude-sonnet-5",
|
||||
label: "Sonnet 5",
|
||||
description: "Sonnet 5 · Efficient for routine tasks",
|
||||
thinkingOptions: [...CLAUDE_EXTENDED_THINKING_OPTIONS],
|
||||
},
|
||||
{
|
||||
provider: "claude",
|
||||
id: "claude-opus-4-7[1m]",
|
||||
label: "Opus 4.7 1M",
|
||||
description: "Opus 4.7 with 1M context window",
|
||||
thinkingOptions: [...CLAUDE_OPUS_EXTENDED_THINKING_OPTIONS],
|
||||
thinkingOptions: [...CLAUDE_EXTENDED_THINKING_OPTIONS],
|
||||
},
|
||||
{
|
||||
provider: "claude",
|
||||
id: "claude-opus-4-7",
|
||||
label: "Opus 4.7",
|
||||
description: "Opus 4.7 · Previous release",
|
||||
thinkingOptions: [...CLAUDE_OPUS_EXTENDED_THINKING_OPTIONS],
|
||||
thinkingOptions: [...CLAUDE_EXTENDED_THINKING_OPTIONS],
|
||||
},
|
||||
{
|
||||
provider: "claude",
|
||||
@@ -218,13 +225,16 @@ export function normalizeClaudeRuntimeModelId(value: string | null | undefined):
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
// Fable uses a single-segment version (claude-fable-5), not the {major}-{minor}
|
||||
// scheme of opus/sonnet/haiku, so match it separately. This maps dated runtime
|
||||
// strings (e.g. claude-fable-5-20260301) back to the catalog ID. No [1m] variant:
|
||||
// Fable 5 is natively 1M, so there is no 200K-default model to opt into 1M.
|
||||
const fableMatch = trimmed.match(/(?:claude-)?fable[-_ ]+(\d+)/i);
|
||||
if (fableMatch) {
|
||||
return `claude-fable-${fableMatch[1]}`;
|
||||
// Fable and Sonnet 5 use single-segment versions, not the {major}-{minor}
|
||||
// scheme of older opus/sonnet/haiku models. They are natively 1M, so map
|
||||
// dated or suffixed runtime strings back to the one catalog ID.
|
||||
const singleSegmentMatch = trimmed.match(/(?:claude-)?(fable|sonnet)[-_ ]+(\d+)/i);
|
||||
if (singleSegmentMatch) {
|
||||
const family = singleSegmentMatch[1].toLowerCase();
|
||||
const major = singleSegmentMatch[2];
|
||||
if (family === "fable" || (family === "sonnet" && major === "5")) {
|
||||
return `claude-${family}-${major}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Match: claude-{family}-{major}-{minor}[1m]? possibly followed by a date suffix
|
||||
|
||||
Reference in New Issue
Block a user