From 4e9697cde2a1a4b4ea19fa38dce8af127401f0ad Mon Sep 17 00:00:00 2001 From: weishen Date: Sun, 5 Apr 2026 07:55:05 +0800 Subject: [PATCH] Add agentbase project design document --- openclaw/xingshu/projects/agentbase-design.md | 293 ++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 openclaw/xingshu/projects/agentbase-design.md diff --git a/openclaw/xingshu/projects/agentbase-design.md b/openclaw/xingshu/projects/agentbase-design.md new file mode 100644 index 00000000..ea61d9ca --- /dev/null +++ b/openclaw/xingshu/projects/agentbase-design.md @@ -0,0 +1,293 @@ +# AgentBase 项目设计文档 + +> 设计日期:2026-04-05 +> 状态:已确认,等待实施 +> 项目位置:`~/Workspace/agentbase/` + +--- + +## 1. 项目概述 + +**项目名**:agentbase +**项目类型**:Django Web 应用 + 数据归档系统 +**核心目标**:遍历 OpenClaw Agent 的 session JSONL 文件,解析并保存到 MariaDB,通过 Django Admin 提供 Web 查询界面。 + +**使用场景**: +- 查找某个 Agent 在某天的所有对话记录 +- 查找某个 Agent 在处理任务时调用了哪些工具(特别是 `exec` 命令的具体内容) +- 查看 Agent 的思考过程(thinking block) +- 增量解析,只解析未处理过的文件 + +--- + +## 2. 数据库设计 + +### 2.1 服务器与 Agent 映射 + +| 服务器 | 标识 | Session 根目录 | +|--------|------|----------------| +| Mac Mini | `macmini` | `/Users/weishen/.openclaw/agents/` | +| Ubuntu1 | `ubuntu1` | `/home/shenwei/.openclaw/agents/` | +| Ubuntu2 | `ubuntu2` | `/home/shenwei/.openclaw/agents/` | + +**纳入的 Agent**:main、xingyao、xinghui、xingjiang、opencode、sisyphus + +### 2.2 Session 文件类型 + +所有 `.jsonl` 文件均需解析,包括: +- `*.jsonl` — 正常 session +- `*.jsonl.reset.*` — reset 快照 +- `*.jsonl.deleted.*` — 删除快照 +- `*-topic-*.jsonl` — 线程 session + +**session_type 判定**: +- 文件名含 `.reset.` → `reset` +- 文件名含 `.deleted.` → `deleted` +- 文件名含 `-topic-` → `topic` +- 默认 → `normal` + +**忽略文件**:`sessions.json`(索引文件,不解析) + +### 2.3 数据库 Schema + +#### 表:`parsed_files`(增量解析控制) + +| 字段 | 类型 | 说明 | +|------|------|------| +| `id` | INT AUTO_INCREMENT | 主键 | +| `server` | VARCHAR(32) | 服务器标识 | +| `agent_id` | VARCHAR(64) | Agent ID | +| `file_path` | VARCHAR(512) | 文件绝对路径 | +| `file_mtime` | BIGINT | 文件最后修改时间(Unix timestamp) | +| `file_size` | BIGINT | 文件大小(字节) | +| `status` | VARCHAR(16) | `pending` / `success` / `failed` | +| `parsed_at` | DATETIME | 本次解析时间 | +| `error_message` | TEXT | 失败时的错误信息(可空) | + +**UNIQUE 约束**:`UNIQUE(server, agent_id, file_path)` + +**增量解析逻辑**: +```sql +-- 插入前检查:同一文件 + 同一修改时间是否已解析 +WHERE NOT EXISTS ( + SELECT 1 FROM parsed_files + WHERE server=? AND agent_id=? AND file_path=? + AND file_mtime=? AND file_size=? AND status='success' +) +``` + +--- + +#### 表:`sessions`(Session 根记录) + +| 字段 | 类型 | 说明 | +|------|------|------| +| `id` | INT AUTO_INCREMENT | 主键 | +| `server` | VARCHAR(32) | 服务器标识 | +| `agent_id` | VARCHAR(64) | Agent ID | +| `session_uuid` | VARCHAR(64) | Session UUID(文件名去掉.jsonl等后缀) | +| `file_path` | VARCHAR(512) | 来源文件路径 | +| `session_type` | VARCHAR(32) | `normal` / `topic` / `reset` / `deleted` | +| `cwd` | VARCHAR(512) | Session 工作目录 | +| `started_at` | DATETIME(3) | Session 开始时间 | +| `first_message_at` | DATETIME(3) | 第一条 message 的时间 | +| `last_message_at` | DATETIME(3) | 最后一条 message 的时间 | +| `message_count` | INT | 该 session 的消息总数 | +| `created_at` | DATETIME | 记录创建时间 | + +**UNIQUE 约束**:`UNIQUE(session_uuid, server, agent_id)` + +--- + +#### 表:`messages`(消息内容) + +| 字段 | 类型 | 说明 | +|------|------|------| +| `id` | INT AUTO_INCREMENT | 主键 | +| `session_id` | INT | 外键 → `sessions.id` | +| `server` | VARCHAR(32) | 服务器标识 | +| `agent_id` | VARCHAR(64) | Agent ID | +| `session_uuid` | VARCHAR(64) | Session UUID(冗余存储,方便查询) | +| `message_uuid` | VARCHAR(64) | 消息 UUID | +| `parent_message_uuid` | VARCHAR(64) | 父消息 UUID(可空) | +| `role` | VARCHAR(32) | `user` / `assistant` / `toolResult` | +| `content_blocks` | JSON | **原文**:原始 content 数组 | +| `text_preview` | VARCHAR(512) | 纯文本摘要(前512字符) | +| `first_tool_call` | VARCHAR(128) | 首个 toolCall name | +| `tool_call_count` | INT | toolCall 总数 | +| `tool_calls_json` | JSON | **拆出**:所有 toolCall block | +| `thinking_text` | TEXT | **拆出**:首个 thinking block | +| `has_thinking` | TINYINT | 是否有 thinking(0/1) | +| `has_tool_calls` | TINYINT | 是否有 toolCall(0/1) | +| `is_error` | TINYINT | 整条 isError 标记 | +| `provider` | VARCHAR(64) | AI Provider(如 `minimax`) | +| `model` | VARCHAR(128) | 模型 ID(如 `MiniMax-M2.7`) | +| `api` | VARCHAR(64) | API 类型(如 `anthropic-messages`) | +| `stop_reason` | VARCHAR(64) | stopReason 字段值 | +| `input_tokens` | INT | 输入 token 数 | +| `output_tokens` | INT | 输出 token 数 | +| `cache_read_tokens` | BIGINT | Cache Read token 数 | +| `cache_write_tokens` | BIGINT | Cache Write token 数 | +| `total_tokens` | INT | 总 token 数 | +| `cost_usd` | DECIMAL(12,8) | 该消息美元成本 | +| `timestamp` | DATETIME(3) | 消息时间 | +| `created_at` | DATETIME | 记录创建时间 | + +**Indexes**: +- `idx_agent_timestamp` ON `(agent_id, timestamp)` +- `idx_first_tool_call` ON `(first_tool_call)` +- `idx_session_id` ON `(session_id)` +- `idx_role` ON `(role)` + +### 2.4 Content Block 结构 + +JSONL 中每条 `type:message` 的 `content` 数组,成员类型如下: + +| content block type | 关键提取字段 | +|---|---| +| `text` | `text`(纯文本) | +| `thinking` | `thinking`、`thinkingSignature` | +| `toolCall` | `id`、`name`、`arguments`(JSON 对象) | +| `toolResult` | `toolCallId`、`toolName`、`content`、`isError`、`details` | + +**`text_preview` 提取规则**(按优先级): +1. 找第一个 `type=="text"` 的 `text` 字段 +2. 找不到则找 `type=="thinking"` 的 `thinking` 字段 +3. 再找不到则找 `type=="toolResult"` 里第一个子 `type=="text"` 的内容 +4. 截取前512字符,strip HTML + +--- + +## 3. Django 项目结构 + +``` +~/Workspace/agentbase/ # Git 仓库根目录 +├── manage.py +├── agentbase/ # Django 项目 +│ ├── __init__.py +│ ├── settings.py # 数据库配置在此 +│ ├── urls.py +│ └── wsgi.py +├── messages/ # Django App +│ ├── __init__.py +│ ├── models.py # ParsedFile / Session / Message +│ ├── admin.py # Django Admin 配置 +│ ├── views.py # Web 查询视图 +│ ├── urls.py +│ ├── management/ +│ │ └── commands/ +│ │ └── parse_sessions.py # Django command +│ └── templates/ +│ └── messages/ +│ └── message_list.html +├── scripts/ +│ └── parse_and_import.py # OpenClaw cron 调用的入口脚本 +├── tests/ +├── requirements.txt +└── README.md +``` + +### 3.1 配置方式 + +数据库连接信息直接写在 `settings.py` 中(不使用 config.yaml)。 + +### 3.2 Django Admin 预期界面 + +**Messages(核心)**: +- 列表页支持按 `agent_id` + `timestamp` 范围 + `role` + `first_tool_call` 过滤 +- 详情页展示 `content_blocks` 原始 JSON、`thinking_text`、`tool_calls_json` +- 适合查找"某 Agent 某天所有对话和思考记录" + +**Sessions**:列出所有 session,按 server/agent_id 过滤。 + +**ParsedFiles**:记录已解析文件列表,支持按 server/agent_id/file_path 搜索。 + +--- + +## 4. 解析脚本设计 + +### 4.1 入口脚本 + +`scripts/parse_and_import.py` + +- OpenClaw cron 任务调用此脚本 +- 也可单独运行:`python parse_and_import.py --server macmini --agent xingyao` +- 内部加载 Django settings,调用 Django ORM 写入数据库 + +### 4.2 解析流程 + +1. **遍历服务器和 Agent**:macmini/ubuntu1/ubuntu2 → 各 Agent 目录 +2. **扫描 session 文件**:列出所有 `.jsonl` 文件,跳过 `sessions.json` +3. **增量检查**:查 `parsed_files` 表,文件 mtime+size 未变且 status=success → 跳过 +4. **解析 JSONL**:逐行读取,提取 `type:session` 和 `type:message` 记录 +5. **写入数据库**:先插入 `sessions`,再批量插入 `messages` +6. **更新 `parsed_files`**:status=success 或 status=failed + error_message + +### 4.3 OpenClaw Cron 任务 + +每日 00:05 执行(00:00 照片整理完成后错开): + +```bash +python ~/Workspace/agentbase/scripts/parse_and_import.py +``` + +- 在 Mac Mini 上执行 +- 通过 SSH 访问 ubuntu1/2 的 session 目录 +- 所有 Agent 的当日新 session 均被解析 + +--- + +## 5. 典型查询示例 + +### 5.1 查某 Agent 某天的所有消息 + +```sql +SELECT id, message_uuid, role, text_preview, has_thinking, first_tool_call, timestamp +FROM messages +WHERE agent_id = 'xingyao' + AND timestamp BETWEEN '2026-04-05 00:00:00' AND '2026-04-05 23:59:59' +ORDER BY timestamp; +``` + +### 5.2 查某 Agent 某天调用过的所有 exec 命令 + +```sql +SELECT m.id, m.timestamp, m.text_preview, m.session_uuid +FROM messages m +WHERE m.agent_id = 'xingyao' + AND m.timestamp BETWEEN '2026-04-05 00:00:00' AND '2026-04-05 23:59:59' + AND m.first_tool_call = 'exec'; +``` + +### 5.3 查包含 thinking 的消息 + +```sql +SELECT id, message_uuid, role, thinking_text, timestamp +FROM messages +WHERE agent_id = 'xingyao' + AND has_thinking = 1 + AND timestamp BETWEEN '2026-04-05 00:00:00' AND '2026-04-05 23:59:59'; +``` + +--- + +## 6. 待确认事项 + +- [ ] 数据库类型:MariaDB?SQLite(开发测试用)? +- [ ] 数据库名称 +- [ ] MariaDB 部署在哪里?(Mac Mini 本地?NAS?独立服务器?) + +--- + +## 7. 后续步骤 + +1. 用户确认以上设计 +2. 创建 Git 仓库 `~/Workspace/agentbase/` +3. 初始化 Django 项目 +4. 编写 `settings.py`(含数据库配置) +5. 编写 `messages/models.py`(三张表) +6. 编写 `messages/admin.py`(Admin 配置) +7. 编写 `scripts/parse_and_import.py`(解析入口) +8. 编写 `messages/management/commands/parse_sessions.py`(Django command) +9. 配置 Django Admin 模板(message_list.html) +10. 创建 OpenClaw cron 任务