minovative-mind-cli 2.2.3 → 2.2.4

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.
@@ -352,7 +352,7 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
352
352
  spinner.message('Thinking...');
353
353
  }
354
354
  }
355
- if (effectiveTargetAgent === 'EXECUTE' && isSubAgentsEnabled()) {
355
+ if (!isPlanMode && effectiveTargetAgent === 'EXECUTE' && isSubAgentsEnabled()) {
356
356
  spinner.stop(); // Clear the spinner before delegating
357
357
  process.stdout.write('\x1b[2K\r');
358
358
  const orchestrator = new Orchestrator(workspaceRoot, chatSessionState.id, inputHandler);
@@ -455,7 +455,7 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
455
455
  const calls = result.response.functionCalls();
456
456
  debugLog(`Initial functionCalls: ${calls && calls.length > 0 ? JSON.stringify(calls) : 'None'}`);
457
457
  // Stage 2: Recursive Tool Loops and Automated Self-Correction (delegated to a helper function to avoid nested loop warning)
458
- const correctionRes = await executeSelfCorrectionLoop(chat, result, workspaceRoot, inputHandler, effectiveTargetAgent, ac.signal, spinner, userInput);
458
+ const correctionRes = await executeSelfCorrectionLoop(chat, result, workspaceRoot, inputHandler, effectiveTargetAgent, ac.signal, spinner, userInput, isPlanMode);
459
459
  const finalText = correctionRes.finalText;
460
460
  // Update latest usage metadata to reflect all completed turns
461
461
  latestUsage = chat.getLatestUsageMetadata() || latestUsage;
@@ -717,7 +717,7 @@ async function compressContextFiles(workspaceRoot, contextResult) {
717
717
  }
718
718
  return compressedFiles;
719
719
  }
720
- async function executeSelfCorrectionLoop(chat, initialResult, workspaceRoot, inputHandler, effectiveTargetAgent, signal, spinner, originalUserInput) {
720
+ async function executeSelfCorrectionLoop(chat, initialResult, workspaceRoot, inputHandler, effectiveTargetAgent, signal, spinner, originalUserInput, isPlanMode) {
721
721
  let correctionAttempts = 0;
722
722
  const MAX_CORRECTIONS = 5;
723
723
  let result = initialResult;
@@ -761,7 +761,7 @@ async function executeSelfCorrectionLoop(chat, initialResult, workspaceRoot, inp
761
761
  }
762
762
  previousChangeCount = currentChanges.length;
763
763
  // ─── Intent Verification Phase ─────────────────────────────────────
764
- if (effectiveTargetAgent === 'EXECUTE' && !intentVerified) {
764
+ if (effectiveTargetAgent === 'EXECUTE' && !intentVerified && !isPlanMode) {
765
765
  spinner.start('Verifying task completion...');
766
766
  const intentVerificationPrompt = `SYSTEM CHECK: Please objectively verify that you have fully completed the user's original explicit request:
767
767
 
@@ -1,24 +1,79 @@
1
1
  import type { Content } from '@google/generative-ai';
2
+ /**
3
+ * Represents the structure of a saved chat session.
4
+ * This data is persisted in the local workspace cache to allow users to resume
5
+ * previous conversations with the AI agent.
6
+ */
2
7
  export interface ChatSessionData {
8
+ /** Unique identifier for the chat session, typically a UUID or timestamp-based string. */
3
9
  id: string;
10
+ /** User-friendly title or summary of the chat session. */
4
11
  title: string;
12
+ /** Epoch timestamp (in milliseconds) indicating when the session was last updated or created. */
5
13
  timestamp: number;
14
+ /** The full conversation history, structured as an array of Content objects compatible with the Gemini API. */
6
15
  history: Content[];
16
+ /** Optional number of remaining credits for the user's account at the time of the session update. */
7
17
  creditsRemaining?: number;
18
+ /** Optional human-readable duration of the last turn (e.g., "1.2s"). */
8
19
  lastTurnDuration?: string;
20
+ /** Optional name of the AI model used during this session (e.g., "gemini-1.5-pro"). */
9
21
  modelName?: string;
22
+ /** Optional total cumulative tokens consumed during the session. */
10
23
  totalTokens?: number;
24
+ /** Optional name of the Git branch active when this session was last updated. */
11
25
  gitBranch?: string;
26
+ /** Optional flag indicating whether auto-approval of commands was enabled in this session. */
12
27
  autoApprove?: boolean;
28
+ /** Optional flag indicating whether sub-agents were enabled or active during this session. */
13
29
  subAgents?: boolean;
14
30
  }
31
+ /**
32
+ * Service responsible for managing the persistence, retrieval, and deletion of chat session histories.
33
+ * It stores session metadata and message history in a local JSON cache (`chat_sessions.json`)
34
+ * within the project's storage directory and enforces a maximum limit of 250 sessions to prevent
35
+ * unbounded storage growth.
36
+ */
15
37
  declare class ChatHistoryService {
38
+ /** The root directory of the currently active workspace. Used to locate the project storage and cache files. */
16
39
  private workspaceRoot;
40
+ /** The maximum number of chat sessions allowed in the cache. Oldest sessions are discarded when this limit is exceeded. */
17
41
  private readonly MAX_SESSIONS;
42
+ /**
43
+ * Initializes the chat history service with the workspace root path.
44
+ * This must be called before attempting to read, save, or delete sessions.
45
+ *
46
+ * @param workspaceRoot - The absolute path to the workspace root directory.
47
+ */
18
48
  init(workspaceRoot: string): void;
49
+ /**
50
+ * Retrieves all saved chat sessions from the local workspace cache.
51
+ * If the service is not initialized or no sessions exist, an empty array is returned.
52
+ *
53
+ * @returns An array of saved `ChatSessionData` objects, ordered as stored in the cache.
54
+ */
19
55
  getSessions(): ChatSessionData[];
56
+ /**
57
+ * Saves or updates a chat session in the local workspace cache.
58
+ * If a session with the same ID already exists, it is updated in place. Otherwise, it is appended.
59
+ * Enforces the maximum session limit of 250 by removing the oldest session if the limit is exceeded.
60
+ *
61
+ * @param session - The chat session data to be saved.
62
+ * @returns A promise that resolves when the session has been successfully written to the cache.
63
+ */
20
64
  saveSession(session: ChatSessionData): Promise<void>;
65
+ /**
66
+ * Deletes a chat session from the local workspace cache and removes its associated archived history file.
67
+ * If the session or its archived history file does not exist, the operation completes without throwing an error.
68
+ *
69
+ * @param id - The unique identifier of the chat session to delete.
70
+ * @returns A promise that resolves when the session and its associated archive have been deleted.
71
+ */
21
72
  deleteSession(id: string): Promise<void>;
22
73
  }
74
+ /**
75
+ * Singleton instance of the `ChatHistoryService` exported for application-wide use.
76
+ * This instance must be initialized with `init(workspaceRoot)` before use.
77
+ */
23
78
  export declare const chatHistoryService: ChatHistoryService;
24
79
  export {};
@@ -1,16 +1,44 @@
1
1
  import { readCache, writeCache } from '../utils/projectStorage.js';
2
+ /**
3
+ * Service responsible for managing the persistence, retrieval, and deletion of chat session histories.
4
+ * It stores session metadata and message history in a local JSON cache (`chat_sessions.json`)
5
+ * within the project's storage directory and enforces a maximum limit of 250 sessions to prevent
6
+ * unbounded storage growth.
7
+ */
2
8
  class ChatHistoryService {
9
+ /** The root directory of the currently active workspace. Used to locate the project storage and cache files. */
3
10
  workspaceRoot = '';
11
+ /** The maximum number of chat sessions allowed in the cache. Oldest sessions are discarded when this limit is exceeded. */
4
12
  MAX_SESSIONS = 250;
13
+ /**
14
+ * Initializes the chat history service with the workspace root path.
15
+ * This must be called before attempting to read, save, or delete sessions.
16
+ *
17
+ * @param workspaceRoot - The absolute path to the workspace root directory.
18
+ */
5
19
  init(workspaceRoot) {
6
20
  this.workspaceRoot = workspaceRoot;
7
21
  }
22
+ /**
23
+ * Retrieves all saved chat sessions from the local workspace cache.
24
+ * If the service is not initialized or no sessions exist, an empty array is returned.
25
+ *
26
+ * @returns An array of saved `ChatSessionData` objects, ordered as stored in the cache.
27
+ */
8
28
  getSessions() {
9
29
  if (!this.workspaceRoot)
10
30
  return [];
11
31
  const sessions = readCache(this.workspaceRoot, 'chat_sessions.json');
12
32
  return sessions || [];
13
33
  }
34
+ /**
35
+ * Saves or updates a chat session in the local workspace cache.
36
+ * If a session with the same ID already exists, it is updated in place. Otherwise, it is appended.
37
+ * Enforces the maximum session limit of 250 by removing the oldest session if the limit is exceeded.
38
+ *
39
+ * @param session - The chat session data to be saved.
40
+ * @returns A promise that resolves when the session has been successfully written to the cache.
41
+ */
14
42
  async saveSession(session) {
15
43
  if (!this.workspaceRoot)
16
44
  return;
@@ -28,6 +56,13 @@ class ChatHistoryService {
28
56
  }
29
57
  await writeCache(this.workspaceRoot, 'chat_sessions.json', sessions);
30
58
  }
59
+ /**
60
+ * Deletes a chat session from the local workspace cache and removes its associated archived history file.
61
+ * If the session or its archived history file does not exist, the operation completes without throwing an error.
62
+ *
63
+ * @param id - The unique identifier of the chat session to delete.
64
+ * @returns A promise that resolves when the session and its associated archive have been deleted.
65
+ */
31
66
  async deleteSession(id) {
32
67
  if (!this.workspaceRoot)
33
68
  return;
@@ -48,4 +83,8 @@ class ChatHistoryService {
48
83
  }
49
84
  }
50
85
  }
86
+ /**
87
+ * Singleton instance of the `ChatHistoryService` exported for application-wide use.
88
+ * This instance must be initialized with `init(workspaceRoot)` before use.
89
+ */
51
90
  export const chatHistoryService = new ChatHistoryService();
@@ -1 +1,35 @@
1
+ /**
2
+ * Synchronizes local workspace metadata with the remote Firestore database.
3
+ * This function tracks user project activity by updating a "last used" timestamp
4
+ * and project details in Firestore whenever a workspace is accessed.
5
+ *
6
+ * ### Internal Logic & Flow:
7
+ * 1. **JWT Decoding**:
8
+ * - Splits the provided `idToken` (JWT) to extract the payload segment (second part).
9
+ * - Decodes the payload from Base64 to a UTF-8 string and parses it as JSON.
10
+ * - Extracts the `user_id` (UID) representing the authenticated user.
11
+ * - If the token is invalid or does not contain a `user_id`, the function exits early.
12
+ *
13
+ * 2. **ID Generation**:
14
+ * - Encodes the absolute `workspaceRoot` path into a Base64 string.
15
+ * - Transforms the Base64 string to be URL-safe by replacing `/` with `_`, `+` with `-`, and removing `=` padding.
16
+ * - This URL-safe string serves as a unique, deterministic document identifier for the workspace in Firestore.
17
+ *
18
+ * 3. **Firestore Integration**:
19
+ * - Constructs a `PATCH` request URL targeting the user's specific project document in Firestore.
20
+ * - Prepares a payload containing:
21
+ * - `name`: The base name of the workspace directory.
22
+ * - `path`: The absolute path to the workspace.
23
+ * - `workspacePath`: The absolute path to the workspace.
24
+ * - `lastUsed`: An ISO 8601 timestamp representing the current time.
25
+ * - Sends the payload via a `PATCH` request to the Firestore REST API, passing the `idToken` in the `Authorization` header.
26
+ *
27
+ * 4. **Error Handling & Logging**:
28
+ * - If the Firestore REST API returns a non-OK status, the response body is read and logged using `debugLog`.
29
+ * - Any thrown exceptions (such as network failures or JSON parsing errors) are caught and logged using `debugLog`.
30
+ *
31
+ * @param idToken - The Firebase ID token (JWT) of the authenticated user.
32
+ * @param workspaceRoot - The absolute file system path of the workspace root.
33
+ * @returns A promise that resolves when the update attempt is complete.
34
+ */
1
35
  export declare function updateWorkspaceStatus(idToken: string, workspaceRoot: string): Promise<void>;
@@ -1,5 +1,39 @@
1
1
  import * as path from 'path';
2
2
  import { debugLog } from '../utils/logger.js';
3
+ /**
4
+ * Synchronizes local workspace metadata with the remote Firestore database.
5
+ * This function tracks user project activity by updating a "last used" timestamp
6
+ * and project details in Firestore whenever a workspace is accessed.
7
+ *
8
+ * ### Internal Logic & Flow:
9
+ * 1. **JWT Decoding**:
10
+ * - Splits the provided `idToken` (JWT) to extract the payload segment (second part).
11
+ * - Decodes the payload from Base64 to a UTF-8 string and parses it as JSON.
12
+ * - Extracts the `user_id` (UID) representing the authenticated user.
13
+ * - If the token is invalid or does not contain a `user_id`, the function exits early.
14
+ *
15
+ * 2. **ID Generation**:
16
+ * - Encodes the absolute `workspaceRoot` path into a Base64 string.
17
+ * - Transforms the Base64 string to be URL-safe by replacing `/` with `_`, `+` with `-`, and removing `=` padding.
18
+ * - This URL-safe string serves as a unique, deterministic document identifier for the workspace in Firestore.
19
+ *
20
+ * 3. **Firestore Integration**:
21
+ * - Constructs a `PATCH` request URL targeting the user's specific project document in Firestore.
22
+ * - Prepares a payload containing:
23
+ * - `name`: The base name of the workspace directory.
24
+ * - `path`: The absolute path to the workspace.
25
+ * - `workspacePath`: The absolute path to the workspace.
26
+ * - `lastUsed`: An ISO 8601 timestamp representing the current time.
27
+ * - Sends the payload via a `PATCH` request to the Firestore REST API, passing the `idToken` in the `Authorization` header.
28
+ *
29
+ * 4. **Error Handling & Logging**:
30
+ * - If the Firestore REST API returns a non-OK status, the response body is read and logged using `debugLog`.
31
+ * - Any thrown exceptions (such as network failures or JSON parsing errors) are caught and logged using `debugLog`.
32
+ *
33
+ * @param idToken - The Firebase ID token (JWT) of the authenticated user.
34
+ * @param workspaceRoot - The absolute file system path of the workspace root.
35
+ * @returns A promise that resolves when the update attempt is complete.
36
+ */
3
37
  export async function updateWorkspaceStatus(idToken, workspaceRoot) {
4
38
  try {
5
39
  // 1. Decode JWT to get user_id (uid)
@@ -14,7 +48,8 @@ export async function updateWorkspaceStatus(idToken, workspaceRoot) {
14
48
  // 2. Generate a URL-safe ID for the workspace based on its path
15
49
  const workspaceId = Buffer.from(workspaceRoot)
16
50
  .toString('base64')
17
- .replace(/\//g, '_')
51
+ // eslint-disable-next-line prefer-regex-literals
52
+ .replace(new RegExp('/', 'g'), '_')
18
53
  .replace(/\+/g, '-')
19
54
  .replace(/=/g, '');
20
55
  // 3. Prepare the Firestore REST API payload
@@ -65,5 +65,5 @@
65
65
  ]
66
66
  }
67
67
  },
68
- "version": "2.2.3"
68
+ "version": "2.2.4"
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.3",
4
+ "version": "2.2.4",
5
5
  "author": "Daniel Ward",
6
6
  "bin": {
7
7
  "minovative-mind-cli": "bin/run.js"