dsh-comfyui-based-tools
支持范围:本插件仅适配 DeepSeek 桌面版(desktop profile)的 Harness runtime。 当前支持的 DeepSeek 桌面版版本:
0.2.1-rc.1~0.2.1-rc.5(版本门禁[MIN_HARNESS_VERSION, MAX_HARNESS_VERSION]=[0.2.1-rc.1, 0.2.1-rc.5], 见src/version-gate.ts;桌面版应用与 runtime 锁步同版发版, 插件 peer 声明^0.2.1-rc.1)——高于上限时插件启动即软禁用, 设置里不再有本插件分区,改在「插件」页本插件详情页出现「已停用」说明面板 并给出版本指引,不影响 DSH 启动与其他插件。dsh web、自定义 profile、SDK/headless 等形态一律不支持——启动时 profile 门禁 (src/profile-gate.ts)会自动软禁用本插件。下文沿用的dsh web开发流示例是 插件模板的历史写法,实际部署与运行请以桌面版为准。
DeepSeek Harness 插件:双端(host + client)结构,开发完成后可直接发布到 npm 或推到 GitHub 供用户安装。
模板自带三个可删改的示例功能,覆盖两端与端间调用:
- Host half(
src/index.ts):注册模型可调用的greet工具,演示inject/Configschema / 事件监听; - Client half(
src/client/index.ts):在「插件」页本插件详情页注册配置面板(plugins.bundle.config槽位),演示 slot 组合、locale 词典(zh/en 双语键集)、CSS Modules 样式与浏览器原地热替换; - Host↔Client 调用(
src/remote.ts+src/client/api.ts):面板上的"调用 host"按钮经 Typert Gateway 调用 host 半的comfyui-tools/ping端点,演示第三方插件的远程调用形态(为什么是手写描述符而非官方@Remote装饰器,见src/remote.ts头注释)。
使用本模板
通过 GitHub 的 "Use this template" 创建新的插件仓库(仓库名随意),克隆到本地后, 先改名。改名前搞懂插件身份由三样东西组成,它们互相派生:
| 概念 | 本模板取值 | 怎么派生 |
|---|---|---|
| 短插件 id | dsh-comfyui-based-tools | = 仓库名(use-this-template 建库时你起的名字;克隆到本地即根文件夹名) |
| npm 包名(scoped) | @liaozhi/dsh-comfyui-based-tools | @<scope>/ + 短 id;@scope = 你的 npm 用户名 |
| 环境前缀 | DSH_COMFYUI_BASED_TOOLS | 短 id 全大写、-/. 转 _ |
@scope 即 npm 用户名(npm whoami 可查,未登录先 npm login)——本插件取 @liaozhi,
故包名为 @liaozhi/dsh-comfyui-based-tools。
改名 = 换这三样东西,各有固定落点。漏改不报错——这些标识只是注册 key,构建/加载 都不校验一致性,漏改只会让对应功能静默失效(面板不出现、RPC 404), 所以必须逐表核对。建议执行顺序:先全局换短 id(包名里的短 id 会一并变)→ 再换 3 处 scope → 再换前缀 → 最后核对顺手项。
① npm 包名(scoped)—— 只 3 处
| 位置 | 改成 |
|---|---|
package.json 的 name | @<新scope>/<新短id> |
cordis.patch.yml 的 name: | "@<新scope>/<新短id>"(必须加引号,YAML 里 @ 是保留指示符;按它解析到包 exports['.']) |
tsdown.config.ts banner 的 __ModuleLoader__ id | 同上(client 按包名发现) |
② 短插件 id —— 其余 15+ 处
| 位置 | 改成 |
|---|---|
cordis.patch.yml 的 id: | <新短id> |
src/index.ts 的 export const name + Typert package: 字段 | 同上(cordis 插件名) |
src/client/index.ts 的 export const name + 两处 slot id | 同上 |
src/remote.ts 的端点描述符 id(<短id>#…) | 同上(Typert 关联) |
tsdown.config.ts 的 CSS 虚拟模块前缀 + 插件名 | 同上 |
③ 环境前缀 —— 2 处 + 各文件错误/日志前缀
| 位置 | 改成 |
|---|---|
src/version-gate.ts 错误前缀、DSH_<前缀>_STRICT 变量名 | <新前缀> + _STRICT |
src/shared/disabled-flag.ts 的 __DSH_<前缀>_DISABLED__ 变量名 | __<新前缀>_DISABLED__ |
src/update-state.ts 的错误/日志前缀(dsh-comfyui-based-tools: / [dsh-comfyui-based-tools]) | 换成新短 id(包名/版本本身从自身 package.json 读,无需改) |
④ 顺手项
| 位置 | 改成 |
|---|---|
src/client/locales.ts 的 title(配置页标题;插件页条目名与导航 label 由插件页按包清单自带,无需 locale key) | 你的 UI 标识(如 "Meme 生成") |
src/shared/update-contract.ts 端点 namespace('comfyui-tools/…')与 src/remote.ts 的 namespace / serviceKey / service | 与 Typert 服务名同源,改服务名时一并改 |
LICENSE 版权行 | 你的名字 |
README.md / AGENTS.md / 示例文案里出现的旧短 id | 同上 |
验证
pnpm install(自动跑prepare完成首次构建)pnpm typecheck && pnpm build通过git grep <旧短id>与git grep <旧包名>,全仓应无残留- 若该目录此前已装进 profile:重跑
dsh plugin --profile web add
开发与生效
唯一生效路径 = 构建后重启/重装 DeepSeek Harness(本插件不接热加载开发流):
pnpm install # 首次(prepare 自动构建)
pnpm build # 之后的每次改动
然后重启 DeepSeek Harness(或到「插件」页卸载本插件后重装)即可看到变更。
离线守护不依赖实例与费用:node scripts/smoke-offline.mjs。
发版纪律(version bump)
改 package.json 的 version 后跑一次构建:scripts/gen-version.mjs 处在 build
链首步,负责重生成 locale/{zh,en}.json 的包显示元数据(插件页卡片的 title 与
兼容窗口描述)——漏跑会让卡片上的版本窗口停在旧值。卡片 title 取自词典的
pluginName(插件身份名),不是面板标题 title——改面板标题不会、也不该
改掉插件名。
- bump 走生命周期:
pnpm version patch --no-git-tag-version(或minor/major), 再git commit -am "chore(release): x.y.z"。package.json的"version"生命周期 脚本会自动跑gen-version并git add locale/,让新版本号与重生成的元数据落在同一次 提交里。三个实测边界:①<patch|minor|major>是pnpm version命令的参数,"version"脚本自身不收任何参数(脚本内npm_package_version已是 bump 后的新值); ② 脏工作树直接被拒(ERR_PNPM_UNCLEAN_WORKING_TREE——git-ignored 的lib/、extracted-workflows/不算脏);③ 别用pnpm run version——那只是直跑脚本、 不 bump。想去掉--no-git-tag-version让 pnpm 自动提交并打vX.Y.Ztag 的话, 配-m "chore(release): %s"; - 发版前的完整守护是
node scripts/smoke-offline.mjs(0g 节守护 locale 元数据与src/version-gate.ts的窗口一致;另需 git-ignored 的extracted-workflows/取证缓存)。
【0.2.1 起】原先还有一层"版本烧录 + 提交期闸门"(src/client/build-version.ts 的
BUILD_VERSION、scripts/check-version-sync.mjs、.githooks/pre-commit)——那是为
陈旧代码检测服务的。该检测已随上游修复整体拆除(卸载→重装不重启由 harness 自行
驱逐旧模块,2026-10-19 真机确认),闸门与生成步骤一并删除,不要再加回来:取证与
回退记录见 docs/harness-defect-workarounds.md 的历史防护回退块。
本地版本 bump 测试(Verdaccio)
「版本提示」弹窗(available)与**「卸载重装免重启生效」**的端到端验证台,两种模式:
pnpm test-version-bump # 交互式:先选模式(缺省 bump)
pnpm test-version-bump --mode bump # bump 模式(工作区当前版本 → patch+1)
pnpm test-version-bump --mode commit --a <ref> --b <ref> # commit 模式(commit a 旧版本 / commit b 新版本)
两种模式的差别只在「两个被测版本从哪来」:bump 模式把工作区当前版本作为版本 A、 A 的 patch+1 作为版本 B(同一个工作区构建两次,适合改完 UI 立刻验证);commit 模式把 commit a、b 的代码树各自 checkout 到临时 git worktree 里构建(工作区不被触碰,未提交 改动不进入构建,适合验证某个已提交的 UI 改动)。
commit 模式的「版本相同」陷阱:本仓库 chore(release) 与 feat 提交分离,提交 UI
改动时 package.json 的 version 往往还没抬——a、b 版本相同就构不成 bump 对比。此时只有
commit b 恰为当前最新提交(HEAD)才能测:脚本在 b 的 worktree 里把版本临时 patch+1 作为
新版本(只改工作文件、不提交,随临时 worktree 一起丢弃);b 不是最新提交则不做任何改动、
输出警告并直接退出(exit 2)——请先 git checkout <commit b>(或把 b 合并/rebase 到当前
分支)让 b 成为 HEAD,或改用 bump 模式。两版 version 本来就不同时直接用各自版本。
脚本按阶段自动/交互执行,dsh 内一律通过 Verdaccio npm 源安装被测包,文件夹形式安装 的副本不参与测试(脚本会清理链接残留):
- 准备:你在 dsh 插件页卸载本插件 → 重启 dsh;脚本清理桌面 profile 里
文件夹安装的残留副本(
<user_home>/.dsh/profiles/desktop/node_modules/<包名>, 链接安装只删链接不进工作区); - 基线(版本 A):候选源首位注入本地 Verdaccio → 构建 → 打包 → 发布 →
你在插件添加页选自定义 npm 源(
127.0.0.1:4873)安装版本 A——这是新装插件, 不用重启 dsh(bump 模式 = 工作区当前版本;commit 模式 = commit a 的代码在临时 worktree 里构建); - 新版本(版本 B):bump 模式 = version patch+1 → 重新构建(locale 显示元数据跟随 新版本;dsh 内副本是 verdaccio 安装的复制品,不受 workspace 构建影响); commit 模式 = 从 commit b 的代码树构建(版本相同时先临时 patch+1)→ 打包 → 发布;
- 验证:先到「插件」页本插件详情页点一次**「检查更新」按钮**(配置面板标题行右侧)
→ available 更新弹窗;再到插件详情页卸载本插件、然后安装版本 B(不重启)→
0.2.1 起 harness 会在重装时驱逐旧模块:插件立刻以新版本运行,且不弹任何
"陈旧代码"对话框(旧防护已拆除,见
docs/harness-defect-workarounds.md)—— 这既是版本更新闭环的验证,也是"上游修复"的回归断言; - 还原:候选源回官方两源 + 版本号回滚(bump 模式;package.json 回 bump 前值,
依据
.verdaccio-storage/version-bump-state.json——本次 bump 仅为测试造数)- 删除临时 worktree(commit 模式;工作区自始至终未被改动)+ 重建(bump 模式)
- 停 Verdaccio。
所有测试资产(verdaccio 配置 / htpasswd / 发布凭据 / tgz / 包数据 / 日志 / bump 状态 /
临时 worktree)都集中在 git-ignored 的 .verdaccio-storage/——整删即净,仓库无残留。
还原是脚本的默认行为:无论正常结束、出错还是 Ctrl+C,退出前都会自动执行(候选源回官方
两源 + 版本号回滚 + 删临时 worktree + 重建),无需任何额外命令。
依赖版本与追新
harness 处于 0.1 rc 快速迭代期,要点:
- peer 与 dev 写同一个
^<已实测的最低版本>:dev = 编译所用版本(typecheck 类型面),peer = 运行时声明。窗口内没有"下限/上限/并集"之分——不要用范围去"夹"多条 harness 线(预发布线内跨版本 API 破坏频繁,范围放宽救不了,取证见docs/dsh-0.1.5-rc.1-upgrade-report.md与docs/compat-plan-0.1.7-rc.1.md)。caret 在预发布线上只覆盖同一major.minor.patch的更高预发布号,所以^0.2.1-rc.1覆盖 0.2.1 线内更高预发布号(含 rc.2…rc.5,pnpm 默认解析语义下同样成立)——同 tuple 内追新(如 rc.2→rc.5)默认不需要改依赖,只抬 MAX;tuple 变化(如 0.2.0→0.2.1)或跨 minor 迁移(0.1.7→0.2.0)时 caret 取不到新线(实测^0.2.0-rc.1对 0.2.1-rc.2 在默认解析下为 false → pnpm 装不到新线的类型面),MIN/MAX 一并上移 + 依赖下限同步改写(peer precheck 按 satisfies(includePrerelease) 校验,旧 caret 对新线 runtime 直接 false → 插件被声明面禁用);只有同 tuple 内的 MIN 上移(旧 MIN 从未通过运行时验证 / 已不可安装;dist-tag 被接任本身不构成理由——0.1.5-rc.2 先例已实测旧 MIN 在被接任后仍保留窗口内;本轮 MIN 上移属 tuple 变化 + 用户指定纳入)时才把依赖下限同步改写到新 MIN。 - harness 版本门禁:模板自带
src/version-gate.ts,要求 harness 版本落在[MIN_HARNESS_VERSION, MAX_HARNESS_VERSION]双边界窗口内(main 当前[0.2.1-rc.1, 0.2.1-rc.5]——rc.5 为当前基线(本机桌面版内置版本),rc.1 为用户指定纳入的同 tuple 相邻预发布:取证覆盖、非单独实机验收,见docs/compat-plan-0.2.1-rc.2.md;rc.2→rc.5 为只抬 MAX 的同 tuple 追新,见docs/compat-plan-0.2.1-rc.5.md。行为地图:低于 MIN 的宿主由 harness 声明面在组合期拦截(静默跳过、插件无机会出面板);窗口内正常加载;高于 MAX 由本插件门禁软禁用并给出可执行的更新/降级指引)。另有src/profile-gate.ts:无 profile 启动(SDK 嵌入等)或非 desktop profile 时插件软禁用——本插件仅支持 DeepSeek 桌面版(desktop-only 收敛,取证见该文件头注释)。0.1.7 起 harness 自身也做插件兼容性检查(peer 依赖 semver satisfies(includePrerelease) 校验,不满足的插件行在启动组装期直接 disabled;0.2.1 起若声明engines.dsh则它单独决定、peers 被忽略,且三个执行点全在 import 之前——本插件刻意不用,理由与激活条件见docs/harness-defect-workarounds.md),插件自身的精细窗口门禁仍在 apply 时执行,两者分工见 version-gate.ts 头注释。版本源 = runtime 内@deepseek-ai/dsh包 version(桌面版应用与 runtime 锁步同版发版,语义与dsh --version一致);【不能】读@deepseek-ai/dsh-tools等内嵌依赖当 harness 版本:caret 语义下实装版本可能高于 CLI 本体(实测@deepseek-ai/[email protected]内嵌的 dsh-tools 已解析到 0.1.5-rc.2,读它会误判软禁用)。解析锚点 = 桌面单锚:桌面版 host 子进程由 Electron spawn,process.argv[2]= runtimeDir(launcher 硬契约,apps/desktop/src/host-process.ts),读<argv[2]>/node_modules/@deepseek-ai/dsh/package.json并校验 name。落在窗口外默认软禁用:醒目错误日志 + 插件不注册任何业务能力,不影响 DSH 启动;DSH_COMFYUI_BASED_TOOLS_STRICT=1恢复抛错 fail-loud。软禁用时 host 半经webserver/index-inject向页面注入__DSH_COMFYUI_BASED_TOOLS_DISABLED__标记(fiber-bound,卸载即撤、无残留),client 半读到后改挂"已停用"说明面板并展示支持版本窗口(src/shared/disabled-flag.ts是两侧共享的标记契约)。
追新流程(手动,无脚本):
版本抬升刻意做成显式手改——目标线选择、破坏面评估、门禁窗口三件事本来就该人工过目(实测教训:0.1.x 线内 0.1.1 → 0.1.2 这种带破坏性变更的跨 patch 追新会被脚本静默扫进来)。追新的每一步都值得慢下来看一眼:
# ① 查目标线的最新版本(各 @deepseek-ai/dsh-* 与 harness 同步发版):
pnpm view @deepseek-ai/dsh versions --json
# ② 手改 package.json:全部 @deepseek-ai/dsh-* 的 peer 与 dev 改为同一个 ^<目标版本>
# (窗口内没有并集写法;新线才有、只 import type 的包只进 dev)
# 同 tuple 内追新(如 rc.2→rc.5)caret 已覆盖,默认无需改依赖,直接跳到 ④;
# 仅当 MIN 也要上移(旧 MIN 从未实测 / 已不可安装 / tuple 变化)时才同步改写依赖下限
# ③ 同步与验证:
pnpm install
pnpm typecheck && pnpm build # 红 = 上游破坏性变更,按升级报告的取证清单修
# ④ 实测通过后手动上调 src/version-gate.ts 的 MAX_HARNESS_VERSION
# (MIN 保持已实测(或用户指定纳入)的最低版本;窗口保持双边界结构)
# ⑤ 同一轮同步指引:AGENTS.md / README.md / version-gate.ts 头注释里的版本表述
# ——留旧窗口 = 让后续 agent 照旧窗口写代码。
- 不用
pnpm update:它会剥掉 rc 包的^(实测),且不碰 peer 侧。 - 窗口 = 已验证承诺:抬 MAX 等于宣布「插件已在那个版本上验证过」,没实测过的版本不要抬;MIN 保持已实测(或用户指定纳入)的最低版本(main 当前
[0.2.1-rc.1, 0.2.1-rc.5];rc.1 属用户指定纳入、取证覆盖而非单独实机验收,已在AGENTS.md与docs/compat-plan-0.2.1-rc.2.md如实标注;rc.5 的抬升依据见docs/compat-plan-0.2.1-rc.5.md)。MIN 上移 = 收缩承诺面:tuple 变化 / 跨 minor 迁移必做(caret 取不到新线;双窗口需 OR 范围夹线、被禁止);同 tuple 内只在旧 MIN 从未通过运行时验证或已不可安装(从 npm versions 移除)时做,且须同轮把依赖 caret 下限改写到新 MIN(0.1.7-rc.2 先例即此情形)——dist-tag 被接任本身不构成理由(0.1.5-rc.2 先例:已实测旧 MIN 被接任后仍保留窗口)。 - 锁文件会钉住首次安装版本:想每次克隆都最新就删掉它,否则按上面流程主动追新。
- 注意 caret 语义会匹配同 tuple 的更高预发布(
^0.2.1-rc.1会解析到 0.2.1 线内更高的 rc/正式版——0.2.1-rc.2在默认解析与 satisfies(includePrerelease) 下都命中)——这正是同 tuple 追新无需改依赖的理由:与门禁窗口重合。tuple 变化即失效:^0.2.0-rc.1对 0.2.1-rc.2 在默认解析下为 false、^0.1.7-rc.2对 0.2.0-rc.1 runtime 为 false(均实测),故 tuple 变化/跨 minor 迁移必须改写依赖下限。
多线兼容(默认不做):
双线/多线支持(peer 并集 + dev 钉线 + 特征探测回退)是 0.1.1→0.1.2 时代的做法,本插件已收敛为单条线(main = 0.2.1 线;compat/0.2.0-rc.1 与 compat/0.1.7-rc.2 分支为冻结的历史发布线;0.1.5 线已随 desktop-only 收敛放弃),不再维护。历史方法论仅存档于 docs/compat-guide-0.1.1-to-0.1.2.md(已加归档标注),仅在确需重新引入多线时参考,并须在 AGENTS.md 与迁移计划里明确标注为多线。
版本更新提示
插件不自更新(0.8.0 起安装通道整体删除——进程内安装只会制造「新 UI + 旧内核」错配):发现新版本只弹窗提示用户「到插件页卸载本插件后重新安装」。0.2.1 起该两步免重启即生效(harness 会停掉旧 bundle、丢弃其模块映射后再装新版本;2026-10-19 真机复核确认);第三方插件仍没有「一键更新」——那只对按需官方插件开放(harness 文案:「其他插件请先卸载再安装新版」)。
- 版本检查(host 半
src/update-state.ts状态机,client 半面板更新条轮询投影,经comfyui-tools/checkUpdate/comfyui-tools/getUpdateStateRPC):当前版本 vs npm registry/<pkg>/latest(严格 semver 比较,含预发布规则);候选源固定官方兜底计划(npm → npmmirror,逐源降级);apply 启动静默查一次 + 面板「检查更新」手动触发,离线不打扰、手动可重试; - 新版本弹窗(client 半
GlobalNotice.tsx,shell.overlay 槽位条目 comfy-update-notice):available相位弹 NoticeModal(复制的 Modal 本体,neutral)提示卸载后重装;弹窗与配置页更新条均内嵌可复制的安装 spec 命令片(插件包名@最新版本,复制后粘进「插件」页安装输入框);「我知道了」仅关闭本次窗口(内存态、零持久化)——下次启动 DSH 若仍未更新则重新弹出(浏览器刷新同样重弹); - 前提:插件必须已发布到 npm。GitHub-only 分发(未发 npm)时 registry 检查失败——面板静默/手动重试,属预期行为;
- 软禁用态没有提示 UI:版本门禁软禁用时 client 半只挂停用面板(不注册版本提醒条目、host 半无 RPC),停用面板自带版本自查与修复引导。
历史(0.2.1 起已拆除):原有一个"陈旧代码"检测(client 半 StaleBanner.tsx + 构建期烧录的 BUILD_VERSION + 与快照 currentVersion 严格不等比较,danger 对话框、共提醒两次),兜底「卸载重装不重启时 host 半继续跑旧代码」这一 harness 缺陷。该缺陷已被上游修复并经 2026-10-19 真机确认,故整个检测连同 scripts/check-version-sync.mjs、.githooks/pre-commit、smoke 0d 节一并拆除(不要再加回来)。残留在案的已知限制:link: 本地链接 + 手工 build 而不经过插件页操作时,host 半仍持进程内旧模块而浏览器端取到新 bundle —— 开发期照旧「改码/改版本后重启 DeepSeek Harness」。取证与回退记录见 docs/harness-defect-workarounds.md 的历史防护回退块。
给其它插件用的状态服务
本插件在 host 半 ctx.provide('comfy-status', ...) 一个只读状态服务,供把本插件作为依赖的其它插件查询身份与当前可用的工具集(同步、零 IO、进程内直调,不走 RPC)。
依赖方不需要 import 本包任何东西——服务键是纯字符串约定,ctx.get('comfy-status') 一句就判得出"本插件装好了没有"(undefined = 没装 / 未启用 / 软禁用),拿到对象再读 status():
// 依赖方(另一个 DSH 插件)的 host 半
const comfy = ctx.get('comfy-status') // undefined = 本插件不可用,走回退路径
if (comfy !== undefined) {
const status = comfy.status()
// {
// name: 'dsh-comfyui-based-tools', // 插件短 id(不是 npm 包名)
// version: '0.8.9' | null, // 运行中模块自报版本(包损坏时 null)
// all_tools_provided: [...7 个工具 ID], // 本插件提供的全部工具(与配置无关)
// ready_tools: [...], // 本会话已注册 = 此刻真能调用的子集
// }
}
口径要点:
ready_tools才是"能不能调"的答案——它是门控真正注册进会话的集合(与面板绿点同一份快照),不是"配置层面就绪";实例离线时该工具不在其中;- 每次调用现算、返回副本;两个数组都按
TOOL_IDS声明顺序排列; - 服务键刻意与面板 RPC 服务键
'comfyui-tools'分开:后者是"浏览器 ↔ host",前者是"插件 ↔ 插件",互不影响; - 契约常量不从插件入口导出(入口只导出 Loader 约定项
name/Config/inject/apply):依赖方用字符串键 +ctx.get即可,不必把本包加进自己的依赖树;要对照返回形状就看src/shared/status-contract.ts(本包也不产出.d.ts)。
发布到 npm
npm login # 首次
pnpm publish # prepack 会自动完成构建
files 白名单只带运行必需的产物(lib/index.js、lib/client.js、cordis.patch.yml、icon.svg、locale/*.json),发布前建议 pnpm pack 检查内容。用户安装:
dsh plugin --profile web add dsh-comfyui-based-tools
上传到 GitHub
直接 push 源码即可(不要提交 lib/,它在 .gitignore 里)。本模板带了 prepare 脚本:用户从 git 安装时 pnpm 会用它现场构建产物(自包含,只依赖 npm 上的公开包)。
用户侧安装分两步(pnpm ≥10 的构建许可要求):
# 1. 首次 add 会被 pnpm 拒绝构建脚本,按提示把包名加进 profile 的
# pnpm-workspace.yaml(~/.dsh/profiles/<profile>/pnpm-workspace.yaml):
# allowBuilds:
# dsh-comfyui-based-tools: true
# 2. 重新执行
dsh plugin --profile web add github:<owner>/dsh-comfyui-based-tools#<commit-sha>
构建许可 = 允许安装时执行该包的代码,提醒你的用户只对他们信任的包开启,并建议 pin commit。 不想让用户配许可的话,也可以发 npm 或提供
pnpm pack产物(tarball 安装不跑构建)。
原理速记
- 一切都是 Cordis 插件;通过
ctx注册的都是可逆 effect,卸载自动清理。 - 分发形态即开发形态:
exports['.']恒指向lib/index.js,npm 包、git 安装、本地开发走同一条加载路径,没有"源码能跑、装上就挂"的落差。 - 依赖规则:
@deepseek-ai/*一律进peerDependencies(运行时由 harness 安装环境提供;dsh profile 的 pnpm 工作区是autoInstallPeers: false+ 安装目录兜底解析,不会为你的 peer 链去 npm 拉包),普通第三方库进dependencies,构建工具进devDependencies。不要把@deepseek-ai/*放进dependencies。type-only / 构建期用的基座可同时进devDependencies(本仓库:cordis/cosmokit/schemastery,以及[email protected]的自动补齐 peercordis-plugin-include/cordis-plugin-group——dev 只服务本仓库编译与解析一致性,不进发布包;取证docs/compat-plan-0.2.1-rc.2.md§5)。 dsh.client声明是包元数据,扫描缓存永不过期:改它要重启 harness。
文件清单
├── src/index.ts # host half 入口(版本门禁 + greet 工具示例 + Typert 端点注册)
├── src/profile-gate.ts # profile 启动门禁(profileContext 判空;无 profile 启动软禁用)
├── src/version-gate.ts # harness 版本门禁(软禁用语义 + 桌面单锚 + semver 比较)
├── src/update-state.ts # 版本提示状态机 host 半(registry latest 检查 + 快照恒填运行中自报版本)
├── src/client/GlobalNotice.tsx # 更新提示(shell.overlay 槽位条目:NoticeModal 提示卸载后重装)
├── scripts/gen-version.mjs # 包显示元数据生成(build 链首步:locale/{zh,en}.json 的 title + 兼容窗口)
├── src/shared/disabled-flag.ts # host→client 的软禁用标记契约(全局变量名 + 载荷形状)
├── src/shared/update-contract.ts # 版本提示 RPC 契约(端点名 + 请求/结果类型,两端共用)
├── src/remote.ts # host 半 Typert 远程端点(comfyui-tools/*,表驱动描述符 + 第三方安全形态)
├── src/css-modules.d.ts # CSS Modules 导入声明(*.module.css)
├── src/client/index.ts # client half 入口(词典/槽位注册组装 + 停用标记分支,无 JSX)
├── src/client/locales.ts # zh/en 词典(所有 UI 文案走 locale key)
├── src/client/api.ts # 浏览器 → host 的 RPC 调用(OpResult 统一错误面)
├── src/client/ComfySection.tsx # 配置页组件(plugins.bundle.config 面板 + 插件更新条)
├── src/client/ComfyDisabledSection.tsx # 版本不兼容"已停用"说明面板
├── src/client/ComfySection.module.css # 配置页样式(CSS Modules + --dsw 设计令牌)
├── docs/compat-guide-0.1.1-to-0.1.2.md # 0.1.1↔0.1.2 兼容手册(两线差异取证 + 带代码方案)
├── docs/compat-plan-TEMPLATE.md # 兼容迁移执行记录骨架(每次追新 cp 一份填写)
├── docs/compat-plan-0.1.7-rc.1.md # 0.1.5-rc.3→0.1.7-rc.1 兼容迁移执行记录
├── docs/compat-plan-0.1.7-rc.2.md # 0.1.7-rc.1→0.1.7-rc.2 同线追新执行记录(main 窗口)
├── docs/compat-plan-0.2.0-rc.1.md # 0.1.7-rc.2→0.2.0-rc.1 跨 minor 迁移执行记录
├── docs/compat-plan-0.2.0-rc.2.md # 0.2.0-rc.1→0.2.0-rc.2 同线追新执行记录
├── docs/compat-plan-0.2.1-rc.2.md # 0.2.0-rc.2→0.2.1-rc.2 新线迁移执行记录
├── docs/compat-plan-0.2.1-rc.5.md # 0.2.1-rc.2→0.2.1-rc.5 同 tuple 追新执行记录(当前窗口)
├── tsdown.config.ts # client bundle 构建(CJS 工厂 + 基线外部化 + CSS Modules 内联自注入)
├── tsconfig.json # 全量类型检查(pnpm typecheck)
├── tsconfig.build.json # host 半构建(lib/index.js)
├── cordis.patch.yml # bundle 层:安装时插入插件行
└── package.json # dsh.bundle + dsh.client 双清单,prepare/prepack 构建