@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.
- package/.opencode/agent/github-reviewer.md +62 -0
- package/.opencode/agent/gitlab-reviewer.md +62 -0
- package/.opencode/agent/local-reviewer.md +71 -0
- package/.opencode/agent/review/performance.md +151 -0
- package/.opencode/agent/review/quality.md +127 -0
- package/.opencode/agent/review/security.md +115 -0
- package/.opencode/agent/review/style.md +116 -0
- package/.opencode/opencode.jsonc +52 -0
- package/LICENSE +201 -0
- package/README.md +361 -0
- package/dist/ci/runner.d.ts +21 -0
- package/dist/ci/runner.d.ts.map +1 -0
- package/dist/ci/runner.js +82 -0
- package/dist/ci/runner.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +137 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +5 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +166 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/review-local.d.ts +9 -0
- package/dist/cli/review-local.d.ts.map +1 -0
- package/dist/cli/review-local.js +105 -0
- package/dist/cli/review-local.js.map +1 -0
- package/dist/cli/review-mr.d.ts +11 -0
- package/dist/cli/review-mr.d.ts.map +1 -0
- package/dist/cli/review-mr.js +128 -0
- package/dist/cli/review-mr.js.map +1 -0
- package/dist/cli/review-pr.d.ts +12 -0
- package/dist/cli/review-pr.d.ts.map +1 -0
- package/dist/cli/review-pr.js +125 -0
- package/dist/cli/review-pr.js.map +1 -0
- package/dist/github/client.d.ts +1346 -0
- package/dist/github/client.d.ts.map +1 -0
- package/dist/github/client.js +137 -0
- package/dist/github/client.js.map +1 -0
- package/dist/gitlab/client.d.ts +55 -0
- package/dist/gitlab/client.d.ts.map +1 -0
- package/dist/gitlab/client.js +86 -0
- package/dist/gitlab/client.js.map +1 -0
- package/dist/gitlab/comment-formatter.d.ts +36 -0
- package/dist/gitlab/comment-formatter.d.ts.map +1 -0
- package/dist/gitlab/comment-formatter.js +118 -0
- package/dist/gitlab/comment-formatter.js.map +1 -0
- package/dist/gitlab/diff-parser.d.ts +41 -0
- package/dist/gitlab/diff-parser.d.ts.map +1 -0
- package/dist/gitlab/diff-parser.js +147 -0
- package/dist/gitlab/diff-parser.js.map +1 -0
- package/dist/lib/config.d.ts +42 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +144 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/opencode/agent-loader.d.ts +31 -0
- package/dist/opencode/agent-loader.d.ts.map +1 -0
- package/dist/opencode/agent-loader.js +115 -0
- package/dist/opencode/agent-loader.js.map +1 -0
- package/dist/opencode/client.d.ts +82 -0
- package/dist/opencode/client.d.ts.map +1 -0
- package/dist/opencode/client.js +184 -0
- package/dist/opencode/client.js.map +1 -0
- package/package.json +70 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { loadConfig, validateConfig } from '../lib/config.js';
|
|
3
|
+
import { reviewMR } from '../cli/review-mr.js';
|
|
4
|
+
/**
|
|
5
|
+
* Detect CI environment from environment variables
|
|
6
|
+
*/
|
|
7
|
+
export function detectCIEnvironment() {
|
|
8
|
+
// GitLab CI detection
|
|
9
|
+
if (process.env.GITLAB_CI === 'true') {
|
|
10
|
+
return {
|
|
11
|
+
platform: 'gitlab',
|
|
12
|
+
projectId: process.env.CI_PROJECT_ID,
|
|
13
|
+
mrIid: process.env.CI_MERGE_REQUEST_IID
|
|
14
|
+
? parseInt(process.env.CI_MERGE_REQUEST_IID, 10)
|
|
15
|
+
: undefined,
|
|
16
|
+
targetBranch: process.env.CI_MERGE_REQUEST_TARGET_BRANCH_NAME,
|
|
17
|
+
sourceBranch: process.env.CI_MERGE_REQUEST_SOURCE_BRANCH_NAME,
|
|
18
|
+
commitSha: process.env.CI_COMMIT_SHA,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
return { platform: 'unknown' };
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Run review in CI/CD environment
|
|
25
|
+
*/
|
|
26
|
+
export async function runCIReview() {
|
|
27
|
+
console.log(chalk.bold.cyan('\nš¤ DRS CI/CD Review Runner\n'));
|
|
28
|
+
// Detect environment
|
|
29
|
+
const env = detectCIEnvironment();
|
|
30
|
+
if (env.platform === 'unknown') {
|
|
31
|
+
console.error(chalk.red('Error: Unknown CI environment'));
|
|
32
|
+
console.error(chalk.gray('Currently supported: GitLab CI'));
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
console.log(chalk.gray(`Detected CI platform: ${env.platform}\n`));
|
|
36
|
+
// Validate required environment variables
|
|
37
|
+
if (!env.projectId) {
|
|
38
|
+
console.error(chalk.red('Error: CI_PROJECT_ID not found'));
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
if (!env.mrIid) {
|
|
42
|
+
console.error(chalk.red('Error: CI_MERGE_REQUEST_IID not found'));
|
|
43
|
+
console.error(chalk.gray('This job should only run on merge requests'));
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
// Load configuration
|
|
47
|
+
const projectDir = process.env.CI_PROJECT_DIR || process.cwd();
|
|
48
|
+
const config = loadConfig(projectDir);
|
|
49
|
+
try {
|
|
50
|
+
validateConfig(config);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
console.error(chalk.red('Configuration error:'), error instanceof Error ? error.message : String(error));
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
console.log(chalk.gray(`Project: ${env.projectId}`));
|
|
57
|
+
console.log(chalk.gray(`MR: !${env.mrIid}`));
|
|
58
|
+
console.log(chalk.gray(`Branch: ${env.sourceBranch} ā ${env.targetBranch}\n`));
|
|
59
|
+
// Run review
|
|
60
|
+
try {
|
|
61
|
+
await reviewMR(config, {
|
|
62
|
+
projectId: env.projectId,
|
|
63
|
+
mrIid: env.mrIid,
|
|
64
|
+
postComments: true, // Always post comments in CI
|
|
65
|
+
});
|
|
66
|
+
console.log(chalk.green.bold('\nā Review complete\n'));
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
console.error(chalk.red('\nā Review failed\n'));
|
|
70
|
+
console.error(error);
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Check if running in CI environment
|
|
76
|
+
*/
|
|
77
|
+
export function isCI() {
|
|
78
|
+
return !!(process.env.CI ||
|
|
79
|
+
process.env.GITLAB_CI ||
|
|
80
|
+
process.env.GITHUB_ACTIONS);
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/ci/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { reviewLocal } from './review-local.js';
|
|
5
|
+
import { reviewMR } from './review-mr.js';
|
|
6
|
+
import { reviewPR } from './review-pr.js';
|
|
7
|
+
import { loadConfig } from '../lib/config.js';
|
|
8
|
+
const program = new Command();
|
|
9
|
+
program
|
|
10
|
+
.name('drs')
|
|
11
|
+
.description('AI-powered code review bot for GitLab MRs and GitHub PRs using OpenCode SDK')
|
|
12
|
+
.version('1.0.0');
|
|
13
|
+
program
|
|
14
|
+
.command('review-local')
|
|
15
|
+
.description('Review local git diff before pushing')
|
|
16
|
+
.option('--staged', 'Review staged changes only (git diff --cached)')
|
|
17
|
+
.option('--agents <agents>', 'Comma-separated list of review agents (default: security,quality)')
|
|
18
|
+
.option('--format <format>', 'Output format: terminal, json, markdown', 'terminal')
|
|
19
|
+
.option('--verbose', 'Verbose output')
|
|
20
|
+
.action(async (options) => {
|
|
21
|
+
try {
|
|
22
|
+
const config = loadConfig(process.cwd(), {
|
|
23
|
+
review: {
|
|
24
|
+
agents: options.agents ? options.agents.split(',').map((a) => a.trim()) : undefined,
|
|
25
|
+
},
|
|
26
|
+
output: {
|
|
27
|
+
format: options.format,
|
|
28
|
+
verbosity: options.verbose ? 'detailed' : 'normal',
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
await reviewLocal(config, {
|
|
32
|
+
staged: options.staged || false,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
program
|
|
41
|
+
.command('review-mr')
|
|
42
|
+
.description('Review a GitLab merge request')
|
|
43
|
+
.requiredOption('--mr <iid>', 'Merge request IID (number)')
|
|
44
|
+
.requiredOption('--project <id>', 'Project ID or path (e.g., "my-org/my-repo" or "123")')
|
|
45
|
+
.option('--agents <agents>', 'Comma-separated list of review agents')
|
|
46
|
+
.option('--post-comments', 'Post review comments to the MR (requires GITLAB_TOKEN)')
|
|
47
|
+
.option('--verbose', 'Verbose output')
|
|
48
|
+
.action(async (options) => {
|
|
49
|
+
try {
|
|
50
|
+
const config = loadConfig(process.cwd(), {
|
|
51
|
+
review: {
|
|
52
|
+
agents: options.agents ? options.agents.split(',').map((a) => a.trim()) : undefined,
|
|
53
|
+
},
|
|
54
|
+
output: {
|
|
55
|
+
verbosity: options.verbose ? 'detailed' : 'normal',
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
await reviewMR(config, {
|
|
59
|
+
projectId: options.project,
|
|
60
|
+
mrIid: parseInt(options.mr, 10),
|
|
61
|
+
postComments: options.postComments || false,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
program
|
|
70
|
+
.command('review-pr')
|
|
71
|
+
.description('Review a GitHub pull request')
|
|
72
|
+
.requiredOption('--pr <number>', 'Pull request number')
|
|
73
|
+
.requiredOption('--owner <owner>', 'Repository owner (e.g., "octocat")')
|
|
74
|
+
.requiredOption('--repo <repo>', 'Repository name (e.g., "hello-world")')
|
|
75
|
+
.option('--agents <agents>', 'Comma-separated list of review agents')
|
|
76
|
+
.option('--post-comments', 'Post review comments to the PR (requires GITHUB_TOKEN)')
|
|
77
|
+
.option('--verbose', 'Verbose output')
|
|
78
|
+
.action(async (options) => {
|
|
79
|
+
try {
|
|
80
|
+
const config = loadConfig(process.cwd(), {
|
|
81
|
+
review: {
|
|
82
|
+
agents: options.agents ? options.agents.split(',').map((a) => a.trim()) : undefined,
|
|
83
|
+
},
|
|
84
|
+
output: {
|
|
85
|
+
verbosity: options.verbose ? 'detailed' : 'normal',
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
await reviewPR(config, {
|
|
89
|
+
owner: options.owner,
|
|
90
|
+
repo: options.repo,
|
|
91
|
+
prNumber: parseInt(options.pr, 10),
|
|
92
|
+
postComments: options.postComments || false,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
program
|
|
101
|
+
.command('list-agents')
|
|
102
|
+
.description('List available review agents')
|
|
103
|
+
.action(async () => {
|
|
104
|
+
try {
|
|
105
|
+
const { listAgents } = await import('../opencode/agent-loader.js');
|
|
106
|
+
const agents = listAgents(process.cwd());
|
|
107
|
+
console.log(chalk.bold('\nš Available Review Agents:\n'));
|
|
108
|
+
for (const agent of agents) {
|
|
109
|
+
console.log(chalk.cyan(` ⢠${agent}`));
|
|
110
|
+
}
|
|
111
|
+
console.log('');
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
program
|
|
119
|
+
.command('init')
|
|
120
|
+
.description('Initialize DRS configuration in current project')
|
|
121
|
+
.action(async () => {
|
|
122
|
+
try {
|
|
123
|
+
const { initProject } = await import('./init.js');
|
|
124
|
+
await initProject(process.cwd());
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
// Parse arguments
|
|
132
|
+
program.parse(process.argv);
|
|
133
|
+
// Show help if no command provided
|
|
134
|
+
if (!process.argv.slice(2).length) {
|
|
135
|
+
program.outputHelp();
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AA8EA;;GAEG;AACH,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwGpE"}
|
package/dist/cli/init.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
const DEFAULT_DRS_CONFIG = `# DRS Configuration
|
|
5
|
+
# Documentation: https://github.com/your-org/drs
|
|
6
|
+
|
|
7
|
+
review:
|
|
8
|
+
# Review agents to use
|
|
9
|
+
agents:
|
|
10
|
+
- security
|
|
11
|
+
- quality
|
|
12
|
+
- style
|
|
13
|
+
- performance
|
|
14
|
+
|
|
15
|
+
# Automatically review new MRs
|
|
16
|
+
autoReview: true
|
|
17
|
+
|
|
18
|
+
# Review when bot is mentioned
|
|
19
|
+
reviewOnMention: true
|
|
20
|
+
|
|
21
|
+
# Review when these labels are added
|
|
22
|
+
reviewOnLabel:
|
|
23
|
+
- needs-review
|
|
24
|
+
- security-review
|
|
25
|
+
|
|
26
|
+
# Files to ignore during review
|
|
27
|
+
ignorePatterns:
|
|
28
|
+
- "*.test.ts"
|
|
29
|
+
- "*.spec.ts"
|
|
30
|
+
- "**/__tests__/**"
|
|
31
|
+
- "**/__mocks__/**"
|
|
32
|
+
- "*.md"
|
|
33
|
+
- "package-lock.json"
|
|
34
|
+
- "yarn.lock"
|
|
35
|
+
- "pnpm-lock.yaml"
|
|
36
|
+
|
|
37
|
+
output:
|
|
38
|
+
format: terminal
|
|
39
|
+
verbosity: normal
|
|
40
|
+
`;
|
|
41
|
+
const EXAMPLE_GITLAB_CI = `# Example GitLab CI configuration for DRS
|
|
42
|
+
# Add this to your .gitlab-ci.yml file
|
|
43
|
+
|
|
44
|
+
stages:
|
|
45
|
+
- review
|
|
46
|
+
- test
|
|
47
|
+
- deploy
|
|
48
|
+
|
|
49
|
+
# AI Code Review
|
|
50
|
+
ai_review:
|
|
51
|
+
stage: review
|
|
52
|
+
image: node:20
|
|
53
|
+
only:
|
|
54
|
+
- merge_requests
|
|
55
|
+
script:
|
|
56
|
+
- npm install -g @diff-review-system/drs
|
|
57
|
+
- drs review-mr --mr $CI_MERGE_REQUEST_IID --project $CI_PROJECT_ID --post-comments
|
|
58
|
+
variables:
|
|
59
|
+
OPENCODE_SERVER: "http://opencode.internal:3000"
|
|
60
|
+
GITLAB_TOKEN: $CI_JOB_TOKEN
|
|
61
|
+
allow_failure: true
|
|
62
|
+
`;
|
|
63
|
+
const EXAMPLE_ENV = `# DRS Environment Variables
|
|
64
|
+
|
|
65
|
+
# OpenCode Server URL
|
|
66
|
+
OPENCODE_SERVER=http://localhost:3000
|
|
67
|
+
|
|
68
|
+
# GitLab Configuration
|
|
69
|
+
GITLAB_URL=https://gitlab.com
|
|
70
|
+
GITLAB_TOKEN=your-gitlab-token-here
|
|
71
|
+
|
|
72
|
+
# Review Configuration (optional, overrides .drs/drs.config.yaml)
|
|
73
|
+
REVIEW_AGENTS=security,quality,style,performance
|
|
74
|
+
`;
|
|
75
|
+
/**
|
|
76
|
+
* Initialize DRS configuration in a project
|
|
77
|
+
*/
|
|
78
|
+
export async function initProject(projectPath) {
|
|
79
|
+
console.log(chalk.bold.cyan('\nš Initializing DRS Configuration\n'));
|
|
80
|
+
// Create .drs directory
|
|
81
|
+
const drsDir = join(projectPath, '.drs');
|
|
82
|
+
if (!existsSync(drsDir)) {
|
|
83
|
+
mkdirSync(drsDir, { recursive: true });
|
|
84
|
+
console.log(chalk.green('ā'), 'Created', chalk.cyan('.drs/'), 'directory');
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
console.log(chalk.yellow('ā '), chalk.cyan('.drs/'), 'directory already exists');
|
|
88
|
+
}
|
|
89
|
+
// Create .drs/agents directory
|
|
90
|
+
const agentsDir = join(drsDir, 'agents');
|
|
91
|
+
if (!existsSync(agentsDir)) {
|
|
92
|
+
mkdirSync(agentsDir, { recursive: true });
|
|
93
|
+
console.log(chalk.green('ā'), 'Created', chalk.cyan('.drs/agents/'), 'directory');
|
|
94
|
+
}
|
|
95
|
+
// Create drs.config.yaml
|
|
96
|
+
const configPath = join(drsDir, 'drs.config.yaml');
|
|
97
|
+
if (!existsSync(configPath)) {
|
|
98
|
+
writeFileSync(configPath, DEFAULT_DRS_CONFIG, 'utf-8');
|
|
99
|
+
console.log(chalk.green('ā'), 'Created', chalk.cyan('.drs/drs.config.yaml'));
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
console.log(chalk.yellow('ā '), chalk.cyan('.drs/drs.config.yaml'), 'already exists');
|
|
103
|
+
}
|
|
104
|
+
// Create examples directory
|
|
105
|
+
const examplesDir = join(drsDir, 'examples');
|
|
106
|
+
if (!existsSync(examplesDir)) {
|
|
107
|
+
mkdirSync(examplesDir, { recursive: true });
|
|
108
|
+
// Write example GitLab CI config
|
|
109
|
+
writeFileSync(join(examplesDir, 'gitlab-ci.example.yml'), EXAMPLE_GITLAB_CI, 'utf-8');
|
|
110
|
+
// Write example .env file
|
|
111
|
+
writeFileSync(join(examplesDir, '.env.example'), EXAMPLE_ENV, 'utf-8');
|
|
112
|
+
console.log(chalk.green('ā'), 'Created example configurations in', chalk.cyan('.drs/examples/'));
|
|
113
|
+
}
|
|
114
|
+
// Create custom agents info
|
|
115
|
+
const customAgentReadme = `# Custom Review Agents
|
|
116
|
+
|
|
117
|
+
Place your custom review agent definitions (markdown files) in this directory.
|
|
118
|
+
|
|
119
|
+
## Example: Custom Security Agent
|
|
120
|
+
|
|
121
|
+
Create a file \`.drs/agents/security.md\` to override the default security agent:
|
|
122
|
+
|
|
123
|
+
\`\`\`markdown
|
|
124
|
+
---
|
|
125
|
+
description: Custom security reviewer with project-specific rules
|
|
126
|
+
color: "#E53E3E"
|
|
127
|
+
model: opencode/claude-sonnet-4-5
|
|
128
|
+
tools:
|
|
129
|
+
Read: true
|
|
130
|
+
Glob: true
|
|
131
|
+
Grep: true
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
You are a security expert for this specific application.
|
|
135
|
+
|
|
136
|
+
## Project-Specific Security Rules
|
|
137
|
+
|
|
138
|
+
[Add your custom security rules here]
|
|
139
|
+
\`\`\`
|
|
140
|
+
|
|
141
|
+
## Priority Order
|
|
142
|
+
|
|
143
|
+
DRS loads agents in this order:
|
|
144
|
+
1. \`.drs/agents/\` (highest priority - project-specific)
|
|
145
|
+
2. \`.opencode/agent/\` (standard OpenCode location)
|
|
146
|
+
3. Built-in DRS agents (fallback)
|
|
147
|
+
|
|
148
|
+
## Learn More
|
|
149
|
+
|
|
150
|
+
- [DRS Documentation](https://github.com/your-org/drs)
|
|
151
|
+
- [OpenCode Agent Guide](https://opencode.ai/docs/agents)
|
|
152
|
+
`;
|
|
153
|
+
const agentsReadmePath = join(agentsDir, 'README.md');
|
|
154
|
+
if (!existsSync(agentsReadmePath)) {
|
|
155
|
+
writeFileSync(agentsReadmePath, customAgentReadme, 'utf-8');
|
|
156
|
+
console.log(chalk.green('ā'), 'Created', chalk.cyan('.drs/agents/README.md'));
|
|
157
|
+
}
|
|
158
|
+
// Summary
|
|
159
|
+
console.log(chalk.bold.green('\nā DRS initialization complete!\n'));
|
|
160
|
+
console.log(chalk.bold('Next steps:\n'));
|
|
161
|
+
console.log(' 1. Edit', chalk.cyan('.drs/drs.config.yaml'), 'to customize review behavior');
|
|
162
|
+
console.log(' 2. Set environment variables (see', chalk.cyan('.drs/examples/.env.example') + ')');
|
|
163
|
+
console.log(' 3. Run', chalk.cyan('drs review-local'), 'to review local changes');
|
|
164
|
+
console.log(' 4. See', chalk.cyan('.drs/examples/gitlab-ci.example.yml'), 'for CI/CD setup\n');
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoC1B,CAAC;AAEF,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;CAqBzB,CAAC;AAEF,MAAM,WAAW,GAAG;;;;;;;;;;;CAWnB,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,WAAmB;IACnD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC,CAAC;IAEtE,wBAAwB;IACxB,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACzC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC,CAAC;IAC7E,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,0BAA0B,CAAC,CAAC;IAClF,CAAC;IAED,+BAA+B;IAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACzC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,WAAW,CAAC,CAAC;IACpF,CAAC;IAED,yBAAyB;IACzB,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACnD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,aAAa,CAAC,UAAU,EAAE,kBAAkB,EAAE,OAAO,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC;IAC/E,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,EAAE,gBAAgB,CAAC,CAAC;IACvF,CAAC;IAED,4BAA4B;IAC5B,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC7C,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7B,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE5C,iCAAiC;QACjC,aAAa,CACX,IAAI,CAAC,WAAW,EAAE,uBAAuB,CAAC,EAC1C,iBAAiB,EACjB,OAAO,CACR,CAAC;QAEF,0BAA0B;QAC1B,aAAa,CACX,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EACjC,WAAW,EACX,OAAO,CACR,CAAC;QAEF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,mCAAmC,EAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACnG,CAAC;IAED,4BAA4B;IAC5B,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqC3B,CAAC;IAEA,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACtD,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAClC,aAAa,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,OAAO,CAAC,CAAC;QAC5D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC;IAChF,CAAC;IAED,UAAU;IACV,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC,CAAC;IAEpE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,EAAE,8BAA8B,CAAC,CAAC;IAC7F,OAAO,CAAC,GAAG,CAAC,qCAAqC,EAAE,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,GAAG,GAAG,CAAC,CAAC;IACnG,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,yBAAyB,CAAC,CAAC;IACnF,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,qCAAqC,CAAC,EAAE,mBAAmB,CAAC,CAAC;AAClG,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DRSConfig } from '../lib/config.js';
|
|
2
|
+
export interface ReviewLocalOptions {
|
|
3
|
+
staged: boolean;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Review local git diff before pushing
|
|
7
|
+
*/
|
|
8
|
+
export declare function reviewLocal(config: DRSConfig, options: ReviewLocalOptions): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=review-local.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-local.d.ts","sourceRoot":"","sources":["../../src/cli/review-local.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAKlD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmH/F"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import simpleGit from 'simple-git';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { createOpencodeClientInstance } from '../opencode/client.js';
|
|
4
|
+
import { parseDiff, getChangedFiles } from '../gitlab/diff-parser.js';
|
|
5
|
+
import { formatTerminalIssue, calculateSummary } from '../gitlab/comment-formatter.js';
|
|
6
|
+
/**
|
|
7
|
+
* Review local git diff before pushing
|
|
8
|
+
*/
|
|
9
|
+
export async function reviewLocal(config, options) {
|
|
10
|
+
console.log(chalk.bold.cyan('\nš DRS Local Diff Review\n'));
|
|
11
|
+
const git = simpleGit();
|
|
12
|
+
const cwd = process.cwd();
|
|
13
|
+
// Check if we're in a git repository
|
|
14
|
+
const isRepo = await git.checkIsRepo();
|
|
15
|
+
if (!isRepo) {
|
|
16
|
+
throw new Error('Not a git repository. Run this command from within a git repository.');
|
|
17
|
+
}
|
|
18
|
+
// Get diff
|
|
19
|
+
console.log(chalk.gray(`Getting ${options.staged ? 'staged' : 'unstaged'} changes...\n`));
|
|
20
|
+
const diffText = options.staged
|
|
21
|
+
? await git.diff(['--cached'])
|
|
22
|
+
: await git.diff();
|
|
23
|
+
if (!diffText || diffText.trim().length === 0) {
|
|
24
|
+
console.log(chalk.yellow('ā No changes to review\n'));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
// Parse diff
|
|
28
|
+
const diffs = parseDiff(diffText);
|
|
29
|
+
const changedFiles = getChangedFiles(diffs);
|
|
30
|
+
if (changedFiles.length === 0) {
|
|
31
|
+
console.log(chalk.yellow('ā No files to review\n'));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
console.log(chalk.gray(`Found ${changedFiles.length} changed file(s)\n`));
|
|
35
|
+
// Connect to OpenCode (or start in-process if serverUrl is empty)
|
|
36
|
+
console.log(chalk.gray('Connecting to OpenCode server...\n'));
|
|
37
|
+
const opencode = await createOpencodeClientInstance({
|
|
38
|
+
baseUrl: config.opencode.serverUrl || undefined,
|
|
39
|
+
directory: cwd,
|
|
40
|
+
});
|
|
41
|
+
// Create review session
|
|
42
|
+
console.log(chalk.gray('Starting AI review...\n'));
|
|
43
|
+
const agentsList = config.review.agents.join(',');
|
|
44
|
+
const session = await opencode.createSession({
|
|
45
|
+
agent: 'local-reviewer',
|
|
46
|
+
message: `Review local diff with agents: ${agentsList}. Files: ${changedFiles.join(', ')}`,
|
|
47
|
+
context: {
|
|
48
|
+
files: changedFiles,
|
|
49
|
+
agents: config.review.agents,
|
|
50
|
+
staged: options.staged,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
// Stream and display 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 summary
|
|
66
|
+
if (issues.length > 0) {
|
|
67
|
+
console.log(chalk.bold('\nāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā'));
|
|
68
|
+
console.log(chalk.bold('š Review Summary'));
|
|
69
|
+
console.log(chalk.bold('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n'));
|
|
70
|
+
const summary = calculateSummary(changedFiles.length, issues);
|
|
71
|
+
console.log(` Files reviewed: ${chalk.cyan(summary.filesReviewed)}`);
|
|
72
|
+
console.log(` Issues found: ${chalk.yellow(summary.issuesFound)}`);
|
|
73
|
+
if (summary.issuesFound > 0) {
|
|
74
|
+
console.log(` š“ Critical: ${chalk.red(summary.bySeverity.CRITICAL)}`);
|
|
75
|
+
console.log(` š” High: ${chalk.yellow(summary.bySeverity.HIGH)}`);
|
|
76
|
+
console.log(` š Medium: ${chalk.hex('#FFA500')(summary.bySeverity.MEDIUM)}`);
|
|
77
|
+
console.log(` āŖ Low: ${chalk.gray(summary.bySeverity.LOW)}`);
|
|
78
|
+
}
|
|
79
|
+
console.log('');
|
|
80
|
+
// Display issues
|
|
81
|
+
for (const issue of issues) {
|
|
82
|
+
console.log(formatTerminalIssue(issue));
|
|
83
|
+
}
|
|
84
|
+
// Recommendation
|
|
85
|
+
const hasCritical = summary.bySeverity.CRITICAL > 0;
|
|
86
|
+
const hasHigh = summary.bySeverity.HIGH > 0;
|
|
87
|
+
if (hasCritical || hasHigh) {
|
|
88
|
+
console.log(chalk.red.bold('\nā ļø Recommendation: Fix critical/high issues before pushing\n'));
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
console.log(chalk.green('\nā No critical issues found. Safe to push.\n'));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
console.log(chalk.green('\nā No issues found! Code looks good.\n'));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
// Clean up session and shutdown in-process server if applicable
|
|
101
|
+
await opencode.closeSession(session.id);
|
|
102
|
+
await opencode.shutdown();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=review-local.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-local.js","sourceRoot":"","sources":["../../src/cli/review-local.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { DRSConfig } from '../lib/config.js';
|
|
2
|
+
export interface ReviewMROptions {
|
|
3
|
+
projectId: string;
|
|
4
|
+
mrIid: number;
|
|
5
|
+
postComments: boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Review a GitLab merge request
|
|
9
|
+
*/
|
|
10
|
+
export declare function reviewMR(config: DRSConfig, options: ReviewMROptions): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=review-mr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-mr.d.ts","sourceRoot":"","sources":["../../src/cli/review-mr.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAWlD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAuJzF"}
|