fix: 修复 Tool Search 缓存失效 — deferred 工具不再动态注入 tools 数组

移除 deferred 工具的 "discover then include" 逻辑,让 tools 数组在整个会话中
保持稳定(只有 core tools + ToolSearch + ExecuteExtraTool),避免每次发现新
工具时 tools JSON 变化导致 prompt cache 失效。

同时强化工具优先级引导:core tools 优先直接调用,ToolSearch/ExecuteExtraTool
仅作为发现和调用 deferred 工具的最后手段。当模型搜索已加载的 core tool 时,
ToolSearch 返回明确的拒绝提示。

Co-Authored-By: glm-5.1[1m] <zai-org@claude-code-best.win>
This commit is contained in:
claude-code-best
2026-05-09 14:56:22 +08:00
parent 8c157f0767
commit c14b7eadd2
7 changed files with 46 additions and 31 deletions

View File

@@ -1,14 +1,15 @@
import { EXECUTE_TOOL_NAME } from './constants.js'
export const DESCRIPTION =
'ExecuteExtraTool — execute a deferred tool by name with parameters. This tool is always available. Use it after discovering a tool via ToolSearch.'
'ExecuteExtraTool — a first-class core tool that is always loaded and available. Execute any deferred tool by name with parameters. Use it after discovering a tool via ToolSearch. This is NOT a remote or external tool — it runs locally with full permissions.'
export function getPrompt(): string {
return `ExecuteExtraTool — execute a deferred tool by name. This tool is always available in your tool list. You do NOT need to search for it.
return `ExecuteExtraTool — a first-class core tool, always loaded, always available in your tool list. Runs locally with full permissions — NOT a remote or external tool. You do NOT need to search for it.
This tool accepts a tool_name and params object, looks up the target tool in the global tool registry, and delegates execution to it.
This tool accepts a tool_name and params object, looks up the target tool in the global tool registry, and delegates execution to it. The target tool runs with the same permissions and capabilities as if it were called directly.
Use this tool after discovering a deferred tool via ToolSearch. The tool_name must match the exact name returned by ToolSearch (e.g., "CronCreate", "mcp__server__action").
When to use: After ToolSearch discovers a deferred tool name, call this tool with {"tool_name": "<name>", "params": {...}} to invoke it immediately.
When NOT to use: For core tools already in your tool list (Read, Edit, Write, Bash, Glob, Grep, Agent, WebFetch, WebSearch, Skill, etc.) — call those directly.
Inputs:
- tool_name: The exact name of the target tool (string)

View File

@@ -554,6 +554,15 @@ export const ToolSearchTool = buildTool({
n => !alreadyLoadedNames.includes(n),
)
// If ALL results are already-loaded core tools, there's nothing to discover
if (deferredNames.length === 0 && alreadyLoadedNames.length > 0) {
return {
type: 'tool_result',
tool_use_id: toolUseID,
content: `No deferred tools found. ${alreadyLoadedNames.join(', ')} ${alreadyLoadedNames.length === 1 ? 'is' : 'are'} already loaded as core tool(s) — call directly, do NOT search for or wrap in ExecuteExtraTool. ToolSearch is only for discovering tools NOT already in your tool list.`,
}
}
const parts: string[] = []
// Core tools: clear "call directly" message, NO ExecuteExtraTool hint

View File

@@ -6,7 +6,7 @@ export { TOOL_SEARCH_TOOL_NAME } from './constants.js'
import { TOOL_SEARCH_TOOL_NAME } from './constants.js'
const PROMPT_HEAD = `Search for deferred tools by name or keyword.
const PROMPT_HEAD = `Search for deferred tools by name or keyword. LOW PRIORITY — only use this tool when no core tool can accomplish the task. Core tools (Read, Edit, Write, Bash, Glob, Grep, Agent, WebFetch, WebSearch, Skill) are always available and should be used directly. This tool is only for discovering additional capabilities like MCP tools, cron scheduling, worktree management, etc.
`