@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,189 @@
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.McpManager = void 0;
7
+ const McpClient_1 = require("./McpClient");
8
+ const McpConfig_1 = require("./McpConfig");
9
+ const ora_1 = __importDefault(require("ora"));
10
+ const chalk_1 = __importDefault(require("chalk"));
11
+ class McpManager {
12
+ constructor() {
13
+ this.connections = new Map();
14
+ this.configManager = new McpConfig_1.McpConfigManager();
15
+ }
16
+ getConfig() {
17
+ return this.configManager;
18
+ }
19
+ async connectToServer(serverName) {
20
+ const config = this.configManager.getServer(serverName);
21
+ if (!config) {
22
+ console.error(chalk_1.default.red(`MCP server "${serverName}" not found in configuration`));
23
+ return null;
24
+ }
25
+ // Check if already connected
26
+ if (this.connections.has(serverName)) {
27
+ console.log(chalk_1.default.yellow(`Already connected to ${serverName}`));
28
+ return this.connections.get(serverName);
29
+ }
30
+ const spinner = (0, ora_1.default)(`Connecting to MCP server: ${serverName}...`).start();
31
+ try {
32
+ // Set environment variables if specified
33
+ if (config.env) {
34
+ for (const [key, value] of Object.entries(config.env)) {
35
+ if (value) {
36
+ process.env[key] = value;
37
+ }
38
+ else if (!process.env[key]) {
39
+ spinner.warn(chalk_1.default.yellow(`Environment variable ${key} is required for ${serverName}`));
40
+ console.log(chalk_1.default.dim(`Set it with: export ${key}=your_key`));
41
+ console.log(chalk_1.default.dim(`Or add it to your MCP configuration`));
42
+ }
43
+ }
44
+ }
45
+ const client = new McpClient_1.McpClient(config.command, config.args);
46
+ await client.initialize();
47
+ const tools = await client.listTools();
48
+ const connection = {
49
+ client,
50
+ config,
51
+ tools,
52
+ connectedAt: new Date()
53
+ };
54
+ this.connections.set(serverName, connection);
55
+ spinner.succeed(chalk_1.default.green(`Connected to ${client.serverName}!`));
56
+ if (tools.length > 0) {
57
+ console.log(chalk_1.default.green(`Added ${tools.length} tools:`));
58
+ tools.forEach(t => {
59
+ const description = t.description.length > 60
60
+ ? t.description.substring(0, 60) + '...'
61
+ : t.description;
62
+ console.log(chalk_1.default.dim(` - ${chalk_1.default.cyan(t.name)}: ${description}`));
63
+ });
64
+ }
65
+ else {
66
+ console.log(chalk_1.default.yellow('No tools available from this server'));
67
+ }
68
+ return connection;
69
+ }
70
+ catch (error) {
71
+ spinner.fail(chalk_1.default.red(`Failed to connect to ${serverName}: ${error.message}`));
72
+ return null;
73
+ }
74
+ }
75
+ async disconnectFromServer(serverName) {
76
+ const connection = this.connections.get(serverName);
77
+ if (!connection) {
78
+ console.log(chalk_1.default.yellow(`Not connected to ${serverName}`));
79
+ return false;
80
+ }
81
+ try {
82
+ connection.client.disconnect();
83
+ this.connections.delete(serverName);
84
+ console.log(chalk_1.default.green(`Disconnected from ${serverName}`));
85
+ return true;
86
+ }
87
+ catch (error) {
88
+ console.error(chalk_1.default.red(`Error disconnecting from ${serverName}: ${error.message}`));
89
+ return false;
90
+ }
91
+ }
92
+ disconnectAll() {
93
+ const serverNames = Array.from(this.connections.keys());
94
+ for (const name of serverNames) {
95
+ this.disconnectFromServer(name);
96
+ }
97
+ }
98
+ getConnections() {
99
+ return Array.from(this.connections.values());
100
+ }
101
+ getConnection(name) {
102
+ return this.connections.get(name);
103
+ }
104
+ getAllTools() {
105
+ const allTools = [];
106
+ for (const connection of this.connections.values()) {
107
+ allTools.push(...connection.tools);
108
+ }
109
+ return allTools;
110
+ }
111
+ getServerNames() {
112
+ return Array.from(this.connections.keys());
113
+ }
114
+ getAvailableServers() {
115
+ return this.configManager.getConfig().servers;
116
+ }
117
+ async autoConnect() {
118
+ const autoConnectServers = this.configManager.getAutoConnectServers();
119
+ if (autoConnectServers.length === 0) {
120
+ return;
121
+ }
122
+ console.log(chalk_1.default.blue(`\nAuto-connecting to ${autoConnectServers.length} MCP servers...`));
123
+ for (const config of autoConnectServers) {
124
+ await this.connectToServer(config.name);
125
+ }
126
+ }
127
+ async listServers() {
128
+ const availableServers = this.configManager.getConfig().servers;
129
+ const connectedServers = this.getServerNames();
130
+ if (availableServers.length === 0) {
131
+ console.log(chalk_1.default.yellow('No MCP servers configured.'));
132
+ return;
133
+ }
134
+ console.log(chalk_1.default.cyan('\nMCP Servers:\n'));
135
+ for (const server of availableServers) {
136
+ const isConnected = connectedServers.includes(server.name);
137
+ const status = isConnected ? chalk_1.default.green('● Connected') : chalk_1.default.gray('○ Disconnected');
138
+ const auto = server.autoConnect ? chalk_1.default.dim('[auto]') : '';
139
+ console.log(`${status} ${chalk_1.default.bold(server.name)} ${auto}`);
140
+ if (server.description) {
141
+ console.log(chalk_1.default.dim(` ${server.description}`));
142
+ }
143
+ if (isConnected) {
144
+ const connection = this.getConnection(server.name);
145
+ if (connection && connection.tools.length > 0) {
146
+ console.log(chalk_1.default.dim(` Tools: ${connection.tools.map(t => t.name).join(', ')}`));
147
+ }
148
+ }
149
+ console.log('');
150
+ }
151
+ }
152
+ async addServer(name, command, args, description) {
153
+ const serverConfig = {
154
+ name,
155
+ command,
156
+ args,
157
+ description,
158
+ autoConnect: false
159
+ };
160
+ this.configManager.addServer(serverConfig);
161
+ console.log(chalk_1.default.green(`Added MCP server "${name}" to configuration`));
162
+ }
163
+ async removeServer(name) {
164
+ // Disconnect if connected
165
+ if (this.connections.has(name)) {
166
+ await this.disconnectFromServer(name);
167
+ }
168
+ this.configManager.removeServer(name);
169
+ console.log(chalk_1.default.green(`Removed MCP server "${name}" from configuration`));
170
+ }
171
+ async testConnection(serverName) {
172
+ const connection = this.getConnection(serverName);
173
+ if (!connection) {
174
+ console.log(chalk_1.default.red(`Not connected to ${serverName}`));
175
+ return false;
176
+ }
177
+ try {
178
+ // Try to list tools as a test
179
+ await connection.client.listTools();
180
+ console.log(chalk_1.default.green(`${serverName} connection is healthy`));
181
+ return true;
182
+ }
183
+ catch (error) {
184
+ console.log(chalk_1.default.red(`${serverName} connection test failed: ${error.message}`));
185
+ return false;
186
+ }
187
+ }
188
+ }
189
+ exports.McpManager = McpManager;
@@ -13,6 +13,7 @@ class PersistentShell {
13
13
  this.delimiter = 'MENTIS_SHELL_DELIMITER';
14
14
  this.resolveCallback = null;
15
15
  this.rejectCallback = null;
16
+ this.COMMAND_TIMEOUT = 120000; // 2 minutes timeout for shell commands
16
17
  // Lazy init: Do not spawn here.
17
18
  }
