Update public preparation and execution fixtures
This commit is contained in:
@@ -247,11 +247,12 @@ func newBackendCapacityEngine(
|
|||||||
promptID, content = "input-prompt", `{{input "input"}}`
|
promptID, content = "input-prompt", `{{input "input"}}`
|
||||||
inputs = []any{map[string]any{"name": "input", "required": true}}
|
inputs = []any{map[string]any{"name": "input", "required": true}}
|
||||||
}
|
}
|
||||||
backend := map[string]any{"endpoint": "http://backend.example/v1", "concurrency_limit": limit}
|
backend := map[string]any{"id": "limited", "endpoint": "http://backend.example/v1", "concurrency_limit": limit}
|
||||||
if queueCapacity != nil {
|
if queueCapacity != nil {
|
||||||
backend["queue_capacity"] = *queueCapacity
|
backend["queue_capacity"] = *queueCapacity
|
||||||
}
|
}
|
||||||
definition := map[string]any{
|
definition := map[string]any{
|
||||||
|
"id": promptID,
|
||||||
"default_profile": "profile",
|
"default_profile": "profile",
|
||||||
"messages": []any{map[string]any{"role": "user", "content": content}},
|
"messages": []any{map[string]any{"role": "user", "content": content}},
|
||||||
"output": map[string]any{"format": "text", "validation_mode": "none"},
|
"output": map[string]any{"format": "text", "validation_mode": "none"},
|
||||||
@@ -265,9 +266,9 @@ func newBackendCapacityEngine(
|
|||||||
}
|
}
|
||||||
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &configkit.Input{
|
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &configkit.Input{
|
||||||
Source: configkit.Mapping("capacity fixture", map[string]any{
|
Source: configkit.Mapping("capacity fixture", map[string]any{
|
||||||
"backends": map[string]any{"limited": backend},
|
"backends": []any{backend},
|
||||||
"profiles": map[string]any{"profile": map[string]any{"backend": "limited", "model": "model"}},
|
"profiles": []any{map[string]any{"id": "profile", "backend": "limited", "model": "model"}},
|
||||||
"prompts": map[string]any{promptID: promptDefinitionWithVersion("1", definition)},
|
"prompts": []any{definition},
|
||||||
}),
|
}),
|
||||||
}}}, options...)
|
}}}, options...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -750,6 +750,13 @@ requirements, and capacity contract fixtures.
|
|||||||
Validation: run the focused root preparation/execution/requirements tests using
|
Validation: run the focused root preparation/execution/requirements tests using
|
||||||
existing injected clients or controlled HTTP transports, with no live provider.
|
existing injected clients or controlled HTTP transports, with no live provider.
|
||||||
|
|
||||||
|
Completion: public prepared execution, frozen rendering, requirement inspection,
|
||||||
|
capacity, and reliable-execution fixtures now use identified resources and no
|
||||||
|
prompt labels. Focused offline preparation, requirement, snapshot, and capacity
|
||||||
|
tests passed on Go 1.27.0. The remaining shared legacy helper and observation
|
||||||
|
test dependencies are assigned to later work, so the full root suite remains
|
||||||
|
deferred.
|
||||||
|
|
||||||
## Stage 18: Migrate Public Diagnostics And Observation Contracts
|
## Stage 18: Migrate Public Diagnostics And Observation Contracts
|
||||||
|
|
||||||
Scope: root smoke diagnostic, observation, prepared-observation, and adapter
|
Scope: root smoke diagnostic, observation, prepared-observation, and adapter
|
||||||
|
|||||||
@@ -18,8 +18,7 @@ import (
|
|||||||
|
|
||||||
const capturedPromptDocument = `
|
const capturedPromptDocument = `
|
||||||
prompts:
|
prompts:
|
||||||
captured:
|
- id: captured
|
||||||
version: "1"
|
|
||||||
default_profile: offline
|
default_profile: offline
|
||||||
session_id: '{{.session}}'
|
session_id: '{{.session}}'
|
||||||
messages:
|
messages:
|
||||||
@@ -40,8 +39,8 @@ func capturedPromptEngine(t *testing.T, source fs.FS) *promptkit.Engine {
|
|||||||
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{
|
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{
|
||||||
Underlays: []configkit.Underlay{
|
Underlays: []configkit.Underlay{
|
||||||
{Inputs: inputs},
|
{Inputs: inputs},
|
||||||
{Inputs: []configkit.Input{{Source: promptkit.ProfileSource("offline profile", map[string]promptkit.ProfileConfig{
|
{Inputs: []configkit.Input{{Source: promptkit.ProfileSource("offline profile", []promptkit.ProfileConfig{
|
||||||
"offline": {Endpoint: &endpoint, Model: &model},
|
{ID: "offline", Endpoint: &endpoint, Model: &model},
|
||||||
})}}},
|
})}}},
|
||||||
},
|
},
|
||||||
}})
|
}})
|
||||||
@@ -145,12 +144,11 @@ func TestPreparationStillReadsRequestArtifactsAndSchemasAfterConstruction(t *tes
|
|||||||
endpoint, model := "https://example.invalid/v1", "offline-model"
|
endpoint, model := "https://example.invalid/v1", "offline-model"
|
||||||
schemas := fstest.MapFS{}
|
schemas := fstest.MapFS{}
|
||||||
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{
|
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{
|
||||||
Underlays: []configkit.Underlay{{Inputs: []configkit.Input{{Source: promptkit.ProfileSource("profile", map[string]promptkit.ProfileConfig{
|
Underlays: []configkit.Underlay{{Inputs: []configkit.Input{{Source: promptkit.ProfileSource("profile", []promptkit.ProfileConfig{
|
||||||
"offline": {Endpoint: &endpoint, Model: &model},
|
{ID: "offline", Endpoint: &endpoint, Model: &model},
|
||||||
})}}}},
|
})}}}},
|
||||||
Main: &configkit.Input{Source: configkit.Mapping("structured prompt", map[string]any{
|
Main: &configkit.Input{Source: configkit.Mapping("structured prompt", map[string]any{
|
||||||
"prompts": map[string]any{"structured": map[string]any{
|
"prompts": []any{map[string]any{"id": "structured",
|
||||||
"version": "1",
|
|
||||||
"default_profile": "offline",
|
"default_profile": "offline",
|
||||||
"inputs": []any{map[string]any{"name": "note", "required": true}},
|
"inputs": []any{map[string]any{"name": "note", "required": true}},
|
||||||
"messages": []any{map[string]any{"role": "user", "content": `{{input "note"}}`}},
|
"messages": []any{map[string]any{"role": "user", "content": `{{input "note"}}`}},
|
||||||
|
|||||||
@@ -87,18 +87,13 @@ func TestPreparedExecutionFreezesSourcesAndReturnsIndependentDetails(t *testing.
|
|||||||
reader.set("changed artifact", "changed-input-hash")
|
reader.set("changed artifact", "changed-input-hash")
|
||||||
|
|
||||||
first := prepared.Details()
|
first := prepared.Details()
|
||||||
if first.PromptVersion == nil || *first.PromptVersion != "1" {
|
|
||||||
t.Fatalf("prepared label = %v, want 1", *first.PromptVersion)
|
|
||||||
}
|
|
||||||
*first.PromptVersion = "mutated details"
|
|
||||||
first.Messages[0].Content = "changed details"
|
first.Messages[0].Content = "changed details"
|
||||||
first.InputHashes["input"] = "changed-details-hash"
|
first.InputHashes["input"] = "changed-details-hash"
|
||||||
first.EffectiveModelParams.ExtraParams["nested"].(map[string]any)["source"] = "changed details"
|
first.EffectiveModelParams.ExtraParams["nested"].(map[string]any)["source"] = "changed details"
|
||||||
first.StructuredOutput.JSONSchema.Schema.(map[string]any)["title"] = "changed details"
|
first.StructuredOutput.JSONSchema.Schema.(map[string]any)["title"] = "changed details"
|
||||||
|
|
||||||
second := prepared.Details()
|
second := prepared.Details()
|
||||||
if second.PromptVersion == nil || *second.PromptVersion != "1" ||
|
if second.Messages[0].Content != "Input=original artifact Label=original variable" {
|
||||||
second.Messages[0].Content != "Input=original artifact Label=original variable" {
|
|
||||||
t.Fatalf("details message changed: %q", second.Messages[0].Content)
|
t.Fatalf("details message changed: %q", second.Messages[0].Content)
|
||||||
}
|
}
|
||||||
if second.InputHashes["input"] != "original-input-hash" {
|
if second.InputHashes["input"] != "original-input-hash" {
|
||||||
@@ -137,7 +132,6 @@ func TestPreparedExecutionFreezesSourcesAndReturnsIndependentDetails(t *testing.
|
|||||||
t.Fatalf("generation did not use frozen details:\nrequest=%+v\ndetails=%+v", generated, second)
|
t.Fatalf("generation did not use frozen details:\nrequest=%+v\ndetails=%+v", generated, second)
|
||||||
}
|
}
|
||||||
if result.PromptID != second.PromptID ||
|
if result.PromptID != second.PromptID ||
|
||||||
result.PromptVersion == nil || second.PromptVersion == nil || *result.PromptVersion != *second.PromptVersion ||
|
|
||||||
result.PromptHash != second.PromptHash ||
|
result.PromptHash != second.PromptHash ||
|
||||||
result.SessionID != second.SessionID ||
|
result.SessionID != second.SessionID ||
|
||||||
result.RenderedPromptHash != second.RenderedPromptHash ||
|
result.RenderedPromptHash != second.RenderedPromptHash ||
|
||||||
@@ -147,13 +141,6 @@ func TestPreparedExecutionFreezesSourcesAndReturnsIndependentDetails(t *testing.
|
|||||||
!reflect.DeepEqual(result.InputHashes, second.InputHashes) {
|
!reflect.DeepEqual(result.InputHashes, second.InputHashes) {
|
||||||
t.Fatalf("result provenance does not match details:\nresult=%+v\ndetails=%+v", result, second)
|
t.Fatalf("result provenance does not match details:\nresult=%+v\ndetails=%+v", result, second)
|
||||||
}
|
}
|
||||||
if result.PromptVersion == second.PromptVersion {
|
|
||||||
t.Fatal("run result and prepared details share a mutable version label")
|
|
||||||
}
|
|
||||||
*result.PromptVersion = "mutated result"
|
|
||||||
if *second.PromptVersion != "1" {
|
|
||||||
t.Fatal("run result label mutation reached prepared details")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPreparedExecutionLifecycleAndEngineBinding(t *testing.T) {
|
func TestPreparedExecutionLifecycleAndEngineBinding(t *testing.T) {
|
||||||
@@ -776,11 +763,11 @@ func newPreparedContractEngine(
|
|||||||
func preparedContractConfig(message string, keyRequired bool) promptkit.Config {
|
func preparedContractConfig(message string, keyRequired bool) promptkit.Config {
|
||||||
return promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &configkit.Input{
|
return promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &configkit.Input{
|
||||||
Source: configkit.Mapping("prepared execution", map[string]any{
|
Source: configkit.Mapping("prepared execution", map[string]any{
|
||||||
"profiles": map[string]any{"profile": map[string]any{
|
"profiles": []any{map[string]any{"id": "profile",
|
||||||
"endpoint": "http://example.test/v1", "model": "model", "api_key_required": keyRequired,
|
"endpoint": "http://example.test/v1", "model": "model", "api_key_required": keyRequired,
|
||||||
}},
|
}},
|
||||||
"prompts": map[string]any{"prepared": map[string]any{
|
"prompts": []any{map[string]any{
|
||||||
"version": "1",
|
"id": "prepared",
|
||||||
"default_profile": "profile",
|
"default_profile": "profile",
|
||||||
"messages": []any{map[string]any{"role": "user", "content": message}},
|
"messages": []any{map[string]any{"role": "user", "content": message}},
|
||||||
"output": map[string]any{"format": "text", "validation_mode": "none"},
|
"output": map[string]any{"format": "text", "validation_mode": "none"},
|
||||||
@@ -792,8 +779,7 @@ func preparedContractConfig(message string, keyRequired bool) promptkit.Config {
|
|||||||
func preparedPromptSource(label string) fstest.MapFS {
|
func preparedPromptSource(label string) fstest.MapFS {
|
||||||
return fstest.MapFS{
|
return fstest.MapFS{
|
||||||
"prompt.yaml": &fstest.MapFile{Data: []byte(`prompts:
|
"prompt.yaml": &fstest.MapFile{Data: []byte(`prompts:
|
||||||
prepared:
|
- id: prepared
|
||||||
version: "1"
|
|
||||||
default_profile: profile
|
default_profile: profile
|
||||||
inputs:
|
inputs:
|
||||||
- name: input
|
- name: input
|
||||||
@@ -813,7 +799,7 @@ func preparedPromptSource(label string) fstest.MapFS {
|
|||||||
func preparedProfileSource(model string) fstest.MapFS {
|
func preparedProfileSource(model string) fstest.MapFS {
|
||||||
return fstest.MapFS{
|
return fstest.MapFS{
|
||||||
"profile.yaml": &fstest.MapFile{Data: []byte(`profiles:
|
"profile.yaml": &fstest.MapFile{Data: []byte(`profiles:
|
||||||
profile:
|
- id: profile
|
||||||
endpoint: http://example.test/v1
|
endpoint: http://example.test/v1
|
||||||
model: ` + model + `
|
model: ` + model + `
|
||||||
`)},
|
`)},
|
||||||
|
|||||||
@@ -83,11 +83,21 @@ func TestPublicRetryRepairSequenceKeepsUsageAndEventsConsistent(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func reliabilityConfig(backends, profiles map[string]any) promptkit.Config {
|
func reliabilityConfig(backends, profiles map[string]any) promptkit.Config {
|
||||||
|
records := func(values map[string]any) []any {
|
||||||
|
result := make([]any, 0, len(values))
|
||||||
|
for id, value := range values {
|
||||||
|
record := map[string]any{"id": id}
|
||||||
|
for key, field := range value.(map[string]any) {
|
||||||
|
record[key] = field
|
||||||
|
}
|
||||||
|
result = append(result, record)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
return promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &configkit.Input{Source: configkit.Mapping("reliable execution", map[string]any{
|
return promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &configkit.Input{Source: configkit.Mapping("reliable execution", map[string]any{
|
||||||
"backends": backends,
|
"backends": records(backends),
|
||||||
"profiles": profiles,
|
"profiles": records(profiles),
|
||||||
"prompts": map[string]any{"prompt": map[string]any{
|
"prompts": []any{map[string]any{"id": "prompt",
|
||||||
"version": "1",
|
|
||||||
"default_profile": "profile-a",
|
"default_profile": "profile-a",
|
||||||
"messages": []any{map[string]any{"role": "user", "content": "hello"}},
|
"messages": []any{map[string]any{"role": "user", "content": "hello"}},
|
||||||
"output": map[string]any{"format": "text", "validation_mode": "none"},
|
"output": map[string]any{"format": "text", "validation_mode": "none"},
|
||||||
@@ -252,8 +262,7 @@ func TestPreparedRetriesFreezeSourceAndCredentialAtExecution(t *testing.T) {
|
|||||||
const envName = "PROMPTKIT_PREPARED_RETRY_KEY"
|
const envName = "PROMPTKIT_PREPARED_RETRY_KEY"
|
||||||
t.Setenv(envName, "first-key")
|
t.Setenv(envName, "first-key")
|
||||||
source := fstest.MapFS{"prompt.yaml": &fstest.MapFile{Data: []byte(`prompts:
|
source := fstest.MapFS{"prompt.yaml": &fstest.MapFile{Data: []byte(`prompts:
|
||||||
prompt:
|
- id: prompt
|
||||||
version: "1"
|
|
||||||
default_profile: profile
|
default_profile: profile
|
||||||
messages:
|
messages:
|
||||||
- role: user
|
- role: user
|
||||||
@@ -291,8 +300,8 @@ func TestPreparedRetriesFreezeSourceAndCredentialAtExecution(t *testing.T) {
|
|||||||
engine, err := promptkit.NewEngine(promptkit.Config{
|
engine, err := promptkit.NewEngine(promptkit.Config{
|
||||||
Sources: promptkit.ConfigurationSources{Underlays: []configkit.Underlay{
|
Sources: promptkit.ConfigurationSources{Underlays: []configkit.Underlay{
|
||||||
{Inputs: inputs},
|
{Inputs: inputs},
|
||||||
{Inputs: []configkit.Input{{Source: promptkit.ProfileSource("profile", map[string]promptkit.ProfileConfig{
|
{Inputs: []configkit.Input{{Source: promptkit.ProfileSource("profile", []promptkit.ProfileConfig{
|
||||||
"profile": {Endpoint: &endpoint, Model: &model},
|
{ID: "profile", Endpoint: &endpoint, Model: &model},
|
||||||
})}}},
|
})}}},
|
||||||
}},
|
}},
|
||||||
HTTPClient: &http.Client{Transport: transport}, TransientRetries: &one,
|
HTTPClient: &http.Client{Transport: transport}, TransientRetries: &one,
|
||||||
@@ -306,8 +315,7 @@ func TestPreparedRetriesFreezeSourceAndCredentialAtExecution(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
source["prompt.yaml"] = &fstest.MapFile{Data: []byte(`prompts:
|
source["prompt.yaml"] = &fstest.MapFile{Data: []byte(`prompts:
|
||||||
prompt:
|
- id: prompt
|
||||||
version: "1"
|
|
||||||
default_profile: profile
|
default_profile: profile
|
||||||
messages:
|
messages:
|
||||||
- role: user
|
- role: user
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ func requirementsEngine(t *testing.T, prompts, profiles map[string]any, options
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &configkit.Input{
|
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{Main: &configkit.Input{
|
||||||
Source: configkit.Mapping("requirements contract", map[string]any{
|
Source: configkit.Mapping("requirements contract", map[string]any{
|
||||||
"prompts": prompts, "profiles": profiles,
|
"prompts": identifiedRequirementRecords(prompts), "profiles": identifiedRequirementRecords(profiles),
|
||||||
}),
|
}),
|
||||||
}}}, options...)
|
}}}, options...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -51,15 +51,19 @@ func contractPrompt(defaultProfile string, content string, inputs []any, session
|
|||||||
return definition
|
return definition
|
||||||
}
|
}
|
||||||
|
|
||||||
func oneVersionPrompt(id, version string, definition map[string]any) map[string]any {
|
func onePrompt(id string, definition map[string]any) map[string]any {
|
||||||
return map[string]any{id: promptDefinitionWithVersion(version, definition)}
|
return map[string]any{id: definition}
|
||||||
}
|
}
|
||||||
|
|
||||||
func promptDefinitionWithVersion(version string, definition map[string]any) map[string]any {
|
func identifiedRequirementRecords(definitions map[string]any) []any {
|
||||||
result := make(map[string]any, len(definition)+1)
|
result := make([]any, 0, len(definitions))
|
||||||
result["version"] = version
|
for id, raw := range definitions {
|
||||||
for key, value := range definition {
|
record := make(map[string]any)
|
||||||
result[key] = value
|
for key, value := range raw.(map[string]any) {
|
||||||
|
record[key] = value
|
||||||
|
}
|
||||||
|
record["id"] = id
|
||||||
|
result = append(result, record)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -75,7 +79,7 @@ func TestInspectRequirementsEnumeratesCapturedDependenciesAndInactiveNames(t *te
|
|||||||
}, `{{input "session-only"}} {{.session_variable}}`, map[string]any{
|
}, `{{input "session-only"}} {{.session_variable}}`, map[string]any{
|
||||||
"format": "json", "validation_mode": "json_schema", "schema_path": "not-loaded.json",
|
"format": "json", "validation_mode": "json_schema", "schema_path": "not-loaded.json",
|
||||||
})
|
})
|
||||||
engine := requirementsEngine(t, oneVersionPrompt("requirements", "v1", definition), map[string]any{
|
engine := requirementsEngine(t, onePrompt("requirements", definition), map[string]any{
|
||||||
"partial": map[string]any{"model": "partial-model", "api_key_required": true},
|
"partial": map[string]any{"model": "partial-model", "api_key_required": true},
|
||||||
}, promptkit.WithArtifactReader(reader), promptkit.WithLLMClient(countingLLMClient{calls: &modelCalls}))
|
}, promptkit.WithArtifactReader(reader), promptkit.WithLLMClient(countingLLMClient{calls: &modelCalls}))
|
||||||
inspection, err := engine.InspectRequirements(context.Background(), promptkit.RequirementInspectionRequest{
|
inspection, err := engine.InspectRequirements(context.Background(), promptkit.RequirementInspectionRequest{
|
||||||
@@ -85,7 +89,7 @@ func TestInspectRequirementsEnumeratesCapturedDependenciesAndInactiveNames(t *te
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("inspect before artifacts, credentials, and schemas exist: %v", err)
|
t.Fatalf("inspect before artifacts, credentials, and schemas exist: %v", err)
|
||||||
}
|
}
|
||||||
if inspection.PromptID != "requirements" || inspection.PromptVersion == nil || *inspection.PromptVersion != "v1" || inspection.ProfileID != "partial" || !inspection.Complete {
|
if inspection.PromptID != "requirements" || inspection.ProfileID != "partial" || !inspection.Complete {
|
||||||
t.Fatalf("selected context or completeness is wrong: %+v", inspection)
|
t.Fatalf("selected context or completeness is wrong: %+v", inspection)
|
||||||
}
|
}
|
||||||
inputs := make(map[string]promptkit.InputRequirement, len(inspection.Inputs))
|
inputs := make(map[string]promptkit.InputRequirement, len(inspection.Inputs))
|
||||||
@@ -134,10 +138,10 @@ func TestInspectRequirementsEnumeratesCapturedDependenciesAndInactiveNames(t *te
|
|||||||
|
|
||||||
func TestInspectRequirementsUsesPromptIDsAndProfileIdentity(t *testing.T) {
|
func TestInspectRequirementsUsesPromptIDsAndProfileIdentity(t *testing.T) {
|
||||||
prompts := map[string]any{
|
prompts := map[string]any{
|
||||||
"first-prompt": promptDefinitionWithVersion("v1", contractPrompt("first", `{{input "one"}}`, nil, "", noValidationOutput)),
|
"first-prompt": contractPrompt("first", `{{input "one"}}`, nil, "", noValidationOutput),
|
||||||
"second-prompt": promptDefinitionWithVersion("v2", contractPrompt("second", `{{input "two"}}`, nil, "", noValidationOutput)),
|
"second-prompt": contractPrompt("second", `{{input "two"}}`, nil, "", noValidationOutput),
|
||||||
"without-default": contractPrompt("", "plain", nil, "", noValidationOutput),
|
"without-default": contractPrompt("", "plain", nil, "", noValidationOutput),
|
||||||
"direct-required": promptDefinitionWithVersion("v1", contractPrompt("direct", "plain", nil, "", noValidationOutput)),
|
"direct-required": contractPrompt("direct", "plain", nil, "", noValidationOutput),
|
||||||
}
|
}
|
||||||
profiles := map[string]any{
|
profiles := map[string]any{
|
||||||
"first": map[string]any{"model": "first-model"},
|
"first": map[string]any{"model": "first-model"},
|
||||||
@@ -146,13 +150,13 @@ func TestInspectRequirementsUsesPromptIDsAndProfileIdentity(t *testing.T) {
|
|||||||
}
|
}
|
||||||
engine := requirementsEngine(t, prompts, profiles)
|
engine := requirementsEngine(t, prompts, profiles)
|
||||||
first, err := engine.InspectRequirements(context.Background(), promptkit.RequirementInspectionRequest{PromptID: "first-prompt"})
|
first, err := engine.InspectRequirements(context.Background(), promptkit.RequirementInspectionRequest{PromptID: "first-prompt"})
|
||||||
if err != nil || first.PromptVersion == nil || *first.PromptVersion != "v1" || first.ProfileID != "first" || len(first.Inputs) != 1 || first.Inputs[0].Name != "one" {
|
if err != nil || first.ProfileID != "first" || len(first.Inputs) != 1 || first.Inputs[0].Name != "one" {
|
||||||
t.Fatalf("first prompt ID/default profile=(%+v, %v)", first, err)
|
t.Fatalf("first prompt ID/default profile=(%+v, %v)", first, err)
|
||||||
}
|
}
|
||||||
second, err := engine.InspectRequirements(context.Background(), promptkit.RequirementInspectionRequest{
|
second, err := engine.InspectRequirements(context.Background(), promptkit.RequirementInspectionRequest{
|
||||||
PromptID: "second-prompt", ProfileID: "first",
|
PromptID: "second-prompt", ProfileID: "first",
|
||||||
})
|
})
|
||||||
if err != nil || second.PromptVersion == nil || *second.PromptVersion != "v2" || second.ProfileID != "first" || second.Inputs[0].Name != "two" {
|
if err != nil || second.ProfileID != "first" || second.Inputs[0].Name != "two" {
|
||||||
t.Fatalf("second prompt ID/request profile=(%+v, %v)", second, err)
|
t.Fatalf("second prompt ID/request profile=(%+v, %v)", second, err)
|
||||||
}
|
}
|
||||||
if _, err := engine.InspectRequirements(context.Background(), promptkit.RequirementInspectionRequest{PromptID: "First-Prompt"}); !errors.Is(err, promptkit.ErrPromptNotFound) {
|
if _, err := engine.InspectRequirements(context.Background(), promptkit.RequirementInspectionRequest{PromptID: "First-Prompt"}); !errors.Is(err, promptkit.ErrPromptNotFound) {
|
||||||
@@ -178,7 +182,7 @@ func TestInspectRequirementsUsesPromptIDsAndProfileIdentity(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestInspectPromptHashMatchesPreparationForCapturedConfiguration(t *testing.T) {
|
func TestInspectPromptHashMatchesPreparationForCapturedConfiguration(t *testing.T) {
|
||||||
prompts := oneVersionPrompt("hash-equality", "v1", contractPrompt(
|
prompts := onePrompt("hash-equality", contractPrompt(
|
||||||
"profile", "Hello {{.name}}", nil, "", noValidationOutput,
|
"profile", "Hello {{.name}}", nil, "", noValidationOutput,
|
||||||
))
|
))
|
||||||
engine := requirementsEngine(t, prompts, map[string]any{
|
engine := requirementsEngine(t, prompts, map[string]any{
|
||||||
@@ -201,11 +205,11 @@ func TestInspectPromptHashMatchesPreparationForCapturedConfiguration(t *testing.
|
|||||||
|
|
||||||
func TestInspectRequirementsReportsConditionalAndCompleteOptionalInventories(t *testing.T) {
|
func TestInspectRequirementsReportsConditionalAndCompleteOptionalInventories(t *testing.T) {
|
||||||
prompts := map[string]any{
|
prompts := map[string]any{
|
||||||
"conditional": promptDefinitionWithVersion("v1", contractPrompt("profile",
|
"conditional": contractPrompt("profile",
|
||||||
`{{if .mode}}{{input "left"}}{{else}}{{input "right"}}{{end}}`, nil, "", noValidationOutput)),
|
`{{if .mode}}{{input "left"}}{{else}}{{input "right"}}{{end}}`, nil, "", noValidationOutput),
|
||||||
"optional": promptDefinitionWithVersion("v1", contractPrompt("profile", `{{index . "lookup"}}`,
|
"optional": contractPrompt("profile", `{{index . "lookup"}}`,
|
||||||
[]any{map[string]any{"name": "declared-optional"}}, "", noValidationOutput)),
|
[]any{map[string]any{"name": "declared-optional"}}, "", noValidationOutput),
|
||||||
"empty": promptDefinitionWithVersion("v1", contractPrompt("profile", "plain", nil, "", noValidationOutput)),
|
"empty": contractPrompt("profile", "plain", nil, "", noValidationOutput),
|
||||||
}
|
}
|
||||||
engine := requirementsEngine(t, prompts, map[string]any{"profile": map[string]any{"model": "partial"}})
|
engine := requirementsEngine(t, prompts, map[string]any{"profile": map[string]any{"model": "partial"}})
|
||||||
conditional, err := engine.InspectRequirements(context.Background(), promptkit.RequirementInspectionRequest{PromptID: "conditional"})
|
conditional, err := engine.InspectRequirements(context.Background(), promptkit.RequirementInspectionRequest{PromptID: "conditional"})
|
||||||
@@ -230,7 +234,7 @@ func TestInspectRequirementsBeforePreparationAndWithDirectSessionBypass(t *testi
|
|||||||
definition := contractPrompt("profile", `Name={{.name}} Transcript={{input "transcript"}}{{if false}}ignored {{input "skipped"}} {{.inactive}}{{end}}`, []any{
|
definition := contractPrompt("profile", `Name={{.name}} Transcript={{input "transcript"}}{{if false}}ignored {{input "skipped"}} {{.inactive}}{{end}}`, []any{
|
||||||
map[string]any{"name": "transcript", "required": true},
|
map[string]any{"name": "transcript", "required": true},
|
||||||
}, `{{.session_var}} {{input "session-only"}}`, noValidationOutput)
|
}, `{{.session_var}} {{input "session-only"}}`, noValidationOutput)
|
||||||
engine := requirementsEngine(t, oneVersionPrompt("ready", "v1", definition), map[string]any{
|
engine := requirementsEngine(t, onePrompt("ready", definition), map[string]any{
|
||||||
"profile": map[string]any{"endpoint": "https://example.test/v1", "model": "offline"},
|
"profile": map[string]any{"endpoint": "https://example.test/v1", "model": "offline"},
|
||||||
})
|
})
|
||||||
inspection, err := engine.InspectRequirements(context.Background(), promptkit.RequirementInspectionRequest{
|
inspection, err := engine.InspectRequirements(context.Background(), promptkit.RequirementInspectionRequest{
|
||||||
@@ -280,7 +284,7 @@ func TestInspectRequirementsReturnsIndependentValuesAndCanOverlapPreparation(t *
|
|||||||
definition := contractPrompt("profile", `{{if .decision}}{{input "conditional"}}{{end}} {{input "declared"}}`, []any{
|
definition := contractPrompt("profile", `{{if .decision}}{{input "conditional"}}{{end}} {{input "declared"}}`, []any{
|
||||||
map[string]any{"name": "declared", "required": true, "description": "captured description"},
|
map[string]any{"name": "declared", "required": true, "description": "captured description"},
|
||||||
}, `{{.session}}`, noValidationOutput)
|
}, `{{.session}}`, noValidationOutput)
|
||||||
engine := requirementsEngine(t, oneVersionPrompt("owned", "v1", definition), map[string]any{
|
engine := requirementsEngine(t, onePrompt("owned", definition), map[string]any{
|
||||||
"profile": map[string]any{"endpoint": "https://example.test/v1", "model": "offline"},
|
"profile": map[string]any{"endpoint": "https://example.test/v1", "model": "offline"},
|
||||||
})
|
})
|
||||||
request := promptkit.RequirementInspectionRequest{PromptID: "owned"}
|
request := promptkit.RequirementInspectionRequest{PromptID: "owned"}
|
||||||
@@ -288,10 +292,6 @@ func TestInspectRequirementsReturnsIndependentValuesAndCanOverlapPreparation(t *
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if first.PromptVersion == nil || *first.PromptVersion != "v1" {
|
|
||||||
t.Fatalf("requirement inspection label = %v, want v1", first.PromptVersion)
|
|
||||||
}
|
|
||||||
*first.PromptVersion = "mutated label"
|
|
||||||
for index := range first.Inputs {
|
for index := range first.Inputs {
|
||||||
if first.Inputs[index].Name == "declared" {
|
if first.Inputs[index].Name == "declared" {
|
||||||
first.Inputs[index].Name = "mutated"
|
first.Inputs[index].Name = "mutated"
|
||||||
@@ -312,8 +312,7 @@ func TestInspectRequirementsReturnsIndependentValuesAndCanOverlapPreparation(t *
|
|||||||
description = input.Description
|
description = input.Description
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if second.PromptVersion == nil || *second.PromptVersion != "v1" ||
|
if second.Inputs[0].Name == "mutated" || second.Variables[0].Name != "decision" ||
|
||||||
second.Inputs[0].Name == "mutated" || second.Variables[0].Name != "decision" ||
|
|
||||||
description == nil || *description != "captured description" ||
|
description == nil || *description != "captured description" ||
|
||||||
len(second.Issues) != 1 || second.Issues[0].Description == "mutated issue" {
|
len(second.Issues) != 1 || second.Issues[0].Description == "mutated issue" {
|
||||||
t.Fatalf("result mutation reached captured state or later result: (%+v, %v)", second, err)
|
t.Fatalf("result mutation reached captured state or later result: (%+v, %v)", second, err)
|
||||||
@@ -352,7 +351,7 @@ func TestInspectRequirementsReturnsIndependentValuesAndCanOverlapPreparation(t *
|
|||||||
func TestInspectRequirementsDoesNotEchoUnrelatedPrivateValues(t *testing.T) {
|
func TestInspectRequirementsDoesNotEchoUnrelatedPrivateValues(t *testing.T) {
|
||||||
t.Setenv("PROMPTKIT_REQUIREMENTS_SECRET", "credential-value-marker")
|
t.Setenv("PROMPTKIT_REQUIREMENTS_SECRET", "credential-value-marker")
|
||||||
definition := contractPrompt("profile", `template-body-marker {{input "required-input"}} {{.known}}`, nil, `{{.session}}`, noValidationOutput)
|
definition := contractPrompt("profile", `template-body-marker {{input "required-input"}} {{.known}}`, nil, `{{.session}}`, noValidationOutput)
|
||||||
engine := requirementsEngine(t, oneVersionPrompt("privacy", "v1", definition), map[string]any{
|
engine := requirementsEngine(t, onePrompt("privacy", definition), map[string]any{
|
||||||
"profile": map[string]any{"endpoint": "https://example.test/v1", "model": "offline", "api_key_env": "PROMPTKIT_REQUIREMENTS_SECRET"},
|
"profile": map[string]any{"endpoint": "https://example.test/v1", "model": "offline", "api_key_env": "PROMPTKIT_REQUIREMENTS_SECRET"},
|
||||||
})
|
})
|
||||||
inspection, err := engine.InspectRequirements(context.Background(), promptkit.RequirementInspectionRequest{
|
inspection, err := engine.InspectRequirements(context.Background(), promptkit.RequirementInspectionRequest{
|
||||||
|
|||||||
Reference in New Issue
Block a user