gitlab-ai-review 3.9.0 → 4.0.0

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
@@ -464,19 +464,42 @@ export class GitLabAIReview {
464
464
  for (const review of mergedReviews) {
465
465
  if (review.hasIssue) {
466
466
  try {
467
- // 构建评论位置参数
467
+ // 找到对应的变更,获取 hunk 范围
468
+ const relatedChange = meaningfulChanges.find(c =>
469
+ c.lineNumber === review.lineNumber ||
470
+ c.lineNumber === review.oldLine ||
471
+ c.lineNumber === review.newLine
472
+ );
473
+
474
+ // 构建评论位置参数,包含整个 hunk 的范围
468
475
  const positionParams = {
469
476
  filePath: fileName,
470
477
  oldPath: change.old_path,
471
478
  };
472
479
 
473
- // 如果是修改块(同时有 oldLine 和 newLine),同时指定两个行号
474
- if (review.oldLine && review.newLine) {
480
+ // 使用 hunk 的完整范围而不是单行
481
+ if (relatedChange && relatedChange.hunkRange) {
482
+ positionParams.oldLine = relatedChange.hunkRange.oldStart;
483
+ positionParams.newLine = relatedChange.hunkRange.newStart;
484
+ // 添加范围信息(GitLab 支持 line_range)
485
+ positionParams.lineRange = {
486
+ start: {
487
+ line_code: `${relatedChange.hunkRange.oldStart}_${relatedChange.hunkRange.oldStart}`,
488
+ type: 'old',
489
+ old_line: relatedChange.hunkRange.oldStart,
490
+ },
491
+ end: {
492
+ line_code: `${relatedChange.hunkRange.newEnd}_${relatedChange.hunkRange.newEnd}`,
493
+ type: 'new',
494
+ new_line: relatedChange.hunkRange.newEnd,
495
+ },
496
+ };
497
+ } else if (review.oldLine && review.newLine) {
498
+ // 修改块:同时指定两个行号
475
499
  positionParams.oldLine = review.oldLine;
476
500
  positionParams.newLine = review.newLine;
477
501
  } else if (review.lineNumber) {
478
- // 单独的删除或新增
479
- const relatedChange = meaningfulChanges.find(c => c.lineNumber === review.lineNumber);
502
+ // 单独的删除或新增(fallback)
480
503
  const isDeletion = relatedChange && relatedChange.type === 'deletion';
481
504
  if (isDeletion) {
482
505
  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,13 +92,18 @@ 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
  }
99
99
  if (lineInfo.oldLine !== undefined) {
100
100
  position.old_line = lineInfo.oldLine;
101
101
  }
102
+
103
+ // 如果提供了范围信息,使用范围评论
104
+ if (lineInfo.lineRange) {
105
+ position.line_range = lineInfo.lineRange;
106
+ }
102
107
 
103
108
  return this.request(
104
109
  `/projects/${encodeURIComponent(projectId)}/merge_requests/${mergeRequestIid}/discussions`,
@@ -210,18 +210,27 @@ export function buildFileReviewWithImpactPrompt(fileName, meaningfulChanges, imp
210
210
 
211
211
  // 文件内部使用情况(重要!)
212
212
  if (impactAnalysis.internalUsage && impactAnalysis.internalUsage.length > 0) {
213
- prompt += `**🚨 文件内部冲突** (${impactAnalysis.internalUsage.length} 处):\n`;
214
- prompt += `当前文件内部仍在使用已删除的符号,将导致运行时错误:\n\n`;
213
+ prompt += `**🚨 文件内部冲突检测** (${impactAnalysis.internalUsage.length} 处):\n`;
214
+ prompt += `当前文件内部发现以下位置使用了被删除的符号:\n\n`;
215
215
 
216
216
  impactAnalysis.internalUsage.slice(0, 5).forEach((usage, index) => {
217
- prompt += `${index + 1}. ${usage.lineNumber} 行使用了被删除的 \`${usage.symbol}\`:\n`;
217
+ const localWarning = usage.maybeLocal ? ' ⚠️ **可能有局部定义/导入**' : '';
218
+ prompt += `${index + 1}. 第 ${usage.lineNumber} 行使用了被删除的 \`${usage.symbol}\`${localWarning}:\n`;
218
219
  prompt += `\`\`\`javascript\n${usage.line}\n\`\`\`\n`;
219
220
  });
220
221
 
221
222
  if (impactAnalysis.internalUsage.length > 5) {
222
223
  prompt += `... 还有 ${impactAnalysis.internalUsage.length - 5} 处\n`;
223
224
  }
224
- prompt += `\n`;
225
+
226
+ prompt += `\n**🔍 重要:作用域分析指南**\n`;
227
+ prompt += `标记了 ⚠️ **可能有局部定义/导入** 的行,表示该行可能:\n`;
228
+ prompt += `1. 定义了局部变量(const/let/var symbol = ...)\n`;
229
+ prompt += `2. 是函数参数(function(symbol) 或 (symbol) => ...)\n`;
230
+ prompt += `3. 从其他模块导入(import { symbol } from ...)\n`;
231
+ prompt += `4. 对象属性或解构({ symbol } 或 symbol:)\n`;
232
+ prompt += `\n**对于这些标记的行,请仔细检查代码上下文,确认是否真的使用了被删除的符号。**\n`;
233
+ prompt += `**如果有局部定义或导入,则不是问题,不要报告!**\n\n`;
225
234
  }
226
235
 
227
236
  // 函数签名
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitlab-ai-review",
3
- "version": "3.9.0",
3
+ "version": "4.0.0",
4
4
  "description": "GitLab AI Review SDK with Impact Analysis - 支持影响分析、删除符号检测、注释代码识别、文件内部冲突检查、智能文件过滤的智能代码审查工具",
5
5
  "main": "index.js",
6
6
  "type": "module",