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
@@ -1,10 +1,46 @@
1
- import { DEFAULT_MODEL, GEMINI_MODELS, MAX_OUTPUT_TOKENS } from '../utils/config.js';
2
- import { toolDeclarations } from './agent-tools.js';
1
+ import { GEMINI_MODELS, DEFAULT_MODEL, MAX_OUTPUT_TOKENS } from '../utils/config.js';
2
+ import { getToolDeclarations } from './agent-tools.js';
3
3
  import { ProxyClient } from './proxyClient.js';
4
4
  import { getAuthorizedIdToken } from './auth.js';
5
5
  import { debugLog } from '../utils/logger.js';
6
- import { GENERAL_CHAT_INSTRUCTION, PLAN_EXECUTION_INSTRUCTION, CONTEXT_SYSTEM_INSTRUCTION, INTENT_ROUTER_SYSTEM_INSTRUCTION, WEB_SEARCH_SYSTEM_INSTRUCTION, } from '../utils/systemPrompts.js';
6
+ import { GENERAL_CHAT_INSTRUCTION, PLAN_EXECUTION_INSTRUCTION, PLAN_MODE_INSTRUCTION, CONTEXT_SYSTEM_INSTRUCTION, INTENT_ROUTER_SYSTEM_INSTRUCTION, WEB_SEARCH_SYSTEM_INSTRUCTION, EXECUTION_COMPLEXITY_SYSTEM_INSTRUCTION, INVESTIGATION_COMPLEXITY_SYSTEM_INSTRUCTION, } from '../utils/systemPrompts.js';
7
+ import { getMetricCollector } from './metrics.js';
8
+ // ─── Model Overrides (for Regression Testing) ────────────────────────
9
+ let contextModelOverride = null;
10
+ let contextTempOverride = null;
11
+ let executionModelOverride = null;
12
+ let executionTempOverride = null;
13
+ export function setModelOverride(agent, overrideStr) {
14
+ const [model, temp] = overrideStr.split(':');
15
+ if (agent === 'context') {
16
+ contextModelOverride = model || null;
17
+ if (temp)
18
+ contextTempOverride = parseFloat(temp);
19
+ }
20
+ else {
21
+ executionModelOverride = model || null;
22
+ if (temp)
23
+ executionTempOverride = parseFloat(temp);
24
+ }
25
+ }
26
+ export function clearModelOverrides() {
27
+ contextModelOverride = null;
28
+ contextTempOverride = null;
29
+ executionModelOverride = null;
30
+ executionTempOverride = null;
31
+ }
7
32
  // ─── AI Service ──────────────────────────────────────────────────────
33
+ let globalActiveModel = DEFAULT_MODEL;
34
+ export function setGlobalActiveModel(model) {
35
+ globalActiveModel = model;
36
+ }
37
+ export function getGlobalActiveModel() {
38
+ return globalActiveModel;
39
+ }
40
+ let globalLatestUsageMetadata = undefined;
41
+ export function getGlobalLatestUsageMetadata() {
42
+ return globalLatestUsageMetadata;
43
+ }
8
44
  const proxyClient = new ProxyClient();
9
45
  // ─── History Limits ──────────────────────────────────────────────────
10
46
  /** Maximum number of Content entries to keep in the sliding history window. */
@@ -91,7 +127,7 @@ export class ProxyChatSession {
91
127
  this.history = this.history.slice(trimCount);
92
128
  }
93
129
  }
