feat: add configurable tool call blocking and monitoring

This commit is contained in:
Ed1s0nZ
2026-09-08 09:44:32 +08:00
parent c70da22de7
commit 6ad9ea2d13
54 changed files with 4635 additions and 152 deletions
+101 -1
View File
@@ -77,6 +77,8 @@
"submit": "Sign in"
},
"nav": {
"security": "Security",
"toolGuard": "Call blocking",
"dashboard": "Dashboard",
"chat": "Chat",
"assets": "Asset Management",
@@ -544,6 +546,7 @@
"generatedFromFact": "Generated from project fact {{factKey}}"
},
"chat": {
"toolExecBlocked": "Tool {{name}} blocked",
"newChat": "New chat",
"newTask": "New task",
"toggleConversationPanel": "Collapse/expand conversation list",
@@ -821,6 +824,96 @@
"hitlStatusOff": "Human-in-the-loop: Off",
"rolePanelTitle": "Select role"
},
"toolGuard": {
"invalidTestResponse": "The server returned an invalid test result",
"fieldTooLong": "Rule names are limited to 200 UTF-8 bytes; patterns and messages to 4096 UTF-8 bytes each. Shorten the content and try again.",
"tooManyRules": "You can configure up to 100 blocking rules.",
"title": "Call blocking",
"description": "Check MCP tool names and arguments before execution and stop matching calls. Human-in-the-loop approvals and tool whitelists do not bypass these checks.",
"reset": "Discard changes",
"save": "Save and apply",
"policyTitle": "Blocking policy",
"enableHint": "Checks for risks before tool execution. Save to apply changes.",
"enabled": "Enable call blocking",
"scopeHint": "Rules inspect visible call text only. They do not resolve IP ownership, redirect destinations, or file contents read by tools. Domain rules cannot cover every indirect access.",
"rulesTitle": "Blocking rules",
"rulesHint": "Enabled rules are checked in order; the first match supplies the blocking message. Patterns use RE2 syntax and are validated by the server when saved or tested.",
"addRule": "Add rule",
"addDialogTitle": "Add blocking rule",
"addDialogHint": "Configure your rule and try sample arguments before adding it to the list.",
"addToList": "Add to list",
"addToListHint": "After adding the rule, select “Save and apply” at the top of the page to activate it.",
"cancelAdd": "Cancel",
"closeDialog": "Close add rule dialog",
"singleTestTitle": "Test this rule",
"closeRuleTest": "Hide rule test",
"singleTestHint": "Test the current draft independently before saving. No tools are executed.",
"testing": "Testing…",
"testReadyHint": "Click Test match to see the result here.",
"testResultLabel": "Test result",
"testChanged": "The content has changed. Run the test again.",
"ruleAdded": "Rule added to the list. Save to apply it.",
"addingRule": "Checking rule…",
"addFailed": "Failed to add rule",
"messageHint": "Messages support {match} (matched text), {tool} (tool name), and {rule} (rule name).",
"testTitle": "Test all rules",
"testHint": "Check the current page configuration, including unsaved changes. This test does not execute any tools.",
"test": "Test match",
"testTool": "Tool name",
"testArguments": "Tool arguments (JSON object)",
"loading": "Processing…",
"unsaved": "Unsaved changes",
"savedState": "Synced with server",
"emptyRules": "No rules yet. Add and save a rule to enable its checks.",
"rule": "Rule",
"ruleEnabled": "Enabled",
"deleteRule": "Delete",
"ruleName": "Rule name",
"pattern": "Pattern (RE2)",
"message": "Blocking message",
"requestFailed": "Request failed",
"invalidResponse": "The server returned an invalid configuration",
"loadFailed": "Failed to load blocking configuration",
"loadFirst": "Load the blocking configuration first",
"requiredFields": "Enter a name and pattern for every rule",
"saveSuccess": "Call blocking configuration saved. Subsequent tool calls will use the new configuration.",
"saveFailed": "Save failed",
"defaultMessage": "Detected {match}. Rule “{rule}” blocked this call. Review the target and operation before trying again.",
"blocked": "Rule matched: this call will be blocked",
"notBlocked": "No enabled rule matched",
"disabledResult": "Call blocking is disabled: this configuration will not block calls",
"matchedRule": "Matched rule",
"matchedText": "Matched text",
"matchedMessage": "Returned blocking message",
"toolRequired": "Enter a tool name to test",
"invalidArguments": "Tool arguments must be a valid JSON object",
"testFailed": "Test failed",
"listHint": "Select a rule to view or edit. Rules are checked in list order.",
"helpTitle": "Rule syntax and matching scope",
"testSummary": "Check overall blocking with the current rule order and enabled states",
"unnamedRule": "Untitled rule",
"expandRule": "Expand rule",
"collapseRule": "Collapse rule",
"ruleOn": "Enabled",
"ruleOff": "Disabled",
"ruleModified": "Modified",
"ruleNew": "New",
"defaultPreview": "Uses the default blocking message when matched",
"protectionOn": "Call blocking is on",
"protectionOff": "Call blocking is off",
"ruleCount": "{{enabled}} of {{total}} rules enabled",
"closeEditor": "Close editor",
"testEntry": "Test all rules",
"validateRule": "Test this rule",
"testAll": "Test all rules",
"testScopeAll": "All rules",
"testScopeSingle": "Single rule: {{name}}",
"testSingleHint": "Tests only this rule, ignoring global and rule switches. Does not save or execute tools.",
"testAllHint": "Tests all rules in their current order and enabled states. Does not save or execute tools.",
"singleMatched": "This rule matched",
"singleNotMatched": "This rule did not match",
"singleResultHint": "This is a single-rule test. Actual blocking also depends on the global switch, enabled rules, and matching order."
},
"hitl": {
"pageTitle": "HITL approvals",
"pageReviewerLabel": "Current reviewer",
@@ -983,6 +1076,7 @@
"peAgentReplanning": "Replanner"
},
"timeline": {
"blocked": "Blocked",
"params": "Parameters:",
"executionResult": "Execution result:",
"executionId": "Execution ID:",
@@ -2242,6 +2336,11 @@
}
},
"mcpMonitor": {
"toolRowNoCompletedAriaLabel": "{{name}}, {{total}} calls, no completed outcomes; view execution records",
"rateExcludesBlocked": "Success rate includes successful and failed calls, excluding blocked and stopped calls",
"timelineBlockedLegend": "Blocked",
"blockedCount": "Blocked {{n}}",
"statusBlocked": "Blocked",
"deselectAll": "Deselect all",
"statusPending": "Pending",
"statusQueued": "Queued",
@@ -2316,7 +2415,7 @@
"timelineLoadError": "Failed to load call trend",
"timelineTotalLegend": "Total calls",
"timelineFailedLegend": "Failed",
"timelineTooltip": "{{time}}: {{total}} calls ({{failed}} failed)",
"timelineTooltip": "{{time}}: {{total}} calls ({{failed}} failed, {{blocked}} blocked)",
"distTitle": "Call distribution",
"distLegend": "Slice area shows share of all calls",
"distClickHint": "Click a bar segment to filter records",
@@ -3209,6 +3308,7 @@
"botCommandsFooter": "Otherwise, text is sent to AI under the bound user or service account's current RBAC permissions."
},
"mcpDetailModal": {
"blockReason": "Block reason",
"title": "Tool call details",
"execInfo": "Execution info",
"tool": "Tool",
+101 -1
View File
@@ -77,6 +77,8 @@
"submit": "登录"
},
"nav": {
"security": "安全防护",
"toolGuard": "调用拦截",
"dashboard": "仪表盘",
"chat": "对话",
"assets": "资产管理",
@@ -532,6 +534,7 @@
"generatedFromFact": "由项目事实 {{factKey}} 生成"
},
"chat": {
"toolExecBlocked": "工具 {{name}} 已拦截",
"newChat": "新对话",
"newTask": "新任务",
"toggleConversationPanel": "折叠/展开对话列表",
@@ -809,6 +812,96 @@
"hitlStatusOff": "人机协同:关闭",
"rolePanelTitle": "选择角色"
},
"toolGuard": {
"invalidTestResponse": "服务端返回的测试结果格式不正确",
"fieldTooLong": "规则名称最多 200 个 UTF-8 字节,正则和提醒各最多 4096 个 UTF-8 字节;请缩短内容。",
"tooManyRules": "最多可配置 100 条拦截规则。",
"title": "调用拦截",
"description": "在 MCP 工具执行前检查工具名称和参数,命中规则立即阻止调用。人机协同审批和工具白名单不会跳过此检查。",
"reset": "撤销修改",
"save": "保存并生效",
"policyTitle": "拦截策略",
"enableHint": "在工具执行前检查风险,修改后保存生效。",
"enabled": "启用调用拦截",
"scopeHint": "正则仅检查调用中可见的文本;不会解析 IP 归属、重定向目标或工具读取的文件内容。域名规则不能保证覆盖所有间接访问。",
"rulesTitle": "拦截规则",
"rulesHint": "按顺序匹配已启用的规则,使用首条命中规则的提醒。正则采用 RE2 语法,保存和试运行时由服务端校验。",
"addRule": "添加规则",
"addDialogTitle": "添加拦截规则",
"addDialogHint": "先配置规则,再用示例参数验证效果,确认后添加到列表。",
"addToList": "添加到列表",
"addToListHint": "添加到列表后,点击页面顶部「保存并生效」应用规则。",
"cancelAdd": "取消",
"closeDialog": "关闭添加规则",
"singleTestTitle": "验证本条规则",
"closeRuleTest": "收起验证",
"singleTestHint": "使用当前填写内容独立验证,无需保存;不会执行工具。",
"testing": "验证中…",
"testReadyHint": "点击「测试匹配」,在这里查看验证结果。",
"testResultLabel": "验证结果",
"testChanged": "内容已修改,请重新测试匹配。",
"ruleAdded": "规则已添加到列表,保存后生效。",
"addingRule": "正在检查规则…",
"addFailed": "添加规则失败",
"messageHint": "拦截提醒可使用 {match}(匹配文本)、{tool}(工具名称)、{rule}(规则名称)。",
"testTitle": "全部规则验证",
"testHint": "使用页面上的当前配置(包括未保存修改),仅检查匹配结果,不执行任何工具。",
"test": "测试匹配",
"testTool": "工具名称",
"testArguments": "工具参数(JSON 对象)",
"loading": "处理中…",
"unsaved": "有未保存修改",
"savedState": "已与服务端同步",
"emptyRules": "暂无规则。添加规则后保存,即可启用对应的拦截措施。",
"rule": "规则",
"ruleEnabled": "启用",
"deleteRule": "删除",
"ruleName": "规则名称",
"pattern": "匹配正则(RE2",
"message": "拦截提醒",
"requestFailed": "请求失败",
"invalidResponse": "服务端返回的配置格式不正确",
"loadFailed": "加载拦截配置失败",
"loadFirst": "请先加载拦截配置",
"requiredFields": "请填写每条规则的名称和匹配正则",
"saveSuccess": "调用拦截配置已保存,后续工具调用将使用新配置。",
"saveFailed": "保存失败",
"defaultMessage": "识别到 {match},调用被规则「{rule}」拦截。请检查目标与操作后重试。",
"blocked": "已命中规则:将阻止调用",
"notBlocked": "未命中已启用的规则",
"disabledResult": "调用拦截已关闭:此配置不会阻止调用",
"matchedRule": "命中规则",
"matchedText": "匹配文本",
"matchedMessage": "返回的拦截提醒",
"toolRequired": "请填写测试工具名称",
"invalidArguments": "工具参数必须是有效的 JSON 对象",
"testFailed": "测试失败",
"listHint": "点击规则查看和编辑,按列表顺序匹配。",
"helpTitle": "规则说明与匹配范围",
"testSummary": "按规则顺序和启停状态,检查整体拦截效果",
"unnamedRule": "未命名规则",
"expandRule": "展开规则",
"collapseRule": "收起规则",
"ruleOn": "已启用",
"ruleOff": "已停用",
"ruleModified": "已修改",
"ruleNew": "新增",
"defaultPreview": "命中后使用默认拦截提醒",
"protectionOn": "调用拦截已开启",
"protectionOff": "调用拦截已关闭",
"ruleCount": "{{enabled}} / {{total}} 条规则已启用",
"closeEditor": "收起编辑",
"testEntry": "全部规则验证",
"validateRule": "验证本条",
"testAll": "验证全部规则",
"testScopeAll": "全部规则验证",
"testScopeSingle": "单条验证:{{name}}",
"testSingleHint": "仅验证本条规则,忽略总开关和规则启停;不保存、不执行工具。",
"testAllHint": "按当前顺序与启停状态验证全部规则,不保存、不执行工具。",
"singleMatched": "本条规则匹配成功",
"singleNotMatched": "本条规则未匹配",
"singleResultHint": "这是单条规则验证结果,实际拦截还取决于总开关、规则启停和匹配顺序。"
},
"hitl": {
"pageTitle": "人机协同审批",
"pageReviewerLabel": "当前审批方",
@@ -971,6 +1064,7 @@
"peAgentReplanning": "重规划"
},
"timeline": {
"blocked": "已拦截",
"params": "参数:",
"executionResult": "执行结果:",
"executionId": "执行ID:",
@@ -2230,6 +2324,11 @@
}
},
"mcpMonitor": {
"toolRowNoCompletedAriaLabel": "{{name}}{{total}} 次调用,暂无完成结果,点击查看执行记录",
"rateExcludesBlocked": "成功率仅统计成功和失败的调用,不包含安全拦截和终止",
"timelineBlockedLegend": "安全拦截",
"blockedCount": "安全拦截 {{n}}",
"statusBlocked": "已拦截",
"deselectAll": "取消全选",
"statusPending": "等待中",
"statusQueued": "排队中",
@@ -2304,7 +2403,7 @@
"timelineLoadError": "无法加载调用趋势",
"timelineTotalLegend": "总调用",
"timelineFailedLegend": "失败",
"timelineTooltip": "{{time}}{{total}} 次(失败 {{failed}}",
"timelineTooltip": "{{time}}{{total}} 次(失败 {{failed}},安全拦截 {{blocked}}",
"distTitle": "调用分布",
"distLegend": "扇区面积为占全部调用比例",
"distClickHint": "点击色条筛选执行记录",
@@ -3197,6 +3296,7 @@
"botCommandsFooter": "除以上命令外,直接输入内容将按绑定用户或服务账号的实时 RBAC 权限发送给 AI。Otherwise, text is sent to AI under the effective RBAC identity."
},
"mcpDetailModal": {
"blockReason": "拦截原因",
"title": "工具调用详情",
"execInfo": "执行信息",
"tool": "工具",