Skip to content

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 余个)、十进制 '、十六进制 😀 都认, 只解一层(& 仍是 &)。富文本字段(重现步骤/描述/备注 HTML)保持原样,解码交给渲染层
  • 新建:工具栏「+ 新建BUG / 新建任务 / 新建需求」——弹出禅道自己的创建表单(字段、选项、默认值、联动条件都来自创建页), 先选创建目标(BUG/需求 → 产品;任务 → 项目,下拉可搜索),提交后回读新建对象的详情页确认真的建成,并直接跳到它的详情
  • 没权限就不显示「新建」:切页签时探一次该类型有没有创建权限(禅道没权限也返回 200,只是创建页里没有表单),没有就把按钮换成一行说明(含原因与探测地址),不再点进去撞红条
  • 新建表单按禅道复刻:控件类型(下拉/多选/复选/单选组/日期/文件)、必填标记、帮助说明、隐藏域默认值都照创建页渲染; 同名单选项合并成一组(禅道「添加之后」是 3 个同名 radio —— 旧实现渲染成 3 个文本框,提交值还会后写覆盖前写); 下拉与正文里的 HTML 实体(&lt;p&gt; 等)还原成原文;整行带 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。DSH 0.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