fix: installer writes hyphenated anthropic IDs, variant=max Anthropic OAuth compat (#3429, #3459)

This commit is contained in:
YeonGyu-Kim
2026-04-16 14:28:56 +09:00
parent 80e73f5727
commit 7bc170fb86
10 changed files with 474 additions and 207 deletions
File diff suppressed because it is too large Load Diff
@@ -74,7 +74,7 @@ describe("generateOmoConfig - model fallback system", () => {
//#then
expect((result.agents as Record<string, { model: string }>).librarian.model).toBe("zai-coding-plan/glm-4.7")
expect((result.agents as Record<string, { model: string }>).sisyphus.model).toBe("anthropic/claude-opus-4.6")
expect((result.agents as Record<string, { model: string }>).sisyphus.model).toBe("anthropic/claude-opus-4-6")
})
test("uses native OpenAI models when only ChatGPT available", () => {
@@ -131,7 +131,7 @@ describe("generateOmoConfig - model fallback system", () => {
}>
//#then
expect(agents.sisyphus.model).toBe("anthropic/claude-opus-4.6")
expect(agents.sisyphus.model).toBe("anthropic/claude-opus-4-6")
expect(agents.sisyphus.fallback_models).toEqual([
{
model: "openai/gpt-5.4",
@@ -141,7 +141,7 @@ describe("generateOmoConfig - model fallback system", () => {
expect(categories.deep.model).toBe("openai/gpt-5.4")
expect(categories.deep.fallback_models).toEqual([
{
model: "anthropic/claude-opus-4.6",
model: "anthropic/claude-opus-4-6",
variant: "max",
},
])
+5 -9
View File
@@ -381,7 +381,7 @@ describe("generateModelConfig", () => {
const result = generateModelConfig(config)
// #then
expect(result.agents?.sisyphus?.model).toBe("anthropic/claude-opus-4.6")
expect(result.agents?.sisyphus?.model).toBe("anthropic/claude-opus-4-6")
})
test("Sisyphus is created when multiple fallback providers are available", () => {
@@ -398,7 +398,7 @@ describe("generateModelConfig", () => {
const result = generateModelConfig(config)
// #then
expect(result.agents?.sisyphus?.model).toBe("anthropic/claude-opus-4.6")
expect(result.agents?.sisyphus?.model).toBe("anthropic/claude-opus-4-6")
})
test("Sisyphus resolves to gpt-5.4 medium when only OpenAI is available", () => {
@@ -573,13 +573,9 @@ describe("generateModelConfig", () => {
// #when generateModelConfig is called
const result = generateModelConfig(config)
// #then explore should not have fallback_models (only one chain entry matches)
// #then explore should not have fallback_models (only one distinct chain entry matches)
expect(result.agents?.explore?.model).toBe("anthropic/claude-haiku-4-5")
expect(result.agents?.explore?.fallback_models).toEqual([
{
model: "anthropic/claude-haiku-4.5",
},
])
expect(result.agents?.explore?.fallback_models).toBeUndefined()
})
test("librarian includes fallback_models when opencode-go and Claude are both available", () => {
@@ -672,7 +668,7 @@ describe("generateModelConfig", () => {
const result = generateModelConfig(config)
// #then should prefer native anthropic over gateway
expect(result.agents?.sisyphus?.model).toBe("anthropic/claude-opus-4.6")
expect(result.agents?.sisyphus?.model).toBe("anthropic/claude-opus-4-6")
})
})
+15 -13
View File
@@ -165,7 +165,7 @@ describe("transformModelForProvider", () => {
})
describe("anthropic provider", () => {
test("transforms claude-opus-4-6 to claude-opus-4.6", () => {
test("preserves hyphenated claude-opus-4-6 for config output (regression: installer must not write dotted IDs)", () => {
// #given anthropic provider and claude-opus-4-6 model
const provider = "anthropic"
const model = "claude-opus-4-6"
@@ -173,11 +173,11 @@ describe("transformModelForProvider", () => {
// #when transformModelForProvider is called
const result = transformModelForProvider(provider, model)
// #then should transform to claude-opus-4.6
expect(result).toBe("claude-opus-4.6")
// #then should keep hyphenated form so Anthropic provider resolution succeeds on fresh installs
expect(result).toBe("claude-opus-4-6")
})
test("transforms claude-sonnet-4-6 to claude-sonnet-4.6", () => {
test("preserves hyphenated claude-sonnet-4-6 for config output", () => {
// #given anthropic provider and claude-sonnet-4-6 model
const provider = "anthropic"
const model = "claude-sonnet-4-6"
@@ -185,11 +185,11 @@ describe("transformModelForProvider", () => {
// #when transformModelForProvider is called
const result = transformModelForProvider(provider, model)
// #then should transform to claude-sonnet-4.6
expect(result).toBe("claude-sonnet-4.6")
// #then should keep hyphenated form
expect(result).toBe("claude-sonnet-4-6")
})
test("transforms claude-haiku-4-5 to claude-haiku-4.5", () => {
test("preserves hyphenated claude-haiku-4-5 for config output", () => {
// #given anthropic provider and claude-haiku-4-5 model
const provider = "anthropic"
const model = "claude-haiku-4-5"
@@ -197,8 +197,8 @@ describe("transformModelForProvider", () => {
// #when transformModelForProvider is called
const result = transformModelForProvider(provider, model)
// #then should transform to claude-haiku-4.5
expect(result).toBe("claude-haiku-4.5")
// #then should keep hyphenated form
expect(result).toBe("claude-haiku-4-5")
})
})
@@ -338,14 +338,16 @@ describe("transformModelForProvider", () => {
})
})
test("uses a CLI-local transform implementation", () => {
// #given
test("uses a CLI-local transform implementation distinct from the shared runtime transform", () => {
// #given the CLI transform (used by the installer) and the shared runtime transform
const cliResult = transformModelForProvider("anthropic", "claude-opus-4-6")
const sharedResult = transformSharedModelForProvider("anthropic", "claude-opus-4-6")
// #when
// #when both are called with the same anthropic claude input
// #then the CLI preserves hyphenated form for config output,
// the shared runtime transform converts dash→dot for API calls
expect(transformModelForProvider).not.toBe(transformSharedModelForProvider)
expect(cliResult).toBe("claude-opus-4.6")
expect(cliResult).toBe("claude-opus-4-6")
expect(sharedResult).toBe("claude-opus-4.6")
})
})
+6 -1
View File
@@ -54,7 +54,12 @@ export function transformModelForProvider(provider: string, model: string): stri
}
if (provider === "anthropic") {
return claudeVersionDot(model)
// Installer writes hyphenated IDs (claude-opus-4-6) to the config. The
// runtime provider-model-id-transform converts dash→dot when calling the
// Anthropic API. Keeping the dotted form in the config breaks fresh
// installs with ProviderModelNotFoundError because Anthropic's provider
// registers models under hyphenated IDs.
return model
}
return model