Metadata-Version: 2.5
Name: gitai-agent
Version: 0.2.1
Summary: 用大模型自动生成 Git 提交信息并推送的 AI Agent
Project-URL: Homepage, https://github.com/your-org/gitai-agent
Project-URL: Documentation, https://github.com/your-org/gitai-agent#readme
Project-URL: Repository, https://github.com/your-org/gitai-agent
Project-URL: Issues, https://github.com/your-org/gitai-agent/issues
Author: GitAI Team
License: MIT
License-File: LICENSE
Keywords: agent,ai,automation,commit,git,llm
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Version Control :: Git
Requires-Python: >=3.9
Requires-Dist: langchain-core>=0.3.0
Requires-Dist: langchain-openai>=0.2.0
Requires-Dist: langgraph>=0.2.0
Requires-Dist: litellm>=1.40.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: tomli>=2.0.1; python_version < '3.11'
Provides-Extra: browser
Requires-Dist: playwright>=1.40; extra == 'browser'
Provides-Extra: dev
Requires-Dist: pytest-cov>=4; extra == 'dev'
Requires-Dist: pytest>=7; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Provides-Extra: docker
Requires-Dist: docker>=7.0.0; extra == 'docker'
Provides-Extra: docs
Requires-Dist: openpyxl>=3.1; extra == 'docs'
Requires-Dist: pypdf>=4.0; extra == 'docs'
Requires-Dist: python-docx>=1.1; extra == 'docs'
Requires-Dist: python-pptx>=0.6; extra == 'docs'
Provides-Extra: full
Requires-Dist: openpyxl>=3.1; extra == 'full'
Requires-Dist: pillow>=10.0; extra == 'full'
Requires-Dist: playwright>=1.40; extra == 'full'
Requires-Dist: pypdf>=4.0; extra == 'full'
Requires-Dist: pytesseract>=0.3; extra == 'full'
Requires-Dist: python-docx>=1.1; extra == 'full'
Requires-Dist: python-pptx>=0.6; extra == 'full'
Provides-Extra: ocr
Requires-Dist: pillow>=10.0; extra == 'ocr'
Requires-Dist: pytesseract>=0.3; extra == 'ocr'
Description-Content-Type: text/markdown

# GitAI - AI 智能体驱动的代码开发助手

