erosolar-cli 1.7.303 → 1.7.305

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 (323) hide show
  1. package/README.md +24 -148
  2. package/dist/bin/erosolar.js +3 -1
  3. package/dist/bin/erosolar.js.map +1 -1
  4. package/dist/capabilities/agentSpawningCapability.d.ts.map +1 -1
  5. package/dist/capabilities/agentSpawningCapability.js +56 -31
  6. package/dist/capabilities/agentSpawningCapability.js.map +1 -1
  7. package/dist/contracts/agent-schemas.json +0 -15
  8. package/dist/contracts/tools.schema.json +0 -9
  9. package/dist/core/agent.d.ts +2 -2
  10. package/dist/core/agent.d.ts.map +1 -1
  11. package/dist/core/agent.js.map +1 -1
  12. package/dist/core/customCommands.d.ts +1 -0
  13. package/dist/core/customCommands.d.ts.map +1 -1
  14. package/dist/core/customCommands.js +3 -0
  15. package/dist/core/customCommands.js.map +1 -1
  16. package/dist/core/hooks.d.ts +113 -0
  17. package/dist/core/hooks.d.ts.map +1 -0
  18. package/dist/core/hooks.js +267 -0
  19. package/dist/core/hooks.js.map +1 -0
  20. package/dist/core/metricsTracker.d.ts +122 -0
  21. package/dist/core/metricsTracker.d.ts.map +1 -0
  22. package/dist/{alpha-zero → core}/metricsTracker.js +2 -5
  23. package/dist/core/metricsTracker.js.map +1 -0
  24. package/dist/core/securityAssessment.d.ts +91 -0
  25. package/dist/core/securityAssessment.d.ts.map +1 -0
  26. package/dist/core/securityAssessment.js +580 -0
  27. package/dist/core/securityAssessment.js.map +1 -0
  28. package/dist/core/toolPreconditions.d.ts.map +1 -1
  29. package/dist/core/toolPreconditions.js +0 -14
  30. package/dist/core/toolPreconditions.js.map +1 -1
  31. package/dist/core/toolRuntime.d.ts +22 -1
  32. package/dist/core/toolRuntime.d.ts.map +1 -1
  33. package/dist/core/toolRuntime.js +0 -5
  34. package/dist/core/toolRuntime.js.map +1 -1
  35. package/dist/core/toolValidation.d.ts.map +1 -1
  36. package/dist/core/toolValidation.js +14 -3
  37. package/dist/core/toolValidation.js.map +1 -1
  38. package/dist/core/validationRunner.d.ts +1 -3
  39. package/dist/core/validationRunner.d.ts.map +1 -1
  40. package/dist/core/validationRunner.js.map +1 -1
  41. package/dist/core/verification.d.ts +137 -0
  42. package/dist/core/verification.d.ts.map +1 -0
  43. package/dist/core/verification.js +323 -0
  44. package/dist/core/verification.js.map +1 -0
  45. package/dist/headless/headlessApp.d.ts.map +1 -1
  46. package/dist/headless/headlessApp.js +21 -0
  47. package/dist/headless/headlessApp.js.map +1 -1
  48. package/dist/mcp/sseClient.d.ts.map +1 -1
  49. package/dist/mcp/sseClient.js +9 -18
  50. package/dist/mcp/sseClient.js.map +1 -1
  51. package/dist/plugins/tools/build/buildPlugin.d.ts +0 -6
  52. package/dist/plugins/tools/build/buildPlugin.d.ts.map +1 -1
  53. package/dist/plugins/tools/build/buildPlugin.js +4 -10
  54. package/dist/plugins/tools/build/buildPlugin.js.map +1 -1
  55. package/dist/plugins/tools/nodeDefaults.d.ts.map +1 -1
  56. package/dist/plugins/tools/nodeDefaults.js +0 -2
  57. package/dist/plugins/tools/nodeDefaults.js.map +1 -1
  58. package/dist/runtime/agentSession.d.ts +2 -2
  59. package/dist/runtime/agentSession.d.ts.map +1 -1
  60. package/dist/runtime/agentSession.js +2 -2
  61. package/dist/runtime/agentSession.js.map +1 -1
  62. package/dist/shell/interactiveShell.d.ts +16 -7
  63. package/dist/shell/interactiveShell.d.ts.map +1 -1
  64. package/dist/shell/interactiveShell.js +225 -163
  65. package/dist/shell/interactiveShell.js.map +1 -1
  66. package/dist/shell/shellApp.d.ts +2 -0
  67. package/dist/shell/shellApp.d.ts.map +1 -1
  68. package/dist/shell/shellApp.js +40 -9
  69. package/dist/shell/shellApp.js.map +1 -1
  70. package/dist/shell/systemPrompt.d.ts.map +1 -1
  71. package/dist/shell/systemPrompt.js +1 -4
  72. package/dist/shell/systemPrompt.js.map +1 -1
  73. package/dist/shell/terminalInput.d.ts +124 -126
  74. package/dist/shell/terminalInput.d.ts.map +1 -1
  75. package/dist/shell/terminalInput.js +548 -638
  76. package/dist/shell/terminalInput.js.map +1 -1
  77. package/dist/shell/terminalInputAdapter.d.ts +56 -20
  78. package/dist/shell/terminalInputAdapter.d.ts.map +1 -1
  79. package/dist/shell/terminalInputAdapter.js +66 -30
  80. package/dist/shell/terminalInputAdapter.js.map +1 -1
  81. package/dist/subagents/agentConfig.d.ts +27 -0
  82. package/dist/subagents/agentConfig.d.ts.map +1 -0
  83. package/dist/subagents/agentConfig.js +89 -0
  84. package/dist/subagents/agentConfig.js.map +1 -0
  85. package/dist/subagents/agentRegistry.d.ts +33 -0
  86. package/dist/subagents/agentRegistry.d.ts.map +1 -0
  87. package/dist/subagents/agentRegistry.js +162 -0
  88. package/dist/subagents/agentRegistry.js.map +1 -0
  89. package/dist/subagents/taskRunner.d.ts +7 -1
  90. package/dist/subagents/taskRunner.d.ts.map +1 -1
  91. package/dist/subagents/taskRunner.js +180 -47
  92. package/dist/subagents/taskRunner.js.map +1 -1
  93. package/dist/ui/ShellUIAdapter.d.ts.map +1 -1
  94. package/dist/ui/ShellUIAdapter.js +13 -12
  95. package/dist/ui/ShellUIAdapter.js.map +1 -1
  96. package/dist/ui/display.d.ts +24 -45
  97. package/dist/ui/display.d.ts.map +1 -1
  98. package/dist/ui/display.js +140 -259
  99. package/dist/ui/display.js.map +1 -1
  100. package/dist/ui/theme.d.ts.map +1 -1
  101. package/dist/ui/theme.js +6 -8
  102. package/dist/ui/theme.js.map +1 -1
  103. package/dist/ui/toolDisplay.d.ts +0 -158
  104. package/dist/ui/toolDisplay.d.ts.map +1 -1
  105. package/dist/ui/toolDisplay.js +0 -348
  106. package/dist/ui/toolDisplay.js.map +1 -1
  107. package/dist/ui/unified/layout.d.ts +1 -0
  108. package/dist/ui/unified/layout.d.ts.map +1 -1
  109. package/dist/ui/unified/layout.js +15 -25
  110. package/dist/ui/unified/layout.js.map +1 -1
  111. package/dist/utils/frontmatter.d.ts +10 -0
  112. package/dist/utils/frontmatter.d.ts.map +1 -0
  113. package/dist/utils/frontmatter.js +78 -0
  114. package/dist/utils/frontmatter.js.map +1 -0
  115. package/package.json +4 -4
  116. package/dist/alpha-zero/agentWrapper.d.ts +0 -84
  117. package/dist/alpha-zero/agentWrapper.d.ts.map +0 -1
  118. package/dist/alpha-zero/agentWrapper.js +0 -171
  119. package/dist/alpha-zero/agentWrapper.js.map +0 -1
  120. package/dist/alpha-zero/codeEvaluator.d.ts +0 -25
  121. package/dist/alpha-zero/codeEvaluator.d.ts.map +0 -1
  122. package/dist/alpha-zero/codeEvaluator.js +0 -273
  123. package/dist/alpha-zero/codeEvaluator.js.map +0 -1
  124. package/dist/alpha-zero/competitiveRunner.d.ts +0 -66
  125. package/dist/alpha-zero/competitiveRunner.d.ts.map +0 -1
  126. package/dist/alpha-zero/competitiveRunner.js +0 -224
  127. package/dist/alpha-zero/competitiveRunner.js.map +0 -1
  128. package/dist/alpha-zero/index.d.ts +0 -67
  129. package/dist/alpha-zero/index.d.ts.map +0 -1
  130. package/dist/alpha-zero/index.js +0 -99
  131. package/dist/alpha-zero/index.js.map +0 -1
  132. package/dist/alpha-zero/introspection.d.ts +0 -128
  133. package/dist/alpha-zero/introspection.d.ts.map +0 -1
  134. package/dist/alpha-zero/introspection.js +0 -300
  135. package/dist/alpha-zero/introspection.js.map +0 -1
  136. package/dist/alpha-zero/metricsTracker.d.ts +0 -71
  137. package/dist/alpha-zero/metricsTracker.d.ts.map +0 -1
  138. package/dist/alpha-zero/metricsTracker.js.map +0 -1
  139. package/dist/alpha-zero/security/core.d.ts +0 -125
  140. package/dist/alpha-zero/security/core.d.ts.map +0 -1
  141. package/dist/alpha-zero/security/core.js +0 -271
  142. package/dist/alpha-zero/security/core.js.map +0 -1
  143. package/dist/alpha-zero/security/google.d.ts +0 -125
  144. package/dist/alpha-zero/security/google.d.ts.map +0 -1
  145. package/dist/alpha-zero/security/google.js +0 -311
  146. package/dist/alpha-zero/security/google.js.map +0 -1
  147. package/dist/alpha-zero/security/googleLoader.d.ts +0 -17
  148. package/dist/alpha-zero/security/googleLoader.d.ts.map +0 -1
  149. package/dist/alpha-zero/security/googleLoader.js +0 -41
  150. package/dist/alpha-zero/security/googleLoader.js.map +0 -1
  151. package/dist/alpha-zero/security/index.d.ts +0 -29
  152. package/dist/alpha-zero/security/index.d.ts.map +0 -1
  153. package/dist/alpha-zero/security/index.js +0 -32
  154. package/dist/alpha-zero/security/index.js.map +0 -1
  155. package/dist/alpha-zero/security/simulation.d.ts +0 -124
  156. package/dist/alpha-zero/security/simulation.d.ts.map +0 -1
  157. package/dist/alpha-zero/security/simulation.js +0 -277
  158. package/dist/alpha-zero/security/simulation.js.map +0 -1
  159. package/dist/alpha-zero/selfModification.d.ts +0 -109
  160. package/dist/alpha-zero/selfModification.d.ts.map +0 -1
  161. package/dist/alpha-zero/selfModification.js +0 -233
  162. package/dist/alpha-zero/selfModification.js.map +0 -1
  163. package/dist/alpha-zero/types.d.ts +0 -170
  164. package/dist/alpha-zero/types.d.ts.map +0 -1
  165. package/dist/alpha-zero/types.js +0 -31
  166. package/dist/alpha-zero/types.js.map +0 -1
  167. package/dist/capabilities/securityTestingCapability.d.ts +0 -13
  168. package/dist/capabilities/securityTestingCapability.d.ts.map +0 -1
  169. package/dist/capabilities/securityTestingCapability.js +0 -25
  170. package/dist/capabilities/securityTestingCapability.js.map +0 -1
  171. package/dist/core/aiFlowOptimizer.d.ts +0 -26
  172. package/dist/core/aiFlowOptimizer.d.ts.map +0 -1
  173. package/dist/core/aiFlowOptimizer.js +0 -31
  174. package/dist/core/aiFlowOptimizer.js.map +0 -1
  175. package/dist/core/aiOptimizationEngine.d.ts +0 -158
  176. package/dist/core/aiOptimizationEngine.d.ts.map +0 -1
  177. package/dist/core/aiOptimizationEngine.js +0 -428
  178. package/dist/core/aiOptimizationEngine.js.map +0 -1
  179. package/dist/core/aiOptimizationIntegration.d.ts +0 -93
  180. package/dist/core/aiOptimizationIntegration.d.ts.map +0 -1
  181. package/dist/core/aiOptimizationIntegration.js +0 -250
  182. package/dist/core/aiOptimizationIntegration.js.map +0 -1
  183. package/dist/core/enhancedErrorRecovery.d.ts +0 -100
  184. package/dist/core/enhancedErrorRecovery.d.ts.map +0 -1
  185. package/dist/core/enhancedErrorRecovery.js +0 -345
  186. package/dist/core/enhancedErrorRecovery.js.map +0 -1
  187. package/dist/core/hooksSystem.d.ts +0 -65
  188. package/dist/core/hooksSystem.d.ts.map +0 -1
  189. package/dist/core/hooksSystem.js +0 -273
  190. package/dist/core/hooksSystem.js.map +0 -1
  191. package/dist/core/memorySystem.d.ts +0 -48
  192. package/dist/core/memorySystem.d.ts.map +0 -1
  193. package/dist/core/memorySystem.js +0 -271
  194. package/dist/core/memorySystem.js.map +0 -1
  195. package/dist/core/unified/errors.d.ts +0 -189
  196. package/dist/core/unified/errors.d.ts.map +0 -1
  197. package/dist/core/unified/errors.js +0 -497
  198. package/dist/core/unified/errors.js.map +0 -1
  199. package/dist/core/unified/index.d.ts +0 -19
  200. package/dist/core/unified/index.d.ts.map +0 -1
  201. package/dist/core/unified/index.js +0 -68
  202. package/dist/core/unified/index.js.map +0 -1
  203. package/dist/core/unified/schema.d.ts +0 -101
  204. package/dist/core/unified/schema.d.ts.map +0 -1
  205. package/dist/core/unified/schema.js +0 -350
  206. package/dist/core/unified/schema.js.map +0 -1
  207. package/dist/core/unified/toolRuntime.d.ts +0 -179
  208. package/dist/core/unified/toolRuntime.d.ts.map +0 -1
  209. package/dist/core/unified/toolRuntime.js +0 -517
  210. package/dist/core/unified/toolRuntime.js.map +0 -1
  211. package/dist/core/unified/tools.d.ts +0 -127
  212. package/dist/core/unified/tools.d.ts.map +0 -1
  213. package/dist/core/unified/tools.js +0 -1333
  214. package/dist/core/unified/tools.js.map +0 -1
  215. package/dist/core/unified/types.d.ts +0 -352
  216. package/dist/core/unified/types.d.ts.map +0 -1
  217. package/dist/core/unified/types.js +0 -12
  218. package/dist/core/unified/types.js.map +0 -1
  219. package/dist/core/unified/version.d.ts +0 -209
  220. package/dist/core/unified/version.d.ts.map +0 -1
  221. package/dist/core/unified/version.js +0 -454
  222. package/dist/core/unified/version.js.map +0 -1
  223. package/dist/plugins/tools/security/securityPlugin.d.ts +0 -3
  224. package/dist/plugins/tools/security/securityPlugin.d.ts.map +0 -1
  225. package/dist/plugins/tools/security/securityPlugin.js +0 -12
  226. package/dist/plugins/tools/security/securityPlugin.js.map +0 -1
  227. package/dist/security/active-stack-security.d.ts +0 -112
  228. package/dist/security/active-stack-security.d.ts.map +0 -1
  229. package/dist/security/active-stack-security.js +0 -296
  230. package/dist/security/active-stack-security.js.map +0 -1
  231. package/dist/security/advanced-persistence-research.d.ts +0 -92
  232. package/dist/security/advanced-persistence-research.d.ts.map +0 -1
  233. package/dist/security/advanced-persistence-research.js +0 -195
  234. package/dist/security/advanced-persistence-research.js.map +0 -1
  235. package/dist/security/advanced-targeting.d.ts +0 -119
  236. package/dist/security/advanced-targeting.d.ts.map +0 -1
  237. package/dist/security/advanced-targeting.js +0 -233
  238. package/dist/security/advanced-targeting.js.map +0 -1
  239. package/dist/security/assessment/vulnerabilityAssessment.d.ts +0 -104
  240. package/dist/security/assessment/vulnerabilityAssessment.d.ts.map +0 -1
  241. package/dist/security/assessment/vulnerabilityAssessment.js +0 -315
  242. package/dist/security/assessment/vulnerabilityAssessment.js.map +0 -1
  243. package/dist/security/authorization/securityAuthorization.d.ts +0 -88
  244. package/dist/security/authorization/securityAuthorization.d.ts.map +0 -1
  245. package/dist/security/authorization/securityAuthorization.js +0 -172
  246. package/dist/security/authorization/securityAuthorization.js.map +0 -1
  247. package/dist/security/comprehensive-targeting.d.ts +0 -85
  248. package/dist/security/comprehensive-targeting.d.ts.map +0 -1
  249. package/dist/security/comprehensive-targeting.js +0 -438
  250. package/dist/security/comprehensive-targeting.js.map +0 -1
  251. package/dist/security/global-security-integration.d.ts +0 -91
  252. package/dist/security/global-security-integration.d.ts.map +0 -1
  253. package/dist/security/global-security-integration.js +0 -218
  254. package/dist/security/global-security-integration.js.map +0 -1
  255. package/dist/security/index.d.ts +0 -38
  256. package/dist/security/index.d.ts.map +0 -1
  257. package/dist/security/index.js +0 -47
  258. package/dist/security/index.js.map +0 -1
  259. package/dist/security/persistence-analyzer.d.ts +0 -56
  260. package/dist/security/persistence-analyzer.d.ts.map +0 -1
  261. package/dist/security/persistence-analyzer.js +0 -187
  262. package/dist/security/persistence-analyzer.js.map +0 -1
  263. package/dist/security/persistence-cli.d.ts +0 -36
  264. package/dist/security/persistence-cli.d.ts.map +0 -1
  265. package/dist/security/persistence-cli.js +0 -160
  266. package/dist/security/persistence-cli.js.map +0 -1
  267. package/dist/security/persistence-research.d.ts +0 -92
  268. package/dist/security/persistence-research.d.ts.map +0 -1
  269. package/dist/security/persistence-research.js +0 -364
  270. package/dist/security/persistence-research.js.map +0 -1
  271. package/dist/security/research/persistenceResearch.d.ts +0 -97
  272. package/dist/security/research/persistenceResearch.d.ts.map +0 -1
  273. package/dist/security/research/persistenceResearch.js +0 -282
  274. package/dist/security/research/persistenceResearch.js.map +0 -1
  275. package/dist/security/security-integration.d.ts +0 -74
  276. package/dist/security/security-integration.d.ts.map +0 -1
  277. package/dist/security/security-integration.js +0 -137
  278. package/dist/security/security-integration.js.map +0 -1
  279. package/dist/security/security-testing-framework.d.ts +0 -112
  280. package/dist/security/security-testing-framework.d.ts.map +0 -1
  281. package/dist/security/security-testing-framework.js +0 -364
  282. package/dist/security/security-testing-framework.js.map +0 -1
  283. package/dist/security/simulation/attackSimulation.d.ts +0 -93
  284. package/dist/security/simulation/attackSimulation.d.ts.map +0 -1
  285. package/dist/security/simulation/attackSimulation.js +0 -341
  286. package/dist/security/simulation/attackSimulation.js.map +0 -1
  287. package/dist/security/strategic-operations.d.ts +0 -100
  288. package/dist/security/strategic-operations.d.ts.map +0 -1
  289. package/dist/security/strategic-operations.js +0 -276
  290. package/dist/security/strategic-operations.js.map +0 -1
  291. package/dist/security/tool-security-wrapper.d.ts +0 -58
  292. package/dist/security/tool-security-wrapper.d.ts.map +0 -1
  293. package/dist/security/tool-security-wrapper.js +0 -156
  294. package/dist/security/tool-security-wrapper.js.map +0 -1
  295. package/dist/shell/claudeCodeStreamHandler.d.ts +0 -145
  296. package/dist/shell/claudeCodeStreamHandler.d.ts.map +0 -1
  297. package/dist/shell/claudeCodeStreamHandler.js +0 -322
  298. package/dist/shell/claudeCodeStreamHandler.js.map +0 -1
  299. package/dist/shell/inputQueueManager.d.ts +0 -144
  300. package/dist/shell/inputQueueManager.d.ts.map +0 -1
  301. package/dist/shell/inputQueueManager.js +0 -290
  302. package/dist/shell/inputQueueManager.js.map +0 -1
  303. package/dist/shell/metricsTracker.d.ts +0 -60
  304. package/dist/shell/metricsTracker.d.ts.map +0 -1
  305. package/dist/shell/metricsTracker.js +0 -119
  306. package/dist/shell/metricsTracker.js.map +0 -1
  307. package/dist/shell/streamingOutputManager.d.ts +0 -115
  308. package/dist/shell/streamingOutputManager.d.ts.map +0 -1
  309. package/dist/shell/streamingOutputManager.js +0 -225
  310. package/dist/shell/streamingOutputManager.js.map +0 -1
  311. package/dist/tools/securityTools.d.ts +0 -22
  312. package/dist/tools/securityTools.d.ts.map +0 -1
  313. package/dist/tools/securityTools.js +0 -448
  314. package/dist/tools/securityTools.js.map +0 -1
  315. package/dist/ui/persistentPrompt.d.ts +0 -50
  316. package/dist/ui/persistentPrompt.d.ts.map +0 -1
  317. package/dist/ui/persistentPrompt.js +0 -92
  318. package/dist/ui/persistentPrompt.js.map +0 -1
  319. package/dist/ui/terminalUISchema.d.ts +0 -195
  320. package/dist/ui/terminalUISchema.d.ts.map +0 -1
  321. package/dist/ui/terminalUISchema.js +0 -113
  322. package/dist/ui/terminalUISchema.js.map +0 -1
  323. package/scripts/deploy-security-capabilities.js +0 -178
@@ -2,7 +2,7 @@ import { stdin as input, stdout as output, exit } from 'node:process';
2
2
  import { exec } from 'node:child_process';
3
3
  import { promisify } from 'node:util';
4
4
  import { display } from '../ui/display.js';
5
- import { theme, formatUserPrompt } from '../ui/theme.js';
5
+ import { theme } from '../ui/theme.js';
6
6
  import { getContextWindowTokens } from '../core/contextWindow.js';
7
7
  import { ensureSecretForProvider, getSecretDefinitionForProvider, getSecretValue, listSecretDefinitions, maskSecret, setSecretValue, } from '../core/secretStore.js';
8
8
  import { saveActiveProfilePreference, saveModelPreference, loadToolSettings, saveToolSettings, clearToolSettings, clearActiveProfilePreference, loadSessionPreferences, saveSessionPreferences, } from '../core/preferences.js';
@@ -19,10 +19,10 @@ 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 './metricsTracker.js';
22
+ import { MetricsTracker } from '../core/metricsTracker.js';
23
23
  import { listAvailablePlugins } from '../plugins/index.js';
24
- import { loadMemory, listMemoryPaths, getDefaultProjectMemoryPath, getUserMemoryEditPath, } from '../core/memorySystem.js';
25
24
  import { TerminalInputAdapter } from './terminalInputAdapter.js';
25
+ import { renderSessionFrame } from '../ui/unified/layout.js';
26
26
  import { isUpdateInProgress } from './updateManager.js';
27
27
  import { writeLock } from '../ui/writeLock.js';
28
28
  import { enterStreamingMode, exitStreamingMode } from '../ui/globalWriteLock.js';
@@ -35,6 +35,7 @@ const DROPDOWN_COLORS = [
35
35
  theme.success,
36
36
  theme.warning,
37
37
  ];
38
+ const STREAMING_SPINNER_FRAMES = ['◐', '◓', '◑', '◒'];
38
39
  // Load MODEL_PRESETS from centralized schema
39
40
  const MODEL_PRESETS = getModels().map((model) => ({
40
41
  id: model.id,
@@ -49,11 +50,13 @@ const MODEL_PRESETS = getModels().map((model) => ({
49
50
  const BASE_SLASH_COMMANDS = getSlashCommands().map((cmd) => ({
50
51
  command: cmd.command,
51
52
  description: cmd.description,
53
+ category: cmd.category,
52
54
  }));
53
55
  // Load PROVIDER_LABELS from centralized schema
54
56
  const PROVIDER_LABELS = Object.fromEntries(getProviders().map((provider) => [provider.id, provider.label]));
55
57
  // Allow enough time for paste detection to kick in before flushing buffered lines
56
58
  const CONTEXT_USAGE_THRESHOLD = 0.9;
59
+ const CONTEXT_AUTOCOMPACT_PERCENT = Math.round(CONTEXT_USAGE_THRESHOLD * 100);
57
60
  const CONTEXT_RECENT_MESSAGE_COUNT = 12;
58
61
  const CONTEXT_CLEANUP_CHARS_PER_CHUNK = 6000;
59
62
  const CONTEXT_CLEANUP_MAX_OUTPUT_TOKENS = 800;
@@ -94,11 +97,12 @@ export class InteractiveShell {
94
97
  uiAdapter;
95
98
  uiUpdates;
96
99
  _fileChangeTracker = new FileChangeTracker(); // Reserved for future file tracking features
97
- sessionMetrics; // Session performance tracking
100
+ alphaZeroMetrics; // Alpha Zero 2 performance tracking
98
101
  statusSubscription = null;
99
102
  followUpQueue = [];
100
103
  isDrainingQueue = false;
101
104
  activeContextWindowTokens = null;
105
+ latestTokenUsage = { used: null, limit: null };
102
106
  sessionPreferences;
103
107
  autosaveEnabled;
104
108
  autoContinueEnabled;
@@ -129,6 +133,8 @@ export class InteractiveShell {
129
133
  statusLineState = null;
130
134
  statusMessageOverride = null;
131
135
  promptRefreshTimer = null;
136
+ launchPaletteShown = false;
137
+ version;
132
138
  constructor(config) {
133
139
  this.profile = config.profile;
134
140
  this.profileLabel = config.profileLabel;
@@ -142,6 +148,7 @@ export class InteractiveShell {
142
148
  this.autoContinueEnabled = this.sessionPreferences.autoContinue;
143
149
  this.sessionRestoreConfig = config.sessionRestore ?? { mode: 'none' };
144
150
  this._enabledPlugins = config.enabledPlugins ?? [];
151
+ this.version = config.version ?? '0.0.0';
145
152
  this.initializeSessionHistory();
146
153
  this.sessionState = {
147
154
  provider: config.initialModel.provider,
@@ -162,6 +169,7 @@ export class InteractiveShell {
162
169
  this.slashCommands.push({
163
170
  command: '/agents',
164
171
  description: 'Select the default agent profile (applies on next launch)',
172
+ category: 'configuration',
165
173
  });
166
174
  }
167
175
  this.customCommands = loadCustomSlashCommands();
@@ -170,18 +178,21 @@ export class InteractiveShell {
170
178
  this.slashCommands.push({
171
179
  command: custom.command,
172
180
  description: `${custom.description} (custom)`,
181
+ category: custom.category ?? 'other',
173
182
  });
174
183
  }
175
184
  if (!this.slashCommands.some((cmd) => cmd.command === '/exit')) {
176
185
  this.slashCommands.push({
177
186
  command: '/exit',
178
187
  description: 'Quit the CLI immediately',
188
+ category: 'other',
179
189
  });
180
190
  }
181
191
  // Add /plugins command
182
192
  this.slashCommands.push({
183
193
  command: '/plugins',
184
194
  description: 'Show available and loaded plugins',
195
+ category: 'configuration',
185
196
  });
186
197
  this.statusTracker = config.statusTracker;
187
198
  this.ui = config.ui;
@@ -214,19 +225,22 @@ export class InteractiveShell {
214
225
  onToggleVerify: () => this.toggleVerificationMode(),
215
226
  onToggleAutoContinue: () => this.toggleAutoContinueMode(),
216
227
  });
217
- // Register output interceptor for cursor positioning during streaming
218
- this.terminalInput.registerOutputInterceptor(display);
219
- // Set banner content to be written during unified UI initialization
220
- this.terminalInput.setBannerContent(display.getBannerContent());
221
- // Initialize unified UI - clears screen, sets up scroll region, writes banner,
222
- // and renders input area at bottom
223
- this.terminalInput.initializeUnifiedUI();
224
228
  // Initialize Alpha Zero 2 metrics tracking
225
- this.sessionMetrics = new MetricsTracker(`${this.profile}-${Date.now()}`);
229
+ this.alphaZeroMetrics = new MetricsTracker(`${this.profile}-${Date.now()}`);
226
230
  this.setupStatusTracking();
227
231
  this.refreshContextGauge();
232
+ // Start terminal input (sets up handlers)
228
233
  this.terminalInput.start();
234
+ // Enable scroll region (Claude Code method)
235
+ // This pins chat box below scroll region
236
+ this.terminalInput.setContentRow(1);
237
+ this.terminalInput.enableScrollRegion();
238
+ // Render chat box at pinned position
229
239
  this.refreshControlBar();
240
+ this.terminalInput.forceRender();
241
+ // Stream banner in scroll region
242
+ const banner = this.buildBanner();
243
+ this.terminalInput.streamContent('\n' + banner + '\n\n');
230
244
  this.rebuildAgent();
231
245
  this.setupHandlers();
232
246
  this.refreshBannerSessionInfo();
@@ -278,9 +292,15 @@ export class InteractiveShell {
278
292
  await this.processInputBlock(initialPrompt);
279
293
  return;
280
294
  }
295
+ this.showLaunchCommandPalette();
281
296
  // Ensure the terminal input is visible
282
297
  this.terminalInput.render();
283
298
  }
299
+ showLaunchCommandPalette() {
300
+ // Disabled: Quick commands palette takes up too much space
301
+ // Users can type /help to see available commands
302
+ this.launchPaletteShown = true;
303
+ }
284
304
  /**
285
305
  * TerminalInputAdapter submit handler
286
306
  */
@@ -294,9 +314,8 @@ export class InteractiveShell {
294
314
  this.handleInputChange('');
295
315
  return;
296
316
  }
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);
317
+ // DON'T clear the input here - keep it visible while streaming.
318
+ // The input will be cleared after streaming completes in the finally block.
300
319
  this.logUserPrompt(approved);
301
320
  void this.processInputBlock(approved).catch((err) => {
302
321
  display.showError(err instanceof Error ? err.message : String(err), err);
@@ -498,11 +517,9 @@ export class InteractiveShell {
498
517
  // Dispose unified UI adapter
499
518
  this.uiAdapter.dispose();
500
519
  display.newLine();
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)));
520
+ console.log(theme.ui.muted(''.repeat(44)));
521
+ console.log(theme.ui.muted(' Goodbye! · support@ero.solar'));
522
+ console.log(theme.ui.muted(''.repeat(44)));
506
523
  exit(0);
507
524
  }
508
525
  /**
@@ -672,13 +689,14 @@ export class InteractiveShell {
672
689
  });
673
690
  }
674
691
  setProcessingStatus(detail) {
692
+ this.latestTokenUsage = { used: null, limit: this.latestTokenUsage.limit };
675
693
  this.statusTracker.setBase('Working on your request', {
676
694
  detail: this.describeStatusDetail(detail),
677
695
  tone: 'info',
678
696
  });
679
697
  }
680
698
  describeStatusDetail(detail) {
681
- const parts = [detail?.trim() || this.describeModelDetail()];
699
+ const parts = detail?.trim() ? [detail.trim()] : [];
682
700
  const queued = this.followUpQueue.length;
683
701
  if (queued > 0) {
684
702
  parts.push(`${queued} follow-up${queued === 1 ? '' : 's'} queued`);
@@ -691,12 +709,18 @@ export class InteractiveShell {
691
709
  }
692
710
  refreshContextGauge() {
693
711
  const tokens = getContextWindowTokens(this.sessionState.model);
694
- this.activeContextWindowTokens =
695
- typeof tokens === 'number' && Number.isFinite(tokens) ? tokens : null;
712
+ const normalizedTokens = typeof tokens === 'number' && Number.isFinite(tokens) ? tokens : null;
713
+ this.activeContextWindowTokens = normalizedTokens;
714
+ if (normalizedTokens !== null) {
715
+ this.latestTokenUsage = {
716
+ used: this.latestTokenUsage.used,
717
+ limit: normalizedTokens,
718
+ };
719
+ }
696
720
  }
697
721
  updateContextUsage(percentage) {
698
722
  this.uiAdapter.updateContextUsage(percentage);
699
- this.terminalInput.setContextUsage(percentage);
723
+ this.terminalInput.setContextUsage(percentage, CONTEXT_AUTOCOMPACT_PERCENT);
700
724
  }
701
725
  refreshControlBar() {
702
726
  this.terminalInput.setModeToggles({
@@ -704,9 +728,9 @@ export class InteractiveShell {
704
728
  autoContinueEnabled: this.autoContinueEnabled,
705
729
  verificationHotkey: 'alt+v',
706
730
  autoContinueHotkey: 'alt+c',
731
+ thinkingModeLabel: this.thinkingMode,
732
+ thinkingHotkey: '/thinking',
707
733
  });
708
- // Update persistent model info display
709
- this.terminalInput.setModelInfo(this.describeModelDetail());
710
734
  this.refreshStatusLine();
711
735
  this.terminalInput.render();
712
736
  }
@@ -737,6 +761,25 @@ export class InteractiveShell {
737
761
  // Set main status (tool execution, etc.) - shown when not overridden
738
762
  const statusText = this.formatStatusLine(this.statusLineState);
739
763
  this.terminalInput.setStatusMessage(statusText);
764
+ // Surface meta header (elapsed + context usage) above the divider
765
+ const elapsedSeconds = this.statusLineState
766
+ ? Math.max(0, Math.floor((Date.now() - this.statusLineState.startedAt) / 1000))
767
+ : null;
768
+ const thinkingMs = display.isSpinnerActive() ? display.getThinkingElapsedMs() : null;
769
+ const tokensUsed = this.latestTokenUsage.used;
770
+ const tokenLimit = this.latestTokenUsage.limit ?? this.activeContextWindowTokens;
771
+ this.terminalInput.setMetaStatus({
772
+ elapsedSeconds,
773
+ tokensUsed,
774
+ tokenLimit,
775
+ thinkingMs,
776
+ thinkingHasContent: display.isSpinnerActive(),
777
+ });
778
+ // Keep model/provider visible in the controls bar
779
+ this.terminalInput.setModelContext({
780
+ model: this.sessionState.model,
781
+ provider: this.providerLabel(this.sessionState.provider),
782
+ });
740
783
  if (forceRender) {
741
784
  this.terminalInput.render();
742
785
  }
@@ -796,13 +839,14 @@ export class InteractiveShell {
796
839
  this.terminalInput.render();
797
840
  }
798
841
  /**
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.
842
+ * Log user prompt to the scroll region so it's part of the conversation flow.
801
843
  */
802
844
  logUserPrompt(text) {
803
- // Display the user's prompt with the standard prefix
804
- const prefix = formatUserPrompt();
805
- display.stream(`\n${prefix}${text}\n\n`);
845
+ if (!text.trim())
846
+ return;
847
+ // Format with user prompt prefix and write to scroll region
848
+ const formatted = `${theme.user('>')} ${text}\n`;
849
+ this.terminalInput.writeToScrollRegion(formatted);
806
850
  }
807
851
  requestPromptRefresh(force = false) {
808
852
  if (force) {
@@ -830,9 +874,29 @@ export class InteractiveShell {
830
874
  this.uiUpdates.setMode('streaming');
831
875
  this.streamingHeartbeatStart = Date.now();
832
876
  this.streamingHeartbeatFrame = 0;
833
- // Note: We don't start a heartbeat during streaming anymore
834
- // because the UI shouldn't be rendering during streaming.
835
- // The streaming status is shown in the streaming header instead.
877
+ const initialFrame = STREAMING_SPINNER_FRAMES[this.streamingHeartbeatFrame];
878
+ this.streamingStatusLabel = this.buildStreamingStatus(`${initialFrame} ${label}`, 0);
879
+ display.updateStreamingStatus(this.streamingStatusLabel);
880
+ this.refreshStatusLine(true);
881
+ // Periodically refresh the pinned input/status region while streaming so
882
+ // elapsed time remains visible without interrupting the scroll region.
883
+ this.uiUpdates.startHeartbeat('streaming', {
884
+ intervalMs: 1000,
885
+ lane: 'heartbeat',
886
+ mode: ['streaming', 'processing'],
887
+ coalesceKey: 'streaming:heartbeat',
888
+ run: () => {
889
+ const elapsedSeconds = this.streamingHeartbeatStart
890
+ ? Math.max(0, Math.floor((Date.now() - this.streamingHeartbeatStart) / 1000))
891
+ : 0;
892
+ this.streamingHeartbeatFrame =
893
+ (this.streamingHeartbeatFrame + 1) % STREAMING_SPINNER_FRAMES.length;
894
+ const frame = STREAMING_SPINNER_FRAMES[this.streamingHeartbeatFrame];
895
+ this.streamingStatusLabel = this.buildStreamingStatus(`${frame} ${label}`, elapsedSeconds);
896
+ display.updateStreamingStatus(this.streamingStatusLabel);
897
+ this.refreshStatusLine(true);
898
+ },
899
+ });
836
900
  }
837
901
  stopStreamingHeartbeat() {
838
902
  // Exit global streaming mode - allows UI to render again
@@ -848,10 +912,28 @@ export class InteractiveShell {
848
912
  // Force refresh to update the input area now that streaming has ended
849
913
  this.refreshStatusLine(true);
850
914
  }
851
- buildStreamingStatus(label) {
915
+ buildStreamingStatus(label, elapsedSeconds) {
852
916
  const detail = this.describeModelDetail();
853
- const prefix = theme.info('');
854
- return detail ? `${prefix} ${label} ${theme.ui.muted('·')} ${detail}` : `${prefix} ${label}`;
917
+ const elapsedLabel = typeof elapsedSeconds === 'number' && elapsedSeconds >= 0
918
+ ? theme.ui.muted(this.formatElapsedShort(elapsedSeconds))
919
+ : null;
920
+ const prefix = theme.info('⏺');
921
+ const parts = [label];
922
+ if (detail) {
923
+ parts.push(theme.ui.muted('·'), detail);
924
+ }
925
+ if (elapsedLabel) {
926
+ parts.push(theme.ui.muted('·'), elapsedLabel);
927
+ }
928
+ return `${prefix} ${parts.join(' ')}`.trim();
929
+ }
930
+ formatElapsedShort(seconds) {
931
+ if (seconds < 60) {
932
+ return `${seconds}s`;
933
+ }
934
+ const minutes = Math.floor(seconds / 60);
935
+ const remaining = seconds % 60;
936
+ return remaining > 0 ? `${minutes}m ${remaining}s` : `${minutes}m`;
855
937
  }
856
938
  refreshQueueIndicators() {
857
939
  if (this.isProcessing) {
@@ -1099,17 +1181,6 @@ export class InteractiveShell {
1099
1181
  case '/discover':
1100
1182
  await this.discoverModelsCommand();
1101
1183
  break;
1102
- case '/memory':
1103
- this.handleMemoryCommand(input);
1104
- break;
1105
- case '/clear':
1106
- display.clear();
1107
- this.cachedHistory = [];
1108
- display.showInfo('Conversation cleared.');
1109
- break;
1110
- case '/help':
1111
- this.showHelp();
1112
- break;
1113
1184
  default:
1114
1185
  if (!(await this.tryCustomSlashCommand(command, input))) {
1115
1186
  display.showWarning(`Unknown command "${command}".`);
@@ -1418,99 +1489,6 @@ export class InteractiveShell {
1418
1489
  // Display keyboard shortcuts help (Claude Code style)
1419
1490
  display.showSystemMessage(formatShortcutsHelp());
1420
1491
  }
1421
- handleMemoryCommand(input) {
1422
- const tokens = input.trim().split(/\s+/).slice(1);
1423
- const action = (tokens.shift() ?? 'show').toLowerCase();
1424
- switch (action) {
1425
- case '':
1426
- case 'show':
1427
- case 'list': {
1428
- this.showMemoryStatus();
1429
- break;
1430
- }
1431
- case 'paths': {
1432
- this.showMemoryPaths();
1433
- break;
1434
- }
1435
- case 'edit': {
1436
- const level = (tokens[0] ?? 'project').toLowerCase();
1437
- this.openMemoryForEdit(level);
1438
- break;
1439
- }
1440
- default:
1441
- display.showWarning('Usage: /memory [show|paths|edit <user|project>]');
1442
- break;
1443
- }
1444
- }
1445
- showMemoryStatus() {
1446
- const memory = loadMemory(this.workingDir);
1447
- const lines = [];
1448
- lines.push(theme.bold('Persistent Memory'));
1449
- lines.push('');
1450
- if (memory.sources.length === 0) {
1451
- lines.push(theme.secondary('No memory files found.'));
1452
- lines.push('');
1453
- lines.push(`Create ${theme.info('EROSOLAR.md')} in your project to add persistent context.`);
1454
- lines.push(`Use ${theme.info('/memory edit project')} to create one.`);
1455
- }
1456
- else {
1457
- for (const source of memory.sources) {
1458
- const levelLabel = source.level === 'enterprise' ? 'Enterprise' :
1459
- source.level === 'user' ? 'User' : 'Project';
1460
- const preview = source.content.slice(0, 200).replace(/\n/g, ' ').trim();
1461
- const truncated = source.content.length > 200 ? '...' : '';
1462
- lines.push(`${theme.success('●')} ${theme.bold(levelLabel)}: ${source.path}`);
1463
- lines.push(` ${theme.dim(preview + truncated)}`);
1464
- lines.push('');
1465
- }
1466
- if (memory.importedPaths.length > memory.sources.length) {
1467
- lines.push(theme.secondary(`Imported ${memory.importedPaths.length - memory.sources.length} additional files via @imports.`));
1468
- }
1469
- }
1470
- display.showSystemMessage(lines.join('\n'));
1471
- }
1472
- showMemoryPaths() {
1473
- const paths = listMemoryPaths(this.workingDir);
1474
- const lines = [];
1475
- lines.push(theme.bold('Memory File Locations'));
1476
- lines.push('');
1477
- for (const { level, path, exists } of paths) {
1478
- const icon = exists ? theme.success('✓') : theme.dim('○');
1479
- const levelLabel = level.charAt(0).toUpperCase() + level.slice(1);
1480
- lines.push(`${icon} ${levelLabel}: ${path}`);
1481
- }
1482
- lines.push('');
1483
- lines.push(theme.secondary('Create any of these files to add persistent memory.'));
1484
- lines.push(theme.secondary('Use @path/to/file.md syntax to import other files.'));
1485
- display.showSystemMessage(lines.join('\n'));
1486
- }
1487
- openMemoryForEdit(level) {
1488
- let targetPath;
1489
- if (level === 'user') {
1490
- targetPath = getUserMemoryEditPath();
1491
- }
1492
- else if (level === 'project') {
1493
- targetPath = getDefaultProjectMemoryPath(this.workingDir);
1494
- }
1495
- else {
1496
- display.showWarning('Specify "user" or "project" to edit. Enterprise memory is read-only.');
1497
- return;
1498
- }
1499
- display.showInfo(`Memory file: ${targetPath}`);
1500
- display.showInfo('Create or edit this file to add persistent context for the AI.');
1501
- display.showInfo('');
1502
- display.showInfo('Example EROSOLAR.md content:');
1503
- display.showInfo('');
1504
- display.showInfo(theme.dim(`# Project Guidelines
1505
-
1506
- When working in this codebase:
1507
- - Follow TypeScript strict mode conventions
1508
- - Use functional patterns where appropriate
1509
- - Run tests before committing
1510
-
1511
- @./docs/coding-standards.md
1512
- `));
1513
- }
1514
1492
  showFileChangeSummary() {
1515
1493
  const summary = this._fileChangeTracker.getSummary();
1516
1494
  const changes = this._fileChangeTracker.getAllChanges();
@@ -1553,11 +1531,11 @@ When working in this codebase:
1553
1531
  display.showSystemMessage(lines.join('\n'));
1554
1532
  }
1555
1533
  showAlphaZeroMetrics() {
1556
- const summary = this.sessionMetrics.getPerformanceSummary();
1534
+ const summary = this.alphaZeroMetrics.getPerformanceSummary();
1557
1535
  display.showSystemMessage(summary);
1558
1536
  }
1559
1537
  showImprovementSuggestions() {
1560
- const suggestions = this.sessionMetrics.getImprovementSuggestions();
1538
+ const suggestions = this.alphaZeroMetrics.getImprovementSuggestions();
1561
1539
  if (suggestions.length === 0) {
1562
1540
  display.showInfo('No improvement suggestions at this time. Keep using the shell to generate metrics!');
1563
1541
  return;
@@ -1603,7 +1581,9 @@ When working in this codebase:
1603
1581
  }
1604
1582
  }
1605
1583
  lines.push(theme.secondary('CLI Flags:'));
1584
+ lines.push(' --alpha-zero Enable Alpha Zero 2 RL framework');
1606
1585
  lines.push(' --coding Enable enhanced coding tools');
1586
+ lines.push(' --security Enable security research tools');
1607
1587
  lines.push(' --all-plugins Enable all optional plugins');
1608
1588
  display.showSystemMessage(lines.join('\n'));
1609
1589
  }
@@ -1847,6 +1827,75 @@ When working in this codebase:
1847
1827
  }
1848
1828
  return `${warning.label}: ${warning.reason}.`;
1849
1829
  }
1830
+ buildLaunchCommandPalette() {
1831
+ const entries = [];
1832
+ const secretsSummary = this.summarizeSecretsForPalette();
1833
+ const toolSummary = this.getToolSelectionSummary();
1834
+ const autosaveLabel = this.autosaveEnabled ? 'on' : 'off';
1835
+ for (const command of this.slashCommands) {
1836
+ const entry = {
1837
+ command: command.command,
1838
+ description: command.description,
1839
+ category: command.category ?? 'other',
1840
+ };
1841
+ switch (command.command) {
1842
+ case '/secrets':
1843
+ if (secretsSummary.text) {
1844
+ entry.description = `${command.description} (${secretsSummary.text})`;
1845
+ entry.tone = secretsSummary.tone;
1846
+ }
1847
+ break;
1848
+ case '/tools':
1849
+ if (toolSummary) {
1850
+ entry.description = `${command.description} (${toolSummary})`;
1851
+ }
1852
+ break;
1853
+ case '/sessions':
1854
+ entry.description = `${command.description} (autosave ${autosaveLabel})`;
1855
+ break;
1856
+ case '/model':
1857
+ entry.description = `${command.description} (current: ${this.sessionState.model})`;
1858
+ break;
1859
+ case '/provider':
1860
+ entry.description = `${command.description} (current: ${this.providerLabel(this.sessionState.provider)})`;
1861
+ break;
1862
+ default:
1863
+ break;
1864
+ }
1865
+ entries.push(entry);
1866
+ }
1867
+ return entries;
1868
+ }
1869
+ summarizeSecretsForPalette() {
1870
+ const definitions = listSecretDefinitions();
1871
+ if (!definitions.length) {
1872
+ return { text: null };
1873
+ }
1874
+ const missing = definitions.filter((definition) => !getSecretValue(definition.id));
1875
+ if (missing.length === 0) {
1876
+ return { text: 'all configured', tone: 'success' };
1877
+ }
1878
+ const labels = missing.map((definition) => definition.label ?? definition.id);
1879
+ return { text: `missing ${this.formatList(labels)}`, tone: 'warn' };
1880
+ }
1881
+ getToolSelectionSummary() {
1882
+ const toolSettings = loadToolSettings();
1883
+ const selection = buildEnabledToolSet(toolSettings);
1884
+ const options = getToolToggleOptions();
1885
+ if (!options.length) {
1886
+ return null;
1887
+ }
1888
+ const enabledCount = options.filter((option) => selection.has(option.id)).length;
1889
+ return `${enabledCount}/${options.length} enabled`;
1890
+ }
1891
+ formatList(values, maxItems = 3) {
1892
+ if (!values.length) {
1893
+ return '';
1894
+ }
1895
+ const shown = values.slice(0, maxItems);
1896
+ const suffix = values.length > maxItems ? ', …' : '';
1897
+ return `${shown.join(', ')}${suffix}`;
1898
+ }
1850
1899
  buildSlashCommandList(header) {
1851
1900
  const lines = [theme.gradient.primary(header), ''];
1852
1901
  for (const command of this.slashCommands) {
@@ -2315,7 +2364,7 @@ When working in this codebase:
2315
2364
  this.autosaveIfEnabled();
2316
2365
  // Track metrics with Alpha Zero 2
2317
2366
  const elapsedMs = Date.now() - requestStartTime;
2318
- this.sessionMetrics.recordMessage(elapsedMs);
2367
+ this.alphaZeroMetrics.recordMessage(elapsedMs);
2319
2368
  if (!responseText?.trim()) {
2320
2369
  display.showWarning('The provider returned an empty response. Check your API key/provider selection or retry the prompt.');
2321
2370
  }
@@ -2333,14 +2382,10 @@ When working in this codebase:
2333
2382
  this.stopStreamingHeartbeat();
2334
2383
  this.isProcessing = false;
2335
2384
  this.terminalInput.setStreaming(false);
2336
- this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
2337
2385
  this.uiAdapter.endProcessing('Ready for prompts');
2338
2386
  this.setIdleStatus();
2339
2387
  display.newLine();
2340
2388
  this.updateStatusMessage(null);
2341
- // Claude Code style: Show unified status bar before prompt
2342
- // This creates consistent UI between startup and post-streaming
2343
- this.showUnifiedStatusBar();
2344
2389
  queueMicrotask(() => this.uiUpdates.setMode('idle'));
2345
2390
  // CRITICAL: Ensure readline prompt is active for user input
2346
2391
  // Claude Code style: New prompt naturally appears at bottom
@@ -2417,13 +2462,14 @@ When truly finished with ALL tasks, explicitly state "TASK_FULLY_COMPLETE".`;
2417
2462
  try {
2418
2463
  // Send the request and capture the response (streaming disabled)
2419
2464
  display.showThinking('Responding...');
2465
+ this.refreshStatusLine(true);
2420
2466
  const response = await agent.send(currentPrompt, true);
2421
2467
  await this.awaitPendingCleanup();
2422
2468
  this.captureHistorySnapshot();
2423
2469
  this.autosaveIfEnabled();
2424
2470
  // Track metrics
2425
2471
  const elapsedMs = Date.now() - overallStartTime;
2426
- this.sessionMetrics.recordMessage(elapsedMs);
2472
+ this.alphaZeroMetrics.recordMessage(elapsedMs);
2427
2473
  if (!response?.trim()) {
2428
2474
  display.showWarning('Model returned an empty response. Retrying this iteration...');
2429
2475
  consecutiveNoProgress++;
@@ -2560,7 +2606,6 @@ What's the next action?`;
2560
2606
  this.stopStreamingHeartbeat();
2561
2607
  this.isProcessing = false;
2562
2608
  this.terminalInput.setStreaming(false);
2563
- this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
2564
2609
  this.uiAdapter.endProcessing('Ready for prompts');
2565
2610
  this.setIdleStatus();
2566
2611
  this.updateStatusMessage(null);
@@ -2917,8 +2962,10 @@ What's the next action?`;
2917
2962
  try {
2918
2963
  // Send the error to the agent for fixing
2919
2964
  display.showThinking('Analyzing build errors');
2965
+ this.refreshStatusLine(true);
2920
2966
  const response = await this.agent.send(prompt, true);
2921
2967
  display.stopThinking();
2968
+ this.refreshStatusLine(true);
2922
2969
  if (response) {
2923
2970
  display.showAssistantMessage(response, { isFinal: true });
2924
2971
  }
@@ -2945,8 +2992,8 @@ What's the next action?`;
2945
2992
  };
2946
2993
  this.agent = this.runtimeSession.createAgent(selection, {
2947
2994
  onStreamChunk: (chunk) => {
2948
- // Stream output directly - no spinner during streaming to avoid race conditions
2949
- display.stream(chunk);
2995
+ // Stream output using clean streamContent() - chat box floats below
2996
+ this.terminalInput.streamContent(chunk);
2950
2997
  },
2951
2998
  onStreamFallback: (info) => this.handleStreamingFallback(info),
2952
2999
  onAssistantMessage: (content, metadata) => {
@@ -2968,18 +3015,16 @@ What's the next action?`;
2968
3015
  display.showAssistantMessage(finalContent, enriched);
2969
3016
  }
2970
3017
  }
2971
- // Show status line at end (Claude Code style: "• Context X% used • Ready for prompts (2s)")
3018
+ // Status shown in mode controls bar - no separate status line needed
2972
3019
  display.stopThinking();
2973
- // Calculate context usage
2974
- let contextInfo;
3020
+ // Update context usage for mode controls display
2975
3021
  if (enriched.contextWindowTokens && metadata.usage) {
2976
3022
  const total = this.totalTokens(metadata.usage);
2977
3023
  if (total && total > 0) {
2978
3024
  const percentage = Math.round((total / enriched.contextWindowTokens) * 100);
2979
- contextInfo = { percentage, tokens: total };
3025
+ this.updateContextUsage(percentage);
2980
3026
  }
2981
3027
  }
2982
- display.showStatusLine('Ready for prompts', enriched.elapsedMs, contextInfo);
2983
3028
  // Auto-verify changes: build first (catches type errors), then tests
2984
3029
  void this.enforceAutoBuild('final-response');
2985
3030
  void this.enforceAutoTests('final-response');
@@ -3049,7 +3094,6 @@ What's the next action?`;
3049
3094
  this.stopStreamingHeartbeat();
3050
3095
  this.updateStatusMessage(null);
3051
3096
  this.terminalInput.setStreaming(false);
3052
- this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
3053
3097
  this.terminalInput.render();
3054
3098
  },
3055
3099
  onVerificationNeeded: () => {
@@ -3086,7 +3130,6 @@ What's the next action?`;
3086
3130
  resetChatBoxAfterModelSwap() {
3087
3131
  this.updateStatusMessage(null);
3088
3132
  this.terminalInput.setStreaming(false);
3089
- this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
3090
3133
  this.terminalInput.render();
3091
3134
  this.ensureReadlineReady();
3092
3135
  }
@@ -3151,9 +3194,14 @@ What's the next action?`;
3151
3194
  return null;
3152
3195
  }
3153
3196
  const usageRatio = total / windowTokens;
3197
+ this.latestTokenUsage = {
3198
+ used: total,
3199
+ limit: windowTokens,
3200
+ };
3154
3201
  // Always update context usage in the UI
3155
3202
  const percentUsed = Math.round(usageRatio * 100);
3156
3203
  this.updateContextUsage(percentUsed);
3204
+ this.refreshStatusLine(true);
3157
3205
  if (usageRatio < CONTEXT_USAGE_THRESHOLD) {
3158
3206
  return null;
3159
3207
  }
@@ -3420,6 +3468,22 @@ What's the next action?`;
3420
3468
  this.sessionState.reasoningEffort = preset.reasoningEffort;
3421
3469
  }
3422
3470
  }
3471
+ /**
3472
+ * Build the session banner.
3473
+ */
3474
+ buildBanner() {
3475
+ const terminalWidth = output.columns ?? 100;
3476
+ const width = Math.min(terminalWidth - 4, 110);
3477
+ return renderSessionFrame({
3478
+ profileLabel: this.profileLabel,
3479
+ profileName: this.profile,
3480
+ model: this.sessionState.model,
3481
+ provider: this.sessionState.provider,
3482
+ workspace: this.workingDir,
3483
+ version: this.version,
3484
+ width,
3485
+ });
3486
+ }
3423
3487
  refreshBannerSessionInfo() {
3424
3488
  const nextState = {
3425
3489
  model: this.sessionState.model,
@@ -3430,13 +3494,11 @@ What's the next action?`;
3430
3494
  return;
3431
3495
  }
3432
3496
  this.refreshContextGauge();
3433
- display.updateSessionInfo(nextState.model, nextState.provider);
3434
- // Update the persistent model info display in terminal input
3435
- this.terminalInput.setModelInfo(this.describeModelDetail());
3497
+ // Banner is no longer stored in display - it was streamed as content
3498
+ // Model/provider changes are visible in the control bar
3436
3499
  if (!this.isProcessing) {
3437
3500
  this.setIdleStatus();
3438
3501
  }
3439
- // Pinned header rows are disabled; scroll region handles all output.
3440
3502
  this.bannerSessionState = nextState;
3441
3503
  }
3442
3504
  providerLabel(id) {