mc-ai-code-review 1.1.24

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.
Files changed (62) hide show
  1. package/bin/ai-code-review.js +28 -0
  2. package/dist/config.d.ts +14 -0
  3. package/dist/config.d.ts.map +1 -0
  4. package/dist/config.js +68 -0
  5. package/dist/config.js.map +1 -0
  6. package/dist/formatters/index.d.ts +5 -0
  7. package/dist/formatters/index.d.ts.map +1 -0
  8. package/dist/formatters/index.js +21 -0
  9. package/dist/formatters/index.js.map +1 -0
  10. package/dist/formatters/rdjson.d.ts +17 -0
  11. package/dist/formatters/rdjson.d.ts.map +1 -0
  12. package/dist/formatters/rdjson.js +65 -0
  13. package/dist/formatters/rdjson.js.map +1 -0
  14. package/dist/index.d.ts +18 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +134 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/performanceReviewer/index.d.ts +17 -0
  19. package/dist/performanceReviewer/index.d.ts.map +1 -0
  20. package/dist/performanceReviewer/index.js +251 -0
  21. package/dist/performanceReviewer/index.js.map +1 -0
  22. package/dist/reviewer/index.d.ts +10 -0
  23. package/dist/reviewer/index.d.ts.map +1 -0
  24. package/dist/reviewer/index.js +115 -0
  25. package/dist/reviewer/index.js.map +1 -0
  26. package/dist/reviewer/modelAdapters/base.d.ts +14 -0
  27. package/dist/reviewer/modelAdapters/base.d.ts.map +1 -0
  28. package/dist/reviewer/modelAdapters/base.js +3 -0
  29. package/dist/reviewer/modelAdapters/base.js.map +1 -0
  30. package/dist/reviewer/modelAdapters/factory.d.ts +13 -0
  31. package/dist/reviewer/modelAdapters/factory.d.ts.map +1 -0
  32. package/dist/reviewer/modelAdapters/factory.js +21 -0
  33. package/dist/reviewer/modelAdapters/factory.js.map +1 -0
  34. package/dist/reviewer/modelAdapters/gemini.d.ts +11 -0
  35. package/dist/reviewer/modelAdapters/gemini.d.ts.map +1 -0
  36. package/dist/reviewer/modelAdapters/gemini.js +61 -0
  37. package/dist/reviewer/modelAdapters/gemini.js.map +1 -0
  38. package/dist/reviewer/modelAdapters/openai.d.ts +12 -0
  39. package/dist/reviewer/modelAdapters/openai.d.ts.map +1 -0
  40. package/dist/reviewer/modelAdapters/openai.js +54 -0
  41. package/dist/reviewer/modelAdapters/openai.js.map +1 -0
  42. package/dist/reviewer/parseResponse.d.ts +10 -0
  43. package/dist/reviewer/parseResponse.d.ts.map +1 -0
  44. package/dist/reviewer/parseResponse.js +97 -0
  45. package/dist/reviewer/parseResponse.js.map +1 -0
  46. package/dist/reviewer/utils.d.ts +44 -0
  47. package/dist/reviewer/utils.d.ts.map +1 -0
  48. package/dist/reviewer/utils.js +392 -0
  49. package/dist/reviewer/utils.js.map +1 -0
  50. package/dist/summarizer/index.d.ts +10 -0
  51. package/dist/summarizer/index.d.ts.map +1 -0
  52. package/dist/summarizer/index.js +142 -0
  53. package/dist/summarizer/index.js.map +1 -0
  54. package/dist/types.d.ts +92 -0
  55. package/dist/types.d.ts.map +1 -0
  56. package/dist/types.js +6 -0
  57. package/dist/types.js.map +1 -0
  58. package/dist/utils.d.ts +5 -0
  59. package/dist/utils.d.ts.map +1 -0
  60. package/dist/utils.js +21 -0
  61. package/dist/utils.js.map +1 -0
  62. package/package.json +44 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseResponse.d.ts","sourceRoot":"","sources":["../../src/reviewer/parseResponse.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAuEtC;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,SAAS,MAAM,KAAG,UAAU,GAAG,IAmB9D,CAAC"}
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ /**
3
+ * AI 响应解析器(共享模块)
4
+ * 兼容代码块包裹、非法控制字符等常见问题
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.parseAIResponse = void 0;
8
+ const stripFences = (s) => (s ?? "")
9
+ .replace(/^```(?:json)?\s*/i, "")
10
+ .replace(/```$/i, "")
11
+ .trim();
12
+ const extractJsonObject = (s) => {
13
+ const text = stripFences(s);
14
+ const start = text.indexOf("{");
15
+ const end = text.lastIndexOf("}");
16
+ if (start >= 0 && end > start)
17
+ return text.slice(start, end + 1);
18
+ return text;
19
+ };
20
+ /**
21
+ * 修复 JSON 字符串字面量中的非法控制字符(未转义的 \n/\r/\t 或其他 0x00-0x1F)
22
+ * 典型症状:SyntaxError: Bad control character in string literal
23
+ */
24
+ const escapeControlCharsInJsonStrings = (json) => {
25
+ let out = "";
26
+ let inString = false;
27
+ let escape = false;
28
+ for (let i = 0; i < json.length; i++) {
29
+ const ch = json[i];
30
+ if (!inString) {
31
+ if (ch === '"')
32
+ inString = true;
33
+ out += ch;
34
+ continue;
35
+ }
36
+ // inString === true
37
+ if (escape) {
38
+ out += ch;
39
+ escape = false;
40
+ continue;
41
+ }
42
+ if (ch === "\\") {
43
+ out += ch;
44
+ escape = true;
45
+ continue;
46
+ }
47
+ if (ch === '"') {
48
+ out += ch;
49
+ inString = false;
50
+ continue;
51
+ }
52
+ const code = ch.charCodeAt(0);
53
+ if (code < 0x20) {
54
+ // JSON 字符串内不允许出现裸控制字符,必须转义
55
+ if (ch === "\n")
56
+ out += "\\n";
57
+ else if (ch === "\r")
58
+ out += "\\r";
59
+ else if (ch === "\t")
60
+ out += "\\t";
61
+ else if (ch === "\b")
62
+ out += "\\b";
63
+ else if (ch === "\f")
64
+ out += "\\f";
65
+ else
66
+ out += `\\u${code.toString(16).padStart(4, "0")}`;
67
+ continue;
68
+ }
69
+ out += ch;
70
+ }
71
+ return out;
72
+ };
73
+ /**
74
+ * 解析 AI 返回的 JSON(兼容代码块包裹)
75
+ */
76
+ const parseAIResponse = (content) => {
77
+ console.error("[reviewer] AI 返回内容:", content);
78
+ const contentText = extractJsonObject(content);
79
+ try {
80
+ return JSON.parse(contentText);
81
+ }
82
+ catch (parseError) {
83
+ // 尝试修复常见"字符串内控制字符未转义"问题后再解析
84
+ try {
85
+ const repaired = escapeControlCharsInJsonStrings(contentText);
86
+ return JSON.parse(repaired);
87
+ }
88
+ catch (parseError2) {
89
+ console.error("[reviewer] AI 返回内容 JSON 解析失败");
90
+ console.error("[reviewer] 原始内容:", content);
91
+ console.error(parseError2);
92
+ return null;
93
+ }
94
+ }
95
+ };
96
+ exports.parseAIResponse = parseAIResponse;
97
+ //# sourceMappingURL=parseResponse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseResponse.js","sourceRoot":"","sources":["../../src/reviewer/parseResponse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * 简单的 glob -> RegExp 转换,只覆盖当前项目常用模式:
3
+ *
4
+ * 支持的模式示例(覆盖当前默认 ignore 规则的需求):
5
+ * - 任意目录下的某类文件,例如 `src/foo.test.ts`
6
+ * - 某个目录及其子目录下的任意文件,例如 `dist/a/b.js`
7
+ * - 当前目录下的某类文件名,例如 `.aicodereviews.config.js`
8
+ */
9
+ export declare const globToRegExp: (pattern: string) => RegExp;
10
+ export declare const matchGlob: (filePath: string, pattern: string) => boolean;
11
+ export declare const shouldIgnoreFile: (filePath: string, ignorePatterns: string[] | undefined) => boolean;
12
+ /**
13
+ * 根据 ignore 规则过滤 diff 中的文件:
14
+ * - 通过 `diff --git a/xxx b/xxx` 识别每个文件的 diff 块
15
+ * - 命中 ignore 的文件整块跳过
16
+ */
17
+ export declare const filterDiffByIgnore: (diff: string, ignorePatterns: string[] | undefined) => string;
18
+ /**
19
+ * 将完整 diff 按文件拆分为独立的 diff 块
20
+ * - 通过 `diff --git a/xxx b/xxx` 识别每个文件的边界
21
+ * - 返回 { file, diff } 数组,file 为不带 a/b/ 前缀的路径
22
+ */
23
+ export type FileDiffChunk = {
24
+ file: string;
25
+ diff: string;
26
+ };
27
+ export declare const splitDiffByFile: (diff: string) => FileDiffChunk[];
28
+ /**
29
+ * 将 diff 中所有新增行汇总成“可评论行索引”文本,帮助模型精确选择 line。
30
+ * 为避免 prompt 过大,默认最多输出 maxLines 条新增行索引。
31
+ */
32
+ export declare const buildAddedLinesIndexText: (diff: string, maxLines?: number) => string;
33
+ /**
34
+ * 将 AI 返回的 file/line 纠偏到“diff 中真实存在的新增行”:
35
+ * - 优先用 comment.code(目标行内容)做匹配
36
+ * - 兜底用 comment.line 找最近的新增行
37
+ * - 若找不到对应文件或该文件无新增行,直接丢弃该条评论(避免错贴到无关代码)
38
+ */
39
+ export declare const alignCommentsToDiffAddedLines: <T extends {
40
+ file: string;
41
+ line: number;
42
+ code?: string;
43
+ }>(diff: string, comments: T[]) => T[];
44
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/reviewer/utils.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,GAAI,SAAS,MAAM,KAAG,MAwB9C,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,UAAU,MAAM,EAAE,SAAS,MAAM,KAAG,OAG7D,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAC3B,UAAU,MAAM,EAChB,gBAAgB,MAAM,EAAE,GAAG,SAAS,KACnC,OAGF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAC7B,MAAM,MAAM,EACZ,gBAAgB,MAAM,EAAE,GAAG,SAAS,KACnC,MAiEF,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,KAAG,aAAa,EAqC3D,CAAC;AA2JF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GACnC,MAAM,MAAM,EACZ,iBAAe,KACd,MAuBF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,GACxC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EAEvD,MAAM,MAAM,EACZ,UAAU,CAAC,EAAE,KACZ,CAAC,EAwHH,CAAC"}
@@ -0,0 +1,392 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.alignCommentsToDiffAddedLines = exports.buildAddedLinesIndexText = exports.splitDiffByFile = exports.filterDiffByIgnore = exports.shouldIgnoreFile = exports.matchGlob = exports.globToRegExp = void 0;
4
+ /**
5
+ * 简单的 glob -> RegExp 转换,只覆盖当前项目常用模式:
6
+ *
7
+ * 支持的模式示例(覆盖当前默认 ignore 规则的需求):
8
+ * - 任意目录下的某类文件,例如 `src/foo.test.ts`
9
+ * - 某个目录及其子目录下的任意文件,例如 `dist/a/b.js`
10
+ * - 当前目录下的某类文件名,例如 `.aicodereviews.config.js`
11
+ */
12
+ const globToRegExp = (pattern) => {
13
+ // 1) 目录前缀匹配:例如 dist/**、node_modules/**
14
+ if (pattern.endsWith("/**")) {
15
+ const prefix = pattern.slice(0, -3); // 去掉末尾的 "/**"
16
+ const escapedPrefix = prefix.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
17
+ // 以该目录开头的任意子路径
18
+ return new RegExp(`^${escapedPrefix}/.*$`);
19
+ }
20
+ // 2) 任意目录下的某类文件:例如 **/*.test.ts
21
+ if (pattern.startsWith("**/")) {
22
+ const rest = pattern.slice(3); // 去掉前缀 "**/"
23
+ const escapedRest = rest
24
+ .replace(/[.+?^${}()|[\]\\]/g, "\\$&")
25
+ .replace(/\*/g, "[^/]*");
26
+ // 前面可以有任意目录(或没有目录),后面是文件名规则
27
+ return new RegExp(`^(?:.*/)?${escapedRest}$`);
28
+ }
29
+ // 3) 普通的 *.ext 之类的模式(不跨目录)
30
+ const escaped = pattern
31
+ .replace(/[.+?^${}()|[\]\\]/g, "\\$&")
32
+ .replace(/\*/g, "[^/]*");
33
+ return new RegExp(`^${escaped}$`);
34
+ };
35
+ exports.globToRegExp = globToRegExp;
36
+ const matchGlob = (filePath, pattern) => {
37
+ const re = (0, exports.globToRegExp)(pattern);
38
+ return re.test(filePath);
39
+ };
40
+ exports.matchGlob = matchGlob;
41
+ const shouldIgnoreFile = (filePath, ignorePatterns) => {
42
+ if (!ignorePatterns || ignorePatterns.length === 0)
43
+ return false;
44
+ return ignorePatterns.some((p) => (0, exports.matchGlob)(filePath, p));
45
+ };
46
+ exports.shouldIgnoreFile = shouldIgnoreFile;
47
+ /**
48
+ * 根据 ignore 规则过滤 diff 中的文件:
49
+ * - 通过 `diff --git a/xxx b/xxx` 识别每个文件的 diff 块
50
+ * - 命中 ignore 的文件整块跳过
51
+ */
52
+ const filterDiffByIgnore = (diff, ignorePatterns) => {
53
+ if (!ignorePatterns || ignorePatterns.length === 0 || !diff.trim()) {
54
+ return diff;
55
+ }
56
+ const lines = diff.split("\n");
57
+ const kept = [];
58
+ // 记录哪些文件会被 CR,哪些文件会被忽略
59
+ const reviewedFiles = new Set();
60
+ const ignoredFiles = new Set();
61
+ let currentFile = null;
62
+ let ignoreCurrent = false;
63
+ for (const line of lines) {
64
+ if (line.startsWith("diff --git ")) {
65
+ // 新文件块开始,先重置状态
66
+ currentFile = null;
67
+ ignoreCurrent = false;
68
+ const match = /^diff --git a\/(.+?) b\/(.+)$/.exec(line);
69
+ if (match) {
70
+ // 通常 a/ 和 b/ 路径相同,使用 b/ 路径
71
+ currentFile = match[2];
72
+ ignoreCurrent = (0, exports.shouldIgnoreFile)(currentFile, ignorePatterns);
73
+ if (currentFile) {
74
+ if (ignoreCurrent) {
75
+ ignoredFiles.add(currentFile);
76
+ }
77
+ else {
78
+ reviewedFiles.add(currentFile);
79
+ }
80
+ }
81
+ }
82
+ if (!ignoreCurrent) {
83
+ kept.push(line);
84
+ }
85
+ continue;
86
+ }
87
+ if (ignoreCurrent) {
88
+ // 当前文件被 ignore,整块 diff 跳过直到下一个 diff --git
89
+ continue;
90
+ }
91
+ kept.push(line);
92
+ }
93
+ // 输出日志到 stderr,不影响 stdout 的 JSON 结果
94
+ if (reviewedFiles.size > 0) {
95
+ console.error("[reviewer] 本次参与 CR 的文件:", Array.from(reviewedFiles).join(", "));
96
+ }
97
+ if (ignoredFiles.size > 0) {
98
+ console.error("[reviewer] 本次被 ignore 的文件:", Array.from(ignoredFiles).join(", "));
99
+ }
100
+ return kept.join("\n");
101
+ };
102
+ exports.filterDiffByIgnore = filterDiffByIgnore;
103
+ const splitDiffByFile = (diff) => {
104
+ if (!diff || !diff.trim())
105
+ return [];
106
+ const lines = diff.split("\n");
107
+ const chunks = [];
108
+ let currentFile = null;
109
+ let currentLines = [];
110
+ const flush = () => {
111
+ if (currentFile && currentLines.length > 0) {
112
+ chunks.push({ file: currentFile, diff: currentLines.join("\n") });
113
+ }
114
+ currentFile = null;
115
+ currentLines = [];
116
+ };
117
+ for (const line of lines) {
118
+ if (line.startsWith("diff --git ")) {
119
+ // 遇到新文件块,先把上一个文件的 diff 保存
120
+ flush();
121
+ const match = /^diff --git a\/(.+?) b\/(.+)$/.exec(line);
122
+ if (match) {
123
+ currentFile = match[2];
124
+ }
125
+ currentLines.push(line);
126
+ continue;
127
+ }
128
+ currentLines.push(line);
129
+ }
130
+ // 最后一个文件块
131
+ flush();
132
+ return chunks;
133
+ };
134
+ exports.splitDiffByFile = splitDiffByFile;
135
+ const normalizeDiffPath = (p) => p
136
+ .trim()
137
+ .replace(/^[ab]\//, "")
138
+ .replace(/^\.\//, "");
139
+ const normalizeLineForMatch = (s) => (s ?? "").replace(/\r/g, "").trim().replace(/\s+/g, " ");
140
+ const diceCoefficientBigram = (a, b) => {
141
+ const s1 = normalizeLineForMatch(a);
142
+ const s2 = normalizeLineForMatch(b);
143
+ if (!s1 && !s2)
144
+ return 1;
145
+ if (!s1 || !s2)
146
+ return 0;
147
+ if (s1 === s2)
148
+ return 1;
149
+ if (s1.length < 2 || s2.length < 2)
150
+ return 0;
151
+ const bigrams = (s) => {
152
+ const m = new Map();
153
+ for (let i = 0; i < s.length - 1; i++) {
154
+ const bg = s.slice(i, i + 2);
155
+ m.set(bg, (m.get(bg) ?? 0) + 1);
156
+ }
157
+ return m;
158
+ };
159
+ const b1 = bigrams(s1);
160
+ const b2 = bigrams(s2);
161
+ let intersection = 0;
162
+ for (const [bg, c1] of b1) {
163
+ const c2 = b2.get(bg) ?? 0;
164
+ intersection += Math.min(c1, c2);
165
+ }
166
+ const total = s1.length - 1 + (s2.length - 1);
167
+ return (2 * intersection) / total;
168
+ };
169
+ const parseUnifiedDiffAddedLines = (diff) => {
170
+ const files = new Map();
171
+ const lines = (diff ?? "").split("\n");
172
+ let currentFile = null;
173
+ let inHunk = false;
174
+ let oldLine = 0;
175
+ let newLine = 0;
176
+ const ensureFile = (filePath) => {
177
+ const key = normalizeDiffPath(filePath);
178
+ const existing = files.get(key);
179
+ if (existing)
180
+ return existing;
181
+ const created = {
182
+ file: key,
183
+ added: [],
184
+ addedByLine: new Map(),
185
+ };
186
+ files.set(key, created);
187
+ return created;
188
+ };
189
+ for (const raw of lines) {
190
+ const lineText = raw ?? "";
191
+ if (lineText.startsWith("diff --git ")) {
192
+ inHunk = false;
193
+ oldLine = 0;
194
+ newLine = 0;
195
+ currentFile = null;
196
+ const m = /^diff --git a\/(.+?) b\/(.+)$/.exec(lineText);
197
+ if (m) {
198
+ currentFile = normalizeDiffPath(m[2]);
199
+ ensureFile(currentFile);
200
+ }
201
+ continue;
202
+ }
203
+ // Prefer "+++ b/xxx" as the canonical path when present (rename/new file cases)
204
+ if (lineText.startsWith("+++ ")) {
205
+ // deleted file: "+++ /dev/null"
206
+ if (lineText.startsWith("+++ /dev/null")) {
207
+ currentFile = null;
208
+ continue;
209
+ }
210
+ const m = /^\+\+\+\s+b\/(.+)$/.exec(lineText);
211
+ if (m) {
212
+ currentFile = normalizeDiffPath(m[1]);
213
+ ensureFile(currentFile);
214
+ }
215
+ continue;
216
+ }
217
+ if (lineText.startsWith("@@")) {
218
+ // @@ -oldStart,oldLen +newStart,newLen @@
219
+ const m = /^@@\s+\-(\d+)(?:,(\d+))?\s+\+(\d+)(?:,(\d+))?\s+@@/.exec(lineText);
220
+ if (!m) {
221
+ inHunk = false;
222
+ continue;
223
+ }
224
+ inHunk = true;
225
+ oldLine = Number(m[1]) || 0;
226
+ newLine = Number(m[3]) || 0;
227
+ continue;
228
+ }
229
+ if (!inHunk || !currentFile) {
230
+ continue;
231
+ }
232
+ // hunk body
233
+ if (lineText.startsWith("+") && !lineText.startsWith("+++")) {
234
+ const idx = ensureFile(currentFile);
235
+ const content = lineText.slice(1);
236
+ idx.added.push({ line: newLine, content });
237
+ idx.addedByLine.set(newLine, content);
238
+ newLine += 1;
239
+ continue;
240
+ }
241
+ if (lineText.startsWith("-") && !lineText.startsWith("---")) {
242
+ oldLine += 1;
243
+ continue;
244
+ }
245
+ if (lineText.startsWith(" ")) {
246
+ oldLine += 1;
247
+ newLine += 1;
248
+ continue;
249
+ }
250
+ // "" or other metadata
251
+ }
252
+ return files;
253
+ };
254
+ /**
255
+ * 将 diff 中所有新增行汇总成“可评论行索引”文本,帮助模型精确选择 line。
256
+ * 为避免 prompt 过大,默认最多输出 maxLines 条新增行索引。
257
+ */
258
+ const buildAddedLinesIndexText = (diff, maxLines = 5000) => {
259
+ const files = parseUnifiedDiffAddedLines(diff);
260
+ const rows = [];
261
+ let emitted = 0;
262
+ for (const [, idx] of files) {
263
+ for (const item of idx.added) {
264
+ if (emitted >= maxLines)
265
+ break;
266
+ rows.push(`[${idx.file}:${item.line}] ${item.content}`);
267
+ emitted += 1;
268
+ }
269
+ if (emitted >= maxLines)
270
+ break;
271
+ }
272
+ if (rows.length === 0) {
273
+ return "(diff 中未检测到可评论的新增行)";
274
+ }
275
+ if (emitted >= maxLines) {
276
+ rows.push(`(注意:仅展示前 ${maxLines} 条新增行索引,后续新增行未展开)`);
277
+ }
278
+ return rows.join("\n");
279
+ };
280
+ exports.buildAddedLinesIndexText = buildAddedLinesIndexText;
281
+ /**
282
+ * 将 AI 返回的 file/line 纠偏到“diff 中真实存在的新增行”:
283
+ * - 优先用 comment.code(目标行内容)做匹配
284
+ * - 兜底用 comment.line 找最近的新增行
285
+ * - 若找不到对应文件或该文件无新增行,直接丢弃该条评论(避免错贴到无关代码)
286
+ */
287
+ const alignCommentsToDiffAddedLines = (diff, comments) => {
288
+ if (!Array.isArray(comments) || comments.length === 0)
289
+ return [];
290
+ const files = parseUnifiedDiffAddedLines(diff);
291
+ const pickNearestByLine = (candidates, target) => {
292
+ let best = candidates[0];
293
+ let bestDist = Math.abs(best.line - target);
294
+ for (let i = 1; i < candidates.length; i++) {
295
+ const d = Math.abs(candidates[i].line - target);
296
+ if (d < bestDist) {
297
+ best = candidates[i];
298
+ bestDist = d;
299
+ }
300
+ }
301
+ return best;
302
+ };
303
+ const pickBestByCode = (candidates, code, preferredLine) => {
304
+ const target = normalizeLineForMatch(code);
305
+ // 1) exact match first
306
+ const exact = [];
307
+ for (const cand of candidates) {
308
+ if (normalizeLineForMatch(cand.content) === target) {
309
+ exact.push(cand);
310
+ }
311
+ }
312
+ if (exact.length === 1)
313
+ return exact[0];
314
+ if (exact.length > 1) {
315
+ if (preferredLine != null && Number.isFinite(preferredLine)) {
316
+ return pickNearestByLine(exact, preferredLine);
317
+ }
318
+ return exact[0];
319
+ }
320
+ // 2) contains heuristic
321
+ const contains = [];
322
+ for (const cand of candidates) {
323
+ const n = normalizeLineForMatch(cand.content);
324
+ if (!n)
325
+ continue;
326
+ if (n.includes(target) || target.includes(n)) {
327
+ contains.push({ cand, score: 0.9 });
328
+ }
329
+ }
330
+ if (contains.length === 1)
331
+ return contains[0].cand;
332
+ if (contains.length > 1) {
333
+ if (preferredLine != null && Number.isFinite(preferredLine)) {
334
+ return pickNearestByLine(contains.map((x) => x.cand), preferredLine);
335
+ }
336
+ return contains[0].cand;
337
+ }
338
+ // 3) fuzzy by dice coefficient
339
+ let best = null;
340
+ let bestScore = 0;
341
+ for (const cand of candidates) {
342
+ const score = diceCoefficientBigram(cand.content, code);
343
+ if (score > bestScore) {
344
+ bestScore = score;
345
+ best = cand;
346
+ }
347
+ }
348
+ // 阈值:过低的匹配宁愿不信,用 line 兜底
349
+ if (best && bestScore >= 0.55)
350
+ return best;
351
+ return null;
352
+ };
353
+ const aligned = [];
354
+ for (const c of comments) {
355
+ if (!c || !c.file)
356
+ continue;
357
+ const normalizedFile = normalizeDiffPath(c.file);
358
+ const idx = files.get(normalizedFile);
359
+ if (!idx || idx.added.length === 0) {
360
+ continue;
361
+ }
362
+ const preferredLine = typeof c.line === "number" && Number.isFinite(c.line) ? c.line : null;
363
+ let chosen = null;
364
+ if (typeof c.code === "string") {
365
+ chosen = pickBestByCode(idx.added, c.code, preferredLine);
366
+ }
367
+ if (!chosen) {
368
+ // 兜底:line 恰好命中新增行
369
+ if (preferredLine != null && idx.addedByLine.has(preferredLine)) {
370
+ chosen = {
371
+ line: preferredLine,
372
+ content: idx.addedByLine.get(preferredLine) ?? "",
373
+ };
374
+ }
375
+ else if (preferredLine != null) {
376
+ chosen = pickNearestByLine(idx.added, preferredLine);
377
+ }
378
+ else {
379
+ chosen = idx.added[0];
380
+ }
381
+ }
382
+ aligned.push({
383
+ ...c,
384
+ file: normalizedFile,
385
+ line: chosen.line,
386
+ // 保留 code(如果模型提供);若没提供则不要擅自填充,避免误导下游
387
+ });
388
+ }
389
+ return aligned;
390
+ };
391
+ exports.alignCommentsToDiffAddedLines = alignCommentsToDiffAddedLines;
392
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/reviewer/utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * 代码改动汇总模块
3
+ * 基于 git diff 生成结构化的 Markdown 改动摘要,输出纯文本供 CI 脚本发布到 GitLab MR
4
+ */
5
+ import { CodeReviewConfig } from "../types";
6
+ /**
7
+ * 生成代码改动汇总,返回纯 Markdown 文本(由 CI 脚本通过 GitLab API 发布)
8
+ */
9
+ export declare const generateSummary: (diff: string, config: CodeReviewConfig) => Promise<string | null>;
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/summarizer/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAmH5C;;GAEG;AACH,eAAO,MAAM,eAAe,GAC1B,MAAM,MAAM,EACZ,QAAQ,gBAAgB,KACvB,OAAO,CAAC,MAAM,GAAG,IAAI,CAoCvB,CAAC"}