Skip to content

dsh-memory-watchdog

Verified

dsh-memory-watchdog · v0.6.0 · MIT · Web UI

Windows commit-memory watchdog for DSH Desktop: attribution, configurable thresholds, a restart gate, read-only pagefile advice, a crash timeline and opt-in restart / crash-resume.

Install

dsh plugin add dsh-memory-watchdog

Confirm the layer applied with dsh --profile default --dump-config — see the install guide.

Source

Tags

Readme

DSH 内存守护(dsh-memory-watchdog)

Windows 版 DSH Desktop 的提交内存(commit charge)看门狗。它持续采样系统提交内存,给出谁在吃内存的归因、分页文件只读建议与最近 7 天的崩溃时间线,并在进入预警或危险区间时给出页面内提示;自动重启默认关闭,崩溃后自动续接默认关闭。它还能把 Host 进程内的 V8 堆分配按插件归因,给出每个插件的内存占用排名与泄漏风险分级。

  • 目标平台:Windows x64
  • DSH 版本:>=0.2.0-rc.1 <0.3
  • 自动重启:默认关闭(opt-in)
  • 崩溃后自动续接:默认关闭(opt-in)
  • 插件内存归因:默认开启(零开销的雷达 + 周期堆分配采样)
  • 采集方式:随插件生命周期运行的轻量 PowerShell 采集进程,只读性能计数
  • 不依赖 WMI / CIM,不安装服务、计划任务或原生组件

自动重启默认关闭

插件加载后立即开始监控和预警,但不会自动重启任何进程,直到你在 DSH 的 “设置 → 插件 → DSH Memory Guard”中打开开关。设置页会常驻显示开启后的完整代价说明,不需要展开或确认弹窗。

关闭开关会立即取消尚未开始的待执行重启;内存监控与预警继续运行。

阈值可以调(默认仍是文档值)

设置项 默认 范围 说明
warningPct 80 50–95 进入 warning 的提交内存百分比
criticalPct 90 55–99 进入 critical 的百分比,强制高于 warningPct
criticalAvailMb 2048 256–32768 可用 commit 低于该值时也判 critical
confirmSamples 3 1–10 状态切换所需的连续样本数
cooldownMinutes 30 5–1440 两次重启之间的最小间隔
restartGatePct 20 0–100 重启门限;0 表示关闭该判定
pluginMemory true 开关 插件内存雷达与插件视图
pluginSampling true 开关 是否按周期自动做堆分配采样
pluginSampleMinutes 15 5–120 周期采样的间隔(分钟)
pluginSampleSeconds 20 5–120 每次采样的窗口长度(秒)
pluginLeakMb 32 8–512 判 high 的每小时增长阈值(MiB),medium 取其 40%

这些字段都是 volatile 设置,改完立即生效,不需要重启 DSH;超出范围的输入会被夹到边界值,criticalPct 永远比 warningPct 高。危险百分比另有绝对兜底:达到 95% 时无论可用量多少都算 critical。

