feat(discord): writes on write-marked roots, web fetch and search, held prompts (#1509)
Row 23. write_file and edit_file for roots marked write: true under the same fence as reads; web_fetch (https only, public addresses, pinned connection, capped body) and web_search through SearXNG; extension renamed to tools.mjs. Engine holds a prompt while pi is busy and sends it as its own run, so a second message mid-turn no longer folds into the first (live defect). fake-pi models the real follow-up folding. Suite 52/52, node tests 129. rev-code-02 APPROVED round 3, comment 26362, tree dbd2ce9a. Records: QUEUE rows 23-24, CURRENT, BUILD-LOG phase, SESSIONS, row 24 brief (git verbs, D5-D7 ruled). Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
@@ -204,7 +204,7 @@ test("binding: tools is optional, validated strictly, a fixed key for reload, an
|
||||
const docs = join(root, "docs");
|
||||
mkdirSync(docs);
|
||||
const ok = validateBinding(rawBinding({ tools: { roots: [{ name: "docs", path: docs }] } }));
|
||||
assert.deepEqual(ok.tools, { roots: [{ name: "docs", path: docs }], maxFileBytes: 262144, maxCallsPerTurn: 8 });
|
||||
assert.deepEqual(ok.tools, { roots: [{ name: "docs", path: docs, write: false }], maxFileBytes: 262144, maxCallsPerTurn: 8, web: null });
|
||||
assert.ok(FIXED_KEYS.includes("tools"));
|
||||
const bad = [
|
||||
[{ tools: [] }, /must be an object/],
|
||||
@@ -217,6 +217,7 @@ test("binding: tools is optional, validated strictly, a fixed key for reload, an
|
||||
[{ tools: { roots: [{ name: "docs", path: docs }], maxCallsPerTurn: 65 } }, /maxCallsPerTurn/],
|
||||
[{ tools: { roots: [{ name: "docs", path: docs }], extra: true } }, /unknown key/],
|
||||
[{ tools: { roots: [{ name: "docs", path: docs, mode: "rw" }] } }, /unknown key/],
|
||||
[{ tools: { roots: [{ name: "docs", path: docs, write: "yes" }] } }, /write must be true or false/],
|
||||
];
|
||||
for (const [o, re] of bad) assert.throws(() => validateBinding(rawBinding(o)), re, JSON.stringify(o));
|
||||
assert.throws(() => reloadDiff(ok, validateBinding(rawBinding())), (e) => e instanceof DiscordError && e.exitCode === 2 && /tools cannot change/.test(e.message));
|
||||
@@ -225,7 +226,9 @@ test("binding: tools is optional, validated strictly, a fixed key for reload, an
|
||||
mkdirSync(join(dataRoot, "discord"), { recursive: true });
|
||||
assert.equal(resolveToolRoots(validateBinding(rawBinding()), { dataRoot }), null);
|
||||
const resolved = resolveToolRoots(ok, { dataRoot });
|
||||
assert.deepEqual(resolved, { roots: [{ name: "docs", path: docs }], maxFileBytes: 262144, maxCallsPerTurn: 8 });
|
||||
assert.deepEqual(resolved, { roots: [{ name: "docs", path: docs, write: false }], maxFileBytes: 262144, maxCallsPerTurn: 8 });
|
||||
const rw = validateBinding(rawBinding({ tools: { roots: [{ name: "docs", path: docs, write: true }] } }));
|
||||
assert.deepEqual(resolveToolRoots(rw, { dataRoot }).roots, [{ name: "docs", path: docs, write: true }], "write: true reaches the extension's config");
|
||||
const inData = validateBinding(rawBinding({ tools: { roots: [{ name: "d", path: join(dataRoot, "discord") }] } }));
|
||||
assert.throws(() => resolveToolRoots(inData, { dataRoot }), /overlaps the data root/);
|
||||
const above = validateBinding(rawBinding({ tools: { roots: [{ name: "r", path: root }] } }));
|
||||
|
||||
Reference in New Issue
Block a user