feat(sources v1): the agent locates files itself — ls/find/grep + tool-call cards
User pivot (2026-09-19): no attachments UI at all. Pasting paths is native for technical users and alien for everyone else - so the agent gets the tools to find what the learner merely NAMES. The learner communicates in messages; the agent locates and reads. Zero cross-stream seams: paths already live in tool parts, so the sources "list" is the transcript. - ls/find/grep: pi-verbatim schemas, descriptions, and output formats (fd's glob semantics, rg's path:line: match format, pi's truncation notices), ported to pure Node - no binaries, no shell-out, read-only by construction. Deltas from pi: home-anchored resolution (the harness has no cwd), .gitignore replaced by hard noise exclusions (node_modules/.git/Library/.Trash), 10s walk timeout with partial results. - read: description swapped to pi-verbatim (doctrine moved to the prompt); relative paths now resolve against the learner's home like the rest. - prompts/shared/05-learner-files.md: one minimal doctrine fragment composed into BOTH agents (composeInstructions grew a shared/ dir, before the agent's own fragments). teacher/30-jobs.md keeps only the pdf-dispatch addendum. - ToolCallCard: the generic quiet tool-call card the user specced - collapsed one-liner (tool name + headline argument), expandable to full input/output, errors red, image payloads never render. Registered for read/ls/find/grep. - ui-message.ts: TeacherUITools entries for the four tools (mechanical). - tests: fs-tools suite (glob semantics, pi formats, exclusions, limits), registry/card renders, shared-fragment composition pins, tool-registry key updates, read re-anchor.
This commit is contained in:
@@ -1089,6 +1089,21 @@ describe("prompt composition", () => {
|
||||
assert.ok(prober.includes("the `read` tool can inspect it directly"), "the prober knows it can read learner files");
|
||||
});
|
||||
|
||||
it("the sources-v1 shared fragment composes into BOTH agents (find/ls/grep doctrine)", () => {
|
||||
for (const kind of ["teacher", "prober"] as const) {
|
||||
const instructions = composeInstructions(kind);
|
||||
assert.ok(instructions.includes("## Learner files"), `${kind} carries the shared learner-files fragment`);
|
||||
assert.ok(instructions.includes("find it yourself with `find`"), `${kind} knows to locate files itself`);
|
||||
assert.ok(instructions.includes("home directory"), `${kind} knows the home-anchored path rule`);
|
||||
}
|
||||
// shared composes BEFORE the agent's own fragments (the seam's order rule)
|
||||
const teacher = composeInstructions("teacher");
|
||||
assert.ok(
|
||||
teacher.indexOf("## Learner files") < teacher.indexOf("## Learner source files"),
|
||||
"shared fragment precedes the teacher's own 30-jobs section",
|
||||
);
|
||||
});
|
||||
|
||||
it("guards prompt size — no fragment can silently balloon (the README-leak class)", () => {
|
||||
// The wave-1 leak: README.md (815 bytes / ~200 tokens) rode into every
|
||||
// teacher turn until the numeric-prefix filter stopped it. This guard
|
||||
|
||||
Reference in New Issue
Block a user