erosolar-cli 1.7.280 → 1.7.281

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 +1 -0
  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 +17 -7
  63. package/dist/shell/interactiveShell.d.ts.map +1 -1
  64. package/dist/shell/interactiveShell.js +218 -161
  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 +78 -178
  74. package/dist/shell/terminalInput.d.ts.map +1 -1
  75. package/dist/shell/terminalInput.js +494 -877
  76. package/dist/shell/terminalInput.js.map +1 -1
  77. package/dist/shell/terminalInputAdapter.d.ts +28 -34
  78. package/dist/shell/terminalInputAdapter.d.ts.map +1 -1
  79. package/dist/shell/terminalInputAdapter.js +26 -47
  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 +22 -39
  97. package/dist/ui/display.d.ts.map +1 -1
  98. package/dist/ui/display.js +136 -277
  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 +1 -1
  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;
@@ -216,20 +227,16 @@ export class InteractiveShell {
216
227
  });
217
228
  // Register output interceptor for cursor positioning during streaming
218
229
  this.terminalInput.registerOutputInterceptor(display);
219
- // Initialize unified UI immediately - clears screen, sets up scroll region,
220
- // and positions cursor at row 1 for content
221
- this.terminalInput.initializeUnifiedUI();
222
- // Write banner directly as the first content (bypasses interceptor)
223
- const banner = display.getBannerContent();
224
- if (banner) {
225
- process.stdout.write(banner + '\n');
226
- }
227
230
  // Initialize Alpha Zero 2 metrics tracking
228
- this.sessionMetrics = new MetricsTracker(`${this.profile}-${Date.now()}`);
231
+ this.alphaZeroMetrics = new MetricsTracker(`${this.profile}-${Date.now()}`);
229
232
  this.setupStatusTracking();
230
233
  this.refreshContextGauge();
231
234
  this.terminalInput.start();
232
235
  this.refreshControlBar();
236
+ // Render banner in the scroll region so it's part of the unified UI
237
+ this.terminalInput.resetContentPosition();
238
+ const bannerContent = this.buildBanner();
239
+ this.terminalInput.writeToScrollRegion(bannerContent + '\n');
233
240
  this.rebuildAgent();
234
241
  this.setupHandlers();
235
242
  this.refreshBannerSessionInfo();
@@ -281,9 +288,15 @@ export class InteractiveShell {
281
288
  await this.processInputBlock(initialPrompt);
282
289
  return;
283
290
  }
291
+ this.showLaunchCommandPalette();
284
292
  // Ensure the terminal input is visible
285
293
  this.terminalInput.render();
286
294
  }
295
+ showLaunchCommandPalette() {
296
+ // Disabled: Quick commands palette takes up too much space
297
+ // Users can type /help to see available commands
298
+ this.launchPaletteShown = true;
299
+ }
287
300
  /**
288
301
  * TerminalInputAdapter submit handler
289
302
  */
@@ -297,9 +310,8 @@ export class InteractiveShell {
297
310
  this.handleInputChange('');
298
311
  return;
299
312
  }
300
- // Enter streaming mode BEFORE logging prompt - this positions cursor correctly
301
- // so content appears right after the banner, not at bottom with blank space above
302
- this.terminalInput.setStreaming(true);
313
+ // DON'T clear the input here - keep it visible while streaming.
314
+ // The input will be cleared after streaming completes in the finally block.
303
315
  this.logUserPrompt(approved);
304
316
  void this.processInputBlock(approved).catch((err) => {
305
317
  display.showError(err instanceof Error ? err.message : String(err), err);
@@ -501,10 +513,9 @@ export class InteractiveShell {
501
513
  // Dispose unified UI adapter
502
514
  this.uiAdapter.dispose();
503
515
  display.newLine();
504
- console.log(theme.gradient.warm('━'.repeat(50)));
505
- console.log(` ${theme.gradient.cool('Goodbye!')} ${theme.ui.muted('·')} ${theme.info('support@ero.solar')}`);
506
- console.log(` ${theme.ui.muted('Read:')} ${theme.accent('anthropic.com/news/disrupting-AI-espionage')}`);
507
- console.log(theme.gradient.warm('━'.repeat(50)));
516
+ console.log(theme.ui.muted('━'.repeat(44)));
517
+ console.log(theme.ui.muted(' Goodbye! · support@ero.solar'));
518
+ console.log(theme.ui.muted(''.repeat(44)));
508
519
  exit(0);
509
520
  }
510
521
  /**
@@ -674,13 +685,14 @@ export class InteractiveShell {
674
685
  });
675
686
  }
676
687
  setProcessingStatus(detail) {
688
+ this.latestTokenUsage = { used: null, limit: this.latestTokenUsage.limit };
677
689
  this.statusTracker.setBase('Working on your request', {
678
690
  detail: this.describeStatusDetail(detail),
679
691
  tone: 'info',
680
692
  });
681
693
  }
682
694
  describeStatusDetail(detail) {
683
- const parts = [detail?.trim() || this.describeModelDetail()];
695
+ const parts = detail?.trim() ? [detail.trim()] : [];
684
696
  const queued = this.followUpQueue.length;
685
697
  if (queued > 0) {
686
698
  parts.push(`${queued} follow-up${queued === 1 ? '' : 's'} queued`);
@@ -693,12 +705,18 @@ export class InteractiveShell {
693
705
  }
694
706
  refreshContextGauge() {
695
707
  const tokens = getContextWindowTokens(this.sessionState.model);
696
- this.activeContextWindowTokens =
697
- typeof tokens === 'number' && Number.isFinite(tokens) ? tokens : null;
708
+ const normalizedTokens = typeof tokens === 'number' && Number.isFinite(tokens) ? tokens : null;
709
+ this.activeContextWindowTokens = normalizedTokens;
710
+ if (normalizedTokens !== null) {
711
+ this.latestTokenUsage = {
712
+ used: this.latestTokenUsage.used,
713
+ limit: normalizedTokens,
714
+ };
715
+ }
698
716
  }
699
717
  updateContextUsage(percentage) {
700
718
  this.uiAdapter.updateContextUsage(percentage);
701
- this.terminalInput.setContextUsage(percentage);
719
+ this.terminalInput.setContextUsage(percentage, CONTEXT_AUTOCOMPACT_PERCENT);
702
720
  }
703
721
  refreshControlBar() {
704
722
  this.terminalInput.setModeToggles({
@@ -706,9 +724,9 @@ export class InteractiveShell {
706
724
  autoContinueEnabled: this.autoContinueEnabled,
707
725
  verificationHotkey: 'alt+v',
708
726
  autoContinueHotkey: 'alt+c',
727
+ thinkingModeLabel: this.thinkingMode,
728
+ thinkingHotkey: '/thinking',
709
729
  });
710
- // Update persistent model info display
711
- this.terminalInput.setModelInfo(this.describeModelDetail());
712
730
  this.refreshStatusLine();
713
731
  this.terminalInput.render();
714
732
  }
@@ -739,6 +757,25 @@ export class InteractiveShell {
739
757
  // Set main status (tool execution, etc.) - shown when not overridden
740
758
  const statusText = this.formatStatusLine(this.statusLineState);
741
759
  this.terminalInput.setStatusMessage(statusText);
760
+ // Surface meta header (elapsed + context usage) above the divider
761
+ const elapsedSeconds = this.statusLineState
762
+ ? Math.max(0, Math.floor((Date.now() - this.statusLineState.startedAt) / 1000))
763
+ : null;
764
+ const thinkingMs = display.isSpinnerActive() ? display.getThinkingElapsedMs() : null;
765
+ const tokensUsed = this.latestTokenUsage.used;
766
+ const tokenLimit = this.latestTokenUsage.limit ?? this.activeContextWindowTokens;
767
+ this.terminalInput.setMetaStatus({
768
+ elapsedSeconds,
769
+ tokensUsed,
770
+ tokenLimit,
771
+ thinkingMs,
772
+ thinkingHasContent: display.isSpinnerActive(),
773
+ });
774
+ // Keep model/provider visible in the controls bar
775
+ this.terminalInput.setModelContext({
776
+ model: this.sessionState.model,
777
+ provider: this.providerLabel(this.sessionState.provider),
778
+ });
742
779
  if (forceRender) {
743
780
  this.terminalInput.render();
744
781
  }
@@ -798,13 +835,14 @@ export class InteractiveShell {
798
835
  this.terminalInput.render();
799
836
  }
800
837
  /**
801
- * Log the user's prompt as a visible message in the conversation.
802
- * This creates a persistent log entry that remains visible during and after streaming.
838
+ * Log user prompt to the scroll region so it's part of the conversation flow.
803
839
  */
804
840
  logUserPrompt(text) {
805
- // Display the user's prompt with the standard prefix
806
- const prefix = formatUserPrompt();
807
- display.stream(`\n${prefix}${text}\n\n`);
841
+ if (!text.trim())
842
+ return;
843
+ // Format with user prompt prefix and write to scroll region
844
+ const formatted = `${theme.user('>')} ${text}\n`;
845
+ this.terminalInput.writeToScrollRegion(formatted);
808
846
  }
809
847
  requestPromptRefresh(force = false) {
810
848
  if (force) {
@@ -832,9 +870,29 @@ export class InteractiveShell {
832
870
  this.uiUpdates.setMode('streaming');
833
871
  this.streamingHeartbeatStart = Date.now();
834
872
  this.streamingHeartbeatFrame = 0;
835
- // Note: We don't start a heartbeat during streaming anymore
836
- // because the UI shouldn't be rendering during streaming.
837
- // The streaming status is shown in the streaming header instead.
873
+ const initialFrame = STREAMING_SPINNER_FRAMES[this.streamingHeartbeatFrame];
874
+ this.streamingStatusLabel = this.buildStreamingStatus(`${initialFrame} ${label}`, 0);
875
+ display.updateStreamingStatus(this.streamingStatusLabel);
876
+ this.refreshStatusLine(true);
877
+ // Periodically refresh the pinned input/status region while streaming so
878
+ // elapsed time remains visible without interrupting the scroll region.
879
+ this.uiUpdates.startHeartbeat('streaming', {
880
+ intervalMs: 1000,
881
+ lane: 'heartbeat',
882
+ mode: ['streaming', 'processing'],
883
+ coalesceKey: 'streaming:heartbeat',
884
+ run: () => {
885
+ const elapsedSeconds = this.streamingHeartbeatStart
886
+ ? Math.max(0, Math.floor((Date.now() - this.streamingHeartbeatStart) / 1000))
887
+ : 0;
888
+ this.streamingHeartbeatFrame =
889
+ (this.streamingHeartbeatFrame + 1) % STREAMING_SPINNER_FRAMES.length;
890
+ const frame = STREAMING_SPINNER_FRAMES[this.streamingHeartbeatFrame];
891
+ this.streamingStatusLabel = this.buildStreamingStatus(`${frame} ${label}`, elapsedSeconds);
892
+ display.updateStreamingStatus(this.streamingStatusLabel);
893
+ this.refreshStatusLine(true);
894
+ },
895
+ });
838
896
  }
839
897
  stopStreamingHeartbeat() {
840
898
  // Exit global streaming mode - allows UI to render again
@@ -850,10 +908,28 @@ export class InteractiveShell {
850
908
  // Force refresh to update the input area now that streaming has ended
851
909
  this.refreshStatusLine(true);
852
910
  }
853
- buildStreamingStatus(label) {
911
+ buildStreamingStatus(label, elapsedSeconds) {
854
912
  const detail = this.describeModelDetail();
855
- const prefix = theme.info('');
856
- return detail ? `${prefix} ${label} ${theme.ui.muted('·')} ${detail}` : `${prefix} ${label}`;
913
+ const elapsedLabel = typeof elapsedSeconds === 'number' && elapsedSeconds >= 0
914
+ ? theme.ui.muted(this.formatElapsedShort(elapsedSeconds))
915
+ : null;
916
+ const prefix = theme.info('⏺');
917
+ const parts = [label];
918
+ if (detail) {
919
+ parts.push(theme.ui.muted('·'), detail);
920
+ }
921
+ if (elapsedLabel) {
922
+ parts.push(theme.ui.muted('·'), elapsedLabel);
923
+ }
924
+ return `${prefix} ${parts.join(' ')}`.trim();
925
+ }
926
+ formatElapsedShort(seconds) {
927
+ if (seconds < 60) {
928
+ return `${seconds}s`;
929
+ }
930
+ const minutes = Math.floor(seconds / 60);
931
+ const remaining = seconds % 60;
932
+ return remaining > 0 ? `${minutes}m ${remaining}s` : `${minutes}m`;
857
933
  }
858
934
  refreshQueueIndicators() {
859
935
  if (this.isProcessing) {
@@ -1101,17 +1177,6 @@ export class InteractiveShell {
1101
1177
  case '/discover':
1102
1178
  await this.discoverModelsCommand();
1103
1179
  break;
1104
- case '/memory':
1105
- this.handleMemoryCommand(input);
1106
- break;
1107
- case '/clear':
1108
- display.clear();
1109
- this.cachedHistory = [];
1110
- display.showInfo('Conversation cleared.');
1111
- break;
1112
- case '/help':
1113
- this.showHelp();
1114
- break;
1115
1180
  default:
1116
1181
  if (!(await this.tryCustomSlashCommand(command, input))) {
1117
1182
  display.showWarning(`Unknown command "${command}".`);
@@ -1420,99 +1485,6 @@ export class InteractiveShell {
1420
1485
  // Display keyboard shortcuts help (Claude Code style)
1421
1486
  display.showSystemMessage(formatShortcutsHelp());
1422
1487
  }
1423
- handleMemoryCommand(input) {
1424
- const tokens = input.trim().split(/\s+/).slice(1);
1425
- const action = (tokens.shift() ?? 'show').toLowerCase();
1426
- switch (action) {
1427
- case '':
1428
- case 'show':
1429
- case 'list': {
1430
- this.showMemoryStatus();
1431
- break;
1432
- }
1433
- case 'paths': {
1434
- this.showMemoryPaths();
1435
- break;
1436
- }
1437
- case 'edit': {
1438
- const level = (tokens[0] ?? 'project').toLowerCase();
1439
- this.openMemoryForEdit(level);
1440
- break;
1441
- }
1442
- default:
1443
- display.showWarning('Usage: /memory [show|paths|edit <user|project>]');
1444
- break;
1445
- }
1446
- }
1447
- showMemoryStatus() {
1448
- const memory = loadMemory(this.workingDir);
1449
- const lines = [];
1450
- lines.push(theme.bold('Persistent Memory'));
1451
- lines.push('');
1452
- if (memory.sources.length === 0) {
1453
- lines.push(theme.secondary('No memory files found.'));
1454
- lines.push('');
1455
- lines.push(`Create ${theme.info('EROSOLAR.md')} in your project to add persistent context.`);
1456
- lines.push(`Use ${theme.info('/memory edit project')} to create one.`);
1457
- }
1458
- else {
1459
- for (const source of memory.sources) {
1460
- const levelLabel = source.level === 'enterprise' ? 'Enterprise' :
1461
- source.level === 'user' ? 'User' : 'Project';
1462
- const preview = source.content.slice(0, 200).replace(/\n/g, ' ').trim();
1463
- const truncated = source.content.length > 200 ? '...' : '';
1464
- lines.push(`${theme.success('●')} ${theme.bold(levelLabel)}: ${source.path}`);
1465
- lines.push(` ${theme.dim(preview + truncated)}`);
1466
- lines.push('');
1467
- }
1468
- if (memory.importedPaths.length > memory.sources.length) {
1469
- lines.push(theme.secondary(`Imported ${memory.importedPaths.length - memory.sources.length} additional files via @imports.`));
1470
- }
1471
- }
1472
- display.showSystemMessage(lines.join('\n'));
1473
- }
1474
- showMemoryPaths() {
1475
- const paths = listMemoryPaths(this.workingDir);
1476
- const lines = [];
1477
- lines.push(theme.bold('Memory File Locations'));
1478
- lines.push('');
1479
- for (const { level, path, exists } of paths) {
1480
- const icon = exists ? theme.success('✓') : theme.dim('○');
1481
- const levelLabel = level.charAt(0).toUpperCase() + level.slice(1);
1482
- lines.push(`${icon} ${levelLabel}: ${path}`);
1483
- }
1484
- lines.push('');
1485
- lines.push(theme.secondary('Create any of these files to add persistent memory.'));
1486
- lines.push(theme.secondary('Use @path/to/file.md syntax to import other files.'));
1487
- display.showSystemMessage(lines.join('\n'));
1488
- }
1489
- openMemoryForEdit(level) {
1490
- let targetPath;
1491
- if (level === 'user') {
1492
- targetPath = getUserMemoryEditPath();
1493
- }
1494
- else if (level === 'project') {
1495
- targetPath = getDefaultProjectMemoryPath(this.workingDir);
1496
- }
1497
- else {
1498
- display.showWarning('Specify "user" or "project" to edit. Enterprise memory is read-only.');
1499
- return;
1500
- }
1501
- display.showInfo(`Memory file: ${targetPath}`);
1502
- display.showInfo('Create or edit this file to add persistent context for the AI.');
1503
- display.showInfo('');
1504
- display.showInfo('Example EROSOLAR.md content:');
1505
- display.showInfo('');
1506
- display.showInfo(theme.dim(`# Project Guidelines
1507
-
1508
- When working in this codebase:
1509
- - Follow TypeScript strict mode conventions
1510
- - Use functional patterns where appropriate
1511
- - Run tests before committing
1512
-
1513
- @./docs/coding-standards.md
1514
- `));
1515
- }
1516
1488
  showFileChangeSummary() {
1517
1489
  const summary = this._fileChangeTracker.getSummary();
1518
1490
  const changes = this._fileChangeTracker.getAllChanges();
@@ -1555,11 +1527,11 @@ When working in this codebase:
1555
1527
  display.showSystemMessage(lines.join('\n'));
1556
1528
  }
1557
1529
  showAlphaZeroMetrics() {
1558
- const summary = this.sessionMetrics.getPerformanceSummary();
1530
+ const summary = this.alphaZeroMetrics.getPerformanceSummary();
1559
1531
  display.showSystemMessage(summary);
1560
1532
  }
1561
1533
  showImprovementSuggestions() {
1562
- const suggestions = this.sessionMetrics.getImprovementSuggestions();
1534
+ const suggestions = this.alphaZeroMetrics.getImprovementSuggestions();
1563
1535
  if (suggestions.length === 0) {
1564
1536
  display.showInfo('No improvement suggestions at this time. Keep using the shell to generate metrics!');
1565
1537
  return;
@@ -1605,7 +1577,9 @@ When working in this codebase:
1605
1577
  }
1606
1578
  }
1607
1579
  lines.push(theme.secondary('CLI Flags:'));
1580
+ lines.push(' --alpha-zero Enable Alpha Zero 2 RL framework');
1608
1581
  lines.push(' --coding Enable enhanced coding tools');
1582
+ lines.push(' --security Enable security research tools');
1609
1583
  lines.push(' --all-plugins Enable all optional plugins');
1610
1584
  display.showSystemMessage(lines.join('\n'));
1611
1585
  }
@@ -1849,6 +1823,75 @@ When working in this codebase:
1849
1823
  }
1850
1824
  return `${warning.label}: ${warning.reason}.`;
1851
1825
  }
1826
+ buildLaunchCommandPalette() {
1827
+ const entries = [];
1828
+ const secretsSummary = this.summarizeSecretsForPalette();
1829
+ const toolSummary = this.getToolSelectionSummary();
1830
+ const autosaveLabel = this.autosaveEnabled ? 'on' : 'off';
1831
+ for (const command of this.slashCommands) {
1832
+ const entry = {
1833
+ command: command.command,
1834
+ description: command.description,
1835
+ category: command.category ?? 'other',
1836
+ };
1837
+ switch (command.command) {
1838
+ case '/secrets':
1839
+ if (secretsSummary.text) {
1840
+ entry.description = `${command.description} (${secretsSummary.text})`;
1841
+ entry.tone = secretsSummary.tone;
1842
+ }
1843
+ break;
1844
+ case '/tools':
1845
+ if (toolSummary) {
1846
+ entry.description = `${command.description} (${toolSummary})`;
1847
+ }
1848
+ break;
1849
+ case '/sessions':
1850
+ entry.description = `${command.description} (autosave ${autosaveLabel})`;
1851
+ break;
1852
+ case '/model':
1853
+ entry.description = `${command.description} (current: ${this.sessionState.model})`;
1854
+ break;
1855
+ case '/provider':
1856
+ entry.description = `${command.description} (current: ${this.providerLabel(this.sessionState.provider)})`;
1857
+ break;
1858
+ default:
1859
+ break;
1860
+ }
1861
+ entries.push(entry);
1862
+ }
1863
+ return entries;
1864
+ }
1865
+ summarizeSecretsForPalette() {
1866
+ const definitions = listSecretDefinitions();
1867
+ if (!definitions.length) {
1868
+ return { text: null };
1869
+ }
1870
+ const missing = definitions.filter((definition) => !getSecretValue(definition.id));
1871
+ if (missing.length === 0) {
1872
+ return { text: 'all configured', tone: 'success' };
1873
+ }
1874
+ const labels = missing.map((definition) => definition.label ?? definition.id);
1875
+ return { text: `missing ${this.formatList(labels)}`, tone: 'warn' };
1876
+ }
1877
+ getToolSelectionSummary() {
1878
+ const toolSettings = loadToolSettings();
1879
+ const selection = buildEnabledToolSet(toolSettings);
1880
+ const options = getToolToggleOptions();
1881
+ if (!options.length) {
1882
+ return null;
1883
+ }
1884
+ const enabledCount = options.filter((option) => selection.has(option.id)).length;
1885
+ return `${enabledCount}/${options.length} enabled`;
1886
+ }
1887
+ formatList(values, maxItems = 3) {
1888
+ if (!values.length) {
1889
+ return '';
1890
+ }
1891
+ const shown = values.slice(0, maxItems);
1892
+ const suffix = values.length > maxItems ? ', …' : '';
1893
+ return `${shown.join(', ')}${suffix}`;
1894
+ }
1852
1895
  buildSlashCommandList(header) {
1853
1896
  const lines = [theme.gradient.primary(header), ''];
1854
1897
  for (const command of this.slashCommands) {
@@ -2317,7 +2360,7 @@ When working in this codebase:
2317
2360
  this.autosaveIfEnabled();
2318
2361
  // Track metrics with Alpha Zero 2
2319
2362
  const elapsedMs = Date.now() - requestStartTime;
2320
- this.sessionMetrics.recordMessage(elapsedMs);
2363
+ this.alphaZeroMetrics.recordMessage(elapsedMs);
2321
2364
  if (!responseText?.trim()) {
2322
2365
  display.showWarning('The provider returned an empty response. Check your API key/provider selection or retry the prompt.');
2323
2366
  }
@@ -2335,14 +2378,10 @@ When working in this codebase:
2335
2378
  this.stopStreamingHeartbeat();
2336
2379
  this.isProcessing = false;
2337
2380
  this.terminalInput.setStreaming(false);
2338
- this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
2339
2381
  this.uiAdapter.endProcessing('Ready for prompts');
2340
2382
  this.setIdleStatus();
2341
2383
  display.newLine();
2342
2384
  this.updateStatusMessage(null);
2343
- // Claude Code style: Show unified status bar before prompt
2344
- // This creates consistent UI between startup and post-streaming
2345
- this.showUnifiedStatusBar();
2346
2385
  queueMicrotask(() => this.uiUpdates.setMode('idle'));
2347
2386
  // CRITICAL: Ensure readline prompt is active for user input
2348
2387
  // Claude Code style: New prompt naturally appears at bottom
@@ -2419,13 +2458,14 @@ When truly finished with ALL tasks, explicitly state "TASK_FULLY_COMPLETE".`;
2419
2458
  try {
2420
2459
  // Send the request and capture the response (streaming disabled)
2421
2460
  display.showThinking('Responding...');
2461
+ this.refreshStatusLine(true);
2422
2462
  const response = await agent.send(currentPrompt, true);
2423
2463
  await this.awaitPendingCleanup();
2424
2464
  this.captureHistorySnapshot();
2425
2465
  this.autosaveIfEnabled();
2426
2466
  // Track metrics
2427
2467
  const elapsedMs = Date.now() - overallStartTime;
2428
- this.sessionMetrics.recordMessage(elapsedMs);
2468
+ this.alphaZeroMetrics.recordMessage(elapsedMs);
2429
2469
  if (!response?.trim()) {
2430
2470
  display.showWarning('Model returned an empty response. Retrying this iteration...');
2431
2471
  consecutiveNoProgress++;
@@ -2562,7 +2602,6 @@ What's the next action?`;
2562
2602
  this.stopStreamingHeartbeat();
2563
2603
  this.isProcessing = false;
2564
2604
  this.terminalInput.setStreaming(false);
2565
- this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
2566
2605
  this.uiAdapter.endProcessing('Ready for prompts');
2567
2606
  this.setIdleStatus();
2568
2607
  this.updateStatusMessage(null);
@@ -2919,8 +2958,10 @@ What's the next action?`;
2919
2958
  try {
2920
2959
  // Send the error to the agent for fixing
2921
2960
  display.showThinking('Analyzing build errors');
2961
+ this.refreshStatusLine(true);
2922
2962
  const response = await this.agent.send(prompt, true);
2923
2963
  display.stopThinking();
2964
+ this.refreshStatusLine(true);
2924
2965
  if (response) {
2925
2966
  display.showAssistantMessage(response, { isFinal: true });
2926
2967
  }
@@ -2970,18 +3011,16 @@ What's the next action?`;
2970
3011
  display.showAssistantMessage(finalContent, enriched);
2971
3012
  }
2972
3013
  }
2973
- // Show status line at end (Claude Code style: "• Context X% used • Ready for prompts (2s)")
3014
+ // Status shown in mode controls bar - no separate status line needed
2974
3015
  display.stopThinking();
2975
- // Calculate context usage
2976
- let contextInfo;
3016
+ // Update context usage for mode controls display
2977
3017
  if (enriched.contextWindowTokens && metadata.usage) {
2978
3018
  const total = this.totalTokens(metadata.usage);
2979
3019
  if (total && total > 0) {
2980
3020
  const percentage = Math.round((total / enriched.contextWindowTokens) * 100);
2981
- contextInfo = { percentage, tokens: total };
3021
+ this.updateContextUsage(percentage);
2982
3022
  }
2983
3023
  }
2984
- display.showStatusLine('Ready for prompts', enriched.elapsedMs, contextInfo);
2985
3024
  // Auto-verify changes: build first (catches type errors), then tests
2986
3025
  void this.enforceAutoBuild('final-response');
2987
3026
  void this.enforceAutoTests('final-response');
@@ -3051,7 +3090,6 @@ What's the next action?`;
3051
3090
  this.stopStreamingHeartbeat();
3052
3091
  this.updateStatusMessage(null);
3053
3092
  this.terminalInput.setStreaming(false);
3054
- this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
3055
3093
  this.terminalInput.render();
3056
3094
  },
3057
3095
  onVerificationNeeded: () => {
@@ -3088,7 +3126,6 @@ What's the next action?`;
3088
3126
  resetChatBoxAfterModelSwap() {
3089
3127
  this.updateStatusMessage(null);
3090
3128
  this.terminalInput.setStreaming(false);
3091
- this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
3092
3129
  this.terminalInput.render();
3093
3130
  this.ensureReadlineReady();
3094
3131
  }
@@ -3153,9 +3190,14 @@ What's the next action?`;
3153
3190
  return null;
3154
3191
  }
3155
3192
  const usageRatio = total / windowTokens;
3193
+ this.latestTokenUsage = {
3194
+ used: total,
3195
+ limit: windowTokens,
3196
+ };
3156
3197
  // Always update context usage in the UI
3157
3198
  const percentUsed = Math.round(usageRatio * 100);
3158
3199
  this.updateContextUsage(percentUsed);
3200
+ this.refreshStatusLine(true);
3159
3201
  if (usageRatio < CONTEXT_USAGE_THRESHOLD) {
3160
3202
  return null;
3161
3203
  }
@@ -3422,6 +3464,23 @@ What's the next action?`;
3422
3464
  this.sessionState.reasoningEffort = preset.reasoningEffort;
3423
3465
  }
3424
3466
  }
3467
+ /**
3468
+ * Build the session banner using the unified layout renderer.
3469
+ * This is streamed as content, not stored in display.
3470
+ */
3471
+ buildBanner() {
3472
+ const terminalWidth = output.columns ?? 100;
3473
+ const width = Math.min(terminalWidth - 4, 110);
3474
+ return renderSessionFrame({
3475
+ profileLabel: this.profileLabel,
3476
+ profileName: this.profile,
3477
+ model: this.sessionState.model,
3478
+ provider: this.sessionState.provider,
3479
+ workspace: this.workingDir,
3480
+ version: this.version,
3481
+ width,
3482
+ });
3483
+ }
3425
3484
  refreshBannerSessionInfo() {
3426
3485
  const nextState = {
3427
3486
  model: this.sessionState.model,
@@ -3432,13 +3491,11 @@ What's the next action?`;
3432
3491
  return;
3433
3492
  }
3434
3493
  this.refreshContextGauge();
3435
- display.updateSessionInfo(nextState.model, nextState.provider);
3436
- // Update the persistent model info display in terminal input
3437
- this.terminalInput.setModelInfo(this.describeModelDetail());
3494
+ // Banner is no longer stored in display - it was streamed as content
3495
+ // Model/provider changes are visible in the control bar
3438
3496
  if (!this.isProcessing) {
3439
3497
  this.setIdleStatus();
3440
3498
  }
3441
- // Pinned header rows are disabled; scroll region handles all output.
3442
3499
  this.bannerSessionState = nextState;
3443
3500
  }
3444
3501
  providerLabel(id) {