工作原理
本页跟随定义 VibeAround 的两段旅程:一条 IM 消息抵达编程 Agent,和一个 Agent CLI 在你的终端里被启动。术语不熟悉的话,先看核心概念。
本页跟随定义 VibeAround 的两段旅程:一条 IM 消息抵达编程 Agent,和一个 Agent CLI 在你的终端里被启动。术语不熟悉的话,先看核心概念。
运行时一览
web SPA ───────────────┐ TUI / CLI (va) desktop-ui (React)
│HTTP │WS ×3 │ │ HTTP + WS │ Tauri IPC
│/api/* │/ws (pty) │ │ (va-client) ▼
│ │/ws/chat │ │ desktop (Tauri shell)
│ │/ws/* state │ │ │ 进程内嵌入
▼ ▼ ▼ ▼ ▼
┌───────────────────────────────────────────────────────────────┐
│ vibearound-server (axum daemon) │
│ REST /api/* · WS (pty, chat, live state) · MCP /mcp │
│ api_bridge /va/local-api · preview 反向代理 · 配对 │
├───────────────────────────────────────────────────────────────┤
│ core 运行时 │
│ channels · workspace threads · process supervisor · │
│ profiles · pty · previews · tunnels · auth · search │
└──┬──────────────┬──────────────┬───────────────┬──────────────┘
│ stdio │ stdio │ pseudo-tty │ 子进程 / SDK
│ JSON-RPC │ JSON-RPC ▼ ▼
│ (ACP) │ (ACP) shell / agent 隧道进程
▼ ▼ CLI 会话 (cloudflared, npx
渠道插件进程 agent CLI (web terminal) localtunnel; ngrok
(telegram, …) 进程 走进程内 SDK)
│
│ HTTP 回环(Bridge 化的 Profile)
▼
/va/local-api bridge ──HTTPS──► 上游模型 API一切都是一个进程加受监督的子进程。桌面应用内嵌的就是独立 va serve 跑的那个守护进程;每个 UI 都是它的客户端。
通信路径
图中每一条边,及其传输方式和负载形状:
| 边 | 传输 | 协议 / 负载 |
|---|---|---|
| web SPA → server(REST) | HTTP /api/* | JSON,bearer token |
| web SPA ↔ server(终端) | WebSocket /ws?session_id= | 原始终端字节 + JSON resize 消息 |
| web SPA ↔ server(聊天) | WebSocket /ws/chat | JSON 聊天事件:类型化输入、流式输出、权限卡片 |
| web SPA ↔ server(实时状态) | WebSocket /ws/channels、/ws/tunnels、/ws/sessions、/ws/agents/runtime | 每次变化重发全量快照("最后一条消息就是状态") |
TUI / va CLI → server | HTTP + /ws/chat | 同一套契约,经 va-client 协议 crate |
| desktop-ui → 桌面外壳 | Tauri IPC | 原生命令(窗口、启动、配置页面) |
| 桌面外壳 → 守护进程 | 进程内 | 直接嵌入 ServerDaemon |
| 守护进程 ↔ 渠道插件 | 子进程 stdio | 换行分隔的 JSON-RPC(ACP 帧):信封进;输出、权限卡片、_va/heartbeat 出 |
| 守护进程 ↔ agent CLI | 子进程 stdio | ACP(JSON-RPC):初始化、会话、提示、通知、权限请求 |
| 守护进程 ↔ web 终端会话 | pseudo-tty | 经 PTY 注册表的字节流 |
| agents → 守护进程(工具) | HTTP /mcp | MCP:streamable HTTP 上的 JSON-RPC(+ SSE) |
| 启动的 CLI → 守护进程(模型) | HTTP 回环 /va/local-api/… | 客户端的供应商方言(OpenAI / Anthropic / Gemini 形状) |
| 守护进程 → 模型供应商 | HTTPS | Bridge 转换后的供应商方言 |
| 守护进程 → 隧道 | 进程内 SDK(ngrok)或子进程(cloudflared、npx localtunnel) | 供应商特定 |
| 守护进程 → 被预览的 dev server | HTTP 反向代理 | 透传 + iframe 工具栏注入 |
模块地图
每项职责的归属。每个运行时模块在 modules/ 下都有深入页面,每条端到端路径在 flows/ 下都有走读:
core —— 运行时库(没有 HTTP 服务,没有 UI):
| 模块 | 负责 |
|---|---|
channels | 插件宿主、stdio/websocket 传输、输入分发、outbox、监控 |
workspace | Workspace、Thread、Route 附着、交接码(事件溯源状态 + 内存 pickup codes) |
process | 监督器(拉起/重启/看门狗)、子进程注册表、ACP 传输、环境增强 |
agent | ACP agent 句柄、启动渲染、MCP/技能配置注入 |
profiles | Profile schema、目录、渲染、Bridge 启动 URL、供应商连接 |
pty | PTY 会话注册表与运行时 —— Web 终端的后端 |
previews | 实时预览注册表、owner/share URL、端口清理 |
tunnels | ngrok / localtunnel / cloudflare 各供应商 |
auth | 守护进程 token、配对码 |
launch_sessions | 原生 CLI 会话发现与归档 |
plugins | 插件发现与清单 |
search | 宿主侧网页搜索运行时 |
config、storage、state、routing、resources | 设置、JSONL 事件存储、StateSource 契约、route key、Agent 注册表 |
server —— core 之上的 axum 外壳: web_server/api(REST)、ws_pty / ws_chat / ws_domains(三族 WebSocket)、mcp(工具端点)、api_bridge(方言转换、模型映射、内容策略、上游)、preview(反向代理、markdown 渲染)、auth + pair(token 中间件、配对)、boot(守护进程装配)。
其他 crate: client(HTTP/WS 契约的纯 Rust 协议库)、cli 和 tui(它的消费者)、desktop(Tauri 外壳 + IPC 命令)、launcher(va-launch 原生启动二进制)。
旅程一:一条 IM 消息变成 Agent 回复
-
平台到插件。 Telegram/飞书/Slack 插件 —— 由守护进程监督的独立 Node.js 进程 —— 接收平台的 webhook 或长轮询事件,归一化为渠道信封:route key、消息 id、文本、附件。
-
插件到守护进程。 信封经插件的 stdio ACP 连接进入守护进程,落到渠道输入队列。
-
有序分发。 输入按 route key 分片到 worker 任务:同一聊天的消息严格按序处理,不同聊天并行。这就是连珠炮消息不会互相竞态的原因。
-
命令还是提示。 文本先对照斜杠命令语法检查(
/new、/close、/switch、/pickup……)。命令由 workspace-thread 层直接处理;其余都成为提示。 -
Route 到 Thread。 Route 解析到它附着的开启 Thread。某 Route 首次联系会在默认 Workspace 创建 Thread 并附着 —— 不需要任何设置步骤。
-
Thread 到 Agent。 Thread 确保宿主 Agent 活着:需要时监督器在 Workspace 目录里拉起该 Agent 的 ACP 适配器,绑定 Profile 的环境已就位(凭据、Bridge base URL),VibeAround 的 MCP 端点和技能注入 Agent 配置。Thread 已有 CLI Session 就恢复它;否则新建一个。
-
提示与流式回传。 提示经 ACP 发给 Agent。通知流回来 —— 文本块、工具调用摘要、权限请求 —— 并扇出到附着在该 Thread 上的每条 Route。权限请求渲染为交互卡片;点按以回调返回,解除 Agent 的等待。
-
闲时收尾。 回合结束后启动 10 分钟闲置计时。到期关停 Agent 进程;Thread 保持开启,下一条消息重新拉起 Agent 并恢复同一个 Session。
旅程二:在你的终端里启动 Agent CLI
Agent Launch 是另一条路 —— 不把 Agent 托管在守护进程里,而是在你自己的终端里打开它:
- 你选 Agent、Workspace 和模型 Profile(桌面 UI 或
va launch --profile <name>)。 - Profile 被渲染成一次具体启动:环境变量、按 Agent 的配置覆盖,以及 —— 当 Profile 指向 Bridge 化的供应商时 —— 指向守护进程本地 API 的 base URL(
http://127.0.0.1:12358/va/local-api/…)。 - 原生启动器(
va-launch,随桌面应用和 CLI 一起发行的独立二进制)校验计划,守护进程在运行时安装项目级 MCP/技能集成,然后在你的终端应用里打开 Agent(Terminal.app、iTerm2、PowerShell 或某个 Linux 终端)。 - 启动的 CLI 的模型请求走 Bridge,所以一份 Kimi 或 DeepSeek 订阅可以原生驱动 Codex 或 Claude Code。这样创建的会话会被守护进程发现并显示为可恢复 —— 这就是终端会话后来能从 IM 接续的原理。
状态放在哪
| 状态 | 位置 | 重启后保留? |
|---|---|---|
| Workspace、Thread、Route 附着 | ~/.vibearound/ 里的 JSONL 事件日志 | 保留 |
| Agent CLI 会话(对话记录) | 各 Agent 自己的存储 | 保留(归 Agent 所有) |
| 模型 Profile、设置 | ~/.vibearound/settings.json + Profile 存储 | 保留 |
| 运行中的 Agent/插件进程 | 内存中,受监督 | 不保留 —— 按需重新拉起 |
| 控制台认证 token | ~/.vibearound/auth.json | 每次守护进程启动重新生成 |
监督器给每个子进程(渠道插件、Agent 适配器)提供崩溃重启,插件另有心跳看门狗;守护进程关停时级联清理,不留孤儿进程。
Source anchors: src/server/src/lib.rs (daemon boot, input sharding), src/server/src/web_server/mod.rs + ws_pty.rs / ws_chat.rs / ws_domains.rs (WebSocket families), src/core/src/lib.rs (module map), src/core/src/channels/ (plugin transport, dispatch), src/core/src/workspace/ (threads, attachments), src/core/src/process/supervisor.rs + acp_transport.rs (ACP framing), src/core/src/tunnels/providers/ (tunnel process forms), src/core/src/profiles/bridge_launch.rs (local API URLs), src/launcher/ (va-launch).
Last verified: v0.7.11
核心概念
VibeAround 的运行时围绕六个概念构建: Workspace(工作区) 、 Thread(会话线程) 、 Route(路由) 、 Session(会话) 、 Agent 和 Profile 。每个功能 —— IM 聊天、Web Chat、交接、Agent 切换 —— 都是这六者的组合。本页定义每一个概念以及它们的关系。
本地 API 与 Bridge
VibeAround 自带模型 API Bridge:一个本地转换层,让任何受支持的客户端 API 方言与任何已配置的供应商对话。"一份 Kimi 订阅驱动 Codex、Claude Code 和 Gemini CLI"就是靠它实现的。本页解释 Bridge 是什么、请求如何流经它;Profile 的配置方法见模型 Profile 指南。