Test the preparation example in Go
This commit is contained in:
@@ -123,6 +123,11 @@ Validation: format and run `go test ./examples/go-library/prepare`. Ensure
|
||||
imports and relative content still resolve from their contributing sources;
|
||||
do not rewrite configuration fixtures merely to bypass path handling.
|
||||
|
||||
Completion: the preparation workflow accepts an explicit context, example
|
||||
directory, and writer while preserving its inline checks and source contexts.
|
||||
Its Go test verifies the retained summary, including explicit null collection
|
||||
metadata, and passed on Go 1.27.0.
|
||||
|
||||
## Stage 3: Test The Observation Example And Its Output
|
||||
|
||||
Scope: `examples/go-library/observe/main.go` and its new `main_test.go`.
|
||||
|
||||
@@ -4,7 +4,9 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"go.maximumdirect.net/configkit"
|
||||
"go.maximumdirect.net/promptkit"
|
||||
@@ -28,26 +30,33 @@ type collectionSummary struct {
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := run(context.Background(), "examples/go-library/prepare", os.Stdout); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func run(ctx context.Context, exampleDir string, out io.Writer) error {
|
||||
support, err := promptkit.CollectionInput(
|
||||
"support",
|
||||
configkit.File("examples/go-library/prepare/collections/support/collection.yaml"),
|
||||
configkit.File(filepath.Join(exampleDir, "collections", "support", "collection.yaml")),
|
||||
)
|
||||
if err != nil {
|
||||
exit(err)
|
||||
return err
|
||||
}
|
||||
review, err := promptkit.CollectionInput(
|
||||
"review",
|
||||
configkit.File("examples/go-library/prepare/collections/review/collection.yaml"),
|
||||
configkit.File(filepath.Join(exampleDir, "collections", "review", "collection.yaml")),
|
||||
)
|
||||
if err != nil {
|
||||
exit(err)
|
||||
return err
|
||||
}
|
||||
override, err := promptkit.CollectionInput(
|
||||
"support",
|
||||
configkit.File("examples/go-library/prepare/collections/support/operator-overrides.yaml"),
|
||||
configkit.File(filepath.Join(exampleDir, "collections", "support", "operator-overrides.yaml")),
|
||||
)
|
||||
if err != nil {
|
||||
exit(err)
|
||||
return err
|
||||
}
|
||||
engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{
|
||||
Underlays: []configkit.Underlay{
|
||||
@@ -56,32 +65,31 @@ func main() {
|
||||
},
|
||||
}})
|
||||
if err != nil {
|
||||
exit(err)
|
||||
return err
|
||||
}
|
||||
ctx := context.Background()
|
||||
scoped, err := engine.WithNamespaces(promptkit.Namespaces{
|
||||
Prompt: "support", Profile: "support", Backend: "support",
|
||||
})
|
||||
if err != nil {
|
||||
exit(err)
|
||||
return err
|
||||
}
|
||||
view, err := engine.InspectConfiguration()
|
||||
if err != nil {
|
||||
exit(err)
|
||||
return err
|
||||
}
|
||||
if _, found := view.Explain(configkit.Keys("collections", "support", "profiles").Index(1).Key("timeout_seconds")); !found {
|
||||
exit(fmt.Errorf("collection profile override was not found"))
|
||||
return fmt.Errorf("collection profile override was not found")
|
||||
}
|
||||
requirements, err := scoped.InspectRequirements(ctx, promptkit.RequirementInspectionRequest{
|
||||
PromptID: "prepare",
|
||||
})
|
||||
if err != nil {
|
||||
exit(err)
|
||||
return err
|
||||
}
|
||||
if !requirements.Complete || len(requirements.Inputs) != 1 ||
|
||||
requirements.Inputs[0].Name != "note" ||
|
||||
requirements.Inputs[0].Kind != promptkit.RequirementRequired {
|
||||
exit(fmt.Errorf("required note input was not discovered before preparation"))
|
||||
return fmt.Errorf("required note input was not discovered before preparation")
|
||||
}
|
||||
|
||||
request := promptkit.RunRequest{
|
||||
@@ -92,39 +100,39 @@ func main() {
|
||||
},
|
||||
}
|
||||
if err := scoped.ValidateRequest(ctx, request); err != nil {
|
||||
exit(err)
|
||||
return err
|
||||
}
|
||||
prepared, err := scoped.Prepare(ctx, request)
|
||||
if err != nil {
|
||||
exit(err)
|
||||
return err
|
||||
}
|
||||
profile, err := scoped.InspectProfile(ctx, "fast")
|
||||
if err != nil {
|
||||
exit(err)
|
||||
return err
|
||||
}
|
||||
if profile.EffectiveModelParams.TimeoutSeconds != 30 {
|
||||
exit(fmt.Errorf(
|
||||
return fmt.Errorf(
|
||||
"later profile override was not applied: timeout is %d seconds",
|
||||
profile.EffectiveModelParams.TimeoutSeconds,
|
||||
))
|
||||
)
|
||||
}
|
||||
namespaces, err := scoped.ListNamespaces(ctx)
|
||||
if err != nil {
|
||||
exit(err)
|
||||
return err
|
||||
}
|
||||
collections, err := scoped.ListCollections(ctx)
|
||||
if err != nil {
|
||||
exit(err)
|
||||
return err
|
||||
}
|
||||
scopedPrompts, err := scoped.ListPrompts(ctx)
|
||||
if err != nil {
|
||||
exit(err)
|
||||
return err
|
||||
}
|
||||
reviewPrompts, err := scoped.ListPrompts(ctx, promptkit.NamespaceFilter{
|
||||
Mode: promptkit.NamespaceNamed, Name: "review",
|
||||
})
|
||||
if err != nil {
|
||||
exit(err)
|
||||
return err
|
||||
}
|
||||
scopedPromptIDs := make([]string, len(scopedPrompts))
|
||||
for index := range scopedPrompts {
|
||||
@@ -141,9 +149,9 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
encoder := json.NewEncoder(os.Stdout)
|
||||
encoder := json.NewEncoder(out)
|
||||
encoder.SetIndent("", " ")
|
||||
if err := encoder.Encode(summary{
|
||||
return encoder.Encode(summary{
|
||||
PromptID: prepared.PromptID,
|
||||
SelectedProfile: prepared.SelectedProfileID,
|
||||
Model: prepared.EffectiveModelParams.Model,
|
||||
@@ -153,12 +161,5 @@ func main() {
|
||||
Collections: collectionSummaries,
|
||||
ScopedPrompts: scopedPromptIDs,
|
||||
ReviewPrompts: reviewPromptIDs,
|
||||
}); err != nil {
|
||||
exit(err)
|
||||
}
|
||||
}
|
||||
|
||||
func exit(err error) {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
})
|
||||
}
|
||||
|
||||
45
examples/go-library/prepare/main_test.go
Normal file
45
examples/go-library/prepare/main_test.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPrepareExample(t *testing.T) {
|
||||
var output bytes.Buffer
|
||||
if err := run(t.Context(), ".", &output); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var got struct {
|
||||
PromptID string `json:"prompt_id"`
|
||||
Profile string `json:"selected_profile"`
|
||||
Model string `json:"model"`
|
||||
MessageCount int `json:"message_count"`
|
||||
Timeout int `json:"profile_timeout_seconds"`
|
||||
Namespaces []string `json:"namespaces"`
|
||||
Collections []map[string]json.RawMessage `json:"collections"`
|
||||
ScopedPrompts []string `json:"scoped_prompts"`
|
||||
ReviewPrompts []string `json:"review_prompts"`
|
||||
}
|
||||
if err := json.Unmarshal(output.Bytes(), &got); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got.PromptID != "support/prepare" || got.Profile != "support/fast" || got.Model != "offline-model" ||
|
||||
got.MessageCount <= 0 || got.Timeout != 30 || !reflect.DeepEqual(got.Namespaces, []string{"review", "support"}) ||
|
||||
!reflect.DeepEqual(got.ScopedPrompts, []string{"support/prepare"}) || !reflect.DeepEqual(got.ReviewPrompts, []string{"review/check"}) || len(got.Collections) != 2 {
|
||||
t.Fatalf("unexpected preparation summary: %+v", got)
|
||||
}
|
||||
for index, want := range []struct{ namespace, release string }{{"review", ""}, {"support", "1.4.0"}} {
|
||||
var namespace string
|
||||
if err := json.Unmarshal(got.Collections[index]["namespace"], &namespace); err != nil || namespace != want.namespace {
|
||||
t.Fatalf("collection namespace = %q, %v", namespace, err)
|
||||
}
|
||||
value, present := got.Collections[index]["release_version"]
|
||||
var release *string
|
||||
if !present || json.Unmarshal(value, &release) != nil || (index == 0 && release != nil) || (index == 1 && (release == nil || *release != want.release)) {
|
||||
t.Fatalf("collection release = %s, present %t; want %q", value, present, want.release)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user