19dc54f842
包含 8 个 Mermaid 图表,覆盖: 1. 全局架构总览 — 所有模块及调用关系 2. 消息处理全链路 — Sequence Diagram 完整流程 3. 模块依赖关系 — 分层依赖图 4. 数据流(消息生命周期) 5. 关键函数调用关系(工具执行/审批/上下文构建) 6. 文件依赖矩阵 7. 启动流程 8. 消费者架构(三消费者)
445 lines
12 KiB
Markdown
445 lines
12 KiB
Markdown
# iAs 代码调用图谱
|
|
|
|
> 微信 AI 智能助手 —— 完整架构与调用关系
|
|
|
|
---
|
|
|
|
## 1. 全局架构总览
|
|
|
|
```mermaid
|
|
flowchart TB
|
|
subgraph CLI["CLI 入口 (main.rs)"]
|
|
A1["clap::Parser Cli 解析"]
|
|
A2["cmd_login"]
|
|
A3["cmd_listen"]
|
|
A4["cmd_send"]
|
|
A5["cmd_whoami"]
|
|
A6["cmd_usage"]
|
|
A7["cmd_tool"]
|
|
A8["cmd_daemon"]
|
|
end
|
|
subgraph DAEMON["守护进程 (daemon.rs)"]
|
|
B0["run()"]
|
|
B1["spawn_consumers()"]
|
|
B2["llm_consumer_loop"]
|
|
B3["tool_consumer_loop"]
|
|
B4["send_consumer_loop"]
|
|
B5["run_llm_round / resume_llm_round"]
|
|
B6["handle_chat_result"]
|
|
B7["execute_tool"]
|
|
end
|
|
subgraph QUEUE["消息队列 (queue/)"]
|
|
C1["MessageQueue 公平轮转"]
|
|
C2["QueueRunner 路由调度"]
|
|
C3["EnqueueHandle"]
|
|
C4["ConsumerChannels"]
|
|
end
|
|
subgraph LLM["LLM 对话系统 (llm/)"]
|
|
D1["Conversation 对话管理器"]
|
|
D2["chat_with_tools() / run_tool_loop()"]
|
|
D3["DeepSeekProvider"]
|
|
D4["LlmProvider trait"]
|
|
D5["StreamReceiver"]
|
|
end
|
|
subgraph CONTEXT["上下文管理 (context/)"]
|
|
E1["ChatSession 消息历史+摘要"]
|
|
E2["builder Token估算+上下文构建"]
|
|
E3["MemoryStore 长期记忆"]
|
|
E4["read_summaries"]
|
|
end
|
|
subgraph TOOLS["工具系统 (tools/)"]
|
|
F1["BuiltinRegistry 工具注册表"]
|
|
F2["ApprovalManager 审批管理"]
|
|
F3["build_capability_guide"]
|
|
F4["unpack_call_params"]
|
|
subgraph BUILTINS["内置工具 (builtins/)"]
|
|
G1["datetime"]
|
|
G2["weather"]
|
|
G3["web_search"]
|
|
G4["fetch_page"]
|
|
G5["memos"]
|
|
G6["amap"]
|
|
end
|
|
end
|
|
subgraph WECHAT["微信通道 (wechat/)"]
|
|
H1["WeChatClient"]
|
|
H2["receive_messages()"]
|
|
H3["send_text()"]
|
|
H4["login()"]
|
|
H5["notify_start/stop"]
|
|
end
|
|
subgraph DB["数据库 (db/)"]
|
|
I1["Database::connect()"]
|
|
I2["models CRUD 操作"]
|
|
end
|
|
subgraph OTHER["其他模块"]
|
|
J1["state.rs 文件状态回退"]
|
|
J2["scheduler.rs 定时任务"]
|
|
J3["logger.rs 日志初始化"]
|
|
J4["channel/mod.rs ChannelId"]
|
|
J5["ipc.rs UDS 协议(已废弃)"]
|
|
J6["worker.rs 旧架构(已废弃)"]
|
|
end
|
|
|
|
A1 --> A2 & A3 & A4 & A5 & A6 & A7 & A8
|
|
A3 --> B0
|
|
A8 --> B0
|
|
B0 --> B1
|
|
B1 --> B2 & B3 & B4
|
|
B2 --> B5 & B6
|
|
B3 --> B7
|
|
B0 --> C1 & C2 & C3
|
|
C2 --> C4
|
|
C4 --> B2 & B3 & B4
|
|
B2 --> D1
|
|
D1 --> D2
|
|
D2 --> D3
|
|
D3 --> D4
|
|
D4 --> D5
|
|
D1 --> E1
|
|
D2 --> E2
|
|
B2 --> E3 & E4
|
|
D2 --> F1
|
|
B3 --> F1 & F2
|
|
B7 --> F1 & F3 & F4
|
|
F1 --> G1 & G2 & G3 & G4 & G5 & G6
|
|
B4 --> H1
|
|
H1 --> H2 & H3
|
|
B0 --> I1
|
|
B2 --> I2
|
|
B4 --> I2
|
|
A2 --> I2 & J1
|
|
A3 --> J1
|
|
B0 --> J1 & J2
|
|
A1 --> J3
|
|
```
|
|
|
|
---
|
|
|
|
## 2. 消息处理全链路
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant WX as 微信用户
|
|
participant WC as WeChatClient
|
|
participant MQ as MessageQueue
|
|
participant QR as QueueRunner
|
|
participant LC as LLM Consumer
|
|
participant TC as Tool Consumer
|
|
participant SC as Send Consumer
|
|
participant LLM as DeepSeek API
|
|
participant BT as BuiltinRegistry
|
|
|
|
WX->>WC: 发送消息
|
|
WC->>MQ: enqueue(UserMessage)
|
|
MQ->>QR: dequeue (公平轮转)
|
|
QR->>LC: llm_tx.send(UserMessage)
|
|
LC->>LC: 加载历史/记忆/摘要
|
|
LC->>LLM: chat_stream(上下文)
|
|
LLM-->>LC: 流式回复 + tool_calls
|
|
|
|
alt 有工具调用
|
|
LC->>MQ: enqueue(ToolCall)
|
|
MQ->>QR: dequeue
|
|
QR->>TC: tool_tx.send(ToolCall)
|
|
|
|
alt 高风险工具
|
|
TC->>TC: ApprovalManager.create()
|
|
TC->>MQ: enqueue(LLMReply: 确认码)
|
|
MQ->>QR: dequeue
|
|
QR->>SC: send_tx.send(LLMReply)
|
|
SC->>WC: send_text(确认码)
|
|
WX-->>WC: 回复确认码
|
|
WC->>MQ: enqueue(UserMessage: 确认码)
|
|
MQ->>QR: dequeue
|
|
QR->>LC: llm_tx.send(确认码)
|
|
LC->>TC: ApprovalManager.handle_reply()
|
|
TC-->>LC: Approved
|
|
LC->>MQ: enqueue(ToolCall + approved=true)
|
|
MQ->>QR: dequeue
|
|
QR->>TC: tool_tx.send(ToolCall)
|
|
end
|
|
|
|
TC->>BT: execute(工具名, 参数)
|
|
BT-->>TC: SkillResult
|
|
TC->>MQ: enqueue(ToolResult)
|
|
MQ->>QR: dequeue
|
|
QR->>LC: llm_tx.send(ToolResult)
|
|
LC->>LLM: resume_tool_loop()
|
|
LLM-->>LC: 最终回复
|
|
end
|
|
|
|
LC->>MQ: enqueue(LLMReply)
|
|
MQ->>QR: dequeue
|
|
QR->>SC: send_tx.send(LLMReply)
|
|
SC->>WC: send_text(回复)
|
|
WC->>WX: 显示回复
|
|
```
|
|
|
|
---
|
|
|
|
## 3. 模块依赖关系
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
subgraph CORE["核心层"]
|
|
MAIN["main.rs"]
|
|
DAEMON["daemon.rs"]
|
|
CLI["cli.rs"]
|
|
end
|
|
subgraph PIPELINE["消息管线"]
|
|
QUEUE["queue/"]
|
|
CHANNEL["channel/"]
|
|
end
|
|
subgraph AI["AI 层"]
|
|
LLM["llm/"]
|
|
CTX["context/"]
|
|
end
|
|
subgraph TOOL["工具层"]
|
|
TOOLS["tools/"]
|
|
BUILTINS["tools/builtins/"]
|
|
APPROVAL["tools/approval.rs"]
|
|
end
|
|
subgraph IO["IO 层"]
|
|
WECHAT["wechat/"]
|
|
DB["db/"]
|
|
STATE["state.rs"]
|
|
SCHED["scheduler.rs"]
|
|
end
|
|
subgraph UTIL["工具层"]
|
|
LOG["logger.rs"]
|
|
IPC["ipc.rs"]
|
|
WORKER["worker.rs"]
|
|
end
|
|
|
|
MAIN --> CLI & DAEMON & LOG & STATE & DB & CTX & LLM & TOOLS & WECHAT & SCHED
|
|
DAEMON --> QUEUE & CHANNEL & WECHAT & DB & STATE & LLM & CTX & TOOLS & SCHED
|
|
QUEUE --> CHANNEL
|
|
LLM --> CTX & TOOLS
|
|
TOOLS --> BUILTINS & APPROVAL
|
|
CTX --> DB
|
|
TOOLS --> DB
|
|
APPROVAL --> DB
|
|
DB --> STATE
|
|
WORKER --> IPC & LLM & TOOLS
|
|
```
|
|
|
|
---
|
|
|
|
## 4. 数据流(消息生命周期)
|
|
|
|
```mermaid
|
|
flowchart TB
|
|
START(["📱 用户发消息"]) --> A["WeChatClient receive_messages()"]
|
|
A --> B["入库: chat_records (inbound)"]
|
|
B --> C["PipelineMessage kind: UserMessage"]
|
|
C --> D["MessageQueue 公平轮转"]
|
|
D --> E["加载历史消息 (最近20条)"]
|
|
E --> F["加载长期记忆 (MemoryStore)"]
|
|
F --> G["加载摘要 (read_summaries)"]
|
|
G --> H["构建上下文 (builder)"]
|
|
H --> I["Conversation chat_with_tools()"]
|
|
I --> J{"LLM 调用了工具?"}
|
|
J -->|"是"| K["Tool Consumer 执行工具"]
|
|
K --> L{"高风险?→ 审批流程"}
|
|
L --> M["结果回喂 LLM"]
|
|
M --> I
|
|
J -->|"否"| N["LLM 生成最终回复"]
|
|
N --> O["Send Consumer send_text()"]
|
|
O --> P["入库: chat_records (outbound)"]
|
|
P --> ENDD(["📱 用户收到回复"])
|
|
```
|
|
|
|
---
|
|
|
|
## 5. 关键函数调用关系
|
|
|
|
### 5.1 工具执行链路
|
|
|
|
```mermaid
|
|
flowchart TB
|
|
subgraph LLM_SIDE["LLM 侧"]
|
|
A["LLM 调用 call_capability()"]
|
|
B["ToolExecutor (闭包)"]
|
|
C["返回 ASYNC_MARKER + 工具名"]
|
|
end
|
|
subgraph QUEUE_SIDE["队列侧"]
|
|
D["PipelineMessage::tool_call()"]
|
|
E["MessageQueue.enqueue()"]
|
|
F["QueueRunner → Tool Consumer"]
|
|
end
|
|
subgraph TOOL_SIDE["工具侧"]
|
|
G["tool_consumer_loop()"]
|
|
H{"高风险?"}
|
|
I["ApprovalManager 审批流程"]
|
|
J["execute_tool()"]
|
|
K{"工具类型?"}
|
|
L["BuiltinRegistry.execute()"]
|
|
M["上下文工具 直接处理"]
|
|
N["unpack_call_params()"]
|
|
end
|
|
subgraph RESULT["结果回喂"]
|
|
O["PipelineMessage::tool_result()"]
|
|
P["LLM Consumer resume_llm_round()"]
|
|
Q["Conversation resume_tool_loop()"]
|
|
end
|
|
|
|
A --> B --> C --> D --> E --> F --> G
|
|
G --> H
|
|
H -->|"是"| I --> J
|
|
H -->|"否"| J
|
|
J --> K
|
|
K -->|"内置工具"| L
|
|
K -->|"上下文工具"| M
|
|
K -->|"call_capability"| N --> K
|
|
J --> O --> P --> Q
|
|
```
|
|
|
|
### 5.2 审批流程
|
|
|
|
```mermaid
|
|
flowchart TB
|
|
A["LLM 请求高风险工具"] --> B["ApprovalManager.create(user_id, tool)"]
|
|
B --> C["生成 6 位确认码 SHA-256 哈希存储"]
|
|
B --> D["创建 oneshot channel"]
|
|
C --> E["发送消息给用户 ⚠️ 操作确认"]
|
|
D --> F["等待用户回复 超时 5 分钟"]
|
|
F --> G{"用户回复"}
|
|
G -->|"匹配确认码"| H["ApprovalDecision::Approved"]
|
|
G -->|"输入 0/取消"| I["ApprovalDecision::Rejected"]
|
|
G -->|"不匹配(最多3次)"| J["减少尝试次数"]
|
|
G -->|"超时"| K["ApprovalDecision::Expired"]
|
|
J --> F
|
|
H --> L["重新入队 UserMessage + approved_tool"]
|
|
I --> M["回复用户: 已取消"]
|
|
K --> N["回复用户: 已超时"]
|
|
```
|
|
|
|
### 5.3 上下文构建流程
|
|
|
|
```mermaid
|
|
flowchart TB
|
|
A["ChatSession (消息历史)"] --> B["estimate_tokens()"]
|
|
B --> C{"Token 超 budget? (默认 28000)"}
|
|
C -->|"是"| D{"checkpoint 之前有未摘要消息?"}
|
|
D -->|"是"| E["trigger_overflow_summary() → 调用 LLM 生成摘要"]
|
|
D -->|"否"| F["裁剪最早的消息 直到符合 budget"]
|
|
C -->|"否"| G{"空闲超时? (12h 无消息)"}
|
|
G -->|"是"| H["trigger_idle_summary() → 清空消息, 保留摘要"]
|
|
G -->|"否"| I["build_context() → 组装最终上下文"]
|
|
E --> I
|
|
F --> I
|
|
H --> I
|
|
I --> J["发送给 LLM"]
|
|
```
|
|
|
|
---
|
|
|
|
## 6. 文件依赖矩阵
|
|
|
|
| 文件 | 依赖的关键模块 |
|
|
|------|---------------|
|
|
| `main.rs` | cli, daemon, db, llm, context, tools, wechat, state, scheduler, logger |
|
|
| `daemon.rs` | queue, channel, wechat, db, state, llm, context, tools, scheduler |
|
|
| `cli.rs` | clap (独立) |
|
|
| `llm/conversation.rs` | context/builder, context/types, llm/provider, llm/types |
|
|
| `llm/deepseek.rs` | llm/provider, llm/types |
|
|
| `llm/provider.rs` | llm/types |
|
|
| `llm/types.rs` | serde (独立) |
|
|
| `context/types.rs` | llm/types |
|
|
| `context/builder.rs` | context/types, llm/types |
|
|
| `context/tools.rs` | db/models |
|
|
| `queue/message_queue.rs` | channel/mod |
|
|
| `queue/runner.rs` | queue/message_queue |
|
|
| `tools/builtin.rs` | tools/types, tools/builtins/* |
|
|
| `tools/approval.rs` | db/models |
|
|
| `tools/mod.rs` | tools/types |
|
|
| `wechat/client.rs` | wechat/types |
|
|
| `wechat/types.rs` | serde (独立) |
|
|
| `db/mod.rs` | db/models |
|
|
| `db/models.rs` | sqlx (独立) |
|
|
| `state.rs` | serde (独立) |
|
|
| `scheduler.rs` | db/models |
|
|
| `worker.rs` | ipc, llm, tools (已废弃) |
|
|
| `ipc.rs` | serde (已废弃) |
|
|
|
|
---
|
|
|
|
## 7. 启动流程
|
|
|
|
```mermaid
|
|
flowchart TB
|
|
START(["ias listen --llm"]) --> A["main()"]
|
|
A --> B["clap::Parser::parse()"]
|
|
B --> C{"命令类型"}
|
|
C -->|"Tool"| D["cmd_tool() 直接执行工具"]
|
|
C -->|"Login"| E["cmd_login() 扫码登录"]
|
|
C -->|"Listen/Service"| F["cmd_listen()"]
|
|
|
|
F --> G["加载 .env"]
|
|
F --> H["Database::connect()"]
|
|
H --> I{"数据库可用?"}
|
|
I -->|"是"| J["创建 MemoryStore (DB 模式)"]
|
|
I -->|"否"| K["创建 MemoryStore (文件模式)"]
|
|
|
|
F --> L["加载认证信息"]
|
|
L --> M{"已登录?"}
|
|
M -->|"否"| N["报错退出"]
|
|
M -->|"是"| O["WeChatClient.set_auth()"]
|
|
|
|
O --> P["WeChatClient.notify_start()"]
|
|
P --> Q["创建 ApprovalManager"]
|
|
Q --> R["创建 Conversation + ToolExecutor"]
|
|
R --> S["启动 Scheduler (定时任务)"]
|
|
S --> T["启动 listen_loop()"]
|
|
|
|
T --> U["WeChatClient.receive_messages()"]
|
|
U --> V{"收到消息?"}
|
|
V -->|"是"| W["enqueue PipelineMessage"]
|
|
W --> X["LLM/Tool/Send 消费者处理"]
|
|
V -->|"否/超时"| U
|
|
```
|
|
|
|
---
|
|
|
|
## 8. 消费者架构(三消费者)
|
|
|
|
```mermaid
|
|
flowchart TB
|
|
subgraph QUEUE2["消息队列"]
|
|
Q["MessageQueue 公平轮转"]
|
|
R["QueueRunner 路由"]
|
|
end
|
|
subgraph LLM_C["LLM Consumer"]
|
|
L1["接收: UserMessage / ToolResult / ScheduledTask"]
|
|
L2["加载用户历史 + 记忆 + 摘要"]
|
|
L3["创建/恢复 Conversation"]
|
|
L4["chat_with_tools() / resume_tool_loop()"]
|
|
L5{"有异步工具等待?"}
|
|
L6["发送 LLMReply"]
|
|
L7["保留 session"]
|
|
L8["清理 session"]
|
|
end
|
|
subgraph TOOL_C["Tool Consumer"]
|
|
T1["接收: ToolCall / ApprovalRequest"]
|
|
T2{"高风险 + 未审批?"}
|
|
T3["ApprovalManager.create()"]
|
|
T4["发送确认码"]
|
|
T5["execute_tool()"]
|
|
T6["发送 ToolResult"]
|
|
end
|
|
subgraph SEND_C["Send Consumer"]
|
|
S1["接收: LLMReply"]
|
|
S2["WeChatClient.send_text()"]
|
|
S3["入库: chat_records (outbound)"]
|
|
end
|
|
|
|
Q --> R
|
|
R -->|"UserMessage / ToolResult"| L1
|
|
R -->|"ToolCall"| T1
|
|
R -->|"LLMReply"| S1
|
|
L1 --> L2 --> L3 --> L4
|
|
L4 --> L5
|
|
L5 -->|"是"| L7
|
|
L5 -->|"否"| L6
|
|
``` |