minovative-mind-cli 2.11.3 → 2.11.5
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/README.md +7 -6
- package/dist/services/agent.js +21 -3
- package/dist/services/ai.d.ts +1 -1
- package/dist/services/ai.js +45 -12
- package/dist/services/investigationComplexity.d.ts +39 -13
- package/dist/services/investigationComplexity.js +325 -46
- package/dist/services/orchestration/investigationAgent.js +1 -1
- package/dist/services/orchestration/investigationOrchestrator.js +5 -0
- package/dist/services/orchestration/orchestrator.js +16 -4
- package/dist/services/orchestration/scopedTools.d.ts +27 -50
- package/dist/services/orchestration/scopedTools.js +60 -18
- package/dist/services/proxyClient.js +132 -47
- package/dist/services/workspaceRegistry.d.ts +81 -8
- package/dist/services/workspaceRegistry.js +222 -34
- package/dist/utils/analysisRunner.js +2 -1
- package/dist/utils/config.d.ts +10 -0
- package/dist/utils/config.js +10 -0
- package/dist/utils/pathSecurity.d.ts +56 -14
- package/dist/utils/pathSecurity.js +120 -39
- package/dist/utils/systemPrompts.d.ts +6 -6
- package/dist/utils/systemPrompts.js +43 -22
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -105,8 +105,8 @@ If you prefer to use your own API key instead of credits, you can configure it v
|
|
|
105
105
|
|
|
106
106
|
Background tasks automatically route to dedicated auxiliary models with native `responseSchema` constraints for optimal latency, cost efficiency, and structured output reliability:
|
|
107
107
|
|
|
108
|
-
- **Intent
|
|
109
|
-
- **Complexity Evaluators**: `Gemini 3.7 Flash` (Temp 0, native `responseSchema`) — domain partitioning and
|
|
108
|
+
- **Intent Routing (`routeIntent`)**: `Gemini 3.7 Flash` (Temp 0, native `responseSchema`) — permissive zero-temperature classification into `SEARCH` vs `SKIP` and `CHAT` vs `EXECUTE` with resilient fallback to repository exploration.
|
|
109
|
+
- **Complexity Evaluators (`evaluateInvestigationComplexity`)**: `Gemini 3.7 Flash` (Temp 0, native `responseSchema`) — permissive parallel domain partitioning, global override detection, primary sub-path auto-focusing, and dynamic agent assignment recovery.
|
|
110
110
|
- **Context Compressor**: `Gemini 3.7 Flash` (Temp 0.2) — surgical code distillation for files exceeding 2,000 characters.
|
|
111
111
|
- **Session Titling**: `Gemini 3.7 Flash` (Temp 0.7, native `responseSchema`) — automated concise chat session titling.
|
|
112
112
|
- **Semantic Cache Classifier**: `Gemini 3.5 Flash Lite` (Temp 0, native `responseSchema`) — intent and topic classification for cache hits.
|
|
@@ -139,13 +139,14 @@ Background tasks automatically route to dedicated auxiliary models with native `
|
|
|
139
139
|
|
|
140
140
|
---
|
|
141
141
|
|
|
142
|
-
## 🌐 Multi-Workspace
|
|
142
|
+
## 🌐 Multi-Workspace, Sub-Path Focusing & Security Guardrails
|
|
143
143
|
|
|
144
144
|
Minovative Mind CLI doesn't restrict you to a single repository. You can logically group multiple external repositories into **Master Workspaces** (Profiles) containing dedicated **Sub-Workspaces** (mapped to short aliases like `@backend` or `@frontend`).
|
|
145
145
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
146
|
+
- **Primary Sub-Path Auto-Focusing & Global Override Detection**: Workspaces can designate a default primary sub-path (e.g. `src/` or `packages/core`), automatically scoping file operations and context turns without repetitive prefixing. If global override search phrases (e.g., "across the codebase", "entire project", "global", "end to end") or root monorepo configurations are detected, sub-path auto-focusing is dynamically bypassed to evaluate the entire repository.
|
|
147
|
+
- **Multi-Workspace Path Security Boundaries**: Strictly enforces workspace and profile containment via `resolveAndValidateMultiWorkspacePath`, preventing directory traversal (`../`), null-byte injections (`\0`), and absolute path escapes.
|
|
148
|
+
- **Canonical Lock Path Resolution in Scoped Tool Execution**: In parallel multi-agent workflows (MMAAK), file mutation tools automatically resolve relative paths, auto-focused sub-paths, and `@alias/` cross-repo prefixes to canonical absolute filesystem paths before acquiring mutexes in `FileLockRegistry`, preventing race conditions and lock collisions across concurrent agents.
|
|
149
|
+
- **Cross-Repo Coordination**: Prefix file paths with `@alias/` (e.g., `@backend/src/api.ts` and `@frontend/src/App.tsx`) to investigate, refactor, and coordinate changes across your entire stack in a single prompt. The terminal highlights cross-workspace actions with a blue `[alias]` visual tag. Use `/workspaces` to create profiles, link sub-workspaces, or switch active environments.
|
|
149
150
|
|
|
150
151
|
---
|
|
151
152
|
|
package/dist/services/agent.js
CHANGED
|
@@ -440,7 +440,7 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
|
|
|
440
440
|
if (gatherRes.contextResult) {
|
|
441
441
|
// Compress each relevant file individually using helper to avoid nested loop warning
|
|
442
442
|
if (!cachedContextResult) {
|
|
443
|
-
gatherRes.contextResult.relevantFiles = await compressContextFiles(workspaceRoot, gatherRes.contextResult);
|
|
443
|
+
gatherRes.contextResult.relevantFiles = await compressContextFiles(workspaceRoot, gatherRes.contextResult, ac.signal);
|
|
444
444
|
}
|
|
445
445
|
// Assemble the final context injection string
|
|
446
446
|
const contextInjection = buildContextInjection(gatherRes.contextResult);
|
|
@@ -970,11 +970,16 @@ async function collectUserInput(history, isPlanMode) {
|
|
|
970
970
|
}
|
|
971
971
|
return { userInput: lines.join('\n').trim(), canceled: false };
|
|
972
972
|
}
|
|
973
|
-
async function compressContextFiles(workspaceRoot, contextResult) {
|
|
973
|
+
async function compressContextFiles(workspaceRoot, contextResult, abortSignal) {
|
|
974
974
|
const cachedContext = readCache(workspaceRoot, 'context_cache.json') || {};
|
|
975
975
|
let cacheUpdated = false;
|
|
976
976
|
const compressedFiles = new Map();
|
|
977
977
|
for (const [filePath, contentObj] of contextResult.relevantFiles.entries()) {
|
|
978
|
+
if (abortSignal?.aborted) {
|
|
979
|
+
// Abort immediately and return raw files without making further network calls
|
|
980
|
+
compressedFiles.set(filePath, contentObj);
|
|
981
|
+
continue;
|
|
982
|
+
}
|
|
978
983
|
const content = contentObj.text;
|
|
979
984
|
const inlineData = contentObj.inlineData;
|
|
980
985
|
if (content.length < 2000 && !inlineData) {
|
|
@@ -991,9 +996,18 @@ async function compressContextFiles(workspaceRoot, contextResult) {
|
|
|
991
996
|
compressedFiles.set(filePath, { text: cachedContext[fileHash] });
|
|
992
997
|
}
|
|
993
998
|
else {
|
|
999
|
+
if (abortSignal?.aborted) {
|
|
1000
|
+
compressedFiles.set(filePath, contentObj);
|
|
1001
|
+
continue;
|
|
1002
|
+
}
|
|
994
1003
|
debugLog(`Context cache MISS for file ${filePath} (hash ${fileHash.substring(0, 8)})`);
|
|
1004
|
+
await new Promise((resolve) => setTimeout(resolve, TPM_COOLING_DELAYS.CONTEXT_COMPRESSION_MS));
|
|
1005
|
+
if (abortSignal?.aborted) {
|
|
1006
|
+
compressedFiles.set(filePath, contentObj);
|
|
1007
|
+
continue;
|
|
1008
|
+
}
|
|
995
1009
|
const compressPrompt = `Summarize the following file contents concisely. Preserve all exports, functions, classes, variables, and architectural purpose. Keep it under 2000 characters if possible. File: ${filePath}`;
|
|
996
|
-
const summary = await compressTextUsingFlashLite(content, compressPrompt, inlineData);
|
|
1010
|
+
const summary = await compressTextUsingFlashLite(content, compressPrompt, inlineData, false, abortSignal);
|
|
997
1011
|
compressedFiles.set(filePath, { text: summary });
|
|
998
1012
|
cachedContext[fileHash] = summary;
|
|
999
1013
|
cacheUpdated = true;
|
|
@@ -1213,6 +1227,10 @@ If you are not done, please continue working using your other tools.`;
|
|
|
1213
1227
|
debugLog(`Verification failed on attempt ${correctionAttempts}/${MAX_CORRECTIONS}. Issues:\n${combinedIssuesForAI}`);
|
|
1214
1228
|
// Compile compilation and syntax diagnostic warnings into an auto-correction prompt
|
|
1215
1229
|
const correctionPrompt = `AUTOMATED SYSTEM CHECK: Your previous changes resulted in the following issues:\n\n${combinedIssuesForAI}\n\nPlease analyze these issues and use your file modification tools to fix them.`;
|
|
1230
|
+
// Cooling-off delay before initiating the self-correction turn
|
|
1231
|
+
await new Promise((resolve) => setTimeout(resolve, TPM_COOLING_DELAYS.CORRECTION_TURN_MS));
|
|
1232
|
+
if (signal.aborted)
|
|
1233
|
+
break;
|
|
1216
1234
|
spinner.start('Thinking (Correction)...');
|
|
1217
1235
|
try {
|
|
1218
1236
|
result = await chat.sendMessage(correctionPrompt, undefined, signal);
|
package/dist/services/ai.d.ts
CHANGED
|
@@ -66,7 +66,7 @@ export declare class ProxyChatSession {
|
|
|
66
66
|
name: string;
|
|
67
67
|
response: any;
|
|
68
68
|
};
|
|
69
|
-
}>, additionalText?: string, abortSignal?: AbortSignal, onChunk?: (chunk: string) => void): Promise<{
|
|
69
|
+
}>, additionalText?: string | AbortSignal, abortSignal?: AbortSignal, onChunk?: (chunk: string) => void): Promise<{
|
|
70
70
|
response: {
|
|
71
71
|
text: () => string;
|
|
72
72
|
functionCalls: () => FunctionCall[] | undefined;
|
package/dist/services/ai.js
CHANGED
|
@@ -13,7 +13,17 @@ function getMultiWorkspaceBlock() {
|
|
|
13
13
|
const summary = workspaceRegistry.buildPromptSummary();
|
|
14
14
|
const primaryRoot = process.cwd();
|
|
15
15
|
const primaryName = primaryRoot.split(/[/\\]/).pop() || 'Primary';
|
|
16
|
+
const primarySubPath = workspaceRegistry.getPrimarySubPath();
|
|
16
17
|
let block = `<workspace_context>\nYour current primary workspace (the default "./" root) is:\n- ./ (Workspace: ${primaryName}) → ${primaryRoot}\n`;
|
|
18
|
+
if (primarySubPath) {
|
|
19
|
+
block += `- Active Primary Sub-Path: "${primarySubPath}" (All relative search, inspection, and file operations focus into this sub-directory by default unless another sub-path or external workspace is explicitly specified).\n`;
|
|
20
|
+
}
|
|
21
|
+
block += `\n<workspace_focus_rules>
|
|
22
|
+
- **Primary Focus Default (CRITICAL)**: Always default your investigation, search, file reading, and modifications to the current primary workspace and active primary sub-path. Unless the user explicitly names another sub-path or external workspace, assume all user instructions ("find this", "update that", "refactor X") refer to the primary workspace and active sub-path you are currently in.
|
|
23
|
+
- **Explicit Sub-Paths**: Only target a different sub-directory if the user explicitly specifies it.
|
|
24
|
+
- **External Workspaces (@alias/)**: Only access external workspaces if the user explicitly references them or uses the registered @alias prefix.
|
|
25
|
+
- **Strict Boundary Defense & Missing Workspace Handling**: Never attempt relative path traversal (like "../other-repo") or use "run_command" (such as node -e or bash scripts with fs/cat/cp) to read or write files outside registered workspace boundaries. If the user asks for a project or workspace that is NOT registered or available, you MUST NOT use commands or scripts to work around it; instead, immediately and clearly inform the user that the project or workspace is not registered and instruct them to add it via "/workspaces".
|
|
26
|
+
</workspace_focus_rules>\n`;
|
|
17
27
|
if (summary) {
|
|
18
28
|
block += `\nThe user has also registered external workspaces that you can access using the @alias/ prefix:\n${summary}\n\nTo read, modify, or search files in an external workspace, prefix the file path with the alias (e.g., "@backend/src/routes.ts"). To search across ALL workspaces, use grep_search with workspace="all".\n\nWhen the user asks to "transfer", "sync", or "port" features between projects, read the source files from one workspace and apply the changes to the target.\n`;
|
|
19
29
|
}
|
|
@@ -65,12 +75,16 @@ const MAX_PART_TEXT_LENGTH = 60_000;
|
|
|
65
75
|
const HISTORICAL_TOOL_OUTPUT_THRESHOLD = 1500;
|
|
66
76
|
const COLLAPSED_TOOL_OUTPUT_MARKER = '\n... [Historical tool output collapsed to save context]';
|
|
67
77
|
function collapseHistoricalOutput(val, threshold = HISTORICAL_TOOL_OUTPUT_THRESHOLD) {
|
|
78
|
+
if (typeof val !== 'string')
|
|
79
|
+
return String(val ?? '');
|
|
68
80
|
if (val.length <= threshold || val.includes('[Historical tool output collapsed')) {
|
|
69
81
|
return val;
|
|
70
82
|
}
|
|
71
83
|
return `${val.substring(0, threshold)}${COLLAPSED_TOOL_OUTPUT_MARKER}`;
|
|
72
84
|
}
|
|
73
85
|
function truncatePartText(text) {
|
|
86
|
+
if (typeof text !== 'string')
|
|
87
|
+
return String(text ?? '');
|
|
74
88
|
if (text.length <= MAX_PART_TEXT_LENGTH)
|
|
75
89
|
return text;
|
|
76
90
|
return text.substring(0, MAX_PART_TEXT_LENGTH) + '\n... (output truncated to prevent memory overflow)';
|
|
@@ -289,6 +303,16 @@ export class ProxyChatSession {
|
|
|
289
303
|
}
|
|
290
304
|
}
|
|
291
305
|
async sendMessage(message, additionalText, abortSignal, onChunk) {
|
|
306
|
+
// Graceful argument normalization if AbortSignal is passed as 2nd argument
|
|
307
|
+
let actualAdditionalText;
|
|
308
|
+
let actualAbortSignal = abortSignal;
|
|
309
|
+
if (additionalText && typeof additionalText !== 'string' && additionalText.aborted !== undefined) {
|
|
310
|
+
actualAbortSignal = additionalText;
|
|
311
|
+
actualAdditionalText = undefined;
|
|
312
|
+
}
|
|
313
|
+
else if (typeof additionalText === 'string') {
|
|
314
|
+
actualAdditionalText = additionalText;
|
|
315
|
+
}
|
|
292
316
|
const idToken = await getAuthorizedIdToken();
|
|
293
317
|
if (!idToken) {
|
|
294
318
|
throw new Error('You are not signed in. Please run `minovative-mind-cli login` first.');
|
|
@@ -331,8 +355,8 @@ export class ProxyChatSession {
|
|
|
331
355
|
}
|
|
332
356
|
}
|
|
333
357
|
}
|
|
334
|
-
if (
|
|
335
|
-
newParts.push({ text: truncatePartText(
|
|
358
|
+
if (actualAdditionalText) {
|
|
359
|
+
newParts.push({ text: truncatePartText(actualAdditionalText) });
|
|
336
360
|
}
|
|
337
361
|
const userEntry = {
|
|
338
362
|
role: 'user',
|
|
@@ -348,12 +372,12 @@ export class ProxyChatSession {
|
|
|
348
372
|
const creds = await loadCredentials();
|
|
349
373
|
result = await proxyClient.generateViaBYOK(creds.geminiApiKey, this.modelName, this.history, this.tools, undefined, // toolConfig
|
|
350
374
|
this.systemInstruction, effectiveGenerationConfig, onChunk ? { onChunk } : undefined, // streamCallbacks
|
|
351
|
-
|
|
375
|
+
actualAbortSignal);
|
|
352
376
|
}
|
|
353
377
|
else {
|
|
354
378
|
result = await proxyClient.generateFunctionCallViaProxy(idToken, this.modelName, this.history, this.tools, undefined, // toolConfig
|
|
355
379
|
this.systemInstruction, effectiveGenerationConfig, onChunk ? { onChunk } : undefined, // streamCallbacks
|
|
356
|
-
|
|
380
|
+
actualAbortSignal);
|
|
357
381
|
}
|
|
358
382
|
this.latestUsageMetadata = result.usageMetadata;
|
|
359
383
|
// Track token usage metrics
|
|
@@ -426,7 +450,7 @@ export function createSharedChatSession() {
|
|
|
426
450
|
let model = executionModelOverride || getGlobalActiveModel();
|
|
427
451
|
if (model === 'auto')
|
|
428
452
|
model = GEMINI_MODELS.FLASH; // Will be overridden per-turn in executeSingleTurn
|
|
429
|
-
return new ProxyChatSession(model, GENERAL_CHAT_INSTRUCTION, [], {
|
|
453
|
+
return new ProxyChatSession(model, GENERAL_CHAT_INSTRUCTION.replace('{{MULTI_WORKSPACE_BLOCK}}', getMultiWorkspaceBlock()), [], {
|
|
430
454
|
maxOutputTokens: MAX_OUTPUT_TOKENS,
|
|
431
455
|
temperature: executionTempOverride !== null ? executionTempOverride : 1,
|
|
432
456
|
topP: 0.95,
|
|
@@ -435,7 +459,7 @@ export function createSharedChatSession() {
|
|
|
435
459
|
}
|
|
436
460
|
export function getGeneralChatConfig() {
|
|
437
461
|
return {
|
|
438
|
-
systemInstruction: GENERAL_CHAT_INSTRUCTION,
|
|
462
|
+
systemInstruction: GENERAL_CHAT_INSTRUCTION.replace('{{MULTI_WORKSPACE_BLOCK}}', getMultiWorkspaceBlock()),
|
|
439
463
|
tools: [{ googleSearch: {} }],
|
|
440
464
|
};
|
|
441
465
|
}
|
|
@@ -447,7 +471,7 @@ export function getPlanExecutionConfig() {
|
|
|
447
471
|
}
|
|
448
472
|
export function getPlanModeConfig() {
|
|
449
473
|
return {
|
|
450
|
-
systemInstruction: PLAN_MODE_INSTRUCTION,
|
|
474
|
+
systemInstruction: PLAN_MODE_INSTRUCTION.replace('{{MULTI_WORKSPACE_BLOCK}}', getMultiWorkspaceBlock()),
|
|
451
475
|
tools: [], // No tools allowed in plan mode
|
|
452
476
|
};
|
|
453
477
|
}
|
|
@@ -464,7 +488,7 @@ export async function compressTextUsingFlashLite(text, instruction = "<directive
|
|
|
464
488
|
const idToken = await getAuthorizedIdToken();
|
|
465
489
|
if (!idToken)
|
|
466
490
|
return text;
|
|
467
|
-
let model = GEMINI_MODELS.
|
|
491
|
+
let model = GEMINI_MODELS.FLASH_LITE;
|
|
468
492
|
const parts = [{ text }];
|
|
469
493
|
if (inlineData) {
|
|
470
494
|
parts.push({ inlineData });
|
|
@@ -675,7 +699,7 @@ export function createContextAgentSession() {
|
|
|
675
699
|
export function createIntentRouterSession() {
|
|
676
700
|
let model = getGlobalActiveModel();
|
|
677
701
|
if (model === 'auto' || model.includes('claude'))
|
|
678
|
-
model = GEMINI_MODELS.
|
|
702
|
+
model = GEMINI_MODELS.FLASH_LITE;
|
|
679
703
|
return new ProxyChatSession(model, INTENT_ROUTER_SYSTEM_INSTRUCTION, [], // no tools
|
|
680
704
|
{
|
|
681
705
|
temperature: 0,
|
|
@@ -702,7 +726,7 @@ export function createIntentRouterSession() {
|
|
|
702
726
|
export function createExecutionComplexitySession() {
|
|
703
727
|
let model = getGlobalActiveModel();
|
|
704
728
|
if (model === 'auto' || model.includes('claude'))
|
|
705
|
-
model = GEMINI_MODELS.
|
|
729
|
+
model = GEMINI_MODELS.FLASH_LITE;
|
|
706
730
|
return new ProxyChatSession(model, EXECUTION_COMPLEXITY_SYSTEM_INSTRUCTION, [], // no tools
|
|
707
731
|
{
|
|
708
732
|
temperature: 0,
|
|
@@ -724,7 +748,7 @@ export function createExecutionComplexitySession() {
|
|
|
724
748
|
export function createInvestigationComplexitySession() {
|
|
725
749
|
let model = getGlobalActiveModel();
|
|
726
750
|
if (model === 'auto' || model.includes('claude'))
|
|
727
|
-
model = GEMINI_MODELS.
|
|
751
|
+
model = GEMINI_MODELS.FLASH_LITE;
|
|
728
752
|
return new ProxyChatSession(model, INVESTIGATION_COMPLEXITY_SYSTEM_INSTRUCTION, [], // no tools
|
|
729
753
|
{
|
|
730
754
|
temperature: 0,
|
|
@@ -737,6 +761,15 @@ export function createInvestigationComplexitySession() {
|
|
|
737
761
|
enum: ['SINGLE', 'PARALLEL'],
|
|
738
762
|
description: 'Investigation strategy (SINGLE or PARALLEL)',
|
|
739
763
|
},
|
|
764
|
+
scope: {
|
|
765
|
+
type: SchemaType.STRING,
|
|
766
|
+
enum: ['SUB_PATH', 'FULL_WORKSPACE', 'EXTERNAL_WORKSPACE'],
|
|
767
|
+
description: 'Investigation scope: SUB_PATH (confined to active primary sub-path), FULL_WORKSPACE (spans whole repository or root files), or EXTERNAL_WORKSPACE (targets @alias/)',
|
|
768
|
+
},
|
|
769
|
+
subPathOverride: {
|
|
770
|
+
type: SchemaType.STRING,
|
|
771
|
+
description: 'The target scope identifier if overridden (e.g. "root", target root file, or @alias), or null if strictly confined to active primary sub-path',
|
|
772
|
+
},
|
|
740
773
|
domains: {
|
|
741
774
|
type: SchemaType.ARRAY,
|
|
742
775
|
items: {
|
|
@@ -829,7 +862,7 @@ export function createWebSearchAgentSession() {
|
|
|
829
862
|
export function createHistorySummarizerSession() {
|
|
830
863
|
let model = getGlobalActiveModel();
|
|
831
864
|
if (model === 'auto' || model.includes('claude'))
|
|
832
|
-
model = GEMINI_MODELS.
|
|
865
|
+
model = GEMINI_MODELS.FLASH_LITE;
|
|
833
866
|
return new ProxyChatSession(model, HISTORY_SUMMARIZER_SYSTEM_INSTRUCTION, [], {
|
|
834
867
|
temperature: 0.2,
|
|
835
868
|
maxOutputTokens: MAX_OUTPUT_TOKENS,
|
|
@@ -10,6 +10,17 @@
|
|
|
10
10
|
* Only invoked when the `/sub-agents` toggle is ON and the Intent Router
|
|
11
11
|
* has already determined that context gathering is needed (SEARCH).
|
|
12
12
|
*/
|
|
13
|
+
/** Options for customizing investigation complexity evaluation. */
|
|
14
|
+
export interface InvestigationComplexityOptions {
|
|
15
|
+
/** Explicit primary sub-path focus override for the evaluation */
|
|
16
|
+
autoFocusSubPath?: string | null;
|
|
17
|
+
/** Explicit sub-path override if user explicitly targeted another scope */
|
|
18
|
+
subPathOverride?: string | null;
|
|
19
|
+
/** Flag to disable sub-path auto-focusing completely */
|
|
20
|
+
disableAutoFocus?: boolean;
|
|
21
|
+
/** Primary workspace root directory path */
|
|
22
|
+
primaryRoot?: string;
|
|
23
|
+
}
|
|
13
24
|
/** A single agent assignment grouping related investigation domains. */
|
|
14
25
|
export interface AgentAssignment {
|
|
15
26
|
/** Human-readable label for this agent (e.g., "Frontend", "Backend") */
|
|
@@ -21,25 +32,40 @@ export interface AgentAssignment {
|
|
|
21
32
|
export interface InvestigationComplexityResult {
|
|
22
33
|
/** Whether investigation should use a single agent or parallel agents */
|
|
23
34
|
strategy: 'SINGLE' | 'PARALLEL';
|
|
35
|
+
/** The evaluated investigation scope */
|
|
36
|
+
scope?: 'SUB_PATH' | 'FULL_WORKSPACE' | 'EXTERNAL_WORKSPACE';
|
|
24
37
|
/** All identified investigation domains (flat list) */
|
|
25
38
|
domains: string[];
|
|
26
|
-
/** Grouped domain assignments — one per agent to spawn */
|
|
39
|
+
/** Grouped domain assignments — one per agent to spawn (2–3 max) */
|
|
27
40
|
agentAssignments: AgentAssignment[];
|
|
28
|
-
/** Brief
|
|
41
|
+
/** Brief explanation of the routing decision */
|
|
29
42
|
reasoning: string;
|
|
43
|
+
/** The active primary sub-path auto-focus, if any */
|
|
44
|
+
focusedSubPath?: string | null;
|
|
45
|
+
/** The active sub-path or workspace override, if detected or provided */
|
|
46
|
+
subPathOverride?: string | null;
|
|
47
|
+
/** Whether the evaluation was constrained by active sub-path auto-focusing */
|
|
48
|
+
isAutoFocused?: boolean;
|
|
30
49
|
}
|
|
31
50
|
/**
|
|
32
|
-
*
|
|
51
|
+
* Checks whether the user's prompt contains an explicit path or workspace override
|
|
52
|
+
* that supersedes default primary sub-path auto-focusing.
|
|
33
53
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
|
|
54
|
+
* @param userRequest - The prompt text from the user
|
|
55
|
+
* @param activeSubPath - The currently active primary sub-path (if any)
|
|
56
|
+
* @returns The detected override identifier or null if no override exists
|
|
57
|
+
*/
|
|
58
|
+
export declare function detectSubPathOverride(userRequest: string, activeSubPath?: string | null): string | null;
|
|
59
|
+
/**
|
|
60
|
+
* Evaluates whether a user request warrants parallel investigation or a single agent.
|
|
61
|
+
* Respects default primary sub-path auto-focusing while allowing explicit overrides.
|
|
38
62
|
*
|
|
39
|
-
* @param userRequest - The user's prompt
|
|
40
|
-
* @param projectType - Detected project type (e.g., "Node.js / TypeScript
|
|
41
|
-
* @param approximateFileCount -
|
|
42
|
-
* @param chatHistory -
|
|
43
|
-
* @
|
|
63
|
+
* @param userRequest - The user's prompt/request
|
|
64
|
+
* @param projectType - Detected project type string (e.g., "Node.js / TypeScript")
|
|
65
|
+
* @param approximateFileCount - Approximate total file count in the project
|
|
66
|
+
* @param chatHistory - Formatted recent conversation history (optional)
|
|
67
|
+
* @param abortSignal - Optional signal to abort the LLM request
|
|
68
|
+
* @param options - Optional sub-path auto-focus and override configuration
|
|
69
|
+
* @returns Structured complexity result with strategy and domain assignments
|
|
44
70
|
*/
|
|
45
|
-
export declare function evaluateInvestigationComplexity(userRequest: string, projectType: string, approximateFileCount: number, chatHistory?: string, abortSignal?: AbortSignal): Promise<InvestigationComplexityResult>;
|
|
71
|
+
export declare function evaluateInvestigationComplexity(userRequest: string, projectType: string, approximateFileCount: number, chatHistory?: string, abortSignal?: AbortSignal, options?: InvestigationComplexityOptions): Promise<InvestigationComplexityResult>;
|