DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

sky1ine139 /

sky1ine139/dsh-plugin-screenshot-ask

Verified

DSH 截图提问插件:原生框选截图直接进输入框,全程不落盘(DeepSeek Harness plugin, Windows)

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@e258de66

dsh-plugin-screenshot-ask — DSH 截图提问

DeepSeek Harness(DSH)插件:原生框选截图,直接进输入框提问。 仓库:https://github.com/sky1ine139/dsh-plugin-screenshot-ask · 仅 Windows

在 DSH 输入框左侧加一个 📷 按钮(或按 Ctrl+Shift+A):DSH 窗口自动最小化 → 屏幕变暗 → 拖动框选 → 选区旁出现「确认 / 取消」按钮 → 确认后窗口回来, 选区直接作为图片附件落进输入框,接着打字提问、回车发送。

和系统快捷键截图最大的区别:全程不落盘。图片以字节流从宿主进程走到浏览器, 成为一个普通的图片草稿附件,不再往 图片 文件夹里堆文件。

点按钮 / Ctrl+Shift+A
   → 宿主进程把浏览器窗口最小化(这样才看得到、也截得到被它挡住的内容)
   → 整个虚拟屏幕盖上变暗的冻结帧(多显示器全覆盖,按物理像素抓取)
   → 拖框选范围(8 个手柄微调,方向键 1px / Shift+方向键 10px 挪动)
   → 点选区旁的「确认」(或双击 / Enter / 右键)→ 窗口恢复并回到输入框
   → PNG 经官方 composer 图片通道进入输入框 → 输入问题 → 回车发送

特性

  • 截图时自动隐藏 DSH 窗口:像豆包那样先把界面让开,选完再回来;脚本被强杀时宿主也会把窗口恢复。
  • 原生框选,不弹浏览器权限框:走的是宿主侧 PowerShell 浮层,不需要 「选择要共享的屏幕」对话框,也不占用屏幕录制权限。
  • 覆盖全部显示器:浮层是整块虚拟屏幕(含负坐标副屏),并按 per-monitor-v2 DPI 感知取真实像素, 混合缩放(100% + 120%)下选区与抓帧不会错位。
  • 明确的确认 / 取消:选区旁边一条工具条 —— 尺寸读数 +「确认」+「取消」。
  • 不落盘:默认不写任何文件。想看落盘截图时才在配置里给 saveFolder。
  • 走官方草稿通道,不合成 drop:直接调会话服务的 createDrafts + inputActions.addAttachments(与内置文件选择器同一条路径),所以它就是一张图片附件: 有缩略图、可删除、可配文字 —— 不会被别的插件截走,也不会被存成文件。
  • 两种入口:按钮左键框选 / 右键整屏;页面内快捷键 Ctrl+Shift+A。
  • 超大可自动降采样:长边超过 maxEdge 时等比缩小;同时守住 DSH 附件通道的两条硬线 (单边 ≤ 2000px、单图 ≤ 5MB),超了会继续缩,不会因为图太大被拒。
  • 安全:捕获路由默认只接受 loopback 请求(截的是宿主机的屏幕,不能被远程访客触发)。

安装

方式一:直接从 GitHub 装(需要 pnpm;本插件无构建步骤,装完即可用)

$bin = "$env:LOCALAPPDATA\DeepSeekHarness\dsh-pkg\node_modules\@deepseek-ai\dsh\lib\bin.js"
node $bin plugin --profile web add github:sky1ine139/dsh-plugin-screenshot-ask

方式二:本地打包再装(自己改代码时用这种)

# 注意:pnpm 的 file: 规范会在空格处断开,所以仓库路径和输出目录都别带空格
cd <这个仓库的本地路径>
npm pack --pack-destination "$env:USERPROFILE\.dsh\plugin-packs"

$bin = "$env:LOCALAPPDATA\DeepSeekHarness\dsh-pkg\node_modules\@deepseek-ai\dsh\lib\bin.js"
node $bin plugin --profile web add "$env:USERPROFILE\.dsh\plugin-packs\dsh-plugin-screenshot-ask-0.2.3.tgz"

必须重启 dsh web 进程(宿主半段与浏览器 bundle 都在进程启动时装载,刷新页面不够):

powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.dsh\restart-dsh-web.ps1"

