Enable bundled OpenRouter configuration by default

This commit is contained in:
2026-11-03 15:30:47 +00:00
parent 2c50eca033
commit 6f57f2f30a
7 changed files with 155 additions and 9 deletions

View File

@@ -0,0 +1,124 @@
package promptkit_test
import (
"context"
"errors"
"net/http"
"reflect"
"strings"
"testing"
"go.maximumdirect.net/configkit"
"go.maximumdirect.net/promptkit"
)
type rejectBundleTransport struct{}
func (rejectBundleTransport) RoundTrip(*http.Request) (*http.Response, error) {
return nil, errors.New("unexpected HTTP request")
}
func TestBundledOpenRouterOptionsAndInventory(t *testing.T) {
t.Setenv("OPENROUTER_API_KEY", "")
for _, test := range []struct {
name string
options []promptkit.Option
enabled bool
}{
{"default", nil, true}, {"enabled", []promptkit.Option{promptkit.WithBundledOpenRouter(true)}, true},
{"disabled", []promptkit.Option{promptkit.WithBundledOpenRouter(false)}, false},
{"last disables", []promptkit.Option{promptkit.WithBundledOpenRouter(true), promptkit.WithBundledOpenRouter(false)}, false},
{"last enables", []promptkit.Option{promptkit.WithBundledOpenRouter(false), promptkit.WithBundledOpenRouter(true)}, true},
} {
t.Run(test.name, func(t *testing.T) {
engine, err := promptkit.NewEngine(promptkit.Config{HTTPClient: &http.Client{Transport: rejectBundleTransport{}}}, test.options...)
if err != nil {
t.Fatal(err)
}
profiles, err := engine.ListProfiles(context.Background())
if err != nil {
t.Fatal(err)
}
backends, err := engine.ListBackends(context.Background())
if err != nil {
t.Fatal(err)
}
prompts, err := engine.ListPrompts(context.Background())
if err != nil {
t.Fatal(err)
}
collections, err := engine.ListCollections(context.Background())
if err != nil {
t.Fatal(err)
}
want := 0
if test.enabled {
want = 17
}
if len(profiles) != want || len(backends) != boolCount(test.enabled) || len(prompts) != 0 || len(collections) != 0 {
t.Fatalf("inventories: %v %v %v %v", profiles, backends, prompts, collections)
}
if test.enabled {
wantProfiles := []string{"auto", "auto-high", "auto-low", "auto-max", "auto-medium", "auto-xhigh", "claude-fable-latest", "claude-haiku-latest", "claude-opus-latest", "claude-sonnet-latest", "free", "gemini-flash-latest", "gemini-pro-latest", "gpt-astra-latest", "gpt-luna-latest", "gpt-sol-latest", "gpt-terra-latest"}
if !reflect.DeepEqual(profiles, wantProfiles) || !reflect.DeepEqual(backends, []string{"openrouter"}) {
t.Fatalf("bundle inventory: %v %v", profiles, backends)
}
for id, model := range map[string]string{"auto": "openrouter/auto", "auto-max": "openrouter/auto", "gpt-luna-latest": "~openai/gpt-luna-latest", "free": "openrouter/free"} {
profile, err := engine.InspectProfile(context.Background(), id)
if err != nil || profile.EffectiveModelParams.Model != model || profile.EffectiveModelParams.BackendID != "openrouter" {
t.Fatalf("profile %s = %+v, %v", id, profile, err)
}
}
view, err := engine.InspectConfiguration()
if err != nil {
t.Fatal(err)
}
if !strings.Contains(fmtSources(view.Sources()), "Promptkit bundled OpenRouter") {
t.Fatal("bundle source missing")
}
if explanation, found := view.Explain(configkit.Keys("backends").Index(0).Key("endpoint")); !found || !strings.Contains(explanation.Effective.YAML, "https://openrouter.ai/api/v1") || len(explanation.History) == 0 {
t.Fatalf("bundle explanation = %+v", explanation)
}
}
})
}
}
func boolCount(value bool) int {
if value {
return 1
}
return 0
}
func fmtSources(sources []configkit.SourceInfo) string {
var b strings.Builder
for _, source := range sources {
b.WriteString(source.Label)
}
return b.String()
}
func TestBundlePreservesCallerUnderlayBackingArray(t *testing.T) {
source := configkit.Mapping("caller", map[string]any{"profiles": []any{map[string]any{"id": "caller", "model": "model"}}})
groups := make([]configkit.Underlay, 1, 2)
groups[0] = configkit.Underlay{Inputs: []configkit.Input{{Source: source}}}
before := append([]configkit.Underlay(nil), groups...)
if _, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{Underlays: groups}}); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(groups, before) || !reflect.DeepEqual(groups[:2][1], configkit.Underlay{}) {
t.Fatal("caller underlays were modified")
}
}
func TestDisabledBundleKeepsCallerOpenRouter(t *testing.T) {
input := configkit.Input{Source: configkit.Mapping("caller", map[string]any{"backends": []any{map[string]any{"id": "openrouter", "endpoint": "https://local.invalid/v1"}}})}
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &input}}, promptkit.WithBundledOpenRouter(false))
if err != nil {
t.Fatal(err)
}
backends, err := engine.ListBackends(context.Background())
if err != nil || !reflect.DeepEqual(backends, []string{"openrouter"}) {
t.Fatalf("backends = %v, %v", backends, err)
}
}

