gitlab-ai-review 2.5.3 → 3.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.
@@ -28,90 +28,244 @@ export function buildSystemPrompt(projectPrompt = '') {
28
28
  }
29
29
 
30
30
  /**
31
- * 构建整个文件所有变更行的批量审查提示词(按 hunk 组织)
31
+ * 构建整个文件所有变更行的批量审查提示词
32
32
  * @param {string} fileName - 文件名
33
33
  * @param {Array} meaningfulChanges - 有意义的变更数组
34
- * @param {Array} hunkGroups - 按 hunk 分组的变更数组
35
34
  * @param {string} projectPrompt - 项目配置的 prompt
36
35
  * @returns {string} 批量审查提示词
37
36
  */
38
- export function buildFileReviewPrompt(fileName, meaningfulChanges, hunkGroups) {
39
- const totalAdditions = meaningfulChanges.filter(c => c.type === 'addition').length;
40
- const totalDeletions = meaningfulChanges.filter(c => c.type === 'deletion').length;
41
-
42
- let prompt = `请审查以下文件的代码变更,只对**有问题的新增行**提出审查意见。
37
+ export function buildFileReviewPrompt(fileName, meaningfulChanges) {
38
+ let prompt = `请审查以下文件的代码变更,只对**有问题的行**提出审查意见,代码没有问题的行不需要评论。
43
39
 
44
40
  **文件名**: ${fileName}
45
- **变更统计**:
46
- - 共 ${hunkGroups.length} 个代码块(hunk)
47
- - 删除了 ${totalDeletions} 行(旧代码)
48
- - 新增了 ${totalAdditions} 行(新代码)
41
+ **变更数量**: ${meaningfulChanges.length} 行
49
42
 
50
- ## 重要说明
51
- - **每个代码块都明确标注了删除内容和新增内容**
52
- - **删除的行**:标注为【删除】,是被移除的旧代码,**无需审查**
53
- - **新增的行**:标注为【新增】,是新加入的代码,**只审查这些行**
54
- - 行号是指新增行在新文件中的位置
43
+ `;
44
+
45
+ meaningfulChanges.forEach((change, index) => {
46
+ prompt += `\n### 变更 ${index + 1} - 第 ${change.lineNumber} 行\n`;
47
+ prompt += `**类型**: ${change.type === 'addition' ? '新增' : '删除'}\n`;
48
+ prompt += `**内容**:\n\`\`\`\n`;
49
+
50
+ // 上下文
51
+ if (change.context?.before?.length > 0) {
52
+ change.context.before.forEach(line => {
53
+ prompt += ` ${line}\n`;
54
+ });
55
+ }
56
+
57
+ // 变更行
58
+ prompt += `${change.type === 'addition' ? '+' : '-'} ${change.content}\n`;
59
+
60
+ // 下文
61
+ if (change.context?.after?.length > 0) {
62
+ change.context.after.forEach(line => {
63
+ prompt += ` ${line}\n`;
64
+ });
65
+ }
66
+
67
+ prompt += `\`\`\`\n`;
68
+ });
69
+
70
+ prompt += `\n## 审查要求
71
+
72
+ 1. 仔细审查每一行变更,判断是否存在问题
73
+ 2. **只对有问题的行提出审查意见**,没有问题的行不需要评论
74
+ 3. **必须使用中文**返回审查意见
75
+ 4. 返回 JSON 格式的结果,格式如下:
76
+
77
+ \`\`\`json
78
+ {
79
+ "reviews": [
80
+ {
81
+ "lineNumber": 15,
82
+ "hasIssue": true,
83
+ "comment": "这里用中文描述具体的问题和改进建议"
84
+ },
85
+ {
86
+ "lineNumber": 20,
87
+ "hasIssue": false
88
+ }
89
+ ]
90
+ }
91
+ \`\`\`
92
+
93
+ 5. 如果所有代码都没有问题,返回空的 reviews 数组:\`{"reviews": []}\`
94
+ 6. 只返回 JSON,不要包含其他文字说明
95
+ 7. comment 字段必须使用中文,要简洁明了`;
55
96
 
