@juspay/yama 1.6.0 → 2.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 (67) hide show
  1. package/.mcp-config.example.json +26 -0
  2. package/CHANGELOG.md +34 -0
  3. package/README.md +311 -685
  4. package/dist/cli/v2.cli.d.ts +13 -0
  5. package/dist/cli/v2.cli.js +290 -0
  6. package/dist/index.d.ts +12 -13
  7. package/dist/index.js +18 -19
  8. package/dist/v2/config/ConfigLoader.d.ts +50 -0
  9. package/dist/v2/config/ConfigLoader.js +205 -0
  10. package/dist/v2/config/DefaultConfig.d.ts +9 -0
  11. package/dist/v2/config/DefaultConfig.js +191 -0
  12. package/dist/v2/core/MCPServerManager.d.ts +22 -0
  13. package/dist/v2/core/MCPServerManager.js +92 -0
  14. package/dist/v2/core/SessionManager.d.ts +72 -0
  15. package/dist/v2/core/SessionManager.js +200 -0
  16. package/dist/v2/core/YamaV2Orchestrator.d.ts +112 -0
  17. package/dist/v2/core/YamaV2Orchestrator.js +549 -0
  18. package/dist/v2/prompts/EnhancementSystemPrompt.d.ts +8 -0
  19. package/dist/v2/prompts/EnhancementSystemPrompt.js +216 -0
  20. package/dist/v2/prompts/PromptBuilder.d.ts +38 -0
  21. package/dist/v2/prompts/PromptBuilder.js +228 -0
  22. package/dist/v2/prompts/ReviewSystemPrompt.d.ts +8 -0
  23. package/dist/v2/prompts/ReviewSystemPrompt.js +270 -0
  24. package/dist/v2/types/config.types.d.ts +120 -0
  25. package/dist/v2/types/config.types.js +5 -0
  26. package/dist/v2/types/mcp.types.d.ts +191 -0
  27. package/dist/v2/types/mcp.types.js +6 -0
  28. package/dist/v2/types/v2.types.d.ts +182 -0
  29. package/dist/v2/types/v2.types.js +42 -0
  30. package/dist/v2/utils/ObservabilityConfig.d.ts +22 -0
  31. package/dist/v2/utils/ObservabilityConfig.js +48 -0
  32. package/package.json +11 -9
  33. package/yama.config.example.yaml +214 -204
  34. package/dist/cli/index.d.ts +0 -12
  35. package/dist/cli/index.js +0 -538
  36. package/dist/core/ContextGatherer.d.ts +0 -110
  37. package/dist/core/ContextGatherer.js +0 -470
  38. package/dist/core/Guardian.d.ts +0 -81
  39. package/dist/core/Guardian.js +0 -480
  40. package/dist/core/providers/BitbucketProvider.d.ts +0 -105
  41. package/dist/core/providers/BitbucketProvider.js +0 -489
  42. package/dist/features/CodeReviewer.d.ts +0 -173
  43. package/dist/features/CodeReviewer.js +0 -1707
  44. package/dist/features/DescriptionEnhancer.d.ts +0 -70
  45. package/dist/features/DescriptionEnhancer.js +0 -511
  46. package/dist/features/MultiInstanceProcessor.d.ts +0 -74
  47. package/dist/features/MultiInstanceProcessor.js +0 -360
  48. package/dist/types/index.d.ts +0 -624
  49. package/dist/types/index.js +0 -104
  50. package/dist/utils/Cache.d.ts +0 -103
  51. package/dist/utils/Cache.js +0 -444
  52. package/dist/utils/ConfigManager.d.ts +0 -88
  53. package/dist/utils/ConfigManager.js +0 -602
  54. package/dist/utils/ContentSimilarityService.d.ts +0 -74
  55. package/dist/utils/ContentSimilarityService.js +0 -215
  56. package/dist/utils/ExactDuplicateRemover.d.ts +0 -77
  57. package/dist/utils/ExactDuplicateRemover.js +0 -361
  58. package/dist/utils/Logger.d.ts +0 -31
  59. package/dist/utils/Logger.js +0 -214
  60. package/dist/utils/MemoryBankManager.d.ts +0 -73
  61. package/dist/utils/MemoryBankManager.js +0 -310
  62. package/dist/utils/ParallelProcessing.d.ts +0 -140
  63. package/dist/utils/ParallelProcessing.js +0 -333
  64. package/dist/utils/ProviderLimits.d.ts +0 -58
  65. package/dist/utils/ProviderLimits.js +0 -143
  66. package/dist/utils/RetryManager.d.ts +0 -78
  67. package/dist/utils/RetryManager.js +0 -205
