@juspay/yama 2.2.1 → 2.3.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 (35) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/LICENSE +21 -0
  3. package/README.md +73 -110
  4. package/dist/cli/cli.d.ts +13 -0
  5. package/dist/cli/cli.js +341 -0
  6. package/dist/cli/v2.cli.d.ts +2 -11
  7. package/dist/cli/v2.cli.js +4 -354
  8. package/dist/index.d.ts +7 -5
  9. package/dist/index.js +5 -3
  10. package/dist/v2/config/ConfigLoader.d.ts +20 -5
  11. package/dist/v2/config/ConfigLoader.js +76 -24
  12. package/dist/v2/config/DefaultConfig.d.ts +3 -3
  13. package/dist/v2/config/DefaultConfig.js +9 -2
  14. package/dist/v2/core/LearningOrchestrator.d.ts +1 -0
  15. package/dist/v2/core/LearningOrchestrator.js +64 -4
  16. package/dist/v2/core/LocalDiffSource.d.ts +26 -0
  17. package/dist/v2/core/LocalDiffSource.js +129 -0
  18. package/dist/v2/core/MCPServerManager.d.ts +13 -1
  19. package/dist/v2/core/MCPServerManager.js +111 -7
  20. package/dist/v2/core/SessionManager.d.ts +1 -1
  21. package/dist/v2/core/SessionManager.js +3 -3
  22. package/dist/v2/core/YamaV2Orchestrator.d.ts +48 -13
  23. package/dist/v2/core/YamaV2Orchestrator.js +543 -63
  24. package/dist/v2/learning/types.d.ts +10 -0
  25. package/dist/v2/memory/MemoryManager.d.ts +57 -0
  26. package/dist/v2/memory/MemoryManager.js +185 -0
  27. package/dist/v2/prompts/PromptBuilder.d.ts +10 -4
  28. package/dist/v2/prompts/PromptBuilder.js +94 -3
  29. package/dist/v2/prompts/ReviewSystemPrompt.d.ts +1 -1
  30. package/dist/v2/prompts/ReviewSystemPrompt.js +7 -5
  31. package/dist/v2/types/config.types.d.ts +61 -1
  32. package/dist/v2/types/v2.types.d.ts +66 -5
  33. package/dist/v2/types/v2.types.js +8 -6
  34. package/package.json +20 -15
  35. package/yama.config.example.yaml +23 -5
