ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

DeepSeek Harness Desktop 如何把外部 Agents Anywhere 包锁成 1 个可追溯 tarball:7 个机制与升级前必查项

DeepSeek Harness Desktop 如何把外部 Agents Anywhere 包锁成 1 个可追溯 tarball:7 个机制与升级前必查项

DeepSeek Harness Desktop 如何把外部 Agents Anywhere 包锁成 1 个可追溯 tarball:7 个机制与升级前必查项

【免费下载链接】deepseek-harness-desktop为 DeepSeek Harness (DSH) 插件生态打造的现代化桌面端解决方案。万物皆「插件」,桌面本身也是「插件」。项目地址: https://gitcode.com/gh_mirrors/de/deepseek-harness-desktop

这篇讲 DeepSeek Harness Desktop 把@agents-anywhere/dsh-bridge-next以「固定版本内置」方式收编进仓库的完整做法:版本怎么命名、提交怎么锁定、tarball 怎么校验、aaEnabled开关怎么按 Profile 生效,以及合入一次上游更新前你必须跑完的验证动作。适合维护过桌面壳或打包管线、想给外部依赖上「追溯锁」的读者;读完你手里会有一套可直接照抄的锁定模式、命令场景表与升级 Checklist。

一个 tarball 的完整身份:内置包到底锁住了什么

DSH Desktop(dsh-plugin-desktop与dsh-plugin-desktop-beta两个变体)并不从 registry 安装 Agents Anywhere 的 bridge,而是把一个已经构建好的 tarball 直接放进仓库。先给结论:这个包的身份由「源码提交 + 校验和 + peer 范围」三元组共同定义,任何一环变化都会产出一个新版本。关键事实集中在vendor/agents-anywhere/这一个目录里:

  • 存放位置:vendor/agents-anywhere/,目录内含README.md、若干*.tgz历史产物和一份provenance.json。

  • 依赖声明:Desktop 变体以本地文件引用引入,例如 dsh-plugin-desktop/package.json:

    "@agents-anywhere/dsh-bridge-next": "file:../vendor/agents-anywhere/agents-anywhere-dsh-bridge-next-0.1.0-dev.0.desktop.c00df092c98b2.rcda81994.tgz"
  • 产物内容:Host 与浏览器(client)bundle、对应 source map,以及 Python Connector 源码。运行时不需要邻近的 AA checkout。

  • 源码零改动:provenance.json的sourceChanges始终为空数组,README 原话是 "The source code is unchanged"。

  • SHA-256 锁定:provenance.json记录产物的校验和,做到「source SHA + artifact checksum 精确定位到底发布了什么」。

scripts/prepare-agents-anywhere-release.mjs 每次准备产物时会重写provenance.json,字段含义如下(以仓库当前记录为例,最近一次准备提交为e53016f05be0e000d5e6b9dfe7c319d1a2d02d50):

字段含义
repository/branch/commitAA 源码来源:仓库地址、分支名、40 位提交 SHA
packageDirectory被打包的上游子目录,固定为dsh-bridge-next
sourceVersion上游原始版本号(如0.1.0-dev.0)
desktopVersion重写后写入产物的 Desktop 构建版本
artifact生成的 tarball 文件名
sha256产物校验和,锁定实际交付物
runtimePeers为 Desktop 两个运行时版本(0.1.5-rc.2与0.1.6-alpha.1)声明的显式 peer 范围
manifestChanges/sourceChangesmanifest 改动清单;源码改动清单(恒为空)

Desktop 版本号如何拼出来

versionForCommit(scripts/prepare-agents-anywhere-release.mjs)实现的命名算法是:

<major>.<minor>.<patch>[-<prerelease>.]desktop.c<commit前12位>.r<peer范围JSON的SHA-256前8位>
段来源例子
desktop前的基础版本上游sourceVersion0.1.0-dev.0
c段上游提交 SHA 的前 12 位c00df092c98b2、ce53016f05be0
r段JSON.stringify(peerRanges)的 SHA-256 前 8 位rcda81994、re9c8ad00

也就是说版本号同时键控于源码提交与Desktop peer 范围:两边任何一边动,就得到新版本号和新 tarball。旧产物从不删除——README 明确 "Old artifacts remain available",这正是vendor/agents-anywhere/下并排躺着多个*.tgz的原因。

从上游 commit 到 yarn.lock:一条单向数据流

