@indiccoder/mentis-cli 1.1.4 → 1.1.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.
Files changed (64) hide show
  1. package/.claude/settings.local.json +8 -0
  2. package/.mentis/session.json +15 -0
  3. package/.mentis/sessions/1769189035730.json +23 -0
  4. package/.mentis/sessions/1769189569160.json +23 -0
  5. package/.mentis/sessions/1769767538672.json +23 -0
  6. package/.mentis/sessions/1769767785155.json +23 -0
  7. package/.mentis/sessions/1769768745802.json +23 -0
  8. package/.mentis/sessions/1769769600884.json +31 -0
  9. package/.mentis/sessions/1769770030160.json +31 -0
  10. package/.mentis/sessions/1769770606004.json +78 -0
  11. package/.mentis/sessions/1769771084515.json +141 -0
  12. package/.mentis/sessions/1769881926630.json +57 -0
  13. package/README.md +17 -0
  14. package/dist/checkpoint/CheckpointManager.js +92 -0
  15. package/dist/debug_google.js +61 -0
  16. package/dist/debug_lite.js +49 -0
  17. package/dist/debug_lite_headers.js +57 -0
  18. package/dist/debug_search.js +16 -0
  19. package/dist/index.js +10 -0
  20. package/dist/mcp/JsonRpcClient.js +16 -0
  21. package/dist/mcp/McpConfig.js +132 -0
  22. package/dist/mcp/McpManager.js +189 -0
  23. package/dist/repl/PersistentShell.js +20 -1
  24. package/dist/repl/ReplManager.js +410 -138
  25. package/dist/tools/AskQuestionTool.js +172 -0
  26. package/dist/tools/EditFileTool.js +141 -0
  27. package/dist/tools/FileTools.js +7 -1
  28. package/dist/tools/PlanModeTool.js +53 -0
  29. package/dist/tools/WebSearchTool.js +190 -27
  30. package/dist/ui/DiffViewer.js +110 -0
  31. package/dist/ui/InputBox.js +16 -2
  32. package/dist/ui/MultiFileSelector.js +123 -0
  33. package/dist/ui/PlanModeUI.js +105 -0
  34. package/dist/ui/ToolExecutor.js +154 -0
  35. package/dist/ui/UIManager.js +12 -2
  36. package/docs/MCP_INTEGRATION.md +290 -0
  37. package/google_dump.html +18 -0
  38. package/lite_dump.html +176 -0
  39. package/lite_headers_dump.html +176 -0
  40. package/package.json +16 -5
  41. package/scripts/test_exa_mcp.ts +90 -0
  42. package/src/checkpoint/CheckpointManager.ts +102 -0
  43. package/src/debug_google.ts +30 -0
  44. package/src/debug_lite.ts +18 -0
  45. package/src/debug_lite_headers.ts +25 -0
  46. package/src/debug_search.ts +18 -0
  47. package/src/index.ts +12 -0
  48. package/src/mcp/JsonRpcClient.ts +19 -0
  49. package/src/mcp/McpConfig.ts +153 -0
  50. package/src/mcp/McpManager.ts +224 -0
  51. package/src/repl/PersistentShell.ts +24 -1
  52. package/src/repl/ReplManager.ts +1521 -1204
  53. package/src/tools/AskQuestionTool.ts +197 -0
  54. package/src/tools/EditFileTool.ts +172 -0
  55. package/src/tools/FileTools.ts +3 -0
  56. package/src/tools/PlanModeTool.ts +50 -0
  57. package/src/tools/WebSearchTool.ts +235 -63
  58. package/src/ui/DiffViewer.ts +117 -0
  59. package/src/ui/InputBox.ts +17 -2
  60. package/src/ui/MultiFileSelector.ts +135 -0
  61. package/src/ui/PlanModeUI.ts +121 -0
  62. package/src/ui/ToolExecutor.ts +182 -0
  63. package/src/ui/UIManager.ts +15 -2
  64. package/console.log(tick) +0 -0
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DiffViewer = void 0;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const diff_1 = require("diff");
9
+ /**
10
+ * Visual diff viewer component
11
+ * Shows file changes with color coding like git diff
12
+ */
13
+ class DiffViewer {
14
+ /**
15
+ * Display a unified diff between old and new content
16
+ */
17
+ static showDiff(filePath, oldContent, newContent, contextLines = 3) {
18
+ const diff = (0, diff_1.diffLines)(oldContent, newContent);
19
+ console.log('');
20
+ console.log(chalk_1.default.gray('─'.repeat(60)));
21
+ console.log(chalk_1.default.cyan(`📝 Diff: ${filePath}`));
22
+ console.log(chalk_1.default.gray('─'.repeat(60)));
23
+ console.log('');
24
+ let unchangedCount = 0;
25
+ const unchangedBuffer = [];
26
+ const flushUnchanged = () => {
27
+ if (unchangedBuffer.length > 0) {
28
+ // Show context lines
29
+ const contextStart = Math.max(0, unchangedBuffer.length - contextLines);
30
+ for (let i = contextStart; i < unchangedBuffer.length; i++) {
31
+ console.log(chalk_1.default.dim(' ' + unchangedBuffer[i].replace(/\n/g, '')));
32
+ }
33
+ unchangedBuffer.length = 0;
34
+ unchangedCount = 0;
35
+ }
36
+ };
37
+ let hasChanges = false;
38
+ let additions = 0;
39
+ let deletions = 0;
40
+ for (const part of diff) {
41
+ const lines = part.value.split('\n');
42
+ // Remove empty last line if exists
43
+ if (lines[lines.length - 1] === '') {
44
+ lines.pop();
45
+ }
46
+ for (const line of lines) {
47
+ if (part.added) {
48
+ flushUnchanged();
49
+ console.log(chalk_1.default.green('+ ' + line));
50
+ additions++;
51
+ hasChanges = true;
52
+ }
53
+ else if (part.removed) {
54
+ flushUnchanged();
55
+ console.log(chalk_1.default.red('- ' + line));
56
+ deletions++;
57
+ hasChanges = true;
58
+ }
59
+ else {
60
+ unchangedBuffer.push(line);
61
+ unchangedCount++;
62
+ }
63
+ }
64
+ }
65
+ flushUnchanged();
66
+ console.log('');
67
+ console.log(chalk_1.default.gray('─'.repeat(60)));
68
+ if (hasChanges) {
69
+ console.log(chalk_1.default.green(`+ ${additions} additions`) + chalk_1.default.dim(' | ') + chalk_1.default.red(`- ${deletions} deletions`));
70
+ }
71
+ else {
72
+ console.log(chalk_1.default.dim('No changes'));
73
+ }
74
+ console.log(chalk_1.default.gray('─'.repeat(60)));
75
+ console.log('');
76
+ }
77
+ /**
78
+ * Display a simple edit preview (for EditFileTool)
79
+ */
80
+ static showEditPreview(filePath, oldString, newString, lineNumber) {
81
+ console.log('');
82
+ console.log(chalk_1.default.gray('─'.repeat(60)));
83
+ console.log(chalk_1.default.cyan(`📝 Edit Preview: ${filePath}`));
84
+ console.log(chalk_1.default.gray('─'.repeat(60)));
85
+ console.log(chalk_1.default.dim(`Line ${lineNumber}:`));
86
+ console.log('');
87
+ const oldLines = oldString.split('\n');
88
+ const newLines = newString.split('\n');
89
+ // Show removed lines in red
90
+ for (const line of oldLines) {
91
+ console.log(chalk_1.default.red('- ' + line));
92
+ }
93
+ // Show added lines in green
94
+ for (const line of newLines) {
95
+ console.log(chalk_1.default.green('+ ' + line));
96
+ }
97
+ console.log('');
98
+ console.log(chalk_1.default.gray('─'.repeat(60)));
99
+ console.log('');
100
+ }
101
+ /**
102
+ * Display approval prompt
103
+ */
104
+ static showApprovalPrompt(filePath, operation) {
105
+ const icon = operation === 'write' ? '📄' : '✏️';
106
+ console.log(chalk_1.default.yellow(`${icon} Approve ${operation} to ${filePath}?`));
107
+ console.log(chalk_1.default.dim(' [y] Yes [n] No [e] Edit'));
108
+ }
109
+ }
110
+ exports.DiffViewer = DiffViewer;
@@ -51,18 +51,32 @@ class InputBox {
51
51
  completer: this.completer.bind(this)
52
52
  });
