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.
- package/dist/index.js +186 -43
- package/package.json +1 -1
- 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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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 (
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
-
|
|
91
|
-
|
|
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
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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 (
|
|
48
|
-
|
|
49
|
-
|
|
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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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() {
|