56
- ---
97
+ return prompt;
98
+ }
99
+
100
+ /**
101
+ * 构建整个文件批量审查的完整消息数组
102
+ * @param {string} fileName - 文件名
103
+ * @param {Array} meaningfulChanges - 有意义的变更数组
104
+ * @param {string} projectPrompt - 项目配置的 prompt
105
+ * @returns {Array} 消息数组
106
+ */
107
+ export function buildFileReviewMessages(fileName, meaningfulChanges, projectPrompt = '') {
108
+ return [
109
+ { role: 'system', content: buildSystemPrompt(projectPrompt) },
110
+ { role: 'user', content: buildFileReviewPrompt(fileName, meaningfulChanges) },
111
+ ];
112
+ }
113
+
114
+ /**
115
+ * 构建包含影响分析的审查提示词
116
+ * @param {string} fileName - 文件名
117
+ * @param {Array} meaningfulChanges - 有意义的变更数组
118
+ * @param {Object} impactAnalysis - 影响分析结果
119
+ * @returns {string} 审查提示词
120
+ */
121
+ export function buildFileReviewWithImpactPrompt(fileName, meaningfulChanges, impactAnalysis) {
122
+ let prompt = `请审查以下文件的代码变更,只对**有问题的行**提出审查意见,代码没有问题的行不需要评论。
123
+
124
+ **文件名**: ${fileName}
125
+ **变更数量**: ${meaningfulChanges.length} 行
57
126
 
58
127
  `;
59
128
 
60
- // 按 hunk 展示变更
61
- hunkGroups.forEach((hunk, hunkIndex) => {
62
- prompt += `## 代码块 ${hunkIndex + 1}:${hunk.header}\n\n`;
129
+ // 添加影响分析信息
130
+ if (impactAnalysis && !impactAnalysis.error) {
131
+ prompt += `\n## 🔍 影响分析\n\n`;
63
132
 
64
- // 展示删除的内容
65
- if (hunk.deletions.length > 0) {
66
- prompt += `### 📝 该代码块中删除的内容(无需审查)\n\n`;
67
- hunk.deletions.forEach((change, index) => {
68
- prompt += `\`\`\`\n`;
69
- // 上下文
70
- if (change.context?.before?.length > 0 && index === 0) {
71
- change.context.before.forEach(line => {
72
- prompt += ` ${line}\n`;
133
+ // 变更的符号统计
134
+ if (impactAnalysis.changedSymbols) {
135
+ const { added, deleted, modified } = impactAnalysis.changedSymbols;
136
+
137
+ if (added.length > 0 || deleted.length > 0 || modified.length > 0) {
138
+ prompt += `**符号变更统计**:\n`;
139
+ if (added.length > 0) {
140
+ prompt += `- 新增: ${added.length} 个\n`;
141
+ }
142
+ if (deleted.length > 0) {
143
+ prompt += `- 删除: ${deleted.length} 个 ⚠️\n`;
144
+ }
145
+ if (modified.length > 0) {
146
+ prompt += `- 修改: ${modified.length} 个 ⚠️\n`;
147
+ }
148
+ prompt += `\n`;
149
+ }
150
+
151
+ // 被删除的符号详情
152
+ if (deleted.length > 0) {
153
+ const deletedDefs = deleted.filter(s => s.type === 'definition');
154
+ if (deletedDefs.length > 0) {
155
+ prompt += `**⚠️ 被删除的函数/类/组件** (${deletedDefs.length} 个):\n`;
156
+ deletedDefs.slice(0, 10).forEach(symbol => {
157
+ prompt += `- \`${symbol.name}\`\n`;
73
158
  });
159
+ prompt += `\n`;
74
160
  }
75
- // 删除的行
76
- prompt += `【删除】${change.content}\n`;
77
- prompt += `\`\`\`\n\n`;
161
+ }
162
+
163
+ // 新增或修改的符号
164
+ const changedDefs = [...added, ...modified].filter(s => s.type === 'definition');
165
+ if (changedDefs.length > 0) {
166
+ prompt += `**新增/修改的函数/类/组件** (${changedDefs.length} 个):\n`;
167
+ changedDefs.slice(0, 10).forEach(symbol => {
168
+ prompt += `- \`${symbol.name}\`\n`;
169
+ });
170
+ prompt += `\n`;
171
+ }
172
+ }
173
+
174
+ // 文件内部使用情况(重要!)
175
+ if (impactAnalysis.internalUsage && impactAnalysis.internalUsage.length > 0) {
176
+ prompt += `**🚨 文件内部冲突** (${impactAnalysis.internalUsage.length} 处):\n`;
177
+ prompt += `当前文件内部仍在使用已删除的符号,将导致运行时错误:\n\n`;
178
+
179
+ impactAnalysis.internalUsage.slice(0, 5).forEach((usage, index) => {
180
+ prompt += `${index + 1}. 第 ${usage.lineNumber} 行使用了被删除的 \`${usage.symbol}\`:\n`;
181
+ prompt += `\`\`\`javascript\n${usage.line}\n\`\`\`\n`;
182
+ });
183
+
184
+ if (impactAnalysis.internalUsage.length > 5) {
185
+ prompt += `... 还有 ${impactAnalysis.internalUsage.length - 5} 处\n`;
186
+ }
187
+ prompt += `\n`;
188
+ }
189
+
190
+ // 函数签名
191
+ if (impactAnalysis.signatures && impactAnalysis.signatures.length > 0) {
192
+ prompt += `**函数/类签名**:\n`;
193
+ impactAnalysis.signatures.forEach(sig => {
194
+ prompt += `\`\`\`javascript\n${sig.signature}\n\`\`\`\n`;
78
195
  });
196
+ prompt += `\n`;
79
197
  }
80
198
 
81
- // 展示新增的内容
82
- if (hunk.additions.length > 0) {
83
- prompt += `### 该代码块中新增的内容(**请审查**)\n\n`;
84
- hunk.additions.forEach((change, index) => {
85
- prompt += `\`\`\`\n`;
86
- // 上下文
87
- if (change.context?.before?.length > 0 && index === 0) {
88
- change.context.before.forEach(line => {
89
- prompt += ` ${line}\n`;
199
+ // 受影响的其他文件
200
+ if (impactAnalysis.affectedFiles && impactAnalysis.affectedFiles.length > 0) {
201
+ prompt += `**其他受影响的文件** (${impactAnalysis.totalAffectedFiles || impactAnalysis.affectedFiles.length} 个`;
202
+ if (impactAnalysis.totalAffectedFiles > impactAnalysis.affectedFiles.length) {
203
+ prompt += `,显示前 ${impactAnalysis.affectedFiles.length} 个`;
204
+ }
205
+ prompt += `):\n\n`;
206
+
207
+ impactAnalysis.affectedFiles.forEach((file, index) => {
208
+ prompt += `### ${index + 1}. ${file.path}\n`;
209
+ prompt += `使用的符号: ${file.symbols.join(', ')}\n`;
210
+
211
+ // 添加代码片段
212
+ if (file.snippets && file.snippets.length > 0) {
213
+ prompt += `\n**使用示例**:\n`;
214
+ file.snippets.forEach(snippet => {
215
+ prompt += `\`\`\`javascript (第 ${snippet.lineNumber} 行附近)\n`;
216
+ prompt += snippet.snippet;
217
+ prompt += `\n\`\`\`\n`;
90
218
  });
91
219
  }
92
- // 新增的行
93
- prompt += `【新增 - 第 ${change.lineNumber} 行】${change.content}\n`;
94
- prompt += `\`\`\`\n\n`;
220
+ prompt += `\n`;
95
221
  });
222
+
223
+ prompt += `---\n\n`;
96
224
  }
225
+ }
226
+
227
+ // 添加代码变更
228
+ prompt += `## 📝 代码变更\n\n`;
229
+ meaningfulChanges.forEach((change, index) => {
230
+ prompt += `### 变更 ${index + 1} - 第 ${change.lineNumber} 行\n`;
231
+ prompt += `**类型**: ${change.type === 'addition' ? '新增' : '删除'}\n`;
232
+ prompt += `**内容**:\n\`\`\`\n`;
233
+
234
+ // 上下文
235
+ if (change.context?.before?.length > 0) {
236
+ change.context.before.forEach(line => {
237
+ prompt += ` ${line}\n`;
238
+ });
239
+ }
240
+
241
+ // 变更行
242
+ prompt += `${change.type === 'addition' ? '+' : '-'} ${change.content}\n`;
97
243
 
98
- // 如果该 hunk 没有删除也没有新增
99
- if (hunk.deletions.length === 0 && hunk.additions.length === 0) {
100
- prompt += `*该代码块无实质性变更*\n\n`;
244
+ // 下文
245
+ if (change.context?.after?.length > 0) {
246
+ change.context.after.forEach(line => {
247
+ prompt += ` ${line}\n`;
248
+ });
101
249
  }
102
250
 
103
- prompt += `---\n\n`;
251
+ prompt += `\`\`\`\n`;
104
252
  });
105
253
 
106
- prompt += `## 审查要求
254
+ prompt += `\n## 审查要求
107
255
 
108
- 1. **只审查上面标注为【新增】的代码行**
109
- 2. **不要审查标注为【删除】的代码行**
110
- 3. 每个代码块的删除和新增内容已明确标注,请关注新增内容的质量
111
- 4. 判断新增的代码是否存在问题(安全、性能、逻辑、最佳实践等)
112
- 5. **只对有问题的新增行提出审查意见**,没有问题的行不需要评论
113
- 6. **必须使用中文**返回审查意见
114
- 7. 返回 JSON 格式的结果,格式如下:
256
+ 1. 仔细审查每一行变更,判断是否存在问题
257
+ 2. **🚨 最高优先级**:检查是否有符号被删除但仍被使用(文件内部或其他文件)
258
+ 3. **特别关注**:
259
+ - 删除的函数/类/组件是否在其他地方被调用
260
+ - 修改的函数签名是否会导致现有调用失效
261
+ - 新增的代码是否会影响其他文件的正常运行
262
+ 4. 检查函数签名是否改变,所有调用方式是否需要更新
263
+ 5. 检查是否有潜在的 API 不兼容问题
264
+ 6. 如果发现文件内部使用了被删除的符号,这是**严重错误**
265
+ 7. 如果发现其他文件使用了被删除/修改的符号,需要提醒可能的影响
266
+ 8. **只对有问题的行提出审查意见**,没有问题的行不需要评论
267
+ 9. **必须使用中文**返回审查意见
268
+ 10. 返回 JSON 格式的结果,格式如下:
115
269
 
116
270
  \`\`\`json
117
271
  {
@@ -129,26 +283,25 @@ export function buildFileReviewPrompt(fileName, meaningfulChanges, hunkGroups) {
129
283
  }
130
284
  \`\`\`
131
285
 
132
- 8. lineNumber 必须是新增行的行号(在【新增 - 第 X 行】中标注的行号)
133
- 9. 如果所有新增代码都没有问题,返回空的 reviews 数组:\`{"reviews": []}\`
134
- 10. 只返回 JSON,不要包含其他文字说明
135
- 11. comment 字段必须使用中文,要简洁明了`;
286
+ 11. 如果所有代码都没有问题,返回空的 reviews 数组:\`{"reviews": []}\`
287
+ 12. 只返回 JSON,不要包含其他文字说明
288
+ 13. comment 字段必须使用中文,要简洁明了,重点指出影响范围`;
136
289
 
137
290
  return prompt;
138
291
  }
139
292
 
140
293
  /**
141
- * 构建整个文件批量审查的完整消息数组
294
+ * 构建包含影响分析的完整消息数组
142
295
  * @param {string} fileName - 文件名
143
296
  * @param {Array} meaningfulChanges - 有意义的变更数组
144
- * @param {Array} hunkGroups - 按 hunk 分组的变更数组
297
+ * @param {Object} impactAnalysis - 影响分析结果
145
298
  * @param {string} projectPrompt - 项目配置的 prompt
146
299
  * @returns {Array} 消息数组
147
300
  */
148
- export function buildFileReviewMessages(fileName, meaningfulChanges, hunkGroups, projectPrompt = '') {
301
+ export function buildFileReviewWithImpactMessages(fileName, meaningfulChanges, impactAnalysis, projectPrompt = '') {
149
302
  return [
150
303
  { role: 'system', content: buildSystemPrompt(projectPrompt) },
151
- { role: 'user', content: buildFileReviewPrompt(fileName, meaningfulChanges, hunkGroups) },
304
+ { role: 'user', content: buildFileReviewWithImpactPrompt(fileName, meaningfulChanges, impactAnalysis) },
152
305
  ];
153
306
  }
154
307
 
@@ -157,5 +310,7 @@ export default {
157
310
  buildSystemPrompt,
158
311
  buildFileReviewPrompt,
159
312
  buildFileReviewMessages,
313
+ buildFileReviewWithImpactPrompt,
314
+ buildFileReviewWithImpactMessages,
160
315
  };
161
316
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gitlab-ai-review",
3
- "version": "2.5.3",
4
- "description": "GitLab AI Review SDK - 支持 SDK 调用和 CLI 执行",
3
+ "version": "3.0.0",
4
+ "description": "GitLab AI Review SDK with Impact Analysis - 支持影响分析、删除符号检测、文件内部冲突检查的智能代码审查工具",
5
5
  "main": "index.js",
6
6
  "type": "module",
7
7
  "bin": {
@@ -22,11 +22,24 @@
22
22
  "gitlab",
23
23
  "ai",
24
24
  "review",
25
+ "code-review",
25
26
  "sdk",
26
- "ci-cd"
27
+ "ci-cd",
28
+ "impact-analysis",
29
+ "static-analysis",
30
+ "merge-request",
31
+ "automation"
27
32
  ],
28
- "author": "",
33
+ "author": "Your Name <your.email@example.com>",
29
34
  "license": "MIT",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "https://github.com/yourusername/gitlab-ai-review.git"
38
+ },
39
+ "bugs": {
40
+ "url": "https://github.com/yourusername/gitlab-ai-review/issues"
41
+ },
42
+ "homepage": "https://github.com/yourusername/gitlab-ai-review#readme",
30
43
  "engines": {
31
44
  "node": ">=18.0.0"
32
45
  },