erosolar-cli 1.7.253 → 1.7.255
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/README.md +148 -22
- package/dist/core/aiFlowOptimizer.d.ts +26 -0
- package/dist/core/aiFlowOptimizer.d.ts.map +1 -0
- package/dist/core/aiFlowOptimizer.js +31 -0
- package/dist/core/aiFlowOptimizer.js.map +1 -0
- package/dist/core/aiOptimizationEngine.d.ts +158 -0
- package/dist/core/aiOptimizationEngine.d.ts.map +1 -0
- package/dist/core/aiOptimizationEngine.js +428 -0
- package/dist/core/aiOptimizationEngine.js.map +1 -0
- package/dist/core/aiOptimizationIntegration.d.ts +93 -0
- package/dist/core/aiOptimizationIntegration.d.ts.map +1 -0
- package/dist/core/aiOptimizationIntegration.js +250 -0
- package/dist/core/aiOptimizationIntegration.js.map +1 -0
- package/dist/core/customCommands.d.ts +0 -1
- package/dist/core/customCommands.d.ts.map +1 -1
- package/dist/core/customCommands.js +0 -3
- package/dist/core/customCommands.js.map +1 -1
- package/dist/core/enhancedErrorRecovery.d.ts +100 -0
- package/dist/core/enhancedErrorRecovery.d.ts.map +1 -0
- package/dist/core/enhancedErrorRecovery.js +345 -0
- package/dist/core/enhancedErrorRecovery.js.map +1 -0
- package/dist/core/toolPreconditions.d.ts.map +1 -1
- package/dist/core/toolPreconditions.js +14 -0
- package/dist/core/toolPreconditions.js.map +1 -1
- package/dist/core/toolRuntime.d.ts.map +1 -1
- package/dist/core/toolRuntime.js +5 -0
- package/dist/core/toolRuntime.js.map +1 -1
- package/dist/core/toolValidation.d.ts.map +1 -1
- package/dist/core/toolValidation.js +3 -14
- package/dist/core/toolValidation.js.map +1 -1
- package/dist/mcp/sseClient.d.ts.map +1 -1
- package/dist/mcp/sseClient.js +18 -9
- package/dist/mcp/sseClient.js.map +1 -1
- package/dist/plugins/tools/build/buildPlugin.d.ts +6 -0
- package/dist/plugins/tools/build/buildPlugin.d.ts.map +1 -1
- package/dist/plugins/tools/build/buildPlugin.js +10 -4
- package/dist/plugins/tools/build/buildPlugin.js.map +1 -1
- package/dist/shell/claudeCodeStreamHandler.d.ts +145 -0
- package/dist/shell/claudeCodeStreamHandler.d.ts.map +1 -0
- package/dist/shell/claudeCodeStreamHandler.js +322 -0
- package/dist/shell/claudeCodeStreamHandler.js.map +1 -0
- package/dist/shell/inputQueueManager.d.ts +144 -0
- package/dist/shell/inputQueueManager.d.ts.map +1 -0
- package/dist/shell/inputQueueManager.js +290 -0
- package/dist/shell/inputQueueManager.js.map +1 -0
- package/dist/shell/interactiveShell.d.ts +2 -10
- package/dist/shell/interactiveShell.d.ts.map +1 -1
- package/dist/shell/interactiveShell.js +31 -183
- package/dist/shell/interactiveShell.js.map +1 -1
- package/dist/shell/streamingOutputManager.d.ts +115 -0
- package/dist/shell/streamingOutputManager.d.ts.map +1 -0
- package/dist/shell/streamingOutputManager.js +225 -0
- package/dist/shell/streamingOutputManager.js.map +1 -0
- package/dist/shell/terminalInput.d.ts +126 -54
- package/dist/shell/terminalInput.d.ts.map +1 -1
- package/dist/shell/terminalInput.js +587 -354
- package/dist/shell/terminalInput.js.map +1 -1
- package/dist/shell/terminalInputAdapter.d.ts +15 -12
- package/dist/shell/terminalInputAdapter.d.ts.map +1 -1
- package/dist/shell/terminalInputAdapter.js +22 -8
- package/dist/shell/terminalInputAdapter.js.map +1 -1
- package/dist/ui/display.d.ts +0 -19
- package/dist/ui/display.d.ts.map +1 -1
- package/dist/ui/display.js +2 -133
- package/dist/ui/display.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/terminalUISchema.d.ts +195 -0
- package/dist/ui/terminalUISchema.d.ts.map +1 -0
- package/dist/ui/terminalUISchema.js +113 -0
- package/dist/ui/terminalUISchema.js.map +1 -0
- package/dist/ui/theme.d.ts.map +1 -1
- package/dist/ui/theme.js +8 -6
- package/dist/ui/theme.js.map +1 -1
- package/dist/ui/unified/layout.d.ts +0 -1
- package/dist/ui/unified/layout.d.ts.map +1 -1
- package/dist/ui/unified/layout.js +25 -15
- package/dist/ui/unified/layout.js.map +1 -1
- package/package.json +1 -1
|
@@ -2,7 +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 { display } from '../ui/display.js';
|
|
5
|
-
import { theme } from '../ui/theme.js';
|
|
5
|
+
import { theme, formatUserPrompt } from '../ui/theme.js';
|
|
6
6
|
import { getContextWindowTokens } from '../core/contextWindow.js';
|
|
7
7
|
import { ensureSecretForProvider, getSecretDefinitionForProvider, getSecretValue, listSecretDefinitions, maskSecret, setSecretValue, } from '../core/secretStore.js';
|
|
8
8
|
import { saveActiveProfilePreference, saveModelPreference, loadToolSettings, saveToolSettings, clearToolSettings, clearActiveProfilePreference, loadSessionPreferences, saveSessionPreferences, } from '../core/preferences.js';
|
|
@@ -34,7 +34,6 @@ const DROPDOWN_COLORS = [
|
|
|
34
34
|
theme.success,
|
|
35
35
|
theme.warning,
|
|
36
36
|
];
|
|
37
|
-
const STREAMING_SPINNER_FRAMES = ['◐', '◓', '◑', '◒'];
|
|
38
37
|
// Load MODEL_PRESETS from centralized schema
|
|
39
38
|
const MODEL_PRESETS = getModels().map((model) => ({
|
|
40
39
|
id: model.id,
|
|
@@ -49,13 +48,11 @@ const MODEL_PRESETS = getModels().map((model) => ({
|
|
|
49
48
|
const BASE_SLASH_COMMANDS = getSlashCommands().map((cmd) => ({
|
|
50
49
|
command: cmd.command,
|
|
51
50
|
description: cmd.description,
|
|
52
|
-
category: cmd.category,
|
|
53
51
|
}));
|
|
54
52
|
// Load PROVIDER_LABELS from centralized schema
|
|
55
53
|
const PROVIDER_LABELS = Object.fromEntries(getProviders().map((provider) => [provider.id, provider.label]));
|
|
56
54
|
// Allow enough time for paste detection to kick in before flushing buffered lines
|
|
57
55
|
const CONTEXT_USAGE_THRESHOLD = 0.9;
|
|
58
|
-
const CONTEXT_AUTOCOMPACT_PERCENT = Math.round(CONTEXT_USAGE_THRESHOLD * 100);
|
|
59
56
|
const CONTEXT_RECENT_MESSAGE_COUNT = 12;
|
|
60
57
|
const CONTEXT_CLEANUP_CHARS_PER_CHUNK = 6000;
|
|
61
58
|
const CONTEXT_CLEANUP_MAX_OUTPUT_TOKENS = 800;
|
|
@@ -101,7 +98,6 @@ export class InteractiveShell {
|
|
|
101
98
|
followUpQueue = [];
|
|
102
99
|
isDrainingQueue = false;
|
|
103
100
|
activeContextWindowTokens = null;
|
|
104
|
-
latestTokenUsage = { used: null, limit: null };
|
|
105
101
|
sessionPreferences;
|
|
106
102
|
autosaveEnabled;
|
|
107
103
|
autoContinueEnabled;
|
|
@@ -132,7 +128,6 @@ export class InteractiveShell {
|
|
|
132
128
|
statusLineState = null;
|
|
133
129
|
statusMessageOverride = null;
|
|
134
130
|
promptRefreshTimer = null;
|
|
135
|
-
launchPaletteShown = false;
|
|
136
131
|
constructor(config) {
|
|
137
132
|
this.profile = config.profile;
|
|
138
133
|
this.profileLabel = config.profileLabel;
|
|
@@ -166,7 +161,6 @@ export class InteractiveShell {
|
|
|
166
161
|
this.slashCommands.push({
|
|
167
162
|
command: '/agents',
|
|
168
163
|
description: 'Select the default agent profile (applies on next launch)',
|
|
169
|
-
category: 'configuration',
|
|
170
164
|
});
|
|
171
165
|
}
|
|
172
166
|
this.customCommands = loadCustomSlashCommands();
|
|
@@ -175,21 +169,18 @@ export class InteractiveShell {
|
|
|
175
169
|
this.slashCommands.push({
|
|
176
170
|
command: custom.command,
|
|
177
171
|
description: `${custom.description} (custom)`,
|
|
178
|
-
category: custom.category ?? 'other',
|
|
179
172
|
});
|
|
180
173
|
}
|
|
181
174
|
if (!this.slashCommands.some((cmd) => cmd.command === '/exit')) {
|
|
182
175
|
this.slashCommands.push({
|
|
183
176
|
command: '/exit',
|
|
184
177
|
description: 'Quit the CLI immediately',
|
|
185
|
-
category: 'other',
|
|
186
178
|
});
|
|
187
179
|
}
|
|
188
180
|
// Add /plugins command
|
|
189
181
|
this.slashCommands.push({
|
|
190
182
|
command: '/plugins',
|
|
191
183
|
description: 'Show available and loaded plugins',
|
|
192
|
-
category: 'configuration',
|
|
193
184
|
});
|
|
194
185
|
this.statusTracker = config.statusTracker;
|
|
195
186
|
this.ui = config.ui;
|
|
@@ -224,6 +215,9 @@ export class InteractiveShell {
|
|
|
224
215
|
});
|
|
225
216
|
// Register output interceptor for cursor positioning during streaming
|
|
226
217
|
this.terminalInput.registerOutputInterceptor(display);
|
|
218
|
+
// Use flow mode: input renders inline after content for a unified layout
|
|
219
|
+
// This eliminates the blank space between banner and input area
|
|
220
|
+
this.terminalInput.setFlowMode(true);
|
|
227
221
|
// Initialize Alpha Zero 2 metrics tracking
|
|
228
222
|
this.alphaZeroMetrics = new MetricsTracker(`${this.profile}-${Date.now()}`);
|
|
229
223
|
this.setupStatusTracking();
|
|
@@ -281,24 +275,9 @@ export class InteractiveShell {
|
|
|
281
275
|
await this.processInputBlock(initialPrompt);
|
|
282
276
|
return;
|
|
283
277
|
}
|
|
284
|
-
this.showLaunchCommandPalette();
|
|
285
278
|
// Ensure the terminal input is visible
|
|
286
279
|
this.terminalInput.render();
|
|
287
280
|
}
|
|
288
|
-
showLaunchCommandPalette() {
|
|
289
|
-
if (this.launchPaletteShown) {
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
const palette = this.buildLaunchCommandPalette();
|
|
293
|
-
if (!palette.length) {
|
|
294
|
-
return;
|
|
295
|
-
}
|
|
296
|
-
display.showCommandPalette(palette, {
|
|
297
|
-
title: 'Quick commands',
|
|
298
|
-
intro: 'Describe a task or run a slash command to get started:',
|
|
299
|
-
});
|
|
300
|
-
this.launchPaletteShown = true;
|
|
301
|
-
}
|
|
302
281
|
/**
|
|
303
282
|
* TerminalInputAdapter submit handler
|
|
304
283
|
*/
|
|
@@ -312,8 +291,9 @@ export class InteractiveShell {
|
|
|
312
291
|
this.handleInputChange('');
|
|
313
292
|
return;
|
|
314
293
|
}
|
|
315
|
-
//
|
|
316
|
-
//
|
|
294
|
+
// Enter streaming mode BEFORE logging prompt - this positions cursor correctly
|
|
295
|
+
// so content appears right after the banner, not at bottom with blank space above
|
|
296
|
+
this.terminalInput.setStreaming(true);
|
|
317
297
|
this.logUserPrompt(approved);
|
|
318
298
|
void this.processInputBlock(approved).catch((err) => {
|
|
319
299
|
display.showError(err instanceof Error ? err.message : String(err), err);
|
|
@@ -515,9 +495,10 @@ export class InteractiveShell {
|
|
|
515
495
|
// Dispose unified UI adapter
|
|
516
496
|
this.uiAdapter.dispose();
|
|
517
497
|
display.newLine();
|
|
518
|
-
console.log(theme.
|
|
519
|
-
console.log(theme.
|
|
520
|
-
console.log(theme.ui.muted('
|
|
498
|
+
console.log(theme.gradient.warm('━'.repeat(50)));
|
|
499
|
+
console.log(` ${theme.gradient.cool('✨ Goodbye!')} ${theme.ui.muted('·')} ${theme.info('support@ero.solar')}`);
|
|
500
|
+
console.log(` ${theme.ui.muted('Read:')} ${theme.accent('anthropic.com/news/disrupting-AI-espionage')}`);
|
|
501
|
+
console.log(theme.gradient.warm('━'.repeat(50)));
|
|
521
502
|
exit(0);
|
|
522
503
|
}
|
|
523
504
|
/**
|
|
@@ -687,7 +668,6 @@ export class InteractiveShell {
|
|
|
687
668
|
});
|
|
688
669
|
}
|
|
689
670
|
setProcessingStatus(detail) {
|
|
690
|
-
this.latestTokenUsage = { used: null, limit: this.latestTokenUsage.limit };
|
|
691
671
|
this.statusTracker.setBase('Working on your request', {
|
|
692
672
|
detail: this.describeStatusDetail(detail),
|
|
693
673
|
tone: 'info',
|
|
@@ -707,18 +687,12 @@ export class InteractiveShell {
|
|
|
707
687
|
}
|
|
708
688
|
refreshContextGauge() {
|
|
709
689
|
const tokens = getContextWindowTokens(this.sessionState.model);
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
if (normalizedTokens !== null) {
|
|
713
|
-
this.latestTokenUsage = {
|
|
714
|
-
used: this.latestTokenUsage.used,
|
|
715
|
-
limit: normalizedTokens,
|
|
716
|
-
};
|
|
717
|
-
}
|
|
690
|
+
this.activeContextWindowTokens =
|
|
691
|
+
typeof tokens === 'number' && Number.isFinite(tokens) ? tokens : null;
|
|
718
692
|
}
|
|
719
693
|
updateContextUsage(percentage) {
|
|
720
694
|
this.uiAdapter.updateContextUsage(percentage);
|
|
721
|
-
this.terminalInput.setContextUsage(percentage
|
|
695
|
+
this.terminalInput.setContextUsage(percentage);
|
|
722
696
|
}
|
|
723
697
|
refreshControlBar() {
|
|
724
698
|
this.terminalInput.setModeToggles({
|
|
@@ -726,7 +700,6 @@ export class InteractiveShell {
|
|
|
726
700
|
autoContinueEnabled: this.autoContinueEnabled,
|
|
727
701
|
verificationHotkey: 'alt+v',
|
|
728
702
|
autoContinueHotkey: 'alt+c',
|
|
729
|
-
thinkingModeLabel: this.thinkingMode,
|
|
730
703
|
});
|
|
731
704
|
this.refreshStatusLine();
|
|
732
705
|
this.terminalInput.render();
|
|
@@ -758,20 +731,6 @@ export class InteractiveShell {
|
|
|
758
731
|
// Set main status (tool execution, etc.) - shown when not overridden
|
|
759
732
|
const statusText = this.formatStatusLine(this.statusLineState);
|
|
760
733
|
this.terminalInput.setStatusMessage(statusText);
|
|
761
|
-
// Surface meta header (elapsed + context usage) above the divider
|
|
762
|
-
const elapsedSeconds = this.statusLineState
|
|
763
|
-
? Math.max(0, Math.floor((Date.now() - this.statusLineState.startedAt) / 1000))
|
|
764
|
-
: null;
|
|
765
|
-
const thinkingMs = display.isSpinnerActive() ? display.getThinkingElapsedMs() : null;
|
|
766
|
-
const tokensUsed = this.latestTokenUsage.used;
|
|
767
|
-
const tokenLimit = this.latestTokenUsage.limit ?? this.activeContextWindowTokens;
|
|
768
|
-
this.terminalInput.setMetaStatus({
|
|
769
|
-
elapsedSeconds,
|
|
770
|
-
tokensUsed,
|
|
771
|
-
tokenLimit,
|
|
772
|
-
thinkingMs,
|
|
773
|
-
thinkingHasContent: display.isSpinnerActive(),
|
|
774
|
-
});
|
|
775
734
|
if (forceRender) {
|
|
776
735
|
this.terminalInput.render();
|
|
777
736
|
}
|
|
@@ -831,11 +790,13 @@ export class InteractiveShell {
|
|
|
831
790
|
this.terminalInput.render();
|
|
832
791
|
}
|
|
833
792
|
/**
|
|
834
|
-
*
|
|
835
|
-
*
|
|
793
|
+
* Log the user's prompt as a visible message in the conversation.
|
|
794
|
+
* This creates a persistent log entry that remains visible during and after streaming.
|
|
836
795
|
*/
|
|
837
|
-
logUserPrompt(
|
|
838
|
-
//
|
|
796
|
+
logUserPrompt(text) {
|
|
797
|
+
// Display the user's prompt with the standard prefix
|
|
798
|
+
const prefix = formatUserPrompt();
|
|
799
|
+
display.stream(`\n${prefix}${text}\n\n`);
|
|
839
800
|
}
|
|
840
801
|
requestPromptRefresh(force = false) {
|
|
841
802
|
if (force) {
|
|
@@ -863,29 +824,9 @@ export class InteractiveShell {
|
|
|
863
824
|
this.uiUpdates.setMode('streaming');
|
|
864
825
|
this.streamingHeartbeatStart = Date.now();
|
|
865
826
|
this.streamingHeartbeatFrame = 0;
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
this.refreshStatusLine(true);
|
|
870
|
-
// Periodically refresh the pinned input/status region while streaming so
|
|
871
|
-
// elapsed time remains visible without interrupting the scroll region.
|
|
872
|
-
this.uiUpdates.startHeartbeat('streaming', {
|
|
873
|
-
intervalMs: 1000,
|
|
874
|
-
lane: 'heartbeat',
|
|
875
|
-
mode: ['streaming', 'processing'],
|
|
876
|
-
coalesceKey: 'streaming:heartbeat',
|
|
877
|
-
run: () => {
|
|
878
|
-
const elapsedSeconds = this.streamingHeartbeatStart
|
|
879
|
-
? Math.max(0, Math.floor((Date.now() - this.streamingHeartbeatStart) / 1000))
|
|
880
|
-
: 0;
|
|
881
|
-
this.streamingHeartbeatFrame =
|
|
882
|
-
(this.streamingHeartbeatFrame + 1) % STREAMING_SPINNER_FRAMES.length;
|
|
883
|
-
const frame = STREAMING_SPINNER_FRAMES[this.streamingHeartbeatFrame];
|
|
884
|
-
this.streamingStatusLabel = this.buildStreamingStatus(`${frame} ${label}`, elapsedSeconds);
|
|
885
|
-
display.updateStreamingStatus(this.streamingStatusLabel);
|
|
886
|
-
this.refreshStatusLine(true);
|
|
887
|
-
},
|
|
888
|
-
});
|
|
827
|
+
// Note: We don't start a heartbeat during streaming anymore
|
|
828
|
+
// because the UI shouldn't be rendering during streaming.
|
|
829
|
+
// The streaming status is shown in the streaming header instead.
|
|
889
830
|
}
|
|
890
831
|
stopStreamingHeartbeat() {
|
|
891
832
|
// Exit global streaming mode - allows UI to render again
|
|
@@ -901,28 +842,10 @@ export class InteractiveShell {
|
|
|
901
842
|
// Force refresh to update the input area now that streaming has ended
|
|
902
843
|
this.refreshStatusLine(true);
|
|
903
844
|
}
|
|
904
|
-
buildStreamingStatus(label
|
|
845
|
+
buildStreamingStatus(label) {
|
|
905
846
|
const detail = this.describeModelDetail();
|
|
906
|
-
const
|
|
907
|
-
|
|
908
|
-
: null;
|
|
909
|
-
const prefix = theme.info('⏺');
|
|
910
|
-
const parts = [label];
|
|
911
|
-
if (detail) {
|
|
912
|
-
parts.push(theme.ui.muted('·'), detail);
|
|
913
|
-
}
|
|
914
|
-
if (elapsedLabel) {
|
|
915
|
-
parts.push(theme.ui.muted('·'), elapsedLabel);
|
|
916
|
-
}
|
|
917
|
-
return `${prefix} ${parts.join(' ')}`.trim();
|
|
918
|
-
}
|
|
919
|
-
formatElapsedShort(seconds) {
|
|
920
|
-
if (seconds < 60) {
|
|
921
|
-
return `${seconds}s`;
|
|
922
|
-
}
|
|
923
|
-
const minutes = Math.floor(seconds / 60);
|
|
924
|
-
const remaining = seconds % 60;
|
|
925
|
-
return remaining > 0 ? `${minutes}m ${remaining}s` : `${minutes}m`;
|
|
847
|
+
const prefix = theme.info('●');
|
|
848
|
+
return detail ? `${prefix} ${label} ${theme.ui.muted('·')} ${detail}` : `${prefix} ${label}`;
|
|
926
849
|
}
|
|
927
850
|
refreshQueueIndicators() {
|
|
928
851
|
if (this.isProcessing) {
|
|
@@ -1816,75 +1739,6 @@ export class InteractiveShell {
|
|
|
1816
1739
|
}
|
|
1817
1740
|
return `${warning.label}: ${warning.reason}.`;
|
|
1818
1741
|
}
|
|
1819
|
-
buildLaunchCommandPalette() {
|
|
1820
|
-
const entries = [];
|
|
1821
|
-
const secretsSummary = this.summarizeSecretsForPalette();
|
|
1822
|
-
const toolSummary = this.getToolSelectionSummary();
|
|
1823
|
-
const autosaveLabel = this.autosaveEnabled ? 'on' : 'off';
|
|
1824
|
-
for (const command of this.slashCommands) {
|
|
1825
|
-
const entry = {
|
|
1826
|
-
command: command.command,
|
|
1827
|
-
description: command.description,
|
|
1828
|
-
category: command.category ?? 'other',
|
|
1829
|
-
};
|
|
1830
|
-
switch (command.command) {
|
|
1831
|
-
case '/secrets':
|
|
1832
|
-
if (secretsSummary.text) {
|
|
1833
|
-
entry.description = `${command.description} (${secretsSummary.text})`;
|
|
1834
|
-
entry.tone = secretsSummary.tone;
|
|
1835
|
-
}
|
|
1836
|
-
break;
|
|
1837
|
-
case '/tools':
|
|
1838
|
-
if (toolSummary) {
|
|
1839
|
-
entry.description = `${command.description} (${toolSummary})`;
|
|
1840
|
-
}
|
|
1841
|
-
break;
|
|
1842
|
-
case '/sessions':
|
|
1843
|
-
entry.description = `${command.description} (autosave ${autosaveLabel})`;
|
|
1844
|
-
break;
|
|
1845
|
-
case '/model':
|
|
1846
|
-
entry.description = `${command.description} (current: ${this.sessionState.model})`;
|
|
1847
|
-
break;
|
|
1848
|
-
case '/provider':
|
|
1849
|
-
entry.description = `${command.description} (current: ${this.providerLabel(this.sessionState.provider)})`;
|
|
1850
|
-
break;
|
|
1851
|
-
default:
|
|
1852
|
-
break;
|
|
1853
|
-
}
|
|
1854
|
-
entries.push(entry);
|
|
1855
|
-
}
|
|
1856
|
-
return entries;
|
|
1857
|
-
}
|
|
1858
|
-
summarizeSecretsForPalette() {
|
|
1859
|
-
const definitions = listSecretDefinitions();
|
|
1860
|
-
if (!definitions.length) {
|
|
1861
|
-
return { text: null };
|
|
1862
|
-
}
|
|
1863
|
-
const missing = definitions.filter((definition) => !getSecretValue(definition.id));
|
|
1864
|
-
if (missing.length === 0) {
|
|
1865
|
-
return { text: 'all configured', tone: 'success' };
|
|
1866
|
-
}
|
|
1867
|
-
const labels = missing.map((definition) => definition.label ?? definition.id);
|
|
1868
|
-
return { text: `missing ${this.formatList(labels)}`, tone: 'warn' };
|
|
1869
|
-
}
|
|
1870
|
-
getToolSelectionSummary() {
|
|
1871
|
-
const toolSettings = loadToolSettings();
|
|
1872
|
-
const selection = buildEnabledToolSet(toolSettings);
|
|
1873
|
-
const options = getToolToggleOptions();
|
|
1874
|
-
if (!options.length) {
|
|
1875
|
-
return null;
|
|
1876
|
-
}
|
|
1877
|
-
const enabledCount = options.filter((option) => selection.has(option.id)).length;
|
|
1878
|
-
return `${enabledCount}/${options.length} enabled`;
|
|
1879
|
-
}
|
|
1880
|
-
formatList(values, maxItems = 3) {
|
|
1881
|
-
if (!values.length) {
|
|
1882
|
-
return '';
|
|
1883
|
-
}
|
|
1884
|
-
const shown = values.slice(0, maxItems);
|
|
1885
|
-
const suffix = values.length > maxItems ? ', …' : '';
|
|
1886
|
-
return `${shown.join(', ')}${suffix}`;
|
|
1887
|
-
}
|
|
1888
1742
|
buildSlashCommandList(header) {
|
|
1889
1743
|
const lines = [theme.gradient.primary(header), ''];
|
|
1890
1744
|
for (const command of this.slashCommands) {
|
|
@@ -2454,7 +2308,6 @@ When truly finished with ALL tasks, explicitly state "TASK_FULLY_COMPLETE".`;
|
|
|
2454
2308
|
try {
|
|
2455
2309
|
// Send the request and capture the response (streaming disabled)
|
|
2456
2310
|
display.showThinking('Responding...');
|
|
2457
|
-
this.refreshStatusLine(true);
|
|
2458
2311
|
const response = await agent.send(currentPrompt, true);
|
|
2459
2312
|
await this.awaitPendingCleanup();
|
|
2460
2313
|
this.captureHistorySnapshot();
|
|
@@ -2954,10 +2807,8 @@ What's the next action?`;
|
|
|
2954
2807
|
try {
|
|
2955
2808
|
// Send the error to the agent for fixing
|
|
2956
2809
|
display.showThinking('Analyzing build errors');
|
|
2957
|
-
this.refreshStatusLine(true);
|
|
2958
2810
|
const response = await this.agent.send(prompt, true);
|
|
2959
2811
|
display.stopThinking();
|
|
2960
|
-
this.refreshStatusLine(true);
|
|
2961
2812
|
if (response) {
|
|
2962
2813
|
display.showAssistantMessage(response, { isFinal: true });
|
|
2963
2814
|
}
|
|
@@ -3007,16 +2858,18 @@ What's the next action?`;
|
|
|
3007
2858
|
display.showAssistantMessage(finalContent, enriched);
|
|
3008
2859
|
}
|
|
3009
2860
|
}
|
|
3010
|
-
//
|
|
2861
|
+
// Show status line at end (Claude Code style: "• Context X% used • Ready for prompts (2s)")
|
|
3011
2862
|
display.stopThinking();
|
|
3012
|
-
//
|
|
2863
|
+
// Calculate context usage
|
|
2864
|
+
let contextInfo;
|
|
3013
2865
|
if (enriched.contextWindowTokens && metadata.usage) {
|
|
3014
2866
|
const total = this.totalTokens(metadata.usage);
|
|
3015
2867
|
if (total && total > 0) {
|
|
3016
2868
|
const percentage = Math.round((total / enriched.contextWindowTokens) * 100);
|
|
3017
|
-
|
|
2869
|
+
contextInfo = { percentage, tokens: total };
|
|
3018
2870
|
}
|
|
3019
2871
|
}
|
|
2872
|
+
display.showStatusLine('Ready for prompts', enriched.elapsedMs, contextInfo);
|
|
3020
2873
|
// Auto-verify changes: build first (catches type errors), then tests
|
|
3021
2874
|
void this.enforceAutoBuild('final-response');
|
|
3022
2875
|
void this.enforceAutoTests('final-response');
|
|
@@ -3186,14 +3039,9 @@ What's the next action?`;
|
|
|
3186
3039
|
return null;
|
|
3187
3040
|
}
|
|
3188
3041
|
const usageRatio = total / windowTokens;
|
|
3189
|
-
this.latestTokenUsage = {
|
|
3190
|
-
used: total,
|
|
3191
|
-
limit: windowTokens,
|
|
3192
|
-
};
|
|
3193
3042
|
// Always update context usage in the UI
|
|
3194
3043
|
const percentUsed = Math.round(usageRatio * 100);
|
|
3195
3044
|
this.updateContextUsage(percentUsed);
|
|
3196
|
-
this.refreshStatusLine(true);
|
|
3197
3045
|
if (usageRatio < CONTEXT_USAGE_THRESHOLD) {
|
|
3198
3046
|
return null;
|
|
3199
3047
|
}
|