Load prompt configuration comparison sides independently

This commit is contained in:
2026-11-10 20:22:23 +00:00
parent 803effc6ea
commit bae96e5dd5
3 changed files with 60 additions and 14 deletions

View File

@@ -44,13 +44,6 @@ func loadApplication(ctx context.Context, selection ckconfig.Selection, _ struct
}
func loadPromptEngine(ctx context.Context, selection ckconfig.Selection, input struct{}, state *invocationState) (*pk.Engine, error) {
if state != nil {
for _, entry := range state.engines {
if reflect.DeepEqual(entry.selection, selection) {
return entry.engine, nil
}
}
}
loaded, err := loadApplication(ctx, selection, input, state)
if err != nil {
return nil, err
@@ -63,12 +56,27 @@ func loadPromptEngine(ctx context.Context, selection ckconfig.Selection, input s
if err != nil {
return nil, err
}
if state != nil {
state.engines = append(state.engines, engineEntry{selection: selection, engine: runtime.Engine})
}
return runtime.Engine, nil
}
func capturePromptEngine(ctx context.Context, selection ckconfig.Selection, input struct{}, state *invocationState) (*pk.Engine, error) {
if state != nil {
for _, entry := range state.engines {
if reflect.DeepEqual(entry.selection, selection) {
return entry.engine, nil
}
}
}
engine, err := loadPromptEngine(ctx, selection, input, state)
if err != nil {
return nil, err
}
if state != nil {
state.engines = append(state.engines, engineEntry{selection: selection, engine: engine})
}
return engine, nil
}
func buildApplication(extra ...commandkit.Declaration) (*commandkit.App, error) {
return buildApplicationWithClient(nil, extra...)
}
@@ -78,15 +86,15 @@ func buildApplicationWithClient(client *http.Client, extra ...commandkit.Declara
appScope.Features.Overrides = true
promptScope := ckprompt.ConfigScope(loadPromptEngine)
configCommand := ckconfig.Command(ckconfig.Suite[struct{}, *invocationState]{NewState: func() *invocationState { return &invocationState{client: client} }, Scopes: []ckconfig.Scope[struct{}, *invocationState]{appScope, promptScope}})
definitions := ckprompt.WithNamespaces(ckprompt.FromEngine(loadPromptEngine), pk.Namespaces{})
definitions := ckprompt.WithNamespaces(ckprompt.FromEngine(capturePromptEngine), pk.Namespaces{})
definitions.NewState = func() *invocationState { return &invocationState{client: client} }
definitions = ckprompt.WithRequestValidation(definitions, loadPromptEngine, func(_ context.Context, seed ckprompt.ValidationRequest, _ struct{}, _ *invocationState) (pk.RunRequest, error) {
definitions = ckprompt.WithRequestValidation(definitions, capturePromptEngine, func(_ context.Context, seed ckprompt.ValidationRequest, _ struct{}, _ *invocationState) (pk.RunRequest, error) {
return applicationPromptRequest(seed.Request, seed.Namespaces), nil
})
definitions = ckprompt.WithRequestPreparation(definitions, loadPromptEngine, func(_ context.Context, seed ckprompt.PreparationRequest, _ struct{}, _ *invocationState) (pk.RunRequest, error) {
definitions = ckprompt.WithRequestPreparation(definitions, capturePromptEngine, func(_ context.Context, seed ckprompt.PreparationRequest, _ struct{}, _ *invocationState) (pk.RunRequest, error) {
return applicationPromptRequest(seed.Request, seed.Namespaces), nil
})
definitions = ckprompt.WithSmokeTesting(definitions, loadPromptEngine, nil)
definitions = ckprompt.WithSmokeTesting(definitions, capturePromptEngine, nil)
declarations := []commandkit.Declaration{configCommand, commandkit.Completion("audita"), processCommand()}
declarations = append(declarations, ckprompt.Declarations(definitions)...)
declarations = append(declarations, extra...)

View File

@@ -11,6 +11,8 @@ import (
"strings"
"testing"
"go.maximumdirect.net/ckconfig"
"go.maximumdirect.net/ckprompt"
commandkit "go.maximumdirect.net/commandkit"
pk "go.maximumdirect.net/promptkit"
)
@@ -80,6 +82,40 @@ func TestExplicitEmptyConfigurationPathFails(t *testing.T) {
}
}
func TestPromptConfigurationComparisonAcquiresEqualSelectionsIndependently(t *testing.T) {
dir := t.TempDir()
main := filepath.Join(dir, "config.yml")
if err := os.WriteFile(main, []byte("version: 3\n"), 0600); err != nil {
t.Fatal(err)
}
resource := filepath.Join(dir, "prompts.yml")
writeProfile := func(model string) {
t.Helper()
if err := os.WriteFile(resource, []byte("profiles: [{id: local, model: "+model+"}]\n"), 0600); err != nil {
t.Fatal(err)
}
}
writeProfile("before")
scope := ckprompt.ConfigScope(func(ctx context.Context, selection ckconfig.Selection, input struct{}, state *invocationState) (*pk.Engine, error) {
engine, err := loadPromptEngine(ctx, selection, input, state)
writeProfile("after")
return engine, err
})
side := ckconfig.ComparisonSide[struct{}]{Selection: ckconfig.Selection{
Config: commandkit.Supplied[string]{Value: main, Set: true},
}}
result, err := scope.Compare(context.Background(), ckconfig.ComparisonRequest[struct{}]{Left: side, Right: side}, &invocationState{})
if err != nil {
t.Fatal(err)
}
for _, difference := range result.Value {
if strings.Contains(difference.Left.YAML, "before") && strings.Contains(difference.Right.YAML, "after") {
return
}
}
t.Fatal("comparison did not capture the model before and after the resource changed")
}
func TestRequestInspectionAndExplicitSmokeUseSameSources(t *testing.T) {
dir := t.TempDir()
file := filepath.Join(dir, "config.yml")