package config import ( "fmt" "os" "strings" "nub/internal/llm" "nub/internal/llm/registry" ) // Resolved ist alles, was der OpenAI-Adapter zum Verbindungsaufbau braucht. type Resolved struct { Model string BaseURL string APIKey string Caps llm.Caps } // Resolve löst den in Model.Endpoint referenzierten Endpoint auf, ermittelt // den API-Key (inkl. "env:VAR"-Indirektion) und merged Caps aus der // Modell-Registry (E-10) mit den Endpoint-Overrides. func Resolve(cfg Config) (Resolved, error) { var ep *Endpoint for i := range cfg.Endpoints { if cfg.Endpoints[i].Name == cfg.Model.Endpoint { ep = &cfg.Endpoints[i] break } } if ep == nil { return Resolved{}, fmt.Errorf("config: model.endpoint %q referenziert keinen konfigurierten [[endpoint]]", cfg.Model.Endpoint) } key := resolveAPIKey(ep.APIKey) if key == "" && !isLocalEndpoint(ep.BaseURL) { return Resolved{}, fmt.Errorf("config: kein API-Key für Endpoint %q — in der Config setzen oder NUB_API_KEY/OPENAI_API_KEY exportieren", ep.Name) } caps := registry.Apply(registry.DefaultCaps(cfg.Model.Default), ep.Caps) return Resolved{ Model: cfg.Model.Default, BaseURL: ep.BaseURL, APIKey: key, Caps: caps, }, nil } func resolveAPIKey(v string) string { if rest, ok := strings.CutPrefix(v, "env:"); ok { return os.Getenv(rest) } if v == "none" { return "" } return v } func isLocalEndpoint(baseURL string) bool { return strings.HasPrefix(baseURL, "http://") }