前言¶
DSH 的理念是「一切皆插件」,WebUI 上的不少能力都由插件注入。做智能体开发时常会遇到这样一个需求:让几个模型围绕同一份上下文轮流讨论——一个出方案、一个挑毛病、一个做总结。在没有专门工具时,通常只能在多个会话之间手动搬运上下文,发言顺序也要自己盯着。
下面介绍的 dsh-group-chat 把这件事做成了群聊形态:你在 DSH WebUI 里当「群主」,管理一组可配置的 AI 角色,让它们围绕共享上下文进行多模型轮流发言。插件由 Qx002 维护,当前版本 0.1.0。
这是什么¶
dsh-group-chat 是一个 DSH 原生多 AI 群聊插件,核心设定有三点:
- 用户是「群主」,AI 角色是群成员,可以配置角色卡、模型、发言模式,也能随时禁言;
- 群聊是独立页面,与工作区原生对话完全隔离——插件不接管原生输入框(不注册
agent/pre-step拦截),原生对话区域的输入框、模型选择、读写权限继续为原有工作流服务; - 纯 Node.js / Cordis 实现,不使用 Tauri / Rust。
核心功能¶
独立群聊页面¶
插件通过 WebUI slot 注入两个入口:
conversation.input.left:输入卡工具栏左端的群聊开关,点击开启或关闭独立群聊页面,状态持久化到enabledSessions,全局开关自动联动;settings.section(idgroup-chat):设置面板中的「群聊设置」页。
群聊页面约覆盖原生对话区域 2/3、居中显示,右上 ✕ 关闭、左上 ⚙ 打开设置。聊天视图是微信式布局:AI 成员消息在左、用户在右,独立输入框支持 Enter 发送、Shift+Enter 换行,也可以发送图片(PNG/JPEG/WebP/GIF,经 DSH attachment 服务持久化后作为 image block 进入模型请求并在气泡内显示)。页面打开期间轮询消息视图。
AI 角色管理¶
先在设置页添加成员,再逐个配置。每个 AI 角色可以设置:
- 角色卡 System Prompt 与初始上下文;
- Provider / Model,由 ModelPicker 级联选择器选择:点击后先列出 DSH 已接入的提供方(
ctx.llm.listProviders()),再列出该提供方通告的模型(listModels(provider)),数据与 DSH 模型目录完全一致;没有目录时也可手动填写 provider/model; - 发言模式(被动回复 / 主动发言)与主动发言策略;
- @ 别名、触发词;
- 禁言/启用权限,成员列表支持快捷禁言。
发言者选择与群主规则¶
每一轮谁发言按固定优先级决定:
mentioned(@名字/别名)→ triggered(触发词)→ active(主动发言成员)→ default(兜底)
候选池先过滤掉被禁言或已移除的成员;单轮发言者数量受 maxAgentsPerTurn 截断;muteAll 开启时不生成任何回复,但用户消息仍会落盘;无人触发时由第一个可用成员兜底。
群主规则集中在设置页:禁言全体、主动发言总开关、单轮回复上限、单轮发言者上限、并行生成、超时、@ 语法。
共享上下文¶
所有发言者看到同一份转写。插件把统一的 Session Log 投影为「[AI名称]: <内容>」行,用户行使用设置里的「用户名称显示」(默认「群主」),按滚动窗口 maxMessages 截取;转写模板可配置,角色卡注入有独立开关。顺序模式下,后发言者能看到本轮先发言者的最新回复——每一步都重新派生转写。
主动发言¶
被动成员等 @ 或触发词,active 模式的成员会自己开口。每个主动成员按 [minIntervalMs, maxIntervalMs] 内的随机间隔挂一次性定时器,触发前检查一组条件:群聊启用、主动发言总开关开启、未禁言全体、该成员未禁言、会话无进行中的轮次、距上次活动满足间隔要求。条件临时不满足就 30 秒后重试。配置变更会即时重置全部主动定时器,策略改动马上生效。
轮次事件与流式输出¶
一轮群聊的事件序列与官方 agent-loop 同构:
turn/start → user/message → 每发言者: step/start → assistant/chunk* → assistant/message → step/end → turn/end
为避免与原生轮次编号冲突,群聊 turn 编号使用 GROUP_TURN_BASE = 1_000_000 起的偏移空间,恢复会话时扫描日志续号。流式方面,每个 chunk 先落盘 assistant/chunk,用官方 BlockAssembler 组装后写 assistant/message,消息带 source: {provider, model} 溯源信息与 usage。
失败语义比较克制:单个发言者失败只记录自身,不影响其他人继续发言;全部失败才以 turn/end(error) 收尾;中途取消标记为 aborted。
配置持久化¶
配置存放在 group-chat 用户设置命名空间:插件通过 installSettingsSection 注册同一份 schema,解析优先级是 schema 默认值 → 入口 base → ~/.dsh/settings.yaml 用户层。环境中没有 settings 服务时,写入路径抛出 GroupChatError(码 NO_SETTINGS),读取降级为入口配置。每次配置提交都会广播 group-chat/config-updated 事件,编排器据此重置主动发言定时器。
安装与构建¶
本次核对的资料(README、package.json)中没有给出官方安装命令,这里不自行拼接。安装方式请以仓库 README 为准(README 中的仓库主页字段目前还是 TODO 占位,以 GitHub 仓库页为准):
https://github.com/Qx002/dsh-group-chat
从源码构建时,插件声明的 peer 依赖如下:
@deepseek-ai/cordis ^4.0.1
@deepseek-ai/dsh-attachment ^0.1.0-rc.6
@deepseek-ai/dsh-llm ^0.1.0-rc.6
@deepseek-ai/dsh-session ^0.1.0-rc.6
@deepseek-ai/dsh-settings ^0.1.0-rc.6
@deepseek-ai/schemastery ^3.18.1
react ^18.2.0
构建命令是 npm run build,等价于 tsc 编译主机端 lib,加上 tsdown 打包浏览器端 client.js。
典型用法¶
从界面开始,流程大致是:
- 点击输入框旁的群聊开关,打开独立群聊页面;
- 左上 ⚙ 进入群聊设置,添加 AI 成员,配置角色卡、模型、发言模式;
- 回到聊天页输入消息,@ 某个成员,或等主动发言成员自己开口;
- 需要叫停时点右上 ✕ 关闭页面(开关同步回「关」,主动发言定时器停止),或在代码里调用
cancelSession。
习惯写代码的话,也可以直接走 Service API:
// 持久化开启某会话的群聊
await ctx.groupChat.enableSession(sessionId);
// 添加 AI 角色
const agent = await ctx.groupChat.addAgent(input);
// 管理成员状态
await ctx.groupChat.setMuted(agent.id, true);
await ctx.groupChat.setMode(agent.id, "active");
// 群主控制
await ctx.groupChat.setMuteAll(true);
await ctx.groupChat.setActiveSpeakEnabled(false);
// 提交用户消息并运行一轮群聊(可携带图片)
// 要求群聊已启用,且该会话在 enabledSessions 中
await ctx.groupChat.submitMessage(sessionId, text, images);
// 中止进行中的群聊轮次
await ctx.groupChat.cancelSession(sessionId);
完整接口还包括 getConfig / getAgent / listAgents / getStatus / watch、updateAgent / removeAgent / setEnabled、updateHostRules / updateSharedContext、setGroupEnabled / setGroupName、isSessionEnabled / listEnabledSessions、getEngine / listModelCatalog。
开发者接口¶
除了 UI,插件留了三类接入点,供其他插件或脚本使用:
- WebUI API 路由
/api/group-chat/*:state、config、models、messages、attachment、toggle、submit、cancel、agents、host。带同源 POST 防护,错误统一为{ok:false, code, message}。 - Cordis 事件:
group-chat/config-updated、agent-added/updated/removed、turn-start、agent-speaking、agent-spoken、turn-end、orchestrator-attached/detached,可按需订阅。 - 客户端 bundle 纯度 gate:客户端只允许引用平台模块(react、cordis、ui-slots 等)与内联安全层,任何其他
@deepseek-ai值导入会在 build 期被拒绝——想与它协作,必须走 cordis 服务而不是直接 import。
适用场景与注意¶
适合谁:
- 想让多个模型围绕同一份上下文讨论、互评、头脑风暴的 DSH 用户;
- 想对比不同模型在同一角色设定下表现的人——每个成员独立配置 Provider/Model;
- 插件开发者:轮次事件与官方 agent-loop 同构,可以基于 Cordis 事件或
ctx.groupChat做二次开发。
几点注意:
- 插件以当前 dsh 进程权限运行,安装前建议先阅读源码;
- package.json 的 files 里包含 LICENSE 文件,但资料未标明具体许可证类型,使用前请到仓库确认;
- 群聊与原生工作区对话完全隔离,群聊内容不会混入工作区对话;
- 版本为 0.1.0,README 标注基础设施、编排器引擎、WebUI 三个阶段均已完成,但整体仍处于早期阶段。
结尾¶
dsh-group-chat 把多模型协作放进了 DSH 原生界面:群主控场、成员按规则轮流发言、共享一份上下文,同时给开发者留了完整的 Service API 与事件订阅。如果你在 DSH 里有多个 AI 角色协作的需求,可以按上面的步骤试一试。
- 插件目录页:https://www.skillhub.cn/plugins/Qx002/dsh-group-chat
- GitHub 仓库:https://github.com/Qx002/dsh-group-chat