- Home
- Plugins
- Workflow & Automation
- dsh-zentao-ai-workbench
dsh-zentao-ai-workbench
lb290/dsh-zentao-ai-workbench
ZenTao workbench for DSH: load a ZenTao browse-page URL into a panel, multi-select bugs, tasks and stories, and hand them to the current or a new session with description, recent comments, screenshots as real image attachments and other files saved locally; when the agent is done it writes comments and status transitions (resolve, close, activate, start, finish and so on) back into ZenTao, one item or a batch, from the panel or through five registered agent tools (bug write-back verified end to end, task and story forms share the same code path).
Install
dsh plugin --profile web add github:lb290/dsh-zentao-ai-workbenchREADME
dsh-zentao-ai-workbench(禅道 AI 工作台)
DeepSeek Harness(DSH)插件:把禅道列表页变成一条 AI 处理流水线。
输入禅道链接 → 读取该页条目 → 多选 → 加入已有会话或新建会话 → AI 处理 → AI 直接回写备注与状态。 全流程不需要再人工登录禅道改状态。
禅道浏览页 URL ──► 工作台面板(10 条/页,多选)
│ ①「加入当前会话」:上下文进草稿,检查后发送
│ ②「新建会话并处理」:新会话 + 自动发送
▼
DSH Agent 逐条处理
│ zentao_add_comment / zentao_update_status / zentao_write_back
▼
禅道「历史记录」出现结论备注,状态变为 已解决 / 已关闭 …
安装
# 由 DSH 的 plugin_manager 安装(当前 profile):
# action: install_bundle, target: <本目录绝对路径>
安装后在左侧栏出现「禅道AI」图标,点开即是主面板。插件包含 host 半边(协议/写回/工具)与
client 半边(面板),与已安装的 dsh-zentao-panel 同构但可写。
首次使用
- 首次启动会自动从
~/.dsh/zentao-panel/config.json导入账号与登录 cookie(已经装过禅道面板就不必再输密码)。 - 没有旧配置时,点面板右上角「登录禅道」,填实例地址(如
http://zentao.example.com/zentao)、账号、密码。- 密码以 base64 存在
~/.dsh/zentao-ai-workbench/config.json(0600 权限);cookie 失效时用密码静默重登。
- 密码以 base64 存在
- 粘贴禅道浏览页链接,例如
http://zentao.example.com/zentao/bug-browse-1-all-assigntome-0-id_desc-10-20.html,点「读取」。
链接规则:只接受与已登录实例同源、同子路径(如
/zentao)下的浏览页链接; host 会把它转成同地址的.json接口取数(这是禅道的原生数据接口,等价于页面渲染的数据源)。
面板用法
- 多选:勾选要处理的条目(支持全选/反选、搜索、展开看描述与截图缩略)。
- 写指令:底部指令框默认「逐条分析并处理…处理完成后调用 zentao_add_comment 写备注、 zentao_update_status 更新状态」;可存模板 chip 复用。
- 加入当前会话:把所选条目渲染成 Markdown 上下文(标题/状态/负责人/描述/步骤 + 图片提示)写入当前会话草稿, 截图会作为真实图片附件一起挂上;检查后自己按发送。
- 新建会话并处理:新建会话(继承当前工作目录)→ 填入上下文与图片 → 自动发送,面板不跳转。
- 回写禅道:弹出的回写层里为每条选择动作(只加备注 / 已解决 / 已关闭 / 重新激活 / 任务开始/完成…) 并填备注,一次提交;结果逐条显示,成功后自动刷新列表状态。
- 复制上下文:任何情况下都能把上下文复制到剪贴板(服务缺失时的兜底)。
模型能看到什么
选中条目下发时,下面这些内容会一起进入会话,模型不需要再登录禅道:
| 内容 | 是否带入 |
|---|---|
| 标题、状态、优先级、严重程度、指派、模块、链接 | ✅ 纯文本 |
| 描述 / 重现步骤文字 | ✅ 纯文本 |
| 描述里的截图 | ✅ 真实图片附件(模型看得见图) |
| 下面的备注 / 历史记录文字 | ✅ 最近 30 条(更早的只注明条数) |
| 备注里的截图 | ✅ 真实图片附件(与描述图合并去重,上限 24 张) |
| 条目附件里的图片 | ✅ 真实图片附件 |
| 条目附件里的其它文件(xlsx/docx/zip…) | ✅ 自动下载到目标会话目录 .zentao-attachments/,上下文里给出本地路径,模型可用文件工具直接读 |
AI 主动用 zentao_item_detail 复核时同样能拿到备注文字、备注图地址与附件列表(传 saveDir 还会顺手把附件落到该目录)。
实测提醒:禅道对无权限/已删除的文件会返回一个 HTML 提示页而不是报错,插件会识别并明确报告「未保存」,不会把假文件喂给模型。
Agent 工具(AI 自动回写)
| 工具 | 用途 |
|---|---|
zentao_list_items | 按浏览链接复核条目列表 |
zentao_item_detail | 读取单条描述/步骤/最近动态/备注图/附件(可传 saveDir 落盘附件) |
zentao_add_comment | 写备注到「历史记录」 |
zentao_update_status | 状态流转(bug: resolve/close/activate;task: start/finish/close/cancel/pause/activate;story: close/activate) |
zentao_write_back | 批量回写:多条的备注+状态一次提交,单条失败不影响其它 |
工具失败返回 {ok:false, message}(不抛异常),模型能读到禅道原话(例如「当前账号没有该操作权限」)再决定下一步。
写回的协议依据(实测)
- 备注:
GET action-comment-{kind}-{id}.html取隐藏uid→POST同地址(actioncomment=<p>…</p>+uid)。 - 状态:
GET {kind}-{action}-{id}.html读表单默认值(hidden input + picker defaultValue + 编辑器字段名) → 合并覆盖项 →POST同地址。resolve必填resolution(默认fixed)。回执形如{"result":"success","message":"保存成功"}。 - 列表:浏览页
.html→.json,双层信封{status,data};bug 是 dict,task/story 可能是数组。 - 详情:
GET /api.php/v1/{bugs|tasks|stories}/{id}(cookie 鉴权)。
已知限制
- 备注回写已在真实实例上真写验证(
tools/probe-writeback.mjs --kind bug --id <id> --action comment --comment "…" --write, 写完用 v1 详情回读「历史记录」确认落库);Bug 的 resolve / close / activate 由作者早期在真实条目上实测通过。 - 任务/需求的状态表单已在真实实例上读取并核对字段(task 的 start/finish/close/activate、story 的 activate 表单
均能正确解析出
finishedDate/realStarted/assignedTo等默认值),但 task/story 的状态流转 POST 尚未实测—— 首次使用建议按下面「真机试跑」对自己建的测试条目各跑一次。 - 禅道的写权限是按动作授予的:本机实测的账号就没有
story-close权限(禅道 302 到user-deny-story-close.html,插件会明确报「没有 close 权限」,不会假装成功)。 - 当前账号若没有某动作权限(如删除),禅道会拒绝,插件会把原话回显,不会假装成功。
- 一次选中超过 20 条时,面板只自动并发拉取前 20 条的详情(其余用列表摘要下发,不带备注与图片);
要拿到全部内容,可以展开单条、分批处理,或让 AI 用
zentao_item_detail复核单条。 - 面板视觉需要在 DSH Web UI 里人工确认(自动化只能验证 slot 注册与资源)。
- 热重载注意:本插件用 webServer 前缀路由
/dsh-zentao-ai-workbench承载面板 RPC,而 webServer 的(kind, path)是唯一键。若在 DSH 运行中反复改代码触发热重载后出现 「duplicate prefix route」,插件会沿用上一代同名路由并打 warn(功能不变), 重启一次 DSH 即彻底清理。首次安装或改完代码后重启 DSH 是最干净的做法。
数据与隐私
- 账号/密码/cookie 只存在本机
~/.dsh/zentao-ai-workbench/config.json(权限 0600),不上传任何第三方。 - 禅道图片通过 host 用登录态下载后再作为 DSH 附件,不经过外部图床。
- 写回是真实写操作,会出现在禅道历史记录并可能通知同事,请确认 AI 结论后再让它回写。
开发与自测
代码结构:
lib/index.js 插件入口(注册 RPC + Agent 工具)
lib/zentao-client.mjs 禅道协议:登录 / 列表 .json / v1 详情 / 表单解析式写回 / 图片与附件下载
lib/service.mjs 多账号会话、缓存、静默重登、批量回写、附件落盘
lib/rpc.mjs loopback RPC 通道(面板 ⇄ host)
lib/tools.mjs 5 个 Agent 工具
client/client.js 左侧栏图标 + 主面板 + 会话头部按钮(只依赖 react)
locale/ 插件展示名与描述
tests/ 离线测试:假禅道服务 + node:test(无需 DSH、无需真机、无需账号)
tools/probe-writeback.mjs 真机探针:默认只读干跑,--write 才真写(凭据取自本机配置)
assets/icon-180.png 插件市场卡片图标(GitHub 托管的位图)
离线测试(全部跑在本机 127.0.0.1 的假禅道服务上,不连任何真实实例):
npm test # = node --test tests/*.test.mjs
node --test --test-isolation=none "tests/*.test.mjs" # 受限沙箱禁子进程时(spawn EPERM)用同进程模式
覆盖:登录握手与 verifyRand 两种响应形态、浏览页 .json 双层信封(bug dict / task-story dict 与数组两种形态)、
v1 详情与备注图/附件归一、action-comment 取 uid + 提交、状态表单「读默认值 → 合并 → POST」、
图片嗅探与「200 但返回 HTML 提示页」的拒绝路径、配置读写与旧面板导入、缓存失效与附件落盘。
真机试跑(状态流转)
tools/probe-writeback.mjs 用本机已配置的账号跑真实禅道(凭据从 ~/.dsh/zentao-ai-workbench/config.json
读取,不带任何硬编码账号;默认只读,只 GET 表单、不提交):
# 1) 拿到自己的条目 id
node tools/probe-writeback.mjs --list task
node tools/probe-writeback.mjs --list story
# 2) 干跑:只读表单,打印解析出的字段与必填项检查(没有任何写操作)
node tools/probe-writeback.mjs --kind task --id <id> --action finish
node tools/probe-writeback.mjs --kind story --id <id> --action activate
# 3) 真写:会进禅道历史记录、可能通知同事 —— 只对「自己建的测试条目」做
node tools/probe-writeback.mjs --kind task --id <id> --action finish --comment "ZTAW 写回测试" --write
真写结束后探针会用 v1 详情回读 status 与最近动态,确认状态真的变了、备注真的落到「历史记录」。
用它自测或报 issue 都能直接证明「这条链路在你的实例上通不通」。
手动对真实业务条目测试请勿使用 --write;面板侧改动需要刷新页面才生效。
协议依据(实测记录)
- 登录:
GET user-login.html种 session →GET user-refreshRandom.html取 verifyRand →POST user-login.html,密码md5(md5(pw)+rand),必须带一组 jQuery 风格请求头。 - 列表:浏览页 URL 的
.html换成.json,双层信封{status,data}(data是字符串需二次解析)。 - 详情:
/api.php/v1/{bugs|tasks|stories}/{id}(cookie 鉴权)。 - 备注:
GET action-comment-{kind}-{id}.html取隐藏uid→POST同地址。 - 状态:
GET {kind}-{action}-{id}.html读表单默认值 → 合并覆盖项 →POST同地址。 - 坑位(都已在代码里处理):cookie 删除指令(
tab=deleted/Max-Age=0)、 表单action自带子路径前缀、会话失效有多种形态(302 / 401 / HTTP 200 + 登录信封)、 无权限或已删文件返回 HTTP 200 的 HTML 提示页。
Related plugins
webnovel-writer
lingfengqaq/webnovel-writer
loopx (dsh-loopx-plugin)
loopx-project/loopx
ouroboros (dsh-plugin)
q00/ouroboros
loopx (dsh-loopx-plugin)
huangruiteng/loopx