@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.
- package/.claude/settings.local.json +8 -0
- package/.mentis/session.json +15 -0
- package/.mentis/sessions/1769189035730.json +23 -0
- package/.mentis/sessions/1769189569160.json +23 -0
- package/.mentis/sessions/1769767538672.json +23 -0
- package/.mentis/sessions/1769767785155.json +23 -0
- package/.mentis/sessions/1769768745802.json +23 -0
- package/.mentis/sessions/1769769600884.json +31 -0
- package/.mentis/sessions/1769770030160.json +31 -0
- package/.mentis/sessions/1769770606004.json +78 -0
- package/.mentis/sessions/1769771084515.json +141 -0
- package/.mentis/sessions/1769881926630.json +57 -0
- package/README.md +17 -0
- package/dist/checkpoint/CheckpointManager.js +92 -0
- package/dist/debug_google.js +61 -0
- package/dist/debug_lite.js +49 -0
- package/dist/debug_lite_headers.js +57 -0
- package/dist/debug_search.js +16 -0
- package/dist/index.js +10 -0
- package/dist/mcp/JsonRpcClient.js +16 -0
- package/dist/mcp/McpConfig.js +132 -0
- package/dist/mcp/McpManager.js +189 -0
- package/dist/repl/PersistentShell.js +20 -1
- package/dist/repl/ReplManager.js +410 -138
- package/dist/tools/AskQuestionTool.js +172 -0
- package/dist/tools/EditFileTool.js +141 -0
- package/dist/tools/FileTools.js +7 -1
- package/dist/tools/PlanModeTool.js +53 -0
- package/dist/tools/WebSearchTool.js +190 -27
- package/dist/ui/DiffViewer.js +110 -0
- package/dist/ui/InputBox.js +16 -2
- package/dist/ui/MultiFileSelector.js +123 -0
- package/dist/ui/PlanModeUI.js +105 -0
- package/dist/ui/ToolExecutor.js +154 -0
- package/dist/ui/UIManager.js +12 -2
- package/docs/MCP_INTEGRATION.md +290 -0
- package/google_dump.html +18 -0
- package/lite_dump.html +176 -0
- package/lite_headers_dump.html +176 -0
- package/package.json +16 -5
- package/scripts/test_exa_mcp.ts +90 -0
- package/src/checkpoint/CheckpointManager.ts +102 -0
- package/src/debug_google.ts +30 -0
- package/src/debug_lite.ts +18 -0
- package/src/debug_lite_headers.ts +25 -0
- package/src/debug_search.ts +18 -0
- package/src/index.ts +12 -0
- package/src/mcp/JsonRpcClient.ts +19 -0
- package/src/mcp/McpConfig.ts +153 -0
- package/src/mcp/McpManager.ts +224 -0
- package/src/repl/PersistentShell.ts +24 -1
- package/src/repl/ReplManager.ts +1521 -1204
- package/src/tools/AskQuestionTool.ts +197 -0
- package/src/tools/EditFileTool.ts +172 -0
- package/src/tools/FileTools.ts +3 -0
- package/src/tools/PlanModeTool.ts +50 -0
- package/src/tools/WebSearchTool.ts +235 -63
- package/src/ui/DiffViewer.ts +117 -0
- package/src/ui/InputBox.ts +17 -2
- package/src/ui/MultiFileSelector.ts +135 -0
- package/src/ui/PlanModeUI.ts +121 -0
- package/src/ui/ToolExecutor.ts +182 -0
- package/src/ui/UIManager.ts +15 -2
- package/console.log(tick) +0 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import inquirer from 'inquirer';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
|
|
4
|
+
export interface QAEntry {
|
|
5
|
+
question: string;
|
|
6
|
+
answer: string;
|
|
7
|
+
timestamp: Date;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Plan Mode UI - Shows Q&A history and handles plan → build transition
|
|
12
|
+
*/
|
|
13
|
+
export class PlanModeUI {
|
|
14
|
+
private static qaHistory: QAEntry[] = [];
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Record a Q&A entry
|
|
18
|
+
*/
|
|
19
|
+
static recordQA(question: string, answer: string): void {
|
|
20
|
+
this.qaHistory.push({
|
|
21
|
+
question,
|
|
22
|
+
answer,
|
|
23
|
+
timestamp: new Date()
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Show the current Q&A history
|
|
29
|
+
*/
|
|
30
|
+
static showQAHistory(): void {
|
|
31
|
+
if (this.qaHistory.length === 0) {
|
|
32
|
+
console.log(chalk.dim(' No questions asked yet.'));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
console.log('');
|
|
37
|
+
console.log(chalk.cyan('📋 Requirements gathered:'));
|
|
38
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
39
|
+
|
|
40
|
+
for (let i = 0; i < this.qaHistory.length; i++) {
|
|
41
|
+
const entry = this.qaHistory[i];
|
|
42
|
+
console.log(chalk.bold(`${i + 1}. ${entry.question}`));
|
|
43
|
+
console.log(chalk.dim(` Answer: ${entry.answer}`));
|
|
44
|
+
console.log('');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Ask if ready to switch to build mode
|
|
52
|
+
*/
|
|
53
|
+
static async askReadyToBuild(): Promise<boolean> {
|
|
54
|
+
console.log('');
|
|
55
|
+
|
|
56
|
+
const { ready } = await inquirer.prompt([
|
|
57
|
+
{
|
|
58
|
+
type: 'confirm',
|
|
59
|
+
name: 'ready',
|
|
60
|
+
message: chalk.cyan('🚀 Ready to switch to BUILD mode and implement?'),
|
|
61
|
+
default: true
|
|
62
|
+
}
|
|
63
|
+
]);
|
|
64
|
+
|
|
65
|
+
return ready;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Show plan mode header/summary
|
|
70
|
+
*/
|
|
71
|
+
static showPlanHeader(): void {
|
|
72
|
+
console.log('');
|
|
73
|
+
console.log(chalk.cyan.bold('🎯 PLAN MODE'));
|
|
74
|
+
console.log(chalk.dim(' Gathering requirements and planning the solution...'));
|
|
75
|
+
console.log(chalk.dim(' Type your requirements, answer questions, then switch to /build to implement.'));
|
|
76
|
+
console.log('');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Show suggestion to switch to build mode
|
|
81
|
+
*/
|
|
82
|
+
static suggestBuildMode(): void {
|
|
83
|
+
console.log('');
|
|
84
|
+
console.log(chalk.yellow('💡 Tip: Type ') + chalk.bold('/build') + chalk.yellow(' to start implementing when ready.'));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Clear Q&A history (e.g., when starting a new session)
|
|
89
|
+
*/
|
|
90
|
+
static clearHistory(): void {
|
|
91
|
+
this.qaHistory = [];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Get Q&A history
|
|
96
|
+
*/
|
|
97
|
+
static getHistory(): QAEntry[] {
|
|
98
|
+
return [...this.qaHistory];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Show a summary of the plan
|
|
103
|
+
*/
|
|
104
|
+
static showPlanSummary(): void {
|
|
105
|
+
if (this.qaHistory.length === 0) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
console.log('');
|
|
110
|
+
console.log(chalk.cyan('📝 Plan Summary:'));
|
|
111
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
112
|
+
console.log(chalk.dim(`Questions answered: ${this.qaHistory.length}`));
|
|
113
|
+
|
|
114
|
+
// Show key answers as bullet points
|
|
115
|
+
for (const entry of this.qaHistory) {
|
|
116
|
+
console.log(chalk.dim(` • ${entry.question}: ${entry.answer}`));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora, { Ora } from 'ora';
|
|
3
|
+
|
|
4
|
+
export interface ToolExecution {
|
|
5
|
+
toolName: string;
|
|
6
|
+
args: Record<string, any>;
|
|
7
|
+
status: 'running' | 'completed' | 'failed';
|
|
8
|
+
result?: string;
|
|
9
|
+
error?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Visual feedback for tool execution
|
|
14
|
+
* Shows colored icons, spinners, and grouped display
|
|
15
|
+
*/
|
|
16
|
+
export class ToolExecutor {
|
|
17
|
+
private static executions: ToolExecution[] = [];
|
|
18
|
+
private static spinners: Map<string, Ora> = new Map();
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Get colored text for a tool name
|
|
22
|
+
*/
|
|
23
|
+
private static colorToolName(toolName: string, color: string): string {
|
|
24
|
+
switch (color) {
|
|
25
|
+
case 'blue': return chalk.blue(toolName);
|
|
26
|
+
case 'yellow': return chalk.yellow(toolName);
|
|
27
|
+
case 'cyan': return chalk.cyan(toolName);
|
|
28
|
+
case 'magenta': return chalk.magenta(toolName);
|
|
29
|
+
case 'green': return chalk.green(toolName);
|
|
30
|
+
case 'red': return chalk.red(toolName);
|
|
31
|
+
case 'gray': return chalk.gray(toolName);
|
|
32
|
+
default: return toolName;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Start a tool execution with visual feedback
|
|
38
|
+
*/
|
|
39
|
+
static startExecution(toolName: string, args: Record<string, any>): void {
|
|
40
|
+
const execution: ToolExecution = {
|
|
41
|
+
toolName,
|
|
42
|
+
args,
|
|
43
|
+
status: 'running'
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
this.executions.push(execution);
|
|
47
|
+
|
|
48
|
+
// Get icon and color for tool type
|
|
49
|
+
const { icon, color } = this.getToolStyle(toolName);
|
|
50
|
+
|
|
51
|
+
// Format args for display (truncate long values)
|
|
52
|
+
const argsDisplay = this.formatArgs(args);
|
|
53
|
+
|
|
54
|
+
// Start spinner
|
|
55
|
+
const spinner = ora({
|
|
56
|
+
text: `${icon} ${this.colorToolName(toolName, color)} ${argsDisplay}`,
|
|
57
|
+
color: color as 'cyan' | 'yellow' | 'red' | 'green' | 'blue' | 'magenta' | 'white' | 'gray'
|
|
58
|
+
});
|
|
59
|
+
spinner.start();
|
|
60
|
+
|
|
61
|
+
this.spinners.set(toolName, spinner);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Complete a tool execution successfully
|
|
66
|
+
*/
|
|
67
|
+
static completeExecution(toolName: string, result: string): void {
|
|
68
|
+
const execution = this.executions.find(e => e.toolName === toolName);
|
|
69
|
+
if (execution) {
|
|
70
|
+
execution.status = 'completed';
|
|
71
|
+
execution.result = result;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const spinner = this.spinners.get(toolName);
|
|
75
|
+
if (spinner) {
|
|
76
|
+
const { icon } = this.getToolStyle(toolName);
|
|
77
|
+
spinner.succeed(`${icon} ${chalk.green(toolName)} completed`);
|
|
78
|
+
this.spinners.delete(toolName);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Mark a tool execution as failed
|
|
84
|
+
*/
|
|
85
|
+
static failExecution(toolName: string, error: string): void {
|
|
86
|
+
const execution = this.executions.find(e => e.toolName === toolName);
|
|
87
|
+
if (execution) {
|
|
88
|
+
execution.status = 'failed';
|
|
89
|
+
execution.error = error;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const spinner = this.spinners.get(toolName);
|
|
93
|
+
if (spinner) {
|
|
94
|
+
const { icon } = this.getToolStyle(toolName);
|
|
95
|
+
spinner.fail(`${icon} ${chalk.red(toolName)} failed: ${error}`);
|
|
96
|
+
this.spinners.delete(toolName);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Show grouped summary of all tool executions
|
|
102
|
+
*/
|
|
103
|
+
static showSummary(): void {
|
|
104
|
+
if (this.executions.length === 0) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
console.log('');
|
|
109
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
110
|
+
console.log(chalk.cyan('🔧 Tool Executions'));
|
|
111
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
112
|
+
|
|
113
|
+
for (const execution of this.executions) {
|
|
114
|
+
const { icon, color } = this.getToolStyle(execution.toolName);
|
|
115
|
+
const statusIcon = execution.status === 'completed' ? '✓' : execution.status === 'failed' ? '✗' : '…';
|
|
116
|
+
|
|
117
|
+
console.log(
|
|
118
|
+
`${icon} ${this.colorToolName(execution.toolName, color)} ${chalk.dim(statusIcon)}`
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
123
|
+
console.log('');
|
|
124
|
+
|
|
125
|
+
// Reset for next batch
|
|
126
|
+
this.executions = [];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Get visual style for a tool type
|
|
131
|
+
*/
|
|
132
|
+
private static getToolStyle(toolName: string): { icon: string; color: string } {
|
|
133
|
+
const styles: Record<string, { icon: string; color: string }> = {
|
|
134
|
+
'read_file': { icon: '📖', color: 'blue' },
|
|
135
|
+
'write_file': { icon: '📄', color: 'yellow' },
|
|
136
|
+
'edit_file': { icon: '✏️', color: 'yellow' },
|
|
137
|
+
'list_dir': { icon: '📁', color: 'cyan' },
|
|
138
|
+
'search_files': { icon: '🔍', color: 'magenta' },
|
|
139
|
+
'search_web': { icon: '🌐', color: 'blue' },
|
|
140
|
+
'run_command': { icon: '💻', color: 'green' },
|
|
141
|
+
'git_commit': { icon: '📝', color: 'green' }
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
return styles[toolName] || { icon: '🔧', color: 'gray' };
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Format arguments for display
|
|
149
|
+
*/
|
|
150
|
+
private static formatArgs(args: Record<string, any>): string {
|
|
151
|
+
const parts: string[] = [];
|
|
152
|
+
|
|
153
|
+
for (const [key, value] of Object.entries(args)) {
|
|
154
|
+
const strValue = String(value);
|
|
155
|
+
// Truncate long values
|
|
156
|
+
const display = strValue.length > 30 ? strValue.slice(0, 30) + '...' : strValue;
|
|
157
|
+
parts.push(`${key}=${chalk.dim(display)}`);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return parts.length > 0 ? chalk.dim(`(${parts.join(', ')})`) : '';
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Show a simple inline tool usage message
|
|
165
|
+
*/
|
|
166
|
+
static showInline(toolName: string, args: Record<string, any>): void {
|
|
167
|
+
const { icon, color } = this.getToolStyle(toolName);
|
|
168
|
+
const argsDisplay = this.formatArgs(args);
|
|
169
|
+
console.log(chalk.dim(` ${icon} ${this.colorToolName(toolName, color)} ${argsDisplay}`));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Clear all pending executions
|
|
174
|
+
*/
|
|
175
|
+
static clear(): void {
|
|
176
|
+
for (const spinner of this.spinners.values()) {
|
|
177
|
+
spinner.stop();
|
|
178
|
+
}
|
|
179
|
+
this.spinners.clear();
|
|
180
|
+
this.executions = [];
|
|
181
|
+
}
|
|
182
|
+
}
|
package/src/ui/UIManager.ts
CHANGED
|
@@ -14,13 +14,13 @@ export class UIManager {
|
|
|
14
14
|
whitespaceBreak: true,
|
|
15
15
|
});
|
|
16
16
|
console.log(gradient.pastel.multiline(logoText));
|
|
17
|
-
console.log(chalk.gray(' v1.1.
|
|
17
|
+
console.log(chalk.gray(' v1.1.6 - AI Coding Agent'));
|
|
18
18
|
console.log('');
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
public static renderDashboard(config: { model: string, mode: string, cwd: string }) {
|
|
22
22
|
const { model, cwd } = config;
|
|
23
|
-
const version = 'v1.1.
|
|
23
|
+
const version = 'v1.1.6';
|
|
24
24
|
|
|
25
25
|
// Layout: Left (Status/Welcome) | Right (Tips/Activity)
|
|
26
26
|
// Total width ~80 chars.
|
|
@@ -84,4 +84,17 @@ export class UIManager {
|
|
|
84
84
|
public static printSeparator() {
|
|
85
85
|
console.log(chalk.gray('──────────────────────────────────────────────────'));
|
|
86
86
|
}
|
|
87
|
+
|
|
88
|
+
public static logBullet(text: string, color: 'cyan' | 'green' | 'yellow' | 'red' | 'blue' | 'magenta' | 'white' = 'white') {
|
|
89
|
+
const bullet = color === 'white' ? '●' : chalk[color]('●');
|
|
90
|
+
console.log(` ${bullet} ${text}`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public static logSystem(text: string) {
|
|
94
|
+
console.log(chalk.dim(` ${text}`));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
public static logTransition(text: string) {
|
|
98
|
+
console.log(` ${chalk.red('+')} ${chalk.red(text)}`);
|
|
99
|
+
}
|
|
87
100
|
}
|
package/console.log(tick)
DELETED
|
File without changes
|