erosolar-cli 1.7.345 → 1.7.346
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 -24
- package/dist/alpha-zero/agentWrapper.d.ts +84 -0
- package/dist/alpha-zero/agentWrapper.d.ts.map +1 -0
- package/dist/alpha-zero/agentWrapper.js +171 -0
- package/dist/alpha-zero/agentWrapper.js.map +1 -0
- package/dist/alpha-zero/codeEvaluator.d.ts +25 -0
- package/dist/alpha-zero/codeEvaluator.d.ts.map +1 -0
- package/dist/alpha-zero/codeEvaluator.js +273 -0
- package/dist/alpha-zero/codeEvaluator.js.map +1 -0
- package/dist/alpha-zero/competitiveRunner.d.ts +66 -0
- package/dist/alpha-zero/competitiveRunner.d.ts.map +1 -0
- package/dist/alpha-zero/competitiveRunner.js +224 -0
- package/dist/alpha-zero/competitiveRunner.js.map +1 -0
- package/dist/alpha-zero/index.d.ts +67 -0
- package/dist/alpha-zero/index.d.ts.map +1 -0
- package/dist/alpha-zero/index.js +99 -0
- package/dist/alpha-zero/index.js.map +1 -0
- package/dist/alpha-zero/introspection.d.ts +128 -0
- package/dist/alpha-zero/introspection.d.ts.map +1 -0
- package/dist/alpha-zero/introspection.js +300 -0
- package/dist/alpha-zero/introspection.js.map +1 -0
- package/dist/alpha-zero/metricsTracker.d.ts +71 -0
- package/dist/alpha-zero/metricsTracker.d.ts.map +1 -0
- package/dist/{core → alpha-zero}/metricsTracker.js +5 -2
- package/dist/alpha-zero/metricsTracker.js.map +1 -0
- package/dist/alpha-zero/security/core.d.ts +125 -0
- package/dist/alpha-zero/security/core.d.ts.map +1 -0
- package/dist/alpha-zero/security/core.js +271 -0
- package/dist/alpha-zero/security/core.js.map +1 -0
- package/dist/alpha-zero/security/google.d.ts +125 -0
- package/dist/alpha-zero/security/google.d.ts.map +1 -0
- package/dist/alpha-zero/security/google.js +311 -0
- package/dist/alpha-zero/security/google.js.map +1 -0
- package/dist/alpha-zero/security/googleLoader.d.ts +17 -0
- package/dist/alpha-zero/security/googleLoader.d.ts.map +1 -0
- package/dist/alpha-zero/security/googleLoader.js +41 -0
- package/dist/alpha-zero/security/googleLoader.js.map +1 -0
- package/dist/alpha-zero/security/index.d.ts +29 -0
- package/dist/alpha-zero/security/index.d.ts.map +1 -0
- package/dist/alpha-zero/security/index.js +32 -0
- package/dist/alpha-zero/security/index.js.map +1 -0
- package/dist/alpha-zero/security/simulation.d.ts +124 -0
- package/dist/alpha-zero/security/simulation.d.ts.map +1 -0
- package/dist/alpha-zero/security/simulation.js +277 -0
- package/dist/alpha-zero/security/simulation.js.map +1 -0
- package/dist/alpha-zero/selfModification.d.ts +109 -0
- package/dist/alpha-zero/selfModification.d.ts.map +1 -0
- package/dist/alpha-zero/selfModification.js +233 -0
- package/dist/alpha-zero/selfModification.js.map +1 -0
- package/dist/alpha-zero/types.d.ts +170 -0
- package/dist/alpha-zero/types.d.ts.map +1 -0
- package/dist/alpha-zero/types.js +31 -0
- package/dist/alpha-zero/types.js.map +1 -0
- package/dist/bin/erosolar.js +21 -5
- package/dist/bin/erosolar.js.map +1 -1
- package/dist/capabilities/agentSpawningCapability.d.ts.map +1 -1
- package/dist/capabilities/agentSpawningCapability.js +31 -56
- package/dist/capabilities/agentSpawningCapability.js.map +1 -1
- package/dist/capabilities/securityTestingCapability.d.ts +13 -0
- package/dist/capabilities/securityTestingCapability.d.ts.map +1 -0
- package/dist/capabilities/securityTestingCapability.js +25 -0
- package/dist/capabilities/securityTestingCapability.js.map +1 -0
- package/dist/contracts/agent-schemas.json +15 -0
- package/dist/contracts/tools.schema.json +9 -0
- 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/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/hooksSystem.d.ts +65 -0
- package/dist/core/hooksSystem.d.ts.map +1 -0
- package/dist/core/hooksSystem.js +273 -0
- package/dist/core/hooksSystem.js.map +1 -0
- package/dist/core/memorySystem.d.ts +48 -0
- package/dist/core/memorySystem.d.ts.map +1 -0
- package/dist/core/memorySystem.js +271 -0
- package/dist/core/memorySystem.js.map +1 -0
- package/dist/core/sessionStore.d.ts +0 -2
- package/dist/core/sessionStore.d.ts.map +1 -1
- package/dist/core/sessionStore.js +0 -1
- package/dist/core/sessionStore.js.map +1 -1
- 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 +1 -22
- 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/core/unified/errors.d.ts +189 -0
- package/dist/core/unified/errors.d.ts.map +1 -0
- package/dist/core/unified/errors.js +497 -0
- package/dist/core/unified/errors.js.map +1 -0
- package/dist/core/unified/index.d.ts +19 -0
- package/dist/core/unified/index.d.ts.map +1 -0
- package/dist/core/unified/index.js +68 -0
- package/dist/core/unified/index.js.map +1 -0
- package/dist/core/unified/schema.d.ts +101 -0
- package/dist/core/unified/schema.d.ts.map +1 -0
- package/dist/core/unified/schema.js +350 -0
- package/dist/core/unified/schema.js.map +1 -0
- package/dist/core/unified/toolRuntime.d.ts +179 -0
- package/dist/core/unified/toolRuntime.d.ts.map +1 -0
- package/dist/core/unified/toolRuntime.js +517 -0
- package/dist/core/unified/toolRuntime.js.map +1 -0
- package/dist/core/unified/tools.d.ts +127 -0
- package/dist/core/unified/tools.d.ts.map +1 -0
- package/dist/core/unified/tools.js +1333 -0
- package/dist/core/unified/tools.js.map +1 -0
- package/dist/core/unified/types.d.ts +352 -0
- package/dist/core/unified/types.d.ts.map +1 -0
- package/dist/core/unified/types.js +12 -0
- package/dist/core/unified/types.js.map +1 -0
- package/dist/core/unified/version.d.ts +209 -0
- package/dist/core/unified/version.d.ts.map +1 -0
- package/dist/core/unified/version.js +454 -0
- package/dist/core/unified/version.js.map +1 -0
- package/dist/core/validationRunner.d.ts +3 -1
- package/dist/core/validationRunner.d.ts.map +1 -1
- package/dist/core/validationRunner.js.map +1 -1
- package/dist/headless/headlessApp.d.ts.map +1 -1
- package/dist/headless/headlessApp.js +0 -21
- package/dist/headless/headlessApp.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/plugins/tools/nodeDefaults.d.ts.map +1 -1
- package/dist/plugins/tools/nodeDefaults.js +2 -0
- package/dist/plugins/tools/nodeDefaults.js.map +1 -1
- package/dist/plugins/tools/security/securityPlugin.d.ts +3 -0
- package/dist/plugins/tools/security/securityPlugin.d.ts.map +1 -0
- package/dist/plugins/tools/security/securityPlugin.js +12 -0
- package/dist/plugins/tools/security/securityPlugin.js.map +1 -0
- 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/security/active-stack-security.d.ts +112 -0
- package/dist/security/active-stack-security.d.ts.map +1 -0
- package/dist/security/active-stack-security.js +296 -0
- package/dist/security/active-stack-security.js.map +1 -0
- package/dist/security/advanced-persistence-research.d.ts +92 -0
- package/dist/security/advanced-persistence-research.d.ts.map +1 -0
- package/dist/security/advanced-persistence-research.js +195 -0
- package/dist/security/advanced-persistence-research.js.map +1 -0
- package/dist/security/advanced-targeting.d.ts +119 -0
- package/dist/security/advanced-targeting.d.ts.map +1 -0
- package/dist/security/advanced-targeting.js +233 -0
- package/dist/security/advanced-targeting.js.map +1 -0
- package/dist/security/assessment/vulnerabilityAssessment.d.ts +104 -0
- package/dist/security/assessment/vulnerabilityAssessment.d.ts.map +1 -0
- package/dist/security/assessment/vulnerabilityAssessment.js +315 -0
- package/dist/security/assessment/vulnerabilityAssessment.js.map +1 -0
- package/dist/security/authorization/securityAuthorization.d.ts +88 -0
- package/dist/security/authorization/securityAuthorization.d.ts.map +1 -0
- package/dist/security/authorization/securityAuthorization.js +172 -0
- package/dist/security/authorization/securityAuthorization.js.map +1 -0
- package/dist/security/comprehensive-targeting.d.ts +85 -0
- package/dist/security/comprehensive-targeting.d.ts.map +1 -0
- package/dist/security/comprehensive-targeting.js +438 -0
- package/dist/security/comprehensive-targeting.js.map +1 -0
- package/dist/security/global-security-integration.d.ts +91 -0
- package/dist/security/global-security-integration.d.ts.map +1 -0
- package/dist/security/global-security-integration.js +218 -0
- package/dist/security/global-security-integration.js.map +1 -0
- package/dist/security/index.d.ts +38 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +47 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/persistence-analyzer.d.ts +56 -0
- package/dist/security/persistence-analyzer.d.ts.map +1 -0
- package/dist/security/persistence-analyzer.js +187 -0
- package/dist/security/persistence-analyzer.js.map +1 -0
- package/dist/security/persistence-cli.d.ts +36 -0
- package/dist/security/persistence-cli.d.ts.map +1 -0
- package/dist/security/persistence-cli.js +160 -0
- package/dist/security/persistence-cli.js.map +1 -0
- package/dist/security/persistence-research.d.ts +92 -0
- package/dist/security/persistence-research.d.ts.map +1 -0
- package/dist/security/persistence-research.js +364 -0
- package/dist/security/persistence-research.js.map +1 -0
- package/dist/security/research/persistenceResearch.d.ts +97 -0
- package/dist/security/research/persistenceResearch.d.ts.map +1 -0
- package/dist/security/research/persistenceResearch.js +282 -0
- package/dist/security/research/persistenceResearch.js.map +1 -0
- package/dist/security/security-integration.d.ts +74 -0
- package/dist/security/security-integration.d.ts.map +1 -0
- package/dist/security/security-integration.js +137 -0
- package/dist/security/security-integration.js.map +1 -0
- package/dist/security/security-testing-framework.d.ts +112 -0
- package/dist/security/security-testing-framework.d.ts.map +1 -0
- package/dist/security/security-testing-framework.js +364 -0
- package/dist/security/security-testing-framework.js.map +1 -0
- package/dist/security/simulation/attackSimulation.d.ts +93 -0
- package/dist/security/simulation/attackSimulation.d.ts.map +1 -0
- package/dist/security/simulation/attackSimulation.js +341 -0
- package/dist/security/simulation/attackSimulation.js.map +1 -0
- package/dist/security/strategic-operations.d.ts +100 -0
- package/dist/security/strategic-operations.d.ts.map +1 -0
- package/dist/security/strategic-operations.js +276 -0
- package/dist/security/strategic-operations.js.map +1 -0
- package/dist/security/tool-security-wrapper.d.ts +58 -0
- package/dist/security/tool-security-wrapper.d.ts.map +1 -0
- package/dist/security/tool-security-wrapper.js +156 -0
- package/dist/security/tool-security-wrapper.js.map +1 -0
- 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 +7 -31
- package/dist/shell/interactiveShell.d.ts.map +1 -1
- package/dist/shell/interactiveShell.js +166 -362
- package/dist/shell/interactiveShell.js.map +1 -1
- package/dist/shell/metricsTracker.d.ts +60 -0
- package/dist/shell/metricsTracker.d.ts.map +1 -0
- package/dist/shell/metricsTracker.js +119 -0
- package/dist/shell/metricsTracker.js.map +1 -0
- package/dist/shell/shellApp.d.ts +0 -2
- package/dist/shell/shellApp.d.ts.map +1 -1
- package/dist/shell/shellApp.js +9 -82
- package/dist/shell/shellApp.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/systemPrompt.d.ts.map +1 -1
- package/dist/shell/systemPrompt.js +4 -1
- package/dist/shell/systemPrompt.js.map +1 -1
- package/dist/shell/terminalInput.d.ts +120 -236
- package/dist/shell/terminalInput.d.ts.map +1 -1
- package/dist/shell/terminalInput.js +539 -1044
- package/dist/shell/terminalInput.js.map +1 -1
- package/dist/shell/terminalInputAdapter.d.ts +21 -99
- package/dist/shell/terminalInputAdapter.d.ts.map +1 -1
- package/dist/shell/terminalInputAdapter.js +30 -135
- package/dist/shell/terminalInputAdapter.js.map +1 -1
- package/dist/subagents/taskRunner.d.ts +1 -7
- package/dist/subagents/taskRunner.d.ts.map +1 -1
- package/dist/subagents/taskRunner.js +47 -180
- package/dist/subagents/taskRunner.js.map +1 -1
- package/dist/tools/securityTools.d.ts +22 -0
- package/dist/tools/securityTools.d.ts.map +1 -0
- package/dist/tools/securityTools.js +448 -0
- package/dist/tools/securityTools.js.map +1 -0
- package/dist/ui/ShellUIAdapter.d.ts +1 -7
- package/dist/ui/ShellUIAdapter.d.ts.map +1 -1
- package/dist/ui/ShellUIAdapter.js +18 -42
- package/dist/ui/ShellUIAdapter.js.map +1 -1
- package/dist/ui/display.d.ts +45 -24
- package/dist/ui/display.d.ts.map +1 -1
- package/dist/ui/display.js +259 -140
- 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/toolDisplay.d.ts +158 -0
- package/dist/ui/toolDisplay.d.ts.map +1 -1
- package/dist/ui/toolDisplay.js +348 -0
- package/dist/ui/toolDisplay.js.map +1 -1
- package/dist/ui/unified/layout.d.ts +0 -20
- package/dist/ui/unified/layout.d.ts.map +1 -1
- package/dist/ui/unified/layout.js +216 -105
- package/dist/ui/unified/layout.js.map +1 -1
- package/package.json +4 -4
- package/scripts/deploy-security-capabilities.js +178 -0
- package/dist/core/hooks.d.ts +0 -113
- package/dist/core/hooks.d.ts.map +0 -1
- package/dist/core/hooks.js +0 -267
- package/dist/core/hooks.js.map +0 -1
- package/dist/core/metricsTracker.d.ts +0 -122
- package/dist/core/metricsTracker.d.ts.map +0 -1
- package/dist/core/metricsTracker.js.map +0 -1
- package/dist/core/securityAssessment.d.ts +0 -91
- package/dist/core/securityAssessment.d.ts.map +0 -1
- package/dist/core/securityAssessment.js +0 -580
- package/dist/core/securityAssessment.js.map +0 -1
- package/dist/core/verification.d.ts +0 -137
- package/dist/core/verification.d.ts.map +0 -1
- package/dist/core/verification.js +0 -323
- package/dist/core/verification.js.map +0 -1
- package/dist/subagents/agentConfig.d.ts +0 -27
- package/dist/subagents/agentConfig.d.ts.map +0 -1
- package/dist/subagents/agentConfig.js +0 -89
- package/dist/subagents/agentConfig.js.map +0 -1
- package/dist/subagents/agentRegistry.d.ts +0 -33
- package/dist/subagents/agentRegistry.d.ts.map +0 -1
- package/dist/subagents/agentRegistry.js +0 -162
- package/dist/subagents/agentRegistry.js.map +0 -1
- package/dist/utils/frontmatter.d.ts +0 -10
- package/dist/utils/frontmatter.d.ts.map +0 -1
- package/dist/utils/frontmatter.js +0 -78
- package/dist/utils/frontmatter.js.map +0 -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';
|
|
@@ -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 './metricsTracker.js';
|
|
23
23
|
import { listAvailablePlugins } from '../plugins/index.js';
|
|
24
|
+
import { loadMemory, listMemoryPaths, getDefaultProjectMemoryPath, getUserMemoryEditPath, } from '../core/memorySystem.js';
|
|
24
25
|
import { TerminalInputAdapter } from './terminalInputAdapter.js';
|
|
25
|
-
import {
|
|
26
|
-
import { isUpdateInProgress, maybeOfferCliUpdate } from './updateManager.js';
|
|
26
|
+
import { isUpdateInProgress } 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,7 +35,6 @@ const DROPDOWN_COLORS = [
|
|
|
35
35
|
theme.success,
|
|
36
36
|
theme.warning,
|
|
37
37
|
];
|
|
38
|
-
const STREAMING_SPINNER_FRAMES = ['◐', '◓', '◑', '◒'];
|
|
39
38
|
// Load MODEL_PRESETS from centralized schema
|
|
40
39
|
const MODEL_PRESETS = getModels().map((model) => ({
|
|
41
40
|
id: model.id,
|
|
@@ -50,13 +49,11 @@ const MODEL_PRESETS = getModels().map((model) => ({
|
|
|
50
49
|
const BASE_SLASH_COMMANDS = getSlashCommands().map((cmd) => ({
|
|
51
50
|
command: cmd.command,
|
|
52
51
|
description: cmd.description,
|
|
53
|
-
category: cmd.category,
|
|
54
52
|
}));
|
|
55
53
|
// Load PROVIDER_LABELS from centralized schema
|
|
56
54
|
const PROVIDER_LABELS = Object.fromEntries(getProviders().map((provider) => [provider.id, provider.label]));
|
|
57
55
|
// Allow enough time for paste detection to kick in before flushing buffered lines
|
|
58
56
|
const CONTEXT_USAGE_THRESHOLD = 0.9;
|
|
59
|
-
const CONTEXT_AUTOCOMPACT_PERCENT = Math.round(CONTEXT_USAGE_THRESHOLD * 100);
|
|
60
57
|
const CONTEXT_RECENT_MESSAGE_COUNT = 12;
|
|
61
58
|
const CONTEXT_CLEANUP_CHARS_PER_CHUNK = 6000;
|
|
62
59
|
const CONTEXT_CLEANUP_MAX_OUTPUT_TOKENS = 800;
|
|
@@ -97,12 +94,11 @@ export class InteractiveShell {
|
|
|
97
94
|
uiAdapter;
|
|
98
95
|
uiUpdates;
|
|
99
96
|
_fileChangeTracker = new FileChangeTracker(); // Reserved for future file tracking features
|
|
100
|
-
|
|
97
|
+
sessionMetrics; // Session performance tracking
|
|
101
98
|
statusSubscription = null;
|
|
102
99
|
followUpQueue = [];
|
|
103
100
|
isDrainingQueue = false;
|
|
104
101
|
activeContextWindowTokens = null;
|
|
105
|
-
latestTokenUsage = { used: null, limit: null };
|
|
106
102
|
sessionPreferences;
|
|
107
103
|
autosaveEnabled;
|
|
108
104
|
autoContinueEnabled;
|
|
@@ -133,9 +129,6 @@ export class InteractiveShell {
|
|
|
133
129
|
statusLineState = null;
|
|
134
130
|
statusMessageOverride = null;
|
|
135
131
|
promptRefreshTimer = null;
|
|
136
|
-
launchPaletteShown = false;
|
|
137
|
-
version;
|
|
138
|
-
alternateScreenEnabled;
|
|
139
132
|
constructor(config) {
|
|
140
133
|
this.profile = config.profile;
|
|
141
134
|
this.profileLabel = config.profileLabel;
|
|
@@ -149,8 +142,6 @@ export class InteractiveShell {
|
|
|
149
142
|
this.autoContinueEnabled = this.sessionPreferences.autoContinue;
|
|
150
143
|
this.sessionRestoreConfig = config.sessionRestore ?? { mode: 'none' };
|
|
151
144
|
this._enabledPlugins = config.enabledPlugins ?? [];
|
|
152
|
-
this.version = config.version ?? '0.0.0';
|
|
153
|
-
this.alternateScreenEnabled = config.alternateScreen ?? true;
|
|
154
145
|
this.initializeSessionHistory();
|
|
155
146
|
this.sessionState = {
|
|
156
147
|
provider: config.initialModel.provider,
|
|
@@ -171,7 +162,6 @@ export class InteractiveShell {
|
|
|
171
162
|
this.slashCommands.push({
|
|
172
163
|
command: '/agents',
|
|
173
164
|
description: 'Select the default agent profile (applies on next launch)',
|
|
174
|
-
category: 'configuration',
|
|
175
165
|
});
|
|
176
166
|
}
|
|
177
167
|
this.customCommands = loadCustomSlashCommands();
|
|
@@ -180,21 +170,18 @@ export class InteractiveShell {
|
|
|
180
170
|
this.slashCommands.push({
|
|
181
171
|
command: custom.command,
|
|
182
172
|
description: `${custom.description} (custom)`,
|
|
183
|
-
category: custom.category ?? 'other',
|
|
184
173
|
});
|
|
185
174
|
}
|
|
186
175
|
if (!this.slashCommands.some((cmd) => cmd.command === '/exit')) {
|
|
187
176
|
this.slashCommands.push({
|
|
188
177
|
command: '/exit',
|
|
189
178
|
description: 'Quit the CLI immediately',
|
|
190
|
-
category: 'other',
|
|
191
179
|
});
|
|
192
180
|
}
|
|
193
181
|
// Add /plugins command
|
|
194
182
|
this.slashCommands.push({
|
|
195
183
|
command: '/plugins',
|
|
196
184
|
description: 'Show available and loaded plugins',
|
|
197
|
-
category: 'configuration',
|
|
198
185
|
});
|
|
199
186
|
this.statusTracker = config.statusTracker;
|
|
200
187
|
this.ui = config.ui;
|
|
@@ -227,25 +214,19 @@ export class InteractiveShell {
|
|
|
227
214
|
onToggleVerify: () => this.toggleVerificationMode(),
|
|
228
215
|
onToggleAutoContinue: () => this.toggleAutoContinueMode(),
|
|
229
216
|
});
|
|
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();
|
|
230
224
|
// Initialize Alpha Zero 2 metrics tracking
|
|
231
|
-
this.
|
|
225
|
+
this.sessionMetrics = new MetricsTracker(`${this.profile}-${Date.now()}`);
|
|
232
226
|
this.setupStatusTracking();
|
|
233
227
|
this.refreshContextGauge();
|
|
234
|
-
// Start terminal input (sets up handlers)
|
|
235
228
|
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
|
|
247
229
|
this.refreshControlBar();
|
|
248
|
-
this.terminalInput.forceRender();
|
|
249
230
|
this.rebuildAgent();
|
|
250
231
|
this.setupHandlers();
|
|
251
232
|
this.refreshBannerSessionInfo();
|
|
@@ -265,10 +246,6 @@ export class InteractiveShell {
|
|
|
265
246
|
this.activeSessionId = stored.id;
|
|
266
247
|
this.activeSessionTitle = stored.title;
|
|
267
248
|
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
|
-
}
|
|
272
249
|
return;
|
|
273
250
|
}
|
|
274
251
|
display.showWarning(`Session "${this.sessionRestoreConfig.sessionId}" not found. Starting fresh session.`);
|
|
@@ -282,10 +259,6 @@ export class InteractiveShell {
|
|
|
282
259
|
this.activeSessionId = null;
|
|
283
260
|
this.activeSessionTitle = autosave.title;
|
|
284
261
|
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
|
-
}
|
|
289
262
|
return;
|
|
290
263
|
}
|
|
291
264
|
display.showWarning('No autosaved session found. Starting fresh session.');
|
|
@@ -300,24 +273,14 @@ export class InteractiveShell {
|
|
|
300
273
|
this.sessionResumeNotice = null;
|
|
301
274
|
}
|
|
302
275
|
async start(initialPrompt) {
|
|
303
|
-
// Check for updates in background (non-blocking)
|
|
304
|
-
if (this.version) {
|
|
305
|
-
void maybeOfferCliUpdate(this.version);
|
|
306
|
-
}
|
|
307
276
|
if (initialPrompt) {
|
|
308
277
|
this.logUserPrompt(initialPrompt);
|
|
309
278
|
await this.processInputBlock(initialPrompt);
|
|
310
279
|
return;
|
|
311
280
|
}
|
|
312
|
-
this.showLaunchCommandPalette();
|
|
313
281
|
// Ensure the terminal input is visible
|
|
314
282
|
this.terminalInput.render();
|
|
315
283
|
}
|
|
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
|
-
}
|
|
321
284
|
/**
|
|
322
285
|
* TerminalInputAdapter submit handler
|
|
323
286
|
*/
|
|
@@ -331,8 +294,9 @@ export class InteractiveShell {
|
|
|
331
294
|
this.handleInputChange('');
|
|
332
295
|
return;
|
|
333
296
|
}
|
|
334
|
-
//
|
|
335
|
-
//
|
|
297
|
+
// Enter streaming mode BEFORE logging prompt - this positions cursor correctly
|
|
298
|
+
// so content appears right after the banner, not at bottom with blank space above
|
|
299
|
+
this.terminalInput.setStreaming(true);
|
|
336
300
|
this.logUserPrompt(approved);
|
|
337
301
|
void this.processInputBlock(approved).catch((err) => {
|
|
338
302
|
display.showError(err instanceof Error ? err.message : String(err), err);
|
|
@@ -521,10 +485,6 @@ export class InteractiveShell {
|
|
|
521
485
|
return;
|
|
522
486
|
}
|
|
523
487
|
this.shuttingDown = true;
|
|
524
|
-
const shouldRestoreScrollback = this.alternateScreenEnabled && this.terminalInput.isAlternateScreenActive();
|
|
525
|
-
const scrollbackSnapshot = shouldRestoreScrollback
|
|
526
|
-
? this.terminalInput.getScrollbackSnapshot()
|
|
527
|
-
: null;
|
|
528
488
|
// Stop any active spinner to prevent process hang
|
|
529
489
|
display.stopThinking(false);
|
|
530
490
|
this.stopStreamingHeartbeat();
|
|
@@ -533,34 +493,18 @@ export class InteractiveShell {
|
|
|
533
493
|
this.teardownStatusTracking();
|
|
534
494
|
// Clear any pending cleanup to prevent hanging
|
|
535
495
|
this.pendingCleanup = null;
|
|
536
|
-
// Reset terminal state before disposing adapters
|
|
537
|
-
this.terminalInput.exitStreamingScrollRegion();
|
|
538
|
-
if (this.alternateScreenEnabled) {
|
|
539
|
-
this.terminalInput.exitAlternateScreen();
|
|
540
|
-
}
|
|
541
496
|
// Dispose terminal input handler
|
|
542
497
|
this.terminalInput.dispose();
|
|
543
498
|
// Dispose unified UI adapter
|
|
544
499
|
this.uiAdapter.dispose();
|
|
545
|
-
if (scrollbackSnapshot && scrollbackSnapshot.length > 0) {
|
|
546
|
-
this.restoreScrollbackSnapshot(scrollbackSnapshot);
|
|
547
|
-
}
|
|
548
500
|
display.newLine();
|
|
549
|
-
|
|
550
|
-
console.log(theme.
|
|
551
|
-
console.log(theme.ui.muted('
|
|
501
|
+
const version = display.getVersion() || 'unknown';
|
|
502
|
+
console.log(theme.gradient.warm('━'.repeat(50)));
|
|
503
|
+
console.log(` ${theme.gradient.cool('✨ Goodbye!')} ${theme.ui.muted('·')} ${theme.info(`erosolar-cli v${version}`)}`);
|
|
504
|
+
console.log(` ${theme.ui.muted('Support:')} ${theme.info('support@ero.solar')}`);
|
|
505
|
+
console.log(theme.gradient.warm('━'.repeat(50)));
|
|
552
506
|
exit(0);
|
|
553
507
|
}
|
|
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
|
-
}
|
|
564
508
|
/**
|
|
565
509
|
* Update status bar message
|
|
566
510
|
*/
|
|
@@ -728,14 +672,13 @@ export class InteractiveShell {
|
|
|
728
672
|
});
|
|
729
673
|
}
|
|
730
674
|
setProcessingStatus(detail) {
|
|
731
|
-
this.latestTokenUsage = { used: null, limit: this.latestTokenUsage.limit };
|
|
732
675
|
this.statusTracker.setBase('Working on your request', {
|
|
733
676
|
detail: this.describeStatusDetail(detail),
|
|
734
677
|
tone: 'info',
|
|
735
678
|
});
|
|
736
679
|
}
|
|
737
680
|
describeStatusDetail(detail) {
|
|
738
|
-
const parts = detail?.trim()
|
|
681
|
+
const parts = [detail?.trim() || this.describeModelDetail()];
|
|
739
682
|
const queued = this.followUpQueue.length;
|
|
740
683
|
if (queued > 0) {
|
|
741
684
|
parts.push(`${queued} follow-up${queued === 1 ? '' : 's'} queued`);
|
|
@@ -748,18 +691,12 @@ export class InteractiveShell {
|
|
|
748
691
|
}
|
|
749
692
|
refreshContextGauge() {
|
|
750
693
|
const tokens = getContextWindowTokens(this.sessionState.model);
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
if (normalizedTokens !== null) {
|
|
754
|
-
this.latestTokenUsage = {
|
|
755
|
-
used: this.latestTokenUsage.used,
|
|
756
|
-
limit: normalizedTokens,
|
|
757
|
-
};
|
|
758
|
-
}
|
|
694
|
+
this.activeContextWindowTokens =
|
|
695
|
+
typeof tokens === 'number' && Number.isFinite(tokens) ? tokens : null;
|
|
759
696
|
}
|
|
760
697
|
updateContextUsage(percentage) {
|
|
761
698
|
this.uiAdapter.updateContextUsage(percentage);
|
|
762
|
-
this.terminalInput.setContextUsage(percentage
|
|
699
|
+
this.terminalInput.setContextUsage(percentage);
|
|
763
700
|
}
|
|
764
701
|
refreshControlBar() {
|
|
765
702
|
this.terminalInput.setModeToggles({
|
|
@@ -767,9 +704,9 @@ export class InteractiveShell {
|
|
|
767
704
|
autoContinueEnabled: this.autoContinueEnabled,
|
|
768
705
|
verificationHotkey: 'alt+v',
|
|
769
706
|
autoContinueHotkey: 'alt+c',
|
|
770
|
-
thinkingModeLabel: this.thinkingMode,
|
|
771
|
-
thinkingHotkey: '/thinking',
|
|
772
707
|
});
|
|
708
|
+
// Update persistent model info display
|
|
709
|
+
this.terminalInput.setModelInfo(this.describeModelDetail());
|
|
773
710
|
this.refreshStatusLine();
|
|
774
711
|
this.terminalInput.render();
|
|
775
712
|
}
|
|
@@ -800,25 +737,6 @@ export class InteractiveShell {
|
|
|
800
737
|
// Set main status (tool execution, etc.) - shown when not overridden
|
|
801
738
|
const statusText = this.formatStatusLine(this.statusLineState);
|
|
802
739
|
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
|
-
});
|
|
822
740
|
if (forceRender) {
|
|
823
741
|
this.terminalInput.render();
|
|
824
742
|
}
|
|
@@ -878,14 +796,15 @@ export class InteractiveShell {
|
|
|
878
796
|
this.terminalInput.render();
|
|
879
797
|
}
|
|
880
798
|
/**
|
|
881
|
-
* Log user prompt
|
|
799
|
+
* Log the user's prompt as a visible message in the conversation.
|
|
800
|
+
* This creates a persistent log entry that remains visible during and after streaming.
|
|
882
801
|
*/
|
|
883
802
|
logUserPrompt(text) {
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
this.terminalInput.
|
|
803
|
+
// Display the user's prompt with the standard prefix
|
|
804
|
+
const prefix = formatUserPrompt();
|
|
805
|
+
display.stream(`\n${prefix}${text}\n\n`);
|
|
806
|
+
// Update content end row so chat box renders below the user prompt
|
|
807
|
+
this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
|
|
889
808
|
}
|
|
890
809
|
requestPromptRefresh(force = false) {
|
|
891
810
|
if (force) {
|
|
@@ -910,40 +829,16 @@ export class InteractiveShell {
|
|
|
910
829
|
this.stopStreamingHeartbeat();
|
|
911
830
|
// Enter global streaming mode - blocks all non-streaming UI output
|
|
912
831
|
enterStreamingMode();
|
|
913
|
-
// Set up scroll region for streaming content
|
|
914
|
-
this.terminalInput.enterStreamingScrollRegion();
|
|
915
832
|
this.uiUpdates.setMode('streaming');
|
|
916
833
|
this.streamingHeartbeatStart = Date.now();
|
|
917
834
|
this.streamingHeartbeatFrame = 0;
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
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
|
-
});
|
|
835
|
+
// Note: We don't start a heartbeat during streaming anymore
|
|
836
|
+
// because the UI shouldn't be rendering during streaming.
|
|
837
|
+
// The streaming status is shown in the streaming header instead.
|
|
941
838
|
}
|
|
942
839
|
stopStreamingHeartbeat() {
|
|
943
840
|
// Exit global streaming mode - allows UI to render again
|
|
944
841
|
exitStreamingMode();
|
|
945
|
-
// Exit scroll region mode
|
|
946
|
-
this.terminalInput.exitStreamingScrollRegion();
|
|
947
842
|
this.uiUpdates.stopHeartbeat('streaming');
|
|
948
843
|
this.streamingHeartbeatStart = null;
|
|
949
844
|
this.streamingHeartbeatFrame = 0;
|
|
@@ -955,28 +850,10 @@ export class InteractiveShell {
|
|
|
955
850
|
// Force refresh to update the input area now that streaming has ended
|
|
956
851
|
this.refreshStatusLine(true);
|
|
957
852
|
}
|
|
958
|
-
buildStreamingStatus(label
|
|
853
|
+
buildStreamingStatus(label) {
|
|
959
854
|
const detail = this.describeModelDetail();
|
|
960
|
-
const
|
|
961
|
-
|
|
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`;
|
|
855
|
+
const prefix = theme.info('●');
|
|
856
|
+
return detail ? `${prefix} ${label} ${theme.ui.muted('·')} ${detail}` : `${prefix} ${label}`;
|
|
980
857
|
}
|
|
981
858
|
refreshQueueIndicators() {
|
|
982
859
|
if (this.isProcessing) {
|
|
@@ -1224,6 +1101,17 @@ export class InteractiveShell {
|
|
|
1224
1101
|
case '/discover':
|
|
1225
1102
|
await this.discoverModelsCommand();
|
|
1226
1103
|
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;
|
|
1227
1115
|
default:
|
|
1228
1116
|
if (!(await this.tryCustomSlashCommand(command, input))) {
|
|
1229
1117
|
display.showWarning(`Unknown command "${command}".`);
|
|
@@ -1532,6 +1420,99 @@ export class InteractiveShell {
|
|
|
1532
1420
|
// Display keyboard shortcuts help (Claude Code style)
|
|
1533
1421
|
display.showSystemMessage(formatShortcutsHelp());
|
|
1534
1422
|
}
|
|
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
|
+
}
|
|
1535
1516
|
showFileChangeSummary() {
|
|
1536
1517
|
const summary = this._fileChangeTracker.getSummary();
|
|
1537
1518
|
const changes = this._fileChangeTracker.getAllChanges();
|
|
@@ -1574,11 +1555,11 @@ export class InteractiveShell {
|
|
|
1574
1555
|
display.showSystemMessage(lines.join('\n'));
|
|
1575
1556
|
}
|
|
1576
1557
|
showAlphaZeroMetrics() {
|
|
1577
|
-
const summary = this.
|
|
1558
|
+
const summary = this.sessionMetrics.getPerformanceSummary();
|
|
1578
1559
|
display.showSystemMessage(summary);
|
|
1579
1560
|
}
|
|
1580
1561
|
showImprovementSuggestions() {
|
|
1581
|
-
const suggestions = this.
|
|
1562
|
+
const suggestions = this.sessionMetrics.getImprovementSuggestions();
|
|
1582
1563
|
if (suggestions.length === 0) {
|
|
1583
1564
|
display.showInfo('No improvement suggestions at this time. Keep using the shell to generate metrics!');
|
|
1584
1565
|
return;
|
|
@@ -1624,9 +1605,7 @@ export class InteractiveShell {
|
|
|
1624
1605
|
}
|
|
1625
1606
|
}
|
|
1626
1607
|
lines.push(theme.secondary('CLI Flags:'));
|
|
1627
|
-
lines.push(' --alpha-zero Enable Alpha Zero 2 RL framework');
|
|
1628
1608
|
lines.push(' --coding Enable enhanced coding tools');
|
|
1629
|
-
lines.push(' --security Enable security research tools');
|
|
1630
1609
|
lines.push(' --all-plugins Enable all optional plugins');
|
|
1631
1610
|
display.showSystemMessage(lines.join('\n'));
|
|
1632
1611
|
}
|
|
@@ -1675,7 +1654,6 @@ export class InteractiveShell {
|
|
|
1675
1654
|
model: this.sessionState.model,
|
|
1676
1655
|
workspaceRoot: this.workingDir,
|
|
1677
1656
|
messages: history,
|
|
1678
|
-
scrollbackBuffer: this.terminalInput.getScrollbackBuffer(),
|
|
1679
1657
|
});
|
|
1680
1658
|
this.cachedHistory = history;
|
|
1681
1659
|
this.updateActiveSession(summary, true);
|
|
@@ -1854,7 +1832,6 @@ export class InteractiveShell {
|
|
|
1854
1832
|
workspaceRoot: this.workingDir,
|
|
1855
1833
|
title: this.activeSessionTitle,
|
|
1856
1834
|
messages: this.cachedHistory,
|
|
1857
|
-
scrollbackBuffer: this.terminalInput.getScrollbackBuffer(),
|
|
1858
1835
|
});
|
|
1859
1836
|
}
|
|
1860
1837
|
describeWorkspaceOptions() {
|
|
@@ -1872,75 +1849,6 @@ export class InteractiveShell {
|
|
|
1872
1849
|
}
|
|
1873
1850
|
return `${warning.label}: ${warning.reason}.`;
|
|
1874
1851
|
}
|
|
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
|
-
}
|
|
1944
1852
|
buildSlashCommandList(header) {
|
|
1945
1853
|
const lines = [theme.gradient.primary(header), ''];
|
|
1946
1854
|
for (const command of this.slashCommands) {
|
|
@@ -2409,7 +2317,7 @@ export class InteractiveShell {
|
|
|
2409
2317
|
this.autosaveIfEnabled();
|
|
2410
2318
|
// Track metrics with Alpha Zero 2
|
|
2411
2319
|
const elapsedMs = Date.now() - requestStartTime;
|
|
2412
|
-
this.
|
|
2320
|
+
this.sessionMetrics.recordMessage(elapsedMs);
|
|
2413
2321
|
if (!responseText?.trim()) {
|
|
2414
2322
|
display.showWarning('The provider returned an empty response. Check your API key/provider selection or retry the prompt.');
|
|
2415
2323
|
}
|
|
@@ -2427,10 +2335,14 @@ export class InteractiveShell {
|
|
|
2427
2335
|
this.stopStreamingHeartbeat();
|
|
2428
2336
|
this.isProcessing = false;
|
|
2429
2337
|
this.terminalInput.setStreaming(false);
|
|
2338
|
+
this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
|
|
2430
2339
|
this.uiAdapter.endProcessing('Ready for prompts');
|
|
2431
2340
|
this.setIdleStatus();
|
|
2432
2341
|
display.newLine();
|
|
2433
2342
|
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();
|
|
2434
2346
|
queueMicrotask(() => this.uiUpdates.setMode('idle'));
|
|
2435
2347
|
// CRITICAL: Ensure readline prompt is active for user input
|
|
2436
2348
|
// Claude Code style: New prompt naturally appears at bottom
|
|
@@ -2507,14 +2419,13 @@ When truly finished with ALL tasks, explicitly state "TASK_FULLY_COMPLETE".`;
|
|
|
2507
2419
|
try {
|
|
2508
2420
|
// Send the request and capture the response (streaming disabled)
|
|
2509
2421
|
display.showThinking('Responding...');
|
|
2510
|
-
this.refreshStatusLine(true);
|
|
2511
2422
|
const response = await agent.send(currentPrompt, true);
|
|
2512
2423
|
await this.awaitPendingCleanup();
|
|
2513
2424
|
this.captureHistorySnapshot();
|
|
2514
2425
|
this.autosaveIfEnabled();
|
|
2515
2426
|
// Track metrics
|
|
2516
2427
|
const elapsedMs = Date.now() - overallStartTime;
|
|
2517
|
-
this.
|
|
2428
|
+
this.sessionMetrics.recordMessage(elapsedMs);
|
|
2518
2429
|
if (!response?.trim()) {
|
|
2519
2430
|
display.showWarning('Model returned an empty response. Retrying this iteration...');
|
|
2520
2431
|
consecutiveNoProgress++;
|
|
@@ -2651,6 +2562,7 @@ What's the next action?`;
|
|
|
2651
2562
|
this.stopStreamingHeartbeat();
|
|
2652
2563
|
this.isProcessing = false;
|
|
2653
2564
|
this.terminalInput.setStreaming(false);
|
|
2565
|
+
this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
|
|
2654
2566
|
this.uiAdapter.endProcessing('Ready for prompts');
|
|
2655
2567
|
this.setIdleStatus();
|
|
2656
2568
|
this.updateStatusMessage(null);
|
|
@@ -3007,10 +2919,8 @@ What's the next action?`;
|
|
|
3007
2919
|
try {
|
|
3008
2920
|
// Send the error to the agent for fixing
|
|
3009
2921
|
display.showThinking('Analyzing build errors');
|
|
3010
|
-
this.refreshStatusLine(true);
|
|
3011
2922
|
const response = await this.agent.send(prompt, true);
|
|
3012
2923
|
display.stopThinking();
|
|
3013
|
-
this.refreshStatusLine(true);
|
|
3014
2924
|
if (response) {
|
|
3015
2925
|
display.showAssistantMessage(response, { isFinal: true });
|
|
3016
2926
|
}
|
|
@@ -3037,8 +2947,8 @@ What's the next action?`;
|
|
|
3037
2947
|
};
|
|
3038
2948
|
this.agent = this.runtimeSession.createAgent(selection, {
|
|
3039
2949
|
onStreamChunk: (chunk) => {
|
|
3040
|
-
// Stream output
|
|
3041
|
-
|
|
2950
|
+
// Stream output directly - no spinner during streaming to avoid race conditions
|
|
2951
|
+
display.stream(chunk);
|
|
3042
2952
|
},
|
|
3043
2953
|
onStreamFallback: (info) => this.handleStreamingFallback(info),
|
|
3044
2954
|
onAssistantMessage: (content, metadata) => {
|
|
@@ -3060,16 +2970,18 @@ What's the next action?`;
|
|
|
3060
2970
|
display.showAssistantMessage(finalContent, enriched);
|
|
3061
2971
|
}
|
|
3062
2972
|
}
|
|
3063
|
-
//
|
|
2973
|
+
// Show status line at end (Claude Code style: "• Context X% used • Ready for prompts (2s)")
|
|
3064
2974
|
display.stopThinking();
|
|
3065
|
-
//
|
|
2975
|
+
// Calculate context usage
|
|
2976
|
+
let contextInfo;
|
|
3066
2977
|
if (enriched.contextWindowTokens && metadata.usage) {
|
|
3067
2978
|
const total = this.totalTokens(metadata.usage);
|
|
3068
2979
|
if (total && total > 0) {
|
|
3069
2980
|
const percentage = Math.round((total / enriched.contextWindowTokens) * 100);
|
|
3070
|
-
|
|
2981
|
+
contextInfo = { percentage, tokens: total };
|
|
3071
2982
|
}
|
|
3072
2983
|
}
|
|
2984
|
+
display.showStatusLine('Ready for prompts', enriched.elapsedMs, contextInfo);
|
|
3073
2985
|
// Auto-verify changes: build first (catches type errors), then tests
|
|
3074
2986
|
void this.enforceAutoBuild('final-response');
|
|
3075
2987
|
void this.enforceAutoTests('final-response');
|
|
@@ -3139,6 +3051,7 @@ What's the next action?`;
|
|
|
3139
3051
|
this.stopStreamingHeartbeat();
|
|
3140
3052
|
this.updateStatusMessage(null);
|
|
3141
3053
|
this.terminalInput.setStreaming(false);
|
|
3054
|
+
this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
|
|
3142
3055
|
this.terminalInput.render();
|
|
3143
3056
|
},
|
|
3144
3057
|
onVerificationNeeded: () => {
|
|
@@ -3175,6 +3088,7 @@ What's the next action?`;
|
|
|
3175
3088
|
resetChatBoxAfterModelSwap() {
|
|
3176
3089
|
this.updateStatusMessage(null);
|
|
3177
3090
|
this.terminalInput.setStreaming(false);
|
|
3091
|
+
this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
|
|
3178
3092
|
this.terminalInput.render();
|
|
3179
3093
|
this.ensureReadlineReady();
|
|
3180
3094
|
}
|
|
@@ -3239,14 +3153,9 @@ What's the next action?`;
|
|
|
3239
3153
|
return null;
|
|
3240
3154
|
}
|
|
3241
3155
|
const usageRatio = total / windowTokens;
|
|
3242
|
-
this.latestTokenUsage = {
|
|
3243
|
-
used: total,
|
|
3244
|
-
limit: windowTokens,
|
|
3245
|
-
};
|
|
3246
3156
|
// Always update context usage in the UI
|
|
3247
3157
|
const percentUsed = Math.round(usageRatio * 100);
|
|
3248
3158
|
this.updateContextUsage(percentUsed);
|
|
3249
|
-
this.refreshStatusLine(true);
|
|
3250
3159
|
if (usageRatio < CONTEXT_USAGE_THRESHOLD) {
|
|
3251
3160
|
return null;
|
|
3252
3161
|
}
|
|
@@ -3513,113 +3422,6 @@ What's the next action?`;
|
|
|
3513
3422
|
this.sessionState.reasoningEffort = preset.reasoningEffort;
|
|
3514
3423
|
}
|
|
3515
3424
|
}
|
|
3516
|
-
/**
|
|
3517
|
-
* Build the session banner with comprehensive feature status.
|
|
3518
|
-
*/
|
|
3519
|
-
buildBanner() {
|
|
3520
|
-
const terminalWidth = output.columns ?? 100;
|
|
3521
|
-
const width = Math.min(terminalWidth - 4, 110);
|
|
3522
|
-
// Collect tool categories for display
|
|
3523
|
-
const toolCategories = this.collectToolCategories();
|
|
3524
|
-
return renderSessionFrame({
|
|
3525
|
-
profileLabel: this.profileLabel,
|
|
3526
|
-
profileName: this.profile,
|
|
3527
|
-
model: this.sessionState.model,
|
|
3528
|
-
provider: this.sessionState.provider,
|
|
3529
|
-
workspace: this.workingDir,
|
|
3530
|
-
version: this.version,
|
|
3531
|
-
width,
|
|
3532
|
-
features: {
|
|
3533
|
-
verification: this.verificationEnabled,
|
|
3534
|
-
autoContinue: this.autoContinueEnabled,
|
|
3535
|
-
thinkingMode: this.thinkingMode,
|
|
3536
|
-
plugins: this._enabledPlugins,
|
|
3537
|
-
tools: toolCategories,
|
|
3538
|
-
sessionId: this.activeSessionId ?? undefined,
|
|
3539
|
-
},
|
|
3540
|
-
});
|
|
3541
|
-
}
|
|
3542
|
-
/**
|
|
3543
|
-
* Collect tool categories for banner display.
|
|
3544
|
-
*/
|
|
3545
|
-
collectToolCategories() {
|
|
3546
|
-
const categories = [];
|
|
3547
|
-
try {
|
|
3548
|
-
const providerTools = this.runtimeSession.toolRuntime.listProviderTools();
|
|
3549
|
-
if (providerTools.length > 0) {
|
|
3550
|
-
// Group by category (first word of tool name or namespace)
|
|
3551
|
-
const groups = new Map();
|
|
3552
|
-
for (const tool of providerTools) {
|
|
3553
|
-
const category = this.extractToolCategory(tool.name);
|
|
3554
|
-
groups.set(category, (groups.get(category) || 0) + 1);
|
|
3555
|
-
}
|
|
3556
|
-
// Convert to array sorted by count
|
|
3557
|
-
const sorted = Array.from(groups.entries())
|
|
3558
|
-
.sort((a, b) => b[1] - a[1])
|
|
3559
|
-
.slice(0, 5); // Top 5 categories
|
|
3560
|
-
for (const [name, count] of sorted) {
|
|
3561
|
-
categories.push({ name, count, icon: this.getToolCategoryIcon(name) });
|
|
3562
|
-
}
|
|
3563
|
-
}
|
|
3564
|
-
}
|
|
3565
|
-
catch {
|
|
3566
|
-
// Ignore errors in tool collection
|
|
3567
|
-
}
|
|
3568
|
-
return categories;
|
|
3569
|
-
}
|
|
3570
|
-
/**
|
|
3571
|
-
* Extract category from tool name.
|
|
3572
|
-
*/
|
|
3573
|
-
extractToolCategory(toolName) {
|
|
3574
|
-
// Common tool prefixes
|
|
3575
|
-
const prefixMap = {
|
|
3576
|
-
git: 'Git',
|
|
3577
|
-
npm: 'NPM',
|
|
3578
|
-
bash: 'Shell',
|
|
3579
|
-
file: 'Files',
|
|
3580
|
-
read: 'Files',
|
|
3581
|
-
write: 'Files',
|
|
3582
|
-
edit: 'Files',
|
|
3583
|
-
search: 'Search',
|
|
3584
|
-
glob: 'Search',
|
|
3585
|
-
grep: 'Search',
|
|
3586
|
-
web: 'Web',
|
|
3587
|
-
fetch: 'Web',
|
|
3588
|
-
test: 'Testing',
|
|
3589
|
-
build: 'Build',
|
|
3590
|
-
deploy: 'Deploy',
|
|
3591
|
-
cloud: 'Cloud',
|
|
3592
|
-
browser: 'Browser',
|
|
3593
|
-
};
|
|
3594
|
-
const lower = toolName.toLowerCase();
|
|
3595
|
-
for (const [prefix, category] of Object.entries(prefixMap)) {
|
|
3596
|
-
if (lower.startsWith(prefix)) {
|
|
3597
|
-
return category;
|
|
3598
|
-
}
|
|
3599
|
-
}
|
|
3600
|
-
// Default to first word capitalized
|
|
3601
|
-
const firstWord = toolName.split(/[_\-\s]/)[0] || 'Other';
|
|
3602
|
-
return firstWord.charAt(0).toUpperCase() + firstWord.slice(1).toLowerCase();
|
|
3603
|
-
}
|
|
3604
|
-
/**
|
|
3605
|
-
* Get icon for tool category.
|
|
3606
|
-
*/
|
|
3607
|
-
getToolCategoryIcon(category) {
|
|
3608
|
-
const icons = {
|
|
3609
|
-
Git: '⎇',
|
|
3610
|
-
NPM: '📦',
|
|
3611
|
-
Shell: '⌘',
|
|
3612
|
-
Files: '📁',
|
|
3613
|
-
Search: '🔍',
|
|
3614
|
-
Web: '🌐',
|
|
3615
|
-
Testing: '🧪',
|
|
3616
|
-
Build: '🔧',
|
|
3617
|
-
Deploy: '🚀',
|
|
3618
|
-
Cloud: '☁',
|
|
3619
|
-
Browser: '🌐',
|
|
3620
|
-
};
|
|
3621
|
-
return icons[category] || '⚙';
|
|
3622
|
-
}
|
|
3623
3425
|
refreshBannerSessionInfo() {
|
|
3624
3426
|
const nextState = {
|
|
3625
3427
|
model: this.sessionState.model,
|
|
@@ -3630,11 +3432,13 @@ What's the next action?`;
|
|
|
3630
3432
|
return;
|
|
3631
3433
|
}
|
|
3632
3434
|
this.refreshContextGauge();
|
|
3633
|
-
|
|
3634
|
-
//
|
|
3435
|
+
display.updateSessionInfo(nextState.model, nextState.provider);
|
|
3436
|
+
// Update the persistent model info display in terminal input
|
|
3437
|
+
this.terminalInput.setModelInfo(this.describeModelDetail());
|
|
3635
3438
|
if (!this.isProcessing) {
|
|
3636
3439
|
this.setIdleStatus();
|
|
3637
3440
|
}
|
|
3441
|
+
// Pinned header rows are disabled; scroll region handles all output.
|
|
3638
3442
|
this.bannerSessionState = nextState;
|
|
3639
3443
|
}
|
|
3640
3444
|
providerLabel(id) {
|