基于 TypeScript + NestJS 构建的 AI 代码评审服务。当前仓库已经调整为 pnpm monorepo:后端服务位于 backend/,Next.js 前端位于 frontend/。
- PR Agent 当前处于 beta 阶段。
- 当前唯一正式支持的接入方式是 GitHub App。
- 仓库里仍可能保留普通 GitHub Webhook 和 GitLab 的代码路径,但它们目前不属于受支持的部署范围。
核心评审
- PR 打开 / 更新 / 合并时自动 AI 代码评审
- 行内评论,支持 GitHub Suggested Changes 建议代码块
- Report 模式汇总评审,含风险等级评估
- 增量评审(仅评审上次评审后的新提交)
- 报告内 Mermaid 变更结构图(按目录/文件可视化)
- Diff 中疑似密钥泄露检测(轻量正则扫描)
- 自动标签(bugfix / feature / refactor / docs / security)
交互命令
/ai-review— 手动触发评审(comment 或 report 模式)/ask <问题>— 多轮代码问答/checks [问题]— CI 失败诊断分析/generate_tests [重点]— 自动生成测试代码/changelog [--apply]— 生成或提交 Changelog/describe [--apply]— 生成或更新 PR 描述/improve [重点]— 仅输出改进建议导向的评审/add_doc [重点](/add-doc)— 仅输出文档/注释改进建议/reflect [目标]— 生成需求澄清与验收标准问题/similar_issue [关键词](/similar-issue)— 检索同仓库相似 Issue/custom_prompt <提示词>— 使用自定义 AI 提示词分析 PR 变更/help_docs <问题>— 基于项目/docs目录内容进行文档问答/analyze— 列出所有变更代码组件并按风险评级/compliance [重点]— 合规与安全审查/improve_component <组件>— 针对指定组件的改进评审/generate_labels— 基于 diff 内容自动生成并应用 PR 标签/similar_code [关键词]— 检测 diff 中重复或相似的代码模式/auto_approve— 基于 AI 风险评估的条件自动 Approve(默认关闭)/scan_repo_discussions— 从最近已合并 PR 的评审讨论中提取最佳实践/feedback— 评审质量反馈,持续优化后续评审
流程守卫
.pr-agent.yml仓库级策略(提醒 / 强制模式)- Issue 与 PR 模板完整性检查
- GitHub Check 集成,可接 Branch Protection(
enforce模式) .github/.gitlab模板/流程文件识别(workflow/template/CODEOWNERS/CONTRIBUTING)并给出流程建议- Issue 创建/编辑时流程预检、PR 创建/编辑/同步时合并前预检(GitHub)
- 仓库缺少
.pr-agent.yml时,Issue 自动分诊(可行性/建议/相似 Issue/自动标签)
当前支持范围
- 仅支持 GitHub App
- 普通 GitHub Webhook — 当前 beta 不支持
- GitLab Webhook — 当前 beta 不支持
- GitHub Actions — 暂不支持
多模型 Provider
- OpenAI
- OpenAI 兼容(DeepSeek 等)
- Anthropic(Claude)
- Google Gemini
| 触发方式 | 评审模式 | 去重窗口 |
|---|---|---|
PR 打开(opened) |
comment / report(按配置) | 5 分钟 |
PR 更新(synchronize) |
comment / report | 5 分钟(按新 commit SHA) |
PR 编辑(edited) |
comment / report | 5 分钟 |
PR 合并(closed + merged) |
report | 24 小时(可配置) |
/ai-review 评论命令 |
comment / report | 5 分钟 |
/ai-review report |
report | 5 分钟 |
/ai-review comment |
comment | 5 分钟 |
Webhook Header x-ai-mode(仅 GitLab,当前 beta 不支持) |
report / comment | 5 分钟 |
| Issue 创建 / 编辑 | 流程预检(GitHub)+ 缺省策略自动分诊(无策略文件时) | 5 分钟 |
| PR 创建 / 编辑 / 同步 | 合并前预检(GitHub) | — |
- 竞争差距落地 backlog:
docs/roadmap/2026-02-19-competitive-gap-backlog.md - GitHub Issue 模板:
.github/ISSUE_TEMPLATE/bug_report.md、.github/ISSUE_TEMPLATE/feature_request.md - GitHub PR 模板:
.github/pull_request_template.md - GitLab Issue 模板:
.gitlab/issue_templates/Bug.md、.gitlab/issue_templates/Feature.md - GitLab MR 模板:
.gitlab/merge_request_templates/default.md
建议的 GitHub Flow 基线:
- 开启 Branch Protection,至少要求
PR Agent Policy与 CI 必过。 - 在仓库启用
.pr-agent.yml的mode: enforce(可先从核心仓库灰度)。 - 统一使用 Issue/PR 模板,避免需求与验证信息缺失。
graph LR
ROOT[pr-agent monorepo]
ROOT --> BE[backend/<br/>NestJS + Probot + tests]
ROOT --> FE[frontend/<br/>Next.js 官网 / 控制台]
ROOT --> OPS[Docker / Compose<br/>后端部署]
ROOT --> NP[Nixpacks<br/>前端部署]
ROOT --> DOCS[docs/<br/>路线图与流程资产]
graph TB
subgraph 平台入口
GH_APP[GitHub App<br/>Probot]
GH_WH[GitHub Webhook]
GL_WH[GitLab Webhook]
end
subgraph NestJS 应用
direction TB
CTRL[Controllers<br/>路由 & 校验]
SVC[Services<br/>签名验证 & 分发]
INT[集成层<br/>GitHub / GitLab 适配器]
RE[评审引擎<br/>AI Reviewer + Patch 解析]
RR[报告渲染器<br/>Markdown + 建议代码块]
end
subgraph 外部服务
AI[AI Providers<br/>OpenAI / Anthropic / Gemini]
GH_API[GitHub API]
GL_API[GitLab API]
NOTIFY[通知推送<br/>Slack / Discord / 企业微信]
end
GH_APP -->|Webhook 事件| CTRL
GH_WH -->|Webhook 事件| CTRL
GL_WH -->|Webhook 事件| CTRL
CTRL --> SVC
SVC --> INT
INT --> RE
RE -->|LLM 调用| AI
RE --> RR
RR -->|发布评论 / 报告| GH_API
RR -->|发布评论 / 报告| GL_API
INT -.->|可选| NOTIFY
sequenceDiagram
participant P as 平台 (GitHub/GitLab)
participant C as Controller
participant S as Service
participant D as 去重模块
participant I as 集成层
participant A as AI 评审引擎
participant R as 报告渲染器
P->>C: Webhook 事件
C->>S: 验证签名 & 解析请求体
S->>D: 去重检查(FNV 哈希,5 分钟窗口)
alt 重复请求
D-->>S: 跳过(已处理过)
else 新请求
D-->>S: 放行
S->>I: 分发到平台处理器
I->>I: 获取 diff、文件内容、策略配置
I->>A: 发送上下文 + diff 给 AI 模型
A-->>I: 结构化评审结果(Zod 校验)
I->>R: 格式化报告 / 行内评论
R->>P: 通过 API 发布评审
I-->>P: 可选:通知 Webhook
end
graph LR
subgraph NestJS 模块
APP[AppModule]
GH[GithubModule]
GL[GitlabModule]
GHA[GithubAppModule]
end
subgraph 集成层
GHR[github-review]
GHW[github-webhook]
GHP[github-policy]
GHC[github-content]
GLR[gitlab-review]
NTF[notification]
end
subgraph 核心层
REV[ai-reviewer]
PAT[patch parser]
RPT[report-renderer]
POL[review-policy]
DDP[dedupe]
HTTP[http client]
STA[runtime-state]
SEC[secret-patterns]
CACHE[cache]
end
APP --> GH
APP --> GL
APP --> GHA
GH --> GHR
GH --> GHW
GHA --> GHR
GHR --> GHP
GHR --> GHC
GHR --> REV
GHR --> RPT
GHR --> NTF
GLR --> REV
GLR --> RPT
GLR --> NTF
GL --> GLR
REV --> PAT
REV --> POL
REV --> HTTP
GHR --> DDP
GLR --> DDP
DDP --> STA
GHR --> SEC
GLR --> SEC
GHP --> CACHE
下图追踪每一条请求路径——从 Webhook 入口经过事件路由、命令解析、通用评审引擎,到最终输出与运维。
flowchart LR
subgraph E["入口端点 (NestJS + Probot)"]
E1["/api/github/webhooks<br/>GithubAppBootstrapService"]
E2["/github/trigger<br/>GithubWebhookController"]
E3["/gitlab/trigger<br/>GitlabWebhookController"]
E4["/github/replay/:eventId<br/>/gitlab/replay/:eventId"]
E5["/health /metrics /webhook/events"]
end
subgraph GHA["GitHub App 事件路由 (backend/src/app.ts)"]
A1["issues.opened, issues.edited<br/>runGitHubIssuePolicyCheck"]
A2["pull_request.opened, edited, synchronize<br/>runGitHubPullRequestPolicyCheck"]
A3["resolveGitHubPullRequestAutoReviewPolicy"]
A4["pull_request.closed (merged)<br/>resolveGitHubReviewBehaviorPolicy"]
A5["issue_comment.created (PR + Issue)<br/>handleGitHubIssueCommentCommand"]
A6["pull_request_review_thread<br/>recordGitHubFeedbackSignal"]
end
subgraph GHW["原生 GitHub Webhook (backend/src/integrations/github/github-webhook.ts)"]
B1["handlePlainGitHubWebhook"]
B2["verifyWebhookSignature + payload schema"]
B3["pull_request / issues / issue_comment / review_thread dispatch"]
B4["runGitHubPullRequestPolicyCheck + runGitHubIssuePolicyCheck"]
B5["handleGitHubIssueCommentCommand"]
end
subgraph GLW["GitLab Webhook (backend/src/integrations/gitlab/gitlab-review.ts)"]
C1["runGitLabWebhook"]
C2["verify token + payload schema"]
C3["handleGitLabMergeRequestWebhook"]
C4["handleGitLabNoteWebhook"]
C5["resolveGitLabReviewPolicy (.pr-agent.yml)"]
end
subgraph CMD["命令解析层"]
D1["parseReviewCommand"]
D2["parseAsk / parseMention / parseChecks / parseGenerateTests"]
D3["parseDescribe / parseChangelog"]
D4["parseImprove / parseAddDoc / parseReflect / parseSimilarIssue / parseFeedback"]
end
subgraph CORE["通用评审引擎"]
R1["runGitHubReview / runGitLabReview"]
R2["去重 + 限流 + 增量 head + 反馈信号"]
R3["收集上下文: diff/files/ci/policy"]
R4["analyzePullRequest / answerPullRequestQuestion"]
R5["patch 解析 + hunk 优先级 + 行映射"]
R6["密钥扫描 + 自动标签"]
end
subgraph OUT["输出与运维"]
O1["buildReportCommentMarkdown"]
O2["buildIssueCommentMarkdown"]
O3["createComment / notes / managed upsert"]
O4["publishNotification (可选)"]
O5["pr_agent_* 指标 + replay 存储"]
end
E1 --> A1
E1 --> A2 --> A3 --> R1
E1 --> A4 --> R1
E1 --> A5
E1 --> A6
E2 --> B1 --> B2 --> B3
B3 --> B4 --> R1
B3 --> B5
E3 --> C1 --> C2
C2 --> C3 --> C5 --> R1
C2 --> C4 --> C5
A5 --> D1
A5 --> D2
A5 --> D3
A5 --> D4
B5 --> D1
B5 --> D2
B5 --> D3
B5 --> D4
C4 --> D1
C4 --> D2
C4 --> D3
C4 --> D4
D1 --> R1
D2 --> R4
D3 --> R4
D4 --> R1
R1 --> R2 --> R3 --> R4 --> R5
R4 --> R6
R5 --> O1 --> O3
R5 --> O2 --> O3
R6 --> O3
O3 --> O4
E4 --> B1
E4 --> C1
E5 --> O5
E2 --> O5
E3 --> O5
O3 -. 反馈信号 .-> R2
| 层级 | 技术 |
|---|---|
| 运行时 | Node.js 22 (Alpine) |
| 语言 | TypeScript 5.7(ES2022,严格模式) |
| 框架 | NestJS 11 |
| HTTP 服务 | Express 4 |
| GitHub App | Probot 13 |
| AI 客户端 | OpenAI SDK 4(同时用于兼容 Provider) |
| 校验 | Zod 3 |
| 状态存储 | 内存 / JSON 文件 / SQLite(Node.js 内置 node:sqlite) |
| 容器 | Docker(多阶段构建) |
pr-agent/
├── backend/
│ ├── src/
│ │ ├── main.ts # NestJS 启动入口
│ │ ├── app.ts # Probot 事件处理(GitHub App)
│ │ ├── app.module.ts # NestJS 根模块
│ │ ├── common/ # 过滤器与共享请求类型
│ │ ├── core/ # 运行时状态、缓存、环境变量、i18n、HTTP
│ │ ├── integrations/ # GitHub / GitLab / 通知适配层
│ │ ├── modules/ # Webhook、健康检查、回放等 NestJS 模块
│ │ └── review/ # AI 评审引擎与报告渲染
│ ├── tests/ # 后端测试套件
│ ├── package.json
│ └── tsconfig.json
├── frontend/
│ ├── app/ # Next.js App Router 页面与布局
│ ├── components/ # 前端 UI 组件
│ ├── public/ # 静态资源
│ ├── package.json
│ └── next.config.ts
├── docs/ # 产品文档、路线图、流程资产
├── data/ # 本地/运行时持久化数据挂载点
├── secrets/ # 本地私钥挂载目录(不提交)
├── Dockerfile # 后端容器镜像
├── docker-compose.yml # 后端部署与本地运维
├── nixpacks.toml # 根目录 Nixpacks 入口,部署 frontend
├── package.json # Workspace 脚本
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── turbo.json
├── README.md
└── README-zh.md
- 仓库根目录
.env同时供本地后端开发和 Docker Compose 使用。 backend/是可部署的评审服务;使用根目录nixpacks.toml时部署的是frontend/,不是后端。- 容器内后端持久化路径默认是
/data/pr-agent/...,宿主机对应为data/pr-agent/...。
后端包使用 Node.js ESM subpath imports(配置位于 backend/tsconfig.json 和 backend/package.json):
| 别名 | 映射路径 |
|---|---|
#core |
backend/src/core/index.ts |
#review |
backend/src/review/index.ts |
#integrations/github |
backend/src/integrations/github/index.ts |
#integrations/gitlab |
backend/src/integrations/gitlab/index.ts |
#integrations/notify |
backend/src/integrations/notify/index.ts |
- Node.js >= 22
- pnpm >= 10
# 安装 workspace 依赖
pnpm install
# 在仓库根目录准备环境变量文件
cp .env.example .env
# 启动后端(backend 包会读取 ../.env)
pnpm dev:backend
# 启动前端
pnpm dev:frontend
# 生产构建后端
pnpm --filter backend build
# 启动已构建的后端
pnpm --filter backend start后端默认监听 3000 端口(可通过 PORT 环境变量配置)。前端单独运行时也默认使用 3000。
curl http://localhost:3000/health
curl http://localhost:3000/health?deep=true # 测试 AI Provider 连通性
curl http://localhost:3000/github/health # GitHub 配置状态复制 .env.example 并填入所需值。当前受支持的最小配置模板是:
.env.github-app.min.example— GitHub App 最小配置
普通 GitHub Webhook 和 GitLab 的最小示例文件仍保留在仓库中,仅供参考,不属于当前 beta 的受支持部署路径。
graph LR
ENV[AI_PROVIDER 环境变量]
ENV -->|openai| OAI[OpenAI<br/>OPENAI_API_KEY + OPENAI_MODEL]
ENV -->|openai-compatible| OC[OpenAI 兼容<br/>OPENAI_BASE_URL + OPENAI_COMPATIBLE_MODEL]
ENV -->|anthropic| ANT[Anthropic<br/>ANTHROPIC_API_KEY + ANTHROPIC_MODEL]
ENV -->|gemini| GEM[Gemini<br/>GEMINI_API_KEY + GEMINI_MODEL]
OpenAI(默认)
AI_PROVIDER=openai
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4.1-miniOpenAI 兼容(如 DeepSeek)
AI_PROVIDER=openai-compatible
OPENAI_BASE_URL=https://api.deepseek.com/v1
OPENAI_COMPATIBLE_API_KEY=...
OPENAI_COMPATIBLE_MODEL=deepseek-chatAnthropic
AI_PROVIDER=anthropic
ANTHROPIC_API_KEY=sk-ant-...
ANTHROPIC_MODEL=claude-3-5-haiku-latest
ANTHROPIC_MAX_TOKENS=8192Gemini
AI_PROVIDER=gemini
GEMINI_API_KEY=...
GEMINI_MODEL=gemini-2.0-flash| 后端 | 环境变量值 | 适用场景 |
|---|---|---|
| 内存 | memory(默认) |
无状态容器、开发环境 |
| JSON 文件 | file |
简单单实例 |
| SQLite | sqlite(推荐) |
生产单实例部署 |
RUNTIME_STATE_BACKEND=sqlite
RUNTIME_STATE_SQLITE_FILE=/data/pr-agent/runtime-state.sqlite3支持企业微信、Slack、Discord 和通用 JSON Webhook:
NOTIFY_WEBHOOK_URL=https://hooks.slack.com/services/...
NOTIFY_WEBHOOK_FORMAT=slack # wecom | slack | discord | genericAI 提供商调参
| 变量 | 默认值 | 说明 |
|---|---|---|
AI_HTTP_TIMEOUT_MS |
30000(30 秒) |
AI 评审请求 HTTP 超时 |
AI_ASK_HTTP_TIMEOUT_MS |
60000(60 秒) |
/ask 命令 HTTP 超时(多轮问答通常需要更长时间) |
AI_HTTP_RETRIES |
2 |
AI 提供商临时故障时的重试次数 |
AI_HTTP_RETRY_BACKOFF_MS |
400 |
AI 请求重试基础退避时延(毫秒) |
AI_MAX_CONCURRENCY |
4 |
AI 请求最大并发数 |
AI_MAX_QUEUE_SIZE |
200 |
AI 等待队列上限(超限后拒绝新任务) |
AI_SHUTDOWN_DRAIN_TIMEOUT_MS |
15000(15 秒) |
进程关闭时等待进行中 AI 请求完成的超时时间 |
AI_DEBUG_LOGS |
false |
记录 AI 请求/响应载荷用于调试 |
HEALTHCHECK_AI_TIMEOUT_MS |
5000(5 秒) |
深度健康检查 AI 探测超时 |
HEALTHCHECK_AI_LIVE_PROBE |
false |
GET /health?deep=true 时是否实际调用 AI API(否则仅检查配置) |
AI_CONCURRENCY_LIMIT 已废弃,不再生效。请改用 AI_MAX_CONCURRENCY 与 AI_MAX_QUEUE_SIZE。
全局运行时与命令限流
| 变量 | 默认值 | 说明 |
|---|---|---|
WEBHOOK_BODY_LIMIT |
1mb |
全局 Express body-parser 上限(超限返回 413) |
COMMAND_RATE_LIMIT_MAX |
10 |
每用户、每 PR/MR、每命令在窗口内的最大触发次数 |
COMMAND_RATE_LIMIT_WINDOW_MS |
3600000(1 小时) |
命令限流时间窗口 |
GitHub 专属
| 变量 | 默认值 | 说明 |
|---|---|---|
GITHUB_MERGED_DEDUPE_TTL_MS |
86400000(24 小时) |
merged + report 事件去重窗口 |
GITHUB_FEEDBACK_SIGNAL_TTL_MS |
2592000000(30 天) |
反馈学习信号保留时长 |
GITHUB_INCREMENTAL_STATE_TTL_MS |
604800000(7 天) |
增量评审 SHA 缓存有效期 |
GITHUB_POLICY_CONFIG_CACHE_TTL_MS |
300000(5 分钟) |
.pr-agent.yml 策略/评审配置缓存 |
GITHUB_POLICY_COMMENT_DEDUPE_TTL_MS |
600000(10 分钟) |
流程提醒评论去重窗口 |
GITHUB_ISSUE_AUTO_TRIAGE_ENABLED |
true |
当仓库缺少 .pr-agent.yml 时,在 issues.opened/edited 自动执行 Issue 分诊 |
GITHUB_ISSUE_AUTO_TRIAGE_AUTO_LABELS |
true |
Issue 自动分诊后自动追加推断标签 |
GITHUB_ISSUE_AUTO_TRIAGE_DEDUPE_TTL_MS |
300000(5 分钟) |
Issue 自动分诊评论去重窗口 |
GITHUB_ISSUE_AUTO_TRIAGE_SIMILAR_LIMIT |
5 |
自动分诊输出中最多展示的相似 Issue 数量 |
GITHUB_ISSUE_TRIAGE_DISABLE_AI |
false |
关闭 AI 调用,仅使用内置兜底分诊文案 |
GITHUB_WEBHOOK_MAX_BODY_BYTES |
10485760(10MB) |
/github/trigger 的额外请求体硬上限 |
GITHUB_WEBHOOK_SKIP_SIGNATURE |
false |
仅调试可用;NODE_ENV=production 时禁止开启 |
GitLab 专属
| 变量 | 默认值 | 说明 |
|---|---|---|
GITLAB_MERGED_DEDUPE_TTL_MS |
86400000(24 小时) |
merged + report 去重窗口 |
GITLAB_INCREMENTAL_STATE_TTL_MS |
604800000(7 天) |
增量评审状态缓存 |
GITLAB_FEEDBACK_SIGNAL_TTL_MS |
2592000000(30 天) |
反馈学习信号保留窗口 |
GITLAB_POLICY_CONFIG_CACHE_TTL_MS |
300000(5 分钟) |
.pr-agent.yml 策略缓存 |
GITLAB_CHANGELOG_PATH |
CHANGELOG.md |
/changelog --apply 写回路径 |
GITLAB_WEBHOOK_MAX_BODY_BYTES |
10485760(10MB) |
/gitlab/trigger 的额外请求体硬上限 |
GITLAB_REQUIRE_WEBHOOK_SECRET |
false |
设为 true 时必须配置 GITLAB_WEBHOOK_SECRET |
ALLOW_INSECURE_GITLAB_HTTP |
false |
仅本地调试允许 http:// GitLab 地址 |
调参建议:
MERGED_DEDUPE_TTL_MS— 控制merged + report事件的去重窗口,防止 Webhook 重投时重复评审。遇到较多 Webhook 重试/Redeliver 时可调大到48h~72h;需要更快允许同一 PR 合并事件再次触发时可调小到1h~6h。该变量只影响合并自动触发;手动评论命令触发(/ai-review ...)仍使用短窗口(5 分钟)去重策略。FEEDBACK_SIGNAL_TTL_MS— 控制/feedback与 review thread resolved/unresolved 信号的保留时长。团队评审节奏慢、希望长期记忆偏好可设为60~90天;规则变化快、希望更快"遗忘"历史偏好可设为7~14天。COMMAND_RATE_LIMIT_*— 控制评论命令的防滥用阈值。高活跃仓库可适当上调,命令刷屏场景可下调。
.env.example 提供基础变量参考;上方补充的是代码已实现但通常不在最小模板中的高级开关。
graph LR
subgraph Docker 构建
B1[阶段 1:构建<br/>node:22-alpine<br/>pnpm install + backend build]
B2[阶段 2:运行时<br/>node:22-alpine<br/>仅生产依赖]
B1 -->|COPY dist/| B2
end
B2 -->|暴露 3000 端口| SRV[pr-agent 容器]
构建 & 运行
docker build -t pr-agent:latest .
docker run -d \
--name pr-agent \
-p 3000:3000 \
--env-file .env \
-v ./data:/data \
pr-agent:latest# 启动
docker compose up -d --build
# 查看日志
docker compose logs -f pr-agent
# 重启
docker compose restart pr-agent
# 停止
docker compose downdocker-compose.yml 挂载的卷:
./data:/data— 持久化状态(SQLite、事件存储)./secrets/github-app.private-key.pem:/run/secrets/github-app-private-key.pem:ro— GitHub App 私钥
根目录 nixpacks.toml 用于从仓库根目录部署 frontend/,不会构建或启动后端。
- Install:
pnpm install --frozen-lockfile - Build:
pnpm --filter frontend build - Start:
pnpm --filter frontend start
graph TD
A[选择平台模式] -->|GitHub App| B1[创建 GitHub App]
A -->|普通 Webhook| B2[生成 PAT Token]
A -->|GitLab| B3[生成 API Token]
B1 --> C[配置 AI Provider]
B2 --> C
B3 --> C
C --> D[设置状态后端 = sqlite]
D --> E[部署容器]
E --> F[配置 Webhook URL]
F --> G[验证健康检查端点]
G --> H[测试 /ai-review 命令]
- 使用 GitHub App 接入模式 — 这是当前 beta 唯一受支持的接入方式
- 配置 AI Provider — 设置
AI_PROVIDER及对应的 API Key / 模型名称 - 启用状态持久化 — 生产环境推荐
RUNTIME_STATE_BACKEND=sqlite - 部署容器 — Docker、Docker Compose、Render、Railway、Fly.io 或 K8s
- 配置 Webhook URL 为
https://<域名>/api/github/webhooks - 验证 — 访问健康检查端点,并在 PR 中测试
/ai-review命令
这是一个适用于 Render/Railway/Fly.io/Docker/K8s 的精简部署路径。
- 使用 GitHub App 模式
- 使用最小环境变量
GitHub App 最小配置(.env.github-app.min.example)
APP_ID=123456
PRIVATE_KEY_PATH=/run/secrets/github-app-private-key.pem
# PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\\n...\\n-----END RSA PRIVATE KEY-----\\n"
WEBHOOK_SECRET=replace-with-webhook-secret
AI_PROVIDER=openai
OPENAI_API_KEY=replace-with-openai-key
OPENAI_MODEL=gpt-4.1-mini推荐的单实例补充配置
RUNTIME_STATE_BACKEND=sqlite
RUNTIME_STATE_SQLITE_FILE=/data/pr-agent/runtime-state.sqlite3
WEBHOOK_EVENT_STORE_ENABLED=false
WEBHOOK_REPLAY_ENABLED=false排障时临时开启 replay
WEBHOOK_EVENT_STORE_ENABLED=true
WEBHOOK_REPLAY_ENABLED=true
WEBHOOK_REPLAY_TOKEN=replace-with-strong-random-token- 启动后端应用
pnpm install --frozen-lockfile
pnpm --filter backend build
pnpm --filter backend start后端服务监听 PORT(默认 3000)。
- 配置 Webhook 地址
- GitHub App:
https://<域名>/api/github/webhooks
- GitHub App:
- Docker 一键启动
docker build -t pr-agent:latest .
docker run -d --name pr-agent -p 3000:3000 --env-file .env pr-agent:latest- 验证清单
GET /healthGET /github/healthGET /metrics- 在 PR/MR 评论中测试:
/ai-review、/ai-review comment - Webhook 失败响应应包含结构化字段:
error/type/status/path/method/timestamp
如果开启 replay:
GET /webhook/eventsPOST /github/replay/:eventId- 请求头:
x-pr-agent-replay-token: <WEBHOOK_REPLAY_TOKEN>
当前仓库未提交 deploy/nginx/ 示例文件,可直接使用下方片段作为基线:
server {
listen 443 ssl;
server_name pr-agent.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}- 创建 GitHub App,配置以下权限:
- Pull requests:Read & write
- Issues:Read & write
- Contents:Read & write(
/changelog --apply需要) - Checks:Read & write(
mode=enforce时必需) - Metadata:Read-only
- 订阅事件:
Pull request(opened/edited/synchronize/closed)Issues(opened/edited)Issue commentPull request review thread(resolved/unresolved,用于反馈学习)
- Webhook URL 设为
https://<域名>/api/github/webhooks - 配置环境变量:
APP_ID=123456
PRIVATE_KEY_PATH=/run/secrets/github-app-private-key.pem
# PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----\n"
WEBHOOK_SECRET=your-webhook-secret- GitHub App 启用条件(见
backend/src/modules/github-app/github-app.bootstrap.service.ts):APP_ID+(PRIVATE_KEY或PRIVATE_KEY_PATH)+WEBHOOK_SECRET。 docker-compose.yml默认挂载私钥路径为./secrets/github-app.private-key.pem:/run/secrets/github-app-private-key.pem:ro。如果本地缺少secrets/目录或 PEM 文件,docker compose up会失败。- 建议本地预先创建:
mkdir -p secrets data。data目录通常可由 Docker 自动创建,但手动创建更可控。
若未配置
APP_ID+PRIVATE_KEY(+WEBHOOK_SECRET),GitHub App 模式会被禁用,此时当前 beta 部署也视为不完整。
- 普通 GitHub Webhook 目前不是受支持的部署目标。
- GitLab Webhook 目前不是受支持的部署目标。
所有命令通过 PR/MR 评论触发。标记 (仅 PR) 的命令需要 Pull Request 上下文(diff、CI 检查),在 Issue 评论中不可用。
| 命令 | 说明 |
|---|---|
/ai-review (仅 PR) |
触发 AI 评审(未显式指定时默认 report) |
/ai-review report (仅 PR) |
强制 Report 模式(汇总评论) |
/ai-review comment (仅 PR) |
强制 Comment 模式(行内评论) |
/ai-review --mode=report / --mode=comment (仅 PR) |
参数方式指定评审模式(与位置参数等价) |
/ask <问题> |
针对 PR 或 Issue 提问(支持多轮对话) |
@bot-name <问题> |
@提及 Bot 进行提问(设置 GITHUB_APP_SLUG 或 GITHUB_BOT_LOGIN) |
/checks [问题] (仅 PR) |
分析 CI 检查失败原因 |
/generate_tests [重点] (仅 PR) |
为变更生成测试代码 |
/changelog [重点] (仅 PR) |
生成 Changelog 条目 |
/changelog --apply [重点] (仅 PR) |
生成并提交 Changelog 到仓库 |
/describe (仅 PR) |
生成 PR/MR 描述 |
/describe --apply (仅 PR) |
生成并更新 PR/MR 描述 |
/improve [重点] (仅 PR) |
以改进建议为主进行评审 |
/add_doc [重点] / /add-doc [重点] (仅 PR) |
仅输出文档/注释改进建议 |
/reflect [目标] (仅 PR) |
生成需求澄清与验收标准问题 |
/similar_issue [关键词] / /similar-issue [关键词] |
检索同仓库相似 Issue |
/custom_prompt <提示词> (仅 PR) |
使用自定义 AI 提示词分析 PR 变更 |
/help_docs <问题> |
基于项目 /docs 目录内容进行文档问答 |
/analyze (仅 PR) |
列出所有变更代码组件并按风险评级 |
/compliance [重点] (仅 PR) |
合规与安全审查 |
/improve_component <组件> (仅 PR) |
针对指定组件的改进评审 |
/generate_labels (仅 PR) |
基于 diff 内容自动生成并应用 PR 标签 |
/similar_code [关键词] (仅 PR) |
检测 diff 中重复或相似的代码模式 |
/auto_approve (仅 PR) |
基于 AI 风险评估的条件自动 Approve(默认关闭) |
/scan_repo_discussions (仅 PR) |
从最近已合并 PR 的评审讨论中提取最佳实践 |
/feedback resolved|dismissed|up|down [备注] |
评审质量反馈 |
支持别名写法,例如:/ai-review ask ...、/ai-review checks ...、/ai-review generate-tests ...、/ai-review add-doc ...。
.pr-agent.yml 的命令开关覆盖 /describe、/ask、/checks、/generate_tests、/changelog、/feedback、/improve、/add_doc、/custom_prompt、/help_docs、/analyze、/compliance、/similar_code、/auto_approve、/scan_repo_discussions;/reflect 依赖 askCommandEnabled;/improve_component 依赖 improveCommandEnabled;/generate_labels 依赖 autoLabelEnabled。
提示:
/ask、/feedback、/similar_issue、/help_docs和@提及在 Issue 和 PR 评论中均可使用。在 Issue 评论中不提供 diff 或 CI 上下文,但会将 Issue 标题和正文作为 AI 上下文。可设置GITHUB_APP_SLUG(GitHub App 的 slug)或GITHUB_BOT_LOGIN(Bot 账号 login)启用@提及检测。带或不带[bot]后缀都支持。
在仓库根目录添加 .pr-agent.yml 来配置仓库级行为:
mode: remind # remind = 仅评论提醒,enforce = 写入失败 GitHub Check
issue:
enabled: true
minBodyLength: 20
requiredSections:
- Summary
- Steps to Reproduce
- Expected Behavior
pullRequest:
enabled: true
minBodyLength: 20
requireLinkedIssue: false
requiredSections:
- Summary
- Test Plan
review:
enabled: true
mode: comment # comment | report
onOpened: true # PR 打开时评审
onEdited: false
onSynchronize: true # 新提交时评审
describeEnabled: true
describeAllowApply: false
checksCommandEnabled: true
includeCiChecks: true
askCommandEnabled: true
generateTestsCommandEnabled: true
changelogCommandEnabled: true
changelogAllowApply: false
feedbackCommandEnabled: true
improveCommandEnabled: true
addDocCommandEnabled: true
customPromptCommandEnabled: true
helpDocsCommandEnabled: true
analyzeCommandEnabled: true
complianceCommandEnabled: true
similarCodeCommandEnabled: true
autoApproveCommandEnabled: false # 默认关闭,安全考虑
scanRepoDiscussionsCommandEnabled: true
secretScanEnabled: true
autoLabelEnabled: true
secretScanCustomPatterns: # 可选:仓库自定义密钥正则
- "(?i)my_internal_token_[a-z0-9]{16,}"
customRules:
- 所有公开 API 必须提供类型注释
- 不允许新增 any 类型GitLab 当前只读取 .pr-agent.yml 中的 review: 段。顶层 mode、issue、pullRequest 的流程校验是 GitHub 流程能力。
模式说明:
remind— 评论提醒缺失项,不阻止合并enforce— 创建失败的 GitHub Check(PR Agent Policy),可在 Branch Protection 中设为必需
模板回退行为:
- 未配置
requiredSections时,会自动从仓库模板提取段落标题进行检查:- Issue:
.github/ISSUE_TEMPLATE/*或.github/ISSUE_TEMPLATE.md - PR:
.github/pull_request_template.md或.github/PULL_REQUEST_TEMPLATE.md
- Issue:
- 若仓库无上述模板,回退到内置默认段落(Issue:
Summary / Steps to Reproduce / Expected Behavior;PR:Summary / Test Plan / Related Issue)。
review 字段说明:
| 字段 | 说明 |
|---|---|
enabled / mode |
启用 AI 评审,设置默认模式(comment / report) |
onOpened / onEdited / onSynchronize |
控制哪些 PR 事件自动触发评审 |
describeEnabled |
是否启用 /describe 命令 |
describeAllowApply |
是否允许 /describe --apply 直接改写 PR 描述 |
checksCommandEnabled |
是否启用 /checks 命令 |
includeCiChecks |
是否把 CI 检查结果带入 AI 上下文 |
askCommandEnabled |
是否启用 /ask 命令 |
generateTestsCommandEnabled |
是否启用 /generate_tests 命令 |
changelogCommandEnabled |
是否启用 /changelog 命令 |
changelogAllowApply |
是否允许 /changelog --apply 直接写回仓库 Changelog |
feedbackCommandEnabled |
是否启用 /feedback 命令 |
improveCommandEnabled |
是否启用 /improve 命令 |
addDocCommandEnabled |
是否启用 /add_doc(/add-doc)命令 |
customPromptCommandEnabled |
是否启用 /custom_prompt 命令 |
helpDocsCommandEnabled |
是否启用 /help_docs 命令 |
analyzeCommandEnabled |
是否启用 /analyze 命令 |
complianceCommandEnabled |
是否启用 /compliance 命令 |
similarCodeCommandEnabled |
是否启用 /similar_code 命令 |
autoApproveCommandEnabled |
是否启用 /auto_approve 命令(默认关闭,安全考虑) |
scanRepoDiscussionsCommandEnabled |
是否启用 /scan_repo_discussions 命令 |
secretScanEnabled |
是否扫描 diff 中疑似密钥泄露并发布安全提示 |
secretScanCustomPatterns |
仓库自定义密钥正则补充规则 |
autoLabelEnabled |
是否根据变更内容自动追加 PR 标签 |
customRules |
团队自定义评审规则(自然语言),在评审与问答中都会强制纳入 |
Prometheus 格式指标通过 GET /metrics 暴露:
pr_agent_webhook_requests_total— 按平台和事件统计的 Webhook 请求数pr_agent_webhook_results_total— 按平台和结果(ok/error)统计pr_agent_webhook_replay_total— 回放执行结果统计pr_agent_webhook_store_writes_total— 调试事件存储写入次数pr_agent_webhook_store_trim_total— 调试事件存储裁剪次数pr_agent_health_checks_total— 健康检查端点调用次数pr_agent_http_errors_total— 全局 HTTP 错误计数pr_agent_process_uptime_seconds— 进程运行时间pr_agent_ai_requests_active— 当前 AI 活跃请求数pr_agent_ai_wait_queue_size— AI 并发等待队列长度pr_agent_ai_shutdown_requested— AI 关停标记(0/1)pr_agent_runtime_state_backend_info{backend=...}— 当前状态后端信息指标
| 端点 | 用途 |
|---|---|
GET /health |
存活探针 |
GET /health?deep=true |
深度检查(AI Provider 连通性) |
GET /github/health |
GitHub Webhook 配置校验 |
GET /gitlab/health |
GitLab Webhook 遗留配置校验(当前 beta 不支持) |
Webhook 错误返回结构化 JSON。已知 Webhook 错误(如 BadWebhookRequestError、WebhookAuthError)包含描述性消息;未识别的内部错误会被过滤为 "internal server error" 以防止信息泄露。
{
"ok": false,
"error": "webhook secret verification failed",
"type": "WebhookAuthError",
"status": 401,
"path": "/github/trigger",
"method": "POST",
"timestamp": "2026-01-01T00:00:00.000Z"
}请求体超过 WEBHOOK_BODY_LIMIT(默认 1mb)时返回 413 Payload Too Large。
排障时临时启用:
WEBHOOK_EVENT_STORE_ENABLED=true
WEBHOOK_REPLAY_ENABLED=true
WEBHOOK_REPLAY_TOKEN=your-secret-token端点(需携带 x-pr-agent-replay-token 请求头):
GET /webhook/events— 列出已存储的事件POST /github/replay/:eventId— 回放 GitHub 事件POST /gitlab/replay/:eventId— 回放 GitLab 事件
- HTTP 重试:指数退避(2 次重试,400ms 基础延迟),针对 408/429/5xx 状态码
- 请求去重:FNV 哈希,5 分钟窗口(合并事件 24 小时)
- 限流:按作用域限制,防止 API 滥用
- 优雅关停:收到 SIGTERM/SIGINT 后排空进行中的请求
# 后端测试
pnpm test:backend
# 后端覆盖率
pnpm --filter backend test:coverage
# 后端类型检查
pnpm --filter backend check
# 前端生产构建回归检查
pnpm --filter frontend build后端测试使用 Node.js 内置测试运行器(node:test)。建议的回归检查覆盖:
- AI 并发控制
- 缓存与去重行为
- Diff 解析与 Hunk 优先级
- GitHub/GitLab 集成逻辑
- HTTP 重试与错误处理
- 策略校验
- 通知适配器
- NestJS 模块装配
私有项目 — 详见仓库说明。