把管线想成一条流水线,原料是 AA 上游仓库main分支的 HEAD,出口是「两个变体 package.json +yarn.lock+ 新 tarball + 新 provenance」。整条链如下:

  1. 解析源提交:DSH_AA_SOURCE_REF若是 40 位完整 SHA 直接使用;否则(默认main)对仓库执行git ls-remote解析出单一提交。
  2. 隔离 checkout:临时目录里git init、添加 remote、git fetch --depth=1 --no-tags origin <commit>后分离检出,再rev-parse HEAD校验与目标一致。
  3. 复制源码:只拷dsh-bridge-next与connector两个子目录,过滤.git、node_modules、.venv、__pycache__等噪声(copySourceTree)。
  4. 重写 manifest(patchManifest):版本号改为desktopVersion、删除 prepack/postpack 钩子、写入三个@deepseek-ai/*peer 范围。
  5. 构建链:依次yarn install --mode=skip-build、yarn build、yarn typecheck、yarn check:build,最后yarn pack --out产出唯一 tarball。
  6. 落账:生成/更新 vendor/agents-anywhere/provenance.json,把两个变体的依赖指到新 tarball,再回根目录跑一次yarn install --mode=skip-build更新 lockfile。

命令按场景记,而不是按脚本名记

入口只有两个(package.json):

"aa:check": "node scripts/prepare-agents-anywhere-release.mjs --check", "aa:prepare-release": "node scripts/prepare-agents-anywhere-release.mjs"

而dev、dev:beta、dist:*、package:dir*等命令统一先串yarn aa:prepare-release再进入各 workspace 的构建步骤,比如:

"dev": "yarn aa:prepare-release && yarn workspace dsh-community-market build && yarn workspace dsh-plugin-desktop dev", "dist:mac:beta": "yarn aa:prepare-release && yarn workspace dsh-community-market build && yarn workspace dsh-plugin-desktop-beta dist:mac"

按你实际想做的事对号入座:

日常开发——解析最新 AA 后直接起桌面端:

corepack yarn dev

正式发布——同样的前置步骤,出口换成打包:

corepack yarn dist:mac:beta

复现已提交的 AA 产物(不访问 GitHub):

DSH_AA_SOURCE_REF=pinned corepack yarn dist:mac:beta

指定精确提交而不是移动分支:

DSH_AA_SOURCE_REF=<40位commit> corepack yarn aa:prepare-release

只读检查远程是否有更新——aa:check仅用git ls-remote取main头部提交与provenance.json比对,输出 "AA is up to date." 或提示可更新,除此之外不做任何写操作:

corepack yarn aa:check

Windows PowerShell 下先设$env:DSH_AA_SOURCE_REF = 'pinned'再跑 Yarn,切回最新构建前记得删掉这个变量。

环境变量与取值约束

变量默认值接受值作用
DSH_AA_SOURCE_REFmain分支名 / 40 位完整 commit SHA /pinned指定 AA 源码来源;pinned表示直接用已提交 tarball
DSH_AA_SOURCE_REPOSITORYAA 公开 GitHub 仓库任意 git 仓库 URL(如带认证的 SSH 地址)更换 AA 源码仓库来源
DSH_VERIFY_AA未设置1开启配合verify:profile启用无头冒烟验证

细节两处:脚本解析提交时会设GIT_TERMINAL_PROMPT=0,防止 CI/无交互环境下卡在凭证提示;单条命令超时上限 600 秒。

用户在产品里经历什么:从开关到 bundle 注入

界面侧只有一个开关:设置里的「开启手机连接 / Turn on phone connection」,用户打开后从侧边栏「手机连接」入口完成后续配置(文案见 dsh-plugin-desktop/src/client/desktop-settings-locales.ts 与 dsh-plugin-desktop/src/setup-wizard-copy.ts)。开关背后是一条完整链路:

  1. 存储:aaEnabled是每个 Profile 的 Desktop 偏好,默认false,与「市场提供方」的选择互相独立(dsh-plugin-desktop/src/profile-preferences.ts)。类型校验严格——必须是 boolean。
  2. 默认即关,且显式地关:旧偏好与首次运行都禁用;跳过 Setup 向导会显式保存禁用(dsh-plugin-desktop/src/setup-wizard-window.ts 中 URL 无aaEnabled参数时取false);Safe Mode 无条件排除(dsh-plugin-desktop/src/safe-mode.ts 写死aaEnabled: false)。读取处与 Safe Mode 路径联动(dsh-plugin-desktop/src/main.ts):safeModePaths === undefined && profilePreferences?.aaEnabled === true。
  3. 修改即重启:改这个选项会先确认持久化,再调度一次 Desktop 重启。
  4. 解析:启用后 dsh-plugin-desktop/src/profile.ts 先把AA_PACKAGE_NAME加进选中 bundle 列表(if (aaEnabled && !selectedBundles.includes(AA_PACKAGE_NAME)) ...),再用与 dshmarket 相同的 Desktop/Profile 包 overlay(resolveOverlayPackage,以INSTALL_ANCHOR与 Profile 的package.json为基址)解析出该包。
  5. 补丁合成:prepareDesktopProfile读取包内package.json的dsh.bundle.patch字段(缺失或非字符串直接判失败),从 AA bundle 补丁中合成条目,要求恰好一个未禁用的 canonical entry(row.id === 'agents-anywhere-bridge-next'且row.name === AA_PACKAGE_NAME,行数必须为 1)。AA 自己声明的补丁被原样保留,Desktop 只补两样:真实dshHome与connectorSourceDir;Connector 目录的app.asar段被重写为app.asar.unpacked(ASAR unpacked 路径),并校验pyproject.toml存在,确保 Python 源码随产物落地。
  6. 状态不重写:Desktop不重写 AA 的stateRoot,也不为每个 Profile 发明独立 DSH home。AA 自己持有登录、设备配对、账户存储和原生运行时端点,所以它的原生账户/设备状态可以跨 Profile 复用;而 Desktop 的启用/禁用偏好仍按 Profile 隔离——两层彻底解耦。dsh-plugin-desktop/scripts/verify-profile-boot.mjs 里有对应断言:启用 AA 后它必须在 DSH home 下发布agents-anywhere/bridge/endpoint.json,且全新 Profile 继承到任何既有 AA 账户("A fresh Profile inherited an AA account")直接判失败。

坏掉的时候发生了什么

管线的失败策略是fail-closed:宁可整体失败,也不静默发布旧插件。把可能出问题的环节逐个过一遍:

  • 如果网络、源码构建或依赖安装任何一步失败,就中止整个打包,并把四个文件快照还原:dsh-plugin-desktop/package.json、dsh-plugin-desktop-beta/package.json、yarn.lock、vendor/agents-anywhere/provenance.json,同时删掉未发布的临时 tarball。

  • 如果还原时根目录安装已经开始,就需要手动补一刀恢复:

    corepack yarn install --immutable
  • 如果上游带prepack/postpack钩子,就在patchManifest阶段被显式删除——release 构建只跑显式的 build/typecheck/check:build。

  • 如果存在与 AA 配置冲突的用户补丁("conflicting AA configuration was removed"),就触发失败。

  • 如果Connector payload 缺失(找不到pyproject.toml)、bundle 缺失或格式错误、canonical entry 非法(非单一、非启用、ID/name 不匹配),就让该次 generation 的 AA 整体失效。

预检的边界要说清楚:它只覆盖上述确定性问题,不会抑制插件在 Cordis 初始化阶段稍后抛出的任意错误。源码侧,AA 层加载抛错被捕获为aaFailure(dsh-plugin-desktop/src/profile.ts)而不阻断其余 bundle;dsh-plugin-desktop/src/host-bootstrap.ts 通过readAa()暴露{ requested, effective }对,让上层能感知「请求了但未生效」。失败会写诊断,Settings 界面给出retry(重试)动作。

pinned 模式:离线复现已提交产物的唯一通道

DSH_AA_SOURCE_REF=pinned走完全不同的路径:不发起任何网络请求,直接校验已提交 tarball 的 SHA-256 与provenance.json记录一致(不一致即抛错)。它要求依赖已先正常安装(因为跳过了安装步骤),这也是复现 CI 验证已提交 pin 的标准姿势。

怎么证明它没坏:三层验证

无头冒烟:verify:aa 怎么跑

Desktop 的check脚本链里包含 dsh-plugin-desktop/package.json 定义的verify:aa,底层是DSH_VERIFY_AA=1 node scripts/verify-profile-boot.mjs。dsh-plugin-desktop/scripts/verify-profile-boot.mjs 是个无头冒烟:在临时 home 里调用真实的prepareDesktopProfile组装完整 DSH Web Profile,然后分两路断言——

  • DSH_VERIFY_AA=1:以启用 AA 组装,断言 client 依赖图包含@agents-anywhere/dsh-bridge-next,且 Host 侧agentsAnywhereRuntime、agentsAnywhereOnboarding两个能力均已激活;
  • DSH_VERIFY_AA_BROKEN=1:注入一个损坏的 AA 包(版本99.0.0、patch 指向不存在的missing.patch.yml),断言aaFailure存在且aaEnabled为 false——失败关闭路径被直接测到。

其余断言覆盖 Profile 服务、agent presets、目录选择器、Web 认证 URL、renderer 清单等。

定向测试

dsh-plugin-desktop/tests/host-process-integration.spec.ts 以aaEnabled: false/true两种状态启动真实 Web Host;dsh-plugin-desktop/tests/client-aa-settings.spec.ts 校验设置界面文案。

历史验证记录:只对其命名提交有效

README 的 Validation history 记了两轮:

  • 当前产物由发布脚本从 AA v2 提交c26402633cb840d376048b0bdb42c2db59e7cb33准备:build/typecheck/build-artifact 检查通过,两个 Desktop 变体均通过真实 AA Host/client Profile 加载,重复准备复用了已验证产物;该轮未测试签名 Electron 包与交互式设备 onboarding。
  • 上一轮手工准备来自 AA v2 提交ae47731c50f02033728faed1ba55f95c8008ec86,包含匹配的 Python Connector 源码,修复了 fresh login 时的 deleted-device recovery、Windows discovery(避免os.kill(pid, 0))、Windows 安全的pwd导入。该轮在隔离源码导出中通过 TypeScript 检查、Host/client 构建、build artifact 与真实 Client factory DOM 检查;全部 111 个插件测试以--test-concurrency=1通过,35 个定向 Connector 测试通过(含 Windows 回归测试);其中包含受控的 Python/后端集成测试,但不含交互式真实模型、手机或原生 Windows 验收测试。

注意一个容易踩的点:provenance.json记录的最近准备提交(e53016f05be0e000d5e6b9dfe7c319d1a2d02d50,artifact...ce53016f05be0.re9c8ad00.tgz)与dsh-plugin-desktop/package.json当前 pin 的c00df092c98b2产物不是同一个——多个历史 tarball 并存正是「旧产物保留」策略的体现。验证历史只对各自命名的提交有效("The historical validation below applies only to its named commit")。

升级合入前的 4 步 Checklist

预检不保证兼容未来所有 AA 变更,合入前逐条过:

  1. 两个变体都跑真实验证:

    DSH_VERIFY_AA=1 corepack yarn workspace dsh-plugin-desktop verify:profile DSH_VERIFY_AA=1 corepack yarn workspace dsh-plugin-desktop-beta verify:profile
  2. 确认 Connector 落盘位置:源码被解包到app.asar之外(app.asar.unpacked),并用匹配的 AA Server/Web 实测 onboarding。

  3. Review 并提交四类变更:两个变体的依赖声明、yarn.lock、provenance.json、新 tarball 产物。

  4. 认清边界:这组检查不构成对任意未来 AA 变更的兼容性保证;每轮验证结论只适用于该轮命名的提交。

Connector 运行时还有几个前置条件容易被忽略:uv必须在PATH中或通过UV_PATH显式给出;需要 Python 3.12+;首次启动可能下载 Python 依赖。另注意区分两个包:内置的@agents-anywhere/dsh-bridge-next归本文机制管辖;旧版@agents-anywhere/dsh-bridge是独立用户插件,不受该选项管辖,它的配置不会被迁移或删除。更早的集成方式曾把 AA 账户写进每个 Profile 的agents-anywhere目录,这些文件被保留但不再自动选中,用户可能需要在 AA 原生 state 目录登录一次——两个布局之间不会静默复制任何账户、凭据或设备绑定。

这套「vendor 内嵌 + 提交锁定 + SHA-256 校验 + 显式 peer 声明 + 无头冒烟回归」的组合,把外部依赖包变成了可追溯、可复现、可回滚的构建单元。真正值得借鉴的是它划边界的方式:Desktop 从不发明独立的 DSH home,让 AA 原生状态跨 Profile 自主复用,而桌面偏好按 Profile 严格隔离——把第三方运行时的主权还给第三方,比集成细节本身更关键。

【免费下载链接】deepseek-harness-desktop为 DeepSeek Harness (DSH) 插件生态打造的现代化桌面端解决方案。万物皆「插件」,桌面本身也是「插件」。项目地址: https://gitcode.com/gh_mirrors/de/deepseek-harness-desktop

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

返回列表