114 lines
11 KiB
Markdown
114 lines
11 KiB
Markdown
# vps-switch 计划
|
||
|
||
> 2026-10-10 起,2026-10-13 按「先做好五大核心功能板块、最后将现成链路工具化为 MCP」重定主线。
|
||
> vps-switch 是 1Shell(Node + Electron,冻结在 4.7.7)的全面重构与升级;旧项目在本项目可用之前照常运行,且随时作为实测对照。
|
||
> 本文是"一页边界":不在这里的东西不进仓库。要加,先改边界那句话。
|
||
|
||
---
|
||
|
||
## 边界
|
||
|
||
**一个轻量级 VPS 管理工具:先把 VPS 仓库、终端、文件浏览器、文件上传下载、探针五大核心板块做到极致,最后将这些现成链路加上护栏工具化为 MCP Server。交付两个产物:GPUI 原生的桌面客户端(Windows / macOS / Linux,`vps-switch-gpui`)与无头的守护进程(`vps-switch`,Linux/Windows),两者共用同一后端与同一套 HTTP/WS API。**
|
||
|
||
设计准则:
|
||
|
||
- 沿用 `AGENTS.md`:不堆提示词(本项目零模型调用)、不堆架构(一份底层实现,UI 与 MCP 共同复用)、不对 agent 隐藏上下文。
|
||
- **概念数必须比 1Shell 少。** 不设内置 AI 聊天、不设协议 agent 入驻、不设技能/脚本库。
|
||
- **先做好人用的本体,再做工具化。** MCP 不是另起炉灶的第二套系统,而是对前五个板块已验证底层链路的薄封装。
|
||
|
||
---
|
||
|
||
## 为什么要按这个路径重构
|
||
|
||
直接调用并复盘正在运行的 1Shell(1 台 `local` + 29 台 VPS,共 30 个目标),它的核心问题很清楚:
|
||
|
||
| 1Shell 的痛点 | 根源 | vps-switch 的解法 |
|
||
|---|---|---|
|
||
| **定位散乱、体积臃肿(80k 行)** | 第一次做项目时误打误撞,把内置 AI 对话、Claude/Codex 驻留面板、技能库、脚本库、工作负载全塞了进来 | 砍掉所有内置 AI 与多余概念,回归纯粹的轻量级 VPS 管理工具 + 外部 MCP 接口 |
|
||
| **主机仓库信息滞后** | `osName` 等信息首次探测后成了死缓存(如某台机器重装为 Ubuntu 后列表仍显示 Alpine 3.23) | SSH 连接建立时轻量静默刷新真实 OS/内核/架构信息,保持仓库数据鲜活 |
|
||
| **终端总有小 bug** | Node 仅做字节透传,服务端无终端状态机;切页丢屏、UTF-8 多字节截断乱码、resize 错位、不知命令何时结束 | 参考 Pebrel 技术栈:Rust 侧 `alacritty_terminal::Term` 持有权威网格状态 + 字节环重连恢复 + 随包 Windows ConPTY + OSC 133/7 真实命令边界与 exit code + WebSocket 纯二进制帧 |
|
||
| **文件上传下载困难(尤其 Agent 调用时)** | 传文件被拆成 `start/append/finish_file_upload` 等 9 个工具,逼大模型在上下文里手搓 base64 分块,慢且极易断 | 做独立的 Rust 流式传输引擎(接收 `本机路径 ↔ 远端路径`),内部自动流式分片、断点续传、SHA256 校验;UI 队列与 MCP 共用同一条链路 |
|
||
| **探针过重、后台刷屏** | 塞了 Agentless / Go Agent / Relay 级联三种模式与复杂告警,40,826 次 SSH 轮询占了 76% 活动,告警刷出 1.1 万条 | 重做轻量探针:复用 SSH 连接或按需/低频采样(CPU、内存、磁盘、实时网速/流量、基础负载),打开面板时实时刷新,后台静默不折腾 |
|
||
|
||
---
|
||
|
||
## 六大板块与推进路线
|
||
|
||
采用**一个板块一个板块做透**的节奏:每个板块先结合 1Shell 实际体验细化讨论,打磨好前端形态与 Rust 底层链路,验收通过后再进入下一板块。
|
||
|
||
### 板块一:VPS 仓库(底座与前端形态定型)
|
||
|
||
先把轻量级工具的**前端整体骨架与视觉形态**打磨定型,同时把底层主机管理与 SSH 连接池做扎实:
|
||
|
||
- **主机模型(Host)**:支持本机(`local`)与远端 SSH 主机;字段涵盖地址、端口、用户名、认证方式(密码 / 私钥加密存储)、跳板机与本机代理出口(`jump_host_id` 支持指定另一台 SSH 跳板机或本机代理端口 `local-proxy`)、分组/标签、置顶、排序、备注链接,以及连接时自动刷新的 `os` 信息(系统家族、发行版、内核、架构)。
|
||
- **1Shell 一键导入**:直接读取并解密本机现有 1Shell 数据库里的 29 台 VPS,一键迁入,开发第一天起就能用真实机队测试。
|
||
- **SSH 连接底座(`russh`)**:单主机连接池与多 channel 复用(终端、执行、SFTP、探针共用连接,支持 SSH 跳板机透明穿透与本机代理端口 SOCKS5/HTTP CONNECT 出口路由),并在真机队(OpenSSH 8.4 ~ 10.2、Alpine、Windows OpenSSH 9.5)上验通。
|
||
- **前端打磨**:确定整个软件的导航布局、配色主题、主机列表/卡片视图、搜索与标签过滤、快速新建/编辑与连接测试交互。
|
||
|
||
### 板块二:终端(参考 Pebrel 技术栈)
|
||
|
||
**Rust 侧持有终端状态,前端只负责高速渲染。** 借鉴 Pebrel(Apache-2.0 的 `alacritty_terminal` 引擎,不抄 GPL 代码)的成熟终端工程实践:
|
||
|
||
- **双解析器与状态保活**:每个终端 pane 在 Rust 守护进程中对应一个 `alacritty_terminal::Term`(持有网格与 scrollback)+ 有界字节环(默认 2 MiB);同一份二进制字节流经 WebSocket 喂给前端 `xterm.js`(WebGL addon)。切页面、关窗口、闪断重连瞬间恢复现场。
|
||
- **PTY 链路**:本机使用 `portable-pty` 并**随包携带 Windows Terminal 的 `conpty.dll` + `OpenConsole.exe`**(告别系统老旧 ConPTY bug);远端复用板块一的 `russh` 连接打开 PTY channel。
|
||
- **Shell Integration(OSC 133 / OSC 7)**:连接时静默注入 bash / zsh / fish / PowerShell 钩子,在 Rust 解析回调中精确截获每条命令的开始、结束、真实 `exit_code` 与当前工作目录 `cwd`。
|
||
- **输入正确性**:支持 bracketed paste、按当前终端模式编码控制键与回车,杜绝粘贴多行直接误执行和乱码。
|
||
- **多 Tab 与分屏树**:支持同一主机或跨主机多 Tab、任意方向分屏与拖拽调整占比,布局持久化。
|
||
|
||
### 板块三:文件浏览器
|
||
|
||
本机文件系统与远端 `russh-sftp` 复用同一套抽象接口:
|
||
|
||
- **目录浏览与操作**:目录树/列表双视图、面包屑与路径直达、隐藏文件切换、权限/大小/修改时间展示、新建文件/文件夹、重命名、删除、修改权限。
|
||
- **在线编辑**:集成 CodeMirror 6,支持语法高亮、搜索替换、保存直写远端(带可选备份),顺手改配置文件不必下载再上传。
|
||
- **与终端联动**:支持跟随当前终端 `cwd`(由 OSC 7 提供)或在当前目录一键打开终端。
|
||
|
||
### 板块四:文件上传下载
|
||
|
||
把文件传输从普通读写里独立出来,做成一个真正的**高速流式传输引擎**:
|
||
|
||
- **核心链路**:直接基于 `本机文件路径 ↔ 远端文件路径` 流式读写,不经过内存全量缓冲、不走 base64 编码。
|
||
- **大文件与弱网保障**:内部自动按大小分块流式传输、支持断点续传、传输完成后校验大小与 SHA256、写临时文件再原子 rename(防止传一半搞坏线上文件)。
|
||
- **传输队列 UI**:支持拖拽上传、批量上传下载、实时显示传输速率、进度百分比、剩余时间,支持暂停/继续/取消。
|
||
- **为工具化铺路**:这套 Rust 传输函数做好后,板块六的 MCP 工具只需传 `{host, local_path, remote_path}` 即可直接调用,彻底消灭 1Shell 里让大模型手搓 9 个分片工具的顽疾。
|
||
|
||
### 板块五:探针
|
||
|
||
砍掉 1Shell 里繁琐的级联与告警轰炸,做一个**轻量、干净、好看的 VPS 状态看板**:
|
||
|
||
- **核心指标**:在线状态与连接延迟、系统运行时长(Uptime)、CPU 使用率与负载(Load)、内存与 Swap、磁盘占用、实时上下行网速与累计流量、关键端口/进程概览。
|
||
- **轻量采集机制**:优先复用已建立的 SSH 连接或采用极低开销的单次合并脚本采样;**按需高频、后台低频/静默**(人打开探针页或选中主机时实时刷新,平时不疯狂建连刷日志)。
|
||
- **兼容 Linux 与 Windows**:Linux(Debian/Ubuntu/Alpine)读取 `/proc` 与系统指标,Windows 走轻量性能计数采集。
|
||
|
||
### 板块六:工具化(MCP Server + 安全护栏)
|
||
|
||
前五个板块全部打磨成熟后,**零重复建设**,直接把已有的底层链路封装为 MCP Server 暴露给外部 Agent(如 Claude Code):
|
||
|
||
- **链路直接复用**:
|
||
- 查主机 / 看状态 → 复用 **板块一(VPS 仓库)** + **板块五(探针)**
|
||
- 执行命令(同步等待或转后台任务,含 Windows PowerShell 编码与 CLIXML 处理)→ 复用 **板块一/二(SSH & 本机执行链路)**
|
||
- 列目录 / 读写改删文件 → 复用 **板块三(文件浏览器内核)**
|
||
- 上传 / 下载大文件 → 复用 **板块四(文件上传下载引擎)**,一次调用完成传输
|
||
- **命令黑名单护栏**:
|
||
- 一份全局名单(`data/deny-list.txt`,一行一条、`*` 通配、按词边界,首启写出内置的不可逆灾难,之后用户自己增删),只覆盖 `vps_exec` 与 `vps_terminal` 的命令通道;文件写/传输类不判定。
|
||
- 命中即拒绝执行并说明命中了哪条;没有白名单、确认流程、风险分级与安全挡位。
|
||
- 存在的理由只有一个:MCP 工具一旦被外部 agent 放行,参数里的命令就不再受它自身权限系统检查,这里是唯一的兜底。
|
||
- 边界:防手滑,不防蓄意绕过(`r\m -rf /`、`$(echo rm) -rf /` 这类形态纯模式匹配必然漏)。
|
||
- **双传输支持**:`--mcp-stdio`(供本机 Claude Code 零配置直连)+ Streamable HTTP(带范围令牌)。
|
||
|
||
---
|
||
|
||
## 技术栈
|
||
|
||
| 层 | 选型 | 备注 |
|
||
|---|---|---|
|
||
| 后端语言与运行时 | Rust + `tokio` | 单一常驻进程,轻量低内存 |
|
||
| SSH / SFTP | `russh` 0.63 + `russh-sftp` | 纯 Rust,连接池 + 多 channel 复用 + 跳板机穿透 |
|
||
| 终端引擎 | `alacritty_terminal`(Apache-2.0) | 借鉴 Pebrel:Rust 侧持有网格与 scrollback,解析回调截获 OSC 133/7 |
|
||
| 本机 PTY | `portable-pty` + 随包 Windows Terminal `conpty.dll` / `OpenConsole.exe` | 解决 Windows 原生 ConPTY 兼容性与渲染 bug |
|
||
| Web 服务与实时通信 | `axum` | REST API + 终端二进制 WebSocket + 状态/探针/传输进度 SSE |
|
||
| 本地存储 | `rusqlite`(bundled) | 单文件 SQLite + 凭据加密存储 |
|
||
| MCP 协议 | `rmcp`(≥ 1.4.0) | 板块六接入,支持 stdio 与 Streamable HTTP |
|
||
| 桌面壳 | GPUI(`gpui-kit` 0.7.3,内部锁 `gpui-pre` 0.3.9) | GPUI 原生桌面客户端(Windows / macOS / Linux);Linux 无头服务不带壳。详见 `docs/gpui-client.md` |
|
||
| 前端 | Vue 3 + TypeScript + Tailwind CSS + xterm.js(WebGL)+ CodeMirror 6 | 轻量、响应迅速、围绕五大板块打造精致 UI |
|