Extend native catalog adapters

This commit is contained in:
2026-10-17 18:44:10 +00:00
parent c1fa18629d
commit dc4261a1ca
5 changed files with 182 additions and 49 deletions

View File

@@ -1,6 +1,6 @@
# Dependency upgrades, discovery, and smoke testing implementation plan
Status: Stages 1–5 complete; Stage 6 is next.
Status: Stages 1–6 complete; Stage 7 is next.
## Authority and baseline
@@ -381,6 +381,15 @@ operator syntax delivered in Stage 7.
**Complete when:** all five catalogs are available through narrow native adapters
and public callback shapes are coherent.
**Completed:** 2026-10-17. Added `CatalogRequest` and `NamespaceRequest`,
updated the prompt/profile callbacks, and exposed backend, namespace, and
collection callbacks. `FromEngine` forwards selections and native filters or
kinds to all five PromptKit catalog methods, preserving returned values,
diagnostics, and errors. Existing catalog callers now send the default request.
Focused adapter tests compare each callback with its native method and cover
invocation values, loader diagnostics/error identity, and cancellation. The
focused adapter/catalog tests and `GOTOOLCHAIN=local go build ./...` passed.
## Stage 7: Add catalog command bindings and YAML output
**Primary files:** ckprompt catalog command construction, input preparation,

View File

