news 2026/9/20 13:27:36

DeepSeek Harness 源码级 Vendor Cordis:把框架层完全握在自己手里的工程实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
DeepSeek Harness 源码级 Vendor Cordis:把框架层完全握在自己手里的工程实践

DeepSeek Harness 源码级 Vendor Cordis:把框架层完全握在自己手里的工程实践

【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址: https://gitcode.com/gh_mirrors/de/deepseek-harness

导读

DeepSeek Harness 构建于 Cordis 框架之上,但并没有把 Cordis 当作普通的 npm 依赖引入,而是将框架核心与基础库以固定 commit 的源码快照形式直接复制进仓库的vendor/目录,通过 pnpm workspace 的linkWorkspacePackages机制让全仓库(包括构建产物)透明地解析到这份自持的源码。这篇文章以仓库中的 技术决策记录(ADR) 为主线,结合 vendor/README.md 的清单与修改日志、pnpm-workspace.yaml 的解析机制、以及scripts/下的机械化守卫脚本,完整还原"为什么 vendor、vendor 了什么、如何保证 vendor 纪律、如何同步与新增"这一整套工程方案。读完你不仅能理解这套做法的动机与代价,还能直接照着仓库里的清单与 cookbook 复现同款流程。

背景与问题:为什么框架层不能直接"npm install"

框架内部行为就是产品正确性的一部分

DeepSeek Harness 是一个 agent harness(智能体执行框架),其核心的 agent loop(智能体循环)建立在 Cordis 框架之上。仓库启动这个工程时,Cordis core 处于4.0.0-rc.6(release candidate,候选发布版)——一个尚未正式发布的版本。

问题的关键在于:harness 依赖的不是 Cordis 的"公开 API",而是框架的内部实现细节

  • fiber 生命周期(fiber lifecycle):Cordis 中一个插件挂载单元(fiber)从加载、激活到卸载的完整生命周期管理;
  • effect disposal(资源释放):effect(副作用)在 fiber 卸载时如何被收集、回滚与清理;
  • waterfall 分发(瀑布式事件分发):事件沿着事件链逐级传递并允许中途否决(veto)的分发机制。

agent loop 的正确性保证(比如"一轮工具调用结束后所有资源必须被确定性释放""某个事件可以被下游拦截")直接取决于这些内部行为的确切表现。而一个 RC 版本意味着上游随时可能在不打招呼的情况下调整这些内部语义。

直接依赖 npm 包的风险

决策记录明确否决了"直接依赖 npm 包"这条最省事的路线,理由非常直接:

  • core 处于候选发布阶段,上游 RC 一次 bump 就可能破坏 harness 依赖的内部行为;
  • 一旦破坏,由于框架行为被封装在 node_modules 里,项目没有一条本地的修复路径——只能干等上游发布修复版本,或者被迫 fork 后切换依赖源,而这又会引入新的不确定性。

这正是经典的"依赖锁定"困境:锁版本号锁得住 semver,锁不住"同一版本号下内部实现是否被我们真正控制"这件事。对于把框架内部语义当作正确性契约的项目,唯一彻底的解法就是把源码本身拿过来。

决策:以源码形式 Vendor 框架层

收录范围:框架层全收,第三方依赖留在 npm

决策的核心是"只持有我们依赖其内部实现的框架层",而不是递归地把依赖树全部复制进来。最终的收录范围落在vendor/目录下,共 9 个包(目录布局见 vendor/):

