Files
dsh_ai1net_server/交付物/IM插件跨进程桥-20260925.md
admin c1b5e4d966 chore(工作区): 全量入库 + 补齐 .gitignore(以工作区为准)
- 变更规模:新增 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/ 知识文件,按口径入库)
2026-10-10 23:13:22 +08:00

5.4 KiB
Raw Permalink Blame History

交付物 · IM 插件跨进程桥(2026-09-25 · 第 2 棒)

工作区:E:/ProgramData/AIProject/aliyun-dsh-server|基线:D:/github/dsh_shenxian 上游:群组插件对接单(只读)+ 本工作区 交付物/IM插件接入完备性审计-20260925.md(本棒即其整改) 用户口径:「按照你的方案处理,完善 IM 功能让群组会话的插件可以开发」


§0 一句话

上一棒查出:插件跑实例内、IM 宿主在平台进程 ⇒ 缺跨进程那一层,插件「登记不上、够不到出向」。 本棒把那座桥建起来 ⇒ 「插件单向发起」的接入现在通了(登记 / 读 / 出向); 「平台要回头叫插件」的还没通(发言规则 / 事件回调)—— 这是唯一剩余缺口,已如实登记。

§1 交付(3 新 3 改)

件 内容
src/im/sdk/registry.ts(新) ImPluginBridgeRegistry:按实例隔离(每实例一份宿主)· room_type 全局唯一(跨实例同名具名拒)· 形状闸先于占用(失败不留残登记)· authorizeOutbound(bot 必须是该房成员)· unregisterInstance / snapshot
sdk/im-plugin-host/index.mjs(新) 插件侧 SDK(零依赖单文件):ready() 登记 / frame() 广播 / say() bot 发言 / rooms() / messages() / subscribe() 轮询增量订阅 / sanitizeManifest() 剔函数
test/im-plugin-bridge.test.mjs(新) 14 例
src/web/routes/im.ts(+230) 5 个端点:plugins/register · plugins/unregister · plugins/out/frame · plugins/out/message · plugins/bridge(观测)
src/im/sdk/index.ts 门面导出
package.json test / verify 各登记 1 处(diff 仅 2 行)

§2 判据读数

  • npm run build rc=0
  • node --test test/im-plugin-bridge.test.mjs = 14 / 14 过 / 0 败
  • npm test = 618 / 608 过 / 5 败 / 5 跳过(基线 604/594 ⇒ +14 全为本棒;5 败仍是投放线 tar EBUSY,未增一败)
  • npm run check:layering rc=0 ✅ 无新增违规

§3 插件作者现在能做什么

import { createImPluginHost } from '@dshs/im-plugin-host'

const host = await createImPluginHost({ pluginId: '@dsh-local/im-plugin-demo', manifest: { /* 声明面 */ } })
await host.ready()
await host.frame({ roomId, channel: 'doc.cursor', data: { at: 42 } })        // 高频广播(不落库)
await host.say({ roomId, botId: 'bot_demo', payload: { kind: 'text' } })     // 落库发言
host.subscribe(roomId, (msg) => { /* 增量消息 */ }, { intervalMs: 1500 })      // 订阅

✅ 能做:纯数据型 · 纯界面型 · 机器人助手型 · 聊天增强型(卡片/公告/投票) · 实时协同型(帧广播部分) ❌ 还不能:回合制 / 限速型(发言规则走同步回调)—— 降级三条见 §5。

§4 两条关键自决(可推翻)

  1. 登记只收「声明面」:check / onEvent / render / onAction 是函数,跨不了进程 ⇒ 只传声明,函数侧回调留在实例内;SDK 的 sanitizeManifest 自动剔除(测试断言"序列化后不含 function")。
  2. 出向发言多一道闸:同进程时 bot 必然由房主加进成员表;跨进程必须自己查 ⇒ authorizeOutbound,且未注入成员判定 ⇒ fail-closed 拒(⛔ 不"判不了就放行")。
  3. 不做"平台反向打进实例"(要实例可寻址 + 心跳,脆)⇒ 改用插件拨出,符合既有"拨出式"纪律(⛔ 插件不开端口)。

§5 反向通道:🔴 已定必须补(2026-09-26 用户拍板 —— 本条覆盖下表原「本期不支持」的口径)

🔴 用户裁定原话:「都需要实现完整,才能让插件接入,否则两边都要返工」 ⇒ 下表两行的"怎么办(降级)"已作废:speakRules.check 与 events.onEvent 两条都要补齐。 做法 = 实例侧 SDK 长轮询拉取(保持"拨出式",⛔ 平台不打进实例、⛔ 不需实例可寻址)。 规格 ⇒ 平台工作区 接续包_IM反向通道实现_20260926.md。⛔ 原会话"不必急着补"的判断被用户推翻。

项 原「本期不支持」原因(已作废) 现状
发言规则 speakRules.check 是"平台写之前同步问插件"的回调 ⇒ 需反向通道 🔴 已定要补(同步语义 + deadline;超时缺省放行、契约可声明 onTimeout:'deny')
events.onEvent 回调 同上 🔴 已定要补(异步语义,⛔ 不阻塞消息流)

| 面板 render / onAction | 不需跨进程(面板在实例内渲染,函数本来就在自己进程里) | 要写数据/发言 ⇒ 用出向 | | 出向的审计归属 | 本口不校验"该插件是否真在该实例启用"(与 /api/im/data/* 现状同源) | 补法 = 把 pluginId 绑进装配凭据 ⇒ 投放线面 |

§6 未做 / 边界

⛔ 未部署 · 未 commit / push · 未动 47/106 · 未动云安全组(D8 仍需你在控制台操作)· 未改 A–E 五单结论。 🔴 下一棒已登记(2026-09-26):反向通道实现 = 接续包_IM反向通道实现_20260926.md(用户已拍板必须补)。 ⚠️ 云安全组操作(D8)仍为用户主动搁置项(交付物/端口决策与设备中继可行性-20260926.md),⛔ 不当待办。