erosolar-cli 1.7.421 → 1.7.423
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/capabilities/statusCapability.d.ts +4 -0
- package/dist/capabilities/statusCapability.d.ts.map +1 -0
- package/dist/capabilities/statusCapability.js +92 -0
- package/dist/capabilities/statusCapability.js.map +1 -0
- package/dist/core/toolRuntime.d.ts +5 -0
- package/dist/core/toolRuntime.d.ts.map +1 -1
- package/dist/core/toolRuntime.js +25 -1
- package/dist/core/toolRuntime.js.map +1 -1
- package/dist/shell/interactiveShell.d.ts +7 -8
- package/dist/shell/interactiveShell.d.ts.map +1 -1
- package/dist/shell/interactiveShell.js +73 -75
- package/dist/shell/interactiveShell.js.map +1 -1
- package/dist/shell/shellApp.d.ts.map +1 -1
- package/dist/shell/shellApp.js +3 -0
- package/dist/shell/shellApp.js.map +1 -1
- package/dist/shell/terminalInput.d.ts +0 -5
- package/dist/shell/terminalInput.d.ts.map +1 -1
- package/dist/shell/terminalInput.js +0 -7
- package/dist/shell/terminalInput.js.map +1 -1
- package/dist/tools/localExplore.d.ts +1 -1
- package/dist/tools/localExplore.d.ts.map +1 -1
- package/dist/tools/localExplore.js +117 -46
- package/dist/tools/localExplore.js.map +1 -1
- package/dist/ui/ShellUIAdapter.d.ts +6 -0
- package/dist/ui/ShellUIAdapter.d.ts.map +1 -1
- package/dist/ui/ShellUIAdapter.js +78 -1
- package/dist/ui/ShellUIAdapter.js.map +1 -1
- package/dist/ui/display.d.ts +0 -31
- package/dist/ui/display.d.ts.map +1 -1
- package/dist/ui/display.js +0 -42
- package/dist/ui/display.js.map +1 -1
- package/dist/ui/streamingFormatter.d.ts +6 -2
- package/dist/ui/streamingFormatter.d.ts.map +1 -1
- package/dist/ui/streamingFormatter.js +37 -23
- package/dist/ui/streamingFormatter.js.map +1 -1
- package/package.json +1 -1
|
@@ -6,7 +6,6 @@ import { join } from 'node:path';
|
|
|
6
6
|
import { display } from '../ui/display.js';
|
|
7
7
|
import { isPlainOutputMode } from '../ui/outputMode.js';
|
|
8
8
|
import { theme } from '../ui/theme.js';
|
|
9
|
-
import { renderDivider } from '../ui/unified/layout.js';
|
|
10
9
|
import { StreamingResponseFormatter } from '../ui/streamingFormatter.js';
|
|
11
10
|
import { getContextWindowTokens } from '../core/contextWindow.js';
|
|
12
11
|
import { ensureSecretForProvider, getSecretDefinitionForProvider, getSecretValue, listSecretDefinitions, maskSecret, setSecretValue, } from '../core/secretStore.js';
|
|
@@ -33,7 +32,7 @@ import { addToolPattern } from '../core/learningPersistence.js';
|
|
|
33
32
|
import { classifyTaskType } from '../core/alphaZeroEngine.js';
|
|
34
33
|
import { analyzeImprovementOpportunities, runSelfImprovementCycle, getImprovementSummary, runAutonomousImprovement, requestAutoImprovementStop, getAutoImprovementState, emergencyRollback, } from '../core/selfImprovement.js';
|
|
35
34
|
import { listAvailablePlugins } from '../plugins/index.js';
|
|
36
|
-
import {
|
|
35
|
+
import { isValidSourceRepo, getRepoName, analyzeSource, runSelfEvolution, stopEvolution, getEvolutionStatus, emergencyEvolutionRollback, learnSourcePatterns, generateFix, } from '../core/selfEvolution.js';
|
|
37
36
|
import { analyzeTokenUsage, discoverModularTargets, getModularStatusDisplay, generateContextOptimizations, getGuidelines, deleteGuideline, getPendingActions, executeModularAction, } from '../core/alphaZeroModular.js';
|
|
38
37
|
import { startOffsecRun, resumeOffsecRun, recordOffsecOutcome, getOffsecNextActions, simulateOffsecRollout, formatOffsecStatus, listOffsecRuns, } from '../core/offsecAlphaZero.js';
|
|
39
38
|
import { generateTestFlows, detectBugs, detectUIUpdates, saveTestFlows, saveBugReports, saveUIUpdates, getTestFlowStatus, } from '../core/intelligentTestFlows.js';
|
|
@@ -77,7 +76,6 @@ const CONTEXT_AUTOCOMPACT_PERCENT = Math.round(CONTEXT_USAGE_THRESHOLD * 100);
|
|
|
77
76
|
const CONTEXT_AUTOCOMPACT_FLOOR = 0.6;
|
|
78
77
|
const MIN_COMPACTION_TOKEN_SAVINGS = 200;
|
|
79
78
|
const MIN_COMPACTION_PERCENT_SAVINGS = 0.5;
|
|
80
|
-
const CONTEXT_RECENT_MESSAGE_COUNT = 12;
|
|
81
79
|
const CONTEXT_CLEANUP_CHARS_PER_CHUNK = 6000;
|
|
82
80
|
const CONTEXT_CLEANUP_MAX_OUTPUT_TOKENS = 800;
|
|
83
81
|
const CONTEXT_CLEANUP_SYSTEM_PROMPT = `Summarize earlier IDE collaboration so the agent can keep working.
|
|
@@ -125,7 +123,6 @@ export class InteractiveShell {
|
|
|
125
123
|
planApprovalBridgeRegistered = false;
|
|
126
124
|
contextCompactionInFlight = false;
|
|
127
125
|
contextCompactionLog = [];
|
|
128
|
-
bannerShown = false;
|
|
129
126
|
lastContextWarningLevel = null;
|
|
130
127
|
sessionPreferences;
|
|
131
128
|
autosaveEnabled;
|
|
@@ -173,9 +170,10 @@ export class InteractiveShell {
|
|
|
173
170
|
statusMessageOverride = null;
|
|
174
171
|
promptRefreshTimer = null;
|
|
175
172
|
launchPaletteShown = false;
|
|
176
|
-
launchBannerText = null;
|
|
177
173
|
version;
|
|
178
174
|
alternateScreenEnabled;
|
|
175
|
+
welcomeShown = false;
|
|
176
|
+
scrollbackRestored = false;
|
|
179
177
|
constructor(config) {
|
|
180
178
|
this.profile = config.profile;
|
|
181
179
|
this.profileLabel = config.profileLabel;
|
|
@@ -348,6 +346,7 @@ export class InteractiveShell {
|
|
|
348
346
|
// Restore scrollback buffer if available
|
|
349
347
|
if (stored.scrollbackBuffer && Array.isArray(stored.scrollbackBuffer)) {
|
|
350
348
|
this.terminalInput.loadScrollbackBuffer(stored.scrollbackBuffer);
|
|
349
|
+
this.scrollbackRestored = true;
|
|
351
350
|
}
|
|
352
351
|
return;
|
|
353
352
|
}
|
|
@@ -365,6 +364,7 @@ export class InteractiveShell {
|
|
|
365
364
|
// Restore scrollback buffer if available
|
|
366
365
|
if (autosave.scrollbackBuffer && Array.isArray(autosave.scrollbackBuffer)) {
|
|
367
366
|
this.terminalInput.loadScrollbackBuffer(autosave.scrollbackBuffer);
|
|
367
|
+
this.scrollbackRestored = true;
|
|
368
368
|
}
|
|
369
369
|
return;
|
|
370
370
|
}
|
|
@@ -379,29 +379,35 @@ export class InteractiveShell {
|
|
|
379
379
|
display.showInfo(this.sessionResumeNotice);
|
|
380
380
|
this.sessionResumeNotice = null;
|
|
381
381
|
}
|
|
382
|
-
|
|
383
|
-
|
|
382
|
+
showWelcomeBanner(force = false) {
|
|
383
|
+
if ((this.welcomeShown || this.scrollbackRestored) && !force) {
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
const header = theme.gradient.primary('Erosolar CLI');
|
|
387
|
+
const modelLine = `${theme.fields.model(this.sessionState.model)} ${theme.ui.muted('@')} ${theme.fields.agent(this.providerLabel(this.sessionState.provider))}`;
|
|
384
388
|
const profileLine = `${theme.fields.profile(this.profileLabel)} ${theme.ui.muted(`(${this.profile})`)}`;
|
|
385
389
|
const workspaceLine = theme.fields.workspace(this.workingDir);
|
|
386
390
|
const versionLine = this.version ? theme.ui.muted(`v${this.version} · support@ero.solar`) : null;
|
|
387
391
|
const hintLine = theme.ui.muted('/help for commands · /model to switch · /secrets for keys');
|
|
388
|
-
const
|
|
389
|
-
const banner = [header, profileLine, workspaceLine, versionLine, hintLine, renderDivider(width)]
|
|
392
|
+
const message = [header, modelLine, profileLine, workspaceLine, versionLine, hintLine]
|
|
390
393
|
.filter(Boolean)
|
|
391
394
|
.join('\n');
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
395
|
+
this.streamEventBlock(message);
|
|
396
|
+
this.welcomeShown = true;
|
|
397
|
+
this.requestPromptRefresh(true);
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Stream a content block as a single event, isolating it from adjacent output.
|
|
401
|
+
*/
|
|
402
|
+
streamEventBlock(content) {
|
|
403
|
+
const normalized = content.replace(/\s+$/u, '');
|
|
404
|
+
if (!normalized) {
|
|
396
405
|
return;
|
|
397
406
|
}
|
|
398
|
-
|
|
399
|
-
this.bannerShown = true;
|
|
400
|
-
this.launchBannerText = banner;
|
|
401
|
-
this.requestPromptRefresh(true);
|
|
407
|
+
this.terminalInput.streamContent(`\n${normalized}\n\n`);
|
|
402
408
|
}
|
|
403
409
|
async start(initialPrompt) {
|
|
404
|
-
this.
|
|
410
|
+
this.showWelcomeBanner();
|
|
405
411
|
if (initialPrompt) {
|
|
406
412
|
await this.processInputBlock(initialPrompt);
|
|
407
413
|
return;
|
|
@@ -579,11 +585,11 @@ export class InteractiveShell {
|
|
|
579
585
|
if (!changed && source === 'shortcut') {
|
|
580
586
|
return;
|
|
581
587
|
}
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
588
|
+
const modeLabel = this.autoContinueEnabled ? 'enabled' : 'disabled';
|
|
589
|
+
const behavior = this.autoContinueEnabled
|
|
590
|
+
? 'The model will be auto-prompted to continue when it expresses intent but does not use tools.'
|
|
591
|
+
: 'The model will not be auto-prompted to continue.';
|
|
592
|
+
display.showInfo(`Auto-continue ${modeLabel}. ${behavior} Toggle with Ctrl+Shift+C.`);
|
|
587
593
|
}
|
|
588
594
|
/**
|
|
589
595
|
* Cycle through thinking modes (Tab shortcut).
|
|
@@ -1297,9 +1303,9 @@ export class InteractiveShell {
|
|
|
1297
1303
|
}
|
|
1298
1304
|
this.lastLoggedPrompt = normalized;
|
|
1299
1305
|
this.lastLoggedPromptAt = now;
|
|
1300
|
-
// Format with user prompt prefix and
|
|
1301
|
-
const formatted = `${theme.user('>')} ${normalized}
|
|
1302
|
-
this.
|
|
1306
|
+
// Format with user prompt prefix and stream as its own event
|
|
1307
|
+
const formatted = `${theme.user('>')} ${normalized}`;
|
|
1308
|
+
this.streamEventBlock(formatted);
|
|
1303
1309
|
}
|
|
1304
1310
|
requestPromptRefresh(force = false) {
|
|
1305
1311
|
if (force) {
|
|
@@ -1384,7 +1390,10 @@ export class InteractiveShell {
|
|
|
1384
1390
|
// Emit a streaming note for stop/quit so the status stays inside the stream
|
|
1385
1391
|
if (reason === 'stop' || reason === 'quit') {
|
|
1386
1392
|
const note = reason === 'quit' ? 'Session closed.' : 'Stream stopped.';
|
|
1387
|
-
this.finishStreamingFormatter(note, {
|
|
1393
|
+
this.finishStreamingFormatter(note, {
|
|
1394
|
+
refreshPrompt: false,
|
|
1395
|
+
mode: reason,
|
|
1396
|
+
});
|
|
1388
1397
|
}
|
|
1389
1398
|
// Force refresh to update the input area now that streaming has ended
|
|
1390
1399
|
if (!quiet) {
|
|
@@ -1414,7 +1423,10 @@ export class InteractiveShell {
|
|
|
1414
1423
|
if (!this.streamingFormatter) {
|
|
1415
1424
|
return;
|
|
1416
1425
|
}
|
|
1417
|
-
const closing = this.streamingFormatter.finish(
|
|
1426
|
+
const closing = this.streamingFormatter.finish({
|
|
1427
|
+
note,
|
|
1428
|
+
mode: options?.mode ?? 'complete',
|
|
1429
|
+
});
|
|
1418
1430
|
if (closing) {
|
|
1419
1431
|
this.terminalInput.streamContent(closing);
|
|
1420
1432
|
}
|
|
@@ -1710,7 +1722,6 @@ export class InteractiveShell {
|
|
|
1710
1722
|
this.showAlphaZeroMetrics();
|
|
1711
1723
|
break;
|
|
1712
1724
|
case '/suggestions':
|
|
1713
|
-
case '/improve':
|
|
1714
1725
|
this.showImprovementSuggestions();
|
|
1715
1726
|
break;
|
|
1716
1727
|
case '/plugins':
|
|
@@ -2137,7 +2148,7 @@ export class InteractiveShell {
|
|
|
2137
2148
|
lines.push(theme.bold('Session File Changes'));
|
|
2138
2149
|
lines.push('');
|
|
2139
2150
|
lines.push(`${theme.info('•')} ${summary.files} file${summary.files === 1 ? '' : 's'} modified`);
|
|
2140
|
-
lines.push(`${theme.info('•')} ${theme.success(
|
|
2151
|
+
lines.push(`${theme.info('•')} ${theme.success(`+${summary.additions}`)} ${theme.error(`-${summary.removals}`)} lines`);
|
|
2141
2152
|
lines.push('');
|
|
2142
2153
|
// Group changes by file
|
|
2143
2154
|
const fileMap = new Map();
|
|
@@ -2161,7 +2172,7 @@ export class InteractiveShell {
|
|
|
2161
2172
|
if (stats.writes > 0)
|
|
2162
2173
|
operations.push(`${stats.writes} write${stats.writes === 1 ? '' : 's'}`);
|
|
2163
2174
|
const opsText = operations.join(', ');
|
|
2164
|
-
const diffText = `${theme.success(
|
|
2175
|
+
const diffText = `${theme.success(`+${stats.additions}`)} ${theme.error(`-${stats.removals}`)}`;
|
|
2165
2176
|
lines.push(` ${theme.dim(path)}`);
|
|
2166
2177
|
lines.push(` ${opsText} • ${diffText}`);
|
|
2167
2178
|
}
|
|
@@ -2618,7 +2629,7 @@ export class InteractiveShell {
|
|
|
2618
2629
|
if (!isValidSourceRepo(this.workingDir)) {
|
|
2619
2630
|
display.showWarning('Self-evolution requires a git repository with source code.');
|
|
2620
2631
|
display.showSystemMessage('');
|
|
2621
|
-
display.showSystemMessage(
|
|
2632
|
+
display.showSystemMessage(`Current directory: ${this.workingDir}`);
|
|
2622
2633
|
display.showSystemMessage('');
|
|
2623
2634
|
display.showSystemMessage('Requirements:');
|
|
2624
2635
|
display.showSystemMessage(' • Must be a git repository (.git folder)');
|
|
@@ -2628,7 +2639,6 @@ export class InteractiveShell {
|
|
|
2628
2639
|
return;
|
|
2629
2640
|
}
|
|
2630
2641
|
const repoName = getRepoName(this.workingDir);
|
|
2631
|
-
const isErosolar = isErosolarRepo(this.workingDir);
|
|
2632
2642
|
if (subcommand === 'analyze') {
|
|
2633
2643
|
display.showSystemMessage(theme.gradient.primary(`🔍 Analyzing ${repoName} Source Code...`));
|
|
2634
2644
|
display.showSystemMessage('');
|
|
@@ -3000,13 +3010,6 @@ export class InteractiveShell {
|
|
|
3000
3010
|
' /offsec win|fail|detect <actionId> [note]\n' +
|
|
3001
3011
|
' /offsec resume <runId>\n' +
|
|
3002
3012
|
' /offsec runs';
|
|
3003
|
-
const loadRun = (explicitId) => {
|
|
3004
|
-
const run = resumeOffsecRun(explicitId ?? this.offsecRunId);
|
|
3005
|
-
if (!run) {
|
|
3006
|
-
display.showWarning('No offsec run found. Start one with /offsec start "<objective>".');
|
|
3007
|
-
}
|
|
3008
|
-
return run;
|
|
3009
|
-
};
|
|
3010
3013
|
if (sub === 'start') {
|
|
3011
3014
|
const rest = args.slice(1);
|
|
3012
3015
|
const scope = [];
|
|
@@ -3445,8 +3448,7 @@ export class InteractiveShell {
|
|
|
3445
3448
|
const value = tokens[0]?.toLowerCase();
|
|
3446
3449
|
if (!value) {
|
|
3447
3450
|
// Show current status
|
|
3448
|
-
display.showInfo(`Auto-continue is ${this.autoContinueEnabled ? 'enabled' : 'disabled'}.
|
|
3449
|
-
`Use /autocontinue on|off or Ctrl+Shift+C to toggle.`);
|
|
3451
|
+
display.showInfo(`Auto-continue is ${this.autoContinueEnabled ? 'enabled' : 'disabled'}. Use /autocontinue on|off or Ctrl+Shift+C to toggle.`);
|
|
3450
3452
|
return;
|
|
3451
3453
|
}
|
|
3452
3454
|
if (value !== 'on' && value !== 'off') {
|
|
@@ -3456,7 +3458,7 @@ export class InteractiveShell {
|
|
|
3456
3458
|
this.setAutoContinueMode(value === 'on', 'command');
|
|
3457
3459
|
}
|
|
3458
3460
|
// ==================== Claude Code Style Commands ====================
|
|
3459
|
-
async handleRewindCommand(
|
|
3461
|
+
async handleRewindCommand(_input) {
|
|
3460
3462
|
const lines = [];
|
|
3461
3463
|
lines.push(theme.bold('Rewind / Checkpoint System'));
|
|
3462
3464
|
lines.push('');
|
|
@@ -3472,7 +3474,7 @@ export class InteractiveShell {
|
|
|
3472
3474
|
lines.push(theme.ui.muted('Press Esc+Esc for quick access to the rewind menu'));
|
|
3473
3475
|
display.showSystemMessage(lines.join('\n'));
|
|
3474
3476
|
}
|
|
3475
|
-
handleMemoryCommand(
|
|
3477
|
+
handleMemoryCommand(_input) {
|
|
3476
3478
|
const lines = [];
|
|
3477
3479
|
lines.push(theme.bold('Memory System (EROSOLAR.md)'));
|
|
3478
3480
|
lines.push('');
|
|
@@ -3513,7 +3515,7 @@ export class InteractiveShell {
|
|
|
3513
3515
|
lines.push(theme.ui.muted('Vim mode is experimental. Toggle with /vim'));
|
|
3514
3516
|
display.showSystemMessage(lines.join('\n'));
|
|
3515
3517
|
}
|
|
3516
|
-
handleOutputStyleCommand(
|
|
3518
|
+
handleOutputStyleCommand(_input) {
|
|
3517
3519
|
const lines = [];
|
|
3518
3520
|
lines.push(theme.bold('Output Styles'));
|
|
3519
3521
|
lines.push('');
|
|
@@ -3634,7 +3636,7 @@ export class InteractiveShell {
|
|
|
3634
3636
|
}
|
|
3635
3637
|
}
|
|
3636
3638
|
}
|
|
3637
|
-
handleExportCommand(
|
|
3639
|
+
handleExportCommand(_input) {
|
|
3638
3640
|
const lines = [];
|
|
3639
3641
|
lines.push(theme.bold('Export Conversation'));
|
|
3640
3642
|
lines.push('');
|
|
@@ -4227,7 +4229,7 @@ export class InteractiveShell {
|
|
|
4227
4229
|
const parts = tool.name.split('__');
|
|
4228
4230
|
const serverName = parts[1] || '';
|
|
4229
4231
|
const toolName = parts.slice(2).join('__') || tool.name;
|
|
4230
|
-
lines.push(` ${theme.info('•')} ${theme.ui.muted(serverName
|
|
4232
|
+
lines.push(` ${theme.info('•')} ${theme.ui.muted(`${serverName}:`)} ${toolName}`);
|
|
4231
4233
|
}
|
|
4232
4234
|
if (mcpTools.length > 15) {
|
|
4233
4235
|
lines.push(` ${theme.ui.muted(`... and ${mcpTools.length - 15} more`)}`);
|
|
@@ -4688,7 +4690,7 @@ export class InteractiveShell {
|
|
|
4688
4690
|
// Start streaming - no header needed, the input area already provides context
|
|
4689
4691
|
this.startStreamingHeartbeat('Streaming response');
|
|
4690
4692
|
responseText = await agent.send(request, true);
|
|
4691
|
-
this.finishStreamingFormatter(undefined, { refreshPrompt: false });
|
|
4693
|
+
this.finishStreamingFormatter(undefined, { refreshPrompt: false, mode: 'complete' });
|
|
4692
4694
|
await this.awaitPendingCleanup();
|
|
4693
4695
|
this.captureHistorySnapshot();
|
|
4694
4696
|
this.autosaveIfEnabled();
|
|
@@ -4744,7 +4746,7 @@ export class InteractiveShell {
|
|
|
4744
4746
|
}
|
|
4745
4747
|
}
|
|
4746
4748
|
finally {
|
|
4747
|
-
this.finishStreamingFormatter(undefined, { refreshPrompt: false });
|
|
4749
|
+
this.finishStreamingFormatter(undefined, { refreshPrompt: false, mode: 'complete' });
|
|
4748
4750
|
display.stopThinking(false);
|
|
4749
4751
|
this.uiUpdates.setMode('processing');
|
|
4750
4752
|
this.stopStreamingHeartbeat('complete', { quiet: true });
|
|
@@ -4753,7 +4755,6 @@ export class InteractiveShell {
|
|
|
4753
4755
|
this.terminalInput.setStreaming(false);
|
|
4754
4756
|
this.uiAdapter.endProcessing('Ready for prompts');
|
|
4755
4757
|
this.setIdleStatus();
|
|
4756
|
-
display.newLine();
|
|
4757
4758
|
this.updateStatusMessage(null);
|
|
4758
4759
|
queueMicrotask(() => this.uiUpdates.setMode('idle'));
|
|
4759
4760
|
// CRITICAL: Ensure readline prompt is active for user input
|
|
@@ -4837,7 +4838,7 @@ When truly finished with ALL tasks, explicitly state "TASK_FULLY_COMPLETE".`;
|
|
|
4837
4838
|
display.showThinking('Responding...');
|
|
4838
4839
|
this.refreshStatusLine(true);
|
|
4839
4840
|
const response = await agent.send(currentPrompt, true);
|
|
4840
|
-
this.finishStreamingFormatter(undefined, { refreshPrompt: false });
|
|
4841
|
+
this.finishStreamingFormatter(undefined, { refreshPrompt: false, mode: 'complete' });
|
|
4841
4842
|
await this.awaitPendingCleanup();
|
|
4842
4843
|
this.captureHistorySnapshot();
|
|
4843
4844
|
this.autosaveIfEnabled();
|
|
@@ -4970,7 +4971,7 @@ What's the next action?`;
|
|
|
4970
4971
|
}
|
|
4971
4972
|
}
|
|
4972
4973
|
finally {
|
|
4973
|
-
this.finishStreamingFormatter(undefined, { refreshPrompt: false });
|
|
4974
|
+
this.finishStreamingFormatter(undefined, { refreshPrompt: false, mode: 'complete' });
|
|
4974
4975
|
const totalElapsed = Date.now() - overallStartTime;
|
|
4975
4976
|
const minutes = Math.floor(totalElapsed / 60000);
|
|
4976
4977
|
const seconds = Math.floor((totalElapsed % 60000) / 1000);
|
|
@@ -4985,10 +4986,6 @@ What's the next action?`;
|
|
|
4985
4986
|
this.uiAdapter.endProcessing('Ready for prompts');
|
|
4986
4987
|
this.setIdleStatus();
|
|
4987
4988
|
this.updateStatusMessage(null);
|
|
4988
|
-
display.newLine();
|
|
4989
|
-
// Claude Code style: Show unified status bar before prompt
|
|
4990
|
-
// This creates consistent UI between startup and post-streaming
|
|
4991
|
-
this.showUnifiedStatusBar();
|
|
4992
4989
|
queueMicrotask(() => this.uiUpdates.setMode('idle'));
|
|
4993
4990
|
// CRITICAL: Ensure readline prompt is active for user input
|
|
4994
4991
|
// Claude Code style: New prompt naturally appears at bottom
|
|
@@ -5182,7 +5179,14 @@ What's the next action?`;
|
|
|
5182
5179
|
return latest;
|
|
5183
5180
|
}
|
|
5184
5181
|
formatCommandError(error) {
|
|
5185
|
-
const
|
|
5182
|
+
const candidates = [];
|
|
5183
|
+
if (error && typeof error === 'object') {
|
|
5184
|
+
const stdout = error.stdout;
|
|
5185
|
+
const stderr = error.stderr;
|
|
5186
|
+
const message = error.message;
|
|
5187
|
+
candidates.push(stdout, stderr, message);
|
|
5188
|
+
}
|
|
5189
|
+
const parts = candidates.filter((part) => typeof part === 'string' && part.trim().length > 0);
|
|
5186
5190
|
return parts.join('\n').trim();
|
|
5187
5191
|
}
|
|
5188
5192
|
runAutoQualityChecks(trigger, assistantResponse, verificationContext) {
|
|
@@ -5515,7 +5519,6 @@ Return ONLY JSON array:
|
|
|
5515
5519
|
display.showThinking('Analyzing build errors');
|
|
5516
5520
|
this.refreshStatusLine(true);
|
|
5517
5521
|
const response = await this.agent.send(prompt, true);
|
|
5518
|
-
this.finishStreamingFormatter();
|
|
5519
5522
|
display.stopThinking();
|
|
5520
5523
|
this.refreshStatusLine(true);
|
|
5521
5524
|
if (response) {
|
|
@@ -5528,7 +5531,7 @@ Return ONLY JSON array:
|
|
|
5528
5531
|
display.showWarning('Agent could not automatically fix build errors. Please review manually.');
|
|
5529
5532
|
}
|
|
5530
5533
|
finally {
|
|
5531
|
-
this.finishStreamingFormatter();
|
|
5534
|
+
this.finishStreamingFormatter(undefined, { refreshPrompt: false, mode: 'complete' });
|
|
5532
5535
|
}
|
|
5533
5536
|
}
|
|
5534
5537
|
rebuildAgent() {
|
|
@@ -5699,9 +5702,9 @@ Return ONLY JSON array:
|
|
|
5699
5702
|
* Ensures the input area is visible and ready for input, just like on startup.
|
|
5700
5703
|
*/
|
|
5701
5704
|
resetChatBoxAfterModelSwap() {
|
|
5702
|
-
this.renderWelcomeBanner(true);
|
|
5703
5705
|
this.updateStatusMessage(null);
|
|
5704
5706
|
this.terminalInput.setStreaming(false);
|
|
5707
|
+
this.requestPromptRefresh(true);
|
|
5705
5708
|
this.ensureReadlineReady();
|
|
5706
5709
|
}
|
|
5707
5710
|
/**
|
|
@@ -6254,7 +6257,7 @@ Return ONLY JSON array:
|
|
|
6254
6257
|
const reason = info.reason ? ` (${info.reason.replace(/-/g, ' ')})` : '';
|
|
6255
6258
|
const partialNote = info.partialResponse ? ' Received partial stream before failure.' : '';
|
|
6256
6259
|
display.showWarning(`Streaming failed${reason}, retrying without streaming.${detail}${partialNote}`);
|
|
6257
|
-
this.finishStreamingFormatter('Stream interrupted - retrying without streaming');
|
|
6260
|
+
this.finishStreamingFormatter('Stream interrupted - retrying without streaming', { mode: 'update' });
|
|
6258
6261
|
this.startStreamingHeartbeat('Fallback in progress');
|
|
6259
6262
|
this.requestPromptRefresh(true);
|
|
6260
6263
|
}
|
|
@@ -6355,7 +6358,7 @@ Return ONLY JSON array:
|
|
|
6355
6358
|
// Truncate to reasonable length
|
|
6356
6359
|
const maxLength = 50;
|
|
6357
6360
|
return cleaned.length > maxLength
|
|
6358
|
-
? cleaned.slice(0, maxLength - 3)
|
|
6361
|
+
? `${cleaned.slice(0, maxLength - 3)}...`
|
|
6359
6362
|
: cleaned;
|
|
6360
6363
|
}
|
|
6361
6364
|
splitThinkingResponse(content) {
|
|
@@ -6520,13 +6523,15 @@ Return ONLY JSON array:
|
|
|
6520
6523
|
await this.scanLocalProviders();
|
|
6521
6524
|
break;
|
|
6522
6525
|
case 'use':
|
|
6523
|
-
|
|
6524
|
-
|
|
6525
|
-
|
|
6526
|
-
|
|
6527
|
-
|
|
6526
|
+
{
|
|
6527
|
+
const provider = tokens[1]?.toLowerCase();
|
|
6528
|
+
if (!provider) {
|
|
6529
|
+
display.showWarning('Usage: /local use <provider>');
|
|
6530
|
+
display.showInfo('Example: /local use ollama');
|
|
6531
|
+
return;
|
|
6532
|
+
}
|
|
6533
|
+
await this.handleProviderCommand(`/provider ${provider}`);
|
|
6528
6534
|
}
|
|
6529
|
-
await this.handleProviderCommand(`/provider ${provider}`);
|
|
6530
6535
|
break;
|
|
6531
6536
|
default:
|
|
6532
6537
|
this.showLocalHelp();
|
|
@@ -6633,13 +6638,6 @@ Return ONLY JSON array:
|
|
|
6633
6638
|
setProviderStatus(providers) {
|
|
6634
6639
|
this.cachedProviderStatus = providers;
|
|
6635
6640
|
}
|
|
6636
|
-
/**
|
|
6637
|
-
* Show the unified status bar (Claude Code style).
|
|
6638
|
-
* Displays provider indicators and ready hints before the prompt.
|
|
6639
|
-
*/
|
|
6640
|
-
showUnifiedStatusBar() {
|
|
6641
|
-
display.showUnifiedStatusBar(this.cachedProviderStatus);
|
|
6642
|
-
}
|
|
6643
6641
|
}
|
|
6644
6642
|
function setsEqual(first, second) {
|
|
6645
6643
|
if (first.size !== second.size) {
|