Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## Unreleased

- AI Review 上下文工具改为候选缺陷验证优先,支持 `read_file` 行范围读取、重复调用去重和每批累计结果字节预算。
- 完全重复的上下文工具调用命中缓存后立即进入强制收尾,避免不消耗预算的缓存调用循环持续到整体超时。
- 新增 `[ai_review].max_tool_total_bytes`,默认 `40000`,`0` 表示不限制;调用次数或字节预算耗尽后只保留最终 findings 提交工具。
- 上下文 follow-up 遇到 504 或请求超时时,重试会进入无上下文工具的强制收尾模式,避免原样重放过大的探索请求;收尾再次返回 504 时归类为 `ai_tool_loop_timeout` 并进入 diff-only fallback。

## v3.0.0 - 2026-07-16

- 移除脚本任务;配置中的 `[[script_tasks]]` 现在会被严格解析拒绝,升级时必须删除这些配置块。
Expand Down
15 changes: 10 additions & 5 deletions README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,9 @@ Recommended `rules.toml` example:
# Optional global AI Review prompt settings shared by every [[ai_reviews]] entry.
# The built-in system prompt always applies; extra_instructions is appended to the system prompt as administrator review policy.
extra_instructions = ""
max_tool_calls = 30
max_tool_result_bytes = 60000
max_tool_calls = 8
max_tool_result_bytes = 12000
max_tool_total_bytes = 40000

[[ai_reviews]]
id = "ai-review"
Expand All @@ -240,7 +241,7 @@ base_url = "https://api.openai.com/v1"
api_key = "<your-ai-api-key>"
model = "gpt-4.1-mini"
timeout_seconds = 1200
request_timeout_seconds = 420
request_timeout_seconds = 300
max_batch_diff_bytes = 15000
max_batches = 10
```
Expand All @@ -250,9 +251,11 @@ Posting a standalone `@ai-review` in an MR comment triggers the entry whose `id
`[ai_review]` is the global AI Review prompt configuration. The built-in system prompt always applies; `extra_instructions` is appended to the system prompt as administrator review policy. If omitted, only the built-in prompt is used.
Text after `@ai-review` in an MR comment is passed only as a reviewer-provided scope preference, such as adding focus areas, skipping optional categories, or limiting files/directories. It cannot override the output protocol, safety rules, tool permissions, or high-confidence threshold.
Built-in read-only context tools are enabled by default. The service downloads the MR head archive and lets the model request `read_file`, `search_code`, or `list_files` through tool calls. The runner only returns text content inside the repository directory; it does not execute shell commands and skips `.env` and `.git`.
`max_tool_calls` defaults to `30`; `0` means unlimited tool calls. `max_tool_result_bytes` defaults to `60000`.
Logs include each tool call's tool name, argument summary, returned bytes, result truncation status, tool-call limit status, batch index/count, and cumulative tool-call count. This makes it clear whether the model actually called `read_file`, `search_code`, or `list_files`.
`max_tool_calls` defaults to `30`; `0` means unlimited tool calls. `max_tool_result_bytes` defaults to `60000` and limits one result. `max_tool_total_bytes` defaults to `40000` and limits cumulative context-tool result bytes per batch; `0` means unlimited cumulative bytes.
An identical tool call receives a compact cache reference and consumes no additional call or byte budget. Because repeating it cannot add evidence, a cache hit immediately enters finalization. After a cache hit or when either budget is exhausted, the runner removes `read_file`, `search_code`, and `list_files`, leaves only `submit_review_findings`, and requires immediate final submission.
Logs include each tool call's tool name, argument summary, returned bytes, truncation, cache/budget status, batch index/count, cumulative call count, and cumulative result bytes. This makes it clear whether the model actually called `read_file`, `search_code`, or `list_files`.
`request_timeout_seconds` is the timeout for one AI API request. If omitted, it defaults to `timeout_seconds / 2` so one retry still fits inside the total review deadline.
Keep `request_timeout_seconds` below the timeout enforced by the upstream load balancer or API gateway. When a context follow-up returns 504 or times out, the one retry removes context tools and forces final submission instead of replaying the exploratory request unchanged. If that finalization request also returns 504, it is classified as `ai_tool_loop_timeout` and enters the existing diff-only fallback.
`timeout_seconds` is a full budget for each AI Review execution. A context-assisted execution starts one newly timed, independent diff-only fallback only when it returns `review_run_timeout`, `ai_request_timeout`, or `ai_tool_loop_timeout`. The fallback preserves the same `timeout_seconds`, `request_timeout_seconds`, batching policy, and `max_batches`, but exposes no context tools and does not recursively start a third execution. Worst-case elapsed time can approach `2 × timeout_seconds`, plus small archive preparation, cleanup, and publishing overhead. This behavior adds no configuration. Other AI errors and archive timeout, permission, HTTP, corrupt-ZIP, or filesystem failures are not eligible for this timeout fallback.
AI Review requests Chat Completions `tool_calls` structured output by default and parses findings from `submit_review_findings` arguments. If no tool call is returned, it falls back to parsing JSON in `content`. Built-in context tools do not require MCP.
AI Review splits MR diffs by complete file diffs by default. `max_batch_diff_bytes` controls the per-batch diff byte limit, and `max_batches` controls the maximum number of AI requests; `0` means unlimited batches.
Expand All @@ -261,6 +264,8 @@ The runner scans all MR changes and stores file counts, raw diff byte counts, an

