diff --git a/server/internal/api/web/pool_keys.go b/server/internal/api/web/pool_keys.go index 3630095..4e9dad1 100644 --- a/server/internal/api/web/pool_keys.go +++ b/server/internal/api/web/pool_keys.go @@ -28,11 +28,12 @@ func (s *Server) handleListProviders(w http.ResponseWriter, r *http.Request) { out := make([]map[string]any, 0, len(rows)) for _, p := range rows { out = append(out, map[string]any{ - "id": p.ID, - "type": p.Type, - "name": p.Name, - "active": p.Active == 1, - "is_free": p.IsFree == 1, + "id": p.ID, + "type": p.Type, + "name": p.Name, + "base_url": p.BaseUrl, + "active": p.Active == 1, + "is_free": p.IsFree == 1, }) } writeJSON(w, 200, out) @@ -81,6 +82,7 @@ func (s *Server) handleCreateProvider(w http.ResponseWriter, r *http.Request) { return } + _ = s.Registry.Reload(r.Context()) writeJSON(w, 201, map[string]any{ "id": req.ID, "type": req.Type, @@ -154,6 +156,7 @@ func (s *Server) handleUpdateProvider(w http.ResponseWriter, r *http.Request) { ID: id, }) + _ = s.Registry.Reload(r.Context()) writeJSON(w, 200, map[string]any{"ok": true}) } @@ -177,6 +180,7 @@ func (s *Server) handleDeleteProvider(w http.ResponseWriter, r *http.Request) { return } + _ = s.Registry.Reload(r.Context()) writeJSON(w, 200, map[string]any{"ok": true}) } diff --git a/server/internal/provider/registry/registry.go b/server/internal/provider/registry/registry.go index 00cdbf6..8e7c5f9 100644 --- a/server/internal/provider/registry/registry.go +++ b/server/internal/provider/registry/registry.go @@ -44,6 +44,7 @@ type ProviderConfig struct { type Registry struct { mu sync.RWMutex providers map[string]ProviderConfig + q *store.Queries // set when loaded from DB, enables Reload } // New creates a registry from a list of provider configs. @@ -73,7 +74,37 @@ func LoadFromDB(ctx context.Context, q *store.Queries) (*Registry, error) { // TODO: parse config_json into map when needed }) } - return New(configs), nil + m := make(map[string]ProviderConfig, len(configs)) + for _, c := range configs { + m[c.ID] = c + } + return &Registry{providers: m, q: q}, nil +} + +// Reload refreshes the registry from the database. Safe to call concurrently. +func (r *Registry) Reload(ctx context.Context) error { + if r.q == nil { + return fmt.Errorf("registry not loaded from DB") + } + rows, err := r.q.ListActiveProviders(ctx) + if err != nil { + return fmt.Errorf("list providers: %w", err) + } + m := make(map[string]ProviderConfig, len(rows)) + for _, row := range rows { + m[row.ID] = ProviderConfig{ + ID: row.ID, + Type: ProviderType(row.Type), + Name: row.Name, + BaseURL: row.BaseUrl, + Active: row.Active == 1, + IsFree: row.IsFree == 1, + } + } + r.mu.Lock() + r.providers = m + r.mu.Unlock() + return nil } // Get returns the config for a provider ID. diff --git a/web/src/lib/api.ts b/web/src/lib/api.ts index 3a0ac3c..ba83c17 100644 --- a/web/src/lib/api.ts +++ b/web/src/lib/api.ts @@ -261,6 +261,7 @@ export interface Provider { id: string; type: string; name: string; + base_url: string; active: boolean; is_free: boolean; } @@ -270,7 +271,7 @@ export const createProvider = (id: string, type: string, name: string, baseUrl: export const updateProvider = (id: string, updates: { type?: string; name?: string; base_url?: string; active?: boolean; is_free?: boolean }) => api.patch(`/api/providers/${id}`, updates); export const deleteProvider = (id: string) => - api.delete(`/api/providers/${id}`); + api.del(`/api/providers/${id}`); export interface PoolKeyProbe { provider_id: string; diff --git a/web/src/routes/admin/providers/+page.svelte b/web/src/routes/admin/providers/+page.svelte index 28921ab..5bb4083 100644 --- a/web/src/routes/admin/providers/+page.svelte +++ b/web/src/routes/admin/providers/+page.svelte @@ -76,7 +76,7 @@ editingId = p.id; editName = p.name; editType = p.type; - editBaseUrl = (p as any).base_url ?? ''; + editBaseUrl = p.base_url ?? ''; editIsFree = p.is_free; }