@@ -1,359 +1,9 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * Yama V2 CLI - AI-Native Code Review Interface
4
- * Command-line interface for autonomous AI-powered code review
5
- */
6
- import { Command } from "commander";
7
- import dotenv from "dotenv";
8
- import { createYamaV2 } from "../v2/core/YamaV2Orchestrator.js";
9
- import { createLearningOrchestrator } from "../v2/core/LearningOrchestrator.js";
10
- // Load environment variables
11
- dotenv.config();
12
- const program = new Command();
13
- /**
14
- * Setup V2 CLI
15
- */
16
- export function setupV2CLI() {
17
- program
18
- .name("yama")
19
- .description("Yama - AI-Native Autonomous Code Review")
20
- .version("2.0.0");
21
- // Global options
22
- program
23
- .option("-v, --verbose", "Enable verbose output")
24
- .option("-c, --config <path>", "Path to configuration file")
25
- .option("--dry-run", "Dry run mode - no actual changes")
26
- .option("--no-banner", "Hide Yama banner");
27
- // Review command
28
- setupReviewCommand();
29
- // Enhance description command
30
- setupEnhanceCommand();
31
- // Learn from PR feedback command
32
- setupLearnCommand();
33
- // Init command
34
- setupInitCommand();
35
- // Migrate config command
36
- setupMigrateCommand();
37
- return program;
38
- }
39
- /**
40
- * Main review command
41
- * Reviews code and enhances description in one session
42
- */
43
- function setupReviewCommand() {
44
- program
45
- .command("review")
46
- .description("Review code and enhance PR description (uses same AI session)")
47
- .requiredOption("-w, --workspace <workspace>", "Bitbucket workspace")
48
- .requiredOption("-r, --repository <repository>", "Repository name")
49
- .option("-p, --pr <id>", "Pull request ID")
50
- .option("-b, --branch <branch>", "Branch name (finds PR automatically)")
51
- .option("--review-only", "Skip description enhancement, only review code")
52
- .action(async (options) => {
53
- try {
54
- const globalOpts = program.opts();
55
- // Validate required options
56
- if (!options.pr && !options.branch) {
57
- console.error("❌ Error: Either --pr or --branch must be specified");
58
- process.exit(1);
59
- }
60
- // Parse PR ID with validation
61
- let pullRequestId;
62
- if (options.pr) {
63
- pullRequestId = parseInt(options.pr, 10);
64
- if (isNaN(pullRequestId)) {
65
- console.error(`❌ Error: Invalid PR ID "${options.pr}" (must be a number)`);
66
- process.exit(1);
67
- }
68
- }
69
- const request = {
70
- workspace: options.workspace,
71
- repository: options.repository,
72
- pullRequestId,
73
- branch: options.branch,
74
- dryRun: globalOpts.dryRun || false,
75
- verbose: globalOpts.verbose || false,
76
- configPath: globalOpts.config,
77
- };
78
- // Create orchestrator
79
- const yama = createYamaV2();
80
- // Initialize
81
- await yama.initialize(request.configPath);
82
- // Start review (with or without description enhancement)
83
- console.log("🚀 Starting autonomous AI review...\n");
84
- const result = options.reviewOnly
85
- ? await yama.startReview(request)
86
- : await yama.startReviewAndEnhance(request);
87
- // Show results
88
- console.log("\n📊 Review Results:");
89
- console.log(` Decision: ${result.decision}`);
90
- console.log(` Files Reviewed: ${result.statistics.filesReviewed}`);
91
- console.log(` Total Comments: ${result.totalComments || result.statistics.totalComments || 0}`);
92
- if (result.descriptionEnhanced !== undefined) {
93
- console.log(` Description Enhanced: ${result.descriptionEnhanced ? "✅ Yes" : "⏭️ Skipped"}`);
94
- }
95
- console.log(` Duration: ${Math.round(result.duration / 1000)}s`);
96
- console.log(` Token Usage: ${result.tokenUsage.total.toLocaleString()} tokens`);
97
- if (globalOpts.verbose) {
98
- console.log("\n📄 Full Results:");
99
- console.log(JSON.stringify(result, null, 2));
100
- }
101
- // Exit with appropriate code
102
- if (result.decision === "BLOCKED") {
103
- process.exit(1);
104
- }
105
- else {
106
- process.exit(0);
107
- }
108
- }
109
- catch (error) {
110
- console.error("\n❌ Review failed:", error.message);
111
- if (error.stack && program.opts().verbose) {
112
- console.error("\nStack trace:");
113
- console.error(error.stack);
114
- }
115
- process.exit(1);
116
- }
117
- });
118
- }
119
- /**
120
- * Enhance description command
121
- */
122
- function setupEnhanceCommand() {
123
- program
124
- .command("enhance")
125
- .description("Enhance PR description using AI (without full review)")
126
- .requiredOption("-w, --workspace <workspace>", "Bitbucket workspace")
127
- .requiredOption("-r, --repository <repository>", "Repository name")
128
- .option("-p, --pr <id>", "Pull request ID")
129
- .option("-b, --branch <branch>", "Branch name")
130
- .action(async (options) => {
131
- try {
132
- const globalOpts = program.opts();
133
- if (!options.pr && !options.branch) {
134
- console.error("❌ Error: Either --pr or --branch must be specified");
135
- process.exit(1);
136
- }
137
- // Parse PR ID with validation
138
- let pullRequestId;
139
- if (options.pr) {
140
- pullRequestId = parseInt(options.pr, 10);
141
- if (isNaN(pullRequestId)) {
142
- console.error(`❌ Error: Invalid PR ID "${options.pr}" (must be a number)`);
143
- process.exit(1);
144
- }
145
- }
146
- const request = {
147
- workspace: options.workspace,
148
- repository: options.repository,
149
- pullRequestId,
150
- branch: options.branch,
151
- dryRun: globalOpts.dryRun || false,
152
- verbose: globalOpts.verbose || false,
153
- configPath: globalOpts.config,
154
- };
155
- const yama = createYamaV2();
156
- await yama.initialize(request.configPath);
157
- const result = await yama.enhanceDescription(request);
158
- console.log("\n✅ Description enhanced successfully");
159
- console.log(JSON.stringify(result, null, 2));
160
- process.exit(0);
161
- }
162
- catch (error) {
163
- console.error("\n❌ Enhancement failed:", error.message);
164
- process.exit(1);
165
- }
166
- });
167
- }
168
- /**
169
- * Learn from PR feedback command
170
- * Extracts learnings from merged PRs to improve future reviews
171
- */
172
- function setupLearnCommand() {
173
- program
174
- .command("learn")
175
- .description("Extract learnings from merged PR to improve future reviews")
176
- .requiredOption("-w, --workspace <workspace>", "Bitbucket workspace")
177
- .requiredOption("-r, --repository <repository>", "Repository name")
178
- .requiredOption("-p, --pr <id>", "Merged pull request ID")
179
- .option("--commit", "Auto-commit knowledge base changes to git")
180
- .option("--summarize", "Force summarization of knowledge base")
181
- .option("--output <path>", "Override knowledge base output path")
182
- .option("--format <format>", "Output format for dry-run preview (md|json)", "md")
183
- .action(async (options) => {
184
- try {
185
- const globalOpts = program.opts();
186
- // Parse and validate PR ID
187
- const pullRequestId = parseInt(options.pr, 10);
188
- if (isNaN(pullRequestId)) {
189
- console.error(`❌ Error: Invalid PR ID "${options.pr}" (must be a number)`);
190
- process.exit(1);
191
- }
192
- // Validate format option
193
- if (options.format && !["md", "json"].includes(options.format)) {
194
- console.error(`❌ Error: Invalid format "${options.format}" (must be md or json)`);
195
- process.exit(1);
196
- }
197
- const request = {
198
- workspace: options.workspace,
199
- repository: options.repository,
200
- pullRequestId,
201
- dryRun: globalOpts.dryRun || false,
202
- commit: options.commit || false,
203
- summarize: options.summarize || false,
204
- outputPath: options.output,
205
- outputFormat: options.format || "md",
206
- };
207
- // Create and initialize learning orchestrator
208
- const orchestrator = createLearningOrchestrator();
209
- await orchestrator.initialize(globalOpts.config);
210
- // Extract learnings
211
- const result = await orchestrator.extractLearnings(request);
212
- // Handle result
213
- if (!result.success) {
214
- console.error(`\n❌ Learning extraction failed: ${result.error}`);
215
- process.exit(1);
216
- }
217
- // Show final summary for live runs
218
- if (!globalOpts.dryRun && result.learningsAdded > 0) {
219
- console.log("\n🎉 Knowledge base updated successfully!");
220
- console.log(` Use 'yama review' to apply these learnings to future reviews.`);
221
- }
222
- process.exit(0);
223
- }
224
- catch (error) {
225
- console.error("\n❌ Learning extraction failed:", error.message);
226
- if (error.stack && program.opts().verbose) {
227
- console.error("\nStack trace:");
228
- console.error(error.stack);
229
- }
230
- process.exit(1);
231
- }
232
- });
233
- }
234
- /**
235
- * Initialize configuration command
236
- */
237
- function setupInitCommand() {
238
- program
239
- .command("init")
240
- .description("Initialize Yama configuration")
241
- .option("--interactive", "Interactive configuration setup")
242
- .action(async (options) => {
243
- try {
244
- console.log("\n⚔️ Yama Configuration Setup\n");
245
- if (options.interactive) {
246
- console.log("Interactive setup not yet implemented.");
247
- console.log("Please copy yama.config.example.yaml to yama.config.yaml");
248
- console.log("and edit it manually.\n");
249
- }
250
- else {
251
- console.log("Creating default configuration file...\n");
252
- const fs = await import("fs/promises");
253
- const path = await import("path");
254
- // Check if config already exists
255
- if (await fs
256
- .access("yama.config.yaml")
257
- .then(() => true)
258
- .catch(() => false)) {
259
- console.log("❌ yama.config.yaml already exists");
260
- console.log(" Remove it first or use a different location\n");
261
- process.exit(1);
262
- }
263
- // Copy example config
264
- const examplePath = path.join(process.cwd(), "yama.config.example.yaml");
265
- const targetPath = path.join(process.cwd(), "yama.config.yaml");
266
- if (await fs
267
- .access(examplePath)
268
- .then(() => true)
269
- .catch(() => false)) {
270
- await fs.copyFile(examplePath, targetPath);
271
- console.log("✅ Created yama.config.yaml from example");
272
- }
273
- else {
274
- console.log("⚠️ Example config not found, creating minimal config...");
275
- await fs.writeFile(targetPath, `version: 2
276
- configType: "yama-v2"
277
-
278
- ai:
279
- provider: "auto"
280
- model: "gemini-2.5-pro"
281
-
282
- mcpServers:
283
- jira:
284
- enabled: false
285
-
286
- review:
287
- enabled: true
288
-
289
- descriptionEnhancement:
290
- enabled: true
291
- `);
292
- console.log("✅ Created minimal yama.config.yaml");
293
- }
294
- console.log("\n📝 Next steps:");
295
- console.log(" 1. Edit yama.config.yaml with your settings");
296
- console.log(" 2. Set environment variables (BITBUCKET_*, JIRA_*)");
297
- console.log(" 3. Run: yama review --help\n");
298
- }
299
- process.exit(0);
300
- }
301
- catch (error) {
302
- console.error("\n❌ Initialization failed:", error.message);
303
- process.exit(1);
304
- }
305
- });
306
- }
307
- /**
308
- * Migrate V1 config to V2 format
309
- */
310
- function setupMigrateCommand() {
311
- program
312
- .command("migrate-config")
313
- .description("Migrate V1 configuration to V2 format")
314
- .option("-i, --input <file>", "Input V1 config file", "yama.v1.config.yaml")
315
- .option("-o, --output <file>", "Output V2 config file", "yama.config.yaml")
316
- .option("--force", "Overwrite existing output file")
317
- .action(async (options) => {
318
- try {
319
- const globalOpts = program.opts();
320
- console.log("\n🔄 Yama V1 → V2 Configuration Migration\n");
321
- // Use child_process to run the migration script
322
- const { spawn } = await import("child_process");
323
- const path = await import("path");
324
- const { fileURLToPath } = await import("url");
325
- const __filename = fileURLToPath(import.meta.url);
326
- const __dirname = path.dirname(__filename);
327
- const scriptPath = path.resolve(__dirname, "../../scripts/migrate-config.cjs");
328
- const args = ["--input", options.input, "--output", options.output];
329
- if (options.force) {
330
- args.push("--force");
331
- }
332
- if (globalOpts.dryRun) {
333
- args.push("--dry-run");
334
- }
335
- const child = spawn("node", [scriptPath, ...args], {
336
- stdio: "inherit",
337
- cwd: process.cwd(),
338
- });
339
- child.on("close", (code) => {
340
- process.exit(code || 0);
341
- });
342
- child.on("error", (err) => {
343
- console.error("❌ Failed to run migration script:", err.message);
344
- process.exit(1);
345
- });
346
- }
347
- catch (error) {
348
- console.error("\n❌ Migration failed:", error.message);
349
- process.exit(1);
350
- }
351
- });
352
- }
353
- // Only run if this is the main module
2
+ // Backward-compatible entrypoint.
3
+ import program, { setupCLI } from "./cli.js";
4
+ export { setupCLI, program as default };
354
5
  if (import.meta.url === `file://${process.argv[1]}`) {
355
- const cli = setupV2CLI();
6
+ const cli = setupCLI();
356
7
  cli.parse(process.argv);
357
8
  }
