@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,29 @@
1
+ import type { ReviewIssue } from './comment-formatter.js';
2
+ /**
3
+ * Parse review issues from agent response messages
4
+ *
5
+ * Agents should output JSON in the following format:
6
+ * ```json
7
+ * {
8
+ * "issues": [
9
+ * {
10
+ * "category": "SECURITY" | "QUALITY" | "STYLE" | "PERFORMANCE",
11
+ * "severity": "CRITICAL" | "HIGH" | "MEDIUM" | "LOW",
12
+ * "title": "Issue title",
13
+ * "file": "path/to/file.ts",
14
+ * "line": 42,
15
+ * "problem": "Description of the problem",
16
+ * "solution": "Suggested fix",
17
+ * "references": ["https://link1", "https://link2"],
18
+ * "agent": "security"
19
+ * }
20
+ * ]
21
+ * }
22
+ * ```
23
+ */
24
+ export declare function parseReviewIssues(content: string, agentName?: string): ReviewIssue[];
25
+ /**
26
+ * Extract agent name from session context or message
27
+ */
28
+ export declare function extractAgentName(message: string): string;
29
+ //# sourceMappingURL=issue-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue-parser.d.ts","sourceRoot":"","sources":["../../src/lib/issue-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,GAAE,MAAkB,GAAG,WAAW,EAAE,CAuE/F;AAqDD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOxD"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Parse review issues from agent response messages
3
+ *
4
+ * Agents should output JSON in the following format:
5
+ * ```json
6
+ * {
7
+ * "issues": [
8
+ * {
9
+ * "category": "SECURITY" | "QUALITY" | "STYLE" | "PERFORMANCE",
10
+ * "severity": "CRITICAL" | "HIGH" | "MEDIUM" | "LOW",
11
+ * "title": "Issue title",
12
+ * "file": "path/to/file.ts",
13
+ * "line": 42,
14
+ * "problem": "Description of the problem",
15
+ * "solution": "Suggested fix",
16
+ * "references": ["https://link1", "https://link2"],
17
+ * "agent": "security"
18
+ * }
19
+ * ]
20
+ * }
21
+ * ```
22
+ */
23
+ export function parseReviewIssues(content, agentName = 'unknown') {
24
+ const issues = [];
25
+ try {
26
+ // Try to find JSON blocks in the content
27
+ // Look for code blocks with ```json or raw JSON objects
28
+ const jsonBlockRegex = /```json\s*([\s\S]*?)\s*```/g;
29
+ let match;
30
+ // First try to find JSON code blocks
31
+ while ((match = jsonBlockRegex.exec(content)) !== null) {
32
+ try {
33
+ const parsed = JSON.parse(match[1]);
34
+ if (parsed.issues && Array.isArray(parsed.issues)) {
35
+ for (const issue of parsed.issues) {
36
+ if (isValidIssue(issue)) {
37
+ issues.push({
38
+ ...issue,
39
+ agent: issue.agent || agentName,
40
+ });
41
+ }
42
+ }
43
+ }
44
+ }
45
+ catch (e) {
46
+ // Continue to next match
47
+ }
48
+ }
49
+ // If no code blocks found, try to find raw JSON objects
50
+ if (issues.length === 0) {
51
+ // Try to parse the entire content as JSON
52
+ try {
53
+ const parsed = JSON.parse(content);
54
+ if (parsed.issues && Array.isArray(parsed.issues)) {
55
+ for (const issue of parsed.issues) {
56
+ if (isValidIssue(issue)) {
57
+ issues.push({
58
+ ...issue,
59
+ agent: issue.agent || agentName,
60
+ });
61
+ }
62
+ }
63
+ }
64
+ }
65
+ catch (e) {
66
+ // Not valid JSON, try to find JSON objects with better bracket matching
67
+ const jsonObjects = extractJsonObjects(content);
68
+ for (const jsonStr of jsonObjects) {
69
+ try {
70
+ const parsed = JSON.parse(jsonStr);
71
+ if (parsed.issues && Array.isArray(parsed.issues)) {
72
+ for (const issue of parsed.issues) {
73
+ if (isValidIssue(issue)) {
74
+ issues.push({
75
+ ...issue,
76
+ agent: issue.agent || agentName,
77
+ });
78
+ }
79
+ }
80
+ }
81
+ }
82
+ catch (e) {
83
+ // Continue to next object
84
+ }
85
+ }
86
+ }
87
+ }
88
+ }
89
+ catch (error) {
90
+ console.warn('Failed to parse review issues from content:', error);
91
+ }
92
+ return issues;
93
+ }
94
+ /**
95
+ * Extract JSON objects from text by matching brackets
96
+ */
97
+ function extractJsonObjects(text) {
98
+ const objects = [];
99
+ let depth = 0;
100
+ let start = -1;
101
+ for (let i = 0; i < text.length; i++) {
102
+ if (text[i] === '{') {
103
+ if (depth === 0) {
104
+ start = i;
105
+ }
106
+ depth++;
107
+ }
108
+ else if (text[i] === '}') {
109
+ depth--;
110
+ if (depth === 0 && start !== -1) {
111
+ const obj = text.substring(start, i + 1);
112
+ // Only consider objects that contain "issues"
113
+ if (obj.includes('"issues"')) {
114
+ objects.push(obj);
115
+ }
116
+ start = -1;
117
+ }
118
+ }
119
+ }
120
+ return objects;
121
+ }
122
+ /**
123
+ * Validate that an object has the required ReviewIssue fields
124
+ */
125
+ function isValidIssue(obj) {
126
+ return (obj &&
127
+ typeof obj === 'object' &&
128
+ typeof obj.category === 'string' &&
129
+ ['SECURITY', 'QUALITY', 'STYLE', 'PERFORMANCE'].includes(obj.category) &&
130
+ typeof obj.severity === 'string' &&
131
+ ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW'].includes(obj.severity) &&
132
+ typeof obj.title === 'string' &&
133
+ typeof obj.file === 'string' &&
134
+ typeof obj.problem === 'string' &&
135
+ typeof obj.solution === 'string' &&
136
+ (obj.line === undefined || typeof obj.line === 'number') &&
137
+ (obj.references === undefined || Array.isArray(obj.references)) &&
138
+ (obj.agent === undefined || typeof obj.agent === 'string'));
139
+ }
140
+ /**
141
+ * Extract agent name from session context or message
142
+ */
143
+ export function extractAgentName(message) {
144
+ // Try to extract from common patterns like "Agent: security" or "Reviewer: quality"
145
+ const agentMatch = message.match(/(?:agent|reviewer):\s*(\w+)/i);
146
+ if (agentMatch) {
147
+ return agentMatch[1];
148
+ }
149
+ return 'unknown';
150
+ }
151
+ //# sourceMappingURL=issue-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue-parser.js","sourceRoot":"","sources":["../../src/lib/issue-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=issue-parser.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue-parser.test.d.ts","sourceRoot":"","sources":["../../src/lib/issue-parser.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,281 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { parseReviewIssues } from './issue-parser.js';
3
+ describe('parseReviewIssues', () => {
4
+ it('should parse valid JSON code block with issues', () => {
5
+ const content = `Here are my findings:
6
+
7
+ \`\`\`json
8
+ {
9
+ "issues": [
10
+ {
11
+ "category": "SECURITY",
12
+ "severity": "CRITICAL",
13
+ "title": "SQL Injection vulnerability",
14
+ "file": "src/api/users.ts",
15
+ "line": 42,
16
+ "problem": "Query uses string concatenation",
17
+ "solution": "Use parameterized queries",
18
+ "references": ["https://owasp.org/sql-injection"],
19
+ "agent": "security"
20
+ }
21
+ ]
22
+ }
23
+ \`\`\``;
24
+ const issues = parseReviewIssues(content, 'security');
25
+ expect(issues).toHaveLength(1);
26
+ expect(issues[0]).toEqual({
27
+ category: 'SECURITY',
28
+ severity: 'CRITICAL',
29
+ title: 'SQL Injection vulnerability',
30
+ file: 'src/api/users.ts',
31
+ line: 42,
32
+ problem: 'Query uses string concatenation',
33
+ solution: 'Use parameterized queries',
34
+ references: ['https://owasp.org/sql-injection'],
35
+ agent: 'security',
36
+ });
37
+ });
38
+ it('should parse multiple issues in a single JSON block', () => {
39
+ const content = `\`\`\`json
40
+ {
41
+ "issues": [
42
+ {
43
+ "category": "QUALITY",
44
+ "severity": "HIGH",
45
+ "title": "High complexity function",
46
+ "file": "src/utils/helper.ts",
47
+ "line": 10,
48
+ "problem": "Function has cyclomatic complexity of 15",
49
+ "solution": "Break into smaller functions",
50
+ "agent": "quality"
51
+ },
52
+ {
53
+ "category": "QUALITY",
54
+ "severity": "MEDIUM",
55
+ "title": "Code duplication",
56
+ "file": "src/utils/helper.ts",
57
+ "line": 50,
58
+ "problem": "Duplicated validation logic",
59
+ "solution": "Extract to shared validator function"
60
+ }
61
+ ]
62
+ }
63
+ \`\`\``;
64
+ const issues = parseReviewIssues(content, 'quality');
65
+ expect(issues).toHaveLength(2);
66
+ expect(issues[0].severity).toBe('HIGH');
67
+ expect(issues[1].severity).toBe('MEDIUM');
68
+ expect(issues[1].agent).toBe('quality'); // Should use default agent name
69
+ });
70
+ it('should parse raw JSON without code block markers', () => {
71
+ const content = `{"issues":[{"category":"PERFORMANCE","severity":"LOW","title":"Inefficient loop","file":"src/app.ts","line":5,"problem":"Using nested loops","solution":"Use hash map"}]}`;
72
+ const issues = parseReviewIssues(content, 'performance');
73
+ expect(issues).toHaveLength(1);
74
+ expect(issues[0].category).toBe('PERFORMANCE');
75
+ expect(issues[0].file).toBe('src/app.ts');
76
+ });
77
+ it('should handle issues without line numbers', () => {
78
+ const content = `\`\`\`json
79
+ {
80
+ "issues": [
81
+ {
82
+ "category": "STYLE",
83
+ "severity": "LOW",
84
+ "title": "Missing file header",
85
+ "file": "src/main.ts",
86
+ "problem": "No copyright header",
87
+ "solution": "Add standard file header",
88
+ "agent": "style"
89
+ }
90
+ ]
91
+ }
92
+ \`\`\``;
93
+ const issues = parseReviewIssues(content, 'style');
94
+ expect(issues).toHaveLength(1);
95
+ expect(issues[0].line).toBeUndefined();
96
+ });
97
+ it('should handle issues without references', () => {
98
+ const content = `\`\`\`json
99
+ {
100
+ "issues": [
101
+ {
102
+ "category": "QUALITY",
103
+ "severity": "MEDIUM",
104
+ "title": "Long function",
105
+ "file": "src/utils.ts",
106
+ "line": 100,
107
+ "problem": "Function exceeds 50 lines",
108
+ "solution": "Refactor into smaller functions",
109
+ "agent": "quality"
110
+ }
111
+ ]
112
+ }
113
+ \`\`\``;
114
+ const issues = parseReviewIssues(content, 'quality');
115
+ expect(issues).toHaveLength(1);
116
+ expect(issues[0].references).toBeUndefined();
117
+ });
118
+ it('should return empty array for invalid JSON', () => {
119
+ const content = 'This is not valid JSON';
120
+ const issues = parseReviewIssues(content);
121
+ expect(issues).toEqual([]);
122
+ });
123
+ it('should return empty array for JSON without issues array', () => {
124
+ const content = `\`\`\`json
125
+ {
126
+ "message": "No issues found"
127
+ }
128
+ \`\`\``;
129
+ const issues = parseReviewIssues(content);
130
+ expect(issues).toEqual([]);
131
+ });
132
+ it('should skip invalid issues that are missing required fields', () => {
133
+ const content = `\`\`\`json
134
+ {
135
+ "issues": [
136
+ {
137
+ "category": "SECURITY",
138
+ "severity": "HIGH",
139
+ "title": "Missing problem field",
140
+ "file": "src/test.ts",
141
+ "solution": "Fix it"
142
+ },
143
+ {
144
+ "category": "QUALITY",
145
+ "severity": "MEDIUM",
146
+ "title": "Valid issue",
147
+ "file": "src/valid.ts",
148
+ "line": 10,
149
+ "problem": "This is valid",
150
+ "solution": "This has all required fields"
151
+ }
152
+ ]
153
+ }
154
+ \`\`\``;
155
+ const issues = parseReviewIssues(content);
156
+ // Should only parse the valid issue
157
+ expect(issues).toHaveLength(1);
158
+ expect(issues[0].title).toBe('Valid issue');
159
+ });
160
+ it('should reject issues with invalid category', () => {
161
+ const content = `\`\`\`json
162
+ {
163
+ "issues": [
164
+ {
165
+ "category": "INVALID_CATEGORY",
166
+ "severity": "HIGH",
167
+ "title": "Test",
168
+ "file": "test.ts",
169
+ "problem": "Problem",
170
+ "solution": "Solution"
171
+ }
172
+ ]
173
+ }
174
+ \`\`\``;
175
+ const issues = parseReviewIssues(content);
176
+ expect(issues).toEqual([]);
177
+ });
178
+ it('should reject issues with invalid severity', () => {
179
+ const content = `\`\`\`json
180
+ {
181
+ "issues": [
182
+ {
183
+ "category": "SECURITY",
184
+ "severity": "SUPER_CRITICAL",
185
+ "title": "Test",
186
+ "file": "test.ts",
187
+ "problem": "Problem",
188
+ "solution": "Solution"
189
+ }
190
+ ]
191
+ }
192
+ \`\`\``;
193
+ const issues = parseReviewIssues(content);
194
+ expect(issues).toEqual([]);
195
+ });
196
+ it('should handle multiple JSON blocks in same content', () => {
197
+ const content = `First agent findings:
198
+
199
+ \`\`\`json
200
+ {
201
+ "issues": [
202
+ {
203
+ "category": "SECURITY",
204
+ "severity": "HIGH",
205
+ "title": "Issue 1",
206
+ "file": "src/a.ts",
207
+ "line": 1,
208
+ "problem": "Problem 1",
209
+ "solution": "Solution 1",
210
+ "agent": "security"
211
+ }
212
+ ]
213
+ }
214
+ \`\`\`
215
+
216
+ Second agent findings:
217
+
218
+ \`\`\`json
219
+ {
220
+ "issues": [
221
+ {
222
+ "category": "QUALITY",
223
+ "severity": "MEDIUM",
224
+ "title": "Issue 2",
225
+ "file": "src/b.ts",
226
+ "line": 2,
227
+ "problem": "Problem 2",
228
+ "solution": "Solution 2",
229
+ "agent": "quality"
230
+ }
231
+ ]
232
+ }
233
+ \`\`\``;
234
+ const issues = parseReviewIssues(content);
235
+ expect(issues).toHaveLength(2);
236
+ expect(issues[0].agent).toBe('security');
237
+ expect(issues[1].agent).toBe('quality');
238
+ });
239
+ it('should use provided agent name when issue does not have agent field', () => {
240
+ const content = `\`\`\`json
241
+ {
242
+ "issues": [
243
+ {
244
+ "category": "PERFORMANCE",
245
+ "severity": "LOW",
246
+ "title": "Slow operation",
247
+ "file": "src/perf.ts",
248
+ "line": 20,
249
+ "problem": "Inefficient algorithm",
250
+ "solution": "Use better algorithm"
251
+ }
252
+ ]
253
+ }
254
+ \`\`\``;
255
+ const issues = parseReviewIssues(content, 'performance-agent');
256
+ expect(issues).toHaveLength(1);
257
+ expect(issues[0].agent).toBe('performance-agent');
258
+ });
259
+ it('should handle whitespace in JSON code blocks', () => {
260
+ const content = `\`\`\`json
261
+
262
+ {
263
+ "issues": [
264
+ {
265
+ "category": "STYLE",
266
+ "severity": "LOW",
267
+ "title": "Formatting",
268
+ "file": "src/style.ts",
269
+ "line": 1,
270
+ "problem": "Inconsistent formatting",
271
+ "solution": "Run prettier"
272
+ }
273
+ ]
274
+ }
275
+
276
+ \`\`\``;
277
+ const issues = parseReviewIssues(content);
278
+ expect(issues).toHaveLength(1);
279
+ });
280
+ });
281
+ //# sourceMappingURL=issue-parser.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue-parser.test.js","sourceRoot":"","sources":["../../src/lib/issue-parser.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Platform abstraction layer for GitHub and GitLab
3
+ *
4
+ * This module provides common interfaces for interacting with different
5
+ * code review platforms (GitHub, GitLab) in a unified way.
6
+ */
7
+ /**
8
+ * Represents a file change in a pull/merge request
9
+ */
10
+ export interface FileChange {
11
+ /** Path to the file */
12
+ filename: string;
13
+ /** Type of change */
14
+ status: 'added' | 'removed' | 'modified' | 'renamed' | 'copied' | 'changed' | 'unchanged';
15
+ /** Number of lines added */
16
+ additions: number;
17
+ /** Number of lines deleted */
18
+ deletions: number;
19
+ /** Unified diff patch */
20
+ patch?: string;
21
+ /** Previous filename (for renamed files) */
22
+ previousFilename?: string;
23
+ }
24
+ /**
25
+ * Represents a pull/merge request
26
+ */
27
+ export interface PullRequest {
28
+ /** PR/MR number or ID */
29
+ number: number;
30
+ /** Title */
31
+ title: string;
32
+ /** Description/body */
33
+ description?: string;
34
+ /** Author username or name */
35
+ author: string;
36
+ /** Source branch */
37
+ sourceBranch: string;
38
+ /** Target branch */
39
+ targetBranch: string;
40
+ /** Head commit SHA */
41
+ headSha: string;
42
+ /** Additional platform-specific data */
43
+ platformData?: any;
44
+ }
45
+ /**
46
+ * Represents a comment on a PR/MR
47
+ */
48
+ export interface Comment {
49
+ /** Comment ID */
50
+ id: number | string;
51
+ /** Comment body/content */
52
+ body: string;
53
+ }
54
+ /**
55
+ * Position data for inline comments
56
+ */
57
+ export interface InlineCommentPosition {
58
+ /** File path */
59
+ path: string;
60
+ /** Line number in the new version */
61
+ line: number;
62
+ /** Commit SHA (GitHub) or diff refs (GitLab) */
63
+ commitSha?: string;
64
+ baseSha?: string;
65
+ headSha?: string;
66
+ startSha?: string;
67
+ }
68
+ /**
69
+ * Common interface for platform clients (GitHub, GitLab, etc.)
70
+ */
71
+ export interface PlatformClient {
72
+ /**
73
+ * Get pull/merge request details
74
+ */
75
+ getPullRequest(projectId: string, prNumber: number): Promise<PullRequest>;
76
+ /**
77
+ * Get list of changed files in a PR/MR
78
+ */
79
+ getChangedFiles(projectId: string, prNumber: number): Promise<FileChange[]>;
80
+ /**
81
+ * Get existing comments on the PR/MR
82
+ */
83
+ getComments(projectId: string, prNumber: number): Promise<Comment[]>;
84
+ /**
85
+ * Get existing inline/review comments
86
+ */
87
+ getInlineComments(projectId: string, prNumber: number): Promise<Comment[]>;
88
+ /**
89
+ * Create a general comment on the PR/MR
90
+ */
91
+ createComment(projectId: string, prNumber: number, body: string): Promise<void>;
92
+ /**
93
+ * Update an existing comment
94
+ */
95
+ updateComment(projectId: string, prNumber: number, commentId: number | string, body: string): Promise<void>;
96
+ /**
97
+ * Create an inline comment at a specific line
98
+ */
99
+ createInlineComment(projectId: string, prNumber: number, body: string, position: InlineCommentPosition): Promise<void>;
100
+ /**
101
+ * Create multiple inline comments in bulk (if supported)
102
+ * Falls back to individual comments if not supported
103
+ */
104
+ createBulkInlineComments(projectId: string, prNumber: number, comments: Array<{
105
+ body: string;
106
+ position: InlineCommentPosition;
107
+ }>): Promise<void>;
108
+ /**
109
+ * Add labels to the PR/MR
110
+ */
111
+ addLabels(projectId: string, prNumber: number, labels: string[]): Promise<void>;
112
+ /**
113
+ * Check if PR/MR has a specific label
114
+ */
115
+ hasLabel(projectId: string, prNumber: number, label: string): Promise<boolean>;
116
+ }
117
+ /**
118
+ * Validator for checking if a line can be commented on
119
+ */
120
+ export interface LineValidator {
121
+ /**
122
+ * Check if a line number is valid for commenting
123
+ */
124
+ isValidLine(file: string, line: number): boolean;
125
+ }
126
+ /**
127
+ * Factory function type for creating platform clients
128
+ */
129
+ export type PlatformClientFactory = () => PlatformClient;
130
+ //# sourceMappingURL=platform-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-client.d.ts","sourceRoot":"","sources":["../../src/lib/platform-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Platform abstraction layer for GitHub and GitLab
3
+ *
4
+ * This module provides common interfaces for interacting with different
5
+ * code review platforms (GitHub, GitLab) in a unified way.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=platform-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-client.js","sourceRoot":"","sources":["../../src/lib/platform-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Position validation utilities for platform-specific inline comment requirements
3
+ */
4
+ import type { InlineCommentPosition } from './platform-client.js';
5
+ /**
6
+ * Result of position validation
7
+ */
8
+ export interface PositionValidationResult {
9
+ isValid: boolean;
10
+ error?: string;
11
+ }
12
+ /**
13
+ * Base interface for position validators
14
+ */
15
+ export interface PositionValidator {
16
+ validate(position: InlineCommentPosition): PositionValidationResult;
17
+ }
18
+ /**
19
+ * GitHub position validator
20
+ * Requires: commitSha
21
+ */
22
+ export declare class GitHubPositionValidator implements PositionValidator {
23
+ validate(position: InlineCommentPosition): PositionValidationResult;
24
+ }
25
+ /**
26
+ * GitLab position validator
27
+ * Requires: baseSha, headSha, startSha
28
+ */
29
+ export declare class GitLabPositionValidator implements PositionValidator {
30
+ validate(position: InlineCommentPosition): PositionValidationResult;
31
+ }
32
+ /**
33
+ * Helper to validate and throw if invalid
34
+ */
35
+ export declare function validatePositionOrThrow(position: InlineCommentPosition, validator: PositionValidator): void;
36
+ //# sourceMappingURL=position-validator.d.ts.map