erosolar-cli 1.7.341 → 1.7.343
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 +24 -148
- package/dist/bin/erosolar.js +5 -21
- package/dist/bin/erosolar.js.map +1 -1
- package/dist/capabilities/agentSpawningCapability.d.ts.map +1 -1
- package/dist/capabilities/agentSpawningCapability.js +56 -31
- package/dist/capabilities/agentSpawningCapability.js.map +1 -1
- package/dist/contracts/agent-schemas.json +0 -15
- package/dist/contracts/tools.schema.json +0 -9
- package/dist/core/agent.d.ts +2 -2
- package/dist/core/agent.d.ts.map +1 -1
- package/dist/core/agent.js.map +1 -1
- package/dist/core/customCommands.d.ts +1 -0
- package/dist/core/customCommands.d.ts.map +1 -1
- package/dist/core/customCommands.js +3 -0
- package/dist/core/customCommands.js.map +1 -1
- package/dist/core/hooks.d.ts +113 -0
- package/dist/core/hooks.d.ts.map +1 -0
- package/dist/core/hooks.js +267 -0
- package/dist/core/hooks.js.map +1 -0
- package/dist/core/metricsTracker.d.ts +122 -0
- package/dist/core/metricsTracker.d.ts.map +1 -0
- package/dist/{alpha-zero → core}/metricsTracker.js +2 -5
- package/dist/core/metricsTracker.js.map +1 -0
- package/dist/core/securityAssessment.d.ts +91 -0
- package/dist/core/securityAssessment.d.ts.map +1 -0
- package/dist/core/securityAssessment.js +580 -0
- package/dist/core/securityAssessment.js.map +1 -0
- package/dist/core/sessionStore.d.ts +2 -0
- package/dist/core/sessionStore.d.ts.map +1 -1
- package/dist/core/sessionStore.js +1 -0
- package/dist/core/sessionStore.js.map +1 -1
- package/dist/core/toolPreconditions.d.ts.map +1 -1
- package/dist/core/toolPreconditions.js +0 -14
- package/dist/core/toolPreconditions.js.map +1 -1
- package/dist/core/toolRuntime.d.ts +22 -1
- package/dist/core/toolRuntime.d.ts.map +1 -1
- package/dist/core/toolRuntime.js +0 -5
- package/dist/core/toolRuntime.js.map +1 -1
- package/dist/core/toolValidation.d.ts.map +1 -1
- package/dist/core/toolValidation.js +14 -3
- package/dist/core/toolValidation.js.map +1 -1
- package/dist/core/validationRunner.d.ts +1 -3
- package/dist/core/validationRunner.d.ts.map +1 -1
- package/dist/core/validationRunner.js.map +1 -1
- package/dist/core/verification.d.ts +137 -0
- package/dist/core/verification.d.ts.map +1 -0
- package/dist/core/verification.js +323 -0
- package/dist/core/verification.js.map +1 -0
- package/dist/headless/headlessApp.d.ts.map +1 -1
- package/dist/headless/headlessApp.js +21 -0
- package/dist/headless/headlessApp.js.map +1 -1
- package/dist/mcp/sseClient.d.ts.map +1 -1
- package/dist/mcp/sseClient.js +9 -18
- package/dist/mcp/sseClient.js.map +1 -1
- package/dist/plugins/tools/build/buildPlugin.d.ts +0 -6
- package/dist/plugins/tools/build/buildPlugin.d.ts.map +1 -1
- package/dist/plugins/tools/build/buildPlugin.js +4 -10
- package/dist/plugins/tools/build/buildPlugin.js.map +1 -1
- package/dist/plugins/tools/nodeDefaults.d.ts.map +1 -1
- package/dist/plugins/tools/nodeDefaults.js +0 -2
- package/dist/plugins/tools/nodeDefaults.js.map +1 -1
- package/dist/runtime/agentSession.d.ts +2 -2
- package/dist/runtime/agentSession.d.ts.map +1 -1
- package/dist/runtime/agentSession.js +2 -2
- package/dist/runtime/agentSession.js.map +1 -1
- package/dist/shell/interactiveShell.d.ts +19 -7
- package/dist/shell/interactiveShell.d.ts.map +1 -1
- package/dist/shell/interactiveShell.js +271 -166
- package/dist/shell/interactiveShell.js.map +1 -1
- package/dist/shell/shellApp.d.ts +2 -0
- package/dist/shell/shellApp.d.ts.map +1 -1
- package/dist/shell/shellApp.js +82 -9
- package/dist/shell/shellApp.js.map +1 -1
- package/dist/shell/systemPrompt.d.ts.map +1 -1
- package/dist/shell/systemPrompt.js +1 -4
- package/dist/shell/systemPrompt.js.map +1 -1
- package/dist/shell/terminalInput.d.ts +218 -120
- package/dist/shell/terminalInput.d.ts.map +1 -1
- package/dist/shell/terminalInput.js +932 -537
- package/dist/shell/terminalInput.js.map +1 -1
- package/dist/shell/terminalInputAdapter.d.ts +99 -21
- package/dist/shell/terminalInputAdapter.d.ts.map +1 -1
- package/dist/shell/terminalInputAdapter.js +135 -30
- package/dist/shell/terminalInputAdapter.js.map +1 -1
- package/dist/subagents/agentConfig.d.ts +27 -0
- package/dist/subagents/agentConfig.d.ts.map +1 -0
- package/dist/subagents/agentConfig.js +89 -0
- package/dist/subagents/agentConfig.js.map +1 -0
- package/dist/subagents/agentRegistry.d.ts +33 -0
- package/dist/subagents/agentRegistry.d.ts.map +1 -0
- package/dist/subagents/agentRegistry.js +162 -0
- package/dist/subagents/agentRegistry.js.map +1 -0
- package/dist/subagents/taskRunner.d.ts +7 -1
- package/dist/subagents/taskRunner.d.ts.map +1 -1
- package/dist/subagents/taskRunner.js +180 -47
- package/dist/subagents/taskRunner.js.map +1 -1
- package/dist/ui/ShellUIAdapter.d.ts.map +1 -1
- package/dist/ui/ShellUIAdapter.js +13 -12
- package/dist/ui/ShellUIAdapter.js.map +1 -1
- package/dist/ui/display.d.ts +24 -45
- package/dist/ui/display.d.ts.map +1 -1
- package/dist/ui/display.js +140 -259
- package/dist/ui/display.js.map +1 -1
- package/dist/ui/theme.d.ts.map +1 -1
- package/dist/ui/theme.js +6 -8
- package/dist/ui/theme.js.map +1 -1
- package/dist/ui/toolDisplay.d.ts +0 -158
- package/dist/ui/toolDisplay.d.ts.map +1 -1
- package/dist/ui/toolDisplay.js +0 -348
- package/dist/ui/toolDisplay.js.map +1 -1
- package/dist/ui/unified/layout.d.ts +1 -0
- package/dist/ui/unified/layout.d.ts.map +1 -1
- package/dist/ui/unified/layout.js +25 -179
- package/dist/ui/unified/layout.js.map +1 -1
- package/dist/utils/frontmatter.d.ts +10 -0
- package/dist/utils/frontmatter.d.ts.map +1 -0
- package/dist/utils/frontmatter.js +78 -0
- package/dist/utils/frontmatter.js.map +1 -0
- package/package.json +4 -4
- package/dist/alpha-zero/agentWrapper.d.ts +0 -84
- package/dist/alpha-zero/agentWrapper.d.ts.map +0 -1
- package/dist/alpha-zero/agentWrapper.js +0 -171
- package/dist/alpha-zero/agentWrapper.js.map +0 -1
- package/dist/alpha-zero/codeEvaluator.d.ts +0 -25
- package/dist/alpha-zero/codeEvaluator.d.ts.map +0 -1
- package/dist/alpha-zero/codeEvaluator.js +0 -273
- package/dist/alpha-zero/codeEvaluator.js.map +0 -1
- package/dist/alpha-zero/competitiveRunner.d.ts +0 -66
- package/dist/alpha-zero/competitiveRunner.d.ts.map +0 -1
- package/dist/alpha-zero/competitiveRunner.js +0 -224
- package/dist/alpha-zero/competitiveRunner.js.map +0 -1
- package/dist/alpha-zero/index.d.ts +0 -67
- package/dist/alpha-zero/index.d.ts.map +0 -1
- package/dist/alpha-zero/index.js +0 -99
- package/dist/alpha-zero/index.js.map +0 -1
- package/dist/alpha-zero/introspection.d.ts +0 -128
- package/dist/alpha-zero/introspection.d.ts.map +0 -1
- package/dist/alpha-zero/introspection.js +0 -300
- package/dist/alpha-zero/introspection.js.map +0 -1
- package/dist/alpha-zero/metricsTracker.d.ts +0 -71
- package/dist/alpha-zero/metricsTracker.d.ts.map +0 -1
- package/dist/alpha-zero/metricsTracker.js.map +0 -1
- package/dist/alpha-zero/security/core.d.ts +0 -125
- package/dist/alpha-zero/security/core.d.ts.map +0 -1
- package/dist/alpha-zero/security/core.js +0 -271
- package/dist/alpha-zero/security/core.js.map +0 -1
- package/dist/alpha-zero/security/google.d.ts +0 -125
- package/dist/alpha-zero/security/google.d.ts.map +0 -1
- package/dist/alpha-zero/security/google.js +0 -311
- package/dist/alpha-zero/security/google.js.map +0 -1
- package/dist/alpha-zero/security/googleLoader.d.ts +0 -17
- package/dist/alpha-zero/security/googleLoader.d.ts.map +0 -1
- package/dist/alpha-zero/security/googleLoader.js +0 -41
- package/dist/alpha-zero/security/googleLoader.js.map +0 -1
- package/dist/alpha-zero/security/index.d.ts +0 -29
- package/dist/alpha-zero/security/index.d.ts.map +0 -1
- package/dist/alpha-zero/security/index.js +0 -32
- package/dist/alpha-zero/security/index.js.map +0 -1
- package/dist/alpha-zero/security/simulation.d.ts +0 -124
- package/dist/alpha-zero/security/simulation.d.ts.map +0 -1
- package/dist/alpha-zero/security/simulation.js +0 -277
- package/dist/alpha-zero/security/simulation.js.map +0 -1
- package/dist/alpha-zero/selfModification.d.ts +0 -109
- package/dist/alpha-zero/selfModification.d.ts.map +0 -1
- package/dist/alpha-zero/selfModification.js +0 -233
- package/dist/alpha-zero/selfModification.js.map +0 -1
- package/dist/alpha-zero/types.d.ts +0 -170
- package/dist/alpha-zero/types.d.ts.map +0 -1
- package/dist/alpha-zero/types.js +0 -31
- package/dist/alpha-zero/types.js.map +0 -1
- package/dist/capabilities/securityTestingCapability.d.ts +0 -13
- package/dist/capabilities/securityTestingCapability.d.ts.map +0 -1
- package/dist/capabilities/securityTestingCapability.js +0 -25
- package/dist/capabilities/securityTestingCapability.js.map +0 -1
- package/dist/core/aiFlowOptimizer.d.ts +0 -26
- package/dist/core/aiFlowOptimizer.d.ts.map +0 -1
- package/dist/core/aiFlowOptimizer.js +0 -31
- package/dist/core/aiFlowOptimizer.js.map +0 -1
- package/dist/core/aiOptimizationEngine.d.ts +0 -158
- package/dist/core/aiOptimizationEngine.d.ts.map +0 -1
- package/dist/core/aiOptimizationEngine.js +0 -428
- package/dist/core/aiOptimizationEngine.js.map +0 -1
- package/dist/core/aiOptimizationIntegration.d.ts +0 -93
- package/dist/core/aiOptimizationIntegration.d.ts.map +0 -1
- package/dist/core/aiOptimizationIntegration.js +0 -250
- package/dist/core/aiOptimizationIntegration.js.map +0 -1
- package/dist/core/enhancedErrorRecovery.d.ts +0 -100
- package/dist/core/enhancedErrorRecovery.d.ts.map +0 -1
- package/dist/core/enhancedErrorRecovery.js +0 -345
- package/dist/core/enhancedErrorRecovery.js.map +0 -1
- package/dist/core/hooksSystem.d.ts +0 -65
- package/dist/core/hooksSystem.d.ts.map +0 -1
- package/dist/core/hooksSystem.js +0 -273
- package/dist/core/hooksSystem.js.map +0 -1
- package/dist/core/memorySystem.d.ts +0 -48
- package/dist/core/memorySystem.d.ts.map +0 -1
- package/dist/core/memorySystem.js +0 -271
- package/dist/core/memorySystem.js.map +0 -1
- package/dist/core/unified/errors.d.ts +0 -189
- package/dist/core/unified/errors.d.ts.map +0 -1
- package/dist/core/unified/errors.js +0 -497
- package/dist/core/unified/errors.js.map +0 -1
- package/dist/core/unified/index.d.ts +0 -19
- package/dist/core/unified/index.d.ts.map +0 -1
- package/dist/core/unified/index.js +0 -68
- package/dist/core/unified/index.js.map +0 -1
- package/dist/core/unified/schema.d.ts +0 -101
- package/dist/core/unified/schema.d.ts.map +0 -1
- package/dist/core/unified/schema.js +0 -350
- package/dist/core/unified/schema.js.map +0 -1
- package/dist/core/unified/toolRuntime.d.ts +0 -179
- package/dist/core/unified/toolRuntime.d.ts.map +0 -1
- package/dist/core/unified/toolRuntime.js +0 -517
- package/dist/core/unified/toolRuntime.js.map +0 -1
- package/dist/core/unified/tools.d.ts +0 -127
- package/dist/core/unified/tools.d.ts.map +0 -1
- package/dist/core/unified/tools.js +0 -1333
- package/dist/core/unified/tools.js.map +0 -1
- package/dist/core/unified/types.d.ts +0 -352
- package/dist/core/unified/types.d.ts.map +0 -1
- package/dist/core/unified/types.js +0 -12
- package/dist/core/unified/types.js.map +0 -1
- package/dist/core/unified/version.d.ts +0 -209
- package/dist/core/unified/version.d.ts.map +0 -1
- package/dist/core/unified/version.js +0 -454
- package/dist/core/unified/version.js.map +0 -1
- package/dist/plugins/tools/security/securityPlugin.d.ts +0 -3
- package/dist/plugins/tools/security/securityPlugin.d.ts.map +0 -1
- package/dist/plugins/tools/security/securityPlugin.js +0 -12
- package/dist/plugins/tools/security/securityPlugin.js.map +0 -1
- package/dist/security/active-stack-security.d.ts +0 -112
- package/dist/security/active-stack-security.d.ts.map +0 -1
- package/dist/security/active-stack-security.js +0 -296
- package/dist/security/active-stack-security.js.map +0 -1
- package/dist/security/advanced-persistence-research.d.ts +0 -92
- package/dist/security/advanced-persistence-research.d.ts.map +0 -1
- package/dist/security/advanced-persistence-research.js +0 -195
- package/dist/security/advanced-persistence-research.js.map +0 -1
- package/dist/security/advanced-targeting.d.ts +0 -119
- package/dist/security/advanced-targeting.d.ts.map +0 -1
- package/dist/security/advanced-targeting.js +0 -233
- package/dist/security/advanced-targeting.js.map +0 -1
- package/dist/security/assessment/vulnerabilityAssessment.d.ts +0 -104
- package/dist/security/assessment/vulnerabilityAssessment.d.ts.map +0 -1
- package/dist/security/assessment/vulnerabilityAssessment.js +0 -315
- package/dist/security/assessment/vulnerabilityAssessment.js.map +0 -1
- package/dist/security/authorization/securityAuthorization.d.ts +0 -88
- package/dist/security/authorization/securityAuthorization.d.ts.map +0 -1
- package/dist/security/authorization/securityAuthorization.js +0 -172
- package/dist/security/authorization/securityAuthorization.js.map +0 -1
- package/dist/security/comprehensive-targeting.d.ts +0 -85
- package/dist/security/comprehensive-targeting.d.ts.map +0 -1
- package/dist/security/comprehensive-targeting.js +0 -438
- package/dist/security/comprehensive-targeting.js.map +0 -1
- package/dist/security/global-security-integration.d.ts +0 -91
- package/dist/security/global-security-integration.d.ts.map +0 -1
- package/dist/security/global-security-integration.js +0 -218
- package/dist/security/global-security-integration.js.map +0 -1
- package/dist/security/index.d.ts +0 -38
- package/dist/security/index.d.ts.map +0 -1
- package/dist/security/index.js +0 -47
- package/dist/security/index.js.map +0 -1
- package/dist/security/persistence-analyzer.d.ts +0 -56
- package/dist/security/persistence-analyzer.d.ts.map +0 -1
- package/dist/security/persistence-analyzer.js +0 -187
- package/dist/security/persistence-analyzer.js.map +0 -1
- package/dist/security/persistence-cli.d.ts +0 -36
- package/dist/security/persistence-cli.d.ts.map +0 -1
- package/dist/security/persistence-cli.js +0 -160
- package/dist/security/persistence-cli.js.map +0 -1
- package/dist/security/persistence-research.d.ts +0 -92
- package/dist/security/persistence-research.d.ts.map +0 -1
- package/dist/security/persistence-research.js +0 -364
- package/dist/security/persistence-research.js.map +0 -1
- package/dist/security/research/persistenceResearch.d.ts +0 -97
- package/dist/security/research/persistenceResearch.d.ts.map +0 -1
- package/dist/security/research/persistenceResearch.js +0 -282
- package/dist/security/research/persistenceResearch.js.map +0 -1
- package/dist/security/security-integration.d.ts +0 -74
- package/dist/security/security-integration.d.ts.map +0 -1
- package/dist/security/security-integration.js +0 -137
- package/dist/security/security-integration.js.map +0 -1
- package/dist/security/security-testing-framework.d.ts +0 -112
- package/dist/security/security-testing-framework.d.ts.map +0 -1
- package/dist/security/security-testing-framework.js +0 -364
- package/dist/security/security-testing-framework.js.map +0 -1
- package/dist/security/simulation/attackSimulation.d.ts +0 -93
- package/dist/security/simulation/attackSimulation.d.ts.map +0 -1
- package/dist/security/simulation/attackSimulation.js +0 -341
- package/dist/security/simulation/attackSimulation.js.map +0 -1
- package/dist/security/strategic-operations.d.ts +0 -100
- package/dist/security/strategic-operations.d.ts.map +0 -1
- package/dist/security/strategic-operations.js +0 -276
- package/dist/security/strategic-operations.js.map +0 -1
- package/dist/security/tool-security-wrapper.d.ts +0 -58
- package/dist/security/tool-security-wrapper.d.ts.map +0 -1
- package/dist/security/tool-security-wrapper.js +0 -156
- package/dist/security/tool-security-wrapper.js.map +0 -1
- package/dist/shell/claudeCodeStreamHandler.d.ts +0 -145
- package/dist/shell/claudeCodeStreamHandler.d.ts.map +0 -1
- package/dist/shell/claudeCodeStreamHandler.js +0 -322
- package/dist/shell/claudeCodeStreamHandler.js.map +0 -1
- package/dist/shell/inputQueueManager.d.ts +0 -144
- package/dist/shell/inputQueueManager.d.ts.map +0 -1
- package/dist/shell/inputQueueManager.js +0 -290
- package/dist/shell/inputQueueManager.js.map +0 -1
- package/dist/shell/metricsTracker.d.ts +0 -60
- package/dist/shell/metricsTracker.d.ts.map +0 -1
- package/dist/shell/metricsTracker.js +0 -119
- package/dist/shell/metricsTracker.js.map +0 -1
- package/dist/shell/streamingOutputManager.d.ts +0 -115
- package/dist/shell/streamingOutputManager.d.ts.map +0 -1
- package/dist/shell/streamingOutputManager.js +0 -225
- package/dist/shell/streamingOutputManager.js.map +0 -1
- package/dist/tools/securityTools.d.ts +0 -22
- package/dist/tools/securityTools.d.ts.map +0 -1
- package/dist/tools/securityTools.js +0 -448
- package/dist/tools/securityTools.js.map +0 -1
- package/dist/ui/persistentPrompt.d.ts +0 -50
- package/dist/ui/persistentPrompt.d.ts.map +0 -1
- package/dist/ui/persistentPrompt.js +0 -92
- package/dist/ui/persistentPrompt.js.map +0 -1
- package/dist/ui/terminalUISchema.d.ts +0 -195
- package/dist/ui/terminalUISchema.d.ts.map +0 -1
- package/dist/ui/terminalUISchema.js +0 -113
- package/dist/ui/terminalUISchema.js.map +0 -1
- package/scripts/deploy-security-capabilities.js +0 -178
|
@@ -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
|
|
5
|
+
import { theme } 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';
|
|
@@ -19,11 +19,11 @@ import { SkillRepository } from '../skills/skillRepository.js';
|
|
|
19
19
|
import { createSkillTools } from '../tools/skillTools.js';
|
|
20
20
|
import { FileChangeTracker } from './fileChangeTracker.js';
|
|
21
21
|
import { formatShortcutsHelp } from '../ui/shortcutsHelp.js';
|
|
22
|
-
import { MetricsTracker } from '
|
|
22
|
+
import { MetricsTracker } from '../core/metricsTracker.js';
|
|
23
23
|
import { listAvailablePlugins } from '../plugins/index.js';
|
|
24
|
-
import { loadMemory, listMemoryPaths, getDefaultProjectMemoryPath, getUserMemoryEditPath, } from '../core/memorySystem.js';
|
|
25
24
|
import { TerminalInputAdapter } from './terminalInputAdapter.js';
|
|
26
|
-
import {
|
|
25
|
+
import { renderSessionFrame } from '../ui/unified/layout.js';
|
|
26
|
+
import { isUpdateInProgress, maybeOfferCliUpdate } from './updateManager.js';
|
|
27
27
|
import { writeLock } from '../ui/writeLock.js';
|
|
28
28
|
import { enterStreamingMode, exitStreamingMode } from '../ui/globalWriteLock.js';
|
|
29
29
|
const execAsync = promisify(exec);
|
|
@@ -35,6 +35,7 @@ const DROPDOWN_COLORS = [
|
|
|
35
35
|
theme.success,
|
|
36
36
|
theme.warning,
|
|
37
37
|
];
|
|
38
|
+
const STREAMING_SPINNER_FRAMES = ['◐', '◓', '◑', '◒'];
|
|
38
39
|
// Load MODEL_PRESETS from centralized schema
|
|
39
40
|
const MODEL_PRESETS = getModels().map((model) => ({
|
|
40
41
|
id: model.id,
|
|
@@ -49,11 +50,13 @@ const MODEL_PRESETS = getModels().map((model) => ({
|
|
|
49
50
|
const BASE_SLASH_COMMANDS = getSlashCommands().map((cmd) => ({
|
|
50
51
|
command: cmd.command,
|
|
51
52
|
description: cmd.description,
|
|
53
|
+
category: cmd.category,
|
|
52
54
|
}));
|
|
53
55
|
// Load PROVIDER_LABELS from centralized schema
|
|
54
56
|
const PROVIDER_LABELS = Object.fromEntries(getProviders().map((provider) => [provider.id, provider.label]));
|
|
55
57
|
// Allow enough time for paste detection to kick in before flushing buffered lines
|
|
56
58
|
const CONTEXT_USAGE_THRESHOLD = 0.9;
|
|
59
|
+
const CONTEXT_AUTOCOMPACT_PERCENT = Math.round(CONTEXT_USAGE_THRESHOLD * 100);
|
|
57
60
|
const CONTEXT_RECENT_MESSAGE_COUNT = 12;
|
|
58
61
|
const CONTEXT_CLEANUP_CHARS_PER_CHUNK = 6000;
|
|
59
62
|
const CONTEXT_CLEANUP_MAX_OUTPUT_TOKENS = 800;
|
|
@@ -94,11 +97,12 @@ export class InteractiveShell {
|
|
|
94
97
|
uiAdapter;
|
|
95
98
|
uiUpdates;
|
|
96
99
|
_fileChangeTracker = new FileChangeTracker(); // Reserved for future file tracking features
|
|
97
|
-
|
|
100
|
+
alphaZeroMetrics; // Alpha Zero 2 performance tracking
|
|
98
101
|
statusSubscription = null;
|
|
99
102
|
followUpQueue = [];
|
|
100
103
|
isDrainingQueue = false;
|
|
101
104
|
activeContextWindowTokens = null;
|
|
105
|
+
latestTokenUsage = { used: null, limit: null };
|
|
102
106
|
sessionPreferences;
|
|
103
107
|
autosaveEnabled;
|
|
104
108
|
autoContinueEnabled;
|
|
@@ -129,6 +133,9 @@ export class InteractiveShell {
|
|
|
129
133
|
statusLineState = null;
|
|
130
134
|
statusMessageOverride = null;
|
|
131
135
|
promptRefreshTimer = null;
|
|
136
|
+
launchPaletteShown = false;
|
|
137
|
+
version;
|
|
138
|
+
alternateScreenEnabled;
|
|
132
139
|
constructor(config) {
|
|
133
140
|
this.profile = config.profile;
|
|
134
141
|
this.profileLabel = config.profileLabel;
|
|
@@ -142,6 +149,8 @@ export class InteractiveShell {
|
|
|
142
149
|
this.autoContinueEnabled = this.sessionPreferences.autoContinue;
|
|
143
150
|
this.sessionRestoreConfig = config.sessionRestore ?? { mode: 'none' };
|
|
144
151
|
this._enabledPlugins = config.enabledPlugins ?? [];
|
|
152
|
+
this.version = config.version ?? '0.0.0';
|
|
153
|
+
this.alternateScreenEnabled = config.alternateScreen ?? true;
|
|
145
154
|
this.initializeSessionHistory();
|
|
146
155
|
this.sessionState = {
|
|
147
156
|
provider: config.initialModel.provider,
|
|
@@ -162,6 +171,7 @@ export class InteractiveShell {
|
|
|
162
171
|
this.slashCommands.push({
|
|
163
172
|
command: '/agents',
|
|
164
173
|
description: 'Select the default agent profile (applies on next launch)',
|
|
174
|
+
category: 'configuration',
|
|
165
175
|
});
|
|
166
176
|
}
|
|
167
177
|
this.customCommands = loadCustomSlashCommands();
|
|
@@ -170,18 +180,21 @@ export class InteractiveShell {
|
|
|
170
180
|
this.slashCommands.push({
|
|
171
181
|
command: custom.command,
|
|
172
182
|
description: `${custom.description} (custom)`,
|
|
183
|
+
category: custom.category ?? 'other',
|
|
173
184
|
});
|
|
174
185
|
}
|
|
175
186
|
if (!this.slashCommands.some((cmd) => cmd.command === '/exit')) {
|
|
176
187
|
this.slashCommands.push({
|
|
177
188
|
command: '/exit',
|
|
178
189
|
description: 'Quit the CLI immediately',
|
|
190
|
+
category: 'other',
|
|
179
191
|
});
|
|
180
192
|
}
|
|
181
193
|
// Add /plugins command
|
|
182
194
|
this.slashCommands.push({
|
|
183
195
|
command: '/plugins',
|
|
184
196
|
description: 'Show available and loaded plugins',
|
|
197
|
+
category: 'configuration',
|
|
185
198
|
});
|
|
186
199
|
this.statusTracker = config.statusTracker;
|
|
187
200
|
this.ui = config.ui;
|
|
@@ -214,19 +227,25 @@ export class InteractiveShell {
|
|
|
214
227
|
onToggleVerify: () => this.toggleVerificationMode(),
|
|
215
228
|
onToggleAutoContinue: () => this.toggleAutoContinueMode(),
|
|
216
229
|
});
|
|
217
|
-
// Register output interceptor for cursor positioning during streaming
|
|
218
|
-
this.terminalInput.registerOutputInterceptor(display);
|
|
219
|
-
// Set banner content to be written during unified UI initialization
|
|
220
|
-
this.terminalInput.setBannerContent(display.getBannerContent());
|
|
221
|
-
// Initialize unified UI - clears screen, sets up scroll region, writes banner,
|
|
222
|
-
// and renders input area at bottom
|
|
223
|
-
this.terminalInput.initializeUnifiedUI();
|
|
224
230
|
// Initialize Alpha Zero 2 metrics tracking
|
|
225
|
-
this.
|
|
231
|
+
this.alphaZeroMetrics = new MetricsTracker(`${this.profile}-${Date.now()}`);
|
|
226
232
|
this.setupStatusTracking();
|
|
227
233
|
this.refreshContextGauge();
|
|
234
|
+
// Start terminal input (sets up handlers)
|
|
228
235
|
this.terminalInput.start();
|
|
236
|
+
// Enter alternate screen buffer when enabled, otherwise clear the main screen for layout
|
|
237
|
+
if (this.alternateScreenEnabled) {
|
|
238
|
+
this.terminalInput.enterAlternateScreen();
|
|
239
|
+
}
|
|
240
|
+
else if (output.isTTY) {
|
|
241
|
+
this.terminalInput.clearScreen();
|
|
242
|
+
}
|
|
243
|
+
// Stream banner first - this sets up scroll region dynamically
|
|
244
|
+
const banner = this.buildBanner();
|
|
245
|
+
this.terminalInput.streamContent(banner + '\n\n');
|
|
246
|
+
// Render chat box after banner is streamed
|
|
229
247
|
this.refreshControlBar();
|
|
248
|
+
this.terminalInput.forceRender();
|
|
230
249
|
this.rebuildAgent();
|
|
231
250
|
this.setupHandlers();
|
|
232
251
|
this.refreshBannerSessionInfo();
|
|
@@ -246,6 +265,10 @@ export class InteractiveShell {
|
|
|
246
265
|
this.activeSessionId = stored.id;
|
|
247
266
|
this.activeSessionTitle = stored.title;
|
|
248
267
|
this.sessionResumeNotice = `Resumed session "${stored.title}".`;
|
|
268
|
+
// Restore scrollback buffer if available
|
|
269
|
+
if (stored.scrollbackBuffer && Array.isArray(stored.scrollbackBuffer)) {
|
|
270
|
+
this.terminalInput.loadScrollbackBuffer(stored.scrollbackBuffer);
|
|
271
|
+
}
|
|
249
272
|
return;
|
|
250
273
|
}
|
|
251
274
|
display.showWarning(`Session "${this.sessionRestoreConfig.sessionId}" not found. Starting fresh session.`);
|
|
@@ -259,6 +282,10 @@ export class InteractiveShell {
|
|
|
259
282
|
this.activeSessionId = null;
|
|
260
283
|
this.activeSessionTitle = autosave.title;
|
|
261
284
|
this.sessionResumeNotice = 'Restored last autosaved session.';
|
|
285
|
+
// Restore scrollback buffer if available
|
|
286
|
+
if (autosave.scrollbackBuffer && Array.isArray(autosave.scrollbackBuffer)) {
|
|
287
|
+
this.terminalInput.loadScrollbackBuffer(autosave.scrollbackBuffer);
|
|
288
|
+
}
|
|
262
289
|
return;
|
|
263
290
|
}
|
|
264
291
|
display.showWarning('No autosaved session found. Starting fresh session.');
|
|
@@ -273,14 +300,24 @@ export class InteractiveShell {
|
|
|
273
300
|
this.sessionResumeNotice = null;
|
|
274
301
|
}
|
|
275
302
|
async start(initialPrompt) {
|
|
303
|
+
// Check for updates in background (non-blocking)
|
|
304
|
+
if (this.version) {
|
|
305
|
+
void maybeOfferCliUpdate(this.version);
|
|
306
|
+
}
|
|
276
307
|
if (initialPrompt) {
|
|
277
308
|
this.logUserPrompt(initialPrompt);
|
|
278
309
|
await this.processInputBlock(initialPrompt);
|
|
279
310
|
return;
|
|
280
311
|
}
|
|
312
|
+
this.showLaunchCommandPalette();
|
|
281
313
|
// Ensure the terminal input is visible
|
|
282
314
|
this.terminalInput.render();
|
|
283
315
|
}
|
|
316
|
+
showLaunchCommandPalette() {
|
|
317
|
+
// Disabled: Quick commands palette takes up too much space
|
|
318
|
+
// Users can type /help to see available commands
|
|
319
|
+
this.launchPaletteShown = true;
|
|
320
|
+
}
|
|
284
321
|
/**
|
|
285
322
|
* TerminalInputAdapter submit handler
|
|
286
323
|
*/
|
|
@@ -294,9 +331,8 @@ export class InteractiveShell {
|
|
|
294
331
|
this.handleInputChange('');
|
|
295
332
|
return;
|
|
296
333
|
}
|
|
297
|
-
//
|
|
298
|
-
//
|
|
299
|
-
this.terminalInput.setStreaming(true);
|
|
334
|
+
// DON'T clear the input here - keep it visible while streaming.
|
|
335
|
+
// The input will be cleared after streaming completes in the finally block.
|
|
300
336
|
this.logUserPrompt(approved);
|
|
301
337
|
void this.processInputBlock(approved).catch((err) => {
|
|
302
338
|
display.showError(err instanceof Error ? err.message : String(err), err);
|
|
@@ -485,6 +521,10 @@ export class InteractiveShell {
|
|
|
485
521
|
return;
|
|
486
522
|
}
|
|
487
523
|
this.shuttingDown = true;
|
|
524
|
+
const shouldRestoreScrollback = this.alternateScreenEnabled && this.terminalInput.isAlternateScreenActive();
|
|
525
|
+
const scrollbackSnapshot = shouldRestoreScrollback
|
|
526
|
+
? this.terminalInput.getScrollbackSnapshot()
|
|
527
|
+
: null;
|
|
488
528
|
// Stop any active spinner to prevent process hang
|
|
489
529
|
display.stopThinking(false);
|
|
490
530
|
this.stopStreamingHeartbeat();
|
|
@@ -493,18 +533,34 @@ export class InteractiveShell {
|
|
|
493
533
|
this.teardownStatusTracking();
|
|
494
534
|
// Clear any pending cleanup to prevent hanging
|
|
495
535
|
this.pendingCleanup = null;
|
|
536
|
+
// Reset terminal state before disposing adapters
|
|
537
|
+
this.terminalInput.exitStreamingScrollRegion();
|
|
538
|
+
if (this.alternateScreenEnabled) {
|
|
539
|
+
this.terminalInput.exitAlternateScreen();
|
|
540
|
+
}
|
|
496
541
|
// Dispose terminal input handler
|
|
497
542
|
this.terminalInput.dispose();
|
|
498
543
|
// Dispose unified UI adapter
|
|
499
544
|
this.uiAdapter.dispose();
|
|
545
|
+
if (scrollbackSnapshot && scrollbackSnapshot.length > 0) {
|
|
546
|
+
this.restoreScrollbackSnapshot(scrollbackSnapshot);
|
|
547
|
+
}
|
|
500
548
|
display.newLine();
|
|
501
|
-
|
|
502
|
-
console.log(theme.
|
|
503
|
-
console.log(
|
|
504
|
-
console.log(` ${theme.ui.muted('Support:')} ${theme.info('support@ero.solar')}`);
|
|
505
|
-
console.log(theme.gradient.warm('━'.repeat(50)));
|
|
549
|
+
console.log(theme.ui.muted('━'.repeat(44)));
|
|
550
|
+
console.log(theme.ui.muted(' Goodbye! · support@ero.solar'));
|
|
551
|
+
console.log(theme.ui.muted('━'.repeat(44)));
|
|
506
552
|
exit(0);
|
|
507
553
|
}
|
|
554
|
+
restoreScrollbackSnapshot(lines) {
|
|
555
|
+
if (!lines.length) {
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
const transcript = lines.join('\n');
|
|
559
|
+
const separator = theme.ui.muted('─'.repeat(44));
|
|
560
|
+
const header = theme.ui.muted('Restored scrollback from this session:');
|
|
561
|
+
// Write directly to stdout after exiting alternate screen to preserve the transcript
|
|
562
|
+
process.stdout.write(`\n${separator}\n${header}\n${transcript}\n${separator}\n`);
|
|
563
|
+
}
|
|
508
564
|
/**
|
|
509
565
|
* Update status bar message
|
|
510
566
|
*/
|
|
@@ -672,13 +728,14 @@ export class InteractiveShell {
|
|
|
672
728
|
});
|
|
673
729
|
}
|
|
674
730
|
setProcessingStatus(detail) {
|
|
731
|
+
this.latestTokenUsage = { used: null, limit: this.latestTokenUsage.limit };
|
|
675
732
|
this.statusTracker.setBase('Working on your request', {
|
|
676
733
|
detail: this.describeStatusDetail(detail),
|
|
677
734
|
tone: 'info',
|
|
678
735
|
});
|
|
679
736
|
}
|
|
680
737
|
describeStatusDetail(detail) {
|
|
681
|
-
const parts =
|
|
738
|
+
const parts = detail?.trim() ? [detail.trim()] : [];
|
|
682
739
|
const queued = this.followUpQueue.length;
|
|
683
740
|
if (queued > 0) {
|
|
684
741
|
parts.push(`${queued} follow-up${queued === 1 ? '' : 's'} queued`);
|
|
@@ -691,12 +748,18 @@ export class InteractiveShell {
|
|
|
691
748
|
}
|
|
692
749
|
refreshContextGauge() {
|
|
693
750
|
const tokens = getContextWindowTokens(this.sessionState.model);
|
|
694
|
-
|
|
695
|
-
|
|
751
|
+
const normalizedTokens = typeof tokens === 'number' && Number.isFinite(tokens) ? tokens : null;
|
|
752
|
+
this.activeContextWindowTokens = normalizedTokens;
|
|
753
|
+
if (normalizedTokens !== null) {
|
|
754
|
+
this.latestTokenUsage = {
|
|
755
|
+
used: this.latestTokenUsage.used,
|
|
756
|
+
limit: normalizedTokens,
|
|
757
|
+
};
|
|
758
|
+
}
|
|
696
759
|
}
|
|
697
760
|
updateContextUsage(percentage) {
|
|
698
761
|
this.uiAdapter.updateContextUsage(percentage);
|
|
699
|
-
this.terminalInput.setContextUsage(percentage);
|
|
762
|
+
this.terminalInput.setContextUsage(percentage, CONTEXT_AUTOCOMPACT_PERCENT);
|
|
700
763
|
}
|
|
701
764
|
refreshControlBar() {
|
|
702
765
|
this.terminalInput.setModeToggles({
|
|
@@ -704,9 +767,9 @@ export class InteractiveShell {
|
|
|
704
767
|
autoContinueEnabled: this.autoContinueEnabled,
|
|
705
768
|
verificationHotkey: 'alt+v',
|
|
706
769
|
autoContinueHotkey: 'alt+c',
|
|
770
|
+
thinkingModeLabel: this.thinkingMode,
|
|
771
|
+
thinkingHotkey: '/thinking',
|
|
707
772
|
});
|
|
708
|
-
// Update persistent model info display
|
|
709
|
-
this.terminalInput.setModelInfo(this.describeModelDetail());
|
|
710
773
|
this.refreshStatusLine();
|
|
711
774
|
this.terminalInput.render();
|
|
712
775
|
}
|
|
@@ -737,6 +800,25 @@ export class InteractiveShell {
|
|
|
737
800
|
// Set main status (tool execution, etc.) - shown when not overridden
|
|
738
801
|
const statusText = this.formatStatusLine(this.statusLineState);
|
|
739
802
|
this.terminalInput.setStatusMessage(statusText);
|
|
803
|
+
// Surface meta header (elapsed + context usage) above the divider
|
|
804
|
+
const elapsedSeconds = this.statusLineState
|
|
805
|
+
? Math.max(0, Math.floor((Date.now() - this.statusLineState.startedAt) / 1000))
|
|
806
|
+
: null;
|
|
807
|
+
const thinkingMs = display.isSpinnerActive() ? display.getThinkingElapsedMs() : null;
|
|
808
|
+
const tokensUsed = this.latestTokenUsage.used;
|
|
809
|
+
const tokenLimit = this.latestTokenUsage.limit ?? this.activeContextWindowTokens;
|
|
810
|
+
this.terminalInput.setMetaStatus({
|
|
811
|
+
elapsedSeconds,
|
|
812
|
+
tokensUsed,
|
|
813
|
+
tokenLimit,
|
|
814
|
+
thinkingMs,
|
|
815
|
+
thinkingHasContent: display.isSpinnerActive(),
|
|
816
|
+
});
|
|
817
|
+
// Keep model/provider visible in the controls bar
|
|
818
|
+
this.terminalInput.setModelContext({
|
|
819
|
+
model: this.sessionState.model,
|
|
820
|
+
provider: this.providerLabel(this.sessionState.provider),
|
|
821
|
+
});
|
|
740
822
|
if (forceRender) {
|
|
741
823
|
this.terminalInput.render();
|
|
742
824
|
}
|
|
@@ -796,15 +878,14 @@ export class InteractiveShell {
|
|
|
796
878
|
this.terminalInput.render();
|
|
797
879
|
}
|
|
798
880
|
/**
|
|
799
|
-
* Log
|
|
800
|
-
* This creates a persistent log entry that remains visible during and after streaming.
|
|
881
|
+
* Log user prompt to the scroll region so it's part of the conversation flow.
|
|
801
882
|
*/
|
|
802
883
|
logUserPrompt(text) {
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
this.terminalInput.
|
|
884
|
+
if (!text.trim())
|
|
885
|
+
return;
|
|
886
|
+
// Format with user prompt prefix and write to scroll region
|
|
887
|
+
const formatted = `${theme.user('>')} ${text}\n`;
|
|
888
|
+
this.terminalInput.writeToScrollRegion(formatted);
|
|
808
889
|
}
|
|
809
890
|
requestPromptRefresh(force = false) {
|
|
810
891
|
if (force) {
|
|
@@ -829,16 +910,40 @@ export class InteractiveShell {
|
|
|
829
910
|
this.stopStreamingHeartbeat();
|
|
830
911
|
// Enter global streaming mode - blocks all non-streaming UI output
|
|
831
912
|
enterStreamingMode();
|
|
913
|
+
// Set up scroll region for streaming content
|
|
914
|
+
this.terminalInput.enterStreamingScrollRegion();
|
|
832
915
|
this.uiUpdates.setMode('streaming');
|
|
833
916
|
this.streamingHeartbeatStart = Date.now();
|
|
834
917
|
this.streamingHeartbeatFrame = 0;
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
918
|
+
const initialFrame = STREAMING_SPINNER_FRAMES[this.streamingHeartbeatFrame];
|
|
919
|
+
this.streamingStatusLabel = this.buildStreamingStatus(`${initialFrame} ${label}`, 0);
|
|
920
|
+
display.updateStreamingStatus(this.streamingStatusLabel);
|
|
921
|
+
this.refreshStatusLine(true);
|
|
922
|
+
// Periodically refresh the pinned input/status region while streaming so
|
|
923
|
+
// elapsed time remains visible without interrupting the scroll region.
|
|
924
|
+
this.uiUpdates.startHeartbeat('streaming', {
|
|
925
|
+
intervalMs: 1000,
|
|
926
|
+
lane: 'heartbeat',
|
|
927
|
+
mode: ['streaming', 'processing'],
|
|
928
|
+
coalesceKey: 'streaming:heartbeat',
|
|
929
|
+
run: () => {
|
|
930
|
+
const elapsedSeconds = this.streamingHeartbeatStart
|
|
931
|
+
? Math.max(0, Math.floor((Date.now() - this.streamingHeartbeatStart) / 1000))
|
|
932
|
+
: 0;
|
|
933
|
+
this.streamingHeartbeatFrame =
|
|
934
|
+
(this.streamingHeartbeatFrame + 1) % STREAMING_SPINNER_FRAMES.length;
|
|
935
|
+
const frame = STREAMING_SPINNER_FRAMES[this.streamingHeartbeatFrame];
|
|
936
|
+
this.streamingStatusLabel = this.buildStreamingStatus(`${frame} ${label}`, elapsedSeconds);
|
|
937
|
+
display.updateStreamingStatus(this.streamingStatusLabel);
|
|
938
|
+
this.refreshStatusLine(true);
|
|
939
|
+
},
|
|
940
|
+
});
|
|
838
941
|
}
|
|
839
942
|
stopStreamingHeartbeat() {
|
|
840
943
|
// Exit global streaming mode - allows UI to render again
|
|
841
944
|
exitStreamingMode();
|
|
945
|
+
// Exit scroll region mode
|
|
946
|
+
this.terminalInput.exitStreamingScrollRegion();
|
|
842
947
|
this.uiUpdates.stopHeartbeat('streaming');
|
|
843
948
|
this.streamingHeartbeatStart = null;
|
|
844
949
|
this.streamingHeartbeatFrame = 0;
|
|
@@ -850,10 +955,28 @@ export class InteractiveShell {
|
|
|
850
955
|
// Force refresh to update the input area now that streaming has ended
|
|
851
956
|
this.refreshStatusLine(true);
|
|
852
957
|
}
|
|
853
|
-
buildStreamingStatus(label) {
|
|
958
|
+
buildStreamingStatus(label, elapsedSeconds) {
|
|
854
959
|
const detail = this.describeModelDetail();
|
|
855
|
-
const
|
|
856
|
-
|
|
960
|
+
const elapsedLabel = typeof elapsedSeconds === 'number' && elapsedSeconds >= 0
|
|
961
|
+
? theme.ui.muted(this.formatElapsedShort(elapsedSeconds))
|
|
962
|
+
: null;
|
|
963
|
+
const prefix = theme.info('⏺');
|
|
964
|
+
const parts = [label];
|
|
965
|
+
if (detail) {
|
|
966
|
+
parts.push(theme.ui.muted('·'), detail);
|
|
967
|
+
}
|
|
968
|
+
if (elapsedLabel) {
|
|
969
|
+
parts.push(theme.ui.muted('·'), elapsedLabel);
|
|
970
|
+
}
|
|
971
|
+
return `${prefix} ${parts.join(' ')}`.trim();
|
|
972
|
+
}
|
|
973
|
+
formatElapsedShort(seconds) {
|
|
974
|
+
if (seconds < 60) {
|
|
975
|
+
return `${seconds}s`;
|
|
976
|
+
}
|
|
977
|
+
const minutes = Math.floor(seconds / 60);
|
|
978
|
+
const remaining = seconds % 60;
|
|
979
|
+
return remaining > 0 ? `${minutes}m ${remaining}s` : `${minutes}m`;
|
|
857
980
|
}
|
|
858
981
|
refreshQueueIndicators() {
|
|
859
982
|
if (this.isProcessing) {
|
|
@@ -1101,17 +1224,6 @@ export class InteractiveShell {
|
|
|
1101
1224
|
case '/discover':
|
|
1102
1225
|
await this.discoverModelsCommand();
|
|
1103
1226
|
break;
|
|
1104
|
-
case '/memory':
|
|
1105
|
-
this.handleMemoryCommand(input);
|
|
1106
|
-
break;
|
|
1107
|
-
case '/clear':
|
|
1108
|
-
display.clear();
|
|
1109
|
-
this.cachedHistory = [];
|
|
1110
|
-
display.showInfo('Conversation cleared.');
|
|
1111
|
-
break;
|
|
1112
|
-
case '/help':
|
|
1113
|
-
this.showHelp();
|
|
1114
|
-
break;
|
|
1115
1227
|
default:
|
|
1116
1228
|
if (!(await this.tryCustomSlashCommand(command, input))) {
|
|
1117
1229
|
display.showWarning(`Unknown command "${command}".`);
|
|
@@ -1420,99 +1532,6 @@ export class InteractiveShell {
|
|
|
1420
1532
|
// Display keyboard shortcuts help (Claude Code style)
|
|
1421
1533
|
display.showSystemMessage(formatShortcutsHelp());
|
|
1422
1534
|
}
|
|
1423
|
-
handleMemoryCommand(input) {
|
|
1424
|
-
const tokens = input.trim().split(/\s+/).slice(1);
|
|
1425
|
-
const action = (tokens.shift() ?? 'show').toLowerCase();
|
|
1426
|
-
switch (action) {
|
|
1427
|
-
case '':
|
|
1428
|
-
case 'show':
|
|
1429
|
-
case 'list': {
|
|
1430
|
-
this.showMemoryStatus();
|
|
1431
|
-
break;
|
|
1432
|
-
}
|
|
1433
|
-
case 'paths': {
|
|
1434
|
-
this.showMemoryPaths();
|
|
1435
|
-
break;
|
|
1436
|
-
}
|
|
1437
|
-
case 'edit': {
|
|
1438
|
-
const level = (tokens[0] ?? 'project').toLowerCase();
|
|
1439
|
-
this.openMemoryForEdit(level);
|
|
1440
|
-
break;
|
|
1441
|
-
}
|
|
1442
|
-
default:
|
|
1443
|
-
display.showWarning('Usage: /memory [show|paths|edit <user|project>]');
|
|
1444
|
-
break;
|
|
1445
|
-
}
|
|
1446
|
-
}
|
|
1447
|
-
showMemoryStatus() {
|
|
1448
|
-
const memory = loadMemory(this.workingDir);
|
|
1449
|
-
const lines = [];
|
|
1450
|
-
lines.push(theme.bold('Persistent Memory'));
|
|
1451
|
-
lines.push('');
|
|
1452
|
-
if (memory.sources.length === 0) {
|
|
1453
|
-
lines.push(theme.secondary('No memory files found.'));
|
|
1454
|
-
lines.push('');
|
|
1455
|
-
lines.push(`Create ${theme.info('EROSOLAR.md')} in your project to add persistent context.`);
|
|
1456
|
-
lines.push(`Use ${theme.info('/memory edit project')} to create one.`);
|
|
1457
|
-
}
|
|
1458
|
-
else {
|
|
1459
|
-
for (const source of memory.sources) {
|
|
1460
|
-
const levelLabel = source.level === 'enterprise' ? 'Enterprise' :
|
|
1461
|
-
source.level === 'user' ? 'User' : 'Project';
|
|
1462
|
-
const preview = source.content.slice(0, 200).replace(/\n/g, ' ').trim();
|
|
1463
|
-
const truncated = source.content.length > 200 ? '...' : '';
|
|
1464
|
-
lines.push(`${theme.success('●')} ${theme.bold(levelLabel)}: ${source.path}`);
|
|
1465
|
-
lines.push(` ${theme.dim(preview + truncated)}`);
|
|
1466
|
-
lines.push('');
|
|
1467
|
-
}
|
|
1468
|
-
if (memory.importedPaths.length > memory.sources.length) {
|
|
1469
|
-
lines.push(theme.secondary(`Imported ${memory.importedPaths.length - memory.sources.length} additional files via @imports.`));
|
|
1470
|
-
}
|
|
1471
|
-
}
|
|
1472
|
-
display.showSystemMessage(lines.join('\n'));
|
|
1473
|
-
}
|
|
1474
|
-
showMemoryPaths() {
|
|
1475
|
-
const paths = listMemoryPaths(this.workingDir);
|
|
1476
|
-
const lines = [];
|
|
1477
|
-
lines.push(theme.bold('Memory File Locations'));
|
|
1478
|
-
lines.push('');
|
|
1479
|
-
for (const { level, path, exists } of paths) {
|
|
1480
|
-
const icon = exists ? theme.success('✓') : theme.dim('○');
|
|
1481
|
-
const levelLabel = level.charAt(0).toUpperCase() + level.slice(1);
|
|
1482
|
-
lines.push(`${icon} ${levelLabel}: ${path}`);
|
|
1483
|
-
}
|
|
1484
|
-
lines.push('');
|
|
1485
|
-
lines.push(theme.secondary('Create any of these files to add persistent memory.'));
|
|
1486
|
-
lines.push(theme.secondary('Use @path/to/file.md syntax to import other files.'));
|
|
1487
|
-
display.showSystemMessage(lines.join('\n'));
|
|
1488
|
-
}
|
|
1489
|
-
openMemoryForEdit(level) {
|
|
1490
|
-
let targetPath;
|
|
1491
|
-
if (level === 'user') {
|
|
1492
|
-
targetPath = getUserMemoryEditPath();
|
|
1493
|
-
}
|
|
1494
|
-
else if (level === 'project') {
|
|
1495
|
-
targetPath = getDefaultProjectMemoryPath(this.workingDir);
|
|
1496
|
-
}
|
|
1497
|
-
else {
|
|
1498
|
-
display.showWarning('Specify "user" or "project" to edit. Enterprise memory is read-only.');
|
|
1499
|
-
return;
|
|
1500
|
-
}
|
|
1501
|
-
display.showInfo(`Memory file: ${targetPath}`);
|
|
1502
|
-
display.showInfo('Create or edit this file to add persistent context for the AI.');
|
|
1503
|
-
display.showInfo('');
|
|
1504
|
-
display.showInfo('Example EROSOLAR.md content:');
|
|
1505
|
-
display.showInfo('');
|
|
1506
|
-
display.showInfo(theme.dim(`# Project Guidelines
|
|
1507
|
-
|
|
1508
|
-
When working in this codebase:
|
|
1509
|
-
- Follow TypeScript strict mode conventions
|
|
1510
|
-
- Use functional patterns where appropriate
|
|
1511
|
-
- Run tests before committing
|
|
1512
|
-
|
|
1513
|
-
@./docs/coding-standards.md
|
|
1514
|
-
`));
|
|
1515
|
-
}
|
|
1516
1535
|
showFileChangeSummary() {
|
|
1517
1536
|
const summary = this._fileChangeTracker.getSummary();
|
|
1518
1537
|
const changes = this._fileChangeTracker.getAllChanges();
|
|
@@ -1555,11 +1574,11 @@ When working in this codebase:
|
|
|
1555
1574
|
display.showSystemMessage(lines.join('\n'));
|
|
1556
1575
|
}
|
|
1557
1576
|
showAlphaZeroMetrics() {
|
|
1558
|
-
const summary = this.
|
|
1577
|
+
const summary = this.alphaZeroMetrics.getPerformanceSummary();
|
|
1559
1578
|
display.showSystemMessage(summary);
|
|
1560
1579
|
}
|
|
1561
1580
|
showImprovementSuggestions() {
|
|
1562
|
-
const suggestions = this.
|
|
1581
|
+
const suggestions = this.alphaZeroMetrics.getImprovementSuggestions();
|
|
1563
1582
|
if (suggestions.length === 0) {
|
|
1564
1583
|
display.showInfo('No improvement suggestions at this time. Keep using the shell to generate metrics!');
|
|
1565
1584
|
return;
|
|
@@ -1605,7 +1624,9 @@ When working in this codebase:
|
|
|
1605
1624
|
}
|
|
1606
1625
|
}
|
|
1607
1626
|
lines.push(theme.secondary('CLI Flags:'));
|
|
1627
|
+
lines.push(' --alpha-zero Enable Alpha Zero 2 RL framework');
|
|
1608
1628
|
lines.push(' --coding Enable enhanced coding tools');
|
|
1629
|
+
lines.push(' --security Enable security research tools');
|
|
1609
1630
|
lines.push(' --all-plugins Enable all optional plugins');
|
|
1610
1631
|
display.showSystemMessage(lines.join('\n'));
|
|
1611
1632
|
}
|
|
@@ -1654,6 +1675,7 @@ When working in this codebase:
|
|
|
1654
1675
|
model: this.sessionState.model,
|
|
1655
1676
|
workspaceRoot: this.workingDir,
|
|
1656
1677
|
messages: history,
|
|
1678
|
+
scrollbackBuffer: this.terminalInput.getScrollbackBuffer(),
|
|
1657
1679
|
});
|
|
1658
1680
|
this.cachedHistory = history;
|
|
1659
1681
|
this.updateActiveSession(summary, true);
|
|
@@ -1832,6 +1854,7 @@ When working in this codebase:
|
|
|
1832
1854
|
workspaceRoot: this.workingDir,
|
|
1833
1855
|
title: this.activeSessionTitle,
|
|
1834
1856
|
messages: this.cachedHistory,
|
|
1857
|
+
scrollbackBuffer: this.terminalInput.getScrollbackBuffer(),
|
|
1835
1858
|
});
|
|
1836
1859
|
}
|
|
1837
1860
|
describeWorkspaceOptions() {
|
|
@@ -1849,6 +1872,75 @@ When working in this codebase:
|
|
|
1849
1872
|
}
|
|
1850
1873
|
return `${warning.label}: ${warning.reason}.`;
|
|
1851
1874
|
}
|
|
1875
|
+
buildLaunchCommandPalette() {
|
|
1876
|
+
const entries = [];
|
|
1877
|
+
const secretsSummary = this.summarizeSecretsForPalette();
|
|
1878
|
+
const toolSummary = this.getToolSelectionSummary();
|
|
1879
|
+
const autosaveLabel = this.autosaveEnabled ? 'on' : 'off';
|
|
1880
|
+
for (const command of this.slashCommands) {
|
|
1881
|
+
const entry = {
|
|
1882
|
+
command: command.command,
|
|
1883
|
+
description: command.description,
|
|
1884
|
+
category: command.category ?? 'other',
|
|
1885
|
+
};
|
|
1886
|
+
switch (command.command) {
|
|
1887
|
+
case '/secrets':
|
|
1888
|
+
if (secretsSummary.text) {
|
|
1889
|
+
entry.description = `${command.description} (${secretsSummary.text})`;
|
|
1890
|
+
entry.tone = secretsSummary.tone;
|
|
1891
|
+
}
|
|
1892
|
+
break;
|
|
1893
|
+
case '/tools':
|
|
1894
|
+
if (toolSummary) {
|
|
1895
|
+
entry.description = `${command.description} (${toolSummary})`;
|
|
1896
|
+
}
|
|
1897
|
+
break;
|
|
1898
|
+
case '/sessions':
|
|
1899
|
+
entry.description = `${command.description} (autosave ${autosaveLabel})`;
|
|
1900
|
+
break;
|
|
1901
|
+
case '/model':
|
|
1902
|
+
entry.description = `${command.description} (current: ${this.sessionState.model})`;
|
|
1903
|
+
break;
|
|
1904
|
+
case '/provider':
|
|
1905
|
+
entry.description = `${command.description} (current: ${this.providerLabel(this.sessionState.provider)})`;
|
|
1906
|
+
break;
|
|
1907
|
+
default:
|
|
1908
|
+
break;
|
|
1909
|
+
}
|
|
1910
|
+
entries.push(entry);
|
|
1911
|
+
}
|
|
1912
|
+
return entries;
|
|
1913
|
+
}
|
|
1914
|
+
summarizeSecretsForPalette() {
|
|
1915
|
+
const definitions = listSecretDefinitions();
|
|
1916
|
+
if (!definitions.length) {
|
|
1917
|
+
return { text: null };
|
|
1918
|
+
}
|
|
1919
|
+
const missing = definitions.filter((definition) => !getSecretValue(definition.id));
|
|
1920
|
+
if (missing.length === 0) {
|
|
1921
|
+
return { text: 'all configured', tone: 'success' };
|
|
1922
|
+
}
|
|
1923
|
+
const labels = missing.map((definition) => definition.label ?? definition.id);
|
|
1924
|
+
return { text: `missing ${this.formatList(labels)}`, tone: 'warn' };
|
|
1925
|
+
}
|
|
1926
|
+
getToolSelectionSummary() {
|
|
1927
|
+
const toolSettings = loadToolSettings();
|
|
1928
|
+
const selection = buildEnabledToolSet(toolSettings);
|
|
1929
|
+
const options = getToolToggleOptions();
|
|
1930
|
+
if (!options.length) {
|
|
1931
|
+
return null;
|
|
1932
|
+
}
|
|
1933
|
+
const enabledCount = options.filter((option) => selection.has(option.id)).length;
|
|
1934
|
+
return `${enabledCount}/${options.length} enabled`;
|
|
1935
|
+
}
|
|
1936
|
+
formatList(values, maxItems = 3) {
|
|
1937
|
+
if (!values.length) {
|
|
1938
|
+
return '';
|
|
1939
|
+
}
|
|
1940
|
+
const shown = values.slice(0, maxItems);
|
|
1941
|
+
const suffix = values.length > maxItems ? ', …' : '';
|
|
1942
|
+
return `${shown.join(', ')}${suffix}`;
|
|
1943
|
+
}
|
|
1852
1944
|
buildSlashCommandList(header) {
|
|
1853
1945
|
const lines = [theme.gradient.primary(header), ''];
|
|
1854
1946
|
for (const command of this.slashCommands) {
|
|
@@ -2317,7 +2409,7 @@ When working in this codebase:
|
|
|
2317
2409
|
this.autosaveIfEnabled();
|
|
2318
2410
|
// Track metrics with Alpha Zero 2
|
|
2319
2411
|
const elapsedMs = Date.now() - requestStartTime;
|
|
2320
|
-
this.
|
|
2412
|
+
this.alphaZeroMetrics.recordMessage(elapsedMs);
|
|
2321
2413
|
if (!responseText?.trim()) {
|
|
2322
2414
|
display.showWarning('The provider returned an empty response. Check your API key/provider selection or retry the prompt.');
|
|
2323
2415
|
}
|
|
@@ -2335,14 +2427,10 @@ When working in this codebase:
|
|
|
2335
2427
|
this.stopStreamingHeartbeat();
|
|
2336
2428
|
this.isProcessing = false;
|
|
2337
2429
|
this.terminalInput.setStreaming(false);
|
|
2338
|
-
this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
|
|
2339
2430
|
this.uiAdapter.endProcessing('Ready for prompts');
|
|
2340
2431
|
this.setIdleStatus();
|
|
2341
2432
|
display.newLine();
|
|
2342
2433
|
this.updateStatusMessage(null);
|
|
2343
|
-
// Claude Code style: Show unified status bar before prompt
|
|
2344
|
-
// This creates consistent UI between startup and post-streaming
|
|
2345
|
-
this.showUnifiedStatusBar();
|
|
2346
2434
|
queueMicrotask(() => this.uiUpdates.setMode('idle'));
|
|
2347
2435
|
// CRITICAL: Ensure readline prompt is active for user input
|
|
2348
2436
|
// Claude Code style: New prompt naturally appears at bottom
|
|
@@ -2419,13 +2507,14 @@ When truly finished with ALL tasks, explicitly state "TASK_FULLY_COMPLETE".`;
|
|
|
2419
2507
|
try {
|
|
2420
2508
|
// Send the request and capture the response (streaming disabled)
|
|
2421
2509
|
display.showThinking('Responding...');
|
|
2510
|
+
this.refreshStatusLine(true);
|
|
2422
2511
|
const response = await agent.send(currentPrompt, true);
|
|
2423
2512
|
await this.awaitPendingCleanup();
|
|
2424
2513
|
this.captureHistorySnapshot();
|
|
2425
2514
|
this.autosaveIfEnabled();
|
|
2426
2515
|
// Track metrics
|
|
2427
2516
|
const elapsedMs = Date.now() - overallStartTime;
|
|
2428
|
-
this.
|
|
2517
|
+
this.alphaZeroMetrics.recordMessage(elapsedMs);
|
|
2429
2518
|
if (!response?.trim()) {
|
|
2430
2519
|
display.showWarning('Model returned an empty response. Retrying this iteration...');
|
|
2431
2520
|
consecutiveNoProgress++;
|
|
@@ -2562,7 +2651,6 @@ What's the next action?`;
|
|
|
2562
2651
|
this.stopStreamingHeartbeat();
|
|
2563
2652
|
this.isProcessing = false;
|
|
2564
2653
|
this.terminalInput.setStreaming(false);
|
|
2565
|
-
this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
|
|
2566
2654
|
this.uiAdapter.endProcessing('Ready for prompts');
|
|
2567
2655
|
this.setIdleStatus();
|
|
2568
2656
|
this.updateStatusMessage(null);
|
|
@@ -2919,8 +3007,10 @@ What's the next action?`;
|
|
|
2919
3007
|
try {
|
|
2920
3008
|
// Send the error to the agent for fixing
|
|
2921
3009
|
display.showThinking('Analyzing build errors');
|
|
3010
|
+
this.refreshStatusLine(true);
|
|
2922
3011
|
const response = await this.agent.send(prompt, true);
|
|
2923
3012
|
display.stopThinking();
|
|
3013
|
+
this.refreshStatusLine(true);
|
|
2924
3014
|
if (response) {
|
|
2925
3015
|
display.showAssistantMessage(response, { isFinal: true });
|
|
2926
3016
|
}
|
|
@@ -2947,8 +3037,8 @@ What's the next action?`;
|
|
|
2947
3037
|
};
|
|
2948
3038
|
this.agent = this.runtimeSession.createAgent(selection, {
|
|
2949
3039
|
onStreamChunk: (chunk) => {
|
|
2950
|
-
// Stream output
|
|
2951
|
-
|
|
3040
|
+
// Stream output using clean streamContent() - chat box floats below
|
|
3041
|
+
this.terminalInput.streamContent(chunk);
|
|
2952
3042
|
},
|
|
2953
3043
|
onStreamFallback: (info) => this.handleStreamingFallback(info),
|
|
2954
3044
|
onAssistantMessage: (content, metadata) => {
|
|
@@ -2970,18 +3060,16 @@ What's the next action?`;
|
|
|
2970
3060
|
display.showAssistantMessage(finalContent, enriched);
|
|
2971
3061
|
}
|
|
2972
3062
|
}
|
|
2973
|
-
//
|
|
3063
|
+
// Status shown in mode controls bar - no separate status line needed
|
|
2974
3064
|
display.stopThinking();
|
|
2975
|
-
//
|
|
2976
|
-
let contextInfo;
|
|
3065
|
+
// Update context usage for mode controls display
|
|
2977
3066
|
if (enriched.contextWindowTokens && metadata.usage) {
|
|
2978
3067
|
const total = this.totalTokens(metadata.usage);
|
|
2979
3068
|
if (total && total > 0) {
|
|
2980
3069
|
const percentage = Math.round((total / enriched.contextWindowTokens) * 100);
|
|
2981
|
-
|
|
3070
|
+
this.updateContextUsage(percentage);
|
|
2982
3071
|
}
|
|
2983
3072
|
}
|
|
2984
|
-
display.showStatusLine('Ready for prompts', enriched.elapsedMs, contextInfo);
|
|
2985
3073
|
// Auto-verify changes: build first (catches type errors), then tests
|
|
2986
3074
|
void this.enforceAutoBuild('final-response');
|
|
2987
3075
|
void this.enforceAutoTests('final-response');
|
|
@@ -3051,7 +3139,6 @@ What's the next action?`;
|
|
|
3051
3139
|
this.stopStreamingHeartbeat();
|
|
3052
3140
|
this.updateStatusMessage(null);
|
|
3053
3141
|
this.terminalInput.setStreaming(false);
|
|
3054
|
-
this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
|
|
3055
3142
|
this.terminalInput.render();
|
|
3056
3143
|
},
|
|
3057
3144
|
onVerificationNeeded: () => {
|
|
@@ -3088,7 +3175,6 @@ What's the next action?`;
|
|
|
3088
3175
|
resetChatBoxAfterModelSwap() {
|
|
3089
3176
|
this.updateStatusMessage(null);
|
|
3090
3177
|
this.terminalInput.setStreaming(false);
|
|
3091
|
-
this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
|
|
3092
3178
|
this.terminalInput.render();
|
|
3093
3179
|
this.ensureReadlineReady();
|
|
3094
3180
|
}
|
|
@@ -3153,9 +3239,14 @@ What's the next action?`;
|
|
|
3153
3239
|
return null;
|
|
3154
3240
|
}
|
|
3155
3241
|
const usageRatio = total / windowTokens;
|
|
3242
|
+
this.latestTokenUsage = {
|
|
3243
|
+
used: total,
|
|
3244
|
+
limit: windowTokens,
|
|
3245
|
+
};
|
|
3156
3246
|
// Always update context usage in the UI
|
|
3157
3247
|
const percentUsed = Math.round(usageRatio * 100);
|
|
3158
3248
|
this.updateContextUsage(percentUsed);
|
|
3249
|
+
this.refreshStatusLine(true);
|
|
3159
3250
|
if (usageRatio < CONTEXT_USAGE_THRESHOLD) {
|
|
3160
3251
|
return null;
|
|
3161
3252
|
}
|
|
@@ -3422,6 +3513,22 @@ What's the next action?`;
|
|
|
3422
3513
|
this.sessionState.reasoningEffort = preset.reasoningEffort;
|
|
3423
3514
|
}
|
|
3424
3515
|
}
|
|
3516
|
+
/**
|
|
3517
|
+
* Build the session banner.
|
|
3518
|
+
*/
|
|
3519
|
+
buildBanner() {
|
|
3520
|
+
const terminalWidth = output.columns ?? 100;
|
|
3521
|
+
const width = Math.min(terminalWidth - 4, 110);
|
|
3522
|
+
return renderSessionFrame({
|
|
3523
|
+
profileLabel: this.profileLabel,
|
|
3524
|
+
profileName: this.profile,
|
|
3525
|
+
model: this.sessionState.model,
|
|
3526
|
+
provider: this.sessionState.provider,
|
|
3527
|
+
workspace: this.workingDir,
|
|
3528
|
+
version: this.version,
|
|
3529
|
+
width,
|
|
3530
|
+
});
|
|
3531
|
+
}
|
|
3425
3532
|
refreshBannerSessionInfo() {
|
|
3426
3533
|
const nextState = {
|
|
3427
3534
|
model: this.sessionState.model,
|
|
@@ -3432,13 +3539,11 @@ What's the next action?`;
|
|
|
3432
3539
|
return;
|
|
3433
3540
|
}
|
|
3434
3541
|
this.refreshContextGauge();
|
|
3435
|
-
display
|
|
3436
|
-
//
|
|
3437
|
-
this.terminalInput.setModelInfo(this.describeModelDetail());
|
|
3542
|
+
// Banner is no longer stored in display - it was streamed as content
|
|
3543
|
+
// Model/provider changes are visible in the control bar
|
|
3438
3544
|
if (!this.isProcessing) {
|
|
3439
3545
|
this.setIdleStatus();
|
|
3440
3546
|
}
|
|
3441
|
-
// Pinned header rows are disabled; scroll region handles all output.
|
|
3442
3547
|
this.bannerSessionState = nextState;
|
|
3443
3548
|
}
|
|
3444
3549
|
providerLabel(id) {
|