minovative-mind-cli 2.1.0 → 2.1.1

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
@@ -112,6 +112,7 @@ Hot-swap during a session using `/models`:
112
112
  | `/commit` | Generate a conventional commit message from your diff |
113
113
  | `/revert` | Undo changes from the last turn, or toggle the revert logger |
114
114
  | `/chats` | View, resume, or delete previous chat sessions |
115
+ | `/workspaces` | Manage active workspaces and linked cross-repo aliases |
115
116
  | `stop` | Abort generation immediately |
116
117
 
117
118
  ---
@@ -4,7 +4,7 @@ import pc from 'picocolors';
4
4
  import { createContextAgentSession, createIntentRouterSession, createWebSearchAgentSession, createExecutionComplexitySession, } from './ai.js';
5
5
  import { evaluateInvestigationComplexity } from './investigationComplexity.js';
6
6
  import { InvestigationOrchestrator } from './orchestration/investigationOrchestrator.js';
7
- import { isSubAgentsEnabled, listDirectory, grepSearch, readFile, traceDependencies, findRecentChanges } from './agent-tools.js';
7
+ import { isSubAgentsEnabled, executeTool } from './agent-tools.js';
8
8
  import { debugLog } from '../utils/logger.js';
9
9
  import { buildDependencyGraph } from '../utils/dependencyTracer.js';
10
10
  import { runEphemeralScript } from '../utils/analysisRunner.js';
