跳过主要内容
D

dsh-pet-shot

dajdkaj/dsh-pet-shot

DSH截屏工具:可以快速截屏,自动将图片加入草稿,截屏图片自动删除。可以搭配dsh-pet使用

安装

dsh plugin --profile web add github:dajdkaj/dsh-pet-shot

README

dsh-pet-shot

在 DeepSeek Harness(DSH) 里框选屏幕区域截图,图片直接进对话输入框,你补完提示词按发送就行。

再也不用「截图 → 存成文件 → 拖进对话框」这一套。

  • 敲 /screenshot 指令 → 自动让开 Harness 窗口 → 框选 → 图进输入框
  • 或者在桌宠上右键 → 更多 → 截图(装了 dsh-pet 的话)

平台:Windows 10 / 11(依赖 PowerShell + .NET 的 GDI 抓屏)。macOS / Linux 暂不支持。


它解决什么问题

截图发给 AI 是高频动作,但每次都要:按 Win+Shift+S → 框选 → 图进剪贴板/文件 → 回到对话框 → 粘贴 → 再写提示词。

这个插件把中间四步压成一个动作:

  1. 触发后自动把 Harness 自己的窗口最小化(不然截到自己)
  2. 原生全屏框选(先冻结整屏再框选,所以选框本身不会出现在截图里)
  3. 图以草稿附件的形式出现在当前对话输入框
  4. 窗口复原,你写提示词、自己按发送

它不会自动替你发送 —— 发什么、配什么文字,由你决定。


功能

说明
两个入口/screenshot 斜杠指令(不需要 dsh-pet);桌宠右键「更多 → 截图」(需要 dsh-pet)
原生框选覆盖整个虚拟屏幕(多显示器是一整块画布,可跨屏拖框);实时显示 宽x高,ESC / 右键取消
不自动发送图只进输入框当草稿,等你补文字后手动发
自动让开遮挡触发时最小化 Harness 窗口;装了 dsh-pet 还会临时隐藏桌宠,结束后都自动还原
不丢图草稿超时未被取走 → 归档到持久目录;模型不支持读图 → 存档并发文字说明(绝不静默删除)
零第三方依赖只用 Node 内置模块 + DSH 宿主服务;截屏靠系统自带的 PowerShell + .NET,不需要装任何东西
不改 dsh-pet 源码菜单通过 dsh-pet 官方的第三方菜单 API 挂载,隐藏走它自己的 /pet-display
可逆安装装/卸只动 profile 里一个包目录 + cordis.patch.yml 三行,卸载脚本自动清理

环境要求

项要求
系统Windows 10 / 11(Windows PowerShell 5.1 即可,不需要 PowerShell 7)
DSH0.2.1-rc.2 及以上
Node.js>= 22(DSH 自带的那份就够)
dsh-pet可选。只有「右键菜单」入口需要(0.3.8 及以上);/screenshot 指令不需要
pnpm可选。install.ps1 优先用它把插件登记成 profile 的真实依赖(避免被插件市场清理);没有 pnpm 会退回手工复制

安装

方式 A:一键脚本(推荐)

把本仓库放到一个不会被移动的固定位置(例如 D:\dsh-pet-shot),然后在 PowerShell 里:

cd D:\dsh-pet-shot
powershell -NoProfile -ExecutionPolicy Bypass -File .\install.ps1

脚本会做三件事,全部可逆:

  1. 把包登记进 profile 依赖(pnpm add file:<本目录>)并同步文件到 <profile>\node_modules\dsh-pet-shot
  2. 往 <profile>\cordis.patch.yml 末尾追加一条 entry(改动前自动备份)
  3. 打印检查结果

装完必须重启一次 DSH,然后刷新浏览器页面:

# 关掉正在跑的 dsh web,再启动
dsh web

为什么必须重启:宿主侧配置是热加载的,但网页侧脚本(client.js)属于 DSH 客户端模块图,只在启动时组装,而且热加载只会重建插件实例、不会重新 import 模块。

常用参数:

# 只看状态,不改任何东西
.\install.ps1 -Check

# profile 不叫 web 时(名字见 %USERPROFILE%\.dsh\profiles\)
.\install.ps1 -Profile tui

# DSH_HOME 不在默认位置
.\install.ps1 -DshHome 'D:\my-dsh-home'

# 开发用:建 junction 指向本目录,改完代码重启即生效(默认是复制)
.\install.ps1 -Link

# 卸载(从 cordis.patch.yml 移除声明 + 删掉装进去的包)
.\install.ps1 -Uninstall

方式 B:手动安装

