refactor(models): bump claude-opus-4-6 to claude-opus-4-7 across fallback chains, categories, and hooks

Updates the canonical Anthropic Opus model in every fallback chain
(sisyphus, oracle, prometheus, metis, momus, visual-engineering,
ultrabrain, deep, artistry, unspecified-high), the unspecified-high
category default, the think-mode HIGH_VARIANT_MAP, the Claude Code
alias map, the claude-thinking legacy alias, the context-limit GA
regex, and event.ts fallback strings.

Widens supportsCachedAnthropicLimit to accept both claude-*-4-6 and
claude-*-4-7 so the 1M context cache still applies across the bump.

Regenerates the bundled model-capabilities snapshot from models.dev
and the model-fallback snapshot to match the new source output.
This commit is contained in:
YeonGyu-Kim
2026-04-17 14:51:52 +09:00
parent b1764a880c
commit def44338ff
85 changed files with 39904 additions and 38116 deletions
+4 -4
View File
@@ -57,7 +57,7 @@ describe("Sisyphus prompt identity", () => {
describe("#given a Sisyphus agent created with default model", () => {
describe("#when checking the prompt", () => {
it("#then contains the agent identity section with override directive", () => {
const config = createSisyphusAgent("anthropic/claude-opus-4-6")
const config = createSisyphusAgent("anthropic/claude-opus-4-7")
expect(config.prompt).toContain("<agent-identity>")
expect(config.prompt).toContain("Sisyphus")
@@ -65,7 +65,7 @@ describe("Sisyphus prompt identity", () => {
})
it("#then identity section appears before the Role section", () => {
const config = createSisyphusAgent("anthropic/claude-opus-4-6")
const config = createSisyphusAgent("anthropic/claude-opus-4-7")
const prompt = config.prompt ?? ""
const identityIndex = prompt.indexOf("<agent-identity>")
const roleIndex = prompt.indexOf("<Role>")
@@ -115,7 +115,7 @@ describe("Agent identity preservation through overrides", () => {
describe("#given a Sisyphus agent with prompt_append override", () => {
describe("#when merging the override", () => {
it("#then identity section is preserved in the merged prompt", () => {
const baseConfig = createSisyphusAgent("anthropic/claude-opus-4-6")
const baseConfig = createSisyphusAgent("anthropic/claude-opus-4-7")
const merged = mergeAgentConfig(baseConfig, { prompt_append: "Extra instructions here" })
expect(merged.prompt).toContain("<agent-identity>")
@@ -129,7 +129,7 @@ describe("Agent identity preservation through overrides", () => {
describe("#given a Sisyphus agent with model override only", () => {
describe("#when merging the override", () => {
it("#then identity section is preserved unchanged", () => {
const baseConfig = createSisyphusAgent("anthropic/claude-opus-4-6")
const baseConfig = createSisyphusAgent("anthropic/claude-opus-4-7")
const merged = mergeAgentConfig(baseConfig, { model: "openai/gpt-5.4" })
expect(merged.prompt).toContain("<agent-identity>")
@@ -43,7 +43,7 @@ describe("maybeCreateSisyphusConfig", () => {
// given
const agentOverrides: AgentOverrides = {
sisyphus: {
model: "anthropic/claude-opus-4-6",
model: "anthropic/claude-opus-4-7",
permission: {
apply_patch: "allow",
},
@@ -55,8 +55,8 @@ describe("maybeCreateSisyphusConfig", () => {
const config = maybeCreateSisyphusConfig({
disabledAgents: [],
agentOverrides,
availableModels: new Set(["anthropic/claude-opus-4-6"]),
systemDefaultModel: "anthropic/claude-opus-4-6",
availableModels: new Set(["anthropic/claude-opus-4-7"]),
systemDefaultModel: "anthropic/claude-opus-4-7",
isFirstRunNoCache: false,
availableAgents: [],
availableSkills: [],
@@ -67,7 +67,7 @@ describe("maybeCreateSisyphusConfig", () => {
// then
expect(config).toBeDefined();
expect(config?.model).toBe("anthropic/claude-opus-4-6");
expect(config?.model).toBe("anthropic/claude-opus-4-7");
// Claude models should allow the user override
expect(config?.permission).toHaveProperty("apply_patch", "allow");
});
@@ -2,13 +2,13 @@ import { describe, expect, spyOn, test } from "bun:test"
import { createBuiltinAgents } from "./builtin-agents"
import * as shared from "../shared"
const TEST_DEFAULT_MODEL = "anthropic/claude-opus-4-6"
const TEST_DEFAULT_MODEL = "anthropic/claude-opus-4-7"
describe("createBuiltinAgents custom agent visibility", () => {
test("#given runtime custom agents #when orchestrator prompts are built #then custom agents are not advertised for automatic delegation", async () => {
//#given
const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(
new Set(["anthropic/claude-opus-4-6", "openai/gpt-5.4"])
new Set(["anthropic/claude-opus-4-7", "openai/gpt-5.4"])
)
try {
@@ -211,7 +211,7 @@ describe("buildParallelDelegationSection", () => {
it("#given Claude model #when building #then returns empty", () => {
//#given
const model = "anthropic/claude-opus-4-6"
const model = "anthropic/claude-opus-4-7"
const categories = [deepCategory]
//#when
+8 -8
View File
@@ -56,7 +56,7 @@ describe("getHephaestusPromptSource", () => {
test("returns 'gpt' for non-GPT models and undefined", () => {
// given
const model1 = "anthropic/claude-opus-4-6";
const model1 = "anthropic/claude-opus-4-7";
const model2 = undefined;
// when
@@ -124,7 +124,7 @@ describe("getHephaestusPrompt", () => {
test("Claude model returns generic GPT prompt (Hephaestus default)", () => {
// given
const model = "anthropic/claude-opus-4-6";
const model = "anthropic/claude-opus-4-7";
// when
const prompt = getHephaestusPrompt(model);
@@ -149,7 +149,7 @@ describe("getHephaestusPrompt", () => {
test("useTaskSystem=false includes Todo Discipline for Claude models", () => {
// given
const model = "anthropic/claude-opus-4-6";
const model = "anthropic/claude-opus-4-7";
// when
const prompt = getHephaestusPrompt(model, false);
@@ -239,7 +239,7 @@ describe("createHephaestusAgent", () => {
// given
const gpt54Model = "openai/gpt-5.4";
const gptGenericModel = "openai/gpt-4o";
const claudeModel = "anthropic/claude-opus-4-6";
const claudeModel = "anthropic/claude-opus-4-7";
// when
const gpt54Config = createHephaestusAgent(gpt54Model);
@@ -322,7 +322,7 @@ describe("maybeCreateHephaestusConfig GPT apply_patch guard", () => {
// given
const agentOverrides: AgentOverrides = {
hephaestus: {
model: "anthropic/claude-opus-4-6",
model: "anthropic/claude-opus-4-7",
permission: {
apply_patch: "allow",
},
@@ -334,8 +334,8 @@ describe("maybeCreateHephaestusConfig GPT apply_patch guard", () => {
const config = maybeCreateHephaestusConfig({
disabledAgents: [],
agentOverrides,
availableModels: new Set(["anthropic/claude-opus-4-6"]),
systemDefaultModel: "anthropic/claude-opus-4-6",
availableModels: new Set(["anthropic/claude-opus-4-7"]),
systemDefaultModel: "anthropic/claude-opus-4-7",
isFirstRunNoCache: false,
availableAgents: [],
availableSkills: [],
@@ -346,7 +346,7 @@ describe("maybeCreateHephaestusConfig GPT apply_patch guard", () => {
// then
expect(config).toBeDefined();
expect(config?.model).toBe("anthropic/claude-opus-4-6");
expect(config?.model).toBe("anthropic/claude-opus-4-7");
expect(config?.permission).toHaveProperty("apply_patch", "allow");
});
});
+7 -7
View File
@@ -18,7 +18,7 @@ describe("isGpt5_4Model", () => {
});
test("does not match non-GPT models", () => {
expect(isGpt5_4Model("anthropic/claude-opus-4-6")).toBe(false);
expect(isGpt5_4Model("anthropic/claude-opus-4-7")).toBe(false);
expect(isGpt5_4Model("google/gemini-3.1-pro")).toBe(false);
expect(isGpt5_4Model("openai/o1")).toBe(false);
});
@@ -64,7 +64,7 @@ describe("isGptModel", () => {
});
test("claude models are not gpt", () => {
expect(isGptModel("anthropic/claude-opus-4-6")).toBe(false);
expect(isGptModel("anthropic/claude-opus-4-7")).toBe(false);
expect(isGptModel("anthropic/claude-sonnet-4-6")).toBe(false);
expect(isGptModel("litellm/anthropic.claude-opus-4-5")).toBe(false);
});
@@ -75,7 +75,7 @@ describe("isGptModel", () => {
});
test("opencode provider is not gpt", () => {
expect(isGptModel("opencode/claude-opus-4-6")).toBe(false);
expect(isGptModel("opencode/claude-opus-4-7")).toBe(false);
});
});
@@ -95,7 +95,7 @@ describe("isMiniMaxModel", () => {
test("does not match non-minimax models", () => {
expect(isMiniMaxModel("openai/gpt-5.4")).toBe(false);
expect(isMiniMaxModel("anthropic/claude-opus-4-6")).toBe(false);
expect(isMiniMaxModel("anthropic/claude-opus-4-7")).toBe(false);
expect(isMiniMaxModel("google/gemini-3.1-pro")).toBe(false);
expect(isMiniMaxModel("opencode-go/kimi-k2.5")).toBe(false);
});
@@ -116,7 +116,7 @@ describe("isGlmModel", () => {
test("#given non-GLM models #then returns false", () => {
expect(isGlmModel("openai/gpt-5.4")).toBe(false);
expect(isGlmModel("anthropic/claude-opus-4-6")).toBe(false);
expect(isGlmModel("anthropic/claude-opus-4-7")).toBe(false);
expect(isGlmModel("google/gemini-3.1-pro")).toBe(false);
});
});
@@ -156,11 +156,11 @@ describe("isGeminiModel", () => {
});
test("#given claude models #then returns false", () => {
expect(isGeminiModel("anthropic/claude-opus-4-6")).toBe(false);
expect(isGeminiModel("anthropic/claude-opus-4-7")).toBe(false);
expect(isGeminiModel("anthropic/claude-sonnet-4-6")).toBe(false);
});
test("#given opencode provider #then returns false", () => {
expect(isGeminiModel("opencode/claude-opus-4-6")).toBe(false);
expect(isGeminiModel("opencode/claude-opus-4-7")).toBe(false);
});
});
+23 -23
View File
@@ -7,7 +7,7 @@ import * as connectedProvidersCache from "../shared/connected-providers-cache"
import * as modelAvailability from "../shared/model-availability"
import * as shared from "../shared"
const TEST_DEFAULT_MODEL = "anthropic/claude-opus-4-6"
const TEST_DEFAULT_MODEL = "anthropic/claude-opus-4-7"
let createBuiltinAgents: (typeof import("./builtin-agents"))["createBuiltinAgents"]
async function importFreshBuiltinAgentsModule(): Promise<typeof import("./builtin-agents")> {
@@ -32,7 +32,7 @@ describe("createBuiltinAgents with model overrides", () => {
// #given
const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(
new Set([
"anthropic/claude-opus-4-6",
"anthropic/claude-opus-4-7",
"kimi-for-coding/k2p5",
"opencode/kimi-k2.5-free",
"zai-coding-plan/glm-5",
@@ -45,7 +45,7 @@ describe("createBuiltinAgents with model overrides", () => {
const agents = await createBuiltinAgents([], {}, undefined, TEST_DEFAULT_MODEL, undefined, undefined, [], {})
// #then
expect(agents.sisyphus.model).toBe("anthropic/claude-opus-4-6")
expect(agents.sisyphus.model).toBe("anthropic/claude-opus-4-7")
expect(agents.sisyphus.thinking).toEqual({ type: "enabled", budgetTokens: 32000 })
expect(agents.sisyphus.reasoningEffort).toBeUndefined()
} finally {
@@ -170,7 +170,7 @@ describe("createBuiltinAgents with model overrides", () => {
test("Sisyphus is created on first run when no availableModels or cache exist", async () => {
// #given
const systemDefaultModel = "anthropic/claude-opus-4-6"
const systemDefaultModel = "anthropic/claude-opus-4-7"
const cacheSpy = spyOn(connectedProvidersCache, "readConnectedProvidersCache").mockReturnValue(null)
const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(new Set())
@@ -180,7 +180,7 @@ describe("createBuiltinAgents with model overrides", () => {
// #then
expect(agents.sisyphus).toBeDefined()
expect(agents.sisyphus.model).toBe("anthropic/claude-opus-4.6")
expect(agents.sisyphus.model).toBe("anthropic/claude-opus-4.7")
} finally {
cacheSpy.mockRestore()
fetchSpy.mockRestore()
@@ -299,7 +299,7 @@ describe("createBuiltinAgents with model overrides", () => {
// #given
const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(
new Set([
"anthropic/claude-opus-4-6",
"anthropic/claude-opus-4-7",
"kimi-for-coding/k2p5",
"opencode/kimi-k2.5-free",
"zai-coding-plan/glm-5",
@@ -341,7 +341,7 @@ describe("createBuiltinAgents with model overrides", () => {
test("excludes hidden custom agents from orchestrator prompts", async () => {
// #given
const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(
new Set(["anthropic/claude-opus-4-6", "openai/gpt-5.4"])
new Set(["anthropic/claude-opus-4-7", "openai/gpt-5.4"])
)
const customAgentSummaries = [
@@ -377,7 +377,7 @@ describe("createBuiltinAgents with model overrides", () => {
test("excludes disabled custom agents from orchestrator prompts", async () => {
// #given
const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(
new Set(["anthropic/claude-opus-4-6", "openai/gpt-5.4"])
new Set(["anthropic/claude-opus-4-7", "openai/gpt-5.4"])
)
const customAgentSummaries = [
@@ -413,7 +413,7 @@ describe("createBuiltinAgents with model overrides", () => {
test("excludes custom agents when disabledAgents contains their name (case-insensitive)", async () => {
// #given
const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(
new Set(["anthropic/claude-opus-4-6", "openai/gpt-5.4"])
new Set(["anthropic/claude-opus-4-7", "openai/gpt-5.4"])
)
const disabledAgents = ["ReSeArChEr"]
@@ -449,7 +449,7 @@ describe("createBuiltinAgents with model overrides", () => {
test("does not advertise duplicate custom agents case-insensitively", async () => {
// #given
const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(
new Set(["anthropic/claude-opus-4-6", "openai/gpt-5.4"])
new Set(["anthropic/claude-opus-4-7", "openai/gpt-5.4"])
)
const customAgentSummaries = [
@@ -481,7 +481,7 @@ describe("createBuiltinAgents with model overrides", () => {
test("does not surface custom agent strings in orchestrator prompts", async () => {
// #given
const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(
new Set(["anthropic/claude-opus-4-6", "openai/gpt-5.4"])
new Set(["anthropic/claude-opus-4-7", "openai/gpt-5.4"])
)
const customAgentSummaries = [
@@ -555,7 +555,7 @@ describe("createBuiltinAgents without systemDefaultModel", () => {
])
const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(
new Set([
"anthropic/claude-opus-4-6",
"anthropic/claude-opus-4-7",
"kimi-for-coding/k2p5",
"opencode/kimi-k2.5-free",
"zai-coding-plan/glm-5",
@@ -569,7 +569,7 @@ describe("createBuiltinAgents without systemDefaultModel", () => {
// #then
expect(agents.sisyphus).toBeDefined()
expect(agents.sisyphus.model).toBe("anthropic/claude-opus-4-6")
expect(agents.sisyphus.model).toBe("anthropic/claude-opus-4-7")
} finally {
cacheSpy.mockRestore()
fetchSpy.mockRestore()
@@ -590,7 +590,7 @@ describe("createBuiltinAgents with requiresProvider gating (hephaestus)", () =>
const providers = options?.connectedProviders ?? []
return providers.includes("openai")
? new Set(["openai/gpt-5.3-codex"])
: new Set(["anthropic/claude-opus-4-6"])
: new Set(["anthropic/claude-opus-4-7"])
})
try {
@@ -609,7 +609,7 @@ describe("createBuiltinAgents with requiresProvider gating (hephaestus)", () =>
test("hephaestus is not created when no required provider is connected", async () => {
// #given - only anthropic models available, not in hephaestus requiresProvider
const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(
new Set(["anthropic/claude-opus-4-6"])
new Set(["anthropic/claude-opus-4-7"])
)
const cacheSpy = spyOn(connectedProvidersCache, "readConnectedProvidersCache").mockReturnValue(["anthropic"])
@@ -699,10 +699,10 @@ describe("createBuiltinAgents with requiresProvider gating (hephaestus)", () =>
test("hephaestus is created when explicit config provided even if provider unavailable", async () => {
// #given
const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(
new Set(["anthropic/claude-opus-4-6"])
new Set(["anthropic/claude-opus-4-7"])
)
const overrides = {
hephaestus: { model: "anthropic/claude-opus-4-6" },
hephaestus: { model: "anthropic/claude-opus-4-7" },
}
try {
@@ -781,7 +781,7 @@ describe("Sisyphus and Librarian environment context toggle", () => {
beforeEach(() => {
fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(
new Set(["anthropic/claude-opus-4-6", "google/gemini-3-flash"])
new Set(["anthropic/claude-opus-4-7", "google/gemini-3-flash"])
)
})
@@ -840,7 +840,7 @@ describe("Atlas is unaffected by environment context toggle", () => {
beforeEach(() => {
fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(
new Set(["anthropic/claude-opus-4-6", "openai/gpt-5.4"])
new Set(["anthropic/claude-opus-4-7", "openai/gpt-5.4"])
)
})
@@ -893,7 +893,7 @@ describe("createBuiltinAgents with requiresAnyModel gating (sisyphus)", () => {
test("sisyphus is created when at least one fallback model is available", async () => {
// #given
const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(
new Set(["anthropic/claude-opus-4-6"])
new Set(["anthropic/claude-opus-4-7"])
)
try {
@@ -918,7 +918,7 @@ describe("createBuiltinAgents with requiresAnyModel gating (sisyphus)", () => {
// #then
expect(agents.sisyphus).toBeDefined()
expect(agents.sisyphus.model).toBe("anthropic/claude-opus-4.6")
expect(agents.sisyphus.model).toBe("anthropic/claude-opus-4.7")
} finally {
cacheSpy.mockRestore()
fetchSpy.mockRestore()
@@ -929,7 +929,7 @@ describe("createBuiltinAgents with requiresAnyModel gating (sisyphus)", () => {
// #given
const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(new Set())
const overrides = {
sisyphus: { model: "anthropic/claude-opus-4-6" },
sisyphus: { model: "anthropic/claude-opus-4-7" },
}
try {
@@ -1039,7 +1039,7 @@ describe("createBuiltinAgents with requiresAnyModel gating (sisyphus)", () => {
describe("buildAgent with category and skills", () => {
const { buildAgent } = require("./agent-builder")
const TEST_MODEL = "anthropic/claude-opus-4-6"
const TEST_MODEL = "anthropic/claude-opus-4-7"
beforeEach(() => {
clearSkillCache()