package ckprompt import ( "errors" commandkit "gitea.maximumdirect.net/eric/CommandKit" promptkit "gitea.maximumdirect.net/eric/promptkit" ) type validationCommandInput[I any] struct { promptID string request ValidationRequest format string captured commandkit.FlagValues[I] selected I } type requestValidationReport struct { PromptID string `yaml:"prompt_id"` Valid bool `yaml:"valid"` } func newValidationCommand[I, S any](suite Suite[I, S]) commandkit.Command { flags := commandkit.CaptureFlags(suite.Selectors, func(input **validationCommandInput[I]) *commandkit.FlagValues[I] { if input == nil || *input == nil { return nil } return &(*input).captured }) flags = append(flags, commandkit.ValueFlag(commandkit.FlagMeta{Name: "config", Usage: "Configuration input path."}, (*string)(nil), parseDefinitionString, func(input **validationCommandInput[I], value commandkit.Supplied[string]) { (*input).request.Selection.Config = value }), commandkit.ValueFlag(commandkit.FlagMeta{Name: "overlay", Usage: "Configuration overlay path."}, (*string)(nil), parseDefinitionString, func(input **validationCommandInput[I], value commandkit.Supplied[string]) { (*input).request.Selection.Overlay = value }), commandkit.ValueFlag(commandkit.FlagMeta{Name: "version", Usage: "Prompt version to validate."}, stringDefault(""), parseDefinitionString, func(input **validationCommandInput[I], value commandkit.Supplied[string]) { (*input).request.Request.PromptVersion = value.Value }), commandkit.ValueFlag(commandkit.FlagMeta{Name: "profile", Usage: "Profile identity for validation."}, stringDefault(""), parseDefinitionString, func(input **validationCommandInput[I], value commandkit.Supplied[string]) { (*input).request.Request.ProfileID = value.Value }), commandkit.ValueFlag(commandkit.FlagMeta{Name: "session-id", Usage: "Session context for validation."}, stringDefault(""), parseDefinitionString, func(input **validationCommandInput[I], value commandkit.Supplied[string]) { (*input).request.Request.SessionID = value.Value }), commandkit.ValueFlag(commandkit.FlagMeta{Name: "format", Usage: "Confirmation format: yaml."}, stringDefault("yaml"), parseDefinitionString, func(input **validationCommandInput[I], value commandkit.Supplied[string]) { (*input).format = value.Value }), commandkit.RepeatFlag(commandkit.FlagMeta{Name: "var", Usage: "Caller variable assignment KEY=VALUE."}, []variableAssignment(nil), parseVariableAssignment, func(input **validationCommandInput[I], value commandkit.Supplied[[]variableAssignment]) { variables := make(map[string]string, len(value.Value)) for _, assignment := range value.Value { variables[assignment.key] = assignment.value } (*input).request.Request.Vars = variables }), commandkit.RepeatFlag(commandkit.FlagMeta{Name: "input", Usage: "Prompt input file assignment NAME=PATH."}, []inputAssignment(nil), parseInputAssignment, func(input **validationCommandInput[I], value commandkit.Supplied[[]inputAssignment]) { inputs := make(map[string]promptkit.ArtifactRef, len(value.Value)) for _, assignment := range value.Value { inputs[assignment.name] = promptkit.File(assignment.path) } (*input).request.Request.Inputs = inputs }), ) return commandkit.NewCommand(commandkit.CommandSpec[*validationCommandInput[I]]{ Name: "validate", Summary: "Validate a concrete PromptKit request without executing it.", NewInput: func() *validationCommandInput[I] { return &validationCommandInput[I]{format: "yaml"} }, Flags: flags, Arguments: []commandkit.Argument[*validationCommandInput[I]]{ commandkit.ValueArgument(commandkit.ArgumentMeta{Name: "id", Usage: "Prompt ID."}, true, parseDefinitionString, func(input **validationCommandInput[I], value commandkit.Supplied[string]) { (*input).promptID = value.Value (*input).request.Request.PromptID = value.Value }), }, CheckInput: func(input *validationCommandInput[I]) error { if input == nil { return errors.New("PromptKit validation input must not be nil") } if err := checkRequirementsFormat(input.format); err != nil { return err } selected, err := prepareSuiteInput(suite, input.request.Selection, input.captured) if err != nil { return err } input.selected = selected return nil }, Run: func(invocation commandkit.Invocation, input *validationCommandInput[I]) commandkit.Outcome { return runRequestValidation(invocation, suite, input) }, }) } func runRequestValidation[I, S any](invocation commandkit.Invocation, suite Suite[I, S], input *validationCommandInput[I]) commandkit.Outcome { if err := promptKitContextError(invocation.Context); err != nil { return definitionFailure(err, nil) } var state S if suite.NewState != nil { state = suite.NewState() } if err := promptKitContextError(invocation.Context); err != nil { return definitionFailure(err, nil) } acquired, err := suite.ValidateRequest(invocation.Context, input.request, input.selected, state) if err != nil { return definitionFailure(err, acquired.Diagnostics) } if err := promptKitContextError(invocation.Context); err != nil { return definitionFailure(err, acquired.Diagnostics) } output, err := encodePromptYAMLBytes(requestValidationReport{PromptID: input.promptID, Valid: true}) if err != nil { return definitionFailure(err, acquired.Diagnostics) } return writePromptReport(invocation, output, acquired.Diagnostics) }