它做什么

  • 每 5 秒读取一次 Windows 提交内存已用量、提交上限、物理内存总量与可用量。

  • 使用连续样本确认状态(默认 3 个),避免单次尖峰误判;使用迟滞避免在阈值附近反复切换:

    状态 进入条件(默认连续 3 个样本) 退出条件
    normal 从 unknown:连续 3 个有效样本且 <75% —
    warning >=80% 或 可用 commit <=6 GiB <75% 回 normal
    critical >=90% 且可用 <=2 GiB,或 >=95% <85% 回 warning
    unknown 数据缺失、无效或样本超过 60 秒 连续 3 个有效样本按区间离开:<75% 回 normal,热区间进 warning / critical
  • 每 30 秒做一次提交内存归因,列出 DSH 进程树占比与占用最高的进程。

  • 每 5 分钟读取一次分页文件与提交上限配置,给出只读建议。

  • 每 10 分钟汇总一次最近 7 天的崩溃与内存事件时间线(DSH 崩溃日志 + Windows 系统日志)。

  • 持续统计每个插件注册的定时器与监听器(零采样开销);采样开启后每 15 分钟抓一段 20 秒的堆分配窗口,按 node_modules/<包名> 排名,并给出每小时增长与泄漏风险分级;面板可手动采样、导出 .heapprofile 或写一份堆快照。

  • 保留最近 50 条事件历史,可在面板查看并一键导出 JSON;另有“复制诊断信息”按钮。

  • 在页面内显示当前状态、动作状态、commit 数值、可用 commit、物理内存、Host RSS、冷却剩余时间、最近错误和最近一次重启记录。

  • warning / critical / 恢复 / 采集异常 / 重启结果 / 设置变更通过页面内 toast 提示;右下角常驻一个状态胶囊,点击胶囊就地展开摘要浮层(压力百分比与已提交/上限、当前状态与下一步动作、自动重启能力、活动检测、最近事件与错误、DSH 占比、重启门限结论、占用最高的三个进程、插件内存汇总与前五个插件),再点一次、按 Esc 或点浮层外部收起;浮层里的数据与设置页卡片同源,底部另有一个「刷新」按钮可立刻重新取一次状态。

  • 采集抖动不打扰:因为样本没送到而进入 unknown 时,提示延迟 2 分钟才弹;这 2 分钟内样本恢复,就只在事件里留两条记录、面板记一个「采样延迟 N 次」计数(摘要浮层与诊断文本里可见,含最大滞后时长),不弹任何 toast。采集器真的停了(非样本延迟导致的 unknown)仍然立刻提示。

  • 插件重启后仍会显示冷却状态;冷却记录保存在本机。

提交内存归因与重启门限

  • 归因使用一次 CreateToolhelp32Snapshot 进程枚举 + 每进程 GetProcessMemoryInfo(PrivateUsage), 分母取系统 commit 已用量;只读,不读取其他进程的内存内容,不使用 WMI/CIM。本机一轮约 1.9 秒(含 PowerShell 启动)。
  • 面板给出 DSH 进程树的进程数、合计 commit、占系统提交的比例,以及 Top 5 进程(进程名 + PID + commit)。
  • 重启门限:默认只有 DSH 进程树占到提交内存的 20% 以上才允许自动重启。占比不足、归因数据缺失或超过 60 秒过期时一律不重启(fail closed),并在面板与 toast 说明原因;每个 critical episode 只会提示一次,不会刷屏。把 restartGatePct 设为 0 可以关闭该判定。

分页文件建议(只读)

  • 读取注册表 Session Manager\Memory Management 的 PagingFiles / ExistingPageFiles、分页文件实际大小,以及 GetPerformanceInfo 的提交上限与物理内存。
  • 提示项:没有分页文件、提交上限只比物理内存多不到 2 GiB、分页文件全部落在系统盘(内存 ≥16 GiB 时)、系统自动管理。
  • 插件不会修改任何系统设置,也不会代你在 Windows 虚拟内存对话框里点确认;调整分页文件需要你手动操作并重启生效。

崩溃时间线

  • 汇总 %APPDATA%\@deepseek-ai\dsh-desktop\logs\crash-*.log(取 --- error --- 段首行)与系统日志中的 2004(虚拟内存耗尽)、26(低虚拟内存提示)、41(意外关机)事件,默认窗口 7 天、最多 20 条。
  • 同时读 Windows 应用日志里的 1000/1001/1002(应用崩溃 / 无响应),从中解析故障模块、异常码与 fault bucket:时间线条目后面会带 [模块名],标题行显示「应用故障 N 次」。故障模块只取文件名(例如 node.exe),正文里的其余字段按 120 字符截断。
  • 同一次事故产生的多份日志(main + renderer + web-boot)合并成一条,优先级 OOM > 应用故障 > host > main > renderer > 应用无响应 > web-boot。
  • 只读本机文件,不上传任何数据。日志正文可能包含本机路径,面板只显示错误首行,导出的诊断文本不含日志正文与会话完整 id。

