MimicLaw 系统架构

基于 MimicLaw 版本 0.1.0(commit 5bcb28a)。

整体数据流

用户 (Telegram / WebSocket / 串口 CLI)


┌──────────────────────────────────────────────────┐
│              ESP32-S3 (MimicLaw)                 │
│                                                  │
│  [输入通道 — Core 0]                              │
│   ├─ Telegram 轮询器 (长轮询, 30s 超时)           │
│   ├─ WebSocket 服务器 (端口 18789)                │
│   └─ 串口 CLI (USB, 115200 波特率)                │
│           │                                      │
│           ▼                                      │
│  ┌──────────────────────┐                        │
│  │    入站队列 (深度 8)  │  FreeRTOS xQueue       │
│  └──────────┬───────────┘                        │
│             │                                    │
│             ▼                                    │
│  ┌──────────────────────────────────────┐        │
│  │      Agent 循环 — Core 1             │        │
│  │                                      │        │
│  │  1. 加载会话历史(最近 20 条)         │        │
│  │  2. 构建系统提示词                    │        │
│  │     SOUL.md + USER.md + MEMORY.md    │        │
│  │     + 最近 3 天的每日笔记             │        │
│  │  3. ReAct 循环(最多 10 次迭代):     │        │
│  │     ├─ 调用 Claude API(带工具)      │        │
│  │     ├─ 如果 tool_use → 执行工具       │        │
│  │     └─ 重复直到 end_turn             │        │
│  │  4. 保存到会话 JSONL                  │        │
│  │  5. 推送响应到出站队列                │        │
│  └──────────────┬───────────────────────┘        │
│                 │                                 │
│                 ▼                                 │
│  ┌──────────────────────┐                        │
│  │    出站队列 (深度 8)  │                        │
│  └──────────┬───────────┘                        │
│             │                                    │
│             ▼                                    │
│  [输出分发 — Core 0]                              │
│   ├─ telegram.sendMessage(超 4096 字符自动分段)  │
│   └─ WebSocket.send                              │
└──────────────────────────────────────────────────┘

         ▼  HTTPS (esp_tls / 代理隧道)
    Anthropic Claude API
    Brave Search API

模块地图

main/
├── mimi.c                 # 入口 (app_main),编排初始化流程
├── mimi_config.h          # 所有编译时常量和 NVS 键名
├── mimi_secrets.h         # 编译时凭据(已 gitignore)

├── bus/                   # 消息总线 — FreeRTOS 队列
│   └── message_bus.c      #   mimi_msg_t: channel, chat_id, content

├── wifi/                  # WiFi STA 管理
│   └── wifi_manager.c     #   连接、指数退避重连、NVS 凭据

├── telegram/              # Telegram Bot API 客户端
│   └── telegram_bot.c     #   长轮询、代理支持、消息分段

├── llm/                   # Anthropic Messages API 客户端
│   └── llm_proxy.c        #   非流式、PSRAM 缓冲区、代理路径

├── agent/                 # AI Agent 核心
│   ├── agent_loop.c       #   ReAct 循环(最多 10 次迭代)
│   └── context_builder.c  #   系统提示词: 引导文件 + 记忆 + 工具

├── memory/                # 持久化存储
│   ├── memory_store.c     #   MEMORY.md + 每日笔记 (SPIFFS)
│   └── session_mgr.c      #   JSONL 会话 + 环形缓冲区 (20 条消息)

├── tools/                 # 工具注册表 + 内置工具
│   ├── tool_registry.c    #   注册工具,构建 JSON Schema
│   ├── tool_web_search.c  #   Brave Search API(直连 + 代理)
│   ├── tool_get_time.c    #   HTTP Date 头 → 系统时钟同步
│   └── tool_files.c       #   SPIFFS 文件操作: read/write/edit/list

├── proxy/                 # HTTP CONNECT 代理隧道
│   └── http_proxy.c       #   TCP → CONNECT → TLS 隧道

├── gateway/               # WebSocket 服务器
│   └── ws_server.c        #   端口 18789, JSON 协议, 最多 4 客户端

├── cli/                   # 串口控制台
│   └── serial_cli.c       #   esp_console REPL, 17 个命令

└── ota/                   # 空中升级
    └── ota_manager.c      #   esp_https_ota 封装

总代码量: ~4,000 行 C 代码。

FreeRTOS 任务布局

任务核心栈大小优先级说明
tg_poll08 KB5Telegram 长轮询循环
agent_loop112 KB6ReAct Agent 循环(阻塞等待入站队列)
outbound_dispatch06 KB5将响应路由到各通道
ws_server (httpd)04 KB5WebSocket 服务器
serial_cli04 KB4esp_console REPL
main01初始化后空闲

设计原则: Core 0 处理所有网络 I/O,Core 1 专用于 Agent 循环。避免 I/O 延迟阻塞 Agent 处理。

Flash 分区布局

基于 partitions.csv(16MB Flash):

偏移大小名称用途
0x00900024 KBnvs配置持久化(WiFi、API 密钥、模型)
0x00F0008 KBotadataOTA 启动状态
0x0110004 KBphy_initWiFi PHY 校准数据
0x0200002 MBota_0固件槽位 A
0x2200002 MBota_1固件槽位 B
0x42000012 MBspiffsMarkdown 记忆、会话、配置
0xFF000064 KBcoredump崩溃转储

RAM 内存预算

