diff --git a/packages/core/src/codemode/instructions.ts b/packages/core/src/codemode/instructions.ts index da12c1c35e..389b887382 100644 --- a/packages/core/src/codemode/instructions.ts +++ b/packages/core/src/codemode/instructions.ts @@ -6,9 +6,7 @@ import { Instructions } from "../instructions/index" import { CodeModeCatalog } from "./catalog" // prettier-ignore -const prompt = (hasMoreTools: boolean) => `The Code Mode tool catalog below is ${hasMoreTools ? "partial" : "complete"}. - -Inside Code Mode, \`tools\` contains only the tools shown below${hasMoreTools ? " or returned by `search`" : ""}; surrounding top-level agent tools are not available and must not be called from the code.${hasMoreTools ? ` +const prompt = (hasMoreTools: boolean) => `The Code Mode tool catalog below is ${hasMoreTools ? "partial" : "complete"}.${hasMoreTools ? ` ## Search diff --git a/packages/core/src/tool/execute.ts b/packages/core/src/tool/execute.ts index c1b297156d..edb22fa78b 100644 --- a/packages/core/src/tool/execute.ts +++ b/packages/core/src/tool/execute.ts @@ -36,7 +36,8 @@ type CollectedFiles = { const description = [ "Run JavaScript to orchestrate tool calls and compose their results through `{ code }` in a confined Code Mode runtime.", "Imports, direct filesystem access, and timers are unavailable. Do not use `fetch`; all external access goes through `tools`.", - 'Call Code Mode tools through `tools` using only exact paths and signatures from the current catalog or `search`. Do not infer or normalize tool names; preserve bracket notation such as `tools.["tool-name"](input)`.', + "Within `{ code }`, the only callable tools are those explicitly listed in the Code Mode catalog instructions or returned by `search`. Inside `{ code }`, ignore tools shown outside the Code Mode catalog. They are not available in the Code Mode runtime.", + 'Call tools through `tools` using only exact paths and signatures from the catalog. Do not infer or normalize tool names; preserve bracket notation such as `tools.["tool-name"](input)`.', "Prefer an explicit `return`; if omitted, the final top-level expression becomes the result.", "Await every call whose completion matters; pending calls are interrupted when execution ends. Run independent calls concurrently with `Promise.all`.", ].join("\n") diff --git a/packages/core/test/codemode/catalog.test.ts b/packages/core/test/codemode/catalog.test.ts index c880c5d53f..e47224ed71 100644 --- a/packages/core/test/codemode/catalog.test.ts +++ b/packages/core/test/codemode/catalog.test.ts @@ -67,9 +67,7 @@ describe("CodeModeInstructions.render", () => { expect(instructions).toContain(` - ${lookup.signature} // Look up an order by ID`) expect(instructions).not.toContain("## Search") expect(instructions).toContain("The Code Mode tool catalog below is complete.") - expect(instructions).toContain( - "`tools` contains only the tools shown below; surrounding top-level agent tools are not available and must not be called from the code.", - ) + expect(instructions).not.toContain("surrounding top-level agent tools") }) test("adds search guidance when the catalog exceeds the budget", () => { @@ -78,9 +76,7 @@ describe("CodeModeInstructions.render", () => { expect(partial).toContain("- orders (1 tool, none shown)") expect(partial).toContain("## Search") expect(partial).toContain("The Code Mode tool catalog below is partial.") - expect(partial).toContain( - "`tools` contains only the tools shown below or returned by `search`; surrounding top-level agent tools are not available and must not be called from the code.", - ) + expect(partial).not.toContain("surrounding top-level agent tools") expect(partial).toContain("- search(input: {") expect(partial).toContain(" limit?: number,\n offset?: number,") expect(partial).not.toContain("tools.orders.lookup(input:") @@ -127,7 +123,8 @@ describe("CodeModeInstructions.update", () => { test("renders additions, changes, and removals as a compact semantic delta", () => { const changed = { ...echo, signature: "tools.notes.echo(input: {\n text: string,\n}): Promise" } const added = entry("notes.list", "List notes") - const text = update([echo, lookup], [changed, added]) + const unchanged = Array.from({ length: 5 }, (_, index) => entry(`stable.tool${index}`, `Stable ${index}`)) + const text = update([echo, lookup, ...unchanged], [changed, added, ...unchanged]) expect(text).toContain("The Code Mode tool catalog has changed.") expect(text).toContain(`New tools are available in addition to those previously listed:\n - ${added.signature}`) expect(text).toContain( diff --git a/packages/core/test/tool-execute.test.ts b/packages/core/test/tool-execute.test.ts index 00f6bef32b..1175c2ea43 100644 --- a/packages/core/test/tool-execute.test.ts +++ b/packages/core/test/tool-execute.test.ts @@ -19,7 +19,8 @@ test("execute describes invariant Code Mode behavior", () => { [ "Run JavaScript to orchestrate tool calls and compose their results through `{ code }` in a confined Code Mode runtime.", "Imports, direct filesystem access, and timers are unavailable. Do not use `fetch`; all external access goes through `tools`.", - 'Call Code Mode tools through `tools` using only exact paths and signatures from the current catalog or `search`. Do not infer or normalize tool names; preserve bracket notation such as `tools.["tool-name"](input)`.', + "Within `{ code }`, the only callable tools are those explicitly listed in the Code Mode catalog instructions or returned by `search`. Inside `{ code }`, ignore tools shown outside the Code Mode catalog. They are not available in the Code Mode runtime.", + 'Call tools through `tools` using only exact paths and signatures from the catalog. Do not infer or normalize tool names; preserve bracket notation such as `tools.["tool-name"](input)`.', "Prefer an explicit `return`; if omitted, the final top-level expression becomes the result.", "Await every call whose completion matters; pending calls are interrupted when execution ends. Run independent calls concurrently with `Promise.all`.", ].join("\n"),