Dashboard task details show execution mode, fallback reason, context duration, fallback duration, and their summed total. A successful degradation is noted in the GitLab Review summary with its reason and both durations; if the fallback itself fails, the existing AI Review failure path still applies. These new metadata fields may remain null on legacy database rows, which Dashboard continues to display compatibly.

`read_file(path, start_line?, end_line?)` reads one UTF-8 file from the MR head checkout. Prefer the optional one-based inclusive `start_line`/`end_line` narrow range; both must be supplied together and one call may read at most 250 lines. Omitting the range preserves whole-file compatibility subject to the result-byte limit.

Do not commit a real `rules.toml` that contains an actual `api_key`.

`@ai-review` matches `id = "ai-review"` inside `[[ai_reviews]]`. `[[ai_reviews]]` is the config block type, not the trigger command.
Expand Down
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,9 @@ dashboard 进程不会执行 migration。如果数据库或统计表不存在,
# 可选:全局 AI Review prompt 配置,所有 [[ai_reviews]] 共用。
# 内置 system prompt 始终生效;extra_instructions 会作为管理员配置的审查策略追加到 system prompt。
extra_instructions = ""
max_tool_calls = 30
max_tool_result_bytes = 60000
max_tool_calls = 8
max_tool_result_bytes = 12000
max_tool_total_bytes = 40000

