diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index 5ead50d..be06894 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -88,6 +88,10 @@ Validation: format changed Go files and run `go test ./examples/go-library/run`. Confirm the test executes the workflow, not just the summary type. These expected values describe this fixture only. +Completion: extracted the execution workflow and JSON encoding into a helper +with explicit context, resource directory, and writer. The focused Go test +executes the workflow and checks its summary; it passed on Go 1.27.0. + ## Stage 2: Test Preparation With Explicit Resource Context Scope: `examples/go-library/prepare/main.go` and its new `main_test.go`. diff --git a/examples/go-library/run/main.go b/examples/go-library/run/main.go index eadc4a6..6595c0c 100644 --- a/examples/go-library/run/main.go +++ b/examples/go-library/run/main.go @@ -4,7 +4,9 @@ import ( "context" "encoding/json" "fmt" + "io" "os" + "path/filepath" "go.maximumdirect.net/configkit" "go.maximumdirect.net/promptkit" @@ -39,41 +41,41 @@ type summary struct { } func main() { + if err := run(context.Background(), "examples/go-library/run", os.Stdout); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} + +func run(ctx context.Context, exampleDir string, out io.Writer) error { endpoint, model := "https://example.invalid/v1", "offline-model" engine, err := promptkit.NewEngine(promptkit.Config{Sources: promptkit.ConfigurationSources{ Underlays: []configkit.Underlay{{Inputs: []configkit.Input{{Source: promptkit.ProfileSource("example profile", []promptkit.ProfileConfig{ {ID: "offline-example", Endpoint: &endpoint, Model: &model}, })}}}}, - Main: &configkit.Input{Source: configkit.File("examples/go-library/run/prompt.yaml")}, + Main: &configkit.Input{Source: configkit.File(filepath.Join(exampleDir, "prompt.yaml"))}, }}, promptkit.WithLLMClient(deterministicClient{})) if err != nil { - exit(err) + return err } - result, err := engine.Run(context.Background(), promptkit.RunRequest{ + result, err := engine.Run(ctx, promptkit.RunRequest{ PromptID: "example.run", Inputs: map[string]promptkit.ArtifactRef{ "note": promptkit.Inline("Ada finished the migration review."), }, }) if err != nil { - exit(err) + return err } - encoder := json.NewEncoder(os.Stdout) + encoder := json.NewEncoder(out) encoder.SetIndent("", " ") - if err := encoder.Encode(summary{ + return encoder.Encode(summary{ Output: result.RawOutput, ValidationStatus: result.Validation.Status, IsValid: result.Validation.IsValid, Model: result.ModelName, TotalTokens: result.Usage.TotalTokens, - }); err != nil { - exit(err) - } -} - -func exit(err error) { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) + }) } diff --git a/examples/go-library/run/main_test.go b/examples/go-library/run/main_test.go new file mode 100644 index 0000000..7986490 --- /dev/null +++ b/examples/go-library/run/main_test.go @@ -0,0 +1,28 @@ +package main + +import ( + "bytes" + "encoding/json" + "testing" +) + +func TestRunExample(t *testing.T) { + var output bytes.Buffer + if err := run(t.Context(), ".", &output); err != nil { + t.Fatal(err) + } + var got struct { + Output string `json:"output"` + Valid *bool `json:"is_valid"` + Status string `json:"validation_status"` + Model string `json:"model"` + Tokens *int `json:"total_tokens"` + } + if err := json.Unmarshal(output.Bytes(), &got); err != nil { + t.Fatal(err) + } + if got.Output != "Ada finished the migration review." || got.Valid == nil || !*got.Valid || + got.Status != "passed" || got.Model != "offline-model" || got.Tokens == nil || *got.Tokens != 18 { + t.Fatalf("unexpected execution summary: %+v", got) + } +}