Files
SenMeshNet/electron/bridges/inspection/planTemplateStore.cjs
zhaolei a5744e720b
Some checks failed
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
feat(plan-management): implement alert-remediation-plan system v1.3
- 8 new store modules + matcher + initialResponse + aggregation + remediation + AlertStateMonitor + planGenerator

- alert chain auto-integrated after runInspection: freeze snapshot + generate response + real-time agg + auto-start monitor

- AlertAIPanel component + MonitoringDetailPanel expandable alert list

- PlanManagementPage: full page with list/edit/AI generate/templates/commands
2026-10-30 16:55:55 +08:00

172 lines
5.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use strict";
/**
* 预案模板 CRUD(方案 D7:模板不含匹配条件/双轨步骤,只含公共联动配置)
*
* 模板结构详见设计方案 §4.2
*/
const { STORAGE_KEY_PLAN_TEMPLATES } = require("./storageKeys.cjs");
const { ALERT_LEVELS } = require("./types.cjs");
let _templates = null;
function _ensureLoaded(readFn) {
if (_templates === null) {
const raw = readFn(STORAGE_KEY_PLAN_TEMPLATES);
_templates = raw ? _safeParse(raw, []) : _getDefaultTemplates();
}
}
function _safeParse(text, def) {
if (text === null || text === undefined) return def;
if (typeof text === "object") return text;
try { return JSON.parse(text); }
catch { return def; }
}
function _save(writeFn) {
writeFn(STORAGE_KEY_PLAN_TEMPLATES, JSON.stringify(_templates));
}
function _getDefaultTemplates() {
const now = Date.now();
return [
{
id: "tpl_level3_critical",
name: "三级预案模板(严重)",
level: ALERT_LEVELS.CRITICAL,
builtin: true,
description: "严重级别告警的公共配置:大屏红色闪烁 + 10 分钟自动升级 + 处置需确认",
display: { color: "#ef4444", icon: "alert-octagon", blink: true, sound: "builtin_alarm" },
notification: {
channels: ["desktop", "webhook"],
recipients: [{ type: "webhook", target: "" }],
repeat_interval_minutes: 5,
max_repeats: 12,
},
escalation_fallback: {
auto_escalate_minutes: 30,
escalation_target_level: ALERT_LEVELS.CRITICAL,
},
remediation_defaults: {
require_confirmation: true,
auto_close_after_remediation_recovery: true,
execution_timeout_sec: 120,
},
created_at: now,
updated_at: now,
},
{
id: "tpl_level2_warning",
name: "二级预案模板(警告)",
level: ALERT_LEVELS.WARNING,
builtin: true,
description: "警告级别告警的公共配置:大屏橙色提示 + 60 分钟自动升级",
display: { color: "#f97316", icon: "alert-triangle", blink: false, sound: null },
notification: {
channels: ["desktop"],
recipients: [],
repeat_interval_minutes: 10,
max_repeats: 6,
},
escalation_fallback: {
auto_escalate_minutes: 60,
escalation_target_level: ALERT_LEVELS.WARNING,
},
remediation_defaults: {
require_confirmation: false,
auto_close_after_remediation_recovery: true,
execution_timeout_sec: 120,
},
created_at: now,
updated_at: now,
},
{
id: "tpl_level1_info",
name: "一级预案模板(提示)",
level: ALERT_LEVELS.INFO,
builtin: true,
description: "提示级别告警的公共配置:大屏蓝色静态展示",
display: { color: "#3b82f6", icon: "info", blink: false, sound: null },
notification: {
channels: ["desktop"],
recipients: [],
repeat_interval_minutes: 0,
max_repeats: 1,
},
escalation_fallback: null,
remediation_defaults: {
require_confirmation: false,
auto_close_after_remediation_recovery: true,
execution_timeout_sec: 120,
},
created_at: now,
updated_at: now,
},
];
}
// ---------- CRUD ----------
function listTemplates(readFn) {
_ensureLoaded(readFn);
return [..._templates];
}
function getTemplate(readFn, templateId) {
_ensureLoaded(readFn);
return _templates.find((t) => t.id === templateId) || null;
}
function createTemplate(readFn, writeFn, data) {
_ensureLoaded(readFn);
const tpl = {
id: data.id || `tpl_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
name: data.name,
level: data.level || ALERT_LEVELS.WARNING,
builtin: false,
description: data.description || "",
display: data.display || { color: "#f97316", icon: "alert-triangle", blink: false, sound: null },
notification: data.notification || { channels: ["desktop"], recipients: [], repeat_interval_minutes: 10, max_repeats: 6 },
escalation_fallback: data.escalation_fallback || null,
remediation_defaults: data.remediation_defaults || { require_confirmation: true, auto_close_after_remediation_recovery: true, execution_timeout_sec: 120 },
created_at: Date.now(),
updated_at: Date.now(),
};
_templates.push(tpl);
_save(writeFn);
return { ...tpl };
}
function updateTemplate(readFn, writeFn, templateId, updates) {
_ensureLoaded(readFn);
const idx = _templates.findIndex((t) => t.id === templateId);
if (idx === -1) return null;
if (_templates[idx].builtin) return null; // 内置模板不可改
_templates[idx] = { ..._templates[idx], ...updates, updated_at: Date.now() };
_save(writeFn);
return { ..._templates[idx] };
}
function deleteTemplate(readFn, writeFn, templateId) {
_ensureLoaded(readFn);
const idx = _templates.findIndex((t) => t.id === templateId);
if (idx === -1) return false;
if (_templates[idx].builtin) return false; // 内置模板不可删
_templates.splice(idx, 1);
_save(writeFn);
return true;
}
function _resetForTest() { _templates = null; }
module.exports = {
listTemplates,
getTemplate,
createTemplate,
updateTemplate,
deleteTemplate,
_resetForTest,
};