dsh-zentao-session
Verified@cnbmtech/dsh-zentao-session · v0.5.6 · MIT · Web UI
ZenTao (禅道) session-based tools and panel for DeepSeek Harness: my bugs, tasks and stories across browse scopes, bug confirm/resolve, remark post and remark edit, plus drag-to-chat Markdown references. Works with legacy ZenTao versions that lack REST API
Install
dsh plugin add @cnbmtech/dsh-zentao-session Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Published to npm without a public repository. Inspect the package contents before installing.
Tags
Creators
Readme
@cnbmtech/dsh-zentao-session
DeepSeek Harness 的禅道(ZenTao)会话式集成插件:11 个模型工具 + 一个「我的工作」面板(BUG / 任务 / 需求),可把条目一键送进对话。
走禅道的会话式接口(
/my-*.json+ 表单页),不依赖 REST API v1/v2 —— 因此在那些api.php被网关改造、官方 REST 不可用的禅道实例上照样能用。
能力
面板(侧边栏「插件」分组 → 禅道)
- 三个页签:我的 BUG / 我的任务 / 我的需求,每个页签自带浏览范围下拉(指派给我 / 由我创建 / 由我解决|完成 / 我评审 / 由我关闭 …,与禅道「我的地盘」的 tab 逐一对应)
- 列表头只留刷新,条数与分页在卡片页脚(整组靠右):页脚从右往左是分页(
‹ 当前页 / 总页数 ›+ 每页 20 / 50 / 100)与条数(共 N 条,筛选时筛选 3 / 7 条), 分页只此一处(早期条数写成「7 / 7 条」与页码「1 / 1」并排,会被读成两处分页;后来挤进头部,面板一窄就整组掉行、看着像错位,故下沉到页脚并整体贴右);刷新按当前范围 + 当前页重新取数,不会把第 2 页打回第 1 页 - HTML 实体统一还原:禅道按
htmlspecialchars下发(&→&、'→'),标题/名称/产品名/模块路径/相关人真名/备注都解码, 且不限于&——命名实体(< > " — … × © …,共 80 余个)、十进制'、十六进制😀都认, 只解一层(&amp;仍是&)。富文本字段(重现步骤/描述/备注 HTML)保持原样,解码交给渲染层 - 新建:工具栏「+ 新建BUG / 新建任务 / 新建需求」——弹出禅道自己的创建表单(字段、选项、默认值、联动条件都来自创建页), 先选创建目标(BUG/需求 → 产品;任务 → 项目,下拉可搜索),提交后回读新建对象的详情页确认真的建成,并直接跳到它的详情
- 没权限就不显示「新建」:切页签时探一次该类型有没有创建权限(禅道没权限也返回 200,只是创建页里没有表单),没有就把按钮换成一行说明(含原因与探测地址),不再点进去撞红条
- 新建表单按禅道复刻:控件类型(下拉/多选/复选/单选组/日期/文件)、必填标记、帮助说明、隐藏域默认值都照创建页渲染;
同名单选项合并成一组(禅道「添加之后」是 3 个同名 radio —— 旧实现渲染成 3 个文本框,提交值还会后写覆盖前写);
下拉与正文里的 HTML 实体(
<p>等)还原成原文;整行带class='hide'/'hidden'的按禅道显隐(有联动条件的交给条件,其余整行隐藏); 核心内容栏是可粘图编辑器——在里面按 Ctrl+V 粘贴截图会先上传到禅道(/file-ajaxPasteImage-<uid>.html,带本次表单令牌 kuid), 再把返回的<img src="/file-read-N.png">插到光标处就地预览(经本机代理,不裸取外域); 「附件」字段支持多选上传(单个 ≤ 8MB,base64 交给宿主后按multipart/form-data提交),超过 8MB 会在本地直接拦下; 选择器(下拉)展开是浮层:坐标按锚点实测、下方放不下就向上翻,不占行内位置,所以同一行的其它控件不会被挤走(点外部或 ESC 关闭); 同一行的控件保持一行(与创建页一致):日期范围(日程规划 预计开始 ~ 截止日期)并排等宽、不拆成两行, 第 2..N 个控件(操作系统 / 浏览器 / 严重程度 / 优先级 / 预计工时)跟在主控件后面用行内小标签补名,不另起一行被缩进一个标签列; 标题/名称独占一行(BUG标题、任务名称、需求名称铺满控件列,挤在同一行会把标题压窄、长标题看不全), 它的附加控件(严重程度 / 优先级 / 预计工时)另起一行、与控件列左对齐; 单选组与左侧字段名在同一行、垂直居中 - 统计卡点击筛选、标题/编号搜索、列表与详情双栏、详情全屏
- 详情里:富文本重现步骤/描述(图片走本机代理并可点击放大、左右切换)、基本信息、处理信息、关联对象、操作历史
- BUG 可直接在面板里走禅道原生表单:确认 / 解决 / 关闭 / 激活 / 指派(提交前拉取真实表单字段,提交后回读证实)
- 添加备注(三段式模板:问题原因/解决方案/解决时间),发错了可以直接改:
zentao_bug_comment_edit按 actionId / 内容片段 / 最近一条定位后重写(实测禅道只给条目页最新一条备注渲染编辑表单,改旧备注会报错并告知最新那条的编号) - 「解决」模型也能直接做:
zentao_bug_resolve走禅道自己的解决表单(解决方案 / 解决版本 / 解决日期 / 三段式备注),默认解决方案=已解决(solve)、解决版本=主干(trunk),提交后回读status=resolved才算成功;只发备注的zentao_bug_comment不会改状态 - 「在禅道中打开」链接附带会话参数,免登录直达
- 拖拽 / 复制为 Markdown 引用:把条目拖到聊天输入框,或点「复制」后粘贴——引用只有三行:标题行、读全文行(该调哪个工具、截图怎么拿)、免登录原地址
- 按角色处理:选好职位(开发/测试/产品/管理)→ 点「按【开发】处理」→ 在当前项目新建对话并自动发送「身份开场白 + 条目引用 + 角色任务书」;任务书排在最后(模型读到最后的才是要它做的事),且是纯文本聊天口吻——不用 Markdown 标题/加粗,只有条目引用那两行带「- 」引导符。开发那套是四步处理流程:查沉淀(只说「用这条记录的标题自己提炼业务词」,不写死任何示例)→ 给分析 → 我确认后再改码 → 回写;末步文案按条目类型替换(BUG 先给
zentao_bug_resolve:三段式写进 comment、默认 solution=solve(已解决)/ build=trunk(主干),提交后回读确认已解决;只补备注才用zentao_bug_comment,并提醒「发错了不用补发更正,用zentao_bug_comment_edit改那条」;任务/需求没有回写通道,直接说明「文案交我,我在禅道里填」) - 提示词不回抄详情:禅道详情页里能看到的东西(状态、优先级、正文、步骤、截图清单、信息缺口)一概不复制进对话——写进上下文只会又碎又容易失真;提示词只给
【禅道BUG #201030】标题、- 读全文:zentao_bug_view({ id: '201030' });截图按详情链接自行取回(带 zentaosid),取不到就明说,不要脑补;不要凭标题猜内容。、- 禅道原地址:https://…/bug-view-201030.html?zentaosid=…这几行 - 截图靠模型自己取,取不到就明说:条目里的图地址都带会话票据(
?zentaosid=…,实测不带 cookie 也能取),「读全文」那行已写明截图要自行取回、取不到就明说别脑补;工具回包里的<img src>同样改写成绝对地址,模型直接复制就能取回来看 - 自动刷新:关 / 1 / 5 / 15 / 30 分钟(页面不可见时跳过,不打扰禅道)
模型工具
| 工具 | 用途 |
|---|---|
zentao_ping |
连通性与凭据自检 |
zentao_my_bugs / zentao_my_tasks / zentao_my_stories |
三类条目列表,type 指定浏览范围 |
zentao_bug_view / zentao_story_view / zentao_task_view |
单条完整详情(正文、截图地址、相关人、操作历史) |
zentao_bug_confirm |
确认 BUG(只置「已确认」,状态仍是激活) |
zentao_bug_resolve |
解决 BUG:提交禅道解决表单(解决方案 / 解决版本 / 解决日期 / 三段式备注),默认 solve(已解决)/ trunk(主干),提交后回读确认 status=resolved(写操作) |
zentao_bug_comment |
追加备注(只加备注,不改状态) |
zentao_bug_comment_edit |
修改已发出的备注(写操作;只能改最新一条,见「已知限制」) |
zentao_plugin_status |
注册诊断(取数失败时排障用) |
插件还会注册一段系统提示,告诉模型这些工具何时用、未登录该怎么办。
⚠️ 「解决」和「备注」是两条不同的写入路径:禅道里只发备注不会把 BUG 变成「已解决」。要「回复三段式并把 BUG 解决」,必须用
zentao_bug_resolve(comment放三段式文案,resolution默认solve、resolvedBuild默认trunk),它会回读status证实;zentao_bug_comment只用于补备注。
安装
前置:DeepSeek Harness 0.1.0-rc.2 ~ 0.2.x(已在 0.2.0-rc.2、0.2.1-rc.1 与 0.2.1-rc.2 上实机验证)、Node ^22.19 || >=24。
ℹ️ 版本声明:
package.json的engines.dsh写的是>=0.1.0-rc.2 <0.3.0。DSH0.2.1起,第三方插件的兼容性优先按engines.dsh判断(未声明时才回落到旧的 peer 规则),声明不覆盖当前宿主就会被跳过并给出告警。宿主升到0.3.x时记得同步放宽这个区间。
方式一:DSH 桌面端插件管理器(推荐)
设置 → 插件 → 「添加插件」,输入三者之一:
- 包名:
@cnbmtech/dsh-zentao-session(npm 或公司私服) - Git 仓库地址:内网 Git / GitHub 地址
- 本地目录路径:例如
D:\dsh-plugins\dsh-zentao-session
⚠️ 选「本地目录」时务必先在该目录里执行过一次
npm install。包管理器只做目录链接,不会替你安装被链接包自己的依赖;目录里没有node_modules时插件会因为找不到@deepseek-ai/dsh-tools而起不来。宿主自带的
@deepseek-ai/*按生态惯例只声明在peerDependencies(本地开发用devDependencies装进插件自己的目录)——不写成dependencies:那样会把钉死的版本塞进 DSH 的共享依赖树、与宿主自己的版本互相干扰(插件清单会告警)。从包名安装时这些包由 DSH 提供,无需额外处理。
方式二:CLI
# 包名
dsh plugin --profile web add @cnbmtech/dsh-zentao-session
# 本地目录(同样记得先 npm install)
dsh plugin --profile web add D:\dsh-plugins\dsh-zentao-session
安装后完全重启 DSH(客户端 bundle 只在启动时加载,关开插件不会刷新)。
ℹ️ 装到旧版本了?(pnpm 11.7 实测)
pnpm 默认带
minimumReleaseAge(24 小时供应链策略),但显式指定版本安装时它会自动把该版本写进pnpm-workspace.yaml的minimumReleaseAgeExclude,无需手动放行。刚发布几分钟内,不带版本号(或
@latest)可能因 pnpm 的 registry 元数据缓存而拿到上一个版本。想要立刻拿到新版就把版本号写全:dsh plugin --profile web add '@cnbmtech/[email protected]'插件管理器里同理,填
@cnbmtech/[email protected];或者等几分钟缓存过期后重装。只有 profile 设了
minimumReleaseAgeStrict: true(策略变成"必须人工确认")时,才需要手动加minimumReleaseAgeExclude条目。
登录与配置
打开侧边栏「禅道」面板,填禅道地址 / 账号 / 密码,点「登录并保存」——凭据写入 DSH 凭据库 ~/.dsh/.credentials.yaml(refs:ZENTAO_BASE_URL / ZENTAO_ACCOUNT / ZENTAO_PASSWORD),之后免登录,且可随时「退出登录」清除密码。
也可以在 profile 的 cordis.patch.yml 里配置 id: zentao-session 的 config(优先级:config > 凭证库 > 环境变量):
| 字段 | 默认 | 说明 |
|---|---|---|
baseUrl |
空 | 禅道地址(不含末尾 /);为空时读凭据 ZENTAO_BASE_URL |
account / password |
空 | 同上,建议放凭据库,不要写进配置文件 |
timeoutMs |
30000 | 单次请求超时 |
defaultLimit |
20 | 列表工具默认返回条数 |
未配置地址时插件不休眠:照常注册工具与路由,只在你真正取数时提示"请先在面板登录"。
安全边界
- 面板数据接口
/api/dsh-zentao-session/*:所有 action(含读)都要求自定义请求头x-dsh-zentao-session: 1,且 Host 必须是回环字面量(防 DNS rebinding) - 截图代理
/api/dsh-zentao-session-file?path=…:只放行禅道/file-(read|download)-数字路径,只回位图/PDF(排除 SVG,避免同源脚本执行面),单文件 8 MB 上限 - 表单写入:令牌
kuid取不到就硬失败,绝不带空令牌出网;非幂等 POST 从不自动重试(避免重复备注——该版本禅道没有删除备注的入口,只能再编辑一次) - 贴图与附件写入同样受上一条约束:粘贴图上传(
/file-ajaxPasteImage-<uid>.html)与带附件的创建提交都要求令牌,请求体上限 32MB,非幂等且不重试 posted: true只代表"禅道没报错";确认/追加备注/改备注都会回读证实后才报成功- 仓库内不含任何禅道地址、账号或密码
排障
| 现象 | 处理 |
|---|---|
| 面板空白 / 页签缺失 | 客户端 bundle 没重新加载 → 完全重启 DSH(不是关开插件),再刷新页面 |
| 工具报「请在面板登录」 | 打开侧边栏「禅道」面板登录一次 |
| 取数失败 | 让模型调用 zentao_plugin_status,它会打出路由/RPC 注册结果与真实错误 |
| 列表比预期少 | 禅道「我的地盘」一页只回 20 条;面板会标注"服务端共 N 条",用范围/筛选收窄,或让模型用工具的 limit |
启动日志出现 skipping profile bundle "@cnbmtech/dsh-zentao-session"(面板/工具全都不在) |
宿主判定版本不兼容:engines.dsh 没覆盖当前 DSH 版本。升级插件到覆盖该版本的发行;确知无碍时可用 dsh plugin allow-version 或插件管理器加"精确版本豁免",再重启 |
已知限制
创建权限按目标探测:探前 3 个产品/项目(第一个有创建页表单即视为可创建),不逐个探完;权限都在别的目标上时会误显示成"没有创建权限"
新建写的是真实禅道:提交即创建(不可撤销,请在禅道里核对或删除);附件走禅道自己的
files[]字段,扩展名/大小最终仍由禅道侧规则决定(被拒时弹窗里会显示禅道原话)创建表单的联动是服务端初始态:切换产品/项目会重新拉取该目标的表单;页面内 JS 联动(如「新建版本」勾选后展开的子字段)以禅道渲染结果为准
目录/链接安装时依赖需自备(见上)
列表按禅道分页(服务端一页 20 条);面板列表页脚可翻页、可改每页条数(20 / 50 / 100,页码与总页数取自服务端 pager),模型工具默认取一页再按
limit截断需求的详情接口不返回产品名(只有产品 id),面板会回落到列表行;列表能拿到就没问题
表单操作只覆盖 BUG(确认/解决/关闭/激活/指派);任务与需求为只读 + 复制/拖拽/送对话
需要禅道账号本身有对应权限;插件不做越权尝试
开发与自测
npm install
node test-client.mjs # 面板全链路(最小 React hooks 模拟宿主)
node test-tools.mjs # 11 个工具的渲染 + lossless JSON
node test-form-encoding.mjs # 写路径铁律(多选重复键 / 302 不重发 / 缺 kuid 不出网)
node test-real-render.mjs # 真实 React SSR 首跳
node test-real-browser.mjs # jsdom + 真实 React 全交互链
目录结构:index.js(宿主:工具 + HTTP/RPC 路由 + 系统提示)、src/client.js(宿主侧禅道客户端:登录/列表/详情/表单)、client.js(浏览器面板 bundle)、cordis.patch.yml(bundle 安装层)。
发布与迭代(维护者)
npm login # 首次:需要 npm 账号,且对 @cnbmtech 组织有发布权
npm version patch # 0.2.0 → 0.2.1(或 minor/major)
npm publish # publishConfig 已设 access=public,无需再加 --access
npm view @cnbmtech/dsh-zentao-session versions # 确认发布成功
- 首次发布前需要在 npm 上创建组织
cnbmtech(免费组织只能发公开包),或用公司私有源:npm publish --registry https://私服地址(并让同事的插件管理器指向该源)。 - 本机开发不必发布:profile 里以
link:指向源码目录,改完代码重启 DSH 即生效;只有同事需要走 npm。 - 同事升级:插件管理器里重新添加同名包(或
dsh plugin --profile web update @cnbmtech/dsh-zentao-session),再完全重启 DSH。 - 发布物只含 10 个文件(
package.json的files白名单),不含node_modules、测试脚本与任何凭据——发布前可用npm pack --dry-run复核。
许可
MIT