前言¶
DSH 的理念是「一切皆插件」,IM 接入通常靠 @xmanrui/dsh-im 或 dsh-onebot-qq 这类插件完成。拿它接微信公众号、QQ 群或个人号时,一个常见问题是:模型回复一大段贴过去,看起来像机器人;想让它像真人一样主动开口,也没有现成能力。这两个插件本身都不提供分段发送和自动发送。
dsh-im-companion(npm 包 @jiang_li/dsh-im-companion)就是补这两块空白的插件,由 jiang_li(GitHub 账号 zingreqe)维护,MIT 协议。它针对已抓取资料中 @xmanrui/dsh-im 和 dsh-onebot-qq 缺失的能力,加了三样东西:分段发送、自动发送、话题库。下面按功能、安装、用法、限制的顺序介绍。
定位¶
一句话:在不改系统提示词、不绕开原有链路的前提下,让用上述两个插件的 DSH 机器人回复更像真人,并能按你定的时间窗主动说话,参数可逐机器人配置。
它不是通用 IM 通道,而是挂在已有 IM 插件上的扩展。两个插件都没装时,插件仍能加载,面板里只有空列表。
核心功能¶
1、分段发送¶
让大模型自己分段,规则很简单:模型输出里的空行就是气泡边界,插件按段落逐条发出。
实现上有个关键点:前几段由本插件发送,最后一段仍走 dsh-im 原来的出站链路,避免同一段内容被发两次。插件不额外注入提示词,因此不会覆盖或绕开系统提示词、记忆插件之类的上下文注入。
2、自动发送¶
按每个机器人的发送时间窗、间隔、随机性、每日上限,定时在真实会话里跑一轮 Agent:触发消息作为 im-proactive 来源的消息放进会话,会话自己的系统提示词、记忆和其他插件注入全部生效,生成结果按段落发回 IM。
默认选取该机器人最新未归档的会话,也可以在面板手动指定某条会话固定使用。
随机性参数的映射方式:0 时实际间隔在 [0, 2×间隔] 内均匀随机,10 时严格固定间隔,中间线性过渡。可以跨夜排时间窗。
3、话题库¶
插件注册了一个 topic_library 工具,模型可以把聊天里出现的话题、兴趣、偏好按「一级分类 / 二级分类 / 描述」收进库里。可配置入库敏感度(0–10,为 0 时工具不出现在模型上下文里)、遗忘天数(0 为不自动遗忘)、固定话题,也可以在面板手动增删改。
主动发消息时可以把已有话题注入提示词,让主动消息不那么生硬。
对两个 IM 插件的适配细节¶
@xmanrui/dsh-im¶
这是个聚合机器人服务插件,支持微信、QQ、飞书、企业微信等连接,优点是不容易被风控,缺点是机器人账号用不了真实账号的功能。本插件对它的扩展方式是在 Host 侧包装 typertGateway.invoke:只处理 dsh-im 的 owner peer(interactions: 'none')发起的 session.page 请求,在含 turn/end 的响应里注入合成 assistant/message 事件,把已发过的前缀段从 dsh-im 的最终答案里抹掉,只留末段。Web UI 的会话传输不受影响。
dsh-onebot-qq¶
这个插件通过 napcat 连接真实 QQ 号,能提供真实账号的聊天能力,但没有自动发送。两者的分段规则被本插件统一。由于 dsh-onebot-qq 不向宿主暴露服务,插件用了两个缝:
1、包装它的 OutboundPipeline.prototype.sendToChat,出站文本按空行拆成多条气泡,仍走它自己的 Markdown 清理、转发块、t2i、队列与重连补发。
2、冷会话(重启后还没收到过消息)bridge 不会投递,插件在 6 秒后接管,先走捕获到的 bridge 实例的出站闸门分段发送,bridge 还没出现时退回 qq_send_segments 工具(每段 500 字以内、每批 9 段)。
面板里每个 QQ 私聊和群聊是独立卡片(onebot:private:<QQ> / onebot:group:<群>),可以同时给多个私聊开自动发送,各自的时间窗、间隔、随机性、每日上限、回复后静默和话题提示互不影响。旧的单个「QQ(dsh-onebot-qq)」配置会自动迁移到它绑定的那条聊天上。
使用该插件控制的真实 QQ 号容易被风控和封号,不建议用主号连接。另外需要机器人之前至少和用户聊过一次,才会存在绑定会话;冷会话会在 30 秒内被索引出来。
安装与启用¶
在 profile 为 web 的 DSH 进程里执行:
dsh plugin --profile web add @jiang_li/dsh-im-companion
装完重启或重载 DSH。插件要求 Node.js >= 22,当前版本 1.4.2。本地开发时,可以把 plugin_manager install_bundle 指向源码目录,profile 里是软链接,改完即生效。
注意 plugin_manager install_bundle 对已安装的包会返回 already-installed,升级版本号不会覆盖安装,需先 remove_bundle 再装。
面板使用¶
装好后刷新 DSH Web 页面,侧边栏出现「主动消息」,面板两个页签。
发送设置页签把每个机器人排成宫格里的一格:
- 分段发送:总开关、段间延迟范围、模拟打字速度(字数上限仅保留给旧的分段函数,IM 分组以模型段落为准)。
- 自动发送:总开关,每机器人一张卡片,含发送会话(留空为「自动:最新未归档会话」)、时间窗(可跨夜)、间隔分钟、随机性 0–10、每日上限、回复后静默时长、时区、话题提示。
- 消息提示词:一段自定义模板,作为用户消息追加进目标会话,不替换系统提示词。
- 「立即发一条」用当前草稿立即试发,不需要先保存,也不会动表单里的其他改动。
话题库页签只在切过去时加载和显示话题数据,包含入库敏感度 0–10、遗忘天数、话题列表与手动编辑。
消息提示词与占位符¶
模板会作为一条 im-proactive 用户消息追加进目标会话。面板上有占位符按钮,点一下插到光标处,「恢复默认」可回到内置模板。支持的占位符:
| 占位符 | 内容 |
|---|---|
{{time}} |
发送时刻(本地时间,如 2026-11-02 18:27) |
{{weekday}} / {{date}} |
星期几 / 日期 |
{{topic}} |
该机器人卡片里的「话题提示」 |
{{topics}} |
话题库里的分类与摘要(最多 40 条,固定项标 ★) |
{{topicHints}} |
最近关注的话题提示 |
{{lastTexts}} |
最近主动发过的内容,避免重复 |
未填值的占位符留空,多余空行自动合并。
存储与改动重载¶
设置、话题库与运行状态写入 ~/.dsh/dsh-im-companion.json,原子写入。自动发送总开关、每个机器人的开关和发送会话改动会立即保存,其余字段在点「保存」时落盘。
改动后的重载方式:
1、改了 Host 侧(index.js、src/*.mjs):plugin_manager set_bundle 禁用再启用即可重新 import,不必重启整个 DSH;不放心就重启。
2、改了客户端半(client.js):dsh-client-modules 只在包来源变化时重读文件,没有 pnpm run dev:web 看护时刷新页面拿到的仍是旧 bundle,需要先用 set_bundle 把插件设为 enabled:false 再设回 true,随后刷新页面。
已知限制¶
1、分段只对能解析出投递目标的 IM 会话生效,解析不到时本轮按原样整段发送。
2、QQ 的分段依赖包装 lib/outbound.js,包升级后若改了类名或方法名,包装会失败并自动退回整段发送,不影响 bridge 本身。
3、自动发送要求该机器人至少有一个已绑定会话,一个都没有时只会在面板运行记录里提示,不会凭空新建会话。
4、主动发送依赖渠道的主动投递能力与 contextToken 新鲜度,掉线或令牌失效会记在运行记录里。
适用场景与注意¶
适合已经在用 @xmanrui/dsh-im(微信公众号、飞书、企业微信等聚合渠道)或 dsh-onebot-qq(napcat 真实 QQ 号)的 DSH 开发者,想改善机器人回复观感、加上主动问候的场景。不想写额外提示词、想保留原链路的分段行为,也符合这插件的实现方式。
安装前建议在 GitHub 仓库 检查源码与 MIT 许可证,确认它包装的 Host 侧 API(typertGateway.invoke、OutboundPipeline.prototype.sendToChat、ChatBridge.prototype.onSessionEvent 等)与你当前的 @xmanrui/dsh-im、dsh-onebot-qq 版本一致。插件以当前 dsh 进程权限运行,自动发送会在设定时间真实对外发消息,时间窗和每日上限要先设好。QQ 真实号场景注意风控,不要用主号。
小结¶
它做的事情很具体:在已有 IM 插件之上加分段发送、自动发送和话题库,改动集中在包装出站链路和触发真实 Agent 轮次,不改系统提示词,参数逐机器人可配。目录页在 https://www.skillhub.cn/plugins/zingreqe/dsh-im-companion,源码在 https://github.com/zingreqe/dsh-im-companion。