dashboard-nanobot/design/remote-node-management.md

14 KiB
Raw Blame History

Dashboard Nanobot 远端节点管理设计(方案 A

本文档定义 Dashboard Nanobot 的多节点远端管理方案,目标是在尽量少侵入 nanobot 核心源码的前提下,让当前面板可以统一管理部署在其它电脑上的 nanobot 实例,并保持与本机 Bot 相近的操作体验。

1. 目标与边界

1.1 目标

  • 中心面板统一管理多台机器上的 nanobot 实例。
  • 远端 Bot 支持:
    • 查看运行状态
    • 启动、停止、重启
    • 下发控制命令,如 /new/stop/restart
    • 查看实时日志和结构化运行事件
    • 读取和编辑工作区文件
    • 创建新 Bot、升级已有 Bot 核心
  • 远端机器既支持 Docker 部署,也支持宿主机直接安装运行。
  • 尽量不修改 nanobot 核心,只复用自定义 dashboard.py channel。

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
  • backend/main.py
    • start/stop/command/workspace/monitor 全部默认操作本机资源

因此,多节点能力不应直接在这些逻辑上继续叠加条件分支,而应先抽象出执行层接口,再分别实现本地与远端两类 Provider。

5. 运行模式设计

每个 Bot 必须明确声明运行模式:

  • docker
  • host

节点代理内部为两种模式提供统一执行接口。

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}
    • 例如 191011910219103

原因:

  • 直装场景下避免端口冲突
  • 避免把 Bot 的本地控制端口暴露给局域网
  • 只允许节点代理本机访问

6. nanobot 侧侵入边界

6.1 保持不变

nanobot 核心本身不需要感知节点、中心控制面或跨机调度。

6.2 仅要求保留的自定义能力

  • 自定义 dashboard.py channel 可用
  • 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 抽象

  • RuntimeProvider
    • start_bot
    • stop_bot
    • restart_bot
    • send_command
    • get_status
    • get_recent_logs
    • stream_monitor
  • WorkspaceProvider
    • list_tree
    • read_file
    • write_markdown
    • upload_files
    • download_file
  • BotProvisionProvider
    • create_bot
    • upgrade_bot
    • delete_bot
    • sync_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_idbot.runtime_kind 路由到不同 Provider。

这样可以减少前端改动,并保持本机 Bot 与远端 Bot 的统一交互模型。

8. 节点代理设计

8.1 职责

远端节点代理 dashboard-edge 负责:

  • 本机 Bot 注册和枚举
  • Bot 创建、升级、删除
  • Bot 启停与重启
  • 命令下发
  • 日志采集与结构化事件解析
  • 工作区文件读写
  • Dashboard Channel 配置自动注入
  • 向中心汇报节点状态和 Bot 状态

8.2 统一执行接口

节点代理内部也需要抽象执行器:

  • DockerExecutor
  • HostProcessExecutor

两者都实现:

  • start_bot
  • stop_bot
  • restart_bot
  • send_command
  • read_logs
  • read_workspace_file
  • write_workspace_file
  • get_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 表:

  • id
  • name
  • status
  • agent_version
  • last_seen_at
  • connection_mode
  • auth_token_hash
  • host_name
  • os_type
  • capabilities_json
  • created_at
  • updated_at

10.2 扩展 bot_instance

建议为 bot_instance 增加:

  • node_id
  • runtime_kind
  • remote_bot_id
  • dashboard_host
  • dashboard_port
  • runtime_meta_json

说明:

  • node_id 标识该 Bot 归属哪个节点
  • runtime_kind 表示 dockerhost
  • dashboard_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/handshake
  • POST /agent/heartbeat
  • GET /agent/capabilities

13.2 Bot 管理

  • GET /agent/bots
  • POST /agent/bots
  • POST /agent/bots/{bot_id}/upgrade
  • DELETE /agent/bots/{bot_id}
  • POST /agent/bots/{bot_id}/start
  • POST /agent/bots/{bot_id}/stop
  • POST /agent/bots/{bot_id}/restart
  • POST /agent/bots/{bot_id}/command

13.3 工作区与文件

  • GET /agent/bots/{bot_id}/workspace/tree
  • GET /agent/bots/{bot_id}/workspace/file
  • PUT /agent/bots/{bot_id}/workspace/file
  • POST /agent/bots/{bot_id}/workspace/upload
  • GET /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 作为兼容执行后端。

实现上优先做三件事:

  1. 中心端抽象 Provider 层,解除对本机 Docker 和本机文件系统的硬绑定。
  2. 设计并落地 dashboard-edge,统一承接远端执行、日志、文件和命令。
  3. 在节点代理侧自动注入 dashboard channel 配置,避免用户手工维护远端 config.json

这样可以在几乎不改 nanobot 核心设计的前提下,将当前面板平滑演进为多节点 Bot 控制平台。