scai 0.1.173 → 0.1.174
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/dist/agents/MainAgent.js
CHANGED
|
@@ -198,6 +198,7 @@ export class MainAgent {
|
|
|
198
198
|
if (!this.isWorkLoopReady())
|
|
199
199
|
return;
|
|
200
200
|
this.ensureTaskForWorkLoop();
|
|
201
|
+
this.recalibrateRoutingAfterVerify();
|
|
201
202
|
// Research gate is evaluated after runResearch() in run().
|
|
202
203
|
}
|
|
203
204
|
/* ───────────── research ───────────── */
|
|
@@ -207,8 +208,10 @@ export class MainAgent {
|
|
|
207
208
|
*/
|
|
208
209
|
async runResearch() {
|
|
209
210
|
var _a, _b;
|
|
210
|
-
if (!this.canExecuteRoute("research"))
|
|
211
|
+
if (!this.canExecuteRoute("research")) {
|
|
212
|
+
this.logLine("RESEARCH", "taskStepSeed", undefined, "skipped (route disallows research)");
|
|
211
213
|
return;
|
|
214
|
+
}
|
|
212
215
|
if (!this.context.task)
|
|
213
216
|
return;
|
|
214
217
|
(_a = this.context.task).taskSteps || (_a.taskSteps = []);
|
|
@@ -305,9 +308,20 @@ export class MainAgent {
|
|
|
305
308
|
.map(step => step.filePath));
|
|
306
309
|
const selectedFiles = this.context.analysis.focus?.selectedFiles ?? [];
|
|
307
310
|
const touchedFromResearch = this.context.analysis.researchArtifacts?.touchedFiles ?? [];
|
|
308
|
-
const
|
|
309
|
-
|
|
311
|
+
const route = this.context.analysis.routingDecision;
|
|
312
|
+
const useFocusedSelectedPlanOnly = this.context.analysis.readiness?.decision === "ready" &&
|
|
313
|
+
(route?.decision === "has-info") &&
|
|
314
|
+
(route?.scopeLocked ?? false) &&
|
|
315
|
+
(route?.allowSearch === false) &&
|
|
316
|
+
selectedFiles.length > 0;
|
|
317
|
+
const verifyMinConfidence = this.getVerifyConfidenceThresholdForPlan();
|
|
318
|
+
const verifyEntries = Object.entries(this.context.analysis.verify?.byFile ?? {});
|
|
319
|
+
const verifyRelevantFiles = verifyEntries
|
|
320
|
+
.filter(([_, verify]) => verify?.isRelevant &&
|
|
321
|
+
(verify.fileConfidence ?? 0) >= verifyMinConfidence)
|
|
310
322
|
.map(([filePath]) => filePath);
|
|
323
|
+
const verifySkippedLowConfidenceCount = verifyEntries.filter(([_, verify]) => !!verify?.isRelevant &&
|
|
324
|
+
(verify.fileConfidence ?? 0) < verifyMinConfidence).length;
|
|
311
325
|
const rankPath = (filePath) => {
|
|
312
326
|
const inSelected = selectedFiles.includes(filePath);
|
|
313
327
|
const inResearchTouched = touchedFromResearch.includes(filePath);
|
|
@@ -322,11 +336,14 @@ export class MainAgent {
|
|
|
322
336
|
return 3;
|
|
323
337
|
return 4;
|
|
324
338
|
};
|
|
325
|
-
const
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
339
|
+
const plannedPathsSource = useFocusedSelectedPlanOnly
|
|
340
|
+
? Array.from(new Set(selectedFiles))
|
|
341
|
+
: Array.from(new Set([
|
|
342
|
+
...selectedFiles,
|
|
343
|
+
...touchedFromResearch,
|
|
344
|
+
...verifyRelevantFiles,
|
|
345
|
+
]));
|
|
346
|
+
const plannedPaths = plannedPathsSource
|
|
330
347
|
.filter(filePath => !!filePath && !filePath.startsWith("__research__/") && fs.existsSync(filePath))
|
|
331
348
|
.sort((a, b) => rankPath(a) - rankPath(b))
|
|
332
349
|
.slice(0, 16);
|
|
@@ -363,10 +380,62 @@ export class MainAgent {
|
|
|
363
380
|
selectedFileCount: selectedFiles.length,
|
|
364
381
|
researchTouchedCount: touchedFromResearch.length,
|
|
365
382
|
verifyRelevantCount: verifyRelevantFiles.length,
|
|
383
|
+
focusedSelectedOnly: useFocusedSelectedPlanOnly,
|
|
384
|
+
verifyMinConfidence,
|
|
385
|
+
verifySkippedLowConfidenceCount,
|
|
366
386
|
seeded,
|
|
367
387
|
});
|
|
368
388
|
this.logLine("PLAN", "taskStepSeed", undefined, `${seededCount} execution step(s) planned`);
|
|
369
389
|
}
|
|
390
|
+
/**
|
|
391
|
+
* Sets minimum verify confidence before a file can be plan-seeded from verify-only signal.
|
|
392
|
+
* Example: single-file lanes require higher confidence than repo-wide lanes.
|
|
393
|
+
*/
|
|
394
|
+
getVerifyConfidenceThresholdForPlan() {
|
|
395
|
+
const scope = this.context.analysis?.scopeType ?? "repo-wide";
|
|
396
|
+
if (scope === "single-file")
|
|
397
|
+
return 0.45;
|
|
398
|
+
if (scope === "multi-file")
|
|
399
|
+
return 0.35;
|
|
400
|
+
return 0.3;
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Re-routes after verify when evidence converges on selected files with high confidence.
|
|
404
|
+
* Example: selected files strongly verified => disable expansion/research and lock focused execution.
|
|
405
|
+
*/
|
|
406
|
+
recalibrateRoutingAfterVerify() {
|
|
407
|
+
var _a;
|
|
408
|
+
(_a = this.context).analysis || (_a.analysis = {});
|
|
409
|
+
const routing = this.context.analysis.routingDecision;
|
|
410
|
+
if (!routing)
|
|
411
|
+
return;
|
|
412
|
+
const selectedFiles = this.context.analysis.focus?.selectedFiles ?? [];
|
|
413
|
+
if (selectedFiles.length === 0)
|
|
414
|
+
return;
|
|
415
|
+
const readinessConfidence = this.context.analysis.readiness?.confidence ?? 0;
|
|
416
|
+
const intentConfidence = this.context.analysis.intent?.confidence ?? 0;
|
|
417
|
+
const minFileConfidence = 0.28;
|
|
418
|
+
const strongSelected = selectedFiles.filter(filePath => {
|
|
419
|
+
const verify = this.context.analysis?.verify?.byFile?.[filePath];
|
|
420
|
+
return verify?.isRelevant === true && (verify.fileConfidence ?? 0) >= minFileConfidence;
|
|
421
|
+
});
|
|
422
|
+
const convergedSingle = selectedFiles.length === 1 &&
|
|
423
|
+
strongSelected.length === 1 &&
|
|
424
|
+
readinessConfidence >= 0.9 &&
|
|
425
|
+
intentConfidence >= 0.8;
|
|
426
|
+
const convergedMulti = selectedFiles.length >= 2 &&
|
|
427
|
+
strongSelected.length >= 2 &&
|
|
428
|
+
readinessConfidence >= 0.9 &&
|
|
429
|
+
intentConfidence >= 0.75;
|
|
430
|
+
if (!convergedSingle && !convergedMulti)
|
|
431
|
+
return;
|
|
432
|
+
routing.decision = "has-info";
|
|
433
|
+
routing.allowSearch = false;
|
|
434
|
+
routing.allowResearch = false;
|
|
435
|
+
routing.scopeLocked = true;
|
|
436
|
+
routing.rationale = `${routing.rationale}; postVerify=focused-selection(${strongSelected.length})`;
|
|
437
|
+
this.logLine("TASK", "Routing recalibrated", undefined, `focused=${selectedFiles.length} selected, strong=${strongSelected.length}`);
|
|
438
|
+
}
|
|
370
439
|
/* ───────────── work loop ───────────── */
|
|
371
440
|
async runWorkLoop() {
|
|
372
441
|
if (this.context.task.status !== "active")
|
|
@@ -39,9 +39,12 @@ export const reasonNextTaskStep = {
|
|
|
39
39
|
...(context.analysis.focus?.selectedFiles ?? []),
|
|
40
40
|
...(context.workingFiles?.map(f => f.path).filter(Boolean) ?? []),
|
|
41
41
|
]));
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
// Use union (not fallback switch) so docs-only or planning-skipped lanes
|
|
43
|
+
// still process all selected files instead of only ad-hoc seeded taskSteps.
|
|
44
|
+
const intendedFiles = Array.from(new Set([
|
|
45
|
+
...plannedExecutionFiles,
|
|
46
|
+
...fallbackIntendedFiles,
|
|
47
|
+
]));
|
|
45
48
|
// ---------------------------
|
|
46
49
|
// 2️⃣ Transformed and analyzed files
|
|
47
50
|
// ---------------------------
|
|
@@ -48,6 +48,19 @@ export const resolveExecutionModeStep = {
|
|
|
48
48
|
docsOnly: true
|
|
49
49
|
};
|
|
50
50
|
break;
|
|
51
|
+
// ───── Generic requests: promote to transform when edit intent is explicit ─────
|
|
52
|
+
case "request":
|
|
53
|
+
if (hasExplicitWriteIntent(normalizedQuery)) {
|
|
54
|
+
mode = "transform";
|
|
55
|
+
rationale = "Request contains explicit edit intent.";
|
|
56
|
+
constraints = {
|
|
57
|
+
allowAnalysis: true,
|
|
58
|
+
allowPlanning: true,
|
|
59
|
+
allowFileWrites: true,
|
|
60
|
+
docsOnly: false
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
break;
|
|
51
64
|
// ───── Everything else is analysis ─────
|
|
52
65
|
case "debugging":
|
|
53
66
|
case "planning":
|
|
@@ -88,5 +101,5 @@ function isQuestionLikeQuery(query) {
|
|
|
88
101
|
}
|
|
89
102
|
function hasExplicitWriteIntent(query) {
|
|
90
103
|
const q = query.toLowerCase();
|
|
91
|
-
return /\b(add|update|edit|modify|refactor|rewrite|implement|fix|create|remove|delete|replace|rename|write|patch|change)\b/.test(q);
|
|
104
|
+
return /\b(add|update|edit|modify|refactor|rewrite|implement|fix|create|remove|delete|replace|rename|write|patch|change|increment|bump|set)\b/.test(q);
|
|
92
105
|
}
|
|
@@ -23,6 +23,9 @@ export const routingDecisionStep = {
|
|
|
23
23
|
const hasExplicitTargets = (context.analysis.intent?.targetFiles?.length ?? 0) > 0;
|
|
24
24
|
const ambiguousIntent = intentConfidence < 0.45;
|
|
25
25
|
const isRefactorLike = intentCategory === "refactorTask" || intentCategory === "codingTask";
|
|
26
|
+
const isAnalysisLike = intentCategory === "question" ||
|
|
27
|
+
intentCategory === "analysis" ||
|
|
28
|
+
intentCategory === "explanation";
|
|
26
29
|
let decision = "has-info";
|
|
27
30
|
let allowSearch = true;
|
|
28
31
|
let scopeLocked = false;
|
|
@@ -50,8 +53,8 @@ export const routingDecisionStep = {
|
|
|
50
53
|
? "single-file-focused"
|
|
51
54
|
: "bounded-analysis";
|
|
52
55
|
const allowResearch = scope !== "none" &&
|
|
53
|
-
(
|
|
54
|
-
(
|
|
56
|
+
((isAnalysisLike && isResearchScope && (decision === "needs-info" || complexitySignals >= 2)) ||
|
|
57
|
+
(isRefactorLike && complexitySignals >= 1));
|
|
55
58
|
const confidence = Math.max(0, Math.min(1, 0.55 + intentConfidence * 0.35 - (ambiguousIntent ? 0.2 : 0)));
|
|
56
59
|
const routingDecision = {
|
|
57
60
|
decision,
|
|
@@ -3,7 +3,7 @@ import chalk from "chalk";
|
|
|
3
3
|
import { RUN_LOG_PATH } from "../constants.js";
|
|
4
4
|
// ---------------- Test Queries ----------------
|
|
5
5
|
export const testQueries = [
|
|
6
|
-
"Add concise comments to semanticAnalysisModule.ts and
|
|
6
|
+
"Add concise comments to semanticAnalysisModule.ts and finalAnswerModule.ts describing phase boundaries.",
|
|
7
7
|
"Refactor MainAgent runVerify flow to reduce nesting while preserving behavior.",
|
|
8
8
|
"Explain how resolveExecutionModeStep, routingDecisionStep, and canExecuteRoute interact.",
|
|
9
9
|
"Add stronger validation and safer fallback behavior in contextReviewStep.ts.",
|