Files
goclaw/cmd/onboard_managed.go
T
Dmitry 2810ad96f0 feat(providers): add AI/ML API preset (#1336)
Approved by github-maintain. Clean implementation of AI/ML API as branded OpenAI-compatible provider. All CI green. Closes #1325.
2026-07-03 20:23:47 +07:00

88 lines
3.1 KiB
Go

package cmd
import (
"context"
"fmt"
"log/slog"
"os"
"time"
"github.com/nextlevelbuilder/goclaw/internal/providers"
"github.com/nextlevelbuilder/goclaw/internal/store"
"github.com/nextlevelbuilder/goclaw/internal/store/pg"
)
// testPostgresConnection verifies connectivity to Postgres with a 5s timeout.
func testPostgresConnection(dsn string) error {
db, err := pg.OpenDB(dsn)
if err != nil {
return err
}
defer db.Close()
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
return db.PingContext(ctx)
}
// defaultPlaceholderProviders defines disabled placeholder providers seeded for
// UI discoverability. Users can later enable and configure them via the dashboard.
var defaultPlaceholderProviders = []store.LLMProviderData{
{Name: "aimlapi", DisplayName: "AI/ML API", ProviderType: store.ProviderAIMLAPI, APIBase: providers.AIMLAPIDefaultAPIBase, Enabled: false},
{Name: "openrouter", DisplayName: "OpenRouter", ProviderType: store.ProviderOpenRouter, APIBase: "https://openrouter.ai/api/v1", Enabled: false},
{Name: "synthetic", DisplayName: "Synthetic", ProviderType: store.ProviderOpenAICompat, APIBase: "https://api.synthetic.new/openai/v1", Enabled: false},
{Name: "alicloud-api", DisplayName: "AliCloud API", ProviderType: store.ProviderDashScope, APIBase: "https://dashscope-intl.aliyuncs.com/compatible-mode/v1", Enabled: false},
{Name: "alicloud-sub", DisplayName: "AliCloud Sub", ProviderType: store.ProviderBailian, APIBase: "https://coding-intl.dashscope.aliyuncs.com/v1", Enabled: false},
{Name: "zai", DisplayName: "Z.ai API", ProviderType: store.ProviderZai, APIBase: "https://api.z.ai/api/paas/v4", Enabled: false},
{Name: "zai-coding", DisplayName: "Z.ai Coding Plan", ProviderType: store.ProviderZaiCoding, APIBase: "https://api.z.ai/api/coding/paas/v4", Enabled: false},
}
// seedOnboardPlaceholders opens a PG store and seeds disabled placeholder providers
// so they appear in the UI for easy configuration.
func seedOnboardPlaceholders(dsn string) error {
storeCfg := store.StoreConfig{
PostgresDSN: dsn,
EncryptionKey: os.Getenv("GOCLAW_ENCRYPTION_KEY"),
}
stores, err := pg.NewPGStores(storeCfg)
if err != nil {
return fmt.Errorf("open PG stores: %w", err)
}
if stores.Providers == nil {
return nil
}
ctx := context.Background()
// Build a set of existing api_base values to avoid overwriting user-configured entries.
existing, err := stores.Providers.ListProviders(ctx)
if err != nil {
return fmt.Errorf("list providers: %w", err)
}
existingBases := make(map[string]bool, len(existing))
for _, p := range existing {
if p.APIBase != "" {
existingBases[p.APIBase] = true
}
}
seeded := 0
for _, ph := range defaultPlaceholderProviders {
if ph.APIBase != "" && existingBases[ph.APIBase] {
continue
}
p := ph // copy
if err := stores.Providers.CreateProvider(ctx, &p); err != nil {
slog.Debug("seed placeholder skipped (may already exist)", "name", ph.Name, "error", err)
continue
}
seeded++
}
if seeded > 0 {
slog.Info("seeded placeholder providers", "count", seeded)
}
return nil
}