wiggum-cli 0.7.2 → 0.7.3
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/dist/repl/repl-loop.d.ts +2 -0
- package/dist/repl/repl-loop.d.ts.map +1 -1
- package/dist/repl/repl-loop.js +96 -52
- package/dist/repl/repl-loop.js.map +1 -1
- package/package.json +1 -1
- package/src/repl/repl-loop.ts +102 -56
package/dist/repl/repl-loop.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { type ReplCommandName } from './command-parser.js';
|
|
|
11
11
|
declare function executeCommand(commandName: ReplCommandName, args: string[], state: SessionState, rl: readline.Interface): Promise<{
|
|
12
12
|
state: SessionState;
|
|
13
13
|
shouldExit: boolean;
|
|
14
|
+
needsRlRecreate: boolean;
|
|
14
15
|
}>;
|
|
15
16
|
/**
|
|
16
17
|
* Process a single line of input
|
|
@@ -18,6 +19,7 @@ declare function executeCommand(commandName: ReplCommandName, args: string[], st
|
|
|
18
19
|
declare function processInput(input: string, state: SessionState, rl: readline.Interface): Promise<{
|
|
19
20
|
state: SessionState;
|
|
20
21
|
shouldExit: boolean;
|
|
22
|
+
needsRlRecreate: boolean;
|
|
21
23
|
}>;
|
|
22
24
|
/**
|
|
23
25
|
* Start the REPL loop
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repl-loop.d.ts","sourceRoot":"","sources":["../../src/repl/repl-loop.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,QAAQ,MAAM,eAAe,CAAC;AAQrC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"repl-loop.d.ts","sourceRoot":"","sources":["../../src/repl/repl-loop.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,QAAQ,MAAM,eAAe,CAAC;AAQrC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,qBAAqB,CAAC;AAwL7B;;GAEG;AACH,iBAAe,cAAc,CAC3B,WAAW,EAAE,eAAe,EAC5B,IAAI,EAAE,MAAM,EAAE,EACd,KAAK,EAAE,YAAY,EACnB,EAAE,EAAE,QAAQ,CAAC,SAAS,GACrB,OAAO,CAAC;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE,CAAC,CA0BjF;AAuBD;;GAEG;AACH,iBAAe,YAAY,CACzB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,YAAY,EACnB,EAAE,EAAE,QAAQ,CAAC,SAAS,GACrB,OAAO,CAAC;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE,CAAC,CA8BjF;AA6BD;;GAEG;AACH,wBAAsB,SAAS,CAAC,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAiDzE;AAED;;GAEG;AACH,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,CAAC"}
|
package/dist/repl/repl-loop.js
CHANGED
|
@@ -13,6 +13,32 @@ import { hasConfig } from '../utils/config.js';
|
|
|
13
13
|
import { updateSessionState } from './session-state.js';
|
|
14
14
|
import { parseInput, resolveCommandAlias, formatHelpText, } from './command-parser.js';
|
|
15
15
|
const PROMPT = `${simpson.yellow('wiggum')}${simpson.brown('>')} `;
|
|
16
|
+
/**
|
|
17
|
+
* Clear any buffered stdin data
|
|
18
|
+
* Prevents leaked input after subcommands that use their own stdin handling
|
|
19
|
+
*/
|
|
20
|
+
async function clearStdinBuffer() {
|
|
21
|
+
return new Promise((resolve) => {
|
|
22
|
+
if (process.stdin.isTTY) {
|
|
23
|
+
// Set raw mode temporarily to drain buffer
|
|
24
|
+
const wasRaw = process.stdin.isRaw;
|
|
25
|
+
process.stdin.setRawMode(true);
|
|
26
|
+
process.stdin.once('readable', () => {
|
|
27
|
+
// Drain any buffered data
|
|
28
|
+
while (process.stdin.read() !== null) {
|
|
29
|
+
// discard
|
|
30
|
+
}
|
|
31
|
+
process.stdin.setRawMode(wasRaw);
|
|
32
|
+
resolve();
|
|
33
|
+
});
|
|
34
|
+
// Trigger readable if nothing buffered
|
|
35
|
+
setTimeout(resolve, 10);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
resolve();
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
16
42
|
/**
|
|
17
43
|
* Handler for the /init command
|
|
18
44
|
*/
|
|
@@ -22,8 +48,9 @@ async function handleInitCommand(_args, state, rl) {
|
|
|
22
48
|
logger.warn('Project is already initialized. Re-running init will update configuration.');
|
|
23
49
|
console.log('');
|
|
24
50
|
}
|
|
25
|
-
//
|
|
26
|
-
|
|
51
|
+
// Close REPL readline to avoid conflicts with subcommand's stdin usage
|
|
52
|
+
// We'll signal to recreate it after the command completes
|
|
53
|
+
rl.close();
|
|
27
54
|
try {
|
|
28
55
|
const result = await runInitWorkflow(state.projectRoot, {
|
|
29
56
|
yes: false, // Always interactive in REPL
|
|
@@ -45,10 +72,6 @@ async function handleInitCommand(_args, state, rl) {
|
|
|
45
72
|
logger.error(`Init failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
46
73
|
return state;
|
|
47
74
|
}
|
|
48
|
-
finally {
|
|
49
|
-
// Resume REPL readline after subcommand completes
|
|
50
|
-
rl.resume();
|
|
51
|
-
}
|
|
52
75
|
}
|
|
53
76
|
/**
|
|
54
77
|
* Handler for the /new command
|
|
@@ -65,8 +88,8 @@ async function handleNewCommand(args, state, rl) {
|
|
|
65
88
|
return state;
|
|
66
89
|
}
|
|
67
90
|
const featureName = args[0];
|
|
68
|
-
//
|
|
69
|
-
rl.
|
|
91
|
+
// Close REPL readline to avoid stdin conflicts with subcommand prompts
|
|
92
|
+
rl.close();
|
|
70
93
|
try {
|
|
71
94
|
// Delegate to the existing new command behavior
|
|
72
95
|
// Always use AI mode in REPL (the command handles fallback to template if no API key)
|
|
@@ -79,9 +102,8 @@ async function handleNewCommand(args, state, rl) {
|
|
|
79
102
|
ai: true, // Always use AI interview in REPL
|
|
80
103
|
});
|
|
81
104
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
rl.resume();
|
|
105
|
+
catch (error) {
|
|
106
|
+
logger.error(`New command failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
85
107
|
}
|
|
86
108
|
return state;
|
|
87
109
|
}
|
|
@@ -99,13 +121,13 @@ async function handleRunCommand(args, state, rl) {
|
|
|
99
121
|
return state;
|
|
100
122
|
}
|
|
101
123
|
const featureName = args[0];
|
|
102
|
-
//
|
|
103
|
-
rl.
|
|
124
|
+
// Close REPL readline to avoid stdin conflicts with subcommand
|
|
125
|
+
rl.close();
|
|
104
126
|
try {
|
|
105
127
|
await runCommand(featureName, {});
|
|
106
128
|
}
|
|
107
|
-
|
|
108
|
-
|
|
129
|
+
catch (error) {
|
|
130
|
+
logger.error(`Run command failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
109
131
|
}
|
|
110
132
|
return state;
|
|
111
133
|
}
|
|
@@ -118,13 +140,13 @@ async function handleMonitorCommand(args, state, rl) {
|
|
|
118
140
|
return state;
|
|
119
141
|
}
|
|
120
142
|
const featureName = args[0];
|
|
121
|
-
//
|
|
122
|
-
rl.
|
|
143
|
+
// Close REPL readline to avoid stdin conflicts with subcommand
|
|
144
|
+
rl.close();
|
|
123
145
|
try {
|
|
124
146
|
await monitorCommand(featureName, {});
|
|
125
147
|
}
|
|
126
|
-
|
|
127
|
-
|
|
148
|
+
catch (error) {
|
|
149
|
+
logger.error(`Monitor command failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
128
150
|
}
|
|
129
151
|
return state;
|
|
130
152
|
}
|
|
@@ -142,21 +164,22 @@ function handleHelpCommand() {
|
|
|
142
164
|
async function executeCommand(commandName, args, state, rl) {
|
|
143
165
|
switch (commandName) {
|
|
144
166
|
case 'init':
|
|
145
|
-
|
|
167
|
+
// Init closes the readline to avoid stdin conflicts
|
|
168
|
+
return { state: await handleInitCommand(args, state, rl), shouldExit: false, needsRlRecreate: true };
|
|
146
169
|
case 'new':
|
|
147
|
-
return { state: await handleNewCommand(args, state, rl), shouldExit: false };
|
|
170
|
+
return { state: await handleNewCommand(args, state, rl), shouldExit: false, needsRlRecreate: true };
|
|
148
171
|
case 'run':
|
|
149
|
-
return { state: await handleRunCommand(args, state, rl), shouldExit: false };
|
|
172
|
+
return { state: await handleRunCommand(args, state, rl), shouldExit: false, needsRlRecreate: true };
|
|
150
173
|
case 'monitor':
|
|
151
|
-
return { state: await handleMonitorCommand(args, state, rl), shouldExit: false };
|
|
174
|
+
return { state: await handleMonitorCommand(args, state, rl), shouldExit: false, needsRlRecreate: true };
|
|
152
175
|
case 'help':
|
|
153
176
|
handleHelpCommand();
|
|
154
|
-
return { state, shouldExit: false };
|
|
177
|
+
return { state, shouldExit: false, needsRlRecreate: false };
|
|
155
178
|
case 'exit':
|
|
156
|
-
return { state, shouldExit: true };
|
|
179
|
+
return { state, shouldExit: true, needsRlRecreate: false };
|
|
157
180
|
default:
|
|
158
181
|
logger.warn(`Unknown command: ${commandName}`);
|
|
159
|
-
return { state, shouldExit: false };
|
|
182
|
+
return { state, shouldExit: false, needsRlRecreate: false };
|
|
160
183
|
}
|
|
161
184
|
}
|
|
162
185
|
/**
|
|
@@ -183,27 +206,52 @@ async function processInput(input, state, rl) {
|
|
|
183
206
|
const parsed = parseInput(input);
|
|
184
207
|
switch (parsed.type) {
|
|
185
208
|
case 'empty':
|
|
186
|
-
return { state, shouldExit: false };
|
|
209
|
+
return { state, shouldExit: false, needsRlRecreate: false };
|
|
187
210
|
case 'slash-command': {
|
|
188
211
|
const { command } = parsed;
|
|
189
212
|
if (!command) {
|
|
190
|
-
return { state, shouldExit: false };
|
|
213
|
+
return { state, shouldExit: false, needsRlRecreate: false };
|
|
191
214
|
}
|
|
192
215
|
const resolvedName = resolveCommandAlias(command.name);
|
|
193
216
|
if (!resolvedName) {
|
|
194
217
|
logger.warn(`Unknown command: /${command.name}. Type /help for available commands.`);
|
|
195
|
-
return { state, shouldExit: false };
|
|
218
|
+
return { state, shouldExit: false, needsRlRecreate: false };
|
|
196
219
|
}
|
|
197
220
|
return executeCommand(resolvedName, command.args, state, rl);
|
|
198
221
|
}
|
|
199
222
|
case 'natural-language': {
|
|
200
223
|
const newState = await handleNaturalLanguage(parsed.text, state);
|
|
201
|
-
return { state: newState, shouldExit: false };
|
|
224
|
+
return { state: newState, shouldExit: false, needsRlRecreate: false };
|
|
202
225
|
}
|
|
203
226
|
default:
|
|
204
|
-
return { state, shouldExit: false };
|
|
227
|
+
return { state, shouldExit: false, needsRlRecreate: false };
|
|
205
228
|
}
|
|
206
229
|
}
|
|
230
|
+
/**
|
|
231
|
+
* Create a new readline interface
|
|
232
|
+
*/
|
|
233
|
+
function createReadline() {
|
|
234
|
+
return readline.createInterface({
|
|
235
|
+
input: process.stdin,
|
|
236
|
+
output: process.stdout,
|
|
237
|
+
prompt: PROMPT,
|
|
238
|
+
terminal: true,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Read a single line from readline
|
|
243
|
+
*/
|
|
244
|
+
function readLine(rl) {
|
|
245
|
+
return new Promise((resolve) => {
|
|
246
|
+
rl.once('line', (line) => resolve(line));
|
|
247
|
+
rl.once('close', () => resolve(null));
|
|
248
|
+
rl.once('SIGINT', () => {
|
|
249
|
+
console.log('');
|
|
250
|
+
logger.info('Use /exit to quit');
|
|
251
|
+
rl.prompt();
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
}
|
|
207
255
|
/**
|
|
208
256
|
* Start the REPL loop
|
|
209
257
|
*/
|
|
@@ -219,26 +267,18 @@ export async function startRepl(initialState) {
|
|
|
219
267
|
console.log(pc.dim('Type /help for commands, /exit to quit'));
|
|
220
268
|
}
|
|
221
269
|
console.log('');
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
prompt: PROMPT,
|
|
226
|
-
terminal: true,
|
|
227
|
-
});
|
|
228
|
-
// Handle Ctrl+C gracefully
|
|
229
|
-
rl.on('SIGINT', () => {
|
|
230
|
-
console.log('');
|
|
231
|
-
logger.info('Use /exit to quit');
|
|
270
|
+
let rl = createReadline();
|
|
271
|
+
let running = true;
|
|
272
|
+
while (running) {
|
|
232
273
|
rl.prompt();
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
for await (const line of rl) {
|
|
274
|
+
const line = await readLine(rl);
|
|
275
|
+
// Handle EOF (Ctrl+D)
|
|
276
|
+
if (line === null) {
|
|
277
|
+
console.log('');
|
|
278
|
+
logger.info('Goodbye!');
|
|
279
|
+
running = false;
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
242
282
|
try {
|
|
243
283
|
const result = await processInput(line, state, rl);
|
|
244
284
|
state = result.state;
|
|
@@ -246,13 +286,17 @@ export async function startRepl(initialState) {
|
|
|
246
286
|
console.log('');
|
|
247
287
|
logger.info('Goodbye!');
|
|
248
288
|
rl.close();
|
|
249
|
-
|
|
289
|
+
running = false;
|
|
290
|
+
break;
|
|
291
|
+
}
|
|
292
|
+
// Recreate readline if needed (after commands that closed it)
|
|
293
|
+
if (result.needsRlRecreate) {
|
|
294
|
+
rl = createReadline();
|
|
250
295
|
}
|
|
251
296
|
}
|
|
252
297
|
catch (error) {
|
|
253
298
|
logger.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
254
299
|
}
|
|
255
|
-
rl.prompt();
|
|
256
300
|
}
|
|
257
301
|
}
|
|
258
302
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repl-loop.js","sourceRoot":"","sources":["../../src/repl/repl-loop.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,QAAQ,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EACL,UAAU,EACV,mBAAmB,EACnB,cAAc,GAEf,MAAM,qBAAqB,CAAC;AAE7B,MAAM,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;AAEnE;;GAEG;AACH,KAAK,UAAU,iBAAiB,CAC9B,KAAe,EACf,KAAmB,EACnB,EAAsB;IAEtB,+BAA+B;IAC/B,IAAI,KAAK,CAAC,WAAW,IAAI,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;QACtD,MAAM,CAAC,IAAI,CAAC,4EAA4E,CAAC,CAAC;QAC1F,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;IAED,uEAAuE;IACvE,EAAE,CAAC,KAAK,EAAE,CAAC;IAEX,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,KAAK,CAAC,WAAW,EAAE;YACtD,GAAG,EAAE,KAAK,EAAE,6BAA6B;SAC1C,CAAC,CAAC;QAEH,IAAI,MAAM,EAAE,CAAC;YACX,gCAAgC;YAChC,OAAO,kBAAkB,CAAC,KAAK,EAAE;gBAC/B,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,WAAW,EAAE,IAAI;aAClB,CAAC,CAAC;QACL,CAAC;QAED,iBAAiB;QACjB,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,gBAAgB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACvF,OAAO,KAAK,CAAC;IACf,CAAC;
|
|
1
|
+
{"version":3,"file":"repl-loop.js","sourceRoot":"","sources":["../../src/repl/repl-loop.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/repl/repl-loop.ts
CHANGED
|
@@ -22,6 +22,32 @@ import {
|
|
|
22
22
|
|
|
23
23
|
const PROMPT = `${simpson.yellow('wiggum')}${simpson.brown('>')} `;
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Clear any buffered stdin data
|
|
27
|
+
* Prevents leaked input after subcommands that use their own stdin handling
|
|
28
|
+
*/
|
|
29
|
+
async function clearStdinBuffer(): Promise<void> {
|
|
30
|
+
return new Promise((resolve) => {
|
|
31
|
+
if (process.stdin.isTTY) {
|
|
32
|
+
// Set raw mode temporarily to drain buffer
|
|
33
|
+
const wasRaw = process.stdin.isRaw;
|
|
34
|
+
process.stdin.setRawMode(true);
|
|
35
|
+
process.stdin.once('readable', () => {
|
|
36
|
+
// Drain any buffered data
|
|
37
|
+
while (process.stdin.read() !== null) {
|
|
38
|
+
// discard
|
|
39
|
+
}
|
|
40
|
+
process.stdin.setRawMode(wasRaw);
|
|
41
|
+
resolve();
|
|
42
|
+
});
|
|
43
|
+
// Trigger readable if nothing buffered
|
|
44
|
+
setTimeout(resolve, 10);
|
|
45
|
+
} else {
|
|
46
|
+
resolve();
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
25
51
|
/**
|
|
26
52
|
* Handler for the /init command
|
|
27
53
|
*/
|
|
@@ -36,8 +62,9 @@ async function handleInitCommand(
|
|
|
36
62
|
console.log('');
|
|
37
63
|
}
|
|
38
64
|
|
|
39
|
-
//
|
|
40
|
-
|
|
65
|
+
// Close REPL readline to avoid conflicts with subcommand's stdin usage
|
|
66
|
+
// We'll signal to recreate it after the command completes
|
|
67
|
+
rl.close();
|
|
41
68
|
|
|
42
69
|
try {
|
|
43
70
|
const result = await runInitWorkflow(state.projectRoot, {
|
|
@@ -60,9 +87,6 @@ async function handleInitCommand(
|
|
|
60
87
|
} catch (error) {
|
|
61
88
|
logger.error(`Init failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
62
89
|
return state;
|
|
63
|
-
} finally {
|
|
64
|
-
// Resume REPL readline after subcommand completes
|
|
65
|
-
rl.resume();
|
|
66
90
|
}
|
|
67
91
|
}
|
|
68
92
|
|
|
@@ -88,8 +112,8 @@ async function handleNewCommand(
|
|
|
88
112
|
|
|
89
113
|
const featureName = args[0];
|
|
90
114
|
|
|
91
|
-
//
|
|
92
|
-
rl.
|
|
115
|
+
// Close REPL readline to avoid stdin conflicts with subcommand prompts
|
|
116
|
+
rl.close();
|
|
93
117
|
|
|
94
118
|
try {
|
|
95
119
|
// Delegate to the existing new command behavior
|
|
@@ -102,9 +126,8 @@ async function handleNewCommand(
|
|
|
102
126
|
model: state.model,
|
|
103
127
|
ai: true, // Always use AI interview in REPL
|
|
104
128
|
});
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
rl.resume();
|
|
129
|
+
} catch (error) {
|
|
130
|
+
logger.error(`New command failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
108
131
|
}
|
|
109
132
|
|
|
110
133
|
return state;
|
|
@@ -131,13 +154,13 @@ async function handleRunCommand(
|
|
|
131
154
|
|
|
132
155
|
const featureName = args[0];
|
|
133
156
|
|
|
134
|
-
//
|
|
135
|
-
rl.
|
|
157
|
+
// Close REPL readline to avoid stdin conflicts with subcommand
|
|
158
|
+
rl.close();
|
|
136
159
|
|
|
137
160
|
try {
|
|
138
161
|
await runCommand(featureName, {});
|
|
139
|
-
}
|
|
140
|
-
|
|
162
|
+
} catch (error) {
|
|
163
|
+
logger.error(`Run command failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
141
164
|
}
|
|
142
165
|
|
|
143
166
|
return state;
|
|
@@ -158,13 +181,13 @@ async function handleMonitorCommand(
|
|
|
158
181
|
|
|
159
182
|
const featureName = args[0];
|
|
160
183
|
|
|
161
|
-
//
|
|
162
|
-
rl.
|
|
184
|
+
// Close REPL readline to avoid stdin conflicts with subcommand
|
|
185
|
+
rl.close();
|
|
163
186
|
|
|
164
187
|
try {
|
|
165
188
|
await monitorCommand(featureName, {});
|
|
166
|
-
}
|
|
167
|
-
|
|
189
|
+
} catch (error) {
|
|
190
|
+
logger.error(`Monitor command failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
168
191
|
}
|
|
169
192
|
|
|
170
193
|
return state;
|
|
@@ -187,30 +210,31 @@ async function executeCommand(
|
|
|
187
210
|
args: string[],
|
|
188
211
|
state: SessionState,
|
|
189
212
|
rl: readline.Interface
|
|
190
|
-
): Promise<{ state: SessionState; shouldExit: boolean }> {
|
|
213
|
+
): Promise<{ state: SessionState; shouldExit: boolean; needsRlRecreate: boolean }> {
|
|
191
214
|
switch (commandName) {
|
|
192
215
|
case 'init':
|
|
193
|
-
|
|
216
|
+
// Init closes the readline to avoid stdin conflicts
|
|
217
|
+
return { state: await handleInitCommand(args, state, rl), shouldExit: false, needsRlRecreate: true };
|
|
194
218
|
|
|
195
219
|
case 'new':
|
|
196
|
-
return { state: await handleNewCommand(args, state, rl), shouldExit: false };
|
|
220
|
+
return { state: await handleNewCommand(args, state, rl), shouldExit: false, needsRlRecreate: true };
|
|
197
221
|
|
|
198
222
|
case 'run':
|
|
199
|
-
return { state: await handleRunCommand(args, state, rl), shouldExit: false };
|
|
223
|
+
return { state: await handleRunCommand(args, state, rl), shouldExit: false, needsRlRecreate: true };
|
|
200
224
|
|
|
201
225
|
case 'monitor':
|
|
202
|
-
return { state: await handleMonitorCommand(args, state, rl), shouldExit: false };
|
|
226
|
+
return { state: await handleMonitorCommand(args, state, rl), shouldExit: false, needsRlRecreate: true };
|
|
203
227
|
|
|
204
228
|
case 'help':
|
|
205
229
|
handleHelpCommand();
|
|
206
|
-
return { state, shouldExit: false };
|
|
230
|
+
return { state, shouldExit: false, needsRlRecreate: false };
|
|
207
231
|
|
|
208
232
|
case 'exit':
|
|
209
|
-
return { state, shouldExit: true };
|
|
233
|
+
return { state, shouldExit: true, needsRlRecreate: false };
|
|
210
234
|
|
|
211
235
|
default:
|
|
212
236
|
logger.warn(`Unknown command: ${commandName}`);
|
|
213
|
-
return { state, shouldExit: false };
|
|
237
|
+
return { state, shouldExit: false, needsRlRecreate: false };
|
|
214
238
|
}
|
|
215
239
|
}
|
|
216
240
|
|
|
@@ -242,23 +266,23 @@ async function processInput(
|
|
|
242
266
|
input: string,
|
|
243
267
|
state: SessionState,
|
|
244
268
|
rl: readline.Interface
|
|
245
|
-
): Promise<{ state: SessionState; shouldExit: boolean }> {
|
|
269
|
+
): Promise<{ state: SessionState; shouldExit: boolean; needsRlRecreate: boolean }> {
|
|
246
270
|
const parsed = parseInput(input);
|
|
247
271
|
|
|
248
272
|
switch (parsed.type) {
|
|
249
273
|
case 'empty':
|
|
250
|
-
return { state, shouldExit: false };
|
|
274
|
+
return { state, shouldExit: false, needsRlRecreate: false };
|
|
251
275
|
|
|
252
276
|
case 'slash-command': {
|
|
253
277
|
const { command } = parsed;
|
|
254
278
|
if (!command) {
|
|
255
|
-
return { state, shouldExit: false };
|
|
279
|
+
return { state, shouldExit: false, needsRlRecreate: false };
|
|
256
280
|
}
|
|
257
281
|
|
|
258
282
|
const resolvedName = resolveCommandAlias(command.name);
|
|
259
283
|
if (!resolvedName) {
|
|
260
284
|
logger.warn(`Unknown command: /${command.name}. Type /help for available commands.`);
|
|
261
|
-
return { state, shouldExit: false };
|
|
285
|
+
return { state, shouldExit: false, needsRlRecreate: false };
|
|
262
286
|
}
|
|
263
287
|
|
|
264
288
|
return executeCommand(resolvedName, command.args, state, rl);
|
|
@@ -266,14 +290,41 @@ async function processInput(
|
|
|
266
290
|
|
|
267
291
|
case 'natural-language': {
|
|
268
292
|
const newState = await handleNaturalLanguage(parsed.text!, state);
|
|
269
|
-
return { state: newState, shouldExit: false };
|
|
293
|
+
return { state: newState, shouldExit: false, needsRlRecreate: false };
|
|
270
294
|
}
|
|
271
295
|
|
|
272
296
|
default:
|
|
273
|
-
return { state, shouldExit: false };
|
|
297
|
+
return { state, shouldExit: false, needsRlRecreate: false };
|
|
274
298
|
}
|
|
275
299
|
}
|
|
276
300
|
|
|
301
|
+
/**
|
|
302
|
+
* Create a new readline interface
|
|
303
|
+
*/
|
|
304
|
+
function createReadline(): readline.Interface {
|
|
305
|
+
return readline.createInterface({
|
|
306
|
+
input: process.stdin,
|
|
307
|
+
output: process.stdout,
|
|
308
|
+
prompt: PROMPT,
|
|
309
|
+
terminal: true,
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Read a single line from readline
|
|
315
|
+
*/
|
|
316
|
+
function readLine(rl: readline.Interface): Promise<string | null> {
|
|
317
|
+
return new Promise((resolve) => {
|
|
318
|
+
rl.once('line', (line) => resolve(line));
|
|
319
|
+
rl.once('close', () => resolve(null));
|
|
320
|
+
rl.once('SIGINT', () => {
|
|
321
|
+
console.log('');
|
|
322
|
+
logger.info('Use /exit to quit');
|
|
323
|
+
rl.prompt();
|
|
324
|
+
});
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
|
|
277
328
|
/**
|
|
278
329
|
* Start the REPL loop
|
|
279
330
|
*/
|
|
@@ -291,30 +342,21 @@ export async function startRepl(initialState: SessionState): Promise<void> {
|
|
|
291
342
|
}
|
|
292
343
|
console.log('');
|
|
293
344
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
output: process.stdout,
|
|
297
|
-
prompt: PROMPT,
|
|
298
|
-
terminal: true,
|
|
299
|
-
});
|
|
345
|
+
let rl = createReadline();
|
|
346
|
+
let running = true;
|
|
300
347
|
|
|
301
|
-
|
|
302
|
-
rl.on('SIGINT', () => {
|
|
303
|
-
console.log('');
|
|
304
|
-
logger.info('Use /exit to quit');
|
|
348
|
+
while (running) {
|
|
305
349
|
rl.prompt();
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
rl.prompt();
|
|
350
|
+
const line = await readLine(rl);
|
|
351
|
+
|
|
352
|
+
// Handle EOF (Ctrl+D)
|
|
353
|
+
if (line === null) {
|
|
354
|
+
console.log('');
|
|
355
|
+
logger.info('Goodbye!');
|
|
356
|
+
running = false;
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
316
359
|
|
|
317
|
-
for await (const line of rl) {
|
|
318
360
|
try {
|
|
319
361
|
const result = await processInput(line, state, rl);
|
|
320
362
|
state = result.state;
|
|
@@ -323,13 +365,17 @@ export async function startRepl(initialState: SessionState): Promise<void> {
|
|
|
323
365
|
console.log('');
|
|
324
366
|
logger.info('Goodbye!');
|
|
325
367
|
rl.close();
|
|
326
|
-
|
|
368
|
+
running = false;
|
|
369
|
+
break;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Recreate readline if needed (after commands that closed it)
|
|
373
|
+
if (result.needsRlRecreate) {
|
|
374
|
+
rl = createReadline();
|
|
327
375
|
}
|
|
328
376
|
} catch (error) {
|
|
329
377
|
logger.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
330
378
|
}
|
|
331
|
-
|
|
332
|
-
rl.prompt();
|
|
333
379
|
}
|
|
334
380
|
}
|
|
335
381
|
|