用途位置大约大小
FreeRTOS 任务栈内部 SRAM~40 KB
WiFi 缓冲区内部 SRAM~30 KB
TLS 连接 (x2)PSRAM~120 KB
JSON 解析缓冲区PSRAM~32 KB
会话历史缓存PSRAM~32 KB
系统提示词缓冲区PSRAM~16 KB
LLM 响应缓冲区PSRAM~32 KB
剩余可用PSRAM~7.7 MB

策略: 小且频繁访问的数据放在内部 SRAM (512 KB)。大缓冲区 (32KB+) 通过 heap_caps_calloc(1, size, MALLOC_CAP_SPIRAM) 从 PSRAM 分配。

SPIFFS 存储布局

/spiffs/
├── config/
│   ├── SOUL.md            # AI 人格定义
│   └── USER.md            # 用户档案
├── memory/
│   ├── MEMORY.md          # 长期持久化记忆
│   └── daily/
│       ├── 2026-02-20.md  # 每日笔记(每天一个文件)
│       └── ...
└── sessions/
    ├── tg_12345.jsonl     # 按对话存储的会话(Telegram)
    └── ws_3.jsonl          # 按客户端存储的会话(WebSocket)

会话格式(JSONL — 每行一个 JSON 对象):

{"role":"user","content":"你好","ts":1738764800}
{"role":"assistant","content":"你好!","ts":1738764802}

只保存 user + assistant 消息。中间的工具调用步骤不持久化,保持会话文件紧凑。

消息总线

消息总线使用两个 FreeRTOS 队列(各深度 8)解耦输入通道和 Agent 循环:

typedef struct {
    char channel[16];   // "telegram", "websocket", "cli"
    char chat_id[32];   // Telegram chat ID 或 "ws_<fd>"
    char *content;      // 堆分配的文本(所有权转移)
} mimi_msg_t;

所有权模型: 发送方用 strdup() 分配 content,队列接管所有权,接收方处理后必须 free()

Claude API 集成

MimicLaw 直接调用 Anthropic Messages API(无 LiteLLM 抽象层):

端点: POST https://api.anthropic.com/v1/messages

与 OpenClaw 的关键差异:

  • 非流式 — 接收完整 JSON 响应,不使用 SSE
  • PSRAM 缓冲区 — 响应体累积在 PSRAM 支持的缓冲区中
  • 代理路径 — 如已配置,通过 HTTP CONNECT 隧道路由
  • 工具调用协议 — 使用 Anthropic 原生 tool_use / tool_result 格式(与 OpenClaw 相同)

agent_loop.c 中的 ReAct 循环:

for 每次迭代 (最多 10 次):
    1. 向用户发送"思考中..."状态提示
    2. 调用 llm_chat_tools(system_prompt, messages, tools_json)
    3. 如果 stop_reason == "end_turn" → 完成
    4. 如果 stop_reason == "tool_use":
       a. 追加 assistant 消息(text + tool_use 块)
       b. 通过 tool_registry 执行每个工具
       c. 追加 user 消息(tool_result 块)
       d. 继续循环

系统提示词构建

context_builder.c 构建:

# MimiClaw

You are MimiClaw, a personal AI assistant running on an ESP32-S3 device.
[人格 + 行为指引]

## Available Tools
[工具注册表中的工具描述]

## Memory
[主动使用文件工具持久化记忆的指令]

## Personality
[SOUL.md 内容]

## User Info
[USER.md 内容]

## Long-term Memory
[MEMORY.md 内容]

## Recent Notes
[最近 3 天的 daily/*.md]

核心设计: 系统提示词指导 Agent 主动使用 write_file / edit_file 工具来持久化记忆,实现了与 OpenClaw 记忆系统相同的"Agent 驱动记忆持久化"模式。

启动流程

app_main()
  ├── init_nvs()
  ├── init_spiffs()              ← 挂载 /spiffs
  ├── message_bus_init()         ← 创建入站 + 出站队列
  ├── memory_store_init()
  ├── session_mgr_init()
  ├── wifi_manager_init()
  ├── http_proxy_init()          ← 加载代理配置
  ├── telegram_bot_init()        ← 加载 Bot Token
  ├── llm_proxy_init()           ← 加载 API Key + 模型
  ├── tool_registry_init()       ← 注册工具,构建 JSON Schema
  ├── agent_loop_init()
  ├── serial_cli_init()          ← 启动 REPL(无需 WiFi 即可使用)

  ├── wifi_manager_start()       ← 连接(优先 NVS → 回退编译时凭据)
  │   └── wait_connected(30s)

  └── [如果 WiFi 已连接]
      ├── telegram_bot_start()   ← 启动 tg_poll 任务 (Core 0)
      ├── agent_loop_start()     ← 启动 agent_loop 任务 (Core 1)
      ├── ws_server_start()      ← 启动 httpd (端口 18789)
      └── outbound_dispatch()    ← 启动分发任务 (Core 0)

如果 WiFi 连接失败,串口 CLI 仍可使用,用于诊断和重新配置。

网络:代理支持

MimicLaw 支持 HTTP CONNECT 代理隧道,适用于无法直接 HTTPS 访问的网络环境(在中国地区常见):

1. TCP 连接到代理服务器
2. 发送: CONNECT api.telegram.org:443 HTTP/1.1
3. 接收: HTTP/1.1 200 Connection established
4. 在隧道上进行 TLS 握手 (esp_tls)
5. 通过隧道发送/接收 HTTPS 数据

所有出站 HTTPS 调用均支持:Telegram API、Claude API、Brave Search API。

兼容 Clash Verge、V2Ray、Squid 等常见 HTTP 代理工具。