@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.
- package/CHANGELOG.md +14 -0
- package/LICENSE +21 -0
- package/README.md +73 -110
- package/dist/cli/cli.d.ts +13 -0
- package/dist/cli/cli.js +341 -0
- package/dist/cli/v2.cli.d.ts +2 -11
- package/dist/cli/v2.cli.js +4 -354
- package/dist/index.d.ts +7 -5
- package/dist/index.js +5 -3
- package/dist/v2/config/ConfigLoader.d.ts +20 -5
- package/dist/v2/config/ConfigLoader.js +76 -24
- package/dist/v2/config/DefaultConfig.d.ts +3 -3
- package/dist/v2/config/DefaultConfig.js +9 -2
- package/dist/v2/core/LearningOrchestrator.d.ts +1 -0
- package/dist/v2/core/LearningOrchestrator.js +64 -4
- package/dist/v2/core/LocalDiffSource.d.ts +26 -0
- package/dist/v2/core/LocalDiffSource.js +129 -0
- package/dist/v2/core/MCPServerManager.d.ts +13 -1
- package/dist/v2/core/MCPServerManager.js +111 -7
- package/dist/v2/core/SessionManager.d.ts +1 -1
- package/dist/v2/core/SessionManager.js +3 -3
- package/dist/v2/core/YamaV2Orchestrator.d.ts +48 -13
- package/dist/v2/core/YamaV2Orchestrator.js +543 -63
- package/dist/v2/learning/types.d.ts +10 -0
- package/dist/v2/memory/MemoryManager.d.ts +57 -0
- package/dist/v2/memory/MemoryManager.js +185 -0
- package/dist/v2/prompts/PromptBuilder.d.ts +10 -4
- package/dist/v2/prompts/PromptBuilder.js +94 -3
- package/dist/v2/prompts/ReviewSystemPrompt.d.ts +1 -1
- package/dist/v2/prompts/ReviewSystemPrompt.js +7 -5
- package/dist/v2/types/config.types.d.ts +61 -1
- package/dist/v2/types/v2.types.d.ts +66 -5
- package/dist/v2/types/v2.types.js +8 -6
- package/package.json +20 -15
- 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
|
-
##
|
|
11
|
+
## Architecture
|
|
12
12
|
|
|
13
|
-
|
|
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
|
-
|
|
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
|
|
73
|
-
npm install @juspay/yama
|
|
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
|
-
|
|
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 {
|
|
163
|
+
import { createYama } from "@juspay/yama";
|
|
163
164
|
|
|
164
|
-
const yama =
|
|
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
|
|
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
|
|
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
|
|
348
|
+
Yama uses MCP (Model Context Protocol) servers for tool access:
|
|
292
349
|
|
|
293
350
|
### Bitbucket MCP
|
|
294
351
|
|
|
295
|
-
- **Package**: `@
|
|
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 $
|
|
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
|
package/dist/cli/cli.js
ADDED
|
@@ -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
|
package/dist/cli/v2.cli.d.ts
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
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
|