minovative-mind-cli 1.5.0 → 2.0.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 (76) hide show
  1. package/README.md +51 -45
  2. package/dist/commands/chat.js +10 -5
  3. package/dist/services/agent/slashCommands.js +163 -37
  4. package/dist/services/agent/toolLoop.d.ts +1 -1
  5. package/dist/services/agent/toolLoop.js +7 -2
  6. package/dist/services/agent/types.d.ts +2 -0
  7. package/dist/services/agent-tools.d.ts +9 -4
  8. package/dist/services/agent-tools.js +145 -21
  9. package/dist/services/agent.d.ts +8 -0
  10. package/dist/services/agent.js +294 -38
  11. package/dist/services/ai.d.ts +19 -5
  12. package/dist/services/ai.js +167 -35
  13. package/dist/services/changeLogger.d.ts +142 -0
  14. package/dist/services/changeLogger.js +132 -3
  15. package/dist/services/contextAgent.d.ts +6 -1
  16. package/dist/services/contextAgent.js +95 -14
  17. package/dist/services/embeddingIndex.d.ts +82 -0
  18. package/dist/services/embeddingIndex.js +613 -0
  19. package/dist/services/investigationComplexity.d.ts +45 -0
  20. package/dist/services/investigationComplexity.js +91 -0
  21. package/dist/services/metrics.d.ts +18 -0
  22. package/dist/services/metrics.js +7 -0
  23. package/dist/services/orchestration/fileLockRegistry.d.ts +125 -0
  24. package/dist/services/orchestration/fileLockRegistry.js +276 -0
  25. package/dist/services/orchestration/investigationAgent.d.ts +85 -0
  26. package/dist/services/orchestration/investigationAgent.js +359 -0
  27. package/dist/services/orchestration/investigationOrchestrator.d.ts +53 -0
  28. package/dist/services/orchestration/investigationOrchestrator.js +180 -0
  29. package/dist/services/orchestration/messageBus.d.ts +162 -0
  30. package/dist/services/orchestration/messageBus.js +225 -0
  31. package/dist/services/orchestration/orchestrator.d.ts +45 -0
  32. package/dist/services/orchestration/orchestrator.js +214 -0
  33. package/dist/services/orchestration/readCache.d.ts +79 -0
  34. package/dist/services/orchestration/readCache.js +108 -0
  35. package/dist/services/orchestration/scopedTools.d.ts +57 -0
  36. package/dist/services/orchestration/scopedTools.js +172 -0
  37. package/dist/services/orchestration/subAgent.d.ts +58 -0
  38. package/dist/services/orchestration/subAgent.js +187 -0
  39. package/dist/services/orchestration/taskGraph.d.ts +129 -0
  40. package/dist/services/orchestration/taskGraph.js +254 -0
  41. package/dist/services/proxyClient.d.ts +25 -0
  42. package/dist/services/proxyClient.js +60 -0
  43. package/dist/utils/asyncContext.d.ts +16 -0
  44. package/dist/utils/asyncContext.js +25 -0
  45. package/dist/utils/config.d.ts +3 -1
  46. package/dist/utils/config.js +3 -1
  47. package/dist/utils/contextPrompts.js +3 -2
  48. package/dist/utils/dependencyTracer/modules/api.d.ts +9 -0
  49. package/dist/utils/dependencyTracer/modules/api.js +62 -0
  50. package/dist/utils/dependencyTracer/modules/graph.d.ts +9 -0
  51. package/dist/utils/dependencyTracer/modules/graph.js +23 -0
  52. package/dist/utils/dependencyTracer/modules/profiles.d.ts +7 -0
  53. package/dist/utils/dependencyTracer/modules/profiles.js +120 -0
  54. package/dist/utils/dependencyTracer/modules/resolver.d.ts +7 -0
  55. package/dist/utils/dependencyTracer/modules/resolver.js +51 -0
  56. package/dist/utils/dependencyTracer/modules/types.d.ts +4 -0
  57. package/dist/utils/dependencyTracer/modules/types.js +1 -0
  58. package/dist/utils/dependencyTracer/modules/walker.d.ts +1 -0
  59. package/dist/utils/dependencyTracer/modules/walker.js +48 -0
  60. package/dist/utils/dependencyTracer.js +31 -17
  61. package/dist/utils/excludedExtensions.js +0 -1
  62. package/dist/utils/historyPrompt.d.ts +9 -0
  63. package/dist/utils/historyPrompt.js +87 -0
  64. package/dist/utils/logo.d.ts +2 -0
  65. package/dist/utils/logo.js +31 -10
  66. package/dist/utils/paste.d.ts +21 -0
  67. package/dist/utils/paste.js +22 -1
  68. package/dist/utils/profiles.d.ts +2 -0
  69. package/dist/utils/profiles.js +44 -0
  70. package/dist/utils/projectStorage.js +10 -7
  71. package/dist/utils/systemPrompts.d.ts +6 -3
  72. package/dist/utils/systemPrompts.js +106 -5
  73. package/dist/utils/types.d.ts +33 -0
  74. package/dist/utils/types.js +1 -0
  75. package/oclif.manifest.json +2 -2
  76. package/package.json +5 -3
package/README.md CHANGED
@@ -16,39 +16,8 @@ the build/performance metrics are green.
16
16
  [![Version](https://img.shields.io/npm/v/minovative-mind-cli.svg)](https://npmjs.org/package/minovative-mind-cli)
17
17
  [![Downloads/week](https://img.shields.io/npm/dw/minovative-mind-cli.svg)](https://npmjs.org/package/minovative-mind-cli)
18
18
 
19
- - Official Website: [https://www.minovativemind.dev/](https://www.minovativemind.dev/)
20
- - Latest Updates: [https://www.minovativemind.dev/updates](https://www.minovativemind.dev/updates)
21
-
22
- ---
23
-
24
- ## How it works
25
-
26
- - Standard AI coding agents: big model + noisy context = expensive and redundant mistakes
27
- - Minovative Mind CLI: flash models + precise context + verified output = better and cheaper results.
28
-
29
- ### The PCV engine runs in three stages before returning a single line of code:
30
-
31
- **1. Investigate**
32
-
33
- - **Maps your project:** Traces import dependencies and identifies recently modified files to understand your focus.
34
- - **Researches context:** Gathers external web documentation and completes background research before touching any code.
35
-
36
- **2. Execute with precision**
37
-
38
- - **Surgical snapshots:** Feeds the agent a compressed, relevant slice of code instead of dumping the entire codebase.
39
- - **Higher success rates:** Delivers 40–50% fewer broken generations on large files compared to standard zero-shot prompts.
40
-
41
- **3. Verify and self-correct**
42
-
43
- - **Runs native builds & audits:** Automatically executes your actual build commands (`npm run build`, `cargo check`, etc.) and scans for performance flaws on modified files only.
44
- - **Autonomously debugs:** Reads the exact compiler output and fixes its own errors across up to 5 hands-free correction cycles.
45
-
46
- ---
47
-
48
- ## See it in action
49
-
50
- - [AI builds a Python Generative Art Engine in one prompt](https://www.youtube.com/watch?v=dy3qNbETqfs)
51
- - [AI builds a Quiz Game from scratch](https://www.youtube.com/watch?v=KjE5nbKEf3w)
19
+ - Official Website: [Main Website](https://www.minovativemind.dev/)
20
+ - Latest Updates: [Updates](https://www.minovativemind.dev/updates)
52
21
 
53
22
  ---
54
23
 
@@ -79,9 +48,40 @@ Works in any terminal — SSH, Docker, CI pipelines, Vim, Windows Command Prompt
79
48
 
80
49
  ---
81
50
 
51
+ ## See it in action
52
+
53
+ - [AI builds a Python Generative Art Engine in one prompt](https://www.youtube.com/watch?v=dy3qNbETqfs)
54
+ - [AI builds a Quiz Game from scratch](https://www.youtube.com/watch?v=KjE5nbKEf3w)
55
+
56
+ ### 🏆 Benchmark Tests
57
+
58
+ **All-Your-Base (C++ Track)**
59
+
60
+ - **Difficulty:** Hard | **Time:** 3.5 minutes
61
+ - **Result:** 🟢 PASSED (17/17 assertions)
62
+ - Successfully deduced the O(N+M) conversion algorithm.
63
+ - Properly handled complex edge cases for zero-equivalents (returning an empty vector).
64
+ - Encountered a compilation error due to missing C++ standard library paths on macOS.
65
+ - Autonomously self-corrected by querying the environment, locating the sysroot, and updating clang++ flags.
66
+ - Flawlessly passed the test suite, handling the problem and edge cases on the first try.
67
+ - [All-Your-Base Summary](https://github.com/Quarantiine/polyglot-benchmark-mmcli/blob/main/cpp/exercises/practice/all-your-base/minovative-tries/attempt_1.md)
68
+
69
+ **Alphametics (Go Track)**
70
+
71
+ - **Difficulty:** Extreme | **Time:** 5.2 minutes
72
+ - **Result:** 🟢 PASSED
73
+ - Solved one of the hardest logic puzzles on the platform by engineering a mathematically rigorous pruning algorithm based on the Rearrangement Inequality.
74
+ - Completely bypassed naive backtracking (10! permutations).
75
+ - Achieved sub-millisecond execution speeds (~140 microseconds) with zero heap allocations during recursion.
76
+ - Autonomously navigated the Go toolchain (\`go test -bench=.\`).
77
+ - Parsed its own architectural performance warnings to optimize the solution.
78
+ - [Alphametics Summary](https://github.com/Quarantiine/polyglot-benchmark-mmcli/blob/main/go/exercises/practice/alphametics/minovative-tries/attempt_1.md)
79
+
80
+ ---
81
+
82
82
  ## Models
83
83
 
84
- Hot-swap during a session with `/models`:
84
+ Hot-swap during a session using `/models`:
85
85
 
86
86
  | Model | Best for |
87
87
  | ------------------------------ | ----------------------------------- |
@@ -99,22 +99,28 @@ Hot-swap during a session with `/models`:
99
99
 
100
100
  ## Session Commands
101
101
 
102
- | Command | What it does |
103
- | --------------- | ----------------------------------------------------- |
104
- | `/models` | Hot-swap the active model |
105
- | `/chats` | View, resume, or delete previous chat sessions |
106
- | `/revert` | Instantly undo all changes from the last turn |
107
- | `/commit` | Generate a conventional commit message from your diff |
108
- | `/auto-approve` | Toggle skipping confirmation prompts for commands |
109
- | `/paste` | Multi-line input mode (cancel with Ctrl+C) |
110
- | `/debug` | Expose internal agent diagnostics |
111
- | `stop` | Abort generation immediately |
102
+ | Command | What it does |
103
+ | --------------- | ---------------------------------------------------------------- |
104
+ | `/models` | Hot-swap the active model |
105
+ | `/plan` | Toggle plan mode to review implementation strategies |
106
+ | `/paste` | Multi-line input mode (cancel with Ctrl+C) |
107
+ | `/clear` | Clear conversation history |
108
+ | `/debug` | Expose internal agent diagnostics |
109
+ | `/auto-approve` | Toggle skipping confirmation prompts for commands |
110
+ | `/sub-agents` | Toggle the MMAAK Engine for parallel investigation and execution |
111
+ | `/stats` | View current session statistics and configuration |
112
+ | `/commit` | Generate a conventional commit message from your diff |
113
+ | `/revert` | Undo changes from the last turn, or toggle the revert logger |
114
+ | `/chats` | View, resume, or delete previous chat sessions |
115
+ | `stop` | Abort generation immediately |
112
116
 
113
117
  ---
114
118
 
115
119
  ## 🌐 Supported Languages
116
120
 
117
- Minovative Mind CLI features deep, context-aware analysis across **11 major programming language families**. Our core engines—**Smart Dependency Tracing**, **Performance Auditing**, and **Ephemeral Analysis Scripts**—provide tailored support depending on the language's syntax and runtime model:
121
+ Minovative Mind CLI fundamentally supports **ALL programming languages** for chat, code generation, planning, and execution, as it relies on Gemini's vast training data.
122
+
123
+ However, the PCV engine features deep, context-aware analysis across **11 major programming language families**. Our core advanced engines—**Smart Dependency Tracing**, **Performance Auditing**, and **Ephemeral Analysis Scripts**—provide tailored support depending on the language's syntax and runtime model:
118
124
 
119
125
  | Language Family | Supported Extensions | Dependency Tracing | Performance Auditing | Ephemeral Analysis |
120
126
  | :--------------------------- | :------------------------------------------- | :----------------: | :------------------: | :----------------: |
@@ -6,7 +6,7 @@ import * as p from '@clack/prompts';
6
6
  import pc from 'picocolors';
7
7
  import { startAgentLoop } from '../services/agent.js';
8
8
  import { getAuthorizedIdToken, login } from '../services/auth.js';
9
- import { printLogo } from '../utils/logo.js';
9
+ import { printLogo, brandBg, brandFg } from '../utils/logo.js';
10
10
  import { updateWorkspaceStatus } from '../services/workspace.js';
11
11
  /**
12
12
  * @class DefaultCommand
@@ -23,13 +23,18 @@ export default class DefaultCommand extends Command {
23
23
 
24
24
  Inside the chat session, you can use the following commands in the slash menu:
25
25
  /models - Select the active model
26
+ /plan - Toggle plan mode to review implementation strategies
26
27
  /paste - Enter multi-line paste mode for long snippets
27
28
  /clear - Clear conversation history
28
29
  /debug - Debug tests or command execution in a sandbox loop
29
30
  /auto-approve - Toggle automatic approval of tool/command runs
30
- /revert - Revert the last file modification made by the agent
31
+ /sub-agents - Toggle the MMAAK Engine for parallel investigation and execution
32
+ /semantic-search - Toggle local vector index capabilities
33
+ /stats - View current session statistics and configuration
31
34
  /commit - Commit current workspace changes to Git
32
-
35
+ /revert - Revert the last file modification made by the agent
36
+ /chats - View, resume, or delete previous chat sessions
37
+
33
38
  Chat Controls:
34
39
  - Multi-line Input: End a line with \\ to continue on the next line
35
40
  - Stop/Abort: Type "stop" to immediately interrupt agent generation
@@ -52,7 +57,7 @@ Chat Controls:
52
57
  const pkg = JSON.parse(await fs.promises.readFile(new URL('../../package.json', import.meta.url), 'utf8'));
53
58
  updateNotifier({ pkg }).notify();
54
59
  printLogo();
55
- p.intro(`${pc.bgCyan(pc.black(' Minovative Mind CLI '))} ${pc.dim('v' + this.config.version)}`);
60
+ p.intro(`${brandBg(' Minovative Mind CLI ')} ${pc.dim('v' + this.config.version)}`);
56
61
  // Check authentication
57
62
  let idToken = await getAuthorizedIdToken();
58
63
  if (!idToken) {
@@ -65,7 +70,7 @@ Chat Controls:
65
70
  // Re-fetch token after successful login
66
71
  idToken = await getAuthorizedIdToken();
67
72
  }
68
- p.log.info(`${pc.dim('Workspace:')} ${pc.cyan(workspaceRoot)}`);
73
+ p.log.info(`${pc.dim('Workspace:')} ${brandFg(workspaceRoot)}`);
69
74
  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.`);
70
75
  // Update workspace status in the background
71
76
  if (idToken) {
@@ -4,13 +4,14 @@ import { promises as fs } from 'node:fs';
4
4
  import path from 'node:path';
5
5
  import { exec } from 'node:child_process';
6
6
  import { promisify } from 'node:util';
7
- import { toggleDebugMode } from '../../utils/logger.js';
7
+ import crypto from 'node:crypto';
8
+ import { toggleDebugMode, isDebugOn } from '../../utils/logger.js';
8
9
  import { changeLogger } from '../changeLogger.js';
9
10
  import { chatHistoryService } from '../chatHistoryService.js';
10
- import { printLogo } from '../../utils/logo.js';
11
+ import { printLogo, brandBg, brandFg } from '../../utils/logo.js';
11
12
  import { readPaste } from '../../utils/paste.js';
12
- import { setApprovalMode, getApprovalMode } from '../agent-tools.js';
13
- import { ProxyChatSession } from '../ai.js';
13
+ import { setApprovalMode, getApprovalMode, isSubAgentsEnabled, setSubAgentsEnabled, isSemanticSearchEnabled, setSemanticSearchEnabled, } from '../agent-tools.js';
14
+ import { ProxyChatSession, setGlobalActiveModel, getGlobalActiveModel, getGlobalLatestUsageMetadata } from '../ai.js';
14
15
  const execAsync = promisify(exec);
15
16
  /**
16
17
  * Handles all slash command operations (/paste, /clear, /models, /debug, /auto-approve, /revert, /commit).
@@ -39,12 +40,22 @@ export async function handleSlashCommand(command, context) {
39
40
  return { shouldContinue: true, isRawPasteMode: false };
40
41
  }
41
42
  }
43
+ if (lowerCommand === '/plan') {
44
+ const newPlanMode = !context.isPlanMode;
45
+ if (newPlanMode) {
46
+ p.log.info(pc.cyan('Plan mode enabled. The AI will formulate a step-by-step plan instead of executing code. Type /plan again to exit.'));
47
+ }
48
+ else {
49
+ p.log.info(pc.cyan('Plan mode disabled. Returning to normal execution.'));
50
+ }
51
+ return { shouldContinue: true, isPlanModeOverride: newPlanMode };
52
+ }
42
53
  if (lowerCommand === '/clear') {
43
54
  chat.clearHistory();
44
55
  process.stdout.write('\x1B[2J\x1B[3J\x1B[H'); // Hard clear screen and scrollback
45
56
  printLogo();
46
- p.intro(`${pc.bgCyan(pc.black(' Minovative Mind CLI '))} ${pc.dim('v' + version)}`);
47
- p.log.info(`${pc.dim('Workspace:')} ${pc.cyan(workspaceRoot)}`);
57
+ p.intro(`${brandBg(' Minovative Mind CLI ')} ${pc.dim('v' + version)}`);
58
+ p.log.info(`${pc.dim('Workspace:')} ${brandFg(workspaceRoot)}`);
48
59
  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.`);
49
60
  p.log.success('Chat history cleared.');
50
61
  console.log(pc.dim('\nType your coding request below. Type "exit" or "quit" to leave.\n'));
@@ -71,10 +82,16 @@ export async function handleSlashCommand(command, context) {
71
82
  label: 'Gemini 3.1 Flash-Lite',
72
83
  hint: 'Ultra-fast and cost-effective',
73
84
  },
85
+ {
86
+ value: 'auto',
87
+ label: 'Auto (Flash-Lite / Flash 3.5)',
88
+ hint: 'Dynamically routes between Flash-Lite and Flash 3.5 based on prompt complexity',
89
+ },
74
90
  ],
75
91
  });
76
92
  if (!p.isCancel(selectedModel)) {
77
93
  chat.setModel(selectedModel);
94
+ setGlobalActiveModel(selectedModel);
78
95
  p.log.success(`Model successfully switched to ${pc.cyan(selectedModel)}`);
79
96
  }
80
97
  return { shouldContinue: true };
@@ -100,32 +117,121 @@ export async function handleSlashCommand(command, context) {
100
117
  }
101
118
  return { shouldContinue: true };
102
119
  }
120
+ if (lowerCommand === '/sub-agents') {
121
+ if (isSubAgentsEnabled()) {
122
+ setSubAgentsEnabled(false);
123
+ p.log.success('MMAAK Engine disabled. Single-agent mode active.');
124
+ }
125
+ else {
126
+ setSubAgentsEnabled(true);
127
+ p.log.success('MMAAK Engine enabled. The system will now use parallel investigation and thread agents.');
128
+ }
129
+ return { shouldContinue: true };
130
+ }
131
+ if (lowerCommand === '/semantic-search') {
132
+ if (isSemanticSearchEnabled()) {
133
+ setSemanticSearchEnabled(false);
134
+ p.log.success('Semantic search disabled. The vector indexing layer is now turned off.');
135
+ }
136
+ else {
137
+ setSemanticSearchEnabled(true);
138
+ p.log.success('Semantic search enabled. The AST-aware vector index is active.');
139
+ }
140
+ return { shouldContinue: true };
141
+ }
142
+ if (lowerCommand === '/stats') {
143
+ const latestUsage = getGlobalLatestUsageMetadata();
144
+ const currentModel = chat.getModel();
145
+ const globalModel = getGlobalActiveModel();
146
+ const displayModel = globalModel === 'auto' ? `Auto (Last turn: ${currentModel})` : currentModel;
147
+ const autoApprove = getApprovalMode() === 'skip-all' ? 'Enabled' : 'Disabled';
148
+ const subAgents = isSubAgentsEnabled() ? 'Enabled' : 'Disabled';
149
+ const semanticSearch = isSemanticSearchEnabled() ? 'Enabled' : 'Disabled';
150
+ const planMode = context.isPlanMode ? 'Enabled' : 'Disabled';
151
+ p.log.step(pc.magenta('📊 Session Statistics & Status'));
152
+ console.log(pc.dim('----------------------------------------'));
153
+ console.log(`${pc.bold('AI Model:')} ${pc.cyan(displayModel)}`);
154
+ console.log(`${pc.bold('Auto-Approve:')} ${autoApprove === 'Enabled' ? pc.green(autoApprove) : pc.yellow(autoApprove)}`);
155
+ console.log(`${pc.bold('Sub-Agents:')} ${subAgents === 'Enabled' ? pc.green(subAgents) : pc.yellow(subAgents)}`);
156
+ console.log(`${pc.bold('Semantic Search:')} ${semanticSearch === 'Enabled' ? pc.green(semanticSearch) : pc.yellow(semanticSearch)}`);
157
+ console.log(`${pc.bold('Plan Mode:')} ${planMode === 'Enabled' ? pc.green(planMode) : pc.yellow(planMode)}`);
158
+ const debugMode = isDebugOn() ? 'Enabled' : 'Disabled';
159
+ console.log(`${pc.bold('Debug Log:')} ${debugMode === 'Enabled' ? pc.green(debugMode) : pc.yellow(debugMode)}`);
160
+ if (latestUsage) {
161
+ if (latestUsage.remainingBalance !== undefined) {
162
+ let diffStr = '';
163
+ if (latestUsage.creditsUsed !== undefined) {
164
+ const before = latestUsage.remainingBalance + latestUsage.creditsUsed;
165
+ console.log(`${pc.bold('Credits Before:')} ${pc.cyan(before.toLocaleString())}`);
166
+ const diff = -latestUsage.creditsUsed;
167
+ if (diff < 0) {
168
+ diffStr = ` ${pc.red(`(${diff})`)}`;
169
+ }
170
+ else if (diff > 0) {
171
+ diffStr = ` ${pc.green(`(+${diff})`)}`;
172
+ }
173
+ else {
174
+ diffStr = ` ${pc.dim(`(0)`)}`;
175
+ }
176
+ }
177
+ console.log(`${pc.bold('Credits Left:')} ${pc.cyan(latestUsage.remainingBalance.toLocaleString())}${diffStr}`);
178
+ }
179
+ const totalInputTokens = (latestUsage.promptTokens || 0) + (latestUsage.cachedTokens || 0);
180
+ if (totalInputTokens > 0) {
181
+ console.log(`${pc.bold('Last Turn Input:')} ${totalInputTokens.toLocaleString()} tokens`);
182
+ }
183
+ if (latestUsage.candidatesTokens) {
184
+ console.log(`${pc.bold('Last Turn Output:')} ${latestUsage.candidatesTokens.toLocaleString()} tokens`);
185
+ }
186
+ }
187
+ else {
188
+ console.log(`${pc.bold('Token Usage:')} No data available yet.`);
189
+ }
190
+ console.log(pc.dim('----------------------------------------\n'));
191
+ return { shouldContinue: true };
192
+ }
103
193
  if (lowerCommand === '/revert') {
194
+ const isEnabled = changeLogger.getIsEnabled();
104
195
  const history = changeLogger.getHistory();
105
- if (!history || history.length === 0) {
106
- p.log.warn('No changes to revert.');
107
- return { shouldContinue: true };
108
- }
109
- const lastChangeSet = history[history.length - 1];
110
196
  const truncate = (str, max) => {
111
197
  const singleLine = str.replace(/\s+/g, ' ').trim();
112
198
  return singleLine.length > max ? singleLine.substring(0, max - 3) + '...' : singleLine;
113
199
  };
200
+ let lastChangeSet = null;
201
+ const options = [];
202
+ if (isEnabled && history && history.length > 0) {
203
+ lastChangeSet = history[history.length - 1];
204
+ options.push({
205
+ value: 'revert_last',
206
+ label: `Revert last change (${truncate(lastChangeSet.description, 50)})${lastChangeSet.status === 'partial' ? ' [Partial]' : ''}`,
207
+ });
208
+ options.push({ value: 'view_history', label: 'View history' });
209
+ }
210
+ if (isEnabled) {
211
+ options.push({ value: 'disable_revert', label: 'Disable' });
212
+ }
213
+ else {
214
+ options.push({ value: 'enable_revert', label: 'Enable' });
215
+ }
216
+ options.push({ value: 'cancel', label: 'Cancel' });
114
217
  const revertMenu = await p['select']({
115
- message: 'Revert Menu',
116
- options: [
117
- {
118
- value: 'revert_last',
119
- label: `Revert last change (${truncate(lastChangeSet.description, 50)})${lastChangeSet.status === 'partial' ? ' [Partial]' : ''}`,
120
- },
121
- { value: 'view_history', label: 'View history' },
122
- { value: 'cancel', label: 'Cancel' },
123
- ],
218
+ message: isEnabled && history.length === 0 ? 'Revert Menu (No changes to revert)' : 'Revert Menu',
219
+ options,
124
220
  });
125
221
  if (p.isCancel(revertMenu) || revertMenu === 'cancel') {
126
222
  return { shouldContinue: true };
127
223
  }
128
- let targetTimestamp = lastChangeSet.timestamp;
224
+ if (revertMenu === 'disable_revert') {
225
+ changeLogger.setIsEnabled(false);
226
+ p.log.success('Revert command has been disabled. File modifications will no longer be tracked.');
227
+ return { shouldContinue: true };
228
+ }
229
+ if (revertMenu === 'enable_revert') {
230
+ changeLogger.setIsEnabled(true);
231
+ p.log.success('Revert command has been enabled. Future file modifications will be tracked.');
232
+ return { shouldContinue: true };
233
+ }
234
+ let targetTimestamp = lastChangeSet ? lastChangeSet.timestamp : null;
129
235
  if (revertMenu === 'view_history') {
130
236
  const historyOptions = history
131
237
  .slice()
@@ -168,26 +274,40 @@ export async function handleSlashCommand(command, context) {
168
274
  return { shouldContinue: true };
169
275
  }
170
276
  if (lowerCommand === '/chats') {
171
- const sessions = chatHistoryService.getSessions();
172
- if (!sessions || sessions.length === 0) {
173
- p.log.warn('No chat history found.');
174
- return { shouldContinue: true };
277
+ const sessions = chatHistoryService.getSessions() || [];
278
+ const hasSessions = sessions.length > 0;
279
+ const options = [{ value: 'new', label: 'New Chat' }];
280
+ if (hasSessions) {
281
+ options.push({ value: 'resume', label: 'View Chats' });
282
+ options.push({ value: 'delete', label: 'Delete Chat' });
175
283
  }
284
+ options.push({ value: 'cancel', label: 'Cancel' });
176
285
  const truncate = (str, max) => {
177
286
  const singleLine = str.replace(/\s+/g, ' ').trim();
178
287
  return singleLine.length > max ? singleLine.substring(0, max - 3) + '...' : singleLine;
179
288
  };
180
289
  const chatsMenu = await p['select']({
181
290
  message: 'Chat Sessions',
182
- options: [
183
- { value: 'resume', label: 'Resume another chat' },
184
- { value: 'delete', label: 'Delete a past chat' },
185
- { value: 'cancel', label: 'Cancel' },
186
- ],
291
+ options,
187
292
  });
188
293
  if (p.isCancel(chatsMenu) || chatsMenu === 'cancel') {
189
294
  return { shouldContinue: true };
190
295
  }
296
+ if (chatsMenu === 'new') {
297
+ chat.clearHistory();
298
+ if (chatSessionState) {
299
+ chatSessionState.id = crypto.randomUUID();
300
+ chatSessionState.title = '';
301
+ }
302
+ process.stdout.write('\x1B[2J\x1B[3J\x1B[H'); // Hard clear screen and scrollback
303
+ printLogo();
304
+ p.intro(`${brandBg(' Minovative Mind CLI ')} ${pc.dim('v' + version)}`);
305
+ p.log.info(`${pc.dim('Workspace:')} ${brandFg(workspaceRoot)}`);
306
+ 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.`);
307
+ p.log.success('Started a new chat session.');
308
+ console.log(pc.dim('\nType your coding request below. Type "exit" or "quit" to leave.\n'));
309
+ return { shouldContinue: true };
310
+ }
191
311
  const sessionOptions = sessions
192
312
  .slice()
193
313
  .reverse()
@@ -212,20 +332,26 @@ export async function handleSlashCommand(command, context) {
212
332
  }
213
333
  process.stdout.write('\x1B[2J\x1B[3J\x1B[H'); // Hard clear screen and scrollback
214
334
  printLogo();
215
- p.intro(`${pc.bgCyan(pc.black(' Minovative Mind CLI '))} ${pc.dim('v' + version)}`);
216
- p.log.info(`${pc.dim('Workspace:')} ${pc.cyan(workspaceRoot)}`);
335
+ p.intro(`${brandBg(' Minovative Mind CLI ')} ${pc.dim('v' + version)}`);
336
+ p.log.info(`${pc.dim('Workspace:')} ${brandFg(workspaceRoot)}`);
217
337
  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.`);
218
338
  p.log.success(`Resumed session: ${session.title}`);
219
339
  // Print the loaded history so the user can see past context
220
340
  for (const item of session.history) {
221
341
  if (item.role === 'user') {
222
- const text = item.parts.map((p) => p.text).filter(Boolean).join('\n');
342
+ const text = item.parts
343
+ .map((p) => p.text)
344
+ .filter(Boolean)
345
+ .join('');
223
346
  if (text) {
224
- p.log.step(pc.cyan(text));
347
+ p.log.step(pc.bgBlue(pc.white(` ${text} `)));
225
348
  }
226
349
  }
227
350
  else if (item.role === 'model') {
228
- const text = item.parts.map((p) => p.text).filter(Boolean).join('\n');
351
+ const text = item.parts
352
+ .map((p) => p.text)
353
+ .filter(Boolean)
354
+ .join('');
229
355
  if (text) {
230
356
  console.log(`\n${pc.blue('◆')} ${pc.bold('Minovative Mind')} ${pc.dim('(Resumed)')}\n`);
231
357
  const { marked } = await import('marked');
@@ -251,8 +377,8 @@ export async function handleSlashCommand(command, context) {
251
377
  chat.clearHistory();
252
378
  process.stdout.write('\x1B[2J\x1B[3J\x1B[H'); // Hard clear screen and scrollback
253
379
  printLogo();
254
- p.intro(`${pc.bgCyan(pc.black(' Minovative Mind CLI '))} ${pc.dim('v' + version)}`);
255
- p.log.info(`${pc.dim('Workspace:')} ${pc.cyan(workspaceRoot)}`);
380
+ p.intro(`${brandBg(' Minovative Mind CLI ')} ${pc.dim('v' + version)}`);
381
+ p.log.info(`${pc.dim('Workspace:')} ${brandFg(workspaceRoot)}`);
256
382
  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.`);
257
383
  p.log.warn('Active session was deleted. Chat history cleared.');
258
384
  console.log(pc.dim('\nType your coding request below. Type "exit" or "quit" to leave.\n'));
@@ -25,7 +25,7 @@ export declare function formatToolCall(name: string, args: Record<string, unknow
25
25
  * 6. **Submit Loop Frame**: Feeds execution outcomes back to the Gemini session and recursively repeats this sequence until the LLM produces a final text answer without further tool requests.
26
26
  *
27
27
  * ### Limits & Recovery Guardrails:
28
- * - **Turn-Limiting**: Capped at `MAX_TURNS` (100) to prevent infinite loops, API token drain, or excessive billing if the AI gets stuck in a repetitive loop.
28
+ * - **Turn-Limiting**: Capped at `MAX_TURNS` (Infinity) to prevent infinite loops, API token drain, or excessive billing if the AI gets stuck in a repetitive loop.
29
29
  * - **Empty-Response Healing**: If the API returns an empty text response with no tools, the system initiates up to `MAX_EMPTY_RETRIES` (3) system-driven wake-up prompts to re-engage the model.
30
30
  *
31
31
  * @param chat - The current active proxy chat session.
@@ -5,6 +5,7 @@ import { executeTool } from '../agent-tools.js';
5
5
  import { getPlanExecutionConfig } from '../ai.js';
6
6
  import { routeIntent } from '../contextAgent.js';
7
7
  import { requestCommandApproval } from './commandApproval.js';
8
+ import { getMetricCollector } from '../metrics.js';
8
9
  // ─── Constants ───────────────────────────────────────────────────────
9
10
  /**
10
11
  * Mapping of tool identifiers to user-friendly terminal emojis.
@@ -92,7 +93,7 @@ export function formatToolCall(name, args) {
92
93
  * 6. **Submit Loop Frame**: Feeds execution outcomes back to the Gemini session and recursively repeats this sequence until the LLM produces a final text answer without further tool requests.
93
94
  *
94
95
  * ### Limits & Recovery Guardrails:
95
- * - **Turn-Limiting**: Capped at `MAX_TURNS` (100) to prevent infinite loops, API token drain, or excessive billing if the AI gets stuck in a repetitive loop.
96
+ * - **Turn-Limiting**: Capped at `MAX_TURNS` (Infinity) to prevent infinite loops, API token drain, or excessive billing if the AI gets stuck in a repetitive loop.
96
97
  * - **Empty-Response Healing**: If the API returns an empty text response with no tools, the system initiates up to `MAX_EMPTY_RETRIES` (3) system-driven wake-up prompts to re-engage the model.
97
98
  *
98
99
  * @param chat - The current active proxy chat session.
@@ -107,7 +108,7 @@ export async function processResponse(chat, result, workspaceRoot, inputHandler,
107
108
  let response = result.response;
108
109
  // Upper limit on autonomous sequential tool executions to prevent out-of-control loops
109
110
  let turnCount = 0;
110
- const MAX_TURNS = 100;
111
+ const MAX_TURNS = Infinity;
111
112
  // Recovery thresholds for handling unexpected empty API payloads
112
113
  let emptyRetryCount = 0;
113
114
  const MAX_EMPTY_RETRIES = 3;
@@ -170,6 +171,9 @@ export async function processResponse(chat, result, workspaceRoot, inputHandler,
170
171
  return finalOutput;
171
172
  }
172
173
  // Process each tool call requested by the model (using helper to avoid nested loop warning)
174
+ const collector = getMetricCollector();
175
+ if (collector)
176
+ collector.recordToolTurn();
173
177
  const execRes = await executeToolCalls(functionCalls, workspaceRoot, inputHandler, abortSignal);
174
178
  if (execRes.aborted) {
175
179
  return '[Generation stopped by user]';
@@ -263,6 +267,7 @@ async function executeToolCalls(functionCalls, workspaceRoot, inputHandler, abor
263
267
  response: {
264
268
  output: toolResult.output,
265
269
  ...(toolResult.error ? { error: toolResult.error } : {}),
270
+ ...(toolResult.inlineData ? { inlineData: toolResult.inlineData } : {}),
266
271
  },
267
272
  },
268
273
  });
@@ -9,6 +9,7 @@ export interface SlashCommandContext {
9
9
  workspaceRoot: string;
10
10
  version: string;
11
11
  isRawPasteMode: boolean;
12
+ isPlanMode: boolean;
12
13
  chatSessionState: {
13
14
  id: string;
14
15
  title: string;
@@ -18,4 +19,5 @@ export interface SlashCommandResult {
18
19
  shouldContinue: boolean;
19
20
  userInputOverride?: string;
20
21
  isRawPasteMode?: boolean;
22
+ isPlanModeOverride?: boolean;
21
23
  }
@@ -2,7 +2,14 @@ import { type FunctionDeclaration } from '@google/generative-ai';
2
2
  export interface ToolResult {
3
3
  error?: string;
4
4
  output: string;
5
+ inlineData?: {
6
+ mimeType: string;
7
+ data: string;
8
+ };
5
9
  }
10
+ export declare function isSemanticSearchEnabled(): boolean;
11
+ export declare function setSemanticSearchEnabled(val: boolean): void;
12
+ export declare function getToolDeclarations(): FunctionDeclaration[];
6
13
  /**
7
14
  * FunctionDeclaration-compatible schema objects that describe
8
15
  * every tool the agent can invoke. Passed to the model at init.
@@ -11,6 +18,8 @@ export declare const toolDeclarations: FunctionDeclaration[];
11
18
  export type ApprovalMode = 'ask' | 'skip-once' | 'skip-all';
12
19
  export declare function getApprovalMode(): ApprovalMode;
13
20
  export declare function setApprovalMode(mode: ApprovalMode): void;
21
+ export declare function isSubAgentsEnabled(): boolean;
22
+ export declare function setSubAgentsEnabled(enabled: boolean): void;
14
23
  /**
15
24
  * If set to 'skip-once', reverts to 'ask' after a single command is run.
16
25
  */
@@ -29,8 +38,4 @@ export declare function grepSearch(workspaceRoot: string, pattern: string, fileG
29
38
  export declare function traceDependencies(workspaceRoot: string, filePath: string, direction?: string, maxDepth?: number): Promise<ToolResult>;
30
39
  export declare function findRecentChanges(workspaceRoot: string, dirPath?: string, minutes?: number, maxDepth?: number): Promise<ToolResult>;
31
40
  export declare function runDebugScript(workspaceRoot: string, language: string, code: string, abortSignal?: AbortSignal): Promise<ToolResult>;
32
- /**
33
- * Dispatches a function call from the model to the appropriate local tool.
34
- * Returns the tool result as a string to feed back to the model.
35
- */
36
41
  export declare function executeTool(workspaceRoot: string, toolName: string, args: Record<string, unknown>, abortSignal?: AbortSignal): Promise<ToolResult>;