[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Tests: 297 passed](https://img.shields.io/badge/tests-297%20passed-brightgreen.svg)](https://github.com/)
[![Version: 0.2.0](https://img.shields.io/badge/version-0.2.0-orange.svg)](https://github.com/)

一个基于大语言模型的 **AI 智能体（Agent）**，能够理解自然语言任务，自动规划并执行代码开发、测试、打包等完整工作流。从简单的文件注释到复杂的项目构建，都能通过自然语言指令完成。

## ✨ 核心特性

### 🤖 单一自治主循环
- **默认只进一个自主 ReAct 主循环**：难不难、要不要拆解由模型自己判——简单问答直接回答，
  多步任务自主调用 `update_plan` 列出 / 推进 / 修订清单（规划是一个工具，不是一个分类器）
- **不再有复杂度/关键词路由**：不会按输入长度或关键词替你选路径，也不会在提示词里写死任务剧本
- **Supervisor / PlanGraph 两张图仍在代码里**，但只有库调用时显式传 `force_mode`
  （测试与高级用法）才会构建它们；CLI 参数与环境配置都不提供模式开关

### 🌍 多平台支持
支持 OpenAI、Claude、Gemini、Ollama、DeepSeek、通义千问、智谱等 **15+ 主流平台**，通过 LangChain 统一接口调用。

### 🛠️ 完整工具链
- **文件操作**：读写文件、列表目录、搜索代码
- **代码执行**：Python 脚本执行、Shell 命令执行
- **沙箱隔离**：Subprocess / Docker 双重沙箱，安全执行任意代码
- **Git 操作**：自动提交、推送、分支管理
- **网络请求**：HTTP/WebSocket 客户端
- **测试工具**：自动化测试执行与验证
- **浏览器自动化**：导航、快照、点击、填表、提取、截图、执行 JS、前端错误自检（基于 Playwright，需可选依赖）
- **文档读取**：读取 PDF / Word / Excel / PPT / 图片 / 文本 / HTML，并支持索引后语义检索
- **双索引代码/文档理解**：语义向量 + BM25 稀疏召回经 RRF 融合与两阶段过滤（`code_index` 工具可全量构建仓库索引并查看覆盖率）
- **交付物溯源守卫**：记录本次运行里真正取到内容的访问；没有来源却新建了表格文件时，写入当场告警、收尾前纠正、最终输出末尾声明（可用 `provenance_guard = false` 关闭）

### 🧠 高级能力
- **RAG 子系统**：文档分块 → 向量化 → 向量存储 → 相似度检索，增强 LLM 上下文
- **Skills 子系统**：可插拔技能系统（brainstorming、TDD、systematic-debugging 等）
- **MCP 客户端**：连接外部 MCP Server，暴露远程工具
- **循环检测与纠偏**：自动识别 LLM 死循环，智能引导正确工具调用
- **循环内上下文压缩**：长任务里把最旧的工具调用轨迹折叠成一段累积摘要（目标 / 已确认事实 / 已改动文件 / 已尝试且失败 / 待办），
  模型跑上百步仍能看到自己已经知道的结论，而不是重复试探；折叠以「调用+结果」为原子单元，不会出现残缺的工具调用序列
  （可用 `enable_loop_compression = false` 退回旧的按条数截断）
- **大文件处理策略**：>3KB 文件自动引导使用 Python 脚本批量处理，避免分段编辑
- **按角色换模型（默认关闭）**：一次任务里模型的活按四个角色划分——主循环 `primary`、制定计划 `planning`、
  反思与交付核验 `review`、高频辅助 `utility`（循环历史摘要 / 检索精排）。打开
  `enable_model_router` 后，后三个角色可以各配一个自己的模型名（这一条路由表里不内置任何模型名，取值全部来自配置；
  平台预置表里各家的 `default_model` 与上下文窗口表是另一回事，见「支持的平台」），
  主循环仍是你配的那一个；算 token 预算的地方也按这一路真会发出去的名字取窗口。路由只换模型名、不换端点，也**不会**在失败时
  自动降级到另一个模型。任务结束附一段真实用量：按（角色, 实际发出的模型名）列出调用次数、失败次数与端点上报的
  token 数——同一个角色用过两个名字就出两行，端点未上报就写“未上报”，不做估算，一次都没上报时不给 token 合计行
  （见 `QUICKSTART.md` 的分流示例）
  一个诚实的边界：**默认路径上只有 `primary` 必发请求**。`planning` / `review` 的调用点
  全在只有显式 `force_mode` 才构建的 PlanGraph / Supervisor 图里，默认主循环的「制定计划」是个
  不发独立模型请求的 `update_plan` 工具；`utility` 则是**条件性**的——检索精排要
  `rerank_with_llm = true`（默认关）、循环摘要要历史真被折叠过，两者都没发生时默认路径上只有 `primary` 一路
- **层级化委派（工具化，非编排剧本）**：模型可以把一块**只需要局部结论**的工作（大范围检索、读长文件比对、核验某个说法）
  交给 `delegate_task`，子 Agent 在一个**全新的上下文**里自己跑，回来只带一份报告：状态（给出结论 / 已中止（含原因）/
  未得出结论—步数用满 / 未见结论）、用了几步、调过哪些工具、查过哪些文件、写入过什么、结论原文。
  状态行只靠结构事实区分（`abort_reason` 字段、`final_output` 是否为空、步数 vs 预算），不去猜子 Agent 的文字；
  子 Agent 自称“已完成”也只会渲染成“给出结论”，报告末行固定提醒父层自行核验。
  这里没有「哪种任务用哪几个角色」的映射表，`goal` 文本就是子任务唯一的角色定义；派不派由模型判断。
  三条结构性约束：深度 1（子 Agent 的工具集里没有 `delegate_task`，不是靠提示词求它别用）、默认只读
  （写类与执行类工具都不交给它，要它改文件得显式传 `allow_write=True`——它走配置层那一张真值表，
  拿不准的值按只读执行并在报告里说一句；仍保留的检索/入库/截图类
  可能落盘，报告会在 `写入：` 行点名（只列带成功回执的文件，这一行不管 `.gitai/` 下
  工具自己的索引与浏览器 profile 缓存；写模式下那些**未按文件回执核对**的
  调用（`run_shell`/`execute_python`/`run_tests`）以「工具名×次数」点名，回显进报告的参数值会被
  折成一行）、串行执行。子 Agent 复用**同一个**主循环图，所以循环检测、
  循环内压缩、token 预算、来源守卫、模型路由原样继承，用量也进同一份台账（记在 `primary` 一路）。
  **并行 fan-out 与递归委派是明确的非目标**：前者要并发访问进程级台账与工具模块全局量（会打开竞态），
  后者的预算与可见性需要另算一套。`update_plan` 管的是“我自己要分几步”，委派管的是“这一步的原文不该进我的上下文”。
  委派**不放宽**任何沙箱与路径边界，子层写入进同一份来源台账
  可用 `enable_delegation = false` 关掉（工具不进列表，看不见才是真调用不到；系统提示词里委派那一节
  也会一并抽走，不宣传模型看不见的东西）

### ⚙️ 灵活配置
支持配置文件、环境变量、命令行参数三种配置方式，优先级清晰明确。

### 🔒 安全可靠
- 支持本地部署的 Ollama，代码不会上传到第三方服务
- 沙箱隔离执行，确保代码执行安全
- 编码容错处理（UTF-8 + errors="replace"），Windows 环境稳定运行

---

## 📦 安装

### 方式一：从源码安装（开发模式）

```bash
# 克隆项目
git clone <repository-url>
cd gitai

# 安装依赖（开发模式）
pip install -e .

# 直接运行
gitai --help
```

### 可选能力依赖（浏览器自动化 / 文档读取）

Agent 的浏览器与文档工具在依赖缺失时自动降级（仅返回安装提示，不影响其余功能）。需要完整能力时：

```bash
# 安装全部可选依赖（浏览器 + 文档解析 + OCR）
pip install -e ".[full]"

# 首次使用浏览器工具前，需下载 Chromium
# （也可在 Agent 会话里直接调用 browser_install 工具：它会真的执行下载，
#   已就绪则不重复下载；耗时可能数分钟、数百 MB，上限由 browser_install_timeout_s 控制）
playwright install chromium
```

也可按需只装某一组：`.[browser]`（Playwright）、`.[docs]`（PDF/Word/Excel/PPT 解析）、`.[ocr]`（图片文字识别）。

说明：
- **反爬墙不再伪装成成功**：打开页面后 Agent 会把观察分为三种结果——已打开 / 被验证页拦截 / 页面未加载出内容；
  拦截与空页面**不回显正文**，也不计入数据源，并在同一地址第 N 次被拦时直接告知“重复打开不会改变结果”。
  该判定只改返回文案，不改循环阈值、不改重试次数；可用 `browser_challenge_notice = false` 回到旧行为。
- **元素定位快速失败**：`browser_click` / `browser_fill` 的 target 必须是 `browser_snapshot` 返回的编号或合法 CSS 选择器，
  传裸文本会当场返回明确错误，而不是等 30 秒超时。
- **表格交付物必须有来源**：本次新建/更新的 `.csv/.tsv/.xls/.xlsx/.parquet` 若没有任何已成功的页面、响应或文件读取作支撑，
  写后结果会附带一行溯源提醒，收尾前会纠正一次，最终输出末尾会给出“数据源为 0”的声明；若只是模板，Agent 声明后即可正常交付。
- **OCR**（图片型 PDF/扫描件文字提取）需在 `.gitai.toml` 中显式开启 `doc_ocr_enabled = true`，并安装系统级 Tesseract。
- **复用本机浏览器登录态** 需显式开启 `browser_reuse_login = true`（会把本机 Chrome/Edge profile 的登录相关文件只读复制到隔离目录，不影响运行中的浏览器）。

### 方式二：从 PyPI 安装（发布后）

```bash
pip install gitai-agent
```

### 依赖要求

- Python 3.9 或更高版本
- Git（用于版本控制操作）

---

## 🚀 快速开始

### 1. 查看支持的平台

```bash
gitai --list-providers
```

### 2. 使用 Ollama 本地模型（推荐，无需 API Key）

```bash
# 确保已安装并启动 Ollama
# ollama pull qwen2.5-coder:7b
# ollama serve

# 使用本地模型生成提交信息
gitai -p ollama -m qwen2.5-coder:7b -y
```

### 3. 使用 OpenAI

```bash
# 设置 API Key
export OPENAI_API_KEY=sk-xxxx

# 生成并提交
gitai -p openai -m gpt-4o-mini -y
```

### 4. 使用 DeepSeek

```bash
# 设置 API Key
export DEEPSEEK_API_KEY=sk-xxxx

# 生成中文提交信息并推送
gitai -p deepseek -l zh -y --push
```

### 5. AI Agent 通用任务（新功能！）

```bash
# 给文件添加中文注释
gitai -p zhipu -a "给 springcloudalibaba.yaml 每行添加完整的中文注释信息" --debug

# 用 Rust 写一个并发压测工具
gitai -p zhipu -a "用rust写一个并发压测http或websocket客户端工具，完整功能，自动化测试，打包最终产品" --debug

# 简单文件修改
gitai -p zhipu -a "把 config.py 里的 timeout 默认值从 60 改成 120" --debug
```

---

## 📖 使用指南

### 核心工作流

整个 Agent 的执行流程如下：

1. **检测变更**：默认自动执行 `git add -A`，将工作区和暂存区的改动都纳入分析范围。如果只想提交已暂存内容，可以使用 `--only-staged` 参数。

2. **生成提交信息**：将变更的统计信息、diff 内容、最近历史提交一起发送给大模型，支持 Conventional Commits 和简单摘要两种风格，还能指定语言（如中文）。

3. **人工确认或直接提交**：默认会展示生成的提交信息并询问确认：
   - `y` - 确认提交
   - `e` - 编辑提交信息
   - `r` - 重新生成
   - `n` - 取消操作
   
   使用 `-y` 参数可跳过交互确认。

4. **提交并推送**：确认后执行 `git commit`，添加 `--push` 参数会自动推送到远程仓库。如果当前分支没有上游，会自动设置 `-u origin <branch>`。

### 常见使用场景

| 场景 | 命令 | 说明 |
|------|------|------|
| 分析并提交 | gitai | 分析全部改动并提交（首次交互确认，后续复用上次参数） |
| 强制交互确认 | gitai -i | 覆盖上次保存的参数，强制进入交互模式 |
| 跳过确认直接提交 | `gitai -y` | 自动生成并提交 |
| 提交并推送 | `gitai -y --push` | 提交后推送到 origin |
| 指定平台和模型 | `gitai -p openai -m gpt-4o -y` | 使用 OpenAI GPT-4o |
| 使用 Ollama 本地模型 | `gitai -p ollama -m qwen2.5-coder:7b -l zh -y` | 本地部署，无需 API Key |
| 只提交已暂存内容 | `gitai --only-staged` | 不自动执行 git add |
| 只生成不提交 | `gitai --dry-run` | 查看生成的提交信息 |
| 查看支持的平台 | `gitai --list-providers` | 列出所有支持的平台 |
| 生成中文提交信息 | `gitai -l zh` | 使用中文生成提交信息 |
| 额外排除文件 | `gitai --exclude "*.csv" --exclude "data/*"` | 排除特定文件 |
| 使用自定义端点 | `gitai -p custom --api-base http://host/v1 -m my-model` | 接入任意 OpenAI 兼容服务 |
| **AI Agent 任务** | `gitai -p zhipu -a "任务描述" --debug` | 自然语言指令，自动规划执行 |

### 💾 智能记忆功能

GitAI 会自动记住你上次使用的命令参数，下次直接运行 `gitai` 即可复用，无需重复输入。

**工作原理：**

1. 当你使用特定参数运行 `gitai` 时（如 `gitai -p zhipu -y --push`），这些参数会被自动保存
2. 下次直接运行 `gitai`（不带任何参数）时，工具会自动加载并使用上次保存的参数
3. 参数状态文件保存在 `~/.config/gitai/last_args.json`（Windows: `C:\Users\<用户名>\.config\gitai\last_args.json`）

**使用示例：**

```bash
# 第一次：使用特定参数运行
gitai -p zhipu -y --push

# 之后：直接运行 gitai，自动复用 -p zhipu -y --push 参数
gitai

# 如果想使用不同的参数，直接指定即可（会覆盖上次保存的参数）
gitai -p ollama -m qwen2.5-coder:7b -y

# 再次直接运行，会使用最新的参数
gitai
```

**注意事项：**

- 只有当你显式提供参数时，才会保存参数状态
- 运行 `gitai --help`、`gitai --list-providers` 等查询命令不会保存参数
- 如果想恢复默认行为，可以删除状态文件：`rm ~/.config/gitai/last_args.json`
- 如果上次保存了 `-y` 参数，但这次想进入交互模式，可以使用 `-i` 或 `--interactive` 强制进入交互模式：
  ```bash
  # 上次保存的是 -y --push，这次强制进入交互模式
  gitai -i --push
  ```

---

## ⚙️ 配置方式

GitAI 支持三种配置方式，优先级从高到低：

1. **命令行参数**（如 `--model`、`--api-base`）
2. **环境变量**（`GITAI_*` 前缀）
3. **配置文件**（`.gitai.toml` 或 `~/.config/gitai/config.toml`）
4. **内置默认值**

### 配置文件

在项目根目录创建 `.gitai.toml` 文件：

```toml
[gitai]
# 大模型平台配置
provider = "ollama"
model = "qwen2.5-coder:7b"
api_base = "http://localhost:11434"

# 生成参数
language = "zh"
style = "conventional"
temperature = 0.2
max_diff_chars = 40000
max_file_chars = 12000

# Git 行为
auto_stage = true
auto_push = false
push_remote = "origin"

# 额外的项目约定
extra_instructions = """
- 这是一个 Python 项目，遵循 PEP 8
- scope 优先使用模块名：cli / config / llm / git
"""

# 排除的文件模式
exclude_patterns = [
    "*.lock",
    "package-lock.json",
    "*.min.js",
    "dist/*",
    "node_modules/*",
]
```

### 环境变量

复制 `.env.example` 为 `.env` 并设置相应的 API Key：

```bash
# 设置 OpenAI API Key
export OPENAI_API_KEY=sk-xxxx

# 或者使用 DeepSeek
export DEEPSEEK_API_KEY=sk-xxxx

# 配置 GitAI
export GITAI_PROVIDER=ollama
export GITAI_MODEL=qwen2.5-coder:7b
export GITAI_LANGUAGE=zh
export GITAI_AUTO_PUSH=false

# 排障开关（默认均为 true）：关掉后回到无溯源守卫/无拦截判定的行为
export GITAI_PROVENANCE_GUARD=false
export GITAI_BROWSER_CHALLENGE_NOTICE=false

# 关掉循环内压缩（改为旧的“满 40 条就截”，不额外调用一次摘要 LLM）
export GITAI_ENABLE_LOOP_COMPRESSION=false

# 打开按角色换模型（默认 false；模型名仍需在 .gitai.toml 的 router_* 字段里配）
export GITAI_ENABLE_MODEL_ROUTER=true

# 关掉层级化委派（delegate_task 不进工具列表，系统提示词里的委派那一节也一起抽走）
export GITAI_ENABLE_DELEGATION=false
# 两个预算数字含义不同：per_task 是非正数就一次都不能派；max_steps 是非正数仍派一次、
# 但子 Agent 一步都跑不了（报告固定为“步数预算已用满（0/0 步）”）
export GITAI_DELEGATE_MAX_STEPS=8
export GITAI_DELEGATE_PER_TASK=2
```

### 查看生效的配置

```bash
gitai --print-config
```

---

## 🎯 提交信息风格

### Conventional Commits（默认）

严格遵循 [Conventional Commits](https://www.conventionalcommits.org/) 规范：

```
<type>(<scope>): <subject>

<body>

<footer>
```

- **type**: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
- **scope**: 可选，模块名称（如 api, cli, deps）
- **subject**: 祈使句，小写开头，不超过 72 字符
- **body**: 详细描述改动（可选）
- **footer**: 破坏性变更说明（可选）

### Simple 模式

简单摘要风格，适合小型项目或个人项目：

```
<summary>

<body>
```

- **summary**: 简洁的摘要，不超过 72 字符
- **body**: 改动细节与原因（可选）

---

## 🏗️ 系统架构

### 架构图

项目提供完整的 drawio 架构图（位于 `docs/` 目录），可用 draw.io 或 diagrams.net 打开查看：

| 图名 | 文件 | 说明 |
|------|------|------|
| **系统总览架构图** | `docs/architecture.drawio` | 展示所有子系统的关系和层次 |
| **Agent 核心流程图** | `docs/agent-core-flow.drawio` | 入口如何选图：默认单主循环，`force_mode` 才进 Supervisor / PlanGraph |
| **Plan-and-Execute 时序图** | `docs/plan-execute-sequence.drawio` | planner → parser → executor 完整链路 |
| **工具调用流程图** | `docs/tool-call-flow.drawio` | LLM → tool_calls → sandbox → result 完整循环 |
| **配置优先级图** | `docs/config-priority.drawio` | CLI > Env > Config File > Defaults 优先级 |
| **RAG 子系统架构图** | `docs/rag-architecture.drawio` | chunker → embedding → vector_store → indexer |
| **Skills 与 MCP 架构图** | `docs/skills-mcp-architecture.drawio` | 技能系统和 MCP 客户端架构 |

### 架构层次

```
┌─────────────────────────────────────────────────────────────┐
│                        用户层 (CLI)                          │
│                   gitai -p zhipu -a "..."                    │
└───────────────────────────┬─────────────────────────────────┘
                            │
┌───────────────────────────▼─────────────────────────────────┐
│                    Agent 核心层                              │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  默认入口：单个自主 ReAct 主循环（agent ↔ tools）      │   │
│  │  规划 = update_plan 工具，由模型自主决定要不要拆       │   │
│  └──────────────────────────────────────────────────────┘   │
│  ┌─────────────┐  ┌─────────────┐                           │
│  │ Supervisor  │  │  PlanGraph  │  ← 仅显式 force_mode 可达 │
│  │ (多专家编排) │  │ (计划链路)   │     无 CLI / 配置开关     │
│  └─────────────┘  └─────────────┘                           │
│                                                             │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  横切能力（主循环与子 Agent 共用同一份）：             │   │
│  │  循环检测与纠偏 · 循环内上下文压缩 · token 预算        │   │
│  │  按角色换模型与用量台账 · 交付物溯源守卫 · 层级化委派  │   │
│  │  双索引检索（向量 + BM25 经 RRF 融合）                 │   │
│  └──────────────────────────────────────────────────────┘   │
└───────────────────────────┬─────────────────────────────────┘
                            │
┌───────────────────────────▼─────────────────────────────────┐
│                    工具层 (Tools)                            │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐        │
│  │file_ops  │ │  shell   │ │code_exec │ │code_search│       │
│  └──────────┘ └──────────┘ └──────────┘ └──────────┘        │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐        │
│  │ testing  │ │git_tools │ │ network  │ │ project  │        │
│  └──────────┘ └──────────┘ └──────────┘ └──────────┘        │
└───────────────────────────┬─────────────────────────────────┘
                            │
┌───────────────────────────▼─────────────────────────────────┐
│                    沙箱层 (Sandbox)                          │
│  ┌──────────────────────┐  ┌──────────────────────────┐     │
│  │  SubprocessSandbox   │  │    DockerSandbox         │     │
│  │  subprocess.run()    │  │    docker run            │     │
│  │  encoding="utf-8"    │  │    容器隔离执行           │     │
│  │  errors="replace"    │  │                          │     │
│  └──────────────────────┘  └──────────────────────────┘     │
└─────────────────────────────────────────────────────────────┘
```

### 核心模块说明

| 模块 | 路径 | 说明 |
|------|------|------|
| **CLI 层** | `gitai/cli.py` | 命令行入口，参数解析，主流程控制 |
| **Agent 层** | `gitai/agent.py` | Agent 主流程，协调变更检测、生成、提交 |
| **Agent Core** | `gitai/agent_core/` | AI 智能体核心：Graph、PlanGraph、LLM 绑定、提示词 |
| **Graph** | `gitai/agent_core/graph.py` | LangGraph 工作流：默认构建单个自主主循环；Supervisor / PlanGraph 仅在显式 `force_mode` 时构建 |
| **PlanGraph** | `gitai/agent_core/plan_graph.py` | Plan-and-Execute 链路：Planner → Parser → Executor（仅显式 `force_mode` 可达） |
| **PlanParser** | `gitai/agent_core/plan_parser.py` | 容错解析器：支持 9 种 LLM 输出变体 |
| **LLM Binding** | `gitai/agent_core/llm_binding.py` | LangChain + OpenAI 多平台适配层 |
| **模型路由** | `gitai/agent_core/router.py` | 按角色换模型（取值来自配置）+ 真实用量台账与收尾报告 |
| **委派内核** | `gitai/agent_core/delegation.py` | `delegate_task` 的闸与报告：宿主注入、工具子集、子 Agent 复用主循环、全新上下文 |
| **Prompts** | `gitai/agent_core/prompts.py` | 系统提示词：大文件策略、幂等脚本、循环纠偏 |
| **RAG** | `gitai/agent_core/rag/` | 检索增强生成：分块、向量化、存储、索引 |
| **Skills** | `gitai/agent_core/skills/` | 可插拔技能系统：发现、加载、执行 |
| **MCP Client** | `gitai/agent_core/mcp_client.py` | MCP 客户端：连接外部 Server，暴露工具 |
| **Tools** | `gitai/tools/` | 工具层：文件、Shell、代码执行、搜索、测试等 |
| **Sandbox** | `gitai/sandbox/` | 沙箱层：Subprocess / Docker 隔离执行 |
| **Config** | `gitai/config.py` | 配置系统：CLI > Env > Config File > Defaults |

---

## 🔧 高级用法

### 自定义 OpenAI 兼容端点

任何提供 OpenAI 兼容 API 的服务都可以接入：

```bash
gitai -p custom --api-base http://your-host:8000/v1 -m your-model -y
```

### 编辑器集成

提交信息确认时可以选择编辑：

- 按 `e` 进入编辑模式
- 使用 `$EDITOR` 环境变量指定的编辑器
- 支持设置 `GITAI_EDITOR` 或 `GIT_EDITOR` 覆盖默认编辑器

### 跳过 Git Hooks

```bash
gitai -y --no-verify
```

### 查看帮助

```bash
gitai --help
```

---

## 🧪 开发

### 安装开发依赖

```bash
pip install -e ".[dev]"
```

### 运行测试

```bash
pytest
```

### 代码格式化

```bash
ruff format .
ruff check .
```

### 测试覆盖

当前项目拥有 **998 个通过用例 + 3 个按环境依赖跳过**（合计 1001，与 `--collect-only` 末行一致），覆盖：
- 入口选图（默认单主循环；Supervisor / PlanGraph 只能显式指定）
- 主循环行为（循环检测与纠偏、写后守卫、收尾闸门、中止原因）
- 循环内上下文压缩（折叠原子单元、累积摘要、关掉后逐字符退回旧行为）
- 双索引检索（分词、BM25、RRF 融合、两阶段过滤、精排、v2 持久化）
- 按角色换模型（角色声明、预算按真实发出去的名字取窗口、用量台账与收尾报告）
- 层级化委派（五道闸、深度 1、默认只读、报告行结构与诚实性）
- 交付物溯源（观察三态化、写后提醒、最终声明）
- PlanParser 容错解析（9 种 LLM 输出变体）
- 沙箱执行（Subprocess / Docker）
- 工具调用（文件操作、代码执行、搜索等）
- 配置系统（多优先级合并）
- RAG 子系统（分块、向量化、存储、索引）
- Skills 管理（发现、加载、执行）

> 上面那个数字是 v0.3.0 收口时的快照，会随用例增加过时；复核：`pytest --collect-only -q` 看末行。

---

## 📝 更新日志

### v0.3.0 (2026-10-28)

- 🧭 **架构收口：单一自治主循环 + 工具化计划**。默认入口不再有任何分类器替模型判断要不要规划；
  规划还原为 `update_plan` 工具。**v0.2.0 里列的「智能复杂度路由」到本版本已退役**：
  `assess_complexity()` 不在 `run_agent` 的调用链上，`run_agent` 也不给入口传 `force_mode`；
  函数留在仓库里当休眠参考（唯一的调用方是单测），`tests/test_architecture_honesty.py` 钉住它不许回到生产路径
- 🧹 **文档口径收口**：`planning` / `review` 两个角色的配置项、`agent_prompts.complexity` 这个键、
  以及两张架构图，都补上了「只在库调用显式传 `force_mode` 时才生效」的限定——默认路径碰不到它们
- 🔍 **双索引代码/文档检索**：语义向量 + BM25 稀疏召回经 RRF 融合，两阶段过滤在检索期吸收规模
- 🗜️ **循环内上下文压缩**：最旧的工具轨迹折叠成累积摘要，上百步仍能看到自己已知的结论
- 🎛️ **按角色换模型（默认关闭）**：四角色显式声明 + 真实用量台账，路由表里不内置模型名
- 🤝 **层级化委派（工具形态）**：`delegate_task` 把只需要局部结论的工作交给子 Agent，
  深度 1 / 默认只读 / 串行；报告只写内核核对过的内容，子 Agent 自称“已完成”也只渲染成“给出结论”
- 🧾 **交付物溯源守卫**：反爬墙与空页不再伪装成成功，无来源的表格当场告警、收尾前纠正、末尾声明
- 📝 **测试规模** 297 → 1001 条

### v0.2.0 (2026-10-14)

- 🎯 **Plan-and-Execute 完整链路**：Planner → Parser → Executor 全链路打通
- 🧠 **智能复杂度路由**：assess_complexity() 自动选择 SimpleAgent / Supervisor / PlanGraph
- 🛠️ **完整工具链**：文件操作、代码执行、Shell、搜索、测试、Git、网络等
- 📦 **沙箱隔离**：Subprocess + Docker 双重沙箱，UTF-8 编码容错
- 📚 **RAG 子系统**：文档分块 → 向量化 → 向量存储 → 索引管理
- 🔌 **Skills 系统**：可插拔技能，支持 brainstorming、TDD、debugging 等
- 🔗 **MCP 客户端**：连接外部 MCP Server，暴露远程工具
- 🔄 **循环检测与纠偏**：自动识别 LLM 死循环，智能引导正确工具
- 📄 **大文件处理策略**：>3KB 文件自动引导使用 Python 脚本批量处理
- 🐛 **Windows 编码修复**：subprocess encoding="utf-8" + errors="replace" 解决 GBK 崩溃
- 📊 **完整架构图文档**：7 张 drawio 图，覆盖所有子系统和流程

---

## 🤝 贡献

欢迎提交 Issue 和 Pull Request！

## 📄 许可证

本项目采用 MIT 许可证 - 详见 [LICENSE](LICENSE) 文件。

## 🙏 致谢

- [litellm](https://github.com/BerriAI/litellm) - 统一的大模型调用层
- [LangChain](https://github.com/langchain-ai/langchain) - LangGraph 工作流框架
- [Ollama](https://ollama.com/) - 本地大模型部署工具
- 所有贡献者和使用者

## 📞 联系方式

如有问题或建议，请提交 Issue 或联系项目维护者。