package promptkit import ( "gitea.maximumdirect.net/eric/ConfigKit" "gitea.maximumdirect.net/eric/promptkit/internal/backend" ) // BackendOpenRouter is the conventional ID for an OpenRouter backend. const BackendOpenRouter = backend.OpenRouterID // BackendRakestrawHome is the conventional ID for a Rakestrawhome backend. const BackendRakestrawHome = backend.RakestrawHomeID // BackendLocal is a conventional ID for a caller-configured local backend. const BackendLocal = "local" // BackendConfig is a presence-aware convenience value for a keyed backend // definition. Nil pointer fields are omitted, while non-nil pointers preserve // explicit zero or blank values. A nil ExtraParams map is omitted; a non-nil // empty map supplies an empty mapping. A nil SmokeTests pointer is omitted; a // non-nil pointer supplies a smoke_tests mapping. Use raw ConfigKit Mapping // inputs for explicit null. BackendConfig has no stable JSON representation. type BackendConfig struct { // Endpoint is the required absolute HTTP(S) base URL after all layers merge. Endpoint *string // APIKeyEnv optionally names an environment variable, not a credential. APIKeyEnv *string // ConcurrencyLimit is zero for unlimited generation; negative is invalid. ConcurrencyLimit *int // QueueCapacity defaults to 1024 for positive concurrency when omitted. // An explicit value, including zero, requires positive concurrency. QueueCapacity *int // ExtraParams supplies JSON-compatible provider request defaults. ExtraParams map[string]any // SmokeTests supplies optional diagnostic defaults and HTTP probe settings. SmokeTests *BackendSmokeTestConfig } // BackendSmokeTestConfig contains optional diagnostic settings associated with // a backend. Nil nested fields are omitted by BackendSource. type BackendSmokeTestConfig struct { // DefaultProfile is the exact profile ID selected as the backend's // diagnostic inference default. A supplied value must not be blank; the ID // is resolved only when that default is selected. DefaultProfile *string // Reachability optionally selects a full HTTP destination for reachability // diagnostics. A nil endpoint uses the effective backend endpoint. Reachability *ReachabilityProbeConfig // Authentication optionally declares a named authentication diagnostic. // A supplied object requires Kind. Authentication *AuthenticationProbeConfig } // ReachabilityProbeConfig configures an optional reachability destination. type ReachabilityProbeConfig struct { // Endpoint is an absolute HTTP(S) URL, including any desired path or query. // Nil selects the effective backend endpoint; an explicit blank value is // invalid. Endpoint *string } // AuthenticationProbeConfig configures an optional named authentication // diagnostic. type AuthenticationProbeConfig struct { // Kind selects the authentication adapter. Supported values are "none" and // "openrouter_key"; surrounding whitespace and case are normalized. Kind *string // Endpoint is an absolute HTTP(S) URL, including any desired path or query. // Nil selects the adapter's backend-relative destination; an explicit blank // value is invalid. Endpoint *string } // BackendSource creates a labeled ConfigKit mapping from keyed backend values. // It encodes fields without validating them; NewEngine validates the final // effective configuration after all selected source layers are combined. // Mapping captures a copy of supported input values at creation; unsupported // values fail when the source is loaded. func BackendSource(label string, backends map[string]BackendConfig) configkit.Source { definitions := make(map[string]any, len(backends)) for id, config := range backends { fields := make(map[string]any) if config.Endpoint != nil { fields["endpoint"] = *config.Endpoint } if config.APIKeyEnv != nil { fields["api_key_env"] = *config.APIKeyEnv } if config.ConcurrencyLimit != nil { fields["concurrency_limit"] = *config.ConcurrencyLimit } if config.QueueCapacity != nil { fields["queue_capacity"] = *config.QueueCapacity } if config.ExtraParams != nil { fields["extra_params"] = providerMapForMapping(config.ExtraParams) } if config.SmokeTests != nil { smokeTests := make(map[string]any) if config.SmokeTests.DefaultProfile != nil { smokeTests["default_profile"] = *config.SmokeTests.DefaultProfile } if config.SmokeTests.Reachability != nil { reachability := make(map[string]any) if config.SmokeTests.Reachability.Endpoint != nil { reachability["endpoint"] = *config.SmokeTests.Reachability.Endpoint } smokeTests["reachability"] = reachability } if config.SmokeTests.Authentication != nil { authentication := make(map[string]any) if config.SmokeTests.Authentication.Kind != nil { authentication["kind"] = *config.SmokeTests.Authentication.Kind } if config.SmokeTests.Authentication.Endpoint != nil { authentication["endpoint"] = *config.SmokeTests.Authentication.Endpoint } smokeTests["authentication"] = authentication } fields["smoke_tests"] = smokeTests } definitions[id] = fields } return configkit.Mapping(label, map[string]any{"backends": definitions}) } // LocalBackend supplies endpoint and concurrency pointers for a caller-chosen // backend ID; it does not select an ID or validate either value. func LocalBackend(endpoint string, concurrencyLimit int) BackendConfig { return BackendConfig{Endpoint: &endpoint, ConcurrencyLimit: &concurrencyLimit} }