94
- async sendMessage(message, additionalText, abortSignal) {
130
+ async sendMessage(message, additionalText, abortSignal, onChunk) {
95
131
  const idToken = await getAuthorizedIdToken();
96
132
  if (!idToken) {
97
133
  throw new Error('You are not signed in. Please run `minovative-mind-cli login` first.');
@@ -102,18 +138,29 @@ export class ProxyChatSession {
102
138
  newParts = [{ text: truncatePartText(message) }];
103
139
  }
104
140
  else {
105
- // It's an array of function responses — truncate output strings
106
- newParts = message.map((m) => ({
107
- functionResponse: {
108
- name: m.functionResponse.name,
109
- response: {
110
- ...m.functionResponse.response,
111
- output: typeof m.functionResponse.response.output === 'string'
112
- ? truncatePartText(m.functionResponse.response.output)
113
- : m.functionResponse.response.output,
141
+ // It's an array of function responses
142
+ newParts = [];
143
+ for (const m of message) {
144
+ newParts.push({
145
+ functionResponse: {
146
+ name: m.functionResponse.name,
147
+ response: {
148
+ ...m.functionResponse.response,
149
+ output: typeof m.functionResponse.response.output === 'string'
150
+ ? truncatePartText(m.functionResponse.response.output)
151
+ : m.functionResponse.response.output,
152
+ },
114
153
  },
115
- },
116
- }));
154
+ });
155
+ // If the tool execution returned inlineData (e.g. reading a PDF), append it as a sibling Part
156
+ if (m.functionResponse.response.inlineData) {
157
+ newParts.push({
158
+ inlineData: m.functionResponse.response.inlineData
159
+ });
160
+ // Remove it from the textual output payload to avoid schema violations in functionResponse
161
+ delete newParts[newParts.length - 2].functionResponse.response.inlineData;
162
+ }
163
+ }
117
164
  }
118
165
  if (additionalText) {
119
166
  newParts.push({ text: truncatePartText(additionalText) });
@@ -125,8 +172,20 @@ export class ProxyChatSession {
125
172
  // Prune old history before sending to keep payload bounded
126
173
  this.pruneHistory();
127
174
  const effectiveGenerationConfig = { ...this.generationConfig };
128
- const result = await proxyClient.generateFunctionCallViaProxy(idToken, this.modelName, this.history, this.tools, undefined, this.systemInstruction, effectiveGenerationConfig, undefined, abortSignal);
175
+ const result = await proxyClient.generateFunctionCallViaProxy(idToken, this.modelName, this.history, this.tools, undefined, // toolConfig
176
+ this.systemInstruction, effectiveGenerationConfig, onChunk ? { onChunk } : undefined, // streamCallbacks
177
+ abortSignal);
129
178
  this.latestUsageMetadata = result.usageMetadata;
179
+ if (result.usageMetadata) {
180
+ globalLatestUsageMetadata = result.usageMetadata;
181
+ }
182
+ // Track token usage metrics
183
+ if (result.usageMetadata) {
184
+ const collector = getMetricCollector();
185
+ if (collector) {
186
+ collector.recordTokenUsage(result.usageMetadata.promptTokens || 0, result.usageMetadata.candidatesTokens || 0, result.usageMetadata.cachedTokens || 0);
187
+ }
188
+ }
130
189
  // Append model response to history
131
190
  let modelParts = [];
132
191
  const allFunctionCalls = [...(result.functionCalls || [])];
@@ -184,9 +243,12 @@ export class ProxyChatSession {
184
243
  * Creates a new shared multi-turn chat session via the proxy.
185
244
  */
186
245
  export function createSharedChatSession() {
187
- return new ProxyChatSession(DEFAULT_MODEL, GENERAL_CHAT_INSTRUCTION, [], {
246
+ let model = executionModelOverride || getGlobalActiveModel();
247
+ if (model === 'auto')
248
+ model = GEMINI_MODELS.FLASH_3_5; // Will be overridden per-turn in executeSingleTurn
249
+ return new ProxyChatSession(model, GENERAL_CHAT_INSTRUCTION, [], {
188
250
  maxOutputTokens: MAX_OUTPUT_TOKENS,
189
- temperature: 1,
251
+ temperature: executionTempOverride !== null ? executionTempOverride : 1,
190
252
  topP: 0.95,
191
253
  topK: 40,
192
254
  });
@@ -200,22 +262,35 @@ export function getGeneralChatConfig() {
200
262
  export function getPlanExecutionConfig() {
201
263
  return {
202
264
  systemInstruction: PLAN_EXECUTION_INSTRUCTION,
203
- tools: [{ functionDeclarations: toolDeclarations }],
265
+ tools: [{ functionDeclarations: getToolDeclarations() }],
266
+ };
267
+ }
268
+ export function getPlanModeConfig() {
269
+ return {
270
+ systemInstruction: PLAN_MODE_INSTRUCTION,
271
+ tools: [], // No tools allowed in plan mode
204
272
  };
205
273
  }
206
274
  /**
207
275
  * Compresses a large string of text using gemini-3.1-flash-lite.
208
276
  * Used for shrinking context payloads to prevent OOM/choking.
209
277
  */
210
- export async function compressTextUsingFlashLite(text, instruction = 'Summarize the following text concisely. Preserve the most critical technical details, function names, and architecture logic. Keep it under 1500 characters.') {
211
- if (!text || text.length < 1000)
278
+ export async function compressTextUsingFlashLite(text, instruction = 'Summarize the following text concisely. Preserve the most critical technical details, function names, and architecture logic. Keep it under 1500 characters.', inlineData) {
279
+ if (!text || (text.length < 1000 && !inlineData))
212
280
  return text; // Don't compress tiny texts
213
281
  try {
214
282
  const idToken = await getAuthorizedIdToken();
215
283
  if (!idToken)
216
284
  return text;
217
- const contents = [{ role: 'user', parts: [{ text }] }];
218
- const result = await proxyClient.generateFunctionCallViaProxy(idToken, 'gemini-3.1-flash-lite', contents, [], // no tools
285
+ let model = getGlobalActiveModel();
286
+ if (model === 'auto')
287
+ model = GEMINI_MODELS.FLASH_LITE_3_1;
288
+ const parts = [{ text }];
289
+ if (inlineData) {
290
+ parts.push({ inlineData });
291
+ }
292
+ const contents = [{ role: 'user', parts }];
293
+ const result = await proxyClient.generateFunctionCallViaProxy(idToken, model, contents, [], // no tools
219
294
  undefined, instruction, { temperature: 0.2 });
220
295
  let textPart = '';
221
296
  if (result.parts) {
@@ -236,9 +311,13 @@ export async function compressTextUsingFlashLite(text, instruction = 'Summarize
236
311
  }
237
312
  }
238
313
  // ─── Context Agent Service ───────────────────────────────────────────
239
- export const CONTEXT_AGENT_MODEL = DEFAULT_MODEL;
240
- export function createContextAgentSession() {
241
- const contextTools = [
314
+ /**
315
+ * Returns the tool declarations for the read-only Context Agent.
316
+ * Extracted as a reusable function so investigation sub-agents can import
317
+ * the same schema without duplicating the declarations.
318
+ */
319
+ export function getContextToolDeclarations() {
320
+ return [
242
321
  {
243
322
  functionDeclarations: [
244
323
  {
@@ -271,7 +350,7 @@ export function createContextAgentSession() {
271
350
  },
272
351
  {
273
352
  name: 'read_file',
274
- description: 'Read a single file. Use startLine and endLine to read specific chunks of massive files.',
353
+ description: 'Read a single file. Supports text files and native parsing of .pdf files (including math and diagrams). Use startLine and endLine to read specific chunks of massive text files.',
275
354
  parameters: {
276
355
  type: 'OBJECT',
277
356
  properties: {
@@ -346,7 +425,8 @@ export function createContextAgentSession() {
346
425
  "language's native AST parser (e.g., TypeScript compiler API, Python ast module, go/parser). " +
347
426
  'The script is executed from a temporary directory and automatically cleaned up after execution. ' +
348
427
  'Output should be structured JSON to stdout with name, type, startLine, endLine for each code element. ' +
349
- 'Use the results to make precise read_file calls with exact startLine/endLine instead of guessing.',
428
+ 'Use the results to make precise read_file calls with exact startLine/endLine instead of guessing. ' +
429
+ 'CRITICAL: Do not use this tool on binary, document, or non-code files (e.g. PDF, image, audio, docx).',
350
430
  parameters: {
351
431
  type: 'OBJECT',
352
432
  properties: {
@@ -393,26 +473,75 @@ export function createContextAgentSession() {
393
473
  required: ['query'],
394
474
  },
395
475
  },
476
+ {
477
+ name: 'semantic_search',
478
+ description: 'Search the codebase by meaning and concept rather than exact text match. ' +
479
+ 'Use this when you need to find code related to a concept, pattern, or behavior ' +
480
+ "but don't know the exact variable or function names to grep for. " +
481
+ 'Examples: "error handling for API requests", "user authentication flow", ' +
482
+ '"database connection pooling logic". Returns ranked results with file paths, ' +
483
+ 'line ranges, and similarity scores.',
484
+ parameters: {
485
+ type: 'OBJECT',
486
+ properties: {
487
+ query: {
488
+ type: 'STRING',
489
+ description: "Natural language description of what you're looking for in the codebase.",
490
+ },
491
+ topK: {
492
+ type: 'NUMBER',
493
+ description: 'Number of results to return. Defaults to 5, maximum 15.',
494
+ },
495
+ },
496
+ required: ['query'],
497
+ },
498
+ },
396
499
  ],
397
500
  },
398
501
  ];
399
- return new ProxyChatSession(CONTEXT_AGENT_MODEL, CONTEXT_SYSTEM_INSTRUCTION, contextTools, {
502
+ }
503
+ export function createContextAgentSession() {
504
+ const contextTools = getContextToolDeclarations();
505
+ let model = contextModelOverride || getGlobalActiveModel();
506
+ if (model === 'auto')
507
+ model = GEMINI_MODELS.FLASH_3_5;
508
+ return new ProxyChatSession(model, CONTEXT_SYSTEM_INSTRUCTION, contextTools, {
400
509
  maxOutputTokens: MAX_OUTPUT_TOKENS,
401
- temperature: 1,
510
+ temperature: contextTempOverride !== null ? contextTempOverride : 1,
402
511
  topP: 0.95,
403
512
  topK: 40,
404
513
  });
405
514
  }
406
515
  // ─── Intent Router Service ───────────────────────────────────────────
407
- export const INTENT_ROUTER_MODEL = GEMINI_MODELS.FLASH_LITE_3_1;
408
516
  export function createIntentRouterSession() {
409
- return new ProxyChatSession(INTENT_ROUTER_MODEL, INTENT_ROUTER_SYSTEM_INSTRUCTION, [], // no tools
517
+ let model = getGlobalActiveModel();
518
+ if (model === 'auto')
519
+ model = GEMINI_MODELS.FLASH_LITE_3_1;
520
+ return new ProxyChatSession(model, INTENT_ROUTER_SYSTEM_INSTRUCTION, [], // no tools
521
+ { temperature: 0, responseMimeType: 'application/json' });
522
+ }
523
+ // ─── Execution Complexity Router Service ──────────────────────────────
524
+ export function createExecutionComplexitySession() {
525
+ let model = getGlobalActiveModel();
526
+ if (model === 'auto')
527
+ model = GEMINI_MODELS.FLASH_LITE_3_1;
528
+ return new ProxyChatSession(model, EXECUTION_COMPLEXITY_SYSTEM_INSTRUCTION, [], // no tools
529
+ { temperature: 0, responseMimeType: 'application/json' });
530
+ }
531
+ // ─── Investigation Complexity Router Service ─────────────────────────
532
+ export function createInvestigationComplexitySession() {
533
+ let model = getGlobalActiveModel();
534
+ if (model === 'auto')
535
+ model = GEMINI_MODELS.FLASH_LITE_3_1;
536
+ return new ProxyChatSession(model, INVESTIGATION_COMPLEXITY_SYSTEM_INSTRUCTION, [], // no tools
410
537
  { temperature: 0, responseMimeType: 'application/json' });
411
538
  }
412
539
  // ─── Web Search Agent Service ───────────────────────────────────────────
413
- export const WEB_SEARCH_AGENT_MODEL = GEMINI_MODELS.FLASH_LITE_3_1;
414
540
  export function createWebSearchAgentSession() {
415
- return new ProxyChatSession(WEB_SEARCH_AGENT_MODEL, WEB_SEARCH_SYSTEM_INSTRUCTION, [{ googleSearch: {} }], {
541
+ let model = getGlobalActiveModel();
542
+ if (model === 'auto')
543
+ model = GEMINI_MODELS.FLASH_3_5;
544
+ return new ProxyChatSession(model, WEB_SEARCH_SYSTEM_INSTRUCTION, [{ googleSearch: {} }], {
416
545
  maxOutputTokens: MAX_OUTPUT_TOKENS,
417
546
  temperature: 1,
418
547
  topP: 0.95,
@@ -432,7 +561,10 @@ export async function generateChatTitle(firstMessage) {
432
561
  return firstMessage.substring(0, maxLength);
433
562
  const instruction = "You are a helpful assistant that generates extremely concise chat titles (max 4-5 words) based on a user's first message. Output ONLY the title, no quotes, no markdown, no punctuation.";
434
563
  const contents = [{ role: 'user', parts: [{ text: firstMessage.substring(0, 500) }] }];
435
- const result = await proxyClient.generateFunctionCallViaProxy(idToken, 'gemini-3.1-flash-lite', contents, [], // no tools
564
+ let model = getGlobalActiveModel();
565
+ if (model === 'auto')
566
+ model = GEMINI_MODELS.FLASH_LITE_3_1;
567
+ const result = await proxyClient.generateFunctionCallViaProxy(idToken, model, contents, [], // no tools
436
568
  undefined, instruction, { temperature: 0.2 });
437
569
  let title = '';
438
570
  if (result.parts) {
@@ -1,31 +1,173 @@
1
+ /**
2
+ * Represents a single file modification tracked within a workspace changeset.
3
+ * Captures the state of a file before a change was applied, facilitating reversion.
4
+ */
1
5
  export interface FileChange {
6
+ /**
7
+ * Relative or absolute file path of the affected file.
8
+ */
2
9
  filePath: string;
10
+ /**
11
+ * The original content of the file before any modification in the changeset.
12
+ * A value of `null` indicates the file was newly created and did not exist previously.
13
+ */
3
14
  originalContent: string | null;
15
+ /**
16
+ * The nature of the file operation that occurred.
17
+ * - 'create': The file was newly written to disk.
18
+ * - 'modify': An existing file was updated.
19
+ * - 'delete': An existing file was removed.
20
+ */
4
21
  action: 'create' | 'modify' | 'delete';
5
22
  }
23
+ /**
24
+ * Represents a transactional unit of workspace modifications.
25
+ * Groups related file changes under a shared timestamp and intent description.
26
+ */
6
27
  export interface ChangeSet {
28
+ /**
29
+ * Unix epoch timestamp (in milliseconds) when this changeset was initiated.
30
+ */
7
31
  timestamp: number;
32
+ /**
33
+ * Developer or system-provided description explaining the intent of the changes (e.g. "Edit index.ts").
34
+ */
8
35
  description: string;
36
+ /**
37
+ * Array of individual file modifications tracking the original states prior to this changeset.
38
+ */
9
39
  changes: FileChange[];
40
+ /**
41
+ * The execution outcome status of this changeset.
42
+ * - 'partial': The change operation is still in progress or was interrupted.
43
+ * - 'complete': All planned modifications in the transaction finished successfully.
44
+ */
10
45
  status?: 'complete' | 'partial';
11
46
  }
47
+ /**
48
+ * Service class responsible for tracking, persisting, and reverting file modifications in the workspace.
49
+ * Uses a local project state file (`revert_state.json`) to persist state across CLI invocations.
50
+ */
12
51
  declare class ChangeLogger {
52
+ /**
53
+ * Ordered history stack of committed changesets, oldest first, newest last.
54
+ */
13
55
  private changeStack;
56
+ /**
57
+ * The active changeset currently receiving recorded modifications.
58
+ * Null if no change transaction is actively in progress.
59
+ */
14
60
  private currentChangeSet;
61
+ /**
62
+ * Absolute path to the active workspace root directory.
63
+ */
15
64
  private workspaceRoot;
65
+ /**
66
+ * Maximum number of historical changesets retained in memory and on disk.
67
+ * Older changesets are discarded on save once this limit is exceeded.
68
+ */
16
69
  private readonly MAX_HISTORY;
70
+ /**
71
+ * Whether the change logger is currently enabled.
72
+ */
73
+ private isEnabled;
74
+ getIsEnabled(): boolean;
75
+ setIsEnabled(enabled: boolean): void;
76
+ /**
77
+ * Initializes the ChangeLogger by setting the workspace root and loading existing
78
+ * history from the local `.minovativemind/revert_state.json` cache file.
79
+ *
80
+ * @param workspaceRoot - The absolute path to the project workspace root.
81
+ */
17
82
  init(workspaceRoot: string): void;
83
+ /**
84
+ * Persists the current committed change stack to the local cache directory.
85
+ * Enforces the `MAX_HISTORY` retention policy by slicing out older entries.
86
+ * Does nothing if the workspace root has not yet been initialized.
87
+ */
18
88
  private saveState;
89
+ /**
90
+ * Retrieves a copy of the active history stack.
91
+ *
92
+ * @returns A shallow copy of the array containing all tracked changesets.
93
+ */
19
94
  getHistory(): ChangeSet[];
95
+ /**
96
+ * Traverses backward through the history stack, popping and collecting changesets
97
+ * until a changeset matching the specified timestamp is encountered (inclusive).
98
+ * Persists the resulting truncated stack after execution.
99
+ *
100
+ * @param timestamp - The unique timestamp identifier of the target changeset to revert back to.
101
+ * @returns An array of popped changesets ordered from newest to oldest.
102
+ */
20
103
  popUntil(timestamp: number): ChangeSet[];
104
+ /**
105
+ * Initiates a new transactional changeset. If a previous changeset was in progress and
106
+ * uncommitted, it is automatically finalized and committed to the history stack first.
107
+ *
108
+ * @param description - Descriptive label summarizing the purpose of the new changeset.
109
+ */
21
110
  startChangeSet(description: string): void;
111
+ /**
112
+ * Records a file change within the active changeset.
113
+ * If no changeset is active, an anonymous default changeset is automatically initialized.
114
+ *
115
+ * @remarks
116
+ * Idempotency Guard: If the specified file already has an entry in the current changeset,
117
+ * the original state is preserved. This ensures that multiple successive modifications to
118
+ * the same file within a single transaction map back to the true original state prior to
119
+ * the onset of the transaction.
120
+ *
121
+ * @param filePath - The relative or absolute path of the file being altered.
122
+ * @param originalContent - The text content of the file prior to the change, or null if created.
123
+ * @param action - The classification of the operation ('create', 'modify', or 'delete').
124
+ */
22
125
  logChange(filePath: string, originalContent: string | null, action: 'create' | 'modify' | 'delete'): void;
126
+ /**
127
+ * Marks the status of the active changeset as 'complete', indicating that all scheduled
128
+ * operations within the scope of this transaction finished without interruption.
129
+ */
23
130
  markComplete(): void;
131
+ /**
132
+ * Retrieves a list of file paths that have been modified in the currently active changeset.
133
+ *
134
+ * @returns An array of string file paths, or an empty array if no changeset is active.
135
+ */
136
+ getChangedFiles(): string[];
137
+ /**
138
+ * Commits the active changeset to the history stack and persists the state to disk,
139
+ * provided that the changeset actually contains one or more recorded file modifications.
140
+ * Resets the active changeset state to null.
141
+ */
24
142
  commitChangeSet(): void;
143
+ /**
144
+ * Retrieves the most recently committed changeset from the history stack without removing it.
145
+ *
146
+ * @returns The latest committed ChangeSet, or null if the stack is currently empty.
147
+ */
25
148
  getLastChangeSet(): ChangeSet | null;
149
+ /**
150
+ * Returns the active, uncommitted changeset currently receiving modifications.
151
+ *
152
+ * @returns The in-progress ChangeSet, or null if no changeset is active.
153
+ */
26
154
  getCurrentChangeSet(): ChangeSet | null;
155
+ /**
156
+ * Removes and returns the most recently committed changeset from the history stack.
157
+ * Persists the newly truncated stack state back to the cache.
158
+ *
159
+ * @returns The removed ChangeSet, or null if no historical changes exist.
160
+ */
27
161
  popLastChangeSet(): ChangeSet | null;
162
+ /**
163
+ * Checks whether the history stack contains any tracked changesets.
164
+ *
165
+ * @returns True if at least one changeset is recorded; false otherwise.
166
+ */
28
167
  hasChanges(): boolean;
29
168
  }
169
+ /**
170
+ * Singleton instance of the ChangeLogger service exported for application-wide tracking.
171
+ */
30
172
  export declare const changeLogger: ChangeLogger;
31
173
  export {};