add zai provider and improve telegram typing UX

This commit is contained in:
Henrique Costa 2026-02-12 19:08:35 -03:00
parent 3e4c022c81
commit b62863b724
7 changed files with 67 additions and 0 deletions

View file

@ -882,6 +882,7 @@ func statusCmd() {
hasOpenAI := cfg.Providers.OpenAI.APIKey != "" hasOpenAI := cfg.Providers.OpenAI.APIKey != ""
hasGemini := cfg.Providers.Gemini.APIKey != "" hasGemini := cfg.Providers.Gemini.APIKey != ""
hasZhipu := cfg.Providers.Zhipu.APIKey != "" hasZhipu := cfg.Providers.Zhipu.APIKey != ""
hasZAI := cfg.Providers.ZAI.APIKey != ""
hasGroq := cfg.Providers.Groq.APIKey != "" hasGroq := cfg.Providers.Groq.APIKey != ""
hasVLLM := cfg.Providers.VLLM.APIBase != "" hasVLLM := cfg.Providers.VLLM.APIBase != ""
@ -896,6 +897,7 @@ func statusCmd() {
fmt.Println("OpenAI API:", status(hasOpenAI)) fmt.Println("OpenAI API:", status(hasOpenAI))
fmt.Println("Gemini API:", status(hasGemini)) fmt.Println("Gemini API:", status(hasGemini))
fmt.Println("Zhipu API:", status(hasZhipu)) fmt.Println("Zhipu API:", status(hasZhipu))
fmt.Println("Z.AI API:", status(hasZAI))
fmt.Println("Groq API:", status(hasGroq)) fmt.Println("Groq API:", status(hasGroq))
if hasVLLM { if hasVLLM {
fmt.Printf("vLLM/Local: ✓ %s\n", cfg.Providers.VLLM.APIBase) fmt.Printf("vLLM/Local: ✓ %s\n", cfg.Providers.VLLM.APIBase)

View file

@ -74,6 +74,10 @@
"api_key": "YOUR_ZHIPU_API_KEY", "api_key": "YOUR_ZHIPU_API_KEY",
"api_base": "" "api_base": ""
}, },
"zai": {
"api_key": "YOUR_ZAI_API_KEY",
"api_base": "https://api.z.ai/api/paas/v4"
},
"gemini": { "gemini": {
"api_key": "", "api_key": "",
"api_base": "" "api_base": ""

View file

@ -139,6 +139,7 @@ type ProvidersConfig struct {
OpenRouter ProviderConfig `json:"openrouter"` OpenRouter ProviderConfig `json:"openrouter"`
Groq ProviderConfig `json:"groq"` Groq ProviderConfig `json:"groq"`
Zhipu ProviderConfig `json:"zhipu"` Zhipu ProviderConfig `json:"zhipu"`
ZAI ProviderConfig `json:"zai"`
VLLM ProviderConfig `json:"vllm"` VLLM ProviderConfig `json:"vllm"`
Gemini ProviderConfig `json:"gemini"` Gemini ProviderConfig `json:"gemini"`
Nvidia ProviderConfig `json:"nvidia"` Nvidia ProviderConfig `json:"nvidia"`
@ -239,6 +240,7 @@ func DefaultConfig() *Config {
OpenRouter: ProviderConfig{}, OpenRouter: ProviderConfig{},
Groq: ProviderConfig{}, Groq: ProviderConfig{},
Zhipu: ProviderConfig{}, Zhipu: ProviderConfig{},
ZAI: ProviderConfig{},
VLLM: ProviderConfig{}, VLLM: ProviderConfig{},
Gemini: ProviderConfig{}, Gemini: ProviderConfig{},
Nvidia: ProviderConfig{}, Nvidia: ProviderConfig{},

View file

@ -17,6 +17,7 @@ var supportedProviders = map[string]bool{
"openrouter": true, "openrouter": true,
"groq": true, "groq": true,
"zhipu": true, "zhipu": true,
"zai": true,
"vllm": true, "vllm": true,
"gemini": true, "gemini": true,
} }
@ -115,6 +116,8 @@ func ConvertConfig(data map[string]interface{}) (*config.Config, []string, error
cfg.Providers.Groq = pc cfg.Providers.Groq = pc
case "zhipu": case "zhipu":
cfg.Providers.Zhipu = pc cfg.Providers.Zhipu = pc
case "zai":
cfg.Providers.ZAI = pc
case "vllm": case "vllm":
cfg.Providers.VLLM = pc cfg.Providers.VLLM = pc
case "gemini": case "gemini":
@ -242,6 +245,9 @@ func MergeConfig(existing, incoming *config.Config) *config.Config {
if existing.Providers.Zhipu.APIKey == "" { if existing.Providers.Zhipu.APIKey == "" {
existing.Providers.Zhipu = incoming.Providers.Zhipu existing.Providers.Zhipu = incoming.Providers.Zhipu
} }
if existing.Providers.ZAI.APIKey == "" {
existing.Providers.ZAI = incoming.Providers.ZAI
}
if existing.Providers.VLLM.APIKey == "" && existing.Providers.VLLM.APIBase == "" { if existing.Providers.VLLM.APIKey == "" && existing.Providers.VLLM.APIBase == "" {
existing.Providers.VLLM = incoming.Providers.VLLM existing.Providers.VLLM = incoming.Providers.VLLM
} }

View file

@ -153,6 +153,10 @@ func zhipuCreator(cfg *config.Config, _ string) (LLMProvider, bool, error) {
return createHTTPProviderFromConfig(cfg.Providers.Zhipu, "https://open.bigmodel.cn/api/paas/v4", true, false) return createHTTPProviderFromConfig(cfg.Providers.Zhipu, "https://open.bigmodel.cn/api/paas/v4", true, false)
} }
func zaiCreator(cfg *config.Config, _ string) (LLMProvider, bool, error) {
return createHTTPProviderFromConfig(cfg.Providers.ZAI, "https://api.z.ai/api/paas/v4", true, false)
}
func geminiCreator(cfg *config.Config, _ string) (LLMProvider, bool, error) { func geminiCreator(cfg *config.Config, _ string) (LLMProvider, bool, error) {
return createHTTPProviderFromConfig(cfg.Providers.Gemini, "https://generativelanguage.googleapis.com/v1beta", true, false) return createHTTPProviderFromConfig(cfg.Providers.Gemini, "https://generativelanguage.googleapis.com/v1beta", true, false)
} }

View file

@ -41,6 +41,13 @@ func init() {
Creator: zhipuCreator, Creator: zhipuCreator,
}) })
RegisterProvider(providerRegistration{
Name: "zai",
Aliases: []string{"z.ai"},
ModelPrefixes: []string{"zai/"},
Creator: zaiCreator,
})
RegisterProvider(providerRegistration{ RegisterProvider(providerRegistration{
Name: "groq", Name: "groq",
ModelPrefixes: []string{"groq/"}, ModelPrefixes: []string{"groq/"},

View file

@ -30,6 +30,48 @@ func TestCreateProvider_ZenExplicit(t *testing.T) {
} }
} }
func TestCreateProvider_ZAIExplicit(t *testing.T) {
cfg := config.DefaultConfig()
cfg.Agents.Defaults.Provider = "zai"
cfg.Agents.Defaults.Model = "glm-4.6"
cfg.Providers.ZAI.APIKey = "zai-key"
provider, err := CreateProvider(cfg)
if err != nil {
t.Fatalf("CreateProvider(zai) error = %v", err)
}
httpProvider, ok := provider.(*HTTPProvider)
if !ok {
t.Fatalf("CreateProvider(zai) returned %T, want *HTTPProvider", provider)
}
if httpProvider.apiBase != "https://api.z.ai/api/paas/v4" {
t.Errorf("apiBase = %q, want %q", httpProvider.apiBase, "https://api.z.ai/api/paas/v4")
}
if httpProvider.apiKey != "zai-key" {
t.Errorf("apiKey = %q, want %q", httpProvider.apiKey, "zai-key")
}
}
func TestCreateProvider_ZAIByModelPrefix(t *testing.T) {
cfg := config.DefaultConfig()
cfg.Agents.Defaults.Model = "zai/glm-4.6"
cfg.Providers.ZAI.APIKey = "zai-key"
provider, err := CreateProvider(cfg)
if err != nil {
t.Fatalf("CreateProvider(zai/*) error = %v", err)
}
httpProvider, ok := provider.(*HTTPProvider)
if !ok {
t.Fatalf("CreateProvider(zai/*) returned %T, want *HTTPProvider", provider)
}
if httpProvider.apiBase != "https://api.z.ai/api/paas/v4" {
t.Errorf("apiBase = %q, want %q", httpProvider.apiBase, "https://api.z.ai/api/paas/v4")
}
}
func TestCreateProvider_ZenByModelPrefix(t *testing.T) { func TestCreateProvider_ZenByModelPrefix(t *testing.T) {
cfg := config.DefaultConfig() cfg := config.DefaultConfig()
cfg.Agents.Defaults.Model = "zen/kimi-k2.5-free" cfg.Agents.Defaults.Model = "zen/kimi-k2.5-free"