目录npm 名(发布用)上游名上游版本角色
vendor/cordis/@deepseek-ai/cordiscordis4.0.0-rc.7框架核心:ContextServiceFiber、事件
vendor/cosmokit/@deepseek-ai/cosmokitcosmokit1.8.1框架与 Schemastery 依赖的共享工具库
vendor/schemastery/@deepseek-ai/schemasteryschemastery3.18.0配置 schema(Schema),支撑每个插件的Config
vendor/loader/@deepseek-ai/cordis-plugin-loader@cordisjs/plugin-loader1.0.0-rc.5cordis.yml加载、插件解析、仓库缓存
vendor/include/@deepseek-ai/cordis-plugin-include@cordisjs/plugin-include1.0.4配置 include 与 patch 覆盖层
vendor/group/@deepseek-ai/cordis-plugin-group@cordisjs/plugin-group1.0.0嵌套插件组
vendor/timer/@deepseek-ai/cordis-plugin-timer@cordisjs/plugin-timer1.1.2可随 fiber 释放的ctx定时器
vendor/hmr/@deepseek-ai/cordis-plugin-hmr@cordisjs/plugin-hmr1.0.15插件与配置的热更新
vendor/logger-console/@deepseek-ai/cordis-plugin-logger-console@cordisjs/plugin-logger-console1.0.0控制台日志导出器

真正第三方的依赖js-yamlchokidar@standard-schema/specpicomatch@babel/code-framesupports-colornode-addon-require-builtin等)依然留在 npm 上,由 pnpm 正常解析。同时清单还明确记录了刻意不收录的包:reggol@cordisjs/utils@cordisjs/element@cordisjs/unyaml(后者只是 dev-time 的 YAML 导入钩子,与运行时无关)。

布局:扁平化 + 保留上游版本号

Vendor 目录采用扁平化布局vendor/<目录>/下直接是src/package.jsontsconfig.jsonREADME.mdLICENSE,一个包一层,没有嵌套的 workspace 前缀。目录名与上游版本号刻意保持与上游一致(比如vendor/cordis/的 manifest 记录上游版本 4.0.0-rc.7),这样 vendor/README.md 里的清单读起来仍然是一份"上游快照",同步时 diff 一目了然。

值得注意的是,最初 ADR 决定"保留原始 npm 包名",但后续的 rescope 决策(见 docs/rescope.md 与 .agents/notes/implemented/process/2026-08-10-vendor-package-rescope.md)将 9 个包全部改名为@deepseek-aiscope。原因是:harness 的每个包都把cordis声明为 peerDependency,发布 harness 就意味着连带发布这层框架;如果沿用上游原名,发布行为相当于在 npm registry 上抢占(squat)上游的包名。改名只动包名,目录名、上游版本号、依赖范围、上游运行时标识符(如 Schemastery 的Symbol.for('schemastery'))全部不变

透明解析的关键:linkWorkspacePackages: true

Vendor 能否"透明"工作的核心机制在 pnpm-workspace.yaml:

