@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 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/github/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,137 @@
1
+ import { Octokit } from '@octokit/rest';
2
+ export class GitHubClient {
3
+ octokit;
4
+ owner;
5
+ repo;
6
+ constructor(config) {
7
+ this.octokit = new Octokit({
8
+ auth: config.token,
9
+ });
10
+ this.owner = config.owner;
11
+ this.repo = config.repo;
12
+ }
13
+ /**
14
+ * Get pull request details
15
+ */
16
+ async getPullRequest(owner, repo, prNumber) {
17
+ const response = await this.octokit.pulls.get({
18
+ owner,
19
+ repo,
20
+ pull_number: prNumber,
21
+ });
22
+ return response.data;
23
+ }
24
+ /**
25
+ * Get pull request files (changes)
26
+ */
27
+ async getPRFiles(owner, repo, prNumber) {
28
+ const response = await this.octokit.pulls.listFiles({
29
+ owner,
30
+ repo,
31
+ pull_number: prNumber,
32
+ per_page: 100,
33
+ });
34
+ return response.data.map(file => ({
35
+ filename: file.filename,
36
+ status: file.status,
37
+ additions: file.additions,
38
+ deletions: file.deletions,
39
+ changes: file.changes,
40
+ patch: file.patch,
41
+ previousFilename: file.previous_filename,
42
+ }));
43
+ }
44
+ /**
45
+ * Post a review comment on the PR
46
+ */
47
+ async createPRComment(owner, repo, prNumber, body) {
48
+ return await this.octokit.issues.createComment({
49
+ owner,
50
+ repo,
51
+ issue_number: prNumber,
52
+ body,
53
+ });
54
+ }
55
+ /**
56
+ * Create a review comment on a specific line
57
+ */
58
+ async createPRReviewComment(owner, repo, prNumber, body, commitId, path, line) {
59
+ return await this.octokit.pulls.createReviewComment({
60
+ owner,
61
+ repo,
62
+ pull_number: prNumber,
63
+ body,
64
+ commit_id: commitId,
65
+ path,
66
+ line,
67
+ });
68
+ }
69
+ /**
70
+ * Create a pull request review with multiple comments
71
+ */
72
+ async createPRReview(owner, repo, prNumber, commitId, body, event, comments) {
73
+ return await this.octokit.pulls.createReview({
74
+ owner,
75
+ repo,
76
+ pull_number: prNumber,
77
+ commit_id: commitId,
78
+ body,
79
+ event,
80
+ comments,
81
+ });
82
+ }
83
+ /**
84
+ * Add labels to a PR
85
+ */
86
+ async addLabels(owner, repo, prNumber, labels) {
87
+ return await this.octokit.issues.addLabels({
88
+ owner,
89
+ repo,
90
+ issue_number: prNumber,
91
+ labels,
92
+ });
93
+ }
94
+ /**
95
+ * Check if PR has a specific label
96
+ */
97
+ async hasLabel(owner, repo, prNumber, label) {
98
+ const response = await this.octokit.issues.listLabelsOnIssue({
99
+ owner,
100
+ repo,
101
+ issue_number: prNumber,
102
+ });
103
+ return response.data.some(l => l.name === label);
104
+ }
105
+ /**
106
+ * Get repository details
107
+ */
108
+ async getRepository(owner, repo) {
109
+ const response = await this.octokit.repos.get({
110
+ owner,
111
+ repo,
112
+ });
113
+ return response.data;
114
+ }
115
+ /**
116
+ * Get the authenticated user
117
+ */
118
+ async getAuthenticatedUser() {
119
+ const response = await this.octokit.users.getAuthenticated();
120
+ return response.data;
121
+ }
122
+ }
123
+ /**
124
+ * Create a GitHub client from environment variables
125
+ */
126
+ export function createGitHubClient() {
127
+ const token = process.env.GITHUB_TOKEN;
128
+ if (!token) {
129
+ throw new Error('GITHUB_TOKEN environment variable is required');
130
+ }
131
+ return new GitHubClient({
132
+ token,
133
+ owner: process.env.GITHUB_OWNER,
134
+ repo: process.env.GITHUB_REPO,
135
+ });
136
+ }
137
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/github/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAkBxC,MAAM,OAAO,YAAY;IACf,OAAO,CAAU;IACjB,KAAK,CAAU;IACf,IAAI,CAAU;IAEtB,YAAY,MAAoB;QAC9B,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC;YACzB,IAAI,EAAE,MAAM,CAAC,KAAK;SACnB,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc,CAAC,KAAa,EAAE,IAAY,EAAE,QAAgB;QAChE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;YAC5C,KAAK;YACL,IAAI;YACJ,WAAW,EAAE,QAAQ;SACtB,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,KAAa,EAAE,IAAY,EAAE,QAAgB;QAC5D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC;YAClD,KAAK;YACL,IAAI;YACJ,WAAW,EAAE,QAAQ;YACrB,QAAQ,EAAE,GAAG;SACd,CAAC,CAAC;QAEH,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAChC,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,MAAM,EAAE,IAAI,CAAC,MAA4B;YACzC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,gBAAgB,EAAE,IAAI,CAAC,iBAAiB;SACzC,CAAC,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,KAAa,EAAE,IAAY,EAAE,QAAgB,EAAE,IAAY;QAC/E,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC;YAC7C,KAAK;YACL,IAAI;YACJ,YAAY,EAAE,QAAQ;YACtB,IAAI;SACL,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,qBAAqB,CACzB,KAAa,EACb,IAAY,EACZ,QAAgB,EAChB,IAAY,EACZ,QAAgB,EAChB,IAAY,EACZ,IAAY;QAEZ,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC;YAClD,KAAK;YACL,IAAI;YACJ,WAAW,EAAE,QAAQ;YACrB,IAAI;YACJ,SAAS,EAAE,QAAQ;YACnB,IAAI;YACJ,IAAI;SACL,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc,CAClB,KAAa,EACb,IAAY,EACZ,QAAgB,EAChB,QAAgB,EAChB,IAAY,EACZ,KAAgD,EAChD,QAIE;QAEF,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC;YAC3C,KAAK;YACL,IAAI;YACJ,WAAW,EAAE,QAAQ;YACrB,SAAS,EAAE,QAAQ;YACnB,IAAI;YACJ,KAAK;YACL,QAAQ;SACT,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS,CAAC,KAAa,EAAE,IAAY,EAAE,QAAgB,EAAE,MAAgB;QAC7E,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC;YACzC,KAAK;YACL,IAAI;YACJ,YAAY,EAAE,QAAQ;YACtB,MAAM;SACP,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ,CAAC,KAAa,EAAE,IAAY,EAAE,QAAgB,EAAE,KAAa;QACzE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC;YAC3D,KAAK;YACL,IAAI;YACJ,YAAY,EAAE,QAAQ;SACvB,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC;IACnD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa,CAAC,KAAa,EAAE,IAAY;QAC7C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;YAC5C,KAAK;YACL,IAAI;SACL,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,oBAAoB;QACxB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC;QAC7D,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IAEvC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IAED,OAAO,IAAI,YAAY,CAAC;QACtB,KAAK;QACL,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY;QAC/B,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW;KAC9B,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,55 @@
1
+ export interface GitLabConfig {
2
+ url: string;
3
+ token: string;
4
+ }
5
+ export interface MRChange {
6
+ oldPath: string;
7
+ newPath: string;
8
+ newFile: boolean;
9
+ renamedFile: boolean;
10
+ deletedFile: boolean;
11
+ diff: string;
12
+ }
13
+ export declare class GitLabClient {
14
+ private client;
15
+ constructor(config: GitLabConfig);
16
+ /**
17
+ * Get merge request details
18
+ */
19
+ getMergeRequest(projectId: string, mrIid: number): Promise<import("@gitbeaker/core/dist/types/types").MergeRequestSchema>;
20
+ /**
21
+ * Get merge request changes (diffs)
22
+ */
23
+ getMRChanges(projectId: string, mrIid: number): Promise<MRChange[]>;
24
+ /**
25
+ * Post a comment to the MR
26
+ */
27
+ createMRComment(projectId: string, mrIid: number, body: string): Promise<import("@gitbeaker/core/dist/types/types").MergeRequestNoteSchema>;
28
+ /**
29
+ * Create a discussion thread on a specific line
30
+ */
31
+ createMRDiscussionThread(projectId: string, mrIid: number, body: string, position: {
32
+ baseSha: string;
33
+ headSha: string;
34
+ startSha: string;
35
+ newPath: string;
36
+ newLine: number;
37
+ }): Promise<import("@gitbeaker/core/dist/types/types").DiscussionSchema>;
38
+ /**
39
+ * Add a label to the MR
40
+ */
41
+ addLabel(projectId: string, mrIid: number, labels: string[]): Promise<import("@gitbeaker/core/dist/types/types").MergeRequestSchema>;
42
+ /**
43
+ * Check if MR has a specific label
44
+ */
45
+ hasLabel(projectId: string, mrIid: number, label: string): Promise<boolean>;
46
+ /**
47
+ * Get project details
48
+ */
49
+ getProject(projectId: string): Promise<import("@gitbeaker/core/dist/types/types").ProjectExtendedSchema>;
50
+ }
51
+ /**
52
+ * Create a GitLab client from environment variables
53
+ */
54
+ export declare function createGitLabClient(): GitLabClient;
55
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/gitlab/client.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAA8B;gBAEhC,MAAM,EAAE,YAAY;IAOhC;;OAEG;IACG,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAItD;;OAEG;IACG,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAczE;;OAEG;IACG,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAIpE;;OAEG;IACG,wBAAwB,CAC5B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE;QACR,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;KACjB;IAeH;;OAEG;IACG,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IAUjE;;OAEG;IACG,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMjF;;OAEG;IACG,UAAU,CAAC,SAAS,EAAE,MAAM;CAGnC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,YAAY,CASjD"}
@@ -0,0 +1,86 @@
1
+ import { Gitlab } from '@gitbeaker/node';
2
+ export class GitLabClient {
3
+ client;
4
+ constructor(config) {
5
+ this.client = new Gitlab({
6
+ host: config.url,
7
+ token: config.token,
8
+ });
9
+ }
10
+ /**
11
+ * Get merge request details
12
+ */
13
+ async getMergeRequest(projectId, mrIid) {
14
+ return await this.client.MergeRequests.show(projectId, mrIid);
15
+ }
16
+ /**
17
+ * Get merge request changes (diffs)
18
+ */
19
+ async getMRChanges(projectId, mrIid) {
20
+ const mr = await this.client.MergeRequests.changes(projectId, mrIid);
21
+ if (!mr.changes)
22
+ return [];
23
+ return mr.changes.map((change) => ({
24
+ oldPath: change.old_path,
25
+ newPath: change.new_path,
26
+ newFile: change.new_file,
27
+ renamedFile: change.renamed_file,
28
+ deletedFile: change.deleted_file,
29
+ diff: change.diff,
30
+ }));
31
+ }
32
+ /**
33
+ * Post a comment to the MR
34
+ */
35
+ async createMRComment(projectId, mrIid, body) {
36
+ return await this.client.MergeRequestNotes.create(projectId, mrIid, body);
37
+ }
38
+ /**
39
+ * Create a discussion thread on a specific line
40
+ */
41
+ async createMRDiscussionThread(projectId, mrIid, body, position) {
42
+ return await this.client.MergeRequestDiscussions.create(projectId, mrIid, body, {
43
+ position: {
44
+ position_type: 'text',
45
+ ...position,
46
+ },
47
+ });
48
+ }
49
+ /**
50
+ * Add a label to the MR
51
+ */
52
+ async addLabel(projectId, mrIid, labels) {
53
+ const mr = await this.getMergeRequest(projectId, mrIid);
54
+ const currentLabels = Array.isArray(mr.labels) ? mr.labels : [];
55
+ const newLabels = [...new Set([...currentLabels, ...labels])];
56
+ return await this.client.MergeRequests.edit(projectId, mrIid, {
57
+ labels: newLabels.join(','),
58
+ });
59
+ }
60
+ /**
61
+ * Check if MR has a specific label
62
+ */
63
+ async hasLabel(projectId, mrIid, label) {
64
+ const mr = await this.getMergeRequest(projectId, mrIid);
65
+ const labels = Array.isArray(mr.labels) ? mr.labels : [];
66
+ return labels.includes(label);
67
+ }
68
+ /**
69
+ * Get project details
70
+ */
71
+ async getProject(projectId) {
72
+ return await this.client.Projects.show(projectId);
73
+ }
74
+ }
75
+ /**
76
+ * Create a GitLab client from environment variables
77
+ */
78
+ export function createGitLabClient() {
79
+ const url = process.env.GITLAB_URL || 'https://gitlab.com';
80
+ const token = process.env.GITLAB_TOKEN;
81
+ if (!token) {
82
+ throw new Error('GITLAB_TOKEN environment variable is required');
83
+ }
84
+ return new GitLabClient({ url, token });
85
+ }
86
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/gitlab/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ export type IssueSeverity = 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW';
2
+ export type IssueCategory = 'SECURITY' | 'QUALITY' | 'STYLE' | 'PERFORMANCE';
3
+ export interface ReviewIssue {
4
+ category: IssueCategory;
5
+ severity: IssueSeverity;
6
+ title: string;
7
+ file: string;
8
+ line?: number;
9
+ problem: string;
10
+ solution: string;
11
+ references?: string[];
12
+ agent: string;
13
+ }
14
+ export interface ReviewSummary {
15
+ filesReviewed: number;
16
+ issuesFound: number;
17
+ bySeverity: Record<IssueSeverity, number>;
18
+ byCategory: Record<IssueCategory, number>;
19
+ }
20
+ /**
21
+ * Format a single review issue as a GitLab comment
22
+ */
23
+ export declare function formatIssueComment(issue: ReviewIssue): string;
24
+ /**
25
+ * Format a review summary as a GitLab comment
26
+ */
27
+ export declare function formatSummaryComment(summary: ReviewSummary, issues: ReviewIssue[]): string;
28
+ /**
29
+ * Format issue for terminal output with colors
30
+ */
31
+ export declare function formatTerminalIssue(issue: ReviewIssue): string;
32
+ /**
33
+ * Calculate review summary from issues
34
+ */
35
+ export declare function calculateSummary(filesReviewed: number, issues: ReviewIssue[]): ReviewSummary;
36
+ //# sourceMappingURL=comment-formatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comment-formatter.d.ts","sourceRoot":"","sources":["../../src/gitlab/comment-formatter.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AACnE,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,CAAC;AAE7E,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,aAAa,CAAC;IACxB,QAAQ,EAAE,aAAa,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IAC1C,UAAU,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;CAC3C;AAgBD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAoB7D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAiD1F;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAY9D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,WAAW,EAAE,GACpB,aAAa,CAwBf"}
@@ -0,0 +1,118 @@
1
+ const SEVERITY_EMOJI = {
2
+ CRITICAL: '🔴',
3
+ HIGH: '🟡',
4
+ MEDIUM: '🟠',
5
+ LOW: '⚪',
6
+ };
7
+ const CATEGORY_EMOJI = {
8
+ SECURITY: '🔒',
9
+ QUALITY: '📊',
10
+ STYLE: '✨',
11
+ PERFORMANCE: '⚡',
12
+ };
13
+ /**
14
+ * Format a single review issue as a GitLab comment
15
+ */
16
+ export function formatIssueComment(issue) {
17
+ const emoji = CATEGORY_EMOJI[issue.category];
18
+ const severityEmoji = SEVERITY_EMOJI[issue.severity];
19
+ let comment = `## ${emoji} ${issue.category} - ${issue.title}\n\n`;
20
+ comment += `**File**: \`${issue.file}${issue.line ? `:${issue.line}` : ''}\`\n`;
21
+ comment += `**Severity**: ${severityEmoji} ${issue.severity}\n`;
22
+ comment += `**Reviewer**: ${issue.agent}\n\n`;
23
+ comment += `### Problem\n${issue.problem}\n\n`;
24
+ comment += `### Solution\n${issue.solution}\n`;
25
+ if (issue.references && issue.references.length > 0) {
26
+ comment += `\n### References\n`;
27
+ for (const ref of issue.references) {
28
+ comment += `- ${ref}\n`;
29
+ }
30
+ }
31
+ return comment;
32
+ }
33
+ /**
34
+ * Format a review summary as a GitLab comment
35
+ */
36
+ export function formatSummaryComment(summary, issues) {
37
+ let comment = `# 🤖 AI Code Review Summary\n\n`;
38
+ comment += `## 📊 Statistics\n\n`;
39
+ comment += `- **Files Reviewed**: ${summary.filesReviewed}\n`;
40
+ comment += `- **Total Issues**: ${summary.issuesFound}\n\n`;
41
+ if (summary.issuesFound > 0) {
42
+ comment += `### By Severity\n`;
43
+ comment += `- ${SEVERITY_EMOJI.CRITICAL} **Critical**: ${summary.bySeverity.CRITICAL}\n`;
44
+ comment += `- ${SEVERITY_EMOJI.HIGH} **High**: ${summary.bySeverity.HIGH}\n`;
45
+ comment += `- ${SEVERITY_EMOJI.MEDIUM} **Medium**: ${summary.bySeverity.MEDIUM}\n`;
46
+ comment += `- ${SEVERITY_EMOJI.LOW} **Low**: ${summary.bySeverity.LOW}\n\n`;
47
+ comment += `### By Category\n`;
48
+ comment += `- ${CATEGORY_EMOJI.SECURITY} **Security**: ${summary.byCategory.SECURITY}\n`;
49
+ comment += `- ${CATEGORY_EMOJI.QUALITY} **Quality**: ${summary.byCategory.QUALITY}\n`;
50
+ comment += `- ${CATEGORY_EMOJI.STYLE} **Style**: ${summary.byCategory.STYLE}\n`;
51
+ comment += `- ${CATEGORY_EMOJI.PERFORMANCE} **Performance**: ${summary.byCategory.PERFORMANCE}\n\n`;
52
+ // List critical and high issues
53
+ const criticalIssues = issues.filter(i => i.severity === 'CRITICAL');
54
+ const highIssues = issues.filter(i => i.severity === 'HIGH');
55
+ if (criticalIssues.length > 0) {
56
+ comment += `## 🔴 Critical Issues\n\n`;
57
+ for (const issue of criticalIssues) {
58
+ comment += `- **${issue.title}** in \`${issue.file}${issue.line ? `:${issue.line}` : ''}\`\n`;
59
+ }
60
+ comment += `\n`;
61
+ }
62
+ if (highIssues.length > 0) {
63
+ comment += `## 🟡 High Priority Issues\n\n`;
64
+ for (const issue of highIssues) {
65
+ comment += `- **${issue.title}** in \`${issue.file}${issue.line ? `:${issue.line}` : ''}\`\n`;
66
+ }
67
+ comment += `\n`;
68
+ }
69
+ comment += `\n---\n`;
70
+ comment += `*Detailed findings have been posted as individual discussion threads on the affected lines.*\n`;
71
+ }
72
+ else {
73
+ comment += `✅ **No issues found!** The code looks good.\n`;
74
+ }
75
+ comment += `\n*Powered by DRS - GitLab Review Bot*\n`;
76
+ return comment;
77
+ }
78
+ /**
79
+ * Format issue for terminal output with colors
80
+ */
81
+ export function formatTerminalIssue(issue) {
82
+ const emoji = CATEGORY_EMOJI[issue.category];
83
+ const severityEmoji = SEVERITY_EMOJI[issue.severity];
84
+ let output = `\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n`;
85
+ output += `${severityEmoji} ${issue.severity}: ${emoji} ${issue.category} - ${issue.title}\n`;
86
+ output += `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n`;
87
+ output += `📁 ${issue.file}${issue.line ? `:${issue.line}` : ''}\n\n`;
88
+ output += `${issue.problem}\n\n`;
89
+ output += `✅ Fix: ${issue.solution}\n`;
90
+ return output;
91
+ }
92
+ /**
93
+ * Calculate review summary from issues
94
+ */
95
+ export function calculateSummary(filesReviewed, issues) {
96
+ const summary = {
97
+ filesReviewed,
98
+ issuesFound: issues.length,
99
+ bySeverity: {
100
+ CRITICAL: 0,
101
+ HIGH: 0,
102
+ MEDIUM: 0,
103
+ LOW: 0,
104
+ },
105
+ byCategory: {
106
+ SECURITY: 0,
107
+ QUALITY: 0,
108
+ STYLE: 0,
109
+ PERFORMANCE: 0,
110
+ },
111
+ };
112
+ for (const issue of issues) {
113
+ summary.bySeverity[issue.severity]++;
114
+ summary.byCategory[issue.category]++;
115
+ }
116
+ return summary;
117
+ }
118
+ //# sourceMappingURL=comment-formatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comment-formatter.js","sourceRoot":"","sources":["../../src/gitlab/comment-formatter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ export interface DiffHunk {
2
+ oldStart: number;
3
+ oldLines: number;
4
+ newStart: number;
5
+ newLines: number;
6
+ lines: DiffLine[];
7
+ }
8
+ export interface DiffLine {
9
+ type: 'add' | 'delete' | 'context';
10
+ content: string;
11
+ oldLineNumber?: number;
12
+ newLineNumber?: number;
13
+ }
14
+ export interface ParsedDiff {
15
+ oldPath: string;
16
+ newPath: string;
17
+ hunks: DiffHunk[];
18
+ isNew: boolean;
19
+ isDeleted: boolean;
20
+ isRenamed: boolean;
21
+ }
22
+ /**
23
+ * Parse a unified diff string into structured format
24
+ */
25
+ export declare function parseDiff(diffText: string): ParsedDiff[];
26
+ /**
27
+ * Get a list of changed file paths from parsed diff
28
+ */
29
+ export declare function getChangedFiles(diffs: ParsedDiff[]): string[];
30
+ /**
31
+ * Get added lines from a diff with their line numbers
32
+ */
33
+ export declare function getAddedLines(diff: ParsedDiff): Array<{
34
+ line: number;
35
+ content: string;
36
+ }>;
37
+ /**
38
+ * Check if a diff contains specific patterns (e.g., for filtering)
39
+ */
40
+ export declare function diffContainsPattern(diff: ParsedDiff, pattern: RegExp): boolean;
41
+ //# sourceMappingURL=diff-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-parser.d.ts","sourceRoot":"","sources":["../../src/gitlab/diff-parser.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,EAAE,CA+GxD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,EAAE,CAK7D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAexF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAS9E"}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Parse a unified diff string into structured format
3
+ */
4
+ export function parseDiff(diffText) {
5
+ const files = [];
6
+ const lines = diffText.split('\n');
7
+ let currentFile = null;
8
+ let currentHunk = null;
9
+ let oldLineNumber = 0;
10
+ let newLineNumber = 0;
11
+ for (let i = 0; i < lines.length; i++) {
12
+ const line = lines[i];
13
+ // File header: diff --git a/path b/path
14
+ if (line.startsWith('diff --git')) {
15
+ if (currentFile && currentHunk) {
16
+ currentFile.hunks.push(currentHunk);
17
+ }
18
+ if (currentFile) {
19
+ files.push(currentFile);
20
+ }
21
+ currentFile = {
22
+ oldPath: '',
23
+ newPath: '',
24
+ hunks: [],
25
+ isNew: false,
26
+ isDeleted: false,
27
+ isRenamed: false,
28
+ };
29
+ currentHunk = null;
30
+ }
31
+ // Old file: --- a/path or --- /dev/null
32
+ if (line.startsWith('---')) {
33
+ if (currentFile) {
34
+ if (line === '--- /dev/null') {
35
+ currentFile.isNew = true;
36
+ currentFile.oldPath = '/dev/null';
37
+ }
38
+ else {
39
+ currentFile.oldPath = line.substring(6); // Remove '--- a/'
40
+ }
41
+ }
42
+ }
43
+ // New file: +++ b/path or +++ /dev/null
44
+ if (line.startsWith('+++')) {
45
+ if (currentFile) {
46
+ if (line === '+++ /dev/null') {
47
+ currentFile.isDeleted = true;
48
+ currentFile.newPath = '/dev/null';
49
+ }
50
+ else {
51
+ currentFile.newPath = line.substring(6); // Remove '+++ b/'
52
+ }
53
+ }
54
+ }
55
+ // Hunk header: @@ -oldStart,oldLines +newStart,newLines @@
56
+ if (line.startsWith('@@')) {
57
+ if (currentFile && currentHunk) {
58
+ currentFile.hunks.push(currentHunk);
59
+ }
60
+ const match = line.match(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
61
+ if (match) {
62
+ oldLineNumber = parseInt(match[1]);
63
+ newLineNumber = parseInt(match[3]);
64
+ currentHunk = {
65
+ oldStart: oldLineNumber,
66
+ oldLines: match[2] ? parseInt(match[2]) : 1,
67
+ newStart: newLineNumber,
68
+ newLines: match[4] ? parseInt(match[4]) : 1,
69
+ lines: [],
70
+ };
71
+ }
72
+ }
73
+ // Diff line content
74
+ if (currentHunk && line.length > 0) {
75
+ if (line.startsWith('+') && !line.startsWith('+++')) {
76
+ currentHunk.lines.push({
77
+ type: 'add',
78
+ content: line.substring(1),
79
+ newLineNumber: newLineNumber++,
80
+ });
81
+ }
82
+ else if (line.startsWith('-') && !line.startsWith('---')) {
83
+ currentHunk.lines.push({
84
+ type: 'delete',
85
+ content: line.substring(1),
86
+ oldLineNumber: oldLineNumber++,
87
+ });
88
+ }
89
+ else if (line.startsWith(' ')) {
90
+ currentHunk.lines.push({
91
+ type: 'context',
92
+ content: line.substring(1),
93
+ oldLineNumber: oldLineNumber++,
94
+ newLineNumber: newLineNumber++,
95
+ });
96
+ }
97
+ }
98
+ }
99
+ // Push last hunk and file
100
+ if (currentFile && currentHunk) {
101
+ currentFile.hunks.push(currentHunk);
102
+ }
103
+ if (currentFile) {
104
+ files.push(currentFile);
105
+ }
106
+ return files;
107
+ }
108
+ /**
109
+ * Get a list of changed file paths from parsed diff
110
+ */
111
+ export function getChangedFiles(diffs) {
112
+ return diffs
113
+ .filter(d => !d.isDeleted)
114
+ .map(d => d.newPath)
115
+ .filter(path => path !== '/dev/null');
116
+ }
117
+ /**
118
+ * Get added lines from a diff with their line numbers
119
+ */
120
+ export function getAddedLines(diff) {
121
+ const added = [];
122
+ for (const hunk of diff.hunks) {
123
+ for (const line of hunk.lines) {
124
+ if (line.type === 'add' && line.newLineNumber) {
125
+ added.push({
126
+ line: line.newLineNumber,
127
+ content: line.content,
128
+ });
129
+ }
130
+ }
131
+ }
132
+ return added;
133
+ }
134
+ /**
135
+ * Check if a diff contains specific patterns (e.g., for filtering)
136
+ */
137
+ export function diffContainsPattern(diff, pattern) {
138
+ for (const hunk of diff.hunks) {
139
+ for (const line of hunk.lines) {
140
+ if (line.type === 'add' && pattern.test(line.content)) {
141
+ return true;
142
+ }
143
+ }
144
+ }
145
+ return false;
146
+ }
147
+ //# sourceMappingURL=diff-parser.js.map