@@ -198,7 +198,7 @@ export async function gatherContext(workspaceRoot, userRequest, chatHistory = ''
198
198
  let primaryProjectType = 'Unknown';
199
199
  for (const { alias, root } of allRoots) {
200
200
  const label = alias ? `@${alias} (${root})` : `Primary Workspace (${root})`;
201
- const treeResult = await listDirectory(root, '.', 10);
201
+ const treeResult = await executeTool(root, 'list_directory', { dirPath: '.', maxDepth: 10 });
202
202
  let tree = treeResult.output;
203
203
  if (tree.length > 30000) {
204
204
  tree = tree.substring(0, 30000) + '\\n... (Project tree truncated due to size)';
@@ -328,7 +328,7 @@ export async function gatherContext(workspaceRoot, userRequest, chatHistory = ''
328
328
  debugLog(`Context Agent finished. Selected files: ${JSON.stringify(filesToRead)}`);
329
329
  for (const filePath of filesToRead) {
330
330
  if (!relevantFiles.has(filePath)) {
331
- const readResult = await readFile(workspaceRoot, filePath);
331
+ const readResult = await executeTool(workspaceRoot, 'read_file', { filePath });
332
332
  if (!readResult.error) {
333
333
  relevantFiles.set(filePath, { text: readResult.output, inlineData: readResult.inlineData });
334
334
  }
@@ -342,15 +342,23 @@ export async function gatherContext(workspaceRoot, userRequest, chatHistory = ''
342
342
  // Execution Agent won't break imports when modifying/deleting/renaming.
343
343
  const MAX_TOTAL_FILES = 15;
344
344
  try {
345
- const graph = await buildDependencyGraph(workspaceRoot);
345
+ const { resolveAndValidateMultiWorkspacePath } = await import('../utils/pathSecurity.js');
346
346
  const autoDiscovered = new Set();
347
347
  for (const filePath of filesToRead) {
348
- const reverseDeps = graph.getImportedBy(filePath);
349
- for (const dep of reverseDeps) {
350
- if (!filesToRead.includes(dep) && !autoDiscovered.has(dep)) {
351
- autoDiscovered.add(dep);
348
+ try {
349
+ const resolved = resolveAndValidateMultiWorkspacePath(workspaceRoot, filePath);
350
+ const graph = await buildDependencyGraph(resolved.workspaceRoot);
351
+ const reverseDeps = graph.getImportedBy(resolved.relativePath);
352
+ for (const dep of reverseDeps) {
353
+ const aliasedDep = resolved.alias ? `@${resolved.alias}/${dep}` : dep;
354
+ if (!filesToRead.includes(aliasedDep) && !autoDiscovered.has(aliasedDep)) {
355
+ autoDiscovered.add(aliasedDep);
356
+ }
352
357
  }
353
358
  }
359
+ catch (e) {
360
+ // Ignore path resolution errors for trace dependencies
361
+ }
354
362
  }
355
363
  // Merge auto-discovered dependents, respecting the file cap
356
364
  const remaining = MAX_TOTAL_FILES - relevantFiles.size;
@@ -359,7 +367,7 @@ export async function gatherContext(workspaceRoot, userRequest, chatHistory = ''
359
367
  if (added >= remaining)
360
368
  break;
361
369
  if (!relevantFiles.has(dep)) {
362
- const readResult = await readFile(workspaceRoot, dep);
370
+ const readResult = await executeTool(workspaceRoot, 'read_file', { filePath: dep });
363
371
  if (!readResult.error) {
364
372
  relevantFiles.set(dep, { text: readResult.output, inlineData: readResult.inlineData });
365
373
  added++;
@@ -389,7 +397,7 @@ export async function gatherContext(workspaceRoot, userRequest, chatHistory = ''
389
397
  const filesToRead = args.files || [];
390
398
  let output = '';
391
399
  for (const filePath of filesToRead) {
392
- const readResult = await readFile(workspaceRoot, filePath);
400
+ const readResult = await executeTool(workspaceRoot, 'read_file', { filePath });
393
401
  if (!readResult.error) {
394
402
  relevantFiles.set(filePath, { text: readResult.output, inlineData: readResult.inlineData });
395
403
  output += `\n--- File: ${filePath} ---\n${readResult.output}\n`;
@@ -406,7 +414,7 @@ export async function gatherContext(workspaceRoot, userRequest, chatHistory = ''
406
414
  });
407
415
  }
408
416
  else if (call.name === 'list_directory') {
409
- const listRes = await listDirectory(workspaceRoot, args.dirPath, args.maxDepth || 1);
417
+ const listRes = await executeTool(workspaceRoot, 'list_directory', args);
410
418
  functionResponses.push({
411
419
  functionResponse: {
412
420
  name: call.name,
@@ -418,7 +426,7 @@ export async function gatherContext(workspaceRoot, userRequest, chatHistory = ''
418
426
  });
419
427
  }
420
428
  else if (call.name === 'search_codebase') {
421
- const grepRes = await grepSearch(workspaceRoot, args.pattern, args.fileGlob);
429
+ const grepRes = await executeTool(workspaceRoot, 'grep_search', { ...args, workspace: 'all' });
422
430
  functionResponses.push({
423
431
  functionResponse: {
424
432
  name: call.name,
@@ -427,44 +435,16 @@ export async function gatherContext(workspaceRoot, userRequest, chatHistory = ''
427
435
  });
428
436
  }
429
437
  else if (call.name === 'semantic_search') {
430
- const query = args.query;
431
- const topK = args.topK || 5;
432
- let output = '';
433
- try {
434
- const { getEmbeddingIndex } = await import('./embeddingIndex.js');
435
- const index = getEmbeddingIndex();
436
- if (!index.isReady()) {
437
- // Lazy load from disk or build if missing
438
- const loaded = await index.load(workspaceRoot);
439
- if (!loaded) {
440
- if (onProgress)
441
- onProgress('Building semantic search index (first run)...');
442
- await index.buildIndex(workspaceRoot, onProgress);
443
- await index.save(workspaceRoot);
444
- }
445
- }
446
- const results = await index.search(query, topK);
447
- if (results.length === 0) {
448
- output = 'No semantically similar code found. (Index might be empty or embedding failed)';
449
- }
450
- else {
451
- output = results
452
- .map((r) => `[Score: ${r.score.toFixed(3)}] ${r.filePath}:${r.startLine}-${r.endLine}\n${r.preview}`)
453
- .join('\n---\n');
454
- }
455
- }
456
- catch (e) {
457
- output = `Semantic search failed: ${e.message}`;
458
- }
438
+ const semRes = await executeTool(workspaceRoot, 'semantic_search', args);
459
439
  functionResponses.push({
460
440
  functionResponse: {
461
441
  name: call.name,
462
- response: { output },
442
+ response: { output: semRes.output },
463
443
  },
464
444
  });
465
445
  }
466
446
  else if (call.name === 'read_file') {
467
- const readRes = await readFile(workspaceRoot, args.filePath, args.startLine, args.endLine, args.targetElements);
447
+ const readRes = await executeTool(workspaceRoot, 'read_file', args);
468
448
  if (!readRes.error) {
469
449
  relevantFiles.set(args.filePath, { text: readRes.output, inlineData: readRes.inlineData });
470
450
  }
@@ -506,7 +486,7 @@ export async function gatherContext(workspaceRoot, userRequest, chatHistory = ''
506
486
  }
507
487
  }
508
488
  else if (call.name === 'find_dependencies') {
509
- const depResult = await traceDependencies(workspaceRoot, args.filePath, args.direction, args.maxDepth);
489
+ const depResult = await executeTool(workspaceRoot, 'find_dependencies', args);
510
490
  functionResponses.push({
511
491
  functionResponse: {
512
492
  name: call.name,
@@ -515,7 +495,7 @@ export async function gatherContext(workspaceRoot, userRequest, chatHistory = ''
515
495
  });
516
496
  }
517
497
  else if (call.name === 'find_recent_changes') {
518
- const recentRes = await findRecentChanges(workspaceRoot, args.dirPath, args.minutes, args.maxDepth);
498
+ const recentRes = await executeTool(workspaceRoot, 'find_recent_changes', args);
519
499
  functionResponses.push({
520
500
  functionResponse: {
521
501
  name: call.name,
@@ -65,5 +65,5 @@
65
65
  ]
66
66
  }
67
67
  },
68
- "version": "2.1.0"
68
+ "version": "2.1.1"
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.1.0",
4
+ "version": "2.1.1",
5
5
  "author": "Daniel Ward",
6
6
  "bin": {
7
7
  "minovative-mind-cli": "bin/run.js"