gitlab-ai-review 1.2.0 → 2.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
@@ -7,6 +7,7 @@ import { getConfig, validateConfig } from './lib/config.js';
7
7
  import { GitLabClient } from './lib/gitlab-client.js';
8
8
  import { AIClient } from './lib/ai-client.js';
9
9
  import * as PromptTools from './lib/prompt-tools.js';
10
+ import * as DiffParser from './lib/diff-parser.js';
10
11
 
11
12
  /**
12
13
  * GitLab AI Review SDK 主类
@@ -14,7 +15,7 @@ import * as PromptTools from './lib/prompt-tools.js';
14
15
  export class GitLabAIReview {
15
16
  constructor(options = {}) {
16
17
  this.name = 'GitLab AI Review SDK';
17
- this.version = '1.2.0';
18
+ this.version = '2.0.0';
18
19
 
19
20
  // 如果传入了配置,使用手动配置;否则使用自动检测
20
21
  if (options.token || options.gitlab) {
@@ -137,93 +138,89 @@ export class GitLabAIReview {
137
138
  }
138
139
 
139
140
  /**
140
- * AI 审查单个文件的代码变更
141
+ * AI 审查特定行的变更并在该行添加评论(附带项目 prompt)
141
142
  * @param {Object} change - 代码变更对象
142
- * @returns {Promise<Object>} 审查结果
143
+ * @param {Object} changeInfo - 具体的行变更信息
144
+ * @returns {Promise<Object>} 评论结果
143
145
  */
