erosolar-cli 1.7.277 → 1.7.279

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 +148 -24
  2. package/dist/alpha-zero/agentWrapper.d.ts +84 -0
  3. package/dist/alpha-zero/agentWrapper.d.ts.map +1 -0
  4. package/dist/alpha-zero/agentWrapper.js +171 -0
  5. package/dist/alpha-zero/agentWrapper.js.map +1 -0
  6. package/dist/alpha-zero/codeEvaluator.d.ts +25 -0
  7. package/dist/alpha-zero/codeEvaluator.d.ts.map +1 -0
  8. package/dist/alpha-zero/codeEvaluator.js +273 -0
  9. package/dist/alpha-zero/codeEvaluator.js.map +1 -0
  10. package/dist/alpha-zero/competitiveRunner.d.ts +66 -0
  11. package/dist/alpha-zero/competitiveRunner.d.ts.map +1 -0
  12. package/dist/alpha-zero/competitiveRunner.js +224 -0
  13. package/dist/alpha-zero/competitiveRunner.js.map +1 -0
  14. package/dist/alpha-zero/index.d.ts +67 -0
  15. package/dist/alpha-zero/index.d.ts.map +1 -0
  16. package/dist/alpha-zero/index.js +99 -0
  17. package/dist/alpha-zero/index.js.map +1 -0
  18. package/dist/alpha-zero/introspection.d.ts +128 -0
  19. package/dist/alpha-zero/introspection.d.ts.map +1 -0
  20. package/dist/alpha-zero/introspection.js +300 -0
  21. package/dist/alpha-zero/introspection.js.map +1 -0
  22. package/dist/alpha-zero/metricsTracker.d.ts +71 -0
  23. package/dist/alpha-zero/metricsTracker.d.ts.map +1 -0
  24. package/dist/{core → alpha-zero}/metricsTracker.js +5 -2
  25. package/dist/alpha-zero/metricsTracker.js.map +1 -0
  26. package/dist/alpha-zero/security/core.d.ts +125 -0
  27. package/dist/alpha-zero/security/core.d.ts.map +1 -0
  28. package/dist/alpha-zero/security/core.js +271 -0
  29. package/dist/alpha-zero/security/core.js.map +1 -0
  30. package/dist/alpha-zero/security/google.d.ts +125 -0
  31. package/dist/alpha-zero/security/google.d.ts.map +1 -0
  32. package/dist/alpha-zero/security/google.js +311 -0
  33. package/dist/alpha-zero/security/google.js.map +1 -0
  34. package/dist/alpha-zero/security/googleLoader.d.ts +17 -0
  35. package/dist/alpha-zero/security/googleLoader.d.ts.map +1 -0
  36. package/dist/alpha-zero/security/googleLoader.js +41 -0
  37. package/dist/alpha-zero/security/googleLoader.js.map +1 -0
  38. package/dist/alpha-zero/security/index.d.ts +29 -0
  39. package/dist/alpha-zero/security/index.d.ts.map +1 -0
  40. package/dist/alpha-zero/security/index.js +32 -0
  41. package/dist/alpha-zero/security/index.js.map +1 -0
  42. package/dist/alpha-zero/security/simulation.d.ts +124 -0
  43. package/dist/alpha-zero/security/simulation.d.ts.map +1 -0
  44. package/dist/alpha-zero/security/simulation.js +277 -0
  45. package/dist/alpha-zero/security/simulation.js.map +1 -0
  46. package/dist/alpha-zero/selfModification.d.ts +109 -0
  47. package/dist/alpha-zero/selfModification.d.ts.map +1 -0
  48. package/dist/alpha-zero/selfModification.js +233 -0
  49. package/dist/alpha-zero/selfModification.js.map +1 -0
  50. package/dist/alpha-zero/types.d.ts +170 -0
  51. package/dist/alpha-zero/types.d.ts.map +1 -0
  52. package/dist/alpha-zero/types.js +31 -0
  53. package/dist/alpha-zero/types.js.map +1 -0
  54. package/dist/bin/erosolar.js +0 -1
  55. package/dist/bin/erosolar.js.map +1 -1
  56. package/dist/capabilities/agentSpawningCapability.d.ts.map +1 -1
  57. package/dist/capabilities/agentSpawningCapability.js +31 -56
  58. package/dist/capabilities/agentSpawningCapability.js.map +1 -1
  59. package/dist/capabilities/securityTestingCapability.d.ts +13 -0
  60. package/dist/capabilities/securityTestingCapability.d.ts.map +1 -0
  61. package/dist/capabilities/securityTestingCapability.js +25 -0
  62. package/dist/capabilities/securityTestingCapability.js.map +1 -0
  63. package/dist/contracts/agent-schemas.json +15 -0
  64. package/dist/contracts/tools.schema.json +9 -0
  65. package/dist/core/agent.d.ts +2 -2
  66. package/dist/core/agent.d.ts.map +1 -1
  67. package/dist/core/agent.js.map +1 -1
  68. package/dist/core/aiFlowOptimizer.d.ts +26 -0
  69. package/dist/core/aiFlowOptimizer.d.ts.map +1 -0
  70. package/dist/core/aiFlowOptimizer.js +31 -0
  71. package/dist/core/aiFlowOptimizer.js.map +1 -0
  72. package/dist/core/aiOptimizationEngine.d.ts +158 -0
  73. package/dist/core/aiOptimizationEngine.d.ts.map +1 -0
  74. package/dist/core/aiOptimizationEngine.js +428 -0
  75. package/dist/core/aiOptimizationEngine.js.map +1 -0
  76. package/dist/core/aiOptimizationIntegration.d.ts +93 -0
  77. package/dist/core/aiOptimizationIntegration.d.ts.map +1 -0
  78. package/dist/core/aiOptimizationIntegration.js +250 -0
  79. package/dist/core/aiOptimizationIntegration.js.map +1 -0
  80. package/dist/core/customCommands.d.ts +0 -1
  81. package/dist/core/customCommands.d.ts.map +1 -1
  82. package/dist/core/customCommands.js +0 -3
  83. package/dist/core/customCommands.js.map +1 -1
  84. package/dist/core/enhancedErrorRecovery.d.ts +100 -0
  85. package/dist/core/enhancedErrorRecovery.d.ts.map +1 -0
  86. package/dist/core/enhancedErrorRecovery.js +345 -0
  87. package/dist/core/enhancedErrorRecovery.js.map +1 -0
  88. package/dist/core/hooksSystem.d.ts +65 -0
  89. package/dist/core/hooksSystem.d.ts.map +1 -0
  90. package/dist/core/hooksSystem.js +273 -0
  91. package/dist/core/hooksSystem.js.map +1 -0
  92. package/dist/core/memorySystem.d.ts +48 -0
  93. package/dist/core/memorySystem.d.ts.map +1 -0
  94. package/dist/core/memorySystem.js +271 -0
  95. package/dist/core/memorySystem.js.map +1 -0
  96. package/dist/core/toolPreconditions.d.ts.map +1 -1
  97. package/dist/core/toolPreconditions.js +14 -0
  98. package/dist/core/toolPreconditions.js.map +1 -1
  99. package/dist/core/toolRuntime.d.ts +1 -22
  100. package/dist/core/toolRuntime.d.ts.map +1 -1
  101. package/dist/core/toolRuntime.js +5 -0
  102. package/dist/core/toolRuntime.js.map +1 -1
  103. package/dist/core/toolValidation.d.ts.map +1 -1
  104. package/dist/core/toolValidation.js +3 -14
  105. package/dist/core/toolValidation.js.map +1 -1
  106. package/dist/core/unified/errors.d.ts +189 -0
  107. package/dist/core/unified/errors.d.ts.map +1 -0
  108. package/dist/core/unified/errors.js +497 -0
  109. package/dist/core/unified/errors.js.map +1 -0
  110. package/dist/core/unified/index.d.ts +19 -0
  111. package/dist/core/unified/index.d.ts.map +1 -0
  112. package/dist/core/unified/index.js +68 -0
  113. package/dist/core/unified/index.js.map +1 -0
  114. package/dist/core/unified/schema.d.ts +101 -0
  115. package/dist/core/unified/schema.d.ts.map +1 -0
  116. package/dist/core/unified/schema.js +350 -0
  117. package/dist/core/unified/schema.js.map +1 -0
  118. package/dist/core/unified/toolRuntime.d.ts +179 -0
  119. package/dist/core/unified/toolRuntime.d.ts.map +1 -0
  120. package/dist/core/unified/toolRuntime.js +517 -0
  121. package/dist/core/unified/toolRuntime.js.map +1 -0
  122. package/dist/core/unified/tools.d.ts +127 -0
  123. package/dist/core/unified/tools.d.ts.map +1 -0
  124. package/dist/core/unified/tools.js +1333 -0
  125. package/dist/core/unified/tools.js.map +1 -0
  126. package/dist/core/unified/types.d.ts +352 -0
  127. package/dist/core/unified/types.d.ts.map +1 -0
  128. package/dist/core/unified/types.js +12 -0
  129. package/dist/core/unified/types.js.map +1 -0
  130. package/dist/core/unified/version.d.ts +209 -0
  131. package/dist/core/unified/version.d.ts.map +1 -0
  132. package/dist/core/unified/version.js +454 -0
  133. package/dist/core/unified/version.js.map +1 -0
  134. package/dist/core/validationRunner.d.ts +3 -1
  135. package/dist/core/validationRunner.d.ts.map +1 -1
  136. package/dist/core/validationRunner.js.map +1 -1
  137. package/dist/headless/headlessApp.d.ts.map +1 -1
  138. package/dist/headless/headlessApp.js +0 -21
  139. package/dist/headless/headlessApp.js.map +1 -1
  140. package/dist/mcp/sseClient.d.ts.map +1 -1
  141. package/dist/mcp/sseClient.js +18 -9
  142. package/dist/mcp/sseClient.js.map +1 -1
  143. package/dist/plugins/tools/build/buildPlugin.d.ts +6 -0
  144. package/dist/plugins/tools/build/buildPlugin.d.ts.map +1 -1
  145. package/dist/plugins/tools/build/buildPlugin.js +10 -4
  146. package/dist/plugins/tools/build/buildPlugin.js.map +1 -1
  147. package/dist/plugins/tools/nodeDefaults.d.ts.map +1 -1
  148. package/dist/plugins/tools/nodeDefaults.js +2 -0
  149. package/dist/plugins/tools/nodeDefaults.js.map +1 -1
  150. package/dist/plugins/tools/security/securityPlugin.d.ts +3 -0
  151. package/dist/plugins/tools/security/securityPlugin.d.ts.map +1 -0
  152. package/dist/plugins/tools/security/securityPlugin.js +12 -0
  153. package/dist/plugins/tools/security/securityPlugin.js.map +1 -0
  154. package/dist/runtime/agentSession.d.ts +2 -2
  155. package/dist/runtime/agentSession.d.ts.map +1 -1
  156. package/dist/runtime/agentSession.js +2 -2
  157. package/dist/runtime/agentSession.js.map +1 -1
  158. package/dist/security/active-stack-security.d.ts +112 -0
  159. package/dist/security/active-stack-security.d.ts.map +1 -0
  160. package/dist/security/active-stack-security.js +296 -0
  161. package/dist/security/active-stack-security.js.map +1 -0
  162. package/dist/security/advanced-persistence-research.d.ts +92 -0
  163. package/dist/security/advanced-persistence-research.d.ts.map +1 -0
  164. package/dist/security/advanced-persistence-research.js +195 -0
  165. package/dist/security/advanced-persistence-research.js.map +1 -0
  166. package/dist/security/advanced-targeting.d.ts +119 -0
  167. package/dist/security/advanced-targeting.d.ts.map +1 -0
  168. package/dist/security/advanced-targeting.js +233 -0
  169. package/dist/security/advanced-targeting.js.map +1 -0
  170. package/dist/security/assessment/vulnerabilityAssessment.d.ts +104 -0
  171. package/dist/security/assessment/vulnerabilityAssessment.d.ts.map +1 -0
  172. package/dist/security/assessment/vulnerabilityAssessment.js +315 -0
  173. package/dist/security/assessment/vulnerabilityAssessment.js.map +1 -0
  174. package/dist/security/authorization/securityAuthorization.d.ts +88 -0
  175. package/dist/security/authorization/securityAuthorization.d.ts.map +1 -0
  176. package/dist/security/authorization/securityAuthorization.js +172 -0
  177. package/dist/security/authorization/securityAuthorization.js.map +1 -0
  178. package/dist/security/comprehensive-targeting.d.ts +85 -0
  179. package/dist/security/comprehensive-targeting.d.ts.map +1 -0
  180. package/dist/security/comprehensive-targeting.js +438 -0
  181. package/dist/security/comprehensive-targeting.js.map +1 -0
  182. package/dist/security/global-security-integration.d.ts +91 -0
  183. package/dist/security/global-security-integration.d.ts.map +1 -0
  184. package/dist/security/global-security-integration.js +218 -0
  185. package/dist/security/global-security-integration.js.map +1 -0
  186. package/dist/security/index.d.ts +38 -0
  187. package/dist/security/index.d.ts.map +1 -0
  188. package/dist/security/index.js +47 -0
  189. package/dist/security/index.js.map +1 -0
  190. package/dist/security/persistence-analyzer.d.ts +56 -0
  191. package/dist/security/persistence-analyzer.d.ts.map +1 -0
  192. package/dist/security/persistence-analyzer.js +187 -0
  193. package/dist/security/persistence-analyzer.js.map +1 -0
  194. package/dist/security/persistence-cli.d.ts +36 -0
  195. package/dist/security/persistence-cli.d.ts.map +1 -0
  196. package/dist/security/persistence-cli.js +160 -0
  197. package/dist/security/persistence-cli.js.map +1 -0
  198. package/dist/security/persistence-research.d.ts +92 -0
  199. package/dist/security/persistence-research.d.ts.map +1 -0
  200. package/dist/security/persistence-research.js +364 -0
  201. package/dist/security/persistence-research.js.map +1 -0
  202. package/dist/security/research/persistenceResearch.d.ts +97 -0
  203. package/dist/security/research/persistenceResearch.d.ts.map +1 -0
  204. package/dist/security/research/persistenceResearch.js +282 -0
  205. package/dist/security/research/persistenceResearch.js.map +1 -0
  206. package/dist/security/security-integration.d.ts +74 -0
  207. package/dist/security/security-integration.d.ts.map +1 -0
  208. package/dist/security/security-integration.js +137 -0
  209. package/dist/security/security-integration.js.map +1 -0
  210. package/dist/security/security-testing-framework.d.ts +112 -0
  211. package/dist/security/security-testing-framework.d.ts.map +1 -0
  212. package/dist/security/security-testing-framework.js +364 -0
  213. package/dist/security/security-testing-framework.js.map +1 -0
  214. package/dist/security/simulation/attackSimulation.d.ts +93 -0
  215. package/dist/security/simulation/attackSimulation.d.ts.map +1 -0
  216. package/dist/security/simulation/attackSimulation.js +341 -0
  217. package/dist/security/simulation/attackSimulation.js.map +1 -0
  218. package/dist/security/strategic-operations.d.ts +100 -0
  219. package/dist/security/strategic-operations.d.ts.map +1 -0
  220. package/dist/security/strategic-operations.js +276 -0
  221. package/dist/security/strategic-operations.js.map +1 -0
  222. package/dist/security/tool-security-wrapper.d.ts +58 -0
  223. package/dist/security/tool-security-wrapper.d.ts.map +1 -0
  224. package/dist/security/tool-security-wrapper.js +156 -0
  225. package/dist/security/tool-security-wrapper.js.map +1 -0
  226. package/dist/shell/claudeCodeStreamHandler.d.ts +145 -0
  227. package/dist/shell/claudeCodeStreamHandler.d.ts.map +1 -0
  228. package/dist/shell/claudeCodeStreamHandler.js +322 -0
  229. package/dist/shell/claudeCodeStreamHandler.js.map +1 -0
  230. package/dist/shell/inputQueueManager.d.ts +144 -0
  231. package/dist/shell/inputQueueManager.d.ts.map +1 -0
  232. package/dist/shell/inputQueueManager.js +290 -0
  233. package/dist/shell/inputQueueManager.js.map +1 -0
  234. package/dist/shell/interactiveShell.d.ts +7 -10
  235. package/dist/shell/interactiveShell.d.ts.map +1 -1
  236. package/dist/shell/interactiveShell.js +156 -198
  237. package/dist/shell/interactiveShell.js.map +1 -1
  238. package/dist/shell/metricsTracker.d.ts +60 -0
  239. package/dist/shell/metricsTracker.d.ts.map +1 -0
  240. package/dist/shell/metricsTracker.js +119 -0
  241. package/dist/shell/metricsTracker.js.map +1 -0
  242. package/dist/shell/shellApp.d.ts +0 -2
  243. package/dist/shell/shellApp.d.ts.map +1 -1
  244. package/dist/shell/shellApp.js +4 -55
  245. package/dist/shell/shellApp.js.map +1 -1
  246. package/dist/shell/streamingOutputManager.d.ts +115 -0
  247. package/dist/shell/streamingOutputManager.d.ts.map +1 -0
  248. package/dist/shell/streamingOutputManager.js +225 -0
  249. package/dist/shell/streamingOutputManager.js.map +1 -0
  250. package/dist/shell/systemPrompt.d.ts.map +1 -1
  251. package/dist/shell/systemPrompt.js +4 -1
  252. package/dist/shell/systemPrompt.js.map +1 -1
  253. package/dist/shell/terminalInput.d.ts +178 -78
  254. package/dist/shell/terminalInput.d.ts.map +1 -1
  255. package/dist/shell/terminalInput.js +877 -494
  256. package/dist/shell/terminalInput.js.map +1 -1
  257. package/dist/shell/terminalInputAdapter.d.ts +34 -28
  258. package/dist/shell/terminalInputAdapter.d.ts.map +1 -1
  259. package/dist/shell/terminalInputAdapter.js +47 -26
  260. package/dist/shell/terminalInputAdapter.js.map +1 -1
  261. package/dist/subagents/taskRunner.d.ts +1 -7
  262. package/dist/subagents/taskRunner.d.ts.map +1 -1
  263. package/dist/subagents/taskRunner.js +47 -180
  264. package/dist/subagents/taskRunner.js.map +1 -1
  265. package/dist/tools/securityTools.d.ts +22 -0
  266. package/dist/tools/securityTools.d.ts.map +1 -0
  267. package/dist/tools/securityTools.js +448 -0
  268. package/dist/tools/securityTools.js.map +1 -0
  269. package/dist/ui/ShellUIAdapter.d.ts.map +1 -1
  270. package/dist/ui/ShellUIAdapter.js +12 -13
  271. package/dist/ui/ShellUIAdapter.js.map +1 -1
  272. package/dist/ui/display.d.ts +13 -26
  273. package/dist/ui/display.d.ts.map +1 -1
  274. package/dist/ui/display.js +69 -147
  275. package/dist/ui/display.js.map +1 -1
  276. package/dist/ui/persistentPrompt.d.ts +50 -0
  277. package/dist/ui/persistentPrompt.d.ts.map +1 -0
  278. package/dist/ui/persistentPrompt.js +92 -0
  279. package/dist/ui/persistentPrompt.js.map +1 -0
  280. package/dist/ui/terminalUISchema.d.ts +195 -0
  281. package/dist/ui/terminalUISchema.d.ts.map +1 -0
  282. package/dist/ui/terminalUISchema.js +113 -0
  283. package/dist/ui/terminalUISchema.js.map +1 -0
  284. package/dist/ui/theme.d.ts.map +1 -1
  285. package/dist/ui/theme.js +8 -6
  286. package/dist/ui/theme.js.map +1 -1
  287. package/dist/ui/toolDisplay.d.ts +158 -0
  288. package/dist/ui/toolDisplay.d.ts.map +1 -1
  289. package/dist/ui/toolDisplay.js +348 -0
  290. package/dist/ui/toolDisplay.js.map +1 -1
  291. package/dist/ui/unified/layout.d.ts +0 -1
  292. package/dist/ui/unified/layout.d.ts.map +1 -1
  293. package/dist/ui/unified/layout.js +25 -15
  294. package/dist/ui/unified/layout.js.map +1 -1
  295. package/package.json +1 -1
  296. package/scripts/deploy-security-capabilities.js +178 -0
  297. package/dist/core/hooks.d.ts +0 -113
  298. package/dist/core/hooks.d.ts.map +0 -1
  299. package/dist/core/hooks.js +0 -267
  300. package/dist/core/hooks.js.map +0 -1
  301. package/dist/core/metricsTracker.d.ts +0 -122
  302. package/dist/core/metricsTracker.d.ts.map +0 -1
  303. package/dist/core/metricsTracker.js.map +0 -1
  304. package/dist/core/securityAssessment.d.ts +0 -91
  305. package/dist/core/securityAssessment.d.ts.map +0 -1
  306. package/dist/core/securityAssessment.js +0 -580
  307. package/dist/core/securityAssessment.js.map +0 -1
  308. package/dist/core/verification.d.ts +0 -137
  309. package/dist/core/verification.d.ts.map +0 -1
  310. package/dist/core/verification.js +0 -323
  311. package/dist/core/verification.js.map +0 -1
  312. package/dist/subagents/agentConfig.d.ts +0 -27
  313. package/dist/subagents/agentConfig.d.ts.map +0 -1
  314. package/dist/subagents/agentConfig.js +0 -89
  315. package/dist/subagents/agentConfig.js.map +0 -1
  316. package/dist/subagents/agentRegistry.d.ts +0 -33
  317. package/dist/subagents/agentRegistry.d.ts.map +0 -1
  318. package/dist/subagents/agentRegistry.js +0 -162
  319. package/dist/subagents/agentRegistry.js.map +0 -1
  320. package/dist/utils/frontmatter.d.ts +0 -10
  321. package/dist/utils/frontmatter.d.ts.map +0 -1
  322. package/dist/utils/frontmatter.js +0 -78
  323. package/dist/utils/frontmatter.js.map +0 -1
