diff --git a/pkg/agent/loop.go b/pkg/agent/loop.go index 0d98e22..1c0916a 100644 --- a/pkg/agent/loop.go +++ b/pkg/agent/loop.go @@ -42,6 +42,7 @@ type Config struct { OnIteration OnIterationHook ToolTimeout time.Duration ChatTemplateKwargs map[string]any // passed to the LLM provider (e.g. Qwen enable_thinking) + AgentsMD string // discovered AGENTS.md content, folded into the system prompt } // Iteration represents a single cycle of the agent loop. @@ -230,7 +231,7 @@ func (l *Loop) RunStream(ctx context.Context, input string, history ...llm.Messa } func (l *Loop) buildInitialMessages(input string, history []llm.Message) []llm.Message { - systemPrompt := persona.AssembleSystemPrompt(l.cfg.Persona, "") + systemPrompt := persona.AssembleSystemPrompt(l.cfg.Persona, l.cfg.AgentsMD) messages := make([]llm.Message, 0, len(history)+2) messages = append(messages, llm.Message{Role: llm.RoleSystem, Content: systemPrompt}) messages = append(messages, history...) diff --git a/pkg/agent/loop_test.go b/pkg/agent/loop_test.go index e81f128..4c59bcf 100644 --- a/pkg/agent/loop_test.go +++ b/pkg/agent/loop_test.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "iter" + "strings" "testing" "time" @@ -116,6 +117,30 @@ func TestRun_NoToolCalls(t *testing.T) { } } +func TestRun_IncludesAgentsMD(t *testing.T) { + var capturedSystemPrompt string + mockClient := &mockLLM{ + generateFunc: func(ctx context.Context, req llm.CompletionRequest) (llm.CompletionResponse, error) { + capturedSystemPrompt = req.Messages[0].Content + return llm.CompletionResponse{Content: "done"}, nil + }, + } + + loop := New(Config{ + LLM: mockClient, + Persona: persona.DefaultPersona(), + Tools: tools.NewRegistry(), + AgentsMD: "Never edit go.mod directly.", + }) + + if _, err := loop.Run(context.Background(), "Hello"); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if !strings.Contains(capturedSystemPrompt, "Never edit go.mod directly.") { + t.Errorf("expected system prompt to include AGENTS.md content, got %q", capturedSystemPrompt) + } +} + func TestRun_ToolCalls(t *testing.T) { registry := tools.NewRegistry() registry.Register(tools.Tool{ diff --git a/pkg/persona/persona.go b/pkg/persona/persona.go index 0d83982..c092b23 100644 --- a/pkg/persona/persona.go +++ b/pkg/persona/persona.go @@ -79,8 +79,8 @@ func AssembleSystemPrompt(p Persona, agentsMD string) string { return strings.Join(parts, "\n\n") } -// discoverAgentsMD walks up the directory tree looking for AGENTS.md files. -func discoverAgentsMD(root string) string { +// DiscoverAgentsMD walks up the directory tree looking for AGENTS.md files. +func DiscoverAgentsMD(root string) string { var parts []string current := root diff --git a/pkg/persona/persona_test.go b/pkg/persona/persona_test.go index 86a3ffc..ed60fea 100644 --- a/pkg/persona/persona_test.go +++ b/pkg/persona/persona_test.go @@ -45,9 +45,9 @@ func TestDiscoverAgentsMD(t *testing.T) { agentsPath := filepath.Join(tmpDir, "AGENTS.md") os.WriteFile(agentsPath, []byte("test instructions"), 0644) - result := discoverAgentsMD(tmpDir) + result := DiscoverAgentsMD(tmpDir) if !contains(result, "test instructions") { - t.Error("expected discoverAgentsMD to find AGENTS.md") + t.Error("expected DiscoverAgentsMD to find AGENTS.md") } }