358
- export default program;
359
9
  //# sourceMappingURL=v2.cli.js.map
package/dist/index.d.ts CHANGED
@@ -2,14 +2,16 @@
2
2
  * Yama - AI-Native Code Review
3
3
  * Main export file
4
4
  */
5
- export { YamaV2Orchestrator, createYamaV2, } from "./v2/core/YamaV2Orchestrator.js";
5
+ export { YamaOrchestrator, createYama, YamaOrchestrator as YamaV2Orchestrator, createYama as createYamaV2, } from "./v2/core/YamaV2Orchestrator.js";
6
+ export { LearningOrchestrator, createLearningOrchestrator, } from "./v2/core/LearningOrchestrator.js";
6
7
  export { ConfigLoader } from "./v2/config/ConfigLoader.js";
7
8
  export { MCPServerManager } from "./v2/core/MCPServerManager.js";
8
9
  export { SessionManager } from "./v2/core/SessionManager.js";
9
10
  export { PromptBuilder } from "./v2/prompts/PromptBuilder.js";
10
- export type { ReviewRequest, ReviewResult, ReviewUpdate, ReviewSession, ReviewStatistics, IssuesBySeverity, TokenUsage, } from "./v2/types/v2.types.js";
11
- export type { YamaV2Config, AIConfig, MCPServersConfig, ReviewConfig, DescriptionEnhancementConfig, } from "./v2/types/config.types.js";
11
+ export { MemoryManager } from "./v2/memory/MemoryManager.js";
12
+ export type { LocalReviewFinding, LocalReviewRequest, LocalReviewResult, ReviewRequest, ReviewMode, ReviewResult, ReviewUpdate, ReviewSession, ReviewStatistics, IssuesBySeverity, TokenUsage, UnifiedReviewRequest, } from "./v2/types/v2.types.js";
13
+ export type { YamaConfig, YamaInitOptions, YamaConfig as YamaV2Config, AIConfig, MCPServersConfig, ReviewConfig, DescriptionEnhancementConfig, MemoryConfig, } from "./v2/types/config.types.js";
12
14
  export type { GetPullRequestResponse, GetPullRequestDiffResponse, GetIssueResponse, SearchCodeResponse, } from "./v2/types/mcp.types.js";
