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.
@@ -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;