dsh-console-sentinel:把跑完的控制台窗口从任务栏收走

前言

在 DSH 里跑长时间自动化任务时,任务栏经常会堆上一排 PowerShell / Python 黑窗口:Fluent 无人值守任务、批量脚本、WMI 拉起的脱离进程各占一个。这时的问题不是「没有输出」,而是分不清哪些还在跑、哪些已经用完,于是谁也不敢随手关——误关正在计算的窗口,代价比多看几个窗口大得多。

dsh-console-sentinel 处理的就是这件事:追踪这些控制台窗口,区分「在忙」和「用完了」,把用完的隐藏掉。进程不杀、日志不动、输出不丢,窗口之后还能叫回来。

这是什么

dsh-console-sentinel 是维护者 loyalchiiina 开发并维护的 DeepSeek Harness(DSH)插件,社区目录里归在 admin-security 分类,许可证为 MIT。

一句话定位:Windows 上的控制台窗口哨兵——自动隐藏(或关闭)空闲的 AI / 脚本控制台窗口。它只操作窗口,不干预进程,因此适合「任务还在跑、界面不需要留」的无人值守场景。仅限 Windows 平台。

工作原理

插件按固定节奏轮询控制台窗口,每一轮做四件事:

  1. 枚举窗口。用内嵌的零依赖 Windows PowerShell 探针(user32 + ntdll P/Invoke)按窗口类找出三类控制台:CASCADIA_HOSTING_WINDOW_CLASS(Windows Terminal)、ConsoleWindowClass(传统 conhost)、PseudoConsoleWindow(ConPTY 伪控制台)。
  2. 来源归类。优先看父进程:父进程是 WmiPrvSE.exe → wmi-detached(WMI 拉起的脱离任务,无人值守 Fluent 计算通常这样启动);父进程是 DSH Desktop.exe → dsh-host;父进程已退出 → orphaned。父链说明不了问题时改看控制台标题:脚本启动的控制台标题默认是被启动程序的路径(...\python.exe),交互式手开的控制台是提示符式标题(Windows PowerShell),归为 script-console。
  3. 判定空闲。每轮采样进程的累计 CPU 时间,低于 cpuThresholdPct(默认 1%)且持续 idleThresholdSec(默认 60 秒)即判定「用完了」。单次后台 CPU 抖动不会重置空闲时钟,由 spikeTolerance(默认 2)控制。
  4. 执行动作。对管理范围内「用完了」的窗口执行 autoAction(默认 hide,即 SW_HIDE,进程继续跑);close 则发送 WM_CLOSE。前台窗口永不自动处理(guardForeground)。

探针的父进程 PID 用 NtQueryInformationProcess 取得,而不是 CIM(Get-CimInstance Win32_Process)——参考机实测 39 秒 vs 24 毫秒(13 个进程),单次完整探针约 350 毫秒。这解释了为什么插件坚持自己内嵌探针。

安装与启用

安装命令来自项目 README:

dsh plugin --profile <name> add dsh-console-sentinel

这是一个 Bundle 插件(dsh.bundle.patch):安装后进入 profile bundle 栈,重启 DSH 后生效。patch 行在其他平台标记为 disabled,apply() 运行时也会再守一次平台限制。

运行要求:Node ^22.19.0 || >=24.0.0;peer 依赖 @deepseek-ai/cordis >=4.0.2、@deepseek-ai/dsh-tools >=0.1.5-rc.2、@deepseek-ai/schemastery >=3.18.0;当前版本 0.3.0。

模型可见的工具

插件提供 5 个工具,模型可以直接调用:

  • console_windows_list —— 列出所有被追踪的控制台窗口及其空闲状态和来源归类。先用它看现场。
  • console_window_action —— 对单个窗口执行 hide / show / minimize / restore / close,用 hwnd 或 pid 定位。hide 无损;close 可能丢失未保存输出。对前台窗口操作需传 force。
  • console_windows_sweep —— 一次性对所有空闲且在范围内的窗口执行动作。跑完一批 Fluent 任务后清任务栏很好用。
  • desktop_windows_cleanup —— 一键关闭其他窗口:关闭桌面除前台、自身、系统外壳和受保护进程以外的所有应用窗口。dryRun 先出计划;protected / keepTitle / keepPid 可临时加固保护。
  • sentinel_whitelist —— 管理持久化豁免白名单,list / add / remove / reset,kind=process(按映像名,如 code.exe)或 kind=title(按标题子串)。白名单同时作用于自动隐藏/关闭与一键关闭窗口,落盘到 ~/.dsh/console-sentinel/whitelist.json。

设置面板

从 0.3.0 起,插件在 DSH「设置」页注册「控制台哨兵」分区(客户端 bundle lib/client.js),不记工具名也能操作:

  • 概览:总窗口 / 空壳 PowerShell / 可见空壳 / 已隐藏 计数,外加「隐藏可见空壳」。
  • 任务栏窗口清理:预演 / 一键关闭其他窗口(前台、系统进程、白名单自动跳过)。
  • 控制台窗口:逐行显示进程名 / 标题 / hwnd / pid / CPU / 空闲秒数 / 子进程数,行内可直接隐藏 / 显示 / 关闭。
  • 豁免白名单:进程名与标题关键字标签式增删、清空,即时落盘。

