erosolar-cli 1.7.396 → 1.7.398
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/browser/BrowserSessionManager.d.ts +3 -1
- package/dist/browser/BrowserSessionManager.d.ts.map +1 -1
- package/dist/browser/BrowserSessionManager.js +24 -4
- package/dist/browser/BrowserSessionManager.js.map +1 -1
- package/dist/contracts/agent-schemas.json +5 -0
- package/dist/contracts/unified-schema.json +2 -1
- package/dist/core/agent.d.ts +5 -0
- package/dist/core/agent.d.ts.map +1 -1
- package/dist/core/agent.js +99 -0
- package/dist/core/agent.js.map +1 -1
- package/dist/core/alphaZeroConfig.d.ts +11 -0
- package/dist/core/alphaZeroConfig.d.ts.map +1 -0
- package/dist/core/alphaZeroConfig.js +59 -0
- package/dist/core/alphaZeroConfig.js.map +1 -0
- package/dist/core/alphaZeroEngine.d.ts +8 -0
- package/dist/core/alphaZeroEngine.d.ts.map +1 -1
- package/dist/core/alphaZeroEngine.js +149 -35
- package/dist/core/alphaZeroEngine.js.map +1 -1
- package/dist/core/alphaZeroEnhanced.d.ts +125 -0
- package/dist/core/alphaZeroEnhanced.d.ts.map +1 -0
- package/dist/core/alphaZeroEnhanced.js +386 -0
- package/dist/core/alphaZeroEnhanced.js.map +1 -0
- package/dist/core/alphaZeroOrchestrator.d.ts +17 -0
- package/dist/core/alphaZeroOrchestrator.d.ts.map +1 -1
- package/dist/core/alphaZeroOrchestrator.js +95 -8
- package/dist/core/alphaZeroOrchestrator.js.map +1 -1
- package/dist/core/autonomousVerification.d.ts +103 -0
- package/dist/core/autonomousVerification.d.ts.map +1 -0
- package/dist/core/autonomousVerification.js +583 -0
- package/dist/core/autonomousVerification.js.map +1 -0
- package/dist/core/cliTestHarness.d.ts +5 -0
- package/dist/core/cliTestHarness.d.ts.map +1 -1
- package/dist/core/cliTestHarness.js +14 -3
- package/dist/core/cliTestHarness.js.map +1 -1
- package/dist/core/contextManager.d.ts +10 -0
- package/dist/core/contextManager.d.ts.map +1 -1
- package/dist/core/contextManager.js +18 -0
- package/dist/core/contextManager.js.map +1 -1
- package/dist/core/offsecAlphaZeroEnhanced.d.ts +98 -0
- package/dist/core/offsecAlphaZeroEnhanced.d.ts.map +1 -0
- package/dist/core/offsecAlphaZeroEnhanced.js +441 -0
- package/dist/core/offsecAlphaZeroEnhanced.js.map +1 -0
- package/dist/core/parallelAgentOrchestrator.d.ts +171 -0
- package/dist/core/parallelAgentOrchestrator.d.ts.map +1 -0
- package/dist/core/parallelAgentOrchestrator.js +459 -0
- package/dist/core/parallelAgentOrchestrator.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/shell/interactiveShell.d.ts +15 -0
- package/dist/shell/interactiveShell.d.ts.map +1 -1
- package/dist/shell/interactiveShell.js +344 -210
- package/dist/shell/interactiveShell.js.map +1 -1
- package/dist/shell/shellApp.d.ts.map +1 -1
- package/dist/shell/shellApp.js +15 -1
- package/dist/shell/shellApp.js.map +1 -1
- package/dist/shell/terminalInput.d.ts +42 -1
- package/dist/shell/terminalInput.d.ts.map +1 -1
- package/dist/shell/terminalInput.js +276 -6
- package/dist/shell/terminalInput.js.map +1 -1
- package/dist/shell/terminalInputAdapter.d.ts +14 -2
- package/dist/shell/terminalInputAdapter.d.ts.map +1 -1
- package/dist/shell/terminalInputAdapter.js +19 -1
- package/dist/shell/terminalInputAdapter.js.map +1 -1
- package/dist/ui/assistantBlockRenderer.d.ts +28 -0
- package/dist/ui/assistantBlockRenderer.d.ts.map +1 -0
- package/dist/ui/assistantBlockRenderer.js +99 -0
- package/dist/ui/assistantBlockRenderer.js.map +1 -0
- package/dist/ui/display.d.ts +11 -0
- package/dist/ui/display.d.ts.map +1 -1
- package/dist/ui/display.js +37 -0
- package/dist/ui/display.js.map +1 -1
- package/dist/ui/theme.d.ts +80 -81
- package/dist/ui/theme.d.ts.map +1 -1
- package/dist/ui/unified/layout.d.ts +0 -23
- package/dist/ui/unified/layout.d.ts.map +1 -1
- package/dist/ui/unified/layout.js +11 -114
- package/dist/ui/unified/layout.js.map +1 -1
- package/package.json +33 -19
|
@@ -2,6 +2,7 @@ import { stdin as input, stdout as output, exit } from 'node:process';
|
|
|
2
2
|
import { exec } from 'node:child_process';
|
|
3
3
|
import { promisify } from 'node:util';
|
|
4
4
|
import { createInterface } from 'node:readline/promises';
|
|
5
|
+
import { AssistantBlockRenderer } from '../ui/assistantBlockRenderer.js';
|
|
5
6
|
import { display } from '../ui/display.js';
|
|
6
7
|
import { theme } from '../ui/theme.js';
|
|
7
8
|
import { getContextWindowTokens } from '../core/contextWindow.js';
|
|
@@ -114,6 +115,8 @@ export class InteractiveShell {
|
|
|
114
115
|
ui;
|
|
115
116
|
uiAdapter;
|
|
116
117
|
uiUpdates;
|
|
118
|
+
assistantBlocksEnabled;
|
|
119
|
+
assistantBlockRenderer = null;
|
|
117
120
|
_fileChangeTracker = new FileChangeTracker(); // Reserved for future file tracking features
|
|
118
121
|
alphaZeroMetrics; // Alpha Zero 2 performance tracking
|
|
119
122
|
statusSubscription = null;
|
|
@@ -168,15 +171,19 @@ export class InteractiveShell {
|
|
|
168
171
|
streamingHeartbeatStart = null;
|
|
169
172
|
streamingHeartbeatFrame = 0;
|
|
170
173
|
streamingStatusLabel = null;
|
|
174
|
+
streamingStatusBase = null;
|
|
175
|
+
streamingStatusDetail = null;
|
|
171
176
|
lastStreamingElapsedSeconds = null; // Preserve final elapsed time
|
|
172
177
|
statusLineState = null;
|
|
173
178
|
statusMessageOverride = null;
|
|
179
|
+
latestThoughtSummary = null;
|
|
174
180
|
hasShownThoughtProcess = false;
|
|
175
181
|
promptRefreshTimer = null;
|
|
176
182
|
launchPaletteShown = false;
|
|
177
183
|
version;
|
|
178
184
|
alternateScreenEnabled;
|
|
179
185
|
inputInitialized = false;
|
|
186
|
+
assistantStreamBuffer = '';
|
|
180
187
|
constructor(config) {
|
|
181
188
|
this.profile = config.profile;
|
|
182
189
|
this.profileLabel = config.profileLabel;
|
|
@@ -192,6 +199,7 @@ export class InteractiveShell {
|
|
|
192
199
|
this.sessionRestoreConfig = config.sessionRestore ?? { mode: 'none' };
|
|
193
200
|
this._enabledPlugins = config.enabledPlugins ?? [];
|
|
194
201
|
this.version = config.version ?? '0.0.0';
|
|
202
|
+
this.assistantBlocksEnabled = Boolean(config.assistantBlocksEnabled);
|
|
195
203
|
// Alternate screen disabled - use terminal-native mode for proper scrollback and text selection
|
|
196
204
|
this.alternateScreenEnabled = false;
|
|
197
205
|
this.initializeSessionHistory();
|
|
@@ -287,6 +295,12 @@ export class InteractiveShell {
|
|
|
287
295
|
onToggleAlphaZero: () => this.toggleAlphaZeroMode('shortcut'),
|
|
288
296
|
onClearContext: () => this.handleClearContext(),
|
|
289
297
|
});
|
|
298
|
+
if (this.assistantBlocksEnabled) {
|
|
299
|
+
this.assistantBlockRenderer = new AssistantBlockRenderer({
|
|
300
|
+
write: (text) => this.terminalInput.streamContent(text),
|
|
301
|
+
updates: this.uiUpdates,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
290
304
|
// Initialize Alpha Zero 2 metrics tracking
|
|
291
305
|
this.alphaZeroMetrics = new MetricsTracker(`${this.profile}-${Date.now()}`);
|
|
292
306
|
this.setupStatusTracking();
|
|
@@ -538,7 +552,8 @@ export class InteractiveShell {
|
|
|
538
552
|
// Keep adapter queue trimmed so hints stay accurate
|
|
539
553
|
this.terminalInput.dequeue();
|
|
540
554
|
this.followUpQueue.push({ type: 'request', text });
|
|
541
|
-
|
|
555
|
+
// Record the queued action in the pinned recent strip instead of the scroll log
|
|
556
|
+
this.terminalInput.recordRecentAction(`queued: ${text}`);
|
|
542
557
|
this.refreshQueueIndicators();
|
|
543
558
|
this.scheduleQueueProcessing();
|
|
544
559
|
this.handleInputChange('');
|
|
@@ -599,15 +614,30 @@ export class InteractiveShell {
|
|
|
599
614
|
* Execute a command immediately during streaming.
|
|
600
615
|
*/
|
|
601
616
|
async executeImmediateCommand(text) {
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
617
|
+
const label = text.trim() || 'command';
|
|
618
|
+
// Keep the action visible in the pinned input area instead of the scroll log
|
|
619
|
+
this.terminalInput.recordRecentAction(label);
|
|
620
|
+
// Surface a lightweight inline status while the command runs
|
|
621
|
+
const previousOverride = this.statusMessageOverride;
|
|
622
|
+
this.statusMessageOverride = `Running ${label}`;
|
|
623
|
+
this.refreshStatusLine(true);
|
|
624
|
+
try {
|
|
625
|
+
await this.processSlashCommand(text);
|
|
626
|
+
}
|
|
627
|
+
finally {
|
|
628
|
+
this.statusMessageOverride = previousOverride;
|
|
629
|
+
this.refreshStatusLine(true);
|
|
630
|
+
}
|
|
605
631
|
}
|
|
606
632
|
/**
|
|
607
633
|
* TerminalInputAdapter change handler
|
|
608
634
|
*/
|
|
609
635
|
handleInputChange(text) {
|
|
636
|
+
const previous = this.currentInput;
|
|
610
637
|
this.currentInput = text;
|
|
638
|
+
if (previous !== text) {
|
|
639
|
+
this.terminalInput.clearInlineCommandPanel();
|
|
640
|
+
}
|
|
611
641
|
if (text.length > 0) {
|
|
612
642
|
this.resetCtrlCSequence();
|
|
613
643
|
}
|
|
@@ -1298,9 +1328,13 @@ export class InteractiveShell {
|
|
|
1298
1328
|
alphaZeroHotkey: 'ctrl+shift+a',
|
|
1299
1329
|
alphaZeroLabel: 'AlphaZero RL',
|
|
1300
1330
|
});
|
|
1331
|
+
this.refreshFeatureStatusDisplay();
|
|
1301
1332
|
this.refreshStatusLine();
|
|
1302
1333
|
this.renderPromptArea();
|
|
1303
1334
|
}
|
|
1335
|
+
refreshFeatureStatusDisplay() {
|
|
1336
|
+
this.terminalInput.setFeatureStatus(this.buildFeatureStatusSnapshot());
|
|
1337
|
+
}
|
|
1304
1338
|
writeLocked(content) {
|
|
1305
1339
|
if (!content) {
|
|
1306
1340
|
return;
|
|
@@ -1308,6 +1342,29 @@ export class InteractiveShell {
|
|
|
1308
1342
|
// Route through display stream so scroll regions and streaming locks stay in sync
|
|
1309
1343
|
display.stream(content);
|
|
1310
1344
|
}
|
|
1345
|
+
resetAssistantStreamBuffer() {
|
|
1346
|
+
this.assistantStreamBuffer = '';
|
|
1347
|
+
}
|
|
1348
|
+
appendAssistantStreamChunk(chunk) {
|
|
1349
|
+
if (!this.assistantBlocksEnabled || !chunk) {
|
|
1350
|
+
return;
|
|
1351
|
+
}
|
|
1352
|
+
this.assistantStreamBuffer += chunk;
|
|
1353
|
+
}
|
|
1354
|
+
consumeAssistantStreamBuffer(fallback) {
|
|
1355
|
+
const buffered = this.assistantStreamBuffer;
|
|
1356
|
+
this.assistantStreamBuffer = '';
|
|
1357
|
+
if (buffered.trim()) {
|
|
1358
|
+
return buffered;
|
|
1359
|
+
}
|
|
1360
|
+
return fallback ?? '';
|
|
1361
|
+
}
|
|
1362
|
+
renderAssistantBlock(type, content, metadata) {
|
|
1363
|
+
if (!this.assistantBlockRenderer) {
|
|
1364
|
+
return;
|
|
1365
|
+
}
|
|
1366
|
+
this.assistantBlockRenderer.renderBlock(type, content, metadata);
|
|
1367
|
+
}
|
|
1311
1368
|
isStreamingUiActive() {
|
|
1312
1369
|
return this.streamingHeartbeatStart !== null;
|
|
1313
1370
|
}
|
|
@@ -1356,19 +1413,23 @@ export class InteractiveShell {
|
|
|
1356
1413
|
// Surface meta header (elapsed + context usage) above the divider
|
|
1357
1414
|
// Use streaming elapsed time if available, otherwise fall back to status line state
|
|
1358
1415
|
let elapsedSeconds = null;
|
|
1359
|
-
|
|
1416
|
+
const shouldShowElapsed = this.streamingHeartbeatStart !== null || this.isProcessing;
|
|
1417
|
+
if (this.streamingHeartbeatStart && shouldShowElapsed) {
|
|
1360
1418
|
// Actively streaming - compute live elapsed
|
|
1361
1419
|
elapsedSeconds = Math.max(0, Math.floor((Date.now() - this.streamingHeartbeatStart) / 1000));
|
|
1362
1420
|
}
|
|
1363
|
-
else if (this.lastStreamingElapsedSeconds !== null) {
|
|
1421
|
+
else if (shouldShowElapsed && this.lastStreamingElapsedSeconds !== null) {
|
|
1364
1422
|
// Just finished streaming - use preserved final time
|
|
1365
1423
|
elapsedSeconds = this.lastStreamingElapsedSeconds;
|
|
1366
1424
|
}
|
|
1367
|
-
else if (this.statusLineState) {
|
|
1425
|
+
else if (shouldShowElapsed && this.statusLineState) {
|
|
1368
1426
|
// Fallback to status line state elapsed
|
|
1369
1427
|
elapsedSeconds = Math.max(0, Math.floor((Date.now() - this.statusLineState.startedAt) / 1000));
|
|
1370
1428
|
}
|
|
1371
|
-
const
|
|
1429
|
+
const hasThoughtSummary = !!this.latestThoughtSummary;
|
|
1430
|
+
const thinkingMs = hasThoughtSummary && display.isSpinnerActive()
|
|
1431
|
+
? display.getThinkingElapsedMs()
|
|
1432
|
+
: null;
|
|
1372
1433
|
const tokensUsed = this.latestTokenUsage.used;
|
|
1373
1434
|
const tokenLimit = this.latestTokenUsage.limit ?? this.activeContextWindowTokens;
|
|
1374
1435
|
this.terminalInput.setMetaStatus({
|
|
@@ -1376,7 +1437,7 @@ export class InteractiveShell {
|
|
|
1376
1437
|
tokensUsed,
|
|
1377
1438
|
tokenLimit,
|
|
1378
1439
|
thinkingMs,
|
|
1379
|
-
thinkingHasContent:
|
|
1440
|
+
thinkingHasContent: hasThoughtSummary,
|
|
1380
1441
|
});
|
|
1381
1442
|
// Keep model/provider visible in the controls bar
|
|
1382
1443
|
this.terminalInput.setModelContext({
|
|
@@ -1483,14 +1544,17 @@ export class InteractiveShell {
|
|
|
1483
1544
|
this.stopStreamingHeartbeat();
|
|
1484
1545
|
// Enter global streaming mode - blocks all non-streaming UI output
|
|
1485
1546
|
enterStreamingMode();
|
|
1547
|
+
this.resetAssistantStreamBuffer();
|
|
1548
|
+
this.streamingStatusBase = label;
|
|
1549
|
+
this.streamingStatusDetail = null;
|
|
1550
|
+
this.latestThoughtSummary = null;
|
|
1551
|
+
this.lastStreamingElapsedSeconds = null;
|
|
1486
1552
|
// Set up scroll region for streaming content
|
|
1487
1553
|
this.terminalInput.enterStreamingScrollRegion();
|
|
1488
1554
|
this.uiUpdates.setMode('streaming');
|
|
1489
1555
|
this.streamingHeartbeatStart = Date.now();
|
|
1490
1556
|
this.streamingHeartbeatFrame = 0;
|
|
1491
|
-
|
|
1492
|
-
this.streamingStatusLabel = this.buildStreamingStatus(`${initialFrame} ${label}`, 0);
|
|
1493
|
-
display.updateStreamingStatus(this.streamingStatusLabel);
|
|
1557
|
+
this.rebuildStreamingStatusLabel();
|
|
1494
1558
|
this.refreshStatusLine(true);
|
|
1495
1559
|
// Periodically refresh the pinned input/status region while streaming so
|
|
1496
1560
|
// elapsed time remains visible without interrupting the scroll region.
|
|
@@ -1500,14 +1564,9 @@ export class InteractiveShell {
|
|
|
1500
1564
|
mode: ['streaming', 'processing'],
|
|
1501
1565
|
coalesceKey: 'streaming:heartbeat',
|
|
1502
1566
|
run: () => {
|
|
1503
|
-
const elapsedSeconds = this.streamingHeartbeatStart
|
|
1504
|
-
? Math.max(0, Math.floor((Date.now() - this.streamingHeartbeatStart) / 1000))
|
|
1505
|
-
: 0;
|
|
1506
1567
|
this.streamingHeartbeatFrame =
|
|
1507
1568
|
(this.streamingHeartbeatFrame + 1) % STREAMING_SPINNER_FRAMES.length;
|
|
1508
|
-
|
|
1509
|
-
this.streamingStatusLabel = this.buildStreamingStatus(`${frame} ${label}`, elapsedSeconds);
|
|
1510
|
-
display.updateStreamingStatus(this.streamingStatusLabel);
|
|
1569
|
+
this.rebuildStreamingStatusLabel();
|
|
1511
1570
|
// Update parallel agent display during streaming
|
|
1512
1571
|
const manager = getParallelAgentManager();
|
|
1513
1572
|
if (manager.isRunning()) {
|
|
@@ -1531,6 +1590,9 @@ export class InteractiveShell {
|
|
|
1531
1590
|
this.streamingHeartbeatStart = null;
|
|
1532
1591
|
this.streamingHeartbeatFrame = 0;
|
|
1533
1592
|
this.streamingStatusLabel = null;
|
|
1593
|
+
this.streamingStatusBase = null;
|
|
1594
|
+
this.streamingStatusDetail = null;
|
|
1595
|
+
this.latestThoughtSummary = null;
|
|
1534
1596
|
// Clear streaming label specifically (keeps override and main status if set)
|
|
1535
1597
|
this.terminalInput.setStreamingLabel(null);
|
|
1536
1598
|
// Clear streaming status from display
|
|
@@ -1540,9 +1602,25 @@ export class InteractiveShell {
|
|
|
1540
1602
|
}
|
|
1541
1603
|
buildStreamingStatus(label, _elapsedSeconds) {
|
|
1542
1604
|
// Model + elapsed time already live in the pinned meta header; keep the streaming
|
|
1543
|
-
// status focused on the activity
|
|
1605
|
+
// status focused on the activity and most recent thought summary.
|
|
1544
1606
|
const prefix = theme.info('⏺');
|
|
1545
|
-
|
|
1607
|
+
const parts = [label.trim()];
|
|
1608
|
+
if (this.streamingStatusDetail) {
|
|
1609
|
+
const detail = this.streamingStatusDetail.length > 52
|
|
1610
|
+
? `${this.streamingStatusDetail.slice(0, 51)}…`
|
|
1611
|
+
: this.streamingStatusDetail;
|
|
1612
|
+
parts.push(theme.ui.muted(detail));
|
|
1613
|
+
}
|
|
1614
|
+
return `${prefix} ${parts.join(' · ')}`.trim();
|
|
1615
|
+
}
|
|
1616
|
+
rebuildStreamingStatusLabel() {
|
|
1617
|
+
if (this.streamingHeartbeatStart === null) {
|
|
1618
|
+
return;
|
|
1619
|
+
}
|
|
1620
|
+
const frame = STREAMING_SPINNER_FRAMES[this.streamingHeartbeatFrame];
|
|
1621
|
+
const base = this.streamingStatusBase ?? 'Streaming';
|
|
1622
|
+
this.streamingStatusLabel = this.buildStreamingStatus(`${frame} ${base}`);
|
|
1623
|
+
display.updateStreamingStatus(this.streamingStatusLabel);
|
|
1546
1624
|
}
|
|
1547
1625
|
formatElapsedShort(seconds) {
|
|
1548
1626
|
if (seconds < 60) {
|
|
@@ -1886,170 +1964,197 @@ export class InteractiveShell {
|
|
|
1886
1964
|
this.renderPromptArea();
|
|
1887
1965
|
return;
|
|
1888
1966
|
}
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
1967
|
+
// Keep the slash action visible in the pinned recent strip
|
|
1968
|
+
this.terminalInput.recordRecentAction(command);
|
|
1969
|
+
const runCommand = async () => {
|
|
1970
|
+
switch (command) {
|
|
1971
|
+
case '/help':
|
|
1972
|
+
case '/?':
|
|
1973
|
+
this.showHelp();
|
|
1974
|
+
break;
|
|
1975
|
+
case '/features':
|
|
1976
|
+
this.showFeaturesMenu(input);
|
|
1977
|
+
break;
|
|
1978
|
+
case '/learn':
|
|
1979
|
+
this.showLearningStatus(input);
|
|
1980
|
+
break;
|
|
1981
|
+
case '/improve':
|
|
1982
|
+
void this.handleImprovementCommand(input);
|
|
1983
|
+
break;
|
|
1984
|
+
case '/model':
|
|
1985
|
+
this.showModelMenu();
|
|
1986
|
+
break;
|
|
1987
|
+
case '/exit':
|
|
1988
|
+
case '/quit':
|
|
1989
|
+
case '/q':
|
|
1990
|
+
this.shutdown();
|
|
1991
|
+
break;
|
|
1992
|
+
case '/secrets':
|
|
1993
|
+
this.showSecretsMenu();
|
|
1994
|
+
break;
|
|
1995
|
+
case '/tools':
|
|
1996
|
+
this.showToolsMenu();
|
|
1997
|
+
break;
|
|
1998
|
+
case '/mcp':
|
|
1999
|
+
await this.showMcpStatus();
|
|
2000
|
+
break;
|
|
2001
|
+
case '/doctor':
|
|
2002
|
+
this.runDoctor();
|
|
2003
|
+
break;
|
|
2004
|
+
case '/checks':
|
|
2005
|
+
await this.runRepoChecksCommand();
|
|
2006
|
+
break;
|
|
2007
|
+
case '/context':
|
|
2008
|
+
await this.refreshWorkspaceContextCommand(input);
|
|
2009
|
+
break;
|
|
2010
|
+
case '/agents':
|
|
2011
|
+
this.showAgentsMenu();
|
|
2012
|
+
break;
|
|
2013
|
+
case '/sessions':
|
|
2014
|
+
await this.handleSessionCommand(input);
|
|
2015
|
+
break;
|
|
2016
|
+
case '/skills':
|
|
2017
|
+
await this.handleSkillsCommand(input);
|
|
2018
|
+
break;
|
|
2019
|
+
case '/thinking':
|
|
2020
|
+
this.handleThinkingCommand(input);
|
|
2021
|
+
break;
|
|
2022
|
+
case '/autocontinue':
|
|
2023
|
+
this.handleAutoContinueCommand(input);
|
|
2024
|
+
break;
|
|
2025
|
+
case '/alphazero':
|
|
2026
|
+
this.handleAlphaZeroCommand(input);
|
|
2027
|
+
break;
|
|
2028
|
+
case '/shortcuts':
|
|
2029
|
+
case '/keys':
|
|
2030
|
+
this.handleShortcutsCommand();
|
|
2031
|
+
break;
|
|
2032
|
+
case '/changes':
|
|
2033
|
+
case '/summary':
|
|
2034
|
+
this.showFileChangeSummary();
|
|
2035
|
+
break;
|
|
2036
|
+
case '/metrics':
|
|
2037
|
+
case '/stats':
|
|
2038
|
+
case '/perf':
|
|
2039
|
+
this.showAlphaZeroMetrics();
|
|
2040
|
+
break;
|
|
2041
|
+
case '/suggestions':
|
|
2042
|
+
case '/improve':
|
|
2043
|
+
this.showImprovementSuggestions();
|
|
2044
|
+
break;
|
|
2045
|
+
case '/plugins':
|
|
2046
|
+
this.showPluginStatus();
|
|
2047
|
+
break;
|
|
2048
|
+
case '/evolve':
|
|
2049
|
+
void this.handleEvolveCommand(input);
|
|
2050
|
+
break;
|
|
2051
|
+
case '/modular':
|
|
2052
|
+
case '/a0':
|
|
2053
|
+
void this.handleModularCommand(input);
|
|
2054
|
+
break;
|
|
2055
|
+
case '/offsec':
|
|
2056
|
+
void this.handleOffsecCommand(input);
|
|
2057
|
+
break;
|
|
2058
|
+
case '/test':
|
|
2059
|
+
case '/tests':
|
|
2060
|
+
void this.handleTestCommand(input);
|
|
2061
|
+
break;
|
|
2062
|
+
case '/provider':
|
|
2063
|
+
await this.handleProviderCommand(input);
|
|
2064
|
+
break;
|
|
2065
|
+
case '/providers':
|
|
2066
|
+
this.showConfiguredProviders();
|
|
2067
|
+
break;
|
|
2068
|
+
case '/local':
|
|
2069
|
+
await this.handleLocalCommand(input);
|
|
2070
|
+
break;
|
|
2071
|
+
case '/discover':
|
|
2072
|
+
await this.discoverModelsCommand();
|
|
2073
|
+
break;
|
|
2074
|
+
// Claude Code style commands
|
|
2075
|
+
case '/rewind':
|
|
2076
|
+
await this.handleRewindCommand(input);
|
|
2077
|
+
break;
|
|
2078
|
+
case '/memory':
|
|
2079
|
+
this.handleMemoryCommand(input);
|
|
2080
|
+
break;
|
|
2081
|
+
case '/vim':
|
|
2082
|
+
this.handleVimCommand();
|
|
2083
|
+
break;
|
|
2084
|
+
case '/output-style':
|
|
2085
|
+
this.handleOutputStyleCommand(input);
|
|
2086
|
+
break;
|
|
2087
|
+
case '/cost':
|
|
2088
|
+
this.handleCostCommand();
|
|
2089
|
+
break;
|
|
2090
|
+
case '/usage':
|
|
2091
|
+
this.handleUsageCommand();
|
|
2092
|
+
break;
|
|
2093
|
+
case '/update':
|
|
2094
|
+
await this.handleUpdateCommand();
|
|
2095
|
+
break;
|
|
2096
|
+
case '/clear':
|
|
2097
|
+
this.handleClearCommand();
|
|
2098
|
+
break;
|
|
2099
|
+
case '/resume':
|
|
2100
|
+
await this.handleResumeCommand(input);
|
|
2101
|
+
break;
|
|
2102
|
+
case '/export':
|
|
2103
|
+
this.handleExportCommand(input);
|
|
2104
|
+
break;
|
|
2105
|
+
case '/review':
|
|
2106
|
+
await this.handleReviewCommand();
|
|
2107
|
+
break;
|
|
2108
|
+
case '/security-review':
|
|
2109
|
+
await this.handleSecurityReviewCommand();
|
|
2110
|
+
break;
|
|
2111
|
+
case '/bug':
|
|
2112
|
+
this.handleBugCommand();
|
|
2113
|
+
break;
|
|
2114
|
+
case '/terminal-setup':
|
|
2115
|
+
this.handleTerminalSetupCommand();
|
|
2116
|
+
break;
|
|
2117
|
+
case '/permissions':
|
|
2118
|
+
this.handlePermissionsCommand();
|
|
2119
|
+
break;
|
|
2120
|
+
case '/init':
|
|
2121
|
+
this.handleInitCommand();
|
|
2122
|
+
break;
|
|
2123
|
+
case '/compact':
|
|
2124
|
+
await this.handleCompactCommand();
|
|
2125
|
+
break;
|
|
2126
|
+
default:
|
|
2127
|
+
if (!(await this.tryCustomSlashCommand(command, input))) {
|
|
2128
|
+
display.showWarning(`Unknown command "${command}".`);
|
|
2129
|
+
}
|
|
2130
|
+
break;
|
|
2131
|
+
}
|
|
2132
|
+
};
|
|
2133
|
+
let capturedOutput = '';
|
|
2134
|
+
try {
|
|
2135
|
+
const { output: outputBuffer } = await display.captureOutput(runCommand);
|
|
2136
|
+
capturedOutput = outputBuffer;
|
|
2050
2137
|
}
|
|
2138
|
+
catch (error) {
|
|
2139
|
+
capturedOutput = error?.capturedOutput ?? capturedOutput;
|
|
2140
|
+
display.showError(error instanceof Error ? error.message : String(error), error);
|
|
2141
|
+
}
|
|
2142
|
+
const panelContent = this.buildInlineCommandPanel(command, capturedOutput);
|
|
2143
|
+
this.terminalInput.setInlineCommandPanel(panelContent);
|
|
2051
2144
|
this.renderPromptArea();
|
|
2052
2145
|
}
|
|
2146
|
+
buildInlineCommandPanel(command, output) {
|
|
2147
|
+
const normalized = output ? output.replace(/\r\n/g, '\n').replace(/\r/g, '\n').trimEnd() : '';
|
|
2148
|
+
if (!normalized) {
|
|
2149
|
+
return null;
|
|
2150
|
+
}
|
|
2151
|
+
const header = theme.ui.muted(command);
|
|
2152
|
+
const body = normalized.split('\n');
|
|
2153
|
+
if (body.length === 1) {
|
|
2154
|
+
return [`${header} ${body[0] ?? ''}`.trimEnd()];
|
|
2155
|
+
}
|
|
2156
|
+
return [header, ...body];
|
|
2157
|
+
}
|
|
2053
2158
|
async tryCustomSlashCommand(command, fullInput) {
|
|
2054
2159
|
const custom = this.customCommandMap.get(command);
|
|
2055
2160
|
if (!custom) {
|
|
@@ -2476,6 +2581,7 @@ export class InteractiveShell {
|
|
|
2476
2581
|
const updated = toggleFeatureFlag(matchedKey, newValue);
|
|
2477
2582
|
const status = updated[matchedKey] ? theme.success('enabled') : theme.ui.muted('disabled');
|
|
2478
2583
|
display.showInfo(`Feature "${FEATURE_FLAG_INFO[matchedKey].label}" is now ${status}.`);
|
|
2584
|
+
this.refreshFeatureStatusDisplay();
|
|
2479
2585
|
display.showInfo('Changes will take effect on next launch or after /features refresh.');
|
|
2480
2586
|
return;
|
|
2481
2587
|
}
|
|
@@ -2488,6 +2594,7 @@ export class InteractiveShell {
|
|
|
2488
2594
|
}
|
|
2489
2595
|
saveFeatureFlags(updated);
|
|
2490
2596
|
display.showInfo(`All features ${newValue ? theme.success('enabled') : theme.ui.muted('disabled')}.`);
|
|
2597
|
+
this.refreshFeatureStatusDisplay();
|
|
2491
2598
|
return;
|
|
2492
2599
|
}
|
|
2493
2600
|
else {
|
|
@@ -3660,9 +3767,7 @@ export class InteractiveShell {
|
|
|
3660
3767
|
}
|
|
3661
3768
|
display.showInfo(`Deleted session "${summary.title}".`);
|
|
3662
3769
|
if (this.activeSessionId === summary.id) {
|
|
3663
|
-
this.
|
|
3664
|
-
this.activeSessionTitle = null;
|
|
3665
|
-
saveSessionPreferences({ lastSessionId: null });
|
|
3770
|
+
this.updateActiveSession(null, true);
|
|
3666
3771
|
}
|
|
3667
3772
|
}
|
|
3668
3773
|
newSessionCommand(title) {
|
|
@@ -3682,6 +3787,7 @@ export class InteractiveShell {
|
|
|
3682
3787
|
clearAutosaveSnapshot(this.profile);
|
|
3683
3788
|
display.showInfo('Started a new empty session.');
|
|
3684
3789
|
this.refreshContextGauge();
|
|
3790
|
+
this.refreshFeatureStatusDisplay();
|
|
3685
3791
|
}
|
|
3686
3792
|
toggleAutosaveCommand(value) {
|
|
3687
3793
|
if (!value) {
|
|
@@ -3999,6 +4105,7 @@ export class InteractiveShell {
|
|
|
3999
4105
|
if (remember) {
|
|
4000
4106
|
saveSessionPreferences({ lastSessionId: summary?.id ?? null });
|
|
4001
4107
|
}
|
|
4108
|
+
this.refreshFeatureStatusDisplay();
|
|
4002
4109
|
}
|
|
4003
4110
|
resolveSessionBySelector(selector) {
|
|
4004
4111
|
const sessions = listSessions(this.profile);
|
|
@@ -5670,20 +5777,38 @@ What's the next action?`;
|
|
|
5670
5777
|
};
|
|
5671
5778
|
this.agent = this.runtimeSession.createAgent(selection, {
|
|
5672
5779
|
onStreamChunk: (chunk) => {
|
|
5780
|
+
if (this.assistantBlocksEnabled) {
|
|
5781
|
+
this.appendAssistantStreamChunk(chunk);
|
|
5782
|
+
return;
|
|
5783
|
+
}
|
|
5673
5784
|
// Stream output using clean streamContent() - chat box floats below
|
|
5674
5785
|
this.terminalInput.streamContent(chunk);
|
|
5675
5786
|
},
|
|
5676
5787
|
onStreamFallback: (info) => this.handleStreamingFallback(info),
|
|
5677
5788
|
onAssistantMessage: (content, metadata) => {
|
|
5678
5789
|
const enriched = this.buildDisplayMetadata(metadata);
|
|
5679
|
-
const
|
|
5790
|
+
const usingBlocks = this.assistantBlocksEnabled && this.assistantBlockRenderer !== null;
|
|
5791
|
+
const sourceContent = usingBlocks && metadata.wasStreamed ? this.consumeAssistantStreamBuffer(content) : content;
|
|
5792
|
+
const parsed = this.splitThinkingResponse(sourceContent);
|
|
5680
5793
|
const thinking = parsed?.thinking ?? null;
|
|
5681
|
-
const
|
|
5682
|
-
|
|
5794
|
+
const shouldRenderThoughtBlock = Boolean(thinking) && !this.hasShownThoughtProcess;
|
|
5795
|
+
const responseContent = parsed ? parsed.response?.trim() ?? '' : sourceContent.trim();
|
|
5796
|
+
const narrativeContent = parsed?.response ?? sourceContent;
|
|
5683
5797
|
if (metadata.isFinal) {
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5798
|
+
if (thinking) {
|
|
5799
|
+
// Update status + summary, but skip the legacy UI output when blocks are enabled
|
|
5800
|
+
this.presentThoughtProcess(thinking, enriched, {
|
|
5801
|
+
wasStreamed: usingBlocks || metadata.wasStreamed,
|
|
5802
|
+
});
|
|
5803
|
+
if (usingBlocks && shouldRenderThoughtBlock) {
|
|
5804
|
+
this.renderAssistantBlock('thought', thinking, enriched);
|
|
5805
|
+
}
|
|
5806
|
+
}
|
|
5807
|
+
if (usingBlocks) {
|
|
5808
|
+
const body = responseContent || sourceContent;
|
|
5809
|
+
this.renderAssistantBlock('response', body, enriched);
|
|
5810
|
+
}
|
|
5811
|
+
else if (!metadata.wasStreamed && responseContent) {
|
|
5687
5812
|
display.showAssistantMessage(responseContent, enriched);
|
|
5688
5813
|
}
|
|
5689
5814
|
// Status shown in mode controls bar - no separate status line needed
|
|
@@ -5702,13 +5827,18 @@ What's the next action?`;
|
|
|
5702
5827
|
}
|
|
5703
5828
|
else {
|
|
5704
5829
|
if (thinking) {
|
|
5705
|
-
this.presentThoughtProcess(thinking, enriched, {
|
|
5830
|
+
this.presentThoughtProcess(thinking, enriched, {
|
|
5831
|
+
wasStreamed: usingBlocks || metadata.wasStreamed,
|
|
5832
|
+
});
|
|
5706
5833
|
}
|
|
5707
5834
|
// Non-final message = narrative text before tool calls (Claude Code style)
|
|
5708
5835
|
// Stop spinner and show the narrative text directly
|
|
5709
5836
|
display.stopThinking();
|
|
5710
|
-
|
|
5711
|
-
|
|
5837
|
+
if (usingBlocks) {
|
|
5838
|
+
const body = metadata.wasStreamed ? responseContent || sourceContent : narrativeContent;
|
|
5839
|
+
this.renderAssistantBlock('thought', body, enriched);
|
|
5840
|
+
}
|
|
5841
|
+
else if (!metadata.wasStreamed) {
|
|
5712
5842
|
const narrative = parsed?.response ?? content;
|
|
5713
5843
|
display.showNarrative(narrative.trim());
|
|
5714
5844
|
}
|
|
@@ -5900,6 +6030,11 @@ What's the next action?`;
|
|
|
5900
6030
|
const summary = this.extractThoughtSummary(thinking);
|
|
5901
6031
|
if (summary) {
|
|
5902
6032
|
display.updateThinking(`💭 ${summary}`);
|
|
6033
|
+
this.latestThoughtSummary = summary;
|
|
6034
|
+
this.streamingStatusDetail = summary;
|
|
6035
|
+
this.terminalInput.recordRecentAction(`💭 ${summary}`);
|
|
6036
|
+
this.rebuildStreamingStatusLabel();
|
|
6037
|
+
this.refreshStatusLine(true);
|
|
5903
6038
|
}
|
|
5904
6039
|
if (!options?.wasStreamed) {
|
|
5905
6040
|
display.showAssistantMessage(thinking, { ...metadata, isFinal: false });
|
|
@@ -6281,6 +6416,7 @@ What's the next action?`;
|
|
|
6281
6416
|
const detail = detailText ? ` Error: ${detailText}` : '';
|
|
6282
6417
|
const reason = info.reason ? ` (${info.reason.replace(/-/g, ' ')})` : '';
|
|
6283
6418
|
const partialNote = info.partialResponse ? ' Received partial stream before failure.' : '';
|
|
6419
|
+
this.resetAssistantStreamBuffer();
|
|
6284
6420
|
display.showWarning(`Streaming failed${reason}, retrying without streaming.${detail}${partialNote}`);
|
|
6285
6421
|
this.startStreamingHeartbeat('Fallback in progress');
|
|
6286
6422
|
this.requestPromptRefresh(true);
|
|
@@ -6360,10 +6496,6 @@ What's the next action?`;
|
|
|
6360
6496
|
buildBanner() {
|
|
6361
6497
|
const terminalWidth = output.columns ?? 100;
|
|
6362
6498
|
const width = Math.min(terminalWidth - 4, 110);
|
|
6363
|
-
// Collect tool categories for display
|
|
6364
|
-
const toolCategories = this.collectToolCategories();
|
|
6365
|
-
// Load feature flags for banner display
|
|
6366
|
-
const featureFlags = loadFeatureFlags();
|
|
6367
6499
|
return renderSessionFrame({
|
|
6368
6500
|
profileLabel: this.profileLabel,
|
|
6369
6501
|
profileName: this.profile,
|
|
@@ -6372,19 +6504,6 @@ What's the next action?`;
|
|
|
6372
6504
|
workspace: this.workingDir,
|
|
6373
6505
|
version: this.version,
|
|
6374
6506
|
width,
|
|
6375
|
-
features: {
|
|
6376
|
-
verification: this.verificationEnabled,
|
|
6377
|
-
autoContinue: this.autoContinueEnabled,
|
|
6378
|
-
thinkingMode: this.thinkingMode,
|
|
6379
|
-
plugins: this._enabledPlugins,
|
|
6380
|
-
tools: toolCategories,
|
|
6381
|
-
sessionId: this.activeSessionId ?? undefined,
|
|
6382
|
-
// Include feature flags
|
|
6383
|
-
alphaZeroDual: featureFlags.alphaZeroDual,
|
|
6384
|
-
autoCompact: featureFlags.autoCompact,
|
|
6385
|
-
mcpEnabled: featureFlags.mcpEnabled,
|
|
6386
|
-
metrics: featureFlags.metrics,
|
|
6387
|
-
},
|
|
6388
6507
|
});
|
|
6389
6508
|
}
|
|
6390
6509
|
/**
|
|
@@ -6415,6 +6534,21 @@ What's the next action?`;
|
|
|
6415
6534
|
}
|
|
6416
6535
|
return categories;
|
|
6417
6536
|
}
|
|
6537
|
+
buildFeatureStatusSnapshot() {
|
|
6538
|
+
const featureFlags = loadFeatureFlags();
|
|
6539
|
+
const toolCategories = this.collectToolCategories();
|
|
6540
|
+
const toolCount = toolCategories.reduce((sum, cat) => sum + cat.count, 0);
|
|
6541
|
+
const pluginCount = this._enabledPlugins.length;
|
|
6542
|
+
return {
|
|
6543
|
+
pluginCount: pluginCount > 0 ? pluginCount : undefined,
|
|
6544
|
+
toolCount: toolCount > 0 ? toolCount : undefined,
|
|
6545
|
+
sessionId: this.activeSessionId,
|
|
6546
|
+
mcpEnabled: featureFlags.mcpEnabled,
|
|
6547
|
+
metricsEnabled: featureFlags.metrics,
|
|
6548
|
+
autoCompact: featureFlags.autoCompact,
|
|
6549
|
+
dualMode: featureFlags.alphaZeroDual,
|
|
6550
|
+
};
|
|
6551
|
+
}
|
|
6418
6552
|
/**
|
|
6419
6553
|
* Extract category from tool name.
|
|
6420
6554
|
*/
|