Store one prompt definition per ID

This commit is contained in:
2026-10-17 05:41:21 +00:00
parent 0cd833513c
commit d40a010538
28 changed files with 393 additions and 445 deletions

View File

@@ -18,10 +18,7 @@ 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": map[string]any{
"2": listingContractPrompt(),
"10": listingContractPrompt(),
}},
"prompts": map[string]any{"example-prompt": promptDefinitionWithVersion("10", listingContractPrompt())},
}),
}}})
if err != nil {
@@ -42,7 +39,6 @@ func TestListIdentitiesBasicContract(t *testing.T) {
}
want := []promptkit.PromptIdentity{
{ID: "example-prompt", Version: "10"},
{ID: "example-prompt", Version: "2"},
}
if len(prompts) != len(want) {
t.Fatalf("prompt listing = %#v, want %#v", prompts, want)
@@ -80,7 +76,7 @@ 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": map[string]any{"v1": listingContractPrompt()}},
"prompts": map[string]any{"example": promptDefinitionWithVersion("v1", listingContractPrompt())},
}),
}}})
if err != nil {
@@ -120,11 +116,8 @@ func TestListIdentitiesUseEffectiveLayeredMembership(t *testing.T) {
"overlay/profile": map[string]any{"endpoint": "https://example.test/v1", "model": "old-model"},
},
"prompts": map[string]any{
"shared/prompt": map[string]any{
"v1": listingContractPrompt(),
"v2": listingContractPrompt(),
},
"underlay-only": map[string]any{"v1": listingContractPrompt()},
"shared/prompt": promptDefinitionWithVersion("v1", listingContractPrompt()),
"underlay-only": promptDefinitionWithVersion("v1", listingContractPrompt()),
},
})}
main := configkit.Input{Source: configkit.Mapping("application overlay", map[string]any{
@@ -132,8 +125,8 @@ func TestListIdentitiesUseEffectiveLayeredMembership(t *testing.T) {
"overlay/profile": map[string]any{"model": "effective-model"},
},
"prompts": map[string]any{
"shared/prompt": map[string]any{"v1": listingContractPrompt()},
"main-only": map[string]any{"v3": listingContractPrompt()},
"shared/prompt": promptDefinitionWithVersion("v2", listingContractPrompt()),
"main-only": promptDefinitionWithVersion("v3", listingContractPrompt()),
},
})}
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{
@@ -177,14 +170,13 @@ func TestListIdentitiesUseEffectiveLayeredMembership(t *testing.T) {
}
wantPrompts := []promptkit.PromptIdentity{
{ID: "main-only", Version: "v3"},
{ID: "shared/prompt", Version: "v1"},
{ID: "shared/prompt", Version: "v2"},
{ID: "underlay-only", Version: "v1"},
}
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", "v2"); got != 1 {
t.Fatalf("overlaid prompt identity appears %d times, want 1", got)
}
}
@@ -211,7 +203,7 @@ 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": map[string]any{"v1": listingContractPrompt()}},
"prompts": map[string]any{"prompt": promptDefinitionWithVersion("v1", listingContractPrompt())},
})
if err != nil {
t.Fatal(err)
@@ -300,7 +292,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 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 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")},
}
inputs, err := promptkit.FilesystemInputs("application listing", files, "config")
if err != nil {
@@ -312,7 +304,7 @@ 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 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 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")
profiles, err := engine.ListProfiles(context.Background())
if err != nil || !containsListingProfile(profiles, "captured-partial") || containsListingProfile(profiles, "replacement-profile") {