@krotovm/gitlab-ai-review 1.0.9 → 1.0.10
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/dist/prompt/index.js +40 -19
- package/dist/prompt/index.js.map +1 -1
- package/package.json +2 -2
package/dist/prompt/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
/** @format */
|
|
1
2
|
export const DEFAULT_PROMPT_LIMITS = {
|
|
2
3
|
maxDiffs: 50,
|
|
3
4
|
maxDiffChars: 16000,
|
|
4
|
-
maxTotalPromptChars: 220000
|
|
5
|
+
maxTotalPromptChars: 220000,
|
|
5
6
|
};
|
|
6
7
|
function truncateWithMarker(value, maxChars, markerLabel) {
|
|
7
8
|
if (value.length <= maxChars)
|
|
@@ -10,40 +11,60 @@ function truncateWithMarker(value, maxChars, markerLabel) {
|
|
|
10
11
|
return `${value.slice(0, maxChars)}\n\n[... ${markerLabel} truncated, omitted ${omitted} chars ...]`;
|
|
11
12
|
}
|
|
12
13
|
const QUESTIONS = `\n\nQuestions:\n
|
|
13
|
-
1. Can you find any bugs or logic errors
|
|
14
|
-
2. Are there optimizations or simplifications that
|
|
15
|
-
const MESSAGES = [
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
1. Can you find any bugs or logic errors that are directly supported by the provided diff and tool outputs? For each issue, cite exact evidence.\n
|
|
15
|
+
2. Are there optimizations or simplifications that are clearly justified by the current code? Skip micro-optimizations without measurable or maintainability benefit.\n\n`;
|
|
16
|
+
const MESSAGES = [
|
|
17
|
+
{
|
|
18
|
+
role: "system",
|
|
19
|
+
content: [
|
|
20
|
+
"You are a senior developer reviewing code changes for bugs and optimization opportunities.",
|
|
21
|
+
"Keep the review short enough that a busy developer will actually read it.",
|
|
22
|
+
"Rules: no praise, no summaries of what was done, no style remarks.",
|
|
23
|
+
"",
|
|
24
|
+
"Accuracy policy (strict):",
|
|
25
|
+
"- Report only findings that are directly supported by diff lines and/or tool outputs.",
|
|
26
|
+
"- Do not invent behavior, fields, or code paths that are not visible in evidence.",
|
|
27
|
+
'- If confidence is below high, do not present as a bug; either skip it or mark it as "Hypothesis" with what evidence is missing.',
|
|
28
|
+
"- Do not suggest removals/cleanups for symbols that are not present in the current code context.",
|
|
29
|
+
"- Avoid generic micro-optimizations unless there is a concrete benefit in this specific change.",
|
|
30
|
+
"",
|
|
31
|
+
"Evidence and formatting:",
|
|
32
|
+
"- Each confirmed finding must include: one-line title, confidence (high/medium), and 2-3 sentences with concrete evidence.",
|
|
33
|
+
"- Reference exact diff snippet(s) or tool output snippet(s) in each finding.",
|
|
34
|
+
'- If no confirmed issues exist, reply with exactly: "No confirmed bugs or high-value optimizations found."',
|
|
35
|
+
"- Format as GitLab-flavoured markdown.",
|
|
36
|
+
].join("\n"),
|
|
37
|
+
},
|
|
38
|
+
];
|
|
19
39
|
export const AI_MODEL_TEMPERATURE = 0.2;
|
|
20
|
-
export const buildPrompt = ({ changes, limits }) => {
|
|
40
|
+
export const buildPrompt = ({ changes, limits, }) => {
|
|
21
41
|
const effectiveLimits = {
|
|
22
42
|
...DEFAULT_PROMPT_LIMITS,
|
|
23
|
-
...(limits ?? {})
|
|
43
|
+
...(limits ?? {}),
|
|
24
44
|
};
|
|
25
45
|
const diffsTrimmed = changes
|
|
26
46
|
.slice(0, effectiveLimits.maxDiffs)
|
|
27
47
|
.map((change, index) => truncateWithMarker(change.diff, effectiveLimits.maxDiffChars, `diff #${index + 1}`));
|
|
28
|
-
const changesText = diffsTrimmed.join(
|
|
48
|
+
const changesText = diffsTrimmed.join("\n\n");
|
|
29
49
|
const intro = `
|
|
30
50
|
Review the following code changes (git diff format) for bugs and optimization opportunities only.
|
|
31
51
|
No full pre-change file context is embedded; use tool calls to request additional context when needed.
|
|
32
52
|
If you see truncation markers, note potential blind spots.
|
|
53
|
+
Do not present assumptions as facts. Prefer no finding over a weakly supported finding.
|
|
33
54
|
`;
|
|
34
55
|
const changesSection = `
|
|
35
56
|
Changes:
|
|
36
|
-
${changesText ||
|
|
57
|
+
${changesText || "(not provided)"}
|
|
37
58
|
`;
|
|
38
59
|
const questionsSection = QUESTIONS;
|
|
39
60
|
const fullPrompt = `${intro}\n${changesSection}\n${questionsSection}`;
|
|
40
|
-
const boundedContent = truncateWithMarker(fullPrompt, effectiveLimits.maxTotalPromptChars,
|
|
41
|
-
return [...MESSAGES, { role:
|
|
61
|
+
const boundedContent = truncateWithMarker(fullPrompt, effectiveLimits.maxTotalPromptChars, "prompt payload");
|
|
62
|
+
return [...MESSAGES, { role: "user", content: boundedContent }];
|
|
42
63
|
};
|
|
43
|
-
const ERROR_ANSWER =
|
|
44
|
-
const DISCLAIMER =
|
|
64
|
+
const ERROR_ANSWER = "I'm sorry, I'm not feeling well today. Please ask a human to review this code change.";
|
|
65
|
+
const DISCLAIMER = "This comment was generated by an artificial intelligence duck.";
|
|
45
66
|
function sanitizeGitLabMarkdown(input) {
|
|
46
|
-
const normalized = input.replace(/\r\n/g,
|
|
67
|
+
const normalized = input.replace(/\r\n/g, "\n").trim();
|
|
47
68
|
// If the model forgets to close a fenced code block, GitLab will render the rest (incl. disclaimer) inside it.
|
|
48
69
|
const fenceCount = (normalized.match(/```/g) ?? []).length;
|
|
49
70
|
const withClosedFence = fenceCount % 2 === 1 ? `${normalized}\n\`\`\`` : normalized;
|
|
@@ -53,12 +74,12 @@ export const buildAnswer = (completion) => {
|
|
|
53
74
|
if (completion instanceof Error) {
|
|
54
75
|
const maybeCause = completion.cause;
|
|
55
76
|
const causeMessage = maybeCause instanceof Error ? maybeCause.message : undefined;
|
|
56
|
-
return `${ERROR_ANSWER}\n\nError: ${completion.message}${causeMessage != null ? `\nCause: ${causeMessage}` :
|
|
77
|
+
return `${ERROR_ANSWER}\n\nError: ${completion.message}${causeMessage != null ? `\nCause: ${causeMessage}` : ""}`;
|
|
57
78
|
}
|
|
58
|
-
if (
|
|
79
|
+
if (completion == null || completion.choices.length === 0) {
|
|
59
80
|
return `${ERROR_ANSWER}\n\n${DISCLAIMER}`;
|
|
60
81
|
}
|
|
61
|
-
const content = completion.choices[0].message.content ??
|
|
82
|
+
const content = completion.choices[0].message.content ?? "";
|
|
62
83
|
const safe = sanitizeGitLabMarkdown(content);
|
|
63
84
|
return `${safe}\n\n---\n_${DISCLAIMER}_`;
|
|
64
85
|
};
|
package/dist/prompt/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prompt/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prompt/index.ts"],"names":[],"mappings":"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"}
|
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.
|
|
4
|
+
"version": "1.0.10",
|
|
5
5
|
"description": "CLI tool to generate AI code reviews for GitLab merge requests and local diffs.",
|
|
6
6
|
"main": "dist/cli.js",
|
|
7
7
|
"bin": {
|
|
@@ -44,4 +44,4 @@
|
|
|
44
44
|
"typescript": "^5.2.2"
|
|
45
45
|
},
|
|
46
46
|
"packageManager": "pnpm@8.15.4+sha256.cea6d0bdf2de3a0549582da3983c70c92ffc577ff4410cbf190817ddc35137c2"
|
|
47
|
-
}
|
|
47
|
+
}
|