diff --git a/clawlet b/clawlet new file mode 100755 index 0000000..ad38253 Binary files /dev/null and b/clawlet differ diff --git a/cmd/clawlet/config.go b/cmd/clawlet/config.go index af8972c..548b3b3 100644 --- a/cmd/clawlet/config.go +++ b/cmd/clawlet/config.go @@ -101,6 +101,12 @@ func applyEnvOverrides(cfg *config.Config) { } cfg.Env["GOOGLE_API_KEY"] = v } + if v := os.Getenv("SHENGSUANYUN_API_KEY"); v != "" { + if cfg.Env == nil { + cfg.Env = map[string]string{} + } + cfg.Env["SHENGSUANYUN_API_KEY"] = v + } if v := strings.TrimSpace(os.Getenv("CLAWLET_WEB_ALLOWED_DOMAINS")); v != "" { cfg.Tools.Web.AllowedDomains = splitCSV(v) } diff --git a/config/config.go b/config/config.go index 4fc03f8..33640a3 100644 --- a/config/config.go +++ b/config/config.go @@ -336,6 +336,7 @@ const ( DefaultOpenRouterBaseURL = "https://openrouter.ai/api/v1" DefaultAnthropicBaseURL = "https://api.anthropic.com" DefaultGeminiBaseURL = "https://generativelanguage.googleapis.com/v1beta" + DefaultShengSuanYunBaseURL = "https://router.shengsuanyun.com/api/v1" DefaultOllamaBaseURL = "http://localhost:11434/v1" DefaultWebFetchMaxResponseBytes = int64(500_000) DefaultWebFetchTimeoutSec = 30 @@ -808,6 +809,8 @@ func (cfg *Config) ApplyLLMRouting() (provider string, configuredModel string) { cfg.LLM.BaseURL = DefaultGeminiBaseURL case "ollama": cfg.LLM.BaseURL = DefaultOllamaBaseURL + case "shengsuanyun": + cfg.LLM.BaseURL = DefaultShengSuanYunBaseURL } } @@ -817,6 +820,8 @@ func (cfg *Config) ApplyLLMRouting() (provider string, configuredModel string) { cfg.LLM.APIKey = strings.TrimSpace(cfg.Env["OPENAI_API_KEY"]) case "openrouter": cfg.LLM.APIKey = strings.TrimSpace(cfg.Env["OPENROUTER_API_KEY"]) + case "shengsuanyun": + cfg.LLM.APIKey = strings.TrimSpace(cfg.Env["SHENGSUANYUN_API_KEY"]) case "anthropic": cfg.LLM.APIKey = strings.TrimSpace(cfg.Env["ANTHROPIC_API_KEY"]) case "gemini": @@ -841,6 +846,9 @@ func parseRoutedModel(s string) (provider string, model string) { if after, ok := strings.CutPrefix(s, "openrouter/"); ok { return "openrouter", after } + if after, ok := strings.CutPrefix(s, "shengsuanyun/"); ok { + return "shengsuanyun", after + } if after, ok := strings.CutPrefix(s, "anthropic/"); ok { return "anthropic", after } diff --git a/llm/client.go b/llm/client.go index ccc1400..3561ed9 100644 --- a/llm/client.go +++ b/llm/client.go @@ -42,7 +42,7 @@ func (c *Client) Chat(ctx context.Context, messages []Message, tools []ToolDefin c.HTTP = &http.Client{Timeout: 120 * time.Second} } switch normalizeProvider(c.Provider) { - case "", "openai", "openrouter", "ollama": + case "", "openai", "openrouter", "ollama","shengsuanyun": return c.chatOpenAICompatible(ctx, messages, tools) case "anthropic": return c.chatAnthropic(ctx, messages, tools)