package agent import ( "os" "path/filepath" "strings" "testing" "ai-agent/internal/llm" "ai-agent/internal/memory" ) func TestBuildSystemPrompt(t *testing.T) { tests := []struct { name string tools []llm.ToolDef skillContent string loadedCtx string memStore *memory.Store iceContext string contains []string notContains []string }{ { name: "no optional sections", contains: []string{"No tools currently available.", "Current date:"}, notContains: []string{"Active Skills", "Loaded Context", "Remembered Facts"}, }, { name: "with tools", tools: []llm.ToolDef{ {Name: "test_tool", Description: "does stuff"}, }, contains: []string{"test_tool", "does stuff"}, notContains: []string{"No tools currently available."}, }, { name: "with skills", skillContent: "skill content here", contains: []string{"Active Skills", "skill content here"}, }, { name: "with loaded context", loadedCtx: "some loaded context", contains: []string{"Loaded Context", "some loaded context"}, }, { name: "ICE overrides memory", iceContext: "ice assembled context", contains: []string{"ice assembled context"}, notContains: []string{"Remembered Facts"}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := buildSystemPrompt("", tt.tools, tt.skillContent, tt.loadedCtx, tt.memStore, tt.iceContext, "", "") for _, want := range tt.contains { if !strings.Contains(result, want) { t.Errorf("buildSystemPrompt() missing %q", want) } } for _, notWant := range tt.notContains { if strings.Contains(result, notWant) { t.Errorf("buildSystemPrompt() should not contain %q", notWant) } } }) } t.Run("with memory store entries", func(t *testing.T) { store := memory.NewStore(filepath.Join(t.TempDir(), "test-memories.json")) _, _ = store.Save("user prefers dark mode", []string{"preference"}) result := buildSystemPrompt("", nil, "", "", store, "", "", "") if !strings.Contains(result, "Remembered Facts") { t.Error("expected Remembered Facts section") } if !strings.Contains(result, "user prefers dark mode") { t.Error("expected memory content in prompt") } }) } func TestBuildSystemPrompt_WithWorkDir(t *testing.T) { result := buildSystemPrompt("", nil, "", "", nil, "", "/home/user/myproject", "") if !strings.Contains(result, "Working directory: /home/user/myproject") { t.Error("expected working directory in prompt") } if !strings.Contains(result, "Environment") { t.Error("expected Environment section header") } } func TestBuildSystemPrompt_EmptyWorkDir(t *testing.T) { result := buildSystemPrompt("", nil, "", "", nil, "", "", "") if strings.Contains(result, "Working directory") { t.Error("should not include working directory when empty") } } func TestBuildSystemPrompt_WithIgnoreContent(t *testing.T) { ignoreContent := "- node_modules\n- *.log\n- build/" result := buildSystemPrompt("", nil, "", "", nil, "", "", ignoreContent) if !strings.Contains(result, "Ignored Paths") { t.Error("expected Ignored Paths section header") } if !strings.Contains(result, "node_modules") { t.Error("expected node_modules in ignore section") } if !strings.Contains(result, "*.log") { t.Error("expected *.log in ignore section") } } func TestBuildSystemPrompt_EmptyIgnoreContent(t *testing.T) { result := buildSystemPrompt("", nil, "", "", nil, "", "", "") if strings.Contains(result, "Ignored Paths") { t.Error("should not include Ignored Paths when content is empty") } } func TestDetectProjectInfo_GoProject(t *testing.T) { dir := t.TempDir() _ = os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module test"), 0o644) info := detectProjectInfo(dir) if !strings.Contains(info, "go.mod") { t.Errorf("expected go.mod in project info, got %q", info) } if !strings.Contains(info, "Go module") { t.Errorf("expected 'Go module' in project info, got %q", info) } } func TestDetectProjectInfo_EmptyDir(t *testing.T) { dir := t.TempDir() info := detectProjectInfo(dir) if info != "" { t.Errorf("expected empty for dir with no markers, got %q", info) } } func TestBuildMemorySection(t *testing.T) { tests := []struct { name string setup func(s *memory.Store) contains []string wantEmpty bool }{ { name: "empty store", setup: func(s *memory.Store) {}, wantEmpty: true, }, { name: "store with tagged entry", setup: func(s *memory.Store) { _, _ = s.Save("likes Go", []string{"lang", "preference"}) }, contains: []string{"Remembered Facts", "likes Go", "[tags: lang, preference]"}, }, { name: "store with untagged entry", setup: func(s *memory.Store) { _, _ = s.Save("project uses modules", nil) }, contains: []string{"Remembered Facts", "project uses modules"}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { store := memory.NewStore(filepath.Join(t.TempDir(), "mem.json")) tt.setup(store) result := buildMemorySection(store) if tt.wantEmpty { if result != "" { t.Errorf("expected empty string, got %q", result) } return } for _, want := range tt.contains { if !strings.Contains(result, want) { t.Errorf("buildMemorySection() missing %q in:\n%s", want, result) } } }) } }