不想跑脚本的话,等价操作是两步:

  1. 放进 profile:在 profile 目录里用 pnpm 把本仓库装成依赖 (%USERPROFILE%\.dsh\profiles\web 是默认 profile 位置):

    cd "$env:USERPROFILE\.dsh\profiles\web"
    pnpm add "file:D:/dsh-pet-shot"
    

    这一步不能省。 只把文件复制进 node_modules 而不写进 dependencies, 下次你用插件市场装/卸任何插件时,pnpm 会按锁文件重建 node_modules, 把「不在依赖图里的目录」直接删掉。

  2. 声明插件:在 %USERPROFILE%\.dsh\profiles\web\cordis.patch.yml 末尾追加:

    - insert:
        - id: dsh-pet-shot
          name: 'dsh-pet-shot'
    

    ⚠️ id: 那一行不能写行尾注释(DSH 的配置预检靠行首正则抓 entry ID,抓不到就判非法)。

  3. 重启 dsh web,刷新页面。


使用

入口一:/screenshot 指令

在 DSH 输入框里敲:

/screenshot

然后:

  1. 插件先把 Harness 窗口最小化(浏览器标签页所在的浏览器,或桌面版独立窗口都支持)
  2. 等窗口动画收完(默认 650 ms),屏幕变暗、出现十字光标
  3. 按住左键拖一个框,松手完成;ESC 或右键取消
  4. 截图进入当前对话的输入框,光标就位 → 写你的提示词 → 按发送
  5. Harness 窗口自动复原

入口二:右键桌宠(需要 dsh-pet)

  1. 右键桌面上的宠物 → 更多 → 截图(只有这一项时 dsh-pet 会平铺,不显示分组名)
  2. 桌宠立刻隐藏(约 0.25 秒后允许抓屏),屏幕变暗出现十字光标
  3. 拖框选择,ESC / 右键取消
  4. 图进输入框,桌宠自动回来

两个入口共用同一套截图工具,也共用「正在截图」的互斥锁 —— 不会同时弹两个框选层。


配置

在 cordis.patch.yml 里给插件加 config: 即可(改完等一两秒热加载生效;client.js 相关项要重启):

- insert:
    - id: dsh-pet-shot
      name: 'dsh-pet-shot'
      config:
        label: '截图'
        sendMode: 'draft'
        windowSettleMs: 800

通用

配置项默认值说明
label'截图'右键菜单里的按钮文字(≤32 字符,不能有控制字符)
owner'dsh-pet-shot'菜单分组身份键。多个插件共用同一 owner 会互相覆盖,一般不用改
bubbletrue是否用桌宠气泡做反馈(走 dsh-pet 的 /broadcast,尽力而为)
bubbleMs8000气泡停留毫秒数
waitMs10000收菜单点击的长轮询时长(服务端上限 10000)

截图后怎么送

配置项默认值说明
sendMode'draft''draft' = 只把图放进输入框,由你手动发送;'auto' = 直接以图片消息发给 agent
text'这是我刚截的屏幕截图,请看一下。'仅 auto 模式:随图一起发出的文字。'' = 只发图
sessionId''仅 auto 模式:发到哪个会话。留空 = 自动选(排除子代理会话,优先可用/运行中,再按更新时间)
draftBubbleText'截图已放进输入框'草稿模式下的气泡文案,'' = 不冒泡
shotTtlMs300000草稿在内存里最多等 5 分钟,过期把截图归档到 fallbackDir
fallbackDir%DSH_HOME%\dsh-pet-shot\shots\归档目录(模型读不了图 / 草稿超时都往这里放)
fallbackOnImageUnsupportedtrue当前模型不支持读图时,是否降级成「存档 + 发一条文字说明路径」

让开遮挡

配置项默认值说明
commandName'screenshot'指令名(小写、不带斜杠)→ 输入框里敲 /screenshot
commandDescription'框选一块屏幕区域截图…'指令描述,显示在指令列表里
commandMinimizeWindowtrue触发时是否先最小化 Harness 窗口。设 false 就不碰窗口(但会把自己截进去)
windowTool包内 tools/window-control.ps1窗口控制脚本路径,一般不用改
windowHint''额外标题关键字(逗号分隔),命中 +120 分 —— 用于标题里没有 deepseek/harness 的自定义封装
windowSettleMs650最小化后至少等多久才允许抓屏(等窗口动画收完)
hidePettrue装 dsh-pet 时,截图期间隐藏桌宠
hideSettleMs250隐藏后至少等多久才允许抓屏(真机实测桌宠约 230 ms 从画面消失)
restorePetPositionfalse是否把桌宠搬回消失前的位置。默认不搬:搬会「先在默认位置出现再瞬移回原位」,观感差

底层

