diff --git a/internal/providers/configs/iflow.json b/internal/providers/configs/iflow.json new file mode 100644 index 00000000..4028a7af --- /dev/null +++ b/internal/providers/configs/iflow.json @@ -0,0 +1,59 @@ +{ + "name": "iFlow", + "id": "iflow", + "type": "iflow", + "api_key": "$IFLOW_API_KEY", + "api_endpoint": "https://apis.iflow.cn/v1", + "default_large_model_id": "glm-4.7", + "default_small_model_id": "glm-4.7", + "models": [ + { + "id": "minimax-m2.1", + "name": "Minimax M2.1", + "cost_per_1m_in": 0, + "cost_per_1m_out": 0, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 204800, + "default_max_tokens": 131100, + "can_reason": true, + "supports_attachments": true + }, + { + "id": "deepseek-v3.2", + "name": "DeepSeek V3.2", + "cost_per_1m_in": 0, + "cost_per_1m_out": 0, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 128000, + "default_max_tokens": 32000, + "can_reason": true, + "supports_attachments": false + }, + { + "id": "glm-4.7", + "name": "GLM 4.7", + "cost_per_1m_in": 0, + "cost_per_1m_out": 0, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 200000, + "default_max_tokens": 128000, + "can_reason": true, + "supports_attachments": false + }, + { + "id": "kimi-k2-thinking", + "name": "Kimi K2 Thinking", + "cost_per_1m_in": 0, + "cost_per_1m_out": 0, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 256000, + "default_max_tokens": 32000, + "can_reason": true, + "supports_attachments": false + } + ] +} \ No newline at end of file diff --git a/internal/providers/configs/xiaomi.json b/internal/providers/configs/xiaomi.json new file mode 100644 index 00000000..e060b45c --- /dev/null +++ b/internal/providers/configs/xiaomi.json @@ -0,0 +1,23 @@ +{ + "name": "Xiaomi", + "id": "xiaomi", + "type": "xiaomi", + "api_key": "$XIAOMI_API_KEY", + "api_endpoint": "https://api.xiaomimimo.com/v1", + "default_large_model_id": "mimo-v2-flash", + "default_small_model_id": "mimo-v2-flash", + "models": [ + { + "id": "mimo-v2-flash", + "name": "Mimo V2 Flash", + "cost_per_1m_in": 0, + "cost_per_1m_out": 0, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 256000, + "default_max_tokens": 128000, + "can_reason": true, + "supports_attachments": false + } + ] +} \ No newline at end of file diff --git a/internal/providers/providers.go b/internal/providers/providers.go index d5299c49..173b488b 100644 --- a/internal/providers/providers.go +++ b/internal/providers/providers.go @@ -66,6 +66,12 @@ var kimiCodingConfig []byte //go:embed configs/copilot.json var copilotConfig []byte +//go:embed configs/xiaomi.json +var xiaomiConfig []byte + +//go:embed configs/iflow.json +var iflowConfig []byte + // ProviderFunc is a function that returns a Provider. type ProviderFunc func() catwalk.Provider @@ -89,6 +95,8 @@ var providerRegistry = []ProviderFunc{ aiHubMixProvider, syntheticProvider, copilotProvider, + xiaomiProvider, + iflowProvider, } // GetAll returns all registered providers. @@ -184,3 +192,11 @@ func kimiCodingProvider() catwalk.Provider { func copilotProvider() catwalk.Provider { return loadProviderFromConfig(copilotConfig) } + +func xiaomiProvider() catwalk.Provider { + return loadProviderFromConfig(xiaomiConfig) +} + +func iflowProvider() catwalk.Provider { + return loadProviderFromConfig(iflowConfig) +} diff --git a/internal/providers/providers_test.go b/internal/providers/providers_test.go new file mode 100644 index 00000000..98d37000 --- /dev/null +++ b/internal/providers/providers_test.go @@ -0,0 +1,62 @@ +package providers + +import ( + "testing" +) + +func TestXiaomiProvider(t *testing.T) { + providers := GetAll() + + var xiaomiFound bool + for _, p := range providers { + if p.ID == "xiaomi" { + xiaomiFound = true + + if p.Name != "Xiaomi" { + t.Errorf("Expected name 'Xiaomi', got '%s'", p.Name) + } + + if p.Type != "xiaomi" { + t.Errorf("Expected type 'xiaomi', got '%s'", p.Type) + } + + if p.APIEndpoint != "https://api.xiaomimimo.com/v1" { + t.Errorf("Expected API endpoint 'https://api.xiaomimimo.com/v1', got '%s'", p.APIEndpoint) + } + + if p.DefaultLargeModelID != "mimo-v2-flash" { + t.Errorf("Expected default large model 'mimo-v2-flash', got '%s'", p.DefaultLargeModelID) + } + + if p.DefaultSmallModelID != "mimo-v2-flash" { + t.Errorf("Expected default small model 'mimo-v2-flash', got '%s'", p.DefaultSmallModelID) + } + + if len(p.Models) != 1 { + t.Errorf("Expected 1 model, got %d", len(p.Models)) + } + + if len(p.Models) > 0 { + model := p.Models[0] + if model.ID != "mimo-v2-flash" { + t.Errorf("Expected model ID 'mimo-v2-flash', got '%s'", model.ID) + } + if model.Name != "Mimo V2 Flash" { + t.Errorf("Expected model name 'Mimo V2 Flash', got '%s'", model.Name) + } + if !model.CanReason { + t.Error("Expected model to have CanReason = true") + } + if model.ContextWindow != 256000 { + t.Errorf("Expected context window 256000, got %d", model.ContextWindow) + } + } + + break + } + } + + if !xiaomiFound { + t.Error("Xiaomi provider not found in provider registry") + } +} \ No newline at end of file