# Channel Modes & Turn Shuffle 规划 ## 背景 `feat/new-feat-notes` 分支中的 `NEW_FEAT.md` 提出了两项新的行为增强需求,需要整合进入 `main` 分支下的 `plans/`: 1. **Multi-Message Mode(人类连续多消息模式)** 2. **Shuffle Mode(轮转顺序重洗牌)** 这两项能力都与 Dirigent 当前的 turn-manager、moderator handoff、no-reply override 机制直接相关,因此应作为 turn orchestration 的功能扩展纳入规划,而不是孤立实现。 --- ## 1. Multi-Message Mode ### 1.1 目标 允许人类在一个 channel 中连续发送多条消息而不被 Agent 打断。 当用户显式进入 multi-message mode 后: - 当前 channel 的 turn manager 暂停 - 所有 Agent 在该 channel 中进入 no-reply 覆盖 - moderator bot 对每条人类追加消息发送 prompt marker,提示继续输入 - 直到人类发送 end marker 才恢复 turn manager - 恢复后由 moderator 按现有调度机制唤醒下一位 Agent --- ### 1.2 配置项 建议新增以下可配置项: - `multiMessageStartMarker`:默认 `↗️` - `multiMessageEndMarker`:默认 `↙️` - `multiMessagePromptMarker`:默认 `⤵️` 这些配置应加入插件 config schema,并在运行时可被 hook/turn-manager 使用。 --- ### 1.3 行为规则 #### 进入 multi-message mode 当 **human** 消息中包含 start marker: - 当前 channel 进入 `multi-message` 状态 - turn manager 暂停 - 当前 channel 下所有 Agent 在该 channel/session 中走 no-reply override #### multi-message mode 中 在该模式下: - 人类每发一条消息 - moderator bot 自动回复 prompt marker(例如 `⤵️`) - Agent 不应参与正常轮转回复 #### 退出 multi-message mode 当 **human** 消息中包含 end marker: - 当前 channel 退出 `multi-message` 状态 - turn manager 恢复 - moderator bot 发送当前调度标识(scheduling identifier)唤醒下一位 Agent --- ### 1.4 状态建议 每个 Discord channel 维护一个 channel mode: - `normal` - `multi-message` - (后续可扩展其他模式) multi-message mode 应与 discussion channel / wait-for-human / no-reply 决策互相兼容,优先级需要明确。 建议优先级初稿: 1. closed discussion channel 2. multi-message mode 3. waiting-for-human 4. normal turn-manager --- ## 2. Shuffle Mode ### 2.1 目标 在 turn-based speaking 中,为每个 Discord channel 增加可选的 turn order reshuffle 能力。 当 shuffle mode 开启时: - 在一轮 turn list 的最后一位 speaker 发言完成后 - 对 turn order 重新洗牌 - 但必须保证:**上一轮最后一位发言者不能在新一轮中成为第一位** --- ### 2.2 配置 / 控制方式 为每个 Discord channel 维护: - `shuffling: boolean` 并新增 slash command: - `/turn-shuffling on` - `/turn-shuffling off` - `/turn-shuffling`(查看当前状态) 该状态应与 channel 级 policy / runtime state 做清晰分工: - 若只是运行时开关,可放 runtime memory - 若希望重启保留,则需要落盘策略 --- ### 2.3 行为规则 当 `shuffling = true` 时: - 正常按 turn order 轮转 - 当“当前 speaker 是该轮最后一位”并完成发言后 - 进入下一轮前重洗 turn order - 新 turn order 必须满足: - 上一轮最后 speaker != 新 turnOrder[0] 若无法满足(极端小集合场景),需要定义 fallback: - 两个 Agent 时可退化为简单交换/固定顺序 - 单 Agent 时不需要 shuffle --- ## 3. 与当前系统的关系 这两个能力都不是独立子系统,而是 Dirigent turn orchestration 的扩展。 ### 涉及模块 - `plugin/turn-manager.ts` - `plugin/hooks/message-received.ts` - `plugin/hooks/before-model-resolve.ts` - `plugin/hooks/before-message-write.ts` - `plugin/hooks/message-sent.ts` - `plugin/commands/dirigent-command.ts` - `plugin/index.ts` - `plugin/openclaw.plugin.json` - 如有必要新增 `plugin/core/channel-modes.ts` 或类似 runtime state 模块 --- ## 4. 建议实现方向 ### 4.1 Multi-Message Mode 建议不要把 multi-message mode 直接塞进规则判断字符串里,而是做成显式 channel runtime state。 建议新增: - channel mode state store - helper: - `enterMultiMessageMode(channelId)` - `exitMultiMessageMode(channelId)` - `isMultiMessageMode(channelId)` 然后: - `message-received` 检测 human 消息中的 start/end marker - `before-model-resolve` 检测当前 channel 是否处于 multi-message mode,若是则直接走 no-reply override - `message-received` 或合适的消息链路中触发 moderator prompt marker - 退出时触发一次 scheduling handoff --- ### 4.2 Shuffle Mode 建议将 shuffle 状态与 turn order 状态放在一起,或由 turn-manager 引用单独的 channel config/state。 建议新增 helper: - `setChannelShuffling(channelId, enabled)` - `getChannelShuffling(channelId)` - `reshuffleTurnOrder(channelId, { avoidFirstAccountId })` 并在 turn cycle 的边界点调用重洗逻辑,而不是在任意发言后随机改顺序。 --- ## 5. 风险与边界 ### Multi-Message Mode - 需要防止 moderator prompt marker 自己再次触发 turn logic - 需要明确 start/end marker 的匹配规则(全文包含、末尾匹配、独立一条指令等) - 需要明确 multi-message mode 下 human @mention 是否还有特殊行为 - 需要避免与 discussion closed / waiting-for-human 冲突 ### Shuffle Mode - 两个 Agent 的洗牌约束需要单独处理 - turn order 若正处于 mention override / waiting-for-human / dormant,需要明确何时允许 reshuffle - 若 turn order 成员变化,shuffle 与 bootstrap 的先后顺序要明确 --- ## 6. 结论 `feat/new-feat-notes` 分支中的内容可以整合为 `main` 下的一份独立规划文档,建议命名为: - `plans/CHANNEL_MODES_AND_SHUFFLE.md` 其定位是: - 汇总 multi-message mode 与 shuffle mode 的产品行为 - 明确它们与现有 turn-manager / moderator / no-reply 机制的关系 - 为后续代码开发和 TASKLIST 拆分提供依据 后续应将对应开发任务补充进 `plans/TASKLIST.md`。