diff --git a/internal/cli/run_test.go b/internal/cli/run_test.go index 2a031ab..e35c59d 100644 --- a/internal/cli/run_test.go +++ b/internal/cli/run_test.go @@ -11,6 +11,7 @@ import ( "sort" "strings" "testing" + "time" "gitea.maximumdirect.net/eric/notarius/internal/core/artifacts" "gitea.maximumdirect.net/eric/notarius/internal/core/config" @@ -25,6 +26,7 @@ import ( "gitea.maximumdirect.net/eric/notarius/internal/modules/merge/appendorder" "gitea.maximumdirect.net/eric/notarius/internal/modules/normalize/noop" jsonoutput "gitea.maximumdirect.net/eric/notarius/internal/modules/output/json" + "gitea.maximumdirect.net/eric/scriptorium" ) func TestRunNoArgsWritesUsageToStdout(t *testing.T) { @@ -179,6 +181,86 @@ func TestProductionCatalogIncludesDefaultModules(t *testing.T) { } } +func TestProductionPromptAssetsRegisterAndPrepareDndPrompts(t *testing.T) { + registry, err := productionPromptAssets() + if err != nil { + t.Fatalf("productionPromptAssets() error = %v, want nil", err) + } + promptFS, err := registry.PromptFS() + if err != nil { + t.Fatalf("PromptFS() error = %v, want nil", err) + } + for _, name := range []string{ + "common-dnd-system.md", + "common-dnd-transcript.md", + "common-dnd-references.md", + "dnd.scenes/dnd.scenes.yaml", + "dnd.scenes/task.md", + "dnd.scenes/instructions.md", + "dnd.spells/dnd.spells.yaml", + "dnd.spells/task.md", + "dnd.spells/instructions.md", + } { + if _, err := promptFS.Open(name); err != nil { + t.Fatalf("PromptFS().Open(%q) error = %v, want nil", name, err) + } + } + + options, err := registry.ScriptoriumOptions() + if err != nil { + t.Fatalf("ScriptoriumOptions() error = %v, want nil", err) + } + options = append(options, scriptorium.WithProfiles(scriptorium.OpenAICompatibleProfile(scriptorium.OpenAICompatibleProfileConfig{ + ID: "production-test-profile", + Endpoint: "http://127.0.0.1:1/v1", + Model: "production-test-model", + }))) + engine, err := scriptorium.NewEngine(scriptorium.Config{Timeout: time.Second}, options...) + if err != nil { + t.Fatalf("NewEngine() error = %v, want nil", err) + } + + scenesPrepared, err := engine.Prepare(context.Background(), scriptorium.RunRequest{ + PromptID: scenes.PromptID, + PromptVersion: scenes.ResponseSchemaVersion, + ProfileID: "production-test-profile", + Inputs: map[string]scriptorium.ArtifactRef{ + "transcript": scriptorium.InlineWithURI("file:///session.json", `{"id":"session-1","segments":[{"id":"u1","text":"We enter the crypt."}]}`), + "roster": scriptorium.Inline("Aria: cleric"), + "glossary": scriptorium.Inline("Brightmantle: temple"), + }, + }) + if err != nil { + t.Fatalf("scene Prepare() error = %v, want nil", err) + } + if got := len(scenesPrepared.Messages); got != 5 { + t.Fatalf("scene message count = %d, want 5", got) + } + if !strings.Contains(scenesPrepared.Messages[3].Content, "Divide the provided transcript") { + t.Fatalf("scene task message missing module text: %q", scenesPrepared.Messages[3].Content) + } + + spellsPrepared, err := engine.Prepare(context.Background(), scriptorium.RunRequest{ + PromptID: spells.PromptID, + PromptVersion: spells.SchemaVersion, + ProfileID: "production-test-profile", + Inputs: map[string]scriptorium.ArtifactRef{ + "transcript": scriptorium.InlineWithURI("file:///session.json", `{"id":"session-1","segments":[{"id":"u1","text":"Mira casts shield."}]}`), + "roster": scriptorium.Inline("Mira: wizard"), + "glossary": scriptorium.Inline("Shield: abjuration"), + }, + }) + if err != nil { + t.Fatalf("spell Prepare() error = %v, want nil", err) + } + if got := len(spellsPrepared.Messages); got != 5 { + t.Fatalf("spell message count = %d, want 5", got) + } + if !strings.Contains(spellsPrepared.Messages[3].Content, "Extract Dungeons & Dragons spell-cast artifacts") { + t.Fatalf("spell task message missing module text: %q", spellsPrepared.Messages[3].Content) + } +} + func TestRunConfigValidateUsesProductionCatalogByDefault(t *testing.T) { configPath := writeTestConfig(t, mvpConfigYAML("dnd-session", "dnd/spells")) var stdout bytes.Buffer