diff --git a/README.md b/README.md index 48204db..1dc250c 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ AI-powered code review assistant for Gitea. Automatically reviews Pull Requests - 🤖 **AI Code Review** - Automatic review of PRs and commits using pluggable LLM providers - 📝 **Line-Level Comments** - Precise feedback on specific code changes -- 🔄 **Dual Review Engines** - Legacy (simple) or Agent-based (multi-agent) review modes +- 🔄 **Task-Based Review Engines** - Agent staged review (skip/light/full) plus optional Codex CLI execution mode - 🔔 **Feishu Notifications** - Integrated notification system for PR events - 🎛️ **Admin Dashboard** - Web UI for managing repository webhooks and LLM provider configuration - 🔐 **Secure Webhooks** - HMAC-SHA256 signature verification @@ -34,8 +34,8 @@ AI-powered code review assistant for Gitea. Automatically reviews Pull Requests | Engine | Description | Use Case | |--------|-------------|----------| -| `legacy` | Single-pass AI review with summary + line comments | Simple, fast reviews | -| `agent` | Multi-agent orchestration with specialists, reflection, and debate | Deep, comprehensive analysis | +| `agent` | Task-based staged review (`skip` / `light` / `full`) with scoped specialist routing and optional reflection/debate escalation | Deep reviews with token-aware execution | +| `codex` | Codex CLI review execution with independent configuration | External Codex-driven review pipeline | ## Quick Start @@ -136,7 +136,7 @@ LLM providers and models are configured exclusively through the **Admin Dashboar 1. Navigate to **LLM 配置** (LLM Configuration) 2. Add your LLM providers (OpenAI Compatible, OpenAI Responses API, Anthropic, Google Gemini) -3. Assign models to review roles (legacy, planner, specialist, judge, embedding) +3. Assign models to review roles (planner, specialist, judge, embedding) > API keys are stored encrypted (AES-256-GCM) in the local SQLite database. @@ -151,13 +151,28 @@ LLM providers and models are configured exclusively through the **Admin Dashboar | Setting | Description | Default | |---------|-------------|---------| -| Review Engine | Engine mode (`legacy` or `agent`) | `legacy` | +| Review Engine | Engine mode (`agent` or `codex`) | `agent` | +| Enable Triage | Enable planner triage for task routing | `true` | +| Small Max Files | Upper file-count bound for `small` review size | `3` | +| Small Max Changed Lines | Upper changed-lines bound for `small` review size | `80` | +| Medium Max Files | Upper file-count bound for `medium` review size | `10` | +| Medium Max Changed Lines | Upper changed-lines bound for `medium` review size | `400` | +| Token Budget Small | Token budget cap for `small` staged tasks | `12000` | +| Token Budget Medium | Token budget cap for `medium` staged tasks | `45000` | +| Token Budget Large | Token budget cap for `large` staged tasks | `120000` | | Review Work Directory | Working directory for repo clones | `/tmp/gitea-assistant` | | Max Parallel Runs | Max concurrent review tasks | `2` | | Max Files per Run | Max files analyzed per review | `200` | | Auto-publish Min Confidence | Min confidence score for auto-publish | `0.8` | | Enable Human Gate | Require human approval before publishing | `true` | +Agent review execution model (current): + +- `skip`: docs/assets/rename-only style changes can bypass specialist review. +- `light`: low-risk code changes run minimal scoped specialist checks. +- `full`: sensitive or larger changes run full specialist tasks, with optional reflection/debate escalation. +- Triage outputs task scopes (`paths`, `riskTags`, `mode`, `tokenBudget`) and orchestrator dispatches specialists by task scope instead of broad fan-out. + #### Memory & Learning (Experimental) | Setting | Description | Default | diff --git a/docs/README.zh-CN.md b/docs/README.zh-CN.md index c606208..55c8542 100644 --- a/docs/README.zh-CN.md +++ b/docs/README.zh-CN.md @@ -10,7 +10,7 @@ - 🤖 **AI 代码审查** - 使用可插拔的 LLM 提供商自动审查 PR 和提交 - 📝 **行级评论** - 针对具体代码变更的精确反馈 -- 🔄 **双引擎模式** - Legacy(简单)或 Agent(多代理)审查模式 +- 🔄 **任务化审查引擎** - Agent 分级审查(skip/light/full)+ 可选 Codex CLI 审查模式 - 🔔 **飞书通知** - PR 事件通知集成 - 🎛️ **管理后台** - 用于管理仓库 Webhook 和 LLM 提供商配置的 Web 界面 - 🔐 **安全验证** - HMAC-SHA256 签名验证 @@ -34,8 +34,8 @@ | 引擎 | 描述 | 适用场景 | |------|------|----------| -| `legacy` | 单次 AI 审查,生成总结和行级评论 | 简单、快速的审查 | -| `agent` | 多代理编排,支持专家、反思和辩论 | 深度、全面的分析 | +| `agent` | 任务化分级审查(`skip` / `light` / `full`),按路径范围派发 specialist,并按需升级到反思/辩论 | 在控制 token 成本的前提下做深度审查 | +| `codex` | 通过 Codex CLI 执行审查,独立配置 | 对接外部 Codex 审查流程 | ## 快速开始 @@ -136,7 +136,7 @@ LLM 提供商和模型通过**管理后台** Web 界面进行配置: 1. 导航到 **LLM 配置** 页面 2. 添加 LLM 提供商(OpenAI 兼容、OpenAI Responses API、Anthropic、Google Gemini) -3. 为审查角色分配模型(legacy、planner、specialist、judge、embedding) +3. 为审查角色分配模型(planner、specialist、judge、embedding) > API 密钥使用 AES-256-GCM 加密存储在本地 SQLite 数据库中。 @@ -151,13 +151,28 @@ LLM 提供商和模型通过**管理后台** Web 界面进行配置: | 配置项 | 描述 | 默认值 | |--------|------|--------| -| 审查引擎 | 引擎模式(`legacy` 或 `agent`) | `legacy` | +| 审查引擎 | 引擎模式(`agent` 或 `codex`) | `agent` | +| 启用分流(Enable Triage) | 启用 planner 分流并输出任务化审查计划 | `true` | +| Small 文件上限 | 判定 `small` 规模审查的文件数上限 | `3` | +| Small 变更行上限 | 判定 `small` 规模审查的变更行数上限 | `80` | +| Medium 文件上限 | 判定 `medium` 规模审查的文件数上限 | `10` | +| Medium 变更行上限 | 判定 `medium` 规模审查的变更行数上限 | `400` | +| Small Token 预算 | `small` 任务的 token 预算上限 | `12000` | +| Medium Token 预算 | `medium` 任务的 token 预算上限 | `45000` | +| Large Token 预算 | `large` 任务的 token 预算上限 | `120000` | | 工作目录 | 仓库克隆工作目录 | `/tmp/gitea-assistant` | | 最大并发数 | 最大并发审查任务数 | `2` | | 最大文件数 | 单次审查最大文件数 | `200` | | 自动发布置信度 | 自动发布最小置信度 | `0.8` | | 启用人工审批 | 发布前要求人工确认 | `true` | +当前 Agent 审查执行模型: + +- `skip`:文档/资源/纯重命名等低风险改动可直接跳过 specialist。 +- `light`:低风险代码改动执行最小化、按路径范围限定的 specialist 审查。 +- `full`:敏感路径或中大型改动执行完整任务审查,并可按配置升级到 reflection/debate。 +- Triage 输出任务(`paths`、`riskTags`、`mode`、`tokenBudget`),Orchestrator 按任务范围派发,不再默认全量扇出。 + #### 记忆与学习(实验性) | 配置项 | 描述 | 默认值 | diff --git a/docs/design/pluggable-llm-providers.md b/docs/design/pluggable-llm-providers.md index 08795c7..43b99d1 100644 --- a/docs/design/pluggable-llm-providers.md +++ b/docs/design/pluggable-llm-providers.md @@ -132,11 +132,10 @@ CREATE TABLE llm_secrets ( -- ============================================================ -- 表3: model_role_assignments — 场景 → 模型映射 -- ============================================================ --- 每个业务场景(如 planner/specialist/judge/legacy/embedding)绑定到 +-- 每个业务场景(如 planner/specialist/judge/embedding)绑定到 -- 一个 provider + 具体 model,支持不同场景用不同 provider。 CREATE TABLE model_role_assignments ( role TEXT PRIMARY KEY CHECK (role IN ( - 'legacy', -- 旧版单次审查(ai-review.ts) 'planner', -- Agent 审查 planner 'specialist', -- Agent 审查 specialist 'judge', -- Agent 审查 judge @@ -184,7 +183,7 @@ CREATE INDEX idx_providers_enabled ON llm_providers(is_enabled); // ── src/llm/types.ts ──────────────────────────────────────── /** 模型角色枚举 */ -export type ModelRole = 'legacy' | 'planner' | 'specialist' | 'judge' | 'embedding'; +export type ModelRole = 'planner' | 'specialist' | 'judge' | 'embedding'; /** 统一消息格式(内部表达,不暴露 provider 差异) */ export interface LLMMessage { @@ -346,7 +345,7 @@ export class LLMGateway { /** * 按业务角色调用 LLM - * @param role 业务角色(legacy/planner/specialist/judge/embedding) + * @param role 业务角色(planner/specialist/judge/embedding) * @param request 请求(不含 model,由角色映射决定) */ async chatForRole( @@ -686,19 +685,19 @@ Settings 页面 │ │ ├── ▸ 高级配置 (collapsible, JSON key-value editor) │ │ └── [测试连接] [保存] [取消] │ │ -│ └── 🧩 角色分配 区域 +│ └── 🧩 角色分配与分级审查映射 区域 │ ┌──────────────────────────────────────────────────────────────┐ -│ │ 角色 │ Provider 下拉 │ 模型 ID │ +│ │ 角色/阶段 │ Provider 下拉 │ 模型 ID │ │ ├──────────────┼──────────────────────┼──────────────────────┤ -│ │ Legacy 审查 │ [公司 OpenAI 代理 ▾] │ [gpt-4o-mini ] │ -│ │ Planner │ [公司 OpenAI 代理 ▾] │ [gpt-4o-mini ] │ -│ │ Specialist │ [Anthropic Claude ▾] │ [claude-sonnet-4 ] │ -│ │ Judge │ [公司 OpenAI 代理 ▾] │ [gpt-4o ] │ -│ │ Embedding │ [公司 OpenAI 代理 ▾] │ [text-embedding-3 ] │ +│ │ Planner(Triage) │ [公司 OpenAI 代理 ▾] │ [gpt-4o-mini ] │ +│ │ Specialist(任务执行) │ [Anthropic Claude ▾] │ [claude-sonnet-4 ] │ +│ │ Judge(汇总裁决) │ [公司 OpenAI 代理 ▾] │ [gpt-4o ] │ +│ │ Embedding(记忆检索) │ [公司 OpenAI 代理 ▾] │ [text-embedding-3 ] │ │ └──────────────────────────────────────────────────────────────┘ │ [保存角色分配] │ ├── ⚙️ 通用设置(现有 Gitea / 飞书 / App / Review 参数) +│ ├── Agent 分级审查参数:small/medium 阈值、token budget、triage 开关 │ └── (复用现有 ConfigManager 组件,数据源统一为 DB) ``` @@ -734,9 +733,9 @@ const MODEL_SUGGESTIONS: Record = { | # | 文件 | 当前代码 | 改造为 | 影响范围 | |---|---|---|---|---| | 1 | `src/index.ts:69-71` | `const openaiClient = new OpenAI({baseURL, apiKey})` | 删除;初始化 `LLMGateway` 单例并传入业务层 | 入口 | -| 2 | `src/services/ai-review.ts:8-10` | `const openai = new OpenAI({...})` | 删除模块级 client;函数接收 `LLMGateway` 参数;`openai.chat.completions.create()` → `gateway.chatForRole('legacy', ...)` | Legacy 审查 | -| 3 | `src/review/orchestrator.ts:45,61-63` | `private readonly openai: OpenAI` + `this.openai = new OpenAI(...)` | 构造函数改接收 `LLMGateway`;传给各 agent | Agent 编排 | -| 4 | `src/review/agents/specialist-agent.ts:93` | `protected readonly openai: OpenAI` | → `protected readonly gateway: LLMGateway`;`reviewLegacy()` 和 `reviewWithReAct()` 中的 `this.openai.chat.completions.create()` 改为 `this.gateway.chatForRole('specialist', ...)` | 核心 agent | +| 2 | `src/controllers/review.ts` | 旧版 webhook 存在回退分支 | 删除回退分支,仅保留 `agent` / `codex` 入队逻辑 | 审查主入口 | +| 3 | `src/review/orchestrator.ts:45,61-63` | `private readonly openai: OpenAI` + `this.openai = new OpenAI(...)` | 构造函数改接收 `LLMGateway`;传给各 agent(任务化分级编排:skip/light/full) | Agent 编排 | +| 4 | `src/review/agents/specialist-agent.ts:93` | `protected readonly openai: OpenAI` | → `protected readonly gateway: LLMGateway`;`reviewWithOptions()` 与 ReAct 调用改为 `this.gateway.chatForRole('specialist', ...)` | 核心 agent | | 5 | `src/review/agents/critic-agent.ts:23` | `private openai: OpenAI` | 同上 | 评审 agent | | 6 | `src/review/agents/reflexion-agent.ts:24` | `constructor(openai: OpenAI, ...)` | 构造传 gateway | 反思 agent | | 7 | `src/review/agents/debate-orchestrator.ts:17` | `private openai: OpenAI` | 同上 | 辩论 agent | diff --git a/frontend/src/components/ReviewConfigPage.tsx b/frontend/src/components/ReviewConfigPage.tsx index 4d139ce..b28a457 100644 --- a/frontend/src/components/ReviewConfigPage.tsx +++ b/frontend/src/components/ReviewConfigPage.tsx @@ -17,15 +17,12 @@ import { toast } from 'sonner'; // Engine-specific field visibility // --------------------------------------------------------------------------- -type EngineMode = 'legacy' | 'agent' | 'codex'; +type EngineMode = 'agent' | 'codex'; /** The engine selector field — always visible at the top. */ const ENGINE_FIELD = 'REVIEW_ENGINE'; -/** Fields shared across legacy & agent (but NOT codex). */ -const LEGACY_AGENT_FIELDS = new Set([ - 'CUSTOM_SUMMARY_PROMPT', - 'CUSTOM_LINE_COMMENT_PROMPT', +const AGENT_SHARED_FIELDS = new Set([ 'GLOBAL_PROMPT', 'REVIEW_WORKDIR', 'REVIEW_MAX_PARALLEL_RUNS', @@ -65,10 +62,8 @@ function getVisibleFields(engine: EngineMode, fields: ConfigFieldDto[]): ConfigF return fields.filter((f) => { if (f.envKey === ENGINE_FIELD) return false; // rendered separately switch (engine) { - case 'legacy': - return LEGACY_AGENT_FIELDS.has(f.envKey); case 'agent': - return LEGACY_AGENT_FIELDS.has(f.envKey) || AGENT_ONLY_FIELDS.has(f.envKey); + return AGENT_SHARED_FIELDS.has(f.envKey) || AGENT_ONLY_FIELDS.has(f.envKey); case 'codex': return CODEX_FIELDS.has(f.envKey); default: @@ -82,7 +77,6 @@ function getVisibleFields(engine: EngineMode, fields: ConfigFieldDto[]): ConfigF // --------------------------------------------------------------------------- const ENGINE_OPTIONS: { value: EngineMode; label: string; description: string }[] = [ - { value: 'legacy', label: 'Legacy', description: '传统单次 LLM 审查' }, { value: 'agent', label: 'Agent', description: '多代理编排深度审查' }, { value: 'codex', label: 'Codex', description: 'Codex CLI 审查' }, ]; @@ -105,7 +99,7 @@ export function ReviewConfigPage() { const engine: EngineMode = useMemo(() => { const val = localConfig[ENGINE_FIELD]; if (val === 'agent' || val === 'codex') return val; - return 'legacy'; + return 'agent'; }, [localConfig]); // Derived: review group and memory group from fetched data @@ -231,13 +225,11 @@ export function ReviewConfigPage() { const syntheticReviewGroup: ConfigGroupDto | null = reviewGroup ? { ...reviewGroup, - label: engine === 'codex' ? 'Codex 审查设置' : engine === 'agent' ? 'Agent 审查设置' : 'Legacy 审查设置', + label: engine === 'codex' ? 'Codex 审查设置' : 'Agent 审查设置', description: engine === 'codex' ? 'Codex CLI 审查引擎配置' - : engine === 'agent' - ? '多代理编排审查引擎配置' - : '传统单次 LLM 审查引擎配置', + : '多代理编排审查引擎配置', fields: visibleReviewFields, } : null; @@ -327,7 +319,7 @@ export function ReviewConfigPage() { -
+
{ENGINE_OPTIONS.map((opt) => (