崩溃后自动续接(默认关闭)

开启 resumeAfterCrash 后,插件会在 DSH 重启后扫描会话,对被中断的对话注入一条“先核对当前状态,再从中断处继续”的提示:

  • 只认 turn/end 的 reason.kind === 'interrupted';你手动停止的 aborted 永不续接。
  • 只处理 12 小时内有过人类提示词、当前未在运行、非空白的会话;距中断需静置 20 秒,避开刚打开会话时的写入竞争。
  • 每个会话每小时最多 2 次尝试;超过 1 小时没有再续就把计数归零。
  • 子代理被打断时,父会话即使自己已经 completed 也会被唤醒一次,并把该子代理标记为已处理,避免僵尸子代理反复唤醒父会话。
  • 注入用的 requestId 形如 memory-watchdog-resume-<sessionId>-<turn>[-child],同一轮同一来源重复扫描不会二次注入。
  • 启动后按 20 秒 / 60 秒 / 180 秒 / 600 秒各扫一轮,被静置期推迟的会话按到期时间自动重排;面板也可以手动“立即扫描”。
  • 账本保存在 $DSH_HOME/memory-watchdog/resume.json,面板展示会话短 id、轮次、来源与尝试次数。
  • 续接的 turn 使用该会话原有的工具与权限运行——这是开启该开关前最需要权衡的一点。

插件内存(按插件归因与泄漏判断)

所有 host 插件跑在同一个 V8 isolate 里,Node 不按模块记账,所以这里给的不是「每个插件的 RSS」,而是两种能解释的信号:分配归因与驻留趋势。表格的底稿是当前 profile 的插件清单:启动时扫 node_modules 下所有 package.json 带 dsh 字段的包(@scope/ 也算),每个插件先占一行并带上识别到的版本,所以即使还没采样也能看见装了什么;采样窗口到达后再填字节数、占比与增长。装到别的 profile 或全局目录的插件不在清单里。

  • 雷达(默认开,零采样开销):包装 setInterval/clearInterval 与 EventEmitter 的 on/once/addListener/removeListener/off/removeAllListeners,用注册栈把每个定时器和监听器记到直接调用者所属的包名下。归属按「已安装插件目录」做最长前缀匹配,本插件自己的帧、node: 内置以及框架/本地脚本的帧直接跳过而不是算到调用方头上(早期版本按「第一个 app 帧」归属,每写一行日志会被算成几个监听器泄漏,已修)。一次都没归因成功时面板会告警,并显示「已归因 N 次 / 丢弃 M 次」。卸载时完整还原全局函数。
  • 周期采样(默认开):每 pluginSampleMinutes 分钟用 HeapProfiler.startSampling(samplingInterval 4096)抓 pluginSampleSeconds 秒窗口,只保留结束时仍然存活的分配;按采样栈里最近的 JS 帧 URL 归到 node_modules/<包名>(含 @scope/pkg、app.asar/dsh/<pkg>、.dsh-src/<pkg>),没有 JS 帧的 native 字节单独计一栏,不摊给任何插件。启动约 45 秒后会先跑一次基线采样,之后按周期进行;窗口历史保留 48 个(默认 15 分钟一轮 ⇒ 约 12 小时的趋势)。
  • 风险分级:窗口跨度不足 10 分钟时只给 unknown,不做结论;足够长时按最小二乘算每小时字节增长,达到 pluginLeakMb 判 high、达到其 40% 判 medium;定时器+监听器总量增量达到 5 也升 medium。high/medium 会列出判定理由(bytes-growth / handle-growth / short-span / not-enough-data),high 时卡片直接建议「只重载该插件」。
  • 分配点下钻:风险为 high/medium 的插件会列出前三个热点分配点,形如 lib/xxx.js:123 · grow · 4.2 MiB——直接给出文件和行号,而不是只说「这个包在涨」。分配点来自采样栈的 url:line 去重累加,node: 内置帧没有文件行号,显示为 —。
  • 采样前强制回收:每个窗口在 stopSampling 之前调用一次 HeapProfiler.collectGarbage,把本次窗口里的短命垃圾清掉再聚合,因此「增长」只算真正活下来的对象。面板会显示上次回收的字节数与耗时(例如「采样前强制 GC 回收 6.3 MiB(55 ms)」)。
  • 首次注册时刻:雷达第一次看到某个包注册定时器或监听器时会记一个时间戳,配合 process.uptime() 反推的宿主启动时刻算出「启动后多久首次注册」,显示在插件行下面,时间早的排前面。这是首次可见注册时刻,不是精确加载耗时——一个插件如果在启动后很久才注册第一个定时器,它的数字就是那个「很久」,而不是它被 require 的耗时。
  • 三个按钮:「采样一次」立刻抓一个窗口;「导出堆采样」把上一次完整 profile 存成 .heapprofile(Chrome DevTools 的 Memory 面板可打开);「堆快照」用 v8.writeHeapSnapshot 写一份 .heapsnapshot(会短暂停顿 Host,面板会提示耗时)。快照只保留最近 2 份。旁边还有「下载诊断包」,见下面「诊断包」一节。
  • 改完即生效:五个开关都是 volatile 设置,不需要重启 DSH;pluginMemory 关掉后雷达会完整还原,采样也不再运行。
  • 热重载 A/B(0.5.0):雷达发现某插件的定时器与监听器从有变无(在插件管理器里停用,或开发时热重载)就记一笔,等它重新出现再比对字节,显示「重载 N 次」与每条的 保留字节差 +8.0 MiB(40.0 MiB → 48.0 MiB)。重载后字节回到原值说明这次重载是干净的,越重载越大则是该插件在重载路径上漏了东西——这是「该重载还是该重启」最直接的证据。

