Add PromptKit requirements command
This commit is contained in:
@@ -31,18 +31,31 @@ type catalogInput[I any] struct {
|
||||
selected I
|
||||
}
|
||||
|
||||
// Command captures the optional PromptKit catalog and named inspection
|
||||
// callbacks and adds only supplied operations, generating list and show groups
|
||||
// independently. An absent suite claims no namespace; attached construction
|
||||
// issues remain reportable. It adds no configuration family; callers compose
|
||||
// ConfigScope independently. Construction, installation, help, and version do
|
||||
// not run suite factories or providers. Suite documents invocation input and
|
||||
// state initialization, zero values, and caller ownership of returned objects.
|
||||
type requirementsInput[I any] struct {
|
||||
selection ckconfig.Selection
|
||||
inspection promptkit.RequirementInspectionRequest
|
||||
format string
|
||||
captured commandkit.FlagValues[I]
|
||||
selected I
|
||||
}
|
||||
|
||||
type variableAssignment struct {
|
||||
key string
|
||||
value string
|
||||
}
|
||||
|
||||
// Command captures the optional PromptKit catalog, named inspection, and
|
||||
// requirements inspection callbacks and adds only supplied operations. An
|
||||
// absent suite claims no namespace; attached construction issues remain
|
||||
// reportable. It adds no configuration family; callers compose ConfigScope
|
||||
// independently. Construction, installation, help, and version do not run
|
||||
// suite factories or providers. Suite documents invocation input and state
|
||||
// initialization, zero values, and caller ownership of returned objects.
|
||||
// Catalog commands accept config/overlay selection and suite selectors, and
|
||||
// render YAML with `yaml` as the only format and default. Named-show formats are
|
||||
// unchanged.
|
||||
func Command[I, S any](suite Suite[I, S]) commandkit.Command {
|
||||
if suite.InspectPrompt == nil && suite.InspectProfile == nil && suite.ListPrompts == nil && suite.ListProfiles == nil {
|
||||
if suite.InspectPrompt == nil && suite.InspectProfile == nil && suite.InspectRequirements == nil && suite.ListPrompts == nil && suite.ListProfiles == nil {
|
||||
command := commandkit.NoCommand()
|
||||
for _, issue := range suite.issues {
|
||||
command = commandkit.WithError(command, issue)
|
||||
@@ -51,7 +64,7 @@ func Command[I, S any](suite Suite[I, S]) commandkit.Command {
|
||||
}
|
||||
|
||||
suite.Selectors = append([]commandkit.Flag[I](nil), suite.Selectors...)
|
||||
rootCommands := make([]commandkit.Command, 0, 2)
|
||||
rootCommands := make([]commandkit.Command, 0, 3)
|
||||
showCommands := make([]commandkit.Command, 0, 2)
|
||||
if suite.InspectPrompt != nil {
|
||||
showCommands = append(showCommands, newDefinitionCommand(suite, "prompt", true))
|
||||
@@ -72,7 +85,10 @@ func Command[I, S any](suite Suite[I, S]) commandkit.Command {
|
||||
if len(listCommands) != 0 {
|
||||
rootCommands = append(rootCommands, commandkit.Group("list", "List PromptKit catalogs.", listCommands...))
|
||||
}
|
||||
command := commandkit.RootGroup("promptkit", "Inspect and list PromptKit definitions.", rootCommands...)
|
||||
if suite.InspectRequirements != nil {
|
||||
rootCommands = append(rootCommands, commandkit.Group("requirements", "Inspect prompt requirements.", newRequirementsCommand(suite)))
|
||||
}
|
||||
command := commandkit.RootGroup("promptkit", "Inspect and list PromptKit definitions and requirements.", rootCommands...)
|
||||
for _, issue := range suite.issues {
|
||||
command = commandkit.WithError(command, issue)
|
||||
}
|
||||
@@ -131,6 +147,13 @@ func checkCatalogFormat(format string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkRequirementsFormat(format string) error {
|
||||
if format != "yaml" {
|
||||
return fmt.Errorf("unsupported requirements format %q; expected yaml", format)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func prepareCatalogInput[I, S any](suite Suite[I, S], input *catalogInput[I]) (I, error) {
|
||||
return prepareSuiteInput(suite, input.selection, input.captured)
|
||||
}
|
||||
@@ -186,6 +209,77 @@ func newDefinitionCommand[I, S any](suite Suite[I, S], name string, prompt bool)
|
||||
return commandkit.NewCommand(spec)
|
||||
}
|
||||
|
||||
func newRequirementsCommand[I, S any](suite Suite[I, S]) commandkit.Command {
|
||||
flags := commandkit.CaptureFlags(suite.Selectors, func(input **requirementsInput[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 **requirementsInput[I], value commandkit.Supplied[string]) {
|
||||
(*input).selection.Config = value
|
||||
}),
|
||||
commandkit.ValueFlag(commandkit.FlagMeta{Name: "overlay", Usage: "Configuration overlay path."}, (*string)(nil), parseDefinitionString,
|
||||
func(input **requirementsInput[I], value commandkit.Supplied[string]) {
|
||||
(*input).selection.Overlay = value
|
||||
}),
|
||||
commandkit.ValueFlag(commandkit.FlagMeta{Name: "version", Usage: "Prompt version to inspect."}, stringDefault(""), parseDefinitionString,
|
||||
func(input **requirementsInput[I], value commandkit.Supplied[string]) {
|
||||
(*input).inspection.PromptVersion = value.Value
|
||||
}),
|
||||
commandkit.ValueFlag(commandkit.FlagMeta{Name: "profile", Usage: "Profile identity for discovery."}, stringDefault(""), parseDefinitionString,
|
||||
func(input **requirementsInput[I], value commandkit.Supplied[string]) {
|
||||
(*input).inspection.ProfileID = value.Value
|
||||
}),
|
||||
commandkit.ValueFlag(commandkit.FlagMeta{Name: "session-id", Usage: "Session context for discovery."}, stringDefault(""), parseDefinitionString,
|
||||
func(input **requirementsInput[I], value commandkit.Supplied[string]) {
|
||||
(*input).inspection.SessionID = value.Value
|
||||
}),
|
||||
commandkit.ValueFlag(commandkit.FlagMeta{Name: "format", Usage: "Report format: yaml."}, stringDefault("yaml"), parseDefinitionString,
|
||||
func(input **requirementsInput[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 **requirementsInput[I], value commandkit.Supplied[[]variableAssignment]) {
|
||||
variables := make(map[string]string, len(value.Value))
|
||||
for _, assignment := range value.Value {
|
||||
variables[assignment.key] = assignment.value
|
||||
}
|
||||
(*input).inspection.Vars = variables
|
||||
}),
|
||||
)
|
||||
|
||||
spec := commandkit.CommandSpec[*requirementsInput[I]]{
|
||||
Name: "show",
|
||||
Summary: "Inspect requirements for a named PromptKit prompt.",
|
||||
NewInput: func() *requirementsInput[I] {
|
||||
return &requirementsInput[I]{}
|
||||
},
|
||||
Flags: flags,
|
||||
Arguments: []commandkit.Argument[*requirementsInput[I]]{
|
||||
commandkit.ValueArgument(commandkit.ArgumentMeta{Name: "id", Usage: "Prompt ID."}, true, parseDefinitionString,
|
||||
func(input **requirementsInput[I], value commandkit.Supplied[string]) {
|
||||
(*input).inspection.PromptID = value.Value
|
||||
}),
|
||||
},
|
||||
CheckInput: func(input *requirementsInput[I]) error {
|
||||
if err := checkRequirementsFormat(input.format); err != nil {
|
||||
return err
|
||||
}
|
||||
selected, err := prepareSuiteInput(suite, input.selection, input.captured)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
input.selected = selected
|
||||
return nil
|
||||
},
|
||||
Run: func(invocation commandkit.Invocation, input *requirementsInput[I]) commandkit.Outcome {
|
||||
return runRequirementsInspection(invocation, suite, input)
|
||||
},
|
||||
}
|
||||
return commandkit.NewCommand(spec)
|
||||
}
|
||||
|
||||
func prepareDefinitionInput[I, S any](suite Suite[I, S], input *definitionInput[I]) (I, error) {
|
||||
return prepareSuiteInput(suite, input.selection, input.captured)
|
||||
}
|
||||
@@ -446,6 +540,42 @@ func profileReportFromInspection(inspection *promptkit.ProfileInspection) profil
|
||||
}
|
||||
}
|
||||
|
||||
func runRequirementsInspection[I, S any](invocation commandkit.Invocation, suite Suite[I, S], input *requirementsInput[I]) commandkit.Outcome {
|
||||
if invocation.Context != nil {
|
||||
if err := invocation.Context.Err(); err != nil {
|
||||
return definitionFailure(err, nil)
|
||||
}
|
||||
}
|
||||
var state S
|
||||
if suite.NewState != nil {
|
||||
state = suite.NewState()
|
||||
}
|
||||
if invocation.Context != nil {
|
||||
if err := invocation.Context.Err(); err != nil {
|
||||
return definitionFailure(err, nil)
|
||||
}
|
||||
}
|
||||
|
||||
request := RequirementsRequest{Selection: input.selection, Inspection: input.inspection}
|
||||
acquired, err := suite.InspectRequirements(invocation.Context, request, input.selected, state)
|
||||
if err != nil {
|
||||
return definitionFailure(err, acquired.Diagnostics)
|
||||
}
|
||||
if acquired.Value == nil {
|
||||
return definitionFailure(errors.New("PromptKit requirements inspection returned nil"), acquired.Diagnostics)
|
||||
}
|
||||
if invocation.Context != nil {
|
||||
if err := invocation.Context.Err(); err != nil {
|
||||
return definitionFailure(err, acquired.Diagnostics)
|
||||
}
|
||||
}
|
||||
output, err := encodePromptYAMLBytes(requirementsReportFromInspection(acquired.Value))
|
||||
if err != nil {
|
||||
return definitionFailure(err, acquired.Diagnostics)
|
||||
}
|
||||
return writePromptReport(invocation, output, acquired.Diagnostics)
|
||||
}
|
||||
|
||||
func renderPromptReport(invocation commandkit.Invocation, report promptInspectionReport, format string, diagnostics []commandkit.Diagnostic) commandkit.Outcome {
|
||||
var output bytes.Buffer
|
||||
if format == "yaml" {
|
||||
@@ -581,4 +711,12 @@ func checkDefinitionFormat(format string) error {
|
||||
|
||||
func parseDefinitionString(value string) (string, error) { return value, nil }
|
||||
|
||||
func parseVariableAssignment(raw string) (variableAssignment, error) {
|
||||
key, value, found := strings.Cut(raw, "=")
|
||||
if !found {
|
||||
return variableAssignment{}, fmt.Errorf("variable assignment %q must contain =", raw)
|
||||
}
|
||||
return variableAssignment{key: key, value: value}, nil
|
||||
}
|
||||
|
||||
func stringDefault(value string) *string { return &value }
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -29,7 +30,7 @@ func TestCommandBuildsIndependentOptionalTrees(t *testing.T) {
|
||||
}}))
|
||||
var output bytes.Buffer
|
||||
outcome := promptOnly.Execute(context.Background(), []string{"help", "promptkit", "show"}, commandkit.Streams{Out: &output, Err: io.Discard})
|
||||
if outcome.Kind != commandkit.OutcomeSuccess || !strings.Contains(output.String(), "\n prompt ") || strings.Contains(output.String(), "\n profile ") || strings.Contains(output.String(), "config") {
|
||||
if outcome.Kind != commandkit.OutcomeSuccess || !strings.Contains(output.String(), "\n prompt ") || strings.Contains(output.String(), "\n profile ") || strings.Contains(output.String(), "requirements") || strings.Contains(output.String(), "config") {
|
||||
t.Fatalf("prompt-only help = (%#v, %q)", outcome, output.String())
|
||||
}
|
||||
|
||||
@@ -49,9 +50,21 @@ func TestCommandBuildsIndependentOptionalTrees(t *testing.T) {
|
||||
InspectProfile: func(context.Context, ProfileRequest, struct{}, struct{}) (commandkit.Acquired[*promptkit.ProfileInspection], error) {
|
||||
return commandkit.Acquired[*promptkit.ProfileInspection]{}, nil
|
||||
},
|
||||
InspectRequirements: func(context.Context, RequirementsRequest, struct{}, struct{}) (commandkit.Acquired[*promptkit.RequirementInspection], error) {
|
||||
return commandkit.Acquired[*promptkit.RequirementInspection]{}, nil
|
||||
},
|
||||
ListPrompts: func(context.Context, ckconfig.Selection, struct{}, struct{}) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
|
||||
return commandkit.Acquired[[]promptkit.PromptIdentity]{}, nil
|
||||
},
|
||||
ListProfiles: func(context.Context, ckconfig.Selection, struct{}, struct{}) (commandkit.Acquired[[]string], error) {
|
||||
return commandkit.Acquired[[]string]{}, nil
|
||||
},
|
||||
})
|
||||
if err := newPromptTestApp(t).Register(both); err != nil {
|
||||
t.Fatalf("both-capability tree failed to register: %v", err)
|
||||
all := newPromptTestApp(t, both)
|
||||
output.Reset()
|
||||
outcome = all.Execute(context.Background(), []string{"help", "promptkit"}, commandkit.Streams{Out: &output, Err: io.Discard})
|
||||
if outcome.Kind != commandkit.OutcomeSuccess || !strings.Contains(output.String(), "show") || !strings.Contains(output.String(), "list") || !strings.Contains(output.String(), "requirements") {
|
||||
t.Fatalf("all-capability tree = (%#v, %q)", outcome, output.String())
|
||||
}
|
||||
|
||||
app := newPromptTestApp(t, Command(Suite[struct{}, struct{}]{Selectors: []commandkit.Flag[struct{}]{{}}}))
|
||||
@@ -64,11 +77,156 @@ func TestCommandBuildsIndependentOptionalTrees(t *testing.T) {
|
||||
invalid := FromEngine[int, int](nil)
|
||||
invalid.ListPrompts, invalid.ListProfiles = nil, nil
|
||||
invalid.InspectPrompt, invalid.InspectProfile = nil, nil
|
||||
invalid.InspectRequirements = nil
|
||||
if err := newPromptTestApp(t).Register(Command(invalid)); err == nil || !strings.Contains(err.Error(), "PromptKit engine loader is nil") {
|
||||
t.Fatalf("empty invalid adapter lost its construction issue: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRequirementsCommandCapturesContextAndVariableAssignments(t *testing.T) {
|
||||
type input struct{ campaign commandkit.Supplied[string] }
|
||||
type state struct{ call int }
|
||||
|
||||
campaignFlag := commandkit.ValueFlag(commandkit.FlagMeta{Name: "campaign", Usage: "Application campaign."}, (*string)(nil), parseDefinitionString,
|
||||
func(target *input, value commandkit.Supplied[string]) { target.campaign = value })
|
||||
newInputCalls, checkInputCalls, newStateCalls, providerCalls := 0, 0, 0, 0
|
||||
var received RequirementsRequest
|
||||
var receivedInput input
|
||||
var receivedState state
|
||||
suite := Suite[input, state]{
|
||||
NewInput: func() input {
|
||||
newInputCalls++
|
||||
return input{}
|
||||
},
|
||||
NewState: func() state {
|
||||
newStateCalls++
|
||||
return state{call: newStateCalls}
|
||||
},
|
||||
Selectors: []commandkit.Flag[input]{campaignFlag},
|
||||
CheckInput: func(selection ckconfig.Selection, value input) error {
|
||||
checkInputCalls++
|
||||
if checkInputCalls == 1 {
|
||||
if !selection.Config.Set || selection.Config.Value != "" || !selection.Overlay.Set || selection.Overlay.Value != "" {
|
||||
t.Errorf("checked selection = %#v", selection)
|
||||
}
|
||||
if !value.campaign.Set || value.campaign.Value != "spring" {
|
||||
t.Errorf("checked campaign = %#v", value.campaign)
|
||||
}
|
||||
} else if selection.Config.Set || selection.Overlay.Set || value.campaign.Set {
|
||||
t.Errorf("second checked input retained prior invocation values: selection=%#v input=%#v", selection, value)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
InspectRequirements: func(_ context.Context, request RequirementsRequest, value input, gotState state) (commandkit.Acquired[*promptkit.RequirementInspection], error) {
|
||||
providerCalls++
|
||||
received, receivedInput, receivedState = request, value, gotState
|
||||
return commandkit.Acquired[*promptkit.RequirementInspection]{Value: &promptkit.RequirementInspection{
|
||||
PromptID: request.Inspection.PromptID, PromptVersion: request.Inspection.PromptVersion,
|
||||
ProfileID: request.Inspection.ProfileID, Complete: true,
|
||||
}}, nil
|
||||
},
|
||||
}
|
||||
app := newPromptTestApp(t, Command(suite))
|
||||
streams := commandkit.Streams{Out: io.Discard, Err: io.Discard}
|
||||
var help bytes.Buffer
|
||||
streams.Out = &help
|
||||
helpOutcome := app.Execute(context.Background(), []string{"help", "promptkit", "requirements", "show"}, streams)
|
||||
if helpOutcome.Kind != commandkit.OutcomeSuccess || !strings.Contains(help.String(), "id") {
|
||||
t.Fatalf("requirements-only help = (%#v, %q)", helpOutcome, help.String())
|
||||
}
|
||||
var familyHelp bytes.Buffer
|
||||
familyOutcome := app.Execute(context.Background(), []string{"help", "promptkit"}, commandkit.Streams{Out: &familyHelp, Err: io.Discard})
|
||||
if familyOutcome.Kind != commandkit.OutcomeSuccess || !strings.Contains(familyHelp.String(), "requirements") || strings.Contains(familyHelp.String(), "\n show ") || strings.Contains(familyHelp.String(), "\n list ") {
|
||||
t.Fatalf("requirements-only family help = (%#v, %q)", familyOutcome, familyHelp.String())
|
||||
}
|
||||
for _, flag := range []string{"--config", "--overlay", "--version", "--profile", "--session-id", "--var", "--format", "--campaign"} {
|
||||
if !strings.Contains(help.String(), flag) {
|
||||
t.Errorf("requirements help omits %s: %q", flag, help.String())
|
||||
}
|
||||
}
|
||||
if strings.Contains(help.String(), "--scope") || newInputCalls != 0 || checkInputCalls != 0 || newStateCalls != 0 || providerCalls != 0 {
|
||||
t.Fatalf("help selected a scope or invoked application code: output=%q factories/checks/providers=%d/%d/%d/%d", help.String(), newInputCalls, checkInputCalls, newStateCalls, providerCalls)
|
||||
}
|
||||
|
||||
var output bytes.Buffer
|
||||
args := []string{
|
||||
"promptkit", "requirements", "show", "briefing", "--campaign", "spring",
|
||||
"--config", "before.yml", "--config=", "--overlay", "base.yml", "--overlay=",
|
||||
"--version", "1", "--version", "2", "--profile", "first", "--profile", "editorial",
|
||||
"--session-id", "old-session", "--session-id", "session-42", "--format", "text", "--format", "yaml",
|
||||
"--var", "note=hello, world", "--var", "empty=", "--var", "token=a=b", "--var", "=value",
|
||||
"--var", "mode=brief", "--var", "mode=full",
|
||||
}
|
||||
outcome := app.Execute(context.Background(), args, commandkit.Streams{Out: &output, Err: io.Discard})
|
||||
if outcome.Kind != commandkit.OutcomeSuccess || outcome.Status != 0 {
|
||||
t.Fatalf("requirements invocation = %#v, output=%q", outcome, output.String())
|
||||
}
|
||||
if newInputCalls != 1 || checkInputCalls != 1 || newStateCalls != 1 || providerCalls != 1 {
|
||||
t.Fatalf("first invocation calls = input/check/state/provider %d/%d/%d/%d", newInputCalls, checkInputCalls, newStateCalls, providerCalls)
|
||||
}
|
||||
if !received.Selection.Config.Set || received.Selection.Config.Value != "" || !received.Selection.Overlay.Set || received.Selection.Overlay.Value != "" {
|
||||
t.Fatalf("configuration selection = %#v", received.Selection)
|
||||
}
|
||||
wantVariables := map[string]string{"note": "hello, world", "empty": "", "token": "a=b", "": "value", "mode": "full"}
|
||||
if received.Inspection.PromptID != "briefing" || received.Inspection.PromptVersion != "2" || received.Inspection.ProfileID != "editorial" || received.Inspection.SessionID != "session-42" || !reflect.DeepEqual(received.Inspection.Vars, wantVariables) {
|
||||
t.Fatalf("native request = %#v, want vars %#v", received.Inspection, wantVariables)
|
||||
}
|
||||
if !receivedInput.campaign.Set || receivedInput.campaign.Value != "spring" || receivedState.call != 1 {
|
||||
t.Fatalf("provider input/state = %#v/%#v", receivedInput, receivedState)
|
||||
}
|
||||
var report map[string]any
|
||||
if err := yaml.Unmarshal(output.Bytes(), &report); err != nil || report["prompt_id"] != "briefing" || report["complete"] != true {
|
||||
t.Fatalf("default requirements YAML = %#v (decode error %v), output=%q", report, err, output.String())
|
||||
}
|
||||
|
||||
output.Reset()
|
||||
outcome = app.Execute(context.Background(), []string{"promptkit", "requirements", "show", "briefing"}, commandkit.Streams{Out: &output, Err: io.Discard})
|
||||
if outcome.Kind != commandkit.OutcomeSuccess || newInputCalls != 2 || checkInputCalls != 2 || newStateCalls != 2 || providerCalls != 2 {
|
||||
t.Fatalf("second invocation = %#v, calls=%d/%d/%d/%d", outcome, newInputCalls, checkInputCalls, newStateCalls, providerCalls)
|
||||
}
|
||||
if len(received.Inspection.Vars) != 0 || received.Inspection.PromptVersion != "" || received.Inspection.ProfileID != "" || received.Inspection.SessionID != "" {
|
||||
t.Fatalf("second invocation retained native values: %#v", received.Inspection)
|
||||
}
|
||||
if !strings.HasPrefix(output.String(), "prompt_id:") {
|
||||
t.Fatalf("omitted format did not default to YAML: %q", output.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestRequirementsCommandUsageFailuresPrecedeApplicationPreparation(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
args []string
|
||||
}{
|
||||
{name: "missing operand", args: []string{"promptkit", "requirements", "show"}},
|
||||
{name: "extra operand", args: []string{"promptkit", "requirements", "show", "briefing", "extra"}},
|
||||
{name: "unsupported format", args: []string{"promptkit", "requirements", "show", "briefing", "--format", "text"}},
|
||||
{name: "malformed variable followed by valid assignment", args: []string{"promptkit", "requirements", "show", "briefing", "--var", "broken", "--var", "mode=full"}},
|
||||
{name: "no built-in scope", args: []string{"promptkit", "requirements", "show", "briefing", "--scope", "all"}},
|
||||
{name: "malformed variable on help", args: []string{"help", "promptkit", "requirements", "show", "--var", "broken"}},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
newInputCalls, checkInputCalls, newStateCalls, providerCalls := 0, 0, 0, 0
|
||||
suite := Suite[struct{}, struct{}]{
|
||||
NewInput: func() struct{} { newInputCalls++; return struct{}{} },
|
||||
CheckInput: func(ckconfig.Selection, struct{}) error {
|
||||
checkInputCalls++
|
||||
return nil
|
||||
},
|
||||
NewState: func() struct{} { newStateCalls++; return struct{}{} },
|
||||
InspectRequirements: func(context.Context, RequirementsRequest, struct{}, struct{}) (commandkit.Acquired[*promptkit.RequirementInspection], error) {
|
||||
providerCalls++
|
||||
return commandkit.Acquired[*promptkit.RequirementInspection]{Value: &promptkit.RequirementInspection{}}, nil
|
||||
},
|
||||
}
|
||||
var output bytes.Buffer
|
||||
outcome := newPromptTestApp(t, Command(suite)).Execute(context.Background(), test.args, commandkit.Streams{Out: &output, Err: io.Discard})
|
||||
if outcome.Kind != commandkit.OutcomeUsage || outcome.Status != 2 || newInputCalls != 0 || checkInputCalls != 0 || newStateCalls != 0 || providerCalls != 0 {
|
||||
t.Fatalf("usage failure = %#v, factories/checks/providers=%d/%d/%d/%d output=%q", outcome, newInputCalls, checkInputCalls, newStateCalls, providerCalls, output.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCatalogCommandTreesAreIndependentAndOmitShow(t *testing.T) {
|
||||
prompts := Command(Suite[struct{}, struct{}]{
|
||||
ListPrompts: func(context.Context, ckconfig.Selection, struct{}, struct{}) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
|
||||
|
||||
Reference in New Issue
Block a user