@@ -29,6 +29,28 @@ type ProfileRequest struct {
ID string
}
// CatalogRequest selects the configuration and native namespace filter for a
// prompt, profile, or backend catalog operation. A zero Filter preserves
// PromptKit's native default selection.
type CatalogRequest struct {
// Selection carries the configuration and overlay supplied to the command.
Selection ckconfig.Selection
// Filter is forwarded unchanged to each filterable native catalog. Its zero
// value preserves PromptKit's default namespace selection.
Filter promptkit.NamespaceFilter
}
// NamespaceRequest selects the configuration and native resource kinds for a
// namespace catalog operation. An empty Kinds slice preserves PromptKit's
// native default selection.
type NamespaceRequest struct {
// Selection carries the configuration and overlay supplied to the command.
Selection ckconfig.Selection
// Kinds is forwarded unchanged to the native namespace catalog. An empty
// slice preserves PromptKit's default kind selection.
Kinds []promptkit.ResourceKind
}
// RequirementsRequest selects a prompt context for native requirements
// inspection.
type RequirementsRequest struct {
@@ -81,11 +103,25 @@ type Suite[I, S any] struct {
// success; PromptKit errors are returned unchanged where supported.
ValidateRequest func(context.Context, ValidationRequest, I, S) (commandkit.Acquired[struct{}], error)
// ListPrompts lists prompt identities after input and state preparation.
// It is optional; a nil callback does not install a prompt catalog command.
ListPrompts func(context.Context, ckconfig.Selection, I, S) (commandkit.Acquired[[]promptkit.PromptIdentity], error)
// ListProfiles lists profile IDs after input and state preparation.
// It is optional; a nil callback does not install a profile catalog command.
ListProfiles func(context.Context, ckconfig.Selection, I, S) (commandkit.Acquired[[]string], error)
// It is optional independently of the other catalogs; nil omits only this
// catalog command.
ListPrompts func(context.Context, CatalogRequest, I, S) (commandkit.Acquired[[]promptkit.PromptIdentity], error)
// ListProfiles lists profile IDs after input and state preparation. It is
// optional independently of the other catalogs; nil omits only this catalog
// command.
ListProfiles func(context.Context, CatalogRequest, I, S) (commandkit.Acquired[[]string], error)
// ListBackends lists backend IDs after input and state preparation. It is
// optional independently of the other catalogs; nil omits only this catalog
// command.
ListBackends func(context.Context, CatalogRequest, I, S) (commandkit.Acquired[[]string], error)
// ListNamespaces lists native namespace names after input and state
// preparation. It is optional independently of the other catalogs; nil omits
// only this catalog command.
ListNamespaces func(context.Context, NamespaceRequest, I, S) (commandkit.Acquired[[]string], error)
// ListCollections lists collection information after input and state
// preparation. It is optional independently of the other catalogs; nil
// omits only this catalog command.
ListCollections func(context.Context, ckconfig.Selection, I, S) (commandkit.Acquired[[]promptkit.CollectionInfo], error)
issues []error
}
@@ -225,11 +261,13 @@ func promptKitContextError(ctx context.Context) error {
return ctx.Err()
}
// FromEngine supplies five PromptKit-backed callbacks: prompt and profile
// catalogs, named prompt and profile inspection, and requirements discovery.
// FromEngine supplies eight PromptKit-backed callbacks: prompt, profile,
// backend, namespace, and collection catalogs, plus named prompt and profile
// inspection and requirements discovery.
// The requirements callback forwards RequirementsRequest.Inspection to
// Engine.InspectRequirements. Concrete request validation is an independent
// capability and can be composed explicitly with WithRequestValidation.
// capability and can be composed explicitly with WithRequestValidation. Smoke
// testing is also an explicit capability installed by its helper.
// FromEngine does not call the loader during construction. Each selected
// operation passes its context, supplied selection, initialized input, and
// shared invocation state to the loader before calling PromptKit's public
@@ -242,22 +280,46 @@ func FromEngine[I, S any](load func(context.Context, ckconfig.Selection, I, S) (
}
return Suite[I, S]{
ListPrompts: func(ctx context.Context, selection ckconfig.Selection, input I, state S) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
engine, _, diagnostics, err := loadPromptKitEngine(ctx, selection, input, state, "", load)
ListPrompts: func(ctx context.Context, request CatalogRequest, input I, state S) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
engine, _, diagnostics, err := loadPromptKitEngine(ctx, request.Selection, input, state, "", load)
if err != nil {
return commandkit.Acquired[[]promptkit.PromptIdentity]{Diagnostics: diagnostics}, err
}
prompts, err := engine.ListPrompts(ctx)
prompts, err := engine.ListPrompts(ctx, request.Filter)
return commandkit.Acquired[[]promptkit.PromptIdentity]{Value: prompts, Diagnostics: diagnostics}, err
},
ListProfiles: func(ctx context.Context, selection ckconfig.Selection, input I, state S) (commandkit.Acquired[[]string], error) {
engine, _, diagnostics, err := loadPromptKitEngine(ctx, selection, input, state, "", load)
ListProfiles: func(ctx context.Context, request CatalogRequest, input I, state S) (commandkit.Acquired[[]string], error) {
engine, _, diagnostics, err := loadPromptKitEngine(ctx, request.Selection, input, state, "", load)
if err != nil {
return commandkit.Acquired[[]string]{Diagnostics: diagnostics}, err
}
profiles, err := engine.ListProfiles(ctx)
profiles, err := engine.ListProfiles(ctx, request.Filter)
return commandkit.Acquired[[]string]{Value: profiles, Diagnostics: diagnostics}, err
},
ListBackends: func(ctx context.Context, request CatalogRequest, input I, state S) (commandkit.Acquired[[]string], error) {
engine, _, diagnostics, err := loadPromptKitEngine(ctx, request.Selection, input, state, "", load)
if err != nil {
return commandkit.Acquired[[]string]{Diagnostics: diagnostics}, err
}
backends, err := engine.ListBackends(ctx, request.Filter)
return commandkit.Acquired[[]string]{Value: backends, Diagnostics: diagnostics}, err
},
ListNamespaces: func(ctx context.Context, request NamespaceRequest, input I, state S) (commandkit.Acquired[[]string], error) {
engine, _, diagnostics, err := loadPromptKitEngine(ctx, request.Selection, input, state, "", load)
if err != nil {
return commandkit.Acquired[[]string]{Diagnostics: diagnostics}, err
}
namespaces, err := engine.ListNamespaces(ctx, request.Kinds...)
return commandkit.Acquired[[]string]{Value: namespaces, Diagnostics: diagnostics}, err
},
ListCollections: func(ctx context.Context, selection ckconfig.Selection, input I, state S) (commandkit.Acquired[[]promptkit.CollectionInfo], error) {
engine, _, diagnostics, err := loadPromptKitEngine(ctx, selection, input, state, "", load)
if err != nil {
return commandkit.Acquired[[]promptkit.CollectionInfo]{Diagnostics: diagnostics}, err
}
collections, err := engine.ListCollections(ctx)
return commandkit.Acquired[[]promptkit.CollectionInfo]{Value: collections, Diagnostics: diagnostics}, err
},
InspectPrompt: func(ctx context.Context, request PromptRequest, input I, state S) (commandkit.Acquired[*promptkit.PromptInspection], error) {
engine, _, diagnostics, err := loadPromptKitEngine(ctx, request.Selection, input, state, "", load)
if err != nil {

View File

@@ -458,25 +458,51 @@ func TestFromEngineListsNativeCatalogsWithInvocationValues(t *testing.T) {
}
return engine, nil
})
if suite.ListPrompts == nil || suite.ListProfiles == nil {
t.Fatalf("FromEngine did not supply both catalog callbacks: %#v", suite)
if suite.ListPrompts == nil || suite.ListProfiles == nil || suite.ListBackends == nil || suite.ListNamespaces == nil || suite.ListCollections == nil {
t.Fatalf("FromEngine did not supply all five catalog callbacks: %#v", suite)
}
wantPrompts, err := engine.ListPrompts(wantContext)
catalogRequest := CatalogRequest{Selection: wantSelection, Filter: promptkit.NamespaceFilter{Mode: promptkit.NamespaceNamed, Name: "missing"}}
namespaceRequest := NamespaceRequest{Selection: wantSelection, Kinds: []promptkit.ResourceKind{promptkit.ResourcePrompt}}
wantPrompts, err := engine.ListPrompts(wantContext, catalogRequest.Filter)
if err != nil {
t.Fatal(err)
}
wantProfiles, err := engine.ListProfiles(wantContext)
wantProfiles, err := engine.ListProfiles(wantContext, catalogRequest.Filter)
if err != nil {
t.Fatal(err)
}
prompts, err := suite.ListPrompts(wantContext, wantSelection, wantInput, wantState)
wantBackends, err := engine.ListBackends(wantContext, catalogRequest.Filter)
if err != nil {
t.Fatal(err)
}
wantNamespaces, err := engine.ListNamespaces(wantContext, namespaceRequest.Kinds...)
if err != nil {
t.Fatal(err)
}
wantCollections, err := engine.ListCollections(wantContext)
if err != nil {
t.Fatal(err)
}
prompts, err := suite.ListPrompts(wantContext, catalogRequest, wantInput, wantState)
if err != nil || !reflect.DeepEqual(prompts.Value, wantPrompts) || len(prompts.Diagnostics) != 0 || loaderCalls != 1 {
t.Fatalf("prompt catalog = (%#v, %v), calls=%d, want %#v", prompts, err, loaderCalls, wantPrompts)
}
profiles, err := suite.ListProfiles(wantContext, wantSelection, wantInput, wantState)
profiles, err := suite.ListProfiles(wantContext, catalogRequest, wantInput, wantState)
if err != nil || !reflect.DeepEqual(profiles.Value, wantProfiles) || len(profiles.Diagnostics) != 0 || loaderCalls != 2 {
t.Fatalf("profile catalog = (%#v, %v), calls=%d, want %#v", profiles, err, loaderCalls, wantProfiles)
}
backends, err := suite.ListBackends(wantContext, catalogRequest, wantInput, wantState)
if err != nil || !reflect.DeepEqual(backends.Value, wantBackends) || len(backends.Diagnostics) != 0 || loaderCalls != 3 {
t.Fatalf("backend catalog = (%#v, %v), calls=%d, want %#v", backends, err, loaderCalls, wantBackends)
}
namespaces, err := suite.ListNamespaces(wantContext, namespaceRequest, wantInput, wantState)
if err != nil || !reflect.DeepEqual(namespaces.Value, wantNamespaces) || len(namespaces.Diagnostics) != 0 || loaderCalls != 4 {
t.Fatalf("namespace catalog = (%#v, %v), calls=%d, want %#v", namespaces, err, loaderCalls, wantNamespaces)
}
collections, err := suite.ListCollections(wantContext, wantSelection, wantInput, wantState)
if err != nil || !reflect.DeepEqual(collections.Value, wantCollections) || len(collections.Diagnostics) != 0 || loaderCalls != 5 {
t.Fatalf("collection catalog = (%#v, %v), calls=%d, want %#v", collections, err, loaderCalls, wantCollections)
}
}
func TestFromEngineCatalogsRetainLoadDiagnosticsAndErrorIdentity(t *testing.T) {
@@ -492,7 +518,7 @@ func TestFromEngineCatalogsRetainLoadDiagnosticsAndErrorIdentity(t *testing.T) {
call func() (int, error)
}{
{name: "prompts", call: func() (int, error) {
acquired, err := suite.ListPrompts(context.Background(), ckconfig.Selection{}, 0, 0)
acquired, err := suite.ListPrompts(context.Background(), CatalogRequest{}, 0, 0)
var retained *configkit.LoadError
if !errors.As(err, &retained) || retained != loadErr || len(acquired.Diagnostics) == 0 {
t.Errorf("prompt load failure = (%#v, %v)", acquired, err)
@@ -500,13 +526,37 @@ func TestFromEngineCatalogsRetainLoadDiagnosticsAndErrorIdentity(t *testing.T) {
return len(acquired.Diagnostics), err
}},
{name: "profiles", call: func() (int, error) {
acquired, err := suite.ListProfiles(context.Background(), ckconfig.Selection{}, 0, 0)
acquired, err := suite.ListProfiles(context.Background(), CatalogRequest{}, 0, 0)
var retained *configkit.LoadError
if !errors.As(err, &retained) || retained != loadErr || len(acquired.Diagnostics) == 0 {
t.Errorf("profile load failure = (%#v, %v)", acquired, err)
}
return len(acquired.Diagnostics), err
}},
{name: "backends", call: func() (int, error) {
acquired, err := suite.ListBackends(context.Background(), CatalogRequest{}, 0, 0)
var retained *configkit.LoadError
if !errors.As(err, &retained) || retained != loadErr || len(acquired.Diagnostics) == 0 {
t.Errorf("backend load failure = (%#v, %v)", acquired, err)
}
return len(acquired.Diagnostics), err
}},
{name: "namespaces", call: func() (int, error) {
acquired, err := suite.ListNamespaces(context.Background(), NamespaceRequest{}, 0, 0)
var retained *configkit.LoadError
if !errors.As(err, &retained) || retained != loadErr || len(acquired.Diagnostics) == 0 {
t.Errorf("namespace load failure = (%#v, %v)", acquired, err)
}
return len(acquired.Diagnostics), err
}},
{name: "collections", call: func() (int, error) {
acquired, err := suite.ListCollections(context.Background(), ckconfig.Selection{}, 0, 0)
var retained *configkit.LoadError
if !errors.As(err, &retained) || retained != loadErr || len(acquired.Diagnostics) == 0 {
t.Errorf("collection load failure = (%#v, %v)", acquired, err)
}
return len(acquired.Diagnostics), err
}},
} {
t.Run(test.name, func(t *testing.T) {
diagnosticCount, err := test.call()
@@ -525,11 +575,23 @@ func TestFromEngineCatalogsHonorCancellationAfterLoad(t *testing.T) {
call func(Suite[int, int], context.Context) error
}{
{name: "prompts", call: func(suite Suite[int, int], ctx context.Context) error {
_, err := suite.ListPrompts(ctx, ckconfig.Selection{}, 0, 0)
_, err := suite.ListPrompts(ctx, CatalogRequest{}, 0, 0)
return err
}},
{name: "profiles", call: func(suite Suite[int, int], ctx context.Context) error {
_, err := suite.ListProfiles(ctx, ckconfig.Selection{}, 0, 0)
_, err := suite.ListProfiles(ctx, CatalogRequest{}, 0, 0)
return err
}},
{name: "backends", call: func(suite Suite[int, int], ctx context.Context) error {
_, err := suite.ListBackends(ctx, CatalogRequest{}, 0, 0)
return err
}},
{name: "namespaces", call: func(suite Suite[int, int], ctx context.Context) error {
_, err := suite.ListNamespaces(ctx, NamespaceRequest{}, 0, 0)
return err
}},
{name: "collections", call: func(suite Suite[int, int], ctx context.Context) error {
_, err := suite.ListCollections(ctx, ckconfig.Selection{}, 0, 0)
return err
}},
} {
@@ -545,7 +607,7 @@ func TestFromEngineCatalogsHonorCancellationAfterLoad(t *testing.T) {
}
})
}
if loaderCalls != 2 {
if loaderCalls != 5 {
t.Fatalf("catalog loaders called = %d, want one per provider", loaderCalls)
}
}

View File

@@ -310,7 +310,7 @@ func runCatalogList[T any, I, S any](
invocation commandkit.Invocation,
suite Suite[I, S],
input *catalogInput[I],
list func(context.Context, ckconfig.Selection, I, S) (commandkit.Acquired[T], error),
list func(context.Context, CatalogRequest, I, S) (commandkit.Acquired[T], error),
encode func(T) ([]byte, error),
) commandkit.Outcome {
if invocation.Context != nil {
@@ -328,7 +328,7 @@ func runCatalogList[T any, I, S any](
}
}
acquired, err := list(invocation.Context, input.selection, input.selected, state)
acquired, err := list(invocation.Context, CatalogRequest{Selection: input.selection}, input.selected, state)
if err != nil {
return definitionFailure(err, acquired.Diagnostics)
}

View File

@@ -56,10 +56,10 @@ func TestCommandBuildsIndependentOptionalTrees(t *testing.T) {
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) {
ListPrompts: func(context.Context, CatalogRequest, 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) {
ListProfiles: func(context.Context, CatalogRequest, struct{}, struct{}) (commandkit.Acquired[[]string], error) {
return commandkit.Acquired[[]string]{}, nil
},
})
@@ -232,12 +232,12 @@ func TestRequirementsCommandUsageFailuresPrecedeApplicationPreparation(t *testin
func TestCatalogCommandTreesAreIndependentAndOmitShow(t *testing.T) {
prompts := Command(Suite[struct{}, struct{}]{
ListPrompts: func(context.Context, ckconfig.Selection, struct{}, struct{}) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
ListPrompts: func(context.Context, CatalogRequest, struct{}, struct{}) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
return commandkit.Acquired[[]promptkit.PromptIdentity]{}, nil
},
})
profiles := Command(Suite[struct{}, struct{}]{
ListProfiles: func(context.Context, ckconfig.Selection, struct{}, struct{}) (commandkit.Acquired[[]string], error) {
ListProfiles: func(context.Context, CatalogRequest, struct{}, struct{}) (commandkit.Acquired[[]string], error) {
return commandkit.Acquired[[]string]{}, nil
},
})
@@ -264,7 +264,7 @@ func TestCatalogCommandTreesAreIndependentAndOmitShow(t *testing.T) {
InspectPrompt: func(context.Context, PromptRequest, struct{}, struct{}) (commandkit.Acquired[*promptkit.PromptInspection], error) {
return commandkit.Acquired[*promptkit.PromptInspection]{}, nil
},
ListPrompts: func(context.Context, ckconfig.Selection, struct{}, struct{}) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
ListPrompts: func(context.Context, CatalogRequest, struct{}, struct{}) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
return commandkit.Acquired[[]promptkit.PromptIdentity]{}, nil
},
})
@@ -298,9 +298,9 @@ func TestCatalogListUsesPreparedInputAndPreflightsFormat(t *testing.T) {
}
return nil
},
ListPrompts: func(_ context.Context, selection ckconfig.Selection, value input, gotState state) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
ListPrompts: func(_ context.Context, request CatalogRequest, value input, gotState state) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
providerCalls++
received, receivedSelection, receivedState = value, selection, gotState
received, receivedSelection, receivedState = value, request.Selection, gotState
return commandkit.Acquired[[]promptkit.PromptIdentity]{Value: []promptkit.PromptIdentity{{ID: "briefing", Version: testStringPointer("1")}}}, nil
},
}
@@ -372,13 +372,13 @@ func TestCatalogLifecycleCapturesSelectorsAndRefreshesInvocationValues(t *testin
}
return nil
},
ListPrompts: func(_ context.Context, selection ckconfig.Selection, got input, gotState *state) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
ListPrompts: func(_ context.Context, request CatalogRequest, got input, gotState *state) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
providers++
if gotState == nil || gotState.run != providers {
t.Errorf("provider state = %#v at invocation %d", gotState, providers)
}
if providers == 1 && (!selection.Config.Set || selection.Config.Value != "" || !selection.Overlay.Set || selection.Overlay.Value != "" || !got.campaign.Set || !got.enabled.Set || !got.limit.Set || !got.labels.Set) {
t.Errorf("first provider values = selection %#v input %#v", selection, got)
if providers == 1 && (!request.Selection.Config.Set || request.Selection.Config.Value != "" || !request.Selection.Overlay.Set || request.Selection.Overlay.Value != "" || !got.campaign.Set || !got.enabled.Set || !got.limit.Set || !got.labels.Set) {
t.Errorf("first provider values = selection %#v input %#v", request.Selection, got)
}
return commandkit.Acquired[[]promptkit.PromptIdentity]{Value: []promptkit.PromptIdentity{}}, nil
},
@@ -424,9 +424,9 @@ func TestCatalogLifecycleCapturesSelectorsAndRefreshesInvocationValues(t *testin
func TestCatalogNilFactoriesSupplyZeroValues(t *testing.T) {
app := newPromptTestApp(t, Command(Suite[*struct{}, *struct{}]{
ListPrompts: func(_ context.Context, selection ckconfig.Selection, input, state *struct{}) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
if input != nil || state != nil || selection.Config.Set || selection.Overlay.Set {
t.Errorf("nil-factory values = selection %#v input %#v state %#v", selection, input, state)
ListPrompts: func(_ context.Context, request CatalogRequest, input, state *struct{}) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
if input != nil || state != nil || request.Selection.Config.Set || request.Selection.Overlay.Set {
t.Errorf("nil-factory values = selection %#v input %#v state %#v", request.Selection, input, state)
}
return commandkit.Acquired[[]promptkit.PromptIdentity]{}, nil
},
@@ -446,10 +446,10 @@ func TestCatalogCommandsRenderNativeValuesAndEmptySequences(t *testing.T) {
}
profiles := []string{"later", "001", "a: true", "later"}
suite := Suite[struct{}, struct{}]{
ListPrompts: func(context.Context, ckconfig.Selection, struct{}, struct{}) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
ListPrompts: func(context.Context, CatalogRequest, struct{}, struct{}) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
return commandkit.Acquired[[]promptkit.PromptIdentity]{Value: prompts}, nil
},
ListProfiles: func(context.Context, ckconfig.Selection, struct{}, struct{}) (commandkit.Acquired[[]string], error) {
ListProfiles: func(context.Context, CatalogRequest, struct{}, struct{}) (commandkit.Acquired[[]string], error) {
return commandkit.Acquired[[]string]{Value: profiles}, nil
},
}
@@ -502,14 +502,14 @@ func TestCatalogCommandsRenderNativeValuesAndEmptySequences(t *testing.T) {
promptEmptyCalls, profileEmptyCalls := 0, 0
emptyApp := newPromptTestApp(t, Command(Suite[struct{}, struct{}]{
ListPrompts: func(context.Context, ckconfig.Selection, struct{}, struct{}) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
ListPrompts: func(context.Context, CatalogRequest, struct{}, struct{}) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
promptEmptyCalls++
if promptEmptyCalls%2 == 0 {
return commandkit.Acquired[[]promptkit.PromptIdentity]{Value: []promptkit.PromptIdentity{}}, nil
}
return commandkit.Acquired[[]promptkit.PromptIdentity]{Value: nil}, nil
},
ListProfiles: func(context.Context, ckconfig.Selection, struct{}, struct{}) (commandkit.Acquired[[]string], error) {
ListProfiles: func(context.Context, CatalogRequest, struct{}, struct{}) (commandkit.Acquired[[]string], error) {
profileEmptyCalls++
if profileEmptyCalls%2 == 0 {
return commandkit.Acquired[[]string]{Value: []string{}}, nil
@@ -530,7 +530,7 @@ func TestCatalogCommandsRenderNativeValuesAndEmptySequences(t *testing.T) {
func TestCatalogRejectsOperandsAndUnavailableSelectors(t *testing.T) {
calls := 0
app := newPromptTestApp(t, Command(Suite[struct{}, struct{}]{ListPrompts: func(context.Context, ckconfig.Selection, struct{}, struct{}) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
app := newPromptTestApp(t, Command(Suite[struct{}, struct{}]{ListPrompts: func(context.Context, CatalogRequest, struct{}, struct{}) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
calls++
return commandkit.Acquired[[]promptkit.PromptIdentity]{}, nil
}}))
@@ -564,7 +564,7 @@ func TestCatalogFailuresRetainDiagnosticsAndDeliveryState(t *testing.T) {
return false
}
providerErr := errors.New("catalog provider failed")
app := newPromptTestApp(t, Command(Suite[struct{}, struct{}]{ListPrompts: func(context.Context, ckconfig.Selection, struct{}, struct{}) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
app := newPromptTestApp(t, Command(Suite[struct{}, struct{}]{ListPrompts: func(context.Context, CatalogRequest, struct{}, struct{}) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
return commandkit.Acquired[[]promptkit.PromptIdentity]{Diagnostics: []commandkit.Diagnostic{diagnostic}}, providerErr
}}))
outcome := app.Execute(context.Background(), []string{"promptkit", "list", "prompts"}, commandkit.Streams{Out: io.Discard, Err: io.Discard})
@@ -573,7 +573,7 @@ func TestCatalogFailuresRetainDiagnosticsAndDeliveryState(t *testing.T) {
}
ctx, cancel := context.WithCancel(context.Background())
canceled := newPromptTestApp(t, Command(Suite[struct{}, struct{}]{ListPrompts: func(context.Context, ckconfig.Selection, struct{}, struct{}) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
canceled := newPromptTestApp(t, Command(Suite[struct{}, struct{}]{ListPrompts: func(context.Context, CatalogRequest, struct{}, struct{}) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
cancel()
return commandkit.Acquired[[]promptkit.PromptIdentity]{Value: []promptkit.PromptIdentity{{ID: "briefing", Version: testStringPointer("1")}}, Diagnostics: []commandkit.Diagnostic{diagnostic}}, nil
}}))
@@ -593,7 +593,7 @@ func TestCatalogFailuresRetainDiagnosticsAndDeliveryState(t *testing.T) {
{name: "short write", writer: partialReportWriter{}, want: io.ErrShortWrite},
} {
t.Run(test.name, func(t *testing.T) {
writerApp := newPromptTestApp(t, Command(Suite[struct{}, struct{}]{ListPrompts: func(context.Context, ckconfig.Selection, struct{}, struct{}) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
writerApp := newPromptTestApp(t, Command(Suite[struct{}, struct{}]{ListPrompts: func(context.Context, CatalogRequest, struct{}, struct{}) (commandkit.Acquired[[]promptkit.PromptIdentity], error) {
return commandkit.Acquired[[]promptkit.PromptIdentity]{Value: []promptkit.PromptIdentity{{ID: "briefing", Version: testStringPointer("1")}}, Diagnostics: []commandkit.Diagnostic{diagnostic}}, nil
}}))
outcome := writerApp.Execute(context.Background(), []string{"promptkit", "list", "prompts"}, commandkit.Streams{Out: test.writer, Err: io.Discard})