2026-10-12 22:16:44 +00:00
|
|
|
package ckprompt
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"errors"
|
2026-10-26 03:35:39 +00:00
|
|
|
"fmt"
|
2026-10-12 22:16:44 +00:00
|
|
|
|
2026-11-04 03:55:17 +00:00
|
|
|
commandkit "go.maximumdirect.net/commandkit"
|
2026-10-12 22:16:44 +00:00
|
|
|
)
|
|
|
|
|
|
2026-11-07 04:19:58 +00:00
|
|
|
type concreteRequestInput[I any] struct {
|
2026-11-07 04:16:09 +00:00
|
|
|
promptID string
|
|
|
|
|
request ValidationRequest
|
|
|
|
|
execution ExecutionInput
|
|
|
|
|
resources ResourceInput
|
|
|
|
|
inputs PromptInputs
|
|
|
|
|
captured commandkit.FlagValues[I]
|
|
|
|
|
selected I
|
2026-10-12 22:16:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type requestValidationReport struct {
|
2026-11-07 04:10:47 +00:00
|
|
|
PromptID string `json:"prompt_id"`
|
|
|
|
|
Valid bool `json:"valid"`
|
2026-10-12 22:16:44 +00:00
|
|
|
}
|
|
|
|
|
|
2026-11-07 04:19:58 +00:00
|
|
|
func newConcreteRequestSpec[I, S any](suite Suite[I, S]) commandkit.CommandSpec[*concreteRequestInput[I]] {
|
|
|
|
|
flags := commandkit.CaptureFlags(suite.Selectors, func(input **concreteRequestInput[I]) *commandkit.FlagValues[I] {
|
2026-10-12 22:16:44 +00:00
|
|
|
if input == nil || *input == nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
return &(*input).captured
|
|
|
|
|
})
|
|
|
|
|
flags = append(flags,
|
2026-11-03 04:09:27 +00:00
|
|
|
commandkit.ValueFlag(commandkit.FlagMeta{Name: "config", Usage: "Configuration input path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
|
2026-11-07 04:19:58 +00:00
|
|
|
func(input **concreteRequestInput[I], value commandkit.Supplied[string]) {
|
2026-10-12 22:16:44 +00:00
|
|
|
(*input).request.Selection.Config = value
|
|
|
|
|
}),
|
2026-11-03 04:09:27 +00:00
|
|
|
commandkit.ValueFlag(commandkit.FlagMeta{Name: "overlay", Usage: "Configuration overlay path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
|
2026-11-07 04:19:58 +00:00
|
|
|
func(input **concreteRequestInput[I], value commandkit.Supplied[string]) {
|
2026-10-12 22:16:44 +00:00
|
|
|
(*input).request.Selection.Overlay = value
|
|
|
|
|
}),
|
|
|
|
|
)
|
|
|
|
|
|
2026-11-07 04:19:58 +00:00
|
|
|
resources := NewResourceFlags(func(input **concreteRequestInput[I]) *ResourceInput { return &(*input).resources })
|
|
|
|
|
execution := NewExecutionFlags(func(input **concreteRequestInput[I]) *ExecutionInput { return &(*input).execution })
|
|
|
|
|
inputs := NewPromptInputFlags(func(input **concreteRequestInput[I]) *PromptInputs { return &(*input).inputs })
|
2026-11-07 04:16:09 +00:00
|
|
|
flags = append(flags, resources.Profile, resources.SessionID, inputs.Variable, inputs.Text, inputs.File)
|
|
|
|
|
flags = append(flags, execution.All()...)
|
|
|
|
|
|
2026-11-07 04:19:58 +00:00
|
|
|
return commandkit.CommandSpec[*concreteRequestInput[I]]{
|
|
|
|
|
NewInput: func() *concreteRequestInput[I] {
|
|
|
|
|
return &concreteRequestInput[I]{}
|
2026-10-12 22:16:44 +00:00
|
|
|
},
|
|
|
|
|
Flags: flags,
|
2026-11-07 04:19:58 +00:00
|
|
|
Arguments: []commandkit.Argument[*concreteRequestInput[I]]{
|
2026-10-12 22:16:44 +00:00
|
|
|
commandkit.ValueArgument(commandkit.ArgumentMeta{Name: "id", Usage: "Prompt ID."}, true, parseDefinitionString,
|
2026-11-07 04:19:58 +00:00
|
|
|
func(input **concreteRequestInput[I], value commandkit.Supplied[string]) {
|
2026-10-12 22:16:44 +00:00
|
|
|
(*input).promptID = value.Value
|
|
|
|
|
(*input).request.Request.PromptID = value.Value
|
|
|
|
|
}),
|
|
|
|
|
},
|
2026-11-07 04:19:58 +00:00
|
|
|
CheckInput: func(input *concreteRequestInput[I]) error {
|
2026-10-12 22:16:44 +00:00
|
|
|
if input == nil {
|
2026-11-07 04:19:58 +00:00
|
|
|
return errors.New("PromptKit request input must not be nil")
|
2026-10-12 22:16:44 +00:00
|
|
|
}
|
2026-11-07 04:16:09 +00:00
|
|
|
input.request.Request.ProfileID = input.resources.Profile.Value
|
|
|
|
|
input.request.Request.SessionID = input.resources.SessionID.Value
|
|
|
|
|
input.request.Request.Vars = input.inputs.Vars
|
|
|
|
|
input.request.Request.Inputs = input.inputs.Inputs
|
|
|
|
|
input.request.Request.Execution = input.execution.Execution
|
|
|
|
|
input.request.Request.TransientRetries = input.execution.TransientRetries
|
2026-10-12 22:16:44 +00:00
|
|
|
selected, err := prepareSuiteInput(suite, input.request.Selection, input.captured)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
input.selected = selected
|
|
|
|
|
return nil
|
|
|
|
|
},
|
2026-11-07 04:19:58 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func newValidationCommand[I, S any](suite Suite[I, S]) commandkit.Command {
|
|
|
|
|
spec := newConcreteRequestSpec(suite)
|
|
|
|
|
spec.Name = "validate"
|
|
|
|
|
spec.Summary = "Validate a concrete PromptKit request without executing it."
|
|
|
|
|
spec.Run = func(invocation commandkit.Invocation, input *concreteRequestInput[I]) commandkit.Outcome {
|
|
|
|
|
return runRequestValidation(invocation, suite, input)
|
|
|
|
|
}
|
|
|
|
|
return commandkit.NewCommand(spec)
|
2026-10-12 22:16:44 +00:00
|
|
|
}
|
|
|
|
|
|
2026-11-07 04:19:58 +00:00
|
|
|
func runRequestValidation[I, S any](invocation commandkit.Invocation, suite Suite[I, S], input *concreteRequestInput[I]) commandkit.Outcome {
|
2026-10-12 22:16:44 +00:00
|
|
|
if err := promptKitContextError(invocation.Context); err != nil {
|
2026-10-26 03:35:39 +00:00
|
|
|
return definitionFailure("PromptKit request validation was canceled.", commandkit.Explanation{}, err)
|
2026-10-12 22:16:44 +00:00
|
|
|
}
|
|
|
|
|
var state S
|
|
|
|
|
if suite.NewState != nil {
|
|
|
|
|
state = suite.NewState()
|
|
|
|
|
}
|
|
|
|
|
if err := promptKitContextError(invocation.Context); err != nil {
|
2026-10-26 03:35:39 +00:00
|
|
|
return definitionFailure("PromptKit request validation was canceled.", commandkit.Explanation{}, err)
|
2026-10-12 22:16:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
acquired, err := suite.ValidateRequest(invocation.Context, input.request, input.selected, state)
|
2026-10-26 03:35:39 +00:00
|
|
|
queuePromptDiagnostics(invocation.Reporter(), acquired.Diagnostics)
|
2026-10-12 22:16:44 +00:00
|
|
|
if err != nil {
|
2026-10-26 03:35:39 +00:00
|
|
|
return definitionFailure(fmt.Sprintf("Unable to validate the PromptKit request for prompt %q.", input.promptID), acquired.Explanation, err)
|
2026-10-12 22:16:44 +00:00
|
|
|
}
|
|
|
|
|
if err := promptKitContextError(invocation.Context); err != nil {
|
2026-10-26 03:35:39 +00:00
|
|
|
return definitionFailure(fmt.Sprintf("Validation of the PromptKit request for prompt %q was canceled.", input.promptID), acquired.Explanation, err)
|
2026-10-12 22:16:44 +00:00
|
|
|
}
|
2026-11-07 04:10:47 +00:00
|
|
|
_ = invocation.Reporter().Report(commandkit.Report{Value: requestValidationReport{PromptID: input.promptID, Valid: true}})
|
|
|
|
|
return commandkit.Success()
|
2026-10-12 22:16:44 +00:00
|
|
|
}
|