18
19
  initialize() {
@@ -60,7 +61,25 @@ class PersistentShell {
60
61
  this.resolveCallback = resolve;
61
62
  this.rejectCallback = reject;
62
63
  this.buffer = '';
63
- const cleanCommand = command.replace(/\n/g, '; ');
64
+ // Set timeout to prevent indefinite hangs
65
+ const timeout = setTimeout(() => {
66
+ this.resolveCallback = null;
67
+ this.rejectCallback = null;
68
+ reject(new Error(`Shell command timeout after ${this.COMMAND_TIMEOUT}ms`));
69
+ }, this.COMMAND_TIMEOUT);
70
+ // Store timeout for cleanup
71
+ const originalResolve = resolve;
72
+ const wrappedResolve = (output) => {
73
+ clearTimeout(timeout);
74
+ originalResolve(output);
75
+ };
76
+ this.resolveCallback = wrappedResolve;
77
+ let cleanCommand = command.replace(/\n/g, '; ');
78
+ // Fix: PowerShell alias 'curl' -> 'Invoke-WebRequest' causes issues for linux-style curl commands.
79
+ // Force usage of 'curl.exe' if on Windows.
80
+ if (os_1.default.platform() === 'win32') {
81
+ cleanCommand = cleanCommand.replace(/(^|[\s|;&])curl(\s|$)/g, '$1curl.exe$2');
82
+ }
64
83
  const fullCommand = `${cleanCommand}; echo "${this.delimiter}"\n`;
65
84
  this.process?.stdin.write(fullCommand);
66
85
  });