dsh-incident-studio:把屏幕帧、日志行和键鼠输入对齐到同一条毫秒时间轴

前言

做智能体(Agent)开发时,一类问题反复出现:你在真实界面上复现了故障,Agent 却只能拿到你打的一段描述和一份日志。画面上很明显的 bug,在几百行日志里无从定位;而「我当时按了什么」只有你自己记得。手动贴截图、截动图、翻日志,拼出来的证据常常缺一角。

dsh-incident-studio(插件名 dsh-incident-studio,维护者 Eclipse-NotFound,分类「工作流」)就是为这件事做的 DSH 插件。它把屏幕画面、日志行、键鼠输入放在同一条毫秒时间轴上,录完打点、圈选区间、拖框标注、写一句话,然后一键把关键帧条带、动图、对齐后的日志切片和描述填进 composer 交给 Agent。

它不绑定任何游戏或项目:日志源是配置出来的,任何会写文件的程序都能接,程序也可以用 HTTP 接口直接推事件。

核心功能

插件在录制期间同步采集四类证据,共用一套墙钟时间:

证据 来源 精度
画面 宿主抓帧(三条路径,见下文) 默认 6 fps,每帧带墙钟时间
事件 日志文件跟随 + 打点 + HTTP 推送 行写入时刻,约几十毫秒;推送可带精确时间
键鼠 轮询助手(仅目标程序在前台时) 约 30 Hz,误差 ±1 个采样间隔
你的描述 画面上的标注框 + 一句话 挂在选中的区间上

交付给 Agent 的每一行日志都带 [00:12.340] 形式的相对时间戳,与图像帧、按键事件同源,Agent 不需要猜是哪一行、也不用猜你当时按了什么。

录制结束后你把内容交给 Agent 的方式是「产物 + 紧凑纪要」:现象、区间、产物路径、标注说明、键鼠统计,以及最多 80 行日志(错误行与打点优先保留,打点行附带「前一条输入」);完整记录在 bundle.md 里。

安装与启用

要求 DeepSeek Harness 0.2.1+(package.json 中写 engines.dsh 为 >=0.2.1-rc.1 <0.3.0)。插件包内 client.js 已经随仓库提交,无需构建。

# 从仓库直接安装(client.js 已随仓库提交,无需构建)
dsh plugin --profile <profile> add https://github.com/Eclipse-NotFound/dsh-incident-studio

桌面端的 profile 由应用自己管理:在 设置 → 插件 里按仓库地址安装。README 特别提醒不要把 CLI 装进 profiles/web,那样不会出现在桌面端。装完需要重启一次才会加载宿主半侧;浏览器半侧随宿主发布,页面会热更新重跑。

停用方式有两种:

# 在 dsh.profile.bundles 里删掉 dsh-incident-studio,或在 profile 的 patch 里加:
- id: incident-studio
  disabled: true

使用流程

面板入口是右侧栏的 +(引导页「Incident Studio」),或 composer 下方的 🎥 Capture 按钮。首次挂载会自己打开一次并记在 localStorage。

1、配置日志源(只需一次):面板 → 设置 → 填日志文件的绝对路径或相对工作区路径。文件可以晚于录制开始出现,先开录制再启动程序也能接上。同一页面填目标进程名(例如 Remains),键鼠记录才知道该在哪个窗口前台时记录。

2、录制:选采集源 →「● Start recording」。出问题时按「⚑ Mark」,可以打多次;打点会自动记下问题出现前你最后按下的那个键。

3、复看与标注:默认区间是最后一次打点 ±3 秒。拖动播放头时日志列表同步定位;点日志行跳回对应画面。Input 区块能展开区间内每一次按键/点击,点击单条同样 seek。在画面上拖出红框,每个框都可以写一句说明。

4、交付:Build artifacts → Fill composer。附件默认带关键帧条带,GIF 可选;确认后回车发送,或直接点 Send now。

产物落盘位置

产物写进当前会话工作区的 .dsh-incidents/<recording-id>/:

.dsh-incidents/20261104-193045-a1b2c3/
  frames-20261104193045.png   6 帧横向条带,带时间戳与红框
  clip-20261104193045.gif     区间动图(460 px 宽)
  input.jsonl                 原始键鼠事件,每行一个 JSON
  bundle.md                   完整纪要:描述、标注坐标、全部事件行、输入记录
  bundle.json                 同上的机器可读版

程序侧:HTTP 推送接口

除了跟随日志文件,本机进程(模组、测试脚本、dev server)可以直接推事件:

