package promptkit import ( "gitea.maximumdirect.net/eric/promptkit/internal/backend" "gitea.maximumdirect.net/eric/promptkit/internal/domain" ) // BackendOpenRouter identifies Promptkit's built-in OpenRouter backend. const BackendOpenRouter = backend.OpenRouterID // Backend configures one engine-scoped OpenAI-compatible backend. // // Backend has no stable JSON representation. Use keyed literals so additions // to this configuration value do not break source compatibility. type Backend struct { // ID is the stable, case-sensitive registry key. NewEngine trims it and // requires a non-blank value. BackendOpenRouter is reserved. ID string // Endpoint is the OpenAI-compatible base endpoint. NewEngine trims it and // requires an absolute HTTP or HTTPS URL with a host and without user // information, a query string, or a fragment. Paths are allowed. Endpoint string // APIKeyEnv optionally names the environment variable containing the API // key. NewEngine trims it and requires the portable form // [A-Za-z_][A-Za-z0-9_]*. Store only the name, never a credential value. APIKeyEnv string // ExtraParams contains backend-wide request defaults. Values must be // JSON-compatible, finite, acyclic, and keyed by non-empty strings. Keys // must not be model, session_id, messages, temperature, max_tokens, top_p, // service_tier, reasoning_effort, or response_format. An empty map supplies // no defaults. NewEngine deeply copies the map. ExtraParams map[string]any } // WithBackend adds one Backend registration to the constructed Engine. // // Registrations accumulate in option order. Every normalized ID must be unique // across consumer registrations and built-ins; a duplicate or invalid // definition makes NewEngine fail with ErrInvalidConfig. In particular, // BackendOpenRouter cannot be replaced. The immutable registration is scoped // to the resulting Engine and cannot be enumerated, replaced, removed, or // mutated after construction. WithBackend does not install package-global // state. func WithBackend(backend Backend) Option { return optionFunc(func(options *engineOptions) error { options.backends = append(options.backends, domain.Backend{ ID: backend.ID, Endpoint: backend.Endpoint, APIKeyEnv: backend.APIKeyEnv, ExtraParams: backend.ExtraParams, }) return nil }) }