minovative-mind-cli 2.9.1 → 2.10.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 CHANGED
@@ -89,7 +89,7 @@ Hot-swap during a session using `/models`:
89
89
  | Model | Best for |
90
90
  | ------------------------- | --------------------------------------------------- |
91
91
  | **Auto** (default) | Automatically selects (3.7 Flash or 3.5 Flash Lite) |
92
- | **Gemini 3.7 Flash** | Next-gen performance, reasoning & fast execution |
92
+ | **Gemini 3.7 Flash** | Next-gen performance, reasoning & fast execution |
93
93
  | **Gemini 3.6 Flash** | Everyday coding — fast and accurate |
94
94
  | **Gemini 3.1 Pro** | Complex architectural changes |
95
95
  | **Gemini 3.5 Flash Lite** | Best for speed and cost efficiency |
@@ -101,11 +101,19 @@ If you prefer to use your own API key instead of credits, you can configure it v
101
101
  - **Configuration:** Use `/config-key` in the chat session to set and manage your API key.
102
102
  - **Error Handling:** If your key is invalid, expired, or you hit rate limits, the CLI will report a `BYOK AI Error`. Please check your API key status in the [Google AI Studio dashboard](https://aistudio.google.com).
103
103
 
104
- > Background tasks (routing, history summarization, context compression, commits) always use lightweight
105
- > models automatically. You pay for those lightweight model
106
- > background ai models and for your selected model
107
- > during chat and code execution.
108
- > Use `/debug` to see exactly what's running.
104
+ ### Auxiliary Model Routing Defaults
105
+
106
+ Background tasks automatically route to dedicated auxiliary models with native `responseSchema` constraints for optimal latency, cost efficiency, and structured output reliability:
107
+
108
+ - **Intent Router (`routeIntent`)**: `Gemini 3.7 Flash` (Temp 0, native `responseSchema`) — zero-temperature classification of `SEARCH` vs `SKIP` and `CHAT` vs `EXECUTE`.
109
+ - **Complexity Evaluators**: `Gemini 3.7 Flash` (Temp 0, native `responseSchema`) — domain partitioning and parallel execution wave feasibility.
110
+ - **Context Compressor**: `Gemini 3.7 Flash` (Temp 0.2) — surgical code distillation for files exceeding 2,000 characters.
111
+ - **Session Titling**: `Gemini 3.7 Flash` (Temp 0.7, native `responseSchema`) — automated concise chat session titling.
112
+ - **Semantic Cache Classifier**: `Gemini 3.5 Flash Lite` (Temp 0, native `responseSchema`) — intent and topic classification for cache hits.
113
+ - **History Summarizer**: `Gemini 3.7 Flash` (Temp 0.2) — 3-part structured conversation compression preserving recent history.
114
+ - **Commit Generator**: `Gemini 3.5 Flash Lite` — conventional commit message synthesis.
115
+
116
+ > You pay for auxiliary model background AI operations and for your selected model during chat and code execution. Use `/debug` to inspect real-time routing diagnostics.
109
117
 
110
118
  ---
111
119
 
@@ -715,7 +715,7 @@ export async function handleSlashCommand(command, context) {
715
715
  }
716
716
  else if (chatsMenu === 'bulk-delete') {
717
717
  const selectedIds = await p['multiselect']({
718
- message: 'Select chat sessions to delete:',
718
+ message: `Select chat sessions to delete: ${pc.dim('(Press Esc to go back / cancel)')}`,
719
719
  options: sessions
720
720
  .slice()
721
721
  .sort((a, b) => (b.timestamp || 0) - (a.timestamp || 0))
@@ -723,7 +723,7 @@ export async function handleSlashCommand(command, context) {
723
723
  value: s.id,
724
724
  label: `${truncate(s.title, 50)} (${new Date(s.timestamp).toLocaleString()})`,
725
725
  })),
726
- required: true,
726
+ required: false,
727
727
  });
728
728
  if (p.isCancel(selectedIds) || !Array.isArray(selectedIds) || selectedIds.length === 0) {
729
729
  p.log.warn('Bulk delete canceled.');
@@ -735,6 +735,16 @@ export async function handleSlashCommand(command, context) {
735
735
  if (confirm) {
736
736
  await chatHistoryService.bulkDeleteSessions(selectedIds);
737
737
  p.log.success(`Successfully deleted ${selectedIds.length} session(s).`);
738
+ if (chatSessionState && selectedIds.includes(chatSessionState.id)) {
739
+ chat.clearHistory();
740
+ process.stdout.write('\x1B[2J\x1B[3J\x1B[H'); // Hard clear screen and scrollback
741
+ printLogo();
742
+ p.intro(`${brandBg(' Minovative Mind CLI ')} ${pc.dim('v' + version)}`);
743
+ p.log.info(`${pc.dim('Workspace:')} ${brandFg(workspaceRoot)}`);
744
+ p.log.info(`${pc.dim('Commands:')} Type ${pc.yellow('/')} to open the command menu and "${pc.yellow('stop')}" to stop the ai generation. Type ${pc.yellow('exit')} to leave.`);
745
+ p.log.warn('Active session was deleted. Chat history cleared.');
746
+ console.log(pc.dim('\nType your coding request below. Type "exit" or "quit" to leave.\n'));
747
+ }
738
748
  }
739
749
  else {
740
750
  p.log.warn('Bulk delete canceled.');
@@ -77,7 +77,7 @@ export declare function getPlanModeConfig(): {
77
77
  tools: never[];
78
78
  };
79
79
  /**
80
- * Compresses a large string of text using gemini-3.5-flash-lite.
80
+ * Compresses a large string of text using Gemini Flash.
81
81
  * Used for shrinking context payloads to prevent OOM/choking.
82
82
  */
83
83
  export declare function compressTextUsingFlashLite(text: string, instruction?: string, inlineData?: any, force?: boolean, abortSignal?: AbortSignal): Promise<string>;
@@ -91,6 +91,7 @@ export declare function createContextAgentSession(): any;
91
91
  export declare function createIntentRouterSession(): any;
92
92
  export declare function createExecutionComplexitySession(): any;
93
93
  export declare function createInvestigationComplexitySession(): any;
94
+ export declare function createInvestigationSemanticSession(): any;
94
95
  export declare function createWebSearchAgentSession(): any;
95
96
  export declare function createHistorySummarizerSession(): any;
96
97
  /**
@@ -5,7 +5,7 @@ import { getMetricCollector } from './metrics.js';
5
5
  import { getAuthorizedIdToken, checkByokSubscription } from './auth.js';
6
6
  import { debugLog } from '../utils/logger.js';
7
7
  import { readCache, writeCache } from '../utils/projectStorage.js';
8
- import { GENERAL_CHAT_INSTRUCTION, PLAN_EXECUTION_INSTRUCTION, PLAN_MODE_INSTRUCTION, CONTEXT_SYSTEM_INSTRUCTION, INTENT_ROUTER_SYSTEM_INSTRUCTION, WEB_SEARCH_SYSTEM_INSTRUCTION, EXECUTION_COMPLEXITY_SYSTEM_INSTRUCTION, INVESTIGATION_COMPLEXITY_SYSTEM_INSTRUCTION, HISTORY_SUMMARIZER_SYSTEM_INSTRUCTION, } from '../utils/systemPrompts.js';
8
+ import { GENERAL_CHAT_INSTRUCTION, PLAN_EXECUTION_INSTRUCTION, PLAN_MODE_INSTRUCTION, CONTEXT_SYSTEM_INSTRUCTION, INTENT_ROUTER_SYSTEM_INSTRUCTION, WEB_SEARCH_SYSTEM_INSTRUCTION, EXECUTION_COMPLEXITY_SYSTEM_INSTRUCTION, INVESTIGATION_COMPLEXITY_SYSTEM_INSTRUCTION, INVESTIGATION_SEMANTIC_SYSTEM_INSTRUCTION, HISTORY_SUMMARIZER_SYSTEM_INSTRUCTION, } from '../utils/systemPrompts.js';
9
9
  import { workspaceRegistry } from './workspaceRegistry.js';
10
10
  import { loadCredentials } from '../utils/credentialStore.js';
11
11
  import { ProxyClient } from './proxyClient.js';
@@ -345,7 +345,7 @@ export function getPlanModeConfig() {
345
345
  };
346
346
  }
347
347
  /**
348
- * Compresses a large string of text using gemini-3.5-flash-lite.
348
+ * Compresses a large string of text using Gemini Flash.
349
349
  * Used for shrinking context payloads to prevent OOM/choking.
350
350
  */
351
351
  export async function compressTextUsingFlashLite(text, instruction = "<directives>\nSummarize the following text concisely. Preserve the most critical technical details, function names, and architecture logic. Make sure it's understandable without the fluff.\n</directives>", inlineData, force = false, abortSignal) {
@@ -357,7 +357,7 @@ export async function compressTextUsingFlashLite(text, instruction = "<directive
357
357
  const idToken = await getAuthorizedIdToken();
358
358
  if (!idToken)
359
359
  return text;
360
- let model = GEMINI_MODELS.FLASH_LITE;
360
+ let model = GEMINI_MODELS.FLASH;
361
361
  const parts = [{ text }];
362
362
  if (inlineData) {
363
363
  parts.push({ inlineData });
@@ -397,7 +397,7 @@ export async function compressTextUsingFlashLite(text, instruction = "<directive
397
397
  if (abortSignal?.aborted || error?.name === 'AbortError' || error?.message?.includes('abort')) {
398
398
  return text;
399
399
  }
400
- debugLog(`Failed to compress text using flash-lite: ${error}`);
400
+ debugLog(`Failed to compress text using flash: ${error}`);
401
401
  if (error?.status === 401 ||
402
402
  error?.status === 403 ||
403
403
  error?.message?.includes('API_KEY_INVALID') ||
@@ -568,25 +568,143 @@ export function createContextAgentSession() {
568
568
  export function createIntentRouterSession() {
569
569
  let model = getGlobalActiveModel();
570
570
  if (model === 'auto' || model.includes('claude'))
571
- model = GEMINI_MODELS.FLASH_LITE;
571
+ model = GEMINI_MODELS.FLASH;
572
572
  return new ProxyChatSession(model, INTENT_ROUTER_SYSTEM_INSTRUCTION, [], // no tools
573
- { temperature: 0, responseMimeType: 'application/json' });
573
+ {
574
+ temperature: 0,
575
+ responseMimeType: 'application/json',
576
+ responseSchema: {
577
+ type: SchemaType.OBJECT,
578
+ properties: {
579
+ context: {
580
+ type: SchemaType.STRING,
581
+ enum: ['SEARCH', 'SKIP'],
582
+ description: 'Whether workspace context search is required',
583
+ },
584
+ agent: {
585
+ type: SchemaType.STRING,
586
+ enum: ['CHAT', 'EXECUTE'],
587
+ description: 'Target agent to route the request to',
588
+ },
589
+ },
590
+ required: ['context', 'agent'],
591
+ },
592
+ });
574
593
  }
575
594
  // ─── Execution Complexity Router Service ──────────────────────────────
576
595
  export function createExecutionComplexitySession() {
577
596
  let model = getGlobalActiveModel();
578
597
  if (model === 'auto' || model.includes('claude'))
579
- model = GEMINI_MODELS.FLASH_LITE;
598
+ model = GEMINI_MODELS.FLASH;
580
599
  return new ProxyChatSession(model, EXECUTION_COMPLEXITY_SYSTEM_INSTRUCTION, [], // no tools
581
- { temperature: 0, responseMimeType: 'application/json' });
600
+ {
601
+ temperature: 0,
602
+ responseMimeType: 'application/json',
603
+ responseSchema: {
604
+ type: SchemaType.OBJECT,
605
+ properties: {
606
+ complexity: {
607
+ type: SchemaType.STRING,
608
+ enum: ['EASY', 'HARD'],
609
+ description: 'Execution task complexity rating',
610
+ },
611
+ },
612
+ required: ['complexity'],
613
+ },
614
+ });
582
615
  }
583
616
  // ─── Investigation Complexity Router Service ─────────────────────────
584
617
  export function createInvestigationComplexitySession() {
585
618
  let model = getGlobalActiveModel();
586
619
  if (model === 'auto' || model.includes('claude'))
587
- model = GEMINI_MODELS.FLASH_LITE;
620
+ model = GEMINI_MODELS.FLASH;
588
621
  return new ProxyChatSession(model, INVESTIGATION_COMPLEXITY_SYSTEM_INSTRUCTION, [], // no tools
589
- { temperature: 0, responseMimeType: 'application/json' });
622
+ {
623
+ temperature: 0,
624
+ responseMimeType: 'application/json',
625
+ responseSchema: {
626
+ type: SchemaType.OBJECT,
627
+ properties: {
628
+ strategy: {
629
+ type: SchemaType.STRING,
630
+ enum: ['SINGLE', 'PARALLEL'],
631
+ description: 'Investigation strategy (SINGLE or PARALLEL)',
632
+ },
633
+ domains: {
634
+ type: SchemaType.ARRAY,
635
+ items: {
636
+ type: SchemaType.STRING,
637
+ },
638
+ description: 'All identified investigation domains',
639
+ },
640
+ agentAssignments: {
641
+ type: SchemaType.ARRAY,
642
+ items: {
643
+ type: SchemaType.OBJECT,
644
+ properties: {
645
+ agentLabel: {
646
+ type: SchemaType.STRING,
647
+ description: 'Label of the sub-agent',
648
+ },
649
+ domains: {
650
+ type: SchemaType.ARRAY,
651
+ items: {
652
+ type: SchemaType.STRING,
653
+ },
654
+ description: 'Domains assigned to this sub-agent',
655
+ },
656
+ },
657
+ required: ['agentLabel', 'domains'],
658
+ },
659
+ description: 'Sub-agent domain group assignments',
660
+ },
661
+ reasoning: {
662
+ type: SchemaType.STRING,
663
+ description: 'Brief justification for the chosen strategy and grouping',
664
+ },
665
+ },
666
+ required: ['strategy', 'domains', 'agentAssignments', 'reasoning'],
667
+ },
668
+ });
669
+ }
670
+ // ─── Investigation Semantic Router Service ───────────────────────────
671
+ export function createInvestigationSemanticSession() {
672
+ let model = getGlobalActiveModel();
673
+ if (model === 'auto' || model.includes('claude'))
674
+ model = GEMINI_MODELS.FLASH_LITE;
675
+ return new ProxyChatSession(model, INVESTIGATION_SEMANTIC_SYSTEM_INSTRUCTION, [], // no tools
676
+ {
677
+ temperature: 0,
678
+ responseMimeType: 'application/json',
679
+ responseSchema: {
680
+ type: SchemaType.OBJECT,
681
+ properties: {
682
+ topics: {
683
+ type: SchemaType.ARRAY,
684
+ items: {
685
+ type: SchemaType.STRING,
686
+ },
687
+ description: 'Technical topic or domain identifiers',
688
+ },
689
+ components: {
690
+ type: SchemaType.ARRAY,
691
+ items: {
692
+ type: SchemaType.STRING,
693
+ },
694
+ description: 'Target component, file, function, or endpoint names',
695
+ },
696
+ intent: {
697
+ type: SchemaType.STRING,
698
+ description: 'Primary intent category (e.g. bug_fix, feature_addition, explanation, refactoring)',
699
+ },
700
+ reasoning: {
701
+ type: SchemaType.STRING,
702
+ description: 'Brief justification for the extracted metadata',
703
+ },
704
+ },
705
+ required: ['topics', 'components', 'intent'],
706
+ },
707
+ });
590
708
  }
591
709
  // ─── Web Search Agent Service ───────────────────────────────────────────
592
710
  export function createWebSearchAgentSession() {
@@ -604,7 +722,7 @@ export function createWebSearchAgentSession() {
604
722
  export function createHistorySummarizerSession() {
605
723
  let model = getGlobalActiveModel();
606
724
  if (model === 'auto' || model.includes('claude'))
607
- model = GEMINI_MODELS.FLASH_LITE;
725
+ model = GEMINI_MODELS.FLASH;
608
726
  return new ProxyChatSession(model, HISTORY_SUMMARIZER_SYSTEM_INSTRUCTION, [], {
609
727
  temperature: 0.2,
610
728
  maxOutputTokens: MAX_OUTPUT_TOKENS,
@@ -655,7 +773,7 @@ export async function generateChatTitle(firstMessage, abortSignal) {
655
773
  const contents = [{ role: 'user', parts: [{ text: firstMessage.substring(0, 500) }] }];
656
774
  let model = getGlobalActiveModel();
657
775
  if (model === 'auto' || model.includes('claude'))
658
- model = GEMINI_MODELS.FLASH_LITE;
776
+ model = GEMINI_MODELS.FLASH;
659
777
  const byokEnabled = await isByokEnabled();
660
778
  let result;
661
779
  if (byokEnabled) {
@@ -246,7 +246,31 @@ export async function gatherContext(workspaceRoot, userRequest, chatHistory = ''
246
246
  }
247
247
  const projectType = primaryProjectType;
248
248
  const { lookupInvestigation, saveInvestigation } = await import('./orchestration/investigationCache.js');
249
- const cacheHit = await lookupInvestigation(workspaceRoot, userRequest);
249
+ const collector = getMetricCollector();
250
+ const lookupStart = Date.now();
251
+ let cacheHit = null;
252
+ try {
253
+ cacheHit = await lookupInvestigation(workspaceRoot, userRequest, {
254
+ abortSignal,
255
+ onProgress,
256
+ allowSemanticFallback: true,
257
+ });
258
+ if (collector) {
259
+ collector.recordCachePerformance('investigation', Date.now() - lookupStart);
260
+ if (cacheHit) {
261
+ collector.recordCacheHit('investigation');
262
+ }
263
+ else {
264
+ collector.recordCacheMiss('investigation');
265
+ }
266
+ }
267
+ }
268
+ catch (err) {
269
+ if (err?.name === 'AbortError' || abortSignal?.aborted) {
270
+ throw err;
271
+ }
272
+ debugLog(`Investigation cache lookup error: ${err?.message || err}`);
273
+ }
250
274
  if (cacheHit) {
251
275
  if (onProgress)
252
276
  onProgress(`⚡ Memory Bank HIT — loaded ${cacheHit.entry.relevantFiles.length} files from cache`);
@@ -596,7 +620,6 @@ export async function gatherContext(workspaceRoot, userRequest, chatHistory = ''
596
620
  // Prepare next turn
597
621
  currentMessage = functionResponses;
598
622
  }
599
- const collector = getMetricCollector();
600
623
  if (collector) {
601
624
  collector.recordContextSelectedFiles(Array.from(relevantFiles.keys()));
602
625
  if (!isInvestigationFinished || relevantFiles.size === 0) {
@@ -604,8 +627,16 @@ export async function gatherContext(workspaceRoot, userRequest, chatHistory = ''
604
627
  }
605
628
  }
606
629
  if (isInvestigationFinished && relevantFiles.size > 0) {
607
- const { saveInvestigation } = await import('./orchestration/investigationCache.js');
608
- await saveInvestigation(workspaceRoot, userRequest, Array.from(relevantFiles.keys()), summary);
630
+ try {
631
+ const { saveInvestigation } = await import('./orchestration/investigationCache.js');
632
+ await saveInvestigation(workspaceRoot, userRequest, Array.from(relevantFiles.keys()), summary, undefined, abortSignal);
633
+ }
634
+ catch (err) {
635
+ if (err?.name === 'AbortError' || abortSignal?.aborted) {
636
+ throw err;
637
+ }
638
+ debugLog(`Failed to save investigation to cache: ${err?.message || err}`);
639
+ }
609
640
  }
610
641
  return {
611
642
  contextResult: { projectTree, projectType, relevantFiles, summary, webSearchSummary, isParallel: false },
@@ -31,7 +31,7 @@ export interface InvestigationComplexityResult {
31
31
  /**
32
32
  * Evaluates whether the investigation phase should be parallelized.
33
33
  *
34
- * Uses `gemini-3.5-flash-lite` (under auto mode) at temperature 0 to classify the prompt's
34
+ * Uses `gemini-3.7-flash` (under auto mode) at temperature 0 to classify the prompt's
35
35
  * investigation complexity. The PM dynamically identifies domains and groups
36
36
  * them into agent assignments. Agent count = `agentAssignments.length`, which
37
37
  * may be fewer than `domains.length` when related domains are batched together.
@@ -16,7 +16,7 @@ import { debugLog } from '../utils/logger.js';
16
16
  /**
17
17
  * Evaluates whether the investigation phase should be parallelized.
18
18
  *
19
- * Uses `gemini-3.5-flash-lite` (under auto mode) at temperature 0 to classify the prompt's
19
+ * Uses `gemini-3.7-flash` (under auto mode) at temperature 0 to classify the prompt's
20
20
  * investigation complexity. The PM dynamically identifies domains and groups
21
21
  * them into agent assignments. Agent count = `agentAssignments.length`, which
22
22
  * may be fewer than `domains.length` when related domains are batched together.
@@ -1,25 +1,100 @@
1
+ export interface SemanticMetadata {
2
+ topics: string[];
3
+ components: string[];
4
+ intent: string;
5
+ reasoning?: string;
6
+ }
1
7
  export interface InvestigationCacheEntry {
2
8
  promptHash: string;
9
+ normalizedPrompt: string;
10
+ topics?: string[];
11
+ components?: string[];
12
+ intent?: string;
13
+ semanticSignature?: string;
3
14
  relevantFiles: string[];
4
15
  summary: string;
5
16
  workspaceFingerprint: string;
6
17
  createdAt: number;
18
+ lastAccessedAt: number;
19
+ hitCount?: number;
7
20
  }
8
21
  export interface InvestigationCacheStore {
9
22
  entries: Record<string, InvestigationCacheEntry>;
23
+ totalHits?: number;
24
+ totalMisses?: number;
25
+ }
26
+ export interface LookupInvestigationOptions {
27
+ abortSignal?: AbortSignal;
28
+ allowSemanticFallback?: boolean;
29
+ semanticSession?: any;
30
+ onProgress?: (message: string) => void;
31
+ fuzzyThreshold?: number;
32
+ semanticThreshold?: number;
10
33
  }
34
+ export interface LookupInvestigationResult {
35
+ entry: InvestigationCacheEntry;
36
+ bytesSaved: number;
37
+ matchTier: 'exact' | 'fuzzy' | 'semantic';
38
+ similarityScore?: number;
39
+ }
40
+ export declare const MAX_CACHE_SIZE_BYTES: number;
41
+ export declare const DEFAULT_FUZZY_THRESHOLD = 0.85;
42
+ export declare const DEFAULT_SEMANTIC_THRESHOLD = 0.7;
43
+ /**
44
+ * Normalizes prompt by trimming, collapsing whitespace, and stripping common conversation prefixes.
45
+ */
11
46
  export declare function normalizePrompt(prompt: string): string;
47
+ /**
48
+ * Computes SHA-256 hash of a normalized prompt string.
49
+ */
12
50
  export declare function hashPrompt(normalized: string): string;
51
+ /**
52
+ * Generates a deterministic signature from topics, components, and intent.
53
+ */
54
+ export declare function generateSemanticSignature(topics: string[], components: string[], intent?: string): string;
55
+ /**
56
+ * Offline heuristic semantic metadata extractor.
57
+ */
58
+ export declare function extractHeuristicSemanticMetadata(prompt: string, relevantFiles?: string[]): SemanticMetadata;
59
+ /**
60
+ * Classifies prompt semantic intent and entity tags using AI or offline heuristic fallback.
61
+ */
62
+ export declare function classifySemanticIntent(userPrompt: string, abortSignal?: AbortSignal, customSession?: any, timeoutMs?: number): Promise<SemanticMetadata | null>;
63
+ /**
64
+ * Computes a SHA-256 fingerprint of the relevant files' mtime and sizes.
65
+ */
13
66
  export declare function generateWorkspaceFingerprint(workspaceRoot: string, relevantFiles: string[]): Promise<string>;
14
- export declare function lookupInvestigation(workspaceRoot: string, userPrompt: string): Promise<{
15
- entry: InvestigationCacheEntry;
16
- bytesSaved: number;
17
- } | null>;
18
- export declare function saveInvestigation(workspaceRoot: string, userPrompt: string, relevantFiles: string[], summary: string): Promise<void>;
67
+ /**
68
+ * Enforces LRU eviction to keep cache store below MAX_CACHE_SIZE_BYTES (5MB).
69
+ */
70
+ export declare function pruneCacheStore(store: InvestigationCacheStore): void;
71
+ /**
72
+ * Looks up cached investigation results using a 2-Tier matching pipeline:
73
+ * - Tier 1A: Exact hash match
74
+ * - Tier 1B: Local fuzzy Levenshtein & token similarity match
75
+ * - Tier 2: AI semantic topic & component classification match
76
+ * All candidates validate the workspace fingerprint before returning.
77
+ */
78
+ export declare function lookupInvestigation(workspaceRoot: string, userPrompt: string, options?: LookupInvestigationOptions): Promise<LookupInvestigationResult | null>;
79
+ /**
80
+ * Saves investigation context with semantic tagging, workspace fingerprint, and LRU pruning.
81
+ */
82
+ export declare function saveInvestigation(workspaceRoot: string, userPrompt: string, relevantFiles: string[], summary: string, semanticMetadata?: Partial<SemanticMetadata>, abortSignal?: AbortSignal): Promise<void>;
83
+ /**
84
+ * Invalidates cache entries that reference any changed files.
85
+ */
19
86
  export declare function invalidateFilesFromInvestigationCache(workspaceRoot: string, changedFiles: string[]): Promise<void>;
87
+ /**
88
+ * Clears all entries in the investigation cache.
89
+ */
90
+ export declare function clearInvestigationCache(workspaceRoot: string): void;
91
+ /**
92
+ * Returns cache statistics for inspection and telemetry.
93
+ */
20
94
  export declare function getInvestigationCacheStats(workspaceRoot: string): {
21
95
  entries: number;
22
96
  sizeBytes: number;
23
97
  hitCount: number;
24
98
  missCount: number;
99
+ topicsCount: number;
25
100
  };