fix(providers): seed Sonnet 5 context window

This commit is contained in:
Mohamed Boudra
2026-07-01 20:23:35 +02:00
parent ab7543ae1d
commit 01eafccb6a
4 changed files with 50 additions and 6 deletions
@@ -1892,6 +1892,45 @@ describe("ClaudeAgentSession context window usage", () => {
}
});
test("selected native-1M Claude models seed active context window usage with 1M max tokens", async () => {
const session = await createSessionForTurns(
[
[
createInitMessage(),
createMessageStartEvent(),
createSuccessResult({ modelUsage: undefined }),
],
],
{ model: "claude-sonnet-5" },
);
try {
const events = await collectStreamEvents(session);
expect(events).toContainEqual(
expect.objectContaining({
type: "usage_updated",
provider: "claude",
usage: {
contextWindowMaxTokens: 1_000_000,
contextWindowUsedTokens: 150,
},
}),
);
expect(events).toContainEqual(
expect.objectContaining({
type: "turn_completed",
provider: "claude",
usage: expect.objectContaining({
contextWindowMaxTokens: 1_000_000,
}),
}),
);
} finally {
await session.close();
}
});
test("message_delta stream events update per-request usage", async () => {
const session = await createSessionForTurns([
[
@@ -1634,7 +1634,8 @@ function resolveInitialContextWindowSize(modelId: string | null | undefined): nu
if (normalized.includes("[1m]") || normalized.includes("context-1m")) {
return 1_000_000;
}
if (normalized.includes("claude-fable-5")) {
const catalogModelId = normalizeClaudeRuntimeModelId(normalized);
if (catalogModelId === "claude-fable-5" || catalogModelId === "claude-sonnet-5") {
return 1_000_000;
}
if (/(?:^|[~/_-])(?:claude[-_ ]*)?(opus|sonnet|haiku)(?:$|[-_ ./])/.test(normalized)) {
@@ -219,6 +219,9 @@ describe("normalizeClaudeRuntimeModelId", () => {
it("preserves [1m] suffix from runtime model strings", () => {
expect(normalizeClaudeRuntimeModelId("claude-opus-4-6[1m]")).toBe("claude-opus-4-6[1m]");
});
it("strips [1m] suffix for natively-1M models", () => {
expect(normalizeClaudeRuntimeModelId("claude-sonnet-5[1m]")).toBe("claude-sonnet-5");
});
@@ -225,15 +225,16 @@ export function normalizeClaudeRuntimeModelId(value: string | null | undefined):
return trimmed;
}
// 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.
// Some new Claude model families use single-segment versions, not the
// {major}-{minor} scheme of older opus/sonnet/haiku models. Map dated or
// suffixed runtime strings back to the matching 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}`;
const modelId = `claude-${family}-${major}`;
if (CLAUDE_MODELS.some((model) => model.id === modelId)) {
return modelId;
}
}