Codex 教程
按顺序阅读,循序渐进掌握相关 AI 工具与实战方法。
此前我们一直用 --patch overlay 挂载本地插件,本章开始把它们打包成可安装、可分发的组合包。DeepSeek Harness 的安装体系建立在两个基础概念上:bundle(组合包)与 profile,二者都靠一份 package.json 承载,但在 dsh 键下声明的 manifest 各不相同。
dsh.bundle,回答“这个包贡献什么”——一个用于插入或覆盖插件行的 patch 文件。它由插件作者编写并随包分发。$DSH_HOME/profiles/<name> 的目录,manifest 声明 dsh.profile,回答“这套配置由哪些 bundle 按什么顺序组成”。它由 dsh plugin 自动创建维护,用户通过 dsh --profile <name> 启动。二者职责互斥:没有任何东西同时是 bundle 和 profile;profile 也始终位于安装目录之外。
先建包目录 mkdir -p hello-plugin,组合包只含三个文件:
hello-plugin/
├── package.json # 声明 dsh.bundle
├── cordis.patch.yml # profile 引用该 bundle 时应用的配置层
└── index.js # patch 行引用的插件模块
package.json 中声明组合包 manifest:
{
"name": "dsh-hello-plugin",
"version": "0.1.0",
"type": "module",
"main": "index.js",
"files": ["index.js", "cordis.patch.yml"],
"dsh": { "bundle": { "patch": "./cordis.patch.yml" } }
}
其中 name 决定 Node 模块解析如何找到已安装代码,files 限定发布内容,dsh.bundle.patch 是核心:声明本包贡献的 patch 文件路径。插件入口保持最简形态:
// hello-plugin/index.js
export const name = 'hello-plugin'
export function apply() {
console.log('[hello-plugin] plugin loaded!')
}
patch 文件与之前使用的 --patch overlay 结构完全同构,唯一差别是插件行按包名而非相对源码路径引用:
# hello-plugin/cordis.patch.yml
- insert:
- id: hello
name: dsh-hello-plugin
安装后 pnpm 会把包链接进 node_modules,Node 的模块解析才能按包名定位代码。若包没有 dsh.bundle 声明,仍可安装,但只作为普通依赖,dsh plugin 会打印警告且不激活任何层——供插件 import 的库就该用这种形态。
profile 目录包含 package.json(声明树外插件依赖与 dsh.profile 的有序 bundles 列表)和用户自己的 cordis.patch.yml(在每个组合包层之后应用)。profile manifest 永远不需要手写,由 dsh plugin 负责维护。
进阶玩法:定义了可运行应用的组合包可以挂载一个普通提供方插件来持有自己的命令行。该提供方导出 inject = ['cmdlineArgs'],用自己的 commander program 调用 parseCmdline,再在 action 中把应用自有服务提供出去:
# 挂载提供方插件:name 指向 bundle 包内的 startup 模块
- id: hello-startup
name: 'dsh-hello-plugin/startup'
# 端口号取自提供方服务,取不到则回退 8080
- id: my-app
name: '@example/my-app'
inject: [myAppStartup]
config:
port: !!js ctx.myAppStartup.port ?? 8080
启动器把同一份不可变参数交给每个插件,因此新增应用专属 flag 无需改动启动器;遇到 --help 时提供方不发布服务,这些行不会激活。Loader 只挂载一次组合,先等待各行的普通注入完成,再基于已注入的上下文求值 !!js 配置。
bundle 声明 dsh.bundle 回答“贡献什么”,profile 声明 dsh.profile 回答“由哪些 bundle 组成”,两者共用 package.json 但 manifest 不同;profile 的 manifest 由工具维护,用户只管启动。