长期趋势(14 天)

  • 每次采样除了写黑匣子,还按本地时间丢进小时桶:n / sum / max / 一份 2% 宽的定长直方图 / 动作与预警计数。直方图让 p50 与 p95 能算出来,而磁盘上不留任何原始样本——这是它敢保留 14 天的原因。
  • $DSH_HOME/memory-watchdog/trend.json 每 10 分钟滚动写一次(一秒一 tick 显然不能每次都重写整个文件),原子写 tmp + rename。崩溃最多丢最后十分钟,不是丢整个文件。
  • 面板的「长期趋势」区显示最近 7 天:每天一行,用 ShareRow 画当天最高占用率与当天动作次数(≥80% 标黄、≥90% 标红),不引第三方图表库。上面一行摘要写「近 14 天 · 采样 N 点 · 最高 X%」。
  • 过期桶按「今天零点往前 13 天」裁剪,所以保留窗口是滚动的,不是从启动算的。
  • 一个桶的直方图如果丢了(文件被手改、旧版本写的),整桶按无效丢弃而不是读成 0——否则趋势线会被静默压平,看起来像「那天很空闲」。
  • 时间分桶跟本地钟走:UTC+05:30 的机器也得是一小时一桶,不能按 UTC 切。

诊断包(一键下载)

  • 面板右下「下载诊断包」按钮打出一个 JSON 附件,文件名形如 dsh-memory-watchdog-diagnostics-2026-10-30T15-04-11-000Z.json。内容是状态摘要、最近 50 条事件、trend.json、plugin-memory.json、blackbox.json 与 capability.json。
  • 不含堆采样(.heapprofile)、堆快照(.heapsnapshot)与任何日志正文。堆文件里是原始堆内容,再怎么脱敏都不该外发——包里有一个 bundle.excluded 字段把这条明写出来,省得别人猜为什么缺东西。
  • 打包前整个 payload 过一遍 lib/redact.js:C:\Users\<name>、/Users/<name>、/home/<name> 一律替换成 ~,session id 只留前 8 位加省略号。这是唯一会把本机信息带出去的通道,所以脱敏规则有独立测试(test/redact.test.js),preflight 也会在 lib/bundle.js 不再调用 redactValue 时直接失败。
  • 缺文件不算失败:没写过的 trend.json 会在包里记成 { ok: false, error: "not written yet" },其余内容照常给你。
  • 走 GET /api/memory-watchdog.bundle,响应带 content-disposition: attachment,浏览器直接存盘而不是渲染。没有引入压缩依赖,就是一个可读的 JSON。

