From e99d565e21801d120face055dc2f9666e6631566 Mon Sep 17 00:00:00 2001 From: roboomp Date: Sat, 18 Jul 2026 09:17:20 +0000 Subject: [PATCH] fix(tools): keep web_search top-level under xdev web_search is a discoverable built-in, so with tools.xdev defaulting to true createTools mounted it under xd:// and dropped it from the top-level toolset. Models that call web_search directly got "Tool web_search not found" on default configs. Pin it in XDEV_KEEP_TOP_LEVEL so it stays a direct-callable tool while other discoverable tools keep mounting. Fixes #5973 --- packages/coding-agent/CHANGELOG.md | 4 ++++ packages/coding-agent/src/tools/xdev.ts | 15 +++++++++++---- .../test/write-xdev-dispatch.test.ts | 19 +++++++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 4522715df..586e84233 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Fixed + +- Fixed `web_search` being unreachable under default config: with `tools.xdev: true`, the discoverable `web_search` tool was mounted under `xd://` and dropped from the top-level toolset, so models calling it directly got "Tool web_search not found". It is now pinned top-level via `XDEV_KEEP_TOP_LEVEL` while other discoverable tools keep mounting under `xd://` ([#5973](https://github.com/can1357/oh-my-pi/issues/5973)). + ## [17.0.4] - 2026-07-18 ### Fixed diff --git a/packages/coding-agent/src/tools/xdev.ts b/packages/coding-agent/src/tools/xdev.ts index 73d2b6d63..48ca0cd17 100644 --- a/packages/coding-agent/src/tools/xdev.ts +++ b/packages/coding-agent/src/tools/xdev.ts @@ -38,11 +38,18 @@ import { ToolError } from "./tool-errors"; /** * Discoverable built-ins that must stay top-level even when xdev mounting is * active: `todo` feeds the todo prelude/prewalk machinery, `ask` is the - * model's user-interaction affordance, and `grep` is the redirect target of - * the bash interceptor rules — each loses its harness integration if hidden - * behind dispatch. + * model's user-interaction affordance, `grep` is the redirect target of the + * bash interceptor rules, and `web_search` is invoked directly by most models + * (which have no notion of the `xd://` protocol) so hiding it behind dispatch + * makes it unreachable in practice (issue #5973) — each loses its harness + * integration or usability if hidden behind dispatch. */ -export const XDEV_KEEP_TOP_LEVEL: Record = { todo: true, ask: true, grep: true }; +export const XDEV_KEEP_TOP_LEVEL: Record = { + todo: true, + ask: true, + grep: true, + web_search: true, +}; /** * Tools that carry the `xd://` transport itself and therefore can never be diff --git a/packages/coding-agent/test/write-xdev-dispatch.test.ts b/packages/coding-agent/test/write-xdev-dispatch.test.ts index bd168e33f..d8bf7190c 100644 --- a/packages/coding-agent/test/write-xdev-dispatch.test.ts +++ b/packages/coding-agent/test/write-xdev-dispatch.test.ts @@ -206,3 +206,22 @@ describe("read and write route xd:// device URLs", () => { } }); }); + +describe("web_search stays top-level under xdev", () => { + it("keeps web_search a direct tool and off the xd:// registry with default config", async () => { + const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "write-xdev-websearch-")); + try { + const session = xdevSession(tempDir); + // Default config: tools.xdev is on. + expect(session.settings.get("tools.xdev")).toBe(true); + const tools = await createTools(session); + // Regression for #5973: models call web_search directly, so it must + // remain a top-level function and never mount behind the xd:// device. + expect(tools.some(entry => entry.name === "web_search")).toBe(true); + const mounted = session.xdevRegistry ? [...session.xdevRegistry.list()].map(t => t.name) : []; + expect(mounted).not.toContain("web_search"); + } finally { + await removeWithRetries(tempDir); + } + }); +});