53
53
  rl.prompt();
54
+ const cleanup = () => {
55
+ rl.close();
56
+ rl.removeAllListeners();
57
+ // Explicitly ensure raw mode is off to prevent terminal freeze
58
+ if (process.stdin.isTTY) {
59
+ process.stdin.setRawMode(false);
60
+ }
61
+ };
54
62
  rl.on('line', (line) => {
55
63
  // Display bottom horizontal line after input
56
64
  console.log(this.createLine());
57
- rl.close();
65
+ cleanup();
58
66
  resolve(line);
59
67
  });
60
68
  // Handle Ctrl+C
61
69
  rl.on('SIGINT', () => {
62
70
  console.log(this.createLine());
63
- rl.close();
71
+ cleanup();
64
72
  resolve('/exit');
65
73
  });
74
+ // Handle stream errors or unexpected close
75
+ rl.on('close', () => {
76
+ // Should already be cleaned up, but safe to ensure
77
+ if (process.stdin.isTTY)
78
+ process.stdin.setRawMode(false);
79
+ });
66
80
  });
67
81
  }
68
82
  /**
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MultiFileSelector = void 0;
7
+ const inquirer_1 = __importDefault(require("inquirer"));
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const fs_1 = require("fs");
10
+ /**
11
+ * Multi-file selector for read approval
12
+ * Shows interactive checklist when AI wants to read multiple files
13
+ */
14
+ class MultiFileSelector {
15
+ /**
16
+ * Show file selection UI for read operations
17
+ * Returns the list of approved files
18
+ */
19
+ static async selectFiles(filePaths, message = 'Select files to read:') {
20
+ if (filePaths.length === 0) {
21
+ return [];
22
+ }
23
+ if (filePaths.length === 1) {
24
+ // Single file - just show what's being read
25
+ console.log(chalk_1.default.dim(`📖 Reading: ${filePaths[0]}`));
26
+ return filePaths;
27
+ }
28
+ // Build file choices with metadata
29
+ const choices = filePaths.map(path => {
30
+ let metadata = '';
31
+ try {
32
+ const stats = (0, fs_1.statSync)(path);
33
+ const size = this.formatFileSize(stats.size);
34
+ metadata = chalk_1.default.dim(` (${size})`);
35
+ }
36
+ catch {
37
+ // File might not exist or be inaccessible
38
+ }
39
+ return {
40
+ name: path + metadata,
41
+ value: path,
42
+ checked: true, // Default to checked
43
+ short: path
44
+ };
45
+ });
46
+ console.log('');
47
+ console.log(chalk_1.default.cyan(`📖 AI wants to read ${filePaths.length} files:`));
48
+ console.log('');
49
+ const { selectedFiles } = await inquirer_1.default.prompt([
50
+ {
51
+ type: 'checkbox',
52
+ name: 'selectedFiles',
53
+ message: message,
54
+ choices: choices,
55
+ pageSize: 15,
56
+ validate: (answer) => {
57
+ if (answer.length === 0) {
58
+ return 'You must select at least one file, or press Ctrl+C to cancel.';
59
+ }
60
+ return true;
61
+ }
62
+ }
63
+ ]);
64
+ // Show what was selected
65
+ if (selectedFiles.length < filePaths.length) {
66
+ console.log(chalk_1.default.dim(` Reading ${selectedFiles.length} of ${filePaths.length} files`));
67
+ }
68
+ return selectedFiles;
69
+ }
70
+ /**
71
+ * Show a simple confirmation for single file reads (optional)
72
+ */
73
+ static async confirmRead(filePath, preview) {
74
+ let message = chalk_1.default.cyan(`📖 Read file: ${filePath}?`);
75
+ if (preview) {
76
+ const lines = preview.split('\n');
77
+ const previewLines = lines.slice(0, 5);
78
+ console.log('');
79
+ console.log(chalk_1.default.gray('─'.repeat(60)));
80
+ console.log(message);
81
+ console.log(chalk_1.default.gray('─'.repeat(60)));
82
+ console.log(chalk_1.default.dim('Preview:'));
83
+ for (const line of previewLines) {
84
+ console.log(chalk_1.default.dim(' ' + line));
85
+ }
86
+ if (lines.length > 5) {
87
+ console.log(chalk_1.default.dim(' ...'));
88
+ }
89
+ console.log(chalk_1.default.gray('─'.repeat(60)));
90
+ }
91
+ else {
92
+ console.log(message);
93
+ }
94
+ const { confirmed } = await inquirer_1.default.prompt([
95
+ {
96
+ type: 'confirm',
97
+ name: 'confirmed',
98
+ message: 'Continue?',
99
+ default: true
100
+ }
101
+ ]);
102
+ return confirmed;
103
+ }
104
+ /**
105
+ * Format file size in human-readable format
106
+ */
107
+ static formatFileSize(bytes) {
108
+ if (bytes === 0)
109
+ return '0 B';
110
+ const k = 1024;
111
+ const sizes = ['B', 'KB', 'MB', 'GB'];
112
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
113
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
114
+ }
115
+ /**
116
+ * Show progress when reading multiple files
117
+ */
118
+ static showReadProgress(current, total, filePath) {
119
+ const progress = chalk_1.default.dim(`[${current}/${total}]`);
120
+ console.log(chalk_1.default.dim(` ${progress} Reading: ${filePath}`));
121
+ }
122
+ }
123
+ exports.MultiFileSelector = MultiFileSelector;
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PlanModeUI = void 0;
7
+ const inquirer_1 = __importDefault(require("inquirer"));
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ /**
10
+ * Plan Mode UI - Shows Q&A history and handles plan → build transition
11
+ */
12
+ class PlanModeUI {
13
+ /**
14
+ * Record a Q&A entry
15
+ */
16
+ static recordQA(question, answer) {
17
+ this.qaHistory.push({
18
+ question,
19
+ answer,
20
+ timestamp: new Date()
21
+ });
22
+ }
23
+ /**
24
+ * Show the current Q&A history
25
+ */
26
+ static showQAHistory() {
27
+ if (this.qaHistory.length === 0) {
28
+ console.log(chalk_1.default.dim(' No questions asked yet.'));
29
+ return;
30
+ }
31
+ console.log('');
32
+ console.log(chalk_1.default.cyan('📋 Requirements gathered:'));
33
+ console.log(chalk_1.default.gray('─'.repeat(60)));
34
+ for (let i = 0; i < this.qaHistory.length; i++) {
35
+ const entry = this.qaHistory[i];
36
+ console.log(chalk_1.default.bold(`${i + 1}. ${entry.question}`));
37
+ console.log(chalk_1.default.dim(` Answer: ${entry.answer}`));
38
+ console.log('');
39
+ }
40
+ console.log(chalk_1.default.gray('─'.repeat(60)));
41
+ }
42
+ /**
43
+ * Ask if ready to switch to build mode
44
+ */
45
+ static async askReadyToBuild() {
46
+ console.log('');
47
+ const { ready } = await inquirer_1.default.prompt([
48
+ {
49
+ type: 'confirm',
50
+ name: 'ready',
51
+ message: chalk_1.default.cyan('🚀 Ready to switch to BUILD mode and implement?'),
52
+ default: true
53
+ }
54
+ ]);
55
+ return ready;
56
+ }
57
+ /**
58
+ * Show plan mode header/summary
59
+ */
60
+ static showPlanHeader() {
61
+ console.log('');
62
+ console.log(chalk_1.default.cyan.bold('🎯 PLAN MODE'));
63
+ console.log(chalk_1.default.dim(' Gathering requirements and planning the solution...'));
64
+ console.log(chalk_1.default.dim(' Type your requirements, answer questions, then switch to /build to implement.'));
65
+ console.log('');
66
+ }
67
+ /**
68
+ * Show suggestion to switch to build mode
69
+ */
70
+ static suggestBuildMode() {
71
+ console.log('');
72
+ console.log(chalk_1.default.yellow('💡 Tip: Type ') + chalk_1.default.bold('/build') + chalk_1.default.yellow(' to start implementing when ready.'));
73
+ }
74
+ /**
75
+ * Clear Q&A history (e.g., when starting a new session)
76
+ */
77
+ static clearHistory() {
78
+ this.qaHistory = [];
79
+ }
80
+ /**
81
+ * Get Q&A history
82
+ */
83
+ static getHistory() {
84
+ return [...this.qaHistory];
85
+ }
86
+ /**
87
+ * Show a summary of the plan
88
+ */
89
+ static showPlanSummary() {
90
+ if (this.qaHistory.length === 0) {
91
+ return;
92
+ }
93
+ console.log('');
94
+ console.log(chalk_1.default.cyan('📝 Plan Summary:'));
95
+ console.log(chalk_1.default.gray('─'.repeat(60)));
96
+ console.log(chalk_1.default.dim(`Questions answered: ${this.qaHistory.length}`));
97
+ // Show key answers as bullet points
98
+ for (const entry of this.qaHistory) {
99
+ console.log(chalk_1.default.dim(` • ${entry.question}: ${entry.answer}`));
100
+ }
101
+ console.log(chalk_1.default.gray('─'.repeat(60)));
102
+ }
103
+ }
104
+ exports.PlanModeUI = PlanModeUI;
105
+ PlanModeUI.qaHistory = [];
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ToolExecutor = void 0;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const ora_1 = __importDefault(require("ora"));
9
+ /**
10
+ * Visual feedback for tool execution
11
+ * Shows colored icons, spinners, and grouped display
12
+ */
13
+ class ToolExecutor {
14
+ /**
15
+ * Get colored text for a tool name
16
+ */
17
+ static colorToolName(toolName, color) {
18
+ switch (color) {
19
+ case 'blue': return chalk_1.default.blue(toolName);
20
+ case 'yellow': return chalk_1.default.yellow(toolName);
21
+ case 'cyan': return chalk_1.default.cyan(toolName);
22
+ case 'magenta': return chalk_1.default.magenta(toolName);
23
+ case 'green': return chalk_1.default.green(toolName);
24
+ case 'red': return chalk_1.default.red(toolName);
25
+ case 'gray': return chalk_1.default.gray(toolName);
26
+ default: return toolName;
27
+ }
28
+ }
29
+ /**
30
+ * Start a tool execution with visual feedback
31
+ */
32
+ static startExecution(toolName, args) {
33
+ const execution = {
34
+ toolName,
35
+ args,
36
+ status: 'running'
37
+ };
38
+ this.executions.push(execution);
39
+ // Get icon and color for tool type
40
+ const { icon, color } = this.getToolStyle(toolName);
41
+ // Format args for display (truncate long values)
42
+ const argsDisplay = this.formatArgs(args);
43
+ // Start spinner
44
+ const spinner = (0, ora_1.default)({
45
+ text: `${icon} ${this.colorToolName(toolName, color)} ${argsDisplay}`,
46
+ color: color
47
+ });
48
+ spinner.start();
49
+ this.spinners.set(toolName, spinner);
50
+ }
51
+ /**
52
+ * Complete a tool execution successfully
53
+ */
54
+ static completeExecution(toolName, result) {
55
+ const execution = this.executions.find(e => e.toolName === toolName);
56
+ if (execution) {
57
+ execution.status = 'completed';
58
+ execution.result = result;
59
+ }
60
+ const spinner = this.spinners.get(toolName);
61
+ if (spinner) {
62
+ const { icon } = this.getToolStyle(toolName);
63
+ spinner.succeed(`${icon} ${chalk_1.default.green(toolName)} completed`);
64
+ this.spinners.delete(toolName);
65
+ }
66
+ }
67
+ /**
68
+ * Mark a tool execution as failed
69
+ */
70
+ static failExecution(toolName, error) {
71
+ const execution = this.executions.find(e => e.toolName === toolName);
72
+ if (execution) {
73
+ execution.status = 'failed';
74
+ execution.error = error;
75
+ }
76
+ const spinner = this.spinners.get(toolName);
77
+ if (spinner) {
78
+ const { icon } = this.getToolStyle(toolName);
79
+ spinner.fail(`${icon} ${chalk_1.default.red(toolName)} failed: ${error}`);
80
+ this.spinners.delete(toolName);
81
+ }
82
+ }
83
+ /**
84
+ * Show grouped summary of all tool executions
85
+ */
86
+ static showSummary() {
87
+ if (this.executions.length === 0) {
88
+ return;
89
+ }
90
+ console.log('');
91
+ console.log(chalk_1.default.gray('─'.repeat(60)));
92
+ console.log(chalk_1.default.cyan('🔧 Tool Executions'));
93
+ console.log(chalk_1.default.gray('─'.repeat(60)));
94
+ for (const execution of this.executions) {
95
+ const { icon, color } = this.getToolStyle(execution.toolName);
96
+ const statusIcon = execution.status === 'completed' ? '✓' : execution.status === 'failed' ? '✗' : '…';
97
+ console.log(`${icon} ${this.colorToolName(execution.toolName, color)} ${chalk_1.default.dim(statusIcon)}`);
98
+ }
99
+ console.log(chalk_1.default.gray('─'.repeat(60)));
100
+ console.log('');
101
+ // Reset for next batch
102
+ this.executions = [];
103
+ }
104
+ /**
105
+ * Get visual style for a tool type
106
+ */
107
+ static getToolStyle(toolName) {
108
+ const styles = {
109
+ 'read_file': { icon: '📖', color: 'blue' },
110
+ 'write_file': { icon: '📄', color: 'yellow' },
111
+ 'edit_file': { icon: '✏️', color: 'yellow' },
112
+ 'list_dir': { icon: '📁', color: 'cyan' },
113
+ 'search_files': { icon: '🔍', color: 'magenta' },
114
+ 'search_web': { icon: '🌐', color: 'blue' },
115
+ 'run_command': { icon: '💻', color: 'green' },
116
+ 'git_commit': { icon: '📝', color: 'green' }
117
+ };
118
+ return styles[toolName] || { icon: '🔧', color: 'gray' };
119
+ }
120
+ /**
121
+ * Format arguments for display
122
+ */
123
+ static formatArgs(args) {
124
+ const parts = [];
125
+ for (const [key, value] of Object.entries(args)) {
126
+ const strValue = String(value);
127
+ // Truncate long values
128
+ const display = strValue.length > 30 ? strValue.slice(0, 30) + '...' : strValue;
129
+ parts.push(`${key}=${chalk_1.default.dim(display)}`);
130
+ }
131
+ return parts.length > 0 ? chalk_1.default.dim(`(${parts.join(', ')})`) : '';
132
+ }
133
+ /**
134
+ * Show a simple inline tool usage message
135
+ */
136
+ static showInline(toolName, args) {
137
+ const { icon, color } = this.getToolStyle(toolName);
138
+ const argsDisplay = this.formatArgs(args);
139
+ console.log(chalk_1.default.dim(` ${icon} ${this.colorToolName(toolName, color)} ${argsDisplay}`));
140
+ }
141
+ /**
142
+ * Clear all pending executions
143
+ */
144
+ static clear() {
145
+ for (const spinner of this.spinners.values()) {
146
+ spinner.stop();
147
+ }
148
+ this.spinners.clear();
149
+ this.executions = [];
150
+ }
151
+ }
152
+ exports.ToolExecutor = ToolExecutor;
153
+ ToolExecutor.executions = [];
154
+ ToolExecutor.spinners = new Map();
@@ -19,12 +19,12 @@ class UIManager {
19
19
  whitespaceBreak: true,
20
20
  });
