Bundle
@jw-king/dsh-plugin-zentao
DeepSeek Harness bundle plugin that connects ZenTao PMS (禅道) REST API v1 as model tools: products, projects, stories, tasks, bugs and more.
- weekly downloads
- 960 weekly downloads
- License
- MIT
- Updated
- Updated yesterday
Readme
# dsh-plugin-zentao
[English](./README.md) | 中文
[DeepSeek Harness](https://github.com/deepseek-harness) 的禅道(ZenTao PMS)集成 Bundle 插件:通过官方 **REST API v1**(Token 认证),把产品、项目、需求、任务、缺陷等能力注册为模型工具。
## 安装
前提:Node.js `^22.19 || >=24`;`dsh plugin` 通过 pnpm 管理插件,需要 pnpm 在 PATH 上(没有就 `npm i -g pnpm`)。
按你运行 DSH 的方式选择其一:**方式一**适合不想全局安装 CLI、直接用 `npx` 跑起来的用户;**方式二**适合已用 `npm install -g` 全局安装 CLI 的用户。
### 方式一:使用 `npx @deepseek-ai/dsh web` 运行(无需全局安装)
```powershell
# 1. 安装插件到 profile(首次会自动初始化 profile)
npx @deepseek-ai/dsh plugin --profile web add @jw-king/dsh-plugin-zentao
# 2. 启动
npx @deepseek-ai/dsh web
```
### 方式二:使用 `npm install -g @deepseek-ai/dsh` 全局安装
```powershell
# 1. 全局安装 DSH CLI
npm install -g @deepseek-ai/dsh
# 2. 安装插件到 profile
dsh plugin --profile web add @jw-king/dsh-plugin-zentao
# 3. 启动
dsh web
```
### 配置插件(两种方式通用)
**安装不需要手动编辑 profile**:`dsh plugin add` 会自动把插件写入 profile 的 `bundles`,插件自带的 `cordis.patch.yml`(`- insert: id: zentao`)在启动时自动应用。
最小配置推荐写入 DSH 管理的凭据文件 `~/.dsh/.credentials.yaml`(`refs` 段),零手动编辑 profile:
```yaml
version: 1
refs:
ZENTAO_BASE_URL: http://your-zentao:8888
ZENTAO_ACCOUNT: your-account
ZENTAO_PASSWORD: your-password
```
> 凭据解析优先级:进程环境变量 > 凭据文件 `refs` > config。也可直接用环境变量 `ZENTAO_BASE_URL`/`ZENTAO_ACCOUNT`/`ZENTAO_PASSWORD`(仅当前会话设置时需与启动命令同一终端)。`baseUrl` 在启动时解析(改动后需重启),账号密码在每次登录时解析(凭据文件支持热更新)。
> ⚠️ **安全建议**:密码放进凭据文件或环境变量,不要写在 `cordis.patch.yml` 里(会提交到版本库)。
只有当需要 `readOnly`/`apiPrefix` 等其他字段、或不想用凭据文件/环境变量时,才手动编辑 profile 的 `~/.dsh/profiles/web/cordis.patch.yml`,添加 config 覆盖(不要重复插入同名 id):
```yaml
# 用 update 覆盖 bundle 插入的 id: zentao 的配置
- update:
- id: zentao
config:
readOnly: true
baseUrl: 'http://your-zentao:8888'
account: 'your-account'
# password 从环境变量 ZENTAO_PASSWORD 读取
```
> ⚠️ **重要**:不要用 `- insert:` 重复插入 `id: zentao`,否则会导致 duplicate id 错误。bundle 已经插入了,profile 只需覆盖 config。
## 更新
升级到最新发布版(升级后重启 `dsh web` 生效):
```powershell
# 方式一(npx 运行)
npx @deepseek-ai/dsh plugin --profile web add @jw-king/dsh-plugin-zentao@latest
# 方式二(全局安装 CLI)
dsh plugin --profile web add @jw-king/dsh-plugin-zentao@latest
# 查看当前安装的版本
dsh plugin --profile web why @jw-king/dsh-plugin-zentao
```
> `add @latest` 不受 semver 范围限制;`dsh plugin --profile web update @jw-king/dsh-plugin-zentao` 只会升到 package.json 记录的 `^0.1.x` 范围内的最新版。
>
> ⚠️ **pnpm v11 注意**:默认 `minimumReleaseAge`(24 小时)供应链策略会跳过发布太新的版本,`add @latest` 可能静默停在旧版(提示 Already up to date)。此时用以下命令升级——单次覆盖策略,**无需指定版本**:
>
> ```powershell
> dsh plugin --profile web update @jw-king/dsh-plugin-zentao --latest --config.minimumReleaseAge=0
> ```
>
> 备选:锁定精确版本(`add @jw-king/dsh-plugin-zentao@0.1.14`,pnpm 自动放行);或在 profile 的 `~/.dsh/profiles/web/pnpm-workspace.yaml` 永久放行 `minimumReleaseAgeExclude: ['@jw-king/*']`(pnpm ≥ 10.17 支持通配符)。
## 移除
```powershell
# 方式二(全局 CLI):从 profile 移除插件,bundles 注册自动清理
dsh plugin --profile web remove @jw-king/dsh-plugin-zentao
# 方式一(npx):把 dsh 换成 npx @deepseek-ai/dsh
npx @deepseek-ai/dsh plugin --profile web remove @jw-king/dsh-plugin-zentao
```
> 与升级同理:若已装版本发布不足 24 小时,`remove` 也会被 `minimumReleaseAge` 策略拦截,追加 `--config.minimumReleaseAge=0` 即可。
可选的手动清理(不再使用时):
- `~/.dsh/profiles/web/cordis.patch.yml` 中 `id: zentao` 的 config 覆盖块
- `~/.dsh/.credentials.yaml` 中的 `ZENTAO_*` 凭据条目
- 环境变量:`[Environment]::SetEnvironmentVariable('ZENTAO_PASSWORD', $null, 'User')`
## 配置
在 `cordis.patch.yml` 的 `config` 下(缺省值来自 Schemastery schema,两环境差异项必须可配置):
| 字段 | 默认 | 说明 |
|---|---|---|
| `baseUrl` | 必填(回退凭据/环境变量 `ZENTAO_BASE_URL`) | 禅道服务地址,例如 `http://localhost:8888`,不含末尾 `/` |
| `account` | 空(回退凭据/环境变量 `ZENTAO_ACCOUNT`) | 禅道账号 |
| `password` | 空(回退凭据/环境变量 `ZENTAO_PASSWORD`) | 禅道密码 |
| `readOnly` | `false` | 只读模式:不注册创建/更新/状态流转工具,`zentao_request` 仅允许 GET |
| `apiPrefix` | `api.php/v1` | REST 前缀;URL 改写部署可改 `index.php/v1` 或 `v1` |
| `timeoutMs` | `30000` | 单次请求超时 |
| `defaultLimit` | `20` | `zentao_list` 默认每页条数 |
| `maxLimit` | `100` | `zentao_list` 每页上限 |
| `allowInsecureTls` | `false` | 内网自签 HTTPS 证书时开启 |
> 未配置 `baseUrl`(且未设置 `ZENTAO_BASE_URL`)时插件休眠:记录一条警告日志,不注册任何工具,不影响 profile 启动。
## 工具
| 工具 | 作用 |
|---|---|
| `zentao_ping` | 登录并返回当前用户,验证连通性与凭据 |
| `zentao_list` | 分页列出对象(产品/项目/执行/需求/任务/缺陷/用例/版本/发布/计划/待办/用户/风险/议题/文档…),自动分页与摘要渲染 |
| `zentao_get` | 按 ID 获取单个对象完整详情 |
| `zentao_create` | 创建(需求/任务/缺陷/产品/项目/待办/用户…),必填字段见工具描述 |
| `zentao_update` | PUT 修改字段 |
| `zentao_action` | 状态流转:`bug.resolve/close/assign/confirm`、`task.start/finish/close/pause/restart/assignto`、`story.change/review/close/active`、`todo.finish/activate` |
| `zentao_request` | 通用透传(method + 相对路径 + query + body),覆盖一切专用工具没带到的端点,如 `options/bugtype`、`projects/1/executions` |
认证对模型透明:插件登录后缓存 token(含服务端 `tokenLife`),会话过期(401/302)自动重登一次再重试。
## 端点依据
路由表、必填字段(`requireFields`)、响应结构转写自官方源码(非二手文档),核对时以这些文件为准:
- 路由表:[`config/apiv1.php`](https://github.com/easysoft/zentaopms/blob/main/config/apiv1.php)
- 认证:[`api/v1/entries/tokens.php`](https://github.com/easysoft/zentaopms/blob/main/api/v1/entries/tokens.php)(`POST {prefix}/tokens` → `201 {token}`,后续请求 `Token` 头)
- 各资源的字段与校验:[`api/v1/entries/`](https://github.com/easysoft/zentaopms/tree/main/api/v1/entries)
## 诊断与测试
```sh
# 用你的真实禅道逐端点验证(登录 / 当前用户 / 产品 / 需求 / 缺陷 / 项目 / 我的任务)
node scripts/check-api.js --base=http://localhost:8888 --account=admin --password=***
# 用 ~/.dsh/.credentials.yaml 的 ZENTAO_* 凭据冒烟「我的缺陷」链路(跨产品拉取 + 指派人过滤)
node scripts/check-my-bugs.js
pnpm install
node --test tests/ # 路由映射、URL 构造、渲染的单元测试
```
## 已知限制
- `zentao_list_my_bugs` 的扫描封顶:不传 `product` 时只扫描产品列表第一页(50 个),每个产品取最近 100 条(按状态范围)再过滤指派人——产品极多或缺陷积压极大时可能漏掉部分旧缺陷,需要精确时传 `product`。
- 仅覆盖 REST **v1**(`api.php/v1`)。禅道各版本间个别端点行为有差异(如 `PUT` 更新在部分旧版本未实现),遇到时按报错用 `zentao_request` 兜底或调整 `apiPrefix`。
- 创建字段的最终校验在服务端;工具返回的具体错误信息(缺哪个字段)直接透传。
- `zentao_update` 依赖对应 entry 是否实现 `put`;未实现时改用 `zentao_action`(如 `story.change`、`bug.resolve`)。
- 列表渲染为摘要文本(完整 JSON 保留在 canonical value 中供 PTC 使用),超过截断线时提示用分页收窄。
## 项目结构
```
index.js # 插件入口:Config schema + apply 注册 7 个工具
src/client.js # 禅道 v1 客户端:token 登录/缓存/401·302 自动重登
src/net.js # node:http(s) 传输层:超时、AbortSignal、自签证书开关
src/kinds.js # 官方路由表 → kind/路径/动作映射(纯函数,可测)
src/render.js # 工具输出渲染(JSON 截断、列表摘要)
scripts/check-api.js# 真实服务器冒烟诊断 CLI
scripts/check-my-bugs.js # 「我的缺陷」链路冒烟(读 ~/.dsh/.credentials.yaml)
cordis.patch.yml # bundle 安装层(dsh plugin add 时应用)
tests/ # node:test 单元测试
```
Install
dsh plugin --profile web add @jw-king/dsh-plugin-zentao@0.1.17
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 jw-king-dsh-plugin-zentao from the hub