opencode-provider-switch/internal/cli/doctor.go

74 lines
2.4 KiB
Go

package cli
import (
"fmt"
"github.com/spf13/cobra"
"github.com/anomalyco/opencode-provider-switch/internal/opencode"
)
func newDoctorCmd() *cobra.Command {
return &cobra.Command{
Use: "doctor",
Short: "Validate olpx config (static checks, no upstream requests)",
Long: `doctor performs static validation for local olpx config and the expected
OpenCode sync result.
It loads local olpx config, checks alias/provider consistency, resolves the
default OpenCode sync target, and validates what provider.olpx would look like
there. It does not send any real requests to upstream providers and does not
consume model quota.
Run doctor before opencode sync or serve whenever you changed providers,
aliases, or local server settings.`,
Example: ` olpx doctor
olpx --config /path/to/config.json doctor`,
RunE: func(cmd *cobra.Command, args []string) error {
cfg, err := loadCfg()
if err != nil {
return err
}
issues := cfg.Validate()
path, existed := opencode.ResolveGlobalConfigPath()
raw, err := opencode.Load(path)
if err != nil {
issues = append(issues, fmt.Errorf("load opencode config target: %w", err))
} else {
aliasNames := cfg.AvailableAliasNames()
baseURL := fmt.Sprintf("http://%s:%d/v1", cfg.Server.Host, cfg.Server.Port)
opencode.EnsureOLPXProvider(raw, baseURL, cfg.Server.APIKey, aliasNames)
if err := opencode.ValidateOLPXProvider(raw, baseURL, cfg.Server.APIKey, aliasNames); err != nil {
issues = append(issues, fmt.Errorf("opencode provider.olpx invalid: %w", err))
}
}
ok := len(issues) == 0
if ok {
fmt.Fprintf(cmd.OutOrStdout(), "✓ config loaded: %s\n", cfg.Path())
} else {
fmt.Fprintf(cmd.OutOrStdout(), "✗ config has %d issue(s):\n", len(issues))
for _, e := range issues {
fmt.Fprintf(cmd.OutOrStdout(), " - %s\n", e)
}
}
fmt.Fprintf(cmd.OutOrStdout(), " providers: %d\n", len(cfg.Providers))
fmt.Fprintf(cmd.OutOrStdout(), " aliases: %d\n", len(cfg.Aliases))
// Preview resolved opencode config target
marker := "(will be created)"
if existed {
marker = "(exists)"
}
fmt.Fprintf(cmd.OutOrStdout(), " opencode config target: %s %s\n", path, marker)
fmt.Fprintf(cmd.OutOrStdout(), " provider.olpx preview: valid=%v\n", ok)
fmt.Fprintf(cmd.OutOrStdout(), " proxy bind: %s:%d\n", cfg.Server.Host, cfg.Server.Port)
if !ok {
return fmt.Errorf("%d config issue(s)", len(issues))
}
return nil
},
}
}