@juspay/yama 1.1.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/CHANGELOG.md +39 -0
- package/README.md +796 -0
- package/dist/cli/index.d.ts +12 -0
- package/dist/cli/index.js +537 -0
- package/dist/core/ContextGatherer.d.ts +105 -0
- package/dist/core/ContextGatherer.js +455 -0
- package/dist/core/Guardian.d.ts +80 -0
- package/dist/core/Guardian.js +457 -0
- package/dist/core/providers/BitbucketProvider.d.ts +105 -0
- package/dist/core/providers/BitbucketProvider.js +438 -0
- package/dist/features/CodeReviewer.d.ts +105 -0
- package/dist/features/CodeReviewer.js +970 -0
- package/dist/features/DescriptionEnhancer.d.ts +64 -0
- package/dist/features/DescriptionEnhancer.js +424 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +60 -0
- package/dist/types/index.d.ts +419 -0
- package/dist/types/index.js +44 -0
- package/dist/utils/Cache.d.ts +92 -0
- package/dist/utils/Cache.js +254 -0
- package/dist/utils/ConfigManager.d.ts +84 -0
- package/dist/utils/ConfigManager.js +555 -0
- package/dist/utils/Logger.d.ts +30 -0
- package/dist/utils/Logger.js +208 -0
- package/package.json +137 -0
- package/yama.config.example.yaml +136 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Yama CLI - Enhanced command line interface
|
|
4
|
+
* Provides backward compatibility with pr-police.js and pr-describe.js
|
|
5
|
+
* Plus new unified commands for the enhanced functionality
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Main execution
|
|
9
|
+
*/
|
|
10
|
+
declare function main(): void;
|
|
11
|
+
export { main };
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,537 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* Yama CLI - Enhanced command line interface
|
|
5
|
+
* Provides backward compatibility with pr-police.js and pr-describe.js
|
|
6
|
+
* Plus new unified commands for the enhanced functionality
|
|
7
|
+
*/
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.main = main;
|
|
13
|
+
const commander_1 = require("commander");
|
|
14
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
15
|
+
const ora_1 = __importDefault(require("ora"));
|
|
16
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
17
|
+
const dotenv_1 = __importDefault(require("dotenv"));
|
|
18
|
+
const Guardian_1 = require("../core/Guardian");
|
|
19
|
+
const Logger_1 = require("../utils/Logger");
|
|
20
|
+
const ConfigManager_1 = require("../utils/ConfigManager");
|
|
21
|
+
const Cache_1 = require("../utils/Cache");
|
|
22
|
+
// Load environment variables
|
|
23
|
+
dotenv_1.default.config();
|
|
24
|
+
const program = new commander_1.Command();
|
|
25
|
+
// Package info
|
|
26
|
+
const packageInfo = {
|
|
27
|
+
name: '@juspay/yama',
|
|
28
|
+
version: '1.1.0',
|
|
29
|
+
description: 'Enterprise-grade Pull Request automation toolkit'
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Main CLI setup
|
|
33
|
+
*/
|
|
34
|
+
function setupCLI() {
|
|
35
|
+
program
|
|
36
|
+
.name('yama')
|
|
37
|
+
.description(packageInfo.description)
|
|
38
|
+
.version(packageInfo.version);
|
|
39
|
+
// Global options
|
|
40
|
+
program
|
|
41
|
+
.option('-v, --verbose', 'Enable verbose logging')
|
|
42
|
+
.option('-c, --config <path>', 'Path to configuration file')
|
|
43
|
+
.option('--dry-run', 'Preview mode - no changes made')
|
|
44
|
+
.option('--no-cache', 'Disable caching');
|
|
45
|
+
// Configure help options (removed custom formatter to fix recursion)
|
|
46
|
+
program.configureHelp({
|
|
47
|
+
sortSubcommands: true
|
|
48
|
+
});
|
|
49
|
+
// Setup commands
|
|
50
|
+
setupProcessCommand();
|
|
51
|
+
setupReviewCommand();
|
|
52
|
+
setupEnhanceCommand();
|
|
53
|
+
setupInitCommand();
|
|
54
|
+
setupStatusCommand();
|
|
55
|
+
setupCacheCommand();
|
|
56
|
+
setupConfigCommand();
|
|
57
|
+
// Backward compatibility aliases
|
|
58
|
+
setupBackwardCompatibility();
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Main unified processing command
|
|
62
|
+
*/
|
|
63
|
+
function setupProcessCommand() {
|
|
64
|
+
program
|
|
65
|
+
.command('process')
|
|
66
|
+
.description('Process PR with multiple operations using unified context (NEW)')
|
|
67
|
+
.requiredOption('-w, --workspace <workspace>', 'Bitbucket workspace')
|
|
68
|
+
.requiredOption('-r, --repository <repository>', 'Repository name')
|
|
69
|
+
.option('-b, --branch <branch>', 'Branch name')
|
|
70
|
+
.option('-p, --pr <id>', 'Pull request ID')
|
|
71
|
+
.option('-o, --operations <operations>', 'Operations to perform (review,enhance-description,all)', 'all')
|
|
72
|
+
.option('--exclude <patterns>', 'Comma-separated exclude patterns', '*.lock,*.svg')
|
|
73
|
+
.option('--context-lines <number>', 'Context lines for diff', '3')
|
|
74
|
+
.action(async (options) => {
|
|
75
|
+
try {
|
|
76
|
+
await handleGlobalOptions(options);
|
|
77
|
+
const operations = parseOperations(options.operations);
|
|
78
|
+
const operationOptions = {
|
|
79
|
+
workspace: options.workspace,
|
|
80
|
+
repository: options.repository,
|
|
81
|
+
branch: options.branch,
|
|
82
|
+
pullRequestId: options.pr,
|
|
83
|
+
operations,
|
|
84
|
+
dryRun: options.dryRun,
|
|
85
|
+
verbose: options.verbose
|
|
86
|
+
};
|
|
87
|
+
const guardian = new Guardian_1.Guardian();
|
|
88
|
+
await guardian.initialize(options.config);
|
|
89
|
+
if (options.verbose) {
|
|
90
|
+
// Use streaming for verbose mode
|
|
91
|
+
console.log(chalk_1.default.blue('\n📡 Starting streaming processing...\n'));
|
|
92
|
+
for await (const update of guardian.processPRStream(operationOptions)) {
|
|
93
|
+
logStreamUpdate(update);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
// Use regular processing
|
|
98
|
+
const spinner = (0, ora_1.default)('Processing PR...').start();
|
|
99
|
+
try {
|
|
100
|
+
const result = await guardian.processPR(operationOptions);
|
|
101
|
+
spinner.succeed('Processing completed');
|
|
102
|
+
printProcessResult(result);
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
spinner.fail('Processing failed');
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
console.error(chalk_1.default.red(`❌ Error: ${error.message}`));
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Code review command (backward compatible with pr-police.js)
|
|
118
|
+
*/
|
|
119
|
+
function setupReviewCommand() {
|
|
120
|
+
program
|
|
121
|
+
.command('review')
|
|
122
|
+
.alias('police') // Backward compatibility
|
|
123
|
+
.description('AI-powered code review (equivalent to pr-police.js)')
|
|
124
|
+
.requiredOption('-w, --workspace <workspace>', 'Bitbucket workspace')
|
|
125
|
+
.requiredOption('-r, --repository <repository>', 'Repository name')
|
|
126
|
+
.option('-b, --branch <branch>', 'Branch name')
|
|
127
|
+
.option('-p, --pr <id>', 'Pull request ID')
|
|
128
|
+
.option('--exclude <patterns>', 'Comma-separated exclude patterns', '*.lock,*.svg')
|
|
129
|
+
.option('--context-lines <number>', 'Context lines for diff', '3')
|
|
130
|
+
.action(async (options) => {
|
|
131
|
+
try {
|
|
132
|
+
await handleGlobalOptions(options);
|
|
133
|
+
const reviewOptions = {
|
|
134
|
+
workspace: options.workspace,
|
|
135
|
+
repository: options.repository,
|
|
136
|
+
branch: options.branch,
|
|
137
|
+
pullRequestId: options.pr,
|
|
138
|
+
dryRun: options.dryRun,
|
|
139
|
+
verbose: options.verbose,
|
|
140
|
+
excludePatterns: options.exclude?.split(',').map((p) => p.trim()),
|
|
141
|
+
contextLines: parseInt(options.contextLines)
|
|
142
|
+
};
|
|
143
|
+
const guardian = new Guardian_1.Guardian();
|
|
144
|
+
await guardian.initialize(options.config);
|
|
145
|
+
const spinner = (0, ora_1.default)('Conducting code review...').start();
|
|
146
|
+
try {
|
|
147
|
+
const result = await guardian.reviewCode(reviewOptions);
|
|
148
|
+
spinner.succeed('Code review completed');
|
|
149
|
+
printReviewResult(result);
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
spinner.fail('Code review failed');
|
|
153
|
+
throw error;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
console.error(chalk_1.default.red(`❌ Error: ${error.message}`));
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Description enhancement command (backward compatible with pr-describe.js)
|
|
164
|
+
*/
|
|
165
|
+
function setupEnhanceCommand() {
|
|
166
|
+
program
|
|
167
|
+
.command('enhance')
|
|
168
|
+
.alias('scribe') // Backward compatibility
|
|
169
|
+
.description('AI-powered description enhancement (equivalent to pr-describe.js)')
|
|
170
|
+
.requiredOption('-w, --workspace <workspace>', 'Bitbucket workspace')
|
|
171
|
+
.requiredOption('-r, --repository <repository>', 'Repository name')
|
|
172
|
+
.option('-b, --branch <branch>', 'Branch name')
|
|
173
|
+
.option('-p, --pr <id>', 'Pull request ID')
|
|
174
|
+
.option('--no-preserve', 'Disable content preservation')
|
|
175
|
+
.action(async (options) => {
|
|
176
|
+
try {
|
|
177
|
+
await handleGlobalOptions(options);
|
|
178
|
+
const enhancementOptions = {
|
|
179
|
+
workspace: options.workspace,
|
|
180
|
+
repository: options.repository,
|
|
181
|
+
branch: options.branch,
|
|
182
|
+
pullRequestId: options.pr,
|
|
183
|
+
dryRun: options.dryRun,
|
|
184
|
+
verbose: options.verbose,
|
|
185
|
+
preserveContent: options.preserve !== false,
|
|
186
|
+
ensureRequiredSections: true
|
|
187
|
+
};
|
|
188
|
+
const guardian = new Guardian_1.Guardian();
|
|
189
|
+
await guardian.initialize(options.config);
|
|
190
|
+
const spinner = (0, ora_1.default)('Enhancing PR description...').start();
|
|
191
|
+
try {
|
|
192
|
+
const result = await guardian.enhanceDescription(enhancementOptions);
|
|
193
|
+
spinner.succeed('Description enhancement completed');
|
|
194
|
+
printEnhancementResult(result);
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
spinner.fail('Description enhancement failed');
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
console.error(chalk_1.default.red(`❌ Error: ${error.message}`));
|
|
203
|
+
process.exit(1);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Initialize configuration command
|
|
209
|
+
*/
|
|
210
|
+
function setupInitCommand() {
|
|
211
|
+
program
|
|
212
|
+
.command('init')
|
|
213
|
+
.description('Initialize Yama configuration')
|
|
214
|
+
.option('-o, --output <path>', 'Output configuration file path')
|
|
215
|
+
.option('-i, --interactive', 'Interactive configuration setup')
|
|
216
|
+
.action(async (options) => {
|
|
217
|
+
try {
|
|
218
|
+
if (options.interactive) {
|
|
219
|
+
await interactiveInit();
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
const configPath = await ConfigManager_1.configManager.createDefaultConfig(options.output);
|
|
223
|
+
console.log(chalk_1.default.green(`✅ Configuration file created: ${configPath}`));
|
|
224
|
+
console.log(chalk_1.default.yellow('💡 Edit the configuration file to customize settings'));
|
|
225
|
+
console.log(chalk_1.default.blue('📖 Visit https://github.com/juspay/yama for documentation'));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
catch (error) {
|
|
229
|
+
console.error(chalk_1.default.red(`❌ Error: ${error.message}`));
|
|
230
|
+
process.exit(1);
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Status and health check command
|
|
236
|
+
*/
|
|
237
|
+
function setupStatusCommand() {
|
|
238
|
+
program
|
|
239
|
+
.command('status')
|
|
240
|
+
.description('Check Yama status and health')
|
|
241
|
+
.option('-d, --detailed', 'Show detailed status information')
|
|
242
|
+
.action(async (options) => {
|
|
243
|
+
try {
|
|
244
|
+
await handleGlobalOptions(options);
|
|
245
|
+
const guardian = new Guardian_1.Guardian();
|
|
246
|
+
await guardian.initialize(options.config);
|
|
247
|
+
const health = await guardian.healthCheck();
|
|
248
|
+
const stats = guardian.getStats();
|
|
249
|
+
console.log(chalk_1.default.cyan('\n🛡️ Yama Status\n'));
|
|
250
|
+
// Health status
|
|
251
|
+
const healthEmoji = health.healthy ? '✅' : '❌';
|
|
252
|
+
console.log(`${healthEmoji} Overall Health: ${health.healthy ? 'Healthy' : 'Issues Detected'}`);
|
|
253
|
+
// Component status
|
|
254
|
+
console.log('\n📊 Component Status:');
|
|
255
|
+
Object.entries(health.components).forEach(([component, status]) => {
|
|
256
|
+
const emoji = status.healthy ? '✅' : '❌';
|
|
257
|
+
console.log(` ${emoji} ${component}: ${status.healthy ? 'OK' : 'Error'}`);
|
|
258
|
+
});
|
|
259
|
+
// Statistics
|
|
260
|
+
if (options.detailed) {
|
|
261
|
+
console.log('\n📈 Statistics:');
|
|
262
|
+
console.log(JSON.stringify(stats, null, 2));
|
|
263
|
+
}
|
|
264
|
+
// Cache status
|
|
265
|
+
const cacheStats = Cache_1.cache.stats();
|
|
266
|
+
console.log(`\n💾 Cache: ${cacheStats.keys} keys, ${cacheStats.hits} hits, ${Math.round(Cache_1.cache.getHitRatio() * 100)}% hit ratio`);
|
|
267
|
+
}
|
|
268
|
+
catch (error) {
|
|
269
|
+
console.error(chalk_1.default.red(`❌ Error: ${error.message}`));
|
|
270
|
+
process.exit(1);
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Cache management command
|
|
276
|
+
*/
|
|
277
|
+
function setupCacheCommand() {
|
|
278
|
+
const cacheCommand = program
|
|
279
|
+
.command('cache')
|
|
280
|
+
.description('Cache management operations');
|
|
281
|
+
cacheCommand
|
|
282
|
+
.command('clear')
|
|
283
|
+
.description('Clear all caches')
|
|
284
|
+
.action(() => {
|
|
285
|
+
Cache_1.cache.clear();
|
|
286
|
+
console.log(chalk_1.default.green('✅ All caches cleared'));
|
|
287
|
+
});
|
|
288
|
+
cacheCommand
|
|
289
|
+
.command('stats')
|
|
290
|
+
.description('Show cache statistics')
|
|
291
|
+
.action(() => {
|
|
292
|
+
const stats = Cache_1.cache.stats();
|
|
293
|
+
const detailed = Cache_1.cache.debug();
|
|
294
|
+
console.log(chalk_1.default.cyan('\n💾 Cache Statistics\n'));
|
|
295
|
+
console.log(`Keys: ${stats.keys}`);
|
|
296
|
+
console.log(`Hits: ${stats.hits}`);
|
|
297
|
+
console.log(`Misses: ${stats.misses}`);
|
|
298
|
+
console.log(`Hit Ratio: ${Math.round(Cache_1.cache.getHitRatio() * 100)}%`);
|
|
299
|
+
console.log('\n📊 Detailed Stats:');
|
|
300
|
+
console.log(JSON.stringify(detailed, null, 2));
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Configuration management command
|
|
305
|
+
*/
|
|
306
|
+
function setupConfigCommand() {
|
|
307
|
+
const configCommand = program
|
|
308
|
+
.command('config')
|
|
309
|
+
.description('Configuration management');
|
|
310
|
+
configCommand
|
|
311
|
+
.command('validate')
|
|
312
|
+
.description('Validate configuration file')
|
|
313
|
+
.option('-c, --config <path>', 'Configuration file path')
|
|
314
|
+
.action(async (options) => {
|
|
315
|
+
try {
|
|
316
|
+
await ConfigManager_1.configManager.loadConfig(options.config);
|
|
317
|
+
console.log(chalk_1.default.green('✅ Configuration is valid'));
|
|
318
|
+
}
|
|
319
|
+
catch (error) {
|
|
320
|
+
console.error(chalk_1.default.red(`❌ Configuration error: ${error.message}`));
|
|
321
|
+
process.exit(1);
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
configCommand
|
|
325
|
+
.command('show')
|
|
326
|
+
.description('Show current configuration')
|
|
327
|
+
.option('-c, --config <path>', 'Configuration file path')
|
|
328
|
+
.action(async (options) => {
|
|
329
|
+
try {
|
|
330
|
+
const config = await ConfigManager_1.configManager.loadConfig(options.config);
|
|
331
|
+
console.log(chalk_1.default.cyan('\n⚙️ Current Configuration\n'));
|
|
332
|
+
// Mask sensitive information
|
|
333
|
+
const sanitizedConfig = { ...config };
|
|
334
|
+
if (sanitizedConfig.providers?.git?.credentials?.token) {
|
|
335
|
+
sanitizedConfig.providers.git.credentials.token = '***MASKED***';
|
|
336
|
+
}
|
|
337
|
+
console.log(JSON.stringify(sanitizedConfig, null, 2));
|
|
338
|
+
}
|
|
339
|
+
catch (error) {
|
|
340
|
+
console.error(chalk_1.default.red(`❌ Error: ${error.message}`));
|
|
341
|
+
process.exit(1);
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Backward compatibility with original scripts
|
|
347
|
+
*/
|
|
348
|
+
function setupBackwardCompatibility() {
|
|
349
|
+
// pr-police.js compatibility
|
|
350
|
+
if (process.argv[1]?.includes('pr-police')) {
|
|
351
|
+
// Redirect to review command
|
|
352
|
+
const args = process.argv.slice(2);
|
|
353
|
+
process.argv = ['node', 'yama', 'review', ...args];
|
|
354
|
+
}
|
|
355
|
+
// pr-describe.js / pr-scribe.js compatibility
|
|
356
|
+
if (process.argv[1]?.includes('pr-scribe') || process.argv[1]?.includes('pr-describe')) {
|
|
357
|
+
// Redirect to enhance command
|
|
358
|
+
const args = process.argv.slice(2);
|
|
359
|
+
process.argv = ['node', 'yama', 'enhance', ...args];
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Utility functions
|
|
364
|
+
*/
|
|
365
|
+
async function handleGlobalOptions(options) {
|
|
366
|
+
// Set up logging
|
|
367
|
+
if (options.verbose) {
|
|
368
|
+
Logger_1.logger.setVerbose(true);
|
|
369
|
+
Logger_1.logger.setLevel('debug');
|
|
370
|
+
}
|
|
371
|
+
// Handle cache disabling
|
|
372
|
+
if (options.cache === false) {
|
|
373
|
+
Cache_1.cache.clear();
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
function parseOperations(operationsStr) {
|
|
377
|
+
const operationMap = {
|
|
378
|
+
'review': 'review',
|
|
379
|
+
'enhance': 'enhance-description',
|
|
380
|
+
'enhance-description': 'enhance-description',
|
|
381
|
+
'security': 'security-scan',
|
|
382
|
+
'security-scan': 'security-scan',
|
|
383
|
+
'analytics': 'analytics',
|
|
384
|
+
'all': 'all'
|
|
385
|
+
};
|
|
386
|
+
return operationsStr.split(',')
|
|
387
|
+
.map(op => op.trim())
|
|
388
|
+
.map(op => operationMap[op] || op)
|
|
389
|
+
.filter(op => op);
|
|
390
|
+
}
|
|
391
|
+
function logStreamUpdate(update) {
|
|
392
|
+
const timestamp = new Date(update.timestamp).toLocaleTimeString();
|
|
393
|
+
const progressStr = update.progress ? ` (${update.progress}%)` : '';
|
|
394
|
+
switch (update.status) {
|
|
395
|
+
case 'started':
|
|
396
|
+
console.log(chalk_1.default.blue(`🚀 [${timestamp}] ${update.operation}: ${update.message}`));
|
|
397
|
+
break;
|
|
398
|
+
case 'progress':
|
|
399
|
+
console.log(chalk_1.default.yellow(`🔄 [${timestamp}] ${update.operation}: ${update.message}${progressStr}`));
|
|
400
|
+
break;
|
|
401
|
+
case 'completed':
|
|
402
|
+
console.log(chalk_1.default.green(`✅ [${timestamp}] ${update.operation}: ${update.message}${progressStr}`));
|
|
403
|
+
break;
|
|
404
|
+
case 'error':
|
|
405
|
+
console.log(chalk_1.default.red(`❌ [${timestamp}] ${update.operation}: ${update.message}`));
|
|
406
|
+
break;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
function printProcessResult(result) {
|
|
410
|
+
console.log(chalk_1.default.cyan('\n🛡️ Yama Process Result\n'));
|
|
411
|
+
console.log(`PR: #${result.pullRequest.id} - ${result.pullRequest.title}`);
|
|
412
|
+
console.log(`Author: ${result.pullRequest.author}`);
|
|
413
|
+
console.log(`Operations: ${result.operations.length}`);
|
|
414
|
+
console.log('\n📊 Summary:');
|
|
415
|
+
console.log(`✅ Success: ${result.summary.successCount}`);
|
|
416
|
+
console.log(`❌ Errors: ${result.summary.errorCount}`);
|
|
417
|
+
console.log(`⏭️ Skipped: ${result.summary.skippedCount}`);
|
|
418
|
+
console.log(`⏱️ Total Duration: ${Math.round(result.summary.totalDuration / 1000)}s`);
|
|
419
|
+
// Show individual operation results
|
|
420
|
+
console.log('\n📋 Operations:');
|
|
421
|
+
result.operations.forEach((op) => {
|
|
422
|
+
const emoji = op.status === 'success' ? '✅' : op.status === 'error' ? '❌' : '⏭️';
|
|
423
|
+
console.log(` ${emoji} ${op.operation}: ${op.status} (${Math.round(op.duration / 1000)}s)`);
|
|
424
|
+
if (op.error) {
|
|
425
|
+
console.log(chalk_1.default.red(` Error: ${op.error}`));
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
function printReviewResult(result) {
|
|
430
|
+
const stats = result.statistics;
|
|
431
|
+
console.log(chalk_1.default.cyan('\n🛡️ Code Review Results\n'));
|
|
432
|
+
console.log(`📊 Total Issues: ${stats.totalIssues}`);
|
|
433
|
+
console.log(`🚨 Critical: ${stats.criticalCount}`);
|
|
434
|
+
console.log(`⚠️ Major: ${stats.majorCount}`);
|
|
435
|
+
console.log(`📝 Minor: ${stats.minorCount}`);
|
|
436
|
+
console.log(`💡 Suggestions: ${stats.suggestionCount}`);
|
|
437
|
+
console.log(`📁 Files Reviewed: ${stats.filesReviewed}`);
|
|
438
|
+
if (stats.criticalCount > 0) {
|
|
439
|
+
console.log(chalk_1.default.red('\n⛔ CRITICAL issues found - must fix before merge!'));
|
|
440
|
+
}
|
|
441
|
+
else if (stats.majorCount > 0) {
|
|
442
|
+
console.log(chalk_1.default.yellow('\n⚠️ Major issues found - should fix before merge'));
|
|
443
|
+
}
|
|
444
|
+
else if (stats.minorCount > 0) {
|
|
445
|
+
console.log(chalk_1.default.blue('\n📝 Minor improvements suggested'));
|
|
446
|
+
}
|
|
447
|
+
else {
|
|
448
|
+
console.log(chalk_1.default.green('\n✅ Code quality approved!'));
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
function printEnhancementResult(result) {
|
|
452
|
+
console.log(chalk_1.default.cyan('\n📝 Description Enhancement Results\n'));
|
|
453
|
+
console.log(`📏 Original Length: ${result.statistics.originalLength} characters`);
|
|
454
|
+
console.log(`📏 Enhanced Length: ${result.statistics.enhancedLength} characters`);
|
|
455
|
+
console.log(`📋 Sections Completed: ${result.statistics.completedSections}/${result.statistics.totalSections}`);
|
|
456
|
+
if (result.sectionsAdded.length > 0) {
|
|
457
|
+
console.log(`➕ Sections Added: ${result.sectionsAdded.join(', ')}`);
|
|
458
|
+
}
|
|
459
|
+
if (result.sectionsEnhanced.length > 0) {
|
|
460
|
+
console.log(`✨ Sections Enhanced: ${result.sectionsEnhanced.join(', ')}`);
|
|
461
|
+
}
|
|
462
|
+
console.log(`📎 Content Preserved: ${result.preservedItems.media} media, ${result.preservedItems.files} files, ${result.preservedItems.links} links`);
|
|
463
|
+
if (result.statistics.completedSections === result.statistics.totalSections) {
|
|
464
|
+
console.log(chalk_1.default.green('\n✅ All required sections completed!'));
|
|
465
|
+
}
|
|
466
|
+
else {
|
|
467
|
+
console.log(chalk_1.default.yellow('\n⚠️ Some required sections may still need attention'));
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
async function interactiveInit() {
|
|
471
|
+
console.log(chalk_1.default.cyan('\n🛡️ Yama Interactive Setup\n'));
|
|
472
|
+
await inquirer_1.default.prompt([
|
|
473
|
+
{
|
|
474
|
+
type: 'input',
|
|
475
|
+
name: 'workspace',
|
|
476
|
+
message: 'Default Bitbucket workspace:',
|
|
477
|
+
default: 'YOUR_WORKSPACE'
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
type: 'input',
|
|
481
|
+
name: 'baseUrl',
|
|
482
|
+
message: 'Bitbucket server URL:',
|
|
483
|
+
default: 'https://your-bitbucket-server.com'
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
type: 'list',
|
|
487
|
+
name: 'aiProvider',
|
|
488
|
+
message: 'AI provider:',
|
|
489
|
+
choices: ['auto', 'google-ai', 'openai', 'anthropic'],
|
|
490
|
+
default: 'auto'
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
type: 'confirm',
|
|
494
|
+
name: 'enableAnalytics',
|
|
495
|
+
message: 'Enable AI analytics:',
|
|
496
|
+
default: true
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
type: 'confirm',
|
|
500
|
+
name: 'enableCache',
|
|
501
|
+
message: 'Enable caching:',
|
|
502
|
+
default: true
|
|
503
|
+
}
|
|
504
|
+
]);
|
|
505
|
+
const configPath = await ConfigManager_1.configManager.createDefaultConfig();
|
|
506
|
+
console.log(chalk_1.default.green(`\n✅ Configuration created: ${configPath}`));
|
|
507
|
+
console.log(chalk_1.default.yellow('💡 Don\'t forget to set your environment variables:'));
|
|
508
|
+
console.log(chalk_1.default.blue(' BITBUCKET_USERNAME=your-username'));
|
|
509
|
+
console.log(chalk_1.default.blue(' BITBUCKET_TOKEN=your-token'));
|
|
510
|
+
console.log(chalk_1.default.blue(' GOOGLE_AI_API_KEY=your-api-key'));
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Main execution
|
|
514
|
+
*/
|
|
515
|
+
function main() {
|
|
516
|
+
setupCLI();
|
|
517
|
+
// Parse command line arguments
|
|
518
|
+
program.parse();
|
|
519
|
+
// Show help if no command provided
|
|
520
|
+
if (!process.argv.slice(2).length) {
|
|
521
|
+
program.outputHelp();
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
// Handle uncaught errors
|
|
525
|
+
process.on('uncaughtException', (error) => {
|
|
526
|
+
console.error(chalk_1.default.red(`\n💥 Uncaught Exception: ${error.message}`));
|
|
527
|
+
process.exit(1);
|
|
528
|
+
});
|
|
529
|
+
process.on('unhandledRejection', (reason) => {
|
|
530
|
+
console.error(chalk_1.default.red(`\n💥 Unhandled Rejection: ${reason}`));
|
|
531
|
+
process.exit(1);
|
|
532
|
+
});
|
|
533
|
+
// Run if this is the main module
|
|
534
|
+
if (require.main === module) {
|
|
535
|
+
main();
|
|
536
|
+
}
|
|
537
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified Context Gatherer - The foundation for all Yama operations
|
|
3
|
+
* Gathers all necessary context once and reuses it across all operations
|
|
4
|
+
*/
|
|
5
|
+
import { PRIdentifier, PRInfo, PRDiff, AIProviderConfig, DiffStrategyConfig } from '../types';
|
|
6
|
+
import { BitbucketProvider } from './providers/BitbucketProvider';
|
|
7
|
+
export interface ProjectContext {
|
|
8
|
+
memoryBank: {
|
|
9
|
+
summary: string;
|
|
10
|
+
projectContext: string;
|
|
11
|
+
patterns: string;
|
|
12
|
+
standards: string;
|
|
13
|
+
};
|
|
14
|
+
clinerules: string;
|
|
15
|
+
filesProcessed: number;
|
|
16
|
+
}
|
|
17
|
+
export interface DiffStrategy {
|
|
18
|
+
strategy: 'whole' | 'file-by-file';
|
|
19
|
+
reason: string;
|
|
20
|
+
fileCount: number;
|
|
21
|
+
estimatedSize: string;
|
|
22
|
+
}
|
|
23
|
+
export interface UnifiedContext {
|
|
24
|
+
pr: PRInfo;
|
|
25
|
+
identifier: PRIdentifier;
|
|
26
|
+
projectContext: ProjectContext;
|
|
27
|
+
diffStrategy: DiffStrategy;
|
|
28
|
+
prDiff?: PRDiff;
|
|
29
|
+
fileDiffs?: Map<string, string>;
|
|
30
|
+
contextId: string;
|
|
31
|
+
gatheredAt: string;
|
|
32
|
+
cacheHits: string[];
|
|
33
|
+
gatheringDuration: number;
|
|
34
|
+
}
|
|
35
|
+
export declare class ContextGatherer {
|
|
36
|
+
private neurolink;
|
|
37
|
+
private bitbucketProvider;
|
|
38
|
+
private aiConfig;
|
|
39
|
+
private startTime;
|
|
40
|
+
constructor(bitbucketProvider: BitbucketProvider, aiConfig: AIProviderConfig);
|
|
41
|
+
/**
|
|
42
|
+
* Main context gathering method - used by all operations
|
|
43
|
+
*/
|
|
44
|
+
gatherContext(identifier: PRIdentifier, options?: {
|
|
45
|
+
excludePatterns?: string[];
|
|
46
|
+
contextLines?: number;
|
|
47
|
+
forceRefresh?: boolean;
|
|
48
|
+
includeDiff?: boolean;
|
|
49
|
+
diffStrategyConfig?: DiffStrategyConfig;
|
|
50
|
+
}): Promise<UnifiedContext>;
|
|
51
|
+
/**
|
|
52
|
+
* Step 1: Find PR and get detailed information
|
|
53
|
+
*/
|
|
54
|
+
private findAndGetPR;
|
|
55
|
+
/**
|
|
56
|
+
* Step 2: Gather project context (memory bank + clinerules)
|
|
57
|
+
*/
|
|
58
|
+
private gatherProjectContext;
|
|
59
|
+
/**
|
|
60
|
+
* Parse project context with AI
|
|
61
|
+
*/
|
|
62
|
+
private parseProjectContextWithAI;
|
|
63
|
+
/**
|
|
64
|
+
* Step 3: Determine optimal diff strategy
|
|
65
|
+
*/
|
|
66
|
+
private determineDiffStrategy;
|
|
67
|
+
/**
|
|
68
|
+
* Estimate diff size based on file count
|
|
69
|
+
*/
|
|
70
|
+
private estimateDiffSize;
|
|
71
|
+
/**
|
|
72
|
+
* Get whole PR diff
|
|
73
|
+
*/
|
|
74
|
+
private getPRDiff;
|
|
75
|
+
/**
|
|
76
|
+
* Get file-by-file diffs for large changesets
|
|
77
|
+
*/
|
|
78
|
+
private getFileByFileDiffs;
|
|
79
|
+
/**
|
|
80
|
+
* Cache the complete context for reuse
|
|
81
|
+
*/
|
|
82
|
+
private cacheContext;
|
|
83
|
+
/**
|
|
84
|
+
* Get cached context if available
|
|
85
|
+
*/
|
|
86
|
+
getCachedContext(identifier: PRIdentifier): Promise<UnifiedContext | null>;
|
|
87
|
+
/**
|
|
88
|
+
* Invalidate context cache for a specific PR
|
|
89
|
+
*/
|
|
90
|
+
invalidateContext(identifier: PRIdentifier): void;
|
|
91
|
+
/**
|
|
92
|
+
* Generate unique context ID
|
|
93
|
+
*/
|
|
94
|
+
private generateContextId;
|
|
95
|
+
/**
|
|
96
|
+
* Parse AI response utility
|
|
97
|
+
*/
|
|
98
|
+
private parseAIResponse;
|
|
99
|
+
/**
|
|
100
|
+
* Get gathering statistics
|
|
101
|
+
*/
|
|
102
|
+
getStats(): any;
|
|
103
|
+
}
|
|
104
|
+
export declare function createContextGatherer(bitbucketProvider: BitbucketProvider, aiConfig: AIProviderConfig): ContextGatherer;
|
|
105
|
+
//# sourceMappingURL=ContextGatherer.d.ts.map
|