closed-loop-cli 1.0.0 → 1.0.2

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.

Potentially problematic release.


This version of closed-loop-cli might be problematic. Click here for more details.

Files changed (3) hide show
  1. package/dist/index.js +186 -43
  2. package/package.json +1 -1
  3. package/src/index.ts +217 -48
package/dist/index.js CHANGED
@@ -46,56 +46,199 @@ const task_agent_1 = require("./orchestrator/task-agent");
46
46
  // Load environment variables
47
47
  dotenv.config();
48
48
  function printHeader() {
49
- console.log('\x1b[35m%s\x1b[0m', '==================================================');
50
- console.log('\x1b[36m%s\x1b[0m', ' Closed-Loop Self-Developing Coding CLI ');
51
- console.log('\x1b[35m%s\x1b[0m', '==================================================');
52
- console.log('Using endpoint: ' + (process.env.ANTHROPIC_BASE_URL || 'default anthropic'));
53
- console.log('Main Model: ' + (process.env.ANTHROPIC_MODEL || 'mimo-v2.5-pro[1m]'));
54
- console.log('Subagent Model: ' + (process.env.CLAUDE_CODE_SUBAGENT_MODEL || 'mimo-v2.5-pro'));
55
- console.log('Type a task to begin, or type "exit" to quit.\n');
49
+ const banner = `
50
+ \x1b[38;5;99m ___ _ _ _
51
+ / __\\ | ___ ___ ___ __| | | | ___ ___ _ __
52
+ / / | |/ _ \\/ __|/ _ \\/ _\` | | |/ _ \\ / _ \\| '_ \\
53
+ / /___| | (_) \\__ \\ __/ (_| | | | (_) | (_) | |_) |
54
+ \\____/|_|\\___/|___/\\___|\\__,_| |_|\\___/ \\___/| .__/
55
+ |_| \x1b[0m`;
56
+ console.log(banner);
57
+ console.log('\x1b[37mTips for getting started:\x1b[0m');
58
+ console.log('\x1b[90m1. Ask questions, edit files, or run commands.\x1b[0m');
59
+ console.log('\x1b[90m2. Be specific for the best results.\x1b[0m');
60
+ console.log('\x1b[90m3. Type "exit" or "quit" to close the session.\x1b[0m\n');
61
+ const endpoint = process.env.ANTHROPIC_BASE_URL || 'default';
62
+ const model = process.env.ANTHROPIC_MODEL || 'mimo-v2.5-pro[1m]';
63
+ const subagent = process.env.CLAUDE_CODE_SUBAGENT_MODEL || 'mimo-v2.5-pro';
64
+ console.log(`\x1b[90mUsing: Endpoint: \x1b[38;5;86m${endpoint}\x1b[90m | Model: \x1b[38;5;153m${model}\x1b[90m | Subagent: \x1b[38;5;208m${subagent}\x1b[0m\n`);
56
65
  }
