--- description: alwaysApply: true --- --- last_reviewed: 2026-10-19 --- # AGENTS — 项目操作指南 本文件为 Agent 提供高信号量的项目操作知识,避免重复探索。 ## 文档边界 * **禁止使用表情文字**输出任何内容。 * `docs/` 目录存放面向开源用户、外部贡献者的公开文档。 * `.agents/` 目录存放维护规范、实施方案、经验总结等内部资料。 * 每个文件夹下都有 `README.md` 说明该文件夹的作用和重要信息。 ## 开发命令(必须使用 uv) 项目使用 `uv` 管理依赖,所有包版本锁定在 `uv.lock` 中。 | 操作 | Makefile (跨平台) | tasks.py (Windows) | |------|-------------------|---------------------| | 安装依赖 + pre-commit | `make install` | `python tasks.py install` | | 代码检查(lint+format+typecheck+deptry) | `make check` | `python tasks.py check` | | 运行测试(含覆盖率报告) | `make test` | `python tasks.py test` | | 运行 CLI 全流程(遗留,即将删除) | `make run` | `python tasks.py run` | | 清理缓存和虚拟环境 | `make clean` | `python tasks.py clean` | **注意:** `tasks.py` 中的 `check` 命令使用 `&&` 连接,Windows PowerShell 不支持 `&&`,但 `tasks.py` 内部已处理为单行字符串。 ## 代码质量工具链(执行顺序) 1. **Ruff lint** — `uv run ruff check .` (select: E, F, W, I, N, UP, B; ignore: E501) 2. **Ruff format** — `uv run ruff format --check .` (line-length: 120) 3. **MyPy strict mode** — `uv run mypy src/main.py` (strict=true, warn_return_any, ignore_missing_imports) 4. **deptry** — `uv run deptry .` (检测未声明、未使用、过时依赖) ### pre-commit 钩子(仅 Ruff) `.pre-commit-config.yaml` 配置了两个 hook: - `ruff --fix` — lint 并自动修复 - `ruff-format` — 格式化 **注意:** MyPy 和 deptry **不在** pre-commit 中,需要手动运行 `make check`。 ## 项目架构(MCP 服务器模式) **唯一业务入口是 MCP 服务器**:`python -m src.mcp.server`(stdio),工具名前缀 `mcp__arb__`。 编排由宿主 Agent(DSH)完成,本项目只提供工具与确定性内核。 > 过渡期状态:`src/main.py`(CLI)与 `src/web`(Flask,已移除 Agent 端点,仅剩上传/表格编辑/下载/提交) > 仍在工作,但**已确定删除**,不要把它们的代码当参考实现,也不要往里加功能。`.invoice_cache` 键名约定两边共用,那部分可以信。 - `src/mcp/` — 工具与协议层(`server.py` 注册与启动,`tools/` 按职能分模块,`schemas.py` 抽取字段定义,`envelope.py` 统一返回信封) - `src/cases.py` — 会话目录 `cases//` 的唯一实现:材料、收件箱、产物与**阶段推导**(阶段由产物推导,不存在状态机文件) - `src/core/` — 确定性内核:`extraction/`(缓存读写、PDF 渲染与文本层)、`matching/`(金额匹配 + `runner.py` 从缓存匹配)、`validation/`(声明式规则校验) - `src/infra/` — 基础设施:`browser/`(Playwright 填报)、`documents/`(CSV/Word/Excel/PDF) - `src/upload/` — 上传收件器(**独立进程** `python -m src.upload.server`):手机扫码/PC 上传落 `cases//inbox/`,不含业务编排,绝不由 MCP 子进程拉起 已删除:`src/agent/`(手写状态机与 SSE 事件)。`required: true` 的字段(含值为空串的备注类字段) 必须存在于 info JSON 中——这是刻意约束;用 `mcp__arb__info_skeleton` 取骨架再填值,别凭记忆造结构。 宿主侧调 MCP 工具时**路径一律用正斜杠**(`D:/Code/...`),反斜杠会被 DSH 的参数绑定层拒收。 ### 数据流关键产物 | 文件 | 生成阶段 | 作用 | |------|---------|------| | `.invoice_cache/.json` | 宿主 Agent 抽取后 `mcp__arb__case_save_extraction` 落盘 | 单张发票/支付记录的结构化数据 | | `match_result.json` | `mcp__arb__match_payments` | 支付截图与发票的关联关系 | | `travel_info.json` / `normal_info.json` | 宿主 Agent 综合,`mcp__arb__save_info` 落盘 | 差旅/普通报销所需的全部结构化数据 | | `invoice_summary.csv` / `payment_records.csv` | `mcp__arb__match_payments` | 发票级与支付级汇总(出库单、申购单取数) | ### 缓存机制 MCP 会话:`cases//.invoice_cache/`(**新**) 遗留只读:`scripts/data/`(CLI)与 `src/web/uploads//`(Web),两者即将删除 缓存文件与源文件同名(如 `发票1.pdf` → `.invoice_cache/发票1.json`),后续步骤均从缓存读取。删除缓存后下次处理会重新提取。 ## 重要约束 * **Windows-only**:易耗品出库单填写依赖 Microsoft Word + COM (`pywin32`),仅 Windows 可用 * **浏览器自动化**:使用 Playwright,填报时会打开 Chromium,请勿手动干扰 * **敏感信息**:`scripts/config.json` 含登录凭据,勿提交到公开仓库 * **发票类型区分**:差旅发票(高铁票/酒店住宿)不生成易耗品出库单,走差旅报销流程;普通发票生成出库单 ## Web 服务(遗留,即将删除) ```bash uv run python src/web/app.py # 访问 http://localhost:5000 ``` Web 端浏览器填报以无头模式运行。会话产物存放在 `src/web/uploads//`,每次上传生成独立会话。 ## 测试 ```bash make test # pytest + coverage report (term-missing) ``` 测试目录:`tests/`,配置在 `pyproject.toml` 中 (`testpaths = ["tests"]`, `pythonpath = ["."]`)。