erosolar-cli 1.7.267 → 1.7.268

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 (321) 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/capabilities/agentSpawningCapability.d.ts.map +1 -1
  55. package/dist/capabilities/agentSpawningCapability.js +31 -56
  56. package/dist/capabilities/agentSpawningCapability.js.map +1 -1
  57. package/dist/capabilities/securityTestingCapability.d.ts +13 -0
  58. package/dist/capabilities/securityTestingCapability.d.ts.map +1 -0
  59. package/dist/capabilities/securityTestingCapability.js +25 -0
  60. package/dist/capabilities/securityTestingCapability.js.map +1 -0
  61. package/dist/contracts/agent-schemas.json +15 -0
  62. package/dist/contracts/tools.schema.json +9 -0
  63. package/dist/core/agent.d.ts +2 -2
  64. package/dist/core/agent.d.ts.map +1 -1
  65. package/dist/core/agent.js.map +1 -1
  66. package/dist/core/aiFlowOptimizer.d.ts +26 -0
  67. package/dist/core/aiFlowOptimizer.d.ts.map +1 -0
  68. package/dist/core/aiFlowOptimizer.js +31 -0
  69. package/dist/core/aiFlowOptimizer.js.map +1 -0
  70. package/dist/core/aiOptimizationEngine.d.ts +158 -0
  71. package/dist/core/aiOptimizationEngine.d.ts.map +1 -0
  72. package/dist/core/aiOptimizationEngine.js +428 -0
  73. package/dist/core/aiOptimizationEngine.js.map +1 -0
  74. package/dist/core/aiOptimizationIntegration.d.ts +93 -0
  75. package/dist/core/aiOptimizationIntegration.d.ts.map +1 -0
  76. package/dist/core/aiOptimizationIntegration.js +250 -0
  77. package/dist/core/aiOptimizationIntegration.js.map +1 -0
  78. package/dist/core/customCommands.d.ts +0 -1
  79. package/dist/core/customCommands.d.ts.map +1 -1
  80. package/dist/core/customCommands.js +0 -3
  81. package/dist/core/customCommands.js.map +1 -1
  82. package/dist/core/enhancedErrorRecovery.d.ts +100 -0
  83. package/dist/core/enhancedErrorRecovery.d.ts.map +1 -0
  84. package/dist/core/enhancedErrorRecovery.js +345 -0
  85. package/dist/core/enhancedErrorRecovery.js.map +1 -0
  86. package/dist/core/hooksSystem.d.ts +65 -0
  87. package/dist/core/hooksSystem.d.ts.map +1 -0
  88. package/dist/core/hooksSystem.js +273 -0
  89. package/dist/core/hooksSystem.js.map +1 -0
  90. package/dist/core/memorySystem.d.ts +48 -0
  91. package/dist/core/memorySystem.d.ts.map +1 -0
  92. package/dist/core/memorySystem.js +271 -0
  93. package/dist/core/memorySystem.js.map +1 -0
  94. package/dist/core/toolPreconditions.d.ts.map +1 -1
  95. package/dist/core/toolPreconditions.js +14 -0
  96. package/dist/core/toolPreconditions.js.map +1 -1
  97. package/dist/core/toolRuntime.d.ts +1 -22
  98. package/dist/core/toolRuntime.d.ts.map +1 -1
  99. package/dist/core/toolRuntime.js +5 -0
  100. package/dist/core/toolRuntime.js.map +1 -1
  101. package/dist/core/toolValidation.d.ts.map +1 -1
  102. package/dist/core/toolValidation.js +3 -14
  103. package/dist/core/toolValidation.js.map +1 -1
  104. package/dist/core/unified/errors.d.ts +189 -0
  105. package/dist/core/unified/errors.d.ts.map +1 -0
  106. package/dist/core/unified/errors.js +497 -0
  107. package/dist/core/unified/errors.js.map +1 -0
  108. package/dist/core/unified/index.d.ts +19 -0
  109. package/dist/core/unified/index.d.ts.map +1 -0
  110. package/dist/core/unified/index.js +68 -0
  111. package/dist/core/unified/index.js.map +1 -0
  112. package/dist/core/unified/schema.d.ts +101 -0
  113. package/dist/core/unified/schema.d.ts.map +1 -0
  114. package/dist/core/unified/schema.js +350 -0
  115. package/dist/core/unified/schema.js.map +1 -0
  116. package/dist/core/unified/toolRuntime.d.ts +179 -0
  117. package/dist/core/unified/toolRuntime.d.ts.map +1 -0
  118. package/dist/core/unified/toolRuntime.js +517 -0
  119. package/dist/core/unified/toolRuntime.js.map +1 -0
  120. package/dist/core/unified/tools.d.ts +127 -0
  121. package/dist/core/unified/tools.d.ts.map +1 -0
  122. package/dist/core/unified/tools.js +1333 -0
  123. package/dist/core/unified/tools.js.map +1 -0
  124. package/dist/core/unified/types.d.ts +352 -0
  125. package/dist/core/unified/types.d.ts.map +1 -0
  126. package/dist/core/unified/types.js +12 -0
  127. package/dist/core/unified/types.js.map +1 -0
  128. package/dist/core/unified/version.d.ts +209 -0
  129. package/dist/core/unified/version.d.ts.map +1 -0
  130. package/dist/core/unified/version.js +454 -0
  131. package/dist/core/unified/version.js.map +1 -0
  132. package/dist/core/validationRunner.d.ts +3 -1
  133. package/dist/core/validationRunner.d.ts.map +1 -1
  134. package/dist/core/validationRunner.js.map +1 -1
  135. package/dist/headless/headlessApp.d.ts.map +1 -1
  136. package/dist/headless/headlessApp.js +0 -21
  137. package/dist/headless/headlessApp.js.map +1 -1
  138. package/dist/mcp/sseClient.d.ts.map +1 -1
  139. package/dist/mcp/sseClient.js +18 -9
  140. package/dist/mcp/sseClient.js.map +1 -1
  141. package/dist/plugins/tools/build/buildPlugin.d.ts +6 -0
  142. package/dist/plugins/tools/build/buildPlugin.d.ts.map +1 -1
  143. package/dist/plugins/tools/build/buildPlugin.js +10 -4
  144. package/dist/plugins/tools/build/buildPlugin.js.map +1 -1
  145. package/dist/plugins/tools/nodeDefaults.d.ts.map +1 -1
  146. package/dist/plugins/tools/nodeDefaults.js +2 -0
  147. package/dist/plugins/tools/nodeDefaults.js.map +1 -1
  148. package/dist/plugins/tools/security/securityPlugin.d.ts +3 -0
  149. package/dist/plugins/tools/security/securityPlugin.d.ts.map +1 -0
  150. package/dist/plugins/tools/security/securityPlugin.js +12 -0
  151. package/dist/plugins/tools/security/securityPlugin.js.map +1 -0
  152. package/dist/runtime/agentSession.d.ts +2 -2
  153. package/dist/runtime/agentSession.d.ts.map +1 -1
  154. package/dist/runtime/agentSession.js +2 -2
  155. package/dist/runtime/agentSession.js.map +1 -1
  156. package/dist/security/active-stack-security.d.ts +112 -0
  157. package/dist/security/active-stack-security.d.ts.map +1 -0
  158. package/dist/security/active-stack-security.js +296 -0
  159. package/dist/security/active-stack-security.js.map +1 -0
  160. package/dist/security/advanced-persistence-research.d.ts +92 -0
  161. package/dist/security/advanced-persistence-research.d.ts.map +1 -0
  162. package/dist/security/advanced-persistence-research.js +195 -0
  163. package/dist/security/advanced-persistence-research.js.map +1 -0
  164. package/dist/security/advanced-targeting.d.ts +119 -0
  165. package/dist/security/advanced-targeting.d.ts.map +1 -0
  166. package/dist/security/advanced-targeting.js +233 -0
  167. package/dist/security/advanced-targeting.js.map +1 -0
  168. package/dist/security/assessment/vulnerabilityAssessment.d.ts +104 -0
  169. package/dist/security/assessment/vulnerabilityAssessment.d.ts.map +1 -0
  170. package/dist/security/assessment/vulnerabilityAssessment.js +315 -0
  171. package/dist/security/assessment/vulnerabilityAssessment.js.map +1 -0
  172. package/dist/security/authorization/securityAuthorization.d.ts +88 -0
  173. package/dist/security/authorization/securityAuthorization.d.ts.map +1 -0
  174. package/dist/security/authorization/securityAuthorization.js +172 -0
  175. package/dist/security/authorization/securityAuthorization.js.map +1 -0
  176. package/dist/security/comprehensive-targeting.d.ts +85 -0
  177. package/dist/security/comprehensive-targeting.d.ts.map +1 -0
  178. package/dist/security/comprehensive-targeting.js +438 -0
  179. package/dist/security/comprehensive-targeting.js.map +1 -0
  180. package/dist/security/global-security-integration.d.ts +91 -0
  181. package/dist/security/global-security-integration.d.ts.map +1 -0
  182. package/dist/security/global-security-integration.js +218 -0
  183. package/dist/security/global-security-integration.js.map +1 -0
  184. package/dist/security/index.d.ts +38 -0
  185. package/dist/security/index.d.ts.map +1 -0
  186. package/dist/security/index.js +47 -0
  187. package/dist/security/index.js.map +1 -0
  188. package/dist/security/persistence-analyzer.d.ts +56 -0
  189. package/dist/security/persistence-analyzer.d.ts.map +1 -0
  190. package/dist/security/persistence-analyzer.js +187 -0
  191. package/dist/security/persistence-analyzer.js.map +1 -0
  192. package/dist/security/persistence-cli.d.ts +36 -0
  193. package/dist/security/persistence-cli.d.ts.map +1 -0
  194. package/dist/security/persistence-cli.js +160 -0
  195. package/dist/security/persistence-cli.js.map +1 -0
  196. package/dist/security/persistence-research.d.ts +92 -0
  197. package/dist/security/persistence-research.d.ts.map +1 -0
  198. package/dist/security/persistence-research.js +364 -0
  199. package/dist/security/persistence-research.js.map +1 -0
  200. package/dist/security/research/persistenceResearch.d.ts +97 -0
  201. package/dist/security/research/persistenceResearch.d.ts.map +1 -0
  202. package/dist/security/research/persistenceResearch.js +282 -0
  203. package/dist/security/research/persistenceResearch.js.map +1 -0
  204. package/dist/security/security-integration.d.ts +74 -0
  205. package/dist/security/security-integration.d.ts.map +1 -0
  206. package/dist/security/security-integration.js +137 -0
  207. package/dist/security/security-integration.js.map +1 -0
  208. package/dist/security/security-testing-framework.d.ts +112 -0
  209. package/dist/security/security-testing-framework.d.ts.map +1 -0
  210. package/dist/security/security-testing-framework.js +364 -0
  211. package/dist/security/security-testing-framework.js.map +1 -0
  212. package/dist/security/simulation/attackSimulation.d.ts +93 -0
  213. package/dist/security/simulation/attackSimulation.d.ts.map +1 -0
  214. package/dist/security/simulation/attackSimulation.js +341 -0
  215. package/dist/security/simulation/attackSimulation.js.map +1 -0
  216. package/dist/security/strategic-operations.d.ts +100 -0
  217. package/dist/security/strategic-operations.d.ts.map +1 -0
  218. package/dist/security/strategic-operations.js +276 -0
  219. package/dist/security/strategic-operations.js.map +1 -0
  220. package/dist/security/tool-security-wrapper.d.ts +58 -0
  221. package/dist/security/tool-security-wrapper.d.ts.map +1 -0
  222. package/dist/security/tool-security-wrapper.js +156 -0
  223. package/dist/security/tool-security-wrapper.js.map +1 -0
  224. package/dist/shell/claudeCodeStreamHandler.d.ts +145 -0
  225. package/dist/shell/claudeCodeStreamHandler.d.ts.map +1 -0
  226. package/dist/shell/claudeCodeStreamHandler.js +322 -0
  227. package/dist/shell/claudeCodeStreamHandler.js.map +1 -0
  228. package/dist/shell/inputQueueManager.d.ts +144 -0
  229. package/dist/shell/inputQueueManager.d.ts.map +1 -0
  230. package/dist/shell/inputQueueManager.js +290 -0
  231. package/dist/shell/inputQueueManager.js.map +1 -0
  232. package/dist/shell/interactiveShell.d.ts +7 -11
  233. package/dist/shell/interactiveShell.d.ts.map +1 -1
  234. package/dist/shell/interactiveShell.js +157 -190
  235. package/dist/shell/interactiveShell.js.map +1 -1
  236. package/dist/shell/metricsTracker.d.ts +60 -0
  237. package/dist/shell/metricsTracker.d.ts.map +1 -0
  238. package/dist/shell/metricsTracker.js +119 -0
  239. package/dist/shell/metricsTracker.js.map +1 -0
  240. package/dist/shell/shellApp.d.ts +0 -2
  241. package/dist/shell/shellApp.d.ts.map +1 -1
  242. package/dist/shell/shellApp.js +1 -36
  243. package/dist/shell/shellApp.js.map +1 -1
  244. package/dist/shell/streamingOutputManager.d.ts +115 -0
  245. package/dist/shell/streamingOutputManager.d.ts.map +1 -0
  246. package/dist/shell/streamingOutputManager.js +225 -0
  247. package/dist/shell/streamingOutputManager.js.map +1 -0
  248. package/dist/shell/systemPrompt.d.ts.map +1 -1
  249. package/dist/shell/systemPrompt.js +4 -1
  250. package/dist/shell/systemPrompt.js.map +1 -1
  251. package/dist/shell/terminalInput.d.ts +153 -77
  252. package/dist/shell/terminalInput.d.ts.map +1 -1
  253. package/dist/shell/terminalInput.js +718 -489
  254. package/dist/shell/terminalInput.js.map +1 -1
  255. package/dist/shell/terminalInputAdapter.d.ts +25 -20
  256. package/dist/shell/terminalInputAdapter.d.ts.map +1 -1
  257. package/dist/shell/terminalInputAdapter.js +36 -14
  258. package/dist/shell/terminalInputAdapter.js.map +1 -1
  259. package/dist/subagents/taskRunner.d.ts +1 -7
  260. package/dist/subagents/taskRunner.d.ts.map +1 -1
  261. package/dist/subagents/taskRunner.js +47 -180
  262. package/dist/subagents/taskRunner.js.map +1 -1
  263. package/dist/tools/securityTools.d.ts +22 -0
  264. package/dist/tools/securityTools.d.ts.map +1 -0
  265. package/dist/tools/securityTools.js +448 -0
  266. package/dist/tools/securityTools.js.map +1 -0
  267. package/dist/ui/ShellUIAdapter.d.ts.map +1 -1
  268. package/dist/ui/ShellUIAdapter.js +12 -13
  269. package/dist/ui/ShellUIAdapter.js.map +1 -1
  270. package/dist/ui/display.d.ts +0 -19
  271. package/dist/ui/display.d.ts.map +1 -1
  272. package/dist/ui/display.js +33 -131
  273. package/dist/ui/display.js.map +1 -1
  274. package/dist/ui/persistentPrompt.d.ts +50 -0
  275. package/dist/ui/persistentPrompt.d.ts.map +1 -0
  276. package/dist/ui/persistentPrompt.js +92 -0
  277. package/dist/ui/persistentPrompt.js.map +1 -0
  278. package/dist/ui/terminalUISchema.d.ts +195 -0
  279. package/dist/ui/terminalUISchema.d.ts.map +1 -0
  280. package/dist/ui/terminalUISchema.js +113 -0
  281. package/dist/ui/terminalUISchema.js.map +1 -0
  282. package/dist/ui/theme.d.ts.map +1 -1
  283. package/dist/ui/theme.js +8 -6
  284. package/dist/ui/theme.js.map +1 -1
  285. package/dist/ui/toolDisplay.d.ts +158 -0
  286. package/dist/ui/toolDisplay.d.ts.map +1 -1
  287. package/dist/ui/toolDisplay.js +348 -0
  288. package/dist/ui/toolDisplay.js.map +1 -1
  289. package/dist/ui/unified/layout.d.ts +0 -1
  290. package/dist/ui/unified/layout.d.ts.map +1 -1
  291. package/dist/ui/unified/layout.js +25 -15
  292. package/dist/ui/unified/layout.js.map +1 -1
  293. package/package.json +1 -1
  294. package/scripts/deploy-security-capabilities.js +178 -0
  295. package/dist/core/hooks.d.ts +0 -113
  296. package/dist/core/hooks.d.ts.map +0 -1
  297. package/dist/core/hooks.js +0 -267
  298. package/dist/core/hooks.js.map +0 -1
  299. package/dist/core/metricsTracker.d.ts +0 -122
  300. package/dist/core/metricsTracker.d.ts.map +0 -1
  301. package/dist/core/metricsTracker.js.map +0 -1
  302. package/dist/core/securityAssessment.d.ts +0 -91
  303. package/dist/core/securityAssessment.d.ts.map +0 -1
  304. package/dist/core/securityAssessment.js +0 -580
  305. package/dist/core/securityAssessment.js.map +0 -1
  306. package/dist/core/verification.d.ts +0 -137
  307. package/dist/core/verification.d.ts.map +0 -1
  308. package/dist/core/verification.js +0 -323
  309. package/dist/core/verification.js.map +0 -1
  310. package/dist/subagents/agentConfig.d.ts +0 -27
  311. package/dist/subagents/agentConfig.d.ts.map +0 -1
  312. package/dist/subagents/agentConfig.js +0 -89
  313. package/dist/subagents/agentConfig.js.map +0 -1
  314. package/dist/subagents/agentRegistry.d.ts +0 -33
  315. package/dist/subagents/agentRegistry.d.ts.map +0 -1
  316. package/dist/subagents/agentRegistry.js +0 -162
  317. package/dist/subagents/agentRegistry.js.map +0 -1
  318. package/dist/utils/frontmatter.d.ts +0 -10
  319. package/dist/utils/frontmatter.d.ts.map +0 -1
  320. package/dist/utils/frontmatter.js +0 -78
  321. 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,8 +216,13 @@ export class InteractiveShell {
224
216
  });
