@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,590 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Enhanced Configuration Manager for Yama
|
|
4
|
+
* Handles configuration loading, validation, and merging from multiple sources
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.configManager = exports.ConfigManager = void 0;
|
|
11
|
+
exports.createConfigManager = createConfigManager;
|
|
12
|
+
const fs_1 = __importDefault(require("fs"));
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
const yaml_1 = __importDefault(require("yaml"));
|
|
15
|
+
const types_1 = require("../types");
|
|
16
|
+
const Logger_1 = require("./Logger");
|
|
17
|
+
class ConfigManager {
|
|
18
|
+
constructor() {
|
|
19
|
+
this.config = null;
|
|
20
|
+
this.configPaths = [];
|
|
21
|
+
this.setupConfigPaths();
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Setup configuration file search paths
|
|
25
|
+
*/
|
|
26
|
+
setupConfigPaths() {
|
|
27
|
+
const cwd = process.cwd();
|
|
28
|
+
const homeDir = require("os").homedir();
|
|
29
|
+
this.configPaths = [
|
|
30
|
+
path_1.default.join(cwd, "yama.config.yaml"),
|
|
31
|
+
path_1.default.join(cwd, "yama.config.yml"),
|
|
32
|
+
path_1.default.join(cwd, "yama.config.json"),
|
|
33
|
+
path_1.default.join(cwd, ".yama.yaml"),
|
|
34
|
+
path_1.default.join(cwd, ".yama.yml"),
|
|
35
|
+
path_1.default.join(cwd, ".yama.json"),
|
|
36
|
+
path_1.default.join(homeDir, ".yama", "config.yaml"),
|
|
37
|
+
path_1.default.join(homeDir, ".yama", "config.yml"),
|
|
38
|
+
path_1.default.join(homeDir, ".yama", "config.json"),
|
|
39
|
+
path_1.default.join(homeDir, ".config", "yama", "config.yaml"),
|
|
40
|
+
path_1.default.join(homeDir, ".config", "yama", "config.yml"),
|
|
41
|
+
path_1.default.join(homeDir, ".config", "yama", "config.json"),
|
|
42
|
+
];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Load configuration from files and environment
|
|
46
|
+
*/
|
|
47
|
+
async loadConfig(configPath) {
|
|
48
|
+
if (this.config) {
|
|
49
|
+
return this.config;
|
|
50
|
+
}
|
|
51
|
+
Logger_1.logger.debug("Loading Yama configuration...");
|
|
52
|
+
// Start with default config
|
|
53
|
+
let config = this.deepClone(ConfigManager.DEFAULT_CONFIG);
|
|
54
|
+
// If specific config path provided, use only that
|
|
55
|
+
if (configPath) {
|
|
56
|
+
if (!fs_1.default.existsSync(configPath)) {
|
|
57
|
+
throw new types_1.ConfigurationError(`Configuration file not found: ${configPath}`);
|
|
58
|
+
}
|
|
59
|
+
const fileConfig = await this.loadConfigFile(configPath);
|
|
60
|
+
config = this.mergeConfigs(config, fileConfig);
|
|
61
|
+
Logger_1.logger.debug(`Loaded configuration from: ${configPath}`);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
// Search for config files in predefined paths
|
|
65
|
+
for (const configFilePath of this.configPaths) {
|
|
66
|
+
if (fs_1.default.existsSync(configFilePath)) {
|
|
67
|
+
try {
|
|
68
|
+
const fileConfig = await this.loadConfigFile(configFilePath);
|
|
69
|
+
config = this.mergeConfigs(config, fileConfig);
|
|
70
|
+
Logger_1.logger.debug(`Loaded configuration from: ${configFilePath}`);
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
Logger_1.logger.warn(`Failed to load config from ${configFilePath}:`, error);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Override with environment variables
|
|
80
|
+
config = this.applyEnvironmentOverrides(config);
|
|
81
|
+
// Validate configuration
|
|
82
|
+
this.validateConfig(config);
|
|
83
|
+
this.config = config;
|
|
84
|
+
Logger_1.logger.debug("Configuration loaded successfully");
|
|
85
|
+
return config;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Load configuration from a specific file
|
|
89
|
+
*/
|
|
90
|
+
async loadConfigFile(filePath) {
|
|
91
|
+
try {
|
|
92
|
+
const content = fs_1.default.readFileSync(filePath, "utf8");
|
|
93
|
+
const ext = path_1.default.extname(filePath).toLowerCase();
|
|
94
|
+
switch (ext) {
|
|
95
|
+
case ".yaml":
|
|
96
|
+
case ".yml":
|
|
97
|
+
return yaml_1.default.parse(content);
|
|
98
|
+
case ".json":
|
|
99
|
+
return JSON.parse(content);
|
|
100
|
+
default:
|
|
101
|
+
throw new types_1.ConfigurationError(`Unsupported config file format: ${ext}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
throw new types_1.ConfigurationError(`Failed to parse config file ${filePath}: ${error.message}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Apply environment variable overrides
|
|
110
|
+
*/
|
|
111
|
+
applyEnvironmentOverrides(config) {
|
|
112
|
+
const env = process.env;
|
|
113
|
+
// AI Provider overrides
|
|
114
|
+
if (env.AI_PROVIDER) {
|
|
115
|
+
config.providers.ai.provider = env.AI_PROVIDER;
|
|
116
|
+
}
|
|
117
|
+
if (env.AI_MODEL) {
|
|
118
|
+
config.providers.ai.model = env.AI_MODEL;
|
|
119
|
+
}
|
|
120
|
+
if (env.AI_TIMEOUT) {
|
|
121
|
+
config.providers.ai.timeout = env.AI_TIMEOUT;
|
|
122
|
+
}
|
|
123
|
+
if (env.AI_TEMPERATURE) {
|
|
124
|
+
config.providers.ai.temperature = parseFloat(env.AI_TEMPERATURE);
|
|
125
|
+
}
|
|
126
|
+
if (env.AI_MAX_TOKENS) {
|
|
127
|
+
config.providers.ai.maxTokens = parseInt(env.AI_MAX_TOKENS);
|
|
128
|
+
}
|
|
129
|
+
// Git Provider overrides
|
|
130
|
+
if (env.BITBUCKET_USERNAME) {
|
|
131
|
+
config.providers.git.credentials.username = env.BITBUCKET_USERNAME;
|
|
132
|
+
}
|
|
133
|
+
if (env.BITBUCKET_TOKEN) {
|
|
134
|
+
config.providers.git.credentials.token = env.BITBUCKET_TOKEN;
|
|
135
|
+
}
|
|
136
|
+
if (env.BITBUCKET_BASE_URL) {
|
|
137
|
+
config.providers.git.credentials.baseUrl = env.BITBUCKET_BASE_URL;
|
|
138
|
+
}
|
|
139
|
+
// Feature toggles
|
|
140
|
+
if (env.ENABLE_CODE_REVIEW !== undefined) {
|
|
141
|
+
config.features.codeReview.enabled = env.ENABLE_CODE_REVIEW === "true";
|
|
142
|
+
}
|
|
143
|
+
if (env.ENABLE_DESCRIPTION_ENHANCEMENT !== undefined) {
|
|
144
|
+
config.features.descriptionEnhancement.enabled =
|
|
145
|
+
env.ENABLE_DESCRIPTION_ENHANCEMENT === "true";
|
|
146
|
+
}
|
|
147
|
+
if (env.ENABLE_SECURITY_SCAN !== undefined) {
|
|
148
|
+
config.features.securityScan.enabled =
|
|
149
|
+
env.ENABLE_SECURITY_SCAN === "true";
|
|
150
|
+
}
|
|
151
|
+
if (env.ENABLE_ANALYTICS !== undefined) {
|
|
152
|
+
config.features.analytics.enabled = env.ENABLE_ANALYTICS === "true";
|
|
153
|
+
}
|
|
154
|
+
// Cache configuration
|
|
155
|
+
if (env.CACHE_ENABLED !== undefined) {
|
|
156
|
+
config.cache.enabled = env.CACHE_ENABLED === "true";
|
|
157
|
+
}
|
|
158
|
+
if (env.CACHE_TTL) {
|
|
159
|
+
config.cache.ttl = env.CACHE_TTL;
|
|
160
|
+
}
|
|
161
|
+
if (env.CACHE_STORAGE) {
|
|
162
|
+
config.cache.storage = env.CACHE_STORAGE;
|
|
163
|
+
}
|
|
164
|
+
// Debug mode
|
|
165
|
+
if (env.GUARDIAN_DEBUG === "true") {
|
|
166
|
+
Logger_1.logger.setLevel("debug");
|
|
167
|
+
Logger_1.logger.setVerbose(true);
|
|
168
|
+
}
|
|
169
|
+
Logger_1.logger.debug("Applied environment variable overrides");
|
|
170
|
+
return config;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Validate configuration
|
|
174
|
+
*/
|
|
175
|
+
validateConfig(config) {
|
|
176
|
+
const errors = [];
|
|
177
|
+
// Validate AI provider credentials
|
|
178
|
+
if (!config.providers.ai.provider) {
|
|
179
|
+
errors.push("AI provider must be specified");
|
|
180
|
+
}
|
|
181
|
+
// Validate Git provider credentials
|
|
182
|
+
if (!config.providers.git.credentials.username) {
|
|
183
|
+
errors.push("Git username must be specified");
|
|
184
|
+
}
|
|
185
|
+
if (!config.providers.git.credentials.token) {
|
|
186
|
+
errors.push("Git token must be specified");
|
|
187
|
+
}
|
|
188
|
+
// Validate enabled features have required configuration
|
|
189
|
+
if (config.features.codeReview.enabled) {
|
|
190
|
+
if (!config.features.codeReview.severityLevels?.length) {
|
|
191
|
+
errors.push("Code review severity levels must be specified when enabled");
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (config.features.descriptionEnhancement.enabled) {
|
|
195
|
+
if (!config.features.descriptionEnhancement.requiredSections?.length) {
|
|
196
|
+
errors.push("Description enhancement required sections must be specified when enabled");
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// Validate cache configuration
|
|
200
|
+
if (config.cache?.enabled) {
|
|
201
|
+
if (!config.cache.storage) {
|
|
202
|
+
errors.push("Cache storage type must be specified when cache is enabled");
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (errors.length > 0) {
|
|
206
|
+
throw new types_1.ConfigurationError(`Configuration validation failed:\n${errors.map((e) => ` - ${e}`).join("\n")}`);
|
|
207
|
+
}
|
|
208
|
+
Logger_1.logger.debug("Configuration validation passed");
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Merge two configuration objects deeply
|
|
212
|
+
*/
|
|
213
|
+
mergeConfigs(base, override) {
|
|
214
|
+
return this.deepMerge(base, override);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Deep merge utility
|
|
218
|
+
*/
|
|
219
|
+
deepMerge(target, source) {
|
|
220
|
+
const result = { ...target };
|
|
221
|
+
for (const key in source) {
|
|
222
|
+
if (source[key] !== null &&
|
|
223
|
+
typeof source[key] === "object" &&
|
|
224
|
+
!Array.isArray(source[key])) {
|
|
225
|
+
result[key] = this.deepMerge(target[key] || {}, source[key]);
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
result[key] = source[key];
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return result;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Deep clone utility
|
|
235
|
+
*/
|
|
236
|
+
deepClone(obj) {
|
|
237
|
+
return JSON.parse(JSON.stringify(obj));
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Get current configuration
|
|
241
|
+
*/
|
|
242
|
+
getConfig() {
|
|
243
|
+
if (!this.config) {
|
|
244
|
+
throw new types_1.ConfigurationError("Configuration not loaded. Call loadConfig() first.");
|
|
245
|
+
}
|
|
246
|
+
return this.config;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Create default configuration file
|
|
250
|
+
*/
|
|
251
|
+
async createDefaultConfig(outputPath) {
|
|
252
|
+
const defaultPath = outputPath || path_1.default.join(process.cwd(), "yama.config.yaml");
|
|
253
|
+
const configContent = yaml_1.default.stringify(ConfigManager.DEFAULT_CONFIG, {
|
|
254
|
+
indent: 2,
|
|
255
|
+
lineWidth: 100,
|
|
256
|
+
});
|
|
257
|
+
// Add comments to make the config file more user-friendly
|
|
258
|
+
const commentedConfig = this.addConfigComments(configContent);
|
|
259
|
+
fs_1.default.writeFileSync(defaultPath, commentedConfig, "utf8");
|
|
260
|
+
Logger_1.logger.info(`Default configuration created at: ${defaultPath}`);
|
|
261
|
+
return defaultPath;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Add helpful comments to configuration file
|
|
265
|
+
*/
|
|
266
|
+
addConfigComments(content) {
|
|
267
|
+
const header = `# Yama Configuration
|
|
268
|
+
# This file configures all aspects of Yama behavior
|
|
269
|
+
# For more information, visit: https://github.com/juspay/yama
|
|
270
|
+
|
|
271
|
+
`;
|
|
272
|
+
const sections = [
|
|
273
|
+
"# AI Provider Configuration",
|
|
274
|
+
"# Git Platform Configuration",
|
|
275
|
+
"# Feature Configuration",
|
|
276
|
+
"# Cache Configuration",
|
|
277
|
+
"# Performance Configuration",
|
|
278
|
+
"# Custom Rules Configuration",
|
|
279
|
+
"# Reporting Configuration",
|
|
280
|
+
];
|
|
281
|
+
let commented = header + content;
|
|
282
|
+
// Add section comments (this is a simplified approach)
|
|
283
|
+
sections.forEach((section) => {
|
|
284
|
+
const key = section.split(" ")[1].toLowerCase();
|
|
285
|
+
commented = commented.replace(new RegExp(`^(${key}:)`, "m"), `${section}\n$1`);
|
|
286
|
+
});
|
|
287
|
+
return commented;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Validate specific configuration section
|
|
291
|
+
*/
|
|
292
|
+
validateSection(section, config) {
|
|
293
|
+
try {
|
|
294
|
+
switch (section) {
|
|
295
|
+
case "providers":
|
|
296
|
+
return this.validateProviders(config);
|
|
297
|
+
case "features":
|
|
298
|
+
return this.validateFeatures(config);
|
|
299
|
+
case "cache":
|
|
300
|
+
return this.validateCache(config);
|
|
301
|
+
default:
|
|
302
|
+
return true;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
catch (error) {
|
|
306
|
+
Logger_1.logger.error(`Validation failed for section ${section}:`, error);
|
|
307
|
+
return false;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
validateProviders(providers) {
|
|
311
|
+
return !!(providers?.ai?.provider &&
|
|
312
|
+
providers?.git?.credentials?.username &&
|
|
313
|
+
providers?.git?.credentials?.token);
|
|
314
|
+
}
|
|
315
|
+
validateFeatures(features) {
|
|
316
|
+
return !!(features && typeof features === "object");
|
|
317
|
+
}
|
|
318
|
+
validateCache(cacheConfig) {
|
|
319
|
+
if (!cacheConfig?.enabled) {
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
return !!(cacheConfig.storage && cacheConfig.ttl);
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Get configuration schema for validation
|
|
326
|
+
*/
|
|
327
|
+
getSchema() {
|
|
328
|
+
return {
|
|
329
|
+
type: "object",
|
|
330
|
+
required: ["providers", "features"],
|
|
331
|
+
properties: {
|
|
332
|
+
providers: {
|
|
333
|
+
type: "object",
|
|
334
|
+
required: ["ai", "git"],
|
|
335
|
+
properties: {
|
|
336
|
+
ai: {
|
|
337
|
+
type: "object",
|
|
338
|
+
required: ["provider"],
|
|
339
|
+
properties: {
|
|
340
|
+
provider: { type: "string" },
|
|
341
|
+
model: { type: "string" },
|
|
342
|
+
enableFallback: { type: "boolean" },
|
|
343
|
+
enableAnalytics: { type: "boolean" },
|
|
344
|
+
timeout: { type: ["string", "number"] },
|
|
345
|
+
temperature: { type: "number", minimum: 0, maximum: 2 },
|
|
346
|
+
maxTokens: { type: "number", minimum: 1 },
|
|
347
|
+
},
|
|
348
|
+
},
|
|
349
|
+
git: {
|
|
350
|
+
type: "object",
|
|
351
|
+
required: ["platform", "credentials"],
|
|
352
|
+
properties: {
|
|
353
|
+
platform: {
|
|
354
|
+
type: "string",
|
|
355
|
+
enum: ["bitbucket", "github", "gitlab", "azure-devops"],
|
|
356
|
+
},
|
|
357
|
+
credentials: {
|
|
358
|
+
type: "object",
|
|
359
|
+
required: ["username", "token"],
|
|
360
|
+
properties: {
|
|
361
|
+
username: { type: "string" },
|
|
362
|
+
token: { type: "string" },
|
|
363
|
+
baseUrl: { type: "string" },
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
},
|
|
368
|
+
},
|
|
369
|
+
},
|
|
370
|
+
features: {
|
|
371
|
+
type: "object",
|
|
372
|
+
required: ["codeReview", "descriptionEnhancement"],
|
|
373
|
+
properties: {
|
|
374
|
+
codeReview: {
|
|
375
|
+
type: "object",
|
|
376
|
+
required: ["enabled"],
|
|
377
|
+
properties: {
|
|
378
|
+
enabled: { type: "boolean" },
|
|
379
|
+
severityLevels: { type: "array", items: { type: "string" } },
|
|
380
|
+
categories: { type: "array", items: { type: "string" } },
|
|
381
|
+
excludePatterns: { type: "array", items: { type: "string" } },
|
|
382
|
+
},
|
|
383
|
+
},
|
|
384
|
+
descriptionEnhancement: {
|
|
385
|
+
type: "object",
|
|
386
|
+
required: ["enabled"],
|
|
387
|
+
properties: {
|
|
388
|
+
enabled: { type: "boolean" },
|
|
389
|
+
preserveContent: { type: "boolean" },
|
|
390
|
+
requiredSections: { type: "array" },
|
|
391
|
+
autoFormat: { type: "boolean" },
|
|
392
|
+
},
|
|
393
|
+
},
|
|
394
|
+
},
|
|
395
|
+
},
|
|
396
|
+
},
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Find the first available configuration file
|
|
401
|
+
*/
|
|
402
|
+
findConfigFile() {
|
|
403
|
+
for (const configPath of this.configPaths) {
|
|
404
|
+
if (fs_1.default.existsSync(configPath)) {
|
|
405
|
+
return configPath;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
return null;
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Watch configuration file for changes and reload automatically
|
|
412
|
+
*/
|
|
413
|
+
watchConfig(callback) {
|
|
414
|
+
if (!this.configPaths.length) {
|
|
415
|
+
Logger_1.logger.warn("No configuration file found to watch");
|
|
416
|
+
return () => { };
|
|
417
|
+
}
|
|
418
|
+
const configPath = this.findConfigFile();
|
|
419
|
+
if (!configPath) {
|
|
420
|
+
Logger_1.logger.warn("No configuration file found to watch");
|
|
421
|
+
return () => { };
|
|
422
|
+
}
|
|
423
|
+
Logger_1.logger.debug(`Watching configuration file: ${configPath}`);
|
|
424
|
+
fs_1.default.watchFile(configPath, { interval: 1000 }, async () => {
|
|
425
|
+
try {
|
|
426
|
+
Logger_1.logger.info("Configuration file changed, reloading...");
|
|
427
|
+
const newConfig = await this.loadConfig();
|
|
428
|
+
if (callback) {
|
|
429
|
+
callback(newConfig);
|
|
430
|
+
}
|
|
431
|
+
Logger_1.logger.success("Configuration reloaded successfully");
|
|
432
|
+
}
|
|
433
|
+
catch (error) {
|
|
434
|
+
Logger_1.logger.error(`Failed to reload configuration: ${error.message}`);
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
// Return cleanup function
|
|
438
|
+
return () => {
|
|
439
|
+
fs_1.default.unwatchFile(configPath);
|
|
440
|
+
Logger_1.logger.debug("Stopped watching configuration file");
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Enable hot-reload for configuration
|
|
445
|
+
*/
|
|
446
|
+
enableHotReload(callback) {
|
|
447
|
+
return this.watchConfig(callback);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
exports.ConfigManager = ConfigManager;
|
|
451
|
+
/**
|
|
452
|
+
* Default configuration
|
|
453
|
+
*/
|
|
454
|
+
ConfigManager.DEFAULT_CONFIG = {
|
|
455
|
+
providers: {
|
|
456
|
+
ai: {
|
|
457
|
+
provider: "auto",
|
|
458
|
+
enableFallback: true,
|
|
459
|
+
enableAnalytics: false,
|
|
460
|
+
enableEvaluation: false,
|
|
461
|
+
timeout: "10m",
|
|
462
|
+
retryAttempts: 3,
|
|
463
|
+
temperature: 0.3,
|
|
464
|
+
maxTokens: 1000000,
|
|
465
|
+
},
|
|
466
|
+
git: {
|
|
467
|
+
platform: "bitbucket",
|
|
468
|
+
credentials: {
|
|
469
|
+
username: process.env.BITBUCKET_USERNAME || "",
|
|
470
|
+
token: process.env.BITBUCKET_TOKEN || "",
|
|
471
|
+
baseUrl: process.env.BITBUCKET_BASE_URL ||
|
|
472
|
+
"https://your-bitbucket-server.com",
|
|
473
|
+
},
|
|
474
|
+
},
|
|
475
|
+
},
|
|
476
|
+
features: {
|
|
477
|
+
codeReview: {
|
|
478
|
+
enabled: true,
|
|
479
|
+
severityLevels: ["CRITICAL", "MAJOR", "MINOR", "SUGGESTION"],
|
|
480
|
+
categories: [
|
|
481
|
+
"security",
|
|
482
|
+
"performance",
|
|
483
|
+
"maintainability",
|
|
484
|
+
"functionality",
|
|
485
|
+
"error_handling",
|
|
486
|
+
"testing",
|
|
487
|
+
],
|
|
488
|
+
excludePatterns: ["*.lock", "*.svg", "*.min.js", "*.map"],
|
|
489
|
+
contextLines: 3,
|
|
490
|
+
systemPrompt: "You are an Expert Security Code Reviewer for enterprise applications. Your role is to:\n\n๐ SECURITY FIRST: Prioritize security vulnerabilities and data protection\nโก PERFORMANCE AWARE: Identify performance bottlenecks and optimization opportunities\n๐๏ธ QUALITY FOCUSED: Ensure maintainable, readable, and robust code\n๐ก๏ธ ERROR RESILIENT: Verify comprehensive error handling and edge cases\n\nYou provide actionable, educational feedback with specific examples and solutions.\nFocus on critical issues that could impact production systems.",
|
|
491
|
+
focusAreas: [
|
|
492
|
+
"๐ Security Analysis (CRITICAL PRIORITY)",
|
|
493
|
+
"โก Performance Review",
|
|
494
|
+
"๐๏ธ Code Quality",
|
|
495
|
+
"๐งช Testing & Error Handling",
|
|
496
|
+
],
|
|
497
|
+
},
|
|
498
|
+
descriptionEnhancement: {
|
|
499
|
+
enabled: true,
|
|
500
|
+
preserveContent: true,
|
|
501
|
+
requiredSections: [
|
|
502
|
+
{
|
|
503
|
+
key: "changelog",
|
|
504
|
+
name: "Changelog (Modules Modified)",
|
|
505
|
+
required: true,
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
key: "testcases",
|
|
509
|
+
name: "Test Cases (What to be tested)",
|
|
510
|
+
required: true,
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
key: "config_changes",
|
|
514
|
+
name: "CAC Config Or Service Config Changes",
|
|
515
|
+
required: true,
|
|
516
|
+
},
|
|
517
|
+
],
|
|
518
|
+
autoFormat: true,
|
|
519
|
+
systemPrompt: "You are an Expert Technical Writer specializing in pull request documentation. Your role is to:\n\n๐ CLARITY FIRST: Create clear, comprehensive PR descriptions that help reviewers understand the changes\n๐ฅ STORY TELLING: Explain the 'why' behind changes, not just the 'what'\n๐ STRUCTURED: Follow consistent formatting with required sections\n๐ CONTEXTUAL: Link changes to business value and technical rationale\n\nCRITICAL INSTRUCTION: Return ONLY the enhanced PR description content as clean markdown. Do NOT include any meta-commentary, explanations about what you're doing, or introductory text like \"I will enhance...\" or \"Here is the enhanced description:\". \n\nOutput the enhanced description directly without any wrapper text or explanations.",
|
|
520
|
+
outputTemplate: "# PR Title Enhancement (if needed)\n\n## Summary\n[Clear overview of what this PR accomplishes]\n\n## Changes Made\n[Specific technical changes - be precise]\n\n## Testing\n[How the changes were tested]\n\n## Impact\n[Business/technical impact and considerations]\n\n## Additional Notes\n[Any deployment notes, follow-ups, or special considerations]",
|
|
521
|
+
enhancementInstructions: 'Return ONLY the enhanced PR description as clean markdown. Do NOT include any explanatory text, meta-commentary, or phrases like "Here is the enhanced description:" or "I will enhance...".\n\nStart directly with the enhanced description content using this structure:',
|
|
522
|
+
},
|
|
523
|
+
securityScan: {
|
|
524
|
+
enabled: true,
|
|
525
|
+
level: "strict",
|
|
526
|
+
scanTypes: ["secrets", "vulnerabilities", "dependencies"],
|
|
527
|
+
},
|
|
528
|
+
analytics: {
|
|
529
|
+
enabled: true,
|
|
530
|
+
trackMetrics: true,
|
|
531
|
+
exportFormat: "json",
|
|
532
|
+
},
|
|
533
|
+
},
|
|
534
|
+
cache: {
|
|
535
|
+
enabled: true,
|
|
536
|
+
ttl: "1h",
|
|
537
|
+
maxSize: "100MB",
|
|
538
|
+
storage: "memory",
|
|
539
|
+
},
|
|
540
|
+
performance: {
|
|
541
|
+
batch: {
|
|
542
|
+
enabled: true,
|
|
543
|
+
maxConcurrent: 5,
|
|
544
|
+
delayBetween: "1s",
|
|
545
|
+
},
|
|
546
|
+
optimization: {
|
|
547
|
+
reuseConnections: true,
|
|
548
|
+
compressRequests: true,
|
|
549
|
+
enableHttp2: true,
|
|
550
|
+
},
|
|
551
|
+
},
|
|
552
|
+
rules: {
|
|
553
|
+
security: [
|
|
554
|
+
{
|
|
555
|
+
name: "No hardcoded secrets",
|
|
556
|
+
pattern: "(password|secret|key|token)\\s*[=:]\\s*['\"][^'\"]{8,}['\"]",
|
|
557
|
+
severity: "CRITICAL",
|
|
558
|
+
message: "Hardcoded secrets detected",
|
|
559
|
+
suggestion: "Use environment variables or secure configuration management",
|
|
560
|
+
},
|
|
561
|
+
],
|
|
562
|
+
performance: [
|
|
563
|
+
{
|
|
564
|
+
name: "Avoid N+1 queries",
|
|
565
|
+
pattern: "for.*\\.(find|get|query|select)",
|
|
566
|
+
severity: "MAJOR",
|
|
567
|
+
message: "Potential N+1 query pattern detected",
|
|
568
|
+
suggestion: "Consider using batch queries or joins",
|
|
569
|
+
},
|
|
570
|
+
],
|
|
571
|
+
},
|
|
572
|
+
reporting: {
|
|
573
|
+
formats: ["markdown", "json"],
|
|
574
|
+
includeAnalytics: true,
|
|
575
|
+
includeMetrics: true,
|
|
576
|
+
},
|
|
577
|
+
monitoring: {
|
|
578
|
+
enabled: true,
|
|
579
|
+
metrics: ["performance", "cache", "api_calls"],
|
|
580
|
+
exportFormat: "json",
|
|
581
|
+
interval: "5m",
|
|
582
|
+
},
|
|
583
|
+
};
|
|
584
|
+
// Export singleton instance
|
|
585
|
+
exports.configManager = new ConfigManager();
|
|
586
|
+
// Export factory function
|
|
587
|
+
function createConfigManager() {
|
|
588
|
+
return new ConfigManager();
|
|
589
|
+
}
|
|
590
|
+
//# sourceMappingURL=ConfigManager.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Logger utility - Optimized from both pr-police.js and pr-describe.js
|
|
3
|
+
* Provides consistent logging across all Guardian operations
|
|
4
|
+
*/
|
|
5
|
+
import { Logger as ILogger, LogLevel, LoggerOptions } from "../types";
|
|
6
|
+
export declare class Logger implements ILogger {
|
|
7
|
+
private options;
|
|
8
|
+
constructor(options?: Partial<LoggerOptions>);
|
|
9
|
+
private shouldLog;
|
|
10
|
+
private formatMessage;
|
|
11
|
+
private colorize;
|
|
12
|
+
debug(message: string, ...args: any[]): void;
|
|
13
|
+
info(message: string, ...args: any[]): void;
|
|
14
|
+
warn(message: string, ...args: any[]): void;
|
|
15
|
+
error(message: string, ...args: any[]): void;
|
|
16
|
+
badge(): void;
|
|
17
|
+
phase(message: string): void;
|
|
18
|
+
success(message: string): void;
|
|
19
|
+
operation(operation: string, status: "started" | "completed" | "failed"): void;
|
|
20
|
+
violation(severity: string, message: string, file?: string): void;
|
|
21
|
+
progress(current: number, total: number, operation: string): void;
|
|
22
|
+
private createProgressBar;
|
|
23
|
+
child(context: Record<string, any>): Logger;
|
|
24
|
+
setLevel(level: LogLevel): void;
|
|
25
|
+
setVerbose(verbose: boolean): void;
|
|
26
|
+
getConfig(): LoggerOptions;
|
|
27
|
+
}
|
|
28
|
+
export declare const logger: Logger;
|
|
29
|
+
export declare function createLogger(options?: Partial<LoggerOptions>): Logger;
|
|
30
|
+
//# sourceMappingURL=Logger.d.ts.map
|