重启后打开日志里新打印的带 token 地址(形如 http://127.0.0.1:3080/?token=..., restart-dsh-web.ps1 会顺便弹一个浏览器标签页),输入框左下方出现相机按钮。

卸载:

node $bin plugin --profile web remove dsh-plugin-screenshot-ask

使用

操作 效果
左键点按钮 最小化窗口并进入框选
右键点按钮 直接截取整个屏幕(多屏为整个虚拟桌面)
Ctrl+Shift+A 等同左键点按钮(页面有焦点时生效)
拖动 拉出选区;松手后选区保留
拖选区内部 移动选区
拖 8 个白点 缩放选区
方向键 / Shift+方向键 选区挪 1px / 10px
点工具条「确认」 截取选区并回到输入框
双击 / Enter / 右键选区 同上(键盘或纯鼠标都能确认)
点工具条「取消」/ Esc / 右键空白处 放弃本次截图,窗口照常恢复
浮层内 Ctrl+A 全选整个屏幕

截取成功后输入框里会出现一张图片缩略图,直接打字提问即可;也可以点缩略图上的 删除按钮反悔,或再截一张(会依次排队进同一条附件栏)。

配置

在 ~/.dsh/profiles/web/cordis.patch.yml 里按 id 覆盖(该文件当前是 [],改成下面这样即可):

- id: screenshot-ask
  config:
    maxEdge: 2000        # 只用于「调小」:长边上限,填更小值图片更小;DSH 附件上限是 2000,填更大也按 2000
    saveFolder: ''       # 非空且目录存在时,额外往这里存一份 PNG(默认不落盘)
    timeoutMs: 180000    # 浮层忘关时的兜底超时(超时会强杀脚本并自动恢复被最小化的窗口)
    hideWindow: true     # false = 截图时不最小化 DSH 窗口(想连 DSH 界面一起截时用)
    allowRemote: false   # true = 允许非 loopback 来源触发截图(不建议)

改完同样需要重启 dsh web。

工作原理

  • 宿主半段 lib/index.js:在 ctx.webServer 上注册两条精确路由 POST /api/screenshot-ask/capture({mode:'rect'|'full', keepWindow?:true})与 GET /api/screenshot-ask/status;capture 拉起 lib/capture.ps1,把它的 JSON(含 base64 PNG)原样回给浏览器。带并发闸、超时、loopback 校验; 若脚本被超时强杀,宿主会读脚本留下的窗口句柄把浏览器窗口恢复回来。

  • 截屏脚本 lib/capture.ps1:

    1. 取前台窗口(就是显示 DSH 的浏览器)→ ShowWindow(SW_MINIMIZE),并把句柄写进状态文件;
    2. 抓一张整屏冻结帧、压暗,作为覆盖整个虚拟屏幕的浮层背景(在 Paint 里画, 不是 BackgroundImage —— 超大窗体上后者不渲染,会退化成一块灰);
    3. 框选 / 移动 / 8 手柄缩放 / 方向键微调都在同一套客户区坐标里绘制,与 CopyFromScreen 天然对齐;选区旁画工具条(尺寸 +「确认」+「取消」),鼠标命中测试与绘制共用同一套布局函数; 重绘走统一失效区域:上一次与当前的选区框 + 工具条四块矩形一起失效。 工具条在选区下方 14~50px 处,只按选区外扩失效会漏掉它 —— 那正是"直接框选后出现带状、 手动调整一下就正常"的成因(手动调整触发了工具条自己的失效); 顶部提示条按显示器逐屏居中绘制:只在整块虚拟屏上居中会让它骑在多屏接缝上, 每块屏各露半截(看起来像凭空多出一个被截断的黑框);
    4. 确认 → 先隐藏浮层再抓帧(浮层不会进图)→ 结束前 finally 恢复并聚焦原窗口。 输出 {ok, dataUrl, width, height, sourceWidth, sourceHeight, bytes, dpiAware, hidden, restored}。 纯 ASCII 源码(Windows PowerShell 5.1 会把无 BOM 的 UTF-8 当 ANSI 读,因此中文串由 Text-Of 按码点拼);几何逻辑带 -SelfTest,多屏覆盖带 -Probe 亮度自检, -DemoDrag 能合成真实拖拽并用像素读数验证工具条确实被画出来。
  • DPI:进程按 per-monitor-v2 → per-monitor → system 依次降级申请 DPI 感知。 只用 SetProcessDPIAware(system)时,副屏若缩放不同,Windows 会把鼠标坐标虚拟化 (实测 120% 屏上坐标 ×1.2),选区与抓帧就会错位 —— 这是本插件踩过的坑。

  • 浏览器半段 lib/client.js:window.__ModuleLoader__.load 经典脚本 bundle, 注册到 conversation.input.left 槽位;拿到 dataURL 后取当前会话 id(ctx.get('sessions')), 用 ctx.get('conversation').createDrafts(sessionId, [file]) 建一张浏览器侧图片草稿, 再交给该会话的 inputActions.addAttachments(ids) 追加进输入框 —— 与内置文件选择器 (ui-conversation 的 addFiles)完全同一条路径:不派发任何 DOM 事件,其他插件的 drop 监听器无从插手,字节也不落盘。追加被拒(提交中的相位)时会 releaseDraftAttachments 回收并提示,不会泄漏草稿。最后把焦点交回输入框。

    曾经的实现是「合成一个 document 级 drop、塞进 DataTransfer」,那是错的: dsh-files 也监听 document 的 drop,会把文件上传到 .dsh-filess/<session>/ 落盘, 再往输入框塞路径 —— 输入框里已有图片草稿时这一步会失败,于是截图变成一张 文件卡外加一条红色报错。现在只在会话服务不可达(老版本 DSH)时才回退到 drop。

已知限制

  • 仅 Windows:截屏依赖 Windows PowerShell + System.Drawing。非 Windows 平台路由返回 501。
  • 没有系统级全局热键:浏览器页拿不到全局键盘。要「在任何窗口里按一下就截」, 需要桌面壳(DSH Desktop / Electron 壳)。当前 Ctrl+Shift+A 只在 DSH 页面有焦点时生效。
  • 隐藏的是「按下按钮那一刻的前台窗口」:通常就是 DSH 所在的浏览器。若想连 DSH 界面 一起截下来,把 hideWindow 设为 false(或调接口时带 keepWindow: true)。
  • 浮层是独立置顶窗口:截图时它会盖住整个屏幕(这正是它不弹权限框的代价)。
  • 不做标注:目前只有框选与整屏,没有红框/箭头/文字。要标注可以配合 dsh-capture(见下)或后续版本。

和现成插件的关系

DSH 插件市场里已经有两个同类插件,本插件是它们的组合与取舍:

  • deepseekbluefish/dsh-screenshot-plugin: 同样的原生框选浮层,但截图存进 ~/Pictures/DSH-Screenshots 并只在输入框写入 [Shot N HH:mm] 标记,需要再配视觉插件让 agent 去读文件 —— 正好是「占空间」的痛点。
  • Max-Null/dsh-capture(@max-null/dsh-capture): 框选 + 标注(矩形/箭头/文字)+ 图片直入输入框,功能更全;但纯浏览器模式下走 getDisplayMedia,每次截图都要在系统选择器里先选一次屏幕,且无法截取被 DSH 窗口 遮住的内容之外的整屏自由度。
  • 本插件 = 前者的原生捕获(无权限对话框、被遮挡内容也能截)+ 后者的直入附件, 并且默认零落盘。

想要「标注 + 全局热键」的完整体验,可考虑装 DSH Desktop 桌面壳(dsh-capture、dsh-appshots 在壳内提供全局快捷键)。

故障排查

现象 处理
输入框旁边没有相机按钮 插件没被装载:确认 dsh plugin --profile web add 成功、profile 的 dsh.profile.bundles 里有 dsh-plugin-screenshot-ask,然后重启 dsh web
点按钮提示「截图失败:… HTTP 404」 宿主半段没加载(如无 webServer 的 TUI 部署),Web 版才有这条路由
提示「没有可用的输入框」 没有打开的会话;先进入一个会话再截图
浮层只有一块屏幕变暗 / 只有一个显示器能框选 运行 -Probe 看两台显示器的 meanLuma 是否都被压暗;仍不行就贴 -DemoRect ... -DemoMs 3000 的输出(里面 realWindowRect 是操作系统认定的真实窗口矩形)
选区位置和实际截到的区域错位 典型的混合 DPI 问题:看 -CaptureRect 输出里的 dpiAware 是否为 true;另外检查环境变量 LIB(绿色版 VC6 会污染 C# 编译,脚本已临时置空处理)
窗口最小化后没回来 正常路径由脚本 finally 恢复;被超时强杀时宿主会用状态文件恢复。若仍卡住:powershell -File lib/capture.ps1 -Mode restore -StateFile "$env:TEMP\dsh-screenshot-ask-hwnd.txt"
图太大、发送慢 调小 maxEdge(如 1600)
截图变成一张「文件卡」,还弹红字「文件已上传但未能加入输入框」 这是别的插件(dsh-files)抢到了 document 级 drop:它把文件落盘到 .dsh-filess/<session>/ 再往输入框塞路径。本插件 v0.2.1 起不再合成 drop,走会话草稿 API;若仍出现,说明 ctx.get('conversation') 不可达(老版本 DSH),控制台会打印 using the drop fallback,可临时停用 dsh-files 或升级 DSH
连拍两张只进了一张 第二张时输入框处于提交相位会被拒(提示「输入框正忙」),等这一条提交完再截;草稿不会被泄漏
输入框已经有图片草稿,能否继续加 可以,同一条附件栏按顺序排队,最多 20 张
工具条位置/尺寸数字和选框对不上(例如徽标写 1146、选框只有 800 宽) v0.2.1 及更早的残留像素:改小选区后选框重画了、工具条那块没重画,于是看到的是旧的工具条(位置和数字都还是旧选区的)。v0.2.2 起重绘范围包含"旧/新 选区框 + 工具条"四块矩形。判据:同一个 Paint 里画的框和文字不可能不一致 —— 不一致就一定是有一块没被重画。回归自检:-DemoDrag "2600,400,3746,800" -DemoDrag2 "3746,600,3400,600" -DemoMs 5000 -KeepWindow(先建 1146 宽选区,再从右中手柄收窄到 800;读 toolbarProbe.confirm 应为 37,132,246 且 at.x 对新选区居中)
某块屏幕顶部凭空多出一个半截黑框(文字被截断,比如只看到「Enter 确认 | Esc 取」) v0.2.2 及更早:顶部提示条按整块虚拟屏居中,正好骑在两屏接缝上,于是每块屏各露半截。v0.2.3 起改为每块显示器各画一条完整提示。自检:-DemoDrag ... -KeepWindow 输出里的 hintProbe,每块屏的 delta 应接近 0(提示文字中心与该屏中心之差)

不想最小化窗口就加 -KeepWindow:

powershell -NoProfile -ExecutionPolicy Bypass -File lib/capture.ps1 -DemoRect 200,150,400,250 -DemoMs 3000 -KeepWindow

自测(不需要重启,直接跑脚本):

# 几何自检
powershell -NoProfile -ExecutionPolicy Bypass -File lib/capture.ps1 -SelfTest
# 无头截取一块区域,验证 base64 PNG 通路
powershell -NoProfile -ExecutionPolicy Bypass -File lib/capture.ps1 -CaptureRect 40,60,320,200
# 每台显示器的实时平均亮度(用来判断遮罩是否覆盖全屏)
powershell -NoProfile -ExecutionPolicy Bypass -File lib/capture.ps1 -Probe
# 渲染自检:弹出自检浮层 3 秒后自动关闭,并报告真实窗口矩形 / 覆盖情况 / Paint 错误
powershell -NoProfile -ExecutionPolicy Bypass -File lib/capture.ps1 -DemoRect 200,150,400,250 -DemoMs 3000
# 合成鼠标点击工具条按钮(真跑一遍命中测试)
powershell -NoProfile -ExecutionPolicy Bypass -File lib/capture.ps1 -DemoRect 200,150,400,250 -DemoMs 6000 -DemoClick confirm
# 合成一次真实的框选拖拽,并读屏幕上工具条三处的实际像素
# 期望:confirm=37,132,246(确认键蓝底)cancel=66,66,70(取消键灰底)
powershell -NoProfile -ExecutionPolicy Bypass -File lib/capture.ps1 -DemoDrag 2600,400,3400,800 -DemoMs 4200 -KeepWindow
# 拖拽 + 点确认,走完整条链路(应返回 width=800 height=400 的 PNG)
powershell -NoProfile -ExecutionPolicy Bypass -File lib/capture.ps1 -DemoDrag 2600,400,3400,800 -DemoClick confirm -DemoMs 6000 -KeepWindow
# 回归:先建 1146 宽选区,再从右中手柄收窄到 800(旧版本会留下旧的工具条)
powershell -NoProfile -ExecutionPolicy Bypass -File lib/capture.ps1 -DemoDrag 2600,400,3746,800 -DemoDrag2 3746,600,3400,600 -DemoMs 5000 -KeepWindow

开发

node scripts/selftest.mjs        # capture.ps1 端到端(自检 + 区域 + 整屏 + 降采样)
node scripts/client-smoke.mjs    # 浏览器半段:假 DOM / 假 React / 假会话服务,覆盖
                                 # 草稿 API 投递、忙时回收、连拍两张、drop 回退、快捷键
node scripts/overlay-probe.mjs   # 全链路:窗口隐藏/恢复 + 遮罩是否覆盖每一台显示器(会短暂最小化窗口)

# 排查用:量一张已有截图里选框/工具条的实际像素位置,或把某块区域放大出来看
powershell -File scripts/scan-shot.ps1 -Path <截图.png>
powershell -File scripts/crop-shot.ps1 -Path <截图.png> -Out out.png -X 1600 -Y 860 -W 524 -H 100 -Scale 2

改完重新 npm pack + dsh plugin add + 重启即可(或 npm run selftest / npm run smoke)。

许可

MIT。浮层实现与 file: 交付思路分别改编自 dsh-screenshot-plugin 与 dsh-capture(均为 MIT),详见 LICENSE。

—/ 5

No ratings yet

Verified DSH bundle

Commit e258de66afc5

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout