minovative-mind-cli 2.13.5 → 2.14.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/README.md +102 -39
- package/dist/services/agent/slashCommands.js +47 -7
- package/dist/services/agent/syntaxAgent.js +13 -0
- package/dist/services/agent-tools.d.ts +1 -1
- package/dist/services/agent-tools.js +2 -2
- package/dist/services/agent.js +119 -7
- package/dist/services/ai.d.ts +19 -0
- package/dist/services/ai.js +96 -5
- package/dist/services/contextAgent.js +23 -0
- package/dist/services/investigationComplexity.js +1 -1
- package/dist/services/mentionEngine.d.ts +385 -0
- package/dist/services/mentionEngine.js +1395 -0
- package/dist/services/orchestration/investigationAgent.js +4 -1
- package/dist/services/orchestration/messageBus.d.ts +26 -3
- package/dist/services/orchestration/messageBus.js +204 -14
- package/dist/services/orchestration/orchestrator.js +4 -0
- package/dist/services/orchestration/scopedTools.js +16 -2
- package/dist/services/orchestration/subAgent.js +14 -2
- package/dist/services/proxyClient.d.ts +38 -2
- package/dist/services/proxyClient.js +42 -24
- package/dist/utils/config.d.ts +75 -0
- package/dist/utils/config.js +93 -0
- package/dist/utils/contextPrompts.d.ts +28 -4
- package/dist/utils/contextPrompts.js +70 -1
- package/dist/utils/historyPrompt.d.ts +166 -7
- package/dist/utils/historyPrompt.js +775 -30
- package/dist/utils/symbolExtractor.d.ts +111 -8
- package/dist/utils/symbolExtractor.js +616 -64
- package/dist/utils/systemPrompts.d.ts +3 -3
- package/dist/utils/systemPrompts.js +5 -3
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
package/dist/services/ai.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SchemaType } from '@google/generative-ai';
|
|
2
|
-
import { GEMINI_MODELS, DEFAULT_MODEL, MAX_OUTPUT_TOKENS, isByokEnabled } from '../utils/config.js';
|
|
2
|
+
import { GEMINI_MODELS, DEFAULT_MODEL, MAX_OUTPUT_TOKENS, isByokEnabled, DEFAULT_MODEL_THINKING_LEVELS, } from '../utils/config.js';
|
|
3
3
|
import { getToolDeclarations } from './agent-tools.js';
|
|
4
4
|
import { getMetricCollector } from './metrics.js';
|
|
5
5
|
import { getAuthorizedIdToken, checkByokSubscription } from './auth.js';
|
|
@@ -56,12 +56,40 @@ export function clearModelOverrides() {
|
|
|
56
56
|
}
|
|
57
57
|
// ─── AI Service ──────────────────────────────────────────────────────
|
|
58
58
|
let globalActiveModel = DEFAULT_MODEL;
|
|
59
|
+
const userModelThinkingLevels = new Map();
|
|
59
60
|
export function setGlobalActiveModel(model) {
|
|
60
61
|
globalActiveModel = model;
|
|
61
62
|
}
|
|
62
63
|
export function getGlobalActiveModel() {
|
|
63
64
|
return globalActiveModel;
|
|
64
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Gets the thinking reasoning level configured for a specific model or active model.
|
|
68
|
+
* Falls back to default model thinking levels or 'MEDIUM' if not explicitly configured.
|
|
69
|
+
*/
|
|
70
|
+
export function getModelThinkingLevel(model) {
|
|
71
|
+
const targetModel = model && model !== 'auto'
|
|
72
|
+
? model
|
|
73
|
+
: globalActiveModel === 'auto'
|
|
74
|
+
? GEMINI_MODELS.FLASH
|
|
75
|
+
: globalActiveModel;
|
|
76
|
+
if (userModelThinkingLevels.has(targetModel)) {
|
|
77
|
+
return userModelThinkingLevels.get(targetModel);
|
|
78
|
+
}
|
|
79
|
+
return DEFAULT_MODEL_THINKING_LEVELS[targetModel] || 'MEDIUM';
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Sets the user-configured thinking reasoning level for a specific model.
|
|
83
|
+
*/
|
|
84
|
+
export function setModelThinkingLevel(model, level) {
|
|
85
|
+
userModelThinkingLevels.set(model, level);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Resets user-configured thinking levels back to default model presets.
|
|
89
|
+
*/
|
|
90
|
+
export function resetModelThinkingLevels() {
|
|
91
|
+
userModelThinkingLevels.clear();
|
|
92
|
+
}
|
|
65
93
|
const proxyClient = new ProxyClient();
|
|
66
94
|
// ─── History Limits ──────────────────────────────────────────────────
|
|
67
95
|
/** Maximum number of Content entries to keep in the sliding history window. */
|
|
@@ -101,6 +129,7 @@ export class ProxyChatSession {
|
|
|
101
129
|
tools;
|
|
102
130
|
toolConfig;
|
|
103
131
|
generationConfig;
|
|
132
|
+
configuredThinkingLevel;
|
|
104
133
|
latestUsageMetadata = undefined;
|
|
105
134
|
constructor(modelName, systemInstruction, tools, generationConfig, toolConfig) {
|
|
106
135
|
this.modelName = modelName;
|
|
@@ -108,6 +137,9 @@ export class ProxyChatSession {
|
|
|
108
137
|
this.tools = tools;
|
|
109
138
|
this.generationConfig = generationConfig;
|
|
110
139
|
this.toolConfig = toolConfig;
|
|
140
|
+
if (generationConfig?.thinkingConfig?.thinkingLevel) {
|
|
141
|
+
this.configuredThinkingLevel = generationConfig.thinkingConfig.thinkingLevel;
|
|
142
|
+
}
|
|
111
143
|
}
|
|
112
144
|
getLatestUsageMetadata() {
|
|
113
145
|
return this.latestUsageMetadata;
|
|
@@ -129,6 +161,28 @@ export class ProxyChatSession {
|
|
|
129
161
|
getModel() {
|
|
130
162
|
return this.modelName;
|
|
131
163
|
}
|
|
164
|
+
setThinkingLevel(level) {
|
|
165
|
+
this.configuredThinkingLevel = level;
|
|
166
|
+
this.generationConfig = {
|
|
167
|
+
...(this.generationConfig || {}),
|
|
168
|
+
thinkingConfig: {
|
|
169
|
+
...(this.generationConfig?.thinkingConfig || {}),
|
|
170
|
+
thinkingLevel: level,
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
getThinkingLevel() {
|
|
175
|
+
return this.configuredThinkingLevel || this.generationConfig?.thinkingConfig?.thinkingLevel;
|
|
176
|
+
}
|
|
177
|
+
setGenerationConfig(generationConfig) {
|
|
178
|
+
this.generationConfig = generationConfig;
|
|
179
|
+
if (generationConfig?.thinkingConfig?.thinkingLevel) {
|
|
180
|
+
this.configuredThinkingLevel = generationConfig.thinkingConfig.thinkingLevel;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
getGenerationConfig() {
|
|
184
|
+
return this.generationConfig;
|
|
185
|
+
}
|
|
132
186
|
clearHistory() {
|
|
133
187
|
this.history = [];
|
|
134
188
|
this.fullHistory = [];
|
|
@@ -309,6 +363,12 @@ export class ProxyChatSession {
|
|
|
309
363
|
if (typeof respObj.result === 'string') {
|
|
310
364
|
respObj.result = collapseHistoricalOutput(respObj.result, threshold);
|
|
311
365
|
}
|
|
366
|
+
if (typeof respObj.stdout === 'string') {
|
|
367
|
+
respObj.stdout = collapseHistoricalOutput(respObj.stdout, threshold);
|
|
368
|
+
}
|
|
369
|
+
if (typeof respObj.stderr === 'string') {
|
|
370
|
+
respObj.stderr = collapseHistoricalOutput(respObj.stderr, threshold);
|
|
371
|
+
}
|
|
312
372
|
}
|
|
313
373
|
}
|
|
314
374
|
}
|
|
@@ -461,11 +521,15 @@ export function createSharedChatSession() {
|
|
|
461
521
|
let model = executionModelOverride || getGlobalActiveModel();
|
|
462
522
|
if (model === 'auto')
|
|
463
523
|
model = GEMINI_MODELS.FLASH; // Will be overridden per-turn in executeSingleTurn
|
|
524
|
+
const thinkingLevel = getModelThinkingLevel(model);
|
|
464
525
|
return new ProxyChatSession(model, GENERAL_CHAT_INSTRUCTION.replace('{{MULTI_WORKSPACE_BLOCK}}', getMultiWorkspaceBlock()), [], {
|
|
465
526
|
maxOutputTokens: MAX_OUTPUT_TOKENS,
|
|
466
527
|
temperature: executionTempOverride !== null ? executionTempOverride : 1,
|
|
467
528
|
topP: 0.95,
|
|
468
529
|
topK: 40,
|
|
530
|
+
thinkingConfig: {
|
|
531
|
+
thinkingLevel,
|
|
532
|
+
},
|
|
469
533
|
});
|
|
470
534
|
}
|
|
471
535
|
export function getGeneralChatConfig() {
|
|
@@ -509,11 +573,11 @@ export async function compressTextUsingFlashLite(text, instruction = "<directive
|
|
|
509
573
|
}
|
|
510
574
|
const creds = await loadCredentials();
|
|
511
575
|
result = await proxyClient.generateViaBYOK(creds.geminiApiKey, model, contents, [], // no tools
|
|
512
|
-
undefined, instruction, { temperature: 0.2 }, undefined, abortSignal);
|
|
576
|
+
undefined, instruction, { temperature: 0.2, thinkingConfig: { thinkingLevel: 'MINIMAL' } }, undefined, abortSignal);
|
|
513
577
|
}
|
|
514
578
|
else {
|
|
515
579
|
result = await proxyClient.generateFunctionCallViaProxy(idToken, model, contents, [], // no tools
|
|
516
|
-
undefined, instruction, { temperature: 0.2 }, // low temp for factual summary
|
|
580
|
+
undefined, instruction, { temperature: 0.2, thinkingConfig: { thinkingLevel: 'MINIMAL' } }, // low temp for factual summary
|
|
517
581
|
undefined, abortSignal);
|
|
518
582
|
}
|
|
519
583
|
let textPart = '';
|
|
@@ -698,6 +762,9 @@ export function createContextAgentSession() {
|
|
|
698
762
|
temperature: contextTempOverride !== null ? contextTempOverride : 1,
|
|
699
763
|
topP: 0.95,
|
|
700
764
|
topK: 40,
|
|
765
|
+
thinkingConfig: {
|
|
766
|
+
thinkingLevel: 'MEDIUM',
|
|
767
|
+
},
|
|
701
768
|
}, {
|
|
702
769
|
functionCallingConfig: {
|
|
703
770
|
mode: 'ANY',
|
|
@@ -712,6 +779,9 @@ export function createIntentRouterSession() {
|
|
|
712
779
|
return new ProxyChatSession(model, INTENT_ROUTER_SYSTEM_INSTRUCTION, [], // no tools
|
|
713
780
|
{
|
|
714
781
|
temperature: 0,
|
|
782
|
+
thinkingConfig: {
|
|
783
|
+
thinkingLevel: 'MINIMAL',
|
|
784
|
+
},
|
|
715
785
|
responseMimeType: 'application/json',
|
|
716
786
|
responseSchema: {
|
|
717
787
|
type: SchemaType.OBJECT,
|
|
@@ -739,6 +809,9 @@ export function createExecutionComplexitySession() {
|
|
|
739
809
|
return new ProxyChatSession(model, EXECUTION_COMPLEXITY_SYSTEM_INSTRUCTION, [], // no tools
|
|
740
810
|
{
|
|
741
811
|
temperature: 0,
|
|
812
|
+
thinkingConfig: {
|
|
813
|
+
thinkingLevel: 'MINIMAL',
|
|
814
|
+
},
|
|
742
815
|
responseMimeType: 'application/json',
|
|
743
816
|
responseSchema: {
|
|
744
817
|
type: SchemaType.OBJECT,
|
|
@@ -761,6 +834,9 @@ export function createInvestigationComplexitySession() {
|
|
|
761
834
|
return new ProxyChatSession(model, INVESTIGATION_COMPLEXITY_SYSTEM_INSTRUCTION, [], // no tools
|
|
762
835
|
{
|
|
763
836
|
temperature: 0,
|
|
837
|
+
thinkingConfig: {
|
|
838
|
+
thinkingLevel: 'MEDIUM',
|
|
839
|
+
},
|
|
764
840
|
responseMimeType: 'application/json',
|
|
765
841
|
responseSchema: {
|
|
766
842
|
type: SchemaType.OBJECT,
|
|
@@ -824,6 +900,9 @@ export function createInvestigationSemanticSession() {
|
|
|
824
900
|
return new ProxyChatSession(model, INVESTIGATION_SEMANTIC_SYSTEM_INSTRUCTION, [], // no tools
|
|
825
901
|
{
|
|
826
902
|
temperature: 0,
|
|
903
|
+
thinkingConfig: {
|
|
904
|
+
thinkingLevel: 'MINIMAL',
|
|
905
|
+
},
|
|
827
906
|
responseMimeType: 'application/json',
|
|
828
907
|
responseSchema: {
|
|
829
908
|
type: SchemaType.OBJECT,
|
|
@@ -865,6 +944,9 @@ export function createWebSearchAgentSession() {
|
|
|
865
944
|
temperature: 1,
|
|
866
945
|
topP: 0.95,
|
|
867
946
|
topK: 40,
|
|
947
|
+
thinkingConfig: {
|
|
948
|
+
thinkingLevel: 'MEDIUM',
|
|
949
|
+
},
|
|
868
950
|
});
|
|
869
951
|
}
|
|
870
952
|
// ─── History Summarizer Agent Service ─────────────────────────────────
|
|
@@ -875,6 +957,9 @@ export function createHistorySummarizerSession() {
|
|
|
875
957
|
return new ProxyChatSession(model, HISTORY_SUMMARIZER_SYSTEM_INSTRUCTION, [], {
|
|
876
958
|
temperature: 0.2,
|
|
877
959
|
maxOutputTokens: MAX_OUTPUT_TOKENS,
|
|
960
|
+
thinkingConfig: {
|
|
961
|
+
thinkingLevel: 'MINIMAL',
|
|
962
|
+
},
|
|
878
963
|
});
|
|
879
964
|
}
|
|
880
965
|
/**
|
|
@@ -974,6 +1059,9 @@ export function createUserProfileExtractorSession() {
|
|
|
974
1059
|
return new ProxyChatSession(model, USER_PROFILE_EXTRACTOR_SYSTEM_INSTRUCTION, [], // no tools
|
|
975
1060
|
{
|
|
976
1061
|
temperature: 0,
|
|
1062
|
+
thinkingConfig: {
|
|
1063
|
+
thinkingLevel: 'MINIMAL',
|
|
1064
|
+
},
|
|
977
1065
|
responseMimeType: 'application/json',
|
|
978
1066
|
responseSchema: {
|
|
979
1067
|
type: SchemaType.OBJECT,
|
|
@@ -1094,6 +1182,9 @@ export function createTrivialMessageClassifierSession() {
|
|
|
1094
1182
|
return new ProxyChatSession(model, TRIVIAL_MESSAGE_CLASSIFIER_SYSTEM_INSTRUCTION, [], // no tools
|
|
1095
1183
|
{
|
|
1096
1184
|
temperature: 0,
|
|
1185
|
+
thinkingConfig: {
|
|
1186
|
+
thinkingLevel: 'MINIMAL',
|
|
1187
|
+
},
|
|
1097
1188
|
responseMimeType: 'application/json',
|
|
1098
1189
|
responseSchema: {
|
|
1099
1190
|
type: SchemaType.OBJECT,
|
|
@@ -1138,11 +1229,11 @@ export async function generateChatTitle(firstMessage, abortSignal) {
|
|
|
1138
1229
|
}
|
|
1139
1230
|
const creds = await loadCredentials();
|
|
1140
1231
|
result = await proxyClient.generateViaBYOK(creds.geminiApiKey, model, contents, [], // no tools
|
|
1141
|
-
undefined, instruction, { temperature: 0.2 }, undefined, abortSignal);
|
|
1232
|
+
undefined, instruction, { temperature: 0.2, thinkingConfig: { thinkingLevel: 'MINIMAL' } }, undefined, abortSignal);
|
|
1142
1233
|
}
|
|
1143
1234
|
else {
|
|
1144
1235
|
result = await proxyClient.generateFunctionCallViaProxy(idToken, model, contents, [], // no tools
|
|
1145
|
-
undefined, instruction, { temperature: 0.2 }, undefined, abortSignal);
|
|
1236
|
+
undefined, instruction, { temperature: 0.2, thinkingConfig: { thinkingLevel: 'MINIMAL' } }, undefined, abortSignal);
|
|
1146
1237
|
}
|
|
1147
1238
|
let title = '';
|
|
1148
1239
|
if (result.parts) {
|
|
@@ -209,6 +209,7 @@ export async function routeIntent(userRequest, chatHistory = '', abortSignal) {
|
|
|
209
209
|
}
|
|
210
210
|
try {
|
|
211
211
|
const session = createIntentRouterSession();
|
|
212
|
+
debugLog(`Intent Router evaluating intent [Model: ${session.getModel()}, Thinking: ${session.getThinkingLevel() || 'MINIMAL'}]`);
|
|
212
213
|
let prompt = `User Request: "${userRequest}"`;
|
|
213
214
|
if (chatHistory) {
|
|
214
215
|
const prunedHistory = pruneTextToTokenBudget(chatHistory, MAX_CHAT_HISTORY_ROUTER_TOKENS, { fromStart: true });
|
|
@@ -242,6 +243,7 @@ export async function evaluateExecutionComplexity(userRequest, investigationSumm
|
|
|
242
243
|
}
|
|
243
244
|
try {
|
|
244
245
|
const session = createExecutionComplexitySession();
|
|
246
|
+
debugLog(`Execution Complexity evaluating [Model: ${session.getModel()}, Thinking: ${session.getThinkingLevel() || 'MINIMAL'}]`);
|
|
245
247
|
let prompt = `User Request: "${userRequest}"
|
|
246
248
|
Investigation Summary: ${investigationSummary || 'None (0 files needed)'}
|
|
247
249
|
Number of Relevant Files: ${numRelevantFiles}`;
|
|
@@ -418,6 +420,7 @@ export async function gatherContext(workspaceRoot, userRequest, chatHistory = ''
|
|
|
418
420
|
}
|
|
419
421
|
// ─── Single Context Agent (Unified Reconnaissance) ───────────
|
|
420
422
|
const session = createContextAgentSession();
|
|
423
|
+
debugLog(`[Context Agent] Starting reconnaissance [Model: ${session.getModel()}, Thinking: ${session.getThinkingLevel() || 'MEDIUM'}]`);
|
|
421
424
|
const relevantFiles = new Map();
|
|
422
425
|
let summary = 'No relevant context found.';
|
|
423
426
|
let isInvestigationFinished = false;
|
|
@@ -430,6 +433,26 @@ export async function gatherContext(workspaceRoot, userRequest, chatHistory = ''
|
|
|
430
433
|
const prunedHistory = pruneTextToTokenBudget(chatHistory, MAX_CHAT_HISTORY_INVESTIGATION_TOKENS, { fromStart: true });
|
|
431
434
|
currentMessage = `Previous Conversation Context:\n${prunedHistory}\n\n` + currentMessage;
|
|
432
435
|
}
|
|
436
|
+
// Parse explicit context mentions from user request to prioritize referenced files
|
|
437
|
+
try {
|
|
438
|
+
const { mentionEngine } = await import('./mentionEngine.js');
|
|
439
|
+
const parsedMentions = mentionEngine.parseMentions(userRequest, workspaceRoot);
|
|
440
|
+
const explicitMentionedFiles = parsedMentions
|
|
441
|
+
.filter((m) => m.type === 'file' && m.valid)
|
|
442
|
+
.map((m) => m.target);
|
|
443
|
+
if (parsedMentions.length > 0) {
|
|
444
|
+
const validMentions = parsedMentions.filter((m) => m.valid);
|
|
445
|
+
if (validMentions.length > 0 && onProgress) {
|
|
446
|
+
const mentionLabels = validMentions.map((m) => m.raw).slice(0, 4).join(', ');
|
|
447
|
+
const overflow = validMentions.length > 4 ? ` (+${validMentions.length - 4} more)` : '';
|
|
448
|
+
onProgress(`Found explicit context: ${mentionLabels}${overflow}`);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
if (explicitMentionedFiles.length > 0) {
|
|
452
|
+
currentMessage += `\n\nExplicit Mentioned Files from User Request:\n${explicitMentionedFiles.map((f) => `- ${f}`).join('\n')}`;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
catch { }
|
|
433
456
|
currentMessage += `\n\nStart investigating to find relevant files.`;
|
|
434
457
|
const MAX_TURNS = Infinity;
|
|
435
458
|
let textRetryCount = 0;
|
|
@@ -235,7 +235,7 @@ Approximate File Count: ${approximateFileCount}`;
|
|
|
235
235
|
if (chatHistory.trim()) {
|
|
236
236
|
prompt += `\n\nRecent Conversation:\n${chatHistory.trim()}`;
|
|
237
237
|
}
|
|
238
|
-
debugLog(`[InvestigationComplexity] Evaluating prompt complexity (autoFocus: ${activeSubPath || 'none'}, override: ${explicitOverride || 'none'})`);
|
|
238
|
+
debugLog(`[InvestigationComplexity] Evaluating prompt complexity (autoFocus: ${activeSubPath || 'none'}, override: ${explicitOverride || 'none'}) [Model: ${session.getModel()}, Thinking: ${session.getThinkingLevel() || 'MEDIUM'}]`);
|
|
239
239
|
const response = await session.sendMessage(prompt, undefined, abortSignal);
|
|
240
240
|
const rawText = typeof response?.response?.text === 'function'
|
|
241
241
|
? response.response.text()
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Context Mentions and Autocomplete Engine for Minovative Mind CLI.
|
|
3
|
+
*
|
|
4
|
+
* This service provides:
|
|
5
|
+
* 1. **Autocomplete Suggestions**: Real-time suggestion generation for `@files`, `@symbols`,
|
|
6
|
+
* `@git` context helpers, `@workspace` aliases, and `@diagnostics` / special mentions.
|
|
7
|
+
* 2. **Mention Parsing**: Robust parsing of `@mention` tokens in user prompts with support for
|
|
8
|
+
* line ranges (`:10-50`), scoped symbol targets (`@symbol:foo`), git modifiers (`@git:diff`),
|
|
9
|
+
* and cross-workspace references (`@alias/path`).
|
|
10
|
+
* 3. **Context Resolution**: Resolves all mentions in a prompt into structured, sanitized,
|
|
11
|
+
* token-budgeted XML injection blocks ready for LLM consumption.
|
|
12
|
+
*/
|
|
13
|
+
import { SymbolKind } from '../utils/symbolExtractor.js';
|
|
14
|
+
/**
|
|
15
|
+
* Types of context mentions supported by the engine.
|
|
16
|
+
*/
|
|
17
|
+
export type MentionType = 'file' | 'symbol' | 'git' | 'workspace' | 'diagnostics' | 'terminal';
|
|
18
|
+
/**
|
|
19
|
+
* Represents a parsed `@mention` token extracted from a user prompt.
|
|
20
|
+
*/
|
|
21
|
+
export interface ParsedMention {
|
|
22
|
+
/** The full raw matched mention string (e.g. `@src/utils/config.ts`, `@git:diff`, `@symbol:runAgent`) */
|
|
23
|
+
raw: string;
|
|
24
|
+
/** The classified type of mention */
|
|
25
|
+
type: MentionType;
|
|
26
|
+
/** The primary target identifier (e.g. `src/utils/config.ts`, `runAgent`, `diff`, `backend`) */
|
|
27
|
+
target: string;
|
|
28
|
+
/** Optional secondary target (e.g. symbol name if format is `@symbol:file.ts:symbolName`) */
|
|
29
|
+
subTarget?: string;
|
|
30
|
+
/** Optional external workspace alias if referencing a registered external workspace */
|
|
31
|
+
workspaceAlias?: string | null;
|
|
32
|
+
/** Optional line range specified in file mention (1-indexed) */
|
|
33
|
+
lineRange?: {
|
|
34
|
+
start: number;
|
|
35
|
+
end: number;
|
|
36
|
+
};
|
|
37
|
+
/** The 0-based character offsets [start, end] of the mention token in the original prompt */
|
|
38
|
+
range: [number, number];
|
|
39
|
+
/** Whether the mention parsed into a structurally valid format */
|
|
40
|
+
valid: boolean;
|
|
41
|
+
/** Optional parse or resolution warning */
|
|
42
|
+
error?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* An autocomplete suggestion item presented to the user during interactive typing.
|
|
46
|
+
*/
|
|
47
|
+
export interface MentionSuggestion {
|
|
48
|
+
/** The display label shown in autocomplete dropdown */
|
|
49
|
+
label: string;
|
|
50
|
+
/** The text inserted/replaced when this suggestion is selected */
|
|
51
|
+
value: string;
|
|
52
|
+
/** The mention classification type */
|
|
53
|
+
type: MentionType;
|
|
54
|
+
/** Optional category badge for styling (e.g. 'file', 'lines', 'sym', 'git', 'ws', 'diag', 'term') */
|
|
55
|
+
category?: 'file' | 'lines' | 'symbol' | 'sym' | 'git' | 'workspace' | 'ws' | 'diagnostics' | 'diag' | 'terminal' | 'term' | 'doc' | string;
|
|
56
|
+
/** A concise human-readable description (e.g. "Git working tree diff", "File (4.2 KB)") */
|
|
57
|
+
description: string;
|
|
58
|
+
/** Detailed metadata or subtitle */
|
|
59
|
+
detail?: string;
|
|
60
|
+
/** Descriptive helper label indicating category/parsing status */
|
|
61
|
+
helperLabel?: string;
|
|
62
|
+
/** Display icon / glyph */
|
|
63
|
+
icon?: string;
|
|
64
|
+
/** Relevance ranking score (higher is better) */
|
|
65
|
+
score?: number;
|
|
66
|
+
/** External workspace alias if applicable */
|
|
67
|
+
workspaceAlias?: string | null;
|
|
68
|
+
/** Associated file path if applicable */
|
|
69
|
+
filePath?: string;
|
|
70
|
+
/** Associated symbol kind if applicable */
|
|
71
|
+
symbolKind?: SymbolKind | string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Configuration options for generating autocomplete suggestions.
|
|
75
|
+
*/
|
|
76
|
+
export interface MentionSuggestionOptions {
|
|
77
|
+
/** The primary workspace root directory (defaults to process.cwd()) */
|
|
78
|
+
workspaceRoot?: string;
|
|
79
|
+
/** The active search query typed after the `@` symbol */
|
|
80
|
+
query?: string;
|
|
81
|
+
/** The 0-based cursor position in the input string */
|
|
82
|
+
cursorPosition?: number;
|
|
83
|
+
/** Maximum number of suggestions to return (defaults to 25) */
|
|
84
|
+
maxSuggestions?: number;
|
|
85
|
+
/** Filter to specific mention types (e.g. only ['file', 'symbol']) */
|
|
86
|
+
includeTypes?: MentionType[];
|
|
87
|
+
/** Optional pre-computed file list to accelerate suggestion generation */
|
|
88
|
+
cachedFileList?: string[];
|
|
89
|
+
/** Maximum number of files to scan for symbols */
|
|
90
|
+
maxSymbolFiles?: number;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Result of resolving a single mention's contents.
|
|
94
|
+
*/
|
|
95
|
+
export interface ResolvedMentionContext {
|
|
96
|
+
/** The original parsed mention */
|
|
97
|
+
mention: ParsedMention;
|
|
98
|
+
/** Whether resolution succeeded without fatal errors */
|
|
99
|
+
resolved: boolean;
|
|
100
|
+
/** The structured XML context block representing the resolved content */
|
|
101
|
+
content: string;
|
|
102
|
+
/** Estimated token count of the content block */
|
|
103
|
+
tokenEstimate: number;
|
|
104
|
+
/** Error message if resolution failed */
|
|
105
|
+
error?: string;
|
|
106
|
+
/** Concise status label indicating resolution summary (e.g. "lines 10-50, 420 chars") */
|
|
107
|
+
statusLabel?: string;
|
|
108
|
+
/** Descriptive helper badge/label for status and parsing details */
|
|
109
|
+
helperLabel?: string;
|
|
110
|
+
/** Supplementary structured metadata */
|
|
111
|
+
metadata?: {
|
|
112
|
+
absolutePath?: string;
|
|
113
|
+
relativePath?: string;
|
|
114
|
+
sizeBytes?: number;
|
|
115
|
+
charCount?: number;
|
|
116
|
+
linesCount?: number;
|
|
117
|
+
totalLines?: number;
|
|
118
|
+
lineRange?: {
|
|
119
|
+
start: number;
|
|
120
|
+
end: number;
|
|
121
|
+
};
|
|
122
|
+
isSliced?: boolean;
|
|
123
|
+
workspaceAlias?: string | null;
|
|
124
|
+
symbol?: string;
|
|
125
|
+
filePath?: string;
|
|
126
|
+
kind?: string;
|
|
127
|
+
signature?: string;
|
|
128
|
+
startLine?: number;
|
|
129
|
+
endLine?: number;
|
|
130
|
+
gitSubCommand?: string;
|
|
131
|
+
contextType?: string;
|
|
132
|
+
outputLines?: number;
|
|
133
|
+
isClean?: boolean;
|
|
134
|
+
alias?: string;
|
|
135
|
+
path?: string;
|
|
136
|
+
profile?: string;
|
|
137
|
+
filesCount?: number;
|
|
138
|
+
filesChecked?: number;
|
|
139
|
+
issuesCount?: number;
|
|
140
|
+
issues?: string[];
|
|
141
|
+
platform?: string;
|
|
142
|
+
arch?: string;
|
|
143
|
+
nodeVersion?: string;
|
|
144
|
+
cwd?: string;
|
|
145
|
+
statusLabel?: string;
|
|
146
|
+
helperLabel?: string;
|
|
147
|
+
category?: string;
|
|
148
|
+
[key: string]: any;
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Options configuring mention content resolution.
|
|
153
|
+
*/
|
|
154
|
+
export interface ResolveMentionsOptions {
|
|
155
|
+
/** Maximum total character budget for resolved context injection */
|
|
156
|
+
maxChars?: number;
|
|
157
|
+
/** Whether to use AST-scoped outlines for large source files */
|
|
158
|
+
useScopedOutline?: boolean;
|
|
159
|
+
/** Git command execution timeout in milliseconds (defaults to 5000) */
|
|
160
|
+
gitTimeoutMs?: number;
|
|
161
|
+
/** Maximum lines per extracted symbol definition (defaults to 300) */
|
|
162
|
+
symbolMaxLines?: number;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Comprehensive result of parsing and resolving all mentions in a prompt.
|
|
166
|
+
*/
|
|
167
|
+
export interface ResolvedMentionsResult {
|
|
168
|
+
/** The original prompt string as provided by the user */
|
|
169
|
+
originalPrompt: string;
|
|
170
|
+
/** Cleaned prompt string with mentions intact */
|
|
171
|
+
cleanedPrompt: string;
|
|
172
|
+
/** Array of individual resolved mention blocks */
|
|
173
|
+
mentions: ResolvedMentionContext[];
|
|
174
|
+
/** The unified XML context injection block `<context_mentions>...</context_mentions>` */
|
|
175
|
+
formattedContext: string;
|
|
176
|
+
/** Total estimated token count across all resolved mentions */
|
|
177
|
+
totalTokens: number;
|
|
178
|
+
/** Indicates whether any valid mentions were found and processed */
|
|
179
|
+
hasMentions: boolean;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Context Mentions Engine.
|
|
183
|
+
*
|
|
184
|
+
* Core engine responsible for parsing `@` tokens, providing fast autocomplete suggestions,
|
|
185
|
+
* and resolving file, symbol, git, workspace, and diagnostic mentions into structured context.
|
|
186
|
+
*/
|
|
187
|
+
export declare class MentionEngine {
|
|
188
|
+
/** In-memory cache for workspace file listings (TTL: 15 seconds) */
|
|
189
|
+
private fileListCache;
|
|
190
|
+
/** In-memory cache for parsed symbol indexes per file path */
|
|
191
|
+
private symbolIndexCache;
|
|
192
|
+
/** Cache TTL in milliseconds */
|
|
193
|
+
private readonly CACHE_TTL_MS;
|
|
194
|
+
/**
|
|
195
|
+
* Parses all `@mention` tokens from a user prompt text string.
|
|
196
|
+
*
|
|
197
|
+
* Correctly ignores email addresses (e.g. `user@domain.com`) and supports:
|
|
198
|
+
* - `@file:<path>` or `@<path>` (e.g. `@src/index.ts`, `@src/index.ts:10-50`)
|
|
199
|
+
* - `@symbol:<name>` or `@#<name>` or `@symbol:<filePath>:<name>`
|
|
200
|
+
* - `@git:diff`, `@git:staged`, `@git:branch`, `@git:log`, `@git:status`, `@diff`
|
|
201
|
+
* - `@<alias>` or `@<alias>/<path>` for registered external workspaces
|
|
202
|
+
* - `@diagnostics`, `@problems`, `@errors`
|
|
203
|
+
*
|
|
204
|
+
* @param prompt - The input prompt text.
|
|
205
|
+
* @param workspaceRoot - Optional workspace root for alias and file disambiguation.
|
|
206
|
+
* @returns Array of ParsedMention objects.
|
|
207
|
+
*/
|
|
208
|
+
parseMentions(prompt: string, workspaceRoot?: string): ParsedMention[];
|
|
209
|
+
/**
|
|
210
|
+
* Classifies a raw mention token into its appropriate MentionType and targets.
|
|
211
|
+
*
|
|
212
|
+
* @private
|
|
213
|
+
*/
|
|
214
|
+
private classifyMentionToken;
|
|
215
|
+
/**
|
|
216
|
+
* Extracts line range numbers from a path string (e.g. `src/index.ts:10-50` or `src/index.ts#10-50` or `src/index.ts:25`).
|
|
217
|
+
*
|
|
218
|
+
* @private
|
|
219
|
+
*/
|
|
220
|
+
private parseLineRange;
|
|
221
|
+
/**
|
|
222
|
+
* Determines the active mention query at a specific cursor position in an input string.
|
|
223
|
+
*
|
|
224
|
+
* @param input - The current input text.
|
|
225
|
+
* @param cursorPosition - The 0-based cursor offset.
|
|
226
|
+
* @returns Object describing the active mention query and range.
|
|
227
|
+
*/
|
|
228
|
+
getActiveMentionQuery(input: string, cursorPosition: number): {
|
|
229
|
+
query: string;
|
|
230
|
+
startIndex: number;
|
|
231
|
+
endIndex: number;
|
|
232
|
+
isMention: boolean;
|
|
233
|
+
};
|
|
234
|
+
/**
|
|
235
|
+
* Generates ranked autocomplete suggestions based on the current prompt text and cursor position.
|
|
236
|
+
*
|
|
237
|
+
* @param input - Full prompt input text.
|
|
238
|
+
* @param cursorPosition - Cursor index.
|
|
239
|
+
* @param options - Suggestion configuration options.
|
|
240
|
+
* @returns Array of ranked MentionSuggestion objects.
|
|
241
|
+
*/
|
|
242
|
+
getSuggestions(input: string, cursorPosition: number, options?: Partial<MentionSuggestionOptions>): Promise<MentionSuggestion[]>;
|
|
243
|
+
/**
|
|
244
|
+
* Generates autocomplete suggestions for a given raw query string (the text after '@').
|
|
245
|
+
*
|
|
246
|
+
* @param query - The query string typed after '@'.
|
|
247
|
+
* @param options - Configuration options.
|
|
248
|
+
* @returns Array of ranked MentionSuggestion objects.
|
|
249
|
+
*/
|
|
250
|
+
getSuggestionsForQuery(query?: string, options?: Partial<MentionSuggestionOptions>): Promise<MentionSuggestion[]>;
|
|
251
|
+
/**
|
|
252
|
+
* Generates built-in git, diagnostics, terminal, and symbol template suggestions.
|
|
253
|
+
*
|
|
254
|
+
* @private
|
|
255
|
+
*/
|
|
256
|
+
private getSpecialSuggestions;
|
|
257
|
+
/**
|
|
258
|
+
* Generates registered workspace alias suggestions.
|
|
259
|
+
*
|
|
260
|
+
* @private
|
|
261
|
+
*/
|
|
262
|
+
private getWorkspaceSuggestions;
|
|
263
|
+
/**
|
|
264
|
+
* Generates workspace file suggestions with fast fuzzy/prefix matching.
|
|
265
|
+
*
|
|
266
|
+
* @private
|
|
267
|
+
*/
|
|
268
|
+
private getFileSuggestions;
|
|
269
|
+
/**
|
|
270
|
+
* Generates symbol suggestions across indexed source files.
|
|
271
|
+
*
|
|
272
|
+
* @private
|
|
273
|
+
*/
|
|
274
|
+
private getSymbolSuggestions;
|
|
275
|
+
/**
|
|
276
|
+
* Calculates a match score between a user query and candidate keywords.
|
|
277
|
+
* Higher scores represent stronger matches.
|
|
278
|
+
*
|
|
279
|
+
* @private
|
|
280
|
+
*/
|
|
281
|
+
private calculateMatchScore;
|
|
282
|
+
/**
|
|
283
|
+
* Returns a cached recursive list of all relative file paths in the workspace.
|
|
284
|
+
*
|
|
285
|
+
* @param workspaceRoot - Root directory path.
|
|
286
|
+
* @param maxFiles - Safety ceiling on maximum files returned (defaults to 3000).
|
|
287
|
+
* @returns Array of relative file paths.
|
|
288
|
+
*/
|
|
289
|
+
getFileList(workspaceRoot: string, maxFiles?: number): Promise<string[]>;
|
|
290
|
+
/**
|
|
291
|
+
* Extracts and returns all declared symbols across workspace source files.
|
|
292
|
+
*
|
|
293
|
+
* @param workspaceRoot - Workspace root path.
|
|
294
|
+
* @param maxFiles - Maximum source files to scan.
|
|
295
|
+
* @returns Array of symbol entries.
|
|
296
|
+
*/
|
|
297
|
+
getSymbolIndex(workspaceRoot: string, maxFiles?: number): Promise<Array<{
|
|
298
|
+
symbol: string;
|
|
299
|
+
kind?: SymbolKind;
|
|
300
|
+
filePath: string;
|
|
301
|
+
signature?: string;
|
|
302
|
+
startLine: number;
|
|
303
|
+
endLine: number;
|
|
304
|
+
}>>;
|
|
305
|
+
/**
|
|
306
|
+
* Resolves all mentions in a prompt string into structured context injection blocks.
|
|
307
|
+
*
|
|
308
|
+
* @param prompt - The user prompt containing `@mentions`.
|
|
309
|
+
* @param workspaceRoot - The primary workspace root path.
|
|
310
|
+
* @param options - Resolution and token budgeting options.
|
|
311
|
+
* @returns Comprehensive ResolvedMentionsResult containing structured XML blocks.
|
|
312
|
+
*/
|
|
313
|
+
resolveMentions(prompt: string, workspaceRoot?: string, options?: ResolveMentionsOptions): Promise<ResolvedMentionsResult>;
|
|
314
|
+
/**
|
|
315
|
+
* Resolves a single parsed mention into its structured XML context block.
|
|
316
|
+
*
|
|
317
|
+
* @private
|
|
318
|
+
*/
|
|
319
|
+
private resolveSingleMention;
|
|
320
|
+
/**
|
|
321
|
+
* Resolves a file mention (`@file:src/index.ts` or `@src/index.ts:10-50`).
|
|
322
|
+
*
|
|
323
|
+
* @private
|
|
324
|
+
*/
|
|
325
|
+
private resolveFileMention;
|
|
326
|
+
/**
|
|
327
|
+
* Resolves a symbol mention (`@symbol:extractSymbols` or `@#extractSymbols`).
|
|
328
|
+
*
|
|
329
|
+
* @private
|
|
330
|
+
*/
|
|
331
|
+
private resolveSymbolMention;
|
|
332
|
+
/**
|
|
333
|
+
* Resolves a git mention (`@git:diff`, `@git:staged`, `@git:branch`, `@git:log`, `@git:status`, `@diff`).
|
|
334
|
+
*
|
|
335
|
+
* @private
|
|
336
|
+
*/
|
|
337
|
+
private resolveGitMention;
|
|
338
|
+
/**
|
|
339
|
+
* Resolves a registered workspace alias mention (`@effortlist-ai`).
|
|
340
|
+
*
|
|
341
|
+
* @private
|
|
342
|
+
*/
|
|
343
|
+
private resolveWorkspaceMention;
|
|
344
|
+
/**
|
|
345
|
+
* Resolves diagnostics / problems mention (`@diagnostics`, `@problems`, `@errors`).
|
|
346
|
+
*
|
|
347
|
+
* @private
|
|
348
|
+
*/
|
|
349
|
+
private resolveDiagnosticsMention;
|
|
350
|
+
/**
|
|
351
|
+
* Resolves terminal / console mention (`@terminal`, `@console`).
|
|
352
|
+
*
|
|
353
|
+
* @private
|
|
354
|
+
*/
|
|
355
|
+
private resolveTerminalMention;
|
|
356
|
+
/**
|
|
357
|
+
* Formats resolved mention blocks into a unified XML context injection string,
|
|
358
|
+
* respecting character budget limits.
|
|
359
|
+
*
|
|
360
|
+
* @param resolvedMentions - Array of resolved mention blocks.
|
|
361
|
+
* @param maxChars - Optional maximum character budget.
|
|
362
|
+
* @returns Unified XML context block.
|
|
363
|
+
*/
|
|
364
|
+
formatMentionsContext(resolvedMentions: ResolvedMentionContext[], maxChars?: number): string;
|
|
365
|
+
/**
|
|
366
|
+
* Helper to get an icon glyph corresponding to a file extension.
|
|
367
|
+
*
|
|
368
|
+
* @private
|
|
369
|
+
*/
|
|
370
|
+
private getFileIcon;
|
|
371
|
+
/**
|
|
372
|
+
* Helper to get an icon glyph corresponding to a symbol kind.
|
|
373
|
+
*
|
|
374
|
+
* @private
|
|
375
|
+
*/
|
|
376
|
+
private getSymbolIcon;
|
|
377
|
+
/**
|
|
378
|
+
* Clears in-memory caches for file listings and symbols.
|
|
379
|
+
*/
|
|
380
|
+
clearCaches(): void;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Singleton instance of the MentionEngine.
|
|
384
|
+
*/
|
|
385
|
+
export declare const mentionEngine: MentionEngine;
|