@krotovm/gitlab-ai-review 1.0.39 → 1.0.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -58,6 +58,7 @@ Set these in your project/group CI settings:
58
58
  - `AI_PROMPT_PROFILE` (optional, default: `default`; one of `default` \| `weak`). Use `weak` for small or heavily-quantized models (≤ ~7B, local Ollama, etc.). The `weak` profile uses shorter system prompts, positive rules instead of negations, and inline few-shot examples for triage / per-file review / consolidation / verification, which dramatically improves output-format adherence on weak models. When the variable is not set, the profile is auto-detected: if the triage pass returns unparseable JSON with `default` prompts, triage is retried once with `weak` and, on success, the whole run continues with it. Set the variable explicitly to pin a profile and disable auto-detection.
59
59
  - `PROJECT_ACCESS_TOKEN` (optional for public projects, but required for most private projects; token with `api` scope)
60
60
  - `GITLAB_TOKEN` (optional alias for `PROJECT_ACCESS_TOKEN`)
61
+ - `AI_REVIEW_CONCURRENCY` (optional) — same as `--max-review-concurrency`, handy as a CI/CD variable; the flag wins when both are set.
61
62
  - `AI_REVIEW_ARTIFACT_HTML_FILE` (optional, default: `ai-review-report.html`; used with `--include-artifacts`)
62
63
 
63
64
  `OPENAI_BASE_URL` is passed through to the `openai` SDK client, so you can use any OpenAI-compatible gateway/provider endpoint.
@@ -77,11 +78,29 @@ GitLab provides these automatically in Merge Request pipelines:
77
78
  - `--max-total-prompt-chars=220000` - Final hard cap for prompt size (single-pass fallback only).
78
79
  - `--triage-diff-chars=2000` - Max chars per file diff sent to the triage pass (Pass 1). Increase for large diffs where the first hunks are mostly git headers.
79
80
  - `--max-findings=5` - Max findings in the final review (CI multi-pass only).
80
- - `--max-review-concurrency=5` - Parallel per-file review API calls (CI multi-pass only).
81
+ - `--max-review-concurrency=2` - Parallel per-file review API calls (CI multi-pass only). Set to 1 for single-GPU backends that queue-starve long requests.
81
82
  - `--debug` - Print full error details (stack and API error fields).
82
83
  - `--include-artifacts` - Generate a local HTML debug artifact with per-pass outputs/tokens.
83
84
  - `--help` - Show help output.
84
85
 