黑匣子(上次运行最后 60 秒)

  • 每 4 秒把一行占用率、RSS、堆用量与压力状态写进 $DSH_HOME/memory-watchdog/blackbox.json,只留最近 12 个点(约 48 秒)。
  • 下次启动读到 pid 不同的文件就把它当作上一次运行的尾部轨迹,在「崩溃与内存事件」区显示「上次运行最后 60 秒」,逐行形如 17:20:41 · 91.2% · RSS 1.8 GiB · 堆 420 MiB · critical。占用率 ≥90% 标红、≥80% 标黄。
  • 同一个 pid 写下的文件(插件热重载)不算崩溃,直接忽略。
  • 写入是原子的(tmp + rename),节流 4 秒一次,正常开销可以忽略;磁盘上只留一个几百字节的小文件。

运行时信号

  • 进程警告计数:按 warning.name 聚合,MaxListenersExceededWarning 这类「越滚越多」的警告会在面板上显示总数与前三个名字。只计数,不拦截。
  • 活动句柄:每 5 秒取一次 process.getActiveResourcesInfo(),显示总数、最近一分钟变化量(带符号)与前几种类型(Timeout / TCPSocketWrap 等)。
  • 事件循环延迟:用 monitorEventLoopDelay(分辨率 20 ms)每 5 秒读一次直方图再重置,显示 p99 / 均值 / 峰值——DSH 卡顿时可以直接看出是内存压力还是事件循环被堵住。
  • 未捕获异常只记 uncaughtExceptionMonitor 的计数与摘要;刻意不监听 unhandledRejection,因为加这个监听器会改变 Node 的默认致命行为,把「本该崩」变成「不崩」。

自动重启如何决定

自动重启只有在以下条件同时满足时才会开始:

  1. 开关已由用户开启;
  2. 压力状态为连续确认的 critical,且交接前样本仍然新鲜;
  3. 不在冷却期内(默认 30 分钟),且当前 critical episode 尚未尝试过重启;
  4. 重启门限通过(DSH 进程树占比达标,或门限已设为 0);
  5. 活动检测明确确认空闲;
  6. 当前平台与 DSH 版本受支持;
  7. helper 能力自检已通过;
  8. 用户没有取消本次待执行动作。

活动检测会检查运行中的 agent、待处理队列(nextTurn / nextStep)、以及全局和各 agent 作用域下状态为 running / stopping 的 job。活动 API 缺失、报错或返回结构不可解释时,一律按“未确认空闲”处理。

确认空闲需要连续 3 次检查(间隔 1 秒),之后还有 1.5 秒宽限期;宽限期内出现新任务会退回等待。任务忙碌时不会强制重启,等待提醒最多每 5 分钟一次。

整个重启由两阶段交接完成:helper 先校验 Host / Electron 主进程的 executable、创建时间与父子关系,写 verified 后等待 Host 的 go;Host 在真正交接前再次检查全部条件(包括重启门限的复评)。未收到 go(20 秒超时)、Host 提前退出或用户取消时,helper 自行退出,不结束任何进程。

