picoclaw/cmd/picoclaw/internal/status/helpers.go
lxowalle 77b0c43392
refactor: support explicit provider field in model list entries (#2609)
* refactor: support explicit model list providers

* fix(web): preserve explicit model providers

* fix(web): preserve legacy provider prefixes on model updates

fix(models): normalize explicit provider-prefixed ids

fix(api): preserve legacy model updates across providers

fix(agent): preserve config identity for explicit provider refs

* fix ci
2026-04-22 11:28:47 +08:00

145 lines
4 KiB
Go

package status
import (
"fmt"
"os"
"github.com/sipeed/picoclaw/cmd/picoclaw/internal"
"github.com/sipeed/picoclaw/cmd/picoclaw/internal/cliui"
"github.com/sipeed/picoclaw/pkg/auth"
"github.com/sipeed/picoclaw/pkg/config"
"github.com/sipeed/picoclaw/pkg/providers"
)
func statusCmd() {
cfg, err := internal.LoadConfig()
if err != nil {
fmt.Printf("Error loading config: %v\n", err)
return
}
configPath := internal.GetConfigPath()
build, _ := config.FormatBuildInfo()
_, configStatErr := os.Stat(configPath)
configOK := configStatErr == nil
workspace := cfg.WorkspacePath()
_, wsErr := os.Stat(workspace)
wsOK := wsErr == nil
report := cliui.StatusReport{
Logo: internal.Logo,
Version: config.FormatVersion(),
Build: build,
ConfigPath: configPath,
ConfigOK: configOK,
WorkspacePath: workspace,
WorkspaceOK: wsOK,
Model: cfg.Agents.Defaults.GetModelName(),
}
if configOK {
// PicoClaw moved to a model-centric configuration (model_list). Status should
// not depend on a legacy cfg.Providers field (which may not exist under some
// build tags). We infer provider availability from model_list entries.
hasProtocolKey := func(protocol string) bool {
want := providers.NormalizeProvider(protocol)
for _, m := range cfg.ModelList {
if m == nil {
continue
}
got, _ := providers.ExtractProtocol(m)
if got == want && m.APIKey() != "" {
return true
}
}
return false
}
findLocalModelBase := func(modelName string) (string, bool) {
for _, m := range cfg.ModelList {
if m == nil {
continue
}
if m.ModelName == modelName && m.APIBase != "" {
return m.APIBase, true
}
}
return "", false
}
findProtocolBase := func(protocol string) (string, bool) {
want := providers.NormalizeProvider(protocol)
for _, m := range cfg.ModelList {
if m == nil {
continue
}
got, _ := providers.ExtractProtocol(m)
if got == want && m.APIBase != "" {
return m.APIBase, true
}
}
return "", false
}
hasOpenRouter := hasProtocolKey("openrouter")
hasAnthropic := hasProtocolKey("anthropic")
hasOpenAI := hasProtocolKey("openai")
hasGemini := hasProtocolKey("gemini")
hasZhipu := hasProtocolKey("zhipu")
hasQwen := hasProtocolKey("qwen")
hasGroq := hasProtocolKey("groq")
hasMoonshot := hasProtocolKey("moonshot")
hasDeepSeek := hasProtocolKey("deepseek")
hasVolcEngine := hasProtocolKey("volcengine")
hasNvidia := hasProtocolKey("nvidia")
// Local endpoints: allow both the special reserved name and protocol-based entries.
vllmBase, hasVLLM := findLocalModelBase("local-model")
if !hasVLLM {
vllmBase, hasVLLM = findProtocolBase("vllm")
}
ollamaBase, hasOllama := findProtocolBase("ollama")
val := func(enabled bool, extra ...string) string {
if enabled {
if len(extra) > 0 && extra[0] != "" {
return "✓ " + extra[0]
}
return "✓"
}
return "not set"
}
report.Providers = []cliui.ProviderRow{
{Name: "OpenRouter API", Val: val(hasOpenRouter)},
{Name: "Anthropic API", Val: val(hasAnthropic)},
{Name: "OpenAI API", Val: val(hasOpenAI)},
{Name: "Gemini API", Val: val(hasGemini)},
{Name: "Zhipu API", Val: val(hasZhipu)},
{Name: "Qwen API", Val: val(hasQwen)},
{Name: "Groq API", Val: val(hasGroq)},
{Name: "Moonshot API", Val: val(hasMoonshot)},
{Name: "DeepSeek API", Val: val(hasDeepSeek)},
{Name: "VolcEngine API", Val: val(hasVolcEngine)},
{Name: "Nvidia API", Val: val(hasNvidia)},
{Name: "vLLM / local", Val: val(hasVLLM, vllmBase)},
{Name: "Ollama", Val: val(hasOllama, ollamaBase)},
}
store, _ := auth.LoadStore()
if store != nil && len(store.Credentials) > 0 {
for provider, cred := range store.Credentials {
st := "authenticated"
if cred.IsExpired() {
st = "expired"
} else if cred.NeedsRefresh() {
st = "needs refresh"
}
report.OAuthLines = append(report.OAuthLines,
fmt.Sprintf("%s (%s): %s", provider, cred.AuthMethod, st))
}
}
}
cliui.PrintStatus(report)
}