View File

@@ -42,7 +42,7 @@ func TestConfigurationInspectionReportsLiteralKeysAndRedactedHistory(t *testing.
}},
})}}},
},
}})
}}, promptkit.WithBundledOpenRouter(false))
if err != nil {
t.Fatalf("construct layered engine: %v", err)
}

View File

@@ -149,6 +149,10 @@ Scope: facade/internal options, assembly, and default/disabled contract tests.
Validation: focused construction/listing/inspection tests, then
`go test ./internal/engine ./...` when intermediate wiring is coherent.
Completion: engine construction installs the bundle by default, with an
ordered opt-out option and a copied underlay slice. Facade contracts and the
full Go suite pass with Go 1.27.0.
## Stage 3: Protect Composition And Application Control
Scope: focused real-loader integration tests through the facade.

View File

@@ -154,6 +154,15 @@ type engineOptions struct {
internal internalengine.Options
}
// WithBundledOpenRouter enables or disables the built-in OpenRouter underlay.
// It is enabled by default; when repeated, the last option wins.
func WithBundledOpenRouter(enabled bool) Option {
return optionFunc(func(options *engineOptions) error {
options.internal.SetBundledOpenRouter(enabled)
return nil
})
}
// WithLLMClient replaces the built-in model client used by [Engine.Run] and
// [Engine.RunPrepared].
//

View File

@@ -41,13 +41,17 @@ type ConfigurationSources struct {
// Options collects construction choices from the public facade.
type Options struct {
llmClient llm.Client
artifactReader artifact.Reader
validator validate.Validator
validatorSource bool
artifactSource bool
llmClient llm.Client
artifactReader artifact.Reader
validator validate.Validator
validatorSource bool
artifactSource bool
disableBundledOpenRouter bool
}
// SetBundledOpenRouter selects whether the built-in OpenRouter source is installed.
func (o *Options) SetBundledOpenRouter(enabled bool) { o.disableBundledOpenRouter = !enabled }
// SetLLMClient selects the client collaborator for one engine.
func (o *Options) SetLLMClient(client llm.Client) { o.llmClient = client }
@@ -124,6 +128,11 @@ func New(cfg Config, options Options) (*Engine, error) {
return nil, err
}
underlays := cfg.Sources.Underlays
if !options.disableBundledOpenRouter {
underlays = make([]configkit.Underlay, 1, len(cfg.Sources.Underlays)+1)
underlays[0] = configuration.BundledOpenRouterUnderlay()
underlays = append(underlays, cfg.Sources.Underlays...)
}
main := configkit.Input{Source: configkit.NoSource()}
if cfg.Sources.Main != nil {
main = *cfg.Sources.Main

View File

@@ -226,7 +226,7 @@ func newNamespaceListingEngine(t *testing.T) *promptkit.Engine {
"profiles": []any{map[string]any{"id": "root-profile", "backend": "root-backend", "model": "root-model"}},
"prompts": []any{listingContractPrompt("root-prompt")},
})}
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &input}})
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &input}}, promptkit.WithBundledOpenRouter(false))
if err != nil {
var loadErr *configkit.LoadError
if errors.As(err, &loadErr) {
@@ -464,7 +464,7 @@ func TestListIdentitiesUseEffectiveLayeredMembership(t *testing.T) {
}
func TestListIdentitiesEmptyEffectiveConfiguration(t *testing.T) {
engine, err := promptkit.NewEngine(promptkit.Config{})
engine, err := promptkit.NewEngine(promptkit.Config{}, promptkit.WithBundledOpenRouter(false))
if err != nil {
t.Fatal(err)
}

View File

@@ -23,7 +23,7 @@ func TestProgrammaticSourcesPreserveOrderAndRejectDuplicates(t *testing.T) {
params["visible"] = "changed"
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{
Underlays: []configkit.Underlay{{Inputs: []configkit.Input{{Source: backendSource}, {Source: profileSource}}}},
}})
}}, promptkit.WithBundledOpenRouter(false))
if err != nil {
t.Fatal(err)
}