面板通过宿主路由 /dsh-console-sentinel/* 取数,客户端 fetch 根相对路径,桌面端自动带 capability header,不使用 iframe。改 lib/client.js 后按 Ctrl+Shift+R 硬刷新;改宿主侧(lib/index.js / package.json)需要完全退出 DSH 再启动。

配置

配置写在 cordis.yml 里,常用键如下:

键 默认值 含义
enabled true 总开关
scanIntervalSec 10 扫描 + CPU 采样间隔
idleThresholdSec 60 持续低 CPU 多少秒算「用完了」
cpuThresholdPct 1 CPU 低于此值算空闲
autoAction hide none | hide | close
probeTimeoutMs 20000 探针硬超时
spikeTolerance 2 连续多少次「忙」采样才重置空闲时钟
guardForeground true 永不自动处理前台窗口
scope.wmiDetached true 管理 WMI 拉起的脱离控制台
scope.dshHost true 管理宿主派生的控制台
scope.orphaned false 管理父进程已退出的控制台
scope.scriptConsole true 管理标题是脚本可执行文件路径的控制台(Windows Terminal 承载的脚本会话)
scope.excludeTitles [] 标题 substring 黑名单
scope.emptyConsole true 把「没有任何工作子进程」的解释器控制台(PowerShell/Python/cmd 只剩 conhost)判为空壳,无论父链如何都纳入管理。这是安全清理残留空 PowerShell 的开关,不必打开整个 orphaned(后者会误伤 mpiexec/fl2610/在跑的计算)
emptyConsoleAction hide 对空壳控制台的动作:none | hide | close;独立于 autoAction,自动动作关闭也能单独生效
whitelist.processes [] 豁免进程映像名(如 code.exe),永不自动处理/一键关闭
whitelist.titles [] 豁免标题子串,永不自动处理/一键关闭

例如把空闲判定放宽到 90 秒,并让标题含 keep-alive 的窗口不受管:

- id: dsh-console-sentinel
  config:
    idleThresholdSec: 90
    scope:
      excludeTitles:
        - keep-alive

典型用法

1、先用 console_windows_list 看当前有哪些窗口、各自着急不忙、来源是哪一类。
2、对单个用完的窗口用 console_window_action hide(用 hwnd 或 pid 定位);需要它回到前台时再 action show。
3、跑完一批 Fluent 任务后,用 console_windows_sweep 一次性收走所有空闲窗口。
4、平时想让某个进程(例如 code.exe)或某个标题关键字永不被动,调用 sentinel_whitelist add;临时用桌面右下角的窗口清理时,区域外进程也由 desktop_windows_cleanup 的 protected / keepTitle / keepPid 再兜一层。

真实窗口状态不可回放,README 只给了上述操作序列,未附截图或端到端日志,实际结果建议在自己的机器上先跑一次 console_windows_list 确认归类是否符合预期。

安全性与适用场景

动作本身是克制的:

  • hide 只调用 ShowWindow(SW_HIDE),进程、日志、输出一概不动;console_window_action 的 show 可随时恢复(用 SW_SHOWNORMAL——实测 SW_SHOW 无法恢复被隐藏的 Windows Terminal 窗口)。
  • close 发送 WM_CLOSE(优雅关闭,和点 X 一样),但可能丢失未保存状态,因此从不是默认动作。
  • 自动动作绝不触碰:前台窗口、手动打开的控制台(manual 来源)、标题命中黑名单或白名单的窗口,以及 HARD_PROTECTED_PROCESSES 里的系统/计算进程(explorer、taskmgr、dsh desktop、fl2610/cx2610/mpiexec/smpd/fluent 等)。
  • 每个动作都发 console-sentinel/action 事件并写日志。

适用场景:长期无人值守跑脚本、需要保留后台计算但不想留窗口的自动化流程,以及「清理任务栏」这个收尾动作。不适合需要窗口一直可见的交互式调试——那种情况应该直接把 autoAction 设为 none,或用白名单固定住窗口。

需要说明的是,插件以当前 dsh 进程的权限运行,能枚举和操作的是这个权限范围内可见的窗口;安装前建议先检查源码与许可证(MIT),确定 scope.* 几个开关和 HARD_PROTECTED_PROCESSES 列表符合你的环境。

工程结构与测试

lib/index.js   Cordis 插件:配置、扫描调度、工具
lib/logic.js   纯台账/空闲状态机(单测覆盖)
lib/probe.js   内嵌 PowerShell 探针 + 窗口动作
tests/         仅 node 的回归测试,不需要真实 Windows

node tests/logic.test.mjs —— 24 项断言,覆盖来源归类、空闲累积、忙碌脉冲重置、范围守卫、台账 GC、排序。也就是说核心判定逻辑可以在非 Windows 机器上回归。

结尾

dsh-console-sentinel 的价值不在「又多了一个窗口管理工具」,而在于它把「这个窗口还在忙吗」这个问题固化成 CPU + 父链 + 标题的三方判定,并用 hide 而不是 kill 来做清理,给了无人值守流程一个不冒数据风险的收尾方式。

  • 目录页:https://www.skillhub.cn/plugins/loyalchiiina/dsh-console-sentinel
  • GitHub:https://github.com/loyalchiiina/dsh-console-sentinel
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