86
+ ## Benchmark
87
+
88
+ Head-to-head against [Alibaba OpenCodeReview](https://github.com/alibaba/open-code-review) v1.8.10 (via its official GitLab CI recipe) on a demo MR with 4 seeded bugs: an auth bypass (`API_KEYS` unset → empty key accepted), a rate limiter whose window never resets, an unbounded per-IP counters Map, and a null-deref crash in a stats endpoint. Same MR, same commit range, same backends.
89
+
90
+ | Tool | Model | Seeded bugs found | Noise (dups / off-target) | Tokens | LLM time |
91
+ | --- | --- | --- | --- | --- | --- |
92
+ | **gitlab-ai-review** | gpt-5.4 | 3 / 4 | 0 | 15.7k | ~17s |
93
+ | OpenCodeReview | gpt-5.4 | 3 / 4 | 2 | 41.5k | ~11s |
94
+ | **gitlab-ai-review** | self-hosted (single GPU) | **4 / 4** | **0** | 37.2k | 7m 24s |
95
+ | OpenCodeReview | self-hosted (single GPU) | 3 / 4 | 8 (incl. 5 duplicates) | 151.8k | 11m 45s |
96
+
97
+ Notes:
98
+
99
+ - On gpt-5.4 both tools found the same 3 bugs and both missed the memory leak. OpenCodeReview added two design opinions, one of which (severity "high") suggested removing the very auth feature the MR introduces.
100
+ - On the self-hosted model the multi-pass pipeline (triage → per-file review → consolidate → verify) paid off: all 4 seeded bugs, zero noise. OpenCodeReview posted 11 comments: 3 unique real findings, 5 duplicates, and 3 off-target — its only rate-limiter comment misdiagnosed the bug, and several comments were attributed to the wrong file or line.
101
+ - Weak-model reviews are output-bound on a single GPU: OpenCodeReview generated 40.2k output tokens vs our 18.5k, and consumed 6× our prompt tokens (111.6k vs 18.7k) — that difference is the wall-clock gap.
102
+ - Methodology caveats: single run per cell on one MR; LLM variance applies.
103
+
85
104
  ## Architecture
86
105
 
87
106
  The reviewer uses a three-pass pipeline optimized for large merge requests:
package/dist/cli.js CHANGED
@@ -33,6 +33,7 @@ function printHelp() {
33
33
  " OPENAI_API_KEY (required) OpenAI API key.",
34
34
  " OPENAI_BASE_URL (optional) Custom OpenAI-compatible API base URL.",
35
35
  " AI_MODEL (optional) OpenAI chat model, e.g. gpt-4o. Default: gpt-4o-mini.",
36
+ " AI_REVIEW_CONCURRENCY (optional) Same as --max-review-concurrency; the flag wins.",
36
37
  " AI_PROMPT_PROFILE (optional) Prompt style: \"default\" | \"weak\". Default: default.",
37
38
  " Use \"weak\" for small/quantized models — shorter prompts,",
38
39
  " positive rules, and few-shot examples.",
@@ -82,7 +83,10 @@ async function main() {
82
83
  const promptLimits = parsePromptLimits(process.argv);
83
84
  const triageDiffChars = parseTriageDiffChars(process.argv);
84
85
  const maxFindings = parseNumberFlag(process.argv, "max-findings", DEFAULT_MAX_FINDINGS, 1);
85
- const reviewConcurrency = parseNumberFlag(process.argv, "max-review-concurrency", DEFAULT_REVIEW_CONCURRENCY, 1);
86
+ const envConcurrency = Number(envOrUndefined("AI_REVIEW_CONCURRENCY"));
87
+ const reviewConcurrency = parseNumberFlag(process.argv, "max-review-concurrency", Number.isFinite(envConcurrency) && envConcurrency >= 1
88
+ ? Math.floor(envConcurrency)
89
+ : DEFAULT_REVIEW_CONCURRENCY, 1);
86
90
  const aiModel = envOrDefault("AI_MODEL", "gpt-4o-mini");
87
91
  const promptProfile = readPromptProfileFromEnv();
88
92
  const allowProfileAutoDemote = envOrUndefined("AI_PROMPT_PROFILE") == null;
@@ -53,8 +53,8 @@ export const buildPrompt = ({ changes, limits, allowTools = false, profile = DEF
53
53
  // Multi-pass pipeline prompts
54
54
  // ---------------------------------------------------------------------------
55
55
  export const DEFAULT_MAX_FINDINGS = 5;
56
- // ponytail: 2 keeps self-hosted gateways under their proxy timeout; raise via
57
- // --max-review-concurrency on backends that batch well.
56
+ // ponytail: 2 suits most gateways; single-GPU backends that queue-starve past
57
+ // the per-call deadline should set AI_REVIEW_CONCURRENCY=1 (or the flag).
58
58
  export const DEFAULT_REVIEW_CONCURRENCY = 2;
59
59
  export function buildTriagePrompt(changes, profile = DEFAULT_PROMPT_PROFILE, triageDiffChars = DEFAULT_TRIAGE_DIFF_CHARS) {
60
60
  return [
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@krotovm/gitlab-ai-review",
4
- "version": "1.0.39",
4
+ "version": "1.0.40",
5
5
  "description": "CLI tool to generate AI code reviews for GitLab merge requests.",
6
6
  "main": "dist/cli.js",
7
7
  "bin": {