minovative-mind-cli 2.2.4 → 2.2.5

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
@@ -86,13 +86,12 @@ Works in any terminal — SSH, Docker, CI pipelines, Vim, Windows Command Prompt
86
86
 
87
87
  Hot-swap during a session using `/models`:
88
88
 
89
- | Model | Best for |
90
- | ------------------------- | --------------------------------------------------- |
89
+ | Model | Best for |
90
+ | ------------------------- | ---------------------------------------------- |
91
91
  | **Auto** (default) | Automatically selects (3.5 Flash or 2.5 Flash) |
92
- | **Gemini 3.5 Flash** | Everyday coding — fast and accurate |
93
- | **Gemini 2.5 Flash** | Cost-efficient reasoning and multimodal tasks |
94
- | **Gemini 3.1 Pro** | Complex architectural changes |
95
- | **Gemini 3.1 Flash Lite** | Maximum speed and cost efficiency |
92
+ | **Gemini 3.5 Flash** | Everyday coding — fast and accurate |
93
+ | **Gemini 3.1 Pro** | Complex architectural changes |
94
+ | **Gemini 3.1 Flash Lite** | Maximum speed and cost efficiency |
96
95
 
97
96
  > Background tasks (routing, compression, commits) always use lightweight
98
97
  > models automatically. You pay for those lightweight model
@@ -104,21 +103,21 @@ Hot-swap during a session using `/models`:
104
103
 
105
104
  ## Session Commands
106
105
 
107
- | Command | What it does |
108
- | --------------- | ---------------------------------------------------------------- |
109
- | `/models` | Hot-swap the active model |
110
- | `/plan` | Toggle plan mode to review implementation strategies |
111
- | `/paste` | Multi-line input mode (cancel with Ctrl+C) |
112
- | `/clear` | Clear conversation history |
113
- | `/debug` | Expose internal agent diagnostics |
114
- | `/auto-approve` | Toggle skipping confirmation prompts for commands |
115
- | `/sub-agents` | Toggle the MMAAK Engine for parallel investigation and execution (concurrency limited to 2) |
116
- | `/stats` | View current session statistics and configuration |
117
- | `/commit` | Generate a conventional commit message from your diff |
118
- | `/revert` | Undo changes from the last turn, or toggle the revert logger |
106
+ | Command | What it does |
107
+ | --------------- | -------------------------------------------------------------------------------------------------------------------------- |
108
+ | `/models` | Hot-swap the active model |
109
+ | `/plan` | Toggle plan mode to review implementation strategies |
110
+ | `/paste` | Multi-line input mode (cancel with Ctrl+C) |
111
+ | `/clear` | Clear conversation history |
112
+ | `/debug` | Expose internal agent diagnostics |
113
+ | `/auto-approve` | Toggle skipping confirmation prompts for commands |
114
+ | `/sub-agents` | Toggle the MMAAK Engine for parallel investigation and execution (concurrency limited to 2) |
115
+ | `/stats` | View current session statistics and configuration |
116
+ | `/commit` | Generate a conventional commit message from your diff |
117
+ | `/revert` | Undo changes from the last turn, or toggle the revert logger |
119
118
  | `/chats` | View, resume, or delete previous chat sessions (with token tracking, Git branch, auto-approve status, and sub-agent state) |
120
- | `/workspaces` | Manage active workspaces and linked cross-repo aliases |
121
- | `stop` | Abort generation immediately |
119
+ | `/workspaces` | Manage active workspaces and linked cross-repo aliases |
120
+ | `stop` | Abort generation immediately |
122
121
 
123
122
  ---
124
123
 
@@ -78,14 +78,14 @@ export async function handleSlashCommand(command, context) {
78
78
  hint: 'Balanced performance',
79
79
  },
80
80
  {
81
- value: 'gemini-2.5-flash',
82
- label: 'Gemini 2.5 Flash',
83
- hint: 'Google Gemini 2.5 Flash model with built-in reasoning',
81
+ value: 'gemini-3.1-flash-lite',
82
+ label: 'Gemini 3.1 Flash-Lite',
83
+ hint: 'Ultra-fast and cost-effective',
84
84
  },
85
85
  {
86
86
  value: 'auto',
87
- label: 'Auto (Gemini 2.5 / Gemini 3.5)',
88
- hint: 'Dynamically routes between Gemini 2.5 and Gemini 3.5 based on prompt complexity',
87
+ label: 'Auto (Flash-Lite / Flash)',
88
+ hint: 'Dynamically routes between Gemini 3.1 Flash-Lite and Gemini 3.5 based on prompt complexity',
89
89
  },
90
90
  ],
91
91
  });
@@ -313,7 +313,7 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
313
313
  if (getGlobalActiveModel() === GEMINI_MODELS.AUTO) {
314
314
  let selectedModel = GEMINI_MODELS.FLASH_3_5;
315
315
  if (effectiveTargetAgent === 'CHAT') {
316
- selectedModel = GEMINI_MODELS.FLASH_2_5;
316
+ selectedModel = GEMINI_MODELS.FLASH_LITE_3_1;
317
317
  }
318
318
  else {
319
319
  spinner.stop(); // MUST clear the investigation spinner first to prevent leaking the setInterval
@@ -321,7 +321,7 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
321
321
  const complexity = await evaluateExecutionComplexity(finalInput, gatherRes.contextResult?.summary, gatherRes.contextResult?.relevantFiles?.size || 0);
322
322
  spinner.stop();
323
323
  process.stdout.write('\x1b[2K\r');
324
- selectedModel = complexity === 'EASY' ? GEMINI_MODELS.FLASH_2_5 : GEMINI_MODELS.FLASH_3_5;
324
+ selectedModel = complexity === 'EASY' ? GEMINI_MODELS.FLASH_LITE_3_1 : GEMINI_MODELS.FLASH_3_5;
325
325
  }
326
326
  chat.setModel(selectedModel);
327
327
  debugLog(`Auto-routing to model ${selectedModel} based on intent ${effectiveTargetAgent}`);
@@ -481,6 +481,10 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
481
481
  const percentSaved = totalInputTokens > 0 ? Math.round((latestUsage.cachedTokens / totalInputTokens) * 100) : 0;
482
482
  p.log.info(`${pc.green('⚡')} ${pc.green('Context Cache Hit:')} ${pc.bold(latestUsage.cachedTokens.toLocaleString())} tokens cached ${pc.dim(`(Saved ~${percentSaved}% of input cost)`)}`);
483
483
  }
484
+ const inputTokens = (latestUsage.promptTokens || 0) + (latestUsage.cachedTokens || 0);
485
+ const outputTokens = latestUsage.candidatesTokens || 0;
486
+ const totalTokens = latestUsage.totalTokenCount || inputTokens + outputTokens;
487
+ p.log.info(`${pc.dim('Tokens Used:')} ${pc.cyan(totalTokens.toLocaleString())} ${pc.dim(`(Input: ${inputTokens.toLocaleString()}, Output: ${outputTokens.toLocaleString()})`)}`);
484
488
  if (latestUsage.remainingBalance !== undefined) {
485
489
  p.log.info(`${pc.dim('Credits Remaining:')} ${pc.cyan(latestUsage.remainingBalance.toLocaleString())}`);
486
490
  }
@@ -494,7 +498,8 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
494
498
  }
495
499
  let turnTokens = 0;
496
500
  if (latestUsage) {
497
- turnTokens = (latestUsage.promptTokens || 0) + (latestUsage.cachedTokens || 0) + (latestUsage.candidatesTokens || 0);
501
+ turnTokens =
502
+ (latestUsage.promptTokens || 0) + (latestUsage.cachedTokens || 0) + (latestUsage.candidatesTokens || 0);
498
503
  }
499
504
  chatSessionState.totalTokens += turnTokens;
500
505
  let gitBranch = '';
@@ -583,11 +588,6 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
583
588
  label: 'Gemini 3.5 Flash',
584
589
  hint: 'Balanced performance',
585
590
  },
586
- {
587
- value: 'gemini-2.5-flash',
588
- label: 'Gemini 2.5 Flash',
589
- hint: 'Google Gemini 2.5 Flash model with built-in reasoning',
590
- },
591
591
  {
592
592
  value: 'gemini-3.1-flash-lite',
593
593
  label: 'Gemini 3.1 Flash-Lite',
@@ -595,8 +595,8 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
595
595
  },
596
596
  {
597
597
  value: 'auto',
598
- label: 'Auto (Gemini 2.5 / Gemini 3.5)',
599
- hint: 'Dynamically routes between Gemini 2.5 and Gemini 3.5 based on prompt complexity',
598
+ label: 'Auto (Flash-Lite / Flash)',
599
+ hint: 'Dynamically routes between Gemini 3.1 Flash-Lite and Gemini 3.5 based on prompt complexity',
600
600
  },
601
601
  ],
602
602
  });
@@ -322,7 +322,7 @@ export async function compressTextUsingFlashLite(text, instruction = 'Summarize
322
322
  return text;
323
323
  let model = getGlobalActiveModel();
324
324
  if (model === 'auto')
325
- model = GEMINI_MODELS.FLASH_2_5;
325
+ model = GEMINI_MODELS.FLASH_LITE_3_1;
326
326
  const parts = [{ text }];
327
327
  if (inlineData) {
328
328
  parts.push({ inlineData });
@@ -531,7 +531,7 @@ export function createContextAgentSession() {
531
531
  export function createIntentRouterSession() {
532
532
  let model = getGlobalActiveModel();
533
533
  if (model === 'auto')
534
- model = GEMINI_MODELS.FLASH_2_5;
534
+ model = GEMINI_MODELS.FLASH_LITE_3_1;
535
535
  return new ProxyChatSession(model, INTENT_ROUTER_SYSTEM_INSTRUCTION, [], // no tools
536
536
  { temperature: 0, responseMimeType: 'application/json' });
537
537
  }
@@ -539,7 +539,7 @@ export function createIntentRouterSession() {
539
539
  export function createExecutionComplexitySession() {
540
540
  let model = getGlobalActiveModel();
541
541
  if (model === 'auto')
542
- model = GEMINI_MODELS.FLASH_2_5;
542
+ model = GEMINI_MODELS.FLASH_LITE_3_1;
543
543
  return new ProxyChatSession(model, EXECUTION_COMPLEXITY_SYSTEM_INSTRUCTION, [], // no tools
544
544
  { temperature: 0, responseMimeType: 'application/json' });
545
545
  }
@@ -547,7 +547,7 @@ export function createExecutionComplexitySession() {
547
547
  export function createInvestigationComplexitySession() {
548
548
  let model = getGlobalActiveModel();
549
549
  if (model === 'auto')
550
- model = GEMINI_MODELS.FLASH_2_5;
550
+ model = GEMINI_MODELS.FLASH_LITE_3_1;
551
551
  return new ProxyChatSession(model, INVESTIGATION_COMPLEXITY_SYSTEM_INSTRUCTION, [], // no tools
552
552
  { temperature: 0, responseMimeType: 'application/json' });
553
553
  }
@@ -31,7 +31,7 @@ export interface InvestigationComplexityResult {
31
31
  /**
32
32
  * Evaluates whether the investigation phase should be parallelized.
33
33
  *
34
- * Uses `gemini-2.5-flash` (under auto mode) at temperature 0 to classify the prompt's
34
+ * Uses `gemini-3.1-flash-lite` (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-2.5-flash` (under auto mode) at temperature 0 to classify the prompt's
19
+ * Uses `gemini-3.1-flash-lite` (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.
@@ -32,6 +32,8 @@ export interface InvestigationResult {
32
32
  webSearchSummary: string;
33
33
  /** Total tokens consumed by this agent */
34
34
  creditsUsed: number;
35
+ inputTokens?: number;
36
+ outputTokens?: number;
35
37
  /** Whether the agent completed successfully */
36
38
  success: boolean;
37
39
  }
@@ -55,6 +57,8 @@ export declare class InvestigationAgentRunner {
55
57
  private chat;
56
58
  private lastHeartbeat;
57
59
  private creditsUsed;
60
+ private inputTokens;
61
+ private outputTokens;
58
62
  /** Shorter stall timeout for investigation agents (120s to allow for heavy vision/web tasks) */
59
63
  static readonly STALL_TIMEOUT_MS = 120000;
60
64
  constructor(agentLabel: string, domains: string[], workspaceRoot: string, readCache: ReadCache, projectTree: string, projectType: string);
@@ -38,6 +38,8 @@ export class InvestigationAgentRunner {
38
38
  chat;
39
39
  lastHeartbeat = Date.now();
40
40
  creditsUsed = 0;
41
+ inputTokens = 0;
42
+ outputTokens = 0;
41
43
  /** Shorter stall timeout for investigation agents (120s to allow for heavy vision/web tasks) */
42
44
  static STALL_TIMEOUT_MS = 120_000;
43
45
  constructor(agentLabel, domains, workspaceRoot, readCache, projectTree, projectType) {
@@ -322,7 +324,7 @@ export class InvestigationAgentRunner {
322
324
  crashed = true;
323
325
  summary = 'Investigation aborted by user.';
324
326
  }
325
- debugLog(`InvestigationAgent [${this.agentLabel}]: Finished. Success=${success && !crashed}, Files=${relevantFiles.size}, Tokens=${this.creditsUsed}`);
327
+ debugLog(`InvestigationAgent [${this.agentLabel}]: Finished. Success=${success && !crashed}, Files=${relevantFiles.size}, Tokens=${this.creditsUsed} (In: ${this.inputTokens}, Out: ${this.outputTokens})`);
326
328
  return {
327
329
  domains: this.domains,
328
330
  agentLabel: this.agentLabel,
@@ -330,6 +332,8 @@ export class InvestigationAgentRunner {
330
332
  summary,
331
333
  webSearchSummary,
332
334
  creditsUsed: this.creditsUsed,
335
+ inputTokens: this.inputTokens,
336
+ outputTokens: this.outputTokens,
333
337
  success: success && !crashed,
334
338
  };
335
339
  }
@@ -339,10 +343,12 @@ export class InvestigationAgentRunner {
339
343
  updateUsage(result) {
340
344
  const usage = result.response.usageMetadata?.();
341
345
  if (usage) {
342
- const tokens = usage.totalTokenCount || ((usage.promptTokens || 0) + (usage.candidatesTokens || 0) + (usage.cachedTokens || 0));
343
- if (tokens) {
344
- this.creditsUsed += tokens;
345
- }
346
+ const input = (usage.promptTokens || 0) + (usage.cachedTokens || 0);
347
+ const output = usage.candidatesTokens || 0;
348
+ const tokens = usage.totalTokenCount || (input + output);
349
+ this.inputTokens += input;
350
+ this.outputTokens += output;
351
+ this.creditsUsed += tokens;
346
352
  }
347
353
  }
348
354
  }
@@ -98,12 +98,14 @@ export class InvestigationOrchestrator {
98
98
  // 7. Log summary
99
99
  const cacheStats = readCache.getStats();
100
100
  const totalTokens = results.reduce((sum, r) => sum + r.creditsUsed, 0);
101
+ const totalInputTokens = results.reduce((sum, r) => sum + (r.inputTokens || 0), 0);
102
+ const totalOutputTokens = results.reduce((sum, r) => sum + (r.outputTokens || 0), 0);
101
103
  const totalFilesBeforeDedup = results.reduce((sum, r) => sum + r.relevantFiles.size, 0);
102
104
  p.log.info(`${pc.green('✓')} Parallel Investigation complete.\n` +
103
105
  ` Agents: ${agentCount} (${failedResults.length} failed) | ` +
104
106
  `Files: ${mergedResult.relevantFiles.size} (deduped from ${totalFilesBeforeDedup}) | ` +
105
107
  `Cache hits: ${cacheStats.hitCount}\n` +
106
- ` Duration: ${duration}s | Tokens: ${totalTokens.toLocaleString()}`);
108
+ ` Duration: ${duration}s | Tokens: ${totalTokens.toLocaleString()} ${pc.dim(`(Input: ${totalInputTokens.toLocaleString()}, Output: ${totalOutputTokens.toLocaleString()})`)}`);
107
109
  return mergedResult;
108
110
  }
109
111
  /**
@@ -226,10 +226,14 @@ export class Orchestrator {
226
226
  p.log.step(pc.cyan('Orchestrator: Reconciling results...'));
227
227
  const stats = this.bus.getStats();
228
228
  let totalTokens = 0;
229
+ let inputTokens = 0;
230
+ let outputTokens = 0;
229
231
  let failedTasks = 0;
230
232
  let rawSummaryData = '';
231
233
  for (const [taskId, res] of this.agentResults.entries()) {
232
234
  totalTokens += res.creditsUsed;
235
+ inputTokens += (res.inputTokens || 0);
236
+ outputTokens += (res.outputTokens || 0);
233
237
  if (!res.success)
234
238
  failedTasks++;
235
239
  debugLog(`Task ${taskId} summary: ${res.summary.substring(0, 100)}...`);
@@ -249,7 +253,7 @@ export class Orchestrator {
249
253
  p.log.info(`${pc.green('✓')} Sub-agent execution complete.\n` +
250
254
  ` Total tasks: ${graph.tasks.length} (${failedTasks} failed)\n` +
251
255
  ` Bus Activity: ${stats.activityCount} actions, ${stats.signalCount} signals\n` +
252
- ` Total Tokens: ${totalTokens.toLocaleString()}`);
256
+ ` Total Tokens: ${totalTokens.toLocaleString()} ${pc.dim(`(Input: ${inputTokens.toLocaleString()}, Output: ${outputTokens.toLocaleString()})`)}`);
253
257
  // Clear the bus persistence now that orchestration is done
254
258
  await this.bus.cleanup();
255
259
  this.locks.shutdown();
@@ -16,6 +16,8 @@ export interface SubAgentResult {
16
16
  summary: string;
17
17
  /** Total credits (tokens) consumed by this agent */
18
18
  creditsUsed: number;
19
+ inputTokens?: number;
20
+ outputTokens?: number;
19
21
  /** Did the agent hit a stall timeout or crash? */
20
22
  crashed: boolean;
21
23
  }
@@ -34,6 +36,8 @@ export declare class SubAgentRunner {
34
36
  private chat;
35
37
  private lastHeartbeat;
36
38
  private creditsUsed;
39
+ private inputTokens;
40
+ private outputTokens;
37
41
  /** Max time without a tool call or response before the agent is considered stalled */
38
42
  static readonly STALL_TIMEOUT_MS = 60000;
39
43
  constructor(taskId: string, intent: string, workspaceRoot: string, bus: MessageBus, locks: FileLockRegistry, globalContext: string, onProgress?: ((msg: string) => void) | undefined);
@@ -24,6 +24,8 @@ export class SubAgentRunner {
24
24
  chat;
25
25
  lastHeartbeat = Date.now();
26
26
  creditsUsed = 0;
27
+ inputTokens = 0;
28
+ outputTokens = 0;
27
29
  /** Max time without a tool call or response before the agent is considered stalled */
28
30
  static STALL_TIMEOUT_MS = 60_000;
29
31
  constructor(taskId, intent, workspaceRoot, bus, locks, globalContext, onProgress) {
@@ -180,11 +182,13 @@ export class SubAgentRunner {
180
182
  crashed = true;
181
183
  finalSummary = 'Aborted by orchestrator.';
182
184
  }
183
- debugLog(`SubAgent [${this.taskId}]: Finished. Success=${success}, Crashed=${crashed}, Tokens=${this.creditsUsed}`);
185
+ debugLog(`SubAgent [${this.taskId}]: Finished. Success=${success}, Crashed=${crashed}, Tokens=${this.creditsUsed} (In: ${this.inputTokens}, Out: ${this.outputTokens})`);
184
186
  return {
185
187
  success: success && !crashed,
186
188
  summary: finalSummary,
187
189
  creditsUsed: this.creditsUsed,
190
+ inputTokens: this.inputTokens,
191
+ outputTokens: this.outputTokens,
188
192
  crashed,
189
193
  };
190
194
  });
@@ -195,10 +199,12 @@ export class SubAgentRunner {
195
199
  updateUsage(result) {
196
200
  const usage = result.response.usageMetadata?.();
197
201
  if (usage) {
198
- const tokens = usage.totalTokenCount || ((usage.promptTokens || 0) + (usage.candidatesTokens || 0) + (usage.cachedTokens || 0));
199
- if (tokens) {
200
- this.creditsUsed += tokens;
201
- }
202
+ const input = (usage.promptTokens || 0) + (usage.cachedTokens || 0);
203
+ const output = usage.candidatesTokens || 0;
204
+ const tokens = usage.totalTokenCount || (input + output);
205
+ this.inputTokens += input;
206
+ this.outputTokens += output;
207
+ this.creditsUsed += tokens;
202
208
  }
203
209
  }
204
210
  }
@@ -16,7 +16,6 @@ export declare const GITHUB_CLIENT_ID = "Ov23linFYFfjO3JILG7r";
16
16
  export declare const GEMINI_MODELS: {
17
17
  readonly PRO_3_1: "gemini-3.1-pro-preview";
18
18
  readonly FLASH_3_5: "gemini-3.5-flash";
19
- readonly FLASH_2_5: "gemini-2.5-flash";
20
19
  readonly FLASH_LITE_3_1: "gemini-3.1-flash-lite";
21
20
  readonly AUTO: "auto";
22
21
  };
@@ -16,7 +16,6 @@ export const GITHUB_CLIENT_ID = 'Ov23linFYFfjO3JILG7r';
16
16
  export const GEMINI_MODELS = {
17
17
  PRO_3_1: 'gemini-3.1-pro-preview',
18
18
  FLASH_3_5: 'gemini-3.5-flash',
19
- FLASH_2_5: 'gemini-2.5-flash',
20
19
  FLASH_LITE_3_1: 'gemini-3.1-flash-lite',
21
20
  AUTO: 'auto',
22
21
  };
@@ -65,5 +65,5 @@
65
65
  ]
66
66
  }
67
67
  },
68
- "version": "2.2.4"
68
+ "version": "2.2.5"
69
69
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "minovative-mind-cli",
3
3
  "description": "An automated AI agent powered by Vertex AI that helps you write software",
4
- "version": "2.2.4",
4
+ "version": "2.2.5",
5
5
  "author": "Daniel Ward",
6
6
  "bin": {
7
7
  "minovative-mind-cli": "bin/run.js"