dsh-computer-use
独立的 Cordis bundle,为 DeepSeek Harness 提供视觉、原生无障碍和 Windows 讲述人操作路径。0.5.16 注册 27 个 computer_* 工具;无障碍观测、层级定位、条件等待、阅读和语义动作可以独立使用,文本模型也能操作原生应用。
Windows 是经过本机运行时验证的主要后端。macOS AX、Linux AT-SPI 已实现并做契约测试,尚无这两个系统的原生运行时验收。接口覆盖与实测范围见 EVIDENCE.md;对标的官方接口见 能力矩阵。目前没有任务成功率基准,也没有 SOTA 等效结论。
操作路径
| 路径 | 工具 | 行为 |
|---|---|---|
| 视觉 | computer_screenshot、computer_find_image、computer_click_image |
多显示器、区域/缩放、Windows 前台窗口捕获、显式后台 PrintWindow、模板匹配与唯一匹配点击。截图可返回图像附件或保存 PNG 后返回文件信息。 |
| 区域视觉观测 | computer_find_color、computer_ocr、computer_wait_visual |
Windows 限定区域 RGB 像素检索、系统 OCR 字/行与有界出现/消失等待;不提窗,不产生点击凭据。 |
| 指针 | computer_move、computer_click、computer_drag、computer_scroll |
截图像素映射到实际捕获边界;Windows 支持三击、modifier、按住、带路径拖动。 |
| 键盘/序列 | computer_key、computer_type、computer_input |
Windows 支持扩展键、Insert/CapsLock、重复/按住,以及一条有界 down/move/up 序列;纯键盘也接受窗口或绑定窗口的语义证据。 |
| 无障碍 | computer_accessibility、computer_find、computer_read、computer_element |
独立快照、元素查找、文本/选择/值/状态读取与控件模式操作。Windows UIA、MSAA 支持分页、分支展开和原生查询。 |
| 定位与等待 | computer_locate、computer_wait、computer_act |
Windows 窗口内逐级消歧,每轮重解容器与目标;共享截止的条件等待、一次动作及可选结果确认。 |
| 树与滚动查找 | computer_tree、computer_scroll_find |
Windows 逐级展开并选择 TreeItem 路径,或显式滚动固定 ScrollPattern 容器查找当前可见项;共同截止、身份核对与逐次结果确认。 |
| 窗口 | computer_windows、computer_window_input |
Windows 列出含无标题弹窗和最小化状态的顶层窗口,从固定窗口查询 owner/线程/进程相关的新根,枚举子 HWND、管理窗口,或向已观测子窗口发送限定点击/滚轮消息。 |
| 标准控件内容 | computer_read_control |
Windows 从已观测子 HWND 有界读取标准 ListView 行、指定列文本及选择/焦点状态,不聚焦、选择或滚动。 |
| 讲述人 | computer_narrator |
只读进程状态;向已运行的讲述人发送固定 Microsoft Standard 布局命令。 |
| 能力 | computer_status |
返回平台能力和显示器几何。 |
根据控件能力、已有证据和实际可靠性选择视觉、无障碍、键盘、讲述人或窗口消息。查询的名称、角色可以来自任务目标或界面;窗口、元素和截图 ID 来自相应工具的真实观测。
独立无障碍与大树
- 调用
computer_windows(operation:"list")获得本会话的短期window_id,也可直接观察当前焦点应用。有效窗口记录可以复用,执行前仍复核原生身份;过期、消失或身份变化时重新列出。 - 调用
computer_accessibility。Windows 可以给window_id;backend:"native"默认 UIA,backend:"msaa"使用独立的传统 IAccessible 实现。 - 浏览一页、展开已观测分支,或用
computer_find(source:"native")查询尚未采集的部分。 computer_read按需读取有界内容;computer_element使用控件实际暴露的 pattern 操作。屏幕外控件也按其能力及 enabled/readonly 等状态检查。- 验证相关结果。目标身份、几何或交互状态变化,或执行结果未知时,更新受影响的观测。
这条路径不需要图像能力。若快照选择绑定 screenshot_id,后续阅读/动作仍必须给同一份图像证据及 SHA-256。动作使相关截图/语义状态失效;窗口和子 HWND 的身份记录保留到其时效结束,并在使用时复核。确定 not_started 的失败保留观测,可能执行过的失败更新相关状态。
概览、分支与续页
获取默认是 summary:返回基本属性、边界、模式可用性和子节点覆盖情况,完整文档与模式状态由 computer_read 获取。Windows 默认 consistency:"snapshot":在所选范围内采集并校验,封存后从同一固定结果集分页。每页默认最多 300 节点、范围深度 6、1 MB 原生响应;一次工具调用的排队、启动及分段采集共用 30 秒截止。max_nodes 同时限定每次原生采集/验证分段的节点数和输出页大小,max_depth、timeout_ms 可逐次指定。scope:"children" 只浏览直属子节点,scope:"subtree" 浏览有界子树。
{"window_id":"<已观测窗口ID>","max_nodes":100,"max_depth":2}
展开已观测分支时,使用包含该元素的快照:
{"snapshot_id":"<分支所在快照ID>","root_element_id":"<已观测元素ID>","scope":"children","max_nodes":100}
返回的 coverage 标明 complete、partial 或 unknown 及原因,consistency 独立标明 collecting、validating 或 frozen。未完成校验时返回空元素和 capture_in_progress,可继续同一采集代次。封存页返回固定的 result_id、SHA-256 和采集起止时间;next_cursor 表示仍有采集进度或未交付的封存页,用该页的 snapshot_id 续取:
{"snapshot_id":"<上一页快照ID>","cursor":"<上一页next_cursor>","max_nodes":100}
采集和验证各保留原生 DFS 栈;概览复读全部摘要,查询复读每个覆盖节点的匹配字段及顺序,并复读命中项的完整摘要,包括未命中项变成命中的情况。变化事件或复读差异使未交付代次报 COMPUTER_SNAPSHOT_CHANGED 并丢弃。新观测在同一 HWND/PID/标题、未发布元素、明确未开始动作且仍有剩余时间时,可在原工具截止内重采最多两次,返回 capture_restarts;已经交付的采集游标不自动换代次,动作、未知结果、资源/时效错误和取消不自动重试。第一页交付前完成校验,之后所有页只读封存行,UI 的插入、删除、重排、改名不会混入这一结果。每页注册独立的工具观测,保留同一结果身份;动作失效后的历史分页可继续阅读,但不会恢复已失效的动作证据。游标绑定会话、后端、工作进程代次、查询、consistency 及深度/scope/detail/截图绑定,改变条件需开始新获取。
每个工作进程最多保留 4 个采集/封存结果,每个结果覆盖最多 20,000 节点,保留数据估算预算 32 MB,合计预算 64 MB。采集和封存各自有 120 秒绝对时效,访问不延长它;时效及淘汰顺序使用单调时钟,采集/验证的原生读取后、封存前和构造输出页前后都检查到期,已到期代次报 cursor_stale 并丢弃;池淘汰会使相应游标与引用失效。节点/保留数据上限命中时只封存已验证范围,返回 capture_node_limit / capture_byte_limit 和 partial;输出页大小不会扩大全树覆盖。深度之外的分支需显式展开或增加深度。
frozen 保证多页来自同一个不可变结果,source_atomic:false 说明源 UI 采集不是事务快照。UIA/MSAA 没有全树事务接口,两次相符的读取及事件校验仍不能证明所有字段曾在源程序的同一瞬间同时存在。需要源程序某一瞬间的全树原子状态时,须由提供者提供事务或可靠的版本化快照接口;此结果不提供该保证。采集范围是否查完由 coverage 表示,与这两层一致性分别判断。
显式 consistency:"live" 保留逐页读取活树的方式,首屏只需本页采集,输出一致性为 unverified。结构事件及每个活动分支最多 8 个导航锚点用于使游标过期;它不能保证页间一致性。固定结果集增加首屏采集/复读成本,封存后续页不再访问提供者,可按范围和所需保证选择模式。
查询与已观测元素动作
computer_find 默认 source:"snapshot",只在给定快照的一页中查找。source:"native" 直接在 Windows 窗口或已观测分支查询,返回可供 read/action 使用的新快照:
{"source":"native","window_id":"<已观测窗口ID>","automation_id":"Commit","match":"exact","max_nodes":1000,"max_depth":12}
只需要少量候选时,snapshot 原生查询可设置 max_matches(1–20,000)。例如先定位一个提交控件:
{"source":"native","window_id":"<已观测窗口ID>","automation_id":"Commit","match":"exact","max_matches":1}
达到指定匹配数后,工作进程复读此前已覆盖的全部节点,再封存该前缀;命中和未命中项都参加校验。coverage.source_status:"partial" / source_reason:"match_limit" 表示尾部尚未搜索,不能据此断言唯一匹配或全局不存在。匹配上限与每页输出数量分开;一个封存结果仍可输出多页,最后一页没有 next_cursor 时,源覆盖仍为 partial。尚未达到上限且搜索完整范围时,覆盖可以为 complete。默认不设置上限,保留完整的有界范围查询;live 查询及缓存页筛选不接受这个参数。
查询同样返回覆盖范围、一致性和游标;续查询可省略原条件及 max_matches 并继承它们,提供不同上限需开始新查询。固定结果集在原生工作进程内按缓存字段筛选:未命中项读取并复核名称、角色、automation ID、启用及屏幕外状态等匹配字段,命中项再读取并复核完整摘要、边界和模式可用性,最终只交付命中行。UIA 导航缓存同时取得 runtime ID,动作前仍重新读取实时身份;MSAA 未命中项省去位置与默认动作 getter。live 模式的 UIA 精确条件使用 PropertyCondition / FindFirst(TreeScope.Element)。缓存范围有界,不使用无界 FindAll(Descendants)。原生查询仍有遍历成本,不承诺任意提供者下的常数时间查找。机制对照见 成熟桌面自动化源码。
正常 Windows 动作使用工作进程注册的原生元素引用,复核窗口生命周期、标题、结构版本、UIA runtime ID 和身份字段后直接调用目标。UIA 同时沿父链复核每条边:从父节点当前直属子列表两端查准确 runtime ID,最多 128 层、20000 次子节点身份检查,超出预算或无法证明归属则拒绝;只读取兄弟身份,不从窗口根导出整树。它会增加原生查询成本,并继续受动作截止约束。引用按会话和进程代次隔离;每个工作进程最多保留 8 个窗口、20000 个元素引用和 32 个 live 游标,另有最多 4 个固定结果集的续页入口;引用时效 120 秒。
UIA 读取包括 TextPattern 文档/选择/字符范围、ValuePattern、范围值、选择集、scroll/window 状态和 grid 信息/单元格。动作包括多选增删、范围值、scroll、文本选择/滚入视图、窗口状态/关闭与 transform 移动/缩放,均要求对应模式。
虚拟化控件概览不会自动实例化所有项目。computer_element(operation:"find_item", property:"name" 或 "automation_id", value:...) 要求 ItemContainerPattern,可能实例化或滚动目标;找到后返回独立元素快照。operation:"realize" 显式调用 VirtualizedItemPattern,再获取相关状态。未实现的虚拟节点不属于“全局不存在”的证据。
MSAA 使用 AccessibleObjectFromWindow / AccessibleChildren,提供传统控件树、名称/角色/状态/值读取、默认动作、值写入和选择。动作使用注册的 IAccessible 引用并检查 HWND/PID、结构版本和身份字段。同一位置出现属性完全相同的替换控件时,MSAA 无法提供 UIA runtime ID 那样的代际保证。
层级定位、条件等待与结果确认
computer_locate 从本会话已列出的 window_id 解析 1–16 级 locator。每一级可以指定名称、role、automation ID、class 或 framework(UIA),支持 exact/contains/regex、直属 children/有界 subtree。每级默认要求唯一匹配;两个候选立即报告 ambiguous,显式 nth(从 0 开始)选择遍历前缀并报告 partial。深度、节点或时间截断报告 incomplete,不能据此证明缺失。默认包括禁用和屏幕外控件,便于等待启用或显示。
{"window_id":"<已观测窗口ID>","locator":[{"automation_id":"right-panel"},{"name":"Apply","role":"Button"}]}
where 在同一个节点上组合 all(AND)、any(OR)和 not。属性叶子接受上述五个字符串属性及自己的 match(默认 exact);同一叶子的多个属性,以及 step 顶层属性与 where,都按 AND。布尔表达式不接受范围、序号或 inclusion 选项。重叠 OR 在一个节点上只计一个候选;两个不同节点命中仍为 ambiguous。
{"window_id":"<已观测窗口ID>","locator":[{"automation_id":"right-panel"},{"role":"Button","where":{"all":[{"any":[{"name":"Apply"},{"name":"\\ACommit(?: changes)?\\z","match":"regex"}]},{"not":{"automation_id":"preview"}}]}}]}
has / has_not 将相对后代条件与外层属性/where 按 AND 组合。例如两个同名 Group 各含一个 Input,用后代是否启用选择其中一个容器:
{"window_id":"<已观测窗口ID>","locator":[{"role":"Group","name":"Panel","has":{"role":"Edit","name":"Input","include_disabled":false},"has_not":{"name":"Loading"}},{"role":"Button","name":"Apply"}]}
内层需要属性或 where,支持独立的 inclusion、scope 和 max_depth,不接受 window、nth 或嵌套关系。内层查找严格排除候选自身,任意一个匹配后代即可证明 has,多个后代不会复制外层候选。has_not 只有查完声明范围且无匹配时通过;节点、时间或深度截断保持 incomplete,不能挑其它候选、选择 nth 或证明 absent。不会隐式展开树或实例化虚拟项。
外层 max_depth 从该 step 的窗口/容器根计算,限制候选与关系的总深度;内层 max_depth 从候选计算,只能进一步收紧范围。外层 scope:"children" 只限制外层候选,携带关系时默认仍有总深度 128;显式总深度 1 无法查完有后代的候选关系。内层 scope:"children" 只查询直属孩子。每次原生解析的外层遍历、两个关系、选中目标和祖先的新鲜复查共用 max_nodes 与时间预算,重复访问也计数。
正则使用 .NET 语义,默认 IgnoreCase + CultureInvariant,允许内联 flags;JSON 中反斜杠须转义。每轮在访问窗口前编译全部 path、关系和布尔分支,不会因短路或外层缺失而忽略无效正则。每次匹配最多 25ms,正则输入最多 16,000 个 UTF-16 单元;每个 where 深度最多 4,每 step 的外层与两个关系合计最多 64 表达式节点、32 属性比较(含顶层属性),每个 all/any 含 1–16 项。无效表达式、正则语法/超时/输入上限都是来源错误,等待不把它们当成不存在或自动重试。
属性缺失或 null 为未知,NOT 未知仍为未知;最终无法判定时返回 locator_property_unavailable,不能用它证明缺席。已能证明的 any true / all false 可短路。MSAA 不提供 automation ID / framework ID,任何分支使用它们都会在遍历前拒绝。这个谓词合同适用于 locator、before/after、树路径和 scroll item;computer_find 保持原 exact/contains 查询合同。
computer_wait 每次轮询从相同 HWND/PID/标题重新解析整条链,容器或控件被替换后读取新目标。condition 支持 present/absent、enabled/disabled、visible/hidden、focused、value/text、selected、expanded/collapsed、toggled 和 stable;stable 同时比较元素身份与边界。唯一/缺失判断只覆盖暴露的有界树,不自动实例化虚拟项。查询和读取只在明确的执行前目标变化时重试;其它提供者错误上报。
computer_act 先等待 before(默认 enabled),执行一次语义 operation,再按可选 after 查询结果。前置、动作和后置共用一个 timeout_ms(默认 10 秒,100ms–120 秒),包含排队与原生启动。动作失败或结果 unknown 都不重放;已完成动作与后置超时/错误分开报告。after 可指定另一条 locator、本会话已经列出的另一个窗口,或用 after.window_query 等待动作创建的新根;后置结果发布新 window_id 和绑定该根的语义证据。
{"window_id":"<已观测窗口ID>","locator":[{"automation_id":"right-panel"},{"automation_id":"input"}],"operation":"set_value","value":"updated","after":{"condition":{"state":"value","value":"updated"}}}
电脑在执行期间可以被人继续操作。窗口绑定不随前台变化切换到另一个同名控件,目标操作前仍校验原生身份、结构版本、模式及 enabled/readonly 状态。UIA 拒绝当前父子列表中已移除的旧对象,即使旧 peer 仍能读属性或保留父链;等待会重新解析替换目标。MSAA 保持前述身份与事件校验范围。UIA/MSAA 不能把条件读取和后续动作做成源程序事务;人或应用在两者之间再次改变状态时,返回实际执行状态并确认结果。动作完成后被人改掉的值会导致后置确认失败,工具不会因此再次写入。需要保留某个现有值时,应显式给出相应 before 条件;这一读值条件也不提供原子比较后写入。
find_item 返回的未实例化 WPF 项可能无法读取普通属性或 runtime ID。工作进程保存 ItemContainer 返回的准确对象,发布标明 virtualized / properties_unavailable 的独立引用,只允许 realize;实例化后重新定位再读/动作。普通可描述项保持完整引用。computer_read(row,column) 的 Grid.GetItem 结果也登记为独立 cell_snapshot_id,可用于单元格选择和后续按需读取。
惰性树与虚拟数据
computer_tree 的 locator 定位树,path 描述直属 TreeItem 的 1–16 级路径;两者合计最多 16 级。它只展开所需祖先,每个展开和末项选择各发送一次,再重新定位并读取展开/选择状态。窗口、容器及已观察分支的 runtime ID 和 worker generation 保持固定;分支移除或替换返回 ancestor_changed,保留已发生步骤并停止。缺失路径在共同截止内返回 timeout,禁用或缺少模式的目标不通过键盘或坐标猜测补做。
{"window_id":"<已观测窗口ID>","locator":[{"role":"Tree","automation_id":"201"}],"path":[{"name":"系统摘要"},{"name":"组件"},{"name":"显示"}],"timeout_ms":12000}
这个示例路径来自实际中文 Windows 系统信息的观测;其它应用应使用它自己暴露的名称与层级。实际系统信息的两轮任务从收拢的根开始,只展开根和组件,再选择显示/声音设备;独立 SelectionItem 和 Tree.Selection 读取确认目标,无关分支保持收拢。
虚拟项优先使用 ItemContainer 的精确查找,需要时显式 Realize 并重新定位。Grid.GetItem 可让实际控件滚动,返回独立 cell_snapshot_id;单元格仅暴露 grid_item 时不能对它猜测 Select,须按实际 selection_item 能力重新定位行。真正 PowerShell Out-GridView 的 600 行任务通过两轮非首屏单元格读取、行选择和独立选择集核对,再以一次 ValuePattern 写入完成筛选并确认剩余行内容。
没有合适 ItemContainer 路径时,computer_scroll_find 显式滚动唯一的 ScrollPattern 容器。item 相对该容器定位;每页只在新读到的目标矩形与视口有正面积交集时返回 found。max_scrolls(默认 10,0–100)、page_wait_ms(默认 300,100–5000)及一个总截止限制流程;每次滚动后独立读取百分比确认变化。它不激活找到的项,返回的语义引用只供随后支持的操作;几何交集不证明无遮挡或指针命中。partial 页不算缺失,scroll_limit/scroll_end 不证明虚拟数据全局不存在。
菜单、Popup 与外部对话框
顶层窗口目录保留有可见面积的无标题窗口,并报告 native_id、className、threadId、ownerId 和 ownerChain。这些原生字段用于审查关系;控制仍使用本会话发布的 window_id。computer_windows(operation:"related", window_id:..., window_query:...) 提供有界只读关系目录,computer_locate / computer_wait / computer_act 的 window_query 可从同一已观测 anchor 每轮重新发现实际新根。
window_query 字段 |
合同 |
|---|---|
relation |
默认 owned 检查实际 HWND owner 链,允许跨进程 owner;same_thread / same_process 只证明线程/进程相关性,不证明归属 |
title / class_name |
精确匹配;显式 title:"" 匹配无标题菜单/Popup,class 必须来自实际观测或明确的目标类 |
max_windows |
默认 1024,范围 1–4096,限制检查的全部顶层 HWND 数,包含未命中的窗口;时间与节点早停报告 partial |
{"window_id":"<已观测原窗口ID>","locator":[{"automation_id":"open"}],"operation":"invoke","after":{"window_query":{"relation":"owned","title":"<目标对话框标题>"},"locator":[{"name":"Cancel","role":"Button"}],"condition":{"state":"present"}}}
关系范围内多个新根报告 ambiguous,返回实际候选窗口,不挑第一项。partial 目录中的零项不能证明消失,一项不能证明唯一;等待消失还要求后续元素范围完整。候选新根在读取间被关闭或替换时,只对明确的 COMPUTER_LOCATOR_CHANGED / not_started 只读变化在同一截止内重新枚举。原 anchor 的 HWND/PID/标题变化、其它来源错误和取消都停止等待,不转成成功缺席,也不改绑到另一个同名窗口。
after.window_query 未指定时继承当前查询;显式 after.window_id 且未指定查询时,直接读取该已列窗口并清除继承查询。因此弹窗动作后可以回原主窗口确认业务状态。新根获得独立窗口与语义引用;根关闭后旧引用不能再次操作,等待替换目标会重新定位。原生关系、控件条件与随后的动作不是源程序事务,仍需确认实际应用结果。
真实四类验收覆盖 TrackPopupMenu、WinForms ToolStripDropDown、WPF Primitives.Popup 与跨进程 owned 对话框。原生菜单动作显式采用 MSAA 默认动作;该菜单的 UIA Invoke 曾无业务结果,未宣称稳定。真实系统声音属性窗口用已观测的 Alt+P 助记键打开,再从 owner 链发现新根、阅读标签页、Cancel 并读回设备名称;首次 UIA 模态 Invoke 超时返回 unknown 的失败证据保留,工具没有重放该动作。
视觉与原生输入
默认 computer_screenshot(output:"image") 返回 screenshot_id、持久化附件 SHA-256 和实际 source_bounds,要求图像输入路由及附件服务。指针工具使用该图像中的坐标。Windows 指名窗口捕获将提窗与抓屏放在同一次 helper 调用里,按控制类审批。
只采集文件时使用:
{"output":"file","save_to":"C:\\captures\\desktop.png"}
文件模式要求 save_to,保存 PNG 并返回路径、尺寸、字节数、时间、哈希与捕获边界;不要求图像路由或附件服务。它不注册可供坐标输入使用的图像证据。截图卡显示图像附件或文件模式的文字信息。模板匹配接受有效的 PNG 路径。
computer_find_image 在屏幕原分辨率逐位置比较像素。threshold 是容差内参与像素比例,默认 0.9;tolerance 是整数 0–255,默认 12。默认沿用 Rec.601 整数灰度;RGB 模式要求一个像素的三个通道都在容差内,才算该像素匹配。没有降采样候选筛选,也没有 16×16 隐式最小尺寸。
| 参数 | 范围与默认 | 行为 |
|---|---|---|
color_mode |
gray / rgb,默认 gray |
灰度亮度或保留 RGB 颜色差异 |
mask_mode |
none / alpha,默认 none |
none 比较全部像素并忽略 PNG alpha;alpha 只纳入达到 cutoff 的像素 |
alpha_min |
整数 1–255,默认 1 | alpha 模式包含透明度 >= 此值的像素;不合成背景、不作透明度加权 |
template_scale |
单个比例 0.1–4,默认 1 | 最近邻缩放;正尺寸四舍五入(.5 向上),不自动尝试多个尺度 |
先缩放模板,再计算遮罩和参与像素;透明像素的隐藏 RGB 不混入相邻有效像素。全排除、缩放成零尺寸、源或变换后超过 1,048,576 像素都明确拒绝。对比度仅统计参与像素:灰度标准差低于 3,或 RGB 各通道标准差都低于 3 时拒绝。保留的半透明像素仍比较 PNG 中的颜色;若屏幕已经把它与背景合成,应选择 cutoff 和容差或使用实际渲染截图作为模板。
结果确认请求的 colorMode/maskMode/alphaMin/templateScale,返回 sourceTemplateWidth/Height、实际 templateWidth/Height、resizeFilter:"nearest" 和 activePixelCount。scale:1 表示抓屏未降采样,与模板比例分别报告。覆盖位置、聚类范围和点击中心都使用实际模板尺寸。
{"template":"C:\\captures\\button.png","window_id":"<已观测窗口ID>","color_mode":"rgb","mask_mode":"alpha","alpha_min":128,"template_scale":1,"threshold":0.95,"tolerance":12,"timeout_ms":5000,"max_positions":20000000}
匹配按行扫描全部合法左上角。每个视觉聚类以遇到的首个匹配为固定锚点:横向距离不超过半模板宽、纵向不超过半模板高时归入最早的相邻锚点;锚点不移动,展示位置可更新为更高分匹配。clusterRule:"row_major_fixed_anchor_half_template" 明确该规则。它表达视觉位置,邻近的不同业务对象仍可能合并,不能凭此识别业务身份。matchCount 统计全部已知聚类;matches 只展示最高分的至多八处,展示上限不截断计数。
coverage:"complete" 表示请求区域中的所有合法位置均已判定,零匹配才报告 status:"not_found"。timeout_ms 默认 5000、范围 1–120000;max_positions 默认 20000000、范围 1–100000000。时间、位置或 100000 聚类资源上限耗尽时返回 coverage:"partial" / status:"incomplete"、stopReason 和 visitedPositions/totalPositions。此时 found 仅表示已有匹配,matchCount 是完整计数的下界,不能断言缺席或唯一。原生预算从模板解码开始,宿主另给启动/序列化五秒余量;阻塞的系统调用由宿主截止终止并报错。
computer_click_image 使用同样参数、默认阈值 0.95,要求完整覆盖且只有一个视觉聚类;部分覆盖找到零处或一处都不点击。旧 helper 缺少覆盖或模式/变换确认字段时直接报错。指名窗口的找图会提窗,原生失败也会使受影响的旧观测失效。找图和随后输入使用独立调用,屏幕内容或窗口在间隙变化仍可能影响点击;实际输入后应验证应用结果。
区域找色、OCR 与视觉等待
三个区域视觉工具都要求整数 region:{x,y,width,height},最多 16,000,000 像素。带 window_id 时相对完整窗口左上角,原生每次重读身份与边界后换算;省略窗口时使用虚拟桌面物理像素,允许负原点。区域必须完整位于来源内,越界直接报错。默认 capture_mode:"screen" 要求指名窗口已在前台,不会暗中提窗;显式 print_window 要求窗口,按应用后台渲染裁切,支持情况取决于应用。
computer_find_color 按行或反向行扫描,RGB 每个通道的偏差都必须 <= 整数 tolerance(0–255,默认 0),alpha 不参与。matchingPixels 统计全部已访问匹配像素;max_samples(1–32,默认 8)只限制展示坐标,不限制总数。max_pixels 默认 16,000,000、最多 100,000,000;位置或时间耗尽返回 partial/incomplete、stopReason 与 visitedPixels/totalPixels。部分零匹配不能证明缺席;像素数量也不证明控件唯一。
{"window_id":"<已观测窗口ID>","region":{"x":12,"y":138,"width":28,"height":28},"rgb":[220,237,249],"tolerance":0,"max_samples":2,"timeout_ms":3000}
computer_ocr(operation:"status") 返回系统已安装语言、图像尺寸上限及分数可用性。operation:"read" 使用 Windows.Media.Ocr,返回 words/lines、lineIndex、行的 wordStart/wordCount、绝对桌面 bounds 与字的 OCR 图像 imageBounds。scale 是显式 1–4 倍 Lanczos3 放大,坐标按实际取整后的 imageWidth/Height 映射。可指定已安装 language;省略使用系统 profile 语言,未安装语言明确拒绝。max_words 默认 500、最多 2000;max_chars 默认 16000、最多 64000,包含重复输出的字和行文本。输出被截断时明确 partial,不把最后一行字前缀合成完整行。
{"operation":"read","window_id":"<已观测窗口ID>","region":{"x":8,"y":1008,"width":1300,"height":32},"language":"zh-Hans-CN","scale":3,"timeout_ms":5000}
系统引擎不提供置信度分数:confidenceAvailable:false、confidenceReason:"engine_does_not_expose_score",字与行 confidence:null;任何 min_confidence(包括 0)均拒绝。OCR 可漏字、误字和符号,不提供文字准确率保证。实际 SketchUp 2024 的完整状态栏在 3 倍读取时识别出选择对象、矩形第一个角等主句,但漏掉部分 Shift/Ctrl 提示并误识别符号;工具状态另外通过原生按钮读回确认,详见 EVIDENCE.md。
computer_wait_visual 的 query.kind 为 color 或 text,支持 state:"present"/"absent"。颜色可给 min_pixels,文字支持 exact/contains、word/line 和 case_sensitive;默认匹配完整行并区分大小写。每次重新抓取同一身份的区域,共用 timeout_ms(默认 10000,等待范围 100–120000)硬截止,包含启动/捕获/识别/返回;poll_ms 默认 100、范围 20–1000。单次找色/OCR 的预算范围 1–120000。来源失焦、身份/边界变化等捕获错误停止等待,分别返回 condition、timeout 或 error,不把错误伪装为消失。已知前缀命中可证明出现,消失要求完整覆盖;文字消失只表示这次没有识别到匹配文字。
{"window_id":"<已观测窗口ID>","region":{"x":12,"y":138,"width":28,"height":28},"query":{"kind":"color","rgb":[220,237,249],"min_pixels":675},"state":"present","timeout_ms":3000}
结果的 visual_id 是独立报告标识,coordinate_space:"desktop_native_pixels";它不注册截图或语义观测,不能作为点击、键盘或元素动作凭据。三个工具均按观测类审批,不发送输入。
Windows 输入序列最多 256 步,显式等待/按住总和最多 10 秒;全文本最多 100000 UTF-16 单元。整条序列先校验再执行,首错停止。正常结束及处理到的错误释放该序列取得的按键/鼠标按钮;不会取得或释放调用前已由外部按住的输入。绑定窗口的序列每步检查身份及前台状态。强制结束进程无法保证析构清理执行,见 SECURITY.md。
computer_key / computer_type 接受有效的 window_id、绑定窗口的 snapshot_id 或前台截图证据。键盘快捷键的实际含义由应用决定,输入投递成功仍需确认相关结果。
后台捕获与子窗口消息
computer_screenshot 给 window_id 和 background:true 时,Windows 用 PrintWindow 按窗口完整边界渲染,返回 capture_mode:"print-window",不主动提窗或恢复窗口,也不回退到前台捕获。GPU/受保护窗口可能失败或返回空白;最小化窗口明确报错,应先显式恢复。
后台图像不能作为全局指针动作的证据。可以使用语义动作,或先 computer_windows(operation:"children") 取得短期 child_window_id,再调用 computer_window_input。消息坐标是子窗口客户区物理像素。接口只有固定 click/scroll,不接受任意消息编号。每次复核 root/parent/PID/class/title,使用 500ms 消息超时。
helper 不主动请求前台,应用的消息处理仍可能自行激活窗口;响应的 foregroundChanged 记录实际变化。delivered:true 仅代表消息已交付,applicationResultVerified:false 表示仍需验证相关结果。窗口 close 同样只是请求关闭,应用可能拒绝或弹出保存对话框。
开发时已验证:Low 完整性标签的 exe 对 Medium 目标执行 PrintWindow 会报 Win32 错误 5;相同字节部署到新临时目录、继承 Medium 后捕获成功。插件不会自动修改标签、提升权限或静默搬迁;可通过 host 配置 nativeHelperPath 明确选择部署产物。显式路径不存在会报错。
标准 ListView 内容读取
用新 computer_windows(operation:"children") 目录中的 child_window_id 调用 computer_read_control,必填 columns 指定 1–32 个唯一的零基列号(0–255),按指定顺序返回。支持 SysListView32 和标准 WinForms ListView 类;LVS_OWNERDATA 虚拟列表、未知类和无法确定的列直接拒绝,改用控件实际提供的 UIA/ItemContainer。目录允许零尺寸辅助 HWND,捕获和定向动作仍要求有效边界。读取前后复核 root/parent/PID/class/title;只读路径可读禁用控件,不主动改变选择、焦点、滚动或前台。
{"child_window_id":"<新目录中的子窗口ID>","columns":[2,0],"start_row":0,"max_rows":100}
| 预算参数 | 默认 | 上限 |
|---|---|---|
max_rows |
100 | 512 |
max_cells |
1000 | 4096 |
max_chars / max_cell_chars |
32000 / 1000 个 UTF-16 单元 | 262144 / 4000 |
timeout_ms / message_timeout_ms |
10000 / 200 ms | 120000 / 1000 ms |
start_row 默认 0。总截止包含排队和 helper 启动,消息截止不超出剩余总预算。结果区分 coverage、stopReason、来源错误和失败行/列,报告实际 cellsRead/charsRead。nextRow 只跨过完整行;末行可能只有部分列或文本,续读要重新取得目录,并从该行开始。容量边界保守标为 incomplete;末尾被截成一半的 UTF-16 代理对缩短为合法前缀,其它畸形 UTF-16 报错。读取末尾复核行数,变化报告 sourceCountChanged;这不是源应用事务快照。报告不产生语义元素或点击凭据。
文本消息使用目标位宽的 LVITEMW 和固定 8192 字节远端缓冲。具名事件先交给目标,再分配缓冲;guard 按 PID 与进程创建时间隔离,并跨 helper 路径、版本和会话共享。超时、取消或未确认文本使该进程隔离:remoteBufferQuarantined 或 remote_buffer_busy_or_quarantined 后不可重试分配,缓冲和一个目标事件句柄由目标退出回收。ReplyMessage 可提前触发完成回调,因此还验证返回长度、首个 NUL 与 UTF-16。遵守协议的标准控件适用;恶意控件先写正确文本再继续使用指针的行为无法由此证明安全。权限拒绝如实报错,产品不自动提权。
Windows 讲述人
computer_narrator(operation:"status") 只检查当前 Windows 登录会话中的 Narrator 进程,不启动讲述人或改设置。命令要求讲述人已运行以及有效的窗口绑定证据;可选 Insert / CapsLock modifier,命令按 Microsoft Standard 布局发送。
支持 item/view 移动、当前项/窗口/标题/文档/选择/行/词阅读、连续阅读、重复语音、scan 切换、激活与停止语音。实际配置布局不能从进程状态中推断,因此响应标为 unknown / Standard assumption。
讲述人虚拟光标、UIA 键盘焦点、语音是不同状态。本版本提供命令投递与 UIA/MSAA 内容读取协作,没有语音捕获或虚拟光标观测。本机只验证了状态桥接及命令/审批/证据合同,没有启动讲述人进行语音验收。
平台范围与运行时
| 能力 | Windows | macOS | Linux |
|---|---|---|---|
| 桌面截图/基本输入/窗口列出与聚焦 | 已实测 | 已实现、契约测试 | 已实现、契约测试;输入/窗口需 X11 xdotool |
| 独立无障碍观测/读取/基本动作 | UIA、MSAA 已实测 | AXValue / AXSelectedText;需 Automation + Accessibility | AT-SPI 文本/范围/选择/caret/数值;需 Python + pyatspi + AT-SPI 总线 |
| 分支展开、续页、原生查询、层级定位/等待、常驻隔离工作进程 | UIA、MSAA | 明确不支持 | 明确不支持 |
| 每次获取的节点/深度/时间预算 | 支持 | 支持,契约测试 | 支持,契约测试 |
| 区域/窗口截图、图像匹配、RGB 找色/OCR/视觉等待 | 已实测;OCR 无分数 | 明确不支持 | 明确不支持 |
| 原子输入序列/路径拖动/扩展 hold/repeat | 已实现及核心真机检查 | 明确拒绝 | 明确拒绝 |
| PrintWindow/子 HWND/窗口管理/讲述人 | Windows 专属 | 明确拒绝 | 明确拒绝 |
macOS/Linux 的快照从焦点应用获取,不支持 Windows 形式的目标窗口语义根、root_element_id、scope:"children"、游标、consistency 选择或 source:"native" 查询;默认快照内查找仍可用。显式 UIA/MSAA 后端请求会报错。macOS AX 不提供本接口的字符范围或 grid 读取;Linux 不提供 grid 读取。macOS 多屏左/上方显示器的截图原点与 Quartz 坐标仍待原生验收。
运行时只通过 Cordis 的服务契约取得 Harness 能力,不导入 Harness 实现。Windows UIA/MSAA 在独立 .NET Framework 控制台进程中运行,首次按源码哈希用系统 csc.exe 编译,使用 ctx.subprocess 管理 UTF-8 JSON 行管道。semanticWorkerCount 默认 2,显式范围 1..4;队列和启动计入调用截止时间。超时或取消会终止对应工作进程并等待退出确认,旧代次引用失效;没有确认退出时不创建替代进程。原生协议区分 not_started、completed 和 unknown;执行错误说明未开始或结果未知,未知结果不自动重试。
讲述人状态仍使用运行时匹配的进程内 C# 桥:普通 Node 使用可选 edge-js,Electron 使用可选 electron-edge-js。0.5.1 已在 Electron 44 / ABI 149 及普通 Node 24 中验证;其他 Electron 版本需匹配的预编译产物。编译器搬迁保留 edge-cs-base.dll 伴随程序集。视觉/窗口输入走仓库自带的 Rust exe。生产后端不走 PowerShell,也不使用系统剪贴板传图。
安装与组合
在官方插件面板添加 GitHub 来源 github:leolee9086/dsh-computer-use#main;CLI 可用时同样通过 Harness 的插件管理入口添加 profile bundle:
pnpm dsh plugin --profile desktop add github:leolee9086/dsh-computer-use#main
bundle patch 同时激活 host computer 服务、工具和工作流提示词,不需要编辑任何 agent 预设。使用 Harness 正常重启入口加载新 host 代码,刷新网页不足以挂载它。包保持现有 src ESM 入口,加载器注册 ID 与包名一致。
默认 observeApproval / controlApproval 都为 ask。权威 DSH 权限预设为 Full access(danger-full-access + approval never)时继承免提示;显式 deny 始终有效。Loader 对单行 config 整体替换,覆盖时需写全该行配置。截图只读/后台与焦点改变分开审批,讲述人 status / command 同样区分观察与控制。
开发与交付验证
Node >=22.19,pnpm;Rust helper 构建需要 Rust >=1.88,Windows 语义工作进程需要系统 .NET Framework 编译器及 UIAutomation 程序集。真实 Harness 回归默认使用相邻 ../deepseek-harness 检出,可设 DSH_HARNESS_ROOT。
pnpm install
pnpm run verify
python test/linux-reader-contracts.py
pnpm run smoke:semantics
pnpm run smoke:snapshots
pnpm run smoke:recovery
pnpm run smoke:matches
pnpm run smoke:lifetimes
pnpm run smoke:locators
pnpm run smoke:windows
# 用当前桌面端实际可执行文件检查 Electron 原生 ABI;按本机路径替换:
pnpm run smoke:electron "C:\path\to\DeepSeek Harness.exe"
# 定向检查原生像素覆盖、窗口输入及 Electron 桥:
pnpm run smoke:images "C:\path\to\DeepSeek Harness.exe"
# 限定区域找色、系统 OCR 和视觉条件等待:
pnpm run smoke:visual "C:\path\to\DeepSeek Harness.exe"
# 标准 ListView 的 32/64 位夹具和真正系统声音应用:
pnpm run smoke:listview "C:\path\to\DeepSeek Harness.exe"
pnpm run smoke:listview "C:\path\to\DeepSeek Harness.exe" app
# 定位谓词:默认 WPF、生产 matcher 合同与真实系统声音设备选择:
pnpm run smoke:locators:electron "C:\path\to\DeepSeek Harness.exe"
# 四类真实菜单/Popup/外部对话框与系统声音属性查看:
pnpm run smoke:popups "C:\path\to\DeepSeek Harness.exe"
# WPF 数据任务、真实系统信息树、真正 Out-GridView:
pnpm run smoke:data "C:\path\to\DeepSeek Harness.exe"
pnpm run verify:profile
# 修改 Rust 原生源码后:
cargo build --release --manifest-path native/Cargo.toml
pnpm run native:stage
pnpm pack --pack-destination .local
verify 检查所有 JS 文件并运行单元/提供者合同及真实 ToolRuntime 回归。verify:profile 读取实际 bundle patch,使用官方 patch 语义及本地 package exports 的解析结果,在临时文件组合中检查真实 Loader、逐行激活、27 工具、提示词和观察允许/控制拒绝。它不执行插件安装或 CLI/profile 层叠,也不改当前 GUI;原 CLI 临时安装验收保留为历史证据。smoke:semantics 用真实 Cordis 本地子进程服务测试万节点 UIA/MSAA、分页/分支/查询/引用/虚拟化、阻塞终止和恢复,并与旧采集算法测量同一提供者的调用量与响应大小。smoke:snapshots 验证两种后端万节点固定分页、未交付代次变化丢弃、查询未命中节点复核、静默插删/重排/属性更新、封存后原生采集零调用,以及历史结果不能绕过实时目标校验。smoke:recovery 验证查询未命中项静默变更后重采一次、持续变化三次尝试后失败、已交付游标不换结果、旧动作引用实时拒绝,以及相同覆盖范围下的按需缓存读取量。smoke:matches 验证真实 UIA/MSAA 在相邻及远端属性 getter 阻塞时仍可早停并封存首项;匹配前缀完整复读、每页一项的固定三页、未命中项及重排变更丢弃、无匹配时搜索完整范围,以及动作实时身份拒绝。smoke:lifetimes 将自建窗口的真实属性读取延迟 1200ms,并把测试进程私有的代次起点移到距期限 1000ms,验证分段内到期丢弃、旧游标拒绝、引用清除及同进程恢复;还验证未来的展示时间戳不会延长封存时效,不修改机器时钟或生产时效常量。smoke:locators 使用默认 WPF AutomationPeer 与真实 ToolRuntime,验证同名消歧、容器替换、动作一次及读回、取消、惰性树、600 项虚拟列表、Grid 单元格和独立 HWND 弹窗;并在等待期间模拟人工编辑、切窗和原目标替换,检查另一个同名窗口未被操作。Electron smoke 还将真实 ToolRuntime 与 WindowsComputer/原生工作进程接在一起,按默认 8 条语义观测上限读取 UIA/MSAA 各 13 页,检查采集变化丢弃、固定续页、历史动作消耗状态、会话隔离及变化恢复;也包含已有 WPF/WinForms 动作。每项验收需在模块及清理完成后返回完成标记,加载失败、提前退出或迟到异常均不能只凭退出码 0 判为通过。Windows 动作 smoke 只操作标题唯一、由自己创建的进程,结束后清理自己的进程和临时目录。smoke:visual 使用真实 ToolRuntime 和系统 OCR 读取自绘 WinForms,覆盖限定区域、方向/容差/计数、截断不能证明消失、定时变化、超时/失焦、遮挡后台读取和移动后相对区域;点击计数保持零。另已完成当前真实 SketchUp 2024 的 R/空格工具切换、中文状态读取及按钮高亮等待,未向画布输入或保存模型;该现场脚本与原始截图/结果仅保存在本地检查点,不是通用应用基准。
smoke:listview 使用真实 Electron、ToolRuntime 和官方 managed subprocess,检查 32/64 位标准控件、UTF-16 与行/列预算、遮挡/禁用读取、零尺寸目录成员、超时/取消后的缓冲保留和后续分配拒绝。app 模式启动真正系统声音应用,逐字对照 UIA 的五个设备名称、重复读取选择/焦点与前台不变,然后清理本次声音进程。Explorer 桌面的 owner-data 拒绝也有实际证据;本机服务窗口读取遇到 Win32 access denied,声音窗口整树 MSAA 枚举失败,不能把这些路径算作成功。它们的限制与成功证据一起记录在 EVIDENCE.md。
smoke:locators:electron 顺序运行默认 WPF 定位验收和本次新开的系统声音窗口。它检查生产编译 matcher 的布尔/正则/未知属性合同、真实 WPF 正则超时零动作,以及声音设备的跨节点 OR 歧义、同节点重叠 OR 唯一、NOT 排除、一次 Select 与独立 selected 读回;只关闭自己新开的声音实例。清理后的完成标记、本轮指标时间和全部 accepted source 哈希都一致才写联合验收。声音阶段不更改音频设置;该任务范围不代表通用应用成功率。
smoke:popups 顺序运行四类真实框架/provider 夹具和本次新开的系统声音窗口,两轮打开/动作计数、关闭后的完整缺席与旧引用拒绝、Forms/WPF 根替换、同名 owned 根歧义、部分范围、取消与 anchor 改名错误均检查。声音窗口只查看属性并 Cancel,不修改设置。调试时可设 DSH_POPUP_MODES 为 native,forms,wpf,external 的非重复子集;该路径跳过真实声音阶段、另存 subset 指标并标明 fullAcceptance:false,不能代替完整验收。
smoke:data 默认顺序运行真实 WPF 默认 peers 的树/虚拟项/Grid/滚动任务,再启动新的系统信息和 Out-GridView 两个真实应用;各阶段及清理完成后才接受标记,联合记录每份原始指标的时间和 SHA-256。fixture 另覆盖缺失/替换分支零选择、滚动次数/不支持/截断与取消。可显式追加 fixture 或 app,或用 DSH_DATA_MODES 选夹具子集;这些入口明确标记非完整联合验收。app 下 DSH_DATA_APP_MODE 为 tree/grid,DSH_DATA_APP_PROBE=1 仅结构探查且 accepted:false。MMC 原先启动报 EACCES;一次系统信息任务在零动作时观察到容器缺失,保留 ancestor_changed 失败而未推断原因。完整成功覆盖上述应用,不构成通用成功率或宏观能力对齐。
native:stage 复制 release exe 并记录二进制与 Rust 源文件哈希;prepack 要求回归成功且产物清单匹配当前版本/源码。打包不含构建缓存或本地检查点。来源、许可与风险边界见 UPSTREAM.md、LICENSE、SECURITY.md,变更见 CHANGELOG.md。