erosolar-cli 1.7.270 → 1.7.271

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 -11
  235. package/dist/shell/interactiveShell.d.ts.map +1 -1
  236. package/dist/shell/interactiveShell.js +157 -195
  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 +1 -36
  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 +168 -76
  254. package/dist/shell/terminalInput.d.ts.map +1 -1
  255. package/dist/shell/terminalInput.js +831 -477
  256. package/dist/shell/terminalInput.js.map +1 -1
  257. package/dist/shell/terminalInputAdapter.d.ts +25 -28
  258. package/dist/shell/terminalInputAdapter.d.ts.map +1 -1
  259. package/dist/shell/terminalInputAdapter.js +36 -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 +0 -23
  273. package/dist/ui/display.d.ts.map +1 -1
  274. package/dist/ui/display.js +33 -137
  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,13 +216,13 @@ export class InteractiveShell {
224
216
  });
225
217
  // Register output interceptor for cursor positioning during streaming
226
218
  this.terminalInput.registerOutputInterceptor(display);
227
- // Advance content cursor past the banner so streaming content appears below it
228
- const bannerHeight = display.getBannerHeight();
229
- if (bannerHeight > 0) {
230
- this.terminalInput.advanceContentRow(bannerHeight);
231
- }
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());
232
224
  // Initialize Alpha Zero 2 metrics tracking
233
- this.alphaZeroMetrics = new MetricsTracker(`${this.profile}-${Date.now()}`);
225
+ this.sessionMetrics = new MetricsTracker(`${this.profile}-${Date.now()}`);
234
226
  this.setupStatusTracking();
235
227
  this.refreshContextGauge();
236
228
  this.terminalInput.start();
@@ -286,15 +278,9 @@ export class InteractiveShell {
286
278
  await this.processInputBlock(initialPrompt);
287
279
  return;
288
280
  }
289
- this.showLaunchCommandPalette();
290
281
  // Ensure the terminal input is visible
291
282
  this.terminalInput.render();
292
283
  }
293
- showLaunchCommandPalette() {
294
- // Disabled: Quick commands palette takes up too much space
295
- // Users can type /help to see available commands
296
- this.launchPaletteShown = true;
297
- }
298
284
  /**
299
285
  * TerminalInputAdapter submit handler
300
286
  */
@@ -308,8 +294,9 @@ export class InteractiveShell {
308
294
  this.handleInputChange('');
309
295
  return;
310
296
  }
311
- // DON'T clear the input here - keep it visible while streaming.
312
- // 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);
313
300
  this.logUserPrompt(approved);
314
301
  void this.processInputBlock(approved).catch((err) => {
315
302
  display.showError(err instanceof Error ? err.message : String(err), err);
@@ -511,9 +498,10 @@ export class InteractiveShell {
511
498
  // Dispose unified UI adapter
512
499
  this.uiAdapter.dispose();
513
500
  display.newLine();
514
- console.log(theme.ui.muted('━'.repeat(44)));
515
- console.log(theme.ui.muted(' Goodbye! · support@ero.solar'));
516
- 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)));
517
505
  exit(0);
518
506
  }