21
21
  console.log(gradient_string_1.default.pastel.multiline(logoText));
22
- console.log(chalk_1.default.gray(' v1.1.3 - AI Coding Agent'));
22
+ console.log(chalk_1.default.gray(' v1.1.6 - AI Coding Agent'));
23
23
  console.log('');
24
24
  }
25
25
  static renderDashboard(config) {
26
26
  const { model, cwd } = config;
27
- const version = 'v1.1.3';
27
+ const version = 'v1.1.6';
28
28
  // Layout: Left (Status/Welcome) | Right (Tips/Activity)
29
29
  // Total width ~80 chars.
30
30
  // Left ~45, Right ~30.
@@ -74,5 +74,15 @@ class UIManager {
74
74
  static printSeparator() {
75
75
  console.log(chalk_1.default.gray('──────────────────────────────────────────────────'));
76
76
  }
77
+ static logBullet(text, color = 'white') {
78
+ const bullet = color === 'white' ? '●' : chalk_1.default[color]('●');
79
+ console.log(` ${bullet} ${text}`);
80
+ }
81
+ static logSystem(text) {
82
+ console.log(chalk_1.default.dim(` ${text}`));
83
+ }
84
+ static logTransition(text) {
85
+ console.log(` ${chalk_1.default.red('+')} ${chalk_1.default.red(text)}`);
86
+ }
77
87
  }
78
88
  exports.UIManager = UIManager;