@diff-review-system/drs 1.0.0 → 1.1.2

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 (135) hide show
  1. package/.opencode/agent/github-reviewer.md +22 -7
  2. package/.opencode/agent/gitlab-reviewer.md +22 -7
  3. package/.opencode/agent/local-reviewer.md +21 -29
  4. package/.opencode/agent/review/performance.md +22 -13
  5. package/.opencode/agent/review/quality.md +22 -13
  6. package/.opencode/agent/review/security.md +22 -19
  7. package/.opencode/agent/review/style.md +22 -10
  8. package/.opencode/opencode.jsonc +7 -19
  9. package/README.md +175 -69
  10. package/dist/ci/runner.d.ts.map +1 -1
  11. package/dist/ci/runner.js +2 -4
  12. package/dist/ci/runner.js.map +1 -1
  13. package/dist/cli/index.js +14 -4
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/cli/init.d.ts.map +1 -1
  16. package/dist/cli/init.js +112 -23
  17. package/dist/cli/init.js.map +1 -1
  18. package/dist/cli/review-local.d.ts.map +1 -1
  19. package/dist/cli/review-local.js +27 -70
  20. package/dist/cli/review-local.js.map +1 -1
  21. package/dist/cli/review-mr.d.ts +1 -0
  22. package/dist/cli/review-mr.d.ts.map +1 -1
  23. package/dist/cli/review-mr.js +34 -119
  24. package/dist/cli/review-mr.js.map +1 -1
  25. package/dist/cli/review-pr.d.ts.map +1 -1
  26. package/dist/cli/review-pr.js +74 -114
  27. package/dist/cli/review-pr.js.map +1 -1
  28. package/dist/github/client.d.ts +199 -4
  29. package/dist/github/client.d.ts.map +1 -1
  30. package/dist/github/client.js +37 -2
  31. package/dist/github/client.js.map +1 -1
  32. package/dist/github/client.test.d.ts +2 -0
  33. package/dist/github/client.test.d.ts.map +1 -0
  34. package/dist/github/client.test.js +206 -0
  35. package/dist/github/client.test.js.map +1 -0
  36. package/dist/github/platform-adapter.d.ts +31 -0
  37. package/dist/github/platform-adapter.d.ts.map +1 -0
  38. package/dist/github/platform-adapter.js +127 -0
  39. package/dist/github/platform-adapter.js.map +1 -0
  40. package/dist/github/platform-adapter.test.d.ts +2 -0
  41. package/dist/github/platform-adapter.test.d.ts.map +1 -0
  42. package/dist/github/platform-adapter.test.js +40 -0
  43. package/dist/github/platform-adapter.test.js.map +1 -0
  44. package/dist/gitlab/client.d.ts +12 -0
  45. package/dist/gitlab/client.d.ts.map +1 -1
  46. package/dist/gitlab/client.js +18 -0
  47. package/dist/gitlab/client.js.map +1 -1
  48. package/dist/gitlab/diff-parser.test.d.ts +2 -0
  49. package/dist/gitlab/diff-parser.test.d.ts.map +1 -0
  50. package/dist/gitlab/diff-parser.test.js +315 -0
  51. package/dist/gitlab/diff-parser.test.js.map +1 -0
  52. package/dist/gitlab/platform-adapter.d.ts +27 -0
  53. package/dist/gitlab/platform-adapter.d.ts.map +1 -0
  54. package/dist/gitlab/platform-adapter.js +120 -0
  55. package/dist/gitlab/platform-adapter.js.map +1 -0
  56. package/dist/gitlab/platform-adapter.test.d.ts +2 -0
  57. package/dist/gitlab/platform-adapter.test.d.ts.map +1 -0
  58. package/dist/gitlab/platform-adapter.test.js +21 -0
  59. package/dist/gitlab/platform-adapter.test.js.map +1 -0
  60. package/dist/index.test.d.ts +2 -0
  61. package/dist/index.test.d.ts.map +1 -0
  62. package/dist/index.test.js +7 -0
  63. package/dist/index.test.js.map +1 -0
  64. package/dist/lib/code-quality-report.d.ts +44 -0
  65. package/dist/lib/code-quality-report.d.ts.map +1 -0
  66. package/dist/lib/code-quality-report.js +62 -0
  67. package/dist/lib/code-quality-report.js.map +1 -0
  68. package/dist/lib/code-quality-report.test.d.ts +2 -0
  69. package/dist/lib/code-quality-report.test.d.ts.map +1 -0
  70. package/dist/lib/code-quality-report.test.js +327 -0
  71. package/dist/lib/code-quality-report.test.js.map +1 -0
  72. package/dist/{gitlab → lib}/comment-formatter.d.ts +4 -2
  73. package/dist/lib/comment-formatter.d.ts.map +1 -0
  74. package/dist/{gitlab → lib}/comment-formatter.js +48 -15
  75. package/dist/lib/comment-formatter.js.map +1 -0
  76. package/dist/lib/comment-manager.d.ts +61 -0
  77. package/dist/lib/comment-manager.d.ts.map +1 -0
  78. package/dist/lib/comment-manager.js +91 -0
  79. package/dist/lib/comment-manager.js.map +1 -0
  80. package/dist/lib/config-model-overrides.test.d.ts +12 -0
  81. package/dist/lib/config-model-overrides.test.d.ts.map +1 -0
  82. package/dist/lib/config-model-overrides.test.js +224 -0
  83. package/dist/lib/config-model-overrides.test.js.map +1 -0
  84. package/dist/lib/config.d.ts +30 -1
  85. package/dist/lib/config.d.ts.map +1 -1
  86. package/dist/lib/config.js +70 -11
  87. package/dist/lib/config.js.map +1 -1
  88. package/dist/lib/config.test.d.ts +2 -0
  89. package/dist/lib/config.test.d.ts.map +1 -0
  90. package/dist/lib/config.test.js +28 -0
  91. package/dist/lib/config.test.js.map +1 -0
  92. package/dist/lib/context-loader.d.ts +29 -0
  93. package/dist/lib/context-loader.d.ts.map +1 -0
  94. package/dist/lib/context-loader.js +68 -0
  95. package/dist/lib/context-loader.js.map +1 -0
  96. package/dist/lib/diff-parser.d.ts.map +1 -0
  97. package/dist/{gitlab → lib}/diff-parser.js +3 -3
  98. package/dist/lib/diff-parser.js.map +1 -0
  99. package/dist/lib/issue-parser.d.ts +29 -0
  100. package/dist/lib/issue-parser.d.ts.map +1 -0
  101. package/dist/lib/issue-parser.js +151 -0
  102. package/dist/lib/issue-parser.js.map +1 -0
  103. package/dist/lib/issue-parser.test.d.ts +2 -0
  104. package/dist/lib/issue-parser.test.d.ts.map +1 -0
  105. package/dist/lib/issue-parser.test.js +281 -0
  106. package/dist/lib/issue-parser.test.js.map +1 -0
  107. package/dist/lib/platform-client.d.ts +130 -0
  108. package/dist/lib/platform-client.d.ts.map +1 -0
  109. package/dist/lib/platform-client.js +8 -0
  110. package/dist/lib/platform-client.js.map +1 -0
  111. package/dist/lib/position-validator.d.ts +36 -0
  112. package/dist/lib/position-validator.d.ts.map +1 -0
  113. package/dist/lib/position-validator.js +43 -0
  114. package/dist/lib/position-validator.js.map +1 -0
  115. package/dist/lib/review-orchestrator.d.ts +60 -0
  116. package/dist/lib/review-orchestrator.d.ts.map +1 -0
  117. package/dist/lib/review-orchestrator.js +183 -0
  118. package/dist/lib/review-orchestrator.js.map +1 -0
  119. package/dist/lib/unified-review-executor.d.ts +32 -0
  120. package/dist/lib/unified-review-executor.d.ts.map +1 -0
  121. package/dist/lib/unified-review-executor.js +228 -0
  122. package/dist/lib/unified-review-executor.js.map +1 -0
  123. package/dist/opencode/agent-loader.d.ts.map +1 -1
  124. package/dist/opencode/agent-loader.js +5 -10
  125. package/dist/opencode/agent-loader.js.map +1 -1
  126. package/dist/opencode/client.d.ts +3 -2
  127. package/dist/opencode/client.d.ts.map +1 -1
  128. package/dist/opencode/client.js +141 -28
  129. package/dist/opencode/client.js.map +1 -1
  130. package/package.json +28 -19
  131. package/dist/gitlab/comment-formatter.d.ts.map +0 -1
  132. package/dist/gitlab/comment-formatter.js.map +0 -1
  133. package/dist/gitlab/diff-parser.d.ts.map +0 -1
  134. package/dist/gitlab/diff-parser.js.map +0 -1
  135. /package/dist/{gitlab → lib}/diff-parser.d.ts +0 -0
