feat: Get required informations for providers and channels
This commit is contained in:
parent
66792f97a1
commit
a1c7f9348d
1 changed files with 159 additions and 167 deletions
|
|
@ -4,6 +4,21 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ChannelInfo describes a channel and the credential keys it expects.
|
||||||
|
type ChannelInfo struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
RequiredCredentials []string `json:"required_credentials"` // config keys needed (tokens/secrets)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProviderInfo describes a provider and its credential requirements.
|
||||||
|
type ProviderInfo struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
RequiredCredentials []string `json:"required_credentials"`
|
||||||
|
OptionalCredentials []string `json:"optional_credentials"`
|
||||||
|
HasCredentials bool `json:"has_credentials"`
|
||||||
|
}
|
||||||
|
|
||||||
// GetAllChannelNames returns all channel keys available in ChannelsConfig.
|
// GetAllChannelNames returns all channel keys available in ChannelsConfig.
|
||||||
func GetAllChannelNames() []string {
|
func GetAllChannelNames() []string {
|
||||||
return []string{
|
return []string{
|
||||||
|
|
@ -22,48 +37,59 @@ func GetAllChannelNames() []string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEnabledChannels returns the list of channels that are enabled in the config.
|
var channelRequirements = map[string][]string{
|
||||||
func GetEnabledChannels(c *Config) []string {
|
"whatsapp": {"bridge_url"},
|
||||||
var res []string
|
"telegram": {"token"},
|
||||||
|
"feishu": {"app_id", "app_secret"},
|
||||||
|
"discord": {"token"},
|
||||||
|
"maixcam": {"host", "port"},
|
||||||
|
"qq": {"app_id", "app_secret"},
|
||||||
|
"dingtalk": {"client_id", "client_secret"},
|
||||||
|
"slack": {"bot_token", "app_token"},
|
||||||
|
"line": {"channel_secret", "channel_access_token"},
|
||||||
|
"onebot": {"ws_url", "access_token"},
|
||||||
|
"wecom": {"token", "encoding_aes_key"},
|
||||||
|
"wecom_app": {"corp_id", "corp_secret", "agent_id", "token"},
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetChannelRequirements returns the list of credential keys expected for that channel.
|
||||||
|
// These are the config field names (not values) that are typically required to operate
|
||||||
|
// the channel (e.g. "token", "bot_token"). Returns nil if the channel is unknown.
|
||||||
|
func GetChannelRequirements(channel string) []string {
|
||||||
|
return channelRequirements[strings.ToLower(channel)]
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEnabledChannelsInfo returns structured information about all known channels
|
||||||
|
// including whether they are enabled in the provided config and which credentials
|
||||||
|
// they expect.
|
||||||
|
func GetEnabledChannelsInfo(c *Config) []ChannelInfo {
|
||||||
|
var res []ChannelInfo
|
||||||
if c == nil {
|
if c == nil {
|
||||||
|
// return requirements only (not enabled) if config not provided
|
||||||
|
for _, name := range GetAllChannelNames() {
|
||||||
|
res = append(res, ChannelInfo{Name: name, Enabled: false, RequiredCredentials: GetChannelRequirements(name)})
|
||||||
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
if c.Channels.WhatsApp.Enabled {
|
|
||||||
res = append(res, "whatsapp")
|
// helper to append
|
||||||
}
|
add := func(name string, enabled bool) {
|
||||||
if c.Channels.Telegram.Enabled {
|
res = append(res, ChannelInfo{Name: name, Enabled: enabled, RequiredCredentials: GetChannelRequirements(name)})
|
||||||
res = append(res, "telegram")
|
|
||||||
}
|
|
||||||
if c.Channels.Feishu.Enabled {
|
|
||||||
res = append(res, "feishu")
|
|
||||||
}
|
|
||||||
if c.Channels.Discord.Enabled {
|
|
||||||
res = append(res, "discord")
|
|
||||||
}
|
|
||||||
if c.Channels.MaixCam.Enabled {
|
|
||||||
res = append(res, "maixcam")
|
|
||||||
}
|
|
||||||
if c.Channels.QQ.Enabled {
|
|
||||||
res = append(res, "qq")
|
|
||||||
}
|
|
||||||
if c.Channels.DingTalk.Enabled {
|
|
||||||
res = append(res, "dingtalk")
|
|
||||||
}
|
|
||||||
if c.Channels.Slack.Enabled {
|
|
||||||
res = append(res, "slack")
|
|
||||||
}
|
|
||||||
if c.Channels.LINE.Enabled {
|
|
||||||
res = append(res, "line")
|
|
||||||
}
|
|
||||||
if c.Channels.OneBot.Enabled {
|
|
||||||
res = append(res, "onebot")
|
|
||||||
}
|
|
||||||
if c.Channels.WeCom.Enabled {
|
|
||||||
res = append(res, "wecom")
|
|
||||||
}
|
|
||||||
if c.Channels.WeComApp.Enabled {
|
|
||||||
res = append(res, "wecom_app")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add("whatsapp", c.Channels.WhatsApp.Enabled)
|
||||||
|
add("telegram", c.Channels.Telegram.Enabled)
|
||||||
|
add("feishu", c.Channels.Feishu.Enabled)
|
||||||
|
add("discord", c.Channels.Discord.Enabled)
|
||||||
|
add("maixcam", c.Channels.MaixCam.Enabled)
|
||||||
|
add("qq", c.Channels.QQ.Enabled)
|
||||||
|
add("dingtalk", c.Channels.DingTalk.Enabled)
|
||||||
|
add("slack", c.Channels.Slack.Enabled)
|
||||||
|
add("line", c.Channels.LINE.Enabled)
|
||||||
|
add("onebot", c.Channels.OneBot.Enabled)
|
||||||
|
add("wecom", c.Channels.WeCom.Enabled)
|
||||||
|
add("wecom_app", c.Channels.WeComApp.Enabled)
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,144 +137,110 @@ func GetSupportedModelNames(c *Config) []string {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSupportedProviders returns a deduplicated list of provider identifiers.
|
// Known providers and their typical credential requirements.
|
||||||
// It includes known provider fields and protocols discovered in model_list entries
|
var knownProviders = map[string]ProviderInfo{
|
||||||
// and the agents default provider if set.
|
"anthropic": {Name: "anthropic", RequiredCredentials: []string{"api_key"}, OptionalCredentials: []string{"api_base"}},
|
||||||
func GetSupportedProviders(c *Config) []string {
|
"openai": {Name: "openai", RequiredCredentials: []string{"api_key"}, OptionalCredentials: []string{"api_base"}},
|
||||||
known := []string{
|
"openrouter": {Name: "openrouter", RequiredCredentials: []string{"api_key"}, OptionalCredentials: []string{"api_base"}},
|
||||||
"anthropic", "openai", "openrouter", "groq", "zhipu", "vllm",
|
"groq": {Name: "groq", RequiredCredentials: []string{"api_key"}},
|
||||||
"gemini", "nvidia", "ollama", "moonshot", "shengsuanyun",
|
"zhipu": {Name: "zhipu", RequiredCredentials: []string{"api_key"}},
|
||||||
"deepseek", "cerebras", "volcengine", "github_copilot", "antigravity",
|
"vllm": {Name: "vllm", RequiredCredentials: []string{"api_key"}},
|
||||||
"qwen",
|
"gemini": {Name: "gemini", RequiredCredentials: []string{"api_key"}},
|
||||||
}
|
"nvidia": {Name: "nvidia", RequiredCredentials: []string{"api_key"}},
|
||||||
|
"ollama": {Name: "ollama", RequiredCredentials: []string{"api_key"}},
|
||||||
set := make(map[string]struct{})
|
"moonshot": {Name: "moonshot", RequiredCredentials: []string{"api_key"}},
|
||||||
for _, k := range known {
|
"shengsuanyun": {Name: "shengsuanyun", RequiredCredentials: []string{"api_key"}},
|
||||||
set[k] = struct{}{}
|
"deepseek": {Name: "deepseek", RequiredCredentials: []string{"api_key"}},
|
||||||
}
|
"cerebras": {Name: "cerebras", RequiredCredentials: []string{"api_key"}},
|
||||||
|
"volcengine": {Name: "volcengine", RequiredCredentials: []string{"api_key"}},
|
||||||
// Add provider from agents defaults if present
|
"github_copilot": {Name: "github_copilot", RequiredCredentials: []string{"api_key"}},
|
||||||
if c != nil && c.Agents.Defaults.Provider != "" {
|
"antigravity": {Name: "antigravity", RequiredCredentials: []string{"api_key"}},
|
||||||
set[strings.ToLower(c.Agents.Defaults.Provider)] = struct{}{}
|
"qwen": {Name: "qwen", RequiredCredentials: []string{"api_key"}},
|
||||||
}
|
|
||||||
|
|
||||||
// Discover protocols used in model_list (protocol/model format)
|
|
||||||
if c != nil {
|
|
||||||
for _, m := range c.ModelList {
|
|
||||||
if m.Model == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
p := parseProtocol(m.Model)
|
|
||||||
if p != "" {
|
|
||||||
set[p] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
res := make([]string, 0, len(set))
|
|
||||||
for k := range set {
|
|
||||||
res = append(res, k)
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetProvidersWithCredentials returns providers that have API key or API base set
|
// GetProvidersInfo returns provider metadata including required/optional fields
|
||||||
// in the legacy ProvidersConfig, as well as protocols with credentials defined
|
// and whether credentials are present in the current config.
|
||||||
// in model_list entries (ModelConfig.APIKey/APIBase).
|
func GetProvidersInfo(c *Config) []ProviderInfo {
|
||||||
func GetProvidersWithCredentials(c *Config) []string {
|
// start from known providers map
|
||||||
if c == nil {
|
res := make([]ProviderInfo, 0, len(knownProviders))
|
||||||
return nil
|
has := map[string]bool{}
|
||||||
}
|
|
||||||
set := make(map[string]struct{})
|
|
||||||
|
|
||||||
// Legacy providers
|
if c != nil {
|
||||||
|
// record legacy providers that have keys
|
||||||
if c.Providers.Anthropic.APIKey != "" || c.Providers.Anthropic.APIBase != "" {
|
if c.Providers.Anthropic.APIKey != "" || c.Providers.Anthropic.APIBase != "" {
|
||||||
set["anthropic"] = struct{}{}
|
has["anthropic"] = true
|
||||||
}
|
}
|
||||||
if c.Providers.OpenAI.APIKey != "" || c.Providers.OpenAI.APIBase != "" {
|
if c.Providers.OpenAI.APIKey != "" || c.Providers.OpenAI.APIBase != "" {
|
||||||
set["openai"] = struct{}{}
|
has["openai"] = true
|
||||||
}
|
}
|
||||||
if c.Providers.OpenRouter.APIKey != "" || c.Providers.OpenRouter.APIBase != "" {
|
if c.Providers.OpenRouter.APIKey != "" || c.Providers.OpenRouter.APIBase != "" {
|
||||||
set["openrouter"] = struct{}{}
|
has["openrouter"] = true
|
||||||
}
|
}
|
||||||
if c.Providers.Groq.APIKey != "" || c.Providers.Groq.APIBase != "" {
|
if c.Providers.Groq.APIKey != "" || c.Providers.Groq.APIBase != "" {
|
||||||
set["groq"] = struct{}{}
|
has["groq"] = true
|
||||||
}
|
}
|
||||||
if c.Providers.Zhipu.APIKey != "" || c.Providers.Zhipu.APIBase != "" {
|
if c.Providers.Zhipu.APIKey != "" || c.Providers.Zhipu.APIBase != "" {
|
||||||
set["zhipu"] = struct{}{}
|
has["zhipu"] = true
|
||||||
}
|
}
|
||||||
if c.Providers.VLLM.APIKey != "" || c.Providers.VLLM.APIBase != "" {
|
if c.Providers.VLLM.APIKey != "" || c.Providers.VLLM.APIBase != "" {
|
||||||
set["vllm"] = struct{}{}
|
has["vllm"] = true
|
||||||
}
|
}
|
||||||
if c.Providers.Gemini.APIKey != "" || c.Providers.Gemini.APIBase != "" {
|
if c.Providers.Gemini.APIKey != "" || c.Providers.Gemini.APIBase != "" {
|
||||||
set["gemini"] = struct{}{}
|
has["gemini"] = true
|
||||||
}
|
}
|
||||||
if c.Providers.Nvidia.APIKey != "" || c.Providers.Nvidia.APIBase != "" {
|
if c.Providers.Nvidia.APIKey != "" || c.Providers.Nvidia.APIBase != "" {
|
||||||
set["nvidia"] = struct{}{}
|
has["nvidia"] = true
|
||||||
}
|
}
|
||||||
if c.Providers.Ollama.APIKey != "" || c.Providers.Ollama.APIBase != "" {
|
if c.Providers.Ollama.APIKey != "" || c.Providers.Ollama.APIBase != "" {
|
||||||
set["ollama"] = struct{}{}
|
has["ollama"] = true
|
||||||
}
|
}
|
||||||
if c.Providers.Moonshot.APIKey != "" || c.Providers.Moonshot.APIBase != "" {
|
if c.Providers.Moonshot.APIKey != "" || c.Providers.Moonshot.APIBase != "" {
|
||||||
set["moonshot"] = struct{}{}
|
has["moonshot"] = true
|
||||||
}
|
}
|
||||||
if c.Providers.ShengSuanYun.APIKey != "" || c.Providers.ShengSuanYun.APIBase != "" {
|
if c.Providers.ShengSuanYun.APIKey != "" || c.Providers.ShengSuanYun.APIBase != "" {
|
||||||
set["shengsuanyun"] = struct{}{}
|
has["shengsuanyun"] = true
|
||||||
}
|
}
|
||||||
if c.Providers.DeepSeek.APIKey != "" || c.Providers.DeepSeek.APIBase != "" {
|
if c.Providers.DeepSeek.APIKey != "" || c.Providers.DeepSeek.APIBase != "" {
|
||||||
set["deepseek"] = struct{}{}
|
has["deepseek"] = true
|
||||||
}
|
}
|
||||||
if c.Providers.Cerebras.APIKey != "" || c.Providers.Cerebras.APIBase != "" {
|
if c.Providers.Cerebras.APIKey != "" || c.Providers.Cerebras.APIBase != "" {
|
||||||
set["cerebras"] = struct{}{}
|
has["cerebras"] = true
|
||||||
}
|
}
|
||||||
if c.Providers.VolcEngine.APIKey != "" || c.Providers.VolcEngine.APIBase != "" {
|
if c.Providers.VolcEngine.APIKey != "" || c.Providers.VolcEngine.APIBase != "" {
|
||||||
set["volcengine"] = struct{}{}
|
has["volcengine"] = true
|
||||||
}
|
}
|
||||||
if c.Providers.GitHubCopilot.APIKey != "" || c.Providers.GitHubCopilot.APIBase != "" {
|
if c.Providers.GitHubCopilot.APIKey != "" || c.Providers.GitHubCopilot.APIBase != "" {
|
||||||
set["github_copilot"] = struct{}{}
|
has["github_copilot"] = true
|
||||||
}
|
}
|
||||||
if c.Providers.Antigravity.APIKey != "" || c.Providers.Antigravity.APIBase != "" {
|
if c.Providers.Antigravity.APIKey != "" || c.Providers.Antigravity.APIBase != "" {
|
||||||
set["antigravity"] = struct{}{}
|
has["antigravity"] = true
|
||||||
}
|
}
|
||||||
if c.Providers.Qwen.APIKey != "" || c.Providers.Qwen.APIBase != "" {
|
if c.Providers.Qwen.APIKey != "" || c.Providers.Qwen.APIBase != "" {
|
||||||
set["qwen"] = struct{}{}
|
has["qwen"] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Model-list based providers
|
// Model-list based credentials: map model protocol -> present
|
||||||
for _, m := range c.ModelList {
|
for _, m := range c.ModelList {
|
||||||
if m.APIKey != "" || m.APIBase != "" {
|
if m.APIKey != "" || m.APIBase != "" {
|
||||||
p := parseProtocol(m.Model)
|
p := parseProtocol(m.Model)
|
||||||
if p == "" {
|
if p == "" {
|
||||||
p = "openai"
|
p = "openai"
|
||||||
}
|
}
|
||||||
set[p] = struct{}{}
|
has[p] = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res := make([]string, 0, len(set))
|
for k, info := range knownProviders {
|
||||||
for k := range set {
|
pi := info
|
||||||
res = append(res, k)
|
// if knownProviders entry didn't set optional/required copies, ensure Name set
|
||||||
|
if pi.Name == "" {
|
||||||
|
pi.Name = k
|
||||||
}
|
}
|
||||||
return res
|
if has[k] {
|
||||||
}
|
pi.HasCredentials = true
|
||||||
|
|
||||||
// GetWebTools returns the names of web tools configured (those present in Tools.Web).
|
|
||||||
func GetWebTools(c *Config) []string {
|
|
||||||
if c == nil {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
var res []string
|
res = append(res, pi)
|
||||||
if c.Tools.Web.Brave.Enabled {
|
|
||||||
res = append(res, "brave")
|
|
||||||
}
|
|
||||||
if c.Tools.Web.Tavily.Enabled {
|
|
||||||
res = append(res, "tavily")
|
|
||||||
}
|
|
||||||
if c.Tools.Web.DuckDuckGo.Enabled {
|
|
||||||
res = append(res, "duckduckgo")
|
|
||||||
}
|
|
||||||
if c.Tools.Web.Perplexity.Enabled {
|
|
||||||
res = append(res, "perplexity")
|
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue