erosolar-cli 1.7.262 → 1.7.263

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.
Files changed (283) hide show
  1. package/README.md +148 -22
  2. package/dist/alpha-zero/agentWrapper.d.ts +84 -0
  3. package/dist/alpha-zero/agentWrapper.d.ts.map +1 -0
  4. package/dist/alpha-zero/agentWrapper.js +171 -0
  5. package/dist/alpha-zero/agentWrapper.js.map +1 -0
  6. package/dist/alpha-zero/codeEvaluator.d.ts +25 -0
  7. package/dist/alpha-zero/codeEvaluator.d.ts.map +1 -0
  8. package/dist/alpha-zero/codeEvaluator.js +273 -0
  9. package/dist/alpha-zero/codeEvaluator.js.map +1 -0
  10. package/dist/alpha-zero/competitiveRunner.d.ts +66 -0
  11. package/dist/alpha-zero/competitiveRunner.d.ts.map +1 -0
  12. package/dist/alpha-zero/competitiveRunner.js +224 -0
  13. package/dist/alpha-zero/competitiveRunner.js.map +1 -0
  14. package/dist/alpha-zero/index.d.ts +67 -0
  15. package/dist/alpha-zero/index.d.ts.map +1 -0
  16. package/dist/alpha-zero/index.js +99 -0
  17. package/dist/alpha-zero/index.js.map +1 -0
  18. package/dist/alpha-zero/introspection.d.ts +128 -0
  19. package/dist/alpha-zero/introspection.d.ts.map +1 -0
  20. package/dist/alpha-zero/introspection.js +300 -0
  21. package/dist/alpha-zero/introspection.js.map +1 -0
  22. package/dist/alpha-zero/metricsTracker.d.ts +71 -0
  23. package/dist/alpha-zero/metricsTracker.d.ts.map +1 -0
  24. package/dist/{core → alpha-zero}/metricsTracker.js +5 -2
  25. package/dist/alpha-zero/metricsTracker.js.map +1 -0
  26. package/dist/alpha-zero/security/core.d.ts +125 -0
  27. package/dist/alpha-zero/security/core.d.ts.map +1 -0
  28. package/dist/alpha-zero/security/core.js +271 -0
  29. package/dist/alpha-zero/security/core.js.map +1 -0
  30. package/dist/alpha-zero/security/google.d.ts +125 -0
  31. package/dist/alpha-zero/security/google.d.ts.map +1 -0
  32. package/dist/alpha-zero/security/google.js +311 -0
  33. package/dist/alpha-zero/security/google.js.map +1 -0
  34. package/dist/alpha-zero/security/googleLoader.d.ts +17 -0
  35. package/dist/alpha-zero/security/googleLoader.d.ts.map +1 -0
  36. package/dist/alpha-zero/security/googleLoader.js +41 -0
  37. package/dist/alpha-zero/security/googleLoader.js.map +1 -0
  38. package/dist/alpha-zero/security/index.d.ts +29 -0
  39. package/dist/alpha-zero/security/index.d.ts.map +1 -0
  40. package/dist/alpha-zero/security/index.js +32 -0
  41. package/dist/alpha-zero/security/index.js.map +1 -0
  42. package/dist/alpha-zero/security/simulation.d.ts +124 -0
  43. package/dist/alpha-zero/security/simulation.d.ts.map +1 -0
  44. package/dist/alpha-zero/security/simulation.js +277 -0
  45. package/dist/alpha-zero/security/simulation.js.map +1 -0
  46. package/dist/alpha-zero/selfModification.d.ts +109 -0
  47. package/dist/alpha-zero/selfModification.d.ts.map +1 -0
  48. package/dist/alpha-zero/selfModification.js +233 -0
  49. package/dist/alpha-zero/selfModification.js.map +1 -0
  50. package/dist/alpha-zero/types.d.ts +170 -0
  51. package/dist/alpha-zero/types.d.ts.map +1 -0
  52. package/dist/alpha-zero/types.js +31 -0
  53. package/dist/alpha-zero/types.js.map +1 -0
  54. package/dist/capabilities/securityTestingCapability.d.ts +13 -0
  55. package/dist/capabilities/securityTestingCapability.d.ts.map +1 -0
  56. package/dist/capabilities/securityTestingCapability.js +25 -0
  57. package/dist/capabilities/securityTestingCapability.js.map +1 -0
  58. package/dist/contracts/agent-schemas.json +15 -0
  59. package/dist/contracts/tools.schema.json +9 -0
  60. package/dist/core/aiFlowOptimizer.d.ts +26 -0
  61. package/dist/core/aiFlowOptimizer.d.ts.map +1 -0
  62. package/dist/core/aiFlowOptimizer.js +31 -0
  63. package/dist/core/aiFlowOptimizer.js.map +1 -0
  64. package/dist/core/aiOptimizationEngine.d.ts +158 -0
  65. package/dist/core/aiOptimizationEngine.d.ts.map +1 -0
  66. package/dist/core/aiOptimizationEngine.js +428 -0
  67. package/dist/core/aiOptimizationEngine.js.map +1 -0
  68. package/dist/core/aiOptimizationIntegration.d.ts +93 -0
  69. package/dist/core/aiOptimizationIntegration.d.ts.map +1 -0
  70. package/dist/core/aiOptimizationIntegration.js +250 -0
  71. package/dist/core/aiOptimizationIntegration.js.map +1 -0
  72. package/dist/core/customCommands.d.ts +0 -1
  73. package/dist/core/customCommands.d.ts.map +1 -1
  74. package/dist/core/customCommands.js +0 -3
  75. package/dist/core/customCommands.js.map +1 -1
  76. package/dist/core/enhancedErrorRecovery.d.ts +100 -0
  77. package/dist/core/enhancedErrorRecovery.d.ts.map +1 -0
  78. package/dist/core/enhancedErrorRecovery.js +345 -0
  79. package/dist/core/enhancedErrorRecovery.js.map +1 -0
  80. package/dist/core/hooksSystem.d.ts +65 -0
  81. package/dist/core/hooksSystem.d.ts.map +1 -0
  82. package/dist/core/hooksSystem.js +273 -0
  83. package/dist/core/hooksSystem.js.map +1 -0
  84. package/dist/core/memorySystem.d.ts +48 -0
  85. package/dist/core/memorySystem.d.ts.map +1 -0
  86. package/dist/core/memorySystem.js +271 -0
  87. package/dist/core/memorySystem.js.map +1 -0
  88. package/dist/core/toolPreconditions.d.ts.map +1 -1
  89. package/dist/core/toolPreconditions.js +14 -0
  90. package/dist/core/toolPreconditions.js.map +1 -1
  91. package/dist/core/toolRuntime.d.ts.map +1 -1
  92. package/dist/core/toolRuntime.js +5 -0
  93. package/dist/core/toolRuntime.js.map +1 -1
  94. package/dist/core/toolValidation.d.ts.map +1 -1
  95. package/dist/core/toolValidation.js +3 -14
  96. package/dist/core/toolValidation.js.map +1 -1
  97. package/dist/core/unified/errors.d.ts +189 -0
  98. package/dist/core/unified/errors.d.ts.map +1 -0
  99. package/dist/core/unified/errors.js +497 -0
  100. package/dist/core/unified/errors.js.map +1 -0
  101. package/dist/core/unified/index.d.ts +19 -0
  102. package/dist/core/unified/index.d.ts.map +1 -0
  103. package/dist/core/unified/index.js +68 -0
  104. package/dist/core/unified/index.js.map +1 -0
  105. package/dist/core/unified/schema.d.ts +101 -0
  106. package/dist/core/unified/schema.d.ts.map +1 -0
  107. package/dist/core/unified/schema.js +350 -0
  108. package/dist/core/unified/schema.js.map +1 -0
  109. package/dist/core/unified/toolRuntime.d.ts +179 -0
  110. package/dist/core/unified/toolRuntime.d.ts.map +1 -0
  111. package/dist/core/unified/toolRuntime.js +517 -0
  112. package/dist/core/unified/toolRuntime.js.map +1 -0
  113. package/dist/core/unified/tools.d.ts +127 -0
  114. package/dist/core/unified/tools.d.ts.map +1 -0
  115. package/dist/core/unified/tools.js +1333 -0
  116. package/dist/core/unified/tools.js.map +1 -0
  117. package/dist/core/unified/types.d.ts +352 -0
  118. package/dist/core/unified/types.d.ts.map +1 -0
  119. package/dist/core/unified/types.js +12 -0
  120. package/dist/core/unified/types.js.map +1 -0
  121. package/dist/core/unified/version.d.ts +209 -0
  122. package/dist/core/unified/version.d.ts.map +1 -0
  123. package/dist/core/unified/version.js +454 -0
  124. package/dist/core/unified/version.js.map +1 -0
  125. package/dist/core/validationRunner.d.ts +3 -1
  126. package/dist/core/validationRunner.d.ts.map +1 -1
  127. package/dist/core/validationRunner.js.map +1 -1
  128. package/dist/mcp/sseClient.d.ts.map +1 -1
  129. package/dist/mcp/sseClient.js +18 -9
  130. package/dist/mcp/sseClient.js.map +1 -1
  131. package/dist/plugins/tools/build/buildPlugin.d.ts +6 -0
  132. package/dist/plugins/tools/build/buildPlugin.d.ts.map +1 -1
  133. package/dist/plugins/tools/build/buildPlugin.js +10 -4
  134. package/dist/plugins/tools/build/buildPlugin.js.map +1 -1
  135. package/dist/plugins/tools/nodeDefaults.d.ts.map +1 -1
  136. package/dist/plugins/tools/nodeDefaults.js +2 -0
  137. package/dist/plugins/tools/nodeDefaults.js.map +1 -1
  138. package/dist/plugins/tools/security/securityPlugin.d.ts +3 -0
  139. package/dist/plugins/tools/security/securityPlugin.d.ts.map +1 -0
  140. package/dist/plugins/tools/security/securityPlugin.js +12 -0
  141. package/dist/plugins/tools/security/securityPlugin.js.map +1 -0
  142. package/dist/security/active-stack-security.d.ts +112 -0
  143. package/dist/security/active-stack-security.d.ts.map +1 -0
  144. package/dist/security/active-stack-security.js +296 -0
  145. package/dist/security/active-stack-security.js.map +1 -0
  146. package/dist/security/advanced-persistence-research.d.ts +92 -0
  147. package/dist/security/advanced-persistence-research.d.ts.map +1 -0
  148. package/dist/security/advanced-persistence-research.js +195 -0
  149. package/dist/security/advanced-persistence-research.js.map +1 -0
  150. package/dist/security/advanced-targeting.d.ts +119 -0
  151. package/dist/security/advanced-targeting.d.ts.map +1 -0
  152. package/dist/security/advanced-targeting.js +233 -0
  153. package/dist/security/advanced-targeting.js.map +1 -0
  154. package/dist/security/assessment/vulnerabilityAssessment.d.ts +104 -0
  155. package/dist/security/assessment/vulnerabilityAssessment.d.ts.map +1 -0
  156. package/dist/security/assessment/vulnerabilityAssessment.js +315 -0
  157. package/dist/security/assessment/vulnerabilityAssessment.js.map +1 -0
  158. package/dist/security/authorization/securityAuthorization.d.ts +88 -0
  159. package/dist/security/authorization/securityAuthorization.d.ts.map +1 -0
  160. package/dist/security/authorization/securityAuthorization.js +172 -0
  161. package/dist/security/authorization/securityAuthorization.js.map +1 -0
  162. package/dist/security/comprehensive-targeting.d.ts +85 -0
  163. package/dist/security/comprehensive-targeting.d.ts.map +1 -0
  164. package/dist/security/comprehensive-targeting.js +438 -0
  165. package/dist/security/comprehensive-targeting.js.map +1 -0
  166. package/dist/security/global-security-integration.d.ts +91 -0
  167. package/dist/security/global-security-integration.d.ts.map +1 -0
  168. package/dist/security/global-security-integration.js +218 -0
  169. package/dist/security/global-security-integration.js.map +1 -0
  170. package/dist/security/index.d.ts +38 -0
  171. package/dist/security/index.d.ts.map +1 -0
  172. package/dist/security/index.js +47 -0
  173. package/dist/security/index.js.map +1 -0
  174. package/dist/security/persistence-analyzer.d.ts +56 -0
  175. package/dist/security/persistence-analyzer.d.ts.map +1 -0
  176. package/dist/security/persistence-analyzer.js +187 -0
  177. package/dist/security/persistence-analyzer.js.map +1 -0
  178. package/dist/security/persistence-cli.d.ts +36 -0
  179. package/dist/security/persistence-cli.d.ts.map +1 -0
  180. package/dist/security/persistence-cli.js +160 -0
  181. package/dist/security/persistence-cli.js.map +1 -0
  182. package/dist/security/persistence-research.d.ts +92 -0
  183. package/dist/security/persistence-research.d.ts.map +1 -0
  184. package/dist/security/persistence-research.js +364 -0
  185. package/dist/security/persistence-research.js.map +1 -0
  186. package/dist/security/research/persistenceResearch.d.ts +97 -0
  187. package/dist/security/research/persistenceResearch.d.ts.map +1 -0
  188. package/dist/security/research/persistenceResearch.js +282 -0
  189. package/dist/security/research/persistenceResearch.js.map +1 -0
  190. package/dist/security/security-integration.d.ts +74 -0
  191. package/dist/security/security-integration.d.ts.map +1 -0
  192. package/dist/security/security-integration.js +137 -0
  193. package/dist/security/security-integration.js.map +1 -0
  194. package/dist/security/security-testing-framework.d.ts +112 -0
  195. package/dist/security/security-testing-framework.d.ts.map +1 -0
  196. package/dist/security/security-testing-framework.js +364 -0
  197. package/dist/security/security-testing-framework.js.map +1 -0
  198. package/dist/security/simulation/attackSimulation.d.ts +93 -0
  199. package/dist/security/simulation/attackSimulation.d.ts.map +1 -0
  200. package/dist/security/simulation/attackSimulation.js +341 -0
  201. package/dist/security/simulation/attackSimulation.js.map +1 -0
  202. package/dist/security/strategic-operations.d.ts +100 -0
  203. package/dist/security/strategic-operations.d.ts.map +1 -0
  204. package/dist/security/strategic-operations.js +276 -0
  205. package/dist/security/strategic-operations.js.map +1 -0
  206. package/dist/security/tool-security-wrapper.d.ts +58 -0
  207. package/dist/security/tool-security-wrapper.d.ts.map +1 -0
  208. package/dist/security/tool-security-wrapper.js +156 -0
  209. package/dist/security/tool-security-wrapper.js.map +1 -0
  210. package/dist/shell/claudeCodeStreamHandler.d.ts +145 -0
  211. package/dist/shell/claudeCodeStreamHandler.d.ts.map +1 -0
  212. package/dist/shell/claudeCodeStreamHandler.js +322 -0
  213. package/dist/shell/claudeCodeStreamHandler.js.map +1 -0
  214. package/dist/shell/inputQueueManager.d.ts +144 -0
  215. package/dist/shell/inputQueueManager.d.ts.map +1 -0
  216. package/dist/shell/inputQueueManager.js +290 -0
  217. package/dist/shell/inputQueueManager.js.map +1 -0
  218. package/dist/shell/interactiveShell.d.ts +7 -11
  219. package/dist/shell/interactiveShell.d.ts.map +1 -1
  220. package/dist/shell/interactiveShell.js +153 -190
  221. package/dist/shell/interactiveShell.js.map +1 -1
  222. package/dist/shell/metricsTracker.d.ts +60 -0
  223. package/dist/shell/metricsTracker.d.ts.map +1 -0
  224. package/dist/shell/metricsTracker.js +119 -0
  225. package/dist/shell/metricsTracker.js.map +1 -0
  226. package/dist/shell/shellApp.d.ts +0 -2
  227. package/dist/shell/shellApp.d.ts.map +1 -1
  228. package/dist/shell/shellApp.js +0 -16
  229. package/dist/shell/shellApp.js.map +1 -1
  230. package/dist/shell/streamingOutputManager.d.ts +115 -0
  231. package/dist/shell/streamingOutputManager.d.ts.map +1 -0
  232. package/dist/shell/streamingOutputManager.js +225 -0
  233. package/dist/shell/streamingOutputManager.js.map +1 -0
  234. package/dist/shell/systemPrompt.d.ts.map +1 -1
  235. package/dist/shell/systemPrompt.js +4 -1
  236. package/dist/shell/systemPrompt.js.map +1 -1
  237. package/dist/shell/terminalInput.d.ts +147 -68
  238. package/dist/shell/terminalInput.d.ts.map +1 -1
  239. package/dist/shell/terminalInput.js +689 -451
  240. package/dist/shell/terminalInput.js.map +1 -1
  241. package/dist/shell/terminalInputAdapter.d.ts +20 -20
  242. package/dist/shell/terminalInputAdapter.d.ts.map +1 -1
  243. package/dist/shell/terminalInputAdapter.js +29 -14
  244. package/dist/shell/terminalInputAdapter.js.map +1 -1
  245. package/dist/tools/securityTools.d.ts +22 -0
  246. package/dist/tools/securityTools.d.ts.map +1 -0
  247. package/dist/tools/securityTools.js +448 -0
  248. package/dist/tools/securityTools.js.map +1 -0
  249. package/dist/ui/ShellUIAdapter.d.ts.map +1 -1
  250. package/dist/ui/ShellUIAdapter.js +12 -13
  251. package/dist/ui/ShellUIAdapter.js.map +1 -1
  252. package/dist/ui/display.d.ts +0 -19
  253. package/dist/ui/display.d.ts.map +1 -1
  254. package/dist/ui/display.js +33 -131
  255. package/dist/ui/display.js.map +1 -1
  256. package/dist/ui/persistentPrompt.d.ts +50 -0
  257. package/dist/ui/persistentPrompt.d.ts.map +1 -0
  258. package/dist/ui/persistentPrompt.js +92 -0
  259. package/dist/ui/persistentPrompt.js.map +1 -0
  260. package/dist/ui/terminalUISchema.d.ts +195 -0
  261. package/dist/ui/terminalUISchema.d.ts.map +1 -0
  262. package/dist/ui/terminalUISchema.js +113 -0
  263. package/dist/ui/terminalUISchema.js.map +1 -0
  264. package/dist/ui/theme.d.ts.map +1 -1
  265. package/dist/ui/theme.js +8 -6
  266. package/dist/ui/theme.js.map +1 -1
  267. package/dist/ui/toolDisplay.d.ts +158 -0
  268. package/dist/ui/toolDisplay.d.ts.map +1 -1
  269. package/dist/ui/toolDisplay.js +348 -0
  270. package/dist/ui/toolDisplay.js.map +1 -1
  271. package/dist/ui/unified/layout.d.ts +0 -1
  272. package/dist/ui/unified/layout.d.ts.map +1 -1
  273. package/dist/ui/unified/layout.js +25 -15
  274. package/dist/ui/unified/layout.js.map +1 -1
  275. package/package.json +1 -1
  276. package/scripts/deploy-security-capabilities.js +178 -0
  277. package/dist/core/hooks.d.ts +0 -113
  278. package/dist/core/hooks.d.ts.map +0 -1
  279. package/dist/core/hooks.js +0 -267
  280. package/dist/core/hooks.js.map +0 -1
  281. package/dist/core/metricsTracker.d.ts +0 -122
  282. package/dist/core/metricsTracker.d.ts.map +0 -1
  283. package/dist/core/metricsTracker.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,8 +19,9 @@ 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 '../core/metricsTracker.js';
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
26
  import { isUpdateInProgress } from './updateManager.js';
26
27
  import { writeLock } from '../ui/writeLock.js';
@@ -34,7 +35,6 @@ const DROPDOWN_COLORS = [
34
35
  theme.success,
35
36
  theme.warning,
36
37
  ];
37
- const STREAMING_SPINNER_FRAMES = ['◐', '◓', '◑', '◒'];
38
38
  // Load MODEL_PRESETS from centralized schema
39
39
  const MODEL_PRESETS = getModels().map((model) => ({
40
40
  id: model.id,
@@ -49,13 +49,11 @@ const MODEL_PRESETS = getModels().map((model) => ({
49
49
  const BASE_SLASH_COMMANDS = getSlashCommands().map((cmd) => ({
50
50
  command: cmd.command,
51
51
  description: cmd.description,
52
- category: cmd.category,
53
52
  }));
54
53
  // Load PROVIDER_LABELS from centralized schema
55
54
  const PROVIDER_LABELS = Object.fromEntries(getProviders().map((provider) => [provider.id, provider.label]));
56
55
  // Allow enough time for paste detection to kick in before flushing buffered lines
57
56
  const CONTEXT_USAGE_THRESHOLD = 0.9;
58
- const CONTEXT_AUTOCOMPACT_PERCENT = Math.round(CONTEXT_USAGE_THRESHOLD * 100);
59
57
  const CONTEXT_RECENT_MESSAGE_COUNT = 12;
60
58
  const CONTEXT_CLEANUP_CHARS_PER_CHUNK = 6000;
61
59
  const CONTEXT_CLEANUP_MAX_OUTPUT_TOKENS = 800;
@@ -96,12 +94,11 @@ export class InteractiveShell {
96
94
  uiAdapter;
97
95
  uiUpdates;
98
96
  _fileChangeTracker = new FileChangeTracker(); // Reserved for future file tracking features
99
- alphaZeroMetrics; // Alpha Zero 2 performance tracking
97
+ sessionMetrics; // Session performance tracking
100
98
  statusSubscription = null;
101
99
  followUpQueue = [];
102
100
  isDrainingQueue = false;
103
101
  activeContextWindowTokens = null;
104
- latestTokenUsage = { used: null, limit: null };
105
102
  sessionPreferences;
106
103
  autosaveEnabled;
107
104
  autoContinueEnabled;
@@ -132,7 +129,6 @@ export class InteractiveShell {
132
129
  statusLineState = null;
133
130
  statusMessageOverride = null;
134
131
  promptRefreshTimer = null;
135
- launchPaletteShown = false;
136
132
  constructor(config) {
137
133
  this.profile = config.profile;
138
134
  this.profileLabel = config.profileLabel;
@@ -166,7 +162,6 @@ export class InteractiveShell {
166
162
  this.slashCommands.push({
167
163
  command: '/agents',
168
164
  description: 'Select the default agent profile (applies on next launch)',
169
- category: 'configuration',
170
165
  });
171
166
  }
172
167
  this.customCommands = loadCustomSlashCommands();
@@ -175,21 +170,18 @@ export class InteractiveShell {
175
170
  this.slashCommands.push({
176
171
  command: custom.command,
177
172
  description: `${custom.description} (custom)`,
178
- category: custom.category ?? 'other',
179
173
  });
180
174
  }
181
175
  if (!this.slashCommands.some((cmd) => cmd.command === '/exit')) {
182
176
  this.slashCommands.push({
183
177
  command: '/exit',
184
178
  description: 'Quit the CLI immediately',
185
- category: 'other',
186
179
  });
187
180
  }
188
181
  // Add /plugins command
189
182
  this.slashCommands.push({
190
183
  command: '/plugins',
191
184
  description: 'Show available and loaded plugins',
192
- category: 'configuration',
193
185
  });
194
186
  this.statusTracker = config.statusTracker;
195
187
  this.ui = config.ui;
@@ -224,8 +216,13 @@ export class InteractiveShell {
224
216
  });
225
217
  // Register output interceptor for cursor positioning during streaming
226
218
  this.terminalInput.registerOutputInterceptor(display);
219
+ // Use flow mode: input renders inline after content for a unified layout
220
+ // This eliminates the blank space between banner and input area
221
+ this.terminalInput.setFlowMode(true);
222
+ // Set content end row so input renders right after startup content
223
+ this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
227
224
  // Initialize Alpha Zero 2 metrics tracking
228
- this.alphaZeroMetrics = new MetricsTracker(`${this.profile}-${Date.now()}`);
225
+ this.sessionMetrics = new MetricsTracker(`${this.profile}-${Date.now()}`);
229
226
  this.setupStatusTracking();
230
227
  this.refreshContextGauge();
231
228
  this.terminalInput.start();
@@ -281,15 +278,9 @@ export class InteractiveShell {
281
278
  await this.processInputBlock(initialPrompt);
282
279
  return;
283
280
  }
284
- this.showLaunchCommandPalette();
285
281
  // Ensure the terminal input is visible
286
282
  this.terminalInput.render();
287
283
  }
288
- showLaunchCommandPalette() {
289
- // Disabled: Quick commands palette takes up too much space
290
- // Users can type /help to see available commands
291
- this.launchPaletteShown = true;
292
- }
293
284
  /**
294
285
  * TerminalInputAdapter submit handler
295
286
  */
@@ -303,8 +294,9 @@ export class InteractiveShell {
303
294
  this.handleInputChange('');
304
295
  return;
305
296
  }
306
- // DON'T clear the input here - keep it visible while streaming.
307
- // The input will be cleared after streaming completes in the finally block.
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);
308
300
  this.logUserPrompt(approved);
309
301
  void this.processInputBlock(approved).catch((err) => {
310
302
  display.showError(err instanceof Error ? err.message : String(err), err);
@@ -506,9 +498,10 @@ export class InteractiveShell {
506
498
  // Dispose unified UI adapter
507
499
  this.uiAdapter.dispose();
508
500
  display.newLine();
509
- console.log(theme.ui.muted('━'.repeat(44)));
510
- console.log(theme.ui.muted(' Goodbye! · support@ero.solar'));
511
- console.log(theme.ui.muted(''.repeat(44)));
501
+ console.log(theme.gradient.warm('━'.repeat(50)));
502
+ console.log(` ${theme.gradient.cool('Goodbye!')} ${theme.ui.muted('·')} ${theme.info('support@ero.solar')}`);
503
+ console.log(` ${theme.ui.muted('Read:')} ${theme.accent('anthropic.com/news/disrupting-AI-espionage')}`);
504
+ console.log(theme.gradient.warm('━'.repeat(50)));
512
505
  exit(0);
513
506
  }
514
507
  /**
@@ -678,14 +671,13 @@ export class InteractiveShell {
678
671
  });
679
672
  }
680
673
  setProcessingStatus(detail) {
681
- this.latestTokenUsage = { used: null, limit: this.latestTokenUsage.limit };
682
674
  this.statusTracker.setBase('Working on your request', {
683
675
  detail: this.describeStatusDetail(detail),
684
676
  tone: 'info',
685
677
  });
686
678
  }
687
679
  describeStatusDetail(detail) {
688
- const parts = detail?.trim() ? [detail.trim()] : [];
680
+ const parts = [detail?.trim() || this.describeModelDetail()];
689
681
  const queued = this.followUpQueue.length;
690
682
  if (queued > 0) {
691
683
  parts.push(`${queued} follow-up${queued === 1 ? '' : 's'} queued`);
@@ -698,18 +690,12 @@ export class InteractiveShell {
698
690
  }
699
691
  refreshContextGauge() {
700
692
  const tokens = getContextWindowTokens(this.sessionState.model);
701
- const normalizedTokens = typeof tokens === 'number' && Number.isFinite(tokens) ? tokens : null;
702
- this.activeContextWindowTokens = normalizedTokens;
703
- if (normalizedTokens !== null) {
704
- this.latestTokenUsage = {
705
- used: this.latestTokenUsage.used,
706
- limit: normalizedTokens,
707
- };
708
- }
693
+ this.activeContextWindowTokens =
694
+ typeof tokens === 'number' && Number.isFinite(tokens) ? tokens : null;
709
695
  }
710
696
  updateContextUsage(percentage) {
711
697
  this.uiAdapter.updateContextUsage(percentage);
712
- this.terminalInput.setContextUsage(percentage, CONTEXT_AUTOCOMPACT_PERCENT);
698
+ this.terminalInput.setContextUsage(percentage);
713
699
  }
714
700
  refreshControlBar() {
715
701
  this.terminalInput.setModeToggles({
@@ -717,8 +703,6 @@ export class InteractiveShell {
717
703
  autoContinueEnabled: this.autoContinueEnabled,
718
704
  verificationHotkey: 'alt+v',
719
705
  autoContinueHotkey: 'alt+c',
720
- thinkingModeLabel: this.thinkingMode,
721
- thinkingHotkey: '/thinking',
722
706
  });
723
707
  this.refreshStatusLine();
724
708
  this.terminalInput.render();
@@ -750,25 +734,6 @@ export class InteractiveShell {
750
734
  // Set main status (tool execution, etc.) - shown when not overridden
751
735
  const statusText = this.formatStatusLine(this.statusLineState);
752
736
  this.terminalInput.setStatusMessage(statusText);
753
- // Surface meta header (elapsed + context usage) above the divider
754
- const elapsedSeconds = this.statusLineState
755
- ? Math.max(0, Math.floor((Date.now() - this.statusLineState.startedAt) / 1000))
756
- : null;
757
- const thinkingMs = display.isSpinnerActive() ? display.getThinkingElapsedMs() : null;
758
- const tokensUsed = this.latestTokenUsage.used;
759
- const tokenLimit = this.latestTokenUsage.limit ?? this.activeContextWindowTokens;
760
- this.terminalInput.setMetaStatus({
761
- elapsedSeconds,
762
- tokensUsed,
763
- tokenLimit,
764
- thinkingMs,
765
- thinkingHasContent: display.isSpinnerActive(),
766
- });
767
- // Keep model/provider visible in the controls bar
768
- this.terminalInput.setModelContext({
769
- model: this.sessionState.model,
770
- provider: this.providerLabel(this.sessionState.provider),
771
- });
772
737
  if (forceRender) {
773
738
  this.terminalInput.render();
774
739
  }
@@ -828,11 +793,13 @@ export class InteractiveShell {
828
793
  this.terminalInput.render();
829
794
  }
830
795
  /**
831
- * Keep submissions out of the transcript to preserve the persistent input area.
832
- * The chat box already holds the user's prompt, so avoid echoing it into output.
796
+ * Log the user's prompt as a visible message in the conversation.
797
+ * This creates a persistent log entry that remains visible during and after streaming.
833
798
  */
834
- logUserPrompt(_text) {
835
- // Intentionally no-op to keep the input area persistent and uncluttered.
799
+ logUserPrompt(text) {
800
+ // Display the user's prompt with the standard prefix
801
+ const prefix = formatUserPrompt();
802
+ display.stream(`\n${prefix}${text}\n\n`);
836
803
  }
837
804
  requestPromptRefresh(force = false) {
838
805
  if (force) {
@@ -860,29 +827,9 @@ export class InteractiveShell {
860
827
  this.uiUpdates.setMode('streaming');
861
828
  this.streamingHeartbeatStart = Date.now();
862
829
  this.streamingHeartbeatFrame = 0;
863
- const initialFrame = STREAMING_SPINNER_FRAMES[this.streamingHeartbeatFrame];
864
- this.streamingStatusLabel = this.buildStreamingStatus(`${initialFrame} ${label}`, 0);
865
- display.updateStreamingStatus(this.streamingStatusLabel);
866
- this.refreshStatusLine(true);
867
- // Periodically refresh the pinned input/status region while streaming so
868
- // elapsed time remains visible without interrupting the scroll region.
869
- this.uiUpdates.startHeartbeat('streaming', {
870
- intervalMs: 1000,
871
- lane: 'heartbeat',
872
- mode: ['streaming', 'processing'],
873
- coalesceKey: 'streaming:heartbeat',
874
- run: () => {
875
- const elapsedSeconds = this.streamingHeartbeatStart
876
- ? Math.max(0, Math.floor((Date.now() - this.streamingHeartbeatStart) / 1000))
877
- : 0;
878
- this.streamingHeartbeatFrame =
879
- (this.streamingHeartbeatFrame + 1) % STREAMING_SPINNER_FRAMES.length;
880
- const frame = STREAMING_SPINNER_FRAMES[this.streamingHeartbeatFrame];
881
- this.streamingStatusLabel = this.buildStreamingStatus(`${frame} ${label}`, elapsedSeconds);
882
- display.updateStreamingStatus(this.streamingStatusLabel);
883
- this.refreshStatusLine(true);
884
- },
885
- });
830
+ // Note: We don't start a heartbeat during streaming anymore
831
+ // because the UI shouldn't be rendering during streaming.
832
+ // The streaming status is shown in the streaming header instead.
886
833
  }
887
834
  stopStreamingHeartbeat() {
888
835
  // Exit global streaming mode - allows UI to render again
@@ -898,28 +845,10 @@ export class InteractiveShell {
898
845
  // Force refresh to update the input area now that streaming has ended
899
846
  this.refreshStatusLine(true);
900
847
  }
901
- buildStreamingStatus(label, elapsedSeconds) {
848
+ buildStreamingStatus(label) {
902
849
  const detail = this.describeModelDetail();
903
- const elapsedLabel = typeof elapsedSeconds === 'number' && elapsedSeconds >= 0
904
- ? theme.ui.muted(this.formatElapsedShort(elapsedSeconds))
905
- : null;
906
- const prefix = theme.info('⏺');
907
- const parts = [label];
908
- if (detail) {
909
- parts.push(theme.ui.muted('·'), detail);
910
- }
911
- if (elapsedLabel) {
912
- parts.push(theme.ui.muted('·'), elapsedLabel);
913
- }
914
- return `${prefix} ${parts.join(' ')}`.trim();
915
- }
916
- formatElapsedShort(seconds) {
917
- if (seconds < 60) {
918
- return `${seconds}s`;
919
- }
920
- const minutes = Math.floor(seconds / 60);
921
- const remaining = seconds % 60;
922
- return remaining > 0 ? `${minutes}m ${remaining}s` : `${minutes}m`;
850
+ const prefix = theme.info('');
851
+ return detail ? `${prefix} ${label} ${theme.ui.muted('·')} ${detail}` : `${prefix} ${label}`;
923
852
  }
924
853
  refreshQueueIndicators() {
925
854
  if (this.isProcessing) {
@@ -1167,6 +1096,17 @@ export class InteractiveShell {
1167
1096
  case '/discover':
1168
1097
  await this.discoverModelsCommand();
1169
1098
  break;
1099
+ case '/memory':
1100
+ this.handleMemoryCommand(input);
1101
+ break;
1102
+ case '/clear':
1103
+ display.clear();
1104
+ this.cachedHistory = [];
1105
+ display.showInfo('Conversation cleared.');
1106
+ break;
1107
+ case '/help':
1108
+ this.showHelp();
1109
+ break;
1170
1110
  default:
1171
1111
  if (!(await this.tryCustomSlashCommand(command, input))) {
1172
1112
  display.showWarning(`Unknown command "${command}".`);
@@ -1475,6 +1415,99 @@ export class InteractiveShell {
1475
1415
  // Display keyboard shortcuts help (Claude Code style)
1476
1416
  display.showSystemMessage(formatShortcutsHelp());
1477
1417
  }
1418
+ handleMemoryCommand(input) {
1419
+ const tokens = input.trim().split(/\s+/).slice(1);
1420
+ const action = (tokens.shift() ?? 'show').toLowerCase();
1421
+ switch (action) {
1422
+ case '':
1423
+ case 'show':
1424
+ case 'list': {
1425
+ this.showMemoryStatus();
1426
+ break;
1427
+ }
1428
+ case 'paths': {
1429
+ this.showMemoryPaths();
1430
+ break;
1431
+ }
1432
+ case 'edit': {
1433
+ const level = (tokens[0] ?? 'project').toLowerCase();
1434
+ this.openMemoryForEdit(level);
1435
+ break;
1436
+ }
1437
+ default:
1438
+ display.showWarning('Usage: /memory [show|paths|edit <user|project>]');
1439
+ break;
1440
+ }
1441
+ }
1442
+ showMemoryStatus() {
1443
+ const memory = loadMemory(this.workingDir);
1444
+ const lines = [];
1445
+ lines.push(theme.bold('Persistent Memory'));
1446
+ lines.push('');
1447
+ if (memory.sources.length === 0) {
1448
+ lines.push(theme.secondary('No memory files found.'));
1449
+ lines.push('');
1450
+ lines.push(`Create ${theme.info('EROSOLAR.md')} in your project to add persistent context.`);
1451
+ lines.push(`Use ${theme.info('/memory edit project')} to create one.`);
1452
+ }
1453
+ else {
1454
+ for (const source of memory.sources) {
1455
+ const levelLabel = source.level === 'enterprise' ? 'Enterprise' :
1456
+ source.level === 'user' ? 'User' : 'Project';
1457
+ const preview = source.content.slice(0, 200).replace(/\n/g, ' ').trim();
1458
+ const truncated = source.content.length > 200 ? '...' : '';
1459
+ lines.push(`${theme.success('●')} ${theme.bold(levelLabel)}: ${source.path}`);
1460
+ lines.push(` ${theme.dim(preview + truncated)}`);
1461
+ lines.push('');
1462
+ }
1463
+ if (memory.importedPaths.length > memory.sources.length) {
1464
+ lines.push(theme.secondary(`Imported ${memory.importedPaths.length - memory.sources.length} additional files via @imports.`));
1465
+ }
1466
+ }
1467
+ display.showSystemMessage(lines.join('\n'));
1468
+ }
1469
+ showMemoryPaths() {
1470
+ const paths = listMemoryPaths(this.workingDir);
1471
+ const lines = [];
1472
+ lines.push(theme.bold('Memory File Locations'));
1473
+ lines.push('');
1474
+ for (const { level, path, exists } of paths) {
1475
+ const icon = exists ? theme.success('✓') : theme.dim('○');
1476
+ const levelLabel = level.charAt(0).toUpperCase() + level.slice(1);
1477
+ lines.push(`${icon} ${levelLabel}: ${path}`);
1478
+ }
1479
+ lines.push('');
1480
+ lines.push(theme.secondary('Create any of these files to add persistent memory.'));
1481
+ lines.push(theme.secondary('Use @path/to/file.md syntax to import other files.'));
1482
+ display.showSystemMessage(lines.join('\n'));
1483
+ }
1484
+ openMemoryForEdit(level) {
1485
+ let targetPath;
1486
+ if (level === 'user') {
1487
+ targetPath = getUserMemoryEditPath();
1488
+ }
1489
+ else if (level === 'project') {
1490
+ targetPath = getDefaultProjectMemoryPath(this.workingDir);
1491
+ }
1492
+ else {
1493
+ display.showWarning('Specify "user" or "project" to edit. Enterprise memory is read-only.');
1494
+ return;
1495
+ }
1496
+ display.showInfo(`Memory file: ${targetPath}`);
1497
+ display.showInfo('Create or edit this file to add persistent context for the AI.');
1498
+ display.showInfo('');
1499
+ display.showInfo('Example EROSOLAR.md content:');
1500
+ display.showInfo('');
1501
+ display.showInfo(theme.dim(`# Project Guidelines
1502
+
1503
+ When working in this codebase:
1504
+ - Follow TypeScript strict mode conventions
1505
+ - Use functional patterns where appropriate
1506
+ - Run tests before committing
1507
+
1508
+ @./docs/coding-standards.md
1509
+ `));
1510
+ }
1478
1511
  showFileChangeSummary() {
1479
1512
  const summary = this._fileChangeTracker.getSummary();
1480
1513
  const changes = this._fileChangeTracker.getAllChanges();
@@ -1517,11 +1550,11 @@ export class InteractiveShell {
1517
1550
  display.showSystemMessage(lines.join('\n'));
1518
1551
  }
1519
1552
  showAlphaZeroMetrics() {
1520
- const summary = this.alphaZeroMetrics.getPerformanceSummary();
1553
+ const summary = this.sessionMetrics.getPerformanceSummary();
1521
1554
  display.showSystemMessage(summary);
1522
1555
  }
1523
1556
  showImprovementSuggestions() {
1524
- const suggestions = this.alphaZeroMetrics.getImprovementSuggestions();
1557
+ const suggestions = this.sessionMetrics.getImprovementSuggestions();
1525
1558
  if (suggestions.length === 0) {
1526
1559
  display.showInfo('No improvement suggestions at this time. Keep using the shell to generate metrics!');
1527
1560
  return;
@@ -1567,9 +1600,7 @@ export class InteractiveShell {
1567
1600
  }
1568
1601
  }
1569
1602
  lines.push(theme.secondary('CLI Flags:'));
1570
- lines.push(' --alpha-zero Enable Alpha Zero 2 RL framework');
1571
1603
  lines.push(' --coding Enable enhanced coding tools');
1572
- lines.push(' --security Enable security research tools');
1573
1604
  lines.push(' --all-plugins Enable all optional plugins');
1574
1605
  display.showSystemMessage(lines.join('\n'));
1575
1606
  }
@@ -1813,75 +1844,6 @@ export class InteractiveShell {
1813
1844
  }
1814
1845
  return `${warning.label}: ${warning.reason}.`;
1815
1846
  }
1816
- buildLaunchCommandPalette() {
1817
- const entries = [];
1818
- const secretsSummary = this.summarizeSecretsForPalette();
1819
- const toolSummary = this.getToolSelectionSummary();
1820
- const autosaveLabel = this.autosaveEnabled ? 'on' : 'off';
1821
- for (const command of this.slashCommands) {
1822
- const entry = {
1823
- command: command.command,
1824
- description: command.description,
1825
- category: command.category ?? 'other',
1826
- };
1827
- switch (command.command) {
1828
- case '/secrets':
1829
- if (secretsSummary.text) {
1830
- entry.description = `${command.description} (${secretsSummary.text})`;
1831
- entry.tone = secretsSummary.tone;
1832
- }
1833
- break;
1834
- case '/tools':
1835
- if (toolSummary) {
1836
- entry.description = `${command.description} (${toolSummary})`;
1837
- }
1838
- break;
1839
- case '/sessions':
1840
- entry.description = `${command.description} (autosave ${autosaveLabel})`;
1841
- break;
1842
- case '/model':
1843
- entry.description = `${command.description} (current: ${this.sessionState.model})`;
1844
- break;
1845
- case '/provider':
1846
- entry.description = `${command.description} (current: ${this.providerLabel(this.sessionState.provider)})`;
1847
- break;
1848
- default:
1849
- break;
1850
- }
1851
- entries.push(entry);
1852
- }
1853
- return entries;
1854
- }
1855
- summarizeSecretsForPalette() {
1856
- const definitions = listSecretDefinitions();
1857
- if (!definitions.length) {
1858
- return { text: null };
1859
- }
1860
- const missing = definitions.filter((definition) => !getSecretValue(definition.id));
1861
- if (missing.length === 0) {
1862
- return { text: 'all configured', tone: 'success' };
1863
- }
1864
- const labels = missing.map((definition) => definition.label ?? definition.id);
1865
- return { text: `missing ${this.formatList(labels)}`, tone: 'warn' };
1866
- }
1867
- getToolSelectionSummary() {
1868
- const toolSettings = loadToolSettings();
1869
- const selection = buildEnabledToolSet(toolSettings);
1870
- const options = getToolToggleOptions();
1871
- if (!options.length) {
1872
- return null;
1873
- }
1874
- const enabledCount = options.filter((option) => selection.has(option.id)).length;
1875
- return `${enabledCount}/${options.length} enabled`;
1876
- }
1877
- formatList(values, maxItems = 3) {
1878
- if (!values.length) {
1879
- return '';
1880
- }
1881
- const shown = values.slice(0, maxItems);
1882
- const suffix = values.length > maxItems ? ', …' : '';
1883
- return `${shown.join(', ')}${suffix}`;
1884
- }
1885
1847
  buildSlashCommandList(header) {
1886
1848
  const lines = [theme.gradient.primary(header), ''];
1887
1849
  for (const command of this.slashCommands) {
@@ -2350,7 +2312,7 @@ export class InteractiveShell {
2350
2312
  this.autosaveIfEnabled();
2351
2313
  // Track metrics with Alpha Zero 2
2352
2314
  const elapsedMs = Date.now() - requestStartTime;
2353
- this.alphaZeroMetrics.recordMessage(elapsedMs);
2315
+ this.sessionMetrics.recordMessage(elapsedMs);
2354
2316
  if (!responseText?.trim()) {
2355
2317
  display.showWarning('The provider returned an empty response. Check your API key/provider selection or retry the prompt.');
2356
2318
  }
@@ -2368,10 +2330,14 @@ export class InteractiveShell {
2368
2330
  this.stopStreamingHeartbeat();
2369
2331
  this.isProcessing = false;
2370
2332
  this.terminalInput.setStreaming(false);
2333
+ this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
2371
2334
  this.uiAdapter.endProcessing('Ready for prompts');
2372
2335
  this.setIdleStatus();
2373
2336
  display.newLine();
2374
2337
  this.updateStatusMessage(null);
2338
+ // Claude Code style: Show unified status bar before prompt
2339
+ // This creates consistent UI between startup and post-streaming
2340
+ this.showUnifiedStatusBar();
2375
2341
  queueMicrotask(() => this.uiUpdates.setMode('idle'));
2376
2342
  // CRITICAL: Ensure readline prompt is active for user input
2377
2343
  // Claude Code style: New prompt naturally appears at bottom
@@ -2448,14 +2414,13 @@ When truly finished with ALL tasks, explicitly state "TASK_FULLY_COMPLETE".`;
2448
2414
  try {
2449
2415
  // Send the request and capture the response (streaming disabled)
2450
2416
  display.showThinking('Responding...');
2451
- this.refreshStatusLine(true);
2452
2417
  const response = await agent.send(currentPrompt, true);
2453
2418
  await this.awaitPendingCleanup();
2454
2419
  this.captureHistorySnapshot();
2455
2420
  this.autosaveIfEnabled();
2456
2421
  // Track metrics
2457
2422
  const elapsedMs = Date.now() - overallStartTime;
2458
- this.alphaZeroMetrics.recordMessage(elapsedMs);
2423
+ this.sessionMetrics.recordMessage(elapsedMs);
2459
2424
  if (!response?.trim()) {
2460
2425
  display.showWarning('Model returned an empty response. Retrying this iteration...');
2461
2426
  consecutiveNoProgress++;
@@ -2592,6 +2557,7 @@ What's the next action?`;
2592
2557
  this.stopStreamingHeartbeat();
2593
2558
  this.isProcessing = false;
2594
2559
  this.terminalInput.setStreaming(false);
2560
+ this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
2595
2561
  this.uiAdapter.endProcessing('Ready for prompts');
2596
2562
  this.setIdleStatus();
2597
2563
  this.updateStatusMessage(null);
@@ -2948,10 +2914,8 @@ What's the next action?`;
2948
2914
  try {
2949
2915
  // Send the error to the agent for fixing
2950
2916
  display.showThinking('Analyzing build errors');
2951
- this.refreshStatusLine(true);
2952
2917
  const response = await this.agent.send(prompt, true);
2953
2918
  display.stopThinking();
2954
- this.refreshStatusLine(true);
2955
2919
  if (response) {
2956
2920
  display.showAssistantMessage(response, { isFinal: true });
2957
2921
  }
@@ -3001,16 +2965,18 @@ What's the next action?`;
3001
2965
  display.showAssistantMessage(finalContent, enriched);
3002
2966
  }
3003
2967
  }
3004
- // Status shown in mode controls bar - no separate status line needed
2968
+ // Show status line at end (Claude Code style: "• Context X% used • Ready for prompts (2s)")
3005
2969
  display.stopThinking();
3006
- // Update context usage for mode controls display
2970
+ // Calculate context usage
2971
+ let contextInfo;
3007
2972
  if (enriched.contextWindowTokens && metadata.usage) {
3008
2973
  const total = this.totalTokens(metadata.usage);
3009
2974
  if (total && total > 0) {
3010
2975
  const percentage = Math.round((total / enriched.contextWindowTokens) * 100);
3011
- this.updateContextUsage(percentage);
2976
+ contextInfo = { percentage, tokens: total };
3012
2977
  }
3013
2978
  }
2979
+ display.showStatusLine('Ready for prompts', enriched.elapsedMs, contextInfo);
3014
2980
  // Auto-verify changes: build first (catches type errors), then tests
3015
2981
  void this.enforceAutoBuild('final-response');
3016
2982
  void this.enforceAutoTests('final-response');
@@ -3080,6 +3046,7 @@ What's the next action?`;
3080
3046
  this.stopStreamingHeartbeat();
3081
3047
  this.updateStatusMessage(null);
3082
3048
  this.terminalInput.setStreaming(false);
3049
+ this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
3083
3050
  this.terminalInput.render();
3084
3051
  },
3085
3052
  onVerificationNeeded: () => {
@@ -3116,6 +3083,7 @@ What's the next action?`;
3116
3083
  resetChatBoxAfterModelSwap() {
3117
3084
  this.updateStatusMessage(null);
3118
3085
  this.terminalInput.setStreaming(false);
3086
+ this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
3119
3087
  this.terminalInput.render();
3120
3088
  this.ensureReadlineReady();
3121
3089
  }
@@ -3180,14 +3148,9 @@ What's the next action?`;
3180
3148
  return null;
3181
3149
  }
3182
3150
  const usageRatio = total / windowTokens;
3183
- this.latestTokenUsage = {
3184
- used: total,
3185
- limit: windowTokens,
3186
- };
3187
3151
  // Always update context usage in the UI
3188
3152
  const percentUsed = Math.round(usageRatio * 100);
3189
3153
  this.updateContextUsage(percentUsed);
3190
- this.refreshStatusLine(true);
3191
3154
  if (usageRatio < CONTEXT_USAGE_THRESHOLD) {
3192
3155
  return null;
3193
3156
  }