@@ -0,0 +1,315 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { parseDiff, getChangedFiles, getAddedLines, diffContainsPattern, } from '../lib/diff-parser.js';
3
+ describe('parseDiff', () => {
4
+ it('should parse a simple unified diff with one file', () => {
5
+ const diff = `diff --git a/src/test.ts b/src/test.ts
6
+ --- a/src/test.ts
7
+ +++ b/src/test.ts
8
+ @@ -1,3 +1,4 @@
9
+ function hello() {
10
+ + console.log('world');
11
+ return 'hello';
12
+ }`;
13
+ const parsed = parseDiff(diff);
14
+ expect(parsed).toHaveLength(1);
15
+ expect(parsed[0].oldPath).toBe('src/test.ts');
16
+ expect(parsed[0].newPath).toBe('src/test.ts');
17
+ expect(parsed[0].isNew).toBe(false);
18
+ expect(parsed[0].isDeleted).toBe(false);
19
+ expect(parsed[0].hunks).toHaveLength(1);
20
+ });
21
+ it('should parse a new file', () => {
22
+ const diff = `diff --git a/src/new.ts b/src/new.ts
23
+ --- /dev/null
24
+ +++ b/src/new.ts
25
+ @@ -0,0 +1,3 @@
26
+ +export function newFunc() {
27
+ + return 'new';
28
+ +}`;
29
+ const parsed = parseDiff(diff);
30
+ expect(parsed).toHaveLength(1);
31
+ expect(parsed[0].isNew).toBe(true);
32
+ expect(parsed[0].oldPath).toBe('/dev/null');
33
+ expect(parsed[0].newPath).toBe('src/new.ts');
34
+ });
35
+ it('should parse a deleted file', () => {
36
+ const diff = `diff --git a/src/old.ts b/src/old.ts
37
+ --- a/src/old.ts
38
+ +++ /dev/null
39
+ @@ -1,3 +0,0 @@
40
+ -export function oldFunc() {
41
+ - return 'old';
42
+ -}`;
43
+ const parsed = parseDiff(diff);
44
+ expect(parsed).toHaveLength(1);
45
+ expect(parsed[0].isDeleted).toBe(true);
46
+ expect(parsed[0].newPath).toBe('/dev/null');
47
+ });
48
+ it('should parse multiple files', () => {
49
+ const diff = `diff --git a/src/file1.ts b/src/file1.ts
50
+ --- a/src/file1.ts
51
+ +++ b/src/file1.ts
52
+ @@ -1,2 +1,3 @@
53
+ line1
54
+ +line2
55
+ line3
56
+ diff --git a/src/file2.ts b/src/file2.ts
57
+ --- a/src/file2.ts
58
+ +++ b/src/file2.ts
59
+ @@ -1,1 +1,2 @@
60
+ line1
61
+ +line2`;
62
+ const parsed = parseDiff(diff);
63
+ expect(parsed).toHaveLength(2);
64
+ expect(parsed[0].newPath).toBe('src/file1.ts');
65
+ expect(parsed[1].newPath).toBe('src/file2.ts');
66
+ });
67
+ it('should parse diff with multiple hunks', () => {
68
+ const diff = `diff --git a/src/multi.ts b/src/multi.ts
69
+ --- a/src/multi.ts
70
+ +++ b/src/multi.ts
71
+ @@ -1,3 +1,4 @@
72
+ function one() {
73
+ + // Added comment
74
+ return 1;
75
+ }
76
+ @@ -10,3 +11,4 @@
77
+ function two() {
78
+ + // Another comment
79
+ return 2;
80
+ }`;
81
+ const parsed = parseDiff(diff);
82
+ expect(parsed).toHaveLength(1);
83
+ expect(parsed[0].hunks).toHaveLength(2);
84
+ expect(parsed[0].hunks[0].oldStart).toBe(1);
85
+ expect(parsed[0].hunks[1].oldStart).toBe(10);
86
+ });
87
+ it('should track line numbers correctly for additions', () => {
88
+ const diff = `diff --git a/src/lines.ts b/src/lines.ts
89
+ --- a/src/lines.ts
90
+ +++ b/src/lines.ts
91
+ @@ -1,3 +1,5 @@
92
+ line1
93
+ +line2-added
94
+ +line3-added
95
+ line4
96
+ line5`;
97
+ const parsed = parseDiff(diff);
98
+ expect(parsed[0].hunks[0].lines).toHaveLength(5);
99
+ const addedLines = parsed[0].hunks[0].lines.filter((l) => l.type === 'add');
100
+ expect(addedLines).toHaveLength(2);
101
+ expect(addedLines[0].newLineNumber).toBe(2);
102
+ expect(addedLines[1].newLineNumber).toBe(3);
103
+ });
104
+ it('should track line numbers correctly for deletions', () => {
105
+ const diff = `diff --git a/src/del.ts b/src/del.ts
106
+ --- a/src/del.ts
107
+ +++ b/src/del.ts
108
+ @@ -1,5 +1,3 @@
109
+ line1
110
+ -line2-deleted
111
+ -line3-deleted
112
+ line4
113
+ line5`;
114
+ const parsed = parseDiff(diff);
115
+ const deletedLines = parsed[0].hunks[0].lines.filter((l) => l.type === 'delete');
116
+ expect(deletedLines).toHaveLength(2);
117
+ expect(deletedLines[0].oldLineNumber).toBe(2);
118
+ expect(deletedLines[1].oldLineNumber).toBe(3);
119
+ });
120
+ it('should handle context lines', () => {
121
+ const diff = `diff --git a/src/ctx.ts b/src/ctx.ts
122
+ --- a/src/ctx.ts
123
+ +++ b/src/ctx.ts
124
+ @@ -1,5 +1,5 @@
125
+ context1
126
+ context2
127
+ -old line
128
+ +new line
129
+ context3
130
+ context4`;
131
+ const parsed = parseDiff(diff);
132
+ const contextLines = parsed[0].hunks[0].lines.filter((l) => l.type === 'context');
133
+ expect(contextLines).toHaveLength(4);
134
+ // Context lines should have both old and new line numbers
135
+ expect(contextLines[0].oldLineNumber).toBe(1);
136
+ expect(contextLines[0].newLineNumber).toBe(1);
137
+ });
138
+ it('should parse GitHub-style patch without diff header', () => {
139
+ // GitHub API sometimes returns patches without the "diff --git" line
140
+ const diff = `--- a/src/file.ts
141
+ +++ b/src/file.ts
142
+ @@ -1,2 +1,3 @@
143
+ line1
144
+ +line2
145
+ line3`;
146
+ const parsed = parseDiff(diff);
147
+ // Should still parse, but may create a file entry when encountering ---
148
+ expect(parsed.length).toBeGreaterThanOrEqual(0);
149
+ });
150
+ it('should handle empty diff', () => {
151
+ const diff = '';
152
+ const parsed = parseDiff(diff);
153
+ expect(parsed).toEqual([]);
154
+ });
155
+ it('should handle hunk with single line change', () => {
156
+ const diff = `diff --git a/src/single.ts b/src/single.ts
157
+ --- a/src/single.ts
158
+ +++ b/src/single.ts
159
+ @@ -1 +1 @@
160
+ -old
161
+ +new`;
162
+ const parsed = parseDiff(diff);
163
+ expect(parsed).toHaveLength(1);
164
+ expect(parsed[0].hunks[0].oldLines).toBe(1);
165
+ expect(parsed[0].hunks[0].newLines).toBe(1);
166
+ });
167
+ });
168
+ describe('getChangedFiles', () => {
169
+ it('should return list of changed files', () => {
170
+ const diff = `diff --git a/src/a.ts b/src/a.ts
171
+ --- a/src/a.ts
172
+ +++ b/src/a.ts
173
+ @@ -1 +1,2 @@
174
+ line
175
+ +new line
176
+ diff --git a/src/b.ts b/src/b.ts
177
+ --- a/src/b.ts
178
+ +++ b/src/b.ts
179
+ @@ -1 +1,2 @@
180
+ line
181
+ +new line`;
182
+ const parsed = parseDiff(diff);
183
+ const files = getChangedFiles(parsed);
184
+ expect(files).toEqual(['src/a.ts', 'src/b.ts']);
185
+ });
186
+ it('should exclude deleted files', () => {
187
+ const diff = `diff --git a/src/deleted.ts b/src/deleted.ts
188
+ --- a/src/deleted.ts
189
+ +++ /dev/null
190
+ @@ -1 +0,0 @@
191
+ -old content
192
+ diff --git a/src/kept.ts b/src/kept.ts
193
+ --- a/src/kept.ts
194
+ +++ b/src/kept.ts
195
+ @@ -1 +1,2 @@
196
+ line
197
+ +new line`;
198
+ const parsed = parseDiff(diff);
199
+ const files = getChangedFiles(parsed);
200
+ expect(files).toEqual(['src/kept.ts']);
201
+ });
202
+ it('should include new files', () => {
203
+ const diff = `diff --git a/src/new.ts b/src/new.ts
204
+ --- /dev/null
205
+ +++ b/src/new.ts
206
+ @@ -0,0 +1,3 @@
207
+ +line1
208
+ +line2
209
+ +line3`;
210
+ const parsed = parseDiff(diff);
211
+ const files = getChangedFiles(parsed);
212
+ expect(files).toEqual(['src/new.ts']);
213
+ });
214
+ it('should return empty array for empty diff', () => {
215
+ const files = getChangedFiles([]);
216
+ expect(files).toEqual([]);
217
+ });
218
+ });
219
+ describe('getAddedLines', () => {
220
+ it('should return all added lines with line numbers', () => {
221
+ const diff = `diff --git a/src/test.ts b/src/test.ts
222
+ --- a/src/test.ts
223
+ +++ b/src/test.ts
224
+ @@ -1,3 +1,5 @@
225
+ line1
226
+ +added line 2
227
+ line3
228
+ +added line 4
229
+ line5`;
230
+ const parsed = parseDiff(diff);
231
+ const added = getAddedLines(parsed[0]);
232
+ expect(added).toHaveLength(2);
233
+ expect(added[0]).toEqual({ line: 2, content: 'added line 2' });
234
+ expect(added[1]).toEqual({ line: 4, content: 'added line 4' });
235
+ });
236
+ it('should return empty array for deletions only', () => {
237
+ const diff = `diff --git a/src/test.ts b/src/test.ts
238
+ --- a/src/test.ts
239
+ +++ b/src/test.ts
240
+ @@ -1,3 +1,1 @@
241
+ -deleted line
242
+ kept line
243
+ -deleted line`;
244
+ const parsed = parseDiff(diff);
245
+ const added = getAddedLines(parsed[0]);
246
+ expect(added).toEqual([]);
247
+ });
248
+ it('should handle multiple hunks', () => {
249
+ const diff = `diff --git a/src/test.ts b/src/test.ts
250
+ --- a/src/test.ts
251
+ +++ b/src/test.ts
252
+ @@ -1,2 +1,3 @@
253
+ line1
254
+ +added in hunk 1
255
+ line2
256
+ @@ -5,2 +6,3 @@
257
+ line5
258
+ +added in hunk 2
259
+ line6`;
260
+ const parsed = parseDiff(diff);
261
+ const added = getAddedLines(parsed[0]);
262
+ expect(added).toHaveLength(2);
263
+ });
264
+ });
265
+ describe('diffContainsPattern', () => {
266
+ it('should find pattern in added lines', () => {
267
+ const diff = `diff --git a/src/test.ts b/src/test.ts
268
+ --- a/src/test.ts
269
+ +++ b/src/test.ts
270
+ @@ -1,2 +1,3 @@
271
+ line1
272
+ +console.log('debug');
273
+ line2`;
274
+ const parsed = parseDiff(diff);
275
+ const contains = diffContainsPattern(parsed[0], /console\.log/);
276
+ expect(contains).toBe(true);
277
+ });
278
+ it('should not match pattern in deleted lines', () => {
279
+ const diff = `diff --git a/src/test.ts b/src/test.ts
280
+ --- a/src/test.ts
281
+ +++ b/src/test.ts
282
+ @@ -1,3 +1,2 @@
283
+ line1
284
+ -console.log('debug');
285
+ line2`;
286
+ const parsed = parseDiff(diff);
287
+ const contains = diffContainsPattern(parsed[0], /console\.log/);
288
+ expect(contains).toBe(false);
289
+ });
290
+ it('should not match pattern in context lines', () => {
291
+ const diff = `diff --git a/src/test.ts b/src/test.ts
292
+ --- a/src/test.ts
293
+ +++ b/src/test.ts
294
+ @@ -1,3 +1,3 @@
295
+ console.log('existing');
296
+ -old line
297
+ +new line`;
298
+ const parsed = parseDiff(diff);
299
+ const contains = diffContainsPattern(parsed[0], /console\.log/);
300
+ expect(contains).toBe(false);
301
+ });
302
+ it('should return false when pattern not found', () => {
303
+ const diff = `diff --git a/src/test.ts b/src/test.ts
304
+ --- a/src/test.ts
305
+ +++ b/src/test.ts
306
+ @@ -1,2 +1,3 @@
307
+ line1
308
+ +const x = 5;
309
+ line2`;
310
+ const parsed = parseDiff(diff);
311
+ const contains = diffContainsPattern(parsed[0], /console\.log/);
312
+ expect(contains).toBe(false);
313
+ });
314
+ });
315
+ //# sourceMappingURL=diff-parser.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-parser.test.js","sourceRoot":"","sources":["../../src/gitlab/diff-parser.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EACL,SAAS,EACT,eAAe,EACf,aAAa,EACb,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAE/B,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACzB,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,IAAI,GAAG;;;;;;;GAOd,CAAC;QAEA,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAE/B,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC9C,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC9C,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,IAAI,GAAG;;;;;;GAMd,CAAC;QAEA,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAE/B,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,IAAI,GAAG;;;;;;GAMd,CAAC;QAEA,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAE/B,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,IAAI,GAAG;;;;;;;;;;;;OAYV,CAAC;QAEJ,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAE/B,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC/C,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,IAAI,GAAG;;;;;;;;;;;;GAYd,CAAC;QAEA,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAE/B,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,IAAI,GAAG;;;;;;;;OAQV,CAAC;QAEJ,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAE/B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAEjD,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC;QAC5E,MAAM,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACnC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,IAAI,GAAG;;;;;;;;OAQV,CAAC;QAEJ,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAE/B,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;QACjF,MAAM,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACrC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,IAAI,GAAG;;;;;;;;;UASP,CAAC;QAEP,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAE/B,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;QAClF,MAAM,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAErC,0DAA0D;QAC1D,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,qEAAqE;QACrE,MAAM,IAAI,GAAG;;;;;OAKV,CAAC;QAEJ,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAE/B,wEAAwE;QACxE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,MAAM,IAAI,GAAG,EAAE,CAAC;QAEhB,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAE/B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,IAAI,GAAG;;;;;KAKZ,CAAC;QAEF,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAE/B,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,IAAI,GAAG;;;;;;;;;;;UAWP,CAAC;QAEP,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;QAEtC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,IAAI,GAAG;;;;;;;;;;UAUP,CAAC;QAEP,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;QAEtC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,MAAM,IAAI,GAAG;;;;;;OAMV,CAAC;QAEJ,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;QAEtC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,KAAK,GAAG,eAAe,CAAC,EAAE,CAAC,CAAC;QAElC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,IAAI,GAAG;;;;;;;;OAQV,CAAC;QAEJ,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAEvC,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC;QAC/D,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,IAAI,GAAG;;;;;;cAMH,CAAC;QAEX,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAEvC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,IAAI,GAAG;;;;;;;;;;OAUV,CAAC;QAEJ,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAEvC,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,IAAI,GAAG;;;;;;OAMV,CAAC;QAEJ,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,QAAQ,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;QAEhE,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,IAAI,GAAG;;;;;;OAMV,CAAC;QAEJ,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,QAAQ,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;QAEhE,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,IAAI,GAAG;;;;;;UAMP,CAAC;QAEP,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,QAAQ,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;QAEhE,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,IAAI,GAAG;;;;;;OAMV,CAAC;QAEJ,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,QAAQ,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;QAEhE,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * GitLab platform adapter implementing the common PlatformClient interface
3
+ */
4
+ import type { GitLabClient } from './client.js';
5
+ import type { PlatformClient, PullRequest, FileChange, Comment, InlineCommentPosition } from '../lib/platform-client.js';
6
+ /**
7
+ * Adapter that wraps GitLabClient to implement PlatformClient interface
8
+ */
9
+ export declare class GitLabPlatformAdapter implements PlatformClient {
10
+ private client;
11
+ private readonly positionValidator;
12
+ constructor(client: GitLabClient);
13
+ getPullRequest(projectId: string, prNumber: number): Promise<PullRequest>;
14
+ getChangedFiles(projectId: string, prNumber: number): Promise<FileChange[]>;
15
+ getComments(projectId: string, prNumber: number): Promise<Comment[]>;
16
+ getInlineComments(projectId: string, prNumber: number): Promise<Comment[]>;
17
+ createComment(projectId: string, prNumber: number, body: string): Promise<void>;
18
+ updateComment(projectId: string, prNumber: number, commentId: number | string, body: string): Promise<void>;
19
+ createInlineComment(projectId: string, prNumber: number, body: string, position: InlineCommentPosition): Promise<void>;
20
+ createBulkInlineComments(projectId: string, prNumber: number, comments: Array<{
21
+ body: string;
22
+ position: InlineCommentPosition;
23
+ }>): Promise<void>;
24
+ addLabels(projectId: string, prNumber: number, labels: string[]): Promise<void>;
25
+ hasLabel(projectId: string, prNumber: number, label: string): Promise<boolean>;
26
+ }
27
+ //# sourceMappingURL=platform-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-adapter.d.ts","sourceRoot":"","sources":["../../src/gitlab/platform-adapter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EACX,UAAU,EACV,OAAO,EACP,qBAAqB,EACtB,MAAM,2BAA2B,CAAC;AAGnC;;GAEG;AACH,qBAAa,qBAAsB,YAAW,cAAc;IAG9C,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAiC;gBAE/C,MAAM,EAAE,YAAY;IAElC,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAezE,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAoB3E,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IASpE,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAmB1E,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/E,aAAa,CACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAAG,MAAM,EAC1B,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC;IAIV,mBAAmB,CACvB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,qBAAqB,GAC9B,OAAO,CAAC,IAAI,CAAC;IAqBV,wBAAwB,CAC5B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,qBAAqB,CAAA;KAAE,CAAC,GACjE,OAAO,CAAC,IAAI,CAAC;IAgCV,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/E,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAGrF"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * GitLab platform adapter implementing the common PlatformClient interface
3
+ */
4
+ import chalk from 'chalk';
5
+ import { GitLabPositionValidator, validatePositionOrThrow } from '../lib/position-validator.js';
6
+ /**
7
+ * Adapter that wraps GitLabClient to implement PlatformClient interface
8
+ */
9
+ export class GitLabPlatformAdapter {
10
+ client;
11
+ positionValidator = new GitLabPositionValidator();
12
+ constructor(client) {
13
+ this.client = client;
14
+ }
15
+ async getPullRequest(projectId, prNumber) {
16
+ const mr = await this.client.getMergeRequest(projectId, prNumber);
17
+ return {
18
+ number: mr.iid,
19
+ title: mr.title,
20
+ description: mr.description || undefined,
21
+ author: (mr.author?.name || mr.author?.username || 'Unknown'),
22
+ sourceBranch: mr.source_branch,
23
+ targetBranch: mr.target_branch,
24
+ headSha: mr.diff_refs?.head_sha || mr.sha || '',
25
+ platformData: mr,
26
+ };
27
+ }
28
+ async getChangedFiles(projectId, prNumber) {
29
+ const changes = await this.client.getMRChanges(projectId, prNumber);
30
+ return changes.map((change) => {
31
+ let status = 'modified';
32
+ if (change.newFile)
33
+ status = 'added';
34
+ else if (change.deletedFile)
35
+ status = 'removed';
36
+ else if (change.renamedFile)
37
+ status = 'renamed';
38
+ return {
39
+ filename: change.newPath,
40
+ status,
41
+ additions: 0, // GitLab doesn't provide this in the same way
42
+ deletions: 0,
43
+ patch: change.diff,
44
+ previousFilename: change.renamedFile ? change.oldPath : undefined,
45
+ };
46
+ });
47
+ }
48
+ async getComments(projectId, prNumber) {
49
+ const notes = await this.client.getMRNotes(projectId, prNumber);
50
+ return notes.map((n) => ({
51
+ id: n.id,
52
+ body: n.body,
53
+ }));
54
+ }
55
+ async getInlineComments(projectId, prNumber) {
56
+ const discussions = await this.client.getMRDiscussions(projectId, prNumber);
57
+ // Flatten all discussion notes
58
+ const comments = [];
59
+ for (const discussion of discussions) {
60
+ if (discussion.notes) {
61
+ for (const note of discussion.notes) {
62
+ comments.push({
63
+ id: note.id,
64
+ body: note.body,
65
+ });
66
+ }
67
+ }
68
+ }
69
+ return comments;
70
+ }
71
+ async createComment(projectId, prNumber, body) {
72
+ await this.client.createMRComment(projectId, prNumber, body);
73
+ }
74
+ async updateComment(projectId, prNumber, commentId, body) {
75
+ await this.client.updateMRNote(projectId, prNumber, Number(commentId), body);
76
+ }
77
+ async createInlineComment(projectId, prNumber, body, position) {
78
+ // Validate position requirements for GitLab
79
+ validatePositionOrThrow(position, this.positionValidator);
80
+ try {
81
+ await this.client.createMRDiscussionThread(projectId, prNumber, body, {
82
+ baseSha: position.baseSha,
83
+ headSha: position.headSha,
84
+ startSha: position.startSha,
85
+ newPath: position.path,
86
+ newLine: position.line,
87
+ });
88
+ }
89
+ catch (error) {
90
+ // If line-specific comment fails, post as general comment
91
+ console.warn(chalk.yellow(` ⚠ Could not post line comment for ${position.path}:${position.line}`));
92
+ await this.client.createMRComment(projectId, prNumber, body);
93
+ }
94
+ }
95
+ async createBulkInlineComments(projectId, prNumber, comments) {
96
+ if (comments.length === 0)
97
+ return;
98
+ console.log(chalk.gray(`\nPosting ${comments.length} new inline comment(s) as discussion threads...\n`));
99
+ // GitLab doesn't have a bulk API, post individually in parallel
100
+ const results = await Promise.allSettled(comments.map(async (comment) => {
101
+ try {
102
+ await this.createInlineComment(projectId, prNumber, comment.body, comment.position);
103
+ console.log(chalk.gray(` ✓ Posted inline comment for ${comment.position.path}:${comment.position.line}`));
104
+ }
105
+ catch (error) {
106
+ console.warn(chalk.yellow(` ⚠ Could not post inline comment for ${comment.position.path}:${comment.position.line} - ${error.message}`));
107
+ throw error; // Re-throw to mark as rejected
108
+ }
109
+ }));
110
+ const successCount = results.filter((r) => r.status === 'fulfilled').length;
111
+ console.log(chalk.green(`✓ Posted ${successCount}/${comments.length} inline comment(s)`));
112
+ }
113
+ async addLabels(projectId, prNumber, labels) {
114
+ await this.client.addLabel(projectId, prNumber, labels);
115
+ }
116
+ async hasLabel(projectId, prNumber, label) {
117
+ return await this.client.hasLabel(projectId, prNumber, label);
118
+ }
119
+ }
120
+ //# sourceMappingURL=platform-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-adapter.js","sourceRoot":"","sources":["../../src/gitlab/platform-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=platform-adapter.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-adapter.test.d.ts","sourceRoot":"","sources":["../../src/gitlab/platform-adapter.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,21 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { GitLabPlatformAdapter } from './platform-adapter.js';
3
+ describe('GitLabPlatformAdapter', () => {
4
+ it('falls back to general comment when inline comment fails', async () => {
5
+ const client = {
6
+ createMRDiscussionThread: vi.fn().mockRejectedValue(new Error('boom')),
7
+ createMRComment: vi.fn().mockResolvedValue(undefined),
8
+ };
9
+ const adapter = new GitLabPlatformAdapter(client);
10
+ await adapter.createInlineComment('project', 42, 'body', {
11
+ path: 'src/index.ts',
12
+ line: 10,
13
+ baseSha: 'base',
14
+ headSha: 'head',
15
+ startSha: 'start',
16
+ });
17
+ expect(client.createMRDiscussionThread).toHaveBeenCalledTimes(1);
18
+ expect(client.createMRComment).toHaveBeenCalledWith('project', 42, 'body');
19
+ });
20
+ });
21
+ //# sourceMappingURL=platform-adapter.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-adapter.test.js","sourceRoot":"","sources":["../../src/gitlab/platform-adapter.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,MAAM,GAAG;YACb,wBAAwB,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC;YACtE,eAAe,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;SACtD,CAAC;QAEF,MAAM,OAAO,GAAG,IAAI,qBAAqB,CAAC,MAAa,CAAC,CAAC;QAEzD,MAAM,OAAO,CAAC,mBAAmB,CAAC,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE;YACvD,IAAI,EAAE,cAAc;YACpB,IAAI,EAAE,EAAE;YACR,OAAO,EAAE,MAAM;YACf,OAAO,EAAE,MAAM;YACf,QAAQ,EAAE,OAAO;SAClB,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACjE,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,oBAAoB,CAAC,SAAS,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ describe('placeholder', () => {
3
+ it('should pass', () => {
4
+ expect(true).toBe(true);
5
+ });
6
+ });
7
+ //# sourceMappingURL=index.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE9C,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,aAAa,EAAE,GAAG,EAAE;QACrB,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * GitLab Code Quality Report Generator
3
+ *
4
+ * Generates code quality reports in GitLab's JSON format for CI/CD integration.
5
+ * @see https://docs.gitlab.com/ci/testing/code_quality/
6
+ */
7
+ import type { ReviewIssue } from './comment-formatter.js';
8
+ /**
9
+ * GitLab Code Quality issue structure
10
+ * Follows the CodeClimate format required by GitLab
11
+ */
12
+ export interface CodeQualityIssue {
13
+ /** Human-readable description of the violation */
14
+ description: string;
15
+ /** Unique name representing the static analysis check */
16
+ check_name: string;
17
+ /** Unique fingerprint to identify the violation (e.g., MD5 hash) */
18
+ fingerprint: string;
19
+ /** Severity level: info, minor, major, critical, or blocker */
20
+ severity: 'info' | 'minor' | 'major' | 'critical' | 'blocker';
21
+ /** Location of the issue */
22
+ location: {
23
+ /** Relative path to the file */
24
+ path: string;
25
+ /** Line information */
26
+ lines: {
27
+ /** Starting line number */
28
+ begin: number;
29
+ };
30
+ };
31
+ }
32
+ /**
33
+ * Convert DRS ReviewIssue to GitLab CodeQuality format
34
+ */
35
+ export declare function convertToCodeQualityIssue(issue: ReviewIssue): CodeQualityIssue;
36
+ /**
37
+ * Generate GitLab code quality report from review issues
38
+ */
39
+ export declare function generateCodeQualityReport(issues: ReviewIssue[]): CodeQualityIssue[];
40
+ /**
41
+ * Convert code quality report to JSON string
42
+ */
43
+ export declare function formatCodeQualityReport(report: CodeQualityIssue[]): string;
44
+ //# sourceMappingURL=code-quality-report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-quality-report.d.ts","sourceRoot":"","sources":["../../src/lib/code-quality-report.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAG1D;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,kDAAkD;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;IAC9D,4BAA4B;IAC5B,QAAQ,EAAE;QACR,gCAAgC;QAChC,IAAI,EAAE,MAAM,CAAC;QACb,uBAAuB;QACvB,KAAK,EAAE;YACL,2BAA2B;YAC3B,KAAK,EAAE,MAAM,CAAC;SACf,CAAC;KACH,CAAC;CACH;AAyBD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,WAAW,GAAG,gBAAgB,CAmB9E;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,gBAAgB,EAAE,CAEnF;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAE1E"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * GitLab Code Quality Report Generator
3
+ *
4
+ * Generates code quality reports in GitLab's JSON format for CI/CD integration.
5
+ * @see https://docs.gitlab.com/ci/testing/code_quality/
6
+ */
7
+ import { createIssueFingerprint } from './comment-manager.js';
8
+ /**
9
+ * Map DRS severity to GitLab code quality severity
10
+ */
11
+ function mapSeverity(drsSeverity) {
12
+ const severityMap = {
13
+ CRITICAL: 'blocker',
14
+ HIGH: 'critical',
15
+ MEDIUM: 'major',
16
+ LOW: 'minor',
17
+ INFO: 'info',
18
+ };
19
+ return severityMap[drsSeverity] || 'info';
20
+ }
21
+ /**
22
+ * Generate check name from category and severity
23
+ */
24
+ function generateCheckName(issue) {
25
+ const category = issue.category.toLowerCase().replace(/\s+/g, '-');
26
+ return `drs-${category}`;
27
+ }
28
+ /**
29
+ * Convert DRS ReviewIssue to GitLab CodeQuality format
30
+ */
31
+ export function convertToCodeQualityIssue(issue) {
32
+ // Build description with problem and solution
33
+ let description = issue.problem;
34
+ if (issue.solution) {
35
+ description += ` ${issue.solution}`;
36
+ }
37
+ return {
38
+ description,
39
+ check_name: generateCheckName(issue),
40
+ fingerprint: createIssueFingerprint(issue),
41
+ severity: mapSeverity(issue.severity),
42
+ location: {
43
+ path: issue.file,
44
+ lines: {
45
+ begin: issue.line || 1,
46
+ },
47
+ },
48
+ };
49
+ }
50
+ /**
51
+ * Generate GitLab code quality report from review issues
52
+ */
53
+ export function generateCodeQualityReport(issues) {
54
+ return issues.map(convertToCodeQualityIssue);
55
+ }
56
+ /**
57
+ * Convert code quality report to JSON string
58
+ */
59
+ export function formatCodeQualityReport(report) {
60
+ return JSON.stringify(report, null, 2);
61
+ }
62
+ //# sourceMappingURL=code-quality-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-quality-report.js","sourceRoot":"","sources":["../../src/lib/code-quality-report.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AA2B9D;;GAEG;AACH,SAAS,WAAW,CAAC,WAAmB;IACtC,MAAM,WAAW,GAAiD;QAChE,QAAQ,EAAE,SAAS;QACnB,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,OAAO;QACf,GAAG,EAAE,OAAO;QACZ,IAAI,EAAE,MAAM;KACb,CAAC;IAEF,OAAO,WAAW,CAAC,WAAW,CAAC,IAAI,MAAM,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,KAAkB;IAC3C,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnE,OAAO,OAAO,QAAQ,EAAE,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,KAAkB;IAC1D,8CAA8C;IAC9C,IAAI,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC;IAChC,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACnB,WAAW,IAAI,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;IACtC,CAAC;IAED,OAAO;QACL,WAAW;QACX,UAAU,EAAE,iBAAiB,CAAC,KAAK,CAAC;QACpC,WAAW,EAAE,sBAAsB,CAAC,KAAK,CAAC;QAC1C,QAAQ,EAAE,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC;QACrC,QAAQ,EAAE;YACR,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,KAAK,EAAE;gBACL,KAAK,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC;aACvB;SACF;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,MAAqB;IAC7D,OAAO,MAAM,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAA0B;IAChE,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACzC,CAAC"}