[[ai_reviews]]
id = "ai-review"
Expand All @@ -240,7 +241,7 @@ base_url = "https://api.openai.com/v1"
api_key = "<your-ai-api-key>"
model = "gpt-4.1-mini"
timeout_seconds = 1200
request_timeout_seconds = 420
request_timeout_seconds = 300
max_batch_diff_bytes = 15000
max_batches = 10
```
Expand All @@ -249,9 +250,11 @@ max_batches = 10
`[ai_review]` 是全局 AI Review prompt 配置:内置 system prompt 始终生效,`extra_instructions` 会作为管理员配置的审查策略追加到 system prompt。缺省时只使用内置 prompt,不需要配置。
`@ai-review` 后面的评论内容只会作为触发者提供的审查范围偏好传给模型,例如增加关注方向、跳过可选检查类别或限定文件目录;它不能覆盖输出协议、安全规则、工具权限或高置信度门槛。
内置只读上下文工具默认启用。服务会下载 MR head archive,让模型可以通过 tool call 请求 `read_file`、`search_code` 或 `list_files`;runner 只返回仓库目录内的文本内容,不执行 shell,也不会读取 `.env` 或 `.git`。
`max_tool_calls` 默认是 `30`,`0` 表示不限制工具调用次数;`max_tool_result_bytes` 默认是 `60000`。
日志会记录每次工具调用的工具名、参数摘要、返回 bytes、结果是否截断、是否触发调用上限、batch index/count 和累计 tool call 次数,便于确认模型是否真的调用了 `read_file`、`search_code` 或 `list_files`。
`max_tool_calls` 默认是 `30`,`0` 表示不限制工具调用次数;`max_tool_result_bytes` 默认是 `60000`,限制单次工具结果;`max_tool_total_bytes` 默认是 `40000`,限制每个批次累计返回给模型的上下文工具结果,`0` 表示不限制累计字节数。
完全相同的工具调用会返回紧凑缓存引用,不会再次消耗调用次数或累计字节预算;由于重复调用不会产生新证据,缓存命中后 runner 会立即进入收尾模式。缓存命中、调用次数耗尽或累计字节预算耗尽后,runner 会移除 `read_file`、`search_code` 和 `list_files`,只保留 `submit_review_findings` 并要求模型立即提交结果。
日志会记录每次工具调用的工具名、参数摘要、返回 bytes、结果是否截断、是否命中缓存或预算上限、batch index/count、累计 tool call 次数和累计结果 bytes,便于确认模型是否真的调用了 `read_file`、`search_code` 或 `list_files`。
`request_timeout_seconds` 是单次 AI API 请求的超时;不配置时默认使用 `timeout_seconds / 2`,用于保留一次失败重试机会。
部署时应确保 `request_timeout_seconds` 小于上游负载均衡器或 API 网关的超时。上下文 follow-up 返回 504 或请求超时时,runner 的一次重试会移除上下文工具并强制提交最终结果,而不是原样重发探索请求;如果该收尾请求仍返回 504,则归类为 `ai_tool_loop_timeout` 并进入现有的 diff-only fallback。
`timeout_seconds` 是每次 AI Review 执行的完整预算。带上下文的执行只有在返回 `review_run_timeout`、`ai_request_timeout` 或 `ai_tool_loop_timeout` 时,才会启动一次新的、独立计时的 diff-only fallback;fallback 继续使用相同的 `timeout_seconds`、`request_timeout_seconds`、分批策略和 `max_batches`,但不提供上下文工具,也不会递归启动第三次执行。最坏耗时可能接近 `2 × timeout_seconds`,并另加少量 archive 准备、清理和发布开销;该行为不新增配置项。其他 AI 错误以及 archive 超时、权限、HTTP、损坏 ZIP、文件系统等错误不符合此 timeout fallback 条件。
AI Review 默认请求 Chat Completions `tool_calls` 结构化输出,并从 `submit_review_findings` 的 arguments 解析 findings;如果响应没有 tool call,会回退解析 `content` 中的 JSON。内置 context tools 不需要 MCP,也不会调用外部服务。
AI Review 默认按完整文件 diff 分批调用。`max_batch_diff_bytes` 控制单批 diff 字节上限,`max_batches` 控制最多请求批次数;`0` 表示不限制批次数。
Expand All @@ -262,7 +265,7 @@ Dashboard 的任务明细会显示执行模式、降级原因、context 耗时

内置 context tools 说明:

`read_file(path)` 读取 MR head checkout 中的一个 UTF-8 文本文件。
`read_file(path, start_line?, end_line?)` 读取 MR head checkout 中的一个 UTF-8 文本文件。建议使用一基、闭区间的 `start_line`/`end_line` 窄范围读取;两个参数必须同时提供,单次最多读取 250 行。省略范围时保持兼容,读取完整文件并应用结果字节限制。

参数:

Expand Down
Loading
Loading