From Desktop Client to Cyber-Physical Avatar.
<img src="https://img.shields.io/badge/version-1.0.3-blue" alt="version">
<img src="https://img.shields.io/badge/platform-Android-green?logo=android" alt="platform">
<img src="https://img.shields.io/badge/framework-Tauri%20v2%20%7C%20Vue%203-26A17B?logo=tauri" alt="framework">
<img src="https://img.shields.io/badge/backend-Rust%20%7C%20Tokio-000000?logo=rust" alt="backend">
<img src="https://img.shields.io/badge/UI-UnoCSS%20%7C%20Glassmorphism-4f46e5" alt="UI">
<img src="https://img.shields.io/badge/license-MIT-yellow" alt="license">
VCP Mobile(代号 Project Avatar)是 VCPChat 的移动端进化版,一个基于 Tauri v2 + Vue 3 + Rust 构建的 Android 原生应用。核心目标是将 AI Agent 的交互能力以低延迟、高内存安全性的方式带入物理移动端。
与桌面端 VCPChat 不同,Project Avatar 并非简单的界面适配,而是一次架构层面的彻底重构。我们采用了 Double-Track 3-Tier 架构 —— Rust 核心层、Tauri IPC 桥接层、Vue 3 渲染层物理隔离,使每一个层级都可以独立演进而不产生耦合债务。
与市面上其他移动端 AI 应用相比,VCP Mobile 的独特之处在于: - Backend-Driven Streaming:消息生命周期完全由后端 SSE 事件驱动,前端不做任何预创建或状态猜测 - 自定义增量同步协议:不依赖第三方云服务,移动端与桌面端通过 WebSocket + HTTP 双通道直接同步 - 14+ 设备能力工具:将手机本身变成一个分布式计算节点,AI 可直接调用位置、传感器、CPU/GPU 信息等原生能力
| 版本 | 关键里程碑 |
|---|---|
| v0.9.0 | 首个 Preview 版本,Tauri v2 + Vue 3 + Rust 基础架构确立 |
| v0.9.6 | 修复消息历史回退遗留,指纹命令注册,APK 签名验证 |
| v0.9.8 | 消息路由体系完善,SSE 生命周期管理,UI 架构重构 |
| v0.9.10 ~ v0.9.12 | 同步 V2 协议实现,群组对话,附件分类与预览体系 |
| v0.9.13 ~ v0.9.14 | 分布式节点模块,设备能力工具集,Model 管理器,WebGL 特效 |
| v1.0.0 | Avatar 正式发布:Backend-Driven Streaming、Tarven 上下文注入、Semantic Z-Index、SlidePage 虚拟导航 |
项目从首个 commit 起即采用 Tauri v2 + Vue 3 + Rust 栈,不存在 Node.js / Electron 或 Tauri v1 的历史阶段。Rust 的所有权模型和零成本抽象为移动端提供了编译期内存安全保障,Tokio 异步运行时确保网络 IO 不阻塞主线程,这对流式聊天体验至关重要。
流式聊天的消息生命周期已全面转为后端 SSE 事件驱动,前端不再承担消息生命周期管理。
StreamEvent(thinking / content / blocks / end / error)逐事件下发chatStreamStore 仅做状态映射,不做任何消息预创建或内容猜测chatHistoryStore,消除前后端状态不一致的隐患LinesCodec 流式解析,降低移动端内存峰值┌─────────────┐ SSE Stream ┌─────────────────┐
│ Backend │ ──StreamEvent─────► │ chatStreamStore│
│ (Rust) │ thinking/content │ (Vue/Pinia) │
└─────────────┘ /blocks/end └─────────────────┘
结构化提示词注入规则引擎,支持在对话流的任意节点精确插入外部上下文。
system_suffix:在系统提示词前/后追加内容user_suffix:在用户消息前/后追加内容context_inject:在对话历史指定深度注入自定义角色消息scope(global / agent / group)分级生效sort_order 排序机制确保多规则冲突时可预期移动端与桌面端通过自定义三阶段协议保持实时同步,无需第三方云服务。
| 阶段 | 动作 | 传输通道 |
|---|---|---|
| 1. Metadata 指纹交换 | 对比 SHA-256 Hash 列表 | WebSocket |
| 2. Content Diff | Hash 不匹配时执行 PULL / PUSH | HTTP |
| 3. Message Stream | 增量拉取缺失消息 | WebSocket |
updated_at 策略,保证最终一致性插件化附件系统,支持从图像到文档的全类型处理。
AttachmentRegistry 注册表 + AttachmentFactory 工厂 + AttachmentClassifier 分类器Image / Video / Audio / Document / Code / Text / OtherAttachmentViewer 全屏查看器,挂载于语义化 z-viewer 层级rename + SHA-256 流式哈希计算modelStore 集中管理模型列表、收藏状态、热门排行ModelSelector BottomSheet 弹层:收藏 > 热门 > 字母序三级排序AgentSettingsView 深度联动,切换模型即时生效11 级语义化层级系统,彻底消灭 z-[999] 魔法数字。
| 语义名 | 数值 | 用途 |
|---|---|---|
content |
0 | 页面内容默认层 |
local |
10 | 局部悬浮(置底按钮、角标) |
drawer |
20 | 左右抽屉 + 遮罩 |
overlay |
30 | 全局覆盖容器 |
page |
40+ | SlidePage 虚拟页面栈 |
sheet |
50 | BottomSheet、ModelSelector |
dialog |
60 | Prompt、ContextMenu |
viewer |
70 | AttachmentViewer、AvatarCropper |
editor |
80 | 全屏 HTML 编辑器 |
toast |
90 | Toast 通知 |
boot |
100 | 启动屏 |
gate |
110 | 权限引导页 |
--layer-* + UnoCSS 快捷类 z-* + TypeScript 常量 LAYER_*overlayStore 管理,动态 Z-Index = 40 + stackIndexdistributed/ 模块将手机转化为 AI 可直接调用的分布式计算节点,提供 14+ 原生设备能力:
device_info / device_status_summary — 设备综合信息location — GPS 与网络定位battery — 电量与充电状态clipboard — 剪贴板读写cpu_info / gpu_info / memory_info / storage_info — 硬件监控network_info — 网络类型与连接状态ambient_sensor / motion_sensor — 环境传感器与运动传感器notification — 本地通知推送frontend_bridge — 前后端能力桥接AgentSettingsView / GroupSettingsView 设置面板,与 ModelSelector 联动vue-cropper 头像裁剪 + Dominant Color 主色调提取group_context_assembler 与 group_speaking_policy 发言策略WebGLFluidBackground.vue 提供高性能流体模拟动态背景,仅用于关于界面(About Section)的视觉特效。
confirm_frontend_boot 回滚保护机制:新资源加载失败时自动回退至上一稳定版本frontend_update_manager 管理下载、校验、应用全生命周期VCP Mobile 采用 Double-Track 3-Tier(双轨三层)架构,将 UI 渲染层、IPC 桥接层、Rust 核心层物理隔离,并向下延伸为 Android 原生插件层,实现端到端的类型安全与内存安全。
┌───────────────────────────────────────────────────────────────┐
│ Rendering Layer │
│ Vue 3.5 + Pinia 3 + UnoCSS │
│ src/ —— 组件、Store、Composable、Directive │
├───────────────────────────────────────────────────────────────┤
│ IPC Bridge Layer │
│ Tauri v2 —— invoke / listen / Channel │
│ 前端调用 Rust command,后端通过 Channel 推送 SSE Stream │
├───────────────────────────────────────────────────────────────┤
│ Core Layer │
│ Rust + Tokio │
│ src-tauri/src/vcp_modules/ —— 7 大领域: │
│ agent / chat / group / infra / persistence / sync / updater │
│ src-tauri/src/distributed/ —— 14+ 设备能力工具 │
├───────────────────────────────────────────────────────────────┤
│ Native Layer │
│ Kotlin Android Plugin (tauri-plugin-vcp-mobile) │
│ 屏幕常亮、前台保活、键盘 Insets、生命周期桥接 │
└───────────────────────────────────────────────────────────────┘
Double-Track 指两条独立的数据通道:
- Request-Response Track:Vue invoke → Rust Command → 返回 Result<T, String>,用于配置读写、CRUD 操作。
- Streaming Track:Rust Channel → 前端 listen / EventSource,用于 SSE Stream、WebSocket 消息、进度推送。
发送消息(Send Message):
Vue Input → chatSessionStore
→ invoke("send_chat_message", payload)
→ Rust chat service → VCP API
← SSE Stream
→ Channel.emit() → Vue chatStreamStore
→ chatHistoryStore 追加消息块
增量同步(Delta Sync):
Vue → invoke("start_sync") → Rust sync service
→ WebSocket 握手 → Delta Sync 协议
→ SHA-256 Hash compare(本地 vs 远端)
→ 生成增量 patch → SQLite WAL 写入
→ 前端 syncStore 更新进度与状态
全局状态由 18 个 Pinia Stores 组成,全部使用 Composition API 风格(defineStore('id', () => { ... })),摒弃 Options API。
| Store | 职责 |
|---|---|
chatSessionStore |
当前会话状态、输入框内容、快捷操作 |
chatHistoryStore |
消息列表、分页加载、消息 CRUD |
chatStreamStore |
SSE Stream 实时状态、thinking 块、block 解析 |
attachmentStore |
附件选择、上传队列、MIME 识别、进度追踪 |
overlayStore |
SlidePage 栈、BottomSheet、Dialog 队列、Z-Index 管理 |
agentStore |
Agent / Group 列表、排序、缓存、卡片级手势状态 |
themeStore |
主题切换、CSS 变量注入、跟随系统深色模式 |
tauri-plugin-vcp-mobile 统一管理全部 Android 原生能力,不同功能采用不同的通信方式:
| 功能 | Rust 模块 | Kotlin 模块 | 通信方式 |
|---|---|---|---|
| 屏幕常亮 | src/screen.rs |
— | Raw JNI(jni crate 直接调用 Activity) |
| 流式前台保活 | src/stream.rs |
StreamKeepaliveService.kt |
PluginHandle.run_mobile_plugin |
| 键盘 Insets | — | KeyboardInsetsManager.kt |
evaluateJavascript 注入 CustomEvent |
| 生命周期事件 | — | LifecycleBridge.kt |
evaluateJavascript 注入 CustomEvent |
| 权限与系统控制 | src/system.rs |
VcpMobilePlugin.kt |
PluginHandle.run_mobile_plugin |
关键设计决策:
- KeyboardInsetsManager 和 LifecycleBridge 不使用 Tauri 标准事件通道,而是通过 evaluateJavascript 直接注入 window.CustomEvent
- StreamKeepaliveService 使用 START_STICKY + IMPORTANCE_HIGH + Android 14+ FOREGROUND_SERVICE_TYPE_REMOTE_MESSAGING
- 屏幕常亮使用 Raw JNI 而非 PluginHandle,避免跨语言序列化开销
VCPMobile/
├── src/ # Vue 3 前端源码
│ ├── main.ts # 应用入口
│ ├── App.vue # 根布局(引导流程 + 侧边栏手势)
│ ├── core/
│ │ ├── stores/ # 18 Pinia Stores(Composition API)
│ │ ├── composables/ # 15 个全局组合式函数
│ │ ├── router/ # Hash 模式路由
│ │ ├── directives/ # v-intersection-observer, v-longpress
│ │ ├── types/ # 全局 TypeScript 类型
│ │ ├── constants/ # 层级常量、主题 Token
│ │ └── utils/ # 同步服务、通用工具
│ ├── features/ # 领域功能模块(Feature Co-location)
│ │ ├── chat/ # 对话引擎、消息渲染、输入增强
│ │ ├── agent/ # Agent/Group CRUD、设置面板、拖拽排序
│ │ ├── topic/ # 主题管理
│ │ ├── settings/ # 全局设置、主题选择
│ │ ├── notification/ # 通知中心与 Toast
│ │ ├── sync/ # 同步状态 UI
│ │ └── distributed/ # 设备工具调用 UI
│ ├── components/
│ │ ├── layout/ # AgentSidebar, BootScreen, RightSidebar
│ │ ├── ui/ # BottomSheet, ToastManager 等原语
│ │ └── settings/ # 设置页原子组件
│ └── assets/ # 主题 CSS、Logo 预览
├── src-tauri/ # Tauri v2 + Rust 后端
│ ├── src/
│ │ ├── lib.rs # Tauri Command 注册、managed state
│ │ ├── vcp_modules/ # 业务逻辑(7 大领域)
│ │ │ ├── agent/
│ │ │ ├── chat/
│ │ │ ├── group/
│ │ │ ├── infra/
│ │ │ ├── persistence/
│ │ │ ├── sync/
│ │ │ └── updater/
│ │ └── distributed/ # 设备能力工具(14+ tools)
│ ├── plugins/vcp-mobile/ # Android 原生插件
│ │ ├── src/ # Rust 侧(screen / stream / system)
│ │ ├── android/ # Kotlin 侧(Service / Bridge / Manager)
│ │ ├── guest-js/ # 前端 TS 调用封装
│ │ └── permissions/ # Tauri v2 权限声明
│ └── Cargo.toml # Rust 依赖与 Release 优化配置
├── docs/ # 四层技术文档体系
│ ├── vue_docs/ # 前端文档(24 份)
│ ├── modules/ # Rust 模块文档(17 份)
│ ├── sync/ # 同步协议文档(20 份)
│ ├── plugins/ # 原生插件文档(9 份)
│ └── *.md # 顶层规范(架构、UI 层级、依赖管理)
├── plans/ # 知识治理体系(5 层目录)
├── scripts/ # 开发辅助脚本
├── .github/workflows/ # CI/CD(类型检查 + Release APK)
├── package.json # pnpm 依赖与脚本
├── vite.config.ts # Vite 配置(端口 1420/1421)
├── uno.config.ts # UnoCSS 预设与主题色
└── tsconfig.json # TS 严格模式配置
| 文件 | 说明 |
|---|---|
src/main.ts |
Vue/Pinia/Router 实例创建,全局指令注册,初始化监听 |
src/App.vue |
根布局:BootScreen 引导、侧边栏手势、全局事件监听 |
src/core/constants/layers.ts |
语义化 Z-Index 体系(content → gate,共 11 层) |
src/core/stores/chatStreamStore.ts |
SSE Stream 状态驱动,Backend-Driven Streaming 核心 |
src-tauri/src/lib.rs |
Tauri 命令路由、managed state 注入、启动钩子 |
src-tauri/src/vcp_modules/chat/chat_manager.rs |
对话生命周期管理、消息发送编排 |
src-tauri/src/vcp_modules/infra/vcp_client.rs |
HTTP 客户端(reqwest + rustls-tls)、SSE 解析 |
src-tauri/src/vcp_modules/sync/sync_service.rs |
三阶段增量同步主控(WebSocket + HTTP) |
src-tauri/src/distributed/tools/device_info.rs |
设备信息工具(14+ 设备能力之一) |
src-tauri/plugins/vcp-mobile/android/.../StreamKeepaliveService.kt |
Android 14+ 前台保活服务 |
docs/SYNC_ARCHITECTURE.md |
增量同步协议完整规范 |
docs/UI_LAYER_ARCHITECTURE.md |
全局 UI 层级与 Z-Index 语义化规范 |
scripts/tauri_android_dev.cjs |
WiFi/USB 双模式真机调试启动器 |
uno.config.ts |
UnoCSS 主题色、快捷类、断点配置 |
vite.config.ts |
Vite 插件链、Tauri 感知开发服务器 |
| 工作流 | 文件 | 触发条件 | 执行内容 |
|---|---|---|---|
| CI | .github/workflows/ci.yml |
push / PR 到 main | vue-tsc --noEmit + cargo fmt --check + cargo clippy -- -D warnings |
| Release | .github/workflows/release.yml |
GitHub Release published | 构建 aarch64 Release APK 并上传 |
Release 工作流环境:Node 22, pnpm 10, Java 17 (temurin), Android NDK 29.0.13846066。APK 自动重命名为 VCPMobile_v{VERSION}_arm64-v8a.apk。
| Layer | Tech | Version | Purpose |
|---|---|---|---|
| Frontend Framework | Vue | 3.5.33 | Reactive UI |
| Frontend Framework | Vue Router | 5.0.6 | Hash routing |
| Frontend State | Pinia | 3.0.4 | State management |
| Frontend State | pinia-plugin-persistedstate | 4.7.1 | State persistence |
| Frontend Style | UnoCSS | 66.6.8 | Atomic CSS |
| Frontend Build | Vite | 6.4.2 | Build tool |
| Front |
$ claude mcp add VCPMobile \
-- python -m otcore.mcp_server <graph>