fix(codemode): treat tools.search as the built-in search (#49249)

This commit is contained in:
Aiden Cline
2026-09-15 19:08:51 -05:00
committed by GitHub
parent 02b12aa60e
commit fa3721fad6
2 changed files with 21 additions and 1 deletions
+7 -1
View File
@@ -409,7 +409,13 @@ export const make = <R>(
keys: (path) => namespaceKeys(root, path),
search: (args) => Effect.suspend(() => executeTool("search", searchTool, args)),
execute: (path, args) =>
Effect.suspend(() => executeTool(canonicalSegments(path).join("."), resolve(root, path), args)),
Effect.suspend(() => {
const segments = canonicalSegments(path)
// Models often write `tools.search(...)` for the bare `search(...)`; honor it unless a tool owns that path.
if (segments.length === 1 && segments[0] === "search" && lookup(root, segments) === undefined)
return executeTool("search", searchTool, args)
return executeTool(segments.join("."), resolve(root, path), args)
}),
}
}
+14
View File
@@ -337,3 +337,17 @@ describe("tool arguments cross in a useful form where JSON.stringify would give
expect(seen).toEqual({ s: [1, 2], r: {}, p: "a=1&b=2", m: {} })
})
})
describe("tools.search alias", () => {
test("tools.search(...) behaves like the bare search(...) when no tool owns that path", async () => {
const runtime = CodeMode.make({ tools: { api: { list: echo("List things", "listed") } } })
const direct = await value(runtime, `return search({ query: "list" })`)
expect(await value(runtime, `return tools.search({ query: "list" })`)).toStrictEqual(direct)
expect(await value(runtime, `return (await tools.search({ query: "list" })).items[0].path`)).toBe("tools.api.list")
})
test("a registered root-level search tool takes precedence", async () => {
const runtime = CodeMode.make({ tools: { search: echo("Custom search", "custom") } })
expect(await value(runtime, `return await tools.search({})`)).toBe("custom")
})
})