minovative-mind-cli 2.13.3 β†’ 2.13.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
@@ -137,7 +137,6 @@ Background tasks automatically route to dedicated auxiliary models with native `
137
137
  | `/config-key` | Configure custom Google AI Studio API key (BYOK mode) |
138
138
  | `/profile` | View, inspect, delete, or reset global adaptive persona memory and AI side-notes |
139
139
  | `/models` | Hot-swap the active model |
140
- | `/plan` | Toggle plan mode to review implementation strategies |
141
140
  | `/paste` | Multi-line input mode (cancel with Ctrl+C) |
142
141
  | `/clear` | Clear conversation history |
143
142
  | `/debug` | Expose internal agent diagnostics |
@@ -165,7 +164,7 @@ Minovative Mind CLI doesn't restrict you to a single repository. You can logical
165
164
 
166
165
  ## 🌐 Supported Languages
167
166
 
168
- Minovative Mind CLI fundamentally supports **ALL programming languages** for chat, code generation, planning, and execution, as it relies on Gemini's vast training data.
167
+ Minovative Mind CLI fundamentally supports **ALL programming languages** for chat, code generation, and execution, as it relies on Gemini's vast training data.
169
168
 
170
169
  However, the PCV engine features deep, context-aware analysis across **12 major programming language families**. Our core advanced enginesβ€”**Smart Dependency Tracing**, **Property-Based & Mutation Verification**, **Performance Auditing** (across 9 language families), and **Ephemeral Analysis Scripts**β€”provide tailored support depending on the language's syntax and runtime model:
171
170
 
@@ -9,7 +9,7 @@ import { Command } from '@oclif/core';
9
9
  export default class DefaultCommand extends Command {
10
10
  /**
11
11
  * The description displayed in the CLI help output.
12
- * Details all supported slash commands (/config-key, /profile, /paste, /plan, /clear, /models,
12
+ * Details all supported slash commands (/config-key, /profile, /paste, /clear, /models,
13
13
  * /debug, /auto-approve, /sub-agents, /stats, /revert, /chats, /workspaces, /commit)
14
14
  * along with interactive chat controls.
15
15
  */
@@ -18,7 +18,7 @@ import { optimizeWorkspaceIDESettings } from '../services/ideOptimization.js';
18
18
  export default class DefaultCommand extends Command {
19
19
  /**
20
20
  * The description displayed in the CLI help output.
21
- * Details all supported slash commands (/config-key, /profile, /paste, /plan, /clear, /models,
21
+ * Details all supported slash commands (/config-key, /profile, /paste, /clear, /models,
22
22
  * /debug, /auto-approve, /sub-agents, /stats, /revert, /chats, /workspaces, /commit)
23
23
  * along with interactive chat controls.
24
24
  */
@@ -28,7 +28,6 @@ Inside the chat session, you can use the following commands in the slash menu:
28
28
  /config-key - BYOK β€” Configure, clear, or view status of custom Google AI Studio API key
29
29
  /profile - View, inspect, delete, or reset global adaptive persona memory and AI side-notes
30
30
  /paste - Enter multi-line paste mode for long code snippets and prompts
31
- /plan - Toggle plan mode to review step-by-step implementation strategies
32
31
  /clear - Clear conversation history, reset terminal screen, and display logo
33
32
  /models - Select or hot-swap the active Gemini model for the session
34
33
  /debug - Toggle internal agent telemetry, diagnostic logging, and execution state
@@ -27,7 +27,6 @@ import { loadUserProfile, deleteSideNote, clearUserProfile, getUserProfilePath,
27
27
  * - `/config-key` : Configure, validate, toggle, or clear Bring Your Own Key (BYOK) Google AI Studio API credentials.
28
28
  * - `/profile` : View, inspect, delete, or reset global adaptive persona memory and AI side-notes.
29
29
  * - `/paste` : Enter multi-line paste mode using EOF tracking (`Ctrl+D` submission).
30
- * - `/plan` : Toggle AI step-by-step implementation planning mode.
31
30
  * - `/clear` : Clear conversation history, wipe terminal screen, and reset CLI header.
32
31
  * - `/models` : Hot-swap the active generative AI model (Gemini 3.1 Pro, Gemini 3.7 Flash, Gemini 3.6 Flash, Gemini 3.5 Flash-Lite, Auto routing).
33
32
  * - `/debug` : Toggle internal agent telemetry and diagnostic logging.
@@ -75,19 +74,6 @@ export async function handleSlashCommand(command, context) {
75
74
  return { shouldContinue: true, isRawPasteMode: false };
76
75
  }
77
76
  }
78
- /**
79
- * `/plan` - Toggles step-by-step AI implementation planning mode.
80
- */
81
- if (lowerCommand === '/plan') {
82
- const newPlanMode = !context.isPlanMode;
83
- if (newPlanMode) {
84
- 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.'));
85
- }
86
- else {
87
- p.log.info(pc.cyan('Plan mode disabled. Returning to normal execution.'));
88
- }
89
- return { shouldContinue: true, isPlanModeOverride: newPlanMode };
90
- }
91
77
  /**
92
78
  * `/clear` - Resets chat conversation history, clears the terminal screen, and reprints CLI header.
93
79
  */
@@ -226,14 +212,12 @@ export async function handleSlashCommand(command, context) {
226
212
  }
227
213
  const autoApprove = getApprovalMode() === 'skip-all' ? 'Enabled' : 'Disabled';
228
214
  const subAgents = isSubAgentsEnabled() ? 'Enabled' : 'Disabled';
229
- const planMode = context.isPlanMode ? 'Enabled' : 'Disabled';
230
215
  const byokEnabled = (await isByokEnabled()) ? 'Enabled' : 'Disabled';
231
216
  p.log.step(pc.magenta('πŸ“Š Session Statistics & Status'));
232
217
  console.log(pc.dim('----------------------------------------'));
233
218
  console.log(`${pc.bold('AI Model:')} ${pc.cyan(displayModel)}`);
234
219
  console.log(`${pc.bold('Auto-Approve:')} ${autoApprove === 'Enabled' ? pc.green(autoApprove) : pc.yellow(autoApprove)}`);
235
220
  console.log(`${pc.bold('Sub-Agents:')} ${subAgents === 'Enabled' ? pc.green(subAgents) : pc.yellow(subAgents)}`);
236
- console.log(`${pc.bold('Plan Mode:')} ${planMode === 'Enabled' ? pc.green(planMode) : pc.yellow(planMode)}`);
237
221
  console.log(`${pc.bold('BYOK:')} ${byokEnabled === 'Enabled' ? pc.green(byokEnabled) : pc.yellow(byokEnabled)}`);
238
222
  const debugMode = isDebugOn() ? 'Enabled' : 'Disabled';
239
223
  console.log(`${pc.bold('Debug Log:')} ${debugMode === 'Enabled' ? pc.green(debugMode) : pc.yellow(debugMode)}`);
@@ -21,8 +21,6 @@ export interface SlashCommandContext {
21
21
  version: string;
22
22
  /** Flag indicating whether raw paste mode is currently enabled. */
23
23
  isRawPasteMode: boolean;
24
- /** Flag indicating whether step-by-step implementation planning mode is currently active. */
25
- isPlanMode: boolean;
26
24
  /** Session state tracking tokens, credits, usage metadata, and model turn counts. */
27
25
  chatSessionState: {
28
26
  id: string;
@@ -46,6 +44,4 @@ export interface SlashCommandResult {
46
44
  userInputOverride?: string;
47
45
  /** Optional override flag to enable or disable raw paste mode. */
48
46
  isRawPasteMode?: boolean;
49
- /** Optional override flag to enable or disable implementation planning mode. */
50
- isPlanModeOverride?: boolean;
51
47
  }
@@ -92,9 +92,6 @@ export declare function startAgentLoop(workspaceRoot: string, version: string):
92
92
  * @param chat - The active ProxyChatSession instance maintaining message history.
93
93
  * @param inputHandler - The AsyncInputHandler instance for managing keyboard interrupts and queueing.
94
94
  * @param chatSessionState - Object tracking session statistics, token counts, credit usage, and model metrics.
95
- * @param isPlanMode - Flag indicating whether plan mode (read-only architecture planning) is active.
96
- * @param cachedContextResult - Optional pre-gathered context result to bypass duplicate investigation turns.
97
- * @returns An object containing optional plan mode actions or context results, or void.
98
95
  */
99
96
  export declare function executeSingleTurn(workspaceRoot: string, userInput: string, chat: any, inputHandler: AsyncInputHandler, chatSessionState: {
100
97
  id: string;
@@ -106,10 +103,7 @@ export declare function executeSingleTurn(workspaceRoot: string, userInput: stri
106
103
  latestUsageMetadata?: any;
107
104
  previousUsageMetadata?: any;
108
105
  modelUsageCounts?: Record<string, number>;
109
- }, isPlanMode: boolean, cachedContextResult?: any): Promise<{
110
- planModeReturn?: string;
111
- contextResult?: any;
112
- } | void>;
106
+ }): Promise<void>;
113
107
  /**
114
108
  * Raw chat history entry count threshold to trigger chat history summarization.
115
109
  * 2 entries = 1 complete conversational user/model turn.
@@ -25,8 +25,8 @@ import { renderTerminalMarkdown } from '../utils/terminal.js';
25
25
  const execAsync = promisify(exec);
26
26
  import { debugLog, isDebugOn } from '../utils/logger.js';
27
27
  import { ensureProjectStorage, ensureIgnored, readCache, writeCache, invalidateCacheForDependents, } from '../utils/projectStorage.js';
28
- import { GEMINI_MODELS, isByokEnabled, TPM_COOLING_DELAYS } from '../utils/config.js';
29
- import { createSharedChatSession, getGeneralChatConfig, getPlanExecutionConfig, compressTextUsingFlashLite, generateChatTitle, getGlobalActiveModel, setGlobalActiveModel, summarizeChatHistory, } from './ai.js';
28
+ import { GEMINI_MODELS, TPM_COOLING_DELAYS } from '../utils/config.js';
29
+ import { createSharedChatSession, getGeneralChatConfig, getPlanExecutionConfig, compressTextUsingFlashLite, generateChatTitle, getGlobalActiveModel, summarizeChatHistory, } from './ai.js';
30
30
  import { getAndResetTurnUsage } from './proxyClient.js';
31
31
  import { changeLogger } from './changeLogger.js';
32
32
  import { chatHistoryService } from './chatHistoryService.js';
@@ -130,7 +130,6 @@ export async function startAgentLoop(workspaceRoot, version) {
130
130
  chat.setSessionInfo(chatSessionState.id, workspaceRoot);
131
131
  const sessionInputHistory = [];
132
132
  let isRawPasteMode = false;
133
- let isPlanMode = false;
134
133
  // Hook process.stdin.emit to intercept fast stream inputs.
135
134
  // When large buffers containing newlines arrive rapidly, we interpret them as a clipboard paste,
136
135
  // sanitizing and collapsing them to prevent premature command line submission.
@@ -165,7 +164,7 @@ export async function startAgentLoop(workspaceRoot, version) {
165
164
  }
166
165
  inputHandler.stop();
167
166
  // Input collection (delegated to a helper function to avoid nested loop warning)
168
- const { userInput: rawInput, canceled } = await collectUserInput(sessionInputHistory, isPlanMode);
167
+ const { userInput: rawInput, canceled } = await collectUserInput(sessionInputHistory);
169
168
  if (canceled) {
170
169
  p.outro(pc.green('Goodbye! Happy coding. πŸš€'));
171
170
  return;
@@ -180,11 +179,6 @@ export async function startAgentLoop(workspaceRoot, version) {
180
179
  message: 'Command Menu',
181
180
  options: [
182
181
  { value: '/models', label: '/models', hint: 'Change the active AI model' },
183
- {
184
- value: '/plan',
185
- label: '/plan',
186
- hint: `Toggle plan mode (build a plan without executing) ${isPlanMode ? pc.green('(ON)') : pc.red('(OFF)')}`,
187
- },
188
182
  { value: '/paste', label: '/paste', hint: 'Paste large text directly into the CLI (Press Ctrl+D to submit)' },
189
183
  { value: '/clear', label: '/clear', hint: 'Clear chat session history' },
190
184
  {
@@ -244,16 +238,12 @@ export async function startAgentLoop(workspaceRoot, version) {
244
238
  workspaceRoot,
245
239
  version,
246
240
  isRawPasteMode,
247
- isPlanMode,
248
241
  chatSessionState,
249
242
  };
250
243
  const slashResult = await handleSlashCommand(userInput, slashCtx);
251
244
  if (slashResult.isRawPasteMode !== undefined) {
252
245
  isRawPasteMode = slashResult.isRawPasteMode;
253
246
  }
254
- if (slashResult.isPlanModeOverride !== undefined) {
255
- isPlanMode = slashResult.isPlanModeOverride;
256
- }
257
247
  if (slashResult.userInputOverride !== undefined) {
258
248
  userInput = slashResult.userInputOverride;
259
249
  }
@@ -262,32 +252,7 @@ export async function startAgentLoop(workspaceRoot, version) {
262
252
  }
263
253
  }
264
254
  // ─── Main Execution Cycle ────────────────────────────────────────
265
- let currentInput = userInput;
266
- let cachedContextResult = null;
267
- while (true) {
268
- const execResult = await executeSingleTurn(workspaceRoot, currentInput, chat, inputHandler, chatSessionState, isPlanMode, cachedContextResult);
269
- const planModeReturn = execResult?.planModeReturn;
270
- const contextResult = execResult?.contextResult;
271
- if (isPlanMode && planModeReturn) {
272
- if (planModeReturn === 'proceed') {
273
- isPlanMode = false;
274
- currentInput = 'Please execute the plan we just finalized.';
275
- cachedContextResult = contextResult;
276
- p.log.info(pc.cyan('Proceeding with execution...'));
277
- continue;
278
- }
279
- else if (planModeReturn === 'edit') {
280
- p.log.info(pc.cyan('Please provide additional instructions to revise the plan.'));
281
- break;
282
- }
283
- else if (planModeReturn === 'exit') {
284
- isPlanMode = false;
285
- p.log.info(pc.cyan('Exited plan mode. Returning to normal chat.'));
286
- break;
287
- }
288
- }
289
- break;
290
- }
255
+ await executeSingleTurn(workspaceRoot, userInput, chat, inputHandler, chatSessionState);
291
256
  }
292
257
  }
293
258
  /**
@@ -301,11 +266,8 @@ export async function startAgentLoop(workspaceRoot, version) {
301
266
  * @param chat - The active ProxyChatSession instance maintaining message history.
302
267
  * @param inputHandler - The AsyncInputHandler instance for managing keyboard interrupts and queueing.
303
268
  * @param chatSessionState - Object tracking session statistics, token counts, credit usage, and model metrics.
304
- * @param isPlanMode - Flag indicating whether plan mode (read-only architecture planning) is active.
305
- * @param cachedContextResult - Optional pre-gathered context result to bypass duplicate investigation turns.
306
- * @returns An object containing optional plan mode actions or context results, or void.
307
269
  */
308
- export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHandler, chatSessionState, isPlanMode, cachedContextResult) {
270
+ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHandler, chatSessionState) {
309
271
  return runWithAgentId('main', async () => {
310
272
  const { resetTurnAccumulator } = await import('./metrics.js');
311
273
  resetTurnAccumulator();
@@ -324,71 +286,67 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
324
286
  if (ac.signal.aborted)
325
287
  return;
326
288
  // Stage 0: Summarize chat history if length threshold is met
327
- if (!cachedContextResult) {
328
- const isDebug = isDebugOn();
329
- if (!inputHandler.isCurrentlyPrompting() && !isDebug) {
330
- spinner.start('Checking conversation history...');
331
- }
332
- const historySummarized = await summarizeHistoryIfNeeded(chat, ac.signal);
333
- if (historySummarized) {
334
- debugLog('Chat history was summarized and compressed prior to context investigation.');
335
- }
336
- if (!inputHandler.isCurrentlyPrompting() && !isDebug) {
337
- spinner.stop();
338
- }
289
+ const isDebug = isDebugOn();
290
+ if (!inputHandler.isCurrentlyPrompting() && !isDebug) {
291
+ spinner.start('Checking conversation history...');
292
+ }
293
+ const historySummarized = await summarizeHistoryIfNeeded(chat, ac.signal);
294
+ if (historySummarized) {
295
+ debugLog('Chat history was summarized and compressed prior to context investigation.');
296
+ }
297
+ if (!inputHandler.isCurrentlyPrompting() && !isDebug) {
298
+ spinner.stop();
339
299
  }
340
300
  if (ac.signal.aborted)
341
301
  return;
342
302
  // Stage 1: Gather Workspace Context and route intentions
343
303
  spinner.start('πŸ” Investigating workspace...');
344
- let gatherRes = { targetAgent: 'EXECUTE', chainedMessages: [], contextResult: cachedContextResult || null };
345
- if (!cachedContextResult) {
346
- const collector = getMetricCollector();
347
- if (collector)
348
- collector.startTimer('contextGather');
349
- const chatHistory = chat.getRecentHistory(3);
350
- const toolLogs = [];
351
- try {
352
- gatherRes = await gatherContext(workspaceRoot, userInput, chatHistory, inputHandler, ac.signal, (msg) => {
353
- if (!inputHandler.isCurrentlyPrompting()) {
354
- spinner.message(`πŸ” Investigating workspace... ${pc.dim(msg)}`);
355
- }
356
- }, (toolMsg, label) => {
357
- const formattedLog = `${pc.dim(`[${label}]`)} ${toolMsg}`;
358
- toolLogs.push(formattedLog);
359
- if (!inputHandler.isCurrentlyPrompting()) {
360
- spinner.message(`πŸ” Investigating workspace... ${formattedLog}`);
361
- }
362
- });
363
- }
364
- catch (gatherErr) {
365
- spinner.stop();
366
- process.stdout.write('\x1b[2K\r');
367
- if (ac.signal.aborted || gatherErr?.name === 'AbortError' || gatherErr?.message?.includes('abort')) {
368
- return;
304
+ let gatherRes = { targetAgent: 'EXECUTE', chainedMessages: [] };
305
+ const collector = getMetricCollector();
306
+ if (collector)
307
+ collector.startTimer('contextGather');
308
+ const chatHistory = chat.getRecentHistory(3);
309
+ const toolLogs = [];
310
+ try {
311
+ gatherRes = await gatherContext(workspaceRoot, userInput, chatHistory, inputHandler, ac.signal, (msg) => {
312
+ if (!inputHandler.isCurrentlyPrompting()) {
313
+ spinner.message(`πŸ” Investigating workspace... ${pc.dim(msg)}`);
369
314
  }
370
- throw gatherErr;
371
- }
372
- if (collector)
373
- collector.stopTimer('contextGather');
374
- if (ac.signal.aborted) {
375
- spinner.stop();
376
- process.stdout.write('\x1b[2K\r');
377
- return;
378
- }
379
- // Print all collected logs at once to prevent flickering, while spinner is stopped
380
- if (toolLogs.length > 0) {
381
- spinner.stop();
382
- toolLogs.forEach((log) => p.log.step(log));
383
- spinner.start(`πŸ” Context gathered successfully.`);
384
- }
385
- // Post-investigation cooling-off delay to allow API Tokens-Per-Minute (TPM) sliding window to settle
386
- await new Promise((resolve) => setTimeout(resolve, TPM_COOLING_DELAYS.POST_INVESTIGATION_MS));
387
- if (ac.signal.aborted) {
388
- spinner.stop();
389
- process.stdout.write('\x1b[2K\r');
315
+ }, (toolMsg, label) => {
316
+ const formattedLog = `${pc.dim(`[${label}]`)} ${toolMsg}`;
317
+ toolLogs.push(formattedLog);
318
+ if (!inputHandler.isCurrentlyPrompting()) {
319
+ spinner.message(`πŸ” Investigating workspace... ${formattedLog}`);
320
+ }
321
+ });
322
+ }
323
+ catch (gatherErr) {
324
+ spinner.stop();
325
+ process.stdout.write('\x1b[2K\r');
326
+ if (ac.signal.aborted || gatherErr?.name === 'AbortError' || gatherErr?.message?.includes('abort')) {
390
327
  return;
391
328
  }
329
+ throw gatherErr;
330
+ }
331
+ if (collector)
332
+ collector.stopTimer('contextGather');
333
+ if (ac.signal.aborted) {
334
+ spinner.stop();
335
+ process.stdout.write('\x1b[2K\r');
336
+ return;
337
+ }
338
+ // Print all collected logs at once to prevent flickering, while spinner is stopped
339
+ if (toolLogs.length > 0) {
340
+ spinner.stop();
341
+ toolLogs.forEach((log) => p.log.step(log));
342
+ spinner.start(`πŸ” Context gathered successfully.`);
343
+ }
344
+ // Post-investigation cooling-off delay to allow API Tokens-Per-Minute (TPM) sliding window to settle
345
+ await new Promise((resolve) => setTimeout(resolve, TPM_COOLING_DELAYS.POST_INVESTIGATION_MS));
346
+ if (ac.signal.aborted) {
347
+ spinner.stop();
348
+ process.stdout.write('\x1b[2K\r');
349
+ return;
392
350
  }
393
351
  let latestUsage = undefined;
394
352
  // Collect any inputs that were queued while the Context Agent was investigating
@@ -427,21 +385,12 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
427
385
  }
428
386
  // Hot-swap the underlying LLM system instruction context depending on intent (conversational vs execution)
429
387
  debugLog(`Intent Router output: original targetAgent = ${gatherRes.targetAgent}, effective = ${effectiveTargetAgent}`);
430
- let config;
431
- if (isPlanMode) {
432
- const { getPlanModeConfig } = await import('./ai.js');
433
- config = getPlanModeConfig();
434
- }
435
- else {
436
- config = effectiveTargetAgent === 'CHAT' ? getGeneralChatConfig() : getPlanExecutionConfig();
437
- }
388
+ const config = effectiveTargetAgent === 'CHAT' ? getGeneralChatConfig() : getPlanExecutionConfig();
438
389
  let dynamicSystemInstruction = config.systemInstruction;
439
390
  // Inject gathered workspace directories, dependency configurations, and matching search patterns
440
391
  if (gatherRes.contextResult) {
441
392
  // Compress each relevant file individually using helper to avoid nested loop warning
442
- if (!cachedContextResult) {
443
- gatherRes.contextResult.relevantFiles = await compressContextFiles(workspaceRoot, gatherRes.contextResult, ac.signal);
444
- }
393
+ gatherRes.contextResult.relevantFiles = await compressContextFiles(workspaceRoot, gatherRes.contextResult, ac.signal);
445
394
  // Assemble the final context injection string
446
395
  const contextInjection = buildContextInjection(gatherRes.contextResult);
447
396
  debugLog(`Final compressed context injection size: ${contextInjection.length} chars`);
@@ -510,7 +459,7 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
510
459
  gitBranch = stdout.trim();
511
460
  }
512
461
  catch { }
513
- if (!isPlanMode && effectiveTargetAgent === 'EXECUTE' && isSubAgentsEnabled()) {
462
+ if (effectiveTargetAgent === 'EXECUTE' && isSubAgentsEnabled()) {
514
463
  spinner.stop(); // Clear the spinner before delegating
515
464
  inputHandler.clearSpinner(); // Prevent prompt from reviving the old spinner
516
465
  process.stdout.write('\x1b[2K\r');
@@ -673,7 +622,7 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
673
622
  const calls = result.response.functionCalls();
674
623
  debugLog(`Initial functionCalls: ${calls && calls.length > 0 ? JSON.stringify(calls) : 'None'}`);
675
624
  // Stage 2: Recursive Tool Loops and Automated Self-Correction (delegated to a helper function to avoid nested loop warning)
676
- const correctionRes = await executeSelfCorrectionLoop(chat, result, workspaceRoot, inputHandler, effectiveTargetAgent, ac.signal, spinner, userInput, isPlanMode);
625
+ const correctionRes = await executeSelfCorrectionLoop(chat, result, workspaceRoot, inputHandler, effectiveTargetAgent, ac.signal, spinner, userInput);
677
626
  const finalText = correctionRes.finalText;
678
627
  inputHandler.stop();
679
628
  // Update latest usage metadata to reflect all completed turns
@@ -685,8 +634,9 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
685
634
  if (modifiedFiles.length > 0) {
686
635
  await invalidateCacheForDependents(workspaceRoot, modifiedFiles);
687
636
  }
637
+ let cleanFinalText = '';
688
638
  if (finalText) {
689
- const cleanFinalText = finalText.replace(/\[TASK_FINISHED\]/g, '').trim();
639
+ cleanFinalText = finalText.replace(/\[TASK_FINISHED\]/g, '').trim();
690
640
  if (cleanFinalText) {
691
641
  console.log(`\n${pc.blue('β—†')} ${pc.bold('Minovative Mind')} ${pc.dim(`(${chat.getModel()})`)}\n`);
692
642
  console.log(renderTerminalMarkdown(cleanFinalText));
@@ -824,93 +774,6 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
824
774
  })
825
775
  .catch((e) => debugLog('Failed to auto-save session: ' + e));
826
776
  }
827
- let planModeReturn = undefined;
828
- if (isPlanMode && finalText && finalText !== '[Generation stopped.]') {
829
- inputHandler.stop(); // MUST stop the async input handler before showing an interactive prompt, or it will intercept stdin and freeze/duplicate
830
- // Ensure the terminal has fully scrolled and there is a clean line break
831
- console.log('\n');
832
- // Small delay to allow stdout to flush and terminal to finish scrolling from the markdown output
833
- // This prevents @clack/prompts from miscalculating the cursor position and duplicating the prompt on arrow keys
834
- await new Promise((resolve) => setTimeout(resolve, 200));
835
- while (true) {
836
- const currentModel = getGlobalActiveModel();
837
- const planAction = await p['select']({
838
- message: 'Plan generated. What would you like to do?',
839
- options: [
840
- { value: 'proceed', label: 'Proceed with plan', hint: 'Executes the generated plan immediately' },
841
- { value: 'edit', label: 'Edit plan', hint: 'Provide additional feedback to revise the plan' },
842
- {
843
- value: 'choose_model',
844
- label: 'Choose AI model',
845
- hint: `Change the active AI model (Current: ${currentModel})`,
846
- },
847
- { value: 'exit', label: 'Exit plan mode', hint: 'Return to normal chat without executing' },
848
- ],
849
- });
850
- if (planAction === 'choose_model') {
851
- const byokEnabled = await isByokEnabled();
852
- const options = [
853
- // {
854
- // value: 'claude-opus-5',
855
- // label: 'Claude 5 Opus',
856
- // hint: 'For hardcore & complex problems',
857
- // },
858
- {
859
- value: 'gemini-3.1-pro-preview',
860
- label: 'Gemini 3.1 Pro',
861
- hint: 'For hardcore & complex problems',
862
- },
863
- // {
864
- // value: 'claude-sonnet-5',
865
- // label: 'Claude 5 Sonnet',
866
- // hint: 'Best for raw speed and cost efficiency',
867
- // },
868
- {
869
- value: 'gemini-3.7-flash',
870
- label: 'Gemini 3.7 Flash',
871
- hint: 'Next-gen reasoning, speed & balanced performance',
872
- },
873
- {
874
- value: 'gemini-3.6-flash',
875
- label: 'Gemini 3.6 Flash',
876
- hint: 'Everyday coding β€” fast and accurate',
877
- },
878
- {
879
- value: 'gemini-3.5-flash-lite',
880
- label: 'Gemini 3.5 Flash-Lite',
881
- hint: 'Best for raw speed and cost efficiency',
882
- },
883
- {
884
- value: 'auto',
885
- label: 'Auto (Flash-Lite / Flash)',
886
- hint: 'Dynamically routes between Gemini 3.5 Flash-Lite and Gemini 3.7 Flash based on prompt complexity',
887
- },
888
- ].filter((o) => !(byokEnabled && o.value.includes('claude')));
889
- const selectedModel = await p['select']({
890
- message: `Select AI Model (Current: ${pc.cyan(currentModel)})`,
891
- initialValue: currentModel,
892
- options: options,
893
- });
894
- if (!p.isCancel(selectedModel)) {
895
- chat.setModel(selectedModel);
896
- setGlobalActiveModel(selectedModel);
897
- p.log.success(`Model successfully switched to ${pc.cyan(selectedModel)}`);
898
- }
899
- continue;
900
- }
901
- if (p.isCancel(planAction) || planAction === 'exit') {
902
- planModeReturn = 'exit';
903
- }
904
- else if (planAction === 'edit') {
905
- planModeReturn = 'edit';
906
- }
907
- else if (planAction === 'proceed') {
908
- planModeReturn = 'proceed';
909
- }
910
- break;
911
- }
912
- }
913
- return { planModeReturn, contextResult: gatherRes.contextResult };
914
777
  }
915
778
  catch (err) {
916
779
  if (ac.signal.aborted || err?.name === 'AbortError' || err?.message?.includes('abort')) {
@@ -931,12 +794,12 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
931
794
  }
932
795
  });
933
796
  }
934
- async function collectUserInput(history, isPlanMode) {
797
+ async function collectUserInput(history) {
935
798
  let lines = [];
936
799
  let isMultiLine = false;
937
800
  while (true) {
938
801
  const userInputRaw = await historyText({
939
- message: isMultiLine ? ' ' : isPlanMode ? pc.cyan('(Plan Mode) ❯') : pc.magenta('❯'),
802
+ message: isMultiLine ? ' ' : pc.magenta('❯'),
940
803
  placeholder: isMultiLine ? '' : 'Use ' + String.fromCharCode(92) + ' for new lines',
941
804
  history,
942
805
  });
@@ -1075,7 +938,7 @@ export async function summarizeHistoryIfNeeded(chat, abortSignal) {
1075
938
  }
1076
939
  return false;
1077
940
  }
1078
- async function executeSelfCorrectionLoop(chat, initialResult, workspaceRoot, inputHandler, effectiveTargetAgent, signal, spinner, originalUserInput, isPlanMode) {
941
+ async function executeSelfCorrectionLoop(chat, initialResult, workspaceRoot, inputHandler, effectiveTargetAgent, signal, spinner, originalUserInput) {
1079
942
  let correctionAttempts = 0;
1080
943
  const MAX_CORRECTIONS = 5;
1081
944
  let result = initialResult;
@@ -1141,7 +1004,7 @@ async function executeSelfCorrectionLoop(chat, initialResult, workspaceRoot, inp
1141
1004
  }
1142
1005
  previousChangeCount = currentChanges.length;
1143
1006
  // ─── Tool-Based Intent Verification ─────────────────────────────────
1144
- if (effectiveTargetAgent === 'EXECUTE' && !intentVerified && !isPlanMode) {
1007
+ if (effectiveTargetAgent === 'EXECUTE' && !intentVerified) {
1145
1008
  if (!currentText.includes('[TASK_FINISHED]')) {
1146
1009
  p.log.warn(pc.yellow('AI paused execution without calling finish_task. Prompting to continue or finish...'));
1147
1010
  const finishReminder = `SYSTEM CHECK: You stopped without calling the \`finish_task\` tool.
@@ -1,4 +1,5 @@
1
1
  import { type Content, type FunctionCall } from '@google/generative-ai';
2
+ export declare function getMultiWorkspaceBlock(): string;
2
3
  export declare function setModelOverride(agent: 'context' | 'execution', overrideStr: string): void;
3
4
  export declare function clearModelOverrides(): void;
4
5
  export declare function setGlobalActiveModel(model: string): void;
@@ -9,11 +10,14 @@ export declare class ProxyChatSession {
9
10
  private modelName;
10
11
  private systemInstruction;
11
12
  private tools;
13
+ private toolConfig?;
12
14
  private generationConfig;
13
15
  private latestUsageMetadata;
14
- constructor(modelName: string, systemInstruction: string, tools: any[], generationConfig: any);
16
+ constructor(modelName: string, systemInstruction: string, tools: any[], generationConfig: any, toolConfig?: any);
15
17
  getLatestUsageMetadata(): any;
16
- setAgentConfig(systemInstruction: string, tools: any[]): void;
18
+ setAgentConfig(systemInstruction: string, tools: any[], toolConfig?: any): void;
19
+ setToolConfig(toolConfig?: any): void;
20
+ getToolConfig(): any;
17
21
  setModel(modelName: string): void;
18
22
  getModel(): string;
19
23
  clearHistory(): void;
@@ -91,10 +95,6 @@ export declare function getPlanExecutionConfig(): {
91
95
  functionDeclarations: import("@google/generative-ai").FunctionDeclaration[];
92
96
  }[];
93
97
  };
94
- export declare function getPlanModeConfig(): {
95
- systemInstruction: string;
96
- tools: never[];
97
- };
98
98
  /**
99
99
  * Compresses a large string of text using Gemini Flash.
100
100
  * Used for shrinking context payloads to prevent OOM/choking.