-
-
Notifications
You must be signed in to change notification settings - Fork 211
feat(config): add default Kiro model aliases for standard Claude model names #209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -736,8 +736,32 @@ func payloadRawString(value any) ([]byte, bool) { | |
| // SanitizeOAuthModelAlias normalizes and deduplicates global OAuth model name aliases. | ||
| // It trims whitespace, normalizes channel keys to lower-case, drops empty entries, | ||
| // allows multiple aliases per upstream name, and ensures aliases are unique within each channel. | ||
| // It also injects default aliases for channels that have built-in defaults (e.g., kiro) | ||
| // when no user-configured aliases exist for those channels. | ||
| func (cfg *Config) SanitizeOAuthModelAlias() { | ||
| if cfg == nil || len(cfg.OAuthModelAlias) == 0 { | ||
| if cfg == nil { | ||
| return | ||
| } | ||
|
|
||
| // Inject default Kiro aliases if no user-configured kiro aliases exist | ||
| if cfg.OAuthModelAlias == nil { | ||
| cfg.OAuthModelAlias = make(map[string][]OAuthModelAlias) | ||
| } | ||
| if _, hasKiro := cfg.OAuthModelAlias["kiro"]; !hasKiro { | ||
| // Check case-insensitive too | ||
| found := false | ||
| for k := range cfg.OAuthModelAlias { | ||
| if strings.EqualFold(strings.TrimSpace(k), "kiro") { | ||
| found = true | ||
| break | ||
| } | ||
| } | ||
| if !found { | ||
| cfg.OAuthModelAlias["kiro"] = defaultKiroAliases() | ||
| } | ||
| } | ||
|
Comment on lines
+750
to
+762
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The logic to check for existing user-configured Kiro aliases can be simplified. The current implementation uses a fast-path check for the lowercase hasUserKiro := false
for k := range cfg.OAuthModelAlias {
if strings.EqualFold(strings.TrimSpace(k), "kiro") {
hasUserKiro = true
break
}
}
if !hasUserKiro {
cfg.OAuthModelAlias["kiro"] = defaultKiroAliases()
} |
||
|
|
||
| if len(cfg.OAuthModelAlias) == 0 { | ||
| return | ||
| } | ||
| out := make(map[string][]OAuthModelAlias, len(cfg.OAuthModelAlias)) | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -20,6 +20,28 @@ var antigravityModelConversionTable = map[string]string{ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "gemini-claude-opus-4-6-thinking": "claude-opus-4-6-thinking", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // defaultKiroAliases returns the default oauth-model-alias configuration | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // for the kiro channel. Maps kiro-prefixed model names to standard Claude model | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // names so that clients like Claude Code can use standard names directly. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func defaultKiroAliases() []OAuthModelAlias { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return []OAuthModelAlias{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Sonnet 4.5 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {Name: "kiro-claude-sonnet-4-5", Alias: "claude-sonnet-4-5-20250929", Fork: true}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {Name: "kiro-claude-sonnet-4-5", Alias: "claude-sonnet-4-5", Fork: true}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Sonnet 4 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {Name: "kiro-claude-sonnet-4", Alias: "claude-sonnet-4-20250514", Fork: true}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {Name: "kiro-claude-sonnet-4", Alias: "claude-sonnet-4", Fork: true}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Opus 4.6 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {Name: "kiro-claude-opus-4-6", Alias: "claude-opus-4-6", Fork: true}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Opus 4.5 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {Name: "kiro-claude-opus-4-5", Alias: "claude-opus-4-5-20251101", Fork: true}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {Name: "kiro-claude-opus-4-5", Alias: "claude-opus-4-5", Fork: true}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Haiku 4.5 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {Name: "kiro-claude-haiku-4-5", Alias: "claude-haiku-4-5-20251001", Fork: true}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {Name: "kiro-claude-haiku-4-5", Alias: "claude-haiku-4-5", Fork: true}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+26
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // defaultAntigravityAliases returns the default oauth-model-alias configuration | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // for the antigravity channel when neither field exists. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func defaultAntigravityAliases() []OAuthModelAlias { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -54,3 +54,88 @@ func TestSanitizeOAuthModelAlias_AllowsMultipleAliasesForSameName(t *testing.T) | |
| } | ||
| } | ||
| } | ||
|
|
||
| func TestSanitizeOAuthModelAlias_InjectsDefaultKiroAliases(t *testing.T) { | ||
| // When no kiro aliases are configured, defaults should be injected | ||
| cfg := &Config{ | ||
| OAuthModelAlias: map[string][]OAuthModelAlias{ | ||
| "codex": { | ||
| {Name: "gpt-5", Alias: "g5"}, | ||
| }, | ||
| }, | ||
| } | ||
|
|
||
| cfg.SanitizeOAuthModelAlias() | ||
|
|
||
| kiroAliases := cfg.OAuthModelAlias["kiro"] | ||
| if len(kiroAliases) == 0 { | ||
| t.Fatal("expected default kiro aliases to be injected") | ||
| } | ||
|
|
||
| // Check that standard Claude model names are present | ||
| aliasSet := make(map[string]bool) | ||
| for _, a := range kiroAliases { | ||
| aliasSet[a.Alias] = true | ||
| } | ||
| expectedAliases := []string{ | ||
| "claude-sonnet-4-5-20250929", | ||
| "claude-sonnet-4-5", | ||
| "claude-sonnet-4-20250514", | ||
| "claude-sonnet-4", | ||
| "claude-opus-4-6", | ||
| "claude-opus-4-5-20251101", | ||
| "claude-opus-4-5", | ||
| "claude-haiku-4-5-20251001", | ||
| "claude-haiku-4-5", | ||
| } | ||
| for _, expected := range expectedAliases { | ||
| if !aliasSet[expected] { | ||
| t.Fatalf("expected default kiro alias %q to be present", expected) | ||
| } | ||
| } | ||
|
Comment on lines
+80
to
+95
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The list of expectedDefaultAliases := defaultKiroAliases()
if len(kiroAliases) != len(expectedDefaultAliases) {
t.Fatalf("expected %d default kiro aliases, got %d", len(expectedDefaultAliases), len(kiroAliases))
}
for _, expected := range expectedDefaultAliases {
if !aliasSet[expected.Alias] {
t.Fatalf("expected default kiro alias %q to be present", expected.Alias)
}
} |
||
|
|
||
| // All should have fork=true | ||
| for _, a := range kiroAliases { | ||
| if !a.Fork { | ||
| t.Fatalf("expected all default kiro aliases to have fork=true, got fork=false for %q", a.Alias) | ||
| } | ||
| } | ||
|
|
||
| // Codex aliases should still be preserved | ||
| if len(cfg.OAuthModelAlias["codex"]) != 1 { | ||
| t.Fatal("expected codex aliases to be preserved") | ||
| } | ||
| } | ||
|
|
||
| func TestSanitizeOAuthModelAlias_DoesNotOverrideUserKiroAliases(t *testing.T) { | ||
| // When user has configured kiro aliases, defaults should NOT be injected | ||
| cfg := &Config{ | ||
| OAuthModelAlias: map[string][]OAuthModelAlias{ | ||
| "kiro": { | ||
| {Name: "kiro-claude-sonnet-4", Alias: "my-custom-sonnet", Fork: true}, | ||
| }, | ||
| }, | ||
| } | ||
|
|
||
| cfg.SanitizeOAuthModelAlias() | ||
|
|
||
| kiroAliases := cfg.OAuthModelAlias["kiro"] | ||
| if len(kiroAliases) != 1 { | ||
| t.Fatalf("expected 1 user-configured kiro alias, got %d", len(kiroAliases)) | ||
| } | ||
| if kiroAliases[0].Alias != "my-custom-sonnet" { | ||
| t.Fatalf("expected user alias to be preserved, got %q", kiroAliases[0].Alias) | ||
| } | ||
| } | ||
|
|
||
| func TestSanitizeOAuthModelAlias_InjectsDefaultKiroWhenEmpty(t *testing.T) { | ||
| // When OAuthModelAlias is nil, kiro defaults should still be injected | ||
| cfg := &Config{} | ||
|
|
||
| cfg.SanitizeOAuthModelAlias() | ||
|
|
||
| kiroAliases := cfg.OAuthModelAlias["kiro"] | ||
| if len(kiroAliases) == 0 { | ||
| t.Fatal("expected default kiro aliases to be injected when OAuthModelAlias is nil") | ||
| } | ||
| } | ||
|
Comment on lines
+110
to
+141
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Injecting default Kiro aliases inside SanitizeOAuthModelAlias means any code path that calls this sanitizer before persisting config (e.g., the management API helper that sanitizes oauth-model-alias payloads) will end up writing these defaults to config.yaml, even though the PR description says defaults are injected in-memory (runtime) rather than via file migration. Consider splitting this into (1) a pure sanitizer that only normalizes/dedupes user-provided aliases and (2) a separate step that overlays built-in defaults at runtime (e.g., only for model listing/routing, or only during config load but excluded from persistence).