@diff-review-system/drs 1.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.
Files changed (63) hide show
  1. package/.opencode/agent/github-reviewer.md +62 -0
  2. package/.opencode/agent/gitlab-reviewer.md +62 -0
  3. package/.opencode/agent/local-reviewer.md +71 -0
  4. package/.opencode/agent/review/performance.md +151 -0
  5. package/.opencode/agent/review/quality.md +127 -0
  6. package/.opencode/agent/review/security.md +115 -0
  7. package/.opencode/agent/review/style.md +116 -0
  8. package/.opencode/opencode.jsonc +52 -0
  9. package/LICENSE +201 -0
  10. package/README.md +361 -0
  11. package/dist/ci/runner.d.ts +21 -0
  12. package/dist/ci/runner.d.ts.map +1 -0
  13. package/dist/ci/runner.js +82 -0
  14. package/dist/ci/runner.js.map +1 -0
  15. package/dist/cli/index.d.ts +3 -0
  16. package/dist/cli/index.d.ts.map +1 -0
  17. package/dist/cli/index.js +137 -0
  18. package/dist/cli/index.js.map +1 -0
  19. package/dist/cli/init.d.ts +5 -0
  20. package/dist/cli/init.d.ts.map +1 -0
  21. package/dist/cli/init.js +166 -0
  22. package/dist/cli/init.js.map +1 -0
  23. package/dist/cli/review-local.d.ts +9 -0
  24. package/dist/cli/review-local.d.ts.map +1 -0
  25. package/dist/cli/review-local.js +105 -0
  26. package/dist/cli/review-local.js.map +1 -0
  27. package/dist/cli/review-mr.d.ts +11 -0
  28. package/dist/cli/review-mr.d.ts.map +1 -0
  29. package/dist/cli/review-mr.js +128 -0
  30. package/dist/cli/review-mr.js.map +1 -0
  31. package/dist/cli/review-pr.d.ts +12 -0
  32. package/dist/cli/review-pr.d.ts.map +1 -0
  33. package/dist/cli/review-pr.js +125 -0
  34. package/dist/cli/review-pr.js.map +1 -0
  35. package/dist/github/client.d.ts +1346 -0
  36. package/dist/github/client.d.ts.map +1 -0
  37. package/dist/github/client.js +137 -0
  38. package/dist/github/client.js.map +1 -0
  39. package/dist/gitlab/client.d.ts +55 -0
  40. package/dist/gitlab/client.d.ts.map +1 -0
  41. package/dist/gitlab/client.js +86 -0
  42. package/dist/gitlab/client.js.map +1 -0
  43. package/dist/gitlab/comment-formatter.d.ts +36 -0
  44. package/dist/gitlab/comment-formatter.d.ts.map +1 -0
  45. package/dist/gitlab/comment-formatter.js +118 -0
  46. package/dist/gitlab/comment-formatter.js.map +1 -0
  47. package/dist/gitlab/diff-parser.d.ts +41 -0
  48. package/dist/gitlab/diff-parser.d.ts.map +1 -0
  49. package/dist/gitlab/diff-parser.js +147 -0
  50. package/dist/gitlab/diff-parser.js.map +1 -0
  51. package/dist/lib/config.d.ts +42 -0
  52. package/dist/lib/config.d.ts.map +1 -0
  53. package/dist/lib/config.js +144 -0
  54. package/dist/lib/config.js.map +1 -0
  55. package/dist/opencode/agent-loader.d.ts +31 -0
  56. package/dist/opencode/agent-loader.d.ts.map +1 -0
  57. package/dist/opencode/agent-loader.js +115 -0
  58. package/dist/opencode/agent-loader.js.map +1 -0
  59. package/dist/opencode/client.d.ts +82 -0
  60. package/dist/opencode/client.d.ts.map +1 -0
  61. package/dist/opencode/client.js +184 -0
  62. package/dist/opencode/client.js.map +1 -0
  63. package/package.json +70 -0
