Files
audita/internal/framework/llm/engine_sources_test.go

164 lines
5.9 KiB
Go
Raw Normal View History

package llm
import (
"context"
"os"
"path/filepath"
"slices"
"testing"
"gitea.maximumdirect.net/eric/audita/v3/internal/core/config"
"gitea.maximumdirect.net/eric/audita/v3/internal/prompts"
ck "go.maximumdirect.net/configkit"
)
func TestEngineCapturesAutomaticPromptSources(t *testing.T) {
dir := t.TempDir()
main := filepath.Join(dir, "config.yml")
write := func(name, text string) {
t.Helper()
if err := os.MkdirAll(filepath.Dir(filepath.Join(dir, name)), 0755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(dir, name), []byte(text), 0644); err != nil {
t.Fatal(err)
}
}
write("config.yml", "version: 3\n")
write("prompts.yml", "collections:\n audita:\n prompts:\n - id: modules.grammar.proposal\n messages:\n - role: user\n content_file: message.txt\n output:\n format: text\n validation_mode: none\n")
write("message.txt", "first")
write("prompts/nested/extra.yml", "prompts:\n - id: extra\n messages:\n - role: user\n content: extra\n output:\n format: text\n validation_mode: none\n")
loaded, err := config.Load(ck.Input{Source: ck.File(main)}, "")
if err != nil {
t.Fatal(err)
}
first, err := NewRuntime(context.Background(), loaded, nil)
if err != nil {
t.Fatal(err)
}
inspect := func(r *Runtime) string {
t.Helper()
p, err := r.Engine.InspectPrompt(context.Background(), prompts.PromptIDModuleGrammarProposal)
if err != nil {
t.Fatal(err)
}
return p.Messages[0].Content
}
if got := inspect(first); got != "first" {
t.Fatalf("prompt = %q", got)
}
for _, name := range []string{"prompts.yml", "message.txt", "prompts/nested/extra.yml"} {
if !slices.Contains(first.SourcePaths, filepath.Join(dir, name)) {
t.Errorf("missing %s in %v", name, first.SourcePaths)
}
}
if _, err := first.Engine.InspectPrompt(context.Background(), prompts.PromptIDModuleGlossaryProposal); err != nil {
t.Fatal(err)
}
if _, err := first.Engine.InspectPrompt(context.Background(), "extra"); err != nil {
t.Fatal(err)
}
write("message.txt", "second")
second, err := NewRuntime(context.Background(), loaded, nil)
if err != nil {
t.Fatal(err)
}
if inspect(first) != "first" || inspect(second) != "second" {
t.Fatal("engine did not capture source at construction")
}
}
func TestEngineWithoutMainUsesEmbeddedPrompts(t *testing.T) {
loaded, err := config.Load(ck.Input{Source: ck.NoSource()}, "")
if err != nil {
t.Fatal(err)
}
runtime, err := NewRuntime(context.Background(), loaded, nil)
if err != nil {
t.Fatal(err)
}
if len(runtime.SourcePaths) != 0 {
t.Fatalf("unexpected paths: %v", runtime.SourcePaths)
}
if _, err := runtime.Engine.InspectPrompt(context.Background(), prompts.PromptIDModuleGrammarProposal); err != nil {
t.Fatal(err)
}
}
func TestEngineCapturesInheritedMessageAndRejectsPeerConflicts(t *testing.T) {
dir := t.TempDir()
write := func(name, text string) {
t.Helper()
file := filepath.Join(dir, name)
if err := os.MkdirAll(filepath.Dir(file), 0755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(file, []byte(text), 0644); err != nil {
t.Fatal(err)
}
}
write("config.yml", "version: 3\n")
write("prompts.yml", "config:\n imports:\n - path: shared/catalog.yml\n required: true\n")
write("shared/catalog.yml", "prompts:\n - id: parent\n messages:\n - role: user\n content_file: instruction.md\n output:\n format: text\n validation_mode: none\n")
write("shared/instruction.md", "inherited content")
write("prompts/child.yml", "prompts:\n - id: child\n extends: {id: parent}\n")
loaded, err := config.Load(ck.Input{Source: ck.File(filepath.Join(dir, "config.yml"))}, "")
if err != nil {
t.Fatal(err)
}
runtime, err := NewRuntime(context.Background(), loaded, nil)
if err != nil {
t.Fatal(err)
}
prompt, err := runtime.Engine.InspectPrompt(context.Background(), "child")
if err != nil || prompt.Messages[0].Content != "inherited content" {
t.Fatalf("inherited prompt: %+v, %v", prompt, err)
}
for _, name := range []string{"prompts.yml", "shared/catalog.yml", "shared/instruction.md", "prompts/child.yml"} {
if !slices.Contains(runtime.SourcePaths, filepath.Join(dir, name)) {
t.Errorf("missing %s in %v", name, runtime.SourcePaths)
}
}
write("prompts/duplicate.yml", "prompts:\n - id: parent\n messages:\n - role: user\n content: duplicate\n output:\n format: text\n validation_mode: none\n")
if _, err := NewRuntime(context.Background(), loaded, nil); err == nil || IsAssetError(err) {
t.Fatalf("peer conflict classification: %v", err)
}
}
func TestEngineUsesRecordedContextWithWiderRoot(t *testing.T) {
root := t.TempDir()
project := filepath.Join(root, "campaign")
if err := os.Mkdir(project, 0755); err != nil {
t.Fatal(err)
}
for name, body := range map[string]string{
"config.yml": "version: 3\n",
"prompts.yml": "config:\n imports:\n - path: ../shared.yml\n required: true\n",
} {
if err := os.WriteFile(filepath.Join(project, name), []byte(body), 0644); err != nil {
t.Fatal(err)
}
}
if err := os.WriteFile(filepath.Join(root, "shared.yml"), []byte("prompts:\n - id: shared\n messages:\n - role: user\n content: shared\n output:\n format: text\n validation_mode: none\n"), 0644); err != nil {
t.Fatal(err)
}
source := ck.SearchConfig("audita", ck.SearchDirectory(project))
loaded, err := config.Load(ck.Input{Source: source, Filesystem: &ck.FilesystemContext{Root: root}}, "")
if err != nil {
t.Fatal(err)
}
t.Chdir(t.TempDir())
runtime, err := NewRuntime(context.Background(), loaded, nil)
if err != nil {
t.Fatal(err)
}
if _, err := runtime.Engine.InspectPrompt(context.Background(), "shared"); err != nil {
t.Fatal(err)
}
for _, file := range []string{filepath.Join(project, "prompts.yml"), filepath.Join(root, "shared.yml")} {
if !slices.Contains(runtime.SourcePaths, file) {
t.Errorf("missing %s in %v", file, runtime.SourcePaths)
}
}
}