@juspay/yama 2.2.2 ā 2.4.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/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 +72 -4
- package/dist/v2/config/DefaultConfig.js +14 -0
- package/dist/v2/core/LearningOrchestrator.d.ts +1 -0
- package/dist/v2/core/LearningOrchestrator.js +64 -4
- package/dist/v2/core/SessionManager.d.ts +3 -1
- package/dist/v2/core/SessionManager.js +30 -0
- package/dist/v2/core/YamaV2Orchestrator.d.ts +16 -7
- package/dist/v2/core/YamaV2Orchestrator.js +213 -35
- package/dist/v2/exploration/ContextExplorerService.d.ts +39 -0
- package/dist/v2/exploration/ContextExplorerService.js +451 -0
- package/dist/v2/exploration/ExplorerPromptBuilder.d.ts +5 -0
- package/dist/v2/exploration/ExplorerPromptBuilder.js +67 -0
- package/dist/v2/exploration/RulesContextLoader.d.ts +12 -0
- package/dist/v2/exploration/RulesContextLoader.js +106 -0
- package/dist/v2/exploration/types.d.ts +26 -0
- package/dist/v2/exploration/types.js +2 -0
- package/dist/v2/learning/types.d.ts +10 -0
- package/dist/v2/memory/MemoryManager.d.ts +65 -0
- package/dist/v2/memory/MemoryManager.js +207 -0
- package/dist/v2/prompts/LangfusePromptManager.js +6 -0
- package/dist/v2/prompts/PromptBuilder.d.ts +18 -1
- package/dist/v2/prompts/PromptBuilder.js +131 -29
- package/dist/v2/prompts/ReviewSystemPrompt.d.ts +9 -4
- package/dist/v2/prompts/ReviewSystemPrompt.js +46 -239
- package/dist/v2/types/config.types.d.ts +70 -1
- package/dist/v2/types/v2.types.d.ts +28 -0
- package/package.json +3 -3
- package/yama.config.example.yaml +25 -0
|
@@ -7,20 +7,27 @@ 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";
|
|
12
|
+
import { ContextExplorerService } from "../exploration/ContextExplorerService.js";
|
|
11
13
|
import { buildObservabilityConfigFromEnv, validateObservabilityConfig, } from "../utils/ObservabilityConfig.js";
|
|
12
14
|
export class YamaOrchestrator {
|
|
13
15
|
neurolink;
|
|
16
|
+
explorer = null;
|
|
14
17
|
mcpManager;
|
|
15
18
|
configLoader;
|
|
16
19
|
promptBuilder;
|
|
17
20
|
sessionManager;
|
|
21
|
+
memoryManager = null;
|
|
18
22
|
localDiffSource;
|
|
19
23
|
config;
|
|
20
24
|
initialized = false;
|
|
21
25
|
mcpInitialized = false;
|
|
22
26
|
localGitMcpInitialized = false;
|
|
27
|
+
exploreToolRegistered = false;
|
|
28
|
+
currentToolContext = null;
|
|
23
29
|
initOptions;
|
|
30
|
+
bootstrapStandardsCache = new Map();
|
|
24
31
|
constructor(options = {}) {
|
|
25
32
|
this.initOptions = options;
|
|
26
33
|
this.configLoader = new ConfigLoader();
|
|
@@ -40,22 +47,35 @@ export class YamaOrchestrator {
|
|
|
40
47
|
const resolvedConfigPath = configPath || this.initOptions.configPath;
|
|
41
48
|
this.config = await this.configLoader.loadConfig(resolvedConfigPath, this.initOptions.configOverrides);
|
|
42
49
|
this.showBanner();
|
|
43
|
-
// Step 2: Initialize
|
|
50
|
+
// Step 2: Initialize
|
|
51
|
+
if (this.config.memory?.enabled) {
|
|
52
|
+
this.memoryManager = new MemoryManager(this.config.memory, this.config.ai.provider, this.config.ai.model);
|
|
53
|
+
console.log(" š§ Per-repo memory enabled\n");
|
|
54
|
+
}
|
|
55
|
+
// Step 3: Initialize NeuroLink with memory config injected
|
|
44
56
|
console.log("š§ Initializing NeuroLink AI engine...");
|
|
45
57
|
this.neurolink = this.initializeNeurolink();
|
|
58
|
+
this.explorer = new ContextExplorerService(this.config, this.sessionManager, this.memoryManager);
|
|
59
|
+
this.registerExploreTool();
|
|
46
60
|
console.log("ā
NeuroLink initialized\n");
|
|
47
61
|
this.initialized = true;
|
|
48
62
|
}
|
|
49
|
-
// Step
|
|
63
|
+
// Step 4: Mode-specific setup
|
|
50
64
|
if (mode === "pr" && !this.mcpInitialized) {
|
|
51
65
|
await this.mcpManager.setupMCPServers(this.neurolink, this.config.mcpServers);
|
|
66
|
+
if (this.explorer && this.config.ai.explore.enabled) {
|
|
67
|
+
await this.explorer.initialize("pr");
|
|
68
|
+
}
|
|
52
69
|
this.mcpInitialized = true;
|
|
53
70
|
}
|
|
54
71
|
else if (mode === "local" && !this.localGitMcpInitialized) {
|
|
55
72
|
await this.mcpManager.setupLocalGitMCPServer(this.neurolink);
|
|
73
|
+
if (this.explorer && this.config.ai.explore.enabled) {
|
|
74
|
+
await this.explorer.initialize("local");
|
|
75
|
+
}
|
|
56
76
|
this.localGitMcpInitialized = true;
|
|
57
77
|
}
|
|
58
|
-
// Step
|
|
78
|
+
// Step 5: Mode-specific validation
|
|
59
79
|
await this.configLoader.validate(mode);
|
|
60
80
|
console.log("ā
Yama initialized successfully\n");
|
|
61
81
|
console.log("ā".repeat(60) + "\n");
|
|
@@ -74,8 +94,9 @@ export class YamaOrchestrator {
|
|
|
74
94
|
const sessionId = this.sessionManager.createSession(request);
|
|
75
95
|
this.logReviewStart(request, sessionId);
|
|
76
96
|
try {
|
|
97
|
+
const bootstrapStandards = await this.getBootstrappedStandards(request, sessionId);
|
|
77
98
|
// Build comprehensive AI instructions
|
|
78
|
-
const instructions = await this.promptBuilder.buildReviewInstructions(request, this.config);
|
|
99
|
+
const instructions = await this.promptBuilder.buildReviewInstructions(request, this.config, bootstrapStandards);
|
|
79
100
|
if (this.config.display.verboseToolCalls) {
|
|
80
101
|
console.log("\nš AI Instructions built:");
|
|
81
102
|
console.log(` Instruction length: ${instructions.length} characters\n`);
|
|
@@ -83,7 +104,7 @@ export class YamaOrchestrator {
|
|
|
83
104
|
// Create tool context for AI
|
|
84
105
|
const toolContext = this.createToolContext(sessionId, request);
|
|
85
106
|
// Set tool context in NeuroLink (using type assertion as setToolContext is documented but may not be in type definitions)
|
|
86
|
-
this.
|
|
107
|
+
this.setToolContext(toolContext);
|
|
87
108
|
// Update session metadata
|
|
88
109
|
this.sessionManager.updateMetadata(sessionId, {
|
|
89
110
|
aiProvider: this.config.ai.provider,
|
|
@@ -92,6 +113,7 @@ export class YamaOrchestrator {
|
|
|
92
113
|
// Execute autonomous AI review
|
|
93
114
|
console.log("š¤ Starting autonomous AI review...");
|
|
94
115
|
console.log(" AI will now make decisions and execute actions autonomously\n");
|
|
116
|
+
// Review call: RETRIEVE memory (for context), but DON'T STORE
|
|
95
117
|
const aiResponse = await this.neurolink.generate({
|
|
96
118
|
input: { text: instructions },
|
|
97
119
|
provider: this.config.ai.provider,
|
|
@@ -103,10 +125,11 @@ export class YamaOrchestrator {
|
|
|
103
125
|
...this.getPRToolFilteringOptions(instructions),
|
|
104
126
|
context: {
|
|
105
127
|
sessionId,
|
|
106
|
-
userId: this.
|
|
128
|
+
userId: this.getUserId(request),
|
|
107
129
|
operation: "code-review",
|
|
108
130
|
metadata: toolContext.metadata,
|
|
109
131
|
},
|
|
132
|
+
memory: { read: true, write: false },
|
|
110
133
|
enableAnalytics: this.config.ai.enableAnalytics,
|
|
111
134
|
enableEvaluation: this.config.ai.enableEvaluation,
|
|
112
135
|
});
|
|
@@ -152,19 +175,14 @@ export class YamaOrchestrator {
|
|
|
152
175
|
try {
|
|
153
176
|
const diffContext = this.localDiffSource.getDiffContext(request);
|
|
154
177
|
const instructions = await this.promptBuilder.buildLocalReviewInstructions(request, this.config, diffContext);
|
|
178
|
+
const toolContext = this.createLocalToolContext(sessionId, pseudoRequest, diffContext);
|
|
179
|
+
this.setToolContext(toolContext);
|
|
155
180
|
const aiResponse = await this.neurolink.generate({
|
|
156
181
|
input: { text: instructions },
|
|
157
182
|
provider: this.config.ai.provider,
|
|
158
183
|
model: this.config.ai.model,
|
|
159
184
|
temperature: this.config.ai.temperature,
|
|
160
185
|
maxTokens: Math.min(this.config.ai.maxTokens, 16_000),
|
|
161
|
-
maxSteps: 100,
|
|
162
|
-
prepareStep: async ({ stepNumber }) => {
|
|
163
|
-
if (stepNumber >= 5) {
|
|
164
|
-
return { toolChoice: "none" };
|
|
165
|
-
}
|
|
166
|
-
return undefined;
|
|
167
|
-
},
|
|
168
186
|
timeout: this.config.ai.timeout,
|
|
169
187
|
enableAnalytics: this.config.ai.enableAnalytics,
|
|
170
188
|
enableEvaluation: this.config.ai.enableEvaluation,
|
|
@@ -175,7 +193,7 @@ export class YamaOrchestrator {
|
|
|
175
193
|
...this.getLocalToolFilteringOptions(),
|
|
176
194
|
context: {
|
|
177
195
|
sessionId,
|
|
178
|
-
userId:
|
|
196
|
+
userId: this.getUserId(pseudoRequest),
|
|
179
197
|
operation: "local-review",
|
|
180
198
|
metadata: {
|
|
181
199
|
repoPath: diffContext.repoPath,
|
|
@@ -203,11 +221,12 @@ export class YamaOrchestrator {
|
|
|
203
221
|
await this.ensureInitialized("pr", request.configPath);
|
|
204
222
|
const sessionId = this.sessionManager.createSession(request);
|
|
205
223
|
try {
|
|
224
|
+
const bootstrapStandards = await this.getBootstrappedStandards(request, sessionId);
|
|
206
225
|
// Build instructions
|
|
207
|
-
const instructions = await this.promptBuilder.buildReviewInstructions(request, this.config);
|
|
226
|
+
const instructions = await this.promptBuilder.buildReviewInstructions(request, this.config, bootstrapStandards);
|
|
208
227
|
// Create tool context
|
|
209
228
|
const toolContext = this.createToolContext(sessionId, request);
|
|
210
|
-
this.
|
|
229
|
+
this.setToolContext(toolContext);
|
|
211
230
|
// Stream AI execution
|
|
212
231
|
yield {
|
|
213
232
|
type: "progress",
|
|
@@ -229,8 +248,9 @@ export class YamaOrchestrator {
|
|
|
229
248
|
...this.getPRToolFilteringOptions(instructions),
|
|
230
249
|
context: {
|
|
231
250
|
sessionId,
|
|
232
|
-
userId: this.
|
|
251
|
+
userId: this.getUserId(request),
|
|
233
252
|
},
|
|
253
|
+
memory: { enabled: false },
|
|
234
254
|
enableAnalytics: true,
|
|
235
255
|
});
|
|
236
256
|
yield {
|
|
@@ -262,15 +282,16 @@ export class YamaOrchestrator {
|
|
|
262
282
|
// ========================================================================
|
|
263
283
|
// PHASE 1: Code Review
|
|
264
284
|
// ========================================================================
|
|
285
|
+
const bootstrapStandards = await this.getBootstrappedStandards(request, sessionId);
|
|
265
286
|
// Build review instructions
|
|
266
|
-
const reviewInstructions = await this.promptBuilder.buildReviewInstructions(request, this.config);
|
|
287
|
+
const reviewInstructions = await this.promptBuilder.buildReviewInstructions(request, this.config, bootstrapStandards);
|
|
267
288
|
if (this.config.display.verboseToolCalls) {
|
|
268
289
|
console.log("\nš Review instructions built:");
|
|
269
290
|
console.log(` Instruction length: ${reviewInstructions.length} characters\n`);
|
|
270
291
|
}
|
|
271
292
|
// Create tool context
|
|
272
293
|
const toolContext = this.createToolContext(sessionId, request);
|
|
273
|
-
this.
|
|
294
|
+
this.setToolContext(toolContext);
|
|
274
295
|
// Update session metadata
|
|
275
296
|
this.sessionManager.updateMetadata(sessionId, {
|
|
276
297
|
aiProvider: this.config.ai.provider,
|
|
@@ -290,10 +311,11 @@ export class YamaOrchestrator {
|
|
|
290
311
|
...this.getPRToolFilteringOptions(reviewInstructions),
|
|
291
312
|
context: {
|
|
292
313
|
sessionId,
|
|
293
|
-
userId: this.
|
|
314
|
+
userId: this.getUserId(request),
|
|
294
315
|
operation: "code-review",
|
|
295
316
|
metadata: toolContext.metadata,
|
|
296
317
|
},
|
|
318
|
+
memory: { read: true, write: false },
|
|
297
319
|
enableAnalytics: this.config.ai.enableAnalytics,
|
|
298
320
|
enableEvaluation: this.config.ai.enableEvaluation,
|
|
299
321
|
});
|
|
@@ -322,10 +344,11 @@ export class YamaOrchestrator {
|
|
|
322
344
|
...this.getPRToolFilteringOptions(enhanceInstructions),
|
|
323
345
|
context: {
|
|
324
346
|
sessionId, // SAME sessionId = AI remembers review context
|
|
325
|
-
userId: this.
|
|
347
|
+
userId: this.getUserId(request),
|
|
326
348
|
operation: "description-enhancement",
|
|
327
349
|
metadata: toolContext.metadata,
|
|
328
350
|
},
|
|
351
|
+
memory: { enabled: false },
|
|
329
352
|
enableAnalytics: this.config.ai.enableAnalytics,
|
|
330
353
|
enableEvaluation: this.config.ai.enableEvaluation,
|
|
331
354
|
});
|
|
@@ -359,7 +382,7 @@ export class YamaOrchestrator {
|
|
|
359
382
|
console.log("\nš Enhancing PR description...\n");
|
|
360
383
|
const instructions = await this.promptBuilder.buildDescriptionEnhancementInstructions(request, this.config);
|
|
361
384
|
const toolContext = this.createToolContext(sessionId, request);
|
|
362
|
-
this.
|
|
385
|
+
this.setToolContext(toolContext);
|
|
363
386
|
const aiResponse = await this.neurolink.generate({
|
|
364
387
|
input: { text: instructions },
|
|
365
388
|
provider: this.config.ai.provider,
|
|
@@ -368,9 +391,10 @@ export class YamaOrchestrator {
|
|
|
368
391
|
...this.getPRToolFilteringOptions(instructions),
|
|
369
392
|
context: {
|
|
370
393
|
sessionId,
|
|
371
|
-
userId: this.
|
|
394
|
+
userId: this.getUserId(request),
|
|
372
395
|
operation: "description-enhancement",
|
|
373
396
|
},
|
|
397
|
+
memory: { enabled: false },
|
|
374
398
|
enableAnalytics: true,
|
|
375
399
|
});
|
|
376
400
|
this.recordToolCallsFromResponse(sessionId, aiResponse);
|
|
@@ -404,12 +428,13 @@ export class YamaOrchestrator {
|
|
|
404
428
|
exportSession(sessionId) {
|
|
405
429
|
return this.sessionManager.exportSession(sessionId);
|
|
406
430
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
431
|
+
getUserId(request) {
|
|
432
|
+
return `${request.workspace}-${request.repository}`.toLowerCase();
|
|
433
|
+
}
|
|
410
434
|
createToolContext(sessionId, request) {
|
|
411
435
|
return {
|
|
412
436
|
sessionId,
|
|
437
|
+
mode: "pr",
|
|
413
438
|
workspace: request.workspace,
|
|
414
439
|
repository: request.repository,
|
|
415
440
|
pullRequestId: request.pullRequestId,
|
|
@@ -421,6 +446,27 @@ export class YamaOrchestrator {
|
|
|
421
446
|
},
|
|
422
447
|
};
|
|
423
448
|
}
|
|
449
|
+
createLocalToolContext(sessionId, request, diffContext) {
|
|
450
|
+
return {
|
|
451
|
+
sessionId,
|
|
452
|
+
mode: "local",
|
|
453
|
+
workspace: request.workspace,
|
|
454
|
+
repository: request.repository,
|
|
455
|
+
dryRun: request.dryRun || false,
|
|
456
|
+
metadata: {
|
|
457
|
+
yamaVersion: "2.2.1",
|
|
458
|
+
startTime: new Date().toISOString(),
|
|
459
|
+
repoPath: diffContext.repoPath,
|
|
460
|
+
diffSource: diffContext.diffSource,
|
|
461
|
+
baseRef: diffContext.baseRef,
|
|
462
|
+
headRef: diffContext.headRef,
|
|
463
|
+
},
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
setToolContext(context) {
|
|
467
|
+
this.currentToolContext = context;
|
|
468
|
+
this.neurolink.setToolContext(context);
|
|
469
|
+
}
|
|
424
470
|
/**
|
|
425
471
|
* Parse AI response into structured review result
|
|
426
472
|
*/
|
|
@@ -825,14 +871,6 @@ export class YamaOrchestrator {
|
|
|
825
871
|
const parsed = Number(value);
|
|
826
872
|
return Number.isFinite(parsed) ? parsed : 0;
|
|
827
873
|
}
|
|
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
874
|
isLocalReviewRequest(request) {
|
|
837
875
|
return (request.mode === "local" ||
|
|
838
876
|
(!("workspace" in request) && !("repository" in request)));
|
|
@@ -912,8 +950,15 @@ export class YamaOrchestrator {
|
|
|
912
950
|
initializeNeurolink() {
|
|
913
951
|
try {
|
|
914
952
|
const observabilityConfig = buildObservabilityConfigFromEnv();
|
|
953
|
+
const conversationMemory = {
|
|
954
|
+
...this.config.ai.conversationMemory,
|
|
955
|
+
};
|
|
956
|
+
if (this.memoryManager) {
|
|
957
|
+
conversationMemory.memory =
|
|
958
|
+
this.memoryManager.buildNeuroLinkMemoryConfig();
|
|
959
|
+
}
|
|
915
960
|
const neurolinkConfig = {
|
|
916
|
-
conversationMemory
|
|
961
|
+
conversationMemory,
|
|
917
962
|
};
|
|
918
963
|
if (observabilityConfig) {
|
|
919
964
|
// Validate observability config
|
|
@@ -934,6 +979,139 @@ export class YamaOrchestrator {
|
|
|
934
979
|
throw new Error(`NeuroLink initialization failed: ${error}`);
|
|
935
980
|
}
|
|
936
981
|
}
|
|
982
|
+
registerExploreTool() {
|
|
983
|
+
if (this.exploreToolRegistered || !this.config.ai.explore.enabled) {
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
986
|
+
this.neurolink.registerTool("explore_context", {
|
|
987
|
+
name: "explore_context",
|
|
988
|
+
description: "Delegate non-trivial research to an isolated Explore worker. Use it for function definitions, project-wide search, logic tracing, commit history, rules/context lookup, or any analysis that would otherwise require broad manual scanning.",
|
|
989
|
+
inputSchema: {
|
|
990
|
+
type: "object",
|
|
991
|
+
properties: {
|
|
992
|
+
task: {
|
|
993
|
+
type: "string",
|
|
994
|
+
description: "The exact research task for Explore to investigate and answer.",
|
|
995
|
+
},
|
|
996
|
+
focus: {
|
|
997
|
+
type: "array",
|
|
998
|
+
description: "Optional list of files, symbols, commits, tickets, or context areas Explore should prioritize.",
|
|
999
|
+
items: {
|
|
1000
|
+
type: "string",
|
|
1001
|
+
},
|
|
1002
|
+
},
|
|
1003
|
+
},
|
|
1004
|
+
required: ["task"],
|
|
1005
|
+
},
|
|
1006
|
+
execute: async (params, context) => {
|
|
1007
|
+
if (!this.explorer) {
|
|
1008
|
+
throw new Error("Explore service is not initialized");
|
|
1009
|
+
}
|
|
1010
|
+
const rawParams = (params || {});
|
|
1011
|
+
const mergedContext = {
|
|
1012
|
+
...(this.currentToolContext || {}),
|
|
1013
|
+
...(context && typeof context === "object"
|
|
1014
|
+
? context
|
|
1015
|
+
: {}),
|
|
1016
|
+
};
|
|
1017
|
+
const runtimeMode = mergedContext.mode === "local" ? "local" : "pr";
|
|
1018
|
+
const runtimeContext = {
|
|
1019
|
+
sessionId: String(mergedContext.sessionId || this.currentToolContext?.sessionId || ""),
|
|
1020
|
+
mode: runtimeMode,
|
|
1021
|
+
workspace: String(mergedContext.workspace || "local"),
|
|
1022
|
+
repository: String(mergedContext.repository || "repository"),
|
|
1023
|
+
pullRequestId: typeof mergedContext.pullRequestId === "number"
|
|
1024
|
+
? mergedContext.pullRequestId
|
|
1025
|
+
: undefined,
|
|
1026
|
+
branch: typeof mergedContext.branch === "string"
|
|
1027
|
+
? mergedContext.branch
|
|
1028
|
+
: undefined,
|
|
1029
|
+
dryRun: typeof mergedContext.dryRun === "boolean"
|
|
1030
|
+
? mergedContext.dryRun
|
|
1031
|
+
: false,
|
|
1032
|
+
metadata: mergedContext.metadata &&
|
|
1033
|
+
typeof mergedContext.metadata === "object" &&
|
|
1034
|
+
!Array.isArray(mergedContext.metadata)
|
|
1035
|
+
? mergedContext.metadata
|
|
1036
|
+
: {},
|
|
1037
|
+
};
|
|
1038
|
+
const focus = Array.isArray(rawParams.focus)
|
|
1039
|
+
? rawParams.focus.filter((value) => typeof value === "string")
|
|
1040
|
+
: undefined;
|
|
1041
|
+
const { result, cached } = await this.explorer.explore({
|
|
1042
|
+
task: String(rawParams.task || "").trim(),
|
|
1043
|
+
focus,
|
|
1044
|
+
}, runtimeContext);
|
|
1045
|
+
return {
|
|
1046
|
+
success: true,
|
|
1047
|
+
data: {
|
|
1048
|
+
...result,
|
|
1049
|
+
cached,
|
|
1050
|
+
},
|
|
1051
|
+
};
|
|
1052
|
+
},
|
|
1053
|
+
});
|
|
1054
|
+
this.exploreToolRegistered = true;
|
|
1055
|
+
}
|
|
1056
|
+
/**
|
|
1057
|
+
* Bootstrap repo-level standards by delegating to explore_context.
|
|
1058
|
+
* Runs once per (workspace/repository) per process lifetime.
|
|
1059
|
+
* Output is injected into the review prompt as <bootstrapped-standards>.
|
|
1060
|
+
* Graceful: any failure returns empty and the review proceeds without it.
|
|
1061
|
+
*/
|
|
1062
|
+
async getBootstrappedStandards(request, sessionId) {
|
|
1063
|
+
if (!this.config.ai.explore.enabled || !this.explorer) {
|
|
1064
|
+
return "";
|
|
1065
|
+
}
|
|
1066
|
+
const cacheKey = `${request.workspace}/${request.repository}`.toLowerCase();
|
|
1067
|
+
const cached = this.bootstrapStandardsCache.get(cacheKey);
|
|
1068
|
+
if (cached !== undefined) {
|
|
1069
|
+
return cached;
|
|
1070
|
+
}
|
|
1071
|
+
const task = `Bootstrap repo review standards for ${request.workspace}/${request.repository}. Inspect the last 15 merged pull requests on this repository. For each, collect inline and summary comments left by HUMAN reviewers (ignore bot authors like "Yama", "yama-bot", "yama-review", "euler.bot"). Focus on comments that asked for code changes, flagged bugs, pushed back on an approach, or cited a convention. Distill the recurring patterns and anti-patterns the human reviewers care about ā especially things that a static config rule set would miss (naming, error-handling idioms, module boundaries, test expectations, migration rules, review etiquette). Return a concise bullet list of 10-20 patterns. Each bullet: one sentence stating the pattern, optionally one sentence of rationale. Do NOT include PR numbers, author names, or raw quotes ā just distilled patterns.`;
|
|
1072
|
+
try {
|
|
1073
|
+
console.log(` š§ Bootstrapping repo standards from recent PRs (one-time per process)...`);
|
|
1074
|
+
const { result } = await this.explorer.explore({ task, focus: [request.repository] }, {
|
|
1075
|
+
sessionId,
|
|
1076
|
+
mode: "pr",
|
|
1077
|
+
workspace: request.workspace,
|
|
1078
|
+
repository: request.repository,
|
|
1079
|
+
pullRequestId: request.pullRequestId,
|
|
1080
|
+
branch: request.branch,
|
|
1081
|
+
dryRun: request.dryRun || false,
|
|
1082
|
+
metadata: { bootstrap: true },
|
|
1083
|
+
});
|
|
1084
|
+
const parts = [];
|
|
1085
|
+
if (result.summary && result.summary.trim().length > 0) {
|
|
1086
|
+
parts.push(result.summary.trim());
|
|
1087
|
+
}
|
|
1088
|
+
if (result.findings && result.findings.length > 0) {
|
|
1089
|
+
const bullets = result.findings.map((f) => `- ${f.claim}`).join("\n");
|
|
1090
|
+
parts.push(bullets);
|
|
1091
|
+
}
|
|
1092
|
+
const combined = parts.join("\n\n").trim();
|
|
1093
|
+
if (combined.length > 0) {
|
|
1094
|
+
console.log(` ā
Bootstrap standards ready (${combined.length} chars)`);
|
|
1095
|
+
if (this.config.display.verboseToolCalls) {
|
|
1096
|
+
console.log(" āāāāāāāāā bootstrapped-standards āāāāāāāāā");
|
|
1097
|
+
for (const line of combined.split("\n")) {
|
|
1098
|
+
console.log(` ${line}`);
|
|
1099
|
+
}
|
|
1100
|
+
console.log(" āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā");
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
else {
|
|
1104
|
+
console.log(` ā ļø Bootstrap returned no standards ā proceeding without them`);
|
|
1105
|
+
}
|
|
1106
|
+
this.bootstrapStandardsCache.set(cacheKey, combined);
|
|
1107
|
+
return combined;
|
|
1108
|
+
}
|
|
1109
|
+
catch (error) {
|
|
1110
|
+
console.warn(` ā ļø Bootstrap standards failed, proceeding without: ${error.message}`);
|
|
1111
|
+
this.bootstrapStandardsCache.set(cacheKey, "");
|
|
1112
|
+
return "";
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
937
1115
|
/**
|
|
938
1116
|
* Ensure orchestrator is initialized
|
|
939
1117
|
*/
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { YamaConfig } from "../types/config.types.js";
|
|
2
|
+
import { SessionManager } from "../core/SessionManager.js";
|
|
3
|
+
import { MemoryManager } from "../memory/MemoryManager.js";
|
|
4
|
+
import { ExploreContextInput, ExploreExecutionResult, ExploreRuntimeContext } from "./types.js";
|
|
5
|
+
export declare class ContextExplorerService {
|
|
6
|
+
private readonly config;
|
|
7
|
+
private readonly sessionManager;
|
|
8
|
+
private readonly memoryManager;
|
|
9
|
+
private readonly projectRoot;
|
|
10
|
+
private readonly promptBuilder;
|
|
11
|
+
private readonly rulesContextLoader;
|
|
12
|
+
private readonly mcpManager;
|
|
13
|
+
private neurolink;
|
|
14
|
+
private prMcpInitialized;
|
|
15
|
+
private localMcpInitialized;
|
|
16
|
+
constructor(config: YamaConfig, sessionManager: SessionManager, memoryManager: MemoryManager | null, projectRoot?: string);
|
|
17
|
+
initialize(mode: "pr" | "local"): Promise<void>;
|
|
18
|
+
explore(input: ExploreContextInput, runtimeContext: ExploreRuntimeContext): Promise<ExploreExecutionResult>;
|
|
19
|
+
private normalizeInput;
|
|
20
|
+
private buildCacheKey;
|
|
21
|
+
private getToolFilteringOptions;
|
|
22
|
+
private shouldExcludeTool;
|
|
23
|
+
private normalizeToolName;
|
|
24
|
+
private normalizeResult;
|
|
25
|
+
private buildExtractionPrompt;
|
|
26
|
+
private truncateForExtraction;
|
|
27
|
+
private shouldCacheResult;
|
|
28
|
+
private normalizeFindings;
|
|
29
|
+
private normalizeEvidence;
|
|
30
|
+
private normalizeConfidence;
|
|
31
|
+
private normalizeSourceType;
|
|
32
|
+
private normalizeNextStep;
|
|
33
|
+
private extractJsonPayload;
|
|
34
|
+
private loadProjectStandards;
|
|
35
|
+
private loadKnowledgeBase;
|
|
36
|
+
private loadRepositoryMemory;
|
|
37
|
+
private initializeNeurolink;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=ContextExplorerService.d.ts.map
|