erosolar-cli 1.7.199 → 1.7.201
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/core/agent.d.ts +3 -0
- package/dist/core/agent.d.ts.map +1 -1
- package/dist/core/agent.js +109 -18
- package/dist/core/agent.js.map +1 -1
- package/dist/core/toolPreconditions.js +1 -1
- package/dist/core/toolPreconditions.js.map +1 -1
- package/dist/core/toolRuntime.js +1 -1
- package/dist/core/toolRuntime.js.map +1 -1
- package/dist/core/toolValidation.js +1 -1
- package/dist/core/toolValidation.js.map +1 -1
- package/dist/shell/interactiveShell.d.ts +18 -0
- package/dist/shell/interactiveShell.d.ts.map +1 -1
- package/dist/shell/interactiveShell.js +100 -23
- package/dist/shell/interactiveShell.js.map +1 -1
- package/dist/shell/terminalInput.d.ts +16 -1
- package/dist/shell/terminalInput.d.ts.map +1 -1
- package/dist/shell/terminalInput.js +86 -31
- package/dist/shell/terminalInput.js.map +1 -1
- package/dist/shell/terminalInputAdapter.d.ts +12 -0
- package/dist/shell/terminalInputAdapter.d.ts.map +1 -1
- package/dist/shell/terminalInputAdapter.js +14 -0
- package/dist/shell/terminalInputAdapter.js.map +1 -1
- package/dist/tools/fileTools.d.ts.map +1 -1
- package/dist/tools/fileTools.js +102 -39
- package/dist/tools/fileTools.js.map +1 -1
- package/dist/ui/display.d.ts +2 -0
- package/dist/ui/display.d.ts.map +1 -1
- package/dist/ui/display.js +9 -13
- package/dist/ui/display.js.map +1 -1
- package/dist/ui/keyboardShortcuts.js +1 -1
- package/dist/ui/keyboardShortcuts.js.map +1 -1
- package/dist/ui/persistentPrompt.d.ts +50 -0
- package/dist/ui/persistentPrompt.d.ts.map +1 -0
- package/dist/ui/persistentPrompt.js +92 -0
- package/dist/ui/persistentPrompt.js.map +1 -0
- package/dist/ui/shortcutsHelp.js +2 -2
- package/dist/ui/shortcutsHelp.js.map +1 -1
- package/package.json +1 -1
|
@@ -74,6 +74,8 @@ export class InteractiveShell {
|
|
|
74
74
|
pendingSecretRetry = null;
|
|
75
75
|
terminalInput;
|
|
76
76
|
currentInput = '';
|
|
77
|
+
ctrlCPressCount = 0;
|
|
78
|
+
ctrlCHandledThisPress = false;
|
|
77
79
|
pendingCleanup = null;
|
|
78
80
|
cleanupInProgress = false;
|
|
79
81
|
slashPreviewVisible = false;
|
|
@@ -94,6 +96,7 @@ export class InteractiveShell {
|
|
|
94
96
|
sessionPreferences;
|
|
95
97
|
autosaveEnabled;
|
|
96
98
|
autoContinueEnabled;
|
|
99
|
+
verificationEnabled = true;
|
|
97
100
|
editGuardMode = 'display-edits';
|
|
98
101
|
pendingPermissionInput = null;
|
|
99
102
|
pendingHistoryLoad = null;
|
|
@@ -184,9 +187,12 @@ export class InteractiveShell {
|
|
|
184
187
|
this.terminalInput = new TerminalInputAdapter(input, output, {
|
|
185
188
|
onSubmit: (text) => this.processInput(text),
|
|
186
189
|
onQueue: (text) => this.handleQueuedInput(text),
|
|
190
|
+
onCtrlC: ({ hadBuffer }) => this.handleCtrlCPress(hadBuffer),
|
|
187
191
|
onInterrupt: () => this.handleInterrupt(),
|
|
188
192
|
onChange: (text) => this.handleInputChange(text),
|
|
189
193
|
onEditModeChange: (mode) => this.handleEditModeChange(mode),
|
|
194
|
+
onToggleVerify: () => this.toggleVerificationMode(),
|
|
195
|
+
onToggleAutoContinue: () => this.toggleAutoContinueMode(),
|
|
190
196
|
});
|
|
191
197
|
// Register output interceptor for cursor positioning during streaming
|
|
192
198
|
this.terminalInput.registerOutputInterceptor(display);
|
|
@@ -195,6 +201,7 @@ export class InteractiveShell {
|
|
|
195
201
|
this.setupStatusTracking();
|
|
196
202
|
this.refreshContextGauge();
|
|
197
203
|
this.terminalInput.start();
|
|
204
|
+
this.refreshControlBar();
|
|
198
205
|
this.rebuildAgent();
|
|
199
206
|
this.setupHandlers();
|
|
200
207
|
this.refreshBannerSessionInfo();
|
|
@@ -281,6 +288,9 @@ export class InteractiveShell {
|
|
|
281
288
|
*/
|
|
282
289
|
handleInputChange(text) {
|
|
283
290
|
this.currentInput = text;
|
|
291
|
+
if (text.length > 0) {
|
|
292
|
+
this.resetCtrlCSequence();
|
|
293
|
+
}
|
|
284
294
|
this.handleSlashCommandPreviewChange();
|
|
285
295
|
}
|
|
286
296
|
/**
|
|
@@ -297,6 +307,41 @@ export class InteractiveShell {
|
|
|
297
307
|
}
|
|
298
308
|
this.terminalInput.render();
|
|
299
309
|
}
|
|
310
|
+
toggleVerificationMode() {
|
|
311
|
+
this.setVerificationMode(!this.verificationEnabled, 'shortcut');
|
|
312
|
+
}
|
|
313
|
+
setVerificationMode(enabled, source) {
|
|
314
|
+
const changed = this.verificationEnabled !== enabled;
|
|
315
|
+
this.verificationEnabled = enabled;
|
|
316
|
+
this.refreshControlBar();
|
|
317
|
+
if (!changed && source === 'shortcut') {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
const message = enabled
|
|
321
|
+
? '✅ Verification on. Auto-tests will run after edits. (alt+v to toggle)'
|
|
322
|
+
: '⏭️ Verification off. Skipping auto-tests until re-enabled. (alt+v to toggle)';
|
|
323
|
+
display.showSystemMessage(message);
|
|
324
|
+
}
|
|
325
|
+
toggleAutoContinueMode() {
|
|
326
|
+
this.setAutoContinueMode(!this.autoContinueEnabled, 'shortcut');
|
|
327
|
+
}
|
|
328
|
+
setAutoContinueMode(enabled, source) {
|
|
329
|
+
const changed = this.autoContinueEnabled !== enabled;
|
|
330
|
+
this.autoContinueEnabled = enabled;
|
|
331
|
+
saveSessionPreferences({ autoContinue: this.autoContinueEnabled });
|
|
332
|
+
if (this.agent) {
|
|
333
|
+
this.agent.setAutoContinue(this.autoContinueEnabled);
|
|
334
|
+
}
|
|
335
|
+
this.refreshControlBar();
|
|
336
|
+
if (!changed && source === 'shortcut') {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
display.showInfo(`Auto-continue ${this.autoContinueEnabled ? 'enabled' : 'disabled'}. ` +
|
|
340
|
+
(this.autoContinueEnabled
|
|
341
|
+
? 'The model will be auto-prompted to continue when it expresses intent but does not use tools.'
|
|
342
|
+
: 'The model will not be auto-prompted to continue.') +
|
|
343
|
+
' Toggle with alt+c.');
|
|
344
|
+
}
|
|
300
345
|
/**
|
|
301
346
|
* Gate submissions when edit permission mode is active.
|
|
302
347
|
* Returns the text to send when approved, or null when waiting for confirmation.
|
|
@@ -342,15 +387,51 @@ export class InteractiveShell {
|
|
|
342
387
|
this.terminalInput.render();
|
|
343
388
|
}
|
|
344
389
|
/**
|
|
345
|
-
*
|
|
390
|
+
* Handle Ctrl+C presses in three stages:
|
|
391
|
+
* 1) Clear chat box text
|
|
392
|
+
* 2) Pause/interrupt AI execution (even while streaming)
|
|
393
|
+
* 3) Quit the program
|
|
346
394
|
*/
|
|
347
|
-
|
|
395
|
+
handleCtrlCPress(hadBuffer) {
|
|
396
|
+
this.ctrlCHandledThisPress = true;
|
|
397
|
+
this.ctrlCPressCount = Math.min(this.ctrlCPressCount + 1, 3);
|
|
398
|
+
if (this.ctrlCPressCount === 1) {
|
|
399
|
+
this.clearChatInput();
|
|
400
|
+
const prefix = hadBuffer ? 'Input cleared.' : 'Nothing to clear.';
|
|
401
|
+
display.showSystemMessage(`${prefix} Press Ctrl+C again to pause the AI; a third time quits.`);
|
|
402
|
+
this.terminalInput.render();
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
if (this.ctrlCPressCount === 2) {
|
|
406
|
+
this.pauseAiExecution();
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
this.shutdown();
|
|
410
|
+
}
|
|
411
|
+
pauseAiExecution() {
|
|
348
412
|
if (this.isProcessing && this.agent) {
|
|
349
413
|
this.agent.requestCancellation();
|
|
350
|
-
display.showWarning('
|
|
414
|
+
display.showWarning('Pausing AI execution... (Press Ctrl+C again to quit)');
|
|
351
415
|
return;
|
|
352
416
|
}
|
|
353
|
-
|
|
417
|
+
display.showInfo('No active AI execution to pause. Press Ctrl+C again to quit.');
|
|
418
|
+
}
|
|
419
|
+
resetCtrlCSequence() {
|
|
420
|
+
this.ctrlCPressCount = 0;
|
|
421
|
+
this.ctrlCHandledThisPress = false;
|
|
422
|
+
}
|
|
423
|
+
clearChatInput() {
|
|
424
|
+
this.pendingPermissionInput = null;
|
|
425
|
+
this.handleInputChange('');
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* TerminalInputAdapter interrupt handler (Ctrl+C with empty buffer)
|
|
429
|
+
*/
|
|
430
|
+
handleInterrupt() {
|
|
431
|
+
if (!this.ctrlCHandledThisPress) {
|
|
432
|
+
this.handleCtrlCPress(false);
|
|
433
|
+
}
|
|
434
|
+
this.ctrlCHandledThisPress = false;
|
|
354
435
|
}
|
|
355
436
|
/**
|
|
356
437
|
* Gracefully tear down the shell and exit
|
|
@@ -570,6 +651,10 @@ export class InteractiveShell {
|
|
|
570
651
|
this.uiAdapter.updateContextUsage(percentage);
|
|
571
652
|
this.terminalInput.setContextUsage(percentage);
|
|
572
653
|
}
|
|
654
|
+
refreshControlBar() {
|
|
655
|
+
// Status indicators are now shown inline in the prompt
|
|
656
|
+
this.terminalInput.render();
|
|
657
|
+
}
|
|
573
658
|
handleSlashCommandPreviewChange() {
|
|
574
659
|
if (this.pendingInteraction) {
|
|
575
660
|
this.slashPreviewVisible = false;
|
|
@@ -631,8 +716,6 @@ export class InteractiveShell {
|
|
|
631
716
|
}
|
|
632
717
|
startStreamingHeartbeat(label = 'Streaming response') {
|
|
633
718
|
this.stopStreamingHeartbeat();
|
|
634
|
-
// Set up scroll region so status stays fixed at bottom while content streams above
|
|
635
|
-
display.setupScrollRegion();
|
|
636
719
|
this.streamingHeartbeatStart = Date.now();
|
|
637
720
|
this.streamingHeartbeatFrame = 0;
|
|
638
721
|
const frames = ['●', '◐', '◉', '◐'];
|
|
@@ -643,10 +726,10 @@ export class InteractiveShell {
|
|
|
643
726
|
? Math.floor((Date.now() - this.streamingHeartbeatStart) / 1000)
|
|
644
727
|
: 0;
|
|
645
728
|
const suffix = elapsed > 0 ? ` • ${elapsed}s` : '';
|
|
646
|
-
|
|
729
|
+
this.terminalInput.setStatusMessage(`${frame} ${label}${suffix}`);
|
|
647
730
|
};
|
|
648
731
|
tick();
|
|
649
|
-
this.streamingHeartbeat = setInterval(tick, 500);
|
|
732
|
+
this.streamingHeartbeat = setInterval(tick, 500);
|
|
650
733
|
}
|
|
651
734
|
stopStreamingHeartbeat() {
|
|
652
735
|
if (this.streamingHeartbeat) {
|
|
@@ -654,9 +737,7 @@ export class InteractiveShell {
|
|
|
654
737
|
this.streamingHeartbeat = null;
|
|
655
738
|
}
|
|
656
739
|
this.streamingHeartbeatStart = null;
|
|
657
|
-
|
|
658
|
-
display.teardownScrollRegion();
|
|
659
|
-
display.clearStreamingStatus();
|
|
740
|
+
this.terminalInput.setStatusMessage(null);
|
|
660
741
|
}
|
|
661
742
|
refreshQueueIndicators() {
|
|
662
743
|
if (this.isProcessing) {
|
|
@@ -1441,23 +1522,14 @@ export class InteractiveShell {
|
|
|
1441
1522
|
if (!value) {
|
|
1442
1523
|
// Show current status
|
|
1443
1524
|
display.showInfo(`Auto-continue is ${this.autoContinueEnabled ? 'enabled' : 'disabled'}. ` +
|
|
1444
|
-
`Use /autocontinue on|off to toggle.`);
|
|
1525
|
+
`Use /autocontinue on|off or alt+c to toggle.`);
|
|
1445
1526
|
return;
|
|
1446
1527
|
}
|
|
1447
1528
|
if (value !== 'on' && value !== 'off') {
|
|
1448
1529
|
display.showWarning('Usage: /autocontinue on|off');
|
|
1449
1530
|
return;
|
|
1450
1531
|
}
|
|
1451
|
-
this.
|
|
1452
|
-
saveSessionPreferences({ autoContinue: this.autoContinueEnabled });
|
|
1453
|
-
// Update the current agent if it exists
|
|
1454
|
-
if (this.agent) {
|
|
1455
|
-
this.agent.setAutoContinue(this.autoContinueEnabled);
|
|
1456
|
-
}
|
|
1457
|
-
display.showInfo(`Auto-continue ${this.autoContinueEnabled ? 'enabled' : 'disabled'}. ` +
|
|
1458
|
-
(this.autoContinueEnabled
|
|
1459
|
-
? 'The model will be auto-prompted to continue when it expresses intent but does not use tools.'
|
|
1460
|
-
: 'The model will not be auto-prompted to continue.'));
|
|
1532
|
+
this.setAutoContinueMode(value === 'on', 'command');
|
|
1461
1533
|
}
|
|
1462
1534
|
updateActiveSession(summary, remember = false) {
|
|
1463
1535
|
this.activeSessionId = summary?.id ?? null;
|
|
@@ -2464,6 +2536,9 @@ What's the next action?`;
|
|
|
2464
2536
|
if (this.autoTestInFlight) {
|
|
2465
2537
|
return;
|
|
2466
2538
|
}
|
|
2539
|
+
if (!this.verificationEnabled) {
|
|
2540
|
+
return;
|
|
2541
|
+
}
|
|
2467
2542
|
const latestChange = this.getLatestFileChangeTimestamp();
|
|
2468
2543
|
if (!latestChange) {
|
|
2469
2544
|
return;
|
|
@@ -2930,7 +3005,9 @@ What's the next action?`;
|
|
|
2930
3005
|
handleStreamingFallback(info) {
|
|
2931
3006
|
const detailText = info.message.trim();
|
|
2932
3007
|
const detail = detailText ? ` Error: ${detailText}` : '';
|
|
2933
|
-
|
|
3008
|
+
const reason = info.reason ? ` (${info.reason.replace(/-/g, ' ')})` : '';
|
|
3009
|
+
const partialNote = info.partialResponse ? ' Received partial stream before failure.' : '';
|
|
3010
|
+
display.showWarning(`Streaming failed${reason}, retrying without streaming.${detail}${partialNote}`);
|
|
2934
3011
|
this.startStreamingHeartbeat('Fallback in progress');
|
|
2935
3012
|
this.requestPromptRefresh(true);
|
|
2936
3013
|
}
|