Metadata-Version: 2.4
Name: tea_agent
Version: 0.10.1
Summary: A self-evolving AI agent with dynamic toolkit management.
Author-email: sunkw <sunkwei@gmail.com>
License-Expression: MIT
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: openai>=1.0.0
Requires-Dist: httpx>=0.25.0
Requires-Dist: numpy>=1.24.0
Requires-Dist: PyYAML>=6.0
Requires-Dist: markdown>=3.4.0
Requires-Dist: tkinterweb>=3.10
Requires-Dist: pyautogui>=0.9.0
Requires-Dist: mss>=9.0.0
Requires-Dist: Pillow>=10.0.0
Requires-Dist: requests>=2.30.0
Requires-Dist: beautifulsoup4>=4.12.0
Requires-Dist: jieba>=0.42.0
Requires-Dist: mcp>=1.0.0
Requires-Dist: playwright>=1.40.0
Requires-Dist: jedi>=0.19.0
Requires-Dist: tree-sitter>=0.21.0
Requires-Dist: tree-sitter-python>=0.21.0
Requires-Dist: textual>=0.50.0
Provides-Extra: web
Requires-Dist: starlette>=0.37.0; extra == "web"
Requires-Dist: uvicorn>=0.27.0; extra == "web"

# Tea Agent v0.10.0

> ⚠️ **这是一个 AI 写 AI 的实验项目，自行承担责任。**

> 一个自进化 AI 编程助手 — 工具驱动、自我进化、多界面形态

