1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
package main
import (
"os"
"path/filepath"
"strings"
"testing"
"mm/internal/config"
)
// inProject runs the test in a fresh directory holding an AGENTS.md of text
// ("" = no file), with the given settings.
func inProject(t *testing.T, text string, settings config.AgentsMdConfig) string {
t.Helper()
saved, savedSchema := config.Cfg.AgentsMd, config.Cfg.OutputSchema
config.Cfg.AgentsMd, config.Cfg.OutputSchema = settings, nil
t.Cleanup(func() { config.Cfg.AgentsMd, config.Cfg.OutputSchema = saved, savedSchema })
dir := t.TempDir()
t.Chdir(dir)
if text != "" {
if err := os.WriteFile("AGENTS.md", []byte(text), 0o644); err != nil {
t.Fatal(err)
}
}
abs, _ := filepath.Abs(filepath.Join(dir, "AGENTS.md"))
return abs
}
var agentsMdOn = config.AgentsMdConfig{Enabled: true, Path: "AGENTS.md"}
func TestBannerNamesTheLoadedFile(t *testing.T) {
path := inProject(t, strings.Repeat("a", 700), agentsMdOn)
col, warnings := agentsMdBanner(false, 100000)
if col != " | agents.md: "+path+" (~200 tokens)" || len(warnings) != 0 {
t.Errorf("column %q, warnings %v", col, warnings)
}
}
func TestBannerWarnsWhenTheFileFillsTheWindow(t *testing.T) {
path := inProject(t, strings.Repeat("a", 700), agentsMdOn) // ~200 tokens
_, warnings := agentsMdBanner(false, 1000) // 20 %
if len(warnings) != 1 || !strings.Contains(warnings[0], path+" is ~200 tokens, 20 % of the 1000-token context window") {
t.Errorf("warnings %v", warnings)
}
if _, warnings := agentsMdBanner(false, 1001); len(warnings) != 0 {
t.Errorf("under 20 %%: %v", warnings)
}
if _, warnings := agentsMdBanner(false, 0); len(warnings) != 0 {
t.Errorf("unknown window: %v", warnings)
}
}
func TestBannerSaysASkippedFileIsNotRead(t *testing.T) {
inProject(t, "too long rules", config.AgentsMdConfig{Enabled: true, Path: "AGENTS.md", MaxChars: 5})
col, warnings := agentsMdBanner(false, 0)
if col != " | agents.md: skipped (too long)" || len(warnings) != 1 || !strings.Contains(warnings[0], "14 characters > agentsMd.maxChars 5") {
t.Errorf("column %q, warnings %v", col, warnings)
}
}
// A structured agent: a neutral mention, no warning — and only when a file
// exists.
func TestBannerMentionsAFileAStructuredAgentIgnores(t *testing.T) {
inProject(t, "prose rules", agentsMdOn)
config.Cfg.OutputSchema = map[string]any{"type": "object"}
col, warnings := agentsMdBanner(false, 0)
if col != " | agents.md: ignored (structured output)" || len(warnings) != 0 {
t.Errorf("column %q, warnings %v", col, warnings)
}
}
func TestBannerSaysNothingWithoutAFileOrWhenOff(t *testing.T) {
inProject(t, "", agentsMdOn)
if col, warnings := agentsMdBanner(false, 0); col != "" || warnings != nil {
t.Errorf("no file: column %q, warnings %v", col, warnings)
}
inProject(t, "rules", config.AgentsMdConfig{Enabled: false, Path: "AGENTS.md"})
if col, warnings := agentsMdBanner(false, 0); col != "" || warnings != nil {
t.Errorf("disabled: column %q, warnings %v", col, warnings)
}
}
func TestBannerInACPModeSaysWhereEachSessionLooks(t *testing.T) {
inProject(t, "", agentsMdOn)
if col, _ := agentsMdBanner(true, 0); col != " | agents.md: <session cwd>/AGENTS.md" {
t.Errorf("column %q", col)
}
}
|