🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

D1 决策实验台 Alyosha28/dsh-cu-d1

DeepSeek Harness
Alyosha283 天前有提交已提供中文文档扫描:含敏感能力

用本地小模型为浏览器与桌面操作提供快速决策

29.9/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/11/2 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add Alyosha28/dsh-cu-d1
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么
dsh 原生插件 · browser
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 3 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 42 处,展示前 42 条)
  • 写入本地文件
    benchmarks/live-public-d1.mts:100
    await mkdir(dirname(output), { recursive: true })
  • 写入本地文件
    benchmarks/live-public-d1.mts:101
    await writeFile(output, JSON.stringify(evidence, null, 2) + '\n', { mode: 0o600 })
  • 写入本地文件
    benchmarks/official-public-browser.mts:36
    await writeFile(configPath, JSON.stringify([...modules.keys()].map(name => ({
  • 写入本地文件
    benchmarks/official-public-browser.mts:78
    await writeFile(join(process.cwd(), 'results/OFFICIAL_BROWSER_SMOKE.json'), JSON.stringify(evidence, null, 2) + '\n', { mode: 0o600 })
  • 删除本地文件递归
    benchmarks/official-public-browser.mts:83
    await rm(root, { recursive: true, force: true })
  • 写入本地文件
    packages/dsh-browser-use-d1/src/downloads.ts:63
    await mkdir(this.dir, { recursive: true })
  • 发起网络请求
    packages/dsh-browser-use-d1/src/downloads.ts:137
    : await approvals.request(agent, {
  • 读取本地文件
    packages/dsh-browser-use-d1/src/downloads.ts:211
    const info = await stat(target)
  • 发起网络请求
    packages/dsh-browser-use-d1/src/extract.ts:149
    const response = await approvals.request(agent, {
  • 发起网络请求
    packages/dsh-browser-use-d1/src/index.ts:694
    const approval = await resource.approvals.request(agent, {
  • 执行外部命令来自配置/变量
    packages/dsh-browser-use-d1/src/preview.ts:116
    const child = spawn(this.helperPath, [], { stdio: ['pipe', 'pipe', 'ignore'] })
  • 删除本地文件递归
    packages/dsh-browser-use-d1/src/preview.ts:215
    await rm(this.temporaryRoot, { recursive: true, force: true, maxRetries: 20, retryDelay: 100 })
  • 读取本地文件
    packages/dsh-browser-use-d1/src/upload.ts:57
    link = await lstat(file)
  • 读取本地文件
    packages/dsh-browser-use-d1/src/upload.ts:63
    const info = await stat(file)
  • 发起网络请求
    packages/dsh-browser-use-d1/src/upload.ts:183
    const approval = await approvals.request(agent, {
  • 发起网络请求
    packages/dsh-computer-use-d1/src/index.ts:302
    const approval = await resource.approvals.request(agent, {
  • 执行外部命令来自配置/变量
    packages/dsh-computer-use-d1/src/indicator.ts:215
    const child = spawn(this.helperPath, [], { stdio: ['pipe', 'pipe', 'ignore'] })
  • 发起网络请求
    packages/dsh-cu-core/src/action-guard.ts:90
    const approval = await gateway.request(agent, {
  • 读取本地文件
    packages/dsh-cu-core/src/audit.ts:105
    text = await readFile(this.path, 'utf8')
  • 写入本地文件
    packages/dsh-cu-core/src/audit.ts:131
    await writeFile(`${this.path}.corrupt`, lines.join('\n') + '\n', { mode: 0o600 })
  • 读取本地文件
    packages/dsh-cu-core/src/audit.ts:135
    for (const line of (await readFile(this.path, 'utf8')).split('\n')) {
  • 写入本地文件
    packages/dsh-cu-core/src/audit.ts:153
    await mkdir(dirname(this.path), { recursive: true, mode: 0o700 })
  • 写入本地文件
    packages/dsh-cu-core/src/audit.ts:155
    await writeFile(temporary, events.map(event => JSON.stringify(event) + '\n').join(''), { mode: 0o600 })
  • 写入本地文件
    packages/dsh-cu-core/src/audit.ts:156
    await rename(temporary, this.path)
  • 发起网络请求
    packages/dsh-cu-core/src/decision.ts:62
    const response = await fetch(this.decideUrl, {
  • 读取本地文件
    packages/dsh-cu-core/src/helper-cache.ts:20
    const content = await readFile(source)
  • 读取本地文件
    packages/dsh-cu-core/src/helper-cache.ts:28
    await access(path, constants.X_OK)
  • 写入本地文件
    packages/dsh-cu-core/src/helper-cache.ts:50
    await mkdir(cacheRoot, { recursive: true, mode: 0o700 })
  • 执行外部命令来自配置/变量
    packages/dsh-cu-core/src/helper-cache.ts:54
    const child = spawn(compiler, [...sources, '-o', temporaryBinary], { stdio: 'ignore' })
  • 写入本地文件
    packages/dsh-cu-core/src/helper-cache.ts:60
    await mkdir(cacheDirectory, { recursive: true, mode: 0o700 })
  • 写入本地文件
    packages/dsh-cu-core/src/helper-cache.ts:61
    await rename(temporaryBinary, binary).catch(async error => {
  • 写入本地文件
    packages/dsh-cu-core/src/helper-cache.ts:64
    await chmod(binary, 0o700)
  • 删除本地文件递归
    packages/dsh-cu-core/src/helper-cache.ts:67
    await rm(buildDirectory, { recursive: true, force: true, maxRetries: 20, retryDelay: 100 })
  • 发起网络请求
    packages/dsh-cu-core/src/policy-approvals.ts:46
    return gateway.request(agent, {
  • 发起网络请求
    packages/dsh-cu-core/src/policy-approvals.ts:63
    return gateway.request(agent, {
  • 读取本地文件
    packages/dsh-cu-core/src/skill-store.ts:99
    text = await readFile(this.path, 'utf8')
  • 读取本地文件
    packages/dsh-cu-core/src/skill-store.ts:136
    const existing = await readFile(`${this.path}.corrupt`, 'utf8').catch(() => '')
  • 写入本地文件
    packages/dsh-cu-core/src/skill-store.ts:137
    await writeFile(`${this.path}.corrupt`, existing + records.map(record => JSON.stringify(record)).join('\n') + '\n', { mode: 0o600 })
  • 写入本地文件
    packages/dsh-cu-core/src/skill-store.ts:145
    await writeFile(`${this.path}.corrupt`, lines.join('\n') + '\n', { mode: 0o600 })
  • 写入本地文件
    packages/dsh-cu-core/src/skill-store.ts:152
    await mkdir(dirname(this.path), { recursive: true, mode: 0o700 })
  • 写入本地文件
    packages/dsh-cu-core/src/skill-store.ts:154
    await writeFile(temporary, JSON.stringify(value, null, 2) + '\n', { mode: 0o600 })
  • 写入本地文件
    packages/dsh-cu-core/src/skill-store.ts:155
    await rename(temporary, this.path)
扫描于 2026/11/4(0 天前) · 范围 全包扫描 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/dsh
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

dsh-cu-d1:本地 D1 决策模型(系统 1),驱动 DeepSeek Harness 的浏览器操作与 macOS 电脑操作,带独立验证、已验证技能、审批和客户端内工具卡片。

README

由 DeepSeek 最新模型翻译生成
DSH CU Decision Lab 用 LiquidAI/d1-2B 做 System 1 决策模型的实验,服务于 DeepSeek Harness 的 Browser Use 和 Computer Use。 仓库 github.com/Alyosha28/dsh-cu-d1 · MIT 已发布到 npm: dsh plugin --profile <profile> add @albaincompleta/dsh-cu-bundle 这个 bundle 依赖 @albaincompleta/dsh-cu-core、-browser-use-d1、-computer-use-d1 和 -client,装一次就能带起整个插件;Harness 兼容性校验会拒绝 0.2.1-rc.5 <0.3.0 之外的任何运行时。 本仓库是可安装的 DSH 插件,不是目录:@albaincompleta/dsh-cu-bundle 声明 dsh.bundle.patch,@albaincompleta/dsh-cu-client 声明 dsh.client,每个包都声明 engines.dsh。
展开完整文档(README 剩余 1 节)
DSH CU Decision Lab

用 LiquidAI/d1-2B 做 System 1 决策模型的实验,服务于 DeepSeek Harness 的 Browser Use 和 Computer Use。

仓库

github.com/Alyosha28/dsh-cu-d1 · MIT

已发布到 npm:

dsh plugin --profile <profile> add @albaincompleta/dsh-cu-bundle

这个 bundle 依赖 @albaincompleta/dsh-cu-core、-browser-use-d1、-computer-use-d1 和 -client,装一次就能带起整个插件;Harness 兼容性校验会拒绝 0.2.1-rc.5 <0.3.0 之外的任何运行时。

本仓库是可安装的 DSH 插件,不是目录:@albaincompleta/dsh-cu-bundle 声明 dsh.bundle.patch,@albaincompleta/dsh-cu-client 声明 dsh.client,每个包都声明 engines.dsh。插件路径就是一个配置档,所以具体安装方式是:

git clone https://github.com/Alyosha28/dsh-cu-d1.git
cd dsh-cu
npm install --include=dev && npm run build

One command: links the packages, mounts @albaincompleta/dsh-cu-bundle, runs the doctor.
npm run install:plugin -- --profile=dsh-cu

Equivalent by hand:
dsh plugin --profile dsh-cu add \
link:$PWD/packages/dsh-cu-bundle link:$PWD/packages/dsh-cu-core \
link:$PWD/packages/dsh-browser-use-d1 link:$PWD/packages/dsh-computer-use-d1 \
link:$PWD/packages/dsh-cu-client

要求 DSH >=0.2.1-rc.5 <0.3.0;其他运行时会由 Harness 兼容性校验拒绝,并给出明确提示。

作为 DSH 插件安装

这些包面向 DeepSeek Harness 0.2.1-rc.5(engines.dsh: >=0.2.1-rc.5 <0.3.0)和 cordis ~4.0.5,也就是桌面应用运行的版本。运行时不一致时,Harness 兼容性校验会直接拒绝并给出明确提示,不会加载版本不匹配的插件。

Build the packages once.
npm install --include=dev && npm run build

Install into a profile: links the packages, mounts the bundle, backs up the
manifest, runs the doctor, and restores the manifest if either step fails.
--dry-run prints the plan before reading anything and exits 0.
npm run install:plugin -- --profile=dsh-cu

Or run each step by hand:
dsh plugin --profile dsh-cu add link:$PWD/packages/dsh-cu-bundle ...
add "@albaincompleta/dsh-cu-bundle" to ~/.dsh/profiles/dsh-cu/package.json
npm run plugin:doctor -- --profile=dsh-cu

插件在配置档层面生效,不在桌面应用内部:任何配置档只要列出 @albaincompleta/dsh-cu-bundle 就会挂载它,无论这个配置档是由命令行启动(dsh --profile dsh-cu …),还是以别的方式分发。装进 Electron 自有的 desktop 配置档是可选项,插件并不需要它才能作为 DSH 插件使用;如果你真要这么做,先退出 DSH,否则运行中的应用会在退出时覆盖 manifest。

plugin:doctor 只回答一个问题:这个配置档带上 D1 服务商后能否启动?它有两个事实来源,任何一项 FAIL 都会以非零状态退出。

- dsh --dump-config(该命令不导入任何插件):条目行存在、已启用、指向预期的包、占据唯一的 browser-provider 槽位,且没有 - id: 出现两次——第二层把 dsh-cu-browser 重新指向另一个包算 FAIL,而不是最后一行获胜。
- 从配置档解析并导入:@albaincompleta/dsh-cu-bundle、-core、-browser-use-d1 和 @deepseek-ai/dsh-browser-use 必须能解析,且 bundle 和两个服务商各导入一次(不挂载)。配置档拼出了正确的行却无法导入服务商,算 FAIL。
- 与宿主 @deepseek-ai/dsh 的版本对齐:不匹配或 peer 未解析算 FAIL,不是 WARN。
- decisionToken / controlToken 解析为 bundle 发布的默认值(dsh-cu-local、dsh-cu-control)算 FAIL,并给出应设置的环境变量。

它不检查的内容:不挂载插件,不启动浏览器、helper 或模型,不证明原生运行会成功,也不检查宿主应用自己的配置档。WARN 只留给无法阻止插件挂载 browser provider 的情况(可选的 native 对、macOS 授权、缺失的客户端包)。

bundle 默认禁用 native 服务商。只有在授予 macOS 辅助功能与屏幕录制权限、并阅读下面的 native 章节之后,才启用两个 native 条目。native 运行缺少授权时,服务商会弹出一次 macOS 隐私对话框(promptPermissions,默认 true),返回 prompted 以及指向确切系统设置面板的深链,控制页面的权限按钮行为相同。npm run plugin:doctor 会打印当前的辅助功能与屏幕录制状态,让缺口在运行失败之前就可见。DSH_CU_DECISION_ENDPOINT、DSH_CU_DECISION_TOKEN、DSH_CU_CONTROL_TOKEN 和 DSH_CU_HEADLESS 在配置档加载时配置 browser 条目;参见 packages/dsh-cu-bundle/README.md。

没有 Playwright 自带的浏览器构建时,服务商会启动已安装的 Google Chrome 或 Edge;两者都不存在时报告 browser_unavailable 并给出恢复步骤,所以新机器无需先跑 npx playwright install。

安装器与发布路径保证什么

- install:plugin -- --profile=<name> 只接受一个目录名:^[a-z0-9][a-z0-9._-]{0,63}$。带分隔符、以点开头或含 .. 段的名称会在触碰文件系统之前被拒绝,且解析后的目录必须位于 DSH_HOME/profiles/ 之下——在 realpath 之后会再检查一次,所以符号链接的配置档也无法逃逸。
- 清单文件先写入临时文件,再重命名,并且只保留一份备份(package.json.bak)。dsh plugin add 失败或 doctor 检查失败时,恢复备份并以非零状态退出。
- 每个包执行 npm publish 时,都会通过 prepublishOnly 运行 scripts/verify-dist.mts:main/types/exports 指向的目标必须同时存在于磁盘和 npm pack 列表中,且 tarball 的文件数必须多于两个。npm run publish:plugin 在每次发布前运行同一道校验,拒绝发布内部依赖尚未上架 registry 的下游包,并在所有退出路径上删除携带 NPM_TOKEN 的临时 npmrc,包括 process.exit 和 SIGINT(已用占位 token 验证:失败的运行不会残留任何 dsh-cu-npmrc- 文件)。
- 这些校验只覆盖本仓库自身的发布路径。它们不覆盖本仓库之外生成的 npm token、registry 侧被攻破,以及用户安装在这些校验存在之前发布的版本。

复用优先的执行

通用自动化请使用官方执行服务商,不要重新实现它们的能力:

- 浏览器: @deepseek-ai/dsh-experimental-browser-use-playwright-mcp 提供上游 Playwright MCP 工具,包括标签页、上传/拖放、快照,以及以 attach 模式访问现有浏览器的标签页和登录状态。
- 原生 macOS: @deepseek-ai/dsh-cua/api 提供已授权的应用/窗口对象 API。getApp 负责授权、启动和初始 AX 观察;调用方不得把它当作应用启动器来轮询。

下面的 D1 服务商仍属于实验性的决策层和 Verified Skill 层。确定性工作流应直接使用官方工具。D1 浏览器服务商不能替代 Playwright MCP 更广的浏览器能力。

可选的实机检查使用真实安装的应用,且不需要账号:

npm run test:live:browser
DSH_CU_REAL_APPS=1 npm run test:live:native

D1 comparison only; requires the local decision service.
D1_DECISION_TOKEN=test-token npm run test:live:d1

test:live:native 不会碰已有的 TextEdit 进程,只测试新建的未保存文档。下面的更大矩阵使用新启动的受控应用和可逆的合成状态。

真实普通应用矩阵覆盖新建的 TextEdit 文档和可重置的 Calculator,包括动态 AX 操作、技能捕获/重跑/审批/回放、过期输入恢复、多窗口与遮挡可用性、运行中停止,以及敏感数据持久化。跑三轮独立测试并汇总各自的耗时证据:

DSH_CU_REAL_APPS=1 DSH_CU_REAL_APP_ROUND=1 npm run test:e2e --workspace @albaincompleta/dsh-cu-computer-use-d1 -- tests/real-app-matrix.e2e.ts
DSH_CU_REAL_APPS=1 DSH_CU_REAL_APP_ROUND=2 npm run test:e2e --workspace @albaincompleta/dsh-cu-computer-use-d1 -- tests/real-app-matrix.e2e.ts
DSH_CU_REAL_APPS=1 DSH_CU_REAL_APP_ROUND=3 npm run test:e2e --workspace @albaincompleta/dsh-cu-computer-use-d1 -- tests/real-app-matrix.e2e.ts
uv run python -m dsh_cu_decision.real_app_acceptance

这些轮次通过 D1 Provider 契约使用确定性决策夹具,隔离执行与生命周期可靠性;它们不衡量真实模型的决策质量。已存在的 TextEdit 或 Calculator 进程会立即触发拒绝,本地化进程名同样如此。报告写入 results/real-apps/ 和 results/REAL_APP_ACCEPTANCE.md。当前版本在每一轮都接受全部九个场景,包括真实多窗口选择守卫、重叠窗口遮挡、Skill 生命周期、运行中停止,以及敏感数据保留。

第三方矩阵覆盖 LibreOffice Writer、WPS Writer、Visual Studio Code 和 Chrome。LibreOffice 与 Chrome 使用独立的 AX 回读;WPS 与 Visual Studio Code 使用独立的 macOS Vision OCR 回读。受控的前台锚点与 20 ms 进程监视器共同验证执行过程不会切换最前台应用。跑三轮独立测试并汇总证据:

DSH_CU_THIRD_PARTY_APPS=1 DSH_CU_THIRD_PARTY_ROUND=1 npm run test:e2e --workspace @albaincompleta/dsh-cu-computer-use-d1 -- tests/third-party-apps.e2e.ts
DSH_CU_THIRD_PARTY_APPS=1 DSH_CU_THIRD_PARTY_ROUND=2 npm run test:e2e --workspace @albaincompleta/dsh-cu-computer-use-d1 -- tests/third-party-apps.e2e.ts
DSH_CU_THIRD_PARTY_APPS=1 DSH_CU_THIRD_PARTY_ROUND=3 npm run test:e2e --workspace @albaincompleta/dsh-cu-computer-use-d1 -- tests/third-party-apps.e2e.ts
uv run python -m dsh_cu_decision.third_party_acceptance

报告写入 results/third-party/ 和 results/THIRD_PARTY_ACCEPTANCE.md。验收覆盖全部四个被测应用,以及保持前台不变的执行。已存在的 LibreOffice 或 WPS 进程会立即触发拒绝。VS Code 与 Chrome 使用隔离配置档,并按精确子进程 PID 挂接,因此用户已有的实例不会进入本次运行。锁定会话下的执行与无人值守生产环境不在验收范围内。

当前能力

- 离线浏览器/桌面操作与目标基准测试。
- 本地 Browser Use 控制,使用真实 Chrome DOM 快照与 Playwright。
- 一个 TypeScript DSH Browser Use Provider,使用官方 SessionResources,支持标准直接工具执行与独立结构化验证。
- 只读的 browser_observe 路径,返回当前元素表,供规划与后置条件编写使用,不经过 D1,也不产生输入。
- DSH-CU 工具在 DSH 客户端内渲染为一等卡片:@albaincompleta/dsh-cu-client 声明 dsh.client,客户端模块扫描器提供其 bundle,每个工具结果在会话记录中显示状态标签、一行摘要和可展开的 payload。
- 运行进行中时,受控标签页会带上标记:标题前缀(● DSH-CU 控制中 · )和 favicon 圆点会一直显示在浏览器标签栏里,切换页面也不会消失,在完成、停止、失败和接管时清除。
- 原生运行和可见浏览器运行期间,会出现菜单栏项(◉ DSH-CU),tooltip 里显示目标,并带一个本地化的「停止」操作。它是辅助状态项:不显示 Dock 图标,不激活,不改变焦点。
- 直接提供 browser_navigate、browser_tabs、browser_upload 和 browser_downloads 工具:打开 URL、列出/选择/打开/关闭标签页、把本地文件上传到一个文件输入框、收集页面下载,全程不需要决策调用。选择标签页时,服务商持有的页面、它的指示器以及后续所有子目标都会移到该标签页。上传需要逐次审批,每次都要列出所有路径;相对路径、缺失文件、目录和非文件输入会在弹出提示前被拒绝。
- 通过 browser_extract 做确定性的类型化 DOM 提取,支持显式定位器、逐字段证据,零决策模型调用。
- 本地化的运行控制页,包含状态、暂停/恢复、停止、接管、系统权限、Verified Skill 管理和审计时间线。
- 合成与真实浏览器的 D1 box 定位基准测试。
- 官方 macOS CUA 评测,覆盖 AX 优先操作、无 AX 时的截图回退、Retina/窗口点转换、过期快照、尺寸变化防护和独立的 fixture 状态校验。

视觉部分属于实验性研究原型。它只控制新启动、明确授权的应用,不使用用户已有的进程或在线账号。

Python 环境搭建

uv sync --extra dev
uv run pytest

模型加载器固定使用 revision cfe5760ff5d5998f91d9ac56bd4b2dbd96996d41,因为 trust_remote_code=True 会执行模型仓库里的自定义 Python 代码。首次运行会下载约 3.84 GB 权重。

浏览器基准测试

uv run python -m dsh_cu_decision.benchmark --local-files-only
uv run python -m dsh_cu_decision.browser_benchmark --local-files-only

两个 runner 都接受 --text-strategy speculative|on-demand。A/B 证据见 results/TEXT_STRATEGY_AB.md。

浏览器 runner 只通过回环 HTTP 提供已检入的 fixture,并使用隔离的 Chrome 实例。只有独立的 DOM 后置条件成立,状态才算成功。

DSH Browser Use Provider

npm install --include=dev
npm run build
npm test
npm run test:plugin

npm run test:plugin 通过 cordis loader 加载构建好的 provider,接入真实的 DSH 服务,然后在无头 Chromium 中对回环 fixture 调用 browser_extract、browser_observe 和 browser_control。这是插件级检查,详见 results/PLUGIN_DSH_TEST.md。
服务商包是 packages/dsh-browser-use-d1 和 packages/dsh-computer-use-d1,共享契约放在 packages/dsh-cu-core。它们对外暴露 d1_browser_subgoal、browser_observe、browser_navigate、browser_tabs、browser_upload、browser_downloads、computer_subgoal,以及控制与发布类工具。子目标必须给出明确的目标,并附带结构化的 verify 断言。browser_observe 返回所拥有页面的当前元素表,不发起决策调用,也不需要输入。浏览器资源通过官方运行时归属于确切的在线 Agent;不需要 PTC。原生操作使用官方 CUA 应用授权和 AX 快照。TYPE_TEXT 对兼容字段使用 setValue;PASTE_TEXT 在几何信息可用时通过相对窗口坐标聚焦选中的元素,否则使用截图框,然后发出一次官方 Paste。剪贴板状态不确定时,触发独立回读并停止,不自动重放输入。STALE_APP 允许在任何输入之前重新选择一次应用。截图回退使用显式的像素/窗口点映射。

可见控制,不打断前台

可见 Browser 启动模式使用后台 Chrome 会话和一个不激活的 macOS 预览面板。面板显示受控标签页、实时页面标题、软件光标、当前阶段与步骤,以及暂停/继续、停止、接管和关闭控件。暂停会挂起当前运行而不中止它;继续则从同一步骤接着执行。完成、失败和接管都会保留结果卡片,直到用户关闭。启动模式下发生接管时,服务商会打开一个有头浏览器,带上当前 cookies、local storage、session storage、滚动位置和已输入的表单值,让你在真实窗口里继续;attach 模式则把已有的受控标签页带到前台。恢复字段时先按 id 或 name 匹配;某个控件的身份已消失时,留空处理,而不是填入另一个字段的值。原生执行使用不激活的 NSPanel 光标和状态浮层,跟随已授权的窗口,并显示应用名和窗口标题。动态 D1 执行与零模型 Skill 重放共用同一套活动事件和清理生命周期。headless: true 会关闭 Browser 预览和接管窗口,供受控测试和无头环境使用。

Browser 服务商在 attach 模式下接受 tabUrl 或 tabTitle。匹配缺失、匹配重复,或者打开了多个标签页却没有选择器时,会以 tab_selection_required 失败,而不是悄悄控制第一个标签页。两个服务商都接受 locale: zh | en,用于面板和审批文案;面向模型的指引保持英文。可见辅助程序在每次源码构建时编译一次,之后从私有临时缓存复用。

决策延迟

决策服务在视觉编码前,会把宽度超过 800 像素的截图降采样,归一化后的框保持不变。在 2508 宽的窗口上实测,单次决策从 879 ms 降到 310 ms,连续六次试验在密集的文章列表上仍稳定选中 CLICK。对于目标较小的界面,可用 DSH_CU_VISION_WIDTH 覆盖这个阈值。scripts/cua-session.mts 是常驻执行会话,跨命令复用 CUA 连接、窗口句柄和指示器,因此重复步骤只需付出截图和推理的开销。启动服务时带上 HF_HUB_OFFLINE=1 和 TRANSFORMERS_OFFLINE=1;不带这两个变量,首次加载会重试模型仓库请求,卡住好几分钟。截图开销为 350–970 ms,取决于窗口内容,且无法通过官方截图接口降低。测量数据与边界记录在 results/CU_PERFORMANCE.md。

指示器由执行适配器驱动,而不是模型输出。在原生受控窗口内进行本地输入,会返回 takeover_detected;需要前台访问的操作返回 foreground_required,不会自动激活。停止、完成、失败、辅助进程退出、心跳丢失,都会释放输入并移除指示器。辅助进程默认编译到私有临时目录,除非用 indicatorHelperPath 指定预编译二进制。

运行针对可见控制的专项检查:

npm test --workspace @albaincompleta/dsh-cu-browser-use-d1 -- tests/indicator.spec.ts
npm run test:e2e --workspace @albaincompleta/dsh-cu-browser-use-d1 -- tests/visible-browser.e2e.ts
npm run test:e2e --workspace @albaincompleta/dsh-cu-computer-use-d1 -- tests/indicator.e2e.ts
npm test --workspace @albaincompleta/dsh-cu-computer-use-d1 -- tests/provider.spec.ts -t "preserves continuous foreground input"

这些检查会查看真实的 macOS 窗口,通过 Accessibility 操作全部三种控件,验证前台与系统指针保持不变,确认动态执行和技能执行期间前台连续输入正常,并覆盖正常清理与强制终止辅助进程两种情况。证据记录在 results/VISIBLE_CONTROL_ACCEPTANCE.md。
Browser Provider 还提供 browser_extract,这是一个只读的结构化提取工具。它接受 1–40 个字段,每个字段用 label、role、text 或 css 显式指定定位方式,结果类型可以是 string、number、boolean 或 url。all: true 返回数组(上限 200 个值);attribute 读取属性,而不是元素内容;required: false 会把缺失的元素记入 missing。元素存在但值为空,这算数据,不算缺失:string 字段返回 "" 并列入 empty,而 number、boolean、url 字段把空值视为 empty_value 并拒绝。必填字段的元素缺失、定位方式有歧义、值无法转换成请求的类型,这三种情况一律失败关闭。结果包含来源 URL、页面标题、每个字段的匹配数,以及 trusted: false;提取到的页面内容始终是不可信数据。提取不会调用 D1,也不会派发输入。字段按顺序逐个读取,不是多字段的原子快照。取消只会停止调用方的等待,已经在进行的 Playwright 导航或读取仍可能在后台完成。

{
"url": "http://127.0.0.1:8080/filters.html",
"fields": [
{ "name": "adults", "type": "number", "locator": { "kind": "label", "text": "Adults" } },
{ "name": "nonstop", "type": "boolean", "locator": { "kind": "label", "text": "Nonstop only" } }
]
}

浏览器控制与发布工具是 browser_control 和 browser_skill_publish;导航、标签页、上传、下载工具是 browser_navigate、browser_tabs、browser_upload 和 browser_downloads;对应的原生工具是 computer_control 和 computer_skill_publish。两者的默认值互不重叠,所以可以在同一个组合里同时挂载两个服务商。toolPrefix 会改变每个浏览器工具的名称(例如 web 会生成 web_extract、web_observe、web_navigate、web_tabs、web_upload、web_control 和 web_skill_publish)。
已验证 URL 技能固定绑定到精确的 HTTP(S) 源和路径;内置 fixture 技能只匹配 loopback URL。在另一个源上显式重放会以 skill_origin_mismatch 停止,并且每次重放动作和每次成功返回之前都会重新检查源。同源路径导航仍然允许。每个可发布技能都带有独立的后置条件。持久化之前,这些断言中捕获的输入值会替换为 {{inputs:...}} 占位符;重放时用当前结构化输入填充它们,并同时检查技能自身的断言和调用方的 verify 断言。如果候选的 URL、窗口标题或步骤元数据包含原始捕获输入,则不会创建该候选。重复的文本输入步骤会获得无冲突的每步输入键,因此脱敏和重放会按顺序保留每个值。结构化值与捕获值冲突,或捕获输入存在 URL 编码表示,也会阻止创建候选。没有源或没有持久化后置条件的旧记录可以读取用于迁移,但不能发布或重放。原生技能在应用提供 appBundleId 时使用精确的 appBundleId 范围,回退方案是精确匹配 windowTitle。内置 fixture 技能需要显式 skillId。原生 paste 步骤保留结构化输入占位符,并与其他技能动作走同一条有界重放路径。

_control 返回的控制页 URL 在 fragment 中携带每服务器页面 token;fragment 本身不会发送到服务器,配置的 controlToken 也绝不会进入工具结果。页面把页面 token 存入 session storage,并作为 bearer 凭证发送。页面显示当前运行状态和上次运行状态、带设置快捷方式的系统权限行、可移除的已验证技能记录,以及审计时间线。browser_observe 和 browser_extract 的结果始终是不可信数据。
共享子目标和安全契约是 benchmarks/computer-subgoal-v1.schema.json。运行时控制包括:凭据/登录门禁、后果性操作确认、重复目标升级、待处理 UI 等待、过期输入拒绝、独立后置条件,以及覆盖模型决策、输入、技能回放和等待的每轮 wall-clock/输入 token/输出 token 预算。P2 增加已验证技能 → D1 → DeepSeek/人工路由;每条结果记录 route、skillId 和 fallbackReason。P3 增加候选生成、独立重跑验证、显式用户批准、不可变发布、持久技能存储,以及有界修复后通过 evolvedFrom 进行的版本化演进。P4 增加 DSH userQuestions 批准、运行控制、暂停/恢复/停止/接管、本地化回环控制页和持久审计。操作批准会指明操作、目标和范围,且只覆盖一个操作;登录批准在输入凭据或点击登录时触发,仅在观察到密码字段时不触发。抛出的权限错误和过期状态错误携带稳定的原因和恢复文本。auditRetentionDays 配置审计保留期,默认 30 天;审计和技能文件使用私有权限,而决策和 CUA 调试日志保留结构元数据,不含原始目标、输入、键入值或截图。P5 完成场景矩阵和范围决策。参见 results/REAL_APP_ACCEPTANCE.md、results/THIRD_PARTY_ACCEPTANCE.md、results/P5_EVALUATION.md、results/P4_CONTROL.md、results/P3_SKILLS.md 和 results/P2_ROUTING.md。

启动回环决策服务后,运行真实模型 e2e:

uv run python -m dsh_cu_decision.server \
--port 8765 --token test-token --local-files-only

D1_DECISION_TOKEN=test-token npm run test:e2e

对比套件使用同一个本地航班任务,搭配脚本化的官方 Playwright MCP 和 D1 服务商。其范围是控制层对比,不是 DeepSeek 规划器对比。

D1 box 基准测试

uv run python -m dsh_cu_decision.visual_benchmark --local-files-only
uv run python -m dsh_cu_decision.visual_browser_benchmark --local-files-only

报告:

- results/d1-box-synthetic.json
- results/d1-box-browser.json

官方 macOS CUA 视觉原型

检出 deepseek-ai/deepseek-harness 到 dsh-v0.2.2-alpha.2,然后构建原生辅助程序:

swift build \
--package-path /tmp/dsh-official-alpha2/packages/experimental/cua-macos/native \
--configuration release

运行 AX 存在的视觉评估和真正的无 AX 回退:

uv run python -m dsh_cu_decision.official_cua_visual \
--execute --local-files-only

uv run python -m dsh_cu_decision.official_cua_axless_visual \
--local-files-only
这些命令只编译和控制一次性官方 AppKit 测试夹具。运行需要 macOS 辅助功能与屏幕录制权限,且会话已解锁。它们不会更改系统权限、选择用户应用,也不会使用用户数据。

原始指标、原生结果和有边界的集成结论见 results/VISUAL_DECISION_REPORT.md。

P0 任务套件与基线

uv run python -m dsh_cu_decision.workflow_e2e --local-files-only
uv run python -m dsh_cu_decision.browser_benchmark \
--case login-blocked --case ambiguous-save --case delayed-results \
--local-files-only --output results/P0_BROWSER_NEGATIVE.json
uv run python -m dsh_cu_decision.p0_report

可复现的场景目录是 benchmarks/scenarios.json。生成的基线是 results/P0_BASELINE.md;它保留了当前的凭据、歧义和重复操作失败,而不是把所有受控成功都当作生产就绪。

智能体技能评估

仓库根目录同时也是一个智能体技能(SKILL.md),在 evals/ 中带有一套 12 个用例的技能升级路由套件。它评估工具选择、控制、发布和拒绝行为,不评估真实浏览器或原生执行。

skill-up validate evals/eval.yaml
skill-up run evals/eval.yaml
skill-up run evals/eval.yaml --iteration 3

结果与限制见 results/SKILL_EVAL.md。

安全与模型许可

D1 不是权限或完成状态的权威。全新状态检查、应用归属、验证和升级仍由模型之外负责。当前结果不足以支持无人值守的桌面控制。

有三条边界值得作为契约明确写出,因为每一条都被解读得比实际更强:

- 模型不能给自己授权。 有后果的操作,其批准来自 DSH userQuestions 服务,由人按操作逐次给出。工具参数里声称已获批准("approved": true、verify 断言、计划、带前缀的指令)不算批准:工具仍会询问,没有批准通道时它会失败关闭,而不是继续执行。重放已发布的 Verified Skill 不是对该规则的绕过;重放能否对确切获批的步骤跳过提示,正在 core/approval 工作流中决定——在那边记录之前,请把「技能重放免于批准」视为不是当前契约。
- doctor 是安装时检查,不是运行时保证。 它报告此刻能解析和导入的内容(见上文);它看不到它运行之后添加到配置档的包、宿主侧覆盖,或服务商内部的运行时故障。
- 本仓库中的决策仅达到沙箱级别。 决策服务绑定回环地址,并要求携带 bearer token,但随 bundle patch 一起发布的 token 是公开的:在设置 DSH_CU_DECISION_TOKEN 和 DSH_CU_CONTROL_TOKEN 之前,同一台机器上的任何人都能访问控制面和决策端点。未设置这两个变量时,doctor 会报错。

d1-2B 使用 LFM Open License v1.0,不是 Apache-2.0 或 MIT。再分发或商用前,请先阅读许可证;其中包含商用收入门槛条件。
预览分享卡片长什么样 ↓Alyosha28/dsh-cu-d1
分享 · DeepSeek Harness Hub
Alyosha28/dsh-cu-d1

用本地小模型为浏览器与桌面操作提供快速决策

这是你的仓库?认领条目

回到顶部