57
- async function startInteractiveCLI(effort = 'standard', codeactMode = false) {
58
- printHeader();
59
- console.log('\x1b[33m%s\x1b[0m', '--- CLAUDE CODE INTERACTIVE MODE (Conversational CLI) ---');
60
- console.log('Conversation history is maintained. Type "exit" or "quit" to leave.\n');
61
- const rl = readline.createInterface({
62
- input: process.stdin,
63
- output: process.stdout,
64
- prompt: '\x1b[35mClaudeCode > \x1b[0m'
65
- });
66
- const history = [];
67
- rl.prompt();
68
- rl.on('line', async (line) => {
69
- const input = line.trim();
70
- if (!input) {
71
- rl.prompt();
66
+ class ClosedLoopTUI {
67
+ history = [];
68
+ input = '';
69
+ cursorIdx = 0;
70
+ isThinking = false;
71
+ effort;
72
+ constructor(effort = 'standard') {
73
+ this.effort = effort;
74
+ }
75
+ start() {
76
+ process.stdout.write('\x1b[?1049h'); // Enter alternate screen
77
+ process.stdout.write('\x1b[?25h'); // Show cursor
78
+ this.render();
79
+ readline.emitKeypressEvents(process.stdin);
80
+ if (process.stdin.isTTY) {
81
+ process.stdin.setRawMode(true);
82
+ }
83
+ process.stdin.on('keypress', this.handleKeypress.bind(this));
84
+ process.stdout.on('resize', () => {
85
+ this.render();
86
+ });
87
+ }
88
+ render() {
89
+ const rows = process.stdout.rows || 24;
90
+ const cols = process.stdout.columns || 80;
91
+ // Clear screen and move cursor to 1,1
92
+ process.stdout.write('\x1b[2J\x1b[H');
93
+ // 1. Draw Banner & Info
94
+ const banner = `
95
+ \x1b[38;5;99m ___ _ _ _
96
+ / __\\ | ___ ___ ___ __| | | | ___ ___ _ __
97
+ / / | |/ _ \\/ __|/ _ \\/ _\` | | |/ _ \\ / _ \\| '_ \\
98
+ / /___| | (_) \\__ \\ __/ (_| | | | (_) | (_) | |_) |
99
+ \\____/|_|\\___/|___/\\___|\\__,_| |_|\\___/ \\___/| .__/
100
+ |_| \x1b[0m`;
101
+ console.log(banner);
102
+ console.log('\x1b[37mTips for getting started:\x1b[0m');
103
+ console.log('\x1b[90m1. Ask questions, edit files, or run commands. 2. Be specific. 3. Type "exit" to quit.\x1b[0m');
104
+ const endpoint = process.env.ANTHROPIC_BASE_URL || 'default';
105
+ const model = process.env.ANTHROPIC_MODEL || 'mimo-v2.5-pro';
106
+ console.log(`\x1b[90mUsing: Endpoint: \x1b[38;5;86m${endpoint}\x1b[90m | Model: \x1b[38;5;153m${model}\x1b[0m\n`);
107
+ // 2. Draw History in the middle
108
+ const historyHeight = rows - 14;
109
+ const historyLines = [];
110
+ // Format history messages into lines
111
+ for (const msg of this.history) {
112
+ if (msg.role === 'user') {
113
+ historyLines.push(`\x1b[38;5;99mUser ❯\x1b[0m ${msg.content}`);
114
+ }
115
+ else {
116
+ const lines = msg.content.split('\n');
117
+ for (const line of lines) {
118
+ historyLines.push(`\x1b[38;5;86mAgent ❯\x1b[0m ${line}`);
119
+ }
120
+ }
121
+ }
122
+ // Slice history to fit historyHeight
123
+ const startIdx = Math.max(0, historyLines.length - historyHeight);
124
+ const visibleHistory = historyLines.slice(startIdx, startIdx + historyHeight);
125
+ for (let i = 0; i < historyHeight; i++) {
126
+ if (i < visibleHistory.length) {
127
+ console.log(visibleHistory[i]);
128
+ }
129
+ else {
130
+ console.log(''); // empty line
131
+ }
132
+ }
133
+ // 3. Draw Bottom Input Box (3 lines)
134
+ const border = '─'.repeat(cols - 2);
135
+ console.log(`\x1b[38;5;99m╭${border}╮\x1b[0m`);
136
+ const promptStr = this.isThinking ? ' \x1b[36m⠋ Thinking...\x1b[0m' : ` › ${this.input}`;
137
+ const visiblePromptLen = this.isThinking ? 14 : 3 + this.input.length;
138
+ const padding = ' '.repeat(Math.max(0, cols - 4 - visiblePromptLen));
139
+ console.log(`\x1b[38;5;99m│\x1b[0m${promptStr}${padding}\x1b[38;5;99m│\x1b[0m`);
140
+ console.log(`\x1b[38;5;99m╰${border}╯\x1b[0m`);
141
+ // Position cursor
142
+ if (!this.isThinking) {
143
+ const cursorCol = 4 + this.cursorIdx;
144
+ const cursorRow = rows - 1;
145
+ process.stdout.write(`\x1b[${cursorRow};${cursorCol}H`);
146
+ }
147
+ else {
148
+ process.stdout.write('\x1b[?25l');
149
+ }
150
+ }
151
+ async handleKeypress(str, key) {
152
+ if (this.isThinking)
72
153
  return;
154
+ if (key.ctrl && key.name === 'c') {
155
+ this.exit();
73
156
  }
74
- if (input.toLowerCase() === 'exit' || input.toLowerCase() === 'quit') {
75
- console.log('Goodbye!');
76
- process.exit(0);
157
+ if (key.name === 'return') {
158
+ const cmd = this.input.trim();
159
+ if (!cmd)
160
+ return;
161
+ if (cmd.toLowerCase() === 'exit' || cmd.toLowerCase() === 'quit') {
162
+ this.exit();
163
+ }
164
+ this.history.push({ role: 'user', content: cmd });
165
+ this.input = '';
166
+ this.cursorIdx = 0;
167
+ this.isThinking = true;
168
+ this.render();
169
+ try {
170
+ // Temporarily leave alternate screen buffer for execution
171
+ process.stdout.write('\x1b[?1049l');
172
+ process.stdout.write('\x1b[?25h');
173
+ if (process.stdin.isTTY) {
174
+ process.stdin.setRawMode(false);
175
+ }
176
+ console.log(`\n\x1b[35;1m=================== EXECUTION MODE ===================\x1b[0m`);
177
+ console.log(`\x1b[90mRunning Task:\x1b[0m ${cmd}\n`);
178
+ const response = await (0, task_agent_1.runTaskAgent)(cmd, {
179
+ role: 'coder_codeact',
180
+ effort: this.effort,
181
+ history: this.history.slice(0, -1)
182
+ });
183
+ // Re-enter TUI and raw mode
184
+ process.stdout.write('\x1b[?1049h');
185
+ if (process.stdin.isTTY) {
186
+ process.stdin.setRawMode(true);
187
+ }
188
+ this.history.push({ role: 'assistant', content: response.result });
189
+ }
190
+ catch (err) {
191
+ // Re-enter TUI and raw mode
192
+ process.stdout.write('\x1b[?1049h');
193
+ if (process.stdin.isTTY) {
194
+ process.stdin.setRawMode(true);
195
+ }
196
+ this.history.push({ role: 'assistant', content: `Error: ${err.message}` });
197
+ }
198
+ this.isThinking = false;
199
+ process.stdout.write('\x1b[?25h');
200
+ this.render();
201
+ return;
77
202
  }
78
- rl.pause(); // Pause standard input while agent runs
79
- try {
80
- const response = await (0, task_agent_1.runTaskAgent)(input, {
81
- role: 'coder_codeact', // Coder with command execution tools
82
- effort,
83
- history: history
84
- });
85
- // Update history
86
- history.push({ role: 'user', content: input });
87
- history.push({ role: 'assistant', content: response.result });
88
- console.log(`\n\x1b[32m[Claude Code Response]:\x1b[0m\n${response.result}\n`);
203
+ if (key.name === 'backspace') {
204
+ if (this.cursorIdx > 0) {
205
+ this.input = this.input.slice(0, this.cursorIdx - 1) + this.input.slice(this.cursorIdx);
206
+ this.cursorIdx--;
207
+ this.render();
208
+ }
209
+ return;
89
210
  }
90
- catch (err) {
91
- console.error('\n\x1b[31m[Agent Error]:\x1b[0m', err.message);
211
+ if (key.name === 'left') {
212
+ if (this.cursorIdx > 0) {
213
+ this.cursorIdx--;
214
+ this.render();
215
+ }
216
+ return;
217
+ }
218
+ if (key.name === 'right') {
219
+ if (this.cursorIdx < this.input.length) {
220
+ this.cursorIdx++;
221
+ this.render();
222
+ }
223
+ return;
224
+ }
225
+ // Handle normal character inputs
226
+ if (str && str.length === 1 && !key.ctrl && !key.meta) {
227
+ this.input = this.input.slice(0, this.cursorIdx) + str + this.input.slice(this.cursorIdx);
228
+ this.cursorIdx++;
229
+ this.render();
92
230
  }
93
- rl.resume();
94
- rl.prompt();
95
- }).on('close', () => {
96
- console.log('\nGoodbye!');
231
+ }
232
+ exit() {
233
+ process.stdout.write('\x1b[?1049l');
234
+ process.stdout.write('\x1b[?25h');
235
+ console.log('Goodbye!');
97
236
  process.exit(0);
98
- });
237
+ }
238
+ }
239
+ async function startInteractiveCLI(effort = 'standard', codeactMode = false) {
240
+ const tui = new ClosedLoopTUI(effort);
241
+ tui.start();
99
242
  }
100
243
  function setupLogRedirection() {
101
244
  const logFile = fs.createWriteStream(path.join(process.cwd(), 'evolution.log'), { flags: 'a' });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "closed-loop-cli",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Self-Developing Multi-Agent CLI Coding Assistant",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
package/src/index.ts CHANGED
@@ -7,6 +7,7 @@ import { AutogenesisEngine } from './orchestrator/autogenesis';
7
7
  import { startDashboardServer } from './dashboard/server';
8
8
  import { startTelegramBot } from './orchestrator/telegram-bot';
9
9
  import { runTaskAgent } from './orchestrator/task-agent';
10
+ import { Spinner } from './tools/tui-tools';
10
11
 
11
12
  // Phase 3 is initialized
12
13
 
@@ -14,63 +15,231 @@ import { runTaskAgent } from './orchestrator/task-agent';
14
15
  dotenv.config();
15
16
 
16
17
  function printHeader() {
17
- console.log('\x1b[35m%s\x1b[0m', '==================================================');
18
- console.log('\x1b[36m%s\x1b[0m', ' Closed-Loop Self-Developing Coding CLI ');
19
- console.log('\x1b[35m%s\x1b[0m', '==================================================');
20
- console.log('Using endpoint: ' + (process.env.ANTHROPIC_BASE_URL || 'default anthropic'));
21
- console.log('Main Model: ' + (process.env.ANTHROPIC_MODEL || 'mimo-v2.5-pro[1m]'));
22
- console.log('Subagent Model: ' + (process.env.CLAUDE_CODE_SUBAGENT_MODEL || 'mimo-v2.5-pro'));
23
- console.log('Type a task to begin, or type "exit" to quit.\n');
18
+ const banner = `
19
+ \x1b[38;5;99m ___ _ _ _
20
+ / __\\ | ___ ___ ___ __| | | | ___ ___ _ __
21
+ / / | |/ _ \\/ __|/ _ \\/ _\` | | |/ _ \\ / _ \\| '_ \\
22
+ / /___| | (_) \\__ \\ __/ (_| | | | (_) | (_) | |_) |
23
+ \\____/|_|\\___/|___/\\___|\\__,_| |_|\\___/ \\___/| .__/
24
+ |_| \x1b[0m`;
25
+
26
+ console.log(banner);
27
+ console.log('\x1b[37mTips for getting started:\x1b[0m');
28
+ console.log('\x1b[90m1. Ask questions, edit files, or run commands.\x1b[0m');
29
+ console.log('\x1b[90m2. Be specific for the best results.\x1b[0m');
30
+ console.log('\x1b[90m3. Type "exit" or "quit" to close the session.\x1b[0m\n');
31
+
32
+ const endpoint = process.env.ANTHROPIC_BASE_URL || 'default';
33
+ const model = process.env.ANTHROPIC_MODEL || 'mimo-v2.5-pro[1m]';
34
+ const subagent = process.env.CLAUDE_CODE_SUBAGENT_MODEL || 'mimo-v2.5-pro';
35
+
36
+ console.log(`\x1b[90mUsing: Endpoint: \x1b[38;5;86m${endpoint}\x1b[90m | Model: \x1b[38;5;153m${model}\x1b[90m | Subagent: \x1b[38;5;208m${subagent}\x1b[0m\n`);
24
37
  }
25
38
 
26
- async function startInteractiveCLI(effort: 'standard' | 'ultracode' = 'standard', codeactMode = false) {
27
- printHeader();
28
- console.log('\x1b[33m%s\x1b[0m', '--- CLAUDE CODE INTERACTIVE MODE (Conversational CLI) ---');
29
- console.log('Conversation history is maintained. Type "exit" or "quit" to leave.\n');
30
-
31
- const rl = readline.createInterface({
32
- input: process.stdin,
33
- output: process.stdout,
34
- prompt: '\x1b[35mClaudeCode > \x1b[0m'
35
- });
36
-
37
- const history: any[] = [];
38
- rl.prompt();
39
-
40
- rl.on('line', async (line) => {
41
- const input = line.trim();
42
- if (!input) {
43
- rl.prompt();
39
+ class ClosedLoopTUI {
40
+ private history: { role: 'user' | 'assistant'; content: string }[] = [];
41
+ private input = '';
42
+ private cursorIdx = 0;
43
+ private isThinking = false;
44
+ private effort: 'standard' | 'ultracode';
45
+
46
+ constructor(effort: 'standard' | 'ultracode' = 'standard') {
47
+ this.effort = effort;
48
+ }
49
+
50
+ start() {
51
+ process.stdout.write('\x1b[?1049h'); // Enter alternate screen
52
+ process.stdout.write('\x1b[?25h'); // Show cursor
53
+ this.render();
54
+
55
+ readline.emitKeypressEvents(process.stdin);
56
+ if (process.stdin.isTTY) {
57
+ process.stdin.setRawMode(true);
58
+ }
59
+
60
+ process.stdin.on('keypress', this.handleKeypress.bind(this));
61
+ process.stdout.on('resize', () => {
62
+ this.render();
63
+ });
64
+ }
65
+
66
+ render() {
67
+ const rows = process.stdout.rows || 24;
68
+ const cols = process.stdout.columns || 80;
69
+
70
+ // Clear screen and move cursor to 1,1
71
+ process.stdout.write('\x1b[2J\x1b[H');
72
+
73
+ // 1. Draw Banner & Info
74
+ const banner = `
75
+ \x1b[38;5;99m ___ _ _ _
76
+ / __\\ | ___ ___ ___ __| | | | ___ ___ _ __
77
+ / / | |/ _ \\/ __|/ _ \\/ _\` | | |/ _ \\ / _ \\| '_ \\
78
+ / /___| | (_) \\__ \\ __/ (_| | | | (_) | (_) | |_) |
79
+ \\____/|_|\\___/|___/\\___|\\__,_| |_|\\___/ \\___/| .__/
80
+ |_| \x1b[0m`;
81
+ console.log(banner);
82
+
83
+ console.log('\x1b[37mTips for getting started:\x1b[0m');
84
+ console.log('\x1b[90m1. Ask questions, edit files, or run commands. 2. Be specific. 3. Type "exit" to quit.\x1b[0m');
85
+
86
+ const endpoint = process.env.ANTHROPIC_BASE_URL || 'default';
87
+ const model = process.env.ANTHROPIC_MODEL || 'mimo-v2.5-pro';
88
+ console.log(`\x1b[90mUsing: Endpoint: \x1b[38;5;86m${endpoint}\x1b[90m | Model: \x1b[38;5;153m${model}\x1b[0m\n`);
89
+
90
+ // 2. Draw History in the middle
91
+ const historyHeight = rows - 14;
92
+ const historyLines: string[] = [];
93
+
94
+ // Format history messages into lines
95
+ for (const msg of this.history) {
96
+ if (msg.role === 'user') {
97
+ historyLines.push(`\x1b[38;5;99mUser ❯\x1b[0m ${msg.content}`);
98
+ } else {
99
+ const lines = msg.content.split('\n');
100
+ for (const line of lines) {
101
+ historyLines.push(`\x1b[38;5;86mAgent ❯\x1b[0m ${line}`);
102
+ }
103
+ }
104
+ }
105
+
106
+ // Slice history to fit historyHeight
107
+ const startIdx = Math.max(0, historyLines.length - historyHeight);
108
+ const visibleHistory = historyLines.slice(startIdx, startIdx + historyHeight);
109
+
110
+ for (let i = 0; i < historyHeight; i++) {
111
+ if (i < visibleHistory.length) {
112
+ console.log(visibleHistory[i]);
113
+ } else {
114
+ console.log(''); // empty line
115
+ }
116
+ }
117
+
118
+ // 3. Draw Bottom Input Box (3 lines)
119
+ const border = '─'.repeat(cols - 2);
120
+ console.log(`\x1b[38;5;99m╭${border}╮\x1b[0m`);
121
+
122
+ const promptStr = this.isThinking ? ' \x1b[36m⠋ Thinking...\x1b[0m' : ` › ${this.input}`;
123
+ const visiblePromptLen = this.isThinking ? 14 : 3 + this.input.length;
124
+ const padding = ' '.repeat(Math.max(0, cols - 4 - visiblePromptLen));
125
+ console.log(`\x1b[38;5;99m│\x1b[0m${promptStr}${padding}\x1b[38;5;99m│\x1b[0m`);
126
+
127
+ console.log(`\x1b[38;5;99m╰${border}╯\x1b[0m`);
128
+
129
+ // Position cursor
130
+ if (!this.isThinking) {
131
+ const cursorCol = 4 + this.cursorIdx;
132
+ const cursorRow = rows - 1;
133
+ process.stdout.write(`\x1b[${cursorRow};${cursorCol}H`);
134
+ } else {
135
+ process.stdout.write('\x1b[?25l');
136
+ }
137
+ }
138
+
139
+ async handleKeypress(str: string, key: any) {
140
+ if (this.isThinking) return;
141
+
142
+ if (key.ctrl && key.name === 'c') {
143
+ this.exit();
144
+ }
145
+
146
+ if (key.name === 'return') {
147
+ const cmd = this.input.trim();
148
+ if (!cmd) return;
149
+
150
+ if (cmd.toLowerCase() === 'exit' || cmd.toLowerCase() === 'quit') {
151
+ this.exit();
152
+ }
153
+
154
+ this.history.push({ role: 'user', content: cmd });
155
+ this.input = '';
156
+ this.cursorIdx = 0;
157
+ this.isThinking = true;
158
+ this.render();
159
+
160
+ try {
161
+ // Temporarily leave alternate screen buffer for execution
162
+ process.stdout.write('\x1b[?1049l');
163
+ process.stdout.write('\x1b[?25h');
164
+ if (process.stdin.isTTY) {
165
+ process.stdin.setRawMode(false);
166
+ }
167
+
168
+ console.log(`\n\x1b[35;1m=================== EXECUTION MODE ===================\x1b[0m`);
169
+ console.log(`\x1b[90mRunning Task:\x1b[0m ${cmd}\n`);
170
+
171
+ const response = await runTaskAgent(cmd, {
172
+ role: 'coder_codeact' as any,
173
+ effort: this.effort,
174
+ history: this.history.slice(0, -1)
175
+ });
176
+
177
+ // Re-enter TUI and raw mode
178
+ process.stdout.write('\x1b[?1049h');
179
+ if (process.stdin.isTTY) {
180
+ process.stdin.setRawMode(true);
181
+ }
182
+
183
+ this.history.push({ role: 'assistant', content: response.result });
184
+ } catch (err: any) {
185
+ // Re-enter TUI and raw mode
186
+ process.stdout.write('\x1b[?1049h');
187
+ if (process.stdin.isTTY) {
188
+ process.stdin.setRawMode(true);
189
+ }
190
+ this.history.push({ role: 'assistant', content: `Error: ${err.message}` });
191
+ }
192
+
193
+ this.isThinking = false;
194
+ process.stdout.write('\x1b[?25h');
195
+ this.render();
44
196
  return;
45
197
  }
46
198
 
47
- if (input.toLowerCase() === 'exit' || input.toLowerCase() === 'quit') {
48
- console.log('Goodbye!');
49
- process.exit(0);
199
+ if (key.name === 'backspace') {
200
+ if (this.cursorIdx > 0) {
201
+ this.input = this.input.slice(0, this.cursorIdx - 1) + this.input.slice(this.cursorIdx);
202
+ this.cursorIdx--;
203
+ this.render();
204
+ }
205
+ return;
50
206
  }
51
207
 
52
- rl.pause(); // Pause standard input while agent runs
53
- try {
54
- const response = await runTaskAgent(input, {
55
- role: 'coder_codeact' as any, // Coder with command execution tools
56
- effort,
57
- history: history
58
- });
59
-
60
- // Update history
61
- history.push({ role: 'user', content: input });
62
- history.push({ role: 'assistant', content: response.result });
63
-
64
- console.log(`\n\x1b[32m[Claude Code Response]:\x1b[0m\n${response.result}\n`);
65
- } catch (err: any) {
66
- console.error('\n\x1b[31m[Agent Error]:\x1b[0m', err.message);
208
+ if (key.name === 'left') {
209
+ if (this.cursorIdx > 0) {
210
+ this.cursorIdx--;
211
+ this.render();
212
+ }
213
+ return;
214
+ }
215
+
216
+ if (key.name === 'right') {
217
+ if (this.cursorIdx < this.input.length) {
218
+ this.cursorIdx++;
219
+ this.render();
220
+ }
221
+ return;
67
222
  }
68
- rl.resume();
69
- rl.prompt();
70
- }).on('close', () => {
71
- console.log('\nGoodbye!');
223
+
224
+ // Handle normal character inputs
225
+ if (str && str.length === 1 && !key.ctrl && !key.meta) {
226
+ this.input = this.input.slice(0, this.cursorIdx) + str + this.input.slice(this.cursorIdx);
227
+ this.cursorIdx++;
228
+ this.render();
229
+ }
230
+ }
231
+
232
+ exit() {
233
+ process.stdout.write('\x1b[?1049l');
234
+ process.stdout.write('\x1b[?25h');
235
+ console.log('Goodbye!');
72
236
  process.exit(0);
73
- });
237
+ }
238
+ }
239
+
240
+ async function startInteractiveCLI(effort: 'standard' | 'ultracode' = 'standard', codeactMode = false) {
241
+ const tui = new ClosedLoopTUI(effort);
242
+ tui.start();
74
243
  }
75
244
 
76
245
  function setupLogRedirection() {