// Package handlers — provider_resolver_adapter.go // // v0.29.1 CS2: Adapter that satisfies sandbox.ProviderResolver using // ResolveProviderConfig + providers.Get. Avoids circular dependency // (sandbox → handlers → sandbox) by having handlers implement the // sandbox-defined interface. package handlers import ( "context" "fmt" "git.gobha.me/xcaliber/chat-switchboard/crypto" "git.gobha.me/xcaliber/chat-switchboard/providers" "git.gobha.me/xcaliber/chat-switchboard/sandbox" "git.gobha.me/xcaliber/chat-switchboard/store" ) // ProviderResolverAdapter implements sandbox.ProviderResolver using // the existing ResolveProviderConfig function and provider registry. type ProviderResolverAdapter struct { stores store.Stores vault *crypto.KeyResolver } // NewProviderResolverAdapter creates an adapter for Starlark provider resolution. func NewProviderResolverAdapter(stores store.Stores, vault *crypto.KeyResolver) *ProviderResolverAdapter { return &ProviderResolverAdapter{stores: stores, vault: vault} } // Resolve satisfies sandbox.ProviderResolver. It resolves the provider // config via the BYOK chain and returns the provider instance + config. func (a *ProviderResolverAdapter) Resolve(ctx context.Context, userID, channelID, providerConfigID, model string) (*sandbox.ProviderResolution, error) { res, err := ResolveProviderConfig(a.stores, a.vault, userID, channelID, providerConfigID, model) if err != nil { return nil, err } provider, err := providers.Get(res.ProviderID) if err != nil { return nil, fmt.Errorf("provider unavailable: %w", err) } return &sandbox.ProviderResolution{ Provider: provider, Config: res.Config, ProviderID: res.ProviderID, Model: res.Model, ConfigID: res.ConfigID, }, nil }