开启前请确认(重要代价)

  • 该开关会重启整个 DSH Desktop(Electron 主进程及其全部子进程),不是只刷新界面或重载插件。
  • 重启可能丢失未发送的草稿。
  • 交接会绕过 Electron 壳的原生退出确认框;profile 与会话数据仍由 Host 的优雅 shutdown 落盘,但界面不会再次询问。
  • 若提交内存压力来自其他软件,重启可能无效(重启门限就是为此而设)。
  • 冷却期内(默认 30 分钟)最多重启一次;每个持续 critical episode 最多尝试一次。失败同样进入冷却,不会自动重试风暴。
  • 重启前会等待旧进程退出(最长 10 秒)与端口释放(最长 10 秒);旧实例未退出或端口未释放时,本次重启记为失败并不再拉起新实例,避免双实例或静默失败。
  • 旧实例退出后最多等待 30 秒让 commit 回落;超时仍会拉起新实例,此时可能很快再次触发。新实例必须在 3 秒启动观察期后、15 秒内重新监听原端口,否则本次重启记为失败(新进程不会被自动结束)。
  • 重启过程可能持续数十秒,期间 DSH Desktop 不可用。
  • 开启崩溃续接后,插件会以你的名义向会话注入消息并让 agent 继续执行;续接的 turn 拥有该会话原有的工具与权限。

插件不承诺防止 OOM、闪退或数据丢失,也不承诺定位到对象级的泄漏根因;插件内存视图只给出按包名的分配归因与趋势分级。它不是独立于 DSH 的系统级看门狗。

权限与进程行为

  • 采集使用固定系统路径的 Windows PowerShell,隐藏窗口运行;每次调用只使用进程级 -ExecutionPolicy Bypass,不修改机器或用户的持久执行策略。
  • 四个 PowerShell 资源都是只读的:collector.ps1(性能计数)、top.ps1(进程 commit 归因)、system-info.ps1(分页文件与提交上限)、crash-history.ps1(崩溃日志 + Get-WinEvent),全部不使用 WMI/CIM/WMIC。
  • 能力自检与交接前检查会读取目标进程的可执行文件路径、创建时间和命令行,并验证 Host 与 Electron 主进程的父子关系。
  • 重启时只处理已校验身份的 Electron 主进程、Host,以及事先记录的、executable 相同的子进程;必要时先挂起,再在超时后结束。不使用 taskkill /IM ... /T /F,不按内存占用选择或结束无关进程。
  • 崩溃续接只调用 DSH 的 sessionController list / inspect / prompt(mode: 'queue');不调用任何进程创建 API,也不写会话日志以外的东西。
  • 插件内存采样只在本进程内用 node:inspector 的 HeapProfiler 读分配栈,不 attach 外部进程、不开调试端口;导出的 profile 与快照只写到 $DSH_HOME/memory-watchdog/。
  • 插件只在 $DSH_HOME/memory-watchdog/(默认 ~/.dsh/memory-watchdog/)下读写状态、事件、能力自检、续接账本和交接文件。
  • 状态、事件、取消与续接接口通过 DSH 带认证的 ctx.connection.fetch 注册,响应禁止缓存;客户端不能传入 PID、executable、命令行、脚本路径或 helper 参数,也不能改配置。
  • 不发起任何网络请求,不上传遥测或诊断数据。

资源开销

  • 常驻采集 PowerShell 进程实测工作集约 62–70 MB、commit 约 49 MB;每 5 秒采样一次,单次采集约 7 ms。
  • 归因一轮约 1.9 s(每 30 秒一次),分页信息约 1.8 s(每 5 分钟一次),崩溃时间线约 1.6 s(每 10 分钟一次);三者都是短命进程,用完即退,不常驻。
  • helper 只在真正交接时启动,不常驻。
  • 插件内存雷达是纯 JS 计数,几乎没有额外开销;堆分配采样只在窗口内记录、窗口结束聚合一次,开销随分配速率变化。写 .heapsnapshot 会让 Host 停顿数百毫秒到数秒(取决于堆大小),面板按钮会先提示。

通知边界

DSH 当前没有向插件暴露系统级通知或托盘 API,因此通知只存在于页面内(toast 与常驻胶囊),不承诺系统级通知。如果 renderer 已经崩溃或页面未打开,页面提示不可用;此时依赖 $DSH_HOME/memory-watchdog/ 下的事件、崩溃时间线和最近重启记录,下次加载时展示。

