feat: dynamically resolve AGENTS.md files from subdirectories as agent explores them (#10678)

This commit is contained in:
Aiden Cline
2026-01-26 10:49:41 -05:00
committed by GitHub
parent b1fbfa7e94
commit 39a73d4894
16 changed files with 282 additions and 106 deletions

View File

@@ -0,0 +1,46 @@
import { describe, expect, test } from "bun:test"
import path from "path"
import { InstructionPrompt } from "../../src/session/instruction"
import { Instance } from "../../src/project/instance"
import { tmpdir } from "../fixture/fixture"
describe("InstructionPrompt.resolve", () => {
test("returns empty when AGENTS.md is at project root (already in systemPaths)", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
await Bun.write(path.join(dir, "AGENTS.md"), "# Root Instructions")
await Bun.write(path.join(dir, "src", "file.ts"), "const x = 1")
},
})
await Instance.provide({
directory: tmp.path,
fn: async () => {
const system = await InstructionPrompt.systemPaths()
expect(system.has(path.join(tmp.path, "AGENTS.md"))).toBe(true)
const results = await InstructionPrompt.resolve([], path.join(tmp.path, "src", "file.ts"))
expect(results).toEqual([])
},
})
})
test("returns AGENTS.md from subdirectory (not in systemPaths)", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
await Bun.write(path.join(dir, "subdir", "AGENTS.md"), "# Subdir Instructions")
await Bun.write(path.join(dir, "subdir", "nested", "file.ts"), "const x = 1")
},
})
await Instance.provide({
directory: tmp.path,
fn: async () => {
const system = await InstructionPrompt.systemPaths()
expect(system.has(path.join(tmp.path, "subdir", "AGENTS.md"))).toBe(false)
const results = await InstructionPrompt.resolve([], path.join(tmp.path, "subdir", "nested", "file.ts"))
expect(results.length).toBe(1)
expect(results[0].filepath).toBe(path.join(tmp.path, "subdir", "AGENTS.md"))
},
})
})
})

View File

@@ -11,6 +11,7 @@ const baseCtx = {
callID: "",
agent: "build",
abort: AbortSignal.any([]),
messages: [],
metadata: () => {},
}

View File

@@ -12,6 +12,7 @@ const ctx = {
callID: "",
agent: "build",
abort: AbortSignal.any([]),
messages: [],
metadata: () => {},
ask: async () => {},
}

View File

@@ -11,6 +11,7 @@ const baseCtx: Omit<Tool.Context, "ask"> = {
callID: "",
agent: "build",
abort: AbortSignal.any([]),
messages: [],
metadata: () => {},
}

View File

@@ -10,6 +10,7 @@ const ctx = {
callID: "",
agent: "build",
abort: AbortSignal.any([]),
messages: [],
metadata: () => {},
ask: async () => {},
}

View File

@@ -9,6 +9,7 @@ const ctx = {
callID: "test-call",
agent: "test-agent",
abort: AbortSignal.any([]),
messages: [],
metadata: () => {},
ask: async () => {},
}

View File

@@ -14,6 +14,7 @@ const ctx = {
callID: "",
agent: "build",
abort: AbortSignal.any([]),
messages: [],
metadata: () => {},
ask: async () => {},
}
@@ -330,3 +331,26 @@ root_type Monster;`
})
})
})
describe("tool.read loaded instructions", () => {
test("loads AGENTS.md from parent directory and includes in metadata", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
await Bun.write(path.join(dir, "subdir", "AGENTS.md"), "# Test Instructions\nDo something special.")
await Bun.write(path.join(dir, "subdir", "nested", "test.txt"), "test content")
},
})
await Instance.provide({
directory: tmp.path,
fn: async () => {
const read = await ReadTool.init()
const result = await read.execute({ filePath: path.join(tmp.path, "subdir", "nested", "test.txt") }, ctx)
expect(result.output).toContain("test content")
expect(result.output).toContain("system-reminder")
expect(result.output).toContain("Test Instructions")
expect(result.metadata.loaded).toBeDefined()
expect(result.metadata.loaded).toContain(path.join(tmp.path, "subdir", "AGENTS.md"))
},
})
})
})