@juspay/yama 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/CHANGELOG.md +51 -0
- package/README.md +828 -0
- package/dist/cli/index.d.ts +12 -0
- package/dist/cli/index.js +541 -0
- package/dist/core/ContextGatherer.d.ts +105 -0
- package/dist/core/ContextGatherer.js +454 -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 +444 -0
- package/dist/features/CodeReviewer.d.ts +105 -0
- package/dist/features/CodeReviewer.js +1041 -0
- package/dist/features/DescriptionEnhancer.d.ts +64 -0
- package/dist/features/DescriptionEnhancer.js +448 -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 +255 -0
- package/dist/utils/ConfigManager.d.ts +84 -0
- package/dist/utils/ConfigManager.js +590 -0
- package/dist/utils/Logger.d.ts +30 -0
- package/dist/utils/Logger.js +217 -0
- package/package.json +138 -0
- package/yama.config.example.yaml +143 -0
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Yama - Unified orchestrator class
|
|
4
|
+
* The main class that coordinates all operations using shared context
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.guardian = exports.Guardian = void 0;
|
|
8
|
+
exports.createGuardian = createGuardian;
|
|
9
|
+
const types_1 = require("../types");
|
|
10
|
+
const BitbucketProvider_1 = require("./providers/BitbucketProvider");
|
|
11
|
+
const ContextGatherer_1 = require("./ContextGatherer");
|
|
12
|
+
const CodeReviewer_1 = require("../features/CodeReviewer");
|
|
13
|
+
const DescriptionEnhancer_1 = require("../features/DescriptionEnhancer");
|
|
14
|
+
const Logger_1 = require("../utils/Logger");
|
|
15
|
+
const ConfigManager_1 = require("../utils/ConfigManager");
|
|
16
|
+
const Cache_1 = require("../utils/Cache");
|
|
17
|
+
class Guardian {
|
|
18
|
+
constructor(config) {
|
|
19
|
+
this.initialized = false;
|
|
20
|
+
this.config = {};
|
|
21
|
+
if (config) {
|
|
22
|
+
this.config = { ...this.config, ...config };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Initialize Guardian with configuration
|
|
27
|
+
*/
|
|
28
|
+
async initialize(configPath) {
|
|
29
|
+
if (this.initialized) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
Logger_1.logger.badge();
|
|
34
|
+
Logger_1.logger.phase("🚀 Initializing Yama...");
|
|
35
|
+
// Load configuration
|
|
36
|
+
this.config = await ConfigManager_1.configManager.loadConfig(configPath);
|
|
37
|
+
// Initialize providers
|
|
38
|
+
this.bitbucketProvider = new BitbucketProvider_1.BitbucketProvider(this.config.providers.git.credentials);
|
|
39
|
+
await this.bitbucketProvider.initialize();
|
|
40
|
+
// Initialize NeuroLink with eval-based dynamic import to bypass TypeScript compilation
|
|
41
|
+
const dynamicImport = eval("(specifier) => import(specifier)");
|
|
42
|
+
const { NeuroLink } = await dynamicImport("@juspay/neurolink");
|
|
43
|
+
this.neurolink = new NeuroLink();
|
|
44
|
+
// Initialize core components
|
|
45
|
+
this.contextGatherer = new ContextGatherer_1.ContextGatherer(this.bitbucketProvider, this.config.providers.ai);
|
|
46
|
+
this.codeReviewer = new CodeReviewer_1.CodeReviewer(this.bitbucketProvider, this.config.providers.ai, this.config.features.codeReview);
|
|
47
|
+
this.descriptionEnhancer = new DescriptionEnhancer_1.DescriptionEnhancer(this.bitbucketProvider, this.config.providers.ai);
|
|
48
|
+
this.initialized = true;
|
|
49
|
+
Logger_1.logger.success("✅ Yama initialized successfully");
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
Logger_1.logger.error(`Failed to initialize Yama: ${error.message}`);
|
|
53
|
+
throw new types_1.GuardianError("INITIALIZATION_ERROR", `Initialization failed: ${error.message}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Main method: Process PR with multiple operations using unified context
|
|
58
|
+
*/
|
|
59
|
+
async processPR(options) {
|
|
60
|
+
await this.ensureInitialized();
|
|
61
|
+
const startTime = Date.now();
|
|
62
|
+
const operations = [];
|
|
63
|
+
try {
|
|
64
|
+
Logger_1.logger.operation("PR Processing", "started");
|
|
65
|
+
Logger_1.logger.info(`Target: ${options.workspace}/${options.repository}`);
|
|
66
|
+
Logger_1.logger.info(`Operations: ${options.operations.join(", ")}`);
|
|
67
|
+
Logger_1.logger.info(`Mode: ${options.dryRun ? "DRY RUN" : "LIVE"}`);
|
|
68
|
+
// Step 1: Gather unified context ONCE for all operations
|
|
69
|
+
Logger_1.logger.phase("📋 Gathering unified context...");
|
|
70
|
+
const context = await this.gatherUnifiedContext(options);
|
|
71
|
+
Logger_1.logger.success(`Context ready: PR #${context.pr.id} - "${context.pr.title}"`);
|
|
72
|
+
Logger_1.logger.info(`Files: ${context.diffStrategy.fileCount}, Strategy: ${context.diffStrategy.strategy}`);
|
|
73
|
+
// Step 2: Execute requested operations using shared context
|
|
74
|
+
for (const operation of options.operations) {
|
|
75
|
+
if (operation === "all") {
|
|
76
|
+
// Execute all available operations
|
|
77
|
+
operations.push(await this.executeOperation("review", context, options));
|
|
78
|
+
operations.push(await this.executeOperation("enhance-description", context, options));
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
operations.push(await this.executeOperation(operation, context, options));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const duration = Date.now() - startTime;
|
|
85
|
+
const successCount = operations.filter((op) => op.status === "success").length;
|
|
86
|
+
const errorCount = operations.filter((op) => op.status === "error").length;
|
|
87
|
+
const skippedCount = operations.filter((op) => op.status === "skipped").length;
|
|
88
|
+
const result = {
|
|
89
|
+
pullRequest: context.pr,
|
|
90
|
+
operations,
|
|
91
|
+
summary: {
|
|
92
|
+
totalOperations: operations.length,
|
|
93
|
+
successCount,
|
|
94
|
+
errorCount,
|
|
95
|
+
skippedCount,
|
|
96
|
+
totalDuration: duration,
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
Logger_1.logger.operation("PR Processing", "completed");
|
|
100
|
+
Logger_1.logger.success(`✅ Processing completed in ${Math.round(duration / 1000)}s: ` +
|
|
101
|
+
`${successCount} success, ${errorCount} errors, ${skippedCount} skipped`);
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
Logger_1.logger.operation("PR Processing", "failed");
|
|
106
|
+
Logger_1.logger.error(`Processing failed: ${error.message}`);
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Streaming version of processPR for real-time updates
|
|
112
|
+
*/
|
|
113
|
+
async *processPRStream(options, _streamOptions) {
|
|
114
|
+
await this.ensureInitialized();
|
|
115
|
+
const startTime = Date.now();
|
|
116
|
+
try {
|
|
117
|
+
// Initial update
|
|
118
|
+
yield {
|
|
119
|
+
operation: "all",
|
|
120
|
+
status: "started",
|
|
121
|
+
message: "Yama processing initiated",
|
|
122
|
+
timestamp: new Date().toISOString(),
|
|
123
|
+
};
|
|
124
|
+
// Context gathering phase
|
|
125
|
+
yield {
|
|
126
|
+
operation: "all",
|
|
127
|
+
status: "progress",
|
|
128
|
+
progress: 10,
|
|
129
|
+
message: "Gathering unified context...",
|
|
130
|
+
timestamp: new Date().toISOString(),
|
|
131
|
+
};
|
|
132
|
+
const context = await this.gatherUnifiedContext(options);
|
|
133
|
+
yield {
|
|
134
|
+
operation: "all",
|
|
135
|
+
status: "progress",
|
|
136
|
+
progress: 30,
|
|
137
|
+
message: `Context ready: PR #${context.pr.id}`,
|
|
138
|
+
data: { prId: context.pr.id, title: context.pr.title },
|
|
139
|
+
timestamp: new Date().toISOString(),
|
|
140
|
+
};
|
|
141
|
+
// Execute operations with progress updates
|
|
142
|
+
const totalOps = options.operations.length;
|
|
143
|
+
let completedOps = 0;
|
|
144
|
+
for (const operation of options.operations) {
|
|
145
|
+
yield {
|
|
146
|
+
operation,
|
|
147
|
+
status: "started",
|
|
148
|
+
message: `Starting ${operation}...`,
|
|
149
|
+
timestamp: new Date().toISOString(),
|
|
150
|
+
};
|
|
151
|
+
try {
|
|
152
|
+
const result = await this.executeOperation(operation, context, options);
|
|
153
|
+
if (result.status === "error") {
|
|
154
|
+
yield {
|
|
155
|
+
operation,
|
|
156
|
+
status: "error",
|
|
157
|
+
message: `${operation} failed: ${result.error}`,
|
|
158
|
+
timestamp: new Date().toISOString(),
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
completedOps++;
|
|
163
|
+
yield {
|
|
164
|
+
operation,
|
|
165
|
+
status: "completed",
|
|
166
|
+
progress: 30 + Math.round((completedOps / totalOps) * 60),
|
|
167
|
+
message: `${operation} completed`,
|
|
168
|
+
data: result,
|
|
169
|
+
timestamp: new Date().toISOString(),
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
// This catch is for unexpected errors that bypass executeOperation's own error handling
|
|
175
|
+
yield {
|
|
176
|
+
operation,
|
|
177
|
+
status: "error",
|
|
178
|
+
message: `${operation} failed: ${error.message}`,
|
|
179
|
+
timestamp: new Date().toISOString(),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// Final completion
|
|
184
|
+
const duration = Date.now() - startTime;
|
|
185
|
+
yield {
|
|
186
|
+
operation: "all",
|
|
187
|
+
status: "completed",
|
|
188
|
+
progress: 100,
|
|
189
|
+
message: `Processing completed in ${Math.round(duration / 1000)}s`,
|
|
190
|
+
timestamp: new Date().toISOString(),
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
yield {
|
|
195
|
+
operation: "all",
|
|
196
|
+
status: "error",
|
|
197
|
+
message: `Processing failed: ${error.message}`,
|
|
198
|
+
timestamp: new Date().toISOString(),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Gather unified context (cached and reusable)
|
|
204
|
+
*/
|
|
205
|
+
async gatherUnifiedContext(options) {
|
|
206
|
+
const identifier = {
|
|
207
|
+
workspace: options.workspace,
|
|
208
|
+
repository: options.repository,
|
|
209
|
+
branch: options.branch,
|
|
210
|
+
pullRequestId: options.pullRequestId,
|
|
211
|
+
};
|
|
212
|
+
// Check if we have cached context first
|
|
213
|
+
const cachedContext = await this.contextGatherer.getCachedContext(identifier);
|
|
214
|
+
if (cachedContext && options.config?.cache?.enabled !== false) {
|
|
215
|
+
Logger_1.logger.debug("✓ Using cached context");
|
|
216
|
+
return cachedContext;
|
|
217
|
+
}
|
|
218
|
+
// Determine what operations need diff data
|
|
219
|
+
const needsDiff = options.operations.some((op) => op === "review" || op === "security-scan" || op === "all");
|
|
220
|
+
const contextOptions = {
|
|
221
|
+
excludePatterns: this.config.features.codeReview.excludePatterns,
|
|
222
|
+
contextLines: this.config.features.codeReview.contextLines,
|
|
223
|
+
forceRefresh: false,
|
|
224
|
+
includeDiff: needsDiff,
|
|
225
|
+
diffStrategyConfig: this.config.features.diffStrategy,
|
|
226
|
+
};
|
|
227
|
+
return await this.contextGatherer.gatherContext(identifier, contextOptions);
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Execute individual operation using shared context
|
|
231
|
+
*/
|
|
232
|
+
async executeOperation(operation, context, options) {
|
|
233
|
+
const startTime = Date.now();
|
|
234
|
+
try {
|
|
235
|
+
let data;
|
|
236
|
+
switch (operation) {
|
|
237
|
+
case "review":
|
|
238
|
+
data = await this.executeCodeReview(context, options);
|
|
239
|
+
break;
|
|
240
|
+
case "enhance-description":
|
|
241
|
+
data = await this.executeDescriptionEnhancement(context, options);
|
|
242
|
+
break;
|
|
243
|
+
case "security-scan":
|
|
244
|
+
// TODO: Implement in future phases
|
|
245
|
+
throw new Error("Security scan not implemented in Phase 1");
|
|
246
|
+
case "analytics":
|
|
247
|
+
// TODO: Implement in future phases
|
|
248
|
+
throw new Error("Analytics not implemented in Phase 1");
|
|
249
|
+
default:
|
|
250
|
+
throw new Error(`Unknown operation: ${operation}`);
|
|
251
|
+
}
|
|
252
|
+
return {
|
|
253
|
+
operation,
|
|
254
|
+
status: "success",
|
|
255
|
+
data,
|
|
256
|
+
duration: Date.now() - startTime,
|
|
257
|
+
timestamp: new Date().toISOString(),
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
Logger_1.logger.error(`Operation ${operation} failed: ${error.message}`);
|
|
262
|
+
return {
|
|
263
|
+
operation,
|
|
264
|
+
status: "error",
|
|
265
|
+
error: error.message,
|
|
266
|
+
duration: Date.now() - startTime,
|
|
267
|
+
timestamp: new Date().toISOString(),
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Execute code review using shared context
|
|
273
|
+
*/
|
|
274
|
+
async executeCodeReview(context, options) {
|
|
275
|
+
if (!this.config.features.codeReview.enabled) {
|
|
276
|
+
Logger_1.logger.info("Code review is disabled in configuration");
|
|
277
|
+
return { skipped: true, reason: "disabled in config" };
|
|
278
|
+
}
|
|
279
|
+
Logger_1.logger.phase("🔍 Executing code review...");
|
|
280
|
+
const reviewOptions = {
|
|
281
|
+
workspace: context.identifier.workspace,
|
|
282
|
+
repository: context.identifier.repository,
|
|
283
|
+
pullRequestId: context.identifier.pullRequestId,
|
|
284
|
+
dryRun: options.dryRun,
|
|
285
|
+
verbose: Logger_1.logger.getConfig().verbose,
|
|
286
|
+
excludePatterns: this.config.features.codeReview.excludePatterns,
|
|
287
|
+
contextLines: this.config.features.codeReview.contextLines,
|
|
288
|
+
};
|
|
289
|
+
// Use the already gathered context instead of gathering again
|
|
290
|
+
return await this.codeReviewer.reviewCodeWithContext(context, reviewOptions);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Execute description enhancement using shared context
|
|
294
|
+
*/
|
|
295
|
+
async executeDescriptionEnhancement(context, options) {
|
|
296
|
+
if (!this.config.features.descriptionEnhancement.enabled) {
|
|
297
|
+
Logger_1.logger.info("Description enhancement is disabled in configuration");
|
|
298
|
+
return { skipped: true, reason: "disabled in config" };
|
|
299
|
+
}
|
|
300
|
+
Logger_1.logger.phase("📝 Executing description enhancement...");
|
|
301
|
+
const enhancementOptions = {
|
|
302
|
+
workspace: context.identifier.workspace,
|
|
303
|
+
repository: context.identifier.repository,
|
|
304
|
+
pullRequestId: context.identifier.pullRequestId,
|
|
305
|
+
dryRun: options.dryRun,
|
|
306
|
+
verbose: Logger_1.logger.getConfig().verbose,
|
|
307
|
+
preserveContent: this.config.features.descriptionEnhancement.preserveContent,
|
|
308
|
+
ensureRequiredSections: true,
|
|
309
|
+
customSections: this.config.features.descriptionEnhancement.requiredSections,
|
|
310
|
+
};
|
|
311
|
+
// Use the already gathered context instead of gathering again
|
|
312
|
+
return await this.descriptionEnhancer.enhanceWithContext(context, enhancementOptions);
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Individual operation methods for backwards compatibility
|
|
316
|
+
*/
|
|
317
|
+
/**
|
|
318
|
+
* Code review operation (standalone)
|
|
319
|
+
*/
|
|
320
|
+
async reviewCode(options) {
|
|
321
|
+
await this.ensureInitialized();
|
|
322
|
+
const identifier = {
|
|
323
|
+
workspace: options.workspace,
|
|
324
|
+
repository: options.repository,
|
|
325
|
+
branch: options.branch,
|
|
326
|
+
pullRequestId: options.pullRequestId,
|
|
327
|
+
};
|
|
328
|
+
Logger_1.logger.operation("Code Review", "started");
|
|
329
|
+
try {
|
|
330
|
+
// Gather context specifically for code review
|
|
331
|
+
const context = await this.contextGatherer.gatherContext(identifier, {
|
|
332
|
+
excludePatterns: options.excludePatterns,
|
|
333
|
+
contextLines: options.contextLines,
|
|
334
|
+
includeDiff: true,
|
|
335
|
+
});
|
|
336
|
+
const result = await this.codeReviewer.reviewCodeWithContext(context, options);
|
|
337
|
+
Logger_1.logger.operation("Code Review", "completed");
|
|
338
|
+
return result;
|
|
339
|
+
}
|
|
340
|
+
catch (error) {
|
|
341
|
+
Logger_1.logger.operation("Code Review", "failed");
|
|
342
|
+
throw error;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Description enhancement operation (standalone)
|
|
347
|
+
*/
|
|
348
|
+
async enhanceDescription(options) {
|
|
349
|
+
await this.ensureInitialized();
|
|
350
|
+
const identifier = {
|
|
351
|
+
workspace: options.workspace,
|
|
352
|
+
repository: options.repository,
|
|
353
|
+
branch: options.branch,
|
|
354
|
+
pullRequestId: options.pullRequestId,
|
|
355
|
+
};
|
|
356
|
+
Logger_1.logger.operation("Description Enhancement", "started");
|
|
357
|
+
try {
|
|
358
|
+
// Gather context specifically for description enhancement
|
|
359
|
+
const context = await this.contextGatherer.gatherContext(identifier, {
|
|
360
|
+
includeDiff: true, // Description enhancement may need to see changes
|
|
361
|
+
});
|
|
362
|
+
const result = await this.descriptionEnhancer.enhanceWithContext(context, options);
|
|
363
|
+
Logger_1.logger.operation("Description Enhancement", "completed");
|
|
364
|
+
return result;
|
|
365
|
+
}
|
|
366
|
+
catch (error) {
|
|
367
|
+
Logger_1.logger.operation("Description Enhancement", "failed");
|
|
368
|
+
throw error;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Health check for all components
|
|
373
|
+
*/
|
|
374
|
+
async healthCheck() {
|
|
375
|
+
const components = {};
|
|
376
|
+
try {
|
|
377
|
+
// Check Bitbucket provider
|
|
378
|
+
components.bitbucket = await this.bitbucketProvider.healthCheck();
|
|
379
|
+
// Check cache
|
|
380
|
+
components.cache = {
|
|
381
|
+
healthy: true,
|
|
382
|
+
stats: Cache_1.cache.stats(),
|
|
383
|
+
};
|
|
384
|
+
// Check NeuroLink (if initialized)
|
|
385
|
+
components.neurolink = {
|
|
386
|
+
healthy: true,
|
|
387
|
+
initialized: !!this.neurolink,
|
|
388
|
+
};
|
|
389
|
+
const allHealthy = Object.values(components).every((comp) => comp.healthy);
|
|
390
|
+
return {
|
|
391
|
+
healthy: allHealthy,
|
|
392
|
+
components,
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
catch (error) {
|
|
396
|
+
return {
|
|
397
|
+
healthy: false,
|
|
398
|
+
components: {
|
|
399
|
+
...components,
|
|
400
|
+
error: error.message,
|
|
401
|
+
},
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Get comprehensive statistics
|
|
407
|
+
*/
|
|
408
|
+
getStats() {
|
|
409
|
+
return {
|
|
410
|
+
initialized: this.initialized,
|
|
411
|
+
config: {
|
|
412
|
+
features: Object.keys(this.config.features || {}),
|
|
413
|
+
cacheEnabled: this.config.cache?.enabled,
|
|
414
|
+
},
|
|
415
|
+
providers: {
|
|
416
|
+
bitbucket: this.bitbucketProvider?.getStats(),
|
|
417
|
+
context: this.contextGatherer?.getStats(),
|
|
418
|
+
},
|
|
419
|
+
cache: Cache_1.cache.stats(),
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Clear all caches
|
|
424
|
+
*/
|
|
425
|
+
clearCache() {
|
|
426
|
+
Cache_1.cache.clear();
|
|
427
|
+
this.bitbucketProvider?.clearCache();
|
|
428
|
+
Logger_1.logger.info("All caches cleared");
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Ensure Guardian is initialized
|
|
432
|
+
*/
|
|
433
|
+
async ensureInitialized() {
|
|
434
|
+
if (!this.initialized) {
|
|
435
|
+
await this.initialize();
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Shutdown Guardian gracefully
|
|
440
|
+
*/
|
|
441
|
+
async shutdown() {
|
|
442
|
+
Logger_1.logger.info("Shutting down Yama...");
|
|
443
|
+
// Clear caches
|
|
444
|
+
this.clearCache();
|
|
445
|
+
// Reset state
|
|
446
|
+
this.initialized = false;
|
|
447
|
+
Logger_1.logger.success("Yama shutdown complete");
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
exports.Guardian = Guardian;
|
|
451
|
+
// Export factory function
|
|
452
|
+
function createGuardian(config) {
|
|
453
|
+
return new Guardian(config);
|
|
454
|
+
}
|
|
455
|
+
// Export default instance
|
|
456
|
+
exports.guardian = new Guardian();
|
|
457
|
+
//# sourceMappingURL=Guardian.js.map
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Bitbucket Provider - Optimized from both pr-police.js and pr-describe.js
|
|
3
|
+
* Provides unified, cached, and optimized Bitbucket operations
|
|
4
|
+
*/
|
|
5
|
+
import { PRIdentifier, PRInfo, PRDiff, GitCredentials } from "../../types";
|
|
6
|
+
export interface BitbucketMCPResponse {
|
|
7
|
+
content?: Array<{
|
|
8
|
+
text?: string;
|
|
9
|
+
}>;
|
|
10
|
+
message?: string;
|
|
11
|
+
error?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare class BitbucketProvider {
|
|
14
|
+
private apiClient;
|
|
15
|
+
private branchHandlers;
|
|
16
|
+
private pullRequestHandlers;
|
|
17
|
+
private reviewHandlers;
|
|
18
|
+
private fileHandlers;
|
|
19
|
+
private initialized;
|
|
20
|
+
private baseUrl;
|
|
21
|
+
private credentials;
|
|
22
|
+
constructor(credentials: GitCredentials);
|
|
23
|
+
/**
|
|
24
|
+
* Initialize MCP handlers with lazy loading and connection reuse
|
|
25
|
+
*/
|
|
26
|
+
initialize(): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Parse MCP response - exactly matching the working pr-police.js implementation
|
|
29
|
+
*/
|
|
30
|
+
private parseMCPResponse;
|
|
31
|
+
/**
|
|
32
|
+
* Find PR for branch with intelligent caching
|
|
33
|
+
*/
|
|
34
|
+
findPRForBranch(identifier: PRIdentifier): Promise<PRInfo>;
|
|
35
|
+
/**
|
|
36
|
+
* Get PR details with enhanced caching
|
|
37
|
+
*/
|
|
38
|
+
getPRDetails(identifier: PRIdentifier): Promise<PRInfo>;
|
|
39
|
+
/**
|
|
40
|
+
* Get PR diff with smart caching and filtering
|
|
41
|
+
*/
|
|
42
|
+
getPRDiff(identifier: PRIdentifier, contextLines?: number, excludePatterns?: string[], includePatterns?: string[]): Promise<PRDiff>;
|
|
43
|
+
/**
|
|
44
|
+
* Get file content with caching
|
|
45
|
+
*/
|
|
46
|
+
getFileContent(workspace: string, repository: string, filePath: string, branch: string): Promise<string>;
|
|
47
|
+
/**
|
|
48
|
+
* List directory content with caching
|
|
49
|
+
*/
|
|
50
|
+
listDirectoryContent(workspace: string, repository: string, path: string, branch: string): Promise<any[]>;
|
|
51
|
+
/**
|
|
52
|
+
* Update PR description with reviewer preservation
|
|
53
|
+
*/
|
|
54
|
+
updatePRDescription(identifier: PRIdentifier, description: string): Promise<{
|
|
55
|
+
success: boolean;
|
|
56
|
+
message: string;
|
|
57
|
+
}>;
|
|
58
|
+
/**
|
|
59
|
+
* Add comment to PR with smart positioning
|
|
60
|
+
*/
|
|
61
|
+
addComment(identifier: PRIdentifier, commentText: string, options?: {
|
|
62
|
+
filePath?: string;
|
|
63
|
+
lineNumber?: number;
|
|
64
|
+
lineType?: "ADDED" | "REMOVED" | "CONTEXT";
|
|
65
|
+
codeSnippet?: string;
|
|
66
|
+
searchContext?: {
|
|
67
|
+
before: string[];
|
|
68
|
+
after: string[];
|
|
69
|
+
};
|
|
70
|
+
matchStrategy?: "exact" | "best" | "strict";
|
|
71
|
+
suggestion?: string;
|
|
72
|
+
}): Promise<{
|
|
73
|
+
success: boolean;
|
|
74
|
+
commentId?: number;
|
|
75
|
+
}>;
|
|
76
|
+
/**
|
|
77
|
+
* Batch operation support for multiple API calls
|
|
78
|
+
*/
|
|
79
|
+
batchOperations<T>(operations: Array<() => Promise<T>>, options?: {
|
|
80
|
+
maxConcurrent?: number;
|
|
81
|
+
delayBetween?: number;
|
|
82
|
+
continueOnError?: boolean;
|
|
83
|
+
}): Promise<Array<{
|
|
84
|
+
success: boolean;
|
|
85
|
+
data?: T;
|
|
86
|
+
error?: string;
|
|
87
|
+
}>>;
|
|
88
|
+
/**
|
|
89
|
+
* Health check for the provider
|
|
90
|
+
*/
|
|
91
|
+
healthCheck(): Promise<{
|
|
92
|
+
healthy: boolean;
|
|
93
|
+
details: any;
|
|
94
|
+
}>;
|
|
95
|
+
/**
|
|
96
|
+
* Get provider statistics and cache metrics
|
|
97
|
+
*/
|
|
98
|
+
getStats(): any;
|
|
99
|
+
/**
|
|
100
|
+
* Clear provider-related cache entries
|
|
101
|
+
*/
|
|
102
|
+
clearCache(): void;
|
|
103
|
+
}
|
|
104
|
+
export declare function createBitbucketProvider(credentials: GitCredentials): BitbucketProvider;
|
|
105
|
+
//# sourceMappingURL=BitbucketProvider.d.ts.map
|