← 返回列表
未验证
让模型自主截屏并直接看到画面内容
尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/9/16 · 已提供中文文档
macOS 上 DeepSeek Harness 的自主屏幕视觉:智能体捕获屏幕并在一次调用中接收图像本身。
综合分
30
GitHub 分
30
用户评分
—
★ Stars
0
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add davidekingsss/dsh-screen-eye该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/16(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-attachment@deepseek-ai/dsh-tools@deepseek-ai/dsh-util-values@deepseek-ai/schemastery用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
dsh-screen-eye 给 macOS 与 Windows 上的 DeepSeek Harness 装一只自主的眼睛:agent 截屏后在同一次工具调用里直接拿到图,于是它能自己去看正在运行的应用、弹窗、报错,或者自己刚写的界面——不必再让你手动截图。 无原生构建步骤、不带预编译二进制、零依赖。 它提供什么 两个模型可调用的工具: | 工具 | 作用 | |---|---| | screenshot | 截屏,并把图片本身作为 image 内容块返回给模型——模型是真的看得见。 | | screen_permission | 在 macOS 上报告本进程当前是否允许截屏;用 action: "guide" 可直接打开对应的系统设置面板并给出需要授权的路径。Windows 没有这项权限可报告,因此该工具在 Windows 上不注册。 | mode 决定截什么:screen(默认,主显示器)、display(按序号指定某一块 屏幕)、region(指定矩形,原点是主屏左上角,因此在主屏左侧或上方的显示器 取负坐标)、displays(不截图,只列出已连接的屏幕,以及 display 需要的序号 和每块屏幕在 Windows 上的起点坐标),以及需要人交互的 window / select (等待用户点选窗口或拖拽出选区)。Windows 没有系统级选区工具,所以在那里 select 会被明确拒绝并说明原因,而 window 指的是当前在最前面的窗口。 把 frames 设为大于 1,一次调用就会按 interval_ms 的间隔连拍那么多张并全部返回, 这是"看清随时间变化的过程"的方式。它刻意不是 GIF:harness 以单帧存储图片, 动画 GIF 到达模型时只剩第一帧。 这两个旋钮都交由你调,而"有用的方向"不一定是调细。采集速度取决于面积—— 整块 4K 屏要 155ms,而 1200×800 的区域只要 56ms——所以要看清一个几百毫秒的 组件动画,正确做法是截它所在的那一小块,而不是要求整屏用更细的间隔。 返回里会报告实际达成的间隔,达不到时明确说明。 docs/motion.md 有实测数据与推理。 决定成本与分辨率的那个旋钮是 interval_ms:它决定运动被采样得多细,而帧数 就是一次连拍的全部花费。这里没有任何东西强加一段固定时长——连拍的长度是 (frames - 1) × interval_ms,而调用若先等待画面变化,结束时机就由画面决定—— 所以唯一的封顶是 timeout_ms(整次调用的预算,默认五分钟,可按次调高)。 帧数上限是 provider 自己的"单请求 600 张图",不是本插件拍的数字:每帧是一张图、 最多 384 个视觉 token(实测约 380),因此帧数是一个成本决策,交给看得见上下文的 调用方比交给插件更合理,工具描述里也把这道算术直接写了出来。 其余情况下每次调用只返回一张图。这是刻意的约束,而不是系统的限制:screencapture 是「每块屏幕写一个文件」,所以在多显示器 Mac 上不加限定的截图会产出多个文件, 而本插件的管线只解析并读取一个路径——其余的会以本插件没有选择过的文件名留在 盘上。因此默认被钉在单块显示器上,要看另一块就用 display。 为什么需要这个插件 多数截图工具假设难点在于「取像素」。在 macOS 上难点是权限,而且它失败 的样子像 bug: screencapture: could not create image from display macOS 把截屏能力锁在「屏幕录制」权限后面,而该权限挂在责任进程上——也就是 macOS 认为要对整棵进程树负责的那个应用。而 DeepSeek Harness 的宿主往往不是 一个正常的 GUI 应用:应用内插件市场通过一个 detached 的辅助进程重启宿主, 宿主因此被挂到 launchd 之下,其上方不存在任何应用身份。这样的进程去申请 屏幕时,macOS 无法把请求归属到任何用户可以授权的对象上,于是*直接拒绝,且 连授权弹窗都不会出现。 这个权限无法用程序授予:TCC 数据库受 SIP 保护,tccutil 只能重置, CGRequestScreenCaptureAccess 对非 bundle 进程拒绝弹窗。所以本插件只做真正 做得到的事: - 检测:真的去截一次并按结果分类,而不是靠启发式猜测; - 算准目标:从正在运行的宿主推导出必须被授权的那一个可执行文件,而不是 泛泛描述; - 打开面板:按需直接跳转到系统设置里对应的那一页; - 把步骤当作工具结果返回:于是 agent 交给你的是一份修复指引,而不是一段 报错。 Windows 没有这道闸门,也就没有这段故事:那里的难点是截图可能成功但没用—— 进程若不感知 DPI,拿到的就是屏幕的降采样副本;若没挂在交互式桌面上,拿到的 就是一张黑图。两者都在下面的 Windows 一节里被解决。 安装 dsh plugin --profile web add github:davidekingsss/dsh-screen-eye 然后重启 dsh dsh plugin --profile web add github:davidekingsss/dsh-screen-eye 然后重启 dsh macOS 与 Windows 是同一条安装命令,平台层自己挑引擎。 若用本地检出目录,而不是已发布的源: dsh plugin --profile web add -w link:/path/to/dsh-screen-eye 本插件没有构建步骤、没有依赖,安装期不编译任何东西。 授予屏幕录制权限(macOS,一次性) 调用一次 screenshot。如果缺权限,返回结果会明确告诉你该怎么做; screen_permission 配合 action: "guide" 会走完整个引导:先检查,只在授权确实缺失时 才打开面板,并返回需要添加的路径。简言之: 1. 打开 系统设置 → 隐私与安全性 → 屏幕与系统音频录制。 2. 点 +,按 ⌘⇧G,粘贴工具报告的那个路径(通常是运行 harness 的 node 二进制),选中它。 3. 把它的开关打开。 不需要重启——授权对下一次截图即生效。 若你是从终端启动 harness,改为给那个终端 App 授权,效果相同。 macOS 可能定期要求重新确认此权限,把同一个开关重新打开即可。 Windows 完全不需要这些,见 Windows。 配置 所有键都是可选的——而且它们全都可以在 harness 自己的设置页里改:设置 → Screen Eye(左侧独立一项,眼睛图标),或者直接手改 ~/.dsh/settings.yaml 里的 screen-eye: 一节。两种方式都是下一次调用即生效、不需要重启,并且插件的挂载 条目始终是"清空某个字段后回落到的那一层"。三层关系、这个页面的形态、以及它背后的 两条平台约束见 docs/settings.md。 | 键 | 默认值 | 含义 | |---|---|---| | outputDir | /Screen Eye | 截图 PNG 的落盘目录——系统图片文件夹,并单独放一个子目录,免得五十张截图混进你自己的照片里。 | | locale | en | 引导文案语言:en 或 zh。 | | timeoutMs | 300000 | 一整次调用的预算(含 wait_for_change 的等待)。等待没用掉的时间才归后面的采集。 | | frames / interval_ms | 1 / 200 | 每次调用的帧数与帧间目标间隔。上限 600,这是 provider 对单请求图片数的限制,不是本插件的策略——超过的部分会被截下来然后替换成占位文本。每帧是一张图、最多 384 个视觉 token(实测约 380),所以帧数是一个成本决策,由你来做。 | | duration_ms | — | 直接说明运动持续多久,由工具自己定帧数与间隔,而不必你手算。 | frames、interval_ms、duration_ms 描述的是同一次连拍,任意两个确定第三个: 帧数 + 间隔给出跨度,帧数 + 时长给出等分该窗口的间隔,间隔 + 时长给出能放几帧。 三个同时给出会被拒绝而不是替你裁决。 这也正是成本杠杆:每帧都是一张图,而图就是成本。窗口不变而调大 interval_ms,就是用更少的图看同一段运动——分辨率换成本;调小则相反。 只给时长时,按常规帧数采样而非上限,因为上限是花钱最多的答案,而你没要它; 但如果这次调用先等待画面变化,结束时机就由画面决定,帧数这时是余量而不是计划。 wait_for_change: true 同时确定了连拍何时结束:画面不再变化时它自己收尾, 于是 frames 变成上限,返回值会说明是哪种结束方式。wait_timeout_ms(默认 30000)是等待运动开始的时间上限。until_still: false 可以退出这一行为,改为拍满 整个窗口——那是"要一段跨度"而不是"要一个事件"时该做的选择。 | maxDimension | 4096 | 截图允许的最大单边像素。4096 是 provider 在"单请求含 15 张及以上图片"时对单边的限制,而一次连拍可以带上百张。超限的截图会被拒绝并报出真实尺寸,而不是缩放到上限——所以要整屏截取更大的显示器,得把这里调高。 | | keepRecent | 50 | outputDir 里保留的最新截图数量。一张截图是几 MB 的 PNG,而用眼睛的 agent 会截很多张,所以这个目录默认是有上限的。设为 0 表示全部保留。 | | requireImageCapableModel | true | 当调用方模型未声明图片输入时直接拒绝,而不是返回一张它看不见的图。 | | deleteAfterCommit | false | 提交到附件存储后删除 PNG。默认关闭,以便返回的路径可再次读取。 | 提交到存储时会去掉那些会让它无法无损保存的记录。在 macOS 上就是去掉 screencapture 给每张截图附带的 ICC 描述文件、EXIF 与 iTXt 记录,而磁盘上的 文件保留它们:这几个记录正是附件存储"保留原字节还是重编码"的判定依据——带 元数据的图片不允许直通——所以去掉它们,截图才能按原字节存下,而不是被编码 成质量 85 的 WebP。在 Windows 上则没有东西可去:GDI+ 这几个记录一个都不写, 截图本来就已满足存储的直通条件。存储无论如何都会转成 sRGB,因此没有任何存活 下来的信息被丢掉;而你能打开的那个文件仍然带着它的色彩描述。 清理只会删除本插件自己写出的文件:outputDir 的直接子项、且文件名严格匹配 本插件生成的形状(shot--.png)的普通文件。它绝不递归、绝不动 其他命名规则的文件,也绝不会删掉刚刚返回给你的那一张。 cordis.patch.yml - insert: - id: screen-eye name: dsh-screen-eye config: locale: zh outputDir: /Users/me/Pictures/agent-shots keepRecent: 200 实现 screenshot 工具 ──▶ lib/capture.mjs ──▶ 平台引擎 ──▶ PNG │ macOS:screencapture │ Windows:PowerShell + System.Drawing └──▶ attachments.saveImage() ──▶ image 内容块 ──▶ 模型 截图不会被缩放到 maxDimension 以内,这个上限也刻意没有设得更低,两者出自同一个实测: harness 在模型看到图片之前,会先按路由的像素预算投影——默认 640,000 像素,16:9 屏幕约 1066×600——所以 4K、5K、6K、8K 显示器截出来的图,到达模型时是同一张。在这个预算之下, 把上限调小省不下一个 token;而在这里做缩放,会在"模型在图上量到的位置"与"region 需要的 屏幕坐标"之间再多插一级缩放,而那正是放大工作流所依赖的映射。 两个引擎都不自带二进制。macOS 走系统自带的 screencapture(1):它不需要任何 编译产物、由 Apple 签名,并且在当前 macOS 上内部已经使用 ScreenCaptureKit; 自带辅助二进制则意味着要产出多架构构建和一个 ad-hoc 签名——而它的哈希每次 重新构建都会变,哈希一变,用户的屏幕录制授权就静默失效。Windows 走每一台 机器都有的 Windows PowerShell 5.1,通过 Add-Type 在内存里临时编译一层垫片 来驱动 System.Drawing,一次调用结束即消失。 图片通过与内置 read_image 完全相同的附件通道抵达模型,因此其校验、降采样与 会话回放行为与任何其他图片一致。 平台支持 macOS 与 Windows,且在两处强制:bundle patch 带 disabled: !!js process.platform !== 'darwin' && process.platform !== 'win32', 其他平台连模块都不会被 import;apply() 再检查一次,使得绕过 patch 的直接 挂载也无法注册没有引擎的截图工具。 Windows Windows 不需要授权也不需要引导——任何挂在交互式桌面上的进程都能截屏——所以 那里根本不注册 screen_permission,screenshot 就是全部工具面。与 macOS 真正 不同的有四点,每一点都是被解决的,而不是被写进文档绕过的; docs/windows.md 里有实测数据。 - 缩放。 Windows PowerShell 默认是 DPI 不感知的,而 DPI 不感知的进程拿到的 是桌面的降采样副本:在 125% 缩放的 3840×2160 面板上,它报告并截取的是 3072×1728。引擎在读取任何东西之前先声明 per-monitor 感知,取到的是真实像素。 - 看不见的会话。 没有挂在交互式窗口站上的进程不会失败——CopyFromScreen 返回黑图,朴素实现会把它当成"成功截到一张黑屏"。引擎先检查窗口站与会话并 点名拒绝,而整帧全黑的照片会带着说明返回,说明这通常意味着什么。 - 连拍。 Windows 上单次截图冷启动约 380ms,且几乎与面积无关,因为每次调用都要付 一次 PowerShell 启动(其中 148ms 是它什么都不做时的启动成本)。现在引擎只启动一次 并常驻:C# 垫片每台机器只编译一次,之后单次截图只需 16-22ms。六帧连拍若拆成 六次冷调用,会把一段 400ms 的动画采样成两秒半,所以 Windows 把整段连拍放进同一个 引擎进程,计划里的间隔才成为可达的。 - 只播一次的动画。 组件过渡只播一次,而模型不可能在用户点击的那一瞬间发出调用 ——实测:在一段 300ms 过渡刚开始时发出的连拍,两个平台都是 0 帧可用。 wait_for_change: true 就是答案:"我盯着这块区域,画面一动就开始拍。"在一段已知的 300ms 过渡上实测:帧序列在动画开始后 103ms 起拍,8 帧中有 4-5 帧落在动画 区间内。macOS 有同样的选项,并且自 2026-09-16 起也有同类的常驻助手进程——它的一次 变化检测耗时 22.6ms,而走 screencapture 要 55.8ms;这决定了同一段 300ms 过渡是 只录到后三分之一,还是完整录下来(见 docs/macos-findings.md)。 结束端同样交给画面判定:等待过变化的连拍,会在画面静止时自己收尾,所以 frames 是上限而不再是"猜动画有多长"。同一段过渡上实测:7 帧覆盖完整段动画后自行停止, 10 帧的额度还剩 3 帧没用。返回值会说明是哪种结束方式;想要"固定一段窗口"而不是 "一个事件"的调用方,用 until_still: false 明确要求。 - 双屏。 显示器按主屏优先列出并带各自的原点,所以第二块屏上的 region ——包括位于主屏左侧、坐标为负的那块——都落在正确像素上。已在 3840×2160 主屏 加一块 x = -2560 的 2560×1600 屏上逐像素比对验证。 - select。 Windows 没有系统级选区工具,所以该模式被明确拒绝并给出原因、 建议改用 region;window 截的是当前在最前面的窗口,因为同样没有可点的东西。 环境要求 - macOS 或 Windows,以及 harness 自身的 Node 运行时。两条截图链路都不需要额外 安装任何包,安装时也不编译任何东西。 - macOS 上需要给运行 harness 的进程授予「屏幕录制」权限(见上文)。Windows 不需要。 - 一个声明了图片输入的模型路由。保持 requireImageCapableModel 默认值时, 被声明为纯文本的路由会在事前被拒绝,并在消息里点名该模型,而不是悄悄截一张 它看不见的图。注意这个声明在 harness 的模型元数据里,而不在模型身上: settings.yaml 可以覆盖内置的模型条目,一条只写了 text 的覆盖会让一个 明明看得见的模型被拒绝。拒绝消息会点名模型和那个设置项,因此修好它只需要 一行,而且不重启即可生效。 开发 npm install node test/selftest.mjs 该测试套件无需启动 harness:逻辑模块被直接导入,工具定义经由桩上下文执行, 因此在一台从未装过 harness 的机器上同样能跑——CI 走的就是这条路,macOS 与 Windows 上各跑一遍。真正实拍的用例只在本机确实看得见自己的屏幕时运行—— macOS 上要有屏幕录制权限,Windows 上要有可见桌面——所以在授权之前套件依然是绿的。 针对某个平台自身模型的用例,直接问那个平台的模型,而不是问当前宿主机:于是 Windows 引擎生成的 PowerShell 在 macOS CI 上也会被断言,macOS 的权限文案在 Windows 上也会被断言。这是刻意的:只有当另一侧也被检查时,这条接缝才有意义。 插件导入的三个 @deepseek-ai/ 包在 devDependencies 里精确钉版本,这是 刻意的:这几个包把当前版本线发在 next dist-tag 下,而 latest 仍指向一个 老得多的版本,不钉版本就会装到旧的那一个、import 直接失败。 docs/verification.md 记录了实际跑过的内容—— 两个平台上的自测、隔离 profile 中的加载器验收、以及端到端 agent 回合——并说明 每一项证明了什么、没证明什么。 docs/macos-debugging.md 是一份自包含的 Mac 端验证手册, 专门写成"可以直接交给一个没有任何上下文的 AI 去执行"的形式:按优先级排列的八个步骤, 每一步都写明怎么跑、期望看到什么、出现偏差意味着什么、要回报哪些数字。 tools/motion-fixture.html 是它要用的动画素材:每 4 秒自动播放一次的 300ms 过渡, 不需要有人在连拍等待时去点击。 docs/macos-findings.md 是 2026-09-16 在 Mac 上跑完这份手册的 实测记录。在信任别处任何 Mac 数字之前都值得先读它:它确认了 region 是像素级精确裁剪、 静止判定的前提成立;同时推翻了"macOS 的检测足够留下 300ms 过渡里的四五帧"这一说法 ——实测只留下一到两帧,因为每次检测都要付一次完整的 screencapture 进程启动开销。 正是这个测量结果让 macOS 也补上了常驻引擎,也让本插件不再像以前说的那样"完全不含编译 产物":该助手进程在使用者的机器上从源码编译,继承屏幕录制授权而不是另外申请, 并且任何失败都会回退到 screencapture。 许可证 MIT
扫码进群