Remove prompt version selectors

This commit is contained in:
2026-10-17 05:47:14 +00:00
parent d40a010538
commit 8cbb7c0daf
36 changed files with 182 additions and 253 deletions

View File

@@ -114,7 +114,7 @@ func newAssembledWorkflowFixture(b *testing.B, name string) assembledWorkflowFix
b.Fatal(err)
}
request := promptkit.RunRequest{
PromptID: "workflow", PromptVersion: "v1", Vars: map[string]string{"name": "Ada"},
PromptID: "workflow", Vars: map[string]string{"name": "Ada"},
}
return assembledWorkflowFixture{
engine: engine, request: request, expectedMessage: expectedMessage, response: response,

View File

@@ -25,7 +25,6 @@ func toDomainRunRequest(req RunRequest) (domain.RunRequest, error) {
}
return domain.RunRequest{
PromptID: req.PromptID,
PromptVersion: req.PromptVersion,
ProfileID: req.ProfileID,
SessionID: req.SessionID,
APIKey: req.APIKey,

View File

@@ -141,7 +141,7 @@ if err != nil {
}
if len(prompts) > 0 {
selected := prompts[0]
inspection, err := engine.InspectPrompt(ctx, selected.ID, selected.Version)
inspection, err := engine.InspectPrompt(ctx, selected.ID)
if err != nil {
return err
}
@@ -286,7 +286,7 @@ declared inputs and output workflow without creating placeholder inputs or
resolving a profile:
```go
inspection, err := engine.InspectPrompt(ctx, "meeting.summary", "")
inspection, err := engine.InspectPrompt(ctx, "meeting.summary")
if err != nil {
return err
}

View File

@@ -46,8 +46,8 @@ admission, or model collaborators. The root
exact contract.
`InspectRequirements` uses the same metadata selection to resolve the
request-profile/default identity, then obtains the exact captured requirement
snapshot by the selected prompt ID and version. The analyzer receives only
request-profile/default identity, then obtains the captured requirement
snapshot by the selected prompt ID. The analyzer receives only
those identity fields rather than an execution definition. It analyzes the
snapshot with the supplied caller variables and normalized direct-session
bypass; it does not resolve target readiness or enter the preparation

View File

@@ -46,7 +46,7 @@ real loader and final-value handoff.
## Prompt Definitions
The configuration adapter indexes each prompt by exact ID and version,
The configuration adapter indexes each prompt by exact ID,
materializes file-backed message content using the exact effective field's
origin and resource context, and checks static message/session template syntax
at construction. It stores captured content, compiled templates, declared
@@ -65,7 +65,7 @@ configuration would replace origins of unchanged content-file fields.
The runner selects full definitions from this index for preparation and uses
captured prompt metadata for `InspectPrompt` and `InspectRequirements`; the
internal requirement snapshot lookup selects by exact prompt ID and version.
internal requirement snapshot lookup uses the selected prompt ID alone.
These paths do not rescan configuration or reopen message files. `InspectPrompt`
returns declared metadata without rendering or resolving profile, input, or
schema resources, and its public shape and prompt hashes do not include the
@@ -73,8 +73,8 @@ captured presence state. Runtime rendering still checks request variables and
input helpers. The [prompt adapter tests](../../internal/configuration/prompts_test.go)
cover resource origins, context containment, capture, and selection.
The configuration adapter shares exact ID/version selection across its
internal prompt lookups. The execution snapshot lookup returns an owned prompt
The configuration adapter shares ID-only selection across its internal prompt
lookups. The execution snapshot lookup returns an owned prompt
definition and cached hash; metadata inspection returns owned input metadata
without copying execution templates. Profile selection likewise has an
identity-only lookup for consumers that do not need the execution target,

View File

@@ -416,6 +416,14 @@ Validation: `GOWORK=off go test ./...` and focused vet of modified packages.
Search declarations/call sites for remaining selection/ambiguity logic; descriptive
label references are valid and should not be blanket-deleted.
Completion: request-side version selectors and version parameters have been
removed from prompt lookup, inspection, requirement analysis, and smoke-test
selection. Generated structured-schema names now derive from the prompt ID;
result-side descriptive label fields remain. Updated the consumer guide and
GoDoc to reflect ID-only selection. Validation passed: `GOWORK=off go test
./...`, focused `GOWORK=off go vet` for modified packages,
`GOWORK=off python3 scripts/check-examples.py`, and `git diff --check`.
## Stage 6: Carry Optional Prompt Labels Through Results
Scope: presence-aware metadata across internal values and the facade.

View File

@@ -24,9 +24,8 @@ var (
// ErrInvalidRequest identifies a request whose required values, overrides,
// credentials, or effective settings are invalid.
ErrInvalidRequest = errors.New("invalid run request")
// ErrPromptNotFound identifies a requested prompt ID or version that is not
// present in the selected prompt source. It does not also match
// ErrPromptLoad.
// ErrPromptNotFound identifies a requested prompt ID that is not present in
// the captured configuration. It does not also match ErrPromptLoad.
ErrPromptNotFound = errors.New("prompt not found")
// ErrProfileNotFound identifies a selected profile ID that is absent from
// every configured profile source. It does not also match ErrProfileLoad.
@@ -242,14 +241,11 @@ func NewEngine(cfg Config, opts ...Option) (*Engine, error) {
return &Engine{internal: assembled}, nil
}
// InspectPrompt resolves one explicit prompt definition without selecting a
// profile or starting execution work.
// InspectPrompt resolves one prompt ID without selecting a profile or starting
// execution work.
//
// InspectPrompt requires a nonblank promptID. It passes nonblank promptID and
// promptVersion values unchanged to the engine's ordinary, case-sensitive
// prompt selection. An empty version succeeds only when that ID has one
// version; a nonempty version selects one exact ID/version pair from the
// captured configuration snapshot.
// InspectPrompt requires a nonblank promptID and performs an exact,
// case-sensitive lookup in the captured configuration snapshot.
//
// A successful result proves that the selected definition and any referenced
// message content files were structurally loaded. Inputs are returned in
@@ -268,21 +264,19 @@ func NewEngine(cfg Config, opts ...Option) (*Engine, error) {
// or content files; construct another Engine to observe source changes.
//
// A nil Engine returns an error matching ErrInvalidConfig. A blank prompt ID
// matches ErrInvalidRequest. An absent exact ID or version matches
// ErrPromptNotFound and not ErrPromptLoad. An ambiguous omitted version matches
// ErrPromptLoad. Invalid definitions and resource failures reject construction
// instead. Cancellation during lookup preserves the context error. InspectPrompt
// returns no partial result on error.
// matches ErrInvalidRequest. An absent exact ID matches ErrPromptNotFound and
// not ErrPromptLoad. Invalid definitions and resource failures reject
// construction instead. Cancellation during lookup preserves the context
// error. InspectPrompt returns no partial result on error.
func (e *Engine) InspectPrompt(
ctx context.Context,
promptID string,
promptVersion string,
) (*PromptInspection, error) {
if e == nil || e.internal == nil {
return nil, fmt.Errorf("%w: engine is nil", ErrInvalidConfig)
}
inspection, err := e.internal.InspectPrompt(ctx, promptID, promptVersion)
inspection, err := e.internal.InspectPrompt(ctx, promptID)
if err != nil {
return nil, mapPublicError(err)
}

View File

@@ -18,9 +18,8 @@ func (r RunRequest) GoString() string {
func (r RunRequest) redactedString() string {
return fmt.Sprintf(
"promptkit.RunRequest{PromptID:%q PromptVersion:%q ProfileID:%q APIKeySet:%t Inputs:%d Vars:%d ExecutionSet:%t ValidationSet:%t AppendedMessages:%d}",
"promptkit.RunRequest{PromptID:%q ProfileID:%q APIKeySet:%t Inputs:%d Vars:%d ExecutionSet:%t ValidationSet:%t AppendedMessages:%d}",
r.PromptID,
r.PromptVersion,
r.ProfileID,
r.APIKey != "",
len(r.Inputs),

View File

@@ -227,7 +227,7 @@ func BenchmarkInspectionSelection(b *testing.B) {
b.Fatal(err)
}
ctx := context.Background()
definition, hash, err := result.GetPromptSnapshot(ctx, "inspection", "1")
definition, hash, err := result.GetPromptSnapshot(ctx, "inspection")
if err != nil || definition.ID != "inspection" || definition.Version != "1" || hash == "" ||
len(definition.Inputs) != 1 || definition.Inputs[0].Name != "transcript" || !definition.Inputs[0].Required {
b.Fatalf("prompt lookup fixture is invalid: definition=%+v hash=%q err=%v", definition, hash, err)
@@ -237,7 +237,7 @@ func BenchmarkInspectionSelection(b *testing.B) {
len(profile.ResolvedTarget.ExtraParams["provider_options"].(map[string]any)) != scenario.entries {
b.Fatalf("profile lookup fixture is invalid: profile=%+v err=%v", profile, err)
}
inspection, err := result.GetPromptInspection(ctx, "inspection", "1")
inspection, err := result.GetPromptInspection(ctx, "inspection")
if err != nil || inspection.PromptID != "inspection" || inspection.PromptVersion != "1" ||
len(inspection.Inputs) != 1 || inspection.Inputs[0].Name != "transcript" {
b.Fatalf("prompt inspection fixture is invalid: inspection=%+v err=%v", inspection, err)
@@ -250,7 +250,7 @@ func BenchmarkInspectionSelection(b *testing.B) {
b.Run("prompt/"+scenario.name, func(b *testing.B) {
b.ReportAllocs()
for b.Loop() {
definition, hash, err := result.GetPromptSnapshot(ctx, "inspection", "1")
definition, hash, err := result.GetPromptSnapshot(ctx, "inspection")
if err != nil {
b.Fatal(err)
}
@@ -262,7 +262,7 @@ func BenchmarkInspectionSelection(b *testing.B) {
b.Run("prompt_inspection/"+scenario.name, func(b *testing.B) {
b.ReportAllocs()
for b.Loop() {
inspection, err := result.GetPromptInspection(ctx, "inspection", "1")
inspection, err := result.GetPromptInspection(ctx, "inspection")
if err != nil {
b.Fatal(err)
}

View File

@@ -286,7 +286,7 @@ func (state *loaded) readContent(fieldPath configkit.Path, name string, lookupOr
return string(content), nil
}
func (state *loaded) lookupPromptEntry(id, version string) (*promptEntry, error) {
func (state *loaded) lookupPromptEntry(id string) (*promptEntry, error) {
if state == nil || strings.TrimSpace(id) == "" {
return nil, errPromptNotFound
}
@@ -322,7 +322,7 @@ func promptLookupError(err error) error {
}
func (state *loaded) prompt(id string) (*domain.PromptDefinition, domain.PromptInspection, error) {
entry, err := state.lookupPromptEntry(id, "")
entry, err := state.lookupPromptEntry(id)
if err != nil {
return nil, domain.PromptInspection{}, err
}
@@ -330,13 +330,12 @@ func (state *loaded) prompt(id string) (*domain.PromptDefinition, domain.PromptI
}
// GetPromptSnapshot returns an independently owned captured definition and its
// construction-time hash. The version argument is retained temporarily at the
// adapter boundary and does not participate in lookup.
func (state *loaded) GetPromptSnapshot(ctx context.Context, id, version string) (*domain.PromptDefinition, string, error) {
// construction-time hash.
func (state *loaded) GetPromptSnapshot(ctx context.Context, id string) (*domain.PromptDefinition, string, error) {
if err := ctx.Err(); err != nil {
return nil, "", err
}
entry, err := state.lookupPromptEntry(id, version)
entry, err := state.lookupPromptEntry(id)
if err != nil {
return nil, "", promptLookupError(err)
}
@@ -345,11 +344,11 @@ func (state *loaded) GetPromptSnapshot(ctx context.Context, id, version string)
// GetPromptInspection returns an independently owned inspection of one
// captured prompt without copying its execution templates.
func (state *loaded) GetPromptInspection(ctx context.Context, id, version string) (*domain.PromptInspection, error) {
func (state *loaded) GetPromptInspection(ctx context.Context, id string) (*domain.PromptInspection, error) {
if err := ctx.Err(); err != nil {
return nil, err
}
entry, err := state.lookupPromptEntry(id, version)
entry, err := state.lookupPromptEntry(id)
if err != nil {
return nil, promptLookupError(err)
}
@@ -357,13 +356,13 @@ func (state *loaded) GetPromptInspection(ctx context.Context, id, version string
}
// GetPromptDefinition implements the runner's prompt lookup boundary.
func (state *loaded) GetPromptDefinition(ctx context.Context, id, version string) (*domain.PromptDefinition, error) {
definition, _, err := state.GetPromptSnapshot(ctx, id, version)
func (state *loaded) GetPromptDefinition(ctx context.Context, id string) (*domain.PromptDefinition, error) {
definition, _, err := state.GetPromptSnapshot(ctx, id)
return definition, err
}
// GetCompiledTemplates returns construction-time parses for one prompt ID.
func (state *loaded) GetCompiledTemplates(id, version string) (prompt.CompiledTemplates, bool) {
func (state *loaded) GetCompiledTemplates(id string) (prompt.CompiledTemplates, bool) {
if state == nil {
return prompt.CompiledTemplates{}, false
}
@@ -377,7 +376,7 @@ func (state *loaded) GetCompiledTemplates(id, version string) (prompt.CompiledTe
// GetRequirementSnapshot returns captured templates and input metadata for
// one prompt ID. Returned metadata and slices are independently
// owned; the compiled templates are shared immutable construction-time parses.
func (state *loaded) GetRequirementSnapshot(id, version string) (prompt.RequirementSnapshot, bool) {
func (state *loaded) GetRequirementSnapshot(id string) (prompt.RequirementSnapshot, bool) {
if state == nil {
return prompt.RequirementSnapshot{}, false
}

View File

@@ -161,11 +161,11 @@ func TestPromptInspectionLookupMatchesSnapshotSelectionAndOwnsInputs(t *testing.
}
{
inspection, err := state.GetPromptInspection(context.Background(), "selected", "")
inspection, err := state.GetPromptInspection(context.Background(), "selected")
if err != nil {
t.Fatalf("inspect prompt ID: %v", err)
}
definition, hash, err := state.GetPromptSnapshot(context.Background(), "selected", "")
definition, hash, err := state.GetPromptSnapshot(context.Background(), "selected")
if err != nil {
t.Fatalf("snapshot prompt ID: %v", err)
}
@@ -180,30 +180,30 @@ func TestPromptInspectionLookupMatchesSnapshotSelectionAndOwnsInputs(t *testing.
}
}
owned, err := state.GetPromptInspection(context.Background(), "selected", "")
owned, err := state.GetPromptInspection(context.Background(), "selected")
if err != nil {
t.Fatal(err)
}
owned.Inputs[0].Name = "caller mutation"
owned.Inputs[0].Description = "caller mutation"
again, err := state.GetPromptInspection(context.Background(), "selected", "")
again, err := state.GetPromptInspection(context.Background(), "selected")
if err != nil || again.Inputs[0].Name != "document" || again.Inputs[0].Description != "source document" {
t.Fatalf("inspection mutation escaped into captured state: inspection=%+v err=%v", again, err)
}
for _, id := range []string{"missing", " "} {
inspection, err := state.GetPromptInspection(context.Background(), id, "")
inspection, err := state.GetPromptInspection(context.Background(), id)
if inspection != nil || !errors.Is(err, promptdef.ErrPromptDefinitionNotFound) {
t.Errorf("inspection lookup %q=(%+v, %v), want not found", id, inspection, err)
}
definition, _, err := state.GetPromptSnapshot(context.Background(), id, "")
definition, _, err := state.GetPromptSnapshot(context.Background(), id)
if definition != nil || !errors.Is(err, promptdef.ErrPromptDefinitionNotFound) {
t.Errorf("snapshot lookup %q=(%+v, %v), want not found", id, definition, err)
}
}
ctx, cancel := context.WithCancel(context.Background())
cancel()
if _, err := state.GetPromptInspection(ctx, "selected", ""); !errors.Is(err, context.Canceled) {
if _, err := state.GetPromptInspection(ctx, "selected"); !errors.Is(err, context.Canceled) {
t.Errorf("canceled inspection selection error=%v", err)
}
}
@@ -269,7 +269,7 @@ func TestRequirementSnapshotCapturesMetadataPresenceAndNormalizedValues(t *testi
t.Fatal(err)
}
snapshot, ok := state.GetRequirementSnapshot("example", "")
snapshot, ok := state.GetRequirementSnapshot("example")
if !ok || len(snapshot.Inputs) != 4 || len(snapshot.Templates.Messages) != 1 || snapshot.Templates.Session == nil {
t.Fatalf("requirement snapshot was not captured: %+v, %t", snapshot, ok)
}
@@ -299,7 +299,7 @@ func TestRequirementSnapshotCapturesMetadataPresenceAndNormalizedValues(t *testi
*snapshot.Inputs[2].ContentType = "caller mutation"
snapshot.Inputs[3].Name = "caller mutation"
snapshot.Templates.Messages[0] = nil
again, ok := state.GetRequirementSnapshot("example", "")
again, ok := state.GetRequirementSnapshot("example")
if !ok || *again.Inputs[2].ContentType != "" || again.Inputs[3].Name != "normalized" || again.Templates.Messages[0] == nil {
t.Fatalf("snapshot mutation escaped into captured state: %+v, %t", again, ok)
}

View File

@@ -61,7 +61,6 @@ type CacheControl struct {
// RunRequest represents a request to generate a single artifact.
type RunRequest struct {
PromptID string
PromptVersion string
ProfileID string
SessionID string
APIKey string `json:"-" yaml:"-"`
@@ -135,7 +134,7 @@ type Artifact struct {
Hash string
}
// PromptIdentity identifies one configured prompt version.
// PromptIdentity identifies one configured prompt and its descriptive version label.
type PromptIdentity struct {
ID string
Version string

View File

@@ -39,7 +39,6 @@ type SmokeTestRequest struct {
Kind SmokeTestKind
BackendID string
PromptID string
PromptVersion string
ProfileID string
Execution *ExecutionTargetOverride
APIKey string `json:"-" yaml:"-"`

View File

@@ -187,8 +187,8 @@ func fileSource(name string) (fs.FS, string, string, error) {
return os.DirFS(directory), filepath.ToSlash(base), directory, nil
}
func (e *Engine) InspectPrompt(ctx context.Context, id, version string) (*domain.PromptInspection, error) {
return e.runner.InspectPrompt(ctx, id, version)
func (e *Engine) InspectPrompt(ctx context.Context, id string) (*domain.PromptInspection, error) {
return e.runner.InspectPrompt(ctx, id)
}
func (e *Engine) InspectRequirements(
ctx context.Context,

View File

@@ -19,8 +19,7 @@ var (
)
type rendererBenchmarkIdentity struct {
id string
version string
id string
}
type rendererBenchmarkLookup struct {
@@ -28,8 +27,8 @@ type rendererBenchmarkLookup struct {
templates CompiledTemplates
}
func (lookup rendererBenchmarkLookup) GetCompiledTemplates(id, version string) (CompiledTemplates, bool) {
if id != lookup.identity.id || version != lookup.identity.version {
func (lookup rendererBenchmarkLookup) GetCompiledTemplates(id string) (CompiledTemplates, bool) {
if id != lookup.identity.id {
return CompiledTemplates{}, false
}
return lookup.templates, true
@@ -148,7 +147,7 @@ func BenchmarkRetainedRenderedOutput(b *testing.B) {
}
compiled := CompiledTemplates{Messages: []*template.Template{mustCompileRendererBenchmarkTemplate(b, content)}}
renderer := NewCompiledRenderer(rendererBenchmarkLookup{
identity: rendererBenchmarkIdentity{id: definition.ID, version: definition.Version},
identity: rendererBenchmarkIdentity{id: definition.ID},
templates: compiled,
})
inputs := map[string]*domain.Artifact{"document": {Name: "document", Body: body}}
@@ -228,7 +227,7 @@ func newCompiledRenderingBenchmarkCase(
return compiledRenderingBenchmarkCase{
name: name,
renderer: NewCompiledRenderer(rendererBenchmarkLookup{
identity: rendererBenchmarkIdentity{id: definition.ID, version: definition.Version},
identity: rendererBenchmarkIdentity{id: definition.ID},
templates: compiled,
}),
definition: definition, inputs: inputs, vars: vars, ctx: context.Background(),

View File

@@ -59,7 +59,7 @@ func (r *goRenderer) Render(ctx context.Context, definition *domain.PromptDefini
var compiled CompiledTemplates
if r.templates != nil {
var found bool
compiled, found = r.templates.GetCompiledTemplates(definition.ID, definition.Version)
compiled, found = r.templates.GetCompiledTemplates(definition.ID)
if !found || len(compiled.Messages) != len(definition.Templates) {
return nil, fmt.Errorf("%w: captured templates are unavailable", ErrRenderFailure)
}

View File

@@ -518,8 +518,7 @@ func TestCompiledRendererKeepsConcurrentRequestsIndependent(t *testing.T) {
t.Fatalf("compile message template: %v", err)
}
renderer := NewCompiledRenderer(compiledRendererTestLookup{
id: promptID,
version: version,
id: promptID,
templates: CompiledTemplates{
Session: sessionTemplate,
Messages: []*template.Template{messageTemplate},
@@ -562,12 +561,12 @@ func TestCompiledRendererKeepsConcurrentRequestsIndependent(t *testing.T) {
}
type compiledRendererTestLookup struct {
id, version string
templates CompiledTemplates
id string
templates CompiledTemplates
}
func (lookup compiledRendererTestLookup) GetCompiledTemplates(id, version string) (CompiledTemplates, bool) {
if id != lookup.id || version != lookup.version {
func (lookup compiledRendererTestLookup) GetCompiledTemplates(id string) (CompiledTemplates, bool) {
if id != lookup.id {
return CompiledTemplates{}, false
}
return lookup.templates, true

View File

@@ -27,7 +27,7 @@ type RequirementSnapshot struct {
// TemplateLookup provides parsed templates for a captured prompt identity.
type TemplateLookup interface {
GetCompiledTemplates(id, version string) (CompiledTemplates, bool)
GetCompiledTemplates(id string) (CompiledTemplates, bool)
}
// CompileTemplate checks static syntax with the same grammar and function

View File

@@ -12,5 +12,5 @@ var ErrPromptDefinitionNotFound = errors.New("prompt definition not found")
// Repository selects prompt definitions from a captured index.
type Repository interface {
GetPromptDefinition(ctx context.Context, id string, version string) (*domain.PromptDefinition, error)
GetPromptDefinition(ctx context.Context, id string) (*domain.PromptDefinition, error)
}

View File

@@ -680,7 +680,7 @@ func TestRunnerPreparedExecutionDetachesTransferredSnapshotSources(t *testing.T)
reader, renderer, llmClient, validator, nil,
)
request := domain.RunRequest{
PromptID: "p", PromptVersion: "1", ProfileID: "exec",
PromptID: "p", ProfileID: "exec",
Inputs: map[string]domain.ArtifactRef{
"transcript": {Type: domain.ArtifactRefFile, URI: "source"},
},

View File

@@ -119,7 +119,7 @@ func newPreparedSnapshotBenchmarkRunner(
nil,
)
request := domain.RunRequest{
PromptID: "p", PromptVersion: "1", ProfileID: "exec",
PromptID: "p", ProfileID: "exec",
Inputs: singleInputRef(), Vars: map[string]string{"name": "Ada"},
AppendedMessages: []domain.RenderedMessage{{
Role: domain.RoleAssistant, Content: "appended message",

View File

@@ -14,14 +14,10 @@ type resolvedPromptDefinition struct {
}
type promptInspectionRepository interface {
GetPromptInspection(context.Context, string, string) (*domain.PromptInspection, error)
GetPromptInspection(context.Context, string) (*domain.PromptInspection, error)
}
func (r *Runner) resolvePromptDefinition(
ctx context.Context,
promptID string,
promptVersion string,
) (*resolvedPromptDefinition, error) {
func (r *Runner) resolvePromptDefinition(ctx context.Context, promptID string) (*resolvedPromptDefinition, error) {
if strings.TrimSpace(promptID) == "" {
return nil, fmt.Errorf("%w: prompt id is required", ErrInvalidRequest)
}
@@ -33,11 +29,11 @@ func (r *Runner) resolvePromptDefinition(
var hash string
var err error
if indexed, ok := r.promptDefs.(interface {
GetPromptSnapshot(context.Context, string, string) (*domain.PromptDefinition, string, error)
GetPromptSnapshot(context.Context, string) (*domain.PromptDefinition, string, error)
}); ok {
definition, hash, err = indexed.GetPromptSnapshot(ctx, promptID, promptVersion)
definition, hash, err = indexed.GetPromptSnapshot(ctx, promptID)
} else {
definition, err = r.promptDefs.GetPromptDefinition(ctx, promptID, promptVersion)
definition, err = r.promptDefs.GetPromptDefinition(ctx, promptID)
}
if err != nil {
return nil, fmt.Errorf("%w: %w", ErrPromptLoad, err)
@@ -55,11 +51,7 @@ func (r *Runner) resolvePromptDefinition(
return &resolvedPromptDefinition{definition: definition, hash: hash}, nil
}
func (r *Runner) resolvePromptInspection(
ctx context.Context,
promptID string,
promptVersion string,
) (*domain.PromptInspection, error) {
func (r *Runner) resolvePromptInspection(ctx context.Context, promptID string) (*domain.PromptInspection, error) {
if strings.TrimSpace(promptID) == "" {
return nil, fmt.Errorf("%w: prompt id is required", ErrInvalidRequest)
}
@@ -67,7 +59,7 @@ func (r *Runner) resolvePromptInspection(
return nil, fmt.Errorf("%w: prompt repository is not configured", ErrPromptLoad)
}
if indexed, ok := r.promptDefs.(promptInspectionRepository); ok {
inspection, err := indexed.GetPromptInspection(ctx, promptID, promptVersion)
inspection, err := indexed.GetPromptInspection(ctx, promptID)
if err != nil {
return nil, fmt.Errorf("%w: %w", ErrPromptLoad, err)
}
@@ -77,7 +69,7 @@ func (r *Runner) resolvePromptInspection(
return inspection, nil
}
selection, err := r.resolvePromptDefinition(ctx, promptID, promptVersion)
selection, err := r.resolvePromptDefinition(ctx, promptID)
if err != nil {
return nil, err
}
@@ -93,11 +85,7 @@ func (r *Runner) resolvePromptInspection(
}
// InspectPrompt resolves one explicit prompt without execution work.
func (r *Runner) InspectPrompt(
ctx context.Context,
promptID string,
promptVersion string,
) (*domain.PromptInspection, error) {
func (r *Runner) InspectPrompt(ctx context.Context, promptID string) (*domain.PromptInspection, error) {
if strings.TrimSpace(promptID) == "" {
return nil, fmt.Errorf("%w: prompt id is required", ErrInvalidRequest)
}
@@ -107,5 +95,5 @@ func (r *Runner) InspectPrompt(
default:
}
return r.resolvePromptInspection(ctx, promptID, promptVersion)
return r.resolvePromptInspection(ctx, promptID)
}

View File

@@ -15,41 +15,35 @@ type inspectionPromptRepository struct {
err error
calls int
id string
version string
}
type promptMetadataRepository struct {
inspection domain.PromptInspection
inspectionErr error
lookupID string
lookupVersion string
}
func (r *inspectionPromptRepository) GetPromptDefinition(
_ context.Context,
id string,
version string,
) (*domain.PromptDefinition, error) {
r.calls++
r.id = id
r.version = version
if r.err != nil {
return nil, r.err
}
return r.definition, nil
}
func (r *promptMetadataRepository) GetPromptDefinition(context.Context, string, string) (*domain.PromptDefinition, error) {
func (r *promptMetadataRepository) GetPromptDefinition(context.Context, string) (*domain.PromptDefinition, error) {
return nil, errors.New("full prompt definition should not be requested")
}
func (r *promptMetadataRepository) GetPromptInspection(
_ context.Context,
id string,
version string,
) (*domain.PromptInspection, error) {
r.lookupID = id
r.lookupVersion = version
inspection := r.inspection
inspection.Inputs = append([]domain.PromptInput(nil), inspection.Inputs...)
return &inspection, r.inspectionErr
@@ -74,7 +68,7 @@ func TestRunnerInspectPromptResolvesOneDefinitionWithoutExecutionCollaborators(t
repository := &inspectionPromptRepository{definition: definition}
runner := &Runner{promptDefs: repository}
inspection, err := runner.InspectPrompt(context.Background(), " prompt-id ", " version ")
inspection, err := runner.InspectPrompt(context.Background(), " prompt-id ")
if err != nil {
t.Fatalf("inspect prompt: %v", err)
}
@@ -82,8 +76,8 @@ func TestRunnerInspectPromptResolvesOneDefinitionWithoutExecutionCollaborators(t
if err != nil {
t.Fatalf("hash prompt definition: %v", err)
}
if repository.calls != 1 || repository.id != " prompt-id " || repository.version != " version " {
t.Fatalf("prompt lookup=(calls=%d id=%q version=%q), want one unchanged lookup", repository.calls, repository.id, repository.version)
if repository.calls != 1 || repository.id != " prompt-id " {
t.Fatalf("prompt lookup=(calls=%d id=%q), want one unchanged ID lookup", repository.calls, repository.id)
}
if inspection.PromptID != definition.ID ||
inspection.PromptVersion != definition.Version ||
@@ -95,7 +89,7 @@ func TestRunnerInspectPromptResolvesOneDefinitionWithoutExecutionCollaborators(t
}
inspection.Inputs[0].Name = "changed"
second, err := runner.InspectPrompt(context.Background(), " prompt-id ", " version ")
second, err := runner.InspectPrompt(context.Background(), " prompt-id ")
if err != nil {
t.Fatalf("inspect prompt again: %v", err)
}
@@ -112,16 +106,16 @@ func TestRunnerInspectPromptUsesOwnedMetadataWhenRepositorySupportsIt(t *testing
OutputContract: domain.OutputContract{Format: domain.FormatJSON, ValidationMode: domain.ValidationJSON},
}}
runner := &Runner{promptDefs: repository}
inspection, err := runner.InspectPrompt(context.Background(), " requested-id ", " requested-version ")
if err != nil || repository.lookupID != " requested-id " || repository.lookupVersion != " requested-version " ||
inspection, err := runner.InspectPrompt(context.Background(), " requested-id ")
if err != nil || repository.lookupID != " requested-id " ||
inspection.PromptID != "captured.prompt" || inspection.PromptVersion != "v2" ||
inspection.PromptHash != "cached-prompt-hash" || inspection.DefaultProfileID != "partial-profile" ||
!reflect.DeepEqual(inspection.Inputs, repository.inspection.Inputs) || inspection.OutputContract != repository.inspection.OutputContract {
t.Fatalf("metadata inspection=(%+v, %v), lookup=(%q,%q)", inspection, err, repository.lookupID, repository.lookupVersion)
t.Fatalf("metadata inspection=(%+v, %v), lookup=%q", inspection, err, repository.lookupID)
}
inspection.Inputs[0].Name = "caller mutation"
inspection.OutputContract.SchemaPath = "caller mutation"
second, err := runner.InspectPrompt(context.Background(), "requested-id", "requested-version")
second, err := runner.InspectPrompt(context.Background(), "requested-id")
if err != nil || second.Inputs[0].Name != "document" || second.OutputContract.SchemaPath != "" {
t.Fatalf("metadata inspection was not caller-owned: (%+v, %v)", second, err)
}
@@ -133,7 +127,7 @@ func TestRunnerInspectPromptUsesCapturedHashWhenMetadataCapabilityIsAbsent(t *te
ID: "captured.prompt", Version: "v1", Inputs: []domain.PromptInput{{Name: "document"}},
},
}
inspection, err := (&Runner{promptDefs: repository}).InspectPrompt(context.Background(), " requested-id ", " requested-version ")
inspection, err := (&Runner{promptDefs: repository}).InspectPrompt(context.Background(), " requested-id ")
if err != nil || inspection.PromptID != "captured.prompt" || inspection.PromptVersion != "v1" ||
inspection.PromptHash != "captured-hash" || inspection.Inputs[0].Name != "document" {
t.Fatalf("captured-hash fallback inspection=(%+v, %v)", inspection, err)
@@ -143,7 +137,7 @@ func TestRunnerInspectPromptUsesCapturedHashWhenMetadataCapabilityIsAbsent(t *te
func TestRunnerInspectPromptClassifiesFailuresWithoutRepositoryWorkAfterCancellation(t *testing.T) {
t.Run("blank ID", func(t *testing.T) {
repository := &inspectionPromptRepository{}
_, err := (&Runner{promptDefs: repository}).InspectPrompt(context.Background(), " \t ", "version")
_, err := (&Runner{promptDefs: repository}).InspectPrompt(context.Background(), " \t ")
if !errors.Is(err, ErrInvalidRequest) || repository.calls != 0 {
t.Fatalf("blank inspection=(%v, calls=%d), want invalid request without lookup", err, repository.calls)
}
@@ -153,7 +147,7 @@ func TestRunnerInspectPromptClassifiesFailuresWithoutRepositoryWorkAfterCancella
ctx, cancel := context.WithCancel(context.Background())
cancel()
repository := &inspectionPromptRepository{}
_, err := (&Runner{promptDefs: repository}).InspectPrompt(ctx, "prompt", "version")
_, err := (&Runner{promptDefs: repository}).InspectPrompt(ctx, "prompt")
if !errors.Is(err, ErrPromptLoad) || !errors.Is(err, context.Canceled) || repository.calls != 0 {
t.Fatalf("canceled inspection=(%v, calls=%d), want prompt load and context identities without lookup", err, repository.calls)
}
@@ -161,7 +155,7 @@ func TestRunnerInspectPromptClassifiesFailuresWithoutRepositoryWorkAfterCancella
t.Run("missing prompt", func(t *testing.T) {
repository := &inspectionPromptRepository{err: promptdef.ErrPromptDefinitionNotFound}
_, err := (&Runner{promptDefs: repository}).InspectPrompt(context.Background(), "missing", "version")
_, err := (&Runner{promptDefs: repository}).InspectPrompt(context.Background(), "missing")
if !errors.Is(err, ErrPromptLoad) || !errors.Is(err, promptdef.ErrPromptDefinitionNotFound) {
t.Fatalf("missing prompt error=%v, want prompt load and not-found identities", err)
}
@@ -179,7 +173,7 @@ func TestRunnerInspectPromptClassifiesFailuresWithoutRepositoryWorkAfterCancella
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
_, err := tc.runner.InspectPrompt(context.Background(), "prompt", "version")
_, err := tc.runner.InspectPrompt(context.Background(), "prompt")
if !errors.Is(err, ErrPromptLoad) {
t.Fatalf("inspection error=%v, want prompt load", err)
}
@@ -202,11 +196,11 @@ func TestRunnerPrepareUsesThePromptInspectionSelectionAndHash(t *testing.T) {
nil,
)
inspection, err := runner.InspectPrompt(context.Background(), definition.ID, definition.Version)
inspection, err := runner.InspectPrompt(context.Background(), definition.ID)
if err != nil {
t.Fatalf("inspect prompt: %v", err)
}
prepared, err := runner.Prepare(context.Background(), domain.RunRequest{PromptID: definition.ID, PromptVersion: definition.Version, ProfileID: "exec"})
prepared, err := runner.Prepare(context.Background(), domain.RunRequest{PromptID: definition.ID, ProfileID: "exec"})
if err != nil {
t.Fatalf("prepare prompt: %v", err)
}

View File

@@ -12,15 +12,14 @@ import (
// RequirementInspectionRequest selects a captured prompt and supplies the
// context used for dependency classification.
type RequirementInspectionRequest struct {
PromptID string
PromptVersion string
ProfileID string
Vars map[string]string
SessionID string
PromptID string
ProfileID string
Vars map[string]string
SessionID string
}
type requirementSnapshotRepository interface {
GetRequirementSnapshot(id, version string) (prompt.RequirementSnapshot, bool)
GetRequirementSnapshot(id string) (prompt.RequirementSnapshot, bool)
}
// InspectRequirements discovers prompt inputs and caller variables without
@@ -40,7 +39,7 @@ func (r *Runner) InspectRequirements(
return nil, fmt.Errorf("%w: %w", ErrPromptLoad, err)
}
selection, err := r.resolvePromptInspection(ctx, req.PromptID, req.PromptVersion)
selection, err := r.resolvePromptInspection(ctx, req.PromptID)
if err != nil {
return nil, err
}
@@ -66,7 +65,7 @@ func (r *Runner) InspectRequirements(
if !ok {
return nil, fmt.Errorf("%w: prompt repository does not provide captured requirement snapshots", ErrPromptLoad)
}
snapshot, ok := repository.GetRequirementSnapshot(selection.PromptID, selection.PromptVersion)
snapshot, ok := repository.GetRequirementSnapshot(selection.PromptID)
if !ok {
return nil, fmt.Errorf("%w: captured requirement snapshot is unavailable", ErrPromptLoad)
}

View File

@@ -12,23 +12,20 @@ import (
)
type requirementInspectionPromptRepository struct {
definition *domain.PromptDefinition
snapshot prompt.RequirementSnapshot
lookupErr error
snapshotFound bool
lookupCalls int
snapshotCalls int
lookupID string
lookupVersion string
snapshotID string
snapshotVersion string
definition *domain.PromptDefinition
snapshot prompt.RequirementSnapshot
lookupErr error
snapshotFound bool
lookupCalls int
snapshotCalls int
lookupID string
snapshotID string
}
type requirementPromptMetadataRepository struct {
*requirementInspectionPromptRepository
inspection domain.PromptInspection
lookupID string
lookupVersion string
inspection domain.PromptInspection
lookupID string
}
type inspectionProfileIdentityRepository struct {
@@ -51,7 +48,6 @@ func (repository *inspectionProfileIdentityRepository) GetProfileIdentity(
func (repository *requirementInspectionPromptRepository) GetPromptDefinition(
context.Context,
string,
string,
) (*domain.PromptDefinition, error) {
return repository.definition, repository.lookupErr
}
@@ -59,10 +55,8 @@ func (repository *requirementInspectionPromptRepository) GetPromptDefinition(
func (repository *requirementPromptMetadataRepository) GetPromptInspection(
_ context.Context,
id string,
version string,
) (*domain.PromptInspection, error) {
repository.lookupID = id
repository.lookupVersion = version
inspection := repository.inspection
inspection.Inputs = append([]domain.PromptInput(nil), inspection.Inputs...)
return &inspection, nil
@@ -71,21 +65,17 @@ func (repository *requirementPromptMetadataRepository) GetPromptInspection(
func (repository *requirementInspectionPromptRepository) GetPromptSnapshot(
_ context.Context,
id string,
version string,
) (*domain.PromptDefinition, string, error) {
repository.lookupCalls++
repository.lookupID = id
repository.lookupVersion = version
return repository.definition, "captured-hash", repository.lookupErr
}
func (repository *requirementInspectionPromptRepository) GetRequirementSnapshot(
id string,
version string,
) (prompt.RequirementSnapshot, bool) {
repository.snapshotCalls++
repository.snapshotID = id
repository.snapshotVersion = version
return repository.snapshot, repository.snapshotFound
}
@@ -111,16 +101,16 @@ func TestRunnerInspectRequirementsUsesCapturedSelectionWithoutExecutionWork(t *t
}}
runner := &Runner{promptDefs: repository, profiles: profiles}
inspection, err := runner.InspectRequirements(context.Background(), RequirementInspectionRequest{
PromptID: " requested ", PromptVersion: " exact-version ", ProfileID: "partial-profile",
PromptID: " requested ", ProfileID: "partial-profile",
Vars: map[string]string{"caller": ""}, SessionID: " direct-session ",
})
if err != nil {
t.Fatalf("inspect requirements: %v", err)
}
if repository.lookupCalls != 1 || repository.lookupID != " requested " || repository.lookupVersion != " exact-version " ||
repository.snapshotCalls != 1 || repository.snapshotID != definition.ID || repository.snapshotVersion != definition.Version {
t.Fatalf("selection lookup=(%d,%q,%q), snapshot=(%d,%q,%q)", repository.lookupCalls, repository.lookupID,
repository.lookupVersion, repository.snapshotCalls, repository.snapshotID, repository.snapshotVersion)
if repository.lookupCalls != 1 || repository.lookupID != " requested " ||
repository.snapshotCalls != 1 || repository.snapshotID != definition.ID {
t.Fatalf("selection lookup=(%d,%q), snapshot=(%d,%q)", repository.lookupCalls, repository.lookupID,
repository.snapshotCalls, repository.snapshotID)
}
if profiles.calls != 1 || profiles.id != "partial-profile" || inspection.PromptID != definition.ID ||
inspection.PromptVersion != definition.Version || inspection.ProfileID != "partial-profile" || !inspection.Complete ||
@@ -158,19 +148,18 @@ func TestRunnerInspectRequirementsUsesPromptMetadataAndExactRequirementSnapshot(
}
inspection, err := (&Runner{promptDefs: promptRepository, profiles: profiles}).InspectRequirements(
context.Background(), RequirementInspectionRequest{
PromptID: " requested-id ", PromptVersion: " requested-version ",
Vars: map[string]string{"caller": "Ada"}, SessionID: " direct-session ",
PromptID: " requested-id ",
Vars: map[string]string{"caller": "Ada"}, SessionID: " direct-session ",
},
)
if err != nil || promptRepository.lookupID != " requested-id " || promptRepository.lookupVersion != " requested-version " ||
baseRepository.snapshotID != "captured-id" || baseRepository.snapshotVersion != "captured-version" ||
if err != nil || promptRepository.lookupID != " requested-id " ||
baseRepository.snapshotID != "captured-id" ||
profiles.identityID != "default-profile" || inspection.PromptID != "captured-id" ||
inspection.PromptVersion != "captured-version" || inspection.ProfileID != "default-profile" ||
!inspection.Complete || len(inspection.Inputs) != 1 || inspection.Inputs[0].Name != "message-input" ||
len(inspection.Variables) != 1 || inspection.Variables[0].Name != "caller" || !inspection.Variables[0].Supplied {
t.Fatalf("metadata-based requirement inspection=(%+v, %v), prompt lookup=(%q,%q), snapshot=(%q,%q), profile=%q",
inspection, err, promptRepository.lookupID, promptRepository.lookupVersion,
baseRepository.snapshotID, baseRepository.snapshotVersion, profiles.identityID)
t.Fatalf("metadata-based requirement inspection=(%+v, %v), prompt lookup=%q, snapshot=%q, profile=%q",
inspection, err, promptRepository.lookupID, baseRepository.snapshotID, profiles.identityID)
}
}
@@ -322,12 +311,12 @@ func TestRunnerInspectRequirementsClassifiesSelectionAndSnapshotFailures(t *test
}
})
t.Run("ambiguous prompt selection", func(t *testing.T) {
ambiguous := errors.New("ambiguous omitted version")
repository := &requirementInspectionPromptRepository{lookupErr: ambiguous}
t.Run("prompt lookup failure", func(t *testing.T) {
lookupFailure := errors.New("prompt lookup failed")
repository := &requirementInspectionPromptRepository{lookupErr: lookupFailure}
_, err := (&Runner{promptDefs: repository}).InspectRequirements(context.Background(), RequirementInspectionRequest{PromptID: "selected"})
if !errors.Is(err, ErrPromptLoad) || !errors.Is(err, ambiguous) || repository.lookupVersion != "" {
t.Fatalf("ambiguous selection error=%v version=%q", err, repository.lookupVersion)
if !errors.Is(err, ErrPromptLoad) || !errors.Is(err, lookupFailure) {
t.Fatalf("prompt lookup error=%v", err)
}
})

View File

@@ -315,7 +315,7 @@ func (r *Runner) resolvePreparation(
return nil, fmt.Errorf("%w: session_id: %v", ErrInvalidRequest, err)
}
promptSelection, err := r.resolvePromptDefinition(ctx, req.PromptID, req.PromptVersion)
promptSelection, err := r.resolvePromptDefinition(ctx, req.PromptID)
if err != nil {
return nil, err
}
@@ -517,22 +517,15 @@ func structuredOutputSpec(def *domain.PromptDefinition, schemaDocument any) *dom
return &domain.StructuredOutputSpec{
Type: domain.StructuredOutputJSONSchema,
JSONSchema: &domain.StructuredOutputJSONSpec{
Name: deriveStructuredSchemaName(def.ID, def.Version),
Name: deriveStructuredSchemaName(def.ID),
Strict: true,
Schema: schemaDocument,
},
}
}
func deriveStructuredSchemaName(promptID string, promptVersion string) string {
func deriveStructuredSchemaName(promptID string) string {
raw := strings.TrimSpace(promptID)
if v := strings.TrimSpace(promptVersion); v != "" {
if raw == "" {
raw = v
} else {
raw = raw + "_" + v
}
}
var b strings.Builder
for _, r := range raw {

View File

@@ -24,10 +24,9 @@ import (
)
type fakePromptRepo struct {
def *domain.PromptDefinition
err error
lastID string
lastVersion string
def *domain.PromptDefinition
err error
lastID string
}
type fakeExecutionProfileRepo struct {
@@ -43,7 +42,6 @@ type staticPromptRepo struct {
func (r staticPromptRepo) GetPromptDefinition(
context.Context,
string,
string,
) (*domain.PromptDefinition, error) {
return r.def, nil
}
@@ -94,9 +92,8 @@ func (f *fakeExecutionProfileRepo) GetProfile(ctx context.Context, id string) (*
return nil, errors.New("profile not found")
}
func (f *fakePromptRepo) GetPromptDefinition(ctx context.Context, id string, version string) (*domain.PromptDefinition, error) {
func (f *fakePromptRepo) GetPromptDefinition(ctx context.Context, id string) (*domain.PromptDefinition, error) {
f.lastID = id
f.lastVersion = version
if f.err != nil {
return nil, f.err
}
@@ -358,9 +355,8 @@ func TestRunnerPrepareWithExplicitProfileSelection(t *testing.T) {
runner := NewRunner(promptRepo, execRepo, reader, renderer, llmClient, nil, nil)
prepared, err := runner.Prepare(context.Background(), domain.RunRequest{
PromptID: "p",
PromptVersion: "1",
ProfileID: "exec",
PromptID: "p",
ProfileID: "exec",
Inputs: map[string]domain.ArtifactRef{
"transcript": {Type: domain.ArtifactRefFile, URI: "a://t"},
"glossary": {Type: domain.ArtifactRefFile, URI: "a://g"},
@@ -956,8 +952,8 @@ func TestRunnerPrepareJSONSchemaBuildsStructuredOutputSpec(t *testing.T) {
if prepared.StructuredOutput.JSONSchema == nil {
t.Fatal("expected structured output json_schema payload")
}
if prepared.StructuredOutput.JSONSchema.Name != "p_1" {
t.Fatalf("expected derived schema name p_1, got %q", prepared.StructuredOutput.JSONSchema.Name)
if prepared.StructuredOutput.JSONSchema.Name != "p" {
t.Fatalf("expected derived schema name p, got %q", prepared.StructuredOutput.JSONSchema.Name)
}
if prepared.StructuredOutput.JSONSchema.Strict != true {
t.Fatalf("expected strict=true, got %v", prepared.StructuredOutput.JSONSchema.Strict)
@@ -1022,28 +1018,25 @@ func TestRunnerRunJSONSchemaSchemaLoadFailureFailsBeforeLLM(t *testing.T) {
func TestDeriveStructuredSchemaName(t *testing.T) {
tests := []struct {
name string
id string
version string
want string
name string
id string
want string
}{
{
name: "sanitizes punctuation and keeps dashes",
id: "prompt.id/alpha",
version: "1.0.0-beta",
want: "prompt_id_alpha_1_0_0-beta",
name: "sanitizes punctuation and keeps dashes",
id: "prompt.id/alpha",
want: "prompt_id_alpha",
},
{
name: "fallback when empty",
id: "",
version: "",
want: "promptkit_schema",
name: "fallback when empty",
id: "",
want: "promptkit_schema",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
got := deriveStructuredSchemaName(tc.id, tc.version)
got := deriveStructuredSchemaName(tc.id)
if got != tc.want {
t.Fatalf("expected %q, got %q", tc.want, got)
}
@@ -1253,9 +1246,8 @@ func TestRunnerRunSuccessful(t *testing.T) {
runner := NewRunner(promptRepo, execRepo, reader, renderer, llmClient, nil, nil)
res, err := runner.Run(context.Background(), domain.RunRequest{
PromptID: "p",
PromptVersion: "1",
ProfileID: "exec",
PromptID: "p",
ProfileID: "exec",
Inputs: map[string]domain.ArtifactRef{
"transcript": {Type: domain.ArtifactRefFile, URI: "a://t"},
"glossary": {Type: domain.ArtifactRefFile, URI: "a://g"},
@@ -2325,8 +2317,8 @@ func TestRunnerRepairStateMachine(t *testing.T) {
t.Fatalf("initial structured output = %+v, want present %v", initialRequest.StructuredOutput, tc.structured)
}
if tc.structured && (initialRequest.StructuredOutput.JSONSchema == nil ||
initialRequest.StructuredOutput.JSONSchema.Name != "p_1") {
t.Fatalf("initial JSON Schema metadata = %+v, want derived schema name p_1", initialRequest.StructuredOutput)
initialRequest.StructuredOutput.JSONSchema.Name != "p") {
t.Fatalf("initial JSON Schema metadata = %+v, want derived schema name p", initialRequest.StructuredOutput)
}
for index, req := range repairer.reqs {

View File

@@ -35,13 +35,9 @@ func (r *Runner) resolveSmokeTestTarget(ctx context.Context, req domain.SmokeTes
return nil, fmt.Errorf("%w: %w", ErrInvalidRequest, err)
}
if req.PromptID == "" && req.PromptVersion != "" {
return nil, fmt.Errorf("%w: prompt version requires a prompt id", ErrInvalidRequest)
}
var promptInspection *domain.PromptInspection
if req.PromptID != "" {
promptInspection, err = r.resolvePromptInspection(ctx, req.PromptID, req.PromptVersion)
promptInspection, err = r.resolvePromptInspection(ctx, req.PromptID)
if err != nil {
return nil, err
}

View File

@@ -88,7 +88,7 @@ func TestResolveSmokeTestTargetSelectionAndRouting(t *testing.T) {
{
name: "prompt default",
request: domain.SmokeTestRequest{
Kind: domain.SmokeTestTextInference, PromptID: "selection.prompt", PromptVersion: "v1",
Kind: domain.SmokeTestTextInference, PromptID: "selection.prompt",
},
profileID: "prompt-profile",
backendID: "beta",
@@ -100,7 +100,7 @@ func TestResolveSmokeTestTargetSelectionAndRouting(t *testing.T) {
{
name: "explicit profile overrides prompt default",
request: domain.SmokeTestRequest{
Kind: domain.SmokeTestTextInference, PromptID: "selection.prompt", PromptVersion: "v1",
Kind: domain.SmokeTestTextInference, PromptID: "selection.prompt",
ProfileID: "alpha-profile", BackendID: "beta",
},
profileID: "alpha-profile",
@@ -138,7 +138,7 @@ func TestResolveSmokeTestTargetSelectionAndRouting(t *testing.T) {
{
name: "prompt profile supplies backend-only target over backend hint",
request: domain.SmokeTestRequest{
Kind: domain.SmokeTestReachability, PromptID: "selection.prompt", PromptVersion: "v1", BackendID: "alpha",
Kind: domain.SmokeTestReachability, PromptID: "selection.prompt", BackendID: "alpha",
},
profileID: "prompt-profile",
backendID: "beta",
@@ -150,7 +150,7 @@ func TestResolveSmokeTestTargetSelectionAndRouting(t *testing.T) {
{
name: "backend-only probe uses backend when prompt has no profile default",
request: domain.SmokeTestRequest{
Kind: domain.SmokeTestReachability, PromptID: "backend.prompt", PromptVersion: "v1", BackendID: "delta",
Kind: domain.SmokeTestReachability, PromptID: "backend.prompt", BackendID: "delta",
},
backendID: "delta",
selectionSource: smokeSelectionSourceBackend,
@@ -171,7 +171,7 @@ func TestResolveSmokeTestTargetSelectionAndRouting(t *testing.T) {
selected.target.EffectiveSettings.Model != test.wantModel {
t.Fatalf("unexpected target: %+v", selected.target)
}
if test.request.PromptID != "" && (selected.target.PromptID != test.request.PromptID || selected.target.PromptVersion != test.request.PromptVersion) {
if test.request.PromptID != "" && selected.target.PromptID != test.request.PromptID {
t.Fatalf("prompt identity was not retained: %+v", selected.target)
}
})
@@ -276,13 +276,6 @@ func TestResolveSmokeTestTargetSelectionAndSettingsErrors(t *testing.T) {
},
wantErr: ErrInvalidRequest,
},
{
name: "version cannot be supplied without prompt",
request: domain.SmokeTestRequest{
Kind: domain.SmokeTestTextInference, PromptVersion: " ", BackendID: "epsilon",
},
wantErr: ErrInvalidRequest,
},
{
name: "dangling backend default fails only when selected",
request: domain.SmokeTestRequest{Kind: domain.SmokeTestTextInference, BackendID: "delta"},

View File

@@ -5,9 +5,9 @@ import (
"fmt"
)
// PromptIdentity identifies one prompt ID and exact version in the effective
// configuration captured when an Engine is constructed. It has no stable JSON
// representation.
// PromptIdentity identifies one prompt ID and its optional descriptive version
// label in the effective configuration captured when an Engine is constructed.
// It has no stable JSON representation.
type PromptIdentity struct {
ID string
Version string
@@ -36,9 +36,9 @@ func (e *Engine) ListProfiles(ctx context.Context) ([]string, error) {
return profiles, nil
}
// ListPrompts returns every prompt ID and exact version in the effective
// configuration captured when the engine was constructed, sorted lexically by
// ID and then version. Versions are not interpreted or prioritized. The
// ListPrompts returns every prompt ID in the effective configuration captured
// when the engine was constructed, sorted lexically by ID. Each identity may
// include its descriptive version label. The
// returned slice is caller-owned and safe to mutate while the engine is used
// concurrently. Empty inventories succeed.
//

View File

@@ -53,7 +53,7 @@ func TestListIdentitiesBasicContract(t *testing.T) {
if err != nil || profile == nil || profile.ProfileID != "configured-profile" {
t.Fatalf("listed profile could not be inspected: (%+v, %v)", profile, err)
}
prompt, err := engine.InspectPrompt(context.Background(), prompts[0].ID, prompts[0].Version)
prompt, err := engine.InspectPrompt(context.Background(), prompts[0].ID)
if err != nil || prompt == nil || prompt.PromptID != prompts[0].ID || prompt.PromptVersion != prompts[0].Version {
t.Fatalf("listed prompt could not be inspected: (%+v, %v)", prompt, err)
}
@@ -275,7 +275,7 @@ func TestListIdentitiesAreOwnedAndSafeForConcurrentUse(t *testing.T) {
results <- fmt.Errorf("inspect profile: %w", err)
return
}
if _, err := engine.InspectPrompt(context.Background(), "prompt", "v1"); err != nil {
if _, err := engine.InspectPrompt(context.Background(), "prompt"); err != nil {
results <- fmt.Errorf("inspect prompt: %w", err)
return
}

View File

@@ -12,9 +12,6 @@ import (
type RequirementInspectionRequest struct {
// PromptID is the exact, case-sensitive configured prompt ID.
PromptID string
// PromptVersion selects an exact version. An empty value uses the prompt
// selection rule that requires exactly one configured version.
PromptVersion string
// ProfileID selects the exact effective profile identity. If empty, the
// prompt's default profile is used; the profile need not be ready for
// execution.
@@ -131,7 +128,7 @@ type RequirementIssue struct {
type RequirementInspection struct {
// PromptID is the selected exact prompt ID.
PromptID string
// PromptVersion is the selected exact prompt version.
// PromptVersion is the selected definition's descriptive version label.
PromptVersion string
// ProfileID is the selected profile identity; it does not indicate
// execution readiness.
@@ -189,7 +186,7 @@ func (e *Engine) InspectRequirements(
return nil, ErrInvalidConfig
}
inspection, err := e.internal.InspectRequirements(ctx, usecase.RequirementInspectionRequest{
PromptID: req.PromptID, PromptVersion: req.PromptVersion, ProfileID: req.ProfileID,
PromptID: req.PromptID, ProfileID: req.ProfileID,
Vars: copyStringMap(req.Vars), SessionID: req.SessionID,
})
if err != nil {

View File

@@ -184,12 +184,12 @@ func TestInspectPromptHashMatchesPreparationForCapturedConfiguration(t *testing.
engine := requirementsEngine(t, prompts, map[string]any{
"profile": map[string]any{"endpoint": "https://example.test/v1", "model": "inspection-model"},
})
inspection, err := engine.InspectPrompt(context.Background(), "hash-equality", "v1")
inspection, err := engine.InspectPrompt(context.Background(), "hash-equality")
if err != nil {
t.Fatalf("inspect captured prompt: %v", err)
}
prepared, err := engine.Prepare(context.Background(), promptkit.RunRequest{
PromptID: "hash-equality", PromptVersion: "v1", Vars: map[string]string{"name": "Ada"},
PromptID: "hash-equality", Vars: map[string]string{"name": "Ada"},
})
if err != nil {
t.Fatalf("prepare captured prompt: %v", err)

View File

@@ -38,9 +38,6 @@ type SmokeTestRequest struct {
// PromptID selects the prompt's default profile when ProfileID is empty. The
// prompt's messages, inputs, templates, and output contract are not executed.
PromptID string
// PromptVersion selects a version of PromptID using ordinary prompt-version
// selection semantics.
PromptVersion string
// ProfileID explicitly selects a profile and takes precedence over a prompt's
// default profile and a backend's configured diagnostic default.
ProfileID string
@@ -68,11 +65,10 @@ func (r SmokeTestRequest) redactedString() string {
retries = fmt.Sprintf("%d", *r.TransientRetries)
}
return fmt.Sprintf(
"promptkit.SmokeTestRequest{Kind:%q BackendIDSet:%t PromptIDSet:%t PromptVersionSet:%t ProfileIDSet:%t APIKeySet:%t TransientRetries:%s}",
"promptkit.SmokeTestRequest{Kind:%q BackendIDSet:%t PromptIDSet:%t ProfileIDSet:%t APIKeySet:%t TransientRetries:%s}",
r.Kind,
r.BackendID != "",
r.PromptID != "",
r.PromptVersion != "",
r.ProfileID != "",
r.APIKey != "",
retries,
@@ -119,7 +115,8 @@ type SmokeTestTarget struct {
BackendID string
// ProfileID is the selected profile, if any.
ProfileID string
// PromptID and PromptVersion identify the prompt used for selection, if any.
// PromptID identifies the selected prompt; PromptVersion carries its
// descriptive version label, if any.
PromptID string
PromptVersion string
// DefaultSourceBackendID identifies the backend whose configured default
@@ -228,7 +225,7 @@ const (
// configuration.
//
// Selection prefers an explicit ProfileID, then the profile selected by
// PromptID and PromptVersion, then a configured backend default profile when
// PromptID, then a configured backend default profile when
// inference requires one. For backend-only probes, a selected profile supplies
// its backend metadata; otherwise BackendID selects a backend directly without
// resolving its default inference profile. A selected profile determines its
@@ -286,7 +283,6 @@ func toDomainSmokeTestRequest(request SmokeTestRequest) (domain.SmokeTestRequest
Kind: domain.SmokeTestKind(request.Kind),
BackendID: request.BackendID,
PromptID: request.PromptID,
PromptVersion: request.PromptVersion,
ProfileID: request.ProfileID,
Execution: execution,
APIKey: request.APIKey,

View File

@@ -279,7 +279,7 @@ func TestSmokeTestUsesPrivateInferenceWithoutApplicationResourcesOrListingChange
if err != nil {
t.Fatal(err)
}
inspectionBefore, err := engine.InspectPrompt(context.Background(), "application-prompt", "")
inspectionBefore, err := engine.InspectPrompt(context.Background(), "application-prompt")
if err != nil {
t.Fatal(err)
}
@@ -330,7 +330,7 @@ func TestSmokeTestUsesPrivateInferenceWithoutApplicationResourcesOrListingChange
if err != nil {
t.Fatal(err)
}
inspectionAfter, err := engine.InspectPrompt(context.Background(), "application-prompt", "")
inspectionAfter, err := engine.InspectPrompt(context.Background(), "application-prompt")
if err != nil {
t.Fatal(err)
}

View File

@@ -87,9 +87,6 @@ const (
type RunRequest struct {
// PromptID is the required non-empty prompt identifier.
PromptID string
// PromptVersion optionally selects one version of PromptID. When empty, the
// prompt source must contain exactly one matching version.
PromptVersion string
// ProfileID selects an execution profile. When empty, the prompt's default
// profile is used; if both are empty, the error matches ErrProfileRequired
// and ErrInvalidRequest.
@@ -162,7 +159,7 @@ type RunRequest struct {
type PreparedRun struct {
// PromptID is the selected prompt identifier.
PromptID string `json:"prompt_id"`
// PromptVersion is the selected prompt version.
// PromptVersion is the selected definition's descriptive version label.
PromptVersion string `json:"prompt_version,omitempty"`
// PromptHash is an opaque equality value for the selected definition.
PromptHash string `json:"prompt_hash,omitempty"`
@@ -220,7 +217,7 @@ type RunResult struct {
Validation ValidationResult `json:"validation"`
// PromptID is the selected prompt identifier.
PromptID string `json:"prompt_id"`
// PromptVersion is the selected prompt version.
// PromptVersion is the selected definition's descriptive version label.
PromptVersion string `json:"prompt_version,omitempty"`
// PromptHash is the same opaque definition equality value exposed by
// PreparedRun.
@@ -403,7 +400,7 @@ type PromptInputDefinition struct {
type PromptInspection struct {
// PromptID is the normalized ID of the selected prompt definition.
PromptID string
// PromptVersion is the normalized version of the selected prompt definition.
// PromptVersion is the selected definition's descriptive version label.
PromptVersion string
// PromptHash is the opaque equality value for the selected definition.
PromptHash string