- 变更规模:新增 514 / 修改 62 / 重命名 155 / 删除 4(归档重组与文档轮次) - .gitignore 修:`归档/**/db-cwd归一-备份-*/` —— 原规则写绝对层级(归档/db-cwd归一-…), 目录搬进 归档/配置与备份/ 后**静默失效**,43 MB 的 DB 备份又变成未跟踪 - .gitignore 补:嵌套 git 内部数据(归档/内嵌git-20261008/、归档/skills-git-旧线-20261007/dotgit-原样移出/) - .gitignore 补:运行态与部署副本(.workbuddy/collab/、.workbuddy/tools/、.workbuddy/.load-pending、.workbuddy/tmp-*) - .gitignore 补:备份件(*.bak-*) - 未跟踪文件从 2190 降到 890(其余为 归档/ 归档件与 .workbuddy/memory/ 知识文件,按口径入库)
15 KiB
接续包 · IM 线 · 2026-09-26 00:32
接续点 · IM 线(插件接入面收尾 + 文档 + 对接答复) · 2026-09-26 00:32
-
来源会话: 本会话(阿里云 dsh 平台开发会话) | 结束原因: 上下文 32.8 万强制收口
-
原目标(用户本轮原话,不翻译、不缩写):
- 「创建接续会话把IM的改造优化处理完成」
- 「然后更新IM接入文档」
- 「并回复插件的对接文档」
-
基线: HEAD=
e6207aa(D:/github/dsh_shenxian,未 commit) | 远端 master = 未核(本会话未 push) | 域锁 = 无(已释放) -
产物(新会话必须逐一确认存在):
- 代码面(
D:/github/dsh_shenxian):src/im/sdk/types.ts(+206)·src/im/sdk/host.ts(+362)·src/im/sdk/binding.ts(新) ·src/im/sdk/registry.ts(新) ·src/im/sdk/index.ts·src/im/hub.ts(+36)·src/im/ws.ts(+84/−1)·src/web/routes/im.ts(+368)·sdk/im-plugin-host/index.mjs(新) +package.json - 测试(新):
test/im-plugin-bridge.test.mjs(14 例)·test/im-backpressure.test.mjs(8 例) - 文档库(
D:/github/dsh_shenxian/dsh-server-docs):01-规范/09-IM插件SDK与扩展点契约.md(§2 加第 8 项 · §3.5 接线器 · §6 修事务口径 · §8 判据四档 · §9 出向端口 · §10 跨进程接入 · §11 投递可靠性与容量)·01-规范/08-插件开发与对接规范.md(修路由指针 + SDK 获取 + 09 指针 + §11 变更记录) - 评估/交付件(本工作区
交付物/):IM插件接入面-20260925.md·IM插件接入完备性审计-20260925.md·用户组网群聊可行性评估-20260925.md·端口与容量瓶颈评估-20260925.md·端口决策与设备中继可行性-20260926.md·扇出背压修复-20260926.md
- 代码面(
-
校验命令:
cd /d/github/dsh_shenxian && npm run build && node --test test/im-plugin-bridge.test.mjs test/im-backpressure.test.mjs 2>&1 | tail -5→ 期望输出: 两个文件合计 22 例、fail 0(bridge 14 + backpressure 8) -
未完成(用户要的、还没做的 —— 优先于 AI 自己加的收尾):
✅ 本棒(「IM接入面收尾-20260926」· 2026-09-26 00:38–01:0x)收口状态
已完成
- 1-① 端到端真跑 ✅(真起平台 + 真 HTTP + 插件侧 SDK 走 5 端点):
脚本
tmp/im-bridge-e2e-20260926.mjs,23 例 / fail 0。⇒ 跑法cd /d/github/dsh_shenxian && node <脚本绝对路径>。 - 1-② 部署到 47 ✅:推
lib/im/**+lib/web/routes/im.js+sdk/**(⛔ 未带别的线的未部署改动)。 47 侧备份/opt/dsh/backups/im-bridge-predeploy-20260926.tgz;重启dshs= active;/api/im/plugins/bridge与/api/im/stats均 401(= 路由已加载,非 404)。 ⚠️ 落地文件属主:tar 会保留本地 uid ⇒ 47 上新文件曾变197108,已 chown -R root:root 修回。 (⛔ 下棒再推时给 tar 加--owner=root --group=root,或推完立刻 chown。) ⚠️ 47 上另有先前就存在的非 root 文件(lib/web/routes/business-plugins.js、admin.js、essential-plugins.js等)——非本棒落地、未动,仅登记。 ⛔ 106 未部署(IM 宿主在 Manager 进程,Worker 不带 IM 路由)⇒ 按需为「不需要」。 - 3 更新 IM 接入文档 ✅(部分):09 新增 §12 插件作者快速上手(五步 + 可跑片段 +
能做/不能做 + 四个必知坑 + 反向通道降级三条)。⛔ 未动任何已落章节(§2–§11 一字未改)。
❌ 仍缺:可跑的最小示例工程(
poc/business-plugins-im/三例仍是旧契约)。 - 4 插件对接答复件 ✅:本工作区
交付物/插件对接答复件-20260926.md(⛔ 未改dsh-plugin-partment一字节)。
🔴 本棒抓出并修掉一个真缺陷(新增,不在原接续包内)
- 症状:插件走完登记后
frame()/say()恒plugin-unavailable。 - 根因:
routes/im.ts的bridgeAuth把请求头里的包名(@dsh-local/im-plugin-demo) 直接当内部 id 去查注册表,而注册表按pluginIdOf(包名)(im_plugin_demo)存 ⇒ 恒查不到。 ⇒ 出向面在生产上不可达(第 8 项等于白做)。 - 为什么单测没抓到:
test/im-plugin-bridge.test.mjs刻意不碰真实网络(mock fetch + 直接把归一化 id 递给注册表)⇒ 从不经过这一层翻译。只有真 HTTP 才暴露。 - 修法:
bridgeAuth现同时交packageName(供"头与清单自洽"判)与pluginId(供注册表查);两处outboundPortFor改用auth.pluginId。改动仅限routes/im.ts(内核四档不变:store.ts零改动 /hub.ts纯插入 /ws.ts只动投递点 /routes/im.ts纯插入 —— 本次属"修 bug"那类,故允许动既有逻辑,须有回归证据)。 - ⚠️ 回归证据未入库:现为
tmp/脚本(接续包原口径即"临时脚本落 tmp/")。 若要永久回归⇒ 下棒需把它落成test/im-plugin-bridge-e2e.test.mjs+ 在package.json的test/verify各登记 1 处(A=B 各 1 行,⛔ 用 Edit 精确替换)。
⛔ 仍未完成(下棒依据)
- 1-③ 生产标定背压阈值 ❌ 未做(缺真实读数):
/api/im/stats现为 401(admin 专属), 无 admin 会话读不到peakPendingBytes;且当前无真实流量 ⇒ 读数恒 0,改了也是拍脑袋。 ⇒ 阈值保持 4 MiB 不变(保守起点),改参数入口已就绪(IM_SEND_BUFFER_LIMIT_BYTES,可注入)。 标定法(拿到 admin 会话或真实流量后照做):连读GET /api/im/stats的peakPendingBytes一段时间, 取其分位值作为阈值下限,改 drop-in 环境变量 →systemctl restart dshs(⛔ 不改代码)。 - 2 反向通道 —— 🔴 2026-09-26 用户已拍板:必须补、且要做完整
(原话「都需要实现完整,才能让插件接入,否则两边都要返工」)。
本棒据此改了 09 §10.4 / §10.5 / §12.5 的口径(从"本期不支持"→"已定必须补")+
同步
交付物/IM插件跨进程桥-20260925.md §5/§6与交付物/插件对接答复件-20260926.md, 并产出施工规格接续包_IM反向通道实现_20260926.md。 ⚠️ 实现交执行棒(本棒受会话预算限制,⛔ 未动任何代码);⛔ 原文"不许拍成已定"的禁令至此解除 —— 因为是用户本人拍的,不是新会话替原会话拍的。 - §1 对接单未消的 4 条(纯文档):#2 表声明入口(P1,需先定口径) · #4 移动端 ·
#5 错误码/自测清单/变更记录 · #8 内部编号 107/108。
⚠️ 接续包原记「P1×2 已消」不准:实测 #1 已消、#2 未消(09 §4 仍有
tables: [{且全篇无dsh.data.schema)。
- 🔴 IM 改造的收尾三件(= 用户「处理完成」的落地口径,按序):
① 端到端真跑验收 —— 桥的 5 个端点(
/api/im/plugins/{register,unregister,out/frame,out/message,bridge})只过了单测,从未真跑;需在本机起平台+用sdk/im-plugin-host走一遍真 HTTP。 ② 部署到 47(+按需 106) —— 本机代码面完成,生产未部署(R8:开发环境服务器,动手前一句话说明即可)。 ③ 生产标定背压阈值 —— 现为保守起点 4 MiB;观测面GET /api/im/stats的peakPendingBytes拿到真实读数后改参数(⛔ 不改代码)。 - 🔴 **「反向通道」是否补 —— ⛔ 属待用户拍板,不许新会话替原会话拍成「已定」:
- 现状:「插件单向发起」已通(登记 / 读 / 出向);「平台回头叫插件」未通(
speakRules.check发言规则、events.onEvent事件回调)。 - 原会话判断(可推翻):「不必急着补」—— 已有降级三条(规则参数写房间
config/ 出向主动纠偏 /host.subscribe()轮询替代事件回调,后者已实测够用)。 - 若要补 ⇒ 需要平台 → 实例的反向调用面(含鉴权、超时、实例可寻址性),是新工作量。
- 现状:「插件单向发起」已通(登记 / 读 / 出向);「平台回头叫插件」未通(
- 更新 IM 接入文档(用户第 2 件事):
09已更新到 §11,但缺一份「插件作者快速上手」 —— 现在用法散在 §10.3,且没有可跑的最小示例工程(poc/business-plugins-im/三个示例是旧契约,未含第 8 项出向与跨进程桥)。 - 回复插件对接文档(用户第 3 件事):即
E:/ProgramData/AIProject/dsh-plugin-partment/对接单_平台侧-IM板块待优化与Macro改造可行性_20260925.md。⚠️ 那是别的工作区 ⇒ ⛔ 只能在本工作区产出「平台侧答复件」,由用户转交,⛔ 不得直接改那边一个字节。答复要覆盖:§1 九条(P1×2 + P2×3 已消,P2×2 + P3×2 待定)+ §2 Macro 改造可行性(第 8 项出向端口已具备,§2-3-1 高频广播已解决:frame档不落库)+ §4 两个待拍板项的平台侧回答。
- 1-① 端到端真跑 ✅(真起平台 + 真 HTTP + 插件侧 SDK 走 5 端点):
脚本
-
下一步(第 1 个动作 = 具体命令):
- 先跑校验命令(见上)—— 不符即停、只报告。
- 读
交付物/IM插件跨进程桥-20260925.md与交付物/扇出背压修复-20260926.md(本会话两份最新落地件,含未完成项与设计取舍)。 - 端到端真跑(未完成 1-①):本机起平台(
DSH_IM_WS默认开)→ 写一个临时脚本用sdk/im-plugin-host的createImPluginHost()走register → frame → say→ 断言ok:true(临时脚本一律落tmp/,⛔ 不入库)。 - 部署(未完成 1-②)→ 标定(1-③)→ 文档(3)→ 答复件(4)。
- ✅ 未完成 2(反向通道)—— 用户已表态(2026-09-26:必须补、做完整)⇒
下棒依据改为
接续包_IM反向通道实现_20260926.md(⛔ 不再是"先不碰")。
-
关键决定(已定项 + 为什么 —— 防新会话推翻重来): ① 🔴 插件跑在「用户实例内」、IM 宿主在「平台进程」⇒ 跨进程 —— 依据:用户自配模型是起实例时写进实例的(
credential_vault→ spawn 写settings.yaml),平台侧拿不到 ⇒ 插件必须在实例内。 ② 桥 = 插件「拨出」而非平台「打进」 —— 符合既有"拨出式"纪律(09 §2-6:⛔ 插件不开监听端口),且断连可退化为普通聊天。 ③ 登记只收「声明面」 ——check/onEvent/render/onAction是函数、跨不了进程;函数侧回调留在实例内。 ④ 出向发言多一道闸 —— bot 必须是该房成员(同进程时必然成立,跨进程必须自己查);未注入成员判定 ⇒ fail-closed 拒。 ⑤ 🔴 背压:慢客户端不虚减delivered——write()返回 false = 水位满(数据已排队、会送达)⇒ 若记成丢帧会污染观测。若用户要"慢客户端单独计 skipped"⇒ 是语义变更、需重新拍板。 ⑥ 判据分两类(已写进09 §8):新增能力 ⇒ 纯插入;修 bug ⇒ 可改既有逻辑,但须「回归用例 + 新行为可观测 + 阈值可注入」。内核四档:store.ts零改动 /hub.ts纯插入 /ws.ts允许改但被删行只限投递点 /routes/im.ts纯插入。 ⑦ 端口 D8 = 用户拍板「先不开,后续有需要再开」(09-26)⇒ ⛔ 不当待办、⛔ 不催;群聊全走 443 中继,功能完整。 ⑧ 设备当中继:路径已存在(桌面端节点接入已实测),但中继方需"别人能连到它"=用户侧 NAT 门槛;推荐替代 = 设备主动拉(⛔ 不需任何端口)。⛔ 未排期。 -
回滚点:
D:/github/dsh_shenxianHEAD=e6207aa(本会话全部改动未 commit ⇒git checkout -- <file>即可回到干净基线);dsh-server-docs同理;部署前须另做 47 侧备份(/opt/dsh/backups/)。 -
⛔ 不要重做:
- 扩展点第 8 项(出向端口)+ 面板动作 + 分片工具(types/host 已落,22 例测试覆盖)
- 跨进程桥平台侧(
registry.ts+ 5 端点 +bridgeAuth) - 插件侧 SDK(
sdk/im-plugin-host/index.mjs) - 背压修复(
ws.ts1 行改写 +hub.ts计数 + 8 例) - 两处规范文档(09 已到 §11;08 已修指针)—— 只补「快速上手」,⛔ 不重写已落章节
§A 本轮(原会话)做了什么 —— 一句话
把「IM 基础」从插件接不进来改造成双向可接入:① 补出向出口(扩展点 8)② 补跨进程桥(登记 / 出向,插件侧 SDK 齐备)③ 修扇出背压隐患;并把两处规范同步到 §11。
§B 判据读数(原会话实测,供新会话对照基线)
npm run buildrc=0npm test= 626 / 616 过 / 5 败 / 5 跳过 —— ⚠️ 5 败是既有环境问题(投放线test/shared-layer-sync.test.mjs的spawnSync tar EBUSY),与本线无关,⛔ 不要去修它(属投放线 lane)- 本线专项:
test/im-plugin-bridge.test.mjs14/14 ·test/im-backpressure.test.mjs8/8 ·test/im-sdk.test.mjs78/75 过 / 3 跳过(跳过 =spawnSync git EBUSY,已改具名跳过) npm run check:layeringrc=0 ✅ 无新增违规- 内核改动形态:
src/im/store.ts零改动;ws.ts被删改的既有行只有 1 行(socket.write(textFrame(text)),正是背压修复点)
§C 工具纪律(本线踩过的)
- ⚠️ 测试跑的是
lib/编译产物 ⇒ 改完必npm run build(原会话踩过:hub.ts新、ws.ts旧混跑 ⇒ 症状像"注入无效",浪费两轮)。定位法 = 打印两个独立观测点(注入值 ✅ 但计数为 0 ⇒ 走的是旧代码)。 - ⚠️ 本机
spawnSync git|tar EBUSY会让测试假失败 ⇒ 取证类用例改t.skip具名跳过。 - 🔴 改
package.json一律用 Edit 精确替换,⛔ 不用「读-改-写整个 JSON」(会重排格式)。原会话实测侥幸未炸,但那是运气。 - 🔴 (「接续包 md5」口径门禁)开工前重算 md5 与 prompt 里的一致才开工;不一致 ⇒ 停手报告。