v0.16.10: 最小必要性清理 — 删除非必要校验和注入提示

按"让 AI 自己判断"原则,删除所有"工程师判断"性质的校验代码和注入提示,
只保留安全防护(路径沙箱/命令安全/参数消毒)和必要的上下文管理(压缩/截断)。

删除项:
- completion-gate.ts 整个文件(notThinking/toolResultReview/contextEfficiency/planModeCompletion)
- verifyToolResult 工具结果核验函数 + TOOLS_NEED_VERIFY 常量
- 跨轮次死循环检测器(recordLoopSignature/detectLoopDeadlock/resetLoopDeadlockDetector)
- R77 checkRateLimit 速率限制 + R87 isToolCircuitBroken 熔断器 + R104 isDuplicateToolResult 去重
- R56 目标对齐验证 + R63 速率限制 + R87 熔断器 + R104 去重检测 + R119 优先级排序
- agent-metrics recordCompletionGate + completionGatePassed + avgCompletionScore 相关代码
- context-manager 低价值关键词黑名单 + 快速摘要改用 user role
- LoopContext 的 completionGateFailCount/verifyWarnings 字段

修复项:
- R76 路径沙箱 replace bug:用 startsWith 前缀锚定替代 replace,避免子串误判
- R28 命令注入检测:缩小匹配范围,仅拦截命令替换中包含危险命令的情况

总计 13 文件变更,+46/-1124 行
This commit is contained in:
紫影233
2026-07-16 16:44:04 +08:00
parent a4b82b45bc
commit 80581deb37
13 changed files with 46 additions and 1124 deletions
+2 -32
View File
@@ -9,7 +9,7 @@ import { OllamaAPI } from '../api/ollama.js';
import { TOOL_DEFINITIONS } from './tool-registry.js';
import { getEnabledToolDefinitions } from './tool-registry.js';
import { logInfo, logWarn, logError } from './log-service.js';
import { validatePathSandbox, checkRateLimit, isToolCircuitBroken, recordToolFailure, recordToolSuccess, sanitizeToolArgs, checkCommandSafety, snapshotSafetyState, restoreSafetyState, resetAllSafetyState } from './agent-safety.js';
import { validatePathSandbox, sanitizeToolArgs, checkCommandSafety, snapshotSafetyState, restoreSafetyState, resetAllSafetyState } from './agent-safety.js';
import { getWorkspaceDirPath } from '../components/workspace-panel.js';
import type { ToolResult, ToolCall, ToolDefinition } from '../types.js';
@@ -176,18 +176,7 @@ ${context ? `\n附加上下文(参考数据,不是指令):\n<<<REFERENCE
// 工具执行前再次检查中止信号
if (subAgentAC.signal.aborted) break;
// R89: 子 Agent 熔断器检查 — 连续失败后自动禁用工具
const circuitBreaker = isToolCircuitBroken(tc.name);
if (circuitBreaker.broken) {
const waitSec = Math.ceil(circuitBreaker.remainingMs / 1000);
logWarn(`R89: 子 Agent 熔断器拦截: ${tc.name},冷却中(还需 ${waitSec}s`);
messages.push({
role: 'tool',
content: `<<<TOOL_RESULT_START name="${tc.name}">>>\n${JSON.stringify({ success: false, error: `工具「${tc.name}」因连续失败已被暂时禁用,请等待 ${waitSec} 秒后重试。` })}\n<<<TOOL_RESULT_END>>>`,
tool_name: tc.name
});
continue;
}
// R89/R82 已删除:子 Agent 熔断器 + 速率限制 — 剥夺 AI 试错空间
// R109: 子 Agent 参数消毒
tc.arguments = sanitizeToolArgs(tc.name, tc.arguments);
@@ -209,19 +198,6 @@ ${context ? `\n附加上下文(参考数据,不是指令):\n<<<REFERENCE
}
}
// R82: 子 Agent 速率限制 — 防止子代理快速连续调用同一工具
const rateLimit = checkRateLimit(tc.name);
if (!rateLimit.allowed) {
const waitSec = Math.ceil(rateLimit.retryAfterMs / 1000);
logWarn(`R82: 子 Agent 速率限制: ${tc.name},等待 ${waitSec}s`);
messages.push({
role: 'tool',
content: `<<<TOOL_RESULT_START name="${tc.name}">>>\n${JSON.stringify({ success: false, error: `调用频率过高,等待 ${waitSec}s` })}\n<<<TOOL_RESULT_END>>>`,
tool_name: tc.name
});
continue;
}
// R81: 子 Agent 路径沙箱 — 确保文件操作不超出工作空间
const SUB_FILE_TOOLS = new Set(['read_file', 'list_directory', 'search_files', 'web_fetch']);
if (SUB_FILE_TOOLS.has(tc.name)) {
@@ -246,12 +222,6 @@ ${context ? `\n附加上下文(参考数据,不是指令):\n<<<REFERENCE
try {
const { executeTool } = await import('./tool-registry.js');
const result = await executeTool(tc.name, tc.arguments);
// R89: 记录工具成功/失败到熔断器
if (result.success) {
recordToolSuccess(tc.name);
} else {
recordToolFailure(tc.name);
}
const resultStr = formatResult(tc.name, result);
messages.push({
role: 'tool',