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:23:39 +00:00
namespaces namespaceInput
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:27:28 +00:00
func newConcreteRequestSpec [ I , S any ] ( suite Suite [ I , S ] , path string , aliases * [ ] commandkit . Declaration ) commandkit . CommandSpec [ * concreteRequestInput [ I ] ] {
2026-11-07 04:19:58 +00:00
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-07 23:31:14 +00:00
commandkit . ValueFlag ( commandkit . FlagMeta { Name : "config" , Usage : "Select the 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-07 23:31:14 +00:00
commandkit . ValueFlag ( commandkit . FlagMeta { Name : "overlay" , Usage : "Select the 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:27:28 +00:00
flags = appendRequestBindings ( flags , path , aliases ,
requestBinding [ * concreteRequestInput [ I ] ] { resources . Profile , requestFlags . Profile } ,
requestBinding [ * concreteRequestInput [ I ] ] { resources . SessionID , requestFlags . SessionID } ,
requestBinding [ * concreteRequestInput [ I ] ] { inputs . Variable , requestFlags . Var } ,
requestBinding [ * concreteRequestInput [ I ] ] { inputs . Text , requestFlags . InputText } ,
requestBinding [ * concreteRequestInput [ I ] ] { inputs . File , requestFlags . InputFile } ,
)
flags = appendRequestBindings ( flags , path , aliases , execution . bindings ( ) ... )
2026-11-07 04:16:09 +00:00
2026-11-07 04:23:39 +00:00
if suite . namespaces != nil {
2026-11-07 04:27:28 +00:00
flags = appendRequestBindings ( flags , path , aliases , namespaceFlags ( func ( input * * concreteRequestInput [ I ] ) * namespaceInput { return & ( * input ) . namespaces } , "prompt" , "profile" , "backend" ) ... )
2026-11-07 04:23:39 +00:00
}
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:23:39 +00:00
input . request . Namespaces = selectedNamespaces ( suite . namespaces , input . namespaces )
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
}
}
2026-11-07 04:27:28 +00:00
func newValidationCommand [ I , S any ] ( suite Suite [ I , S ] , aliases * [ ] commandkit . Declaration ) commandkit . Command {
spec := newConcreteRequestSpec ( suite , "promptkit requirements validate" , aliases )
2026-11-07 04:19:58 +00:00
spec . Name = "validate"
2026-11-07 23:31:14 +00:00
spec . Summary = "Check whether a request can be prepared without calling the model."
2026-11-07 04:19:58 +00:00
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
}