@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
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # [2.3.0](https://github.com/juspay/yama/compare/v2.2.2...v2.3.0) (2026-04-01)
2
+
3
+
4
+ ### Features
5
+
6
+ * **memory:** add per-repo memory management and configuration ([0b1fd5d](https://github.com/juspay/yama/commit/0b1fd5de8f0e46402f3c54766a5e0c7bd937cca2))
7
+
8
+ ## [2.2.2](https://github.com/juspay/yama/compare/v2.2.1...v2.2.2) (2026-03-26)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **core:** fix MCP timeout, local review output format, and ReDoS in JSON parser ([89dbc27](https://github.com/juspay/yama/commit/89dbc27bd35b738dc808ffa2eaa31807dceab2b5))
14
+
1
15
  ## [2.2.1](https://github.com/juspay/yama/compare/v2.2.0...v2.2.1) (2026-02-23)
2
16
 
3
17
 
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Juspay Technologies
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -8,11 +8,9 @@
8
8
 
9
9
  **Named after the Hindu deity of justice and death, Yama judges code quality and ensures only the worthy changes pass through.**
10
10
 
11
- ## What's New in V2?
11
+ ## Architecture
12
12
 
13
- Yama V2 represents a **complete architectural shift** from coded orchestration to **AI-native autonomous orchestration**:
14
-
15
- | Aspect | V1 | V2 |
13
+ | Aspect | Legacy | Current |
16
14
  | ------------------------- | ---------------------- | ----------------------------- |
17
15
  | **Architecture** | Coded orchestration | AI autonomous orchestration |
18
16
  | **Bitbucket Integration** | Direct handler imports | External MCP server |
@@ -28,7 +26,9 @@ Yama V2 represents a **complete architectural shift** from coded orchestration t
28
26
  ## Architecture Overview
29
27
 
30
28
  ```
31
- YamaV2Orchestrator
29
+ YamaOrchestrator
30
+
31
+ MemoryManager (per-repo condensed memory)
32
32
 
33
33
  NeuroLink AI Agent (Autonomous)
34
34
 
@@ -40,6 +40,7 @@ Pull Request Operations
40
40
  ### AI Autonomous Workflow
41
41
 
42
42
  1. **Context Gathering** (AI-driven)
43
+ - Reads per-repo memory (past review learnings)
43
44
  - Reads PR details
44
45
  - Finds and reads Jira ticket
45
46
  - Loads project standards from memory-bank
@@ -66,11 +67,11 @@ Pull Request Operations
66
67
  ### 1. Prerequisites
67
68
 
68
69
  ```bash
69
- # Node.js 18+ required
70
+ # Node.js 20.18.1+ required
70
71
  node --version
71
72
 
72
- # Install Yama V2
73
- npm install @juspay/yama@2.0.0
73
+ # Install Yama
74
+ npm install @juspay/yama
74
75
  ```
75
76
 
76
77
  ### 2. Environment Variables
@@ -80,7 +81,7 @@ Create a `.env` file:
80
81
  ```bash
81
82
  # Bitbucket
82
83
  BITBUCKET_USERNAME=your.email@company.com
83
- BITBUCKET_APP_PASSWORD=your-http-access-token
84
+ BITBUCKET_TOKEN=your-http-access-token
84
85
  BITBUCKET_BASE_URL=https://bitbucket.yourcompany.com
85
86
 
86
87
  # Jira (optional)
@@ -159,9 +160,9 @@ npx yama enhance \
159
160
  ### Programmatic Usage
160
161
 
161
162
  ```typescript
162
- import { createYamaV2 } from "@juspay/yama";
163
+ import { createYama } from "@juspay/yama";
163
164
 
164
- const yama = createYamaV2();
165
+ const yama = createYama();
165
166
 
166
167
  await yama.initialize();
167
168
 
@@ -176,13 +177,58 @@ console.log("Decision:", result.decision);
176
177
  console.log("Issues:", result.statistics.issuesFound);
177
178
  ```
178
179
 
180
+ ### Local SDK Mode (No Config File Required)
181
+
182
+ Note: Local mode initializes Git MCP internally via the package script
183
+ `mcp:git:server` (`uvx mcp-server-git` with `npx @modelcontextprotocol/server-git` fallback).
184
+
185
+ ```typescript
186
+ import { createYama } from "@juspay/yama";
187
+
188
+ const yama = createYama();
189
+
190
+ const result = await yama.reviewLocalDiff({
191
+ mode: "local",
192
+ repoPath: process.cwd(),
193
+ diffSource: "staged", // staged | uncommitted | range
194
+ focus: ["Security Analysis", "Code Quality"],
195
+ prompt: "Prioritize correctness and edge cases",
196
+ outputSchemaVersion: "1.0",
197
+ });
198
+
199
+ console.log(result.decision);
200
+ console.log(result.issues);
201
+ ```
202
+
203
+ SDK override example (no config file edit needed):
204
+
205
+ ```typescript
206
+ const yama = createYama({
207
+ configOverrides: {
208
+ ai: {
209
+ provider: "anthropic",
210
+ model: "claude-3-7-sonnet-latest",
211
+ },
212
+ },
213
+ });
214
+ ```
215
+
216
+ Precedence in SDK mode:
217
+ `configOverrides` > config file > environment variables > defaults
218
+
219
+ CLI local mode:
220
+
221
+ ```bash
222
+ npx yama review --mode local --repo-path . --diff-source staged
223
+ ```
224
+
179
225
  ## Configuration
180
226
 
181
227
  ### Basic Configuration
182
228
 
183
229
  ```yaml
184
230
  version: 2
185
- configType: "yama-v2"
231
+ configType: "yama"
186
232
 
187
233
  ai:
188
234
  provider: "auto"
@@ -231,7 +277,7 @@ Create `memory-bank/coding-standards.md`:
231
277
  - Database queries: < 50ms p95
232
278
  ```
233
279
 
234
- Yama V2 AI will automatically read and apply these standards.
280
+ Yama AI will automatically read and apply these standards.
235
281
 
236
282
  ## AI Autonomous Features
237
283
 
@@ -268,6 +314,17 @@ AI uses tools to understand code:
268
314
  - `get_file_content()` - Read related files
269
315
  - `list_directory_content()` - Explore structure
270
316
 
317
+ ### Per-Repo Memory
318
+
319
+ AI learns from past reviews and remembers across PRs:
320
+
321
+ - Reads condensed memory before each review for context
322
+ - Writes learnings after PR merge (false positives, missed issues, team conventions)
323
+ - LLM-powered condensation keeps memory within a configurable word limit
324
+ - Per-repo isolation — each repository gets independent memory keyed by `workspace-repository`
325
+ - Storage as `.md` files at configurable path (e.g., `memory-bank/yama/memory/`)
326
+ - Environment variable overrides for all settings (`YAMA_MEMORY_ENABLED`, `YAMA_MEMORY_MAX_WORDS`, etc.)
327
+
271
328
  ## Blocking Criteria
272
329
 
273
330
  AI applies these criteria automatically:
@@ -288,11 +345,11 @@ AI applies these criteria automatically:
288
345
 
289
346
  ## MCP Servers
290
347
 
291
- Yama V2 uses MCP (Model Context Protocol) servers for tool access:
348
+ Yama uses MCP (Model Context Protocol) servers for tool access:
292
349
 
293
350
  ### Bitbucket MCP
294
351
 
295
- - **Package**: `@anthropic/bitbucket-mcp-server`
352
+ - **Package**: `@nexus2520/bitbucket-mcp-server`
296
353
  - **Tools**: get_pull_request, add_comment, search_code, etc.
297
354
  - **Status**: Production ready
298
355
 
@@ -327,7 +384,7 @@ Analytics include:
327
384
  ```bash
328
385
  # Verify environment variables
329
386
  echo $BITBUCKET_USERNAME
330
- echo $BITBUCKET_APP_PASSWORD
387
+ echo $BITBUCKET_TOKEN
331
388
  echo $BITBUCKET_BASE_URL
332
389
  ```
333
390
 
@@ -363,100 +420,6 @@ echo $BITBUCKET_BASE_URL
363
420
  3. **Exclude generated files** - Skip lock files, minified code
364
421
  4. **Limit file count** - Split large PRs
365
422
 
366
- ## Migration from V1
367
-
368
- **Breaking Change**: V1 has been completely replaced by V2. There is no backward compatibility.
369
-
370
- ### Automated Config Migration
371
-
372
- Use the built-in migration script to convert your V1 config to V2 format:
373
-
374
- ```bash
375
- # Rename your current config to V1
376
- mv yama.config.yaml yama.v1.config.yaml
377
-
378
- # Run migration (dry-run first to preview)
379
- npx yama migrate-config --dry-run
380
-
381
- # Run actual migration
382
- npx yama migrate-config
383
-
384
- # Or with custom paths
385
- npx yama migrate-config \
386
- --input yama.v1.config.yaml \
387
- --output yama.config.yaml \
388
- --force
389
- ```
390
-
391
- The migration script will:
392
-
393
- - ✅ Migrate AI provider settings
394
- - ✅ Convert focus areas to structured format
395
- - ✅ Transform required sections with descriptions
396
- - ✅ Apply V2 defaults for new features
397
- - ⚠️ Warn about dropped V1 features (batchProcessing, multiInstance, etc.)
398
- - 📊 Generate a detailed migration report
399
-
400
- ### V1 → V2 Migration Steps
401
-
402
- 1. **Migrate configuration** (automated):
403
-
404
- ```bash
405
- npx yama migrate-config
406
- ```
407
-
408
- 2. **Update imports**:
409
-
410
- ```typescript
411
- // V1 (removed)
412
- // import { Guardian } from "@juspay/yama";
413
-
414
- // V2 (use this)
415
- import { createYamaV2 } from "@juspay/yama";
416
- const yama = createYamaV2();
417
- ```
418
-
419
- 3. **Set environment variables**: V2 uses MCP servers configured via env vars
420
-
421
- ```bash
422
- # Bitbucket (required)
423
- export BITBUCKET_USERNAME=your.email@company.com
424
- export BITBUCKET_APP_PASSWORD=your-http-access-token
425
- export BITBUCKET_BASE_URL=https://bitbucket.yourcompany.com
426
-
427
- # Jira (optional)
428
- export JIRA_EMAIL=your-email@company.com
429
- export JIRA_API_TOKEN=your-jira-api-token
430
- export JIRA_BASE_URL=https://yourcompany.atlassian.net
431
- ```
432
-
433
- 4. **Test thoroughly**: V2 uses autonomous AI orchestration - validate behavior in dry-run mode first
434
-
435
- ```bash
436
- npx yama review --workspace YOUR_WORKSPACE --repository my-repo --pr 123 --dry-run
437
- ```
438
-
439
- ### What Gets Migrated
440
-
441
- | V1 Section | V2 Section | Notes |
442
- | --------------------------------- | ------------------------ | ------------------------ |
443
- | `providers.ai` | `ai` | Direct mapping |
444
- | `features.codeReview` | `review` | Restructured |
445
- | `features.descriptionEnhancement` | `descriptionEnhancement` | Restructured |
446
- | `monitoring` | `monitoring` | Enhanced |
447
- | `rules` | `projectStandards` | Converted to focus areas |
448
-
449
- ### What Gets Dropped
450
-
451
- These V1 features are **removed** in V2 (AI handles autonomously):
452
-
453
- - `providers.git` → Use environment variables
454
- - `features.codeReview.batchProcessing` → AI manages batching
455
- - `features.codeReview.multiInstance` → Single autonomous agent
456
- - `features.codeReview.semanticDeduplication` → AI deduplicates naturally
457
- - `features.securityScan` → Built into AI prompts
458
- - `cache` → MCP tools handle caching
459
-
460
423
  ## Contributing
461
424
 
462
425
  We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Yama CLI - AI-Native Code Review Interface
4
+ */
5
+ import { Command } from "commander";
6
+ declare const program: Command;
7
+ /**
8
+ * Setup CLI
9
+ */
10
+ export declare function setupCLI(): Command;
11
+ export declare const setupV2CLI: typeof setupCLI;
12
+ export default program;
13
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1,341 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Yama CLI - AI-Native Code Review Interface
4
+ */
5
+ import { Command } from "commander";
6
+ import dotenv from "dotenv";
7
+ import { VERSION, createYama } from "../index.js";
8
+ import { createLearningOrchestrator } from "../v2/core/LearningOrchestrator.js";
9
+ // Load environment variables
10
+ dotenv.config();
11
+ const program = new Command();
12
+ /**
13
+ * Setup CLI
14
+ */
15
+ export function setupCLI() {
16
+ program
17
+ .name("yama")
18
+ .description("Yama - AI-Native Autonomous Code Review")
19
+ .version(VERSION);
20
+ // Global options
21
+ program
22
+ .option("-v, --verbose", "Enable verbose output")
23
+ .option("-c, --config <path>", "Path to configuration file")
24
+ .option("--dry-run", "Dry run mode - no actual changes")
25
+ .option("--no-banner", "Hide Yama banner");
26
+ // Commands
27
+ setupReviewCommand();
28
+ setupEnhanceCommand();
29
+ setupLearnCommand();
30
+ setupInitCommand();
31
+ return program;
32
+ }
33
+ // Backward-compatible alias.
34
+ export const setupV2CLI = setupCLI;
35
+ /**
36
+ * Main review command
37
+ * Reviews code and enhances description in one session
38
+ */
39
+ function setupReviewCommand() {
40
+ program
41
+ .command("review")
42
+ .description("Review code and enhance PR description (uses same AI session)")
43
+ .option("--mode <mode>", "Review mode (pr|local)", "pr")
44
+ .option("-w, --workspace <workspace>", "Bitbucket workspace")
45
+ .option("-r, --repository <repository>", "Repository name")
46
+ .option("-p, --pr <id>", "Pull request ID")
47
+ .option("-b, --branch <branch>", "Branch name (finds PR automatically)")
48
+ .option("--repo-path <path>", "Local repository path (local mode)")
49
+ .option("--diff-source <source>", "Diff source: staged | uncommitted | range (local mode)", "uncommitted")
50
+ .option("--base <ref>", "Base git ref for range diff (local mode)")
51
+ .option("--head <ref>", "Head git ref for range diff (local mode)")
52
+ .option("--focus <areas>", "Comma-separated review focus areas (both modes)")
53
+ .option("--output-schema-version <version>", "Output schema version for local mode JSON", "1.0")
54
+ .option("--prompt <text>", "Additional review instruction prompt (both modes)")
55
+ .option("--review-only", "Skip description enhancement, only review code")
56
+ .action(async (options) => {
57
+ try {
58
+ const globalOpts = program.opts();
59
+ const mode = (options.mode || "pr").toLowerCase();
60
+ const focus = options.focus
61
+ ? String(options.focus)
62
+ .split(",")
63
+ .map((value) => value.trim())
64
+ .filter(Boolean)
65
+ : undefined;
66
+ const yama = createYama({ configPath: globalOpts.config });
67
+ if (mode === "local") {
68
+ const request = {
69
+ mode: "local",
70
+ repoPath: options.repoPath,
71
+ diffSource: options.diffSource,
72
+ baseRef: options.base,
73
+ headRef: options.head,
74
+ dryRun: globalOpts.dryRun || false,
75
+ verbose: globalOpts.verbose || false,
76
+ configPath: globalOpts.config,
77
+ prompt: options.prompt,
78
+ focus,
79
+ outputSchemaVersion: options.outputSchemaVersion,
80
+ };
81
+ console.log("🚀 Starting local SDK diff review...\n");
82
+ const result = await yama.reviewLocalDiff(request);
83
+ console.log("\n📊 Local Review Results:");
84
+ console.log(` Decision: ${result.decision}`);
85
+ console.log(` Files Changed: ${result.statistics.filesChanged}`);
86
+ console.log(` Issues: ${result.statistics.issuesFound}`);
87
+ console.log(` Enhancements: ${result.statistics.enhancementsFound}`);
88
+ console.log(` Duration: ${result.duration}s`);
89
+ console.log(` Token Usage: ${result.tokenUsage.total.toLocaleString()} tokens`);
90
+ if (globalOpts.verbose) {
91
+ console.log("\n📄 Full Results:");
92
+ console.log(JSON.stringify(result, null, 2));
93
+ }
94
+ process.exit(result.decision === "BLOCKED" ? 1 : 0);
95
+ }
96
+ if (!options.workspace || !options.repository) {
97
+ console.error("❌ Error: --workspace and --repository are required in pr mode");
98
+ process.exit(1);
99
+ }
100
+ if (!options.pr && !options.branch) {
101
+ console.error("❌ Error: Either --pr or --branch must be specified");
102
+ process.exit(1);
103
+ }
104
+ let pullRequestId;
105
+ if (options.pr) {
106
+ pullRequestId = parseInt(options.pr, 10);
107
+ if (isNaN(pullRequestId)) {
108
+ console.error(`❌ Error: Invalid PR ID "${options.pr}" (must be a number)`);
109
+ process.exit(1);
110
+ }
111
+ }
112
+ const request = {
113
+ mode: "pr",
114
+ workspace: options.workspace,
115
+ repository: options.repository,
116
+ pullRequestId,
117
+ branch: options.branch,
118
+ dryRun: globalOpts.dryRun || false,
119
+ verbose: globalOpts.verbose || false,
120
+ configPath: globalOpts.config,
121
+ prompt: options.prompt,
122
+ focus,
123
+ outputSchemaVersion: options.outputSchemaVersion,
124
+ };
125
+ await yama.initialize(request.configPath);
126
+ console.log("🚀 Starting autonomous AI review...\n");
127
+ const result = options.reviewOnly
128
+ ? await yama.startReview(request)
129
+ : await yama.startReviewAndEnhance(request);
130
+ console.log("\n📊 Review Results:");
131
+ console.log(` Decision: ${result.decision}`);
132
+ console.log(` Files Reviewed: ${result.statistics.filesReviewed}`);
133
+ console.log(` Total Comments: ${result.totalComments || result.statistics.totalComments || 0}`);
134
+ if (result.descriptionEnhanced !== undefined) {
135
+ console.log(` Description Enhanced: ${result.descriptionEnhanced ? "✅ Yes" : "⏭️ Skipped"}`);
136
+ }
137
+ console.log(` Duration: ${result.duration}s`);
138
+ console.log(` Token Usage: ${result.tokenUsage.total.toLocaleString()} tokens`);
139
+ if (globalOpts.verbose) {
140
+ console.log("\n📄 Full Results:");
141
+ console.log(JSON.stringify(result, null, 2));
142
+ }
143
+ process.exit(result.decision === "BLOCKED" ? 1 : 0);
144
+ }
145
+ catch (error) {
146
+ console.error("\n❌ Review failed:", error.message);
147
+ if (error.stack && program.opts().verbose) {
148
+ console.error("\nStack trace:");
149
+ console.error(error.stack);
150
+ }
151
+ process.exit(1);
152
+ }
153
+ });
154
+ }
155
+ /**
156
+ * Enhance description command
157
+ */
158
+ function setupEnhanceCommand() {
159
+ program
160
+ .command("enhance")
161
+ .description("Enhance PR description using AI (without full review)")
162
+ .requiredOption("-w, --workspace <workspace>", "Bitbucket workspace")
163
+ .requiredOption("-r, --repository <repository>", "Repository name")
164
+ .option("-p, --pr <id>", "Pull request ID")
165
+ .option("-b, --branch <branch>", "Branch name")
166
+ .action(async (options) => {
167
+ try {
168
+ const globalOpts = program.opts();
169
+ if (!options.pr && !options.branch) {
170
+ console.error("❌ Error: Either --pr or --branch must be specified");
171
+ process.exit(1);
172
+ }
173
+ let pullRequestId;
174
+ if (options.pr) {
175
+ pullRequestId = parseInt(options.pr, 10);
176
+ if (isNaN(pullRequestId)) {
177
+ console.error(`❌ Error: Invalid PR ID "${options.pr}" (must be a number)`);
178
+ process.exit(1);
179
+ }
180
+ }
181
+ const request = {
182
+ mode: "pr",
183
+ workspace: options.workspace,
184
+ repository: options.repository,
185
+ pullRequestId,
186
+ branch: options.branch,
187
+ dryRun: globalOpts.dryRun || false,
188
+ verbose: globalOpts.verbose || false,
189
+ configPath: globalOpts.config,
190
+ };
191
+ const yama = createYama({ configPath: globalOpts.config });
192
+ await yama.initialize(request.configPath);
193
+ const result = await yama.enhanceDescription(request);
194
+ console.log("\n✅ Description enhanced successfully");
195
+ console.log(JSON.stringify(result, null, 2));
196
+ process.exit(0);
197
+ }
198
+ catch (error) {
199
+ console.error("\n❌ Enhancement failed:", error.message);
200
+ process.exit(1);
201
+ }
202
+ });
203
+ }
204
+ /**
205
+ * Learn from PR feedback command
206
+ * Extracts learnings from merged PRs to improve future reviews
207
+ */
208
+ function setupLearnCommand() {
209
+ program
210
+ .command("learn")
211
+ .description("Extract learnings from merged PR to improve future reviews")
212
+ .requiredOption("-w, --workspace <workspace>", "Bitbucket workspace")
213
+ .requiredOption("-r, --repository <repository>", "Repository name")
214
+ .requiredOption("-p, --pr <id>", "Merged pull request ID")
215
+ .option("--commit", "Auto-commit knowledge base changes to git")
216
+ .option("--summarize", "Force summarization of knowledge base")
217
+ .option("--output <path>", "Override knowledge base output path")
218
+ .option("--format <format>", "Output format for dry-run preview (md|json)", "md")
219
+ .action(async (options) => {
220
+ try {
221
+ const globalOpts = program.opts();
222
+ const pullRequestId = parseInt(options.pr, 10);
223
+ if (isNaN(pullRequestId)) {
224
+ console.error(`❌ Error: Invalid PR ID "${options.pr}" (must be a number)`);
225
+ process.exit(1);
226
+ }
227
+ if (options.format && !["md", "json"].includes(options.format)) {
228
+ console.error(`❌ Error: Invalid format "${options.format}" (must be md or json)`);
229
+ process.exit(1);
230
+ }
231
+ const request = {
232
+ workspace: options.workspace,
233
+ repository: options.repository,
234
+ pullRequestId,
235
+ dryRun: globalOpts.dryRun || false,
236
+ commit: options.commit || false,
237
+ summarize: options.summarize || false,
238
+ outputPath: options.output,
239
+ outputFormat: options.format || "md",
240
+ };
241
+ const orchestrator = createLearningOrchestrator();
242
+ await orchestrator.initialize(globalOpts.config);
243
+ const result = await orchestrator.extractLearnings(request);
244
+ if (!result.success) {
245
+ console.error(`\n❌ Learning extraction failed: ${result.error}`);
246
+ process.exit(1);
247
+ }
248
+ if (!globalOpts.dryRun && result.learningsAdded > 0) {
249
+ console.log("\n🎉 Knowledge base updated successfully!");
250
+ console.log(" Use 'yama review' to apply these learnings to future reviews.");
251
+ }
252
+ process.exit(0);
253
+ }
254
+ catch (error) {
255
+ console.error("\n❌ Learning extraction failed:", error.message);
256
+ if (error.stack && program.opts().verbose) {
257
+ console.error("\nStack trace:");
258
+ console.error(error.stack);
259
+ }
260
+ process.exit(1);
261
+ }
262
+ });
263
+ }
264
+ /**
265
+ * Initialize configuration command
266
+ */
267
+ function setupInitCommand() {
268
+ program
269
+ .command("init")
270
+ .description("Initialize Yama configuration")
271
+ .option("--interactive", "Interactive configuration setup")
272
+ .action(async (options) => {
273
+ try {
274
+ console.log("\n⚔️ Yama Configuration Setup\n");
275
+ if (options.interactive) {
276
+ console.log("Interactive setup not yet implemented.");
277
+ console.log("Please copy yama.config.example.yaml to yama.config.yaml");
278
+ console.log("and edit it manually.\n");
279
+ }
280
+ else {
281
+ console.log("Creating default configuration file...\n");
282
+ const fs = await import("fs/promises");
283
+ const path = await import("path");
284
+ if (await fs
285
+ .access("yama.config.yaml")
286
+ .then(() => true)
287
+ .catch(() => false)) {
288
+ console.log("❌ yama.config.yaml already exists");
289
+ console.log(" Remove it first or use a different location\n");
290
+ process.exit(1);
291
+ }
292
+ const examplePath = path.join(process.cwd(), "yama.config.example.yaml");
293
+ const targetPath = path.join(process.cwd(), "yama.config.yaml");
294
+ if (await fs
295
+ .access(examplePath)
296
+ .then(() => true)
297
+ .catch(() => false)) {
298
+ await fs.copyFile(examplePath, targetPath);
299
+ console.log("✅ Created yama.config.yaml from example");
300
+ }
301
+ else {
302
+ console.log("⚠️ Example config not found, creating minimal config...");
303
+ await fs.writeFile(targetPath, `version: 2
304
+ configType: "yama"
305
+
306
+ ai:
307
+ provider: "auto"
308
+ model: "gemini-2.5-pro"
309
+
310
+ mcpServers:
311
+ jira:
312
+ enabled: false
313
+
314
+ review:
315
+ enabled: true
316
+
317
+ descriptionEnhancement:
318
+ enabled: true
319
+ `);
320
+ console.log("✅ Created minimal yama.config.yaml");
321
+ }
322
+ console.log("\n📝 Next steps:");
323
+ console.log(" 1. Edit yama.config.yaml with your settings");
324
+ console.log(" 2. Set environment variables (BITBUCKET_*, JIRA_*)");
325
+ console.log(" 3. Run: yama review --help\n");
326
+ }
327
+ process.exit(0);
328
+ }
329
+ catch (error) {
330
+ console.error("\n❌ Initialization failed:", error.message);
331
+ process.exit(1);
332
+ }
333
+ });
334
+ }
335
+ // Only run if this is the main module
336
+ if (import.meta.url === `file://${process.argv[1]}`) {
337
+ const cli = setupCLI();
338
+ cli.parse(process.argv);
339
+ }
340
+ export default program;
341
+ //# sourceMappingURL=cli.js.map
@@ -1,13 +1,4 @@
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
- declare const program: Command;
8
- /**
9
- * Setup V2 CLI
10
- */
11
- export declare function setupV2CLI(): Command;
12
- export default program;
2
+ import program, { setupCLI } from "./cli.js";
3
+ export { setupCLI, program as default };
13
4
  //# sourceMappingURL=v2.cli.d.ts.map