@@ -2,7 +2,7 @@ import { stdin as input, stdout as output, exit } from 'node:process';
2
2
  import { exec } from 'node:child_process';
3
3
  import { promisify } from 'node:util';
4
4
  import { display } from '../ui/display.js';
5
- import { theme } from '../ui/theme.js';
5
+ import { theme, formatUserPrompt } from '../ui/theme.js';
6
6
  import { getContextWindowTokens } from '../core/contextWindow.js';
7
7
  import { ensureSecretForProvider, getSecretDefinitionForProvider, getSecretValue, listSecretDefinitions, maskSecret, setSecretValue, } from '../core/secretStore.js';
8
8
  import { saveActiveProfilePreference, saveModelPreference, loadToolSettings, saveToolSettings, clearToolSettings, clearActiveProfilePreference, loadSessionPreferences, saveSessionPreferences, } from '../core/preferences.js';
@@ -19,8 +19,9 @@ import { SkillRepository } from '../skills/skillRepository.js';
19
19
  import { createSkillTools } from '../tools/skillTools.js';
20
20
  import { FileChangeTracker } from './fileChangeTracker.js';
21
21
  import { formatShortcutsHelp } from '../ui/shortcutsHelp.js';
22
- import { MetricsTracker } from '../core/metricsTracker.js';
22
+ import { MetricsTracker } from './metricsTracker.js';
23
23
  import { listAvailablePlugins } from '../plugins/index.js';
