@krotovm/gitlab-ai-review 1.0.40 → 1.0.41

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
@@ -2,8 +2,15 @@
2
2
 
3
3
  # AI Code Reviewer
4
4
 
5
+ [![npm](https://img.shields.io/npm/v/@krotovm/gitlab-ai-review)](https://www.npmjs.com/package/@krotovm/gitlab-ai-review)
6
+ [![downloads](https://img.shields.io/npm/dm/@krotovm/gitlab-ai-review)](https://www.npmjs.com/package/@krotovm/gitlab-ai-review)
7
+ [![license](https://img.shields.io/npm/l/@krotovm/gitlab-ai-review)](https://github.com/KrotovM/gitlab-ai-mr-reviewer/blob/main/LICENSE)
8
+ [![GitLab CI/CD Catalog](https://img.shields.io/gitlab/v/release/KrotovM/gitlab-ai-review?label=GitLab%20CI%2FCD%20Catalog&color=fc6d26)](https://gitlab.com/explore/catalog/KrotovM/gitlab-ai-review)
9
+
5
10
  Gitlab AI Code Review is a CLI tool that leverages OpenAI models to automatically review code changes and post a Markdown review to GitLab merge requests from CI.
6
11
 
12
+ ![AI review comment posted on a GitLab merge request](docs/review.png)
13
+
7
14
  ## Features
8
15
 
9
16
  - Automatically reviews code changes in GitLab repositories
@@ -30,6 +37,15 @@ ai_review:
30
37
  - npx -y @krotovm/gitlab-ai-review
31
38
  ```
32
39
 
40
+ Or include it as a [CI/CD component from the GitLab Catalog](https://gitlab.com/explore/catalog/KrotovM/gitlab-ai-review) (gitlab.com):
41
+
42
+ ```yaml
43
+ include:
44
+ - component: gitlab.com/KrotovM/gitlab-ai-review/review@1.0.2
45
+ inputs:
46
+ args: "--include-artifacts"
47
+ ```
48
+
33
49
  Save debug HTML as a CI artifact:
34
50
 
35
51
  ```yaml
@@ -48,6 +64,10 @@ ai_review:
48
64
  - ai-review-report.html
49
65
  ```
50
66
 
67
+ The HTML artifact breaks the run down per pass — tokens, durations, triage decisions, per-file findings, and errors:
68
+
69
+ ![AI review debug report artifact](docs/report.png)
70
+
51
71
  ## Env variables
52
72
 
53
73
  Set these in your project/group CI settings:
@@ -110,3 +130,7 @@ The reviewer uses a three-pass pipeline optimized for large merge requests:
110
130
  3. **Consolidate** - Per-file findings are merged, deduplicated, ranked by severity, and trimmed to top N (default 5).
111
131
 
112
132
  If the triage pass fails (API error, unparseable response), the pipeline falls back to the original single-pass approach automatically.
133
+
134
+ The pipeline in a CI job log — triage, parallel tool-assisted file reviews, consolidation, verification:
135
+
136
+ ![Multi-pass pipeline in the CI job log](docs/job.png)
@@ -2,7 +2,7 @@
2
2
  import OpenAI from "openai";
3
3
  import { buildAnswer, buildConsolidatePrompt, buildFileReviewPrompt, buildPrompt, buildTriagePrompt, buildVerificationPrompt, DEFAULT_PROMPT_PROFILE, extractCompletionText, isEmptyReviewBody, NO_FINDINGS_SENTENCE, parseTriageResponseDetailed, parseTriageResponse, } from "../prompt/index.js";
4
4
  import { fetchFileAtRef, searchRepository, } from "../gitlab/services.js";
5
- import { truncateWithMarker } from "../prompt/utils.js";
5
+ import { parseReviewFindings, truncateWithMarker } from "../prompt/utils.js";
6
6
  import { logToolUsageMinimal, MAX_FILE_TOOL_ROUNDS, MAX_TOOL_ROUNDS, MAX_VERIFICATION_TOOL_ROUNDS, TOOL_NAME_GET_FILE, TOOL_NAME_GREP, } from "./tooling.js";
7
7
  /** Hard deadline per model call, retries included. Must exceed the gateway's own
8
8
  * proxy timeout so the SDK's 5xx retries stay the first line of defense. */
@@ -849,6 +849,22 @@ export async function reviewMergeRequestMultiPass(params) {
849
849
  // every final-answer path gets it regardless of model formatting discipline.
850
850
  const summaryText = triageResult.summary.trim().replace(/\s*\n\s*/g, " ");
851
851
  const withHeader = (body) => `### 🤖 AI Code Review\n\n${summaryText === "" ? "" : `> ${summaryText}\n\n`}${body}`;
852
+ // Cap transparency: if consolidation likely trimmed the list (final count hit
853
+ // the cap while per-file review produced more candidates), say so in the note
854
+ // instead of silently dropping findings.
855
+ // ponytail: candidates deduped by file+title only; differently-worded dupes
856
+ // across files still inflate the count, which is why the note says "candidate".
857
+ const candidateCount = new Set(perFileFindings.flatMap((f) => parseReviewFindings(f.findings).map((x) => `${x.file}|${x.title.toLowerCase()}`))).size;
858
+ const withCapNote = (body) => {
859
+ const finalCount = parseReviewFindings(body).length;
860
+ if (finalCount < maxFindings || candidateCount <= finalCount)
861
+ return body;
862
+ const note = `\n\nℹ️ Showing top ${finalCount} of ${candidateCount} candidate findings (\`--max-findings=${maxFindings}\`). Run with \`--include-artifacts\` for the full list.`;
863
+ const disclaimerAt = body.lastIndexOf("\n\n---\n_");
864
+ return disclaimerAt === -1
865
+ ? body + note
866
+ : body.slice(0, disclaimerAt) + note + body.slice(disclaimerAt);
867
+ };
852
868
  logStep("Pass 3/4: consolidating findings");
853
869
  const consolidateMessages = buildConsolidatePrompt({
854
870
  perFileFindings,
@@ -875,7 +891,7 @@ export async function reviewMergeRequestMultiPass(params) {
875
891
  });
876
892
  const consolidatedText = extractCompletionText(consolidateCompletion);
877
893
  if (consolidatedText == null || consolidatedText.trim() === "") {
878
- return withHeader(buildAnswer(consolidateCompletion));
894
+ return withHeader(withCapNote(buildAnswer(consolidateCompletion)));
879
895
  }
880
896
  logStep("Pass 4/4: verifying consolidated findings (repo tools)");
881
897
  const verificationMessages = buildVerificationPrompt({
@@ -901,11 +917,11 @@ export async function reviewMergeRequestMultiPass(params) {
901
917
  debugDumpFile,
902
918
  debugRecordWriter,
903
919
  });
904
- return withHeader(buildAnswer(verificationCompletion));
920
+ return withHeader(withCapNote(buildAnswer(verificationCompletion)));
905
921
  }
906
922
  catch (error) {
907
923
  logStep(`Verification failed: ${error?.message ?? error}. Returning consolidated findings.`);
908
- return withHeader(buildAnswer(consolidateCompletion));
924
+ return withHeader(withCapNote(buildAnswer(consolidateCompletion)));
909
925
  }
910
926
  }
911
927
  catch (error) {
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.40",
4
+ "version": "1.0.41",
5
5
  "description": "CLI tool to generate AI code reviews for GitLab merge requests.",
6
6
  "main": "dist/cli.js",
7
7
  "bin": {