@@ -0,0 +1,128 @@
1
+ import chalk from 'chalk';
2
+ import { createGitLabClient } from '../gitlab/client.js';
3
+ import { createOpencodeClientInstance } from '../opencode/client.js';
4
+ import { parseDiff, getChangedFiles } from '../gitlab/diff-parser.js';
5
+ import { formatSummaryComment, formatIssueComment, calculateSummary, } from '../gitlab/comment-formatter.js';
6
+ /**
7
+ * Review a GitLab merge request
8
+ */
9
+ export async function reviewMR(config, options) {
10
+ console.log(chalk.bold.cyan('\nšŸ” DRS GitLab MR Review\n'));
11
+ // Initialize GitLab client
12
+ const gitlab = createGitLabClient();
13
+ // Fetch MR details
14
+ console.log(chalk.gray(`Fetching MR !${options.mrIid} from project ${options.projectId}...\n`));
15
+ const mr = await gitlab.getMergeRequest(options.projectId, options.mrIid);
16
+ const changes = await gitlab.getMRChanges(options.projectId, options.mrIid);
17
+ console.log(chalk.bold(`MR: ${mr.title}`));
18
+ console.log(chalk.gray(`Author: ${mr.author?.name || 'Unknown'}`));
19
+ console.log(chalk.gray(`Branch: ${mr.source_branch} → ${mr.target_branch}`));
20
+ console.log(chalk.gray(`Files changed: ${changes.length}\n`));
21
+ if (changes.length === 0) {
22
+ console.log(chalk.yellow('āœ“ No changes to review\n'));
23
+ return;
24
+ }
25
+ // Parse diffs
26
+ const diffs = changes.map(change => parseDiff(change.diff)).flat();
27
+ const changedFiles = getChangedFiles(diffs);
28
+ // Connect to OpenCode (or start in-process if serverUrl is empty)
29
+ console.log(chalk.gray('Connecting to OpenCode server...\n'));
30
+ const opencode = await createOpencodeClientInstance({
31
+ baseUrl: config.opencode.serverUrl || undefined,
32
+ });
33
+ // Create review session
34
+ console.log(chalk.gray('Starting AI review...\n'));
35
+ const agentsList = config.review.agents.join(',');
36
+ const session = await opencode.createSession({
37
+ agent: 'gitlab-reviewer',
38
+ message: `Review MR !${options.mrIid} in project ${options.projectId}. Agents: ${agentsList}. Files: ${changedFiles.join(', ')}`,
39
+ context: {
40
+ projectId: options.projectId,
41
+ mrIid: options.mrIid,
42
+ files: changedFiles,
43
+ agents: config.review.agents,
44
+ mr: {
45
+ title: mr.title,
46
+ description: mr.description,
47
+ author: mr.author?.name,
48
+ sourceBranch: mr.source_branch,
49
+ targetBranch: mr.target_branch,
50
+ },
51
+ },
52
+ });
53
+ // Stream and collect results
54
+ const issues = [];
55
+ try {
56
+ for await (const message of opencode.streamMessages(session.id)) {
57
+ if (message.role === 'assistant') {
58
+ // Parse issues from assistant messages
59
+ // TODO: Implement structured output parsing once OpenCode SDK supports it
60
+ console.log(message.content);
61
+ // For now, we'll display raw output
62
+ // In production, parse structured JSON responses from agents
63
+ }
64
+ }
65
+ // Display and post summary
66
+ const summary = calculateSummary(changedFiles.length, issues);
67
+ console.log(chalk.bold('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
68
+ console.log(chalk.bold('šŸ“Š Review Summary'));
69
+ console.log(chalk.bold('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'));
70
+ console.log(` Files reviewed: ${chalk.cyan(summary.filesReviewed)}`);
71
+ console.log(` Issues found: ${chalk.yellow(summary.issuesFound)}`);
72
+ if (summary.issuesFound > 0) {
73
+ console.log(` šŸ”“ Critical: ${chalk.red(summary.bySeverity.CRITICAL)}`);
74
+ console.log(` 🟔 High: ${chalk.yellow(summary.bySeverity.HIGH)}`);
75
+ console.log(` 🟠 Medium: ${chalk.hex('#FFA500')(summary.bySeverity.MEDIUM)}`);
76
+ console.log(` ⚪ Low: ${chalk.gray(summary.bySeverity.LOW)}`);
77
+ }
78
+ console.log('');
79
+ // Post comments to GitLab if requested
80
+ if (options.postComments) {
81
+ console.log(chalk.gray('Posting review comments to GitLab...\n'));
82
+ // Post summary comment
83
+ const summaryComment = formatSummaryComment(summary, issues);
84
+ await gitlab.createMRComment(options.projectId, options.mrIid, summaryComment);
85
+ // Post individual issue comments as discussion threads
86
+ for (const issue of issues) {
87
+ const diffRefs = mr.diff_refs;
88
+ if (issue.line && diffRefs && diffRefs.base_sha && diffRefs.head_sha && diffRefs.start_sha) {
89
+ try {
90
+ await gitlab.createMRDiscussionThread(options.projectId, options.mrIid, formatIssueComment(issue), {
91
+ baseSha: diffRefs.base_sha,
92
+ headSha: diffRefs.head_sha,
93
+ startSha: diffRefs.start_sha,
94
+ newPath: issue.file,
95
+ newLine: issue.line,
96
+ });
97
+ }
98
+ catch (error) {
99
+ // If line-specific comment fails, post as general comment
100
+ console.warn(chalk.yellow(`Warning: Could not post line comment for ${issue.file}:${issue.line}`));
101
+ await gitlab.createMRComment(options.projectId, options.mrIid, formatIssueComment(issue));
102
+ }
103
+ }
104
+ else {
105
+ // Post as general comment if no line number
106
+ await gitlab.createMRComment(options.projectId, options.mrIid, formatIssueComment(issue));
107
+ }
108
+ }
109
+ // Add ai-reviewed label
110
+ await gitlab.addLabel(options.projectId, options.mrIid, ['ai-reviewed']);
111
+ console.log(chalk.green('āœ“ Review posted to GitLab MR\n'));
112
+ }
113
+ // Exit with error code if critical issues found
114
+ if (summary.bySeverity.CRITICAL > 0) {
115
+ console.log(chalk.red.bold('āš ļø Critical issues found!\n'));
116
+ process.exit(1);
117
+ }
118
+ else if (summary.issuesFound === 0) {
119
+ console.log(chalk.green('āœ“ No issues found! MR looks good.\n'));
120
+ }
121
+ }
122
+ finally {
123
+ // Clean up session and shutdown in-process server if applicable
124
+ await opencode.closeSession(session.id);
125
+ await opencode.shutdown();
126
+ }
127
+ }
128
+ //# sourceMappingURL=review-mr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-mr.js","sourceRoot":"","sources":["../../src/cli/review-mr.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { DRSConfig } from '../lib/config.js';
2
+ export interface ReviewPROptions {
3
+ owner: string;
4
+ repo: string;
5
+ prNumber: number;
6
+ postComments: boolean;
7
+ }
8
+ /**
9
+ * Review a GitHub pull request
10
+ */
11
+ export declare function reviewPR(config: DRSConfig, options: ReviewPROptions): Promise<void>;
12
+ //# sourceMappingURL=review-pr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-pr.d.ts","sourceRoot":"","sources":["../../src/cli/review-pr.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAWlD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA0JzF"}
@@ -0,0 +1,125 @@
1
+ import chalk from 'chalk';
2
+ import { createGitHubClient } from '../github/client.js';
3
+ import { createOpencodeClientInstance } from '../opencode/client.js';
4
+ import { parseDiff, getChangedFiles } from '../gitlab/diff-parser.js';
5
+ import { formatSummaryComment, formatIssueComment, calculateSummary, } from '../gitlab/comment-formatter.js';
6
+ /**
7
+ * Review a GitHub pull request
8
+ */
9
+ export async function reviewPR(config, options) {
10
+ console.log(chalk.bold.cyan('\nšŸ” DRS GitHub PR Review\n'));
11
+ // Initialize GitHub client
12
+ const github = createGitHubClient();
13
+ // Fetch PR details
14
+ console.log(chalk.gray(`Fetching PR #${options.prNumber} from ${options.owner}/${options.repo}...\n`));
15
+ const pr = await github.getPullRequest(options.owner, options.repo, options.prNumber);
16
+ const files = await github.getPRFiles(options.owner, options.repo, options.prNumber);
17
+ console.log(chalk.bold(`PR: ${pr.title}`));
18
+ console.log(chalk.gray(`Author: ${pr.user?.login || 'Unknown'}`));
19
+ console.log(chalk.gray(`Branch: ${pr.head.ref} → ${pr.base.ref}`));
20
+ console.log(chalk.gray(`Files changed: ${files.length}\n`));
21
+ if (files.length === 0) {
22
+ console.log(chalk.yellow('āœ“ No changes to review\n'));
23
+ return;
24
+ }
25
+ // Parse diffs
26
+ const diffs = files
27
+ .filter(file => file.patch) // Only files with diffs
28
+ .map(file => parseDiff(file.patch || ''))
29
+ .flat();
30
+ const changedFiles = getChangedFiles(diffs);
31
+ // Connect to OpenCode (or start in-process if serverUrl is empty)
32
+ console.log(chalk.gray('Connecting to OpenCode server...\n'));
33
+ const opencode = await createOpencodeClientInstance({
34
+ baseUrl: config.opencode.serverUrl || undefined,
35
+ });
36
+ // Create review session
37
+ console.log(chalk.gray('Starting AI review...\n'));
38
+ const agentsList = config.review.agents.join(',');
39
+ const session = await opencode.createSession({
40
+ agent: 'github-reviewer',
41
+ message: `Review PR #${options.prNumber} in ${options.owner}/${options.repo}. Agents: ${agentsList}. Files: ${changedFiles.join(', ')}`,
42
+ context: {
43
+ owner: options.owner,
44
+ repo: options.repo,
45
+ prNumber: options.prNumber,
46
+ files: changedFiles,
47
+ agents: config.review.agents,
48
+ pr: {
49
+ title: pr.title,
50
+ description: pr.body,
51
+ author: pr.user?.login,
52
+ headRef: pr.head.ref,
53
+ baseRef: pr.base.ref,
54
+ },
55
+ },
56
+ });
57
+ // Stream and collect results
58
+ const issues = [];
59
+ try {
60
+ for await (const message of opencode.streamMessages(session.id)) {
61
+ if (message.role === 'assistant') {
62
+ // Parse issues from assistant messages
63
+ // TODO: Implement structured output parsing once OpenCode SDK supports it
64
+ console.log(message.content);
65
+ // For now, we'll display raw output
66
+ // In production, parse structured JSON responses from agents
67
+ }
68
+ }
69
+ // Display and post summary
70
+ const summary = calculateSummary(changedFiles.length, issues);
71
+ console.log(chalk.bold('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
72
+ console.log(chalk.bold('šŸ“Š Review Summary'));
73
+ console.log(chalk.bold('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'));
74
+ console.log(` Files reviewed: ${chalk.cyan(summary.filesReviewed)}`);
75
+ console.log(` Issues found: ${chalk.yellow(summary.issuesFound)}`);
76
+ if (summary.issuesFound > 0) {
77
+ console.log(` šŸ”“ Critical: ${chalk.red(summary.bySeverity.CRITICAL)}`);
78
+ console.log(` 🟔 High: ${chalk.yellow(summary.bySeverity.HIGH)}`);
79
+ console.log(` 🟠 Medium: ${chalk.hex('#FFA500')(summary.bySeverity.MEDIUM)}`);
80
+ console.log(` ⚪ Low: ${chalk.gray(summary.bySeverity.LOW)}`);
81
+ }
82
+ console.log('');
83
+ // Post comments to GitHub if requested
84
+ if (options.postComments) {
85
+ console.log(chalk.gray('Posting review comments to GitHub...\n'));
86
+ // Post summary comment
87
+ const summaryComment = formatSummaryComment(summary, issues);
88
+ await github.createPRComment(options.owner, options.repo, options.prNumber, summaryComment);
89
+ // Post individual issue comments as review comments
90
+ for (const issue of issues) {
91
+ if (issue.line && pr.head.sha) {
92
+ try {
93
+ await github.createPRReviewComment(options.owner, options.repo, options.prNumber, formatIssueComment(issue), pr.head.sha, issue.file, issue.line);
94
+ }
95
+ catch (error) {
96
+ // If line-specific comment fails, post as general comment
97
+ console.warn(chalk.yellow(`Warning: Could not post line comment for ${issue.file}:${issue.line}`));
98
+ await github.createPRComment(options.owner, options.repo, options.prNumber, formatIssueComment(issue));
99
+ }
100
+ }
101
+ else {
102
+ // Post as general comment if no line number
103
+ await github.createPRComment(options.owner, options.repo, options.prNumber, formatIssueComment(issue));
104
+ }
105
+ }
106
+ // Add ai-reviewed label
107
+ await github.addLabels(options.owner, options.repo, options.prNumber, ['ai-reviewed']);
108
+ console.log(chalk.green('āœ“ Review posted to GitHub PR\n'));
109
+ }
110
+ // Exit with error code if critical issues found
111
+ if (summary.bySeverity.CRITICAL > 0) {
112
+ console.log(chalk.red.bold('āš ļø Critical issues found!\n'));
113
+ process.exit(1);
114
+ }
115
+ else if (summary.issuesFound === 0) {
116
+ console.log(chalk.green('āœ“ No issues found! PR looks good.\n'));
117
+ }
118
+ }
119
+ finally {
120
+ // Clean up session and shutdown in-process server if applicable
121
+ await opencode.closeSession(session.id);
122
+ await opencode.shutdown();
123
+ }
124
+ }
125
+ //# sourceMappingURL=review-pr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-pr.js","sourceRoot":"","sources":["../../src/cli/review-pr.ts"],"names":[],"mappings":"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"}