Bundle
dsh-plugin-practice
Practice bundle for learning DeepSeek Harness plugin development
- Source
- Ri0n72Y
- License
- MIT
- Updated
- Updated 7 days ago
Readme
# dsh-plugin-practice
用于学习 DeepSeek Harness / Cordis 插件开发的最小练习仓库。代码按课程逐步累积,同时也可以作为一个标准 DSH Bundle 安装进 profile。
当前内容覆盖:Plugin lifecycle、Tool、Config、Service / Consumer、Event、waterfall middleware。
## 当前结构
```text
dsh-plugin-practice/
├── src/
│ ├── plugin.ts
│ ├── workspace-info.ts
│ ├── configurable-greet.ts
│ ├── workspace-name-service.ts
│ ├── workspace-name-tool.ts
│ ├── workspace-event-contract.ts
│ ├── workspace-event-emitter.ts
│ ├── workspace-event-listener.ts
│ ├── workspace-transform-contract.ts
│ ├── workspace-transform-uppercase.ts
│ ├── workspace-transform-block.ts
│ └── workspace-transform-tool.ts
├── cordis.patch.yml
├── cordis.dev.patch.yml
├── package.json
├── tsconfig.json
└── tsdown.config.ts
```
`cordis.patch.yml` 是正式 Bundle 使用的 patch;`cordis.dev.patch.yml` 用于直接加载本地 TypeScript 源码。
## 环境要求
- Node.js `^22.19.0 || >=24.0.0`
- pnpm(仓库声明 `pnpm@11.7.0`)
- 本机已经安装可直接执行的 `dsh` CLI
先运行:
```sh
dsh --help
```
确认 CLI 可用。
## 本地开发与一键部署
克隆仓库并安装依赖:
```sh
git clone https://github.com/Ri0n72Y/dsh-plugin-practice.git
cd dsh-plugin-practice
pnpm install
```
日常开发完成后,直接执行:
```sh
pnpm deploy
```
`deploy` 在 `package.json` 中定义为:
```json
{
"scripts": {
"deploy": "pnpm run prepare && dsh plugin --profile practice add ."
}
}
```
因此一条命令会完成:
```text
src/*.ts
→ pnpm run prepare
→ tsdown 构建 lib/*.js
→ dsh plugin --profile practice add .
→ 当前 checkout 安装 / 更新进 practice profile
```
然后启动 DSH:
```sh
dsh --profile practice
```
如果想先检查最终组合配置:
```sh
dsh --profile practice --dump-config
```
默认开发 profile 固定为 `practice`;需要修改时直接调整 `package.json` 中的 `deploy` script。
## 直接使用 DSH 官方命令安装
`pnpm deploy` 只是把构建和官方安装命令串起来。真正负责插件安装和 profile 管理的仍然是 DSH:
```sh
dsh plugin --profile practice add .
```
DSH 也支持直接安装 Git 仓库:
```sh
dsh plugin --profile practice add github:Ri0n72Y/dsh-plugin-practice
```
本仓库是 TypeScript 包,因此 `package.json` 提供了 `prepare`,供 Git 安装后从 `src/` 构建 `lib/`。pnpm 10+ 第一次安装 Git 依赖时可能要求在 profile 的 `pnpm-workspace.yaml` 中通过 `allowBuilds` 授权构建脚本。
## Bundle manifest
`package.json` 通过官方约定声明当前包是一个 DSH Bundle:
```json
{
"dsh": {
"bundle": {
"patch": "./cordis.patch.yml"
}
}
}
```
正式 patch 通过包导出路径加载构建后的插件:
```yaml
- insert:
- id: practice-workspace-info
name: 'dsh-plugin-practice/workspace-info'
```
安装关系是:
```text
pnpm deploy
→ prepare / build
→ dsh plugin add .
→ package.json / dsh.bundle
→ cordis.patch.yml
→ dsh-plugin-practice/<subpath>
→ lib/*.js
```
## 源码开发 / overlay 模式
如果希望直接加载 `.ts` 文件,可以使用 `cordis.dev.patch.yml`。
先把其中的:
```text
/ABSOLUTE/PATH/TO/dsh-plugin-practice
```
替换为仓库真实绝对路径,然后运行:
```sh
dsh web --patch /ABSOLUTE/PATH/TO/dsh-plugin-practice/cordis.dev.patch.yml
```
如果从 DeepSeek Harness 源码仓库运行 CLI:
```sh
pnpm dsh web --patch /ABSOLUTE/PATH/TO/dsh-plugin-practice/cordis.dev.patch.yml
```
## 当前课程内容
| Lesson | 文件 | 核心概念 |
|---|---|---|
| 1 | `src/plugin.ts` | `apply(ctx)`、`ctx.effect()`、disposer、插件生命周期 |
| 2 | `src/workspace-info.ts` | `inject = ['tools']`、`defineTool()`、参数与 canonical output |
| 3 | `src/configurable-greet.ts` | `Config` interface、Schemastery、默认值、运行时配置校验 |
| 4 | `src/workspace-name-service.ts` + `workspace-name-tool.ts` | Service Provider、Context declaration merging、Consumer / inject |
| 5 | `workspace-event-*` | typed Events、`ctx.emit()`、`ctx.on()`、松耦合广播 |
| 6 | `workspace-transform-*` | `ctx.waterfall()`、`next()`、around middleware、短路 |
```mermaid
flowchart LR
Config["Config"] --> Plugin["Plugin"]
Provider["Service Provider"] --> Service["ctx.workspaceName"]
Service --> Consumer["Consumer Plugin"]
Consumer --> Tool["Model-facing Tool"]
Tool --> Event["Cordis Event"]
Event --> Listener["Listener Plugin"]
Tool --> Waterfall["Waterfall"]
Waterfall --> MiddlewareA["Middleware A"]
MiddlewareA --> MiddlewareB["Middleware B"]
Plugin --> Effect["Lifecycle Effects"]
```
## 安装后测试
部署并启动:
```sh
pnpm deploy
dsh --profile practice
```
然后在 Agent 中测试:
```text
Use the workspace_info tool and tell me the current workspace.
Use configured_greet to greet Ada.
Use workspace_name and return only the workspace name.
Use announce_workspace to announce the current workspace.
Use waterfall_demo with input "hello".
Use waterfall_demo with input "blocked words".
```
预期行为:
- `workspace_info` 返回当前 DSH Node 进程的 `cwd` 和目录名。
- `configured_greet` 使用 Bundle patch 中的 `greeting: Hi`,例如返回 `Hi, Ada!`。
- `workspace_name` 通过自定义 `ctx.workspaceName` Service 获取目录名。
- `announce_workspace` 发出 `practice/workspace-announced`,监听插件在终端输出 `[workspace-event] announced: <name>`。
- `waterfall_demo("hello")` 经过 uppercase middleware 后返回 `HELLO`。
- `waterfall_demo("blocked words")` 在 block middleware 中短路默认处理,再由外层 uppercase middleware 包装返回,最终得到 `** BLOCKED **`。
- Lesson 1 插件运行时每 5 秒输出一次 `[practice-lifecycle] heartbeat`;卸载时输出 `disposed`。
## 卸载
```sh
dsh plugin --profile practice remove dsh-plugin-practice
```
## 常用开发命令
```sh
pnpm run typecheck
pnpm run build
pnpm run check
pnpm deploy
dsh --profile practice --dump-config
dsh --profile practice
```
## 版本说明
这个练习仓库跟随 DeepSeek Harness 当前开发版本学习。DSH 仍处于快速迭代阶段;如果 API 发生 breaking change,应优先对照官方开发文档和当前 TypeScript 接口调整。
Install
dsh plugin --profile web add github:Ri0n72Y/dsh-plugin-practice
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-plugin-practice from the hub
- This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.