Update public configuration and inventory contracts

This commit is contained in:
2026-11-02 12:50:58 +00:00
parent 682cb84c82
commit 6b8eefd18b
7 changed files with 89 additions and 98 deletions

View File

@@ -40,7 +40,7 @@ func TestCollectionInputLoadsNativeImportsAndLaterOverride(t *testing.T) {
if err := os.WriteFile(mainPath, []byte("config:\n imports:\n - path: defaults.yaml\n required: true\n"), 0o600); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(defaultsPath, []byte("prompts:\n greeting:\n version: imported\n messages:\n - role: user\n content: Hello\n output:\n format: text\n validation_mode: none\n"), 0o600); err != nil {
if err := os.WriteFile(defaultsPath, []byte("prompts:\n - id: greeting\n messages:\n - role: user\n content: Hello\n output:\n format: text\n validation_mode: none\n"), 0o600); err != nil {
t.Fatal(err)
}
input, err := promptkit.CollectionInput("docs", configkit.File(mainPath))
@@ -50,7 +50,7 @@ func TestCollectionInputLoadsNativeImportsAndLaterOverride(t *testing.T) {
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{
Underlays: []configkit.Underlay{{Inputs: []configkit.Input{input}}},
Main: &configkit.Input{
Source: configkit.Mapping("later collection override", map[string]any{"prompts": map[string]any{"greeting": map[string]any{"version": "overridden"}}}),
Source: configkit.Mapping("later collection override", map[string]any{"prompts": []any{map[string]any{"id": "greeting", "inputs": []any{map[string]any{"name": "overridden"}}, "messages": []any{map[string]any{"role": "user", "content": "Updated"}}, "output": map[string]any{"format": "text", "validation_mode": "none"}}}}),
Destination: configkit.Keys("collections", "docs"),
},
}})
@@ -58,7 +58,7 @@ func TestCollectionInputLoadsNativeImportsAndLaterOverride(t *testing.T) {
t.Fatalf("construct engine with native collection import: %v", err)
}
inspection, err := engine.InspectPrompt(context.Background(), "docs/greeting")
if err != nil || inspection.PromptVersion == nil || *inspection.PromptVersion != "overridden" {
if err != nil || inspection.PromptID != "docs/greeting" || len(inspection.Inputs) != 1 || inspection.Inputs[0].Name != "overridden" {
t.Fatalf("inspect imported and overlaid prompt = (%+v, %v)", inspection, err)
}
}
@@ -66,7 +66,7 @@ func TestCollectionInputLoadsNativeImportsAndLaterOverride(t *testing.T) {
func TestCollectionInputLoadsEmbeddedImportsAndLaterOverride(t *testing.T) {
files := fstest.MapFS{
"collection.yaml": {Data: []byte("config:\n imports:\n - path: defaults.yaml\n required: true\n")},
"defaults.yaml": {Data: []byte("prompts:\n greeting:\n version: imported\n messages:\n - role: user\n content: Hello\n output:\n format: text\n validation_mode: none\n")},
"defaults.yaml": {Data: []byte("prompts:\n - id: greeting\n messages:\n - role: user\n content: Hello\n output:\n format: text\n validation_mode: none\n")},
}
filesystem := configkit.NewFilesystem("embedded collection", files)
input, err := promptkit.CollectionInput("docs", filesystem.File("collection.yaml"))
@@ -77,7 +77,7 @@ func TestCollectionInputLoadsEmbeddedImportsAndLaterOverride(t *testing.T) {
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{
Underlays: []configkit.Underlay{{Inputs: []configkit.Input{input}}},
Main: &configkit.Input{
Source: configkit.Mapping("later collection override", map[string]any{"prompts": map[string]any{"greeting": map[string]any{"version": "overridden"}}}),
Source: configkit.Mapping("later collection override", map[string]any{"prompts": []any{map[string]any{"id": "greeting", "inputs": []any{map[string]any{"name": "overridden"}}, "messages": []any{map[string]any{"role": "user", "content": "Updated"}}, "output": map[string]any{"format": "text", "validation_mode": "none"}}}}),
Destination: configkit.Keys("collections", "docs"),
},
}})
@@ -85,7 +85,7 @@ func TestCollectionInputLoadsEmbeddedImportsAndLaterOverride(t *testing.T) {
t.Fatalf("construct engine with embedded collection import: %v", err)
}
inspection, err := engine.InspectPrompt(context.Background(), "docs/greeting")
if err != nil || inspection.PromptVersion == nil || *inspection.PromptVersion != "overridden" {
if err != nil || inspection.PromptID != "docs/greeting" || len(inspection.Inputs) != 1 || inspection.Inputs[0].Name != "overridden" {
t.Fatalf("inspect imported and overlaid prompt = (%+v, %v)", inspection, err)
}
}

View File

@@ -73,8 +73,8 @@ func TestProfileEnvironmentLookupAcceptsNonShellNames(t *testing.T) {
func TestPublicConstructionWithLocalBackendAndProgrammaticProfile(t *testing.T) {
backendID, model := "workstation", "offline-model"
prompt := configkit.Input{Source: configkit.Mapping("prompt", map[string]any{
"prompts": map[string]any{"hello": map[string]any{
"version": "1",
"prompts": []any{map[string]any{
"id": "hello",
"default_profile": "offline",
"messages": []any{map[string]any{"role": "user", "content": "Hello"}},
"output": map[string]any{"format": "text", "validation_mode": "none"},
@@ -143,12 +143,11 @@ func TestPublicConstructionCombinesEmbeddedOperatorAndProgrammaticInputs(t *test
embedded, err := promptkit.FilesystemInputs("embedded defaults", fstest.MapFS{
"config/default.yaml": &fstest.MapFile{Data: []byte(`
profiles:
application:
- id: application
endpoint: https://example.invalid/v1
model: default-model
prompts:
hello:
version: "1"
- id: hello
default_profile: application
messages:
- role: user
@@ -162,16 +161,16 @@ prompts:
t.Fatalf("select embedded defaults: %v", err)
}
operatorDirectory := t.TempDir()
if err := os.WriteFile(filepath.Join(operatorDirectory, "override.yaml"), []byte("profiles:\n application:\n model: operator-model\n"), 0o644); err != nil {
if err := os.WriteFile(filepath.Join(operatorDirectory, "override.yaml"), []byte("profiles:\n - id: application\n endpoint: https://example.invalid/v1\n model: operator-model\n"), 0o644); err != nil {
t.Fatalf("write operator input: %v", err)
}
operator, err := promptkit.DirectoryInputs(operatorDirectory)
if err != nil {
t.Fatalf("select operator inputs: %v", err)
}
programmaticModel := "programmatic-model"
programmaticModel, programmaticEndpoint := "programmatic-model", "https://example.invalid/v1"
programmatic := configkit.Input{Source: promptkit.ProfileSource("programmatic settings", []promptkit.ProfileConfig{
{ID: "application", Model: &programmaticModel},
{ID: "application", Endpoint: &programmaticEndpoint, Model: &programmaticModel},
})}
for _, test := range []struct {
name string
@@ -207,7 +206,7 @@ prompts:
func TestPublicConstructionPreservesConfigKitLoadError(t *testing.T) {
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &configkit.Input{
Source: configkit.Mapping("invalid", map[string]any{"profiles": map[string]any{"broken": map[string]any{"unknown": true}}}),
Source: configkit.Mapping("invalid", map[string]any{"profiles": []any{map[string]any{"id": "broken", "unknown": true}}}),
}}})
var loadErr *configkit.LoadError
if engine != nil || !errors.Is(err, promptkit.ErrInvalidConfig) || !errors.As(err, &loadErr) {
@@ -291,7 +290,7 @@ func TestBackendSourceOwnsSmokeTestValuesAndDefersDefaultLookup(t *testing.T) {
"https://backend.example/v1",
"not-yet-listed",
"https://probe.example/ready?check=1",
"openrouter_key",
" OPENROUTER_KEY ",
"https://probe.example/key?scope=current",
} {
if !strings.Contains(contents, want) {

View File

@@ -701,6 +701,13 @@ inspection, listing, and namespace contract tests.
Validation: run the affected external-package contract tests using real ConfigKit
composition and offline sources. Do not add index/list-position guarantees.
Completion: public source, construction, profile inheritance/inspection,
namespace, and inventory fixtures now use explicit-ID lists and identity
inheritance. Layered replacements supply complete records, and configuration
inspection assertions reflect composed values. Focused offline contract tests
passed on Go 1.27.0. Tests depending on the shared legacy execution fixture and
the full root package remain assigned to subsequent fixture migrations.
## Stage 16: Migrate Internal Execution And Rendering Fixtures
Scope: remaining `internal/usecase`, `internal/prompt`, `internal/domain`, and

View File

@@ -17,8 +17,8 @@ import (
func TestListIdentitiesBasicContract(t *testing.T) {
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &configkit.Input{
Source: configkit.Mapping("listing", map[string]any{
"profiles": map[string]any{"configured-profile": map[string]any{"model": "example-model"}},
"prompts": map[string]any{"example-prompt": promptDefinitionWithVersion("10", listingContractPrompt())},
"profiles": []any{map[string]any{"id": "configured-profile", "model": "example-model"}},
"prompts": []any{listingContractPrompt("example-prompt")},
}),
}}})
if err != nil {
@@ -38,13 +38,13 @@ func TestListIdentitiesBasicContract(t *testing.T) {
t.Fatal(err)
}
want := []promptkit.PromptIdentity{
{ID: "example-prompt", Version: stringPointerForTest("10")},
{ID: "example-prompt"},
}
if len(prompts) != len(want) {
t.Fatalf("prompt listing = %#v, want %#v", prompts, want)
}
for i := range want {
if prompts[i].ID != want[i].ID || prompts[i].Version == nil || *prompts[i].Version != *want[i].Version {
if prompts[i].ID != want[i].ID {
t.Fatalf("prompt listing = %#v, want %#v", prompts, want)
}
}
@@ -54,8 +54,7 @@ func TestListIdentitiesBasicContract(t *testing.T) {
t.Fatalf("listed profile could not be inspected: (%+v, %v)", profile, err)
}
prompt, err := engine.InspectPrompt(context.Background(), prompts[0].ID)
if err != nil || prompt == nil || prompt.PromptID != prompts[0].ID || prompt.PromptVersion == nil ||
*prompt.PromptVersion != *prompts[0].Version {
if err != nil || prompt == nil || prompt.PromptID != prompts[0].ID {
t.Fatalf("listed prompt could not be inspected: (%+v, %v)", prompt, err)
}
}
@@ -135,16 +134,15 @@ func TestScopedIdentityListingsApplyNamespaceFilters(t *testing.T) {
}
prompts, err := scoped.ListPrompts(context.Background(), promptkit.NamespaceFilter{Mode: promptkit.NamespaceNamed, Name: "team"})
if err != nil || len(prompts) != 1 || prompts[0].ID != "team/prompt" || prompts[0].Version == nil || *prompts[0].Version != "team-v1" {
if err != nil || len(prompts) != 1 || prompts[0].ID != "team/prompt" {
t.Fatalf("named prompt identity = %#v, %v", prompts, err)
}
if _, err := scoped.InspectPrompt(context.Background(), prompts[0].ID); err != nil {
t.Fatalf("listed full prompt ID did not round trip: %v", err)
}
*prompts[0].Version = "caller change"
prompts[0].ID = "caller change"
prompts, err = scoped.ListPrompts(context.Background(), promptkit.NamespaceFilter{Mode: promptkit.NamespaceNamed, Name: "team"})
if err != nil || len(prompts) != 1 || prompts[0].ID != "team/prompt" || prompts[0].Version == nil || *prompts[0].Version != "team-v1" {
if err != nil || len(prompts) != 1 || prompts[0].ID != "team/prompt" {
t.Fatalf("mutating filtered prompt inventory escaped: %#v, %v", prompts, err)
}
profiles, err := scoped.ListProfiles(context.Background(), promptkit.NamespaceFilter{Mode: promptkit.NamespaceNamed, Name: "team"})
@@ -214,9 +212,9 @@ func newNamespaceListingEngine(t *testing.T) *promptkit.Engine {
t.Helper()
collection := func(namespace string) map[string]any {
return map[string]any{
"backends": map[string]any{"backend": map[string]any{"endpoint": "https://example.test/v1"}},
"profiles": map[string]any{"profile": map[string]any{"backend": namespace + "/backend", "model": "example-model"}},
"prompts": map[string]any{"prompt": promptDefinitionWithVersion("team-v1", listingContractPrompt())},
"backends": []any{map[string]any{"id": "backend", "endpoint": "https://example.test/v1"}},
"profiles": []any{map[string]any{"id": "profile", "backend": namespace + "/backend", "model": "example-model"}},
"prompts": []any{listingContractPrompt("prompt")},
}
}
input := configkit.Input{Source: configkit.Mapping("namespaced listing", map[string]any{
@@ -224,9 +222,9 @@ func newNamespaceListingEngine(t *testing.T) *promptkit.Engine {
"team": collection("team"),
"team-blue": collection("team-blue"),
},
"backends": map[string]any{"root-backend": map[string]any{"endpoint": "https://root.example.test/v1"}},
"profiles": map[string]any{"root-profile": map[string]any{"backend": "root-backend", "model": "root-model"}},
"prompts": map[string]any{"root-prompt": promptDefinitionWithVersion("root-v1", listingContractPrompt())},
"backends": []any{map[string]any{"id": "root-backend", "endpoint": "https://root.example.test/v1"}},
"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}})
if err != nil {
@@ -241,18 +239,18 @@ func newNamespaceListingEngine(t *testing.T) *promptkit.Engine {
func TestResourceAndCollectionInventories(t *testing.T) {
underlay := configkit.Input{Source: configkit.Mapping("inventory defaults", map[string]any{
"backends": map[string]any{"root-backend": map[string]any{"endpoint": "https://root.example.test/v1"}},
"profiles": map[string]any{"root-profile": map[string]any{"endpoint": "https://root.example.test/v1", "model": "root-model"}},
"prompts": map[string]any{"root-prompt": listingContractPrompt()},
"backends": []any{map[string]any{"id": "root-backend", "endpoint": "https://root.example.test/v1"}},
"profiles": []any{map[string]any{"id": "root-profile", "endpoint": "https://root.example.test/v1", "model": "root-model"}},
"prompts": []any{listingContractPrompt("root-prompt")},
"collections": map[string]any{
"alpha": map[string]any{
"backends": map[string]any{"api": map[string]any{"endpoint": "https://alpha.example.test/v1"}},
"profiles": map[string]any{"profile": map[string]any{"backend": "alpha/api", "model": "alpha-model"}},
"prompts": map[string]any{"prompt": listingContractPrompt()},
"backends": []any{map[string]any{"id": "api", "endpoint": "https://alpha.example.test/v1"}},
"profiles": []any{map[string]any{"id": "profile", "backend": "alpha/api", "model": "alpha-model"}},
"prompts": []any{listingContractPrompt("prompt")},
},
"alpha-beta": map[string]any{"prompts": map[string]any{"prompt": listingContractPrompt()}},
"beta": map[string]any{"backends": map[string]any{"api": map[string]any{"endpoint": "https://beta.example.test/v1"}}},
"resource-only": map[string]any{"profiles": map[string]any{"profile": map[string]any{"endpoint": "https://resource.example.test/v1", "model": "resource-model"}}},
"alpha-beta": map[string]any{"prompts": []any{listingContractPrompt("prompt")}},
"beta": map[string]any{"backends": []any{map[string]any{"id": "api", "endpoint": "https://beta.example.test/v1"}}},
"resource-only": map[string]any{"profiles": []any{map[string]any{"id": "profile", "endpoint": "https://resource.example.test/v1", "model": "resource-model"}}},
"metadata-only": map[string]any{"release_version": "v1"},
"empty-label": map[string]any{"release_version": ""},
"null-label": map[string]any{"release_version": nil},
@@ -363,8 +361,8 @@ func TestListIdentitiesInvalidEngine(t *testing.T) {
func TestListIdentitiesPreserveContextErrorsWithoutPartialResults(t *testing.T) {
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &configkit.Input{
Source: configkit.Mapping("listing", map[string]any{
"profiles": map[string]any{"profile": map[string]any{}},
"prompts": map[string]any{"example": promptDefinitionWithVersion("v1", listingContractPrompt())},
"profiles": []any{map[string]any{"id": "profile"}},
"prompts": []any{listingContractPrompt("example")},
}),
}}})
if err != nil {
@@ -399,26 +397,20 @@ func TestListIdentitiesPreserveContextErrorsWithoutPartialResults(t *testing.T)
func TestListIdentitiesUseEffectiveLayeredMembership(t *testing.T) {
underlay := configkit.Input{Source: configkit.Mapping("consumer defaults", map[string]any{
"collections": map[string]any{"shared": map[string]any{
"profiles": map[string]any{
"base": map[string]any{"endpoint": "https://example.test/v1", "model": "base-model"},
"child": map[string]any{"extends": "base"},
"overlay": map[string]any{"endpoint": "https://example.test/v1", "model": "old-model"},
},
"prompts": map[string]any{
"prompt": promptDefinitionWithVersion("v1", listingContractPrompt()),
"profiles": []any{
map[string]any{"id": "base", "endpoint": "https://example.test/v1", "model": "base-model"},
map[string]any{"id": "child", "extends": map[string]any{"id": "base"}},
map[string]any{"id": "overlay", "endpoint": "https://example.test/v1", "model": "old-model"},
},
"prompts": []any{listingContractPrompt("prompt")},
}},
"prompts": map[string]any{
"underlay-only": promptDefinitionWithVersion("v1", listingContractPrompt()),
},
"prompts": []any{listingContractPrompt("underlay-only")},
})}
main := configkit.Input{Source: configkit.Mapping("application overlay", map[string]any{
"collections": map[string]any{"shared": map[string]any{"profiles": map[string]any{
"overlay": map[string]any{"model": "effective-model"},
"collections": map[string]any{"shared": map[string]any{"profiles": []any{
map[string]any{"id": "overlay", "model": "effective-model"},
}}},
"prompts": map[string]any{
"main-only": promptDefinitionWithVersion("v3", listingContractPrompt()),
},
"prompts": []any{listingContractPrompt("main-only")},
})}
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{
Underlays: []configkit.Underlay{{Inputs: []configkit.Input{underlay}}},
@@ -459,14 +451,14 @@ func TestListIdentitiesUseEffectiveLayeredMembership(t *testing.T) {
t.Fatal(err)
}
wantPrompts := []promptkit.PromptIdentity{
{ID: "main-only", Version: stringPointerForTest("v3")},
{ID: "shared/prompt", Version: stringPointerForTest("v1")},
{ID: "underlay-only", Version: stringPointerForTest("v1")},
{ID: "main-only"},
{ID: "shared/prompt"},
{ID: "underlay-only"},
}
if !reflect.DeepEqual(prompts, wantPrompts) {
t.Fatalf("effective prompt identities = %#v, want %#v", prompts, wantPrompts)
}
if got := countListingPrompt(prompts, "shared/prompt", "v1"); got != 1 {
if got := countListingPrompt(prompts, "shared/prompt"); got != 1 {
t.Fatalf("overlaid prompt identity appears %d times, want 1", got)
}
}
@@ -488,8 +480,8 @@ func TestListIdentitiesEmptyEffectiveConfiguration(t *testing.T) {
func TestListIdentitiesAreOwnedAndSafeForConcurrentUse(t *testing.T) {
engine, err := newListingContractEngine(t, map[string]any{
"profiles": map[string]any{"profile": map[string]any{"model": "partial-model"}},
"prompts": map[string]any{"prompt": promptDefinitionWithVersion("v1", listingContractPrompt())},
"profiles": []any{map[string]any{"id": "profile", "model": "partial-model"}},
"prompts": []any{listingContractPrompt("prompt")},
})
if err != nil {
t.Fatal(err)
@@ -511,9 +503,6 @@ func TestListIdentitiesAreOwnedAndSafeForConcurrentUse(t *testing.T) {
for i := range prompts {
if prompts[i].ID == "prompt" {
prompts[i].ID = "caller mutation"
if prompts[i].Version != nil {
*prompts[i].Version = "caller mutation"
}
}
}
profiles, err = engine.ListProfiles(context.Background())
@@ -521,7 +510,7 @@ func TestListIdentitiesAreOwnedAndSafeForConcurrentUse(t *testing.T) {
t.Fatalf("profile result mutation escaped into engine: %#v, %v", profiles, err)
}
prompts, err = engine.ListPrompts(context.Background())
if err != nil || countListingPrompt(prompts, "prompt", "v1") != 1 {
if err != nil || countListingPrompt(prompts, "prompt") != 1 {
t.Fatalf("prompt result mutation escaped into engine: %#v, %v", prompts, err)
}
@@ -557,9 +546,6 @@ func TestListIdentitiesAreOwnedAndSafeForConcurrentUse(t *testing.T) {
return
}
prompts[0].ID = "worker mutation"
if prompts[0].Version != nil {
*prompts[0].Version = "worker mutation"
}
if _, err := engine.InspectProfile(context.Background(), "profile"); err != nil {
results <- fmt.Errorf("inspect profile: %w", err)
@@ -582,7 +568,7 @@ func TestListIdentitiesAreOwnedAndSafeForConcurrentUse(t *testing.T) {
func TestListIdentitiesUseCapturedSourcesWithoutExecutionWork(t *testing.T) {
files := fstest.MapFS{
"config/listing.yaml": &fstest.MapFile{Data: []byte("profiles:\n captured-partial:\n model: partial-model\nprompts:\n captured-prompt:\n version: v1\n messages:\n - role: user\n content: Hello.\n output:\n format: text\n validation_mode: basic\n")},
"config/listing.yaml": &fstest.MapFile{Data: []byte("profiles:\n - id: captured-partial\n model: partial-model\nprompts:\n - id: captured-prompt\n messages:\n - role: user\n content: Hello.\n output:\n format: text\n validation_mode: basic\n")},
}
inputs, err := promptkit.FilesystemInputs("application listing", files, "config")
if err != nil {
@@ -594,20 +580,21 @@ func TestListIdentitiesUseCapturedSourcesWithoutExecutionWork(t *testing.T) {
if err != nil {
t.Fatal(err)
}
files["config/listing.yaml"].Data = []byte("profiles:\n replacement-profile: {}\nprompts:\n replacement-prompt:\n version: v2\n messages:\n - role: user\n content: Changed.\n output:\n format: text\n validation_mode: basic\n")
files["config/listing.yaml"].Data = []byte("profiles:\n - id: replacement-profile\nprompts:\n - id: replacement-prompt\n messages:\n - role: user\n content: Changed.\n output:\n format: text\n validation_mode: basic\n")
profiles, err := engine.ListProfiles(context.Background())
if err != nil || !containsListingProfile(profiles, "captured-partial") || containsListingProfile(profiles, "replacement-profile") {
t.Fatalf("profile listing did not use captured source: %#v, %v", profiles, err)
}
prompts, err := engine.ListPrompts(context.Background())
if err != nil || countListingPrompt(prompts, "captured-prompt", "v1") != 1 || countListingPrompt(prompts, "replacement-prompt", "v2") != 0 {
if err != nil || countListingPrompt(prompts, "captured-prompt") != 1 || countListingPrompt(prompts, "replacement-prompt") != 0 {
t.Fatalf("prompt listing did not use captured source: %#v, %v", prompts, err)
}
}
func listingContractPrompt() map[string]any {
func listingContractPrompt(id string) map[string]any {
return map[string]any{
"id": id,
"messages": []any{map[string]any{"role": "user", "content": "Hello."}},
"output": map[string]any{"format": "text", "validation_mode": "basic"},
}
@@ -632,10 +619,10 @@ func countListingProfile(profiles []string, id string) int {
return count
}
func countListingPrompt(prompts []promptkit.PromptIdentity, id, version string) int {
func countListingPrompt(prompts []promptkit.PromptIdentity, id string) int {
count := 0
for _, prompt := range prompts {
if prompt.ID == id && prompt.Version != nil && *prompt.Version == version {
if prompt.ID == id {
count++
}
}

View File

@@ -268,12 +268,11 @@ func newNamespacedContractEngine(t *testing.T, client promptkit.LLMClient) *prom
for _, namespace := range []string{"alpha", "beta"} {
endpoint := "https://" + namespace + ".example/v1"
input, err := promptkit.CollectionInput(namespace, configkit.Mapping(namespace+" resources", map[string]any{
"backends": map[string]any{"backend": map[string]any{"endpoint": endpoint}},
"profiles": map[string]any{"shared": map[string]any{
"backends": []any{map[string]any{"id": "backend", "endpoint": endpoint}},
"profiles": []any{map[string]any{"id": "shared",
"backend": namespace + "/backend", "model": namespace + "-model",
}},
"prompts": map[string]any{"shared": map[string]any{
"version": "1",
"prompts": []any{map[string]any{"id": "shared",
"default_profile": "root-only",
"messages": []any{map[string]any{"role": "user", "content": "Hello"}},
"output": map[string]any{"format": "text", "validation_mode": "none"},
@@ -286,11 +285,10 @@ func newNamespacedContractEngine(t *testing.T, client promptkit.LLMClient) *prom
inputs = append(inputs, input)
}
inputs = append(inputs, configkit.Input{Source: configkit.Mapping("root resources", map[string]any{
"profiles": map[string]any{"root-only": map[string]any{
"profiles": []any{map[string]any{"id": "root-only",
"endpoint": "https://root.example/v1", "model": "root-model",
}},
"prompts": map[string]any{"root-only": map[string]any{
"version": "1",
"prompts": []any{map[string]any{"id": "root-only",
"messages": []any{map[string]any{"role": "user", "content": "Root prompt"}},
"output": map[string]any{"format": "text", "validation_mode": "none"},
}},

View File

@@ -61,7 +61,7 @@ func TestProfileInheritanceConfiguredBaseAliasWorkflow(t *testing.T) {
func TestProfileInheritanceYAMLAliasOfConfiguredProfile(t *testing.T) {
inputs, err := promptkit.FilesystemInputs("profile alias", fstest.MapFS{
"config/alias.yaml": &fstest.MapFile{Data: []byte("profiles:\n base:\n model: synthetic-model\n yaml-alias:\n extends: base\n")},
"config/alias.yaml": &fstest.MapFile{Data: []byte("profiles:\n - id: base\n model: synthetic-model\n - id: yaml-alias\n extends: {id: base}\n")},
}, "config")
if err != nil {
t.Fatal(err)
@@ -79,12 +79,12 @@ func TestProfileInheritanceYAMLAliasOfConfiguredProfile(t *testing.T) {
func TestProfileInheritanceRetainsRequiredCredentialBehavior(t *testing.T) {
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &configkit.Input{
Source: configkit.Mapping("credentials", map[string]any{
"backends": map[string]any{"credential-backend": map[string]any{
"backends": []any{map[string]any{"id": "credential-backend",
"endpoint": "https://credential.example/v1", "api_key_env": "OPTIONAL_BACKEND_KEY",
}},
"profiles": map[string]any{
"credential-base": map[string]any{"backend": "credential-backend", "model": "model", "api_key_required": true},
"credential-child": map[string]any{"extends": "credential-base"},
"profiles": []any{
map[string]any{"id": "credential-base", "backend": "credential-backend", "model": "model", "api_key_required": true},
map[string]any{"id": "credential-child", "extends": map[string]any{"id": "credential-base"}},
},
}),
}}})
@@ -106,8 +106,8 @@ func TestProfileInheritancePreservesPublicErrorIdentities(t *testing.T) {
t.Fatalf("missing profile = (%+v, %v)", inspection, err)
}
for _, document := range []map[string]any{
{"profiles": map[string]any{"child": map[string]any{"extends": "missing"}}},
{"profiles": map[string]any{"a": map[string]any{"extends": "b"}, "b": map[string]any{"extends": "a"}}},
{"profiles": []any{map[string]any{"id": "child", "extends": map[string]any{"id": "missing"}}}},
{"profiles": []any{map[string]any{"id": "a", "extends": map[string]any{"id": "b"}}, map[string]any{"id": "b", "extends": map[string]any{"id": "a"}}}},
} {
invalid, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &configkit.Input{
Source: configkit.Mapping("invalid inheritance", document),
@@ -120,7 +120,7 @@ func TestProfileInheritancePreservesPublicErrorIdentities(t *testing.T) {
func TestProfileInheritanceFreezesPreparedExecution(t *testing.T) {
profiles := &mutableInheritanceProfileFS{files: fstest.MapFS{
"config/profiles.yaml": &fstest.MapFile{Data: []byte("profiles:\n base:\n endpoint: https://base.example/v1\n model: first-model\n child:\n extends: base\n")},
"config/profiles.yaml": &fstest.MapFile{Data: []byte("profiles:\n - id: base\n endpoint: https://base.example/v1\n model: first-model\n - id: child\n extends: {id: base}\n")},
}}
inputs, err := promptkit.FilesystemInputs("profiles", profiles, "config")
if err != nil {
@@ -138,7 +138,7 @@ func TestProfileInheritanceFreezesPreparedExecution(t *testing.T) {
if err != nil {
t.Fatal(err)
}
profiles.set("config/profiles.yaml", "profiles:\n base:\n endpoint: https://base.example/v1\n model: second-model\n child:\n extends: base\n")
profiles.set("config/profiles.yaml", "profiles:\n - id: base\n endpoint: https://base.example/v1\n model: second-model\n - id: child\n extends: {id: base}\n")
result, err := engine.RunPrepared(context.Background(), prepared)
if err != nil || result == nil || client.model != "first-model" {
t.Fatalf("prepared execution = (%+v, %v), model %q", result, err, client.model)

View File

@@ -12,7 +12,7 @@ import (
func TestInspectProfileUsesLiteralFileKeyForPreparation(t *testing.T) {
profiles, err := promptkit.FilesystemInputs("literal profile", fstest.MapFS{
"config/profile.yaml": &fstest.MapFile{Data: []byte("profiles:\n ' literal ':\n endpoint: https://example.test/v1\n model: model\n")},
"config/profile.yaml": &fstest.MapFile{Data: []byte("profiles:\n - id: ' literal '\n endpoint: https://example.test/v1\n model: model\n")},
}, "config")
if err != nil {
t.Fatal(err)
@@ -20,8 +20,8 @@ func TestInspectProfileUsesLiteralFileKeyForPreparation(t *testing.T) {
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{
Underlays: []configkit.Underlay{{Inputs: profiles}},
Main: &configkit.Input{Source: configkit.Mapping("prompt", map[string]any{
"prompts": map[string]any{"prompt": map[string]any{
"version": "1",
"prompts": []any{map[string]any{
"id": "prompt",
"default_profile": " literal ",
"messages": []any{map[string]any{"role": "user", "content": "hello"}},
"output": map[string]any{"format": "text", "validation_mode": "none"},
@@ -50,8 +50,8 @@ func TestInspectProfileUsesLiteralFileKeyForPreparation(t *testing.T) {
func TestInspectProfileIsIndependentAndDoesNotInvokeProvider(t *testing.T) {
client := &fakeLLMClient{response: &promptkit.GenerateResponse{Content: "unexpected"}}
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &configkit.Input{
Source: configkit.Mapping("inspection", map[string]any{"profiles": map[string]any{
"profile": map[string]any{
Source: configkit.Mapping("inspection", map[string]any{"profiles": []any{
map[string]any{"id": "profile",
"endpoint": "https://example.test/v1", "model": "model", "api_key_required": true,
"extra_params": map[string]any{"nested": map[string]any{"value": "original"}},
},
@@ -77,7 +77,7 @@ func TestInspectProfilePublicErrorsAndPartialTarget(t *testing.T) {
t.Fatalf("nil engine: %v", err)
}
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &configkit.Input{
Source: configkit.Mapping("partial", map[string]any{"profiles": map[string]any{"profile": map[string]any{"model": "model"}}}),
Source: configkit.Mapping("partial", map[string]any{"profiles": []any{map[string]any{"id": "profile", "model": "model"}}}),
}}})
if err != nil {
t.Fatal(err)