# API 接口文档 ## 概述 PR-Helper 提供 RESTful JSON API 和 SSE 流式端点。所有 API 都需要认证(除登录/注册外)。 ## 认证 ### 会话认证 - 基于 Cookie 的会话 - Cookie 名称: `pr_session` - 有效期: 7 天 - HttpOnly: true ### 认证头 所有受保护的 API 需要有效的会话 Cookie。 ## 公开端点 ### 登录页面 ``` GET /login ``` 返回登录页面 HTML。 ### 注册页面 ``` GET /register ``` 返回注册页面 HTML。 ### 用户登录 ``` POST /api/auth/login Content-Type: application/json { "email": "user@example.com", "password": "password123" } ``` **响应**: ```json { "message": "登录成功" } ``` **错误**: ```json { "error": "邮箱或密码错误" } ``` ### 用户注册 ``` POST /api/auth/register Content-Type: application/json { "email": "user@example.com", "password": "password123" } ``` **响应**: ```json { "message": "注册成功" } ``` ### 用户登出 ``` POST /api/auth/logout ``` **响应**: ```json { "message": "已登出" } ``` ## 页面端点 ### 首页 ``` GET / ``` 返回首页 HTML(仓库列表)。 ### 仓库详情页 ``` GET /repo/:id ``` 返回仓库详情页 HTML(Git 图形、差异查看器等)。 ### 设置页 ``` GET /settings ``` 返回设置页面 HTML。 ## 仓库管理 API ### 获取仓库列表 ``` GET /api/repos ``` **响应**: ```json [ { "id": 1, "url": "https://github.com/user/repo.git", "local_path": "data/repos/user_repo.git_1234567890", "size_bytes": 1048576, "cloned_at": "2024-01-01T00:00:00Z", "last_used": "2024-01-01T12:00:00Z", "auth_type": "none" } ] ``` ### 克隆仓库 ``` POST /api/repos Content-Type: application/json { "url": "https://github.com/user/repo.git", "auth_type": "none", "credential": "" } ``` **认证类型**: - `none`: 无认证 - `https`: HTTPS 基本认证(credential = "username:password") **响应 (SSE 流)**: ``` event: progress data: {"step":"开始克隆","current":0,"total":0} event: progress data: {"step":"克隆完成","current":1,"total":1} event: done data: {"repo_id":1,"branches":["main","dev"],"tags":["v1.0"],"commit_num":100} ``` ### 删除仓库 ``` DELETE /api/repos/:id ``` **响应**: ```json { "message": "仓库已删除" } ``` ### 清理仓库缓存 ``` POST /api/repos/:id/cleanup ``` 删除并重新克隆仓库。 **响应 (SSE 流)**: ``` event: progress data: {"step":"清理完成"} event: progress data: {"step":"开始克隆"} event: done data: {"repo_id":1} ``` ### 拉取更新 ``` POST /api/repos/:id/pull ``` **响应 (SSE 流)**: ``` event: progress data: {"step":"拉取完成"} event: done data: {"commit_num":105,"branches":["main","dev"]} ``` ### 获取 Git 图形 ``` GET /api/repos/:id/graph ``` **响应**: ```json { "commits": [ { "hash": "abc123...", "short_hash": "abc1234", "message": "feat: add new feature", "author": "John Doe", "email": "john@example.com", "timestamp": "2024-01-01T12:00:00Z", "parent_ids": ["def456..."] } ], "refs": [ { "name": "main", "hash": "abc123...", "is_head": true, "is_tag": false }, { "name": "v1.0", "hash": "abc123...", "is_head": false, "is_tag": true } ], "edges": [ { "source": "abc123...", "target": "def456..." } ] } ``` ### 获取引用列表 ``` GET /api/repos/:id/refs ``` **响应**: ```json [ { "name": "main", "hash": "abc123...", "is_head": true, "is_tag": false }, { "name": "v1.0", "hash": "abc123...", "is_head": false, "is_tag": true } ] ``` ### 获取提交列表 ``` GET /api/repos/:id/commits?ref=main&limit=50 ``` **参数**: | 参数 | 类型 | 必需 | 说明 | |------|------|------|------| | ref | string | 否 | 分支/标签名(默认 HEAD) | | limit | int | 否 | 最大提交数(默认 50) | **响应**: ```json [ { "hash": "abc123...", "short_hash": "abc1234", "message": "feat: add new feature", "author": "John Doe", "email": "john@example.com", "timestamp": "2024-01-01T12:00:00Z", "parent_ids": ["def456..."] } ] ``` ### 获取差异 ``` GET /api/repos/:id/diff?base=main&head=feature ``` **参数**: | 参数 | 类型 | 必需 | 说明 | |------|------|------|------| | base | string | 是 | 基准分支/标签/提交 | | head | string | 是 | 目标分支/标签/提交 | | per_file | bool | 否 | 是否按文件返回 | **响应 (统一差异)**: ```json { "diff": "diff --git a/main.go b/main.go\n..." } ``` **响应 (按文件)**: ```json [ { "filename": "main.go", "patch": "diff --git a/main.go b/main.go\n..." } ] ``` ## PR 生成 API ### 生成 PR 描述 ``` POST /api/repos/:id/generate Content-Type: application/json { "base": "main", "head": "feature" } ``` **响应 (SSE 流)**: ``` event: content data: {"content":"# 标题\n\n"} event: content data: {"content":"**类型**: feat\n\n"} event: content data: {"content":"## 概述\n..."} event: done data: {"content":""} ``` ## 代码审查 API ### 执行代码审查 ``` POST /api/repos/:id/review Content-Type: application/json { "base": "main", "head": "feature", "top_n": 20, "concurrency": 5 } ``` **参数**: | 参数 | 类型 | 必需 | 说明 | |------|------|------|------| | base | string | 是 | 基准分支 | | head | string | 是 | 目标分支 | | top_n | int | 否 | 审查文件数上限(默认 20) | | concurrency | int | 否 | 并发数(默认 5) | **响应 (SSE 流)**: ``` event: start data: {"total_files":30,"reviewed_files":20,"top_n":20} event: file_start data: {"file":"main.go","index":1,"total":20} event: content data: {"content":"..."} event: suggestion data: {"file":"main.go","severity":"warning","content":"..."} event: file_end data: {"file":"main.go"} event: summary data: {"score":7,"overall":"...","findings":"...","recommendations":"..."} event: analysis_saved data: {"analysis_id":1} event: done data: {"content":""} ``` ### 获取审查历史 ``` GET /api/repos/:id/review/analyses ``` **响应**: ```json [ { "id": 1, "base_ref": "main", "head_ref": "feature", "created_at": "2024-01-01T12:00:00Z" } ] ``` ### 获取单个审查结果 ``` GET /api/repos/:id/review/analyses/:aid ``` **响应**: ```json { "id": 1, "base_ref": "main", "head_ref": "feature", "created_at": "2024-01-01T12:00:00Z", "result": { "file_reviews": [...], "summary": {...}, "top_n": 20 } } ``` ### 保存审查笔记 ``` POST /api/repos/:id/review/notes Content-Type: application/json { "analysis_id": 1, "scope": "file", "scope_key": "main.go", "content": "这个文件需要重构" } ``` **scope 类型**: | scope | scope_key | 说明 | |-------|-----------|------| | overall | (空) | 整体笔记 | | file | 文件名 | 文件级笔记 | | suggestion | 建议 ID | 建议级笔记 | **响应**: ```json { "id": 1, "analysis_id": 1, "scope": "file", "scope_key": "main.go", "content": "这个文件需要重构", "created_at": "2024-01-01T12:00:00Z", "updated_at": "2024-01-01T12:00:00Z" } ``` ### 获取审查笔记 ``` GET /api/repos/:id/review/notes?analysis_id=1&scope=file ``` **参数**: | 参数 | 类型 | 必需 | 说明 | |------|------|------|------| | analysis_id | int | 是 | 分析 ID | | scope | string | 否 | 过滤作用域 | **响应**: ```json [ { "id": 1, "analysis_id": 1, "scope": "file", "scope_key": "main.go", "content": "这个文件需要重构", "created_at": "2024-01-01T12:00:00Z", "updated_at": "2024-01-01T12:00:00Z" } ] ``` ## 设置 API ### 获取设置 ``` GET /api/settings ``` **响应**: ```json { "llm.endpoint": "https://api.deepseek.com", "llm.api_key": "sk-...", "llm.model": "deepseek-v4-pro", "review.top_n": "20", "review.concurrency": "5", "cache.max_age_days": "7", "cache.max_size_mb": "5000" } ``` ### 更新设置 ``` PUT /api/settings Content-Type: application/json { "llm.endpoint": "https://api.openai.com", "llm.api_key": "sk-...", "llm.model": "gpt-4" } ``` **响应**: ```json { "message": "设置已更新" } ``` ## 错误响应 ### 格式 ```json { "error": "错误信息" } ``` ### 常见状态码 | 状态码 | 说明 | |--------|------| | 200 | 成功 | | 400 | 请求参数错误 | | 401 | 未认证 | | 404 | 资源不存在 | | 500 | 服务器内部错误 | ## SSE 协议 ### 事件格式 ``` event: {event_name} data: {json_data} ``` - 每个事件以 `event:` 开头 - 数据以 `data:` 开头 - 事件之间用空行分隔 - 数据必须是有效的 JSON ### 客户端实现 ```javascript SSE.post(url, body, { eventName: (data) => { // 处理事件 }, error: (data) => { // 处理错误 }, done: () => { // 流结束 } }); ``` ### 中断请求 ```javascript const controller = SSE.post(url, body, handlers); // 中断 controller.abort(); ``` ## 限流 当前无速率限制。建议在反向代理层实现限流。 ## CORS 当前不支持跨域请求。仅限同源访问。