安装
npx -y @deepseek-ai/dsh plugin --profile web add github:qyingji0122/fanout-plugin此安装命令根据 GitHub 仓库地址生成,是未经验证的安装起点。
README
维护者编写的文档快照。
fanout-plugin · DeepSeek Harness 并行多智能体编排插件
发布一条指令,同时派出多个 DeepSeek 副进程并行执行;主进程可随时与任一进程通话、修改指令、中断或收集结果。带对话流内嵌的可视化状态面板。
✨ 功能特性
- 并行派出:
/fanout命令或fanout_dispatch工具,一次派出 1~8 个 DeepSeek 副进程同时独立执行 - 按分工派出:
roles参数或/fanout 任务A | 任务B | ...语法,每个角色一个进程;不指定则全部执行同一任务 - 随时通话修改:
fanout_talk向任一副进程发送新指令/修改要求;priority=interrupt时先中断其当前工作再立即执行新指令 - 冷唤醒续谈:副进程是可续会话(continuable),即使已完成也可以再次通话唤醒继续工作
- 状态面板:对话流中自动展开的细长状态条(
🛰 并行副进程),实时显示每个进程的运行状态、结束原因、输出摘要,可一键发送指令/中断 - 状态查看:
fanout_status查看全部进程状态;fanout_collect收集已完成进程的最终汇报 - 中断控制:
fanout_interrupt中断单个或全部进程(会话保留,可后续再谈)
📦 交付物
| 文件 | 说明 |
|---|---|
host.js | Host 半部源码(工具/命令/RPC/事件/注册表,返回 Cordis Plugin 的函数体) |
client.js | Client 半部源码(对话流面板,React + 主题 token) |
README.md | 本文档 |
🚀 安装方式
本插件为 DSH(DeepSeek Harness)的动态 Cordis 插件,进程内定义并运行:
- 在 DSH 会话中调用
cordis_define:plugin.kind: "new",idPrefix: "fanou"code.host=host.js内容(函数体,return { inject, apply(ctx) {...} })code.client=client.js内容
- 调用
cordis_run激活(首次需在 GUI 批准) - 插件运行后自动注册 5 个模型工具、
/fanout命令与对话流面板
📖 使用方法
方式一:命令(不经模型,立即派出)
/fanout 3 帮我审查项目代码 # 3 个进程执行相同任务
/fanout 审查A模块 | 审查B模块 # 按分工各派一个进程
方式二:对话(主进程自动调度)
「派 5 个进程并行分析这份文档」
主进程(模型)会自动调用 fanout_dispatch 并全程协调。
方式三:面板(对话流内)
对话里自动出现的 🛰 并行副进程 长条:
- 显示每个进程:状态圆点(呼吸=运行中 / 绿=完成 / 灰=未知)+ 序号 + 分工 + 状态
- 点击进程行展开:完整 ID、输出摘要、发送新指令、中断、「先中断当前工作」选项
- 点击标题条可收起/展开
模型工具一览
| 工具 | 作用 |
|---|---|
fanout_dispatch | 发布指令并派出多个副进程并行执行(mission / roles / workers / model) |
fanout_talk | 与指定副进程通话/修改指令(worker_id 支持唯一前缀,priority: queue|interrupt) |
fanout_status | 查看本会话所有副进程状态 |
fanout_interrupt | 中断一个或全部副进程 |
fanout_collect | 收集已完成副进程的最终汇报 |
🏗️ 架构说明
┌─ 主会话(主进程 Agent)──────────────────────────────┐
│ /fanout 命令 · fanout_* 工具 · 对话流面板 (Client) │
└──────────────┬───────────────────────────────────────┘
│ harness.registerTool / commands / RPC
┌──────────────▼───────────────────────────────────────┐
│ Host 插件(apply) │
│ · registry: parentId → Map<childId, {label,role, │
│ startedAt, state, stopReason, lastOutput}> │
│ · dispatch: subagents.startContinuable() 并行启动 │
│ · talk: subagents.followup()(冷唤醒可续会话) │
│ · interrupt:subagents.interrupt(ancestor 授权) │
│ · subagent/end 事件 → 状态/输出写回注册表 │
│ · RPC: fanout:list / fanout:talk / fanout:interrupt │
└──────────────┬───────────────────────────────────────┘
│ startContinuable / followup / interrupt
┌──────────────▼───────────────────────────────────────┐
│ 副进程 × N(continuable subagent,独立会话并行执行) │
│ 自动继承默认模型/工作目录,按统一格式汇报 │
└──────────────────────────────────────────────────────┘
关键实现点:
- 并行派出:
Promise.allSettled同时调用subagents.startContinuable({provider, label, request: {prompt, parent, agentOptions?}, signal});provider 自动选取第一个支持prepareContinuable的(spawn/fork) - 副进程 prompt 模板:编号身份 + 总任务 + 分工 + 独立执行要求 + 统一汇报格式(状态/成果摘要/产出)+ 等待后续指令
- 状态恢复:插件更新/重启后内存注册表清空,
fanout_status通过listChildren持久化枚举补全;fanout_talk将历史进程登记回注册表,使subagent/end事件能恢复其结束状态与输出 - 面板:挂载于
conversation.chat.turnTail(chain,注册序在宿主「产出的文件」提示之后,不抢占);每 3 秒经 RPC 轮询状态
⚠️ 已知限制
- 通话权限绑定发起会话:只有派出副进程的会话(主进程)能通话/修改;新开会话不能接管
- 插件更新/重启后,历史副进程状态短暂显示「未知」,再次通话后自动恢复
- 副进程消耗 API 额度;被中断的工作不会自动重排
- 副进程数量上限 8(
clamp(workers, 1, 8))
📋 版本历史
| 版本 | 说明 |
|---|---|
| v1 | 初始实现:5 工具 + /fanout 命令 + 输入区上方面板 |
| v2 | 修正 output schema 为 value schema DSL 风格(属性级 required) |
| v3 | 修复 fanout_status render 函数签名 |
| v4 | UI 改为对话流内细长圆角长条(turnTail),移除输入区面板 |
| v5 | resolveWorker 增加持久化枚举回退,重启后仍可通话历史进程 |
| v6 | 通话/枚举时登记注册表,subagent/end 可恢复历史进程状态 |
| v7 | 行内改「进程 N」序号(按派出时间排序),完整 ID 移至详情,默认字体 |
| v8 | 面板默认自动展开 |
| v9 | 仅当有「运行中」的副进程时显示面板,全部结束后自动隐藏 |
📄 许可
MIT
仓库信息
- 开发语言
- JavaScript
- 许可证
- 未提供
- 最后更新
- 2026年8月17日 09:28
谨慎安装
请检查源代码、权限、生命周期脚本、依赖与网络访问;不受信任的插件应先在隔离环境中测试。