Expose prompt requirement inspection
This commit is contained in:
158
requirements.go
Normal file
158
requirements.go
Normal file
@@ -0,0 +1,158 @@
|
||||
package promptkit
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"gitea.maximumdirect.net/eric/promptkit/internal/domain"
|
||||
"gitea.maximumdirect.net/eric/promptkit/internal/usecase"
|
||||
)
|
||||
|
||||
// RequirementInspectionRequest selects a prompt and supplies caller context
|
||||
// for requirement discovery. It requires no artifact bindings or credentials.
|
||||
type RequirementInspectionRequest struct {
|
||||
PromptID string
|
||||
PromptVersion string
|
||||
ProfileID string
|
||||
Vars map[string]string
|
||||
SessionID string
|
||||
}
|
||||
|
||||
// RequirementKind describes how a selected prompt may depend on an input or
|
||||
// caller variable for the supplied context.
|
||||
type RequirementKind string
|
||||
|
||||
const (
|
||||
// RequirementRequired identifies a declaration or definite access.
|
||||
RequirementRequired RequirementKind = "required"
|
||||
// RequirementConditional identifies a dependency whose reachability is
|
||||
// unresolved for the supplied context.
|
||||
RequirementConditional RequirementKind = "conditional"
|
||||
// RequirementOptional identifies a dependency known not to be required,
|
||||
// including a reference used only on a known skipped path.
|
||||
RequirementOptional RequirementKind = "optional"
|
||||
)
|
||||
|
||||
// InputRequirement describes a declared or template-referenced prompt input.
|
||||
type InputRequirement struct {
|
||||
Name string
|
||||
Kind RequirementKind
|
||||
Declared bool
|
||||
ContentType *string
|
||||
Description *string
|
||||
Explanation string
|
||||
}
|
||||
|
||||
// VariableRequirement describes a caller-map key referenced by a prompt.
|
||||
type VariableRequirement struct {
|
||||
Name string
|
||||
Kind RequirementKind
|
||||
Supplied bool
|
||||
Explanation string
|
||||
}
|
||||
|
||||
// RequirementIssueCode identifies a limitation that can affect discovery.
|
||||
type RequirementIssueCode string
|
||||
|
||||
const (
|
||||
RequirementIssueMissingVariable RequirementIssueCode = "missing_variable"
|
||||
RequirementIssueInputContent RequirementIssueCode = "input_content"
|
||||
RequirementIssueDynamicInputName RequirementIssueCode = "dynamic_input_name"
|
||||
RequirementIssueUnsupportedConstruct RequirementIssueCode = "unsupported_construct"
|
||||
)
|
||||
|
||||
// RequirementIssue describes one discovery limitation using safe summary
|
||||
// text. Descriptions are not intended as machine-readable details.
|
||||
type RequirementIssue struct {
|
||||
Code RequirementIssueCode
|
||||
InputName string
|
||||
VariableName string
|
||||
Description string
|
||||
}
|
||||
|
||||
// RequirementInspection contains discovered dependencies for one selected
|
||||
// prompt context. Complete describes discovery, not renderability or readiness.
|
||||
type RequirementInspection struct {
|
||||
PromptID string
|
||||
PromptVersion string
|
||||
ProfileID string
|
||||
Inputs []InputRequirement
|
||||
Variables []VariableRequirement
|
||||
Complete bool
|
||||
Issues []RequirementIssue
|
||||
}
|
||||
|
||||
// InspectRequirements discovers inputs and caller variables for one selected
|
||||
// prompt before its input artifacts exist. It uses exact, case-sensitive
|
||||
// prompt selection and requires a profile ID either in the request or the
|
||||
// selected prompt's default. The selected profile establishes identity only;
|
||||
// it need not be execution-ready. A normalized nonblank SessionID bypasses the
|
||||
// captured session template. Vars are copied before analysis, and returned
|
||||
// slices and metadata pointers belong to the caller.
|
||||
//
|
||||
// This method does not perform artifact, schema, credential, rendering,
|
||||
// validation, capacity, observation, provider, or execution work. Complete
|
||||
// describes dependency discovery, not whether every dependency is supplied or
|
||||
// the prompt is ready to execute. Discovery limitations return a partial
|
||||
// inspection and no error; selection and operational failures return no
|
||||
// inspection. Blank prompt IDs, invalid session IDs, and absent profile
|
||||
// selection match ErrInvalidRequest; an absent profile selection also matches
|
||||
// ErrProfileRequired. Missing prompt/profile IDs match ErrPromptNotFound or
|
||||
// ErrProfileNotFound. Other selection/snapshot failures match ErrPromptLoad or
|
||||
// ErrProfileLoad. A nil Engine matches ErrInvalidConfig.
|
||||
func (e *Engine) InspectRequirements(
|
||||
ctx context.Context,
|
||||
req RequirementInspectionRequest,
|
||||
) (*RequirementInspection, error) {
|
||||
if e == nil || e.internal == nil {
|
||||
return nil, ErrInvalidConfig
|
||||
}
|
||||
inspection, err := e.internal.InspectRequirements(ctx, usecase.RequirementInspectionRequest{
|
||||
PromptID: req.PromptID, PromptVersion: req.PromptVersion, ProfileID: req.ProfileID,
|
||||
Vars: copyStringMap(req.Vars), SessionID: req.SessionID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, mapPublicError(err)
|
||||
}
|
||||
return fromDomainRequirementInspection(inspection), nil
|
||||
}
|
||||
|
||||
func fromDomainRequirementInspection(inspection *domain.RequirementInspection) *RequirementInspection {
|
||||
if inspection == nil {
|
||||
return nil
|
||||
}
|
||||
result := &RequirementInspection{
|
||||
PromptID: inspection.PromptID, PromptVersion: inspection.PromptVersion,
|
||||
ProfileID: inspection.ProfileID, Complete: inspection.Complete,
|
||||
Inputs: make([]InputRequirement, len(inspection.Inputs)),
|
||||
Variables: make([]VariableRequirement, len(inspection.Variables)),
|
||||
Issues: make([]RequirementIssue, len(inspection.Issues)),
|
||||
}
|
||||
for index, input := range inspection.Inputs {
|
||||
result.Inputs[index] = InputRequirement{
|
||||
Name: input.Name, Kind: RequirementKind(input.Kind), Declared: input.Declared,
|
||||
ContentType: copyRequirementString(input.ContentType), Description: copyRequirementString(input.Description),
|
||||
Explanation: input.Explanation,
|
||||
}
|
||||
}
|
||||
for index, variable := range inspection.Variables {
|
||||
result.Variables[index] = VariableRequirement{
|
||||
Name: variable.Name, Kind: RequirementKind(variable.Kind), Supplied: variable.Supplied,
|
||||
Explanation: variable.Explanation,
|
||||
}
|
||||
}
|
||||
for index, issue := range inspection.Issues {
|
||||
result.Issues[index] = RequirementIssue{
|
||||
Code: RequirementIssueCode(issue.Code), InputName: issue.InputName,
|
||||
VariableName: issue.VariableName, Description: issue.Description,
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func copyRequirementString(value *string) *string {
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
copy := *value
|
||||
return ©
|
||||
}
|
||||
Reference in New Issue
Block a user