24
+ import { loadMemory, listMemoryPaths, getDefaultProjectMemoryPath, getUserMemoryEditPath, } from '../core/memorySystem.js';
24
25
  import { TerminalInputAdapter } from './terminalInputAdapter.js';
25
26
  import { isUpdateInProgress } from './updateManager.js';
26
27
  import { writeLock } from '../ui/writeLock.js';
@@ -34,7 +35,6 @@ const DROPDOWN_COLORS = [
34
35
  theme.success,
35
36
  theme.warning,
36
37
  ];
37
- const STREAMING_SPINNER_FRAMES = ['◐', '◓', '◑', '◒'];
38
38
  // Load MODEL_PRESETS from centralized schema
39
39
  const MODEL_PRESETS = getModels().map((model) => ({
40
40
  id: model.id,
@@ -49,13 +49,11 @@ const MODEL_PRESETS = getModels().map((model) => ({
49
49
  const BASE_SLASH_COMMANDS = getSlashCommands().map((cmd) => ({
50
50
  command: cmd.command,
51
51
  description: cmd.description,
52
- category: cmd.category,
53
52
  }));
54
53
  // Load PROVIDER_LABELS from centralized schema
55
54
  const PROVIDER_LABELS = Object.fromEntries(getProviders().map((provider) => [provider.id, provider.label]));
56
55
  // Allow enough time for paste detection to kick in before flushing buffered lines
57
56
  const CONTEXT_USAGE_THRESHOLD = 0.9;
58
- const CONTEXT_AUTOCOMPACT_PERCENT = Math.round(CONTEXT_USAGE_THRESHOLD * 100);
59
57
  const CONTEXT_RECENT_MESSAGE_COUNT = 12;
60
58
  const CONTEXT_CLEANUP_CHARS_PER_CHUNK = 6000;
61
59
  const CONTEXT_CLEANUP_MAX_OUTPUT_TOKENS = 800;
@@ -96,12 +94,11 @@ export class InteractiveShell {
96
94
  uiAdapter;
97
95
  uiUpdates;
98
96
  _fileChangeTracker = new FileChangeTracker(); // Reserved for future file tracking features
99
- alphaZeroMetrics; // Alpha Zero 2 performance tracking
97
+ sessionMetrics; // Session performance tracking
100
98
  statusSubscription = null;
101
99
  followUpQueue = [];
102
100
  isDrainingQueue = false;
103
101
  activeContextWindowTokens = null;
104
- latestTokenUsage = { used: null, limit: null };
105
102
  sessionPreferences;
106
103
  autosaveEnabled;
107
104
  autoContinueEnabled;
@@ -132,7 +129,6 @@ export class InteractiveShell {
132
129
  statusLineState = null;
133
130
  statusMessageOverride = null;
134
131
  promptRefreshTimer = null;
135
- launchPaletteShown = false;
136
132
  constructor(config) {
137
133
  this.profile = config.profile;
138
134
  this.profileLabel = config.profileLabel;
@@ -166,7 +162,6 @@ export class InteractiveShell {
166
162
  this.slashCommands.push({
167
163
  command: '/agents',
168
164
  description: 'Select the default agent profile (applies on next launch)',
169
- category: 'configuration',
170
165
  });
171
166
  }
172
167
  this.customCommands = loadCustomSlashCommands();
@@ -175,21 +170,18 @@ export class InteractiveShell {
175
170
  this.slashCommands.push({
176
171
  command: custom.command,
177
172
  description: `${custom.description} (custom)`,
178
- category: custom.category ?? 'other',
179
173
  });
180
174
  }
181
175
  if (!this.slashCommands.some((cmd) => cmd.command === '/exit')) {
182
176
  this.slashCommands.push({
183
177
  command: '/exit',
184
178
  description: 'Quit the CLI immediately',
185
- category: 'other',
186
179
  });
187
180
  }
188
181
  // Add /plugins command
189
182
  this.slashCommands.push({
190
183
  command: '/plugins',
191
184
  description: 'Show available and loaded plugins',
192
- category: 'configuration',
193
185
  });
194
186
  this.statusTracker = config.statusTracker;
195
187
  this.ui = config.ui;
@@ -224,18 +216,17 @@ export class InteractiveShell {
224
216
  });
225
217
  // Register output interceptor for cursor positioning during streaming
226
218
  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 as content into the scroll region (not stored, just streamed)
223
+ display.renderBannerToContent();
227
224
  // Initialize Alpha Zero 2 metrics tracking
228
- this.alphaZeroMetrics = new MetricsTracker(`${this.profile}-${Date.now()}`);
225
+ this.sessionMetrics = new MetricsTracker(`${this.profile}-${Date.now()}`);
229
226
  this.setupStatusTracking();
230
227
  this.refreshContextGauge();
231
228
  this.terminalInput.start();
232
229
  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
- }
239
230
  this.rebuildAgent();
240
231
  this.setupHandlers();
241
232
  this.refreshBannerSessionInfo();
@@ -287,15 +278,9 @@ export class InteractiveShell {
287
278
  await this.processInputBlock(initialPrompt);
288
279
  return;
289
280
  }
290
- this.showLaunchCommandPalette();
291
281
  // Ensure the terminal input is visible
292
282
  this.terminalInput.render();
293
283
  }
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
- }
299
284
  /**
300
285
  * TerminalInputAdapter submit handler
301
286
  */
@@ -309,8 +294,9 @@ export class InteractiveShell {
309
294
  this.handleInputChange('');
310
295
  return;
311
296
  }
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.
297
+ // Enter streaming mode BEFORE logging prompt - this positions cursor correctly
298
+ // so content appears right after the banner, not at bottom with blank space above
299
+ this.terminalInput.setStreaming(true);
314
300
  this.logUserPrompt(approved);
315
301
  void this.processInputBlock(approved).catch((err) => {
316
302
  display.showError(err instanceof Error ? err.message : String(err), err);
@@ -512,9 +498,10 @@ export class InteractiveShell {
512
498
  // Dispose unified UI adapter
513
499
  this.uiAdapter.dispose();
514
500
  display.newLine();
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)));
501
+ console.log(theme.gradient.warm('━'.repeat(50)));
502
+ console.log(` ${theme.gradient.cool('Goodbye!')} ${theme.ui.muted('·')} ${theme.info('support@ero.solar')}`);
503
+ console.log(` ${theme.ui.muted('Read:')} ${theme.accent('anthropic.com/news/disrupting-AI-espionage')}`);
504
+ console.log(theme.gradient.warm('━'.repeat(50)));
518
505
  exit(0);
519
506
  }
520
507
  /**
@@ -684,14 +671,13 @@ export class InteractiveShell {
684
671
  });
685
672
  }
686
673
  setProcessingStatus(detail) {
687
- this.latestTokenUsage = { used: null, limit: this.latestTokenUsage.limit };
688
674
  this.statusTracker.setBase('Working on your request', {
689
675
  detail: this.describeStatusDetail(detail),
690
676
  tone: 'info',
691
677
  });
692
678
  }
693
679
  describeStatusDetail(detail) {
694
- const parts = detail?.trim() ? [detail.trim()] : [];
680
+ const parts = [detail?.trim() || this.describeModelDetail()];
695
681
  const queued = this.followUpQueue.length;
696
682
  if (queued > 0) {
697
683
  parts.push(`${queued} follow-up${queued === 1 ? '' : 's'} queued`);
@@ -704,18 +690,12 @@ export class InteractiveShell {
704
690
  }
705
691
  refreshContextGauge() {
706
692
  const tokens = getContextWindowTokens(this.sessionState.model);
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
- }
693
+ this.activeContextWindowTokens =
694
+ typeof tokens === 'number' && Number.isFinite(tokens) ? tokens : null;
715
695
  }
716
696
  updateContextUsage(percentage) {
717
697
  this.uiAdapter.updateContextUsage(percentage);
718
- this.terminalInput.setContextUsage(percentage, CONTEXT_AUTOCOMPACT_PERCENT);
698
+ this.terminalInput.setContextUsage(percentage);
719
699
  }
720
700
  refreshControlBar() {
721
701
  this.terminalInput.setModeToggles({
@@ -723,9 +703,9 @@ export class InteractiveShell {
723
703
  autoContinueEnabled: this.autoContinueEnabled,
724
704
  verificationHotkey: 'alt+v',
725
705
  autoContinueHotkey: 'alt+c',
726
- thinkingModeLabel: this.thinkingMode,
727
- thinkingHotkey: '/thinking',
728
706
  });
707
+ // Update persistent model info display
708
+ this.terminalInput.setModelInfo(this.describeModelDetail());
729
709
  this.refreshStatusLine();
730
710
  this.terminalInput.render();
731
711
  }
@@ -756,25 +736,6 @@ export class InteractiveShell {
756
736
  // Set main status (tool execution, etc.) - shown when not overridden
757
737
  const statusText = this.formatStatusLine(this.statusLineState);
758
738
  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
- });
778
739
  if (forceRender) {
779
740
  this.terminalInput.render();
780
741
  }
@@ -834,14 +795,13 @@ export class InteractiveShell {
834
795
  this.terminalInput.render();
835
796
  }
836
797
  /**
837
- * Log user prompt to the scroll region so it's part of the conversation flow.
798
+ * Log the user's prompt as a visible message in the conversation.
799
+ * This creates a persistent log entry that remains visible during and after streaming.
838
800
  */
839
801
  logUserPrompt(text) {
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);
802
+ // Display the user's prompt with the standard prefix
803
+ const prefix = formatUserPrompt();
804
+ display.stream(`\n${prefix}${text}\n\n`);
845
805
  }
846
806
  requestPromptRefresh(force = false) {
847
807
  if (force) {
@@ -869,29 +829,9 @@ export class InteractiveShell {
869
829
  this.uiUpdates.setMode('streaming');
870
830
  this.streamingHeartbeatStart = Date.now();
871
831
  this.streamingHeartbeatFrame = 0;
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
- });
832
+ // Note: We don't start a heartbeat during streaming anymore
833
+ // because the UI shouldn't be rendering during streaming.
834
+ // The streaming status is shown in the streaming header instead.
895
835
  }
896
836
  stopStreamingHeartbeat() {
897
837
  // Exit global streaming mode - allows UI to render again
@@ -907,28 +847,10 @@ export class InteractiveShell {
907
847
  // Force refresh to update the input area now that streaming has ended
908
848
  this.refreshStatusLine(true);
909
849
  }
910
- buildStreamingStatus(label, elapsedSeconds) {
850
+ buildStreamingStatus(label) {
911
851
  const detail = this.describeModelDetail();
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`;
852
+ const prefix = theme.info('');
853
+ return detail ? `${prefix} ${label} ${theme.ui.muted('·')} ${detail}` : `${prefix} ${label}`;
932
854
  }
933
855
  refreshQueueIndicators() {
934
856
  if (this.isProcessing) {
@@ -1176,6 +1098,17 @@ export class InteractiveShell {
1176
1098
  case '/discover':
1177
1099
  await this.discoverModelsCommand();
1178
1100
  break;
1101
+ case '/memory':
1102
+ this.handleMemoryCommand(input);
1103
+ break;
1104
+ case '/clear':
1105
+ display.clear();
1106
+ this.cachedHistory = [];
1107
+ display.showInfo('Conversation cleared.');
1108
+ break;
1109
+ case '/help':
1110
+ this.showHelp();
1111
+ break;
1179
1112
  default:
1180
1113
  if (!(await this.tryCustomSlashCommand(command, input))) {
1181
1114
  display.showWarning(`Unknown command "${command}".`);
@@ -1484,6 +1417,99 @@ export class InteractiveShell {
1484
1417
  // Display keyboard shortcuts help (Claude Code style)
1485
1418
  display.showSystemMessage(formatShortcutsHelp());
1486
1419
  }
1420
+ handleMemoryCommand(input) {
1421
+ const tokens = input.trim().split(/\s+/).slice(1);
1422
+ const action = (tokens.shift() ?? 'show').toLowerCase();
1423
+ switch (action) {
1424
+ case '':
1425
+ case 'show':
1426
+ case 'list': {
1427
+ this.showMemoryStatus();
1428
+ break;
1429
+ }
1430
+ case 'paths': {
1431
+ this.showMemoryPaths();
1432
+ break;
1433
+ }
1434
+ case 'edit': {
1435
+ const level = (tokens[0] ?? 'project').toLowerCase();
1436
+ this.openMemoryForEdit(level);
1437
+ break;
1438
+ }
1439
+ default:
1440
+ display.showWarning('Usage: /memory [show|paths|edit <user|project>]');
1441
+ break;
1442
+ }
1443
+ }
1444
+ showMemoryStatus() {
1445
+ const memory = loadMemory(this.workingDir);
1446
+ const lines = [];
1447
+ lines.push(theme.bold('Persistent Memory'));
1448
+ lines.push('');
1449
+ if (memory.sources.length === 0) {
1450
+ lines.push(theme.secondary('No memory files found.'));
1451
+ lines.push('');
1452
+ lines.push(`Create ${theme.info('EROSOLAR.md')} in your project to add persistent context.`);
1453
+ lines.push(`Use ${theme.info('/memory edit project')} to create one.`);
1454
+ }
1455
+ else {
1456
+ for (const source of memory.sources) {
1457
+ const levelLabel = source.level === 'enterprise' ? 'Enterprise' :
1458
+ source.level === 'user' ? 'User' : 'Project';
1459
+ const preview = source.content.slice(0, 200).replace(/\n/g, ' ').trim();
1460
+ const truncated = source.content.length > 200 ? '...' : '';
1461
+ lines.push(`${theme.success('●')} ${theme.bold(levelLabel)}: ${source.path}`);
1462
+ lines.push(` ${theme.dim(preview + truncated)}`);
1463
+ lines.push('');
1464
+ }
1465
+ if (memory.importedPaths.length > memory.sources.length) {
1466
+ lines.push(theme.secondary(`Imported ${memory.importedPaths.length - memory.sources.length} additional files via @imports.`));
1467
+ }
1468
+ }
1469
+ display.showSystemMessage(lines.join('\n'));
1470
+ }
1471
+ showMemoryPaths() {
1472
+ const paths = listMemoryPaths(this.workingDir);
1473
+ const lines = [];
1474
+ lines.push(theme.bold('Memory File Locations'));
1475
+ lines.push('');
1476
+ for (const { level, path, exists } of paths) {
1477
+ const icon = exists ? theme.success('✓') : theme.dim('○');
1478
+ const levelLabel = level.charAt(0).toUpperCase() + level.slice(1);
1479
+ lines.push(`${icon} ${levelLabel}: ${path}`);
1480
+ }
1481
+ lines.push('');
1482
+ lines.push(theme.secondary('Create any of these files to add persistent memory.'));
1483
+ lines.push(theme.secondary('Use @path/to/file.md syntax to import other files.'));
1484
+ display.showSystemMessage(lines.join('\n'));
1485
+ }
1486
+ openMemoryForEdit(level) {
1487
+ let targetPath;
1488
+ if (level === 'user') {
1489
+ targetPath = getUserMemoryEditPath();
1490
+ }
1491
+ else if (level === 'project') {
1492
+ targetPath = getDefaultProjectMemoryPath(this.workingDir);
1493
+ }
1494
+ else {
1495
+ display.showWarning('Specify "user" or "project" to edit. Enterprise memory is read-only.');
1496
+ return;
1497
+ }
1498
+ display.showInfo(`Memory file: ${targetPath}`);
1499
+ display.showInfo('Create or edit this file to add persistent context for the AI.');
1500
+ display.showInfo('');
1501
+ display.showInfo('Example EROSOLAR.md content:');
1502
+ display.showInfo('');
1503
+ display.showInfo(theme.dim(`# Project Guidelines
1504
+
1505
+ When working in this codebase:
1506
+ - Follow TypeScript strict mode conventions
1507
+ - Use functional patterns where appropriate
1508
+ - Run tests before committing
1509
+
1510
+ @./docs/coding-standards.md
1511
+ `));
1512
+ }
1487
1513
  showFileChangeSummary() {
1488
1514
  const summary = this._fileChangeTracker.getSummary();
1489
1515
  const changes = this._fileChangeTracker.getAllChanges();
@@ -1526,11 +1552,11 @@ export class InteractiveShell {
1526
1552
  display.showSystemMessage(lines.join('\n'));
1527
1553
  }
1528
1554
  showAlphaZeroMetrics() {
1529
- const summary = this.alphaZeroMetrics.getPerformanceSummary();
1555
+ const summary = this.sessionMetrics.getPerformanceSummary();
1530
1556
  display.showSystemMessage(summary);
1531
1557
  }
1532
1558
  showImprovementSuggestions() {
1533
- const suggestions = this.alphaZeroMetrics.getImprovementSuggestions();
1559
+ const suggestions = this.sessionMetrics.getImprovementSuggestions();
1534
1560
  if (suggestions.length === 0) {
1535
1561
  display.showInfo('No improvement suggestions at this time. Keep using the shell to generate metrics!');
1536
1562
  return;
@@ -1576,9 +1602,7 @@ export class InteractiveShell {
1576
1602
  }
1577
1603
  }
1578
1604
  lines.push(theme.secondary('CLI Flags:'));
1579
- lines.push(' --alpha-zero Enable Alpha Zero 2 RL framework');
1580
1605
  lines.push(' --coding Enable enhanced coding tools');
1581
- lines.push(' --security Enable security research tools');
1582
1606
  lines.push(' --all-plugins Enable all optional plugins');
1583
1607
  display.showSystemMessage(lines.join('\n'));
1584
1608
  }
@@ -1822,75 +1846,6 @@ export class InteractiveShell {
1822
1846
  }
1823
1847
  return `${warning.label}: ${warning.reason}.`;
1824
1848
  }
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
- }
1894
1849
  buildSlashCommandList(header) {
1895
1850
  const lines = [theme.gradient.primary(header), ''];
1896
1851
  for (const command of this.slashCommands) {
@@ -2359,7 +2314,7 @@ export class InteractiveShell {
2359
2314
  this.autosaveIfEnabled();
2360
2315
  // Track metrics with Alpha Zero 2
2361
2316
  const elapsedMs = Date.now() - requestStartTime;
2362
- this.alphaZeroMetrics.recordMessage(elapsedMs);
2317
+ this.sessionMetrics.recordMessage(elapsedMs);
2363
2318
  if (!responseText?.trim()) {
2364
2319
  display.showWarning('The provider returned an empty response. Check your API key/provider selection or retry the prompt.');
2365
2320
  }
@@ -2377,10 +2332,14 @@ export class InteractiveShell {
2377
2332
  this.stopStreamingHeartbeat();
2378
2333
  this.isProcessing = false;
2379
2334
  this.terminalInput.setStreaming(false);
2335
+ this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
2380
2336
  this.uiAdapter.endProcessing('Ready for prompts');
2381
2337
  this.setIdleStatus();
2382
2338
  display.newLine();
2383
2339
  this.updateStatusMessage(null);
2340
+ // Claude Code style: Show unified status bar before prompt
2341
+ // This creates consistent UI between startup and post-streaming
2342
+ this.showUnifiedStatusBar();
2384
2343
  queueMicrotask(() => this.uiUpdates.setMode('idle'));
2385
2344
  // CRITICAL: Ensure readline prompt is active for user input
2386
2345
  // Claude Code style: New prompt naturally appears at bottom
@@ -2457,14 +2416,13 @@ When truly finished with ALL tasks, explicitly state "TASK_FULLY_COMPLETE".`;
2457
2416
  try {
2458
2417
  // Send the request and capture the response (streaming disabled)
2459
2418
  display.showThinking('Responding...');
2460
- this.refreshStatusLine(true);
2461
2419
  const response = await agent.send(currentPrompt, true);
2462
2420
  await this.awaitPendingCleanup();
2463
2421
  this.captureHistorySnapshot();
2464
2422
  this.autosaveIfEnabled();
2465
2423
  // Track metrics
2466
2424
  const elapsedMs = Date.now() - overallStartTime;
2467
- this.alphaZeroMetrics.recordMessage(elapsedMs);
2425
+ this.sessionMetrics.recordMessage(elapsedMs);
2468
2426
  if (!response?.trim()) {
2469
2427
  display.showWarning('Model returned an empty response. Retrying this iteration...');
2470
2428
  consecutiveNoProgress++;
@@ -2601,6 +2559,7 @@ What's the next action?`;
2601
2559
  this.stopStreamingHeartbeat();
2602
2560
  this.isProcessing = false;
2603
2561
  this.terminalInput.setStreaming(false);
2562
+ this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
2604
2563
  this.uiAdapter.endProcessing('Ready for prompts');
2605
2564
  this.setIdleStatus();
2606
2565
  this.updateStatusMessage(null);
@@ -2957,10 +2916,8 @@ What's the next action?`;
2957
2916
  try {
2958
2917
  // Send the error to the agent for fixing
2959
2918
  display.showThinking('Analyzing build errors');
2960
- this.refreshStatusLine(true);
2961
2919
  const response = await this.agent.send(prompt, true);
2962
2920
  display.stopThinking();
2963
- this.refreshStatusLine(true);
2964
2921
  if (response) {
2965
2922
  display.showAssistantMessage(response, { isFinal: true });
2966
2923
  }
@@ -3010,16 +2967,18 @@ What's the next action?`;
3010
2967
  display.showAssistantMessage(finalContent, enriched);
3011
2968
  }
3012
2969
  }
3013
- // Status shown in mode controls bar - no separate status line needed
2970
+ // Show status line at end (Claude Code style: "• Context X% used • Ready for prompts (2s)")
3014
2971
  display.stopThinking();
3015
- // Update context usage for mode controls display
2972
+ // Calculate context usage
2973
+ let contextInfo;
3016
2974
  if (enriched.contextWindowTokens && metadata.usage) {
3017
2975
  const total = this.totalTokens(metadata.usage);
3018
2976
  if (total && total > 0) {
3019
2977
  const percentage = Math.round((total / enriched.contextWindowTokens) * 100);
3020
- this.updateContextUsage(percentage);
2978
+ contextInfo = { percentage, tokens: total };
3021
2979
  }
3022
2980
  }
2981
+ display.showStatusLine('Ready for prompts', enriched.elapsedMs, contextInfo);
3023
2982
  // Auto-verify changes: build first (catches type errors), then tests
3024
2983
  void this.enforceAutoBuild('final-response');
3025
2984
  void this.enforceAutoTests('final-response');
@@ -3089,6 +3048,7 @@ What's the next action?`;
3089
3048
  this.stopStreamingHeartbeat();
3090
3049
  this.updateStatusMessage(null);
3091
3050
  this.terminalInput.setStreaming(false);
3051
+ this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
3092
3052
  this.terminalInput.render();
3093
3053
  },
3094
3054
  onVerificationNeeded: () => {
@@ -3125,6 +3085,7 @@ What's the next action?`;
3125
3085
  resetChatBoxAfterModelSwap() {
3126
3086
  this.updateStatusMessage(null);
3127
3087
  this.terminalInput.setStreaming(false);
3088
+ this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
3128
3089
  this.terminalInput.render();
3129
3090
  this.ensureReadlineReady();
3130
3091
  }
@@ -3189,14 +3150,9 @@ What's the next action?`;
3189
3150
  return null;
3190
3151
  }
3191
3152
  const usageRatio = total / windowTokens;
3192
- this.latestTokenUsage = {
3193
- used: total,
3194
- limit: windowTokens,
3195
- };
3196
3153
  // Always update context usage in the UI
3197
3154
  const percentUsed = Math.round(usageRatio * 100);
3198
3155
  this.updateContextUsage(percentUsed);
3199
- this.refreshStatusLine(true);
3200
3156
  if (usageRatio < CONTEXT_USAGE_THRESHOLD) {
3201
3157
  return null;
3202
3158
  }
@@ -3474,6 +3430,8 @@ What's the next action?`;
3474
3430
  }
3475
3431
  this.refreshContextGauge();
3476
3432
  display.updateSessionInfo(nextState.model, nextState.provider);
3433
+ // Update the persistent model info display in terminal input
3434
+ this.terminalInput.setModelInfo(this.describeModelDetail());
3477
3435
  if (!this.isProcessing) {
3478
3436
  this.setIdleStatus();
3479
3437
  }