144
- async reviewCodeChange(change) {
146
+ async reviewAndCommentOnLine(change, changeInfo) {
145
147
  const aiClient = this.getAIClient();
146
- const guardConfig = this.config.ai?.guardConfig?.content || '';
148
+
149
+ // 获取项目配置的 prompt(来自 reviewguard.md)
150
+ const projectPrompt = this.config.ai?.guardConfig?.content || '';
147
151
 
148
- // 使用 PromptTools 构建消息
149
- const messages = PromptTools.buildReviewMessages({
150
- diff: change.diff,
152
+ // 构建针对特定行的审查消息(附带项目 prompt)
153
+ const messages = PromptTools.buildLineReviewMessages({
154
+ ...changeInfo,
151
155
  fileName: change.new_path || change.old_path,
152
- guardConfig,
153
- });
156
+ }, projectPrompt);
154
157
 
155
- // 调用 AI
156
- return aiClient.sendMessage(messages);
157
- }
158
-
159
- /**
160
- * AI 审查 MR 的所有代码变更
161
- * @returns {Promise<Array>} 审查结果数组
162
- */
163
- async reviewMergeRequest() {
164
- const changes = await this.getMergeRequestChanges();
165
- const aiClient = this.getAIClient();
166
- const guardConfig = this.config.ai?.guardConfig?.content || '';
158
+ // 调用 AI 审查
159
+ const review = await aiClient.sendMessage(messages);
167
160
 
168
- const reviews = [];
161
+ // 在该行添加评论
162
+ const lineInfo = {
163
+ filePath: change.new_path || change.old_path,
164
+ oldPath: change.old_path,
165
+ newLine: changeInfo.lineNumber,
166
+ };
169
167
 
170
- for (const change of changes) {
171
- try {
172
- // 使用 PromptTools 构建消息
173
- const messages = PromptTools.buildReviewMessages({
174
- diff: change.diff,
175
- fileName: change.new_path || change.old_path,
176
- guardConfig,
177
- });
178
-
179
- // 调用 AI
180
- const result = await aiClient.sendMessage(messages);
181
-
182
- reviews.push({
183
- fileName: change.new_path || change.old_path,
184
- status: 'success',
185
- ...result,
186
- });
187
- } catch (error) {
188
- reviews.push({
189
- fileName: change.new_path || change.old_path,
190
- status: 'error',
191
- error: error.message,
192
- });
193
- }
194
- }
168
+ const commentResult = await this.gitlabClient.createLineComment(
169
+ this.config.project.projectId,
170
+ this.config.project.mergeRequestIid,
171
+ `🤖 **AI 代码审查**\n\n${review.content}`,
172
+ lineInfo
173
+ );
195
174
 
196
- return reviews;
175
+ return {
176
+ review,
177
+ comment: commentResult,
178
+ };
197
179
  }
198
180
 
199
181
  /**
200
- * AI 审查 MR 并自动添加评论
182
+ * AI 审查 MR 的所有有意义的变更并自动添加行级评论
183
+ * @param {Object} options - 选项
184
+ * @param {number} options.maxComments - 最大评论数量(避免过多评论)
185
+ * @returns {Promise<Array>} 评论结果数组
201
186
  */
202
- async reviewAndComment() {
203
- const reviews = await this.reviewMergeRequest();
204
-
205
- // 构建评论内容
206
- let comment = '## 🤖 AI 代码审查报告\n\n';
207
-
208
- for (const review of reviews) {
209
- if (review.status === 'error') {
210
- comment += `### ❌ ${review.fileName}\n`;
211
- comment += `审查失败: ${review.error}\n\n`;
212
- continue;
187
+ async reviewAndCommentOnLines(options = {}) {
188
+ const { maxComments = 10 } = options;
189
+ const changes = await this.getMergeRequestChanges();
190
+ const results = [];
191
+
192
+ for (const change of changes) {
193
+ if (results.length >= maxComments) {
194
+ console.log(`已达到最大评论数量限制 (${maxComments}),停止审查`);
195
+ break;
213
196
  }
214
197
 
215
- comment += `### 📄 ${review.fileName}\n\n`;
216
-
217
- if (review.reasoning) {
218
- comment += `**思考过程**:\n${review.reasoning}\n\n`;
198
+ // 解析 diff,提取有意义的变更
199
+ const hunks = DiffParser.parseDiff(change.diff);
200
+ const meaningfulChanges = DiffParser.extractMeaningfulChanges(hunks);
201
+
202
+ // 对每个有意义的变更进行审查
203
+ for (const meaningfulChange of meaningfulChanges.slice(0, maxComments - results.length)) {
204
+ try {
205
+ const result = await this.reviewAndCommentOnLine(change, meaningfulChange);
206
+ results.push({
207
+ status: 'success',
208
+ fileName: change.new_path || change.old_path,
209
+ lineNumber: meaningfulChange.lineNumber,
210
+ ...result,
211
+ });
212
+ } catch (error) {
213
+ results.push({
214
+ status: 'error',
215
+ fileName: change.new_path || change.old_path,
216
+ lineNumber: meaningfulChange.lineNumber,
217
+ error: error.message,
218
+ });
219
+ }
219
220
  }
220
-
221
- comment += `**审查意见**:\n${review.content}\n\n`;
222
- comment += `---\n\n`;
223
221
  }
224
222
 
225
- // 添加评论到 MR
226
- return this.addComment(comment);
223
+ return results;
227
224
  }
228
225
 
229
226
  /**
@@ -238,7 +235,7 @@ export class GitLabAIReview {
238
235
  export { getConfig, validateConfig } from './lib/config.js';
239
236
  export { GitLabClient } from './lib/gitlab-client.js';
240
237
  export { AIClient } from './lib/ai-client.js';
241
- export { PromptTools };
238
+ export { PromptTools, DiffParser };
242
239
 
243
240
  // 默认导出
244
241
  export default GitLabAIReview;
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Diff 解析工具 - 解析 Git Diff 格式
3
+ */
4
+
5
+ /**
6
+ * 解析 diff 的 hunk 头部信息
7
+ * 例如: @@ -14,7 +14,7 @@
8
+ * @param {string} hunkHeader - hunk 头部字符串
9
+ * @returns {Object} 解析后的位置信息
10
+ */
11
+ export function parseHunkHeader(hunkHeader) {
12
+ const match = hunkHeader.match(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
13
+
14
+ if (!match) {
15
+ return null;
16
+ }
17
+
18
+ return {
19
+ oldStart: parseInt(match[1], 10),
20
+ oldLines: match[2] ? parseInt(match[2], 10) : 1,
21
+ newStart: parseInt(match[3], 10),
22
+ newLines: match[4] ? parseInt(match[4], 10) : 1,
23
+ };
24
+ }
25
+
26
+ /**
27
+ * 解析完整的 diff 内容,提取所有变更位置
28
+ * @param {string} diff - diff 内容
29
+ * @returns {Array} 变更块数组
30
+ */
31
+ export function parseDiff(diff) {
32
+ if (!diff) return [];
33
+
34
+ const lines = diff.split('\n');
35
+ const hunks = [];
36
+ let currentHunk = null;
37
+
38
+ for (let i = 0; i < lines.length; i++) {
39
+ const line = lines[i];
40
+
41
+ // 检测 hunk 头部
42
+ if (line.startsWith('@@')) {
43
+ if (currentHunk) {
44
+ hunks.push(currentHunk);
45
+ }
46
+
47
+ const hunkInfo = parseHunkHeader(line);
48
+ currentHunk = {
49
+ ...hunkInfo,
50
+ header: line,
51
+ changes: [],
52
+ contextBefore: [],
53
+ contextAfter: [],
54
+ };
55
+ } else if (currentHunk) {
56
+ // 收集变更行
57
+ if (line.startsWith('+') && !line.startsWith('+++')) {
58
+ currentHunk.changes.push({
59
+ type: 'addition',
60
+ content: line.substring(1),
61
+ line: line,
62
+ });
63
+ } else if (line.startsWith('-') && !line.startsWith('---')) {
64
+ currentHunk.changes.push({
65
+ type: 'deletion',
66
+ content: line.substring(1),
67
+ line: line,
68
+ });
69
+ } else if (line.startsWith(' ')) {
70
+ currentHunk.changes.push({
71
+ type: 'context',
72
+ content: line.substring(1),
73
+ line: line,
74
+ });
75
+ }
76
+ }
77
+ }
78
+
79
+ if (currentHunk) {
80
+ hunks.push(currentHunk);
81
+ }
82
+
83
+ return hunks;
84
+ }
85
+
86
+ /**
87
+ * 计算变更在新文件中的具体行号
88
+ * @param {Object} hunk - hunk 信息
89
+ * @param {number} changeIndex - 变更在 changes 数组中的索引
90
+ * @returns {number} 新文件中的行号
91
+ */
92
+ export function calculateNewLineNumber(hunk, changeIndex) {
93
+ let lineNumber = hunk.newStart;
94
+
95
+ for (let i = 0; i <= changeIndex; i++) {
96
+ const change = hunk.changes[i];
97
+ if (change.type === 'addition' || change.type === 'context') {
98
+ if (i === changeIndex) {
99
+ return lineNumber;
100
+ }
101
+ lineNumber++;
102
+ }
103
+ }
104
+
105
+ return lineNumber;
106
+ }
107
+
108
+ /**
109
+ * 提取有意义的变更(忽略纯空白变更)
110
+ * @param {Array} hunks - hunks 数组
111
+ * @returns {Array} 有意义的变更数组
112
+ */
113
+ export function extractMeaningfulChanges(hunks) {
114
+ const meaningfulChanges = [];
115
+
116
+ hunks.forEach(hunk => {
117
+ let currentNewLine = hunk.newStart;
118
+
119
+ hunk.changes.forEach((change, index) => {
120
+ if (change.type === 'addition') {
121
+ const content = change.content.trim();
122
+
123
+ // 过滤空行和仅包含符号的行
124
+ if (content.length > 0 && !/^[{}()\[\];,]*$/.test(content)) {
125
+ meaningfulChanges.push({
126
+ type: 'addition',
127
+ content: change.content,
128
+ lineNumber: currentNewLine,
129
+ hunk: hunk.header,
130
+ context: {
131
+ before: hunk.changes.slice(Math.max(0, index - 2), index).map(c => c.content),
132
+ after: hunk.changes.slice(index + 1, index + 3).map(c => c.content),
133
+ },
134
+ });
135
+ }
136
+ currentNewLine++;
137
+ } else if (change.type === 'deletion') {
138
+ const content = change.content.trim();
139
+
140
+ if (content.length > 0 && !/^[{}()\[\];,]*$/.test(content)) {
141
+ meaningfulChanges.push({
142
+ type: 'deletion',
143
+ content: change.content,
144
+ oldLineNumber: currentNewLine,
145
+ hunk: hunk.header,
146
+ context: {
147
+ before: hunk.changes.slice(Math.max(0, index - 2), index).map(c => c.content),
148
+ after: hunk.changes.slice(index + 1, index + 3).map(c => c.content),
149
+ },
150
+ });
151
+ }
152
+ } else if (change.type === 'context') {
153
+ currentNewLine++;
154
+ }
155
+ });
156
+ });
157
+
158
+ return meaningfulChanges;
159
+ }
160
+
161
+ /**
162
+ * 生成变更摘要
163
+ * @param {string} diff - diff 内容
164
+ * @returns {Object} 变更摘要
165
+ */
166
+ export function generateDiffSummary(diff) {
167
+ if (!diff) {
168
+ return { additions: 0, deletions: 0, changes: 0 };
169
+ }
170
+
171
+ const lines = diff.split('\n');
172
+ let additions = 0;
173
+ let deletions = 0;
174
+
175
+ lines.forEach(line => {
176
+ if (line.startsWith('+') && !line.startsWith('+++')) {
177
+ additions++;
178
+ } else if (line.startsWith('-') && !line.startsWith('---')) {
179
+ deletions++;
180
+ }
181
+ });
182
+
183
+ return {
184
+ additions,
185
+ deletions,
186
+ changes: additions + deletions,
187
+ };
188
+ }
189
+
190
+ export default {
191
+ parseHunkHeader,
192
+ parseDiff,
193
+ calculateNewLineNumber,
194
+ extractMeaningfulChanges,
195
+ generateDiffSummary,
196
+ };
197
+
@@ -69,9 +69,37 @@ export class GitLabClient {
69
69
  }
70
70
 
71
71
  /**
72
- * 在 MR 上创建讨论(行内评论)
72
+ * 在 MR 的特定行上创建评论
73
+ * @param {string} projectId - 项目 ID
74
+ * @param {number} mergeRequestIid - MR IID
75
+ * @param {string} body - 评论内容
76
+ * @param {Object} lineInfo - 行信息
77
+ * @param {string} lineInfo.filePath - 文件路径
78
+ * @param {number} lineInfo.newLine - 新文件行号
79
+ * @param {number} lineInfo.oldLine - 旧文件行号(可选)
80
+ * @returns {Promise<Object>} 创建的讨论
73
81
  */
74
- async createMergeRequestDiscussion(projectId, mergeRequestIid, body, position) {
82
+ async createLineComment(projectId, mergeRequestIid, body, lineInfo) {
83
+ // 先获取 MR 信息以获取 SHA
84
+ const mr = await this.getMergeRequest(projectId, mergeRequestIid);
85
+
86
+ const position = {
87
+ base_sha: mr.diff_refs.base_sha,
88
+ head_sha: mr.diff_refs.head_sha,
89
+ start_sha: mr.diff_refs.start_sha,
90
+ position_type: 'text',
91
+ new_path: lineInfo.filePath,
92
+ old_path: lineInfo.oldPath || lineInfo.filePath,
93
+ };
94
+
95
+ // 设置行号
96
+ if (lineInfo.newLine !== undefined) {
97
+ position.new_line = lineInfo.newLine;
98
+ }
99
+ if (lineInfo.oldLine !== undefined) {
100
+ position.old_line = lineInfo.oldLine;
101
+ }
102
+
75
103
  return this.request(
76
104
  `/projects/${encodeURIComponent(projectId)}/merge_requests/${mergeRequestIid}/discussions`,
77
105
  {
@@ -83,5 +111,39 @@ export class GitLabClient {
83
111
  }
84
112
  );
85
113
  }
114
+
115
+ /**
116
+ * 批量创建行级评论
117
+ * @param {string} projectId - 项目 ID
118
+ * @param {number} mergeRequestIid - MR IID
119
+ * @param {Array} comments - 评论数组
120
+ * @returns {Promise<Array>} 创建结果数组
121
+ */
122
+ async createMultipleLineComments(projectId, mergeRequestIid, comments) {
123
+ const results = [];
124
+
125
+ for (const comment of comments) {
126
+ try {
127
+ const result = await this.createLineComment(
128
+ projectId,
129
+ mergeRequestIid,
130
+ comment.body,
131
+ comment.lineInfo
132
+ );
133
+ results.push({
134
+ status: 'success',
135
+ result,
136
+ });
137
+ } catch (error) {
138
+ results.push({
139
+ status: 'error',
140
+ error: error.message,
141
+ comment,
142
+ });
143
+ }
144
+ }
145
+
146
+ return results;
147
+ }
86
148
  }
87
149
 
@@ -1,13 +1,14 @@
1
1
  /**
2
- * Prompt 工具 - 用于拼接代码审查的提示词
2
+ * Prompt 工具 - 用于拼接行级代码审查的提示词
3
+ * 简化版:只支持行级审查
3
4
  */
4
5
 
5
6
  /**
6
- * 构建系统提示词
7
- * @param {string} guardConfig - AI Review Guard 配置内容
7
+ * 构建系统提示词(附带项目 prompt)
8
+ * @param {string} projectPrompt - 项目配置的 prompt(来自 reviewguard.md)
8
9
  * @returns {string} 系统提示词
9
10
  */
10
- export function buildSystemPrompt(guardConfig = '') {
11
+ export function buildSystemPrompt(projectPrompt = '') {
11
12
  let prompt = `你是一个专业的代码审查助手,负责审查 GitLab Merge Request 的代码变更。
12
13
 
13
14
  你的职责是:
@@ -18,125 +19,83 @@ export function buildSystemPrompt(guardConfig = '') {
18
19
 
19
20
  请以专业、建设性的语气提供审查意见。`;
20
21
 
21
- if (guardConfig) {
22
- prompt += `\n\n项目特定的审查规则:\n${guardConfig}`;
22
+ // 附带项目特定的审查规则
23
+ if (projectPrompt) {
24
+ prompt += `\n\n## 项目特定的审查规则\n\n${projectPrompt}`;
23
25
  }
24
26
 
25
27
  return prompt;
26
28
  }
27
29
 
28
30
  /**
29
- * 构建代码审查的用户提示词
30
- * @param {string} diff - 代码差异
31
- * @param {string} fileName - 文件名
32
- * @returns {string} 用户提示词
31
+ * 构建针对特定行变更的审查提示词(附带项目 prompt)
32
+ * @param {Object} changeInfo - 变更信息
33
+ * @param {string} changeInfo.content - 变更内容
34
+ * @param {string} changeInfo.type - 变更类型(addition/deletion)
35
+ * @param {number} changeInfo.lineNumber - 行号
36
+ * @param {string} changeInfo.fileName - 文件名
37
+ * @param {Object} changeInfo.context - 上下文
38
+ * @returns {string} 审查提示词
33
39
  */
34
- export function buildReviewPrompt(diff, fileName) {
35
- return `请审查以下代码变更:
40
+ export function buildLineReviewPrompt(changeInfo) {
41
+ const { content, type, lineNumber, fileName, context } = changeInfo;
42
+
43
+ let prompt = `请审查以下代码变更:
36
44
 
37
- **文件名**: ${fileName}
45
+ **文件**: ${fileName}
46
+ **行号**: ${lineNumber}
47
+ **变更类型**: ${type === 'addition' ? '新增' : '删除'}
38
48
 
39
- **代码差异**:
40
- \`\`\`diff
41
- ${diff}
49
+ **变更内容**:
50
+ \`\`\`
51
+ ${type === 'addition' ? '+' : '-'} ${content}
42
52
  \`\`\`
53
+ `;
54
+
55
+ if (context && (context.before.length > 0 || context.after.length > 0)) {
56
+ prompt += '\n**上下文**:\n```\n';
57
+ if (context.before.length > 0) {
58
+ context.before.forEach(line => {
59
+ prompt += ` ${line}\n`;
60
+ });
61
+ }
62
+ prompt += `${type === 'addition' ? '+' : '-'} ${content}\n`;
63
+ if (context.after.length > 0) {
64
+ context.after.forEach(line => {
65
+ prompt += ` ${line}\n`;
66
+ });
67
+ }
68
+ prompt += '```\n';
69
+ }
70
+
71
+ prompt += `
72
+ 请提供简洁的审查意见:
73
+ 1. 如果有问题,指出具体问题
74
+ 2. 如果有改进建议,提供具体的建议
75
+ 3. 如果代码没有问题,简单说明"代码质量良好"
43
76
 
44
- 请提供:
45
- 1. 主要问题(如果有)
46
- 2. 改进建议
47
- 3. 优点(如果有)
77
+ 请直接给出审查意见,不要重复代码内容。`;
48
78
 
49
- 如果代码没有问题,请简要说明代码质量良好。`;
79
+ return prompt;
50
80
  }
51
81
 
52
82
  /**
53
- * 构建完整的审查消息数组
54
- * @param {Object} params - 参数
55
- * @param {string} params.diff - 代码差异
56
- * @param {string} params.fileName - 文件名
57
- * @param {string} params.guardConfig - AI Review Guard 配置
83
+ * 构建针对特定行变更的完整消息数组(附带项目 prompt)
84
+ * @param {Object} changeInfo - 变更信息
85
+ * @param {string} projectPrompt - 项目配置的 prompt(来自 reviewguard.md)
58
86
  * @returns {Array} 消息数组
59
87
  */
60
- export function buildReviewMessages({ diff, fileName, guardConfig = '' }) {
88
+ export function buildLineReviewMessages(changeInfo, projectPrompt = '') {
61
89
  return [
62
- { role: 'system', content: buildSystemPrompt(guardConfig) },
63
- { role: 'user', content: buildReviewPrompt(diff, fileName) },
90
+ { role: 'system', content: buildSystemPrompt(projectPrompt) },
91
+ { role: 'user', content: buildLineReviewPrompt(changeInfo) },
64
92
  ];
65
93
  }
66
94
 
67
- /**
68
- * 构建批量审查的提示词
69
- * @param {Array} changes - 代码变更数组
70
- * @param {string} guardConfig - AI Review Guard 配置
71
- * @returns {string} 批量审查提示词
72
- */
73
- export function buildBatchReviewPrompt(changes, guardConfig = '') {
74
- let prompt = buildSystemPrompt(guardConfig);
75
-
76
- prompt += '\n\n请审查以下 ' + changes.length + ' 个文件的代码变更:\n\n';
77
-
78
- changes.forEach((change, index) => {
79
- const fileName = change.new_path || change.old_path;
80
- const status = change.new_file ? '新增' : change.deleted_file ? '删除' : '修改';
81
-
82
- prompt += `## ${index + 1}. ${fileName} (${status})\n\n`;
83
- prompt += '```diff\n';
84
- prompt += change.diff || '(无差异内容)';
85
- prompt += '\n```\n\n';
86
- });
87
-
88
- prompt += '\n请为每个文件提供审查意见,并在最后给出整体评价。';
89
-
90
- return prompt;
91
- }
92
-
93
- /**
94
- * 格式化 diff 内容(可选的预处理)
95
- * @param {string} diff - 原始 diff
96
- * @returns {string} 格式化后的 diff
97
- */
98
- export function formatDiff(diff) {
99
- if (!diff) return '(无变更内容)';
100
-
101
- // 移除过长的 diff(可选)
102
- const maxLines = 500;
103
- const lines = diff.split('\n');
104
-
105
- if (lines.length > maxLines) {
106
- return lines.slice(0, maxLines).join('\n') +
107
- `\n... (省略 ${lines.length - maxLines} 行)`;
108
- }
109
-
110
- return diff;
111
- }
112
-
113
- /**
114
- * 从 change 对象中提取关键信息
115
- * @param {Object} change - GitLab change 对象
116
- * @returns {Object} 提取的信息
117
- */
118
- export function extractChangeInfo(change) {
119
- return {
120
- fileName: change.new_path || change.old_path,
121
- oldPath: change.old_path,
122
- newPath: change.new_path,
123
- status: change.new_file ? 'added' :
124
- change.deleted_file ? 'deleted' :
125
- change.renamed_file ? 'renamed' :
126
- 'modified',
127
- diff: change.diff || '',
128
- isNewFile: change.new_file,
129
- isDeleted: change.deleted_file,
130
- isRenamed: change.renamed_file,
131
- };
132
- }
133
-
95
+ // 只导出行级审查需要的函数
134
96
  export default {
135
97
  buildSystemPrompt,
136
- buildReviewPrompt,
137
- buildReviewMessages,
138
- buildBatchReviewPrompt,
139
- formatDiff,
140
- extractChangeInfo,
98
+ buildLineReviewPrompt,
99
+ buildLineReviewMessages,
141
100
  };
142
101
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gitlab-ai-review",
3
- "version": "1.2.0",
4
- "description": "GitLab AI Review SDK - 支持 CI/CD 自动配置和 ARK API",
3
+ "version": "2.0.0",
4
+ "description": "GitLab AI Review SDK - 行级代码审查,附带项目 Prompt",
5
5
  "main": "index.js",
6
6
  "type": "module",
7
7
  "scripts": {