[![Python](https://img.shields.io/badge/Python-%3E%3D3.10-blue)](https://python.org)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Version](https://img.shields.io/badge/version-0.10.0-blue)](https://pypi.org/project/tea-agent)

Tea Agent 是一款**会自我进化的 AI 编程助手**，拥有 70+ 可调用的工具，能自主编写代码、调试、搜索、文件操作、浏览器操控，并能在运行中动态加载新工具。支持 **GUI / CLI / Web / REST API / ACP Protocol / TUI** 六种界面形态。

---

## ✨ 核心特性

- 🧠 **自进化引擎** — Agent 可以修改自身代码、创建新工具、优化提示词，实现自主进化
- 🧰 **60+ 内置工具** — 涵盖文件操作、代码编辑、搜索、截图、OCR、包管理、Git 等
- ⏱️ **智能命令超时** — 后台监控进程 CPU/MEM/IO，活跃进程自动延长超时至 4x，空闲进程及时终止
- 🖥️ **六种界面** — GUI（Tkinter）、CLI、Web（Starlette + SSE）、REST API、ACP Protocol、TUI（Textual），按需选择
- 🌐 **Web V2 实时流式界面** — 单页应用(SPA)，内存搜索、记忆管理、任务调度、历史会话，全部功能浏览器内完成
- 📚 **项目知识库** — 自动构建符号索引、调用图，支持代码影响分析
- 🔄 **断点续聊** — 聊天记录持久化，重启后恢复上下文
- 📋 **Plan / TODO** — 内置任务规划与追踪系统
- 🌐 **MCP 协议** — 支持连接外部 MCP Server，扩展第三方工具
- 🎯 **模式切换** — design / develop / test / review / docs / devops 六阶段工作流
- 🤖 **多 Agent 协作** — 任务分解 + 并行执行，子 Agent 独立完成子任务
- 📊 **任务评估** — 自动评估任务质量，记录成功/失败经验
- 💎 **技能结晶** — Plan 执行后自动结晶 → 新对话按语义匹配注入 → 技能自进化闭环

---

## 📦 安装

```bash
# 从 PyPI 安装
pip install tea_agent

# 或从源码
git clone https://github.com/sunkwei/tea_agent
cd tea_agent
pip install -e .

# Web 界面依赖（可选）
pip install starlette uvicorn
```

Playwright 浏览器（可选，用于 JS 渲染页面抓取）：
```bash
playwright install chromium
```

---

## 🚀 快速开始

```bash
# Web V2 界面 — 单页应用，全功能浏览器体验（推荐）
python -m tea_agent.server

# GUI 桌面界面（Tkinter）
tea_agent

# ACP Protocol Server（VS Code 集成）
python -m tea_agent.protocol --port 9090

# CLI 对话
python -m tea_agent.cli

# TUI 界面
python -m tea_agent.tui
```

---

## 💻 界面形态

Tea Agent 提供 **六种界面形态**，覆盖从桌面到 Web、从命令行到 API 的全部使用场景。

---

### 1. GUI 桌面界面 (`tea_agent`)

基于 **Tkinter** 的原生桌面客户端，支持 Windows / Linux / macOS。

**启动方式：**
```bash
tea_agent                         # 入口命令
python -m tea_agent.gui           # 模块方式
```

**功能特性：**
- 🔄 实时流式对话，Markdown 渲染，工具调用可视化
- 📋 左侧会话列表，支持搜索、切换、新建、删除
- 🧠 长期记忆管理面板（查看/搜索/添加/删除）
- ⏱️ 定时任务管理（scheduler 增删改查）
- 📤 PDF 导出、聊天记录导出
- 🌙 系统托盘常驻，全局热键唤出
- 🎨 主题切换 + 字体缩放

---

### 2. CLI 命令行界面 (`python -m tea_agent.cli`)

轻量级终端对话界面，适合远程服务器、CI/CD 管道、脚本集成。

**启动方式：**
```bash
python -m tea_agent.cli           # 交互模式
python -m tea_agent.cli --oneshot "帮我写一个快速排序"  # 单次模式
```

**功能特性：**
- 📝 交互式 REPL 对话，支持多行输入（`\` 换行，EOF 提交）
- 🎨 语法高亮 + 工具调用实时显示
- 💾 聊天记录按 UUID 持久化
- 📋 `/history` 命令查看历史，`/clear` 清屏
- 🔧 支持指定配置文件：`python -m tea_agent.cli -c config_prod.yaml`
- 单次模式适合脚本调用：直接输出结果到 stdout

---

### 3. Web V2 界面 (`python -m tea_agent.server`)

新一代单页应用（SPA），纯前端 HTML/JS + 后端 Starlette API，所有功能在浏览器中完成。

> **注意**：`python -m tea_agent.server` 同时启动 REST API 和 Web V2 前端。
> 浏览器访问 `http://127.0.0.1:8081` 即可使用完整 Web 界面。

**启动方式：**
```bash
python -m tea_agent.server           # 默认端口 8081
tea-agent-api                        # PyPI 入口
python -m tea_agent.server --port 8099 --host 0.0.0.0
```

**界面特性：**

| 功能 | 说明 |
|------|------|
| 💬 **流式对话** | SSE 实时推送，逐 token 输出 |
| 📋 **会话管理** | 左侧列表面板，点击切换历史会话，自动加载消息 |
| 🧠 **记忆管理** | 弹窗面板，查看/搜索/添加/删除长期记忆 |
| ⏱️ **任务调度** | 定时任务 CRUD，cron / interval / daily 等 |
| 🔍 **全局搜索** | 搜索聊天记录、记忆、任务 |
| 📤 **PDF 导出** | 导出当前会话为 PDF |
| 🌙 **主题切换** | 深色/浅色主题 + 强调色定制 |
| 📎 **图片预览** | 消息中图片点击放大 |

**技术架构：**
```
前端: 纯 HTML5 + CSS3 + Vanilla JS（无框架依赖）
后端: Starlette + SSE 流式
API:  /v1/chat/completions（OpenAI 兼容）
      /v1/sessions（CRUD）
      /v1/memory（记忆管理）
      /v1/tasks（任务调度）
      /v1/search（全局搜索）
      /v1/export/pdf（PDF 导出）
```

---

### 4. REST API Server (`python -m tea_agent.server`)

OpenAI 兼容的 HTTP API 服务器，方便第三方应用集成。

**启动方式：**
```bash
tea-agent-api                        # PyPI 入口
python -m tea_agent.server           # 模块方式
python -m tea_agent.server --port 8081 --host 0.0.0.0
```

**API 路由：**

| 方法 | 路由 | 说明 |
|------|------|------|
| `GET` | `/health` | 健康检查 |
| `POST` | `/v1/chat/completions` | OpenAI 兼容聊天（支持 stream） |
| `GET` | `/v1/models` | 当前模型信息 |
| `GET` | `/v1/tools` | 所有可用工具列表 |
| `POST` | `/v1/tools/{name}/run` | 直接调用指定工具 |
| `GET/POST` | `/v1/sessions` | 列出/创建会话 |
| `GET/DELETE` | `/v1/sessions/{id}` | 获取/删除会话 |
| `GET` | `/v1/sessions/{id}/messages` | 获取会话消息 |
| `GET` | `/v1/config` | 获取配置 |
| `POST` | `/v1/config/switch` | 切换配置文件 |
| `GET/POST/DELETE` | `/v1/memory` | 记忆管理 |
| `GET/POST/DELETE` | `/v1/tasks` | 定时任务管理 |
| `GET` | `/v1/search` | 全局搜索 |
| `POST` | `/v1/export/pdf` | 导出 PDF |
| `GET` | `/docs` | OpenAPI 文档 |
| `GET` | `/openapi.json` | OpenAPI Schema |

**示例：**
```bash
# 流式聊天
curl -N -X POST http://127.0.0.1:8081/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"messages":[{"role":"user","content":"Hello"}],"stream":true}'

# 非流式聊天
curl -X POST http://127.0.0.1:8081/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"messages":[{"role":"user","content":"Hello"}],"stream":false}'

# 列出会话
curl http://127.0.0.1:8081/v1/sessions

# 搜索
curl "http://127.0.0.1:8081/v1/search?q=keyword"
```

---

### 5. ACP Protocol Server (`python -m tea_agent.protocol`)

Agent Communication Protocol 服务器，提供标准化的 Agent-to-Agent 通信，可用于 VS Code / Cursor 等 IDE 集成。

**启动方式：**
```bash
python -m tea_agent.protocol --port 9090
```

**API 路由：**

| 方法 | 路由 | 说明 |
|------|------|------|
| `GET` | `/health` | 健康检查 |
| `GET` | `/v1/agents` | 发现所有可用 Agent |
| `GET` | `/v1/agents/tea-agent` | Tea Agent 详情（含工具列表） |
| `POST` | `/v1/agents/tea-agent/chat` | 发送消息（支持 stream） |
| `GET/POST` | `/v1/sessions` | 列出/创建会话 |
| `GET/DELETE` | `/v1/sessions/{id}` | 获取/删除会话 |
| `GET` | `/v1/sessions/{id}/messages` | 获取会话消息 |

**特性：**
- 🧰 **工具发现** — 客户端可查询 Agent 的完整工具列表和 JSON Schema
- 📡 **SSE 流式** — 实时推送对话内容，支持逐 token 输出
- 🧵 **会话管理** — 多会话隔离，可获取历史消息
- 🔗 **IDE 集成** — 标准 ACP 协议，可对接任何 ACP 客户端

---

### 6. Web V1 旧版 (`tea-agent-web`)

基于 Starlette + SSE 的旧版 Web 界面，工具调用可视化卡片。

```bash
tea-agent-web
python -m tea_agent.web
```

> 推荐使用 Web V2（`python -m tea_agent.gui2`），功能更全面。

---

## 🧠 长期记忆系统

Tea Agent 的记忆系统模拟人类记忆的工作方式：**优先级分层**、**相关性检索**、**自然衰减**、**去重合并**。底层基于 SQLite 持久化 + embedding 语义向量，由 `MemoryManager` 统一管理。

---

### 1. 记忆存储结构

每条记忆包含以下核心字段：

| 字段 | 类型 | 说明 |
|------|------|------|
| `content` | TEXT | 记忆内容（精简摘要） |
| `priority` | INT (0-3) | 优先级：`0=CRITICAL` / `1=HIGH` / `2=MEDIUM` / `3=LOW` |
| `importance` | INT (1-5) | 重要度：5=关键，忽略会导致严重问题；1=琐碎 |
| `category` | TEXT | 分类：`instruction`(指令) / `preference`(偏好) / `fact`(事实) / `reminder`(提醒) / `general`(通用) |
| `tags` | TEXT | 逗号分隔标签，用于快速匹配 |
| `content_hash` | TEXT | SHA256 前 16 位，快速去重指纹 |
| `embedding` | BLOB | `numpy.float32` 向量，用于余弦相似度语义搜索 |
| `expires_at` | DATETIME | 过期时间，NULL=永不过期 |
| `pinned` | INT | 是否钉住（豁免年龄衰减） |
| `created_at` | DATETIME | 创建时间（用于年龄衰减计算） |

---

### 2. 选择算法

每次对话开始时，`MemoryManager.select_memories()` 从活跃记忆池中选出最相关的 **≤30 条** 注入上下文：

```
score = 相关性(关键词匹配) × 重要度(importance/5) × 时效因子 × 优先级因子

时效因子: 1天内=1.0, 7天=0.9, 30天=0.7, 90天=0.5, >90天=0.3
优先级因子: (4 - priority) / 4
```

**分层保底策略**（确保不会全选 CRITICAL）：

```
1. CRITICAL 优先入选（上限 10 条，FIFO 取最新）
2. 非 CRITICAL 按 score 排序
3. 分层保底配额：
   - HIGH   ≥ 3 条
   - MEDIUM ≥ 2 条
   - LOW    ≥ 1 条
4. 剩余名额自由竞争（score 最高的先选）
5. 入选记忆更新 last_accessed_at
```

---

### 3. 年龄衰减

模拟 Ebbinghaus 遗忘曲线。每次选择前自动执行 `degrade_by_age()`，**pinned=true 的记忆豁免**：

| 原始优先级 | 衰减条件 | 降级为 |
|-----------|---------|--------|
| CRITICAL | 创建 > 30 天 | HIGH |
| HIGH | 创建 > 60 天 | MEDIUM |
| MEDIUM | 创建 > 90 天 | LOW |

---

### 4. LLM 优先级精调

`MemoryManager.llm_adjust_priorities()` 使用便宜 LLM 评估近期对话主题，微调记忆优先级：

```
输入：近期对话主题摘要 (≤2000字符) + 当前活跃记忆列表 (≤100条, 每条≤80字符预览)
规则：
  - 只能 ±1 级调整（不允许跳级）
  - 每次最多调整 3 条
  - 升级时重置 created_at（重新计时衰减）
  - 仅输出 JSON 数组，无额外文本
```

---

### 5. 记忆提取

对话结束后，`MemoryManager` 通过 LLM 从用户消息中自动提取记忆：

```
提取分类：
  instruction → 用户明确要求"记住"的规则   → priority=0 (CRITICAL)
  preference  → 用户表达的习惯/偏好          → priority=1 (HIGH)
  reminder    → 有时效性的提醒（含 expires_at）→ priority=1 (HIGH)
  fact        → 技术事实/架构决策             → priority=2 (MEDIUM)
  general     → 其他参考信息                 → priority=3 (LOW)

容错解析：
  1. 直接 JSON.parse
  2. 提取 markdown ```json 代码块
  3. 提取 JSON 数组正则匹配
  4. 对象型 -> 从常见键名 (memories/items/results/data) 提取数组
```

---

### 6. 去重合并

提取结果写入前，`ingest_extracted()` 执行去重合并流水线：

```
每条新记忆：
  1. jieba 分词 → 关键词 Jaccard 相似度计算
  2. 同分类加权 10%
  3. 相似度 ≥ 0.3 → 合并更新已有记忆：
     - content: 保留更长的，或拼接
     - priority: 取较小值（更关键）
     - importance: 取较高值
     - tags: 并集去重
     - expires_at: 保留更早的过期时间
  4. < 0.3 → 新增记录
```

**批量去重** (`detect_duplicates` / `auto_dedup`)：通过 embedding 余弦相似度（阈值 0.92）扫描全部活跃记忆，发现近似重复对自动合并提权。

---

### 7. CRITICAL FIFO 淘汰

CRITICAL 记忆上限 15 条，超出时软删除最旧的（FIFO），防止指令记忆无限膨胀。

---

### 8. 反思归纳

`reflect_and_summarize()` 按类别聚类近期记忆，生成摘要并归档：

```
类别聚类 (instruction/preference/fact/reminder/general)
  → 每类 ≥ 2 条 → 关键词频率生成摘要
  → 摘要作为 CRITICAL/importance=5 存储
  → 原始记忆 importance -1（降级）
```

---

### 格式化注入

入选记忆按优先级格式化注入系统提示区：

```python
def _prefix_for(memory):
    if priority == CRITICAL:  return "!!! 必须遵循:"
    if category == "reminder": return "⏰ 提醒:"
    if category == "preference": return "💡 偏好:"
    if category == "fact":      return "📌 事实:"
    return "📎"
```

> Agent 可通过 `toolkit_memory` 工具手动管理记忆（增删查改）。见 [`docs/TOOLS.md`](docs/TOOLS.md)

---

## 📜 四级历史压缩 (L0 → L3 → L2 → L1)

Tea Agent 使用**四级分层**构建发送给 LLM 的上下文，在有限的 token 窗口内最大化信息密度。四大层级由 `session/_history_builder.py` 的 `build_api_messages()` 统一组装。

```
┌─────────────────────────────────────────────────┐
│  Level 0: 系统层                                 │
│  ├─ 系统提示词                                   │
│  ├─ 技能推荐注入 (SkillRegistry 语义匹配)          │
│  ├─ 未完成任务自动恢复 (TODO/Plan)                │
│  └─ 长期记忆注入 (MemoryManager 选取)             │
├─────────────────────────────────────────────────┤
│  Level 3: 摘要层 (LLM 生成)                      │
│  └─ L2 溢出时生成：保留关键结论，丢弃细节          │
├─────────────────────────────────────────────────┤
│  Level 2: 历史对列表 (SQLite 持久化)              │
│  └─ user + AI final msg 对，按相关性动态筛选注入   │
├─────────────────────────────────────────────────┤
│  Level 1: 最新对话 (当前 session)                 │
│  ├─ 压缩工具链 (中间工具调用→摘要，保留最终回复)   │
│  ├─ 旧工具输出 → 占位符                           │
│  └─ 工具输出截断 (首尾各半，按换行对齐)            │
└─────────────────────────────────────────────────┘
```

---

### Level 0: 系统层

```python
# build_api_messages() 中的 L0 组装顺序
result = []

# 1. 系统提示词
result.append({"role": "system", "content": system_prompt})

# 2. 未完成任务自动恢复 (toolkit_task_resume)
resume_info = toolkit_task_resume(action="check")
if resume_info["has_pending"]:
    result.append({"role": "user", "content": format_resume(resume_info)})

# 3. 长期记忆注入
if context._injected_memories_text:
    result.append({"role": "user", "content": context._injected_memories_text})
```

---

### Level 3 (L3) — 语义摘要

`SummaryStore` 管理两种 L3 摘要：

| 摘要类型 | 存储位置 | 生成时机 | 内容 |
|---------|----------|---------|------|
| **语义摘要** | `topics.semantic_summary` | L2 溢出时（50→20 裁剪） | 项目背景 / 已完成修改 / 关键决策 / 错误修复 / 架构约束 / 用户偏好 / 待办事项 |
| **工具链摘要** | `topics.tool_chain_summary` | 后台异步线程 | 最近一轮工具调用链回顾 |

**L2→L3 摘要生成** (`generate_l2_to_l3_summary`)：

```
触发条件: push_to_level2() 返回 should_summarize=True
          (即 L2 count ≥ 50 → 最老 30 条溢出)

摘要流程:
  1. 取溢出 30 条 L2 条目（含 user + thinking + assistant）
  2. 合并现有 L3 摘要（如有）
  3. 用 cheap model 生成新摘要（参数: temperature=0.3, max_tokens=4096）
  4. 存入 topics.semantic_summary
  5. L2 裁剪到最新 20 条

压缩比: 30 轮对话 (≈20K tokens) → ~500 tokens 摘要
```

**L3 注入格式**：

```
[系统记忆 — 以下为需要遵循的有效信息和规则]

##### 长期背景/偏好/关键结论
{semantic_summary}

---

##### 历史工具调用链回顾
{tool_chain_summary}
```

---

### Level 2 (L2) — 历史对列表

L2 是一个**固定大小的环形缓冲区**，存储在 SQLite `topics.level2_json` 列中，容量 50 条。

**条目结构**：

```json
{
  "user": "用户的原始消息",
  "assistant": "AI 的最终回复（不含工具调用中间过程）",
  "thinking": "工具调用轮的 assistant content + reasoning（从 rounds 中提取）",
  "files": ["涉及的文件路径（可选）"]
}
```

**写入流程** (`push_to_level2`)：

```python
def push_to_level2(topic_id, user_msg, ai_msg, files, rounds):
    # 从 rounds 中提取 thinking：所有带 tool_calls 的 assistant 消息
    thinking = extract_thinking_from_rounds(rounds)
    entry = {"user": user_msg, "assistant": ai_msg, "thinking": thinking, "files": files}
    level2.append(entry)

    overflow = []
    should_summarize = False
    if len(level2) >= 50:
        overflow = level2[:30]      # 最老 30 条 → 送给 L3 摘要
        level2 = level2[-20:]        # 保留最新 20 条
        should_summarize = True

    return len(level2), overflow, should_summarize
```

**相关性筛选** (`filter_level2_by_relevance`)：

```
对每条 L2 条目，用当前 user 消息的关键词做 Jaccard 相似度匹配：
  - 提取 user 消息的 2字中文 + 3字母英文关键词
  - 提取 L2 条目的 user + thinking + assistant 中的关键词
  - 计算 Jaccard 系数: |交集| / |并集|
  - 文件路径额外加权 (file_overlap ≥ 1 → min(score, 0.4 + count × 0.1))

筛选规则:
  ≥ 0.15   →  保留完整 user+assistant 对（注入为 [历史记录]）
  ≥ 0.05   →  仅保留摘要片段（"User: xxx... → Assistant: yyy..."）
  < 0.05   →  不注入（节省 token）
 全部<0.05 →  保底注入最高分的一条（完整对）
```

---

### Level 1 (L1) — 最新对话

L1 是**当前 session 的原始消息**（`context.messages`），经多层压缩后传入 API。

#### 第一道防线：实时工具输出截断

每个工具调用返回时立即截断，防止单个输出超大：

```python
max_tool_output = 128 * 1024  # 128KB
if len(result_bytes) > max_tool_output:
    # 首尾各保留一半，按换行边界对齐
    head = result_bytes[:max_tool_output // 2]  # 64KB
    tail = result_bytes[-max_tool_output // 2:] # 64KB
    result_str = f"{head.decode()}\n\n... [工具输出截断] ...\n\n{tail.decode()}"
```

#### 第二道防线：旧工具输出占位符化

`_find_prune_cutoff()` 找到最近 3 个 user 消息的分界线：

```
3 轮外的 tool 消息 → "[工具结果已省略: N 字符]"
3 轮内的 tool 消息 → 完整保留
```

#### 第三道防线：渐进式 token 裁剪

当 `max_context_tokens > 0` 时，触发 `_progressive_trim()` 5 级裁剪：

| 策略 | 操作 | 说明 |
|------|------|------|
| 1 | 删除 `[历史记录]` L2 条目 | 最旧的先删 |
| 2 | 替换旧工具输出为占位符 | `[工具结果已省略: N 字符]` |
| 3 | 清空 reasoning_content | 释放 thinking token |
| 4 | 截断长文本 | 限制 4096 字符 |
| 5 | 删除 L1 旧轮次 | 保留最近 5 轮 user 消息 |
| 兜底 | 截断最后一条消息 | 仅保留前 1/3 |

---

### 组装流程总览

```
build_api_messages(context, system_prompt) 完整流程:

1. Level 0: 系统提示词 + TODO 恢复 + 记忆注入
2. Level 3: 语义摘要 + 工具链摘要 (注入后加 assistant "好的，已了解...")
3. Level 2: 相关性筛选 → [历史记录] user + assistant 对
4. Level 1: 截断边界计算 → tool 占位符 → 消息遍历:
   - tool_calls 完整性检查
   - 多模态格式转换
   - reasoning_content 补齐
5. 渐进式裁剪: estimate_messages_tokens() > 80% budget → _progressive_trim()
6. JSON 完整性校验 + 孤立 tool 消息移除
```

### Token 估算

使用启发式算法快速估算 token 数（无需 tiktoken）：
- 英文：约 4 字符 = 1 token
- 中文：约 1.5 字 = 1 token
- 图片：固定 ~85 tokens
- 消息结构开销：每条 +4 tokens

### 异步摘要

每轮对话结束后，`do_async_summaries()` 在后台线程执行：
1. **标题摘要** (`auto_summary`): 用 cheap model 为 topic 生成一句话标题
2. **L2→L3 摘要** (`l2_to_l3_summary`): 仅在 L2 溢出时触发

便宜模型产生的 token 消耗通过 `agent._pending_cheap_tokens` 合并到下一轮 GUI 显示。

---

## 🔄 自进化引擎

Tea Agent 的自进化体系由**五个层次**构成：工具热插拔（基础）→ 安全自修改 → 提示词进化 → 经验固化 → 后台进化线程。

---

### 1. 工具热插拔：`toolkit_save` / `toolkit_reload`

Agent 可以在运行时创建新工具、修改现有工具，并**立即生效**，无需重启。

```
Agent 发现需要新能力
  │
  ├─ 1. 编写 Python 函数代码
  ├─ 2. 定义 OpenAI function schema (参数/描述)
  │
  ├─ 3. toolkit_save(name, meta, pycode)
  │     ├─ 存储到 tea_agent/toolkit/{name}.py
  │     ├─ 自动版本管理 (v1.0.0 → v1.1.0 → ...)
  │     ├─ 保存历史版本到 .versions/ 目录
  │     └─ 自动生成 skills/{name}/SKILL.md 文档
  │
  ├─ 4. toolkit_reload()
  │     ├─ 扫描 toolkit/ 目录所有 .py 文件
  │     ├─ 动态 importlib 加载模块
  │     ├─ 注册 meta 函数 → 生成 tool schema
  │     └─ 所有 toolkit_* 函数 → 全局可用
  │
  └─ 5. 新工具立即可用于后续对话
```

**版本管理**：

| 特性 | 说明 |
|------|------|
| **自动版本号** | 每次 save 自动递增 `v1.0.0 → v1.0.1 → v1.1.0` |
| **安全回滚** | `toolkit_rollback(name, version)` 可回退到任意历史版本 |
| **版本列表** | `toolkit_list_versions(name)` 查看所有历史版本 |
| **SKILL.md** | 保存后自动生成技能文档，参数表 + 示例代码 |

---

### 2. 五层安全自修改：`toolkit_self_evolve`

Agent 修改自身代码时，通过**五层安全机制**确保不会自毁：

```
┌──────────────────────────────────────────────┐
│  Layer 0: Git 快照                              │
│  git add + git commit "snapshot: pre-evolve"   │
│  仅在工作区干净时执行                            │
├──────────────────────────────────────────────┤
│  Layer 1: 时间戳 .bak 文件                       │
│  {file}.bak.{YYYYMMDD_HHMMSS}                 │
│  永不覆盖历史备份                                │
├──────────────────────────────────────────────┤
│  Layer 1.5: Python 语法严格检查                  │
│  换行符 / 缩进 / 括号匹配 / 冒号缺失 / 分号      │
│  失败 → 立即回滚                                 │
├──────────────────────────────────────────────┤
│  Layer 2: py_compile 编译验证                   │
│  失败 → 自动回滚 tmp_bak + git reset --hard    │
├──────────────────────────────────────────────┤
│  Layer 2.5: LSP 智能检查                        │
│  ├─ 影响分析 (ts_analyzer): 调用者/依赖/风险    │
│  ├─ ruff lint 对比: 新旧 lint 数量差异          │
│  ├─ 函数签名对比: 参数是否变更                   │
│  └─ jedi 语义诊断: 未定义/未使用的符号           │
│  非阻塞：lint 新增 > 0 或签名变更仅警告          │
├──────────────────────────────────────────────┤
│  Layer 3: pytest 测试验证                       │
│  失败（passed < total）→ git reset --hard 回滚  │
└──────────────────────────────────────────────┘
```

回滚链：Layer 1.5 失败 → 恢复 tmp_bak；Layer 2 失败 → 恢复 git；Layer 3 失败 → git reset --hard。

---

### 3. 提示词进化：`toolkit_prompt_evolve`

Agent 可以**自我优化系统提示词**，由 `SystemPromptManager` 管理多版本：

```
版本管理流程:
  配置表 system_prompts (is_active, version, content, created_at)

进化操作:
  action='list'     → 查看所有版本历史
  action='current'  → 查看当前活跃版本
  action='evolve'   → 基于反思建议 + 长期记忆 → LLM 生成新版本 → 设为活跃
  action='rollback' → 回滚到指定版本（旧版设为活跃）
  action='set'      → 手动设置新版本

进化输入:
  - 当前提示词 (≤500字要求)
  - 最近的反思建议 (ReflectionManager.last_prompt_suggestion)
  - 相关长期记忆 (MemoryManager 选取)
```

---

### 4. 经验固化：`toolkit_experience_solidify`

任务完成后自动复盘，转化为可复用模式：

```
action='auto':
  analyze → 分析任务执行过程
  ├─ 成功 → solidify → 固化到技能库 (toolkit_dynamic_skill)
  └─ 失败 → lesson   → 记录到经验库 (toolkit_evolution_exp)

分类标签:
  dependency / architecture / ui / performance / testing / deployment
```

**动态技能系统** (`toolkit_dynamic_skill`)：

```
record     → 记录成功的 agent 组合模式（task + agents[]）
recommend  → 根据任务推荐 agent 组合
search     → 搜索相似技能模式
list       → 列出所有技能模式
```

---

### 5. 后台进化线程：`toolkit_self_evolve_thread`

每小时自动运行一轮三合一巡检：

```
1. 工具使用率分析 → 优化建议
   - 统计各工具调用次数
   - 识别低使用率工具（建议删除或合并）
   - 识别高频组合（建议合并为复合工具）

2. docs/TOOLS.md 同步
   - 扫描 toolkit/ 目录
   - 根据 meta 信息生成工具文档
   - 按类别分组 + 参数表格

3. 技能模式整理
   - 清理过时技能
   - 合并相似模式
   - 更新模式评分
```

---

### 自进化能力全景

| 能力 | 工具 | 安全层级 | 说明 |
|------|------|---------|------|
| 创建新工具 | `toolkit_save` + `toolkit_reload` | 版本回滚 | 热插拔，无需重启 |
| 修改源文件 | `toolkit_self_evolve` | 5层安全 | Git↔Bak↔编译↔LSP↔测试 |
| 优化提示词 | `toolkit_prompt_evolve` | 版本回滚 | 基于反思+记忆 |
| 固化经验 | `toolkit_experience_solidify` | 分类标签 | 成功→技能，失败→教训 |
| 后台进化 | `toolkit_self_evolve_thread` | 每小时 | 工具分析+文档同步+技能整理 |
| 代码智能 | `toolkit_lsp` | 只读 | diagnose/completion/definition/references |

---

## 🧰 工具概览（70+）

| 类别 | 工具 |
|------|------|
| 📁 文件操作 | `toolkit_file`, `toolkit_save_file`, `toolkit_explr` |
| ✏️ 代码编辑 | `toolkit_edit`, `toolkit_diff_edit`, `toolkit_diff`, `toolkit_self_evolve`, `toolkit_clean_comments`, `toolkit_format_code` |
| 🔍 搜索 | `toolkit_search`, `toolkit_lsp`, `toolkit_query_chat_history` |
| 📸 截图/OCR | `toolkit_screenshot`, `toolkit_ocr`, `toolkit_screen_read` |
| 🖱️ 操控 | `toolkit_input`, `toolkit_browser_tab`, `toolkit_js_fetch` |
| 📦 包管理 | `toolkit_pkg`, `toolkit_build`, `toolkit_read_pyproject` |
| 🧪 测试 | `toolkit_run_tests`, `toolkit_test_gui` |
| 🗓️ 工具 | `toolkit_lunar`, `toolkit_weather_my`, `toolkit_gettime`, `toolkit_date_diff` |
| 🔧 系统 | `toolkit_exec`, `toolkit_config`, `toolkit_os_info`, `toolkit_sudo_gui` |
| 🧠 记忆/知识 | `toolkit_memory`, `toolkit_kb`, `toolkit_reflection`, `toolkit_proactive` |
| 🤖 多 Agent | `toolkit_parallel_subtasks`, `toolkit_dynamic_skill`, `toolkit_experience_solidify` |
| 📋 计划/任务 | `toolkit_plan`, `toolkit_todo`, `toolkit_scheduler`, `toolkit_task_resume` |
| 🔌 MCP 集成 | `toolkit_mcp` |
| 🌐 Web/GUI | `toolkit_browser_tab`, `toolkit_dump_topic`, `toolkit_export_last_pdf`, `toolkit_notify` |
| 📤 导出 | `toolkit_dump_topic`, `toolkit_export_last_pdf` |
| 🧬 自进化 | `toolkit_self_evolve`, `toolkit_self_evolve_thread`, `toolkit_prompt_evolve`, `toolkit_evolution_exp` |
| 🛠️ 其他 | `toolkit_question`, `toolkit_stream_save`, `toolkit_set_topic_title`, `toolkit_self_report`, `toolkit_comment`, `toolkit_toggle_reasoning`, `toolkit_get_config_path`, `toolkit_get_models`, `toolkit_list_provider_models`, `toolkit_ip_location_my`, `toolkit_custom_commands`, `toolkit_scheduler_storage`, `toolkit_mode` |

> 完整工具列表见 [`docs/TOOLS.md`](docs/TOOLS.md)（每小时自动更新）

---

## 🤖 多 Agent 协作

```python
from tea_agent.multi_agent import Dispatcher, LiteAgent

# 一步到位：分解 + 执行
dispatcher = Dispatcher()
result = dispatcher.dispatch("重构项目添加类型注解")
print(result["summary"])

# 可视化执行计划（不执行）
print(dispatcher.visualize("为 gui.py 添加类型注解"))

# 单独使用 LiteAgent
agent = LiteAgent()
result = agent.execute_sync("读取 README.md 并总结")
```

### 架构

```
Dispatcher.dispatch(goal)
  │
  ├─ _identify_pattern()     → 识别任务模式
  ├─ _generate_tasks()       → 生成 SubTask 列表
  ├─ _topological_sort()     → 拓扑排序（分层）
  │
  ├─ _execute_layers()       → 逐层执行
  │   ├─ 第 1 层: [task_1] ─── LiteAgent.execute_sync()
  │   │              ↓ 结果写入 accumulated_context
  │   ├─ 第 2 层: [task_2] ─── LiteAgent.execute_sync()  ← 带前置上下文
  │   │              ↓
  │   └─ ...
  │
  └─ _merge_results()        → 整合结果
```

---

## 🏗️ 项目结构

```
tea_agent/
├── gui.py                 # GUI 桌面入口（Tkinter）
├── gui2/                  # Web V2 界面（SPA + Bottle）
│   ├── server.py          # Bottle 静态服务器
│   └── frontend/          # HTML/CSS/JS 单页应用
│       └── index.html     # 全部界面逻辑（无框架依赖）
├── web/                   # Web V1 界面（Starlette + SSE）
│   ├── server.py          # SSE 流式服务器
│   └── static/            # 前端资源
├── server/                # REST API Server（OpenAI 兼容）
│   ├── server.py          # Starlette 路由 + SSE
│   └── __main__.py        # python -m tea_agent.server
├── protocol/              # ACP Protocol Server
│   ├── acp_server.py      # ACP 协议实现
│   └── __main__.py        # python -m tea_agent.protocol
├── cli.py                 # CLI 命令行
├── tui.py                 # TUI 界面（Textual）
├── agent.py               # Agent 核心引擎
├── config.py              # 配置管理
├── memory.py              # 长期记忆
├── prompt_manager.py      # 提示词版本管理
├── toolkit/               # 70+ 工具模块
├── session/               # 会话管理（历史压缩/Token 裁剪）
├── multi_agent/           # 多 Agent 协作
├── lsp/                   # LSP 代码智能
├── store/                 # 数据存储（10 子模块）
├── evaluation/            # 任务评估
├── skills/                # 技能结晶
├── sdk/                   # Python SDK（外部调用）
└── _gui/                  # GUI 组件（12 模块）
```

---

## 🔧 配置

配置文件 `~/.tea_agent/config.yaml`：

```yaml
main_model:
  api_key: "sk-xxx"
  api_url: "https://api.openai.com/v1"
  model_name: "gpt-4o"
  max_context_tokens: 0   # 0=不限制，>0 时启用渐进式 token 裁剪
cheap_model:
  api_key: ""
  api_url: ""
  model_name: ""
  max_context_tokens: 0   # 独立配置，适用于本地小模型
embedding:
  provider: openai
  model: text-embedding-3-small
```

### 上下文窗口控制

`max_context_tokens` 用于限制发送给 LLM 的最大上下文 token 数：

- **0** = 不限制，发送全部历史
- **64000**（默认）= 适合 64K~128K 窗口的主流模型
- **32000** = 适合 32K 窗口模型
- **128000** = 适合 GPT-4o / Claude 等大窗口模型

启用后，系统会自动预估 token 数，超出预算时按优先级渐进裁剪：
1. 删除旧的 `[历史记录]` 条目
2. 替换旧工具输出为占位符
3. 清空 thinking 内容
4. 截断长文本
5. 删除旧轮次（保留最近 5 轮）

> 主模型和便宜模型独立配置，互不影响。

Agent 可在运行时通过 `toolkit_config` 自主调优参数。

---

## 📄 许可证

MIT License © 2024-2026 sunkw
