mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-30 23:14:37 +00:00
354 lines
18 KiB
Markdown
354 lines
18 KiB
Markdown
---
|
||
description: OpenHuman 代码库的深度架构参考 —— 仓库布局、运行时范围、双 socket 同步、RPC 流程。
|
||
icon: code-branch
|
||
lang: zh-CN
|
||
---
|
||
|
||
# OpenHuman 架构
|
||
|
||
**基于 Rust 构建的加密社区 AI 超级助手。**
|
||
|
||
OpenHuman 是一款为加密货币生态系统量身打造的跨平台通信与自动化平台。单一的 React + Rust(Tauri)代码库可以面向多个平台;**我们目前为用户文档和发布的仅是桌面端** —— **Windows、macOS 和 Linux**。Android、iOS 和 Web **尚未**在当前文档或发布中支持。技术栈包括一个托管的 Node.js 运行时,用于支持工具能力的技能;持久化的 Rust 原生 WebSocket 基础设施;以及一个 AI 工具协议,让语言模型实时调用任何已连接的服务。
|
||
|
||
---
|
||
|
||
## 仓库布局(monorepo)
|
||
|
||
| 路径 | 内容 |
|
||
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||
| **`app/`** | Yarn workspace **`openhuman-app`**:Vite/React UI(`app/src/`)、Tauri 壳层(`app/src-tauri/`)、Vitest 测试 |
|
||
| **仓库根目录 `src/`** | Rust **`openhuman_core`** 库 + **`openhuman-core`** CLI 二进制文件 —— 核心服务器、JSON-RPC、一等 JavaScript 运行时(`src/openhuman/javascript/`),由托管的 Node.js 实现驱动、频道、内存等 |
|
||
| **`Cargo.toml`**(根目录) | 构建 `openhuman-core` 二进制文件(`cargo build --bin openhuman-core`),staging 到 `app/src-tauri/binaries/` 以供桌面打包 |
|
||
| **`skills/`** | 运行时消耗的技能包 |
|
||
| **`docs/`** | 本书 + 每棵树指南(`docs/src/`、`docs/src-tauri/`) |
|
||
|
||
桌面应用 **WebView** 从 `app/` 加载 UI;繁重的 RPC 和技能在 **`openhuman-core`** 进程中运行,可通过 HTTP 从 Tauri 主机访问(`core_rpc_relay`)。
|
||
|
||
---
|
||
|
||
## 平台覆盖范围
|
||
|
||
**今天支持的(终端用户):** 桌面端。Windows、macOS、Linux(原生安装包)。
|
||
|
||
**尚未支持:** Android、iOS、独立 Web 客户端(仓库中可能以实验性目标存在;不要视为产品就绪)。
|
||
|
||
```text
|
||
OpenHuman(已发布)
|
||
|
|
||
Desktop
|
||
/ | \
|
||
Windows macOS Linux
|
||
x64 x64 x64
|
||
ARM64 ARM64 ARM64
|
||
```
|
||
|
||
Tauri v2 将 Rust 核心编译为每个平台的原生二进制文件,将 React 前端作为轻量级 WebView 嵌入。桌面构建产出 `.dmg`、`.msi`、`.AppImage` 和 `.deb` 安装包。额外目标(移动端、Web)在明确文档化支持之前均超出范围。
|
||
|
||
---
|
||
|
||
## 高层架构
|
||
|
||
```text
|
||
+------------------------------------------------------------------+
|
||
| React 前端 |
|
||
| Redux Toolkit | Socket.io 客户端 | MCP 传输层 | UI |
|
||
+------------------------------------------------------------------+
|
||
| Tauri IPC 桥接 |
|
||
+------------------------------------------------------------------+
|
||
| Rust 核心引擎 |
|
||
| |
|
||
| +------------------+ +------------------+ +-----------------+ |
|
||
| | QuickJS 技能 | | Socket 管理器 | | AI 加密 | |
|
||
| | 运行时引擎 | | (持久化 WS) | | & 内存存储 | |
|
||
| +------------------+ +------------------+ +-----------------+ |
|
||
| |
|
||
| +------------------+ +------------------+ +-----------------+ |
|
||
| | 技能注册表 | | Cron 调度器 | | 会话 & 认证 | |
|
||
| | & 桥接 API | | (5s tick 循环) | | 管理 | |
|
||
| +------------------+ +------------------+ +-----------------+ |
|
||
| |
|
||
| +------------------+ +------------------+ +-----------------+ |
|
||
| | Telegram | | SQLite 存储 | | OS 钥匙串 | |
|
||
| | 集成 | | (rusqlite) | | 集成 | |
|
||
| +------------------+ +------------------+ +-----------------+ |
|
||
+------------------------------------------------------------------+
|
||
|
|
||
+-----------+-----------+
|
||
| |
|
||
后端服务 外部 API
|
||
(Socket.io 服务器) (Telegram 等)
|
||
```
|
||
|
||
前端通过两种方式与 **openhuman** Rust 核心通信:用于一小部分壳层命令的 **Tauri IPC**(窗口、AI 文件辅助函数、**`core_rpc_relay`**),以及用于业务逻辑和技能的 **HTTP JSON-RPC**。核心拥有持久连接(如适用)、内存/功能的加密工作,以及 **QuickJS** 沙盒化技能执行。
|
||
|
||
---
|
||
|
||
## Rust 驱动的性能
|
||
|
||
OpenHuman 选择 Tauri + Rust 而非 Electron,基于根本的性能和安全原因:
|
||
|
||
| 指标 | OpenHuman(Tauri + Rust) | 典型 Electron 应用 |
|
||
| ------------------------- | -------------------------------------------------------- | ---------------------------- |
|
||
| 二进制体积 | 取决于功能(CEF 运行时 + 技能包占主导) | ~150 MB+ |
|
||
| 每技能上下文内存 | ~1-2 MB(QuickJS) | ~150 MB+(Chromium 渲染器) |
|
||
| 冷启动 | 亚 500ms | 2-5 秒 |
|
||
| 垃圾回收暂停 | 无(Rust 所有权模型) | V8 GC 暂停 |
|
||
| 内存安全 | 编译期保证 | 运行时异常 |
|
||
| TLS 实现 | rustls(无 OpenSSL 依赖) | Chromium 的 BoringSSL |
|
||
|
||
**这对加密平台为何重要**:交易员和分析师在运行 OpenHuman 的同时,还会运行资源密集型工具、图表软件、多个浏览器标签、交易终端。原生二进制文件加上亚 500ms 启动意味着应用感觉像原生应用,不会碍事。零 GC 暂停意味着实时价格推送和警报永远不会因内存管理而延迟。
|
||
|
||
**Tokio 异步运行时**驱动所有 I/O。WebSocket 连接、HTTP 请求、文件操作和技能间通信,都是线程池上的非阻塞任务。数千个并发操作(技能执行、cron job、socket 事件)共享一小套固定的 OS 线程。
|
||
|
||
---
|
||
|
||
## 实时 Socket 基础设施
|
||
|
||
OpenHuman 实现了**双 socket 架构**:桌面端使用 Rust 原生 WebSocket 客户端,Web 端使用 JavaScript Socket.io 客户端。Rust 实现能在应用后台存活,独立于 WebView 运行,并通过 rustls 处理 TLS。
|
||
|
||
```text
|
||
桌面模式: Web 模式:
|
||
|
||
+-------------+ +-------------+
|
||
| React UI | | React UI |
|
||
+------+------+ +------+------+
|
||
| Tauri IPC | Direct
|
||
+------+------+ +------+------+
|
||
| Rust Socket | | JS Socket |
|
||
| Manager | | .io Client |
|
||
+------+------+ +------+------+
|
||
| tokio-tungstenite | Socket.io
|
||
| + rustls TLS | (websocket/polling)
|
||
+------+------+ +------+------+
|
||
| Backend | | Backend |
|
||
+-------------+ +-------------+
|
||
```
|
||
|
||
**Rust Socket 管理器**通过原始 WebSocket 实现 Engine.IO v4 + Socket.IO v4 帧:
|
||
|
||
- **握手**:WebSocket 连接、Engine.IO OPEN(提取 `sid`、`pingInterval`、`pingTimeout`)、带 JWT 认证的 Socket.IO CONNECT、CONNECT ACK
|
||
- **保活**:响应 Engine.IO PING 以 PONG;超时阈值 = `pingInterval + pingTimeout + 5s`(默认:50 秒)
|
||
- **重连**:指数退避,从 1 秒到最大 30 秒。成功连接丢失后重置为 1s;如果连接从未建立则持续增长
|
||
- **CORS 绕过**:Rust `reqwest` HTTP 客户端直接发起外部 API 调用,不受浏览器 CORS 限制
|
||
|
||
socket 连接在所有技能间**共享**。当事件到达时,socket 管理器通过异步消息通道将它们路由到相应的技能。这完全消除了每个技能的连接开销。
|
||
|
||
**`tool:sync` 协议**:每次 socket 连接和技能生命周期变化时,客户端都会发出一个 `tool:sync` 事件,包含可用工具的完整列表及其连接状态。这使后端 AI 系统能实时感知所有能力。
|
||
|
||
---
|
||
|
||
## 技能运行时引擎
|
||
|
||
OpenHuman 的决定性能力是其运行在 Rust 进程内部的**沙盒化 JavaScript 执行引擎**。技能是轻量级自动化脚本,通过自定义工具、集成和定时任务扩展平台。
|
||
|
||
```text
|
||
+---------------------------------------------------------------+
|
||
| RuntimeEngine |
|
||
| |
|
||
| +-------------------+ +-------------------+ |
|
||
| | SkillRegistry | | CronScheduler | |
|
||
| | (HashMap + MPSC) | | (5s tick loop) | |
|
||
| +--------+----------+ +--------+----------+ |
|
||
| | | |
|
||
| +--------v----------+ +--------v----------+ +----------+ |
|
||
| | JavaScript Layer | | runtime_node | | Bridge | |
|
||
| | skill metadata | | managed Node.js | | APIs | |
|
||
| | + prompt context | | system/bundled | +----+-----+ |
|
||
| | + tool discovery | | tool execution | | |
|
||
| +-------------------+ +-------------------+ | |
|
||
| | |
|
||
| +---------------------------------------------------v-----+ |
|
||
| | net | db | store | cron | log | tauri | | |
|
||
| | HTTP SQLite KV Schedule Log Platform| | |
|
||
| +------------------------------------------------------+ | |
|
||
+---------------------------------------------------------------+
|
||
```
|
||
|
||
**Node.js 运行时**:核心尽可能解析兼容的系统 `node`,否则将托管发行版安装到 OpenHuman 缓存中。技能主要暴露工具元数据,并使用运行时桥接来列出和执行工具,而非在核心内运行隔离的 QuickJS VM。
|
||
|
||
| 参数 | 值 |
|
||
| ---------------------- | ----- |
|
||
| 公共语言槽位 | `javascript` |
|
||
| 当前 JS 后端 | `runtime_node` |
|
||
| 托管 Node 版本 | 默认 `v22.11.0` |
|
||
| 运行时来源 | 系统 `node` 或托管安装 |
|
||
| 完整性验证 | 针对 `SHASUMS256.txt` 的 SHA-256 |
|
||
|
||
**工具桥架构**:`SKILL.md` 包提供元数据、指令和可选的捆绑 JS 辅助函数。Rust 核心拥有权威的工具注册表,JavaScript 运行时桥接列出工具并将具名工具调用分派到核心或 Node-backed 辅助函数中。
|
||
|
||
**桥接 API** 向运行时桥接和 Node-backed 辅助函数暴露平台能力:
|
||
|
||
| 桥接 | 能力 |
|
||
| --------- | ----------------------------------------------------------- |
|
||
| **net** | 通过 `reqwest` 的 HTTP fetch(默认 30s 超时,所有方法) |
|
||
| **db** | 通过 `rusqlite` 的每个技能 SQLite 数据库 |
|
||
| **store** | 键值持久化 |
|
||
| **cron** | 定时注册(6 字段 cron 表达式) |
|
||
| **log** | 通过 Rust `log` crate 的结构化日志 |
|
||
| **tauri** | 平台检测、通知、白名单环境变量 |
|
||
|
||
**技能发现** 使用 `SKILL.md` 加上可选的捆绑资源:
|
||
|
||
| 字段 | 用途 |
|
||
| ------------------ | ------- |
|
||
| `name` | 人类可读的显示名称 |
|
||
| `description` | 触发/选择摘要 |
|
||
| `metadata.id` | 存在时的稳定技能 slug |
|
||
| `allowed-tools` | 工具允许列表指引 |
|
||
| 捆绑资源 | 脚本、参考、资源 |
|
||
|
||
技能从 GitHub 仓库同步并在运行时发现。执行不再建模为每个技能一个嵌入式 QuickJS VM;JavaScript 行为通过共享运行时桥接流动。
|
||
|
||
**Cron 调度器**:一个 5 秒 tick 循环对照 UTC 时间检查所有已注册的调度,使用 `cron` crate 进行表达式解析。当调度触发时,调度器向技能的通道发送 `CronTrigger` 消息,调用技能的 `onCronTrigger()` 处理程序。
|
||
|
||
---
|
||
|
||
## AI & 工具协议(MCP)
|
||
|
||
OpenHuman 实现了**模型上下文协议**,一个基于 Socket.io 的 JSON-RPC 2.0 层,让 AI 模型发现并由技能暴露的工具。
|
||
|
||
```text
|
||
用户提示
|
||
|
|
||
v
|
||
AI 模型(后端)
|
||
|
|
||
| 1. mcp:listTools --> 前端/Rust 聚合所有技能工具
|
||
| <-- 工具目录
|
||
|
|
||
| 2. 决定调用哪个工具
|
||
|
|
||
| 3. mcp:toolCall { skillId__toolName, arguments }
|
||
| |
|
||
| v
|
||
| Socket 管理器路由到技能注册表
|
||
| |
|
||
| v
|
||
| QuickJS 技能实例执行工具
|
||
| |
|
||
| v
|
||
| 桥接 API 调用(HTTP、DB 等)
|
||
| |
|
||
| <-- mcp:toolCallResponse { result }
|
||
|
|
||
v
|
||
AI 对用户的响应
|
||
```
|
||
|
||
**传输**:每次请求 30 秒超时,`mcp:` 事件前缀,请求 ID 在待处理响应映射中跟踪。工具名称以 `skillId__toolName` 命名空间化,以实现明确路由。
|
||
|
||
**工具同步**:`tool:sync` 事件在每次 socket 连接和技能状态变化时广播完整的工具清单、技能 ID、名称、连接状态和工具列表。后端 AI 系统始终拥有可用能力的最新视图。
|
||
|
||
**AI 记忆系统**:
|
||
|
||
| 功能 | 实现 |
|
||
| ------------------ | ------------------------------------------------------ |
|
||
| 静态加密 | 带 Argon2id 密钥派生的 AES-256-GCM |
|
||
| 分块 | 每块 512 token,64 token 重叠 |
|
||
| 搜索 | 混合:70% 向量相似度 + 30% FTS5 全文 |
|
||
| 嵌入 | OpenAI `text-embedding-3-small` |
|
||
| 知识图谱 | 通过 REST API 的 Neo4j,用于实体关系 |
|
||
| 会话 | 带压缩和工具压缩的 JSONL 转录 |
|
||
|
||
记忆加密密钥通过 Argon2id 从用户凭证派生,确保记忆文件在未经认证的情况下不可读。混合搜索结合语义理解(向量相似度)和关键词精确度(SQLite FTS5)以实现可靠的召回。
|
||
|
||
---
|
||
|
||
## 安全架构
|
||
|
||
```text
|
||
+-------------------------------------------------------------------+
|
||
| 安全层 |
|
||
| |
|
||
| +------------------+ +------------------+ +------------------+ |
|
||
| | OS 钥匙串 | | AES-256-GCM | | 沙盒化 | |
|
||
| | (macOS/Win/Lin) | | 内存加密 | | QuickJS 每 | |
|
||
| | 用于凭证 | | + Argon2id KDF | | 技能 (64 MB) | |
|
||
| +------------------+ +------------------+ +------------------+ |
|
||
| |
|
||
| +------------------+ +------------------+ +------------------+ |
|
||
| | 一次性 | | rustls TLS | | 无 localStorage | |
|
||
| | 登录 token | | 用于所有网络 | | 存储敏感数据 | |
|
||
| | (5-min TTL) | | 连接 | | | |
|
||
| +------------------+ +------------------+ +------------------+ |
|
||
+-------------------------------------------------------------------+
|
||
```
|
||
|
||
- **凭证存储**:通过 `keyring` crate 的 OS 钥匙串集成(macOS Keychain、Windows Credential Manager、Linux Secret Service),仅限桌面端
|
||
- **内存加密**:带 Argon2id 密钥派生的 AES-256-GCM。所有 AI 内存静态加密
|
||
- **技能沙盒化**:每个 QuickJS 实例都有强制内存限制(默认 64 MB)和栈限制(512 KB)。禁止跨技能内存访问
|
||
- **认证交接**:Web 到桌面认证使用 5 分钟 TTL 的一次性登录 token,通过 Rust HTTP 客户端交换(绕过 CORS)
|
||
- **网络 TLS**:所有 WebSocket 和 HTTP 连接使用 rustls,不依赖平台 OpenSSL
|
||
- **状态管理**:敏感数据保存在 Redux(内存)和 OS 钥匙串(持久化)中。凭证或 token 不使用 localStorage
|
||
- **提示注入防护**:用户提示在模型/工具执行前经过规范化/评分,并在服务器端强制执行(`allow | review | block`)。详见 [`docs/PROMPT_INJECTION_GUARD.md`](../../docs/PROMPT_INJECTION_GUARD.md)
|
||
|
||
---
|
||
|
||
## 端到端数据流
|
||
|
||
从用户操作到外部服务再返回的完整流程:
|
||
|
||
```text
|
||
用户在聊天 UI 中输入命令
|
||
|
|
||
v
|
||
React 前端分派到 AI 提供商
|
||
|
|
||
v
|
||
AI 模型接收提示 + 工具目录(通过 tool:sync)
|
||
|
|
||
v
|
||
AI 决定调用技能工具(例如,发送 Telegram 消息)
|
||
|
|
||
v
|
||
通过 Socket.io 发送 mcp:toolCall 事件
|
||
|
|
||
v
|
||
Socket 管理器(Rust)接收事件,解析 skillId__toolName
|
||
|
|
||
v
|
||
技能注册表通过 MPSC 通道将消息路由到正确的 QuickJS 实例
|
||
|
|
||
v
|
||
QuickJS 技能执行工具处理程序
|
||
|
|
||
v
|
||
桥接 API:net.rs 通过 reqwest 发起 HTTP 请求(无 CORS,rustls TLS)
|
||
|
|
||
v
|
||
外部服务响应(例如,Telegram API)
|
||
|
|
||
v
|
||
结果回流:桥接 -> QuickJS -> 注册表 -> Socket -> MCP -> AI -> UI
|
||
|
|
||
v
|
||
用户在聊天界面中看到结果
|
||
```
|
||
|
||
每一层都是异步且非阻塞的。Rust 核心在固定的 Tokio 线程池上处理数千个并发的技能执行、cron 触发和 socket 事件。
|
||
|
||
---
|
||
|
||
## 技术栈
|
||
|
||
| 层 | 技术 | 原因 |
|
||
| -------------- | ------------------------------- | -------------------------------------------------------- |
|
||
| **前端** | React 19, TypeScript 5.8 | 现代组件模型,类型安全 |
|
||
| **状态** | Redux Toolkit + Persist | 可预测状态,支持离线持久化 |
|
||
| **构建** | Vite 7 | 亚秒级 HMR,优化的生产构建 |
|
||
| **样式** | Tailwind CSS | 工具优先,一致的设计系统 |
|
||
| **框架** | Tauri v2 | 原生跨平台,开销最小 |
|
||
| **语言** | Rust (2021 edition) | 内存安全,零成本抽象 |
|
||
| **异步** | Tokio | 高性能异步 I/O 运行时 |
|
||
| **JS 运行时** | Node.js | 用于工具辅助函数和技能相关 JS 的托管 V8 运行时 |
|
||
| **数据库** | SQLite (rusqlite) | 嵌入式,零配置,每技能隔离 |
|
||
| **WebSocket** | tokio-tungstenite + rustls | 持久连接,原生 TLS |
|
||
| **HTTP** | reqwest | 异步 HTTP,支持 rustls + native-tLS 双栈 |
|
||
| **加密** | aes-gcm + argon2 | AES-256-GCM 加密,Argon2id 密钥派生 |
|
||
| **调度** | cron crate + 自定义调度器 | 标准 cron 表达式,5 秒精度 |
|
||
| **Telegram** | 已移除 | Telegram 集成已移除 |
|
||
| **实时** | Socket.io(客户端) | 双向基于事件的通信 |
|
||
| **AI** | MCP(JSON-RPC 2.0) | LLM 集成的标准化工具协议 |
|
||
| **搜索** | OpenAI 嵌入 + SQLite FTS5 | 混合语义 + 关键词搜索 |
|
||
| **图谱** | Neo4j | 实体关系知识图谱 |
|