curl -X POST http://127.0.0.1:<dsh端口>/dsh-incident-studio/api/ingest \
  -H "content-type: application/json" \
  -H "x-incident-token: <面板设置里显示的令牌>" \
  -d '{"text":"进入 raiders 房间","src":"RConnect","level":"info"}'

x-incident-token 每进程一个,在面板设置里可见;同源面板自己推送不需要令牌。请求体带 wall(epoch 毫秒)时按你给的时间入轴,否则用收到时刻。

三条采集路径

插件按宿主进程能力选路径,三条路的产物都是「带墙钟时间的帧」,后续标注、导出、交付完全一致:

宿主进程能拿到什么 走哪条 说明
electron.desktopCapturer 定时抓 JPEG 默认 6 fps / 960 px / q62,可以按窗口选源
只有 Node(Electron utility 进程 / 纯 dsh web) Windows GDI 抓屏助手 tools/grab-frames.ps1 整个虚拟桌面;长驻 PowerShell 写 JPEG,主机收帧后删临时文件
真实浏览器打开 dsh web getDisplayMedia + MediaRecorder 需要屏幕共享授权,停录后本地抽帧

README 注明一个实测结论:DSH 桌面宿主拿不到 desktopCapturer(/state 里 nativeReason: "desktopCapturer 不可用"),桌面端实际走 GDI。GDI 用 System.Drawing + Graphics.CopyFromScreen,320 px / 4 fps 时单帧约 5 KB。代价是无法选单个窗口。帧缓冲默认上限 900 帧 / 96 MB / 5 分钟,超出丢最早的帧。

键鼠记录的取舍

tools/record-input.ps1 是长驻助手,每 20 ms 读一次 GetAsyncKeyState,只写变化。设计上刻意不装键盘钩子、不做键位翻译、不碰 ToUnicode:钩子既像键盘记录器,又会把系统输入延迟拖进你的进程。记录范围默认只在目标程序持有前台时进行,切出去会写一条失焦日志。

首次启动会做一次真探测,结果落在 $DSH_HOME/storages/dsh-incident-studio/input-capability.json,面板设置里能看到可用键位数或具体原因。依赖 Windows + 系统自带的 Windows PowerShell 5.1。

配置写在 <DSH_HOME>/storages/dsh-incident-studio/profiles.json(DSH_HOME 默认 ~/.dsh),面板设置改的就是这个文件:

{
  "version": 1,
  "activeId": "my-project",
  "profiles": [
    {
      "id": "my-project",
      "name": "我的项目",
      "sources": [
        { "id": "main", "label": "主日志", "color": "#6aa9ff", "kind": "file",
          "path": "C:/Users/you/AppData/Roaming/MyApp/logs/main.log", "enabled": true, "preRoll": true }
      ],
      "input": { "enabled": true, "targets": "Remains.exe", "scope": "target", "pollMs": 20, "trailHz": 0 }
    }
  ]
}

path 不展开 %VAR% 和 $HOME;preRoll(默认开)在录制开始时抓文件尾部最多 96 KB / 800 行并标成「录制前」;input.targets 是目标进程名(最多 8 个),scope 为 "all" 时记录除插件自身外所有前台窗口。

适用场景与注意

适合需要在真实界面上复现问题的人——游戏模组、GUI 客户端、前端交互这类「看一眼就明白、翻日志很难找」的场景。插件不绑定项目,日志源和目标进程都由你配置,可以同时跟多个日志文件。

注意几点:

  • 插件以当前 dsh 宿主进程的权限运行,抓帧、键鼠采集和 HTTP 推送都可能触及本机敏感数据。安装或启用前应当先读一遍源码与 LICENSE(MIT),确认它采集的边界符合你的环境要求。
  • 抓帧和键鼠记录只在按下「开始录制」之后进行,停止即停。桌面端 GDI 拍的是整个虚拟桌面,敏感窗口请先移开。
  • 键鼠记录不记任何文字内容,只在目标程序持有前台时采集;插件宿主进程本身始终被排除,面板里的输入不会被记入。

结尾

这个插件的价值在于可核对性:画面、日志、按键在同一时间轴上,Agent 拿到的不再是「你猜的那一刻」,而是有坐标、有时间戳、有输入序列的证据。项目在社区目录的分类是「工作流」,星标 0,仍属早期阶段;功能边界和踩坑记录都在 README 里,决定引入前建议通读。

目录页:https://www.skillhub.cn/plugins/Eclipse-NotFound/dsh-incident-studio
仓库:https://github.com/Eclipse-NotFound/dsh-incident-studio

羽毛球分组比赛记分
小程序二维码

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

小夜