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:
@@ -83,7 +83,7 @@ describe("findNearestMessageExcludingCompaction", () => {
|
||||
// given
|
||||
const message = {
|
||||
agent: "sisyphus",
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4-6" },
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4-7" },
|
||||
}
|
||||
writeFileSync(join(tempDir, "001.json"), JSON.stringify(message))
|
||||
|
||||
@@ -94,18 +94,18 @@ describe("findNearestMessageExcludingCompaction", () => {
|
||||
expect(result).not.toBeNull()
|
||||
expect(result?.agent).toBe("sisyphus")
|
||||
expect(result?.model?.providerID).toBe("anthropic")
|
||||
expect(result?.model?.modelID).toBe("claude-opus-4-6")
|
||||
expect(result?.model?.modelID).toBe("claude-opus-4-7")
|
||||
})
|
||||
|
||||
test("skips compaction agent messages", () => {
|
||||
// given
|
||||
const compactionMessage = {
|
||||
agent: "compaction",
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4-6" },
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4-7" },
|
||||
}
|
||||
const validMessage = {
|
||||
agent: "sisyphus",
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4-6" },
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4-7" },
|
||||
}
|
||||
writeFileSync(join(tempDir, "002.json"), JSON.stringify(compactionMessage))
|
||||
writeFileSync(join(tempDir, "001.json"), JSON.stringify(validMessage))
|
||||
@@ -125,12 +125,12 @@ describe("findNearestMessageExcludingCompaction", () => {
|
||||
writeFileSync(join(tempDir, "002.json"), JSON.stringify({
|
||||
id: compactionMessageID,
|
||||
agent: "atlas",
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4-6" },
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4-7" },
|
||||
}))
|
||||
writeFileSync(join(tempDir, "001.json"), JSON.stringify({
|
||||
id: "msg_001",
|
||||
agent: "sisyphus",
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4-6" },
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4-7" },
|
||||
}))
|
||||
mkdirSync(partDir, { recursive: true })
|
||||
writeFileSync(join(partDir, "prt_0001.json"), JSON.stringify({ type: "compaction" }))
|
||||
|
||||
@@ -94,7 +94,7 @@ describe("ConcurrencyManager.getConcurrencyLimit", () => {
|
||||
|
||||
// when
|
||||
const modelLimit = manager.getConcurrencyLimit("anthropic/claude-sonnet-4-6")
|
||||
const providerLimit = manager.getConcurrencyLimit("anthropic/claude-opus-4-6")
|
||||
const providerLimit = manager.getConcurrencyLimit("anthropic/claude-opus-4-7")
|
||||
const defaultLimit = manager.getConcurrencyLimit("google/gemini-3.1-pro")
|
||||
|
||||
// then
|
||||
|
||||
@@ -855,7 +855,7 @@ describe("BackgroundManager.notifyParentSession - dynamic message lookup", () =>
|
||||
{
|
||||
info: {
|
||||
agent: "sisyphus",
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4.6" },
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4.7" },
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -890,7 +890,7 @@ describe("BackgroundManager.notifyParentSession - dynamic message lookup", () =>
|
||||
|
||||
//#then
|
||||
expect(capturedBody?.agent).toBe("sisyphus")
|
||||
expect(capturedBody?.model).toEqual({ providerID: "anthropic", modelID: "claude-opus-4.6" })
|
||||
expect(capturedBody?.model).toEqual({ providerID: "anthropic", modelID: "claude-opus-4.7" })
|
||||
|
||||
manager.shutdown()
|
||||
})
|
||||
@@ -913,7 +913,7 @@ describe("BackgroundManager.notifyParentSession - dynamic message lookup", () =>
|
||||
}
|
||||
const currentMessage: CurrentMessage = {
|
||||
agent: "sisyphus",
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4.6" },
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4.7" },
|
||||
}
|
||||
|
||||
// when
|
||||
@@ -921,7 +921,7 @@ describe("BackgroundManager.notifyParentSession - dynamic message lookup", () =>
|
||||
|
||||
// then - uses currentMessage values, not task.parentModel/parentAgent
|
||||
expect(promptBody.agent).toBe("sisyphus")
|
||||
expect(promptBody.model).toEqual({ providerID: "anthropic", modelID: "claude-opus-4.6" })
|
||||
expect(promptBody.model).toEqual({ providerID: "anthropic", modelID: "claude-opus-4.7" })
|
||||
})
|
||||
|
||||
test("should fallback to parentAgent when currentMessage.agent is undefined", async () => {
|
||||
@@ -1155,7 +1155,7 @@ describe("BackgroundManager.notifyParentSession - notifications toggle", () => {
|
||||
agent: "explore",
|
||||
model: {
|
||||
providerID: "anthropic",
|
||||
modelID: "claude-opus-4.6",
|
||||
modelID: "claude-opus-4.7",
|
||||
variant: "high",
|
||||
},
|
||||
},
|
||||
@@ -1211,7 +1211,7 @@ describe("BackgroundManager.notifyParentSession - variant propagation", () => {
|
||||
agent: "explore",
|
||||
model: {
|
||||
providerID: "anthropic",
|
||||
modelID: "claude-opus-4.6",
|
||||
modelID: "claude-opus-4.7",
|
||||
variant: "max",
|
||||
},
|
||||
},
|
||||
@@ -1231,7 +1231,7 @@ describe("BackgroundManager.notifyParentSession - variant propagation", () => {
|
||||
status: "completed",
|
||||
startedAt: new Date(),
|
||||
completedAt: new Date(),
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4.6", variant: "high" },
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4.7", variant: "high" },
|
||||
}
|
||||
getPendingByParent(manager).set("session-parent", new Set([task.id]))
|
||||
|
||||
@@ -1272,7 +1272,7 @@ describe("BackgroundManager.notifyParentSession - variant propagation", () => {
|
||||
status: "completed",
|
||||
startedAt: new Date(),
|
||||
completedAt: new Date(),
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4.6" },
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4.7" },
|
||||
}
|
||||
getPendingByParent(manager).set("session-parent", new Set([task.id]))
|
||||
|
||||
@@ -1349,7 +1349,7 @@ describe("BackgroundManager.tryCompleteTask", () => {
|
||||
|
||||
test("should release concurrency and clear key on completion", async () => {
|
||||
// given
|
||||
const concurrencyKey = "anthropic/claude-opus-4.6"
|
||||
const concurrencyKey = "anthropic/claude-opus-4.7"
|
||||
const concurrencyManager = getConcurrencyManager(manager)
|
||||
await concurrencyManager.acquire(concurrencyKey)
|
||||
|
||||
@@ -1378,7 +1378,7 @@ describe("BackgroundManager.tryCompleteTask", () => {
|
||||
|
||||
test("should prevent double completion and double release", async () => {
|
||||
// given
|
||||
const concurrencyKey = "anthropic/claude-opus-4.6"
|
||||
const concurrencyKey = "anthropic/claude-opus-4.7"
|
||||
const concurrencyManager = getConcurrencyManager(manager)
|
||||
await concurrencyManager.acquire(concurrencyKey)
|
||||
|
||||
@@ -1508,7 +1508,7 @@ describe("BackgroundManager.tryCompleteTask", () => {
|
||||
|
||||
test("should release task concurrencyKey when startTask throws after assigning it", async () => {
|
||||
// given
|
||||
const concurrencyKey = "anthropic/claude-opus-4.6"
|
||||
const concurrencyKey = "anthropic/claude-opus-4.7"
|
||||
const concurrencyManager = getConcurrencyManager(manager)
|
||||
|
||||
const task = createMockTask({
|
||||
@@ -1524,7 +1524,7 @@ describe("BackgroundManager.tryCompleteTask", () => {
|
||||
agent: task.agent,
|
||||
parentSessionID: task.parentSessionID,
|
||||
parentMessageID: task.parentMessageID,
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4.6" },
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4.7" },
|
||||
}
|
||||
getTaskMap(manager).set(task.id, task)
|
||||
getQueuesByKey(manager).set(concurrencyKey, [{ task, input }])
|
||||
@@ -1544,7 +1544,7 @@ describe("BackgroundManager.tryCompleteTask", () => {
|
||||
|
||||
test("should mark task as error when startTask throws after session creation", async () => {
|
||||
//#given - startTask creates session but fails before sending prompt
|
||||
const concurrencyKey = "anthropic/claude-opus-4.6"
|
||||
const concurrencyKey = "anthropic/claude-opus-4.7"
|
||||
|
||||
const task = createMockTask({
|
||||
id: "task-zombie-session",
|
||||
@@ -1561,7 +1561,7 @@ describe("BackgroundManager.tryCompleteTask", () => {
|
||||
agent: task.agent,
|
||||
parentSessionID: task.parentSessionID,
|
||||
parentMessageID: task.parentMessageID,
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4.6" },
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4.7" },
|
||||
}
|
||||
getTaskMap(manager).set(task.id, task)
|
||||
getQueuesByKey(manager).set(concurrencyKey, [{ task, input }])
|
||||
@@ -1585,7 +1585,7 @@ describe("BackgroundManager.tryCompleteTask", () => {
|
||||
|
||||
test("should release queue slot when queued task is already interrupt", async () => {
|
||||
// given
|
||||
const concurrencyKey = "anthropic/claude-opus-4.6"
|
||||
const concurrencyKey = "anthropic/claude-opus-4.7"
|
||||
const concurrencyManager = getConcurrencyManager(manager)
|
||||
|
||||
const task = createMockTask({
|
||||
@@ -1601,7 +1601,7 @@ describe("BackgroundManager.tryCompleteTask", () => {
|
||||
agent: task.agent,
|
||||
parentSessionID: task.parentSessionID,
|
||||
parentMessageID: task.parentMessageID,
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4.6" },
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4.7" },
|
||||
}
|
||||
getTaskMap(manager).set(task.id, task)
|
||||
getQueuesByKey(manager).set(concurrencyKey, [{ task, input }])
|
||||
@@ -2104,7 +2104,7 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => {
|
||||
agent: "test-agent",
|
||||
parentSessionID: "parent-session",
|
||||
parentMessageID: "parent-message",
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4.6" },
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4.7" },
|
||||
}
|
||||
const launchInputWithoutModel = {
|
||||
description: "Test task without model",
|
||||
@@ -2124,7 +2124,7 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => {
|
||||
expect(taskWithModel.status).toBe("pending")
|
||||
expect(taskWithoutModel.status).toBe("pending")
|
||||
expect(promptBodies).toHaveLength(2)
|
||||
expect(promptBodies[0].model).toEqual({ providerID: "anthropic", modelID: "claude-opus-4.6" })
|
||||
expect(promptBodies[0].model).toEqual({ providerID: "anthropic", modelID: "claude-opus-4.7" })
|
||||
expect(promptBodies[0].agent).toBe("test-agent")
|
||||
expect(promptBodies[1].agent).toBe("test-agent")
|
||||
expect("model" in promptBodies[1]).toBe(false)
|
||||
@@ -3245,7 +3245,7 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => {
|
||||
description: "Task 1",
|
||||
prompt: "Do something",
|
||||
agent: "test-agent",
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4.6" },
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4.7" },
|
||||
parentSessionID: "parent-session",
|
||||
parentMessageID: "parent-message",
|
||||
}
|
||||
@@ -4225,7 +4225,7 @@ describe("BackgroundManager.handleEvent - session.deleted cascade", () => {
|
||||
|
||||
describe("BackgroundManager.handleEvent - session.error", () => {
|
||||
const defaultRetryFallbackChain = [
|
||||
{ providers: ["anthropic"], model: "claude-opus-4-6", variant: "max" },
|
||||
{ providers: ["anthropic"], model: "claude-opus-4-7", variant: "max" },
|
||||
{ providers: ["anthropic"], model: "gpt-5.3-codex", variant: "high" },
|
||||
]
|
||||
|
||||
@@ -4249,7 +4249,7 @@ describe("BackgroundManager.handleEvent - session.error", () => {
|
||||
agent: "sisyphus",
|
||||
status: "running",
|
||||
concurrencyKey: input.concurrencyKey,
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4.6-thinking" },
|
||||
model: { providerID: "anthropic", modelID: "claude-opus-4.7-thinking" },
|
||||
fallbackChain: input.fallbackChain ?? defaultRetryFallbackChain,
|
||||
attemptCount: 0,
|
||||
})
|
||||
@@ -4394,7 +4394,7 @@ describe("BackgroundManager.handleEvent - session.error", () => {
|
||||
//#given
|
||||
const manager = createBackgroundManager()
|
||||
const concurrencyManager = getConcurrencyManager(manager)
|
||||
const concurrencyKey = "anthropic/claude-opus-4.6-thinking"
|
||||
const concurrencyKey = "anthropic/claude-opus-4.7-thinking"
|
||||
await concurrencyManager.acquire(concurrencyKey)
|
||||
|
||||
stubProcessKey(manager)
|
||||
@@ -4406,7 +4406,7 @@ describe("BackgroundManager.handleEvent - session.error", () => {
|
||||
description: "task that should retry",
|
||||
concurrencyKey,
|
||||
fallbackChain: [
|
||||
{ providers: ["anthropic"], model: "claude-opus-4-6", variant: "max" },
|
||||
{ providers: ["anthropic"], model: "claude-opus-4-7", variant: "max" },
|
||||
{ providers: ["anthropic"], model: "claude-opus-4-5", variant: "max" },
|
||||
],
|
||||
})
|
||||
@@ -4420,7 +4420,7 @@ describe("BackgroundManager.handleEvent - session.error", () => {
|
||||
name: "UnknownError",
|
||||
data: {
|
||||
message:
|
||||
"Bad Gateway: {\"error\":{\"message\":\"unknown provider for model claude-opus-4.6-thinking\"}}",
|
||||
"Bad Gateway: {\"error\":{\"message\":\"unknown provider for model claude-opus-4.7-thinking\"}}",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -4431,7 +4431,7 @@ describe("BackgroundManager.handleEvent - session.error", () => {
|
||||
expect(task.attemptCount).toBe(1)
|
||||
expect(task.model).toEqual({
|
||||
providerID: "anthropic",
|
||||
modelID: "claude-opus-4.6",
|
||||
modelID: "claude-opus-4.7",
|
||||
variant: "max",
|
||||
})
|
||||
expect(task.concurrencyKey).toBeUndefined()
|
||||
@@ -4469,7 +4469,7 @@ describe("BackgroundManager.handleEvent - session.error", () => {
|
||||
expect(task.attemptCount).toBe(1)
|
||||
expect(task.model).toEqual({
|
||||
providerID: "anthropic",
|
||||
modelID: "claude-opus-4.6",
|
||||
modelID: "claude-opus-4.7",
|
||||
variant: "max",
|
||||
})
|
||||
|
||||
@@ -4497,7 +4497,7 @@ describe("BackgroundManager.handleEvent - session.error", () => {
|
||||
name: "UnknownError",
|
||||
data: {
|
||||
message:
|
||||
"Bad Gateway: {\"error\":{\"message\":\"unknown provider for model claude-opus-4.6-thinking\"}}",
|
||||
"Bad Gateway: {\"error\":{\"message\":\"unknown provider for model claude-opus-4.7-thinking\"}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -4514,7 +4514,7 @@ describe("BackgroundManager.handleEvent - session.error", () => {
|
||||
expect(task.attemptCount).toBe(1)
|
||||
expect(task.model).toEqual({
|
||||
providerID: "anthropic",
|
||||
modelID: "claude-opus-4.6",
|
||||
modelID: "claude-opus-4.7",
|
||||
variant: "max",
|
||||
})
|
||||
|
||||
|
||||
@@ -648,7 +648,7 @@ describe("checkAndInterruptStaleTasks", () => {
|
||||
const task = createRunningTask({
|
||||
startedAt: new Date(Date.now() - 15 * 60 * 1000),
|
||||
progress: undefined,
|
||||
concurrencyKey: "anthropic/claude-opus-4-6",
|
||||
concurrencyKey: "anthropic/claude-opus-4-7",
|
||||
})
|
||||
|
||||
//#when
|
||||
@@ -661,7 +661,7 @@ describe("checkAndInterruptStaleTasks", () => {
|
||||
})
|
||||
|
||||
//#then
|
||||
expect(releaseMock).toHaveBeenCalledWith("anthropic/claude-opus-4-6")
|
||||
expect(releaseMock).toHaveBeenCalledWith("anthropic/claude-opus-4-7")
|
||||
expect(task.concurrencyKey).toBeUndefined()
|
||||
})
|
||||
|
||||
|
||||
@@ -23,8 +23,8 @@ describe("mapClaudeModelToOpenCode", () => {
|
||||
expect(mapClaudeModelToOpenCode("sonnet")).toEqual({ providerID: "anthropic", modelID: "claude-sonnet-4-6" })
|
||||
})
|
||||
|
||||
it("#when called with opus #then maps to anthropic claude-opus-4-6 object", () => {
|
||||
expect(mapClaudeModelToOpenCode("opus")).toEqual({ providerID: "anthropic", modelID: "claude-opus-4-6" })
|
||||
it("#when called with opus #then maps to anthropic claude-opus-4-7 object", () => {
|
||||
expect(mapClaudeModelToOpenCode("opus")).toEqual({ providerID: "anthropic", modelID: "claude-opus-4-7" })
|
||||
})
|
||||
|
||||
it("#when called with haiku #then maps to anthropic claude-haiku-4-5 object", () => {
|
||||
@@ -47,8 +47,8 @@ describe("mapClaudeModelToOpenCode", () => {
|
||||
expect(mapClaudeModelToOpenCode("claude-sonnet-4-5-20250514")).toEqual({ providerID: "anthropic", modelID: "claude-sonnet-4-5-20250514" })
|
||||
})
|
||||
|
||||
it("#when called with claude-opus-4-6 #then adds anthropic object format", () => {
|
||||
expect(mapClaudeModelToOpenCode("claude-opus-4-6")).toEqual({ providerID: "anthropic", modelID: "claude-opus-4-6" })
|
||||
it("#when called with claude-opus-4-7 #then adds anthropic object format", () => {
|
||||
expect(mapClaudeModelToOpenCode("claude-opus-4-7")).toEqual({ providerID: "anthropic", modelID: "claude-opus-4-7" })
|
||||
})
|
||||
|
||||
it("#when called with claude-haiku-4-5-20251001 #then adds anthropic object format", () => {
|
||||
|
||||
@@ -5,7 +5,7 @@ const ANTHROPIC_PREFIX = "anthropic/"
|
||||
|
||||
const CLAUDE_CODE_ALIAS_MAP = new Map<string, string>([
|
||||
["sonnet", `${ANTHROPIC_PREFIX}claude-sonnet-4-6`],
|
||||
["opus", `${ANTHROPIC_PREFIX}claude-opus-4-6`],
|
||||
["opus", `${ANTHROPIC_PREFIX}claude-opus-4-7`],
|
||||
["haiku", `${ANTHROPIC_PREFIX}claude-haiku-4-5`],
|
||||
])
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ describe("readOpencodeConfigAgents", () => {
|
||||
agents: {
|
||||
"my-agent": {
|
||||
description: "Custom agent",
|
||||
model: "claude-opus-4-6",
|
||||
model: "claude-opus-4-7",
|
||||
mode: "subagent",
|
||||
prompt: "You are a helpful assistant",
|
||||
},
|
||||
|
||||
@@ -203,7 +203,7 @@ describe("TaskToastManager", () => {
|
||||
description: "Task with inherited model",
|
||||
agent: "sisyphus-junior",
|
||||
isBackground: false,
|
||||
modelInfo: { model: "cliproxy/claude-opus-4-6", type: "inherited" as const },
|
||||
modelInfo: { model: "cliproxy/claude-opus-4-7", type: "inherited" as const },
|
||||
}
|
||||
|
||||
// when - addTask is called
|
||||
@@ -213,7 +213,7 @@ describe("TaskToastManager", () => {
|
||||
expect(mockClient.tui.showToast).toHaveBeenCalled()
|
||||
const call = mockClient.tui.showToast.mock.calls[0][0]
|
||||
expect(call.body.message).toContain("[FALLBACK]")
|
||||
expect(call.body.message).toContain("cliproxy/claude-opus-4-6")
|
||||
expect(call.body.message).toContain("cliproxy/claude-opus-4-7")
|
||||
expect(call.body.message).toContain("(inherited from parent)")
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user