# 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 架构图 ```mermaid 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}` - 例如 `19101`、`19102`、`19103` 原因: - 直装场景下避免端口冲突 - 避免把 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_id` 和 `bot.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` 表示 `docker` 或 `host` - `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 模式建议写入: ```json { "enabled": true, "host": "0.0.0.0", "port": 9000, "allowFrom": ["*"] } ``` Host 模式建议写入: ```json { "enabled": true, "host": "127.0.0.1", "port": 19101, "allowFrom": ["127.0.0.1", "::1"] } ``` 其中 `port` 由节点代理自动分配,不能写死。 ### 11.3 面板行为约束 中心面板与节点代理都应把 `dashboard` 视为内建保留渠道: - 自动存在 - 不允许删除 - 不允许普通用户手改关键监听参数 ## 12. 关键数据流 ### 12.1 命令下发流 ```mermaid 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 运行事件回传流 ```mermaid 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 工作区文件流 ```mermaid 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 控制平台。