erosolar-cli 1.7.275 → 1.7.276

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