mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-19 04:40:52 +08:00
Merge pull request #1465 from router-for-me/kimi-fix
fix(kimi): add OAuth model-alias channel support and cover OAuth excl…
This commit is contained in:
@@ -221,7 +221,7 @@ nonstream-keepalive-interval: 0
|
|||||||
|
|
||||||
# Global OAuth model name aliases (per channel)
|
# Global OAuth model name aliases (per channel)
|
||||||
# These aliases rename model IDs for both model listing and request routing.
|
# These aliases rename model IDs for both model listing and request routing.
|
||||||
# Supported channels: gemini-cli, vertex, aistudio, antigravity, claude, codex, qwen, iflow.
|
# Supported channels: gemini-cli, vertex, aistudio, antigravity, claude, codex, qwen, iflow, kimi.
|
||||||
# NOTE: Aliases do not apply to gemini-api-key, codex-api-key, claude-api-key, openai-compatibility, vertex-api-key, or ampcode.
|
# NOTE: Aliases do not apply to gemini-api-key, codex-api-key, claude-api-key, openai-compatibility, vertex-api-key, or ampcode.
|
||||||
# You can repeat the same name with different aliases to expose multiple client model names.
|
# You can repeat the same name with different aliases to expose multiple client model names.
|
||||||
oauth-model-alias:
|
oauth-model-alias:
|
||||||
@@ -262,6 +262,9 @@ oauth-model-alias:
|
|||||||
# iflow:
|
# iflow:
|
||||||
# - name: "glm-4.7"
|
# - name: "glm-4.7"
|
||||||
# alias: "glm-god"
|
# alias: "glm-god"
|
||||||
|
# kimi:
|
||||||
|
# - name: "kimi-k2.5"
|
||||||
|
# alias: "k2.5"
|
||||||
|
|
||||||
# OAuth provider excluded models
|
# OAuth provider excluded models
|
||||||
# oauth-excluded-models:
|
# oauth-excluded-models:
|
||||||
@@ -284,6 +287,8 @@ oauth-model-alias:
|
|||||||
# - "vision-model"
|
# - "vision-model"
|
||||||
# iflow:
|
# iflow:
|
||||||
# - "tstars2.0"
|
# - "tstars2.0"
|
||||||
|
# kimi:
|
||||||
|
# - "kimi-k2-thinking"
|
||||||
|
|
||||||
# Optional payload configuration
|
# Optional payload configuration
|
||||||
# payload:
|
# payload:
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ func modelAliasChannel(auth *Auth) string {
|
|||||||
// and auth kind. Returns empty string if the provider/authKind combination doesn't support
|
// and auth kind. Returns empty string if the provider/authKind combination doesn't support
|
||||||
// OAuth model alias (e.g., API key authentication).
|
// OAuth model alias (e.g., API key authentication).
|
||||||
//
|
//
|
||||||
// Supported channels: gemini-cli, vertex, aistudio, antigravity, claude, codex, qwen, iflow.
|
// Supported channels: gemini-cli, vertex, aistudio, antigravity, claude, codex, qwen, iflow, kimi.
|
||||||
func OAuthModelAliasChannel(provider, authKind string) string {
|
func OAuthModelAliasChannel(provider, authKind string) string {
|
||||||
provider = strings.ToLower(strings.TrimSpace(provider))
|
provider = strings.ToLower(strings.TrimSpace(provider))
|
||||||
authKind = strings.ToLower(strings.TrimSpace(authKind))
|
authKind = strings.ToLower(strings.TrimSpace(authKind))
|
||||||
@@ -245,7 +245,7 @@ func OAuthModelAliasChannel(provider, authKind string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return "codex"
|
return "codex"
|
||||||
case "gemini-cli", "aistudio", "antigravity", "qwen", "iflow":
|
case "gemini-cli", "aistudio", "antigravity", "qwen", "iflow", "kimi":
|
||||||
return provider
|
return provider
|
||||||
default:
|
default:
|
||||||
return ""
|
return ""
|
||||||
|
|||||||
@@ -70,6 +70,15 @@ func TestResolveOAuthUpstreamModel_SuffixPreservation(t *testing.T) {
|
|||||||
input: "gemini-2.5-pro(none)",
|
input: "gemini-2.5-pro(none)",
|
||||||
want: "gemini-2.5-pro-exp-03-25(none)",
|
want: "gemini-2.5-pro-exp-03-25(none)",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "kimi suffix preserved",
|
||||||
|
aliases: map[string][]internalconfig.OAuthModelAlias{
|
||||||
|
"kimi": {{Name: "kimi-k2.5", Alias: "k2.5"}},
|
||||||
|
},
|
||||||
|
channel: "kimi",
|
||||||
|
input: "k2.5(high)",
|
||||||
|
want: "kimi-k2.5(high)",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "case insensitive alias lookup with suffix",
|
name: "case insensitive alias lookup with suffix",
|
||||||
aliases: map[string][]internalconfig.OAuthModelAlias{
|
aliases: map[string][]internalconfig.OAuthModelAlias{
|
||||||
@@ -152,11 +161,21 @@ func createAuthForChannel(channel string) *Auth {
|
|||||||
return &Auth{Provider: "qwen"}
|
return &Auth{Provider: "qwen"}
|
||||||
case "iflow":
|
case "iflow":
|
||||||
return &Auth{Provider: "iflow"}
|
return &Auth{Provider: "iflow"}
|
||||||
|
case "kimi":
|
||||||
|
return &Auth{Provider: "kimi"}
|
||||||
default:
|
default:
|
||||||
return &Auth{Provider: channel}
|
return &Auth{Provider: channel}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestOAuthModelAliasChannel_Kimi(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
if got := OAuthModelAliasChannel("kimi", "oauth"); got != "kimi" {
|
||||||
|
t.Fatalf("OAuthModelAliasChannel() = %q, want %q", got, "kimi")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestApplyOAuthModelAlias_SuffixPreservation(t *testing.T) {
|
func TestApplyOAuthModelAlias_SuffixPreservation(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|||||||
45
sdk/cliproxy/service_oauth_excluded_models_test.go
Normal file
45
sdk/cliproxy/service_oauth_excluded_models_test.go
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package cliproxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/router-for-me/CLIProxyAPI/v6/sdk/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestOAuthExcludedModels_KimiOAuth(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
svc := &Service{
|
||||||
|
cfg: &config.Config{
|
||||||
|
OAuthExcludedModels: map[string][]string{
|
||||||
|
"kimi": {"kimi-k2-thinking", "kimi-k2.5"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
got := svc.oauthExcludedModels("kimi", "oauth")
|
||||||
|
if len(got) != 2 {
|
||||||
|
t.Fatalf("expected 2 excluded models, got %d", len(got))
|
||||||
|
}
|
||||||
|
if got[0] != "kimi-k2-thinking" || got[1] != "kimi-k2.5" {
|
||||||
|
t.Fatalf("unexpected excluded models: %#v", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOAuthExcludedModels_KimiAPIKeyReturnsNil(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
svc := &Service{
|
||||||
|
cfg: &config.Config{
|
||||||
|
OAuthExcludedModels: map[string][]string{
|
||||||
|
"kimi": {"kimi-k2-thinking"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
got := svc.oauthExcludedModels("kimi", "apikey")
|
||||||
|
if got != nil {
|
||||||
|
t.Fatalf("expected nil for apikey auth kind, got %#v", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -90,3 +90,27 @@ func TestApplyOAuthModelAlias_ForkAddsMultipleAliases(t *testing.T) {
|
|||||||
t.Fatalf("expected forked model name %q, got %q", "models/g5-2", out[2].Name)
|
t.Fatalf("expected forked model name %q, got %q", "models/g5-2", out[2].Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestApplyOAuthModelAlias_KimiRename(t *testing.T) {
|
||||||
|
cfg := &config.Config{
|
||||||
|
OAuthModelAlias: map[string][]config.OAuthModelAlias{
|
||||||
|
"kimi": {
|
||||||
|
{Name: "kimi-k2.5", Alias: "k2.5"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
models := []*ModelInfo{
|
||||||
|
{ID: "kimi-k2.5", Name: "models/kimi-k2.5"},
|
||||||
|
}
|
||||||
|
|
||||||
|
out := applyOAuthModelAlias(cfg, "kimi", "oauth", models)
|
||||||
|
if len(out) != 1 {
|
||||||
|
t.Fatalf("expected 1 model, got %d", len(out))
|
||||||
|
}
|
||||||
|
if out[0].ID != "k2.5" {
|
||||||
|
t.Fatalf("expected model id %q, got %q", "k2.5", out[0].ID)
|
||||||
|
}
|
||||||
|
if out[0].Name != "models/k2.5" {
|
||||||
|
t.Fatalf("expected model name %q, got %q", "models/k2.5", out[0].Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user