Compare commits

..

6 Commits

Author SHA1 Message Date
9375448087 fix(moonshot): resolve 401 Unauthorized errors by trimming API keys and improving request compatibility
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
2026-03-26 17:09:27 +00:00
5be2f6f7aa fix: use Moonshot test model
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
2026-03-26 10:12:44 -04:00
eebcadcba1 fix: surface moonshot on providers page
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
2026-03-25 09:35:41 -04:00
6b2bd13903 chore: remove tracked binary gophergate
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
2026-03-25 13:32:51 +00:00
5dfda0a10c merge: resolve conflicts in server.go and integrate moonshot support 2026-03-25 13:32:40 +00:00
bd1d17cc4d feat: add moonshot kimi k2.5 support
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Build (push) Has been cancelled
2026-03-25 09:27:46 -04:00
6 changed files with 44 additions and 27 deletions

Binary file not shown.

View File

@@ -203,5 +203,5 @@ func (c *Config) GetAPIKey(provider string) (string, error) {
if val == "" {
return "", fmt.Errorf("environment variable %s not set for %s", envVar, provider)
}
return val, nil
return strings.TrimSpace(val), nil
}

View File

@@ -58,9 +58,20 @@ func MessagesToOpenAIJSON(messages []models.UnifiedMessage) ([]interface{}, erro
}
}
var finalContent interface{}
if len(parts) == 1 {
if p, ok := parts[0].(map[string]interface{}); ok && p["type"] == "text" {
finalContent = p["text"]
} else {
finalContent = parts
}
} else {
finalContent = parts
}
msg := map[string]interface{}{
"role": m.Role,
"content": parts,
"content": finalContent,
}
if m.ReasoningContent != nil {

View File

@@ -21,7 +21,7 @@ func NewMoonshotProvider(cfg config.MoonshotConfig, apiKey string) *MoonshotProv
return &MoonshotProvider{
client: resty.New(),
config: cfg,
apiKey: apiKey,
apiKey: strings.TrimSpace(apiKey),
}
}
@@ -43,11 +43,15 @@ func (p *MoonshotProvider) ChatCompletion(ctx context.Context, req *models.Unifi
}
}
baseURL := strings.TrimRight(p.config.BaseURL, "/")
resp, err := p.client.R().
SetContext(ctx).
SetHeader("Authorization", "Bearer "+p.apiKey).
SetHeader("Content-Type", "application/json").
SetHeader("Accept", "application/json").
SetBody(body).
Post(fmt.Sprintf("%s/chat/completions", p.config.BaseURL))
Post(fmt.Sprintf("%s/chat/completions", baseURL))
if err != nil {
return nil, fmt.Errorf("request failed: %w", err)
@@ -79,12 +83,16 @@ func (p *MoonshotProvider) ChatCompletionStream(ctx context.Context, req *models
}
}
baseURL := strings.TrimRight(p.config.BaseURL, "/")
resp, err := p.client.R().
SetContext(ctx).
SetHeader("Authorization", "Bearer "+p.apiKey).
SetHeader("Content-Type", "application/json").
SetHeader("Accept", "text/event-stream").
SetBody(body).
SetDoNotParseResponse(true).
Post(fmt.Sprintf("%s/chat/completions", p.config.BaseURL))
Post(fmt.Sprintf("%s/chat/completions", baseURL))
if err != nil {
return nil, fmt.Errorf("request failed: %w", err)

View File

@@ -801,7 +801,7 @@ func (s *Server) handleGetProviders(c *gin.Context) {
dbMap[cfg.ID] = cfg
}
providerIDs := []string{"openai", "gemini", "deepseek", "grok", "ollama"}
providerIDs := []string{"openai", "gemini", "deepseek", "moonshot", "grok", "ollama"}
var result []gin.H
for _, id := range providerIDs {
@@ -822,6 +822,10 @@ func (s *Server) handleGetProviders(c *gin.Context) {
name = "DeepSeek"
enabled = s.cfg.Providers.DeepSeek.Enabled
baseURL = s.cfg.Providers.DeepSeek.BaseURL
case "moonshot":
name = "Moonshot"
enabled = s.cfg.Providers.Moonshot.Enabled
baseURL = s.cfg.Providers.Moonshot.BaseURL
case "grok":
name = "xAI Grok"
enabled = s.cfg.Providers.Grok.Enabled
@@ -870,6 +874,7 @@ func (s *Server) handleGetProviders(c *gin.Context) {
if s.registry != nil {
registryID := id
if id == "gemini" { registryID = "google" }
if id == "moonshot" { registryID = "moonshot" }
if id == "grok" { registryID = "xai" }
if pInfo, ok := s.registry.Providers[registryID]; ok {
@@ -978,6 +983,8 @@ func (s *Server) handleTestProvider(c *gin.Context) {
testReq.Model = "gemini-2.0-flash"
} else if name == "deepseek" {
testReq.Model = "deepseek-chat"
} else if name == "moonshot" {
testReq.Model = "kimi-k2.5"
} else if name == "grok" {
testReq.Model = "grok-4-1-fast-non-reasoning"
}

View File

@@ -54,26 +54,9 @@ func NewServer(cfg *config.Config, database *db.DB) *Server {
}
}()
// Initialize providers
if cfg.Providers.OpenAI.Enabled {
apiKey, _ := cfg.GetAPIKey("openai")
s.providers["openai"] = providers.NewOpenAIProvider(cfg.Providers.OpenAI, apiKey)
}
if cfg.Providers.Gemini.Enabled {
apiKey, _ := cfg.GetAPIKey("gemini")
s.providers["gemini"] = providers.NewGeminiProvider(cfg.Providers.Gemini, apiKey)
}
if cfg.Providers.DeepSeek.Enabled {
apiKey, _ := cfg.GetAPIKey("deepseek")
s.providers["deepseek"] = providers.NewDeepSeekProvider(cfg.Providers.DeepSeek, apiKey)
}
if cfg.Providers.Moonshot.Enabled {
apiKey, _ := cfg.GetAPIKey("moonshot")
s.providers["moonshot"] = providers.NewMoonshotProvider(cfg.Providers.Moonshot, apiKey)
}
if cfg.Providers.Grok.Enabled {
apiKey, _ := cfg.GetAPIKey("grok")
s.providers["grok"] = providers.NewGrokProvider(cfg.Providers.Grok, apiKey)
// Initialize providers from DB and Config
if err := s.RefreshProviders(); err != nil {
fmt.Printf("Warning: Failed to initial refresh providers: %v\n", err)
}
s.setupRoutes()
@@ -92,7 +75,7 @@ func (s *Server) RefreshProviders() error {
dbMap[cfg.ID] = cfg
}
providerIDs := []string{"openai", "gemini", "deepseek", "grok"}
providerIDs := []string{"openai", "gemini", "deepseek", "moonshot", "grok"}
for _, id := range providerIDs {
// Default values from config
enabled := false
@@ -112,6 +95,10 @@ func (s *Server) RefreshProviders() error {
enabled = s.cfg.Providers.DeepSeek.Enabled
baseURL = s.cfg.Providers.DeepSeek.BaseURL
apiKey, _ = s.cfg.GetAPIKey("deepseek")
case "moonshot":
enabled = s.cfg.Providers.Moonshot.Enabled
baseURL = s.cfg.Providers.Moonshot.BaseURL
apiKey, _ = s.cfg.GetAPIKey("moonshot")
case "grok":
enabled = s.cfg.Providers.Grok.Enabled
baseURL = s.cfg.Providers.Grok.BaseURL
@@ -157,6 +144,10 @@ func (s *Server) RefreshProviders() error {
cfg := s.cfg.Providers.DeepSeek
cfg.BaseURL = baseURL
s.providers["deepseek"] = providers.NewDeepSeekProvider(cfg, apiKey)
case "moonshot":
cfg := s.cfg.Providers.Moonshot
cfg.BaseURL = baseURL
s.providers["moonshot"] = providers.NewMoonshotProvider(cfg, apiKey)
case "grok":
cfg := s.cfg.Providers.Grok
cfg.BaseURL = baseURL