519
507
  /**
@@ -683,14 +671,13 @@ export class InteractiveShell {
683
671
  });
684
672
  }
685
673
  setProcessingStatus(detail) {
686
- this.latestTokenUsage = { used: null, limit: this.latestTokenUsage.limit };
687
674
  this.statusTracker.setBase('Working on your request', {
688
675
  detail: this.describeStatusDetail(detail),
689
676
  tone: 'info',
690
677
  });
691
678
  }
692
679
  describeStatusDetail(detail) {
693
- const parts = detail?.trim() ? [detail.trim()] : [];
680
+ const parts = [detail?.trim() || this.describeModelDetail()];
694
681
  const queued = this.followUpQueue.length;
695
682
  if (queued > 0) {
696
683
  parts.push(`${queued} follow-up${queued === 1 ? '' : 's'} queued`);
@@ -703,18 +690,12 @@ export class InteractiveShell {
703
690
  }
704
691
  refreshContextGauge() {
705
692
  const tokens = getContextWindowTokens(this.sessionState.model);
706
- const normalizedTokens = typeof tokens === 'number' && Number.isFinite(tokens) ? tokens : null;
707
- this.activeContextWindowTokens = normalizedTokens;
708
- if (normalizedTokens !== null) {
709
- this.latestTokenUsage = {
710
- used: this.latestTokenUsage.used,
711
- limit: normalizedTokens,
712
- };
713
- }
693
+ this.activeContextWindowTokens =
694
+ typeof tokens === 'number' && Number.isFinite(tokens) ? tokens : null;
714
695
  }
715
696
  updateContextUsage(percentage) {
716
697
  this.uiAdapter.updateContextUsage(percentage);
717
- this.terminalInput.setContextUsage(percentage, CONTEXT_AUTOCOMPACT_PERCENT);
698
+ this.terminalInput.setContextUsage(percentage);
718
699
  }
719
700
  refreshControlBar() {
720
701
  this.terminalInput.setModeToggles({
@@ -722,9 +703,9 @@ export class InteractiveShell {
722
703
  autoContinueEnabled: this.autoContinueEnabled,
723
704
  verificationHotkey: 'alt+v',
724
705
  autoContinueHotkey: 'alt+c',
725
- thinkingModeLabel: this.thinkingMode,
726
- thinkingHotkey: '/thinking',
727
706
  });
707
+ // Update persistent model info display
708
+ this.terminalInput.setModelInfo(this.describeModelDetail());
728
709
  this.refreshStatusLine();
729
710
  this.terminalInput.render();
730
711
  }
@@ -755,25 +736,6 @@ export class InteractiveShell {
755
736
  // Set main status (tool execution, etc.) - shown when not overridden
756
737
  const statusText = this.formatStatusLine(this.statusLineState);
757
738
  this.terminalInput.setStatusMessage(statusText);
758
- // Surface meta header (elapsed + context usage) above the divider
759
- const elapsedSeconds = this.statusLineState
760
- ? Math.max(0, Math.floor((Date.now() - this.statusLineState.startedAt) / 1000))
761
- : null;
762
- const thinkingMs = display.isSpinnerActive() ? display.getThinkingElapsedMs() : null;
763
- const tokensUsed = this.latestTokenUsage.used;
764
- const tokenLimit = this.latestTokenUsage.limit ?? this.activeContextWindowTokens;
765
- this.terminalInput.setMetaStatus({
766
- elapsedSeconds,
767
- tokensUsed,
768
- tokenLimit,
769
- thinkingMs,
770
- thinkingHasContent: display.isSpinnerActive(),
771
- });
772
- // Keep model/provider visible in the controls bar
773
- this.terminalInput.setModelContext({
774
- model: this.sessionState.model,
775
- provider: this.providerLabel(this.sessionState.provider),
776
- });
777
739
  if (forceRender) {
778
740
  this.terminalInput.render();
779
741
  }
@@ -833,11 +795,13 @@ export class InteractiveShell {
833
795
  this.terminalInput.render();
834
796
  }
835
797
  /**
836
- * Keep submissions out of the transcript to preserve the persistent input area.
837
- * 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.
838
800
  */
839
- logUserPrompt(_text) {
840
- // 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`);
841
805
  }
842
806
  requestPromptRefresh(force = false) {
843
807
  if (force) {
@@ -865,29 +829,9 @@ export class InteractiveShell {
865
829
  this.uiUpdates.setMode('streaming');
866
830
  this.streamingHeartbeatStart = Date.now();
867
831
  this.streamingHeartbeatFrame = 0;
868
- const initialFrame = STREAMING_SPINNER_FRAMES[this.streamingHeartbeatFrame];
869
- this.streamingStatusLabel = this.buildStreamingStatus(`${initialFrame} ${label}`, 0);
870
- display.updateStreamingStatus(this.streamingStatusLabel);
871
- this.refreshStatusLine(true);
872
- // Periodically refresh the pinned input/status region while streaming so
873
- // elapsed time remains visible without interrupting the scroll region.
874
- this.uiUpdates.startHeartbeat('streaming', {
875
- intervalMs: 1000,
876
- lane: 'heartbeat',
877
- mode: ['streaming', 'processing'],
878
- coalesceKey: 'streaming:heartbeat',
879
- run: () => {
880
- const elapsedSeconds = this.streamingHeartbeatStart
881
- ? Math.max(0, Math.floor((Date.now() - this.streamingHeartbeatStart) / 1000))
882
- : 0;
883
- this.streamingHeartbeatFrame =
884
- (this.streamingHeartbeatFrame + 1) % STREAMING_SPINNER_FRAMES.length;
885
- const frame = STREAMING_SPINNER_FRAMES[this.streamingHeartbeatFrame];
886
- this.streamingStatusLabel = this.buildStreamingStatus(`${frame} ${label}`, elapsedSeconds);
887
- display.updateStreamingStatus(this.streamingStatusLabel);
888
- this.refreshStatusLine(true);
889
- },
890
- });
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.
891
835
  }
892
836
  stopStreamingHeartbeat() {
893
837
  // Exit global streaming mode - allows UI to render again
@@ -903,28 +847,10 @@ export class InteractiveShell {
903
847
  // Force refresh to update the input area now that streaming has ended
904
848
  this.refreshStatusLine(true);
905
849
  }
906
- buildStreamingStatus(label, elapsedSeconds) {
850
+ buildStreamingStatus(label) {
907
851
  const detail = this.describeModelDetail();
908
- const elapsedLabel = typeof elapsedSeconds === 'number' && elapsedSeconds >= 0
909
- ? theme.ui.muted(this.formatElapsedShort(elapsedSeconds))
910
- : null;
911
- const prefix = theme.info('⏺');
912
- const parts = [label];
913
- if (detail) {
914
- parts.push(theme.ui.muted('·'), detail);
915
- }
916
- if (elapsedLabel) {
917
- parts.push(theme.ui.muted('·'), elapsedLabel);
918
- }
919
- return `${prefix} ${parts.join(' ')}`.trim();
920
- }
921
- formatElapsedShort(seconds) {
922
- if (seconds < 60) {
923
- return `${seconds}s`;
924
- }
925
- const minutes = Math.floor(seconds / 60);
926
- const remaining = seconds % 60;
927
- 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}`;
928
854
  }
929
855
  refreshQueueIndicators() {
930
856
  if (this.isProcessing) {
@@ -1172,6 +1098,17 @@ export class InteractiveShell {
1172
1098
  case '/discover':
1173
1099
  await this.discoverModelsCommand();
1174
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;
1175
1112
  default:
1176
1113
  if (!(await this.tryCustomSlashCommand(command, input))) {
1177
1114
  display.showWarning(`Unknown command "${command}".`);
@@ -1480,6 +1417,99 @@ export class InteractiveShell {
1480
1417
  // Display keyboard shortcuts help (Claude Code style)
1481
1418
  display.showSystemMessage(formatShortcutsHelp());
1482
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
+ }
1483
1513
  showFileChangeSummary() {
1484
1514
  const summary = this._fileChangeTracker.getSummary();
1485
1515
  const changes = this._fileChangeTracker.getAllChanges();
@@ -1522,11 +1552,11 @@ export class InteractiveShell {
1522
1552
  display.showSystemMessage(lines.join('\n'));
1523
1553
  }
1524
1554
  showAlphaZeroMetrics() {
1525
- const summary = this.alphaZeroMetrics.getPerformanceSummary();
1555
+ const summary = this.sessionMetrics.getPerformanceSummary();
1526
1556
  display.showSystemMessage(summary);
1527
1557
  }
1528
1558
  showImprovementSuggestions() {
1529
- const suggestions = this.alphaZeroMetrics.getImprovementSuggestions();
1559
+ const suggestions = this.sessionMetrics.getImprovementSuggestions();
1530
1560
  if (suggestions.length === 0) {
1531
1561
  display.showInfo('No improvement suggestions at this time. Keep using the shell to generate metrics!');
1532
1562
  return;
@@ -1572,9 +1602,7 @@ export class InteractiveShell {
1572
1602
  }
1573
1603
  }
1574
1604
  lines.push(theme.secondary('CLI Flags:'));
1575
- lines.push(' --alpha-zero Enable Alpha Zero 2 RL framework');
1576
1605
  lines.push(' --coding Enable enhanced coding tools');
1577
- lines.push(' --security Enable security research tools');
1578
1606
  lines.push(' --all-plugins Enable all optional plugins');
1579
1607
  display.showSystemMessage(lines.join('\n'));
1580
1608
  }
@@ -1818,75 +1846,6 @@ export class InteractiveShell {
1818
1846
  }
1819
1847
  return `${warning.label}: ${warning.reason}.`;
1820
1848
  }
1821
- buildLaunchCommandPalette() {
1822
- const entries = [];
1823
- const secretsSummary = this.summarizeSecretsForPalette();
1824
- const toolSummary = this.getToolSelectionSummary();
1825
- const autosaveLabel = this.autosaveEnabled ? 'on' : 'off';
1826
- for (const command of this.slashCommands) {
1827
- const entry = {
1828
- command: command.command,
1829
- description: command.description,
1830
- category: command.category ?? 'other',
1831
- };
1832
- switch (command.command) {
1833
- case '/secrets':
1834
- if (secretsSummary.text) {
1835
- entry.description = `${command.description} (${secretsSummary.text})`;
1836
- entry.tone = secretsSummary.tone;
1837
- }
1838
- break;
1839
- case '/tools':
1840
- if (toolSummary) {
1841
- entry.description = `${command.description} (${toolSummary})`;
1842
- }
1843
- break;
1844
- case '/sessions':
1845
- entry.description = `${command.description} (autosave ${autosaveLabel})`;
1846
- break;
1847
- case '/model':
1848
- entry.description = `${command.description} (current: ${this.sessionState.model})`;
1849
- break;
1850
- case '/provider':
1851
- entry.description = `${command.description} (current: ${this.providerLabel(this.sessionState.provider)})`;
1852
- break;
1853
- default:
1854
- break;
1855
- }
1856
- entries.push(entry);
1857
- }
1858
- return entries;
1859
- }
1860
- summarizeSecretsForPalette() {
1861
- const definitions = listSecretDefinitions();
1862
- if (!definitions.length) {
1863
- return { text: null };
1864
- }
1865
- const missing = definitions.filter((definition) => !getSecretValue(definition.id));
1866
- if (missing.length === 0) {
1867
- return { text: 'all configured', tone: 'success' };
1868
- }
1869
- const labels = missing.map((definition) => definition.label ?? definition.id);
1870
- return { text: `missing ${this.formatList(labels)}`, tone: 'warn' };
1871
- }
1872
- getToolSelectionSummary() {
1873
- const toolSettings = loadToolSettings();
1874
- const selection = buildEnabledToolSet(toolSettings);
1875
- const options = getToolToggleOptions();
1876
- if (!options.length) {
1877
- return null;
1878
- }
1879
- const enabledCount = options.filter((option) => selection.has(option.id)).length;
1880
- return `${enabledCount}/${options.length} enabled`;
1881
- }
1882
- formatList(values, maxItems = 3) {
1883
- if (!values.length) {
1884
- return '';
1885
- }
1886
- const shown = values.slice(0, maxItems);
1887
- const suffix = values.length > maxItems ? ', …' : '';
1888
- return `${shown.join(', ')}${suffix}`;
1889
- }
1890
1849
  buildSlashCommandList(header) {
1891
1850
  const lines = [theme.gradient.primary(header), ''];
1892
1851
  for (const command of this.slashCommands) {
@@ -2355,7 +2314,7 @@ export class InteractiveShell {
2355
2314
  this.autosaveIfEnabled();
2356
2315
  // Track metrics with Alpha Zero 2
2357
2316
  const elapsedMs = Date.now() - requestStartTime;
2358
- this.alphaZeroMetrics.recordMessage(elapsedMs);
2317
+ this.sessionMetrics.recordMessage(elapsedMs);
2359
2318
  if (!responseText?.trim()) {
2360
2319
  display.showWarning('The provider returned an empty response. Check your API key/provider selection or retry the prompt.');
2361
2320
  }
@@ -2373,10 +2332,14 @@ export class InteractiveShell {
2373
2332
  this.stopStreamingHeartbeat();
2374
2333
  this.isProcessing = false;
2375
2334
  this.terminalInput.setStreaming(false);
2335
+ this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
2376
2336
  this.uiAdapter.endProcessing('Ready for prompts');
2377
2337
  this.setIdleStatus();
2378
2338
  display.newLine();
2379
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();
2380
2343
  queueMicrotask(() => this.uiUpdates.setMode('idle'));
2381
2344
  // CRITICAL: Ensure readline prompt is active for user input
2382
2345
  // Claude Code style: New prompt naturally appears at bottom
@@ -2453,14 +2416,13 @@ When truly finished with ALL tasks, explicitly state "TASK_FULLY_COMPLETE".`;
2453
2416
  try {
2454
2417
  // Send the request and capture the response (streaming disabled)
2455
2418
  display.showThinking('Responding...');
2456
- this.refreshStatusLine(true);
2457
2419
  const response = await agent.send(currentPrompt, true);
2458
2420
  await this.awaitPendingCleanup();
2459
2421
  this.captureHistorySnapshot();
2460
2422
  this.autosaveIfEnabled();
2461
2423
  // Track metrics
2462
2424
  const elapsedMs = Date.now() - overallStartTime;
2463
- this.alphaZeroMetrics.recordMessage(elapsedMs);
2425
+ this.sessionMetrics.recordMessage(elapsedMs);
2464
2426
  if (!response?.trim()) {
2465
2427
  display.showWarning('Model returned an empty response. Retrying this iteration...');
2466
2428
  consecutiveNoProgress++;
@@ -2597,6 +2559,7 @@ What's the next action?`;
2597
2559
  this.stopStreamingHeartbeat();
2598
2560
  this.isProcessing = false;
2599
2561
  this.terminalInput.setStreaming(false);
2562
+ this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
2600
2563
  this.uiAdapter.endProcessing('Ready for prompts');
2601
2564
  this.setIdleStatus();
2602
2565
  this.updateStatusMessage(null);
@@ -2953,10 +2916,8 @@ What's the next action?`;
2953
2916
  try {
2954
2917
  // Send the error to the agent for fixing
2955
2918
  display.showThinking('Analyzing build errors');
2956
- this.refreshStatusLine(true);
2957
2919
  const response = await this.agent.send(prompt, true);
2958
2920
  display.stopThinking();
2959
- this.refreshStatusLine(true);
2960
2921
  if (response) {
2961
2922
  display.showAssistantMessage(response, { isFinal: true });
2962
2923
  }
@@ -3006,16 +2967,18 @@ What's the next action?`;
3006
2967
  display.showAssistantMessage(finalContent, enriched);
3007
2968
  }
3008
2969
  }
3009
- // 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)")
3010
2971
  display.stopThinking();
3011
- // Update context usage for mode controls display
2972
+ // Calculate context usage
2973
+ let contextInfo;
3012
2974
  if (enriched.contextWindowTokens && metadata.usage) {
3013
2975
  const total = this.totalTokens(metadata.usage);
3014
2976
  if (total && total > 0) {
3015
2977
  const percentage = Math.round((total / enriched.contextWindowTokens) * 100);
3016
- this.updateContextUsage(percentage);
2978
+ contextInfo = { percentage, tokens: total };
3017
2979
  }
3018
2980
  }
2981
+ display.showStatusLine('Ready for prompts', enriched.elapsedMs, contextInfo);
3019
2982
  // Auto-verify changes: build first (catches type errors), then tests
3020
2983
  void this.enforceAutoBuild('final-response');
3021
2984
  void this.enforceAutoTests('final-response');
@@ -3085,6 +3048,7 @@ What's the next action?`;
3085
3048
  this.stopStreamingHeartbeat();
3086
3049
  this.updateStatusMessage(null);
3087
3050
  this.terminalInput.setStreaming(false);
3051
+ this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
3088
3052
  this.terminalInput.render();
3089
3053
  },
3090
3054
  onVerificationNeeded: () => {
@@ -3121,6 +3085,7 @@ What's the next action?`;
3121
3085
  resetChatBoxAfterModelSwap() {
3122
3086
  this.updateStatusMessage(null);
3123
3087
  this.terminalInput.setStreaming(false);
3088
+ this.terminalInput.setContentEndRow(display.getTotalWrittenLines());
3124
3089
  this.terminalInput.render();
3125
3090
  this.ensureReadlineReady();
3126
3091
  }
@@ -3185,14 +3150,9 @@ What's the next action?`;
3185
3150
  return null;
3186
3151
  }
3187
3152
  const usageRatio = total / windowTokens;
3188
- this.latestTokenUsage = {
3189
- used: total,
3190
- limit: windowTokens,
3191
- };
3192
3153
  // Always update context usage in the UI
3193
3154
  const percentUsed = Math.round(usageRatio * 100);
3194
3155
  this.updateContextUsage(percentUsed);
3195
- this.refreshStatusLine(true);
3196
3156
  if (usageRatio < CONTEXT_USAGE_THRESHOLD) {
3197
3157
  return null;
3198
3158
  }
@@ -3470,6 +3430,8 @@ What's the next action?`;
3470
3430
  }
3471
3431
  this.refreshContextGauge();
3472
3432
  display.updateSessionInfo(nextState.model, nextState.provider);
3433
+ // Update the persistent model info display in terminal input
3434
+ this.terminalInput.setModelInfo(this.describeModelDetail());
3473
3435
  if (!this.isProcessing) {
3474
3436
  this.setIdleStatus();
3475
3437
  }