

















@@ -194,6 +194,10 @@ import {
194194} from "../../tool-allowlist-guard.js";
195195import { UNKNOWN_TOOL_THRESHOLD } from "../../tool-loop-detection.js";
196196import { normalizeToolName } from "../../tool-policy.js";
197+import {
198+filterRuntimeCompatibleTools,
199+type RuntimeToolSchemaDiagnostic,
200+} from "../../tool-schema-projection.js";
197201import {
198202addClientToolsToToolSearchCatalog,
199203applyToolSearchCatalog,
@@ -480,6 +484,40 @@ function collectTrustedLocalMediaToolNames(params: {
480484]);
481485}
482486487+function logRuntimeToolSchemaQuarantine(params: {
488+diagnostics: readonly RuntimeToolSchemaDiagnostic[];
489+tools: readonly Parameters<typeof getPluginToolMeta>[0][];
490+runId: string;
491+sessionKey?: string;
492+sessionId?: string;
493+}): void {
494+if (params.diagnostics.length === 0) {
495+return;
496+}
497+const summary = params.diagnostics
498+.map((diagnostic) => {
499+const tool = params.tools[diagnostic.toolIndex];
500+const pluginId = tool ? getPluginToolMeta(tool)?.pluginId : undefined;
501+const owner = pluginId ? ` plugin=${pluginId}` : "";
502+emitTrustedDiagnosticEvent({
503+type: "tool.execution.blocked",
504+runId: params.runId,
505+ ...(params.sessionKey ? { sessionKey: params.sessionKey } : {}),
506+ ...(params.sessionId ? { sessionId: params.sessionId } : {}),
507+toolName: diagnostic.toolName,
508+toolSource: pluginId ? "plugin" : "core",
509+ ...(pluginId ? { toolOwner: pluginId } : {}),
510+deniedReason: "unsupported_tool_schema",
511+reason: diagnostic.violations.join(", "),
512+});
513+return `${diagnostic.toolName}${owner}: ${diagnostic.violations.join(", ")}`;
514+})
515+.join("; ");
516+log.warn(
517+`[tools] quarantined ${params.diagnostics.length} unsupported tool schema${params.diagnostics.length === 1 ? "" : "s"} before model runtime projection: ${summary}. Run openclaw doctor for details.`,
518+);
519+}
520+483521const MAX_BTW_SNAPSHOT_MESSAGES = 100;
484522const TOOL_SEARCH_CONTROL_ALLOWLIST_NAMES = [
485523TOOL_SEARCH_CODE_MODE_TOOL_NAME,
@@ -1917,11 +1955,22 @@ export async function runEmbeddedAttempt(
19171955model: params.model,
19181956})
19191957 : filteredBundledTools;
1920-const uncompactedEffectiveTools = filterLocalModelLeanTools({
1958+const projectedUncompactedEffectiveTools = filterLocalModelLeanTools({
19211959tools: [...tools, ...normalizedBundledTools],
19221960config: params.config,
19231961agentId: sessionAgentId,
19241962});
1963+const uncompactedToolSchemaProjection = filterRuntimeCompatibleTools(
1964+projectedUncompactedEffectiveTools,
1965+);
1966+logRuntimeToolSchemaQuarantine({
1967+diagnostics: uncompactedToolSchemaProjection.diagnostics,
1968+tools: projectedUncompactedEffectiveTools,
1969+runId: params.runId,
1970+sessionKey: params.sessionKey,
1971+sessionId: params.sessionId,
1972+});
1973+const uncompactedEffectiveTools = [...uncompactedToolSchemaProjection.tools];
19251974let effectiveTools = uncompactedEffectiveTools;
19261975const catalogToolHookContext = {
19271976agentId: sessionAgentId,
@@ -1978,11 +2027,20 @@ export async function runEmbeddedAttempt(
19782027toolHookContext: catalogToolHookContext,
19792028});
19802029toolSearchCatalogApplied = true;
1981-effectiveTools = filterLocalModelLeanTools({
2030+const projectedToolSearchTools = filterLocalModelLeanTools({
19822031tools: toolSearch.tools,
19832032config: params.config,
19842033agentId: sessionAgentId,
19852034});
2035+const toolSearchSchemaProjection = filterRuntimeCompatibleTools(projectedToolSearchTools);
2036+logRuntimeToolSchemaQuarantine({
2037+diagnostics: toolSearchSchemaProjection.diagnostics,
2038+tools: projectedToolSearchTools,
2039+runId: params.runId,
2040+sessionKey: params.sessionKey,
2041+sessionId: params.sessionId,
2042+});
2043+effectiveTools = [...toolSearchSchemaProjection.tools];
19862044if (toolSearch.compacted) {
19872045prepStages.mark(codeModeControlsEnabledForRun ? "code-mode" : "tool-search");
19882046log.info(
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。