配置项默认值说明
captureScript包内 tools/capture-region.ps1截图脚本路径
powershell'powershell.exe'PowerShell 可执行文件(PowerShell 7 可写 pwsh.exe)
captureArgs[]追加到截图脚本后面的参数。例如 ['-Rect','0,0,800,600'] 就不弹框、直接截固定区域(自动化用)
captureTimeoutMs120000框选超时,超时杀进程
ttlSweepMs30000草稿过期清扫周期(一般不用改)

工作原理

  /screenshot 指令                      右键桌宠 → 更多 → 截图
        │                                        │
        └───────────────┬────────────────────────┘
                        ▼
        ① 最小化 Harness 窗口(window-control.ps1,按标题/进程名打分)
        ② 隐藏桌宠(dsh-pet /pet-display none)
                        ▼
        ③ capture-region.ps1
           · 先把整屏 CopyFromScreen 冻结成位图   ← 关键:先冻结,再显示 UI
           · 再铺一层置顶全屏窗口做框选
           · 从冻结帧裁剪保存 PNG
                        ▼
        ④ 成功:登记为待发草稿 ──→ client.js 长轮询取走
                                  └→ createDrafts + input.addAttachments
                                     → 图出现在输入框,等你按发送
           取消(退出码 2)/ 出错:气泡提示,不产生草稿
                        ▼
        ⑤ finally:复原窗口 + 复原桌宠(无论成功、失败、取消)

为什么先冻结整屏再画框:如果边显示选框边抓屏,半透明遮罩和选框本身会被拍进图里。 所以脚本第一件事是把屏幕拷进内存位图,之后的框选 UI 只是给「人」看的,最终裁剪的是冻结帧。

等待并行化:隐藏桌宠 / 最小化窗口成功后,插件不会在 JS 里 sleep,而是把 notBefore = 现在 + 等待时长 通过 -NotBefore 交给截图脚本,让「等宠物消失」和 「PowerShell 冷启动 + .NET 编译」同时进行 —— 这是把「点击到框选出现」从约 2 秒压到约 0.9 秒的关键。

组成部分

文件作用
index.js宿主侧 Cordis 插件。注册菜单/指令、长轮询点击、让开窗口与桌宠、拉起截图脚本、管理草稿队列、清理临时文件。零第三方依赖
client.js网页侧脚本(DSH 客户端插件)。长轮询待发截图 → 下载 PNG → conversation.createDrafts 造成图片草稿 → input.addAttachments 挂到当前输入框 → 回报 ack
tools/capture-region.ps1截图工具。PowerShell + .NET:冻结整屏 → 全屏框选 UI → 裁剪保存。支持 -Rect(无 UI)、-Probe(只报虚拟屏幕尺寸)、-NotBefore(等到指定时刻再抓屏)
tools/window-control.ps1窗口控制工具。EnumWindows 枚举可见顶层窗口 → 按标题/进程名打分挑出 Harness 窗口 → ShowWindow 最小化并记下 hwnd,截完复原
install.ps1安装 / 卸载 / 自检
cordis.patch.yml挂载声明(DSH 启动时读它来加载本插件)
test/三套测试:test/capture(截图脚本 56 项)、test/plugin(宿主逻辑 46 项,mock 服务器 + 假 spawn)、test/client(网页脚本 7 项,node:vm 沙箱)
docs/VERIFICATION.md独立验证报告(对抗性测试 + 失效模式排查)

内部 HTTP 路由(前缀 /dsh-pet-shot,给网页侧用):

  • GET /dsh-pet-shot/pending?wait=<ms> — 长轮询最旧一张待发截图,返回 {ok, shot:{id,name,mediaType,size}|null}
  • GET /dsh-pet-shot/shot/<id> — PNG 二进制
  • POST /dsh-pet-shot/ack/<id> — 确认收到 → 先删临时文件再回 {ok, removed}(幂等)

截图脚本的退出码契约:0 成功(stdout 末行 OK x y w h)、2 用户取消、3 出错(stderr ERROR ...)。


测试

本仓库自带三套可独立运行的测试(不需要启动 DSH):

# 截图脚本(真实拉起 PowerShell,真抓屏;需要能创建子进程的普通终端)
powershell -NoProfile -ExecutionPolicy Bypass -File .\test\capture\run-tests.ps1

# 宿主侧插件逻辑(mock dsh-pet 服务器 + 假子进程,不碰真实会话)
node .\test\plugin\run-tests.mjs

# 网页侧脚本(node:vm 沙箱 + 假 DSH 上下文)
node .\test\client\run-tests.mjs

