14 KiB
Dashboard Nanobot 远端节点管理设计(方案 A)
本文档定义 Dashboard Nanobot 的多节点远端管理方案,目标是在尽量少侵入 nanobot 核心源码的前提下,让当前面板可以统一管理部署在其它电脑上的 nanobot 实例,并保持与本机 Bot 相近的操作体验。
1. 目标与边界
1.1 目标
- 中心面板统一管理多台机器上的 nanobot 实例。
- 远端 Bot 支持:
- 查看运行状态
- 启动、停止、重启
- 下发控制命令,如
/new、/stop、/restart - 查看实时日志和结构化运行事件
- 读取和编辑工作区文件
- 创建新 Bot、升级已有 Bot 核心
- 远端机器既支持 Docker 部署,也支持宿主机直接安装运行。
- 尽量不修改 nanobot 核心,只复用自定义
dashboard.pychannel。
1.2 非目标
- 不让中心面板直接通过 SSH 管理远端机器。
- 不让中心面板直接操作远端 Docker Remote API。
- 不在 nanobot 核心中引入“多节点”或“集群”概念。
- 不要求用户手工编辑远端
config.json。
1.3 设计原则
- 控制平面与执行平面分离。
- 远端机器自治,中心只负责编排与聚合。
- nanobot 核心零或极低侵入。
- Docker 与宿主机直装都作为一等运行模式支持。
- 面向逐步上线,优先跑通命令与状态链路,再补管理能力。
2. 总体方案
采用“中心控制面 + 远端节点代理”的双层结构。
- 中心控制面:
- 当前 dashboard 的 frontend + backend
- 负责统一 UI、数据库、权限、审计、聚合视图
- 远端节点代理:
- 每台远端机器部署一个轻量
dashboard-edge - 负责本机 Bot 生命周期、工作区、日志流、命令投递
- 每台远端机器部署一个轻量
- nanobot 实例:
- 继续使用自定义
dashboard.py - 对外只暴露本地 Dashboard Channel
- 继续使用自定义
2.1 架构图
flowchart LR
UI["Dashboard Frontend"] --> CP["Central Backend"]
CP <--> DB["Central DB"]
CP <--> EDGE1["Node Agent A"]
CP <--> EDGE2["Node Agent B"]
EDGE1 <--> BOT1["Nanobot (Host Process)"]
EDGE1 <--> BOT2["Nanobot (Docker)"]
EDGE2 <--> BOT3["Nanobot (Host Process)"]
2.2 关键结论
- 不扩展 nanobot 去理解“远端管理”。
- 不要求面板直接连接远端 Bot 的文件系统或 Docker。
- 所有远端执行动作都先到节点代理,再由节点代理在本机执行。
3. 为什么选择方案 A
相对于“中心直接 SSH 管理远端机器”或“每台机器都跑一套完整 dashboard 后端”,方案 A 更适合当前项目:
- 与现有架构兼容性最高。
- 可以同时覆盖 Docker 和宿主机直装。
- 中心端仍保留统一数据库与统一 UI,不会产生多套后台状态漂移。
- 节点代理可以封装平台差异,如 macOS、Linux、Windows 的进程管理差异。
- 自定义
dashboard.py可以直接复用,不需要重新定义 bot 内部协议。
4. 与现有代码的关系
当前代码默认“控制端和执行端在同一台机器”:
backend/core/docker_manager.py- 直接调用本机 Docker
backend/core/config_manager.py- 直接写本机 workspace 和
.nanobot/config.json
- 直接写本机 workspace 和
backend/main.pystart/stop/command/workspace/monitor全部默认操作本机资源
因此,多节点能力不应直接在这些逻辑上继续叠加条件分支,而应先抽象出执行层接口,再分别实现本地与远端两类 Provider。
5. 运行模式设计
每个 Bot 必须明确声明运行模式:
dockerhost
节点代理内部为两种模式提供统一执行接口。
5.1 Docker 模式
- Bot 运行在本机 Docker 容器中。
- 节点代理负责:
- 启停容器
- 监控容器日志
- 发送命令到容器内 dashboard channel
- 管理挂载的
.nanobot/workspace
5.2 Host 模式
- Bot 直接运行在宿主机进程中。
- 节点代理负责:
- 启停本机进程或系统服务
- 捕获 stdout/stderr
- 发送命令到本机 dashboard channel
- 管理本机工作区
5.3 Host 模式的关键约束
宿主机直装时,多个 Bot 不能共用固定端口,因此 Dashboard Channel 端口必须由节点代理自动分配并持久化。
推荐策略:
- Docker 模式:
- 容器内可继续使用
0.0.0.0:9000
- 容器内可继续使用
- Host 模式:
- 使用
127.0.0.1:{auto_assigned_port} - 例如
19101、19102、19103
- 使用
原因:
- 直装场景下避免端口冲突
- 避免把 Bot 的本地控制端口暴露给局域网
- 只允许节点代理本机访问
6. nanobot 侧侵入边界
6.1 保持不变
nanobot 核心本身不需要感知节点、中心控制面或跨机调度。
6.2 仅要求保留的自定义能力
- 自定义
dashboard.pychannel 可用 start()和stop()使用基类状态字段self._running- 支持
config.json中启用channels.dashboard dashboard.py支持:POST /chat入站命令- 结构化 stdout 出站消息
6.3 dashboard.py 的定位
它仍然只是“本机 Bot 控制通道”,不是中心与远端节点之间的通信协议。
分工如下:
- 中心与节点代理通信:Node Agent API / WebSocket
- 节点代理与 Bot 通信:本机
dashboard.py
7. 中心端改造方案
中心端不直接继续依赖本机 Docker 和本机文件系统,而是抽象出执行接口。
7.1 建议新增 Provider 抽象
RuntimeProviderstart_botstop_botrestart_botsend_commandget_statusget_recent_logsstream_monitor
WorkspaceProviderlist_treeread_filewrite_markdownupload_filesdownload_file
BotProvisionProvidercreate_botupgrade_botdelete_botsync_config
7.2 Provider 实现建议
LocalRuntimeProvider- 复用当前
docker_manager.py
- 复用当前
LocalWorkspaceProvider- 复用当前本地 workspace 读写逻辑
RemoteRuntimeProvider- 通过节点代理 API / WebSocket 调用远端动作
RemoteWorkspaceProvider- 通过节点代理文件接口访问远端 workspace
7.3 中心端路由层原则
前端 API 尽量保持稳定,例如:
/api/bots/{bot_id}/start/api/bots/{bot_id}/stop/api/bots/{bot_id}/command/api/bots/{bot_id}/workspace/tree
但这些接口在后端内部根据 bot.node_id 和 bot.runtime_kind 路由到不同 Provider。
这样可以减少前端改动,并保持本机 Bot 与远端 Bot 的统一交互模型。
8. 节点代理设计
8.1 职责
远端节点代理 dashboard-edge 负责:
- 本机 Bot 注册和枚举
- Bot 创建、升级、删除
- Bot 启停与重启
- 命令下发
- 日志采集与结构化事件解析
- 工作区文件读写
- Dashboard Channel 配置自动注入
- 向中心汇报节点状态和 Bot 状态
8.2 统一执行接口
节点代理内部也需要抽象执行器:
DockerExecutorHostProcessExecutor
两者都实现:
start_botstop_botrestart_botsend_commandread_logsread_workspace_filewrite_workspace_fileget_resource_snapshot
8.3 HostProcessExecutor 推荐实现
首版建议使用“节点代理托管子进程”的方式,而不是一开始就深度接入系统服务管理器。
优点:
- 首版开发快
- 可直接拿到 stdout/stderr
- 更容易复用现有 dashboard channel 日志解析逻辑
后续可演进为:
- Linux:
systemd - macOS:
launchd - Windows: Service
9. 节点与中心的通信模型
建议采用“节点主动连中心”的反向长连接优先模型,同时兼容同网环境下的 HTTPS 直连。
9.1 推荐默认模式
- 节点启动后主动向中心注册
- 建立长期 WebSocket
- 中心通过该连接发送控制命令
- 节点通过该连接回传:
- 心跳
- Bot 状态
- 结构化事件
- 日志摘要
9.2 为什么优先反向长连接
- 适配 NAT 与家庭宽带场景
- 远端节点无需开放入站端口
- 更适合公网分散机器接入
9.3 可选直连模式
当节点与中心在同一内网或 VPN 内时,可允许中心通过 HTTPS 直接调用节点代理 API。
10. Bot 元数据模型调整
当前 bot_instance 只适合单机场景,需要扩展节点信息。
10.1 新增 node_instance
建议新增 node_instance 表:
idnamestatusagent_versionlast_seen_atconnection_modeauth_token_hashhost_nameos_typecapabilities_jsoncreated_atupdated_at
10.2 扩展 bot_instance
建议为 bot_instance 增加:
node_idruntime_kindremote_bot_iddashboard_hostdashboard_portruntime_meta_json
说明:
node_id标识该 Bot 归属哪个节点runtime_kind表示docker或hostdashboard_port用于 Host 模式的本地控制端口映射remote_bot_id允许未来节点端使用独立内部 ID
10.3 Bot ID 策略
建议中心平台继续保持 bot_instance.id 全局唯一。
如果远端已有同名 Bot,可:
- 中心分配平台级 ID
- 节点侧保留原始
remote_bot_id
这样可避免跨节点命名冲突。
11. Dashboard Channel 配置策略
11.1 配置自动注入
所有由中心或节点代理创建、升级、同步的 Bot,都由节点代理自动保证 channels.dashboard 存在。
用户不需要手工编辑 config.json。
11.2 生成策略
Docker 模式建议写入:
{
"enabled": true,
"host": "0.0.0.0",
"port": 9000,
"allowFrom": ["*"]
}
Host 模式建议写入:
{
"enabled": true,
"host": "127.0.0.1",
"port": 19101,
"allowFrom": ["127.0.0.1", "::1"]
}
其中 port 由节点代理自动分配,不能写死。
11.3 面板行为约束
中心面板与节点代理都应把 dashboard 视为内建保留渠道:
- 自动存在
- 不允许删除
- 不允许普通用户手改关键监听参数
12. 关键数据流
12.1 命令下发流
sequenceDiagram
participant UI as Frontend
participant CP as Central Backend
participant EDGE as Node Agent
participant BOT as Nanobot Dashboard Channel
UI->>CP: POST /api/bots/{id}/command
CP->>EDGE: send_command(bot_id, command)
EDGE->>BOT: POST /chat
BOT-->>EDGE: 200 OK
EDGE-->>CP: accepted
CP-->>UI: success
12.2 运行事件回传流
sequenceDiagram
participant BOT as Nanobot
participant EDGE as Node Agent
participant CP as Central Backend
participant UI as Frontend
BOT->>EDGE: stdout structured packet
EDGE->>EDGE: parse packet
EDGE->>CP: runtime event push
CP->>CP: persist message/state/event
CP->>UI: websocket broadcast
12.3 工作区文件流
sequenceDiagram
participant UI as Frontend
participant CP as Central Backend
participant EDGE as Node Agent
UI->>CP: GET /api/bots/{id}/workspace/file
CP->>EDGE: read_workspace_file(bot_id, path)
EDGE-->>CP: file content
CP-->>UI: markdown/text payload
13. 节点代理 API 草案
首版建议具备如下能力。
13.1 节点管理
POST /agent/handshakePOST /agent/heartbeatGET /agent/capabilities
13.2 Bot 管理
GET /agent/botsPOST /agent/botsPOST /agent/bots/{bot_id}/upgradeDELETE /agent/bots/{bot_id}POST /agent/bots/{bot_id}/startPOST /agent/bots/{bot_id}/stopPOST /agent/bots/{bot_id}/restartPOST /agent/bots/{bot_id}/command
13.3 工作区与文件
GET /agent/bots/{bot_id}/workspace/treeGET /agent/bots/{bot_id}/workspace/filePUT /agent/bots/{bot_id}/workspace/filePOST /agent/bots/{bot_id}/workspace/uploadGET /agent/bots/{bot_id}/logs
13.4 推送通道
WS /agent/ws
推送内容包括:
- 节点上线/离线
- 心跳
- Bot 状态
- 结构化运行消息
- 运维事件
14. 安全模型
14.1 基础要求
- 节点与中心之间必须使用 HTTPS 或 WSS。
- 节点首次接入使用一次性注册码。
- 注册完成后发放长期令牌。
- 中心只保存令牌摘要,不保存明文。
14.2 权限边界
- 中心不能直接访问远端文件系统,只能经节点代理。
- 节点代理只能操作本机所属 Bot 工作区。
- 所有文件接口必须保留路径越界校验。
14.3 命令幂等
每次命令下发都应带 request_id,节点代理应避免因网络重试导致重复执行。
14.4 审计
中心端应记录:
- 谁对哪个 Bot 下发了什么命令
- 命令发往哪个节点
- 节点是否接受和执行
- 最终结果和错误原因
15. 分阶段实施计划
15.1 第一阶段:跑通远端控制链路
目标:
- 节点注册
- 节点在线状态
- 远端 Bot 列表
start/stop/restart/new、/stop、/restart下发- 实时日志与状态回传
特点:
- 优先打通“像本机一样可通讯、可下发指令”
- 暂不强求全部文件管理能力
15.2 第二阶段:补齐远端 Bot 生命周期管理
目标:
- 新建远端 Bot
- 升级旧 Bot 到新核心
- 自动补
dashboard配置 - 支持 Docker 与 Host 两类运行模式
15.3 第三阶段:补齐工作区能力
目标:
- 文件树浏览
- Markdown 在线编辑与保存
- 文件上传下载
- 技能包管理
15.4 第四阶段:稳定性与权限强化
目标:
- 节点断线恢复
- 节点版本兼容检查
- 审计日志完善
- 权限分级
- 节点灰度升级
16. 风险与注意事项
16.1 最大技术风险
- Host 模式的端口分配与持久化管理
- 节点代理重启后的进程状态恢复
- 不同操作系统上的进程守护差异
- 网络抖动下的命令幂等与状态一致性
16.2 兼容性风险
- 不同版本 nanobot 核心对 channel 生命周期字段要求可能不同
dashboard.py需要继续保持与 post5 的self._running兼容- 老版本 Bot 升级时必须自动补全
channels.dashboard
16.3 明确不建议的路径
- 不建议中心直接 SSH 管理远端机器
- 不建议暴露 Docker Remote API 给中心
- 不建议让每台远端机器都维护一套完整 dashboard 主后台数据库
17. 最终建议
项目应以“中心控制面 + 远端节点代理”为长期结构,宿主机直装作为一等公民,Docker 作为兼容执行后端。
实现上优先做三件事:
- 中心端抽象 Provider 层,解除对本机 Docker 和本机文件系统的硬绑定。
- 设计并落地
dashboard-edge,统一承接远端执行、日志、文件和命令。 - 在节点代理侧自动注入
dashboardchannel 配置,避免用户手工维护远端config.json。
这样可以在几乎不改 nanobot 核心设计的前提下,将当前面板平滑演进为多节点 Bot 控制平台。