225
217
  // Register output interceptor for cursor positioning during streaming
226
218
  this.terminalInput.registerOutputInterceptor(display);
219
+ // Use flow mode: input renders inline after content for a unified layout
220
+ // This eliminates the blank space between banner and input area
221
+ this.terminalInput.setFlowMode(true);
222
+ // Set content end row so input renders right after startup content
223
+ this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
227
224
  // Initialize Alpha Zero 2 metrics tracking
228
- this.alphaZeroMetrics = new MetricsTracker(`${this.profile}-${Date.now()}`);
225
+ this.sessionMetrics = new MetricsTracker(`${this.profile}-${Date.now()}`);
229
226
  this.setupStatusTracking();
230
227
  this.refreshContextGauge();
231
228
  this.terminalInput.start();
@@ -281,15 +278,9 @@ export class InteractiveShell {
281
278
  await this.processInputBlock(initialPrompt);
282
279
  return;
283
280
  }
284
- this.showLaunchCommandPalette();
285
281
  // Ensure the terminal input is visible
286
282
  this.terminalInput.render();
287
283
  }
288
- showLaunchCommandPalette() {
289
- // Disabled: Quick commands palette takes up too much space
290
- // Users can type /help to see available commands
291
- this.launchPaletteShown = true;
292
- }
293
284
  /**
294
285
  * TerminalInputAdapter submit handler
295
286
  */
@@ -303,8 +294,9 @@ export class InteractiveShell {
303
294
  this.handleInputChange('');
304
295
  return;
305
296
  }
306
- // DON'T clear the input here - keep it visible while streaming.
307
- // The input will be cleared after streaming completes in the finally block.
297
+ // Enter streaming mode BEFORE logging prompt - this positions cursor correctly
298
+ // so content appears right after the banner, not at bottom with blank space above
299
+ this.terminalInput.setStreaming(true);
308
300
  this.logUserPrompt(approved);
309
301
  void this.processInputBlock(approved).catch((err) => {
310
302
  display.showError(err instanceof Error ? err.message : String(err), err);
@@ -506,9 +498,10 @@ export class InteractiveShell {
506
498
  // Dispose unified UI adapter
507
499
  this.uiAdapter.dispose();
508
500
  display.newLine();
509
- console.log(theme.ui.muted('━'.repeat(44)));
510
- console.log(theme.ui.muted(' Goodbye! · support@ero.solar'));
511
- console.log(theme.ui.muted(''.repeat(44)));
501
+ console.log(theme.gradient.warm('━'.repeat(50)));
502
+ console.log(` ${theme.gradient.cool('Goodbye!')} ${theme.ui.muted('·')} ${theme.info('support@ero.solar')}`);
503
+ console.log(` ${theme.ui.muted('Read:')} ${theme.accent('anthropic.com/news/disrupting-AI-espionage')}`);
504
+ console.log(theme.gradient.warm('━'.repeat(50)));
512
505
  exit(0);
513
506
  }
514
507
  /**
@@ -678,14 +671,13 @@ export class InteractiveShell {
678
671
  });
679
672
  }
680
673
  setProcessingStatus(detail) {
681
- this.latestTokenUsage = { used: null, limit: this.latestTokenUsage.limit };
682
674
  this.statusTracker.setBase('Working on your request', {
683
675
  detail: this.describeStatusDetail(detail),
684
676
  tone: 'info',
685
677
  });
686
678
  }
687
679
  describeStatusDetail(detail) {
688
- const parts = detail?.trim() ? [detail.trim()] : [];
680
+ const parts = [detail?.trim() || this.describeModelDetail()];
689
681
  const queued = this.followUpQueue.length;
690
682
  if (queued > 0) {
691
683
  parts.push(`${queued} follow-up${queued === 1 ? '' : 's'} queued`);
@@ -698,18 +690,12 @@ export class InteractiveShell {
698
690
  }
699
691
  refreshContextGauge() {
700
692
  const tokens = getContextWindowTokens(this.sessionState.model);
701
- const normalizedTokens = typeof tokens === 'number' && Number.isFinite(tokens) ? tokens : null;
702
- this.activeContextWindowTokens = normalizedTokens;
703
- if (normalizedTokens !== null) {
704
- this.latestTokenUsage = {
705
- used: this.latestTokenUsage.used,
706
- limit: normalizedTokens,
707
- };
708
- }
693
+ this.activeContextWindowTokens =
694
+ typeof tokens === 'number' && Number.isFinite(tokens) ? tokens : null;
709
695
  }
710
696
  updateContextUsage(percentage) {
711
697
  this.uiAdapter.updateContextUsage(percentage);
712
- this.terminalInput.setContextUsage(percentage, CONTEXT_AUTOCOMPACT_PERCENT);
698
+ this.terminalInput.setContextUsage(percentage);
713
699
  }
714
700
  refreshControlBar() {
715
701
  this.terminalInput.setModeToggles({
@@ -717,9 +703,9 @@ export class InteractiveShell {
717
703
  autoContinueEnabled: this.autoContinueEnabled,
718
704
  verificationHotkey: 'alt+v',
719
705
  autoContinueHotkey: 'alt+c',
720
- thinkingModeLabel: this.thinkingMode,
721
- thinkingHotkey: '/thinking',
722
706
  });
707
+ // Update persistent model info display
708
+ this.terminalInput.setModelInfo(this.describeModelDetail());
723
709
  this.refreshStatusLine();
724
710
  this.terminalInput.render();
725
711
  }
@@ -750,25 +736,6 @@ export class InteractiveShell {
750
736
  // Set main status (tool execution, etc.) - shown when not overridden
751
737
  const statusText = this.formatStatusLine(this.statusLineState);
752
738
  this.terminalInput.setStatusMessage(statusText);
753
- // Surface meta header (elapsed + context usage) above the divider
754
- const elapsedSeconds = this.statusLineState
755
- ? Math.max(0, Math.floor((Date.now() - this.statusLineState.startedAt) / 1000))
756
- : null;
757
- const thinkingMs = display.isSpinnerActive() ? display.getThinkingElapsedMs() : null;
758
- const tokensUsed = this.latestTokenUsage.used;
759
- const tokenLimit = this.latestTokenUsage.limit ?? this.activeContextWindowTokens;
760
- this.terminalInput.setMetaStatus({
761
- elapsedSeconds,
762
- tokensUsed,
763
- tokenLimit,
764
- thinkingMs,
765
- thinkingHasContent: display.isSpinnerActive(),
766
- });
767
- // Keep model/provider visible in the controls bar
768
- this.terminalInput.setModelContext({
769
- model: this.sessionState.model,
770
- provider: this.providerLabel(this.sessionState.provider),
771
- });
772
739
  if (forceRender) {
773
740
  this.terminalInput.render();
774
741
  }
@@ -828,11 +795,13 @@ export class InteractiveShell {
828
795
  this.terminalInput.render();
829
796
  }
830
797
  /**
831
- * Keep submissions out of the transcript to preserve the persistent input area.
832
- * The chat box already holds the user's prompt, so avoid echoing it into output.
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.
833
800
  */
834
- logUserPrompt(_text) {
835
- // Intentionally no-op to keep the input area persistent and uncluttered.
801
+ logUserPrompt(text) {
802
+ // Display the user's prompt with the standard prefix
803
+ const prefix = formatUserPrompt();
804
+ display.stream(`\n${prefix}${text}\n\n`);
836
805
  }
837
806
  requestPromptRefresh(force = false) {
838
807
  if (force) {
@@ -860,29 +829,9 @@ export class InteractiveShell {
860
829
  this.uiUpdates.setMode('streaming');
861
830
  this.streamingHeartbeatStart = Date.now();
862
831
  this.streamingHeartbeatFrame = 0;
863
- const initialFrame = STREAMING_SPINNER_FRAMES[this.streamingHeartbeatFrame];
864
- this.streamingStatusLabel = this.buildStreamingStatus(`${initialFrame} ${label}`, 0);
865
- display.updateStreamingStatus(this.streamingStatusLabel);
866
- this.refreshStatusLine(true);
867
- // Periodically refresh the pinned input/status region while streaming so
868
- // elapsed time remains visible without interrupting the scroll region.
869
- this.uiUpdates.startHeartbeat('streaming', {
870
- intervalMs: 1000,
871
- lane: 'heartbeat',
872
- mode: ['streaming', 'processing'],
873
- coalesceKey: 'streaming:heartbeat',
874
- run: () => {
875
- const elapsedSeconds = this.streamingHeartbeatStart
876
- ? Math.max(0, Math.floor((Date.now() - this.streamingHeartbeatStart) / 1000))
877
- : 0;
878
- this.streamingHeartbeatFrame =
879
- (this.streamingHeartbeatFrame + 1) % STREAMING_SPINNER_FRAMES.length;
880
- const frame = STREAMING_SPINNER_FRAMES[this.streamingHeartbeatFrame];
881
- this.streamingStatusLabel = this.buildStreamingStatus(`${frame} ${label}`, elapsedSeconds);
882
- display.updateStreamingStatus(this.streamingStatusLabel);
883
- this.refreshStatusLine(true);
884
- },
885
- });
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.
886
835
  }
887
836
  stopStreamingHeartbeat() {
888
837
  // Exit global streaming mode - allows UI to render again
@@ -898,28 +847,10 @@ export class InteractiveShell {
898
847
  // Force refresh to update the input area now that streaming has ended
899
848
  this.refreshStatusLine(true);
900
849
  }
901
- buildStreamingStatus(label, elapsedSeconds) {
850
+ buildStreamingStatus(label) {
902
851
  const detail = this.describeModelDetail();
903
- const elapsedLabel = typeof elapsedSeconds === 'number' && elapsedSeconds >= 0
904
- ? theme.ui.muted(this.formatElapsedShort(elapsedSeconds))
905
- : null;
906
- const prefix = theme.info('⏺');
907
- const parts = [label];
908
- if (detail) {
909
- parts.push(theme.ui.muted('·'), detail);
910
- }
911
- if (elapsedLabel) {
912
- parts.push(theme.ui.muted('·'), elapsedLabel);
913
- }
914
- return `${prefix} ${parts.join(' ')}`.trim();
915
- }
916
- formatElapsedShort(seconds) {
917
- if (seconds < 60) {
918
- return `${seconds}s`;
919
- }
920
- const minutes = Math.floor(seconds / 60);
921
- const remaining = seconds % 60;
922
- return remaining > 0 ? `${minutes}m ${remaining}s` : `${minutes}m`;
852
+ const prefix = theme.info('');
853
+ return detail ? `${prefix} ${label} ${theme.ui.muted('·')} ${detail}` : `${prefix} ${label}`;
923
854
  }
924
855
  refreshQueueIndicators() {
925
856
  if (this.isProcessing) {
@@ -1167,6 +1098,17 @@ export class InteractiveShell {
1167
1098
  case '/discover':
1168
1099
  await this.discoverModelsCommand();
1169
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;
1170
1112
  default:
1171
1113
  if (!(await this.tryCustomSlashCommand(command, input))) {
1172
1114
  display.showWarning(`Unknown command "${command}".`);
@@ -1475,6 +1417,99 @@ export class InteractiveShell {
1475
1417
  // Display keyboard shortcuts help (Claude Code style)
1476
1418
  display.showSystemMessage(formatShortcutsHelp());
1477
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
+ }
1478
1513
  showFileChangeSummary() {
1479
1514
  const summary = this._fileChangeTracker.getSummary();
1480
1515
  const changes = this._fileChangeTracker.getAllChanges();
@@ -1517,11 +1552,11 @@ export class InteractiveShell {
1517
1552
  display.showSystemMessage(lines.join('\n'));
1518
1553
  }
1519
1554
  showAlphaZeroMetrics() {
1520
- const summary = this.alphaZeroMetrics.getPerformanceSummary();
1555
+ const summary = this.sessionMetrics.getPerformanceSummary();
1521
1556
  display.showSystemMessage(summary);
1522
1557
  }
1523
1558
  showImprovementSuggestions() {
1524
- const suggestions = this.alphaZeroMetrics.getImprovementSuggestions();
1559
+ const suggestions = this.sessionMetrics.getImprovementSuggestions();
1525
1560
  if (suggestions.length === 0) {
1526
1561
  display.showInfo('No improvement suggestions at this time. Keep using the shell to generate metrics!');
1527
1562
  return;
@@ -1567,9 +1602,7 @@ export class InteractiveShell {
1567
1602
  }
1568
1603
  }
1569
1604
  lines.push(theme.secondary('CLI Flags:'));
1570
- lines.push(' --alpha-zero Enable Alpha Zero 2 RL framework');
1571
1605
  lines.push(' --coding Enable enhanced coding tools');
1572
- lines.push(' --security Enable security research tools');
1573
1606
  lines.push(' --all-plugins Enable all optional plugins');
1574
1607
  display.showSystemMessage(lines.join('\n'));
1575
1608
  }
@@ -1813,75 +1846,6 @@ export class InteractiveShell {
1813
1846
  }
1814
1847
  return `${warning.label}: ${warning.reason}.`;
1815
1848
  }
1816
- buildLaunchCommandPalette() {
1817
- const entries = [];
1818
- const secretsSummary = this.summarizeSecretsForPalette();
1819
- const toolSummary = this.getToolSelectionSummary();
1820
- const autosaveLabel = this.autosaveEnabled ? 'on' : 'off';
1821
- for (const command of this.slashCommands) {
1822
- const entry = {
1823
- command: command.command,
1824
- description: command.description,
1825
- category: command.category ?? 'other',
1826
- };
1827
- switch (command.command) {
1828
- case '/secrets':
1829
- if (secretsSummary.text) {
1830
- entry.description = `${command.description} (${secretsSummary.text})`;
1831
- entry.tone = secretsSummary.tone;
1832
- }
1833
- break;
1834
- case '/tools':
1835
- if (toolSummary) {
1836
- entry.description = `${command.description} (${toolSummary})`;
1837
- }
1838
- break;
1839
- case '/sessions':
1840
- entry.description = `${command.description} (autosave ${autosaveLabel})`;
1841
- break;
1842
- case '/model':
1843
- entry.description = `${command.description} (current: ${this.sessionState.model})`;
1844
- break;
1845
- case '/provider':
1846
- entry.description = `${command.description} (current: ${this.providerLabel(this.sessionState.provider)})`;
1847
- break;
1848
- default:
1849
- break;
1850
- }
1851
- entries.push(entry);
1852
- }
1853
- return entries;
1854
- }
1855
- summarizeSecretsForPalette() {
1856
- const definitions = listSecretDefinitions();
1857
- if (!definitions.length) {
1858
- return { text: null };
1859
- }
1860
- const missing = definitions.filter((definition) => !getSecretValue(definition.id));
1861
- if (missing.length === 0) {
1862
- return { text: 'all configured', tone: 'success' };
1863
- }
1864
- const labels = missing.map((definition) => definition.label ?? definition.id);
1865
- return { text: `missing ${this.formatList(labels)}`, tone: 'warn' };
1866
- }
1867
- getToolSelectionSummary() {
1868
- const toolSettings = loadToolSettings();
1869
- const selection = buildEnabledToolSet(toolSettings);
1870
- const options = getToolToggleOptions();
1871
- if (!options.length) {
1872
- return null;
1873
- }
1874
- const enabledCount = options.filter((option) => selection.has(option.id)).length;
1875
- return `${enabledCount}/${options.length} enabled`;
1876
- }
1877
- formatList(values, maxItems = 3) {
1878
- if (!values.length) {
1879
- return '';
1880
- }
1881
- const shown = values.slice(0, maxItems);
1882
- const suffix = values.length > maxItems ? ', …' : '';
1883
- return `${shown.join(', ')}${suffix}`;
1884
- }
1885
1849
  buildSlashCommandList(header) {
1886
1850
  const lines = [theme.gradient.primary(header), ''];
1887
1851
  for (const command of this.slashCommands) {
@@ -2350,7 +2314,7 @@ export class InteractiveShell {
2350
2314
  this.autosaveIfEnabled();
2351
2315
  // Track metrics with Alpha Zero 2
2352
2316
  const elapsedMs = Date.now() - requestStartTime;
2353
- this.alphaZeroMetrics.recordMessage(elapsedMs);
2317
+ this.sessionMetrics.recordMessage(elapsedMs);
2354
2318
  if (!responseText?.trim()) {
2355
2319
  display.showWarning('The provider returned an empty response. Check your API key/provider selection or retry the prompt.');
2356
2320
  }
@@ -2368,10 +2332,14 @@ export class InteractiveShell {
2368
2332
  this.stopStreamingHeartbeat();
2369
2333
  this.isProcessing = false;
2370
2334
  this.terminalInput.setStreaming(false);
2335
+ this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
2371
2336
  this.uiAdapter.endProcessing('Ready for prompts');
2372
2337
  this.setIdleStatus();
2373
2338
  display.newLine();
2374
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();
2375
2343
  queueMicrotask(() => this.uiUpdates.setMode('idle'));
2376
2344
  // CRITICAL: Ensure readline prompt is active for user input
2377
2345
  // Claude Code style: New prompt naturally appears at bottom
@@ -2448,14 +2416,13 @@ When truly finished with ALL tasks, explicitly state "TASK_FULLY_COMPLETE".`;
2448
2416
  try {
2449
2417
  // Send the request and capture the response (streaming disabled)
2450
2418
  display.showThinking('Responding...');
2451
- this.refreshStatusLine(true);
2452
2419
  const response = await agent.send(currentPrompt, true);
2453
2420
  await this.awaitPendingCleanup();
2454
2421
  this.captureHistorySnapshot();
2455
2422
  this.autosaveIfEnabled();
2456
2423
  // Track metrics
2457
2424
  const elapsedMs = Date.now() - overallStartTime;
2458
- this.alphaZeroMetrics.recordMessage(elapsedMs);
2425
+ this.sessionMetrics.recordMessage(elapsedMs);
2459
2426
  if (!response?.trim()) {
2460
2427
  display.showWarning('Model returned an empty response. Retrying this iteration...');
2461
2428
  consecutiveNoProgress++;
@@ -2592,6 +2559,7 @@ What's the next action?`;
2592
2559
  this.stopStreamingHeartbeat();
2593
2560
  this.isProcessing = false;
2594
2561
  this.terminalInput.setStreaming(false);
2562
+ this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
2595
2563
  this.uiAdapter.endProcessing('Ready for prompts');
2596
2564
  this.setIdleStatus();
2597
2565
  this.updateStatusMessage(null);
@@ -2948,10 +2916,8 @@ What's the next action?`;
2948
2916
  try {
2949
2917
  // Send the error to the agent for fixing
2950
2918
  display.showThinking('Analyzing build errors');
2951
- this.refreshStatusLine(true);
2952
2919
  const response = await this.agent.send(prompt, true);
2953
2920
  display.stopThinking();
2954
- this.refreshStatusLine(true);
2955
2921
  if (response) {
2956
2922
  display.showAssistantMessage(response, { isFinal: true });
2957
2923
  }
@@ -3001,16 +2967,18 @@ What's the next action?`;
3001
2967
  display.showAssistantMessage(finalContent, enriched);
3002
2968
  }
3003
2969
  }
3004
- // 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)")
3005
2971
  display.stopThinking();
3006
- // Update context usage for mode controls display
2972
+ // Calculate context usage
2973
+ let contextInfo;
3007
2974
  if (enriched.contextWindowTokens && metadata.usage) {
3008
2975
  const total = this.totalTokens(metadata.usage);
3009
2976
  if (total && total > 0) {
3010
2977
  const percentage = Math.round((total / enriched.contextWindowTokens) * 100);
3011
- this.updateContextUsage(percentage);
2978
+ contextInfo = { percentage, tokens: total };
3012
2979
  }
3013
2980
  }
2981
+ display.showStatusLine('Ready for prompts', enriched.elapsedMs, contextInfo);
3014
2982
  // Auto-verify changes: build first (catches type errors), then tests
3015
2983
  void this.enforceAutoBuild('final-response');
3016
2984
  void this.enforceAutoTests('final-response');
@@ -3080,6 +3048,7 @@ What's the next action?`;
3080
3048
  this.stopStreamingHeartbeat();
3081
3049
  this.updateStatusMessage(null);
3082
3050
  this.terminalInput.setStreaming(false);
3051
+ this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
3083
3052
  this.terminalInput.render();
3084
3053
  },
3085
3054
  onVerificationNeeded: () => {
@@ -3116,6 +3085,7 @@ What's the next action?`;
3116
3085
  resetChatBoxAfterModelSwap() {
3117
3086
  this.updateStatusMessage(null);
3118
3087
  this.terminalInput.setStreaming(false);
3088
+ this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
3119
3089
  this.terminalInput.render();
3120
3090
  this.ensureReadlineReady();
3121
3091
  }
@@ -3180,14 +3150,9 @@ What's the next action?`;
3180
3150
  return null;
3181
3151
  }
3182
3152
  const usageRatio = total / windowTokens;
3183
- this.latestTokenUsage = {
3184
- used: total,
3185
- limit: windowTokens,
3186
- };
3187
3153
  // Always update context usage in the UI
3188
3154
  const percentUsed = Math.round(usageRatio * 100);
3189
3155
  this.updateContextUsage(percentUsed);
3190
- this.refreshStatusLine(true);
3191
3156
  if (usageRatio < CONTEXT_USAGE_THRESHOLD) {
3192
3157
  return null;
3193
3158
  }
@@ -3465,6 +3430,8 @@ What's the next action?`;
3465
3430
  }
3466
3431
  this.refreshContextGauge();
3467
3432
  display.updateSessionInfo(nextState.model, nextState.provider);
3433
+ // Update the persistent model info display in terminal input
3434
+ this.terminalInput.setModelInfo(this.describeModelDetail());
3468
3435
  if (!this.isProcessing) {
3469
3436
  this.setIdleStatus();
3470
3437
  }