已知边界

  • Host 完全卡死或 OOM 时,插件自身无法继续执行,这是不可消除的边界。
  • renderer 先于 Host 退出时,页面通知不可用。
  • 归因只能读到有权限打开的进程(本机约 320 个进程里 197 个可读),DSH 占比按系统 commit 已用量计算,因此是下界估计。
  • 崩溃续接无法区分“中断前那个 turn 已经做完一半”,因此注入文本要求先核对状态;这降低了风险但不是零风险。
  • 活动检测能降低误重启概率,但不消除所有并发时序竞争。
  • 插件内存采样只看窗口内分配、且结束时仍然存活的对象——它是「这段时间谁在涨」的证据,不是插件的总驻留量;GC 之前的短命分配不会出现,native 字节也没有归属。分配点同理:(native) 帧没有 JS 文件和行号,只能按最近的 JS 调用者归档,所以热点行显示为 — 时说明这段内存不是某个 JS 行分配的。
  • 渲染进程里的 client 插件在另一个进程,host 侧的 inspector 够不着,不在插件内存视图范围内;面板里那一栏只给 Host 进程的总量。
  • 黑匣子的粒度是 4 秒一个点、只留最近约 48 秒,所以它说明「崩溃前的走势」,不能当作完整的时序监控;进程被强杀时最后一个点最多缺失 4 秒。
  • 「运行时信号」里的句柄与事件循环数据只在本进程活着时有效,进程重启后从零开始;进程警告与未捕获异常只计数不拦截,因此不能用来「防止崩溃」。
  • 不同 Windows / DSH 启动方式可能改变 Job 标志;helper 自检发现自己位于 Job 内时不再一律停用,而是用两个立刻自行退出的空转子进程实测「新建进程能否脱离 Job」:能脱离就继续提供自动重启(面板标注脱离方式),不能脱离才失败关闭,全程不结束任何进程。换启动方式(任务栏 / 资源管理器)只在「这个 Job 是终端或 agent 带进来的」时才有效——本机实测 DSH 自己就会给进程树建一个 Job,此时换启动方式无效。
  • 真实环境中的重启、不同启动方式与长期稳定性仍需按发布检查清单单独验证。

安装与卸载

从 DSH Market 安装本插件,或使用 DSH 的插件安装能力安装构建好的 npm tarball。安装后无需另行安装服务或运行构建脚本。

卸载时插件会清理自己的定时器、取消待执行动作并停止采集子进程。$DSH_HOME/memory-watchdog/ 下的历史记录不会自动删除,可在确认不再需要后手动删除。不要在重启交接已经开始时卸载插件:helper 已独立运行,可能仍会完成本次重启。

开发

npm test          # node:test 单元与集成测试
npm run preflight # 包内容与安全规则检查
npm pack          # 生成不要求消费者构建的 tarball

源码为 ESM JavaScript、PowerShell 和浏览器端 client bundle;不包含 TypeScript 编译步骤、原生 addon 或安装脚本。

数据文件

文件 用途
state.json 持久冷却与最近尝试信息
last-event.json 最近一次压力 / 动作事件
events.json 最近 50 条事件历史(面板与导出用)
last-restart.json 最近一次重启结果(启动时展示)
capability.json 最近一次 helper 能力自检
resume.json 崩溃续接账本(尝试次数、已处理子代理、不可读会话)
plugin-memory.json 插件内存账本(窗口序列、风险判定、热重载 A/B、采样元信息)
blackbox.json 黑匣子:当前运行最近 12 个压力采样(下次启动当作上次运行的尾部轨迹)
heap-<time>.heapprofile 「导出堆采样」保存的分配 profile
heap-<time>.heapsnapshot 「堆快照」保存的 V8 堆快照(保留最近 2 份)
handoff/<id>/ 两阶段交接标记与结果

许可证

MIT,见 LICENSE。