gitlab-ai-review 3.9.1 → 4.0.1

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/index.js CHANGED
@@ -205,19 +205,53 @@ export class GitLabAIReview {
205
205
  // 调用 AI 一次性审查整个文件的所有变更(按文件批量)
206
206
  const fileReview = await this.reviewFileChanges(change, meaningfulChanges);
207
207
 
208
+ // 智能合并修改块的评论
209
+ const mergedReviews = this.mergeModificationReviews(fileReview.reviews, meaningfulChanges);
210
+
208
211
  // 根据 AI 返回的结果,只对有问题的行添加评论
209
- for (const review of fileReview.reviews) {
212
+ for (const review of mergedReviews) {
210
213
  if (review.hasIssue) {
211
214
  try {
215
+ // 找到对应的变更
216
+ const relatedChange = meaningfulChanges.find(c =>
217
+ c.lineNumber === review.lineNumber ||
218
+ c.lineNumber === review.oldLine ||
219
+ c.lineNumber === review.newLine
220
+ );
221
+
222
+ // 构建评论位置参数
223
+ const positionParams = {
224
+ filePath: fileName,
225
+ oldPath: change.old_path,
226
+ };
227
+
228
+ // 优先使用 hunk 的起始行(让评论定位到 diff 块的开头)
229
+ if (relatedChange && relatedChange.hunkRange) {
230
+ const isDeletion = relatedChange.type === 'deletion';
231
+ if (isDeletion) {
232
+ positionParams.oldLine = relatedChange.hunkRange.oldStart;
233
+ } else {
234
+ positionParams.newLine = relatedChange.hunkRange.newStart;
235
+ }
236
+ } else if (review.oldLine && review.newLine) {
237
+ // 修改块:同时指定两个行号
238
+ positionParams.oldLine = review.oldLine;
239
+ positionParams.newLine = review.newLine;
240
+ } else if (review.lineNumber) {
241
+ // 单独的删除或新增(fallback)
242
+ const isDeletion = relatedChange && relatedChange.type === 'deletion';
243
+ if (isDeletion) {
244
+ positionParams.oldLine = review.lineNumber;
245
+ } else {
246
+ positionParams.newLine = review.lineNumber;
247
+ }
248
+ }
249
+
212
250
  const commentResult = await this.gitlabClient.createLineComment(
213
251
  this.config.project.projectId,
214
252
  this.config.project.mergeRequestIid,
215
253
  `🤖 **AI 代码审查**\n\n${review.comment}`,
216
- {
217
- filePath: fileName,
218
- oldPath: change.old_path,
219
- newLine: review.lineNumber,
220
- }
254
+ positionParams
221
255
  );
222
256
 
223
257
  results.push({
@@ -464,19 +498,33 @@ export class GitLabAIReview {
464
498
  for (const review of mergedReviews) {
465
499
  if (review.hasIssue) {
466
500
  try {
501
+ // 找到对应的变更
502
+ const relatedChange = meaningfulChanges.find(c =>
503
+ c.lineNumber === review.lineNumber ||
504
+ c.lineNumber === review.oldLine ||
505
+ c.lineNumber === review.newLine
506
+ );
507
+
467
508
  // 构建评论位置参数
468
509
  const positionParams = {
469
510
  filePath: fileName,
470
511
  oldPath: change.old_path,
471
512
  };
472
513
 
473
- // 如果是修改块(同时有 oldLine newLine),同时指定两个行号
474
- if (review.oldLine && review.newLine) {
514
+ // 优先使用 hunk 的起始行(让评论定位到 diff 块的开头)
515
+ if (relatedChange && relatedChange.hunkRange) {
516
+ const isDeletion = relatedChange.type === 'deletion';
517
+ if (isDeletion) {
518
+ positionParams.oldLine = relatedChange.hunkRange.oldStart;
519
+ } else {
520
+ positionParams.newLine = relatedChange.hunkRange.newStart;
521
+ }
522
+ } else if (review.oldLine && review.newLine) {
523
+ // 修改块:同时指定两个行号
475
524
  positionParams.oldLine = review.oldLine;
476
525
  positionParams.newLine = review.newLine;
477
526
  } else if (review.lineNumber) {
478
- // 单独的删除或新增
479
- const relatedChange = meaningfulChanges.find(c => c.lineNumber === review.lineNumber);
527
+ // 单独的删除或新增(fallback)
480
528
  const isDeletion = relatedChange && relatedChange.type === 'deletion';
481
529
  if (isDeletion) {
482
530
  positionParams.oldLine = review.lineNumber;
@@ -128,6 +128,12 @@ export function extractMeaningfulChanges(hunks) {
128
128
  content: change.content,
129
129
  lineNumber: currentNewLine,
130
130
  hunk: hunk.header,
131
+ hunkRange: { // 添加 hunk 的范围信息
132
+ oldStart: hunk.oldStart,
133
+ oldEnd: hunk.oldStart + hunk.oldLines - 1,
134
+ newStart: hunk.newStart,
135
+ newEnd: hunk.newStart + hunk.newLines - 1,
136
+ },
131
137
  context: {
132
138
  before: hunk.changes.slice(Math.max(0, index - 2), index).map(c => c.content),
133
139
  after: hunk.changes.slice(index + 1, index + 3).map(c => c.content),
@@ -144,6 +150,12 @@ export function extractMeaningfulChanges(hunks) {
144
150
  content: change.content,
145
151
  lineNumber: currentOldLine, // 使用旧文件的行号
146
152
  hunk: hunk.header,
153
+ hunkRange: { // 添加 hunk 的范围信息
154
+ oldStart: hunk.oldStart,
155
+ oldEnd: hunk.oldStart + hunk.oldLines - 1,
156
+ newStart: hunk.newStart,
157
+ newEnd: hunk.newStart + hunk.newLines - 1,
158
+ },
147
159
  context: {
148
160
  before: hunk.changes.slice(Math.max(0, index - 2), index).map(c => c.content),
149
161
  after: hunk.changes.slice(index + 1, index + 3).map(c => c.content),
@@ -92,7 +92,7 @@ export class GitLabClient {
92
92
  old_path: lineInfo.oldPath || lineInfo.filePath,
93
93
  };
94
94
 
95
- // 设置行号
95
+ // 设置行号(只能设置其中一个,或者两个都设置表示修改块)
96
96
  if (lineInfo.newLine !== undefined) {
97
97
  position.new_line = lineInfo.newLine;
98
98
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitlab-ai-review",
3
- "version": "3.9.1",
3
+ "version": "4.0.1",
4
4
  "description": "GitLab AI Review SDK with Impact Analysis - 支持影响分析、删除符号检测、注释代码识别、文件内部冲突检查、智能文件过滤的智能代码审查工具",
5
5
  "main": "index.js",
6
6
  "type": "module",