minovative-mind-cli 2.13.4 → 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.
Files changed (37) hide show
  1. package/README.md +104 -42
  2. package/dist/commands/chat.d.ts +1 -1
  3. package/dist/commands/chat.js +1 -2
  4. package/dist/services/agent/slashCommands.js +47 -23
  5. package/dist/services/agent/syntaxAgent.js +13 -0
  6. package/dist/services/agent/types.d.ts +0 -4
  7. package/dist/services/agent-tools.d.ts +1 -1
  8. package/dist/services/agent-tools.js +2 -2
  9. package/dist/services/agent.d.ts +1 -7
  10. package/dist/services/agent.js +184 -209
  11. package/dist/services/ai.d.ts +19 -4
  12. package/dist/services/ai.js +97 -12
  13. package/dist/services/contextAgent.js +33 -8
  14. package/dist/services/investigationComplexity.js +1 -1
  15. package/dist/services/mentionEngine.d.ts +385 -0
  16. package/dist/services/mentionEngine.js +1395 -0
  17. package/dist/services/orchestration/investigationAgent.js +4 -1
  18. package/dist/services/orchestration/messageBus.d.ts +27 -4
  19. package/dist/services/orchestration/messageBus.js +206 -22
  20. package/dist/services/orchestration/orchestrator.js +4 -0
  21. package/dist/services/orchestration/scopedTools.js +16 -2
  22. package/dist/services/orchestration/subAgent.js +14 -2
  23. package/dist/services/proxyClient.d.ts +38 -2
  24. package/dist/services/proxyClient.js +42 -24
  25. package/dist/services/swebench/sweBenchRunnerService.js +1 -1
  26. package/dist/utils/config.d.ts +75 -0
  27. package/dist/utils/config.js +93 -0
  28. package/dist/utils/contextPrompts.d.ts +28 -4
  29. package/dist/utils/contextPrompts.js +70 -1
  30. package/dist/utils/historyPrompt.d.ts +166 -7
  31. package/dist/utils/historyPrompt.js +775 -30
  32. package/dist/utils/symbolExtractor.d.ts +111 -8
  33. package/dist/utils/symbolExtractor.js +616 -64
  34. package/dist/utils/systemPrompts.d.ts +3 -4
  35. package/dist/utils/systemPrompts.js +5 -34
  36. package/oclif.manifest.json +2 -2
  37. package/package.json +1 -1
@@ -1,11 +1,11 @@
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';
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, INVESTIGATION_SEMANTIC_SYSTEM_INSTRUCTION, HISTORY_SUMMARIZER_SYSTEM_INSTRUCTION, USER_PROFILE_EXTRACTOR_SYSTEM_INSTRUCTION, TRIVIAL_MESSAGE_CLASSIFIER_SYSTEM_INSTRUCTION, } from '../utils/systemPrompts.js';
8
+ import { GENERAL_CHAT_INSTRUCTION, PLAN_EXECUTION_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, USER_PROFILE_EXTRACTOR_SYSTEM_INSTRUCTION, TRIVIAL_MESSAGE_CLASSIFIER_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';
@@ -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() {
@@ -480,12 +544,6 @@ export function getPlanExecutionConfig() {
480
544
  tools: [{ functionDeclarations: getToolDeclarations({ isExecutionAgent: true }) }],
481
545
  };
482
546
  }
483
- export function getPlanModeConfig() {
484
- return {
485
- systemInstruction: PLAN_MODE_INSTRUCTION.replace('{{MULTI_WORKSPACE_BLOCK}}', getMultiWorkspaceBlock()),
486
- tools: [], // No tools allowed in plan mode
487
- };
488
- }
489
547
  /**
490
548
  * Compresses a large string of text using Gemini Flash.
491
549
  * Used for shrinking context payloads to prevent OOM/choking.
@@ -515,11 +573,11 @@ export async function compressTextUsingFlashLite(text, instruction = "<directive
515
573
  }
516
574
  const creds = await loadCredentials();
517
575
  result = await proxyClient.generateViaBYOK(creds.geminiApiKey, model, contents, [], // no tools
518
- undefined, instruction, { temperature: 0.2 }, undefined, abortSignal);
576
+ undefined, instruction, { temperature: 0.2, thinkingConfig: { thinkingLevel: 'MINIMAL' } }, undefined, abortSignal);
519
577
  }
520
578
  else {
521
579
  result = await proxyClient.generateFunctionCallViaProxy(idToken, model, contents, [], // no tools
522
- undefined, instruction, { temperature: 0.2 }, // low temp for factual summary
580
+ undefined, instruction, { temperature: 0.2, thinkingConfig: { thinkingLevel: 'MINIMAL' } }, // low temp for factual summary
523
581
  undefined, abortSignal);
524
582
  }
525
583
  let textPart = '';
@@ -704,6 +762,9 @@ export function createContextAgentSession() {
704
762
  temperature: contextTempOverride !== null ? contextTempOverride : 1,
705
763
  topP: 0.95,
706
764
  topK: 40,
765
+ thinkingConfig: {
766
+ thinkingLevel: 'MEDIUM',
767
+ },
707
768
  }, {
708
769
  functionCallingConfig: {
709
770
  mode: 'ANY',
@@ -718,6 +779,9 @@ export function createIntentRouterSession() {
718
779
  return new ProxyChatSession(model, INTENT_ROUTER_SYSTEM_INSTRUCTION, [], // no tools
719
780
  {
720
781
  temperature: 0,
782
+ thinkingConfig: {
783
+ thinkingLevel: 'MINIMAL',
784
+ },
721
785
  responseMimeType: 'application/json',
722
786
  responseSchema: {
723
787
  type: SchemaType.OBJECT,
@@ -745,6 +809,9 @@ export function createExecutionComplexitySession() {
745
809
  return new ProxyChatSession(model, EXECUTION_COMPLEXITY_SYSTEM_INSTRUCTION, [], // no tools
746
810
  {
747
811
  temperature: 0,
812
+ thinkingConfig: {
813
+ thinkingLevel: 'MINIMAL',
814
+ },
748
815
  responseMimeType: 'application/json',
749
816
  responseSchema: {
750
817
  type: SchemaType.OBJECT,
@@ -767,6 +834,9 @@ export function createInvestigationComplexitySession() {
767
834
  return new ProxyChatSession(model, INVESTIGATION_COMPLEXITY_SYSTEM_INSTRUCTION, [], // no tools
768
835
  {
769
836
  temperature: 0,
837
+ thinkingConfig: {
838
+ thinkingLevel: 'MEDIUM',
839
+ },
770
840
  responseMimeType: 'application/json',
771
841
  responseSchema: {
772
842
  type: SchemaType.OBJECT,
@@ -830,6 +900,9 @@ export function createInvestigationSemanticSession() {
830
900
  return new ProxyChatSession(model, INVESTIGATION_SEMANTIC_SYSTEM_INSTRUCTION, [], // no tools
831
901
  {
832
902
  temperature: 0,
903
+ thinkingConfig: {
904
+ thinkingLevel: 'MINIMAL',
905
+ },
833
906
  responseMimeType: 'application/json',
834
907
  responseSchema: {
835
908
  type: SchemaType.OBJECT,
@@ -871,6 +944,9 @@ export function createWebSearchAgentSession() {
871
944
  temperature: 1,
872
945
  topP: 0.95,
873
946
  topK: 40,
947
+ thinkingConfig: {
948
+ thinkingLevel: 'MEDIUM',
949
+ },
874
950
  });
875
951
  }
876
952
  // ─── History Summarizer Agent Service ─────────────────────────────────
@@ -881,6 +957,9 @@ export function createHistorySummarizerSession() {
881
957
  return new ProxyChatSession(model, HISTORY_SUMMARIZER_SYSTEM_INSTRUCTION, [], {
882
958
  temperature: 0.2,
883
959
  maxOutputTokens: MAX_OUTPUT_TOKENS,
960
+ thinkingConfig: {
961
+ thinkingLevel: 'MINIMAL',
962
+ },
884
963
  });
885
964
  }
886
965
  /**
@@ -980,6 +1059,9 @@ export function createUserProfileExtractorSession() {
980
1059
  return new ProxyChatSession(model, USER_PROFILE_EXTRACTOR_SYSTEM_INSTRUCTION, [], // no tools
981
1060
  {
982
1061
  temperature: 0,
1062
+ thinkingConfig: {
1063
+ thinkingLevel: 'MINIMAL',
1064
+ },
983
1065
  responseMimeType: 'application/json',
984
1066
  responseSchema: {
985
1067
  type: SchemaType.OBJECT,
@@ -1100,6 +1182,9 @@ export function createTrivialMessageClassifierSession() {
1100
1182
  return new ProxyChatSession(model, TRIVIAL_MESSAGE_CLASSIFIER_SYSTEM_INSTRUCTION, [], // no tools
1101
1183
  {
1102
1184
  temperature: 0,
1185
+ thinkingConfig: {
1186
+ thinkingLevel: 'MINIMAL',
1187
+ },
1103
1188
  responseMimeType: 'application/json',
1104
1189
  responseSchema: {
1105
1190
  type: SchemaType.OBJECT,
@@ -1144,11 +1229,11 @@ export async function generateChatTitle(firstMessage, abortSignal) {
1144
1229
  }
1145
1230
  const creds = await loadCredentials();
1146
1231
  result = await proxyClient.generateViaBYOK(creds.geminiApiKey, model, contents, [], // no tools
1147
- undefined, instruction, { temperature: 0.2 }, undefined, abortSignal);
1232
+ undefined, instruction, { temperature: 0.2, thinkingConfig: { thinkingLevel: 'MINIMAL' } }, undefined, abortSignal);
1148
1233
  }
1149
1234
  else {
1150
1235
  result = await proxyClient.generateFunctionCallViaProxy(idToken, model, contents, [], // no tools
1151
- undefined, instruction, { temperature: 0.2 }, undefined, abortSignal);
1236
+ undefined, instruction, { temperature: 0.2, thinkingConfig: { thinkingLevel: 'MINIMAL' } }, undefined, abortSignal);
1152
1237
  }
1153
1238
  let title = '';
1154
1239
  if (result.parts) {
@@ -10,13 +10,13 @@ import { getMetricCollector } from './metrics.js';
10
10
  import { estimateTokenCount, pruneTextToTokenBudget } from '../utils/historyPrompt.js';
11
11
  const metrics = getMetricCollector();
12
12
  /** Token budget constants for context optimization */
13
- const MAX_TREE_TOKENS = 12000;
14
- const MAX_CHAT_HISTORY_ROUTER_TOKENS = 3000;
15
- const MAX_CHAT_HISTORY_INVESTIGATION_TOKENS = 4500;
16
- const MAX_SINGLE_FILE_TOKENS = 25000;
17
- const MAX_TOTAL_FILE_TOKENS = 150000;
18
- const MAX_TOTAL_FILES = 30;
19
- const MAX_TOOL_OUTPUT_TOKENS = 10000;
13
+ const MAX_TREE_TOKENS = 100000;
14
+ const MAX_CHAT_HISTORY_ROUTER_TOKENS = 10000;
15
+ const MAX_CHAT_HISTORY_INVESTIGATION_TOKENS = 50000;
16
+ const MAX_SINGLE_FILE_TOKENS = 200000;
17
+ const MAX_TOTAL_FILE_TOKENS = 200000;
18
+ const MAX_TOTAL_FILES = 50;
19
+ const MAX_TOOL_OUTPUT_TOKENS = 200000;
20
20
  /**
21
21
  * Bounds individual file content to ensure it does not exceed the single-file token budget.
22
22
  *
@@ -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;
@@ -723,7 +746,9 @@ export async function gatherContext(workspaceRoot, userRequest, chatHistory = ''
723
746
  };
724
747
  }
725
748
  else if (call.name === 'run_analysis_script') {
726
- const analysisResult = await runEphemeralScript(workspaceRoot, args.language, args.code, { abortSignal });
749
+ const analysisResult = await runEphemeralScript(workspaceRoot, args.language, args.code, {
750
+ abortSignal,
751
+ });
727
752
  const rawOutput = analysisResult.exitCode === 0
728
753
  ? analysisResult.stdout || '(script produced no output)'
729
754
  : `Script failed (exit ${analysisResult.exitCode}):\n${analysisResult.stderr}`;
@@ -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()