三套测试的完整真实输出都留在 test/*/RESULTS.md 里(含历史版本的修复记录)。


排障

右键菜单里没有「截图」

按顺序查:

# 1. 插件装好了吗
.\install.ps1 -Check

# 2. 宿主侧插件活着吗(应该返回 200)
curl.exe -s -o NUL -w "%{http_code}`n" "http://127.0.0.1:3080/dsh-pet-shot/pending?wait=50"

# 3. 菜单注册上了吗(应该返回 {"ok":true,"events":{"截图":null}})
curl.exe -s "http://127.0.0.1:3080/dsh-pet-7340/menu/events?owner=dsh-pet-shot&wait=200"
  • 第 2 步 404 → 插件没加载:cordis.patch.yml 里没有 entry,或包不在 node_modules 里(重跑 install.ps1)
  • 第 3 步 unknown-owner → 插件活着但没注册:重启 DSH
  • 都正常但还是没有 → 右键菜单来自 dsh-pet 的 Electron helper,等它下一次刷新(约 1 秒);或重启 dsh-pet

/screenshot 指令不存在

指令由宿主侧插件注册。确认第 2 步返回 200 后,重启 dsh web 并刷新页面 —— index.js 改动不会被热加载重新 import,运行中的实例始终是启动时那份代码。

窗口没被最小化

说明窗口识别失败(打分低于 40 分门槛)。这是故意的保守行为:宁可截到窗口,也不乱动别人的窗口。 本机可以看打分结果:

powershell -NoProfile -ExecutionPolicy Bypass -File .\tools\window-control.ps1 -Action probe

找出你那个窗口的名字,把关键字填进 windowHint:

config:
  windowHint: '我的浏览器标题里的一段字'

截图后图没进输入框

图会先留在队列里(不会丢)。检查:

  1. 页面刷新过吗?client.js 只在 DSH 启动时组装 —— 装了插件但没重启,草稿就没人来取
  2. 等 5 分钟,图会归档到 %DSH_HOME%\dsh-pet-shot\shots\
  3. 输入框处于「正在提交」状态时挂不上附件,稍等一下再触发一次

截图里出现了不该有的东西

  • 框选时把 DSH 页面盖住了 → 用 /screenshot(会自动最小化),或把页面拖到不遮挡的位置
  • 桌宠出现在图里 → 检查 hidePet(需要 dsh-pet 正在显示桌宠)

已知限制

  • 仅 Windows:抓屏与窗口控制都依赖 Win32 / .NET(CopyFromScreen、ShowWindow、VirtualScreen)。
  • 必须用鼠标框选:框选层会抢焦点并覆盖整个桌面,选中期间不能操作其它窗口(选完立刻恢复)。
  • 冷启动下限约 0.5 秒:每次截图都要新起一个 PowerShell 进程(~0.36 s)并编译一次 DPI 声明(~0.2 s)。 要再快得改成常驻进程,代价是复杂度与僵尸进程风险。
  • 窗口识别是启发式的:靠标题/进程名打分。自定义封装的标题可能认不出来 —— 这时不会误伤别的窗口, 而是直接截当前画面。用 windowHint 可以稳定命中。
  • 多显示器 / 混合 DPI 未充分验证:代码按 VirtualScreen 处理(不用 Maximized,那只覆盖单屏), 负坐标与 150% / 200% 缩放的组合在真机上只验证过单屏 1920×1080@125%。
  • HDR / 特殊色彩空间可能有颜色偏差(GDI 抓屏的固有限制)。
  • 草稿只在网页开着时能送到:网页侧没加载时截图留在队列里,5 分钟后归档。
  • 气泡可能不显示:dsh-pet 的 /broadcast 受它自己的占用锁门禁影响,宠物在播别的动作时气泡会被丢弃。 这是尽力而为的反馈,不影响截图本身。
  • 安装依赖仓库的绝对路径:profile 的 package.json 里记的是 file:<本仓库路径>。移动或删除本仓库后, 插件市场再装东西会报依赖解析失败 —— 要么把仓库放回原处,要么 install.ps1 -Uninstall 后在新位置重装。

隐私

  • 完全本地:不联网、不上传、不收集任何数据。截图只在本机流转。
  • 截图去哪了:成功送进输入框的截图,在客户端确认收到后立刻删除临时文件; 未被取走 / 模型读不了图的会归档到 %DSH_HOME%\dsh-pet-shot\shots\,你自己管理。
  • 没有第三方依赖:package.json 里没有 dependencies,代码只用 Node 内置模块与系统自带的 PowerShell。 也就是说,这个插件不引入任何供应链风险。
  • 权限:它会调用 powershell.exe 执行本包内的两个 .ps1;会读写 DSH profile 下的 node_modules/dsh-pet-shot 与 cordis.patch.yml(安装/卸载时)。除此之外不碰你的文件。

卸载

.\install.ps1 -Uninstall

然后重启 dsh web。归档目录 %DSH_HOME%\dsh-pet-shot\shots\ 不会自动删(里面是你截过的图), 需要的话自己清掉。


许可

MIT

相关插件