feat(coding-agent): added opt-in task prewalk and tightened --tools and xdev behavior
- Added a `task.prewalk` option (default `false`), removed default task `prewalk` flags, and updated prewalk resolution so bunded generic task execution only prewalks when explicitly enabled. - Enforced strict `--tools` validation in CLI parsing, making unknown tool names fail fast with `CliUsageError` instead of being silently filtered. - Migrated legacy discovery settings (`tools.discoveryMode`, `tools.essentialOverride`, MCP discovery keys) into updated `tools.xdev` handling with preserved explicit override behavior. - Hardened xdev/ACP execution flow by capping `docsAll` payloads with overflow listing and remapping `xd://` dispatches/approval gating for correct execute/read behavior and reduced duplicate prompts.
This commit is contained in:
@@ -7,6 +7,7 @@ import * as themeModule from "@oh-my-pi/pi-coding-agent/modes/theme/theme";
|
||||
import { ToolChoiceQueue } from "@oh-my-pi/pi-coding-agent/session/tool-choice-queue";
|
||||
import { createTools, type ToolSession } from "@oh-my-pi/pi-coding-agent/tools";
|
||||
import { writeToolRenderer } from "@oh-my-pi/pi-coding-agent/tools/write";
|
||||
import { XdevRegistry } from "@oh-my-pi/pi-coding-agent/tools/xdev";
|
||||
import { removeWithRetries } from "@oh-my-pi/pi-utils";
|
||||
|
||||
// xdev mounting is default-on: discoverable tools like ast_edit unmount into
|
||||
@@ -105,4 +106,30 @@ describe("read and write route xd:// device URLs", () => {
|
||||
const rendered = writeToolRenderer.renderCall({ path: "xd://ast_edit", content }, options, uiTheme);
|
||||
expect(rendered).toBeDefined();
|
||||
});
|
||||
|
||||
it("docsAll inlines small device docs and falls back to a listing past the caps", async () => {
|
||||
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "write-xdev-docs-"));
|
||||
try {
|
||||
const session = xdevSession(tempDir);
|
||||
await createTools(session);
|
||||
const mounted = session.xdevRegistry?.list() ?? [];
|
||||
expect(mounted.length).toBeGreaterThan(0);
|
||||
|
||||
// One device with a pathological description must fall back to the
|
||||
// listing without starving the rest of the catalog.
|
||||
const giant = Object.create(mounted[0]!) as (typeof mounted)[number];
|
||||
Object.defineProperty(giant, "name", { value: "giant_mcp_tool" });
|
||||
Object.defineProperty(giant, "description", { value: "x".repeat(XdevRegistry.DOCS_PER_DEVICE_CAP + 1) });
|
||||
const registry = new XdevRegistry([...mounted, giant]);
|
||||
|
||||
const docs = registry.docsAll();
|
||||
expect(docs.length).toBeLessThan(XdevRegistry.DOCS_TOTAL_BUDGET + XdevRegistry.DOCS_PER_DEVICE_CAP);
|
||||
expect(docs).toContain(`## ${mounted[0]!.name}`);
|
||||
expect(docs).toContain("## Additional devices (docs on demand)");
|
||||
expect(docs).toContain("- xd://giant_mcp_tool —");
|
||||
expect(docs).not.toContain("## giant_mcp_tool");
|
||||
} finally {
|
||||
await removeWithRetries(tempDir);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user