@@ -1,104 +0,0 @@
1
- /**
2
- * Core TypeScript types for Yama
3
- * Consolidates all interfaces and types used across the application
4
- */
5
- // ============================================================================
6
- // Error Types
7
- // ============================================================================
8
- export class GuardianError extends Error {
9
- code;
10
- context;
11
- constructor(code, message, context) {
12
- super(message);
13
- this.code = code;
14
- this.context = context;
15
- this.name = "GuardianError";
16
- }
17
- }
18
- export class ConfigurationError extends GuardianError {
19
- constructor(message, context) {
20
- super("CONFIGURATION_ERROR", message, context);
21
- this.name = "ConfigurationError";
22
- }
23
- }
24
- export class ProviderError extends GuardianError {
25
- constructor(message, context) {
26
- super("PROVIDER_ERROR", message, context);
27
- this.name = "ProviderError";
28
- }
29
- }
30
- export class ValidationError extends GuardianError {
31
- constructor(message, context) {
32
- super("VALIDATION_ERROR", message, context);
33
- this.name = "ValidationError";
34
- }
35
- }
36
- // ============================================================================
37
- // Cache Error Types
38
- // ============================================================================
39
- export var CacheErrorCode;
40
- (function (CacheErrorCode) {
41
- // System-level cache errors
42
- CacheErrorCode["CACHE_SYSTEM_FAILURE"] = "CACHE_SYSTEM_FAILURE";
43
- CacheErrorCode["CACHE_MEMORY_EXHAUSTED"] = "CACHE_MEMORY_EXHAUSTED";
44
- CacheErrorCode["CACHE_INITIALIZATION_FAILED"] = "CACHE_INITIALIZATION_FAILED";
45
- // Storage-related errors
46
- CacheErrorCode["CACHE_STORAGE_FULL"] = "CACHE_STORAGE_FULL";
47
- CacheErrorCode["CACHE_STORAGE_PERMISSION"] = "CACHE_STORAGE_PERMISSION";
48
- CacheErrorCode["CACHE_STORAGE_CORRUPTION"] = "CACHE_STORAGE_CORRUPTION";
49
- // Network-related errors (for future Redis support)
50
- CacheErrorCode["CACHE_NETWORK_CONNECTION"] = "CACHE_NETWORK_CONNECTION";
51
- CacheErrorCode["CACHE_NETWORK_TIMEOUT"] = "CACHE_NETWORK_TIMEOUT";
52
- CacheErrorCode["CACHE_NETWORK_AUTH"] = "CACHE_NETWORK_AUTH";
53
- // Configuration errors
54
- CacheErrorCode["CACHE_CONFIG_INVALID"] = "CACHE_CONFIG_INVALID";
55
- CacheErrorCode["CACHE_CONFIG_MISSING"] = "CACHE_CONFIG_MISSING";
56
- // Operation errors
57
- CacheErrorCode["CACHE_OPERATION_FAILED"] = "CACHE_OPERATION_FAILED";
58
- CacheErrorCode["CACHE_SERIALIZATION_ERROR"] = "CACHE_SERIALIZATION_ERROR";
59
- CacheErrorCode["CACHE_KEY_INVALID"] = "CACHE_KEY_INVALID";
60
- })(CacheErrorCode || (CacheErrorCode = {}));
61
- export class CacheError extends GuardianError {
62
- operation;
63
- key;
64
- constructor(code, message, operation, key, context) {
65
- super(code, message, context);
66
- this.operation = operation;
67
- this.key = key;
68
- this.name = "CacheError";
69
- }
70
- }
71
- export class CacheSystemError extends CacheError {
72
- constructor(message, operation, key, context) {
73
- super(CacheErrorCode.CACHE_SYSTEM_FAILURE, message, operation, key, context);
74
- this.name = "CacheSystemError";
75
- }
76
- }
77
- export class CacheStorageError extends CacheError {
78
- constructor(code = CacheErrorCode.CACHE_STORAGE_FULL, message, operation, key, context) {
79
- super(code, message, operation, key, context);
80
- this.name = "CacheStorageError";
81
- }
82
- }
83
- export class CacheNetworkError extends CacheError {
84
- constructor(code = CacheErrorCode.CACHE_NETWORK_CONNECTION, message, operation, key, context) {
85
- super(code, message, operation, key, context);
86
- this.name = "CacheNetworkError";
87
- }
88
- }
89
- export class CacheConfigurationError extends CacheError {
90
- constructor(code = CacheErrorCode.CACHE_CONFIG_INVALID, message, operation, key, context) {
91
- super(code, message, operation, key, context);
92
- this.name = "CacheConfigurationError";
93
- }
94
- }
95
- export class CacheOperationError extends CacheError {
96
- constructor(code = CacheErrorCode.CACHE_OPERATION_FAILED, message, operation, key, context) {
97
- super(code, message, operation, key, context);
98
- this.name = "CacheOperationError";
99
- }
100
- }
101
- // ============================================================================
102
- // Export all types - Main file, no re-exports needed
103
- // ============================================================================
104
- //# sourceMappingURL=index.js.map
@@ -1,103 +0,0 @@
1
- /**
2
- * Enhanced Cache utility for Yama
3
- * Provides intelligent caching for PR data, file contents, and AI responses
4
- */
5
- import { Cache as ICache, CacheOptions } from "../types/index.js";
6
- export declare class Cache implements ICache {
7
- private cache;
8
- private statsData;
9
- constructor(options?: CacheOptions);
10
- /**
11
- * Get value from cache with resilient error handling
12
- */
13
- get<T>(key: string): T | undefined;
14
- /**
15
- * Set value in cache with optional TTL
16
- */
17
- set<T>(key: string, value: T, ttl?: number): boolean;
18
- /**
19
- * Delete key from cache
20
- */
21
- del(key: string): number;
22
- /**
23
- * Check if key exists in cache
24
- */
25
- has(key: string): boolean;
26
- /**
27
- * Clear all cache entries
28
- */
29
- clear(): void;
30
- /**
31
- * Get all cache keys
32
- */
33
- keys(): string[];
34
- /**
35
- * Get cache statistics
36
- */
37
- stats(): {
38
- hits: number;
39
- misses: number;
40
- keys: number;
41
- size: number;
42
- cacheErrors: number;
43
- nonCacheErrors: number;
44
- };
45
- /**
46
- * Get detailed cache statistics from node-cache
47
- */
48
- getDetailedStats(): any;
49
- /**
50
- * Get or set pattern with automatic fallback on cache failures
51
- */
52
- getOrSet<T>(key: string, fetchFn: () => Promise<T>, ttl?: number): Promise<T>;
53
- /**
54
- * Resilient get or set pattern that bypasses cache entirely on cache system failures
55
- */
56
- getOrSetResilient<T>(key: string, fetchFn: () => Promise<T>, ttl?: number): Promise<T>;
57
- /**
58
- * Cache with tags for group invalidation
59
- */
60
- private tags;
61
- setWithTags<T>(key: string, value: T, tags: string[], ttl?: number): boolean;
62
- /**
63
- * Invalidate all keys with a specific tag
64
- */
65
- invalidateTag(tag: string): number;
66
- /**
67
- * Invalidate all keys matching a pattern
68
- */
69
- invalidatePattern(pattern: string): number;
70
- /**
71
- * Cache key generators for common patterns
72
- */
73
- static keys: {
74
- prInfo: (workspace: string, repository: string, prId: string | number) => string;
75
- prDiff: (workspace: string, repository: string, prId: string | number) => string;
76
- fileContent: (workspace: string, repository: string, filePath: string, branch: string) => string;
77
- directoryContent: (workspace: string, repository: string, path: string, branch: string) => string;
78
- branchInfo: (workspace: string, repository: string, branch: string) => string;
79
- aiResponse: (prompt: string, provider: string, model: string) => string;
80
- projectContext: (workspace: string, repository: string, branch: string) => string;
81
- reviewResult: (workspace: string, repository: string, prId: string | number, configHash: string) => string;
82
- memoryBankFiles: (workspace: string, repository: string, branch: string, path: string) => string;
83
- };
84
- /**
85
- * Smart cache warming for common patterns
86
- */
87
- warmPRCache(workspace: string, repository: string, prId: string | number): Promise<void>;
88
- /**
89
- * Cleanup expired entries and optimize memory
90
- */
91
- cleanup(): void;
92
- /**
93
- * Get cache hit ratio
94
- */
95
- getHitRatio(): number;
96
- /**
97
- * Export cache state for debugging
98
- */
99
- debug(): any;
100
- }
101
- export declare const cache: Cache;
102
- export declare function createCache(options?: CacheOptions): Cache;
103
- //# sourceMappingURL=Cache.d.ts.map
@@ -1,444 +0,0 @@
1
- /**
2
- * Enhanced Cache utility for Yama
3
- * Provides intelligent caching for PR data, file contents, and AI responses
4
- */
5
- import NodeCache from "node-cache";
6
- import { CacheError, } from "../types/index.js";
7
- import { logger } from "./Logger.js";
8
- /**
9
- * Enhanced cache error detection utility
10
- * Provides multi-layer error classification to avoid false positives
11
- */
12
- class CacheErrorDetector {
13
- /**
14
- * Detect if an error is cache-related using multiple strategies
15
- */
16
- static isCacheError(error, operation, key) {
17
- // Strategy 1: Check error type/class (most reliable)
18
- if (error instanceof CacheError) {
19
- return true;
20
- }
21
- // Strategy 2: Check for specific cache error patterns in NodeCache
22
- if (error instanceof Error) {
23
- const errorMessage = error.message.toLowerCase();
24
- const stackTrace = error.stack?.toLowerCase() || "";
25
- // Check for NodeCache-specific error patterns
26
- const nodeCachePatterns = [
27
- /node_modules\/node-cache/,
28
- /cache\.js:\d+/,
29
- /nodecache/,
30
- ];
31
- const isNodeCacheError = nodeCachePatterns.some((pattern) => pattern.test(stackTrace));
32
- if (isNodeCacheError) {
33
- return true;
34
- }
35
- // Strategy 3: Check for specific cache-related error messages (more targeted)
36
- const cacheSpecificPatterns = [
37
- /cache.*(?:full|exhausted|limit)/,
38
- /memory.*(?:cache|allocation).*(?:failed|error)/,
39
- /storage.*(?:cache|quota).*(?:exceeded|full)/,
40
- /cache.*(?:initialization|setup).*(?:failed|error)/,
41
- /ttl.*(?:invalid|expired)/,
42
- /cache.*(?:key|value).*(?:invalid|malformed)/,
43
- ];
44
- const hasCacheSpecificError = cacheSpecificPatterns.some((pattern) => pattern.test(errorMessage));
45
- if (hasCacheSpecificError) {
46
- return true;
47
- }
48
- // Strategy 4: Context-aware detection
49
- if (operation && key) {
50
- // If we're in a cache operation and get memory/storage errors, likely cache-related
51
- const cacheOperations = [
52
- "get",
53
- "set",
54
- "del",
55
- "clear",
56
- "has",
57
- "getorset",
58
- "getorsetresilient",
59
- ];
60
- const isCacheOperation = cacheOperations.includes(operation.toLowerCase());
61
- const contextualPatterns = [
62
- /^out of memory$/,
63
- /storage quota exceeded/,
64
- /disk full/,
65
- ];
66
- if (isCacheOperation &&
67
- contextualPatterns.some((pattern) => pattern.test(errorMessage))) {
68
- return true;
69
- }
70
- }
71
- }
72
- return false;
73
- }
74
- /**
75
- * Classify cache error for better handling and logging
76
- */
77
- static classifyError(error, operation, key) {
78
- if (!this.isCacheError(error, operation, key)) {
79
- return {
80
- isCache: false,
81
- category: "unknown",
82
- confidence: "high",
83
- reason: "Not identified as cache-related error",
84
- };
85
- }
86
- if (error instanceof CacheError) {
87
- const category = error.code.includes("STORAGE")
88
- ? "storage"
89
- : error.code.includes("NETWORK")
90
- ? "network"
91
- : error.code.includes("SYSTEM")
92
- ? "system"
93
- : "operation";
94
- return {
95
- isCache: true,
96
- category,
97
- confidence: "high",
98
- reason: `Explicit cache error: ${error.code}`,
99
- };
100
- }
101
- if (error instanceof Error) {
102
- const message = error.message.toLowerCase();
103
- const stack = error.stack?.toLowerCase() || "";
104
- // High confidence patterns
105
- if (/node_modules\/node-cache/.test(stack)) {
106
- return {
107
- isCache: true,
108
- category: "system",
109
- confidence: "high",
110
- reason: "NodeCache stack trace detected",
111
- };
112
- }
113
- // Medium confidence patterns
114
- if (/cache.*(?:full|exhausted)/.test(message)) {
115
- return {
116
- isCache: true,
117
- category: "storage",
118
- confidence: "medium",
119
- reason: "Cache capacity error pattern",
120
- };
121
- }
122
- if (/memory.*cache.*failed/.test(message)) {
123
- return {
124
- isCache: true,
125
- category: "system",
126
- confidence: "medium",
127
- reason: "Memory allocation error in cache context",
128
- };
129
- }
130
- }
131
- return {
132
- isCache: true,
133
- category: "unknown",
134
- confidence: "low",
135
- reason: "Fallback detection",
136
- };
137
- }
138
- }
139
- export class Cache {
140
- cache;
141
- statsData = {
142
- hits: 0,
143
- misses: 0,
144
- cacheErrors: 0,
145
- nonCacheErrors: 0,
146
- };
147
- constructor(options = {}) {
148
- const { ttl = 3600, // 1 hour default
149
- maxSize = 100, // 100 keys max
150
- checkPeriod = 600, // Check every 10 minutes
151
- } = options;
152
- this.cache = new NodeCache({
153
- stdTTL: ttl,
154
- maxKeys: maxSize,
155
- checkperiod: checkPeriod,
156
- useClones: false,
157
- deleteOnExpire: true,
158
- });
159
- this.cache.on("set", (key, _value) => {
160
- logger.debug(`Cache SET: ${key}`);
161
- });
162
- this.cache.on("expired", (key, _value) => {
163
- logger.debug(`Cache EXPIRED: ${key}`);
164
- });
165
- this.cache.on("del", (key, _value) => {
166
- logger.debug(`Cache DELETE: ${key}`);
167
- });
168
- }
169
- /**
170
- * Get value from cache with resilient error handling
171
- */
172
- get(key) {
173
- try {
174
- const value = this.cache.get(key);
175
- if (value !== undefined) {
176
- this.statsData.hits++;
177
- logger.debug(`Cache HIT: ${key}`);
178
- return value;
179
- }
180
- else {
181
- this.statsData.misses++;
182
- logger.debug(`Cache MISS: ${key}`);
183
- return undefined;
184
- }
185
- }
186
- catch (error) {
187
- this.statsData.misses++;
188
- logger.warn(`Cache GET error for ${key}, treating as miss:`, error);
189
- return undefined;
190
- }
191
- }
192
- /**
193
- * Set value in cache with optional TTL
194
- */
195
- set(key, value, ttl) {
196
- try {
197
- const success = this.cache.set(key, value, ttl || 0);
198
- if (success) {
199
- logger.debug(`Cache SET successful: ${key}`);
200
- }
201
- else {
202
- logger.warn(`Cache SET failed: ${key}`);
203
- }
204
- return success;
205
- }
206
- catch (error) {
207
- logger.error(`Cache SET error: ${key}`, error);
208
- return false;
209
- }
210
- }
211
- /**
212
- * Delete key from cache
213
- */
214
- del(key) {
215
- const deleted = this.cache.del(key);
216
- logger.debug(`Cache DELETE: ${key}, deleted: ${deleted}`);
217
- return deleted;
218
- }
219
- /**
220
- * Check if key exists in cache
221
- */
222
- has(key) {
223
- return this.cache.has(key);
224
- }
225
- /**
226
- * Clear all cache entries
227
- */
228
- clear() {
229
- this.cache.flushAll();
230
- this.statsData.hits = 0;
231
- this.statsData.misses = 0;
232
- logger.debug("Cache cleared");
233
- }
234
- /**
235
- * Get all cache keys
236
- */
237
- keys() {
238
- return this.cache.keys();
239
- }
240
- /**
241
- * Get cache statistics
242
- */
243
- stats() {
244
- return {
245
- hits: this.statsData.hits,
246
- misses: this.statsData.misses,
247
- keys: this.cache.keys().length,
248
- size: this.cache.getStats().keys,
249
- cacheErrors: this.statsData.cacheErrors,
250
- nonCacheErrors: this.statsData.nonCacheErrors,
251
- };
252
- }
253
- /**
254
- * Get detailed cache statistics from node-cache
255
- */
256
- getDetailedStats() {
257
- return this.cache.getStats();
258
- }
259
- /**
260
- * Get or set pattern with automatic fallback on cache failures
261
- */
262
- async getOrSet(key, fetchFn, ttl) {
263
- // Try to get from cache with resilient error handling
264
- const cached = this.get(key);
265
- if (cached !== undefined) {
266
- return cached;
267
- }
268
- try {
269
- logger.debug(`Cache FETCH: ${key}`);
270
- const value = await fetchFn();
271
- // Try to cache the result, but don't fail if caching fails
272
- try {
273
- this.set(key, value, ttl);
274
- }
275
- catch (cacheError) {
276
- logger.warn(`Cache SET failed for ${key}, continuing without cache:`, cacheError);
277
- }
278
- return value;
279
- }
280
- catch (error) {
281
- logger.error(`Cache FETCH error: ${key}`, error);
282
- throw error;
283
- }
284
- }
285
- /**
286
- * Resilient get or set pattern that bypasses cache entirely on cache system failures
287
- */
288
- async getOrSetResilient(key, fetchFn, ttl) {
289
- try {
290
- // Try normal cache flow first
291
- return await this.getOrSet(key, fetchFn, ttl);
292
- }
293
- catch (error) {
294
- // Use enhanced error detection to determine if this is a cache-related error
295
- const errorClassification = CacheErrorDetector.classifyError(error, "getOrSet", key);
296
- if (errorClassification.isCache) {
297
- // Track cache error statistics
298
- this.statsData.cacheErrors++;
299
- logger.warn(`Cache system error detected for ${key} (${errorClassification.confidence} confidence: ${errorClassification.reason}), bypassing cache entirely`, {
300
- error: error instanceof Error ? error.message : String(error),
301
- category: errorClassification.category,
302
- confidence: errorClassification.confidence,
303
- key,
304
- operation: "getOrSet",
305
- });
306
- // Bypass cache completely and just fetch the data
307
- return await fetchFn();
308
- }
309
- // Track non-cache errors for debugging
310
- this.statsData.nonCacheErrors++;
311
- // Re-throw non-cache errors
312
- throw error;
313
- }
314
- }
315
- /**
316
- * Cache with tags for group invalidation
317
- */
318
- tags = new Map();
319
- setWithTags(key, value, tags, ttl) {
320
- const success = this.set(key, value, ttl);
321
- if (success) {
322
- // Associate key with tags
323
- tags.forEach((tag) => {
324
- if (!this.tags.has(tag)) {
325
- this.tags.set(tag, new Set());
326
- }
327
- this.tags.get(tag).add(key);
328
- });
329
- }
330
- return success;
331
- }
332
- /**
333
- * Invalidate all keys with a specific tag
334
- */
335
- invalidateTag(tag) {
336
- const keys = this.tags.get(tag);
337
- if (!keys) {
338
- return 0;
339
- }
340
- let deleted = 0;
341
- keys.forEach((key) => {
342
- deleted += this.del(key);
343
- });
344
- // Clean up tag associations
345
- this.tags.delete(tag);
346
- logger.debug(`Invalidated tag "${tag}": ${deleted} keys`);
347
- return deleted;
348
- }
349
- /**
350
- * Invalidate all keys matching a pattern
351
- */
352
- invalidatePattern(pattern) {
353
- const regex = new RegExp(pattern.replace(/\*/g, ".*"));
354
- const allKeys = this.keys();
355
- let deleted = 0;
356
- allKeys.forEach((key) => {
357
- if (regex.test(key)) {
358
- deleted += this.del(key);
359
- }
360
- });
361
- logger.debug(`Invalidated pattern "${pattern}": ${deleted} keys`);
362
- return deleted;
363
- }
364
- /**
365
- * Cache key generators for common patterns
366
- */
367
- static keys = {
368
- prInfo: (workspace, repository, prId) => `pr:${workspace}:${repository}:${prId}`,
369
- prDiff: (workspace, repository, prId) => `diff:${workspace}:${repository}:${prId}`,
370
- fileContent: (workspace, repository, filePath, branch) => `file:${workspace}:${repository}:${branch}:${filePath}`,
371
- directoryContent: (workspace, repository, path, branch) => `dir:${workspace}:${repository}:${branch}:${path}`,
372
- branchInfo: (workspace, repository, branch) => `branch:${workspace}:${repository}:${branch}`,
373
- aiResponse: (prompt, provider, model) => {
374
- // Create a hash of the prompt for consistent keys
375
- const hash = Buffer.from(prompt).toString("base64").slice(0, 16);
376
- return `ai:${provider}:${model}:${hash}`;
377
- },
378
- projectContext: (workspace, repository, branch) => `context:${workspace}:${repository}:${branch}`,
379
- reviewResult: (workspace, repository, prId, configHash) => `review:${workspace}:${repository}:${prId}:${configHash}`,
380
- memoryBankFiles: (workspace, repository, branch, path) => `memory-bank:${workspace}:${repository}:${branch}:${path}`,
381
- };
382
- /**
383
- * Smart cache warming for common patterns
384
- */
385
- async warmPRCache(workspace, repository, prId) {
386
- logger.debug(`Warming cache for PR ${workspace}/${repository}#${prId}`);
387
- // Pre-generate cache keys that are likely to be needed
388
- const keys = [
389
- Cache.keys.prInfo(workspace, repository, prId),
390
- Cache.keys.prDiff(workspace, repository, prId),
391
- ];
392
- // This would be implemented by the calling code to actually fetch the data
393
- logger.debug(`Cache warming prepared for keys: ${keys.join(", ")}`);
394
- }
395
- /**
396
- * Cleanup expired entries and optimize memory
397
- */
398
- cleanup() {
399
- // Node-cache handles TTL cleanup automatically, but we can force it
400
- const beforeKeys = this.cache.keys().length;
401
- // Force check for expired keys
402
- this.cache.keys().forEach((key) => {
403
- this.cache.get(key); // This triggers expiry check
404
- });
405
- const afterKeys = this.cache.keys().length;
406
- const cleaned = beforeKeys - afterKeys;
407
- if (cleaned > 0) {
408
- logger.debug(`Cache cleanup: removed ${cleaned} expired entries`);
409
- }
410
- // Clean up tag associations for deleted keys
411
- this.tags.forEach((keys, tag) => {
412
- const validKeys = new Set(Array.from(keys).filter((key) => this.cache.has(key)));
413
- if (validKeys.size !== keys.size) {
414
- this.tags.set(tag, validKeys);
415
- }
416
- });
417
- }
418
- /**
419
- * Get cache hit ratio
420
- */
421
- getHitRatio() {
422
- const total = this.statsData.hits + this.statsData.misses;
423
- return total > 0 ? this.statsData.hits / total : 0;
424
- }
425
- /**
426
- * Export cache state for debugging
427
- */
428
- debug() {
429
- return {
430
- stats: this.stats(),
431
- hitRatio: this.getHitRatio(),
432
- detailedStats: this.getDetailedStats(),
433
- keys: this.keys(),
434
- tags: Object.fromEntries(this.tags.entries()),
435
- };
436
- }
437
- }
438
- // Export singleton instance
439
- export const cache = new Cache();
440
- // Export factory function
441
- export function createCache(options) {
442
- return new Cache(options);
443
- }
444
- //# sourceMappingURL=Cache.js.map