packages: - vendor/* - packages/*/* - native/landlock-run - native/landlock-run/packages/* - apps/* - website - python/sdk-runtime # Vendored framework packages keep their upstream semver ranges, while local # builds must resolve those matching names to this workspace's pinned sources. linkWorkspacePackages: true

vendor/*直接进了 workspace 列表,而linkWorkspacePackages: true意味着:只要某个依赖声明的 semver 范围与某个 workspace 包的名字+版本匹配,pnpm 就把它解析到这个 workspace,而不是去 registry 拉取同名包。由于 vendored 包保留了上游的版本号(如^4.0.0-rc.7),所有 harness 包对框架的依赖声明会原样命中这些固定的 workspace——无论是以 TypeScript 源码跑测试,还是构建后的lib/产物被引用,解析结果都是同一份 vendored 源码。

这一点在 vendor/cordis/package.json 中有直接体现:内部依赖写的是"@deepseek-ai/cosmokit": "workspace:^"、可选 peer 依赖"@deepseek-ai/cordis-plugin-loader": "workspace:^",全部显式锚定到 workspace,杜绝任何 registry 副本混入的可能。

Manifest 即契约:vendor/README.md 与机械化守卫

清单表:每个包一个 commit SHA

vendor/README.md 是这层框架的权威 manifest,开头即说明收录动机:"copied into this monorepo instead of being depended on via npm, so that the harness fully owns its framework layer (auditable, patchable, pinned)"(可审计、可打补丁、版本锁定)。清单表为每个包记录 6 个字段:目录、npm 名、上游名、版本、上游仓库、commit SHA。例如:

  • cordis/:上游cordis,4.0.0-rc.7,commit56b3d4f725681cf4556c1a8695a709cc3b6eed74(cordiverse/cordispackages/core);
  • cosmokit/:上游cosmokit,1.8.1,commit16f6fc058ade66e8ac5da0033d35a8d0f279f544
  • hmr/include/group/timer/logger-console/:统一锚定 commitabb0a307cb1d3b0947f455d590cf5ba922d4caa4

有了"包 → 上游仓库 → commit"的精确映射,任何一次本地改动都能回溯到它基于的上游基线,"diff 表面"始终是已知的。

修改日志:本地与上游的每一处分歧都必须登记

Manifest 的第二部分是详尽的本地修改日志(Local modifications),目前记录到第 18 条,覆盖了package.json重建、tsconfig.json重建、TypeScript 内部导入 specifier 改造、hmr 的 locale-YAML 移除,以及一批深层的框架行为补丁(后文详述)。这条日志的纪律是"保持穷尽——每一处与上游的分歧都必须列出"。这份日志同时是同步时的"重放清单":上游更新后,哪些补丁需要重新应用、哪些可以丢弃,一目了然。

三条机械化防线

让"vendor 纪律"不依赖人肉自觉,仓库用三个脚本把它变成了硬约束:

1. pre-commit 守卫 scripts/check-vendor-manifest.sh

staged=$(git diff --cached --name-only) vendor_src_changed=$(echo "$staged" | grep -E '^vendor/[^/]+/(src/|bin\.js)' || true) manifest_changed=$(echo "$staged" | grep -x 'vendor/README.md' || true) if [[ -n "$vendor_src_changed" && -z "$manifest_changed" ]]; then echo 'vendor manifest guard: vendored SOURCE changed without updating vendor/README.md:' ... exit 1 fi

逻辑简单但有效:任何暂存区里vendor/*/src或 vendoredbin.js的改动,必须同时包含vendor/README.md的改动,否则提交被拒绝。该脚本已挂进 lefthook.yml 的pre-commit任务(job 名为vendor manifest guard),与 lint、第三方法务声明(third-party notices)等检查并列。

2. lockfile 解析校验 scripts/verify-vendored-links.ts

这是 hygiene(卫生)门禁。它扫描pnpm-lock.yaml

  • 对每个 importer 里出现的 vendored 包名,断言其versionlink:开头——否则构建会在不知不觉中使用 registry 副本;
  • packages/snapshots区段,断言不存在以 vendored 包名为前缀的 registry 条目(如@deepseek-ai/cordis@4.0.0-rc.7)。

它把"移除 workspace 链接后构建产物会静默改用 npm 副本"这类隐患直接堵死:linkWorkspacePackages一旦失效,这个门禁会在 CI 里报错,而不是等到运行时出现难以排查的框架行为漂移。

3. rescope 校验 scripts/rescope-vendor.ts

rescope 脚本同时承担改名与校验:pnpm run rescope-vendor --check断言改名后无残留、每条 exact edit 都命中、再次--apply是幂等的。它有一个重要设计:只重写带定界符的完整包名 token(引号包裹的'cordis'"cordis/subpath"、YAML 的name: cordis),从而天然排除cordis.yml、Loader 的cordis:协议前缀、cordisagent preset id、cordiverse/cordis等"恰好含这个词但并非包引用"的场景,改名的精确性由脚本而非人肉保证。

本地修改日志里的关键工程补丁

Manifest 的修改日志记录了 18 条本地分歧,其中几条值得单独展开,因为它们直接服务于 agent harness 的核心正确性:

  • fiber 生命周期加固(日志第 6 条,cordis/src/fiber.ts:本地封堵了三处重入式(reentrant)释放漏洞——effect 的 owner 列表包装器在 setup 执行体运行前注册,使得"从 setup 内部发起的卸载"能等待 setup 与所有已收集的 cleanup;同步 setup 失败时移除包装器并回滚已收集的 cleanup;fiber 处于UNLOADING状态时拒绝创建新 effect(PENDING/LOADING仍合法),防止清理期注册逃出卸载快照。此外Fiber.update()现在返回internal/updatewaterfall 的结果,使 Loader 调用方在保持同步配置校验的同时可以await一次重启。
  • 事务化 Loader/Include 配置对账(日志第 8 条):Loader 先导入变更后的 entry 再释放旧者,候选应用失败时恢复原插件/配置;Group 更新并发启动候选、等待所有结果,并在活更新失败时撤销变更;Include 只在成功后才提交缓存内容。这些行为由 packages/boot/app-boot/tests/config-reload.spec.ts 等测试覆盖。
  • HMR 精确配置监听与初始扫描抑制(日志第 9、12 条)registerConfig()监听模块根之外的绝对配置路径、序列化并合并刷新、返回可释放的异步 disposer;主 watcher 使用ignoreInitial: true,避免启动阶段刚消费过的文件被重复 announce、以及 Include 初始化中途被刷新导致死锁(曾出现退出码 13 且无诊断的故障)。
  • applyEntryPatches导出(日志第 11 条):把 Include 的私有补丁应用逻辑抽取为纯函数导出,使dsh --dump-config能在不启动整棵 fiber 树的情况下精确打印 Include 挂载后的配置,配置工具永远不需要(也不会)重实现补丁算法。
  • 懒加载配置解析(日志第 15 条):移植上游 PR(cordiverse/cordis#41),原始 fiber 配置仅在声明注入激活后才通过internal/config解析,保证disabled: !!js这类表达式在正确的上下文里求值。

这些补丁大多不是"改 bug",而是把框架语义加固到 agent harness 需要的强度——这正是"拥有框架层"的价值:你可以直接在仓库内修框架,而不是去上游开 issue 然后等待。

上游同步与新增包:两条被写下来的流程

同步既有包的五步流程

Manifest 末尾写明了手动的同步过程(因为上游同步是刻意保持手动的,以控制 diff 面):

  1. 在上游 workspace 记录相关子模块的git rev-parse HEAD
  2. 把包的src/(以及变更的bin.jsREADME.mdLICENSE)复制覆盖到 vendored 目录;
  3. 重新应用上述本地修改(若上游已使其不再必要则删除对应日志条目——无论如何都要更新日志);
  4. 更新清单表中的版本与 commit hash;
  5. 在仓库根执行pnpm install && pnpm run test && pnpm run build

同步后还需执行 rescope 的重新应用(pnpm run rescope-vendor --apply)以及它提示的连锁操作:pnpm install更新 lockfile、pnpm run gen-third-party-notices重生成第三方声明、pnpm run verify-translation-pairing --write重新记录受影响的双语文档对。

新增一个 vendor 包的 checklist

当 harness 需要另一个上游 Cordis 包(例如@cordisjs/plugin-http)时,docs/cookbook/adding-a-vendored-package.md 提供了逐文件清单,核心步骤:

  1. 复制源码vendor/<dir>/下放src/(上游原样)、package.json(改名 rescope、保留exports/type、声明元数据指向lib/typespublishConfig.access: public)、tsconfig.jsonextends仓库根tsconfig.base.jsonrootDir: src,并为依赖的其他 vendored 包声明references);
  2. 注册到根配置:在 tsconfig.base.json 的paths加一项"<npm-name>": ["./vendor/<dir>/src"]、在 tsconfig.host.json 的references加一项、在vendor/README.md清单表加一行并登记本地修改;vendor/*等 glob 覆盖的 workspace/构建/vitest 配置则无需改动;
  3. 注意 manifest 守卫vendor/*/src的暂存变更必须与vendor/README.md的暂存变更同 commit;
  4. 验证pnpm install注册 workspace,然后pnpm run typecheckpnpm run build && pnpm run constraints,再按 docs/testing.md 的选择运行行为测试。

cookbook 特别强调了一个边界事实:vendor 一个包往往意味着 vendor 它的依赖树(例如@cordisjs/plugin-http会拉入@cordisjs/fetch-file),这与"真正的第三方依赖留 npm"的分界线并不冲突——分界线是"我们是否依赖其内部实现"。

后果与权衡:这套方案的收益和代价

按决策记录总结,这套方案换来的是四条明确的收益:

  • 框架层完全自持:可审计、可打补丁、版本锁定。上游 RC 无法再导致本项目故障,框架 bug 可以在仓库内直接修复——这正是本地修改日志里 18 条补丁存在的意义;
  • 源码与产物执行同一份框架:构建后的包与源码测试运行的是同一代 vendored Cordis;反过来,一旦移除 workspace 链接,构建产物会在包名不变的情况下静默改用 npm 副本——这正是verify-vendored-links门禁要拦截的失效模式;
  • diff 面始终可知:commit SHA 清单 + 穷尽式修改日志,让"本地相对上游改了哪里"永远可审计;
  • 第三方依赖保持正常供应链js-yamlchokidar等仍由 npm 解析,没有把整个依赖树都拖进源码库。

对应的代价与约束也写在文档里:

  • 上游同步是手动的,需要按 manifest 流程逐包操作并重放补丁——这是换取"可控"所付出的运维成本;
  • vendored 包保留上游代码风格,lint 与严格性门禁将它们排除(其tsconfig.json本地放宽了仓库较新的编译器选项,如noUncheckedIndexedAccessexactOptionalPropertyTypes等);
  • 名称必须 rescope@deepseek-ai,否则发布 harness 会在 registry 上抢占上游包名——这带来一套额外的改名/校验工具链。

从仓库现状看,这套决策不是纸面文档:vendor/下 9 个包的真实源码、18 条修改日志、三个守卫脚本、两份流程文档(manifest 的同步流程与 cookbook 的新增流程)全部落地且互相引用。对于"框架内部行为即正确性契约"的工程,这正是"everything is a plugin"背后的地基——先把地基握在自己手里,再谈插件化。

进一步阅读

  • 决策原文(英文):.agents/notes/implemented/process/2026-06-11-vendor-cordis-as-source.md(中文:.zh.md)
  • 包清单、修改日志与同步流程:vendor/README.md
  • workspace 解析与安全策略:pnpm-workspace.yaml
  • 守卫脚本:scripts/check-vendor-manifest.sh、scripts/verify-vendored-links.ts、scripts/rescope-vendor.ts
  • 名称映射与 rescope 说明:docs/rescope.md
  • 新增 vendor 包的操作指南:docs/cookbook/adding-a-vendored-package.md
  • 门禁挂接点:lefthook.yml

【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址: https://gitcode.com/gh_mirrors/de/deepseek-harness

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 13:26:04

基于Python的兵棋推演游戏源码解析与二次开发指南

简介&#xff1a;这是一份基于Python实现的兵棋推演游戏源码&#xff0c;面向对人工智能与战略模拟感兴趣的开发者&#xff0c;可用于学习智能体通信、指令处理与可视化推演流程。资源共35个文件&#xff0c;包括33个Python脚本、1个txt及1个markdown说明&#xff0c;压缩包仅1…

作者头像 李华
网站建设 2026/9/20 13:25:15

Phoenix 项目 Elixir 编码规范实战指南:从代码风格到高可靠测试

Phoenix 项目 Elixir 编码规范实战指南&#xff1a;从代码风格到高可靠测试 【免费下载链接】phoenix Peace of mind from prototype to production 项目地址: https://gitcode.com/gh_mirrors/ph/phoenix 本篇技术指南基于 Phoenix 框架仓库的 usage-rules/elixir.md 编…

作者头像 李华
网站建设 2026/9/20 13:24:45

OpenClaw 请求 401?TaoToken 这样核对 API 地址

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 13:20:47

蓝鲸PaaS APM服务实战:svc-otel让蓝鲸应用性能问题无所遁形

蓝鲸PaaS APM服务实战&#xff1a;svc-otel让蓝鲸应用性能问题无所遁形 【免费下载链接】blueking-paas 蓝鲸智云 PaaS 平台是一个开放式的开发平台&#xff0c;让开发者可以方便快捷地创建、开发、部署和管理 SaaS 应用。它提供了完善的前后台开发框架、服务总线&#xff08;E…

作者头像 李华