添加中文文档
This commit is contained in:
215
docs/zh/architecture-diagram.md
Normal file
215
docs/zh/architecture-diagram.md
Normal file
@@ -0,0 +1,215 @@
|
||||
# NanoClaw 架构图
|
||||
|
||||
## 系统概览
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph Platforms["消息平台"]
|
||||
P1[Discord]
|
||||
P2[Telegram]
|
||||
P3[Slack]
|
||||
P4[GitHub / Linear]
|
||||
P5[WhatsApp / iMessage / Teams / GChat / Matrix / Webex / Email]
|
||||
end
|
||||
|
||||
subgraph Host["宿主机进程 (Node)"]
|
||||
direction TB
|
||||
Bridge["Chat SDK 桥接<br/>(src/channels/chat-sdk-bridge.ts)"]
|
||||
Router["路由器<br/>(src/router.ts)<br/>platformId + threadId -> messaging_group -> agent_group -> session"]
|
||||
SessMgr["Session 管理器<br/>(src/session-manager.ts)<br/>创建 inbound.db + outbound.db"]
|
||||
Runner["容器运行器<br/>(src/container-runner.ts)<br/>OneCLI ensureAgent + 启动"]
|
||||
Delivery["投递轮询器<br/>(src/delivery.ts)<br/>活跃时 1s / sweep 时 60s"]
|
||||
Sweep["宿主机 Sweep<br/>(src/host-sweep.ts)<br/>心跳、重试、重复执行"]
|
||||
Central[("中央库<br/>data/v2.db<br/>agent_groups<br/>messaging_groups<br/>messaging_group_agents<br/>sessions<br/>pending_approvals")]
|
||||
end
|
||||
|
||||
subgraph OneCLI["OneCLI 网关 (0.3.1)"]
|
||||
Vault["Agent Vault<br/>秘密 + OAuth"]
|
||||
Approvals["configureManualApproval<br/>-> pending_approvals"]
|
||||
end
|
||||
|
||||
subgraph Session["每个 Session 的容器 (Docker / Apple Container)"]
|
||||
direction TB
|
||||
PollLoop["轮询循环<br/>(container/agent-runner)"]
|
||||
Provider["Agent 提供程序<br/>(claude、opencode、mock;待办: codex)"]
|
||||
MCP["MCP 工具<br/>send_message, send_file, edit_message,<br/>add_reaction, send_card, ask_user_question,<br/>schedule_task, create_agent,<br/>install_packages, add_mcp_server"]
|
||||
Skills["容器技能<br/>(container/skills/)"]
|
||||
InDB[("inbound.db<br/>宿主机写入<br/>偶数 seq<br/>messages_in<br/>destinations<br/>processing_ack")]
|
||||
OutDB[("outbound.db<br/>容器写入<br/>奇数 seq<br/>messages_out<br/>心跳文件")]
|
||||
end
|
||||
|
||||
subgraph Groups["Agent Group 文件系统 (groups/*)"]
|
||||
Folder["CLAUDE.md<br/>记忆<br/>每个 group 的技能<br/>container_config"]
|
||||
end
|
||||
|
||||
P1 & P2 & P3 & P4 & P5 --> Bridge
|
||||
Bridge --> Router
|
||||
Router --> Central
|
||||
Router --> SessMgr
|
||||
SessMgr --> InDB
|
||||
SessMgr --> Runner
|
||||
Runner --> OneCLI
|
||||
Runner --> PollLoop
|
||||
PollLoop --> InDB
|
||||
PollLoop --> Provider
|
||||
Provider --> MCP
|
||||
Provider --> Skills
|
||||
MCP --> OutDB
|
||||
OutDB --> Delivery
|
||||
Delivery --> Central
|
||||
Delivery --> Bridge
|
||||
Bridge --> P1 & P2 & P3 & P4 & P5
|
||||
Sweep --> InDB
|
||||
Sweep --> OutDB
|
||||
Sweep --> Central
|
||||
Runner -.挂载.-> Folder
|
||||
MCP -.审批.-> Approvals
|
||||
Approvals --> Central
|
||||
Provider -.API 调用.-> Vault
|
||||
```
|
||||
|
||||
## 消息流程 (入站 -> agent -> 出站)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant P as 平台 (例如 Telegram)
|
||||
participant B as Chat SDK 桥接
|
||||
participant R as 路由器
|
||||
participant SM as Session 管理器
|
||||
participant IDB as inbound.db
|
||||
participant C as 容器 (agent-runner)
|
||||
participant ODB as outbound.db
|
||||
participant D as 投递轮询器
|
||||
|
||||
P->>B: 新消息
|
||||
B->>R: routeInbound(platformId, threadId, msg)
|
||||
R->>R: 解析 messaging_group -> agent_group -> session<br/>(agent-shared | shared | per-thread)
|
||||
R->>SM: 确保 session + DB 存在
|
||||
R->>IDB: INSERT messages_in (偶数 seq)
|
||||
R->>C: 唤醒容器 (docker run / 已在运行)
|
||||
C->>IDB: 轮询 messages_in
|
||||
C->>C: 格式化 xml, 流式传输到选定的 provider
|
||||
C->>ODB: INSERT messages_out (奇数 seq)<br/>解析 <message to="name"> 块
|
||||
D->>ODB: 1s 轮询(活跃)/ 60s(sweep)
|
||||
D->>D: hasDestination() 重新验证
|
||||
D->>B: 通过适配器投递
|
||||
B->>P: 发送消息 / 编辑 / 反应 / 文件 / 卡片
|
||||
```
|
||||
|
||||
## 命名目的地 + Agent 到 Agent
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph AgentA["Agent Group A (主agent)"]
|
||||
A_out["输出:<br/><message to='slack'>...</message><br/><message to='browser-agent'>...</message><br/><internal>scratchpad</internal>"]
|
||||
end
|
||||
|
||||
subgraph Dests["inbound.db.destinations (每个 agent)"]
|
||||
D1["slack -> messaging_group 42"]
|
||||
D2["browser-agent -> agent_group 7<br/>(双向行)"]
|
||||
D3["github -> messaging_group 13"]
|
||||
end
|
||||
|
||||
subgraph AgentB["Agent Group B (浏览器子agent)"]
|
||||
B_session["自己的 inbound.db / outbound.db<br/>继承了返回到 A 的目的地"]
|
||||
end
|
||||
|
||||
Slack[Slack 频道]
|
||||
GitHub[GitHub PR 线程]
|
||||
|
||||
A_out -->|解析 + 查找| Dests
|
||||
D1 -->|投递| Slack
|
||||
D2 -->|写入 B 的 inbound.db| B_session
|
||||
D3 -->|投递| GitHub
|
||||
B_session -.通过 'parent' 回复.-> Dests
|
||||
```
|
||||
|
||||
## 实体模型 + 隔离级别
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
agent_groups ||--o{ messaging_group_agents : 已连接
|
||||
messaging_groups ||--o{ messaging_group_agents : 已连接
|
||||
agent_groups ||--o{ sessions : 运行
|
||||
messaging_groups ||--o{ sessions : 上下文
|
||||
agent_groups ||--o{ agent_destinations : 拥有
|
||||
agent_groups ||--o{ pending_approvals : 请求
|
||||
|
||||
agent_groups {
|
||||
int id
|
||||
string name
|
||||
string folder
|
||||
string agent_provider
|
||||
json container_config
|
||||
}
|
||||
messaging_groups {
|
||||
int id
|
||||
string channel_type
|
||||
string platform_id
|
||||
string name
|
||||
bool is_group
|
||||
string unknown_sender_policy "strict | request_approval | public"
|
||||
}
|
||||
users {
|
||||
string id PK "命名空间 <channel>:<handle>"
|
||||
string kind
|
||||
string display_name
|
||||
}
|
||||
user_roles {
|
||||
string user_id FK
|
||||
string role "owner | admin"
|
||||
string agent_group_id FK "null = 全局"
|
||||
}
|
||||
agent_group_members {
|
||||
string user_id FK
|
||||
string agent_group_id FK
|
||||
}
|
||||
user_dms {
|
||||
string user_id FK
|
||||
string channel_type
|
||||
string messaging_group_id FK
|
||||
}
|
||||
messaging_group_agents {
|
||||
int messaging_group_id
|
||||
int agent_group_id
|
||||
string session_mode "agent-shared | shared | per-thread"
|
||||
json trigger_rules
|
||||
int priority
|
||||
}
|
||||
sessions {
|
||||
int id
|
||||
int agent_group_id
|
||||
int messaging_group_id
|
||||
string sdk_session_id
|
||||
string status
|
||||
}
|
||||
```
|
||||
|
||||
### 隔离级别速查表
|
||||
|
||||
| 级别 | `session_mode` | 共享内容 | 示例 |
|
||||
|---|---|---|---|
|
||||
| 1. 共享 session | `agent-shared` | 工作区 + 记忆 + 对话 | Slack + GitHub webhooks 在同一线程 |
|
||||
| 2. 相同 agent,独立 session | `shared` / `per-thread` | 仅工作区 + 记忆 | 一个 agent 跨 3 个 Telegram 聊天 |
|
||||
| 3. 独立的 agent group | (不同的 `agent_group_id`) | 无 | 个人 vs 工作频道 |
|
||||
|
||||
## 双库拆分(为什么)
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph Mount["/workspace (挂载到容器中的卷)"]
|
||||
In[("inbound.db")]
|
||||
Out[("outbound.db")]
|
||||
HB["/.heartbeat (文件 touch)"]
|
||||
end
|
||||
|
||||
Host[宿主机进程] -->|"仅写入<br/>(偶数 seq)"| In
|
||||
Host -->|读取| Out
|
||||
Container[agent-runner] -->|读取| In
|
||||
Container -->|"仅写入<br/>(奇数 seq)"| Out
|
||||
Container -->|每次轮询 touch| HB
|
||||
HostSweep[宿主机 sweep] -->|stat mtime| HB
|
||||
HostSweep -->|读取 processing_ack| In
|
||||
|
||||
note1["每个文件有且仅有一个写入者。<br/>消除了 SQLite 跨进程写入竞争。<br/>无冲突的 seq 编号。"]
|
||||
```
|
||||
Reference in New Issue
Block a user