From 1bb5390263c33af511878f5955552592e2cf1b64 Mon Sep 17 00:00:00 2001 From: zhaolei <256168157@qq.com> Date: Fri, 30 Oct 2026 16:35:50 +0800 Subject: [PATCH] docs: add system overview and plan-management-and-alert-remediation v1.3 design doc - system-overview.md: full platform summary for NetMesh v2.x - plan-management-and-alert-remediation.md: dual-track alert response design with 26 decisions - alertRecordStore.cjs: remove auto_recover per D25 (alerts must be manually closed) --- docs/plan-management-and-alert-remediation.md | 995 ++++++++++++++++++ docs/system-overview.md | 295 ++++++ .../bridges/inspection/alertRecordStore.cjs | 11 +- 3 files changed, 1293 insertions(+), 8 deletions(-) create mode 100644 docs/plan-management-and-alert-remediation.md create mode 100644 docs/system-overview.md diff --git a/docs/plan-management-and-alert-remediation.md b/docs/plan-management-and-alert-remediation.md new file mode 100644 index 0000000..074c0f1 --- /dev/null +++ b/docs/plan-management-and-alert-remediation.md @@ -0,0 +1,995 @@ +# NetMesh 预案管理与告警联动 —— 设计方案 v1.3 + +> 版本:v1.3 · 日期:2026-10-30 · 状态:评审中 +> v1.3 变更:补全 AI 初始响应包性能保护、AlertStateMonitor 升级执行载体、处置引擎 ↔ AI Agent 集成通路、auto_close 语义修正、human_action ↔ remediation 映射约束、plan_snapshot 冻结时机、notification_chain.auto 一期范围、AI 预案 Review Workflow、裁决表新增 D21-D26 +> v1.2 变更:引入值班员动作预案层级,与操作级预案双轨绑定;新增处置步骤执行权限分级;新增 AI 初始响应包自动推送 + +--- + +## 〇、裁决表(Decision Table) + +多轮讨论后固化所有争议点,正文所有章节强制对齐此表。 + +| # | 争议点 | 最终结论 | 理由 | +|---|--------|----------|------| +| D1 | 预案与现有 `alertRuleStore` 的关系 | **预案增强规则**,不取代 | alertRuleStore 负责「指标异常检测 → 产出原始告警」,预案在后面做二次匹配 + 处置编排,渐进式接入 | +| D2 | 聚合升级触发方式 | **实时触发**(每来一条新告警就检查窗口内计数) | 巡检调度器周期执行,多台故障告警扎堆进来,实时触发比窗口到期触发延迟更小;窗口状态直接复用 alertRecordStore 活跃告警列表 | +| D3 | 匹配优先级 | **同 level 下 scope 最精确者胜出**,level 从高到低过滤 | 正常配置下每个 device_type × level 只应有一份预案,多命中是配置错误 | +| D4 | 白名单方式 | **预置命令 ID(方式 C)为主** + 临时处置用前缀匹配(方式 A)+ confirm | 预置 ID 最安全,运维选而不是写;临时输入走严格校验 + 确认 | +| D5 | 处置会话来源 | 复用现有 AI Agent capabilityTools 的 SSH/terminal 通路(通过 aiBridge 调用 Catty Agent session) | 凭据、审计、权限全部统一,不另开 SSH | +| D6 | 聚合窗口维度 | 初始版本开放 `catalog_type` + `tier` 两个维度 | 覆盖 80% 场景,太多维度会把配置搞复杂 | +| D7 | 模板 vs 预案的边界 | 模板**不含**匹配条件、值班员动作预案、处置步骤,只含公共联动配置 | 避免路由器/服务器处置步骤串台 | +| D8 | 处置失败回滚 | 初始版本**不做自动回滚**,步骤级配置 `on_failure` 动作(retry/stop/escalate) | 回滚逻辑和设备类型强相关,路由器命令的回滚和服务器完全不同,一期不做 | +| D9 | 预案版本化 | **匹配到预案的那一刻就冻结 snapshot**(写入 alertRecord.matched_plan_snapshot) | 处置开始后才冻结有窗口期漏洞——initial_response 用旧预案但 remediation 用新预案导致信息不一致;匹配时刻冻结保证整条链路一致 | +| D10 | 并发处置 | 聚合升级告警的多设备处置**串行执行**,不做并发 | 串行安全性高,且 AI Agent 已有 sessionExecutionQueue 做执行排队;并发留到后续 | +| D11 | 安全类告警分类 | 新增 alert_type 分类,安全类(firewall_intrusion 等)优先级独立于 performance/connectivity | 在聚合升级和匹配中权重更高 | +| D12 | 一期通知通道 | **监控大屏弹窗增强 + webhook**。dingtalk/wechat/email 外置推送后置(P5) | 现有值班员通过监控大屏弹窗感知告警,一期在现有弹窗内嵌入 AI 初始响应包,值班员弹窗一开即能看到完整响应信息 | +| D13 | 预案配置入口 | **AI 描述生成 + 表单手动 共存**,不是替代 | 新手用 AI 快速生成草稿,高级运维用表单精确控制;AI 生成的预案必须走人工审核节点才能启用 | +| D14 | AI 生成的安全边界 | **三重防线**:schema 验证 → 白名单交叉校验 → 人工审核 | AI 可能编造 command_id 或输出高危命令,必须机器校验 + 人工确认双保险 | +| D15 | AI Prompt 上下文 | **显式注入 command_catalog + catalog_type 字典 + 模板变量 Reference**,让 AI 查表而不是瞎猜 | 避免 AI 乱编 device_type、command_id、template variable;AI 只做"翻译"不做"发明" | +| D16 | 预案双轨绑定 | **同一个 device_plan 同时包含「值班员动作预案」和「操作级预案」**(称为"双轨"),匹配条件 + scope 是**匹配元数据**(不属于预案轨) | 操作步骤必须嵌入在人员动作链里(先通知 → 再处置 → 后确认),分开会断裂 | +| D17 | 处置步骤执行权限 | **三级执行权限:auto / confirm / manual_only** | show 类命令 AI 自动跑;重启/改配置需值班员确认;console 密码重置等禁止 AI 碰只能人工执行 | +| D18 | AI 初始响应包 | **告警触发后 AI 自动生成初始响应包,直接嵌入监控大屏弹窗**(不用等运维手动询问) | 弹窗内显示完整设备画像 + 告警详情 + 快速 checklist + 匹配预案摘要,值班员可以一键复制/转发运维群 | +| D19 | 值班员响应优先级 | **值班员动作预案的通知/确认/升级动作优先级高于 AI 自动处置** | AI 自动处置只能执行 `auto` 权限的步骤;`confirm` 和 `manual_only` 必须等值班员触发,值班员可以随时暂停 AI 自动处置 | +| D20 | 大屏弹窗增强策略 | **在现有告警弹窗(useMonitoringData → MonitoringTopologyView 里的 alert 展示位)基础上追加 AI 响应包面板**,不替换原有告警详情区 | 值班员已有大屏使用习惯,弹窗内新增"AI 响应包 Tab 或折叠面板"即可,降低学习成本 | +| D21 | 多告警关联 | **一期不支持同设备多条不同 rule 告警合成**,每条 alertRecord 独立匹配预案;P6 再做 | alertRecordStore 去重粒度是 device_id + rule_id,同设备不同 rule 产生 N 条独立告警;一期合成逻辑和处置步骤编排复杂度太高 | +| D22 | AI 初始响应包性能保护 | **三层保护**:① 去抖(同告警 5min 只生成一次)② 限流(最多 3 并发,PromiseQueue 排队)③ 超时降级(15s 硬超时,AI 不可用时用 human_action_guide 直接组装) | 巡检周期跑完可能一批告警同时触发 → N 次 AI 调用排队超时;降级保证即使 AI 不可用也有响应包 | +| D23 | 升级兜底执行载体 | **新增 AlertStateMonitor 模块**(每 5min 定时扫活跃告警),执行 escalation_fallback.auto_escalate_minutes 超时检查 + remediation 超时暂停 | 现有 alertAggregationEngine 是"事件驱动"(来一条新告警检查一次),不会主动扫存量告警的超时情况 | +| D24 | 处置引擎 ↔ AI Agent 集成 | **remediationEngine 通过 aiBridge 发工具调用请求**,让 Catty Agent 在它自己的 session 上下文里执行 | 凭据、审计、权限全部走 Catty Agent 现有链路;remediationEngine 不直接 import capabilityTools | +| D25 | auto_close 语义 | **字段改名为 auto_close_after_remediation_recovery**;只有 remediation.status === "completed" 时才检查指标恢复 → 自动关告警 | 之前模板里的 auto_close_on_recovery 和 processAlert 里 auto_recover 语义混淆,容易导致告警未处置就被指标恢复自动关掉 | +| D26 | notification_chain.auto 一期处理 | **webhook / desktop → 一期实现**;dingtalk/wechat → 标注 "pending_external" 需外置通知网关;phone → 标注 "manual_only" 显示电话号码让值班员自己拨 | 预案里写 auto: true 但一期不实现的通道,必须明确告知值班员哪些会自动发、哪些需要手动 | + +--- + +## 一、两类预案体系 + +### 1.1 双轨绑定概念 + +**一个 device_plan 里包含匹配元数据 + 两个预案轨**,共同构成完整的告警响应闭环: + +``` +device_plan + ├── 匹配元数据(不属于预案轨) + │ ├── match 匹配条件(metric_rules / alert_types / device_tiers / device_tags) + │ └── scope 适用范围(host_ids / host_groups) + │ + ├── human_action_guide ← 第一轨:值班员动作预案(人看的,指导怎么响应) + │ ├── receiving_alerts "收到告警第一时间做什么" + │ ├── info_gathering "先收集哪些信息" + │ ├── notification_chain "通知谁、怎么通知" + │ ├── escalation_triggers "什么情况必须升级/上报" + │ ├── pre_remediation "处置前必须做的防护动作" + │ └── post_remediation "处置完要做什么确认/回传/归档" + │ + └── remediation ← 第二轨:操作级预案(机器执行的命令步骤) + └── steps[] 每个 step 带 execution: "auto" | "confirm" | "manual_only" +``` + +**两者的关系**:值班员动作预案是骨架/流程,操作级预案是骨架里嵌入的可自动执行的工具。 + +### 1.2 human_action ↔ remediation 映射约束 + +两者都描述"怎么处理",必须保持映射一致性。匹配器匹配成功后、处置引擎开始前做一次完整性检查: + +``` +human_action_guide ↔ remediation 映射规则: + ├── info_gathering 条目 → auto / confirm step(按 priority 排序) + │ 例: info_gathering { priority: 1, action: "SSH display cpu-usage" } + │ → remediation.steps[0] = { command_id: "...", execution: "auto" } + │ + ├── pre_remediation 条目 → confirm 或 manual_only step + │ (备份 running-config → confirm;创建变更单 → manual_only) + │ + ├── escalation_triggers → 不映射 step + │ (由 AlertStateMonitor 定时检查,不进处置引擎) + │ + └── post_remediation 条目 → manual_only step + (值班员手动勾完成,不自动调用 AI) + +完整性检查: + - human_action_guide 里每个 info_gathering 条目必须有对应的 remediation step + - 缺失 → 在 initial_response.warnings 里标注,不阻断告警 + - 值班员可以在处置工作台手动补全缺失 step +``` + +### 1.3 典型场景对照 + +**场景:核心交换机 CPU 持续 > 90% 5 分钟** + +``` +┌──────────────────────────────────────────────────────────────────────┐ +│ 值班员动作预案(human_action_guide) │ +│ │ +│ 1. 收到告警 → 打开拓扑图确认设备位置(核心机房 A 架 12 位) │ +│ 2. 用 console/SSH 登录,先观察 30 秒看是否自然恢复 │ +│ 3. 如果持续不降 → 通知网络组 oncall(王工 138xxxx,钉钉已自动发) │ +│ 4. 30 分钟未恢复 → 升级到三级预案,通知运维经理 + 值班经理 │ +│ 5. 处置前:拍一张 show running-config 快照,写入变更单 │ +│ 6. 处置后:show cpu-usage 确认恢复 → 回传截图到运维群 → 关闭告警 │ +└──────────────────────────────────────────────────────────────────────┘ + │ 第 3 步值班员看了一眼 CPU 确实 > 90% 持续不降 + │ 点击"开始处置"按钮触发 + ▼ +┌──────────────────────────────────────────────────────────────────────┐ +│ 操作级预案(remediation) │ +│ │ +│ Step 1 [auto] show processes cpu │ +│ → AI 自动执行,输出 CPU 使用率明细 │ +│ → 值班员看输出判断是哪个进程 │ +│ │ +│ Step 2 [confirm] display diagnostic-information save │ +│ → AI 执行前弹确认框,值班员点确认后执行 │ +│ → 采集诊断信息上传告警归档 │ +│ │ +│ Step 3 [confirm] cpu-usage threshold 90 log │ +│ → 调 CPU 告警阈值到 90% 避免重复告警(策略性调整) │ +│ │ +│ Step 4 [manual_only] 联系应用组停止异常进程 │ +│ → 这条不产生命令,只是值班员的任务项 │ +│ → 必须值班员手动完成后勾选"已完成" │ +└──────────────────────────────────────────────────────────────────────┘ +``` + +### 1.4 两类预案的职责边界 + +| 维度 | 值班员动作预案 | 操作级预案 | +|------|---------------|-----------| +| 执行主体 | 值班员(人) | AI Agent / 运维手动 | +| 核心内容 | 判断、通知、确认、升级、防护、归档 | 命令、脚本、SFTP、配置变更 | +| 载体 | checklist + 说明文字 + 联系人信息 | command_id / command_template + 参数 | +| 权限 | 流程级(什么时候该做什么人) | 操作级(哪些命令可以跑、谁来触发) | +| AI 能不能自动生成 | ✅ 可以,从自然语言描述翻译 | ✅ 可以,从 command_catalog 查表匹配 | +| AI 能不能自动执行 | ❌ 不行,必须值班员参与 | ✅ 看 execution 权限 | + +--- + +## 二、模块职责与边界 + +``` +┌──────────────────────────────────────────────────────────────────────────┐ +│ 现有链路(保留不动) │ +│ │ +│ inspectionScheduler ──► alertRuleStore ──► alertRecordStore │ +│ (定时巡检) (指标异常检测) (写入原始告警: active) │ +└────────────────────────────────┬─────────────────────────────────────────┘ + │ 每条新告警 + ▼ +┌──────────────────────────────────────────────────────────────────────────┐ +│ 新模块(独立于现有链路) │ +│ │ +│ ┌──────────────────────────────────┐ │ +│ │ 2.1 预案匹配器 │ │ +│ │ alertPlanMatcher │ │ +│ │ · 查 deviceStore 拿到设备画像 │ │ +│ │ · 遍历设备预案做匹配 │ │ +│ │ · 匹配时刻冻结 plan_snapshot │ ← D9: 匹配时刻冻结,不是处置开始时 │ +│ │ · 合并模板 + 预案双轨配置 │ │ +│ │ · 写 matched_plan_snapshot │ │ +│ └───────────────┬──────────────────┘ │ +│ │ │ +│ ┌─────────┴──────────┐ │ +│ ▼ ▼ │ +│ ┌─────────────────┐ ┌─────────────────────┐ │ +│ │ 2.2 聚合升级引擎 │ │ 2.3 初始响应包生成器 │ │ +│ │ alertAggregation │ │ initialResponseGen │ │ +│ │ Engine │ │ │ │ +│ │ · 实时检查窗口计数│ │ · 去抖 + 限流 + 超时 │ ← D22: 三层性能保护 │ +│ │ · 产出升级告警 │ │ · 匹配 AI 不可用降级 │ │ +│ └────────┬────────┘ └──────────┬──────────┘ │ +│ │ │ │ +│ ┌────────┴───────────────────────┴──────────┐ │ +│ │ 2.4 处置执行引擎 │ │ +│ │ remediationEngine │ │ +│ │ · 按 execution 权限分级执行 │ │ +│ │ · 通过 aiBridge 调 Catty Agent session │ ← D24: 不直接 import │ +│ │ · 白名单校验 + 结果校验 │ │ +│ │ · 审计日志 │ │ +│ └─────────────────────────────┬──────────────┘ │ +│ │ │ +│ ┌─────────────────────────────┴──────────────┐ │ +│ │ 2.5 AlertStateMonitor (定时扫描) │ ← D23: 新增执行载体 │ +│ │ · 每 5min 扫活跃告警超时情况 │ │ +│ │ · 处理 escalation_fallback.auto_escalate │ │ +│ │ · 处置超时暂停 │ │ +│ └────────────────────────────────────────────┘ │ +│ │ +│ ┌──────────────────────────────────────────────┐ │ +│ │ 2.6 通知分发 notificationDispatcher │ │ +│ │ · 监控大屏弹窗 AI 响应包面板(D20) │ │ +│ │ · webhook │ │ +│ │ · notification_chain.auto 分级处理(D26) │ │ +│ └──────────────────────────────────────────────┘ │ +│ │ +│ ┌──────────────────────────────────────────────┐ │ +│ │ 2.7 AI 预案生成器 planGenerator │ │ +│ │ · 双轨草稿生成 │ │ +│ │ · 三重校验 │ │ +│ │ · Review Workflow(D13/D26-补充) │ │ +│ └──────────────────────────────────────────────┘ │ +└──────────────────────────────────────────────────────────────────────────┘ +``` + +### 各模块职责 + +**预案匹配器**(`alertPlanMatcher`) +- 触发时机:alertRecordStore 写入新告警后立即调用 +- 核心输出:匹配到的模板 + devicePlan + **matched_plan_snapshot**(匹配时刻就冻结 JSON clone,保证整条链路一致,不被后续配置变更影响) +- 跳过 `status: "draft"` 的预案(AI 生成待审核的不参与自动匹配) +- 匹配后做 human_action ↔ remediation 完整性检查 + +**初始响应包生成器**(`initialResponseGenerator`) +- 触发时机:预案匹配成功后立即调用 +- **三层性能保护(D22)**: + - 去抖:同一条告警 5 分钟内只生成一次(alertRecord.id 作为 key) + - 限流:全局最多 3 个并发 AI 调用,超出的进入 PromiseQueue 排队 + - 超时:15s 硬超时(`AbortController`),超时后 `initial_response.status = "partial"` 只填模板固定字段 + - 降级:AI provider 未配置或完全不可用时,跳过 AI 调用,直接用 `devicePlan.human_action_guide` + deviceStore 设备画像 + alertRecord 基础字段组装 initial_response(不走 AI 也能产出基本响应包) +- 写入 alertRecord.initial_response → 监控大屏弹窗自动渲染 + +**聚合升级引擎**(`alertAggregationEngine`) +- 输入:每条从 alertRecordStore 新写入的 active 告警 +- 维护:窗口内活跃告警列表(直接读 alertRecordStore active 状态,不需要额外内存结构) +- 聚合规则按 `catalog_type` / `tier` 分组计数 +- 命中规则时产出升级告警(新 alertRecord,`escalation` 字段标记来源) + +**处置执行引擎**(`remediationEngine`) +- **AI Agent 集成通路(D24)**:不直接 import harness 的 capabilityTools,而是通过 aiBridge 发一个"执行一次工具调用"的请求,让 Catty Agent 在它自己的 session 上下文里执行。好处:凭据管理、审计日志、权限控制全部走 Catty Agent 现有链路 +- 按 `step.execution` 分级执行: + - `auto` → AI 自动执行(不需要值班员触发) + - `confirm` → 执行前弹确认框,值班员点"允许"后执行 + - `manual_only` → 不调用 AI,只在工作台展示 checklist 卡片,值班员手动完成后点"标记完成" +- 值班员可以**随时暂停** AI 自动处置(所有 auto 步骤停止排队,已在跑的 step 执行完当前命令后停止) +- `auto_close_after_remediation_recovery`(D25):只有 remediation.status === "completed" 且处置后指标恢复正常时,才自动关告警。不影响未进入处置的告警 + +**AlertStateMonitor**(`alertStateMonitor`)—— D23 新增 +- 定时任务:每 5 分钟跑一次 +- 扫描 alertRecordStore 里 status=active + status=acknowledged + 已匹配预案的告警 +- 检查: + - 告警挂了多久 → 超 `escalation_fallback.auto_escalate_minutes` → 调用 alertAggregationEngine.escalateAlert() + - `human_action_guide.escalation_triggers` 里的时间条件是否满足 + - remediation.status === "running" 超时 → 暂停处置 + 通知值班员 + - remediation.status === "completed" → 检查 `auto_close_after_remediation_recovery` + +**通知分发**(`notificationDispatcher`) +- **一期主通道**:监控大屏弹窗增强 +- **一期辅助通道**:webhook +- **notification_chain.auto 分级处理(D26)**: + - `channel === "webhook"` → 一期实现,推送到配置的 webhook URL + - `channel === "desktop"` → 一期实现,监控大屏弹窗 + - `channel === "dingtalk" | "wechat" | "email"` → 标注 `pending_external`,在 initial_response.auto_notifications_sent 里注明"需外置通知网关" + - `channel === "phone"` → 标注 `manual_only`,在 initial_response.pending_notifications 里显示电话号码让值班员自己拨 + +**AI 预案生成器**(`planGenerator`)+ Review Workflow +- 同时生成 `human_action_guide` + `remediation` 两个层级的草稿 +- 三重校验:schema 验证 → 白名单交叉校验 → 人工审核 +- **Review Workflow**: + 1. AI 生成 → devicePlan.status = "draft", source = "ai" + 2. 预案列表页标记 `[草稿·待审核]` + 3. 点开预案 → 表单页顶部有"审核"面板: + - `[通过并启用]` → status = "active"(同时触发 matcher.index) + - `[驳回并反馈]` → 反馈文字存 devicePlan.reject_reason → 可以让 AI 基于反馈重新生成 + 4. 审核权限:required_role === "admin" + 5. 审核历史:devicePlan.review_log = [{ ts, actor, action, reason }] + +--- + +## 三、数据流时序 + +### 3.1 完整告警响应闭环(双轨预案 + 匹配时刻冻结 snapshot + 三层性能保护) + +`` +inspectionScheduler ──► 巡检设备 ──► CPU 91%(华为 S6720 核心交换机) + │ + ▼ + alertRuleStore.evaluateRule + 规则 "CPU > 90% 持续 2 次" ──► 命中 + │ + ▼ + alertRecordStore.processAlert + 写入 active 告警 { level: "critical", alert_type: "performance_high" } + │ + ▼ + alertAggregationEngine(实时事件驱动) + 窗口内只有 1 台核心交换机 cpu_high → 未达聚合阈值 → 跳过 + │ + ▼ + ★ alertPlanMatcher(匹配时刻冻结 snapshot,D9) + 查 deviceStore: device_type=switch, tier=core + 匹配: plan_switch_critical_core(status !== draft) + 合并模板 + 预案双轨配置 + 立即写入 alertRecord.matched_plan_snapshot = JSON.parse(JSON.stringify(devicePlan)) + │ + ▼ + ★ 初始响应包生成器(D22 三层保护) + ├── 去抖: 5 分钟内第一次 → 通过 + ├── 限流: 并发数 1 < 3 → 通过 + ├── 超时: 开始 15s 倒计时 + ├── 调 Catty Agent(用 initialResponse 专用 prompt) + ├── 降级检查: AI provider 正常 → 继续 + └── 生成成功 → initial_response.status = "complete" + │ + ▼ + ┌─────────────────────────────────────────┐ + │ 📍 AI 初始响应包(完整包) │ + │ │ + │ 📍 设备画像 │ + │ 核心交换机-01 | 华为 S6720 | 10.0.1.5 │ + │ tier=core | 组=核心区 | 核心机房A架12位 │ + │ │ + │ 🔥 告警详情 │ + │ cpu_high | level=critical │ + │ 当前值 91% | 阈值 90% | 持续 300s │ + │ │ + │ 📋 快速 checklist(值班员先做这 3 件) │ + │ 1. SSH 登录 → show processes cpu │ + │ 2. 观察 30s 看是否自然恢复 │ + │ 3. 持续不降 → 通知网络组 │ + │ │ + │ 🧭 匹配预案: 核心交换机三级预案 │ + │ 30min 未恢复自动升级(AlertStateMonitor)│ + │ │ + │ 📞 通知链路(D26 分级): │ + │ ✅ desktop + webhook → 一期实现 │ + │ ⏸ dingtalk → pending_external(需网关)│ + │ ✋ phone 王工 138xxxx → 手动拨打 │ + │ │ + └──────────────────┬──────────────────────┘ + │ + ▼ + notificationDispatcher + → 监控大屏告警弹窗内追加 AI 响应包面板 + 值班员在大屏上看到完整包,一键复制转发运维群 + webhook 同时推送到配置的外部网关 + │ + ▼ + 值班员 SSH 登录 → 确认 CPU 持续不降 + 点"开始处置" → remediationEngine.start(alert_id) + │ + ▼ + remediationEngine + 读 alertRecord.matched_plan_snapshot(冻结快照,与 initial_response 同一份) + │ + ▼ + for step in remediation.steps: + ┌──────────────────────────────────────┐ + │ execution === "auto" │ + │ → aiBridge.requestToolCall( │ + │ alertRecord.id, │ + │ command_id, params │ + │ ) │ + │ → Catty Agent 执行 │ + │ → 结果回写 step.stdout_preview │ + │ + audit_log │ + │ 值班员可以随时暂停 │ + ├──────────────────────────────────────┤ + │ execution === "confirm" │ + │ → 弹确认框 → 值班员点"允许" │ + │ → 同上走 aiBridge → Catty Agent │ + ├──────────────────────────────────────┤ + │ execution === "manual_only" │ + │ → 工作台展示 checklist 卡片 │ + │ → 值班员手动完成后点"标记完成" │ + └──────────────────────────────────────┘ + │ + ▼ + 处置完成 → remediation.status = "completed" + remediationEngine 检查 auto_close_after_remediation_recovery(D25) + → 指标恢复正常 → alertRecord.status = "resolved" + → 指标未恢复 → alertRecord 仍保持 active + audit_log 追加全链路记录 + │ + ▼ + 值班员关闭告警 → 填写处置总结 note + 通知网关推送到运维群:✅ 告警已关闭 | CPU 恢复 35% | 耗时 47 分钟 +`` + +### 3.2 AlertStateMonitor 超时检查时序 + +` +AlertStateMonitor.start() + → setInterval(run, 5 * 60 * 1000) // 每 5 分钟跑一次 + +run() { + activeAlerts = alertRecordStore.list({ status: ["active", "acknowledged"] }) + + for alert in activeAlerts { + plan = alert.matched_plan_snapshot + if (!plan) continue; // 没匹配预案的不处理 + + // 检查 1: escalation_fallback.auto_escalate_minutes + if (plan.escalation_fallback?.auto_escalate_minutes) { + elapsed = (Date.now() - alert.triggered_at) / 60000 + if (elapsed >= plan.escalation_fallback.auto_escalate_minutes) { + alertAggregationEngine.escalateAlert(alert.id, { + reason: "escalation_fallback_timeout", + target_level: plan.escalation_fallback.escalation_target_level + }) + } + } + + // 检查 2: remediation 运行超时 + if (alert.remediation?.status === "running") { + runningFor = (Date.now() - alert.remediation.started_at) / 60000 + if (runningFor > 30) { // 30 分钟硬阈值 + remediationEngine.pause(alert.id, { reason: "timeout" }) + notificationDispatcher.notify(alert, { type: "remediation_timeout" }) + } + } + } +} +` + +### 3.3 多台设备同时故障(触发升级 + 匹配时刻冻结 + 初始响应包联动) + +` +T=0min switch-A offline ──► 原始告警 (critical) + → matcher 匹配 switch_offline_plan → 冻结 snapshot-A +T=0min switch-B offline ──► 原始告警 (critical) + → matcher 匹配 switch_offline_plan → 冻结 snapshot-A(同一份预案) +T=1min switch-C offline ──► 原始告警 (critical) + → matcher 匹配 switch_offline_plan → 冻结 snapshot-A + │ + ▼ + alertAggregationEngine 实时检查: + 每次新告警进来都检查窗口内计数 + 第 3 条进来时: catalog_type=switch, tier=core, + window=5min, threshold=3 台 offline → 命中! + │ + ▼ + 写入升级告警 (新 alertRecord): + level: "critical", + escalation: { trigger: "aggregation", + source_alert_ids: [A,B,C] } + │ + ▼ + alertPlanMatcher(重新匹配升级后的 critical 预案) + 匹配 switch_critical_escalation_plan + 冻结 snapshot-escalation + │ + ▼ + AI 初始响应包(聚合版,snapshot-escalation): + 📊 聚合: 3 台核心交换机同时离线(5分钟内) + 📍 设备: switch-A(10.0.1.1), switch-B(10.0.1.2), switch-C(10.0.1.3) + 🔥 可能原因: 核心机房 A 架配电故障 / 光纤中断 + 📋 值班员 checklist: + 1. 电话确认机房 A 架配电状态 + 2. 查 SNMP 网关是否能连通机房设备 + 3. 通知机房运维到场 + 📞 通知: 网络组 oncall + 机房运维经理 + 值班经理 + (聚合升级的初始响应包重点突出可能原因和通知链路) + │ + ▼ + 推送到值班员 + 运维群 +` + +### 3.4 AI 初始响应包三层保护具体流程 + +` +initialResponseGenerator.generate(alertRecord) { + // ① 去抖 + const debounceKey = initial_response:; + if (_generatedCache.has(debounceKey)) { + log('[initialResponse] skip: 5min 内已生成过'); + return _generatedCache.get(debounceKey); + } + + // ② 限流 + if (_activeCount >= 3) { + log('[initialResponse] queue: 并发已满,等待'); + return _queue.enqueue(() => generate(alertRecord)); + } + _activeCount++; + + try { + // ③ 超时控制 + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 15000); + + // 降级检查 + const provider = getAIProvider(); + if (!provider) { + log('[initialResponse] 降级: AI 不可用,直接组装'); + return this._fallbackGenerate(alertRecord); + } + + // 调 Catty Agent + const result = await cattyAgent.streamText({ + provider, + systemPrompt: INITIAL_RESPONSE_SYSTEM_PROMPT, + userMessage: buildInitialResponseUserMessage(alertRecord, matchedSnapshot, deviceProfile), + tools: [], // 响应包生成不需要 AI 调工具 + signal: controller.signal, + }); + + clearTimeout(timeoutId); + + // AI 解析可能有问题 → 降级到 fallback + let parsed; + try { parsed = JSON.parse(result.text); } + catch { parsed = this._fallbackGenerate(alertRecord); parsed.status = "partial_ai_invalid"; } + + return parsed; + } catch (err) { + log('[initialResponse] 失败/超时,降级到 fallback', err.message); + return this._fallbackGenerate(alertRecord, { reason: err.message }); + } finally { + _activeCount--; + _generatedCache.set(debounceKey, result, 5 * 60 * 1000); + } +} + +_fallbackGenerate(alert, options = {}) { + // 不用 AI,直接组装: human_action_guide + deviceStore + alertRecord + return { + status: options.reason ? "partial_fallback" : "complete_fallback", + device: extractFromDeviceStore(alert), + alert: extractFromAlertRecord(alert), + quick_checklist: alert.matched_plan_snapshot.human_action_guide?.info_gathering ?? [], + matched_plan: { name: alert.matched_plan_snapshot?.name ?? "未知预案" }, + possible_causes: [], // AI 推断字段 fallback 不填 + ...aggregateExtraFields(alert), + }; +} +` + +### 3.5 notification_chain.auto 分级处理(D26) + +` +notificationDispatcher.resolveChannels(humanActionGuide.notification_chain) { + for (const item of humanActionGuide.notification_chain) { + if (!item.auto) continue; // auto=false 的手动通知直接跳过 + + const resolved = { channel: item.channel, status: "", target: null, note: "" }; + + switch (item.channel) { + case "webhook": + resolved.status = "sent"; // 一期实现 + resolved.target = findWebhookConfig(item.role); + break; + case "desktop": + resolved.status = "sent"; // 一期实现(大屏弹窗 = desktop 通知) + break; + case "dingtalk": + case "wechat": + case "email": + resolved.status = "pending_external"; + resolved.note = "需外置通知网关(P5 实现)"; + break; + case "phone": + resolved.status = "manual_only"; + resolved.note = 请值班员手动拨打 ; + break; + default: + resolved.status = "unknown"; + } + + results.push(resolved); + } + + // 写回 alertRecord.initial_response.auto_notifications_sent + // + alertRecord.initial_response.pending_notifications + return results; +} +` + +--- + +## 四、关键数据结构 + +### 4.1 新增存储 key + +在 electron/bridges/inspection/storageKeys.cjs 里加: + +` +STORAGE_KEY_PLAN_TEMPLATES → plan_templates_v1 +STORAGE_KEY_DEVICE_PLANS → device_plans_v1 +STORAGE_KEY_AGGREGATION_RULES → aggregation_rules_v1 +STORAGE_KEY_COMMAND_CATALOG → command_catalog_v1 +` + +### 4.2 预案模板(plan_template) + +模板**不含**匹配条件、值班员动作预案、处置步骤——这些全是设备预案层的。模板只存公共联动配置。 + +``js +{ + id: "tpl_level3_critical", + name: "三级预案模板(严重)", + level: "critical", // critical | warning | info(与现有 ALERT_LEVELS 对齐) + builtin: true, // 系统预置 vs 自定义 + description: "...", + ── 大屏样式 ── + display: { + color: "#ef4444", icon: "alert-octagon", blink: true, + sound: "builtin_alarm", + }, + ── 通知策略 ── + notification: { + channels: ["desktop", "webhook"], + recipients: [ { type: "webhook", target: "https://hooks.example.com/alert" } ], + repeat_interval_minutes: 5, + max_repeats: 12, + }, + ── 升级兜底(D23 AlertStateMonitor 读取)── + escalation_fallback: { + auto_escalate_minutes: 30, // 挂 30min 没处置 → 自动升级 + escalation_target_level: "critical", + }, + ── 处置安全默认值 ── + remediation_defaults: { + require_confirmation: true, + auto_close_after_remediation_recovery: true, // ← D25: 改名 + execution_timeout_sec: 120, + }, + ── 审计 ── + created_at: 1729800000000, + updated_at: 1729800000000, +} +`` + +**约束**:模板不含 match、scope、human_action_guide、 emediation.steps、security —— 这些全是设备预案层的。 + +### 4.3 设备预案(device_plan)—— 双轨完整结构 + +``js +{ + id: "plan_switch_critical_core", + template_id: "tpl_level3_critical", + device_type: "switch", // router | switch | server | firewall | plugin:xxx + level: "critical", + enabled: true, + builtin: false, + status: "active" | "draft", // draft = AI 生成待审核 + source: "manual" | "ai", + ai_provider: null | "catty-minimax", + ai_prompt_version: null | "v2", + reject_reason: null | "xxx", // 审核驳回原因 + review_log: [ // Review Workflow(D13) + { ts: 1729800000000, actor: "admin", action: "approve", reason: null }, + { ts: 1729799000000, actor: "admin", action: "reject", reason: "command_id 不完整" }, + ], + description: "核心交换机三级预案 - CPU 过载处置", + + ═══════════════════════════════════════════════════════════════ + 【匹配元数据(不属于预案轨)】 + ═══════════════════════════════════════════════════════════════ + match: { + metric_rules: [ { metric_key: "cpu_usage", op: ">", value: 90 } ], + alert_types: ["performance_high"], + device_tiers: ["core"], + device_tags: [], + }, + scope: { host_ids: [], host_groups: [] }, + + ═══════════════════════════════════════════════════════════════ + 【第一轨】值班员动作预案 + ═══════════════════════════════════════════════════════════════ + human_action_guide: { + receiving_alerts: [ + "在拓扑图定位设备位置", + "确认告警是否已被其他值班员处理", + ], + info_gathering: [ + { priority: 1, action: "SSH 登录执行 display cpu-usage", + purpose: "确认 CPU 持续时间", expected_output: "平均 CPU 使用率" }, + { priority: 2, action: "查最近 24h 巡检历史", + purpose: "确认是否之前有过类似告警" }, + { priority: 3, action: "display diagnostic-information", + purpose: "采集诊断信息,保存归档" }, + ], + notification_chain: [ + { role: "网络组 oncall", channel: "dingtalk", + trigger: "收到告警立即", contact: "王工 138xxxx", auto: true }, + { role: "机房运维经理", channel: "phone", + trigger: "30 分钟未恢复", contact: "李经理 137xxxx", auto: false }, + { role: "值班经理", channel: "phone", + trigger: "60 分钟未恢复 或 聚合升级", contact: "张经理 136xxxx", auto: false }, + ], + escalation_triggers: [ + { condition: "告警持续 30 分钟未恢复", target_level: "critical" }, + { condition: "聚合升级触发(≥3 台同类型核心设备)", + target_level: "critical" }, + { condition: "安全告警(firewall_intrusion 等)", + target_level: "critical", note: "禁止 AI 自动处置" }, + ], + pre_remediation: [ + "备份当前 running-config", + "确认运维变更单已创建", + "通知相关业务方(如有业务影响)", + ], + post_remediation: [ + "show cpu-usage 确认恢复到正常阈值以下", + "show logging 检查处置命令产生的日志", + "将处置过程 + AI 输出截图上传告警归档", + "关闭告警时填写处置总结 note", + ], + }, + + ═══════════════════════════════════════════════════════════════ + 【第二轨】操作级预案(含 execution 权限分级) + ═══════════════════════════════════════════════════════════════ + remediation: { + require_confirmation: true, + steps: [ + { + order: 1, + action: "command", + command_id: "switch_show_cpu", + command_params: {}, + timeout_sec: 30, + execution: "auto", + required_confirmation: false, + on_success: "next", + on_failure: "stop", + }, + { + order: 2, + action: "command", + command_id: "switch_collect_diagnostic", + command_params: {}, + timeout_sec: 120, + execution: "confirm", + required_confirmation: true, + on_success: "next", + on_failure: "retry:2", + }, + { + order: 3, + action: "command", + command_id: "switch_adjust_cpu_threshold", + command_params: { threshold: "95" }, + timeout_sec: 30, + execution: "confirm", + required_confirmation: true, + on_success: "next", + on_failure: "escalate", + }, + { + order: 4, + action: "note", + title: "联系应用组确认", + description: "CPU 高负载疑似应用进程导致,需联系应用组确认是否可以停止", + contact: "应用组 oncall 李工 139xxxx", + execution: "manual_only", + }, + ], + }, + + ═══════════════════════════════════════════════════════════════ + 【安全 + 权限】 + ═══════════════════════════════════════════════════════════════ + security: { + allowed_command_ids: [ "switch_show_cpu", "switch_collect_diagnostic" ], + allowed_commands: [ "show *", "display *" ], + blocked_patterns: [ "rm -rf /", "shutdown now", "reload" ], + }, + required_role: "operator", + created_at: 1729800000000, + updated_at: 1729800000000, +} +`` + +### 4.4 执行权限分级(execution) + +| 权限值 | 谁触发 | AI 是否执行 | 对应能力 | +|--------|--------|------------|----------| +| "auto" | AI 自动 | ✅ 直接执行 | show/display/info 命令、无风险查询 | +| "confirm" | 值班员点击"允许" | ✅ 值班员允许后执行 | 重启接口、调阈值、改配置、备份、采集诊断 | +| "manual_only" | 值班员手动完成后点"标记完成" | ❌ 不执行 AI | 联系应用组、console 密码重置、到场操作、策略性确认 | + +**AI 自动处置边界**:AI 只负责 uto 权限步骤,confirm 必须等值班员点击,manual_only 只展示 checklist 卡片。值班员可以随时**暂停全部处置**(所有 auto 步骤停止排队,已在跑的 step 执行完当前命令后停止)。 + +### 4.5 初始响应包结构(initial_response) + +`js +{ + alert_id: "alert_cpu_high_switch_01", + generated_at: 1729800000000, + generator: "catty-agent" | "fallback", + status: "complete" | "partial" | "partial_ai_invalid" | "complete_fallback" | "partial_fallback", + ── 设备画像 ── + device: { + host_id, label, hostname, catalog_type, tier, group, location, + last_inspection: { at, health_score } + }, + ── 告警详情 ── + alert: { alert_type, metric_key, metric_value, threshold, duration_seconds, level, triggered_at }, + ── 快速 checklist(值班员先做这几件事) ── + quick_checklist: [ { priority, action, purpose } ], + ── 匹配预案摘要 ── + matched_plan: { name, level, escalation_target_level, escalate_after_minutes }, + ── 通知链路(D26 分级)── + auto_notifications_sent: [ + { role: "网络组 oncall", channel: "webhook", at: 1729800000000, status: "sent" }, + { role: "网络组 oncall", channel: "dingtalk", status: "pending_external", + note: "需外置通知网关(P5 实现)" }, + ], + pending_notifications: [ + { role: "机房运维经理", channel: "phone", trigger: "30 分钟未恢复", + contact: "李经理 137xxxx", status: "manual_only" }, + ], + ── 可能原因(AI 推断,非确定) ── + possible_causes: [ + { probability: "high", label: "应用进程异常占用 CPU", hint: "display cpu-usage" }, + ], + ── 聚合版额外字段 ── + aggregate: null | { + type: "escalation", + trigger: "aggregation", + device_count: 3, + device_labels: ["switch-A", "switch-B", "switch-C"], + possible_root_cause: "核心机房 A 架配电故障", + }, + ── D22: 降级/警告 ── + warnings: [ + "human_action_guide.info_gathering 第 3 条未找到对应 remediation step(处置步骤缺失)", + "AI provider 不可用,响应包为 fallback 组装,possible_causes 为空", + ], +} +` + +### 4.6 alertRecord 扩展字段(向后兼容) + +**matched_plan_snapshot(D9: 匹配时刻冻结)** 是核心新字段,initial_response 和 remediation 都读这同一份: + +``js +{ + // ── 原有字段保留不动 ── + id, rule_id, rule_name, device_id, device_name, + metric, metric_value, threshold, level, message, + triggered_at, status, acknowledged_by, acknowledged_at, + resolved_at, resolved_reason, note, + + // ── 预案匹配(D9: 匹配时刻冻结 snapshot)── + matched_plan_id, matched_template_id, match_score, + matched_plan_snapshot: { ...完整 devicePlan JSON clone }, // ← 核心 + + // ── 升级信息 ── + escalation: null | { trigger, source_alert_ids, ... }, + + // ── v1.2: AI 初始响应包 ── + initial_response: { ...initial_response 结构 }, + + // ── v1.2: 值班员动作任务进度 ── + human_action_tasks: [ + { id, action, status: "pending"|"done"|"skipped", completed_by, completed_at } + ], + + // ── 处置执行(扩展 execution 权限 + auto_close 语义修正)── + remediation: { + plan_snapshot: { ... }, // ← 指向 matched_plan_snapshot 的同一份引用 + frozen_at: 1729800000000, + status: "pending" | "running" | "completed" | "partial" | "failed" | "cancelled" | "paused", + paused_at: null | 1729800120000, + auto_close_after_recovery: true, // ← D25 字段名 + steps: [ + { + order, execution: "auto"|"confirm"|"manual_only", + status: "pending"|"running"|"success"|"failed"|"timeout"|"skipped", + started_at, finished_at, executor, exit_code, + stdout_preview, confirmed_by, confirmed_at, error + } + ] + }, + + // ── 全链路审计 ── + audit_log: [ + { ts, actor, action, detail } + // v1.3 新增 action 类型: + // "initial_response_generated" (AI 自动生成,含 status) + // "initial_response_fallback" (AI 不可用降级) + // "notification_sent" / "notification_pending_external" / "notification_manual_only" + // "auto_execution_paused" / "remediation_timeout" + // "aggregation_escalation" (聚合升级触发) + // "escalation_fallback_timeout" (AlertStateMonitor 兜底升级) + ] +} +`` + +--- + +## 五、模板变量 Reference + +处置步骤 command_params 里可用的模板变量(同 v1.2 不变)。 + +--- + +## 六、AI 预案生成 + Review Workflow + +### 6.1 定位与边界 + +AI 描述生成 + 表单手动共存。AI 生成的预案 status = "draft",必须走人工审核才能启用。 + +### 6.2 Prompt 设计骨架(双轨 Prompt) + +同 v1.2,不变。 + +### 6.3 Review Workflow 前端交互 + +` +预案列表页 + ├── [自动刷新·AI 生成预案在最顶部] + ├── 行标记 [草稿·待审核] badge(source=ai + status=draft) + ├── 点击预案 → 表单页(已预填 AI 生成内容) + │ └── 顶部审核面板: + │ ┌──────────────────────────────────────────────────┐ + │ │ ✨ AI 生成预案草稿 │ + │ │ provider: catty-minimax | prompt_version: v2 │ + │ │ warnings: command_id 'switch_collect_diagnostic' │ + │ risk_level=high,启用需人工确认 │ + │ │ │ + │ │ 审核: │ + │ │ [✅ 通过并启用] [❌ 驳回并反馈] │ + │ └──────────────────────────────────────────────────┘ + │ + └── 审核记录折叠面板: + ┌─────────────────────────────────────┐ + │ 📋 审核历史 │ + │ 2026-10-30 14:20 admin 通过 │ + │ 2026-10-30 14:18 admin 驳回 │ + │ 原因: command_id 不完整 │ + └─────────────────────────────────────┘ +` + +### 6.4 初始响应包生成器(initialResponseGenerator) + +同 v1.2 的 Prompt 骨架 + v1.3 的三层保护(见 3.4 节完整实现流程)。 + +--- + +## 七、现有代码的具体改动落点 + +| 位置 | 改动 | 类型 | +|------|------|------| +| electron/bridges/inspection/storageKeys.cjs | 新增 4 个存储 key | 扩展 | +| electron/bridges/inspection/types.cjs | 新增 ALERT_TYPE_CATEGORIES | 扩展 | +| electron/bridges/inspection/alertRuleStore.cjs | rule 新增 lert_type | 扩展(向后兼容) | +| electron/bridges/inspection/alertRecordStore.cjs | alertRecord 扩展(matched_plan_snapshot、human_action_tasks、initial_response、remediation.auto_close_after_recovery、audit_log 新增 action 类型);新增 escalateAlert()、listActiveForMonitor()(给 AlertStateMonitor 用) | 扩展(向后兼容) | +| electron/bridges/inspection/index.cjs | inspection 回调链插入:告警写完 → matcher(**匹配时刻冻结 snapshot**) → 聚合检查 → 初始响应包生成(**三层保护**);注册 AlertStateMonitor 定时任务 | 新增调用点 | +| **新建** electron/bridges/inspection/planTemplateStore.cjs | 预案模板 CRUD + 预置 seed | 新文件 | +| **新建** electron/bridges/inspection/devicePlanStore.cjs | 设备预案 CRUD + 匹配(scope 排序、AND 条件校验、白名单校验)+ Review Workflow(approve/reject + review_log)+ snapshot 冻结逻辑 | 新文件 | +| **新建** electron/bridges/inspection/aggregationEngine.cjs | 实时聚合检查 + 升级告警产出 + escalateAlert()(给 AlertStateMonitor 用) | 新文件 | +| **新建** electron/bridges/inspection/commandCatalogStore.cjs | 预置命令 ID 目录 | 新文件 | +| **新建** electron/bridges/inspection/remediationEngine.cjs | 处置引擎;**通过 aiBridge.requestToolCall 调 Catty Agent**(不直接 import capabilityTools);execution 权限分级;暂停/恢复;auto_close_after_recovery(D25) | 新文件 | +| **新建** electron/bridges/inspection/alertStateMonitor.cjs | **D23 新增**:每 5min 定时扫活跃告警;处理 escalation_fallback.auto_escalate_minutes;处置超时暂停;auto_close_after_recovery 检查 | 新文件 | +| **新建** electron/bridges/inspection/planGenerator.cjs | AI 双轨预案生成器 + Review Workflow | 新文件 | +| **新建** electron/bridges/inspection/initialResponseGenerator.cjs | AI 初始响应包自动生成;**D22 三层性能保护**(去抖 / 限流 PromiseQueue / 超时 AbortController + fallback);**D26 notification_chain 分级处理** | 新文件 | +| **新建** electron/bridges/inspection/devicePlan.schema.json | 设备预案 JSON Schema | 新文件 | +| **新建** electron/bridges/inspection/initialResponse.schema.json | 初始响应包 JSON Schema | 新文件 | +| electron/remoteHttpServer.cjs | 新增路由:预案 CRUD、聚合规则、命令目录、plan/generate、plan/approve、plan/reject、plan-context、alert/:id/remediation/*、alert/:id/initial-response、alertStateMonitor/status | 扩展路由 | +| electron/preload/api.cjs | 暴露预案相关 IPC | 扩展 | +| **前端** components/inspection/ | 预案模板管理页、设备预案管理页(双轨表单 + AI 生成面板 + Review Workflow 审核面板)、聚合规则配置页、处置工作台(含值班员 checklist 卡片 + 执行权限分级 UI) | 新组件 | +| components/monitoring/MonitoringTopologyView.tsx | 现有告警弹窗内追加 AI 响应包面板(Tab 切换:告警详情 / AI 响应包 / 处置工作台);匹配预案名、处置状态灯 | 扩展(不替换原有弹窗) | +| components/monitoring/useMonitoringData.ts | hook 扩展:拉 alertRecord 时取 initial_response;matched_plan_snapshot;aggregation 识别 | 扩展 | +| electron/bridges/aiBridge.cjs | 扩展一个轻量 equestToolCall(alert_id, command_id, params) 方法,供 remediationEngine 调用 | 扩展(薄封装) | + +--- + +## 八、实施阶段建议 + +| 阶段 | 内容 | 前置 | 关键风险 | +|------|------|------|----------| +| **P0 - 骨架** | storageKeys、types、7 个 store 文件(模板/预案/命令目录/聚合规则/**预案生成**/**初始响应包**/**AlertStateMonitor**)、2 个 schema、远程 HTTP 路由、AJV 校验、Prompt 工程、**aiBridge.requestToolCall 薄封装** | 无 | AI provider 未配置时 initialResponseGenerator 必须能降级 | +| **P1 - 匹配链路** | alertRecord 扩展 + 预案匹配器对接(**匹配时刻冻结 snapshot**);human_action ↔ remediation 完整性检查;AI 生成的 draft 预案跳过匹配 | P0 | matcher 跳过 draft 预案后,draft 预案不会参与自动匹配 | +| **P2 - 聚合升级** | 聚合引擎 + 升级告警产出 + AlertStateMonitor 注册定时任务 + alertRuleStore alert_type 扩展 | P1 | AlertStateMonitor 扫存量告警时不能重复 escalate(需 dedup) | +| **P3 - 处置执行** | remediationEngine(**通过 aiBridge 调 Catty Agent**)+ execution 权限分级 + 暂停/恢复 + 处置工作台前端;**auto_close_after_recovery** 只在 remediation.completed 后检查 | P1(可与 P2 并行) | D24: remediationEngine ↔ aiBridge 集成是关键 | +| **P4 - 通知 + 大屏** | monitoringDispatcher(**D26 分级处理**)+ 大屏弹窗 AI 响应包面板 | P2 + P3 | 大屏弹窗原有告警详情区必须保留,AI 响应包做 Tab 切换 | +| **P5 - Review Workflow + 外置通知** | planGenerator Review Workflow 审核面板 + dingtalk/wechat/email 外置通知网关适配 | P4 | 外置通知网关需要凭据管理模块 | +| **P6 - 多告警关联** | 同设备多条不同 rule 告警合成 + 综合预案匹配 | P5 | D21 已声明一期不支持,P6 重做 matcher 逻辑 | + +--- + +## 九、开放问题(后续版本讨论) + +| # | 问题 | 说明 | +|---|------|------| +| Q1 | 预案能不能跨设备类型? | 现在 device_type 单值,未来能不能一个预案同时匹配 router + switch? | +| Q2 | command_catalog 谁来 review? | 预置命令的 risk_level 标注和审批流程,需要和运维团队对齐 | +| Q3 | Catty Agent session 隔离 | 处置执行时调 Catty Agent,会不会和值班员正在用的 Catty session 冲突?需要 dedicated session | +| Q4 | AlertStateMonitor 怎么部署 | 和 inspectionScheduler 同进程?还是独立 worker?主进程已经有 scheduler 了 | +| Q5 | initialResponse 的多语言 | 响应包都是中文,有没有英文环境需求? | +| Q6 | plan_snapshot 的存储量 | 每条告警都存一份完整 devicePlan clone(几十 KB),活跃告警多了 localStorage 会不会爆? | +| Q7 | 处置结果和巡检闭环 | 处置执行的输出能不能反馈给 inspectionScheduler 自动触发巡检复查? | +| Q8 | AI 初始响应包的效果追踪 | 有没有反馈机制让值班员评价 initial_response 有用没用?反向改进 Prompt | +| Q9 | 预案导入导出 | 预案模板和设备预案能不能 JSON 导入导出?跨环境同步 | +| Q10 | command_catalog 与 vault 的凭据关联 | 有些命令需要 vault 里的特定凭据(比如 enable secret),command_catalog 怎么声明依赖? | diff --git a/docs/system-overview.md b/docs/system-overview.md new file mode 100644 index 0000000..4ccf174 --- /dev/null +++ b/docs/system-overview.md @@ -0,0 +1,295 @@ +# NetMesh 系统总结 + +> 项目代号:Netcatty · 版本:v2.x · 日期:2026-10-30 + +--- + +## 一、项目定位 + +**NetMesh(品牌名 Netcatty)** 是一款 **AI 原生的 SSH 客户端 / 网络运维终端 / 服务器管理平台**,以"让 AI 帮你管服务器"为核心理念,面向开发者、运维工程师、DevOps 团队。 + +它不是一个纯终端工具,而是一个**终端 + SFTP + 主机库 + 巡检监控 + 告警处置 + AI Agent + MCP Server + 云同步 + 插件生态**的完整平台。 + +--- + +## 二、核心功能清单 + +### 2.1 主机与连接管理 + +| 功能 | 说明 | +|------|------| +| 多协议主机支持 | SSH / Telnet / Mosh / ET(自研加密协议)/ 本地 Shell / Serial 串口 / 插件扩展协议 | +| 跳板机链路 | 多级跳板机链式连接,自动探测最优路径 | +| 代理配置 | HTTP / SOCKS5 代理,每台主机独立或全局配置 | +| 算法覆写 | 不同主机支持不同加密算法、KEX、MAC 协商策略 | +| 主机分组与标签 | 任意层级分组、自定义标签,支持按分组批量操作 | +| Host Key 管理 | known_hosts 自动维护、指纹校验、信任策略配置 | +| SSH Agent 转发 | 支持系统 SSH Agent 和内置 Agent | +| 凭据安全存储 | AES-GCM 加密存储私钥和密码,内存中零明文 | + +### 2.2 终端能力 + +| 功能 | 说明 | +|------|------| +| 多终端分割 | 拖拽式工作区分割,水平/垂直/自由布局,支持标签页 | +| xterm.js 6 渲染 | WebGL 加速、图片渲染、搜索高亮、序列化回放 | +| 终端主题 | 内置 20+ 主题,支持自定义配色 | +| 命令历史 | 跨终端会话命令历史、模糊搜索、智能推荐 | +| 片段(Snippets) | 常用命令片段库,一键插入,支持参数化模板 | +| 快捷键绑定 | Vim/Emacs/自定义快捷键方案 | +| 防刷屏与截断 | 长输出自动截断 + 查看完整内容 | +| 终端录屏 | 会话录制为 JSON 序列化文件,离线回放 | + +### 2.3 SFTP 文件管理 + +| 功能 | 说明 | +|------|------| +| 双栏文件浏览 | 本地/远程双栏同步滚动,拖拽上传下载 | +| 断点续传 | 大文件传输中断后自动续传 | +| SCP 后端 | 原生 SCP 协议支持(自研后端,不依赖外部库) | +| 文件搜索 | 递归搜索、按类型/大小/时间过滤 | +| 文件编辑 | Monaco Editor 内置编辑,SFTP 远程编辑即时保存 | +| 传输中心 | 全局传输队列、速度显示、失败重试、并发控制 | +| 临时文件安全 | 所有下载到本地的临时文件通过专用 tempDir 管理,程序退出自动清理 | + +### 2.4 端口转发 + +| 功能 | 说明 | +|------|------| +| 本地转发(L) | 本地端口 → 远程主机端口 | +| 远程转发(R) | 远程主机端口 → 本地端口 | +| 动态转发(SOCKS5) | 本地 SOCKS5 代理 → 通过远程主机出网 | +| 隧道管理 | 多隧道并发、状态监控、自动重连、流量统计 | + +### 2.5 巡检与监控 + +| 功能 | 说明 | +|------|------| +| 定时巡检调度 | 可配置周期、并发度、超时、重试策略 | +| 多设备类型适配 | 路由器 / 交换机 / 服务器 / 防火墙,每类设备独立采集适配器 | +| 巡检指标 | CPU / 内存 / 磁盘 / 网络 / 进程 / 服务 / 端口 / GPU / Docker | +| 健康评分 | 每台设备巡检后计算综合健康分 | +| 拓扑视图 | 大屏可视化监控,按告警等级着色,实时刷新 | +| 巡检报告 | 自动生成巡检报告,支持 AI 汇总(内置 AI 对巡检结果做自然语言总结) | +| 远程 HTTP API | 内置轻量 HTTP 服务器,支持外部系统调用巡检 API、获取告警、推送到大屏 | + +### 2.6 告警系统(v2.x 新增) + +| 功能 | 说明 | +|------|------| +| 告警规则引擎 | 指标阈值、持续时间、触发次数、告警等级(info/warning/critical) | +| 多通道通知 | Desktop 弹窗、Webhook(钉钉/企业微信/飞书/自定义) | +| 告警中心页 | 活动告警列表、历史告警、ACK 确认、关闭、备注 | +| 规则分组 | 按设备类型、分组、标签批量绑定规则 | +| **AI 预案匹配**(设计中) | 告警触发后匹配预设的"值班员动作预案 + 操作级预案"双轨配置 | +| **AI 初始响应包**(设计中) | 告警触发时 AI 自动生成结构化响应包,嵌入大屏弹窗,值班员可直接转发运维群 | +| **聚合升级**(设计中) | 时间窗口内多台设备同类型告警自动升级 | +| **AI 处置执行**(设计中) | 预案中的可执行步骤由 AI Agent 自动/半自动执行 | + +### 2.7 AI Agent 系统(核心差异化能力) + +| 能力 | 说明 | +|------|------| +| 内置 AI 对话(Catty) | 侧边栏 AI 对话面板,多厂商 LLM 接入 | +| AI 多主机编排 | 一个指令同时操作多台主机("所有核心交换机 show version") | +| AI 自动执行命令 | 三种执行权限:observer(只看不写)/ confirm(写需确认)/ auto(全自动) | +| 安全审批机制 | 危险命令自动拦截、执行前弹窗审批、审批记录审计 | +| AI 上下文感知 | 自动知道当前终端会话、当前主机、当前告警、巡检历史 | +| AI 压缩与记忆 | 长对话自动摘要压缩,413 Token 超限自动降级处理 | +| Codex App Server | 实验性 Codex 持久化运行时,支持原生审批、线程/Turn 管理 | + +### 2.8 MCP Server(Model Context Protocol) + +| 能力 | 说明 | +|------|------| +| 内置 MCP stdio 服务器 | 让 Claude Desktop / Cursor / Cline / Codex 等外部 AI 代理操作 NetMesh 连接的主机 | +| 能力暴露 | 30+ 目录命令(终端/SFTP/Vault/端口转发/巡检/片段/harness)通过统一的 RPC 分发 | +| 权限控制 | MCP 会话的 observer / confirm / auto 三级模式 | +| MCP Tool Registry | 代码生成驱动,新增能力自动暴露到 MCP | + +### 2.9 云同步 + +| 能力 | 说明 | +|------|------| +| 多后端支持 | GitHub Gist / Google Drive / OneDrive / S3 / WebDAV | +| CRDT 收敛同步 | 自研无冲突复制数据类型,支持多端并发编辑收敛 | +| 端到端加密 | 所有同步数据 AES-GCM 加密,密钥本地派生 | +| 同步范围 | 主机库 / 密钥 / 片段 / 分组 / 标签 / 设置 | +| 冲突解决 | 自动检测冲突、合并、或提示手动选择 | + +### 2.10 插件系统 + +| 能力 | 说明 | +|------|------| +| 插件包格式 | `.ncpkg` 格式,原子发布、版本化、沙箱运行 | +| 沙箱隔离 | 普通插件运行在 BrowserWindow 沙箱 + 离线网络 | +| Node-only 插件 | 高级开发模式:utilityProcess 运行、有限 Node API | +| 插件 RPC | `PluginRpcRouter` 负责请求关联、取消、超时、流量限制 | +| 插件安全 | 禁止访问本地文件系统、禁止连接外网、插件间完全隔离 | + +### 2.11 其他 + +| 能力 | 说明 | +|------|------| +| 应用锁 | Windows Hello / 系统级密码锁 | +| 主题与外观 | 明暗主题、强调色、终端主题独立配置 | +| 国际化 | 多语言框架 | +| 键盘快捷键 | 全局快捷键可自定义 | +| 数据导出/导入 | 主机库、密钥、片段 JSON 格式导入导出 | + +--- + +## 三、技术创新点 + +### 3.1 架构创新 + +**三层解耦架构(Domain → Application State → UI)** +- Domain 层是纯逻辑,零副作用(workspace 树操作、CRDT 合并、发行版归一化) +- Application State 层是状态拥有者,持久化边界清晰(~120 个 hooks,状态变更统一经过 hooks) +- UI 层纯展示,不包含业务逻辑 +- 结果:测试粒度细、复用性强、AI Agent 和 MCP Server 可以独立调用 Domain 层能力 + +**双运行时架构** +- 主进程:CommonJS `.cjs`,IPC bridge + SSH/SFTP + 插件宿主 +- 渲染层:ESM + TypeScript + React 19 + Vite 7 +- 两套模块系统分离但通过 preload API 严格对接 + +### 3.2 AI Agent Harness(最有特色的创新) + +**专为终端运维场景设计的 AI 运行时**——不是通用 ChatBot,而是一个能理解多主机、多会话、多告警上下文的 Agent 编排引擎: + +| 子系统 | 创新 | +|--------|------| +| **AgentRuntime** | Turn 生命周期管理、trace 事件分发、每 Turn 独立的 ToolOutputStore + ToolResultDedup(解决长输出工具结果重复读取的问题) | +| **上下文预算与压缩** | `contextBudget` + `compactionPruner` + `staleContextPruner` 三套机制:413 Token 超限自动压缩、过期工具结果自动裁剪、步骤间增量压缩 | +| **动态 Threshold** | 上下文预算阈值不是固定值,而是根据模型能力和会话深度动态调整 | +| **SessionState 重新注入** | AI 多轮对话中维护 session 状态(当前主机链、活跃端口转发、最近告警),每轮自动注入 system prompt | +| **Capability Tools 注册表** | 从 `electron/capabilities/catalog/` 代码生成(`npm run generate:capability-tools`),一套能力目录自动生成 Catty/MCP/CLI 三路工具暴露 | +| **白名单+权限分级** | 预置命令目录(command_catalog)+ 三种执行权限(observer/confirm/auto)+ blocked_patterns 黑名单,三重防线确保 AI 不会执行危险命令 | +| **Prompt 版本化** | System Prompt 有版本号,便于后续迭代和 A/B 测试 | + +### 3.3 MCP + CLI + RPC 三通路统一 + +一套能力目录(30+ 命令),自动生成三个暴露面: + +``` +electron/capabilities/catalog/ + codegen/toolSurfaces.cjs + │ + ├──► Catty Sidebar Tools (cattyToolSpecs.json) + ├──► MCP stdio Server (netcatty-mcp-server.cjs) + └──► netcatty-tool-cli (CLI 工具链) +``` + +**创新**:新增一个能力命令,只要在 catalog 里加一条 entry(描述、device_types、agentKinds、surfaces),三个通路自动暴露。不需要改 MCP handler、不需要写 CLI 代码、不需要改 prompt。 + +### 3.4 CRDT 收敛同步(自研) + +不同于市面上大多数"最后写入胜出"的同步方案,NetMesh 用 **CRDT(无冲突复制数据类型)** 实现多端同步: + +- 支持主机库、密钥、片段、分组等结构化数据的并发编辑收敛 +- 网络分区恢复后自动合并,不会丢数据,不会产生冲突需要手动选 +- 端到端加密 + 数据分片 + 版本向量 +- 多后端统一适配(Gist/Drive/OneDrive/S3/WebDAV) + +### 3.5 插件安全模型 + +**BrowserWindow 沙箱 + utilityProcess + RPC 路由三层隔离**: + +- 普通插件运行在 `BrowserWindow` 的沙箱 session,离线网络(只能连 `netcatty-plugin://` 协议) +- 高级 Node-only 插件运行在独立 `utilityProcess` +- 所有插件对主进程的调用必须经过 `PluginRpcRouter`(请求关联、取消、超时、流量限制、协议失败隔离) +- 插件包 `.ncpkg` 原子发布,安装时校验完整性,删除时全量清理 + +### 3.6 告警双轨预案体系(设计中) + +行业内少见的设计——预案同时包含「值班员动作流程」和「AI 操作步骤」两个层级,绑定在一个对象里: + +- **值班员动作预案(human_action_guide)**:什么时候通知谁、什么情况必须升级、处置前要做哪些防护、处置后要做哪些归档 +- **操作级预案(remediation)**:具体命令步骤,每个步骤带三级执行权限(auto/confirm/manual_only) +- **AI 初始响应包**:告警触发时 AI 自动生成结构化响应包,嵌入监控大屏弹窗,值班员一键复制转发运维群 + +--- + +## 四、AI 使用全景 + +### 4.1 AI 在系统中的定位 + +AI 不是一个"附加功能",而是系统的**核心运维能力层**。它能: + +``` +理解告警 → 匹配预案 → 生成响应包 → 自动执行安全命令 → 协助处置 → 归档总结 +``` + +### 4.2 AI 的三种入口 + +| 入口 | 面向谁 | 触发方式 | +|------|--------|----------| +| **Catty 侧边栏对话** | 所有用户 | 主动发起对话 | +| **MCP Server(外部 Agent)** | 高级用户(Claude Desktop/Cursor) | 外部 Agent 自动调用 | +| **自动响应包生成** | 值班员(被动接收) | 告警触发时系统自动生成(不需要人触发) | + +### 4.3 AI 能做什么 + +#### (1)运维执行 + +- ✅ **读操作**:show 命令、display 命令、df -h、ps aux、cat 配置文件(observer 模式自动执行) +- ✅ **写操作(需确认)**:重启服务、改配置、调阈值、采集诊断(confirm 模式弹窗审批后执行) +- ❌ **危险操作拦截**:shutdown、reboot、rm -rf /、reload(blocked_patterns 自动拦截) + +#### (2)多主机编排 + +- 一条指令同时操作 N 台主机:"所有 Linux 服务器检查磁盘使用率" +- 自动分组:"核心区的交换机" → 自动匹配 catalog_type + tier +- 聚合输出:多台主机的命令执行结果汇总成一张表 + +#### (3)巡检报告 AI 汇总 + +每轮巡检结束后,内置 AI 自动生成自然语言总结: +> "本轮巡检覆盖 23 台设备,2 台交换机 CPU 高负载(huawei_h3c_switch-A: 91%,huawei_h3c_switch-B: 88%),3 台服务器磁盘使用率超过 80%,1 台防火墙健康分偏低(62分),建议优先处理核心区交换机 CPU 告警。" + +#### (4)告警 AI 初始响应包(设计中) + +告警触发后,AI 自动生成结构化包(设备画像 + 快速 checklist + 匹配预案 + AI 推断的可能原因),直接嵌入监控大屏弹窗: +> 值班员看到弹窗 → Tab 切到"🤖 AI 响应包" → 一键复制 → 转发运维群。大家拿到完整信息,不用自己翻拓扑图、查巡检历史。 + +#### (5)预案 AI 描述生成(设计中) + +运维说一句话,AI 翻译成结构化预案草稿: +> 运维:"核心交换机 CPU 超过 90% 持续 5 分钟,先 display cpu-usage 确认,持续不降就重启核心接口" +> AI 生成:符合 device_plan schema 的 JSON 草稿 → 三重校验(schema + command_catalog 交叉 + blocked_patterns)→ 保存为 draft → 运维微调 → 启用。 + +### 4.4 AI 的安全设计 + +| 层级 | 机制 | +|------|------| +| **命令白名单** | command_catalog 目录(预置命令 ID + 设备类型 + risk_level + 审计记录) | +| **前缀匹配** | allowed_commands 正则前缀匹配(show *、display *、df -h) | +| **黑名单反查** | blocked_patterns(shutdown、reload、rm -rf /)优先级高于白名单 | +| **执行权限分级** | observer(只读自动)/ confirm(写需弹窗审批)/ auto(全自动) | +| **审批流** | Catty 的 cattyToolApproval.ts + Codex App Server 的 native 审批 + MCP 的 setupMcpApprovalBridge | +| **Trace 审计** | 每步 ToolOutput 都记录 traceStore,包含 usage / performance / tool input output | +| **输出截断与持久化** | 大输出自动截断存 preview,完整内容 spill 到 tool_output_read;跨 Turn 持久化 | +| **上下文隔离** | 每个 chat session 独立 context、独立 plan_snapshot、独立 turn_state | + +### 4.5 AI 多厂商适配 + +| 类别 | 已适配 | +|------|--------| +| 内置 SDK 集成 | MiniMax(主力 Catty Provider) | +| 外部 SDK IPC | Claude(@anthropic-ai/sdk)、Codex(@openai/codex-sdk)、Cursor、Copilot、Grok、OpenCode | +| Codex App Server | 实验性,`codex app-server --stdio` 持久化运行时 | +| Vercel AI SDK v7 | Catty 主路径,streamText + tool calling + context management | + +--- + +## 五、项目规模与工程数据 + +| 指标 | 数值 | +|------|------| +| 技术栈 | Electron 42 + React 19 + Vite 7 + TypeScript 5.9 + xterm.js 6 | +| 模块系统 | 主进程 CommonJS `.cjs` / 渲染层 ESM + TS 双轨 | +| Workspace | npm workspaces(`packages/` 插件契约/SDK/CLI) | +| 依赖 | ~100 npm 包(ssh2、ssh2-sftp-client、node-pty、Tailwind CSS 4、Radix UI、Monaco Editor、ajv、@mcp/sdk、vercel ai sdk) | +| 测试 | Node --test + tsx,domain 纯函数 / state hooks / 主进程 bridge 都有伴生测试 | +| 代码生成 | 能力目录 → MCP 工具 / Catty 工具 / CLI 三路暴露(`npm run generate:capability-tools`) | +| 跨平台 | macOS / Windows / Linux 三端 | diff --git a/electron/bridges/inspection/alertRecordStore.cjs b/electron/bridges/inspection/alertRecordStore.cjs index 40c9cde..a41d16d 100644 --- a/electron/bridges/inspection/alertRecordStore.cjs +++ b/electron/bridges/inspection/alertRecordStore.cjs @@ -116,14 +116,9 @@ function processAlert(readFn, writeFn, device, rule, metricValue, isTriggered) { _saveCounters(writeFn); } - // 有活跃告警 → 自动恢复(ACTIVE 和 ACKNOWLEDGED 都要恢复) - if (activeAlert && (activeAlert.status === ALERT_RECORD_STATUS.ACTIVE || activeAlert.status === ALERT_RECORD_STATUS.ACKNOWLEDGED)) { - activeAlert.status = ALERT_RECORD_STATUS.RESOLVED; - activeAlert.resolved_at = Date.now(); - activeAlert.resolved_reason = "auto_recover"; - _saveAlerts(writeFn); - return { ...activeAlert, action: "resolved" }; - } + // 注意:不再自动恢复告警(auto_recover 已移除)。 + // 告警一旦触发就保持 ACTIVE / ACKNOWLEDGED,必须由值班员手动 resolveAlert() 或 closeAlert() 才会关闭。 + // 原因:闪断/偶发正常会导致告警"闪了一下就没了",值班员还没来得及处理就消失了。 return null; }