13
- export declare const VERSION = "2.0.0";
14
- export { createYamaV2 as default } from "./v2/core/YamaV2Orchestrator.js";
15
+ export declare const VERSION = "2.2.1";
16
+ export { createYama as default } from "./v2/core/YamaV2Orchestrator.js";
15
17
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -5,17 +5,19 @@
5
5
  // ============================================================================
6
6
  // Core Exports
7
7
  // ============================================================================
8
- export { YamaV2Orchestrator, createYamaV2, } from "./v2/core/YamaV2Orchestrator.js";
8
+ export { YamaOrchestrator, createYama, YamaOrchestrator as YamaV2Orchestrator, createYama as createYamaV2, } from "./v2/core/YamaV2Orchestrator.js";
9
+ export { LearningOrchestrator, createLearningOrchestrator, } from "./v2/core/LearningOrchestrator.js";
9
10
  export { ConfigLoader } from "./v2/config/ConfigLoader.js";
10
11
  export { MCPServerManager } from "./v2/core/MCPServerManager.js";
11
12
  export { SessionManager } from "./v2/core/SessionManager.js";
12
13
  export { PromptBuilder } from "./v2/prompts/PromptBuilder.js";
14
+ export { MemoryManager } from "./v2/memory/MemoryManager.js";
13
15
  // ============================================================================
14
16
  // Version Information
15
17
  // ============================================================================
16
- export const VERSION = "2.0.0";
18
+ export const VERSION = "2.2.1";
17
19
  // ============================================================================
18
20
  // Default Export
19
21
  // ============================================================================
20
- export { createYamaV2 as default } from "./v2/core/YamaV2Orchestrator.js";
22
+ export { createYama as default } from "./v2/core/YamaV2Orchestrator.js";
21
23
  //# sourceMappingURL=index.js.map
@@ -1,23 +1,23 @@
1
1
  /**
2
- * Multi-Layer Configuration Loader for Yama V2
2
+ * Multi-Layer Configuration Loader for Yama
3
3
  * Loads and merges configuration from multiple sources
4
4
  */
5
- import { YamaV2Config } from "../types/config.types.js";
5
+ import { YamaConfig } from "../types/config.types.js";
6
6
  export declare class ConfigLoader {
7
7
  private config;
8
8
  private configPath;
9
9
  /**
10
10
  * Load configuration from file with multi-layer support
11
11
  */
12
- loadConfig(configPath?: string): Promise<YamaV2Config>;
12
+ loadConfig(configPath?: string, instanceOverrides?: Partial<YamaConfig>): Promise<YamaConfig>;
13
13
  /**
14
14
  * Get current loaded configuration
15
15
  */
16
- getConfig(): YamaV2Config;
16
+ getConfig(): YamaConfig;
17
17
  /**
18
18
  * Validate configuration completeness and correctness
19
19
  */
20
- validate(): Promise<void>;
20
+ validate(mode?: "pr" | "local"): Promise<void>;
21
21
  /**
22
22
  * Resolve configuration file path
23
23
  */
@@ -42,6 +42,21 @@ export declare class ConfigLoader {
42
42
  * Apply environment variable overrides
43
43
  */
44
44
  private applyEnvironmentOverrides;
45
+ /**
46
+ * Apply memory-related environment variable overrides.
47
+ *
48
+ * Env vars (YAMA_MEMORY_*) take precedence over yaml config.
49
+ * If YAMA_MEMORY_ENABLED is set but no memory config exists in yaml,
50
+ * a default config is created so the other overrides have a target.
51
+ *
52
+ * Supported env vars:
53
+ * YAMA_MEMORY_ENABLED — "true" / "false"
54
+ * YAMA_MEMORY_STORAGE_PATH — e.g. "memory-bank/yama/memory"
55
+ * YAMA_MEMORY_MAX_WORDS — e.g. "200"
56
+ * YAMA_MEMORY_AUTO_COMMIT — "true" / "false"
57
+ * YAMA_MEMORY_PROMPT — custom condensation prompt
58
+ */
59
+ private applyMemoryOverrides;
45
60
  /**
46
61
  * Basic configuration validation
47
62
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Multi-Layer Configuration Loader for Yama V2
2
+ * Multi-Layer Configuration Loader for Yama
3
3
  * Loads and merges configuration from multiple sources
4
4
  */
5
5
  import { readFile } from "fs/promises";
@@ -14,11 +14,14 @@ export class ConfigLoader {
14
14
  /**
15
15
  * Load configuration from file with multi-layer support
16
16
  */
17
- async loadConfig(configPath) {
18
- console.log("📋 Loading Yama V2 configuration...");
17
+ async loadConfig(configPath, instanceOverrides) {
18
+ console.log("📋 Loading Yama configuration...");
19
19
  // Layer 1: Start with default config
20
20
  let config = DefaultConfig.get();
21
- // Layer 2: Load from file if provided or search for default locations
21
+ // Layer 2: Apply environment variable overrides
22
+ // Lowest user-provided layer in SDK mode precedence.
23
+ config = this.applyEnvironmentOverrides(config);
24
+ // Layer 3: Load from file if provided or search for default locations
22
25
  const filePath = await this.resolveConfigPath(configPath);
23
26
  if (filePath) {
24
27
  console.log(` Reading config from: ${filePath}`);
@@ -29,8 +32,11 @@ export class ConfigLoader {
29
32
  else {
30
33
  console.log(" Using default configuration (no config file found)");
31
34
  }
32
- // Layer 3: Apply environment variable overrides
33
- config = this.applyEnvironmentOverrides(config);
35
+ config.memory = this.applyMemoryOverrides(config.memory);
36
+ // Layer 4: Apply SDK instance overrides (highest priority)
37
+ if (instanceOverrides) {
38
+ config = this.mergeConfigs(config, instanceOverrides);
39
+ }
34
40
  // Validate configuration
35
41
  this.validateConfig(config);
36
42
  this.config = config;
@@ -49,7 +55,7 @@ export class ConfigLoader {
49
55
  /**
50
56
  * Validate configuration completeness and correctness
51
57
  */
52
- async validate() {
58
+ async validate(mode = "pr") {
53
59
  if (!this.config) {
54
60
  throw new ConfigurationError("No configuration to validate");
55
61
  }
@@ -61,25 +67,28 @@ export class ConfigLoader {
61
67
  if (!this.config.ai.model) {
62
68
  errors.push("AI model not configured");
63
69
  }
64
- // Check environment variables for Bitbucket (always required)
65
- if (!process.env.BITBUCKET_USERNAME) {
66
- errors.push("BITBUCKET_USERNAME environment variable not set");
67
- }
68
- if (!process.env.BITBUCKET_TOKEN) {
69
- errors.push("BITBUCKET_TOKEN environment variable not set");
70
- }
71
- if (!process.env.BITBUCKET_BASE_URL) {
72
- errors.push("BITBUCKET_BASE_URL environment variable not set");
73
- }
74
- if (this.config.mcpServers.jira.enabled) {
75
- if (!process.env.JIRA_EMAIL) {
76
- errors.push("JIRA_EMAIL environment variable not set");
70
+ // Local mode is SDK-first and does not require MCP credentials.
71
+ if (mode === "pr") {
72
+ // Check environment variables for Bitbucket (required in PR mode)
73
+ if (!process.env.BITBUCKET_USERNAME) {
74
+ errors.push("BITBUCKET_USERNAME environment variable not set");
77
75
  }
78
- if (!process.env.JIRA_API_TOKEN) {
79
- errors.push("JIRA_API_TOKEN environment variable not set");
76
+ if (!process.env.BITBUCKET_TOKEN) {
77
+ errors.push("BITBUCKET_TOKEN environment variable not set");
80
78
  }
81
- if (!process.env.JIRA_BASE_URL) {
82
- errors.push("JIRA_BASE_URL environment variable not set");
79
+ if (!process.env.BITBUCKET_BASE_URL) {
80
+ errors.push("BITBUCKET_BASE_URL environment variable not set");
81
+ }
82
+ if (this.config.mcpServers.jira.enabled) {
83
+ if (!process.env.JIRA_EMAIL) {
84
+ errors.push("JIRA_EMAIL environment variable not set");
85
+ }
86
+ if (!process.env.JIRA_API_TOKEN) {
87
+ errors.push("JIRA_API_TOKEN environment variable not set");
88
+ }
89
+ if (!process.env.JIRA_BASE_URL) {
90
+ errors.push("JIRA_BASE_URL environment variable not set");
91
+ }
83
92
  }
84
93
  }
85
94
  if (errors.length > 0) {
@@ -179,8 +188,51 @@ export class ConfigLoader {
179
188
  if (process.env.AI_MAX_TOKENS) {
180
189
  config.ai.maxTokens = parseInt(process.env.AI_MAX_TOKENS, 10);
181
190
  }
191
+ if (process.env.AI_ENABLE_TOOL_FILTERING) {
192
+ config.ai.enableToolFiltering =
193
+ process.env.AI_ENABLE_TOOL_FILTERING === "true";
194
+ }
195
+ if (process.env.AI_TOOL_FILTERING_MODE) {
196
+ const mode = process.env.AI_TOOL_FILTERING_MODE;
197
+ if (mode === "off" || mode === "log-only" || mode === "active") {
198
+ config.ai.toolFilteringMode = mode;
199
+ }
200
+ }
182
201
  return config;
183
202
  }
203
+ /**
204
+ * Apply memory-related environment variable overrides.
205
+ *
206
+ * Env vars (YAMA_MEMORY_*) take precedence over yaml config.
207
+ * If YAMA_MEMORY_ENABLED is set but no memory config exists in yaml,
208
+ * a default config is created so the other overrides have a target.
209
+ *
210
+ * Supported env vars:
211
+ * YAMA_MEMORY_ENABLED — "true" / "false"
212
+ * YAMA_MEMORY_STORAGE_PATH — e.g. "memory-bank/yama/memory"
213
+ * YAMA_MEMORY_MAX_WORDS — e.g. "200"
214
+ * YAMA_MEMORY_AUTO_COMMIT — "true" / "false"
215
+ * YAMA_MEMORY_PROMPT — custom condensation prompt
216
+ */
217
+ applyMemoryOverrides(memory) {
218
+ const env = process.env;
219
+ if (env.YAMA_MEMORY_ENABLED) {
220
+ memory.enabled = env.YAMA_MEMORY_ENABLED === "true";
221
+ }
222
+ if (env.YAMA_MEMORY_STORAGE_PATH) {
223
+ memory.storagePath = env.YAMA_MEMORY_STORAGE_PATH;
224
+ }
225
+ if (env.YAMA_MEMORY_MAX_WORDS) {
226
+ memory.maxWords = parseInt(env.YAMA_MEMORY_MAX_WORDS, 10);
227
+ }
228
+ if (env.YAMA_MEMORY_AUTO_COMMIT) {
229
+ memory.autoCommit = env.YAMA_MEMORY_AUTO_COMMIT === "true";
230
+ }
231
+ if (env.YAMA_MEMORY_PROMPT) {
232
+ memory.prompt = env.YAMA_MEMORY_PROMPT;
233
+ }
234
+ return memory;
235
+ }
184
236
  /**
185
237
  * Basic configuration validation
186
238
  */
@@ -1,9 +1,9 @@
1
1
  /**
2
- * Default Configuration for Yama V2
2
+ * Default Configuration for Yama
3
3
  * Provides sensible defaults when no config file is present
4
4
  */
5
- import { YamaV2Config } from "../types/config.types.js";
5
+ import { YamaConfig } from "../types/config.types.js";
6
6
  export declare class DefaultConfig {
7
- static get(): YamaV2Config;
7
+ static get(): YamaConfig;
8
8
  }
9
9
  //# sourceMappingURL=DefaultConfig.d.ts.map
@@ -1,12 +1,12 @@
1
1
  /**
2
- * Default Configuration for Yama V2
2
+ * Default Configuration for Yama
3
3
  * Provides sensible defaults when no config file is present
4
4
  */
5
5
  export class DefaultConfig {
6
6
  static get() {
7
7
  return {
8
8
  version: 2,
9
- configType: "yama-v2",
9
+ configType: "yama",
10
10
  display: {
11
11
  showBanner: true,
12
12
  streamingMode: false,
@@ -22,6 +22,8 @@ export class DefaultConfig {
22
22
  enableEvaluation: false,
23
23
  timeout: "15m",
24
24
  retryAttempts: 3,
25
+ enableToolFiltering: false,
26
+ toolFilteringMode: "off",
25
27
  conversationMemory: {
26
28
  enabled: true,
27
29
  store: "memory",
@@ -156,6 +158,11 @@ export class DefaultConfig {
156
158
  summaryRetentionCount: 20,
157
159
  autoCommit: false,
158
160
  },
161
+ memory: {
162
+ enabled: false,
163
+ storagePath: ".yama/memory",
164
+ maxWords: 200,
165
+ },
159
166
  projectStandards: {
160
167
  customPromptsPath: "config/prompts/",
161
168
  additionalFocusAreas: [],
@@ -9,6 +9,7 @@ export declare class LearningOrchestrator {
9
9
  private mcpManager;
10
10
  private configLoader;
11
11
  private promptManager;
12
+ private memoryManager;
12
13
  private config;
13
14
  private initialized;
14
15
  constructor();