From 4fc95bd5a7eb165d78342c407dd36cc90d264706 Mon Sep 17 00:00:00 2001 From: claude-code-best Date: Sat, 9 May 2026 09:45:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20Remote=20Control=20=E6=9D=A1=E4=BB=B6?= =?UTF-8?q?=E5=B7=A5=E5=85=B7=E6=B3=A8=E5=85=A5=20=E2=80=94=20PushNotifica?= =?UTF-8?q?tion/SendUserFile/Brief=20=E4=BB=85=20bridge=20=E5=90=AF?= =?UTF-8?q?=E7=94=A8=E6=97=B6=E5=8F=AF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PushNotificationTool、SendUserFileTool 添加 isEnabled() 使用 isBridgeEnabled() - BriefTool 的 isEnabled() 从 isBriefEnabled() 改为 isBridgeEnabled() - ExecuteTool 添加 isEnabled() 兜底检查,不可用时返回友好错误 - useReplBridge bridge 首次连接时插入 system 消息通知模型新工具可用 - 移除 toolSearch 中 firstParty base URL 白名单检测,默认启用 tool search Co-Authored-By: glm-5.1[1m] --- .../src/tools/BriefTool/BriefTool.ts | 3 +- .../src/tools/ExecuteTool/ExecuteTool.ts | 15 ++++++++ .../PushNotificationTool.ts | 4 ++ .../SendUserFileTool/SendUserFileTool.ts | 4 ++ src/hooks/useReplBridge.tsx | 11 ++++++ src/utils/toolSearch.ts | 38 ++----------------- 6 files changed, 40 insertions(+), 35 deletions(-) diff --git a/packages/builtin-tools/src/tools/BriefTool/BriefTool.ts b/packages/builtin-tools/src/tools/BriefTool/BriefTool.ts index b7c801b48..52ed23212 100644 --- a/packages/builtin-tools/src/tools/BriefTool/BriefTool.ts +++ b/packages/builtin-tools/src/tools/BriefTool/BriefTool.ts @@ -8,6 +8,7 @@ import { buildTool, type ToolDef } from 'src/Tool.js' import { isEnvTruthy } from 'src/utils/envUtils.js' import { lazySchema } from 'src/utils/lazySchema.js' import { plural } from 'src/utils/stringUtils.js' +import { isBridgeEnabled } from 'src/bridge/bridgeEnabled.js' import { resolveAttachments, validateAttachmentPaths } from './attachments.js' import { BRIEF_TOOL_NAME, @@ -149,7 +150,7 @@ export const BriefTool = buildTool({ return outputSchema() }, isEnabled() { - return isBriefEnabled() + return isBridgeEnabled() }, isConcurrencySafe() { return true diff --git a/packages/builtin-tools/src/tools/ExecuteTool/ExecuteTool.ts b/packages/builtin-tools/src/tools/ExecuteTool/ExecuteTool.ts index 7e9514acb..1c6febc89 100644 --- a/packages/builtin-tools/src/tools/ExecuteTool/ExecuteTool.ts +++ b/packages/builtin-tools/src/tools/ExecuteTool/ExecuteTool.ts @@ -74,6 +74,21 @@ export const ExecuteTool = buildTool({ } } + // Check if the target tool is currently enabled + if (!targetTool.isEnabled()) { + return { + data: { + result: null, + tool_name: input.tool_name, + }, + newMessages: [ + createUserMessage({ + content: `工具 "${input.tool_name}" 当前不可用:Remote Control 未连接。`, + }), + ], + } + } + // Check permissions on the target tool const permResult = await targetTool.checkPermissions?.( input.params as Record, diff --git a/packages/builtin-tools/src/tools/PushNotificationTool/PushNotificationTool.ts b/packages/builtin-tools/src/tools/PushNotificationTool/PushNotificationTool.ts index d2db8b9e4..c13f2fd59 100644 --- a/packages/builtin-tools/src/tools/PushNotificationTool/PushNotificationTool.ts +++ b/packages/builtin-tools/src/tools/PushNotificationTool/PushNotificationTool.ts @@ -4,6 +4,7 @@ import type { ToolResultBlockParam } from 'src/Tool.js' import { buildTool } from 'src/Tool.js' import { lazySchema } from 'src/utils/lazySchema.js' import { logForDebugging } from 'src/utils/debug.js' +import { isBridgeEnabled } from 'src/bridge/bridgeEnabled.js' const PUSH_NOTIFICATION_TOOL_NAME = 'PushNotification' @@ -48,6 +49,9 @@ Use this when: Requires Remote Control to be configured. Respects user notification settings (taskCompleteNotifEnabled, inputNeededNotifEnabled, agentPushNotifEnabled).` }, + isEnabled() { + return isBridgeEnabled() + }, isConcurrencySafe() { return true }, diff --git a/packages/builtin-tools/src/tools/SendUserFileTool/SendUserFileTool.ts b/packages/builtin-tools/src/tools/SendUserFileTool/SendUserFileTool.ts index 542115d0f..b1aab78cc 100644 --- a/packages/builtin-tools/src/tools/SendUserFileTool/SendUserFileTool.ts +++ b/packages/builtin-tools/src/tools/SendUserFileTool/SendUserFileTool.ts @@ -3,6 +3,7 @@ import type { ToolResultBlockParam } from 'src/Tool.js' import { buildTool } from 'src/Tool.js' import { lazySchema } from 'src/utils/lazySchema.js' import { SEND_USER_FILE_TOOL_NAME } from './prompt.js' +import { isBridgeEnabled } from 'src/bridge/bridgeEnabled.js' const inputSchema = lazySchema(() => z.strictObject({ @@ -42,6 +43,9 @@ Guidelines: - Large files may take time to transfer` }, + isEnabled() { + return isBridgeEnabled() + }, isConcurrencySafe() { return true }, diff --git a/src/hooks/useReplBridge.tsx b/src/hooks/useReplBridge.tsx index d80db942f..f743f93dd 100644 --- a/src/hooks/useReplBridge.tsx +++ b/src/hooks/useReplBridge.tsx @@ -302,6 +302,7 @@ export function useReplBridge( }); break; case 'connected': { + const wasSessionActive = store.getState().replBridgeSessionActive; setAppState(prev => { if (prev.replBridgeSessionActive) return prev; return { @@ -312,6 +313,16 @@ export function useReplBridge( replBridgeError: undefined, }; }); + // Notify model about newly available bridge-dependent tools + if (!wasSessionActive) { + setMessages(prev => [ + ...prev, + createSystemMessage( + 'Remote Control 已连接。现在可以使用 PushNotification、SendUserFile、Brief 工具,请使用 ToolSearch 搜索发现。', + 'info', + ), + ]); + } // Send system/init so remote clients (web/iOS/Android) get // session metadata. REPL uses query() directly — never hits // QueryEngine's SDKMessage layer — so this is the only path diff --git a/src/utils/toolSearch.ts b/src/utils/toolSearch.ts index 51f8b8ac8..5715e8a6f 100644 --- a/src/utils/toolSearch.ts +++ b/src/utils/toolSearch.ts @@ -34,10 +34,6 @@ import { getMergedBetas } from './betas.js' import { getContextWindowForModel } from './context.js' import { logForDebugging } from './debug.js' import { isEnvDefinedFalsy, isEnvTruthy } from './envUtils.js' -import { - getAPIProvider, - isFirstPartyAnthropicBaseUrl, -} from './model/providers.js' import { jsonStringify } from './slowOperations.js' import { zodToJsonSchema } from './zodToJsonSchema.js' @@ -279,36 +275,10 @@ export function isToolSearchEnabledOptimistic(): boolean { return false } - // tool_reference is a beta content type that third-party API gateways - // (ANTHROPIC_BASE_URL proxies) typically don't support. When the provider - // is 'firstParty' but the base URL points elsewhere, the proxy will reject - // tool_reference blocks with a 400. Vertex/Bedrock/Foundry are unaffected — - // they have their own endpoints and beta headers. - // https://github.com/anthropics/claude-code/issues/30912 - // - // HOWEVER: some proxies DO support tool_reference (LiteLLM passthrough, - // Cloudflare AI Gateway, corp gateways that forward beta headers). The - // blanket disable breaks defer_loading for those users — all MCP tools - // loaded into main context instead of on-demand (gh-31936 / CC-457, - // likely the real cause of CC-330 "v2.1.70 defer_loading regression"). - // This gate only applies when ENABLE_TOOL_SEARCH is unset/empty (default - // behavior). Setting any non-empty value — 'true', 'auto', 'auto:N' — - // means the user is explicitly configuring tool search and asserts their - // setup supports it. The falsy check (rather than === undefined) aligns - // with getToolSearchMode(), which also treats "" as unset. - if ( - !process.env.ENABLE_TOOL_SEARCH && - getAPIProvider() === 'firstParty' && - !isFirstPartyAnthropicBaseUrl() - ) { - if (!loggedOptimistic) { - loggedOptimistic = true - logForDebugging( - `[ToolSearch:optimistic] disabled: ANTHROPIC_BASE_URL=${process.env.ANTHROPIC_BASE_URL} is not a first-party Anthropic host. Set ENABLE_TOOL_SEARCH=true (or auto / auto:N) if your proxy forwards tool_reference blocks.`, - ) - } - return false - } + // 此项目为逆向工程版本,用户均使用第三方代理(如 open.bigmodel.cn), + // 原版的 firstParty base URL 白名单检测会导致 tool search 默认禁用。 + // 移除该检测,默认启用 tool search。 + // 用户仍可通过 ENABLE_TOOL_SEARCH=false 显式禁用。 if (!loggedOptimistic) { loggedOptimistic = true