@juspay/yama 2.2.2 → 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 +7 -0
- package/README.md +14 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -0
- package/dist/v2/config/ConfigLoader.d.ts +15 -0
- package/dist/v2/config/ConfigLoader.js +34 -0
- package/dist/v2/config/DefaultConfig.js +5 -0
- package/dist/v2/core/LearningOrchestrator.d.ts +1 -0
- package/dist/v2/core/LearningOrchestrator.js +64 -4
- package/dist/v2/core/YamaV2Orchestrator.d.ts +2 -7
- package/dist/v2/core/YamaV2Orchestrator.js +32 -20
- 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/types/config.types.d.ts +51 -0
- package/package.json +2 -2
- package/yama.config.example.yaml +15 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
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
|
+
|
|
1
8
|
## [2.2.2](https://github.com/juspay/yama/compare/v2.2.1...v2.2.2) (2026-03-26)
|
|
2
9
|
|
|
3
10
|
|
package/README.md
CHANGED
|
@@ -28,6 +28,8 @@
|
|
|
28
28
|
```
|
|
29
29
|
YamaOrchestrator
|
|
30
30
|
↓
|
|
31
|
+
MemoryManager (per-repo condensed memory)
|
|
32
|
+
↓
|
|
31
33
|
NeuroLink AI Agent (Autonomous)
|
|
32
34
|
↓
|
|
33
35
|
MCP Tools (Bitbucket + Jira)
|
|
@@ -38,6 +40,7 @@ Pull Request Operations
|
|
|
38
40
|
### AI Autonomous Workflow
|
|
39
41
|
|
|
40
42
|
1. **Context Gathering** (AI-driven)
|
|
43
|
+
- Reads per-repo memory (past review learnings)
|
|
41
44
|
- Reads PR details
|
|
42
45
|
- Finds and reads Jira ticket
|
|
43
46
|
- Loads project standards from memory-bank
|
|
@@ -311,6 +314,17 @@ AI uses tools to understand code:
|
|
|
311
314
|
- `get_file_content()` - Read related files
|
|
312
315
|
- `list_directory_content()` - Explore structure
|
|
313
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
|
+
|
|
314
328
|
## Blocking Criteria
|
|
315
329
|
|
|
316
330
|
AI applies these criteria automatically:
|
package/dist/index.d.ts
CHANGED
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
* Main export file
|
|
4
4
|
*/
|
|
5
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";
|
|
11
|
+
export { MemoryManager } from "./v2/memory/MemoryManager.js";
|
|
10
12
|
export type { LocalReviewFinding, LocalReviewRequest, LocalReviewResult, ReviewRequest, ReviewMode, ReviewResult, ReviewUpdate, ReviewSession, ReviewStatistics, IssuesBySeverity, TokenUsage, UnifiedReviewRequest, } from "./v2/types/v2.types.js";
|
|
11
|
-
export type { YamaConfig, YamaInitOptions, YamaConfig as YamaV2Config, AIConfig, MCPServersConfig, ReviewConfig, DescriptionEnhancementConfig, } from "./v2/types/config.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
15
|
export declare const VERSION = "2.2.1";
|
|
14
16
|
export { createYama as default } from "./v2/core/YamaV2Orchestrator.js";
|
package/dist/index.js
CHANGED
|
@@ -6,10 +6,12 @@
|
|
|
6
6
|
// Core Exports
|
|
7
7
|
// ============================================================================
|
|
8
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
|
// ============================================================================
|
|
@@ -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
|
*/
|
|
@@ -32,6 +32,7 @@ export class ConfigLoader {
|
|
|
32
32
|
else {
|
|
33
33
|
console.log(" Using default configuration (no config file found)");
|
|
34
34
|
}
|
|
35
|
+
config.memory = this.applyMemoryOverrides(config.memory);
|
|
35
36
|
// Layer 4: Apply SDK instance overrides (highest priority)
|
|
36
37
|
if (instanceOverrides) {
|
|
37
38
|
config = this.mergeConfigs(config, instanceOverrides);
|
|
@@ -199,6 +200,39 @@ export class ConfigLoader {
|
|
|
199
200
|
}
|
|
200
201
|
return config;
|
|
201
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
|
+
}
|
|
202
236
|
/**
|
|
203
237
|
* Basic configuration validation
|
|
204
238
|
*/
|
|
@@ -158,6 +158,11 @@ export class DefaultConfig {
|
|
|
158
158
|
summaryRetentionCount: 20,
|
|
159
159
|
autoCommit: false,
|
|
160
160
|
},
|
|
161
|
+
memory: {
|
|
162
|
+
enabled: false,
|
|
163
|
+
storagePath: ".yama/memory",
|
|
164
|
+
maxWords: 200,
|
|
165
|
+
},
|
|
161
166
|
projectStandards: {
|
|
162
167
|
customPromptsPath: "config/prompts/",
|
|
163
168
|
additionalFocusAreas: [],
|
|
@@ -8,12 +8,14 @@ import { MCPServerManager } from "./MCPServerManager.js";
|
|
|
8
8
|
import { ConfigLoader } from "../config/ConfigLoader.js";
|
|
9
9
|
import { LangfusePromptManager } from "../prompts/LangfusePromptManager.js";
|
|
10
10
|
import { KnowledgeBaseManager } from "../learning/KnowledgeBaseManager.js";
|
|
11
|
+
import { MemoryManager } from "../memory/MemoryManager.js";
|
|
11
12
|
import { buildObservabilityConfigFromEnv, validateObservabilityConfig, } from "../utils/ObservabilityConfig.js";
|
|
12
13
|
export class LearningOrchestrator {
|
|
13
14
|
neurolink;
|
|
14
15
|
mcpManager;
|
|
15
16
|
configLoader;
|
|
16
17
|
promptManager;
|
|
18
|
+
memoryManager = null;
|
|
17
19
|
config;
|
|
18
20
|
initialized = false;
|
|
19
21
|
constructor() {
|
|
@@ -32,7 +34,12 @@ export class LearningOrchestrator {
|
|
|
32
34
|
try {
|
|
33
35
|
// Load configuration
|
|
34
36
|
this.config = await this.configLoader.loadConfig(configPath);
|
|
35
|
-
// Initialize NeuroLink
|
|
37
|
+
// Initialize Memory Manager (if enabled) — must happen before NeuroLink
|
|
38
|
+
if (this.config.memory?.enabled) {
|
|
39
|
+
this.memoryManager = new MemoryManager(this.config.memory, this.config.ai.provider, this.config.ai.model);
|
|
40
|
+
console.log(" 🧠 Per-repo memory enabled\n");
|
|
41
|
+
}
|
|
42
|
+
// Initialize NeuroLink with memory config injected
|
|
36
43
|
console.log(" 🔧 Initializing NeuroLink AI engine...");
|
|
37
44
|
this.neurolink = this.initializeNeurolink();
|
|
38
45
|
console.log(" ✅ NeuroLink initialized\n");
|
|
@@ -126,6 +133,52 @@ export class LearningOrchestrator {
|
|
|
126
133
|
if (duplicateCount > 0) {
|
|
127
134
|
console.log(` ⏭️ Skipped ${duplicateCount} duplicates`);
|
|
128
135
|
}
|
|
136
|
+
// Resolve commit mode: commitMode takes precedence, fall back to legacy commit flag
|
|
137
|
+
const commitMode = request.commitMode ||
|
|
138
|
+
(request.commit || this.config.knowledgeBase.autoCommit
|
|
139
|
+
? "kb"
|
|
140
|
+
: undefined);
|
|
141
|
+
const shouldCommitMemory = commitMode === "memory" || commitMode === "all";
|
|
142
|
+
const shouldCommitKb = commitMode === "kb" || commitMode === "all";
|
|
143
|
+
// Store learnings in per-repo memory via NeuroLink
|
|
144
|
+
// read: false (we don't need to read memory here)
|
|
145
|
+
// write: true (condense learnings into memory file)
|
|
146
|
+
if (this.memoryManager && addedCount > 0 && shouldCommitMemory) {
|
|
147
|
+
try {
|
|
148
|
+
const byCategory = new Map();
|
|
149
|
+
for (const l of learnings) {
|
|
150
|
+
const cat = l.category.replace(/_/g, " ");
|
|
151
|
+
if (!byCategory.has(cat)) {
|
|
152
|
+
byCategory.set(cat, []);
|
|
153
|
+
}
|
|
154
|
+
byCategory.get(cat).push(l.learning);
|
|
155
|
+
}
|
|
156
|
+
const parts = [];
|
|
157
|
+
for (const [category, items] of byCategory) {
|
|
158
|
+
parts.push(`${category}: ${items.join("; ")}`);
|
|
159
|
+
}
|
|
160
|
+
const ownerId = MemoryManager.buildOwnerId(request.workspace, request.repository);
|
|
161
|
+
await this.neurolink.generate({
|
|
162
|
+
input: { text: parts.join(". ") },
|
|
163
|
+
provider: this.config.ai.provider,
|
|
164
|
+
model: this.config.ai.model,
|
|
165
|
+
temperature: 0.1,
|
|
166
|
+
maxTokens: 100,
|
|
167
|
+
disableTools: true,
|
|
168
|
+
context: {
|
|
169
|
+
userId: ownerId,
|
|
170
|
+
operation: "memory-store-learnings",
|
|
171
|
+
},
|
|
172
|
+
memory: { read: false, write: true },
|
|
173
|
+
});
|
|
174
|
+
console.log(` 🧠 Learning memory stored for ${ownerId}`);
|
|
175
|
+
// Auto-commit and push memory files to repo
|
|
176
|
+
await this.memoryManager.commitMemoryChanges();
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
console.warn(` ⚠️ Failed to store learning memory: ${error.message}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
129
182
|
// Check if summarization is needed
|
|
130
183
|
let summarized = false;
|
|
131
184
|
if (request.summarize || (await kbManager.needsSummarization())) {
|
|
@@ -134,9 +187,9 @@ export class LearningOrchestrator {
|
|
|
134
187
|
summarized = true;
|
|
135
188
|
console.log(" ✅ Summarization complete");
|
|
136
189
|
}
|
|
137
|
-
// Commit if requested
|
|
190
|
+
// Commit knowledge base if requested
|
|
138
191
|
let committed = false;
|
|
139
|
-
if (
|
|
192
|
+
if (shouldCommitKb) {
|
|
140
193
|
console.log("\n📤 Committing knowledge base...");
|
|
141
194
|
await kbManager.commit(request.pullRequestId, addedCount);
|
|
142
195
|
committed = true;
|
|
@@ -352,8 +405,15 @@ Analyze the PR data above and extract learnings.
|
|
|
352
405
|
*/
|
|
353
406
|
initializeNeurolink() {
|
|
354
407
|
const observabilityConfig = buildObservabilityConfigFromEnv();
|
|
408
|
+
const conversationMemory = {
|
|
409
|
+
...this.config.ai.conversationMemory,
|
|
410
|
+
};
|
|
411
|
+
if (this.memoryManager) {
|
|
412
|
+
conversationMemory.memory =
|
|
413
|
+
this.memoryManager.buildNeuroLinkMemoryConfig();
|
|
414
|
+
}
|
|
355
415
|
const neurolinkConfig = {
|
|
356
|
-
conversationMemory
|
|
416
|
+
conversationMemory,
|
|
357
417
|
};
|
|
358
418
|
if (observabilityConfig &&
|
|
359
419
|
validateObservabilityConfig(observabilityConfig)) {
|
|
@@ -10,6 +10,7 @@ export declare class YamaOrchestrator {
|
|
|
10
10
|
private configLoader;
|
|
11
11
|
private promptBuilder;
|
|
12
12
|
private sessionManager;
|
|
13
|
+
private memoryManager;
|
|
13
14
|
private localDiffSource;
|
|
14
15
|
private config;
|
|
15
16
|
private initialized;
|
|
@@ -64,9 +65,7 @@ export declare class YamaOrchestrator {
|
|
|
64
65
|
* Export session data
|
|
65
66
|
*/
|
|
66
67
|
exportSession(sessionId: string): any;
|
|
67
|
-
|
|
68
|
-
* Create tool context for AI
|
|
69
|
-
*/
|
|
68
|
+
private getUserId;
|
|
70
69
|
private createToolContext;
|
|
71
70
|
/**
|
|
72
71
|
* Parse AI response into structured review result
|
|
@@ -105,10 +104,6 @@ export declare class YamaOrchestrator {
|
|
|
105
104
|
*/
|
|
106
105
|
private calculateCost;
|
|
107
106
|
private toSafeNumber;
|
|
108
|
-
/**
|
|
109
|
-
* Generate userId for NeuroLink context from repository and branch/PR
|
|
110
|
-
*/
|
|
111
|
-
private generateUserId;
|
|
112
107
|
private isLocalReviewRequest;
|
|
113
108
|
/**
|
|
114
109
|
* Query-level tool filtering for PR mode.
|
|
@@ -7,6 +7,7 @@ import { MCPServerManager } from "./MCPServerManager.js";
|
|
|
7
7
|
import { ConfigLoader } from "../config/ConfigLoader.js";
|
|
8
8
|
import { PromptBuilder } from "../prompts/PromptBuilder.js";
|
|
9
9
|
import { SessionManager } from "./SessionManager.js";
|
|
10
|
+
import { MemoryManager } from "../memory/MemoryManager.js";
|
|
10
11
|
import { LocalDiffSource } from "./LocalDiffSource.js";
|
|
11
12
|
import { buildObservabilityConfigFromEnv, validateObservabilityConfig, } from "../utils/ObservabilityConfig.js";
|
|
12
13
|
export class YamaOrchestrator {
|
|
@@ -15,6 +16,7 @@ export class YamaOrchestrator {
|
|
|
15
16
|
configLoader;
|
|
16
17
|
promptBuilder;
|
|
17
18
|
sessionManager;
|
|
19
|
+
memoryManager = null;
|
|
18
20
|
localDiffSource;
|
|
19
21
|
config;
|
|
20
22
|
initialized = false;
|
|
@@ -40,13 +42,18 @@ export class YamaOrchestrator {
|
|
|
40
42
|
const resolvedConfigPath = configPath || this.initOptions.configPath;
|
|
41
43
|
this.config = await this.configLoader.loadConfig(resolvedConfigPath, this.initOptions.configOverrides);
|
|
42
44
|
this.showBanner();
|
|
43
|
-
// Step 2: Initialize
|
|
45
|
+
// Step 2: Initialize
|
|
46
|
+
if (this.config.memory?.enabled) {
|
|
47
|
+
this.memoryManager = new MemoryManager(this.config.memory, this.config.ai.provider, this.config.ai.model);
|
|
48
|
+
console.log(" 🧠 Per-repo memory enabled\n");
|
|
49
|
+
}
|
|
50
|
+
// Step 3: Initialize NeuroLink with memory config injected
|
|
44
51
|
console.log("🧠 Initializing NeuroLink AI engine...");
|
|
45
52
|
this.neurolink = this.initializeNeurolink();
|
|
46
53
|
console.log("✅ NeuroLink initialized\n");
|
|
47
54
|
this.initialized = true;
|
|
48
55
|
}
|
|
49
|
-
// Step
|
|
56
|
+
// Step 4: Mode-specific setup
|
|
50
57
|
if (mode === "pr" && !this.mcpInitialized) {
|
|
51
58
|
await this.mcpManager.setupMCPServers(this.neurolink, this.config.mcpServers);
|
|
52
59
|
this.mcpInitialized = true;
|
|
@@ -55,7 +62,7 @@ export class YamaOrchestrator {
|
|
|
55
62
|
await this.mcpManager.setupLocalGitMCPServer(this.neurolink);
|
|
56
63
|
this.localGitMcpInitialized = true;
|
|
57
64
|
}
|
|
58
|
-
// Step
|
|
65
|
+
// Step 5: Mode-specific validation
|
|
59
66
|
await this.configLoader.validate(mode);
|
|
60
67
|
console.log("✅ Yama initialized successfully\n");
|
|
61
68
|
console.log("═".repeat(60) + "\n");
|
|
@@ -92,6 +99,7 @@ export class YamaOrchestrator {
|
|
|
92
99
|
// Execute autonomous AI review
|
|
93
100
|
console.log("🤖 Starting autonomous AI review...");
|
|
94
101
|
console.log(" AI will now make decisions and execute actions autonomously\n");
|
|
102
|
+
// Review call: RETRIEVE memory (for context), but DON'T STORE
|
|
95
103
|
const aiResponse = await this.neurolink.generate({
|
|
96
104
|
input: { text: instructions },
|
|
97
105
|
provider: this.config.ai.provider,
|
|
@@ -103,10 +111,11 @@ export class YamaOrchestrator {
|
|
|
103
111
|
...this.getPRToolFilteringOptions(instructions),
|
|
104
112
|
context: {
|
|
105
113
|
sessionId,
|
|
106
|
-
userId: this.
|
|
114
|
+
userId: this.getUserId(request),
|
|
107
115
|
operation: "code-review",
|
|
108
116
|
metadata: toolContext.metadata,
|
|
109
117
|
},
|
|
118
|
+
memory: { read: true, write: false },
|
|
110
119
|
enableAnalytics: this.config.ai.enableAnalytics,
|
|
111
120
|
enableEvaluation: this.config.ai.enableEvaluation,
|
|
112
121
|
});
|
|
@@ -229,8 +238,9 @@ export class YamaOrchestrator {
|
|
|
229
238
|
...this.getPRToolFilteringOptions(instructions),
|
|
230
239
|
context: {
|
|
231
240
|
sessionId,
|
|
232
|
-
userId: this.
|
|
241
|
+
userId: this.getUserId(request),
|
|
233
242
|
},
|
|
243
|
+
memory: { enabled: false },
|
|
234
244
|
enableAnalytics: true,
|
|
235
245
|
});
|
|
236
246
|
yield {
|
|
@@ -290,10 +300,11 @@ export class YamaOrchestrator {
|
|
|
290
300
|
...this.getPRToolFilteringOptions(reviewInstructions),
|
|
291
301
|
context: {
|
|
292
302
|
sessionId,
|
|
293
|
-
userId: this.
|
|
303
|
+
userId: this.getUserId(request),
|
|
294
304
|
operation: "code-review",
|
|
295
305
|
metadata: toolContext.metadata,
|
|
296
306
|
},
|
|
307
|
+
memory: { read: true, write: false },
|
|
297
308
|
enableAnalytics: this.config.ai.enableAnalytics,
|
|
298
309
|
enableEvaluation: this.config.ai.enableEvaluation,
|
|
299
310
|
});
|
|
@@ -322,10 +333,11 @@ export class YamaOrchestrator {
|
|
|
322
333
|
...this.getPRToolFilteringOptions(enhanceInstructions),
|
|
323
334
|
context: {
|
|
324
335
|
sessionId, // SAME sessionId = AI remembers review context
|
|
325
|
-
userId: this.
|
|
336
|
+
userId: this.getUserId(request),
|
|
326
337
|
operation: "description-enhancement",
|
|
327
338
|
metadata: toolContext.metadata,
|
|
328
339
|
},
|
|
340
|
+
memory: { enabled: false },
|
|
329
341
|
enableAnalytics: this.config.ai.enableAnalytics,
|
|
330
342
|
enableEvaluation: this.config.ai.enableEvaluation,
|
|
331
343
|
});
|
|
@@ -368,9 +380,10 @@ export class YamaOrchestrator {
|
|
|
368
380
|
...this.getPRToolFilteringOptions(instructions),
|
|
369
381
|
context: {
|
|
370
382
|
sessionId,
|
|
371
|
-
userId: this.
|
|
383
|
+
userId: this.getUserId(request),
|
|
372
384
|
operation: "description-enhancement",
|
|
373
385
|
},
|
|
386
|
+
memory: { enabled: false },
|
|
374
387
|
enableAnalytics: true,
|
|
375
388
|
});
|
|
376
389
|
this.recordToolCallsFromResponse(sessionId, aiResponse);
|
|
@@ -404,9 +417,9 @@ export class YamaOrchestrator {
|
|
|
404
417
|
exportSession(sessionId) {
|
|
405
418
|
return this.sessionManager.exportSession(sessionId);
|
|
406
419
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
420
|
+
getUserId(request) {
|
|
421
|
+
return `${request.workspace}-${request.repository}`.toLowerCase();
|
|
422
|
+
}
|
|
410
423
|
createToolContext(sessionId, request) {
|
|
411
424
|
return {
|
|
412
425
|
sessionId,
|
|
@@ -825,14 +838,6 @@ export class YamaOrchestrator {
|
|
|
825
838
|
const parsed = Number(value);
|
|
826
839
|
return Number.isFinite(parsed) ? parsed : 0;
|
|
827
840
|
}
|
|
828
|
-
/**
|
|
829
|
-
* Generate userId for NeuroLink context from repository and branch/PR
|
|
830
|
-
*/
|
|
831
|
-
generateUserId(request) {
|
|
832
|
-
const repo = request.repository;
|
|
833
|
-
const identifier = request.branch || `pr-${request.pullRequestId}`;
|
|
834
|
-
return `${repo}-${identifier}`;
|
|
835
|
-
}
|
|
836
841
|
isLocalReviewRequest(request) {
|
|
837
842
|
return (request.mode === "local" ||
|
|
838
843
|
(!("workspace" in request) && !("repository" in request)));
|
|
@@ -912,8 +917,15 @@ export class YamaOrchestrator {
|
|
|
912
917
|
initializeNeurolink() {
|
|
913
918
|
try {
|
|
914
919
|
const observabilityConfig = buildObservabilityConfigFromEnv();
|
|
920
|
+
const conversationMemory = {
|
|
921
|
+
...this.config.ai.conversationMemory,
|
|
922
|
+
};
|
|
923
|
+
if (this.memoryManager) {
|
|
924
|
+
conversationMemory.memory =
|
|
925
|
+
this.memoryManager.buildNeuroLinkMemoryConfig();
|
|
926
|
+
}
|
|
915
927
|
const neurolinkConfig = {
|
|
916
|
-
conversationMemory
|
|
928
|
+
conversationMemory,
|
|
917
929
|
};
|
|
918
930
|
if (observabilityConfig) {
|
|
919
931
|
// Validate observability config
|
|
@@ -58,12 +58,22 @@ export interface KnowledgeBase {
|
|
|
58
58
|
/**
|
|
59
59
|
* Request for the learn command
|
|
60
60
|
*/
|
|
61
|
+
/**
|
|
62
|
+
* Controls which storage systems are committed after learning extraction.
|
|
63
|
+
* - "kb" — commit only the knowledge base file (existing behavior)
|
|
64
|
+
* - "memory" — commit only per-repo memory files (via NeuroLink + git push)
|
|
65
|
+
* - "all" — commit both knowledge base and per-repo memory
|
|
66
|
+
*/
|
|
67
|
+
export type LearnCommitMode = "kb" | "memory" | "all";
|
|
61
68
|
export interface LearnRequest {
|
|
62
69
|
workspace: string;
|
|
63
70
|
repository: string;
|
|
64
71
|
pullRequestId: number;
|
|
65
72
|
dryRun?: boolean;
|
|
73
|
+
/** @deprecated Use commitMode instead */
|
|
66
74
|
commit?: boolean;
|
|
75
|
+
/** Controls which storage systems are committed after extraction */
|
|
76
|
+
commitMode?: LearnCommitMode;
|
|
67
77
|
summarize?: boolean;
|
|
68
78
|
outputPath?: string;
|
|
69
79
|
outputFormat?: "md" | "json";
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Manager
|
|
3
|
+
*
|
|
4
|
+
* Provides per-repository condensed memory configuration for NeuroLink.
|
|
5
|
+
*
|
|
6
|
+
* This manager builds the NeuroLink-compatible memory SDK config with
|
|
7
|
+
* file-based custom storage, so that NeuroLink's generate()/stream() calls
|
|
8
|
+
* can retrieve and store memory using context.userId as the per-repo key.
|
|
9
|
+
*
|
|
10
|
+
* Callers control WHEN memory is read/written via per-call flags:
|
|
11
|
+
* memory: { enabled: true, read: true, write: false }
|
|
12
|
+
*
|
|
13
|
+
* This avoids noise from operational calls (e.g., fetching PR data)
|
|
14
|
+
* polluting the condensed memory.
|
|
15
|
+
*
|
|
16
|
+
* Storage: file-based (.yama/memory/{workspace}-{repository}.txt) (lowercased)
|
|
17
|
+
* Condensation: LLM-powered via NeuroLink's built-in Hippocampus
|
|
18
|
+
*/
|
|
19
|
+
import { MemoryConfig } from "../types/config.types.js";
|
|
20
|
+
export declare class MemoryManager {
|
|
21
|
+
private readonly config;
|
|
22
|
+
private readonly projectRoot;
|
|
23
|
+
private readonly aiProvider;
|
|
24
|
+
private readonly aiModel;
|
|
25
|
+
constructor(config: MemoryConfig, aiProvider: string, aiModel: string, projectRoot?: string);
|
|
26
|
+
/**
|
|
27
|
+
* Resolve the storage directory path (handles both absolute and relative paths).
|
|
28
|
+
*/
|
|
29
|
+
private resolveStorageDir;
|
|
30
|
+
/**
|
|
31
|
+
* Build the NeuroLink-compatible Memory config object.
|
|
32
|
+
*
|
|
33
|
+
* Passed to NeuroLink constructor as `conversationMemory.memory`.
|
|
34
|
+
* NeuroLink internally initializes Hippocampus with our file-based
|
|
35
|
+
* storage and review-specific condensation prompt.
|
|
36
|
+
*/
|
|
37
|
+
buildNeuroLinkMemoryConfig(): Record<string, unknown>;
|
|
38
|
+
/**
|
|
39
|
+
* Build a deterministic owner ID from workspace and repository.
|
|
40
|
+
* This value is passed as `context.userId` in generate() calls.
|
|
41
|
+
*/
|
|
42
|
+
static buildOwnerId(workspace: string, repository: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Commit memory files to the repository if autoCommit is enabled.
|
|
45
|
+
*
|
|
46
|
+
* Checks git status for changes in the storagePath directory,
|
|
47
|
+
* then stages, commits, and pushes. Uses [skip ci] to prevent
|
|
48
|
+
* infinite CI loops. Never throws — failures are logged and ignored
|
|
49
|
+
* so they never block the review result.
|
|
50
|
+
*/
|
|
51
|
+
commitMemoryChanges(): Promise<boolean>;
|
|
52
|
+
/**
|
|
53
|
+
* Map an ownerId to a safe file path.
|
|
54
|
+
*/
|
|
55
|
+
private ownerIdToFilePath;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=MemoryManager.d.ts.map
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Manager
|
|
3
|
+
*
|
|
4
|
+
* Provides per-repository condensed memory configuration for NeuroLink.
|
|
5
|
+
*
|
|
6
|
+
* This manager builds the NeuroLink-compatible memory SDK config with
|
|
7
|
+
* file-based custom storage, so that NeuroLink's generate()/stream() calls
|
|
8
|
+
* can retrieve and store memory using context.userId as the per-repo key.
|
|
9
|
+
*
|
|
10
|
+
* Callers control WHEN memory is read/written via per-call flags:
|
|
11
|
+
* memory: { enabled: true, read: true, write: false }
|
|
12
|
+
*
|
|
13
|
+
* This avoids noise from operational calls (e.g., fetching PR data)
|
|
14
|
+
* polluting the condensed memory.
|
|
15
|
+
*
|
|
16
|
+
* Storage: file-based (.yama/memory/{workspace}-{repository}.txt) (lowercased)
|
|
17
|
+
* Condensation: LLM-powered via NeuroLink's built-in Hippocampus
|
|
18
|
+
*/
|
|
19
|
+
import { readFile, writeFile, mkdir, unlink } from "fs/promises";
|
|
20
|
+
import { existsSync } from "fs";
|
|
21
|
+
import { join, dirname, isAbsolute } from "path";
|
|
22
|
+
import { execFile } from "child_process";
|
|
23
|
+
import { promisify } from "util";
|
|
24
|
+
const execFileAsync = promisify(execFile);
|
|
25
|
+
// ============================================================================
|
|
26
|
+
// Constants
|
|
27
|
+
// ============================================================================
|
|
28
|
+
/**
|
|
29
|
+
* Condensation prompt tailored for code review memory.
|
|
30
|
+
* Guides the LLM to retain review patterns, team conventions, and
|
|
31
|
+
* frequently flagged issues rather than individual PR details.
|
|
32
|
+
*/
|
|
33
|
+
const REVIEW_MEMORY_CONDENSATION_PROMPT = `You are a memory condensation engine for an AI code reviewer called Yama.
|
|
34
|
+
You receive:
|
|
35
|
+
1. OLD_MEMORY: the existing condensed memory for a specific repository (may be empty)
|
|
36
|
+
2. NEW_CONTENT: new information from a recent code review or learning extraction
|
|
37
|
+
|
|
38
|
+
Your job: merge old memory with the new information into a single condensed summary.
|
|
39
|
+
|
|
40
|
+
Rules:
|
|
41
|
+
- Output ONLY the condensed memory text, nothing else
|
|
42
|
+
- Maximum {{MAX_WORDS}} words
|
|
43
|
+
- PRIORITIZE retaining (most important first):
|
|
44
|
+
1. False positive patterns: things the team confirmed are NOT issues
|
|
45
|
+
2. Team coding conventions and style preferences
|
|
46
|
+
3. Recurring review themes and common issue categories
|
|
47
|
+
4. Repository-specific domain knowledge and architecture decisions
|
|
48
|
+
5. Patterns the AI missed that developers caught
|
|
49
|
+
6. Review outcome trends (approval rate, common blocking reasons)
|
|
50
|
+
- DROP: individual PR numbers, timestamps, one-off issues, greeting text
|
|
51
|
+
- Keep learnings GENERIC and applicable to future reviews
|
|
52
|
+
- If NEW_CONTENT has nothing worth remembering, return OLD_MEMORY unchanged
|
|
53
|
+
- If both are empty, return empty string`;
|
|
54
|
+
// ============================================================================
|
|
55
|
+
// Manager
|
|
56
|
+
// ============================================================================
|
|
57
|
+
export class MemoryManager {
|
|
58
|
+
config;
|
|
59
|
+
projectRoot;
|
|
60
|
+
aiProvider;
|
|
61
|
+
aiModel;
|
|
62
|
+
constructor(config, aiProvider, aiModel, projectRoot) {
|
|
63
|
+
this.config = config;
|
|
64
|
+
this.aiProvider = aiProvider;
|
|
65
|
+
this.aiModel = aiModel;
|
|
66
|
+
this.projectRoot = projectRoot || process.cwd();
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Resolve the storage directory path (handles both absolute and relative paths).
|
|
70
|
+
*/
|
|
71
|
+
resolveStorageDir() {
|
|
72
|
+
return isAbsolute(this.config.storagePath)
|
|
73
|
+
? this.config.storagePath
|
|
74
|
+
: join(this.projectRoot, this.config.storagePath);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Build the NeuroLink-compatible Memory config object.
|
|
78
|
+
*
|
|
79
|
+
* Passed to NeuroLink constructor as `conversationMemory.memory`.
|
|
80
|
+
* NeuroLink internally initializes Hippocampus with our file-based
|
|
81
|
+
* storage and review-specific condensation prompt.
|
|
82
|
+
*/
|
|
83
|
+
buildNeuroLinkMemoryConfig() {
|
|
84
|
+
const storageDir = this.resolveStorageDir();
|
|
85
|
+
return {
|
|
86
|
+
enabled: true,
|
|
87
|
+
storage: this.config.storage || {
|
|
88
|
+
type: "custom",
|
|
89
|
+
onGet: async (ownerId) => {
|
|
90
|
+
const filePath = this.ownerIdToFilePath(storageDir, ownerId);
|
|
91
|
+
if (!existsSync(filePath)) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
return await readFile(filePath, "utf-8");
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
onSet: async (ownerId, memory) => {
|
|
102
|
+
const filePath = this.ownerIdToFilePath(storageDir, ownerId);
|
|
103
|
+
const dir = dirname(filePath);
|
|
104
|
+
if (!existsSync(dir)) {
|
|
105
|
+
await mkdir(dir, { recursive: true });
|
|
106
|
+
}
|
|
107
|
+
await writeFile(filePath, memory, "utf-8");
|
|
108
|
+
},
|
|
109
|
+
onDelete: async (ownerId) => {
|
|
110
|
+
const filePath = this.ownerIdToFilePath(storageDir, ownerId);
|
|
111
|
+
if (existsSync(filePath)) {
|
|
112
|
+
await unlink(filePath);
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
neurolink: this.config.neurolink || {
|
|
117
|
+
provider: this.aiProvider,
|
|
118
|
+
model: this.aiModel,
|
|
119
|
+
temperature: 0.1,
|
|
120
|
+
},
|
|
121
|
+
maxWords: this.config.maxWords,
|
|
122
|
+
prompt: this.config.prompt || REVIEW_MEMORY_CONDENSATION_PROMPT,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Build a deterministic owner ID from workspace and repository.
|
|
127
|
+
* This value is passed as `context.userId` in generate() calls.
|
|
128
|
+
*/
|
|
129
|
+
static buildOwnerId(workspace, repository) {
|
|
130
|
+
return `${workspace}-${repository}`.toLowerCase();
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Commit memory files to the repository if autoCommit is enabled.
|
|
134
|
+
*
|
|
135
|
+
* Checks git status for changes in the storagePath directory,
|
|
136
|
+
* then stages, commits, and pushes. Uses [skip ci] to prevent
|
|
137
|
+
* infinite CI loops. Never throws — failures are logged and ignored
|
|
138
|
+
* so they never block the review result.
|
|
139
|
+
*/
|
|
140
|
+
async commitMemoryChanges() {
|
|
141
|
+
if (!this.config.autoCommit) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
const storageDir = this.resolveStorageDir();
|
|
145
|
+
if (!existsSync(storageDir)) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
// Check if there are any changes to commit
|
|
150
|
+
const { stdout: statusOutput } = await execFileAsync("git", ["status", "--porcelain", storageDir], { cwd: this.projectRoot });
|
|
151
|
+
if (!statusOutput.trim()) {
|
|
152
|
+
console.log(" 🧠 No memory changes to commit");
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
const commitMessage = this.config.commitMessage ||
|
|
156
|
+
"chore: update yama review memory [skip ci]";
|
|
157
|
+
// Stage memory files
|
|
158
|
+
await execFileAsync("git", ["add", storageDir], {
|
|
159
|
+
cwd: this.projectRoot,
|
|
160
|
+
});
|
|
161
|
+
// Commit with [skip ci] to prevent infinite loops
|
|
162
|
+
await execFileAsync("git", ["commit", "-m", commitMessage], {
|
|
163
|
+
cwd: this.projectRoot,
|
|
164
|
+
});
|
|
165
|
+
// Push to the current branch
|
|
166
|
+
await execFileAsync("git", ["push"], {
|
|
167
|
+
cwd: this.projectRoot,
|
|
168
|
+
});
|
|
169
|
+
console.log(" 🧠 Memory changes committed and pushed");
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
console.warn(` ⚠️ Memory auto-commit failed: ${error.message}`);
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Map an ownerId to a safe file path.
|
|
179
|
+
*/
|
|
180
|
+
ownerIdToFilePath(storageDir, ownerId) {
|
|
181
|
+
const safeId = ownerId.replace(/[^a-zA-Z0-9-]/g, "-");
|
|
182
|
+
return join(storageDir, `${safeId}.md`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=MemoryManager.js.map
|
|
@@ -12,6 +12,7 @@ export interface YamaConfig {
|
|
|
12
12
|
descriptionEnhancement: DescriptionEnhancementConfig;
|
|
13
13
|
memoryBank: MemoryBankConfig;
|
|
14
14
|
knowledgeBase: KnowledgeBaseConfig;
|
|
15
|
+
memory: MemoryConfig;
|
|
15
16
|
projectStandards?: ProjectStandardsConfig;
|
|
16
17
|
monitoring: MonitoringConfig;
|
|
17
18
|
performance: PerformanceConfig;
|
|
@@ -114,6 +115,56 @@ export interface KnowledgeBaseConfig {
|
|
|
114
115
|
/** Auto-commit knowledge base changes (default for --commit flag) */
|
|
115
116
|
autoCommit: boolean;
|
|
116
117
|
}
|
|
118
|
+
/** Storage backend configuration for Hippocampus memory */
|
|
119
|
+
export type MemoryStorageConfig = {
|
|
120
|
+
type: "sqlite";
|
|
121
|
+
path?: string;
|
|
122
|
+
} | {
|
|
123
|
+
type: "redis";
|
|
124
|
+
host?: string;
|
|
125
|
+
port?: number;
|
|
126
|
+
password?: string;
|
|
127
|
+
db?: number;
|
|
128
|
+
keyPrefix?: string;
|
|
129
|
+
ttl?: number;
|
|
130
|
+
} | {
|
|
131
|
+
type: "s3";
|
|
132
|
+
bucket: string;
|
|
133
|
+
prefix?: string;
|
|
134
|
+
} | {
|
|
135
|
+
type: "custom";
|
|
136
|
+
onGet: (ownerId: string) => Promise<string | null>;
|
|
137
|
+
onSet: (ownerId: string, memory: string) => Promise<void>;
|
|
138
|
+
onDelete: (ownerId: string) => Promise<void>;
|
|
139
|
+
onClose?: () => Promise<void>;
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* Yama-specific memory configuration.
|
|
143
|
+
* Mirrors NeuroLink's Memory type (HippocampusConfig & { enabled }) with
|
|
144
|
+
* Yama-specific fields for file-based storage.
|
|
145
|
+
*/
|
|
146
|
+
export interface MemoryConfig {
|
|
147
|
+
/** Enable per-repo condensed memory feature */
|
|
148
|
+
enabled: boolean;
|
|
149
|
+
/** Directory for file-based memory storage (relative to project root) */
|
|
150
|
+
storagePath: string;
|
|
151
|
+
/** Maximum word count for condensed memory per repository (default: 50) */
|
|
152
|
+
maxWords?: number;
|
|
153
|
+
/** Custom condensation prompt (overrides default review-specific prompt) */
|
|
154
|
+
prompt?: string;
|
|
155
|
+
/** Storage backend configuration (default: file-based custom storage managed by Yama) */
|
|
156
|
+
storage?: MemoryStorageConfig;
|
|
157
|
+
/** AI provider/model for memory condensation (defaults to main AI provider) */
|
|
158
|
+
neurolink?: {
|
|
159
|
+
provider?: string;
|
|
160
|
+
model?: string;
|
|
161
|
+
temperature?: number;
|
|
162
|
+
};
|
|
163
|
+
/** Auto-commit memory files to the repo after review (default: false) */
|
|
164
|
+
autoCommit?: boolean;
|
|
165
|
+
/** Git commit message for memory auto-commits (default: "chore: update yama review memory [skip ci]") */
|
|
166
|
+
commitMessage?: string;
|
|
167
|
+
}
|
|
117
168
|
export interface ProjectStandardsConfig {
|
|
118
169
|
customPromptsPath: string;
|
|
119
170
|
additionalFocusAreas: FocusArea[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/yama",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Enterprise-grade Pull Request automation toolkit with AI-powered code review and description enhancement",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pr",
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"check:all": "npm run lint && npm run format --check && npm run validate && npm run validate:commit"
|
|
90
90
|
},
|
|
91
91
|
"dependencies": {
|
|
92
|
-
"@juspay/neurolink": "^9.
|
|
92
|
+
"@juspay/neurolink": "^9.42.0",
|
|
93
93
|
"langfuse": "^3.35.0",
|
|
94
94
|
"@nexus2520/bitbucket-mcp-server": "2.0.1",
|
|
95
95
|
"@nexus2520/jira-mcp-server": "^1.1.1",
|
package/yama.config.example.yaml
CHANGED
|
@@ -231,6 +231,21 @@ knowledgeBase:
|
|
|
231
231
|
# Automatically commit knowledge base changes (with --commit flag)
|
|
232
232
|
autoCommit: false
|
|
233
233
|
|
|
234
|
+
# Per-repo condensed memory
|
|
235
|
+
# Memory accumulates durable facts about each repository across reviews
|
|
236
|
+
memory:
|
|
237
|
+
enabled: true
|
|
238
|
+
storagePath: ".yama/memory"
|
|
239
|
+
# Maximum word count for condensed memory per repository (default: 50)
|
|
240
|
+
maxWords: 200
|
|
241
|
+
# prompt: "Your custom condensation prompt here..."
|
|
242
|
+
# neurolink:
|
|
243
|
+
# provider: google-ai
|
|
244
|
+
# model: gemini-2.0-flash
|
|
245
|
+
# temperature: 0.1
|
|
246
|
+
autoCommit: true # Auto-commit memory files to repo after each review (persists across CI builds)
|
|
247
|
+
# commitMessage: "chore: update yama review memory [skip ci]"
|
|
248
|
+
|
|
234
249
|
# ============================================================================
|
|
235
250
|
# Project-Specific Standards (Override in your repository)
|
|
236
251
|
# ============================================================================
|