@yjjeong/omg 0.1.0

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 (702) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/LICENSE +21 -0
  3. package/README.md +153 -0
  4. package/dist/cli/args.d.ts +39 -0
  5. package/dist/cli/args.d.ts.map +1 -0
  6. package/dist/cli/args.js +129 -0
  7. package/dist/cli/args.js.map +1 -0
  8. package/dist/cli/autoCommit.d.ts +20 -0
  9. package/dist/cli/autoCommit.d.ts.map +1 -0
  10. package/dist/cli/autoCommit.js +121 -0
  11. package/dist/cli/autoCommit.js.map +1 -0
  12. package/dist/cli/bgTasks.d.ts +57 -0
  13. package/dist/cli/bgTasks.d.ts.map +1 -0
  14. package/dist/cli/bgTasks.js +193 -0
  15. package/dist/cli/bgTasks.js.map +1 -0
  16. package/dist/cli/compactor.d.ts +48 -0
  17. package/dist/cli/compactor.d.ts.map +1 -0
  18. package/dist/cli/compactor.js +73 -0
  19. package/dist/cli/compactor.js.map +1 -0
  20. package/dist/cli/doctor.d.ts +77 -0
  21. package/dist/cli/doctor.d.ts.map +1 -0
  22. package/dist/cli/doctor.js +279 -0
  23. package/dist/cli/doctor.js.map +1 -0
  24. package/dist/cli/gitStatus.d.ts +7 -0
  25. package/dist/cli/gitStatus.d.ts.map +1 -0
  26. package/dist/cli/gitStatus.js +70 -0
  27. package/dist/cli/gitStatus.js.map +1 -0
  28. package/dist/cli/handoff.d.ts +36 -0
  29. package/dist/cli/handoff.d.ts.map +1 -0
  30. package/dist/cli/handoff.js +60 -0
  31. package/dist/cli/handoff.js.map +1 -0
  32. package/dist/cli/interactive/brokers.d.ts +31 -0
  33. package/dist/cli/interactive/brokers.d.ts.map +1 -0
  34. package/dist/cli/interactive/brokers.js +259 -0
  35. package/dist/cli/interactive/brokers.js.map +1 -0
  36. package/dist/cli/interactive/index.d.ts +8 -0
  37. package/dist/cli/interactive/index.d.ts.map +1 -0
  38. package/dist/cli/interactive/index.js +731 -0
  39. package/dist/cli/interactive/index.js.map +1 -0
  40. package/dist/cli/interactive/proxyQuestions.d.ts +15 -0
  41. package/dist/cli/interactive/proxyQuestions.d.ts.map +1 -0
  42. package/dist/cli/interactive/proxyQuestions.js +48 -0
  43. package/dist/cli/interactive/proxyQuestions.js.map +1 -0
  44. package/dist/cli/interactive/tabManager.d.ts +32 -0
  45. package/dist/cli/interactive/tabManager.d.ts.map +1 -0
  46. package/dist/cli/interactive/tabManager.js +244 -0
  47. package/dist/cli/interactive/tabManager.js.map +1 -0
  48. package/dist/cli/interactive/teamHint.d.ts +2 -0
  49. package/dist/cli/interactive/teamHint.d.ts.map +1 -0
  50. package/dist/cli/interactive/teamHint.js +14 -0
  51. package/dist/cli/interactive/teamHint.js.map +1 -0
  52. package/dist/cli/login.d.ts +13 -0
  53. package/dist/cli/login.d.ts.map +1 -0
  54. package/dist/cli/login.js +53 -0
  55. package/dist/cli/login.js.map +1 -0
  56. package/dist/cli/modes/demo.d.ts +12 -0
  57. package/dist/cli/modes/demo.d.ts.map +1 -0
  58. package/dist/cli/modes/demo.js +48 -0
  59. package/dist/cli/modes/demo.js.map +1 -0
  60. package/dist/cli/modes/doctor.d.ts +28 -0
  61. package/dist/cli/modes/doctor.d.ts.map +1 -0
  62. package/dist/cli/modes/doctor.js +79 -0
  63. package/dist/cli/modes/doctor.js.map +1 -0
  64. package/dist/cli/modes/login.d.ts +5 -0
  65. package/dist/cli/modes/login.d.ts.map +1 -0
  66. package/dist/cli/modes/login.js +40 -0
  67. package/dist/cli/modes/login.js.map +1 -0
  68. package/dist/cli/modes/mcpServe.d.ts +9 -0
  69. package/dist/cli/modes/mcpServe.d.ts.map +1 -0
  70. package/dist/cli/modes/mcpServe.js +112 -0
  71. package/dist/cli/modes/mcpServe.js.map +1 -0
  72. package/dist/cli/modes/orchestrator.d.ts +14 -0
  73. package/dist/cli/modes/orchestrator.d.ts.map +1 -0
  74. package/dist/cli/modes/orchestrator.js +64 -0
  75. package/dist/cli/modes/orchestrator.js.map +1 -0
  76. package/dist/cli/modes/team.d.ts +14 -0
  77. package/dist/cli/modes/team.d.ts.map +1 -0
  78. package/dist/cli/modes/team.js +87 -0
  79. package/dist/cli/modes/team.js.map +1 -0
  80. package/dist/cli/registry.d.ts +3 -0
  81. package/dist/cli/registry.d.ts.map +1 -0
  82. package/dist/cli/registry.js +15 -0
  83. package/dist/cli/registry.js.map +1 -0
  84. package/dist/cli/slash/core.d.ts +3 -0
  85. package/dist/cli/slash/core.d.ts.map +1 -0
  86. package/dist/cli/slash/core.js +509 -0
  87. package/dist/cli/slash/core.js.map +1 -0
  88. package/dist/cli/slash/index.d.ts +3 -0
  89. package/dist/cli/slash/index.d.ts.map +1 -0
  90. package/dist/cli/slash/index.js +28 -0
  91. package/dist/cli/slash/index.js.map +1 -0
  92. package/dist/cli/slash/modes.d.ts +3 -0
  93. package/dist/cli/slash/modes.d.ts.map +1 -0
  94. package/dist/cli/slash/modes.js +530 -0
  95. package/dist/cli/slash/modes.js.map +1 -0
  96. package/dist/cli/slash/session.d.ts +3 -0
  97. package/dist/cli/slash/session.d.ts.map +1 -0
  98. package/dist/cli/slash/session.js +376 -0
  99. package/dist/cli/slash/session.js.map +1 -0
  100. package/dist/cli/slash/shared.d.ts +43 -0
  101. package/dist/cli/slash/shared.d.ts.map +1 -0
  102. package/dist/cli/slash/shared.js +6 -0
  103. package/dist/cli/slash/shared.js.map +1 -0
  104. package/dist/cli/slash/tabs.d.ts +3 -0
  105. package/dist/cli/slash/tabs.d.ts.map +1 -0
  106. package/dist/cli/slash/tabs.js +497 -0
  107. package/dist/cli/slash/tabs.js.map +1 -0
  108. package/dist/cli/slash/team.d.ts +3 -0
  109. package/dist/cli/slash/team.d.ts.map +1 -0
  110. package/dist/cli/slash/team.js +85 -0
  111. package/dist/cli/slash/team.js.map +1 -0
  112. package/dist/cli/slash.d.ts +3 -0
  113. package/dist/cli/slash.d.ts.map +1 -0
  114. package/dist/cli/slash.js +8 -0
  115. package/dist/cli/slash.js.map +1 -0
  116. package/dist/cli/teamPipeline.d.ts +42 -0
  117. package/dist/cli/teamPipeline.d.ts.map +1 -0
  118. package/dist/cli/teamPipeline.js +406 -0
  119. package/dist/cli/teamPipeline.js.map +1 -0
  120. package/dist/cli/touchedFiles.d.ts +14 -0
  121. package/dist/cli/touchedFiles.d.ts.map +1 -0
  122. package/dist/cli/touchedFiles.js +66 -0
  123. package/dist/cli/touchedFiles.js.map +1 -0
  124. package/dist/cli/turn.d.ts +47 -0
  125. package/dist/cli/turn.d.ts.map +1 -0
  126. package/dist/cli/turn.js +626 -0
  127. package/dist/cli/turn.js.map +1 -0
  128. package/dist/cli/types.d.ts +47 -0
  129. package/dist/cli/types.d.ts.map +1 -0
  130. package/dist/cli/types.js +5 -0
  131. package/dist/cli/types.js.map +1 -0
  132. package/dist/cli/uiSession.d.ts +10 -0
  133. package/dist/cli/uiSession.d.ts.map +1 -0
  134. package/dist/cli/uiSession.js +66 -0
  135. package/dist/cli/uiSession.js.map +1 -0
  136. package/dist/cli.d.ts +3 -0
  137. package/dist/cli.d.ts.map +1 -0
  138. package/dist/cli.js +128 -0
  139. package/dist/cli.js.map +1 -0
  140. package/dist/core/adapter.d.ts +47 -0
  141. package/dist/core/adapter.d.ts.map +1 -0
  142. package/dist/core/adapter.js +48 -0
  143. package/dist/core/adapter.js.map +1 -0
  144. package/dist/core/adapters/anthropic.d.ts +35 -0
  145. package/dist/core/adapters/anthropic.d.ts.map +1 -0
  146. package/dist/core/adapters/anthropic.js +203 -0
  147. package/dist/core/adapters/anthropic.js.map +1 -0
  148. package/dist/core/adapters/claudeCli.d.ts +126 -0
  149. package/dist/core/adapters/claudeCli.d.ts.map +1 -0
  150. package/dist/core/adapters/claudeCli.js +584 -0
  151. package/dist/core/adapters/claudeCli.js.map +1 -0
  152. package/dist/core/adapters/cliAdapterBase.d.ts +48 -0
  153. package/dist/core/adapters/cliAdapterBase.d.ts.map +1 -0
  154. package/dist/core/adapters/cliAdapterBase.js +105 -0
  155. package/dist/core/adapters/cliAdapterBase.js.map +1 -0
  156. package/dist/core/adapters/cliStderr.d.ts +35 -0
  157. package/dist/core/adapters/cliStderr.d.ts.map +1 -0
  158. package/dist/core/adapters/cliStderr.js +87 -0
  159. package/dist/core/adapters/cliStderr.js.map +1 -0
  160. package/dist/core/adapters/codexCli.d.ts +113 -0
  161. package/dist/core/adapters/codexCli.d.ts.map +1 -0
  162. package/dist/core/adapters/codexCli.js +424 -0
  163. package/dist/core/adapters/codexCli.js.map +1 -0
  164. package/dist/core/adapters/gemini.d.ts +17 -0
  165. package/dist/core/adapters/gemini.d.ts.map +1 -0
  166. package/dist/core/adapters/gemini.js +133 -0
  167. package/dist/core/adapters/gemini.js.map +1 -0
  168. package/dist/core/adapters/geminiCli.d.ts +91 -0
  169. package/dist/core/adapters/geminiCli.d.ts.map +1 -0
  170. package/dist/core/adapters/geminiCli.js +276 -0
  171. package/dist/core/adapters/geminiCli.js.map +1 -0
  172. package/dist/core/adapters/nudges.d.ts +21 -0
  173. package/dist/core/adapters/nudges.d.ts.map +1 -0
  174. package/dist/core/adapters/nudges.js +75 -0
  175. package/dist/core/adapters/nudges.js.map +1 -0
  176. package/dist/core/adapters/openai.d.ts +17 -0
  177. package/dist/core/adapters/openai.d.ts.map +1 -0
  178. package/dist/core/adapters/openai.js +138 -0
  179. package/dist/core/adapters/openai.js.map +1 -0
  180. package/dist/core/adapters/parseFailures.d.ts +10 -0
  181. package/dist/core/adapters/parseFailures.d.ts.map +1 -0
  182. package/dist/core/adapters/parseFailures.js +35 -0
  183. package/dist/core/adapters/parseFailures.js.map +1 -0
  184. package/dist/core/adapters/utils.d.ts +11 -0
  185. package/dist/core/adapters/utils.d.ts.map +1 -0
  186. package/dist/core/adapters/utils.js +33 -0
  187. package/dist/core/adapters/utils.js.map +1 -0
  188. package/dist/core/askBroker.d.ts +11 -0
  189. package/dist/core/askBroker.d.ts.map +1 -0
  190. package/dist/core/askBroker.js +78 -0
  191. package/dist/core/askBroker.js.map +1 -0
  192. package/dist/core/atomicWrite.d.ts +5 -0
  193. package/dist/core/atomicWrite.d.ts.map +1 -0
  194. package/dist/core/atomicWrite.js +18 -0
  195. package/dist/core/atomicWrite.js.map +1 -0
  196. package/dist/core/brokers/askBroker.d.ts +11 -0
  197. package/dist/core/brokers/askBroker.d.ts.map +1 -0
  198. package/dist/core/brokers/askBroker.js +78 -0
  199. package/dist/core/brokers/askBroker.js.map +1 -0
  200. package/dist/core/brokers/permissionBroker.d.ts +7 -0
  201. package/dist/core/brokers/permissionBroker.d.ts.map +1 -0
  202. package/dist/core/brokers/permissionBroker.js +63 -0
  203. package/dist/core/brokers/permissionBroker.js.map +1 -0
  204. package/dist/core/brokers/socketBroker.d.ts +35 -0
  205. package/dist/core/brokers/socketBroker.d.ts.map +1 -0
  206. package/dist/core/brokers/socketBroker.js +74 -0
  207. package/dist/core/brokers/socketBroker.js.map +1 -0
  208. package/dist/core/clipboard.d.ts +4 -0
  209. package/dist/core/clipboard.d.ts.map +1 -0
  210. package/dist/core/clipboard.js +46 -0
  211. package/dist/core/clipboard.js.map +1 -0
  212. package/dist/core/compactor.d.ts +32 -0
  213. package/dist/core/compactor.d.ts.map +1 -0
  214. package/dist/core/compactor.js +91 -0
  215. package/dist/core/compactor.js.map +1 -0
  216. package/dist/core/consensusEngine.d.ts +21 -0
  217. package/dist/core/consensusEngine.d.ts.map +1 -0
  218. package/dist/core/consensusEngine.js +116 -0
  219. package/dist/core/consensusEngine.js.map +1 -0
  220. package/dist/core/context/contextCompressor.d.ts +10 -0
  221. package/dist/core/context/contextCompressor.d.ts.map +1 -0
  222. package/dist/core/context/contextCompressor.js +54 -0
  223. package/dist/core/context/contextCompressor.js.map +1 -0
  224. package/dist/core/context/contextWindows.d.ts +25 -0
  225. package/dist/core/context/contextWindows.d.ts.map +1 -0
  226. package/dist/core/context/contextWindows.js +101 -0
  227. package/dist/core/context/contextWindows.js.map +1 -0
  228. package/dist/core/context/summarizer.d.ts +65 -0
  229. package/dist/core/context/summarizer.d.ts.map +1 -0
  230. package/dist/core/context/summarizer.js +184 -0
  231. package/dist/core/context/summarizer.js.map +1 -0
  232. package/dist/core/context/usageCache.d.ts +19 -0
  233. package/dist/core/context/usageCache.d.ts.map +1 -0
  234. package/dist/core/context/usageCache.js +157 -0
  235. package/dist/core/context/usageCache.js.map +1 -0
  236. package/dist/core/context/usageWindow.d.ts +19 -0
  237. package/dist/core/context/usageWindow.d.ts.map +1 -0
  238. package/dist/core/context/usageWindow.js +73 -0
  239. package/dist/core/context/usageWindow.js.map +1 -0
  240. package/dist/core/contextCompressor.d.ts +10 -0
  241. package/dist/core/contextCompressor.d.ts.map +1 -0
  242. package/dist/core/contextCompressor.js +54 -0
  243. package/dist/core/contextCompressor.js.map +1 -0
  244. package/dist/core/contextWindows.d.ts +5 -0
  245. package/dist/core/contextWindows.d.ts.map +1 -0
  246. package/dist/core/contextWindows.js +60 -0
  247. package/dist/core/contextWindows.js.map +1 -0
  248. package/dist/core/continuum/digest.d.ts +35 -0
  249. package/dist/core/continuum/digest.d.ts.map +1 -0
  250. package/dist/core/continuum/digest.js +91 -0
  251. package/dist/core/continuum/digest.js.map +1 -0
  252. package/dist/core/continuum/index.d.ts +6 -0
  253. package/dist/core/continuum/index.d.ts.map +1 -0
  254. package/dist/core/continuum/index.js +7 -0
  255. package/dist/core/continuum/index.js.map +1 -0
  256. package/dist/core/continuum/inject.d.ts +9 -0
  257. package/dist/core/continuum/inject.d.ts.map +1 -0
  258. package/dist/core/continuum/inject.js +78 -0
  259. package/dist/core/continuum/inject.js.map +1 -0
  260. package/dist/core/continuum/projectId.d.ts +10 -0
  261. package/dist/core/continuum/projectId.d.ts.map +1 -0
  262. package/dist/core/continuum/projectId.js +60 -0
  263. package/dist/core/continuum/projectId.js.map +1 -0
  264. package/dist/core/continuum/store.d.ts +24 -0
  265. package/dist/core/continuum/store.d.ts.map +1 -0
  266. package/dist/core/continuum/store.js +144 -0
  267. package/dist/core/continuum/store.js.map +1 -0
  268. package/dist/core/continuum/types.d.ts +87 -0
  269. package/dist/core/continuum/types.d.ts.map +1 -0
  270. package/dist/core/continuum/types.js +9 -0
  271. package/dist/core/continuum/types.js.map +1 -0
  272. package/dist/core/dag.d.ts +21 -0
  273. package/dist/core/dag.d.ts.map +1 -0
  274. package/dist/core/dag.js +71 -0
  275. package/dist/core/dag.js.map +1 -0
  276. package/dist/core/director.d.ts +11 -0
  277. package/dist/core/director.d.ts.map +1 -0
  278. package/dist/core/director.js +37 -0
  279. package/dist/core/director.js.map +1 -0
  280. package/dist/core/hookedToolBroker.d.ts +25 -0
  281. package/dist/core/hookedToolBroker.d.ts.map +1 -0
  282. package/dist/core/hookedToolBroker.js +95 -0
  283. package/dist/core/hookedToolBroker.js.map +1 -0
  284. package/dist/core/langHint.d.ts +9 -0
  285. package/dist/core/langHint.d.ts.map +1 -0
  286. package/dist/core/langHint.js +33 -0
  287. package/dist/core/langHint.js.map +1 -0
  288. package/dist/core/mcp/mcpClient.d.ts +42 -0
  289. package/dist/core/mcp/mcpClient.d.ts.map +1 -0
  290. package/dist/core/mcp/mcpClient.js +134 -0
  291. package/dist/core/mcp/mcpClient.js.map +1 -0
  292. package/dist/core/mcp/mcpConfig.d.ts +58 -0
  293. package/dist/core/mcp/mcpConfig.d.ts.map +1 -0
  294. package/dist/core/mcp/mcpConfig.js +148 -0
  295. package/dist/core/mcp/mcpConfig.js.map +1 -0
  296. package/dist/core/mcp/mcpManager.d.ts +31 -0
  297. package/dist/core/mcp/mcpManager.d.ts.map +1 -0
  298. package/dist/core/mcp/mcpManager.js +83 -0
  299. package/dist/core/mcp/mcpManager.js.map +1 -0
  300. package/dist/core/mcpClient.d.ts +42 -0
  301. package/dist/core/mcpClient.d.ts.map +1 -0
  302. package/dist/core/mcpClient.js +134 -0
  303. package/dist/core/mcpClient.js.map +1 -0
  304. package/dist/core/mcpConfig.d.ts +24 -0
  305. package/dist/core/mcpConfig.d.ts.map +1 -0
  306. package/dist/core/mcpConfig.js +74 -0
  307. package/dist/core/mcpConfig.js.map +1 -0
  308. package/dist/core/mcpManager.d.ts +31 -0
  309. package/dist/core/mcpManager.d.ts.map +1 -0
  310. package/dist/core/mcpManager.js +83 -0
  311. package/dist/core/mcpManager.js.map +1 -0
  312. package/dist/core/memory.d.ts +22 -0
  313. package/dist/core/memory.d.ts.map +1 -0
  314. package/dist/core/memory.js +102 -0
  315. package/dist/core/memory.js.map +1 -0
  316. package/dist/core/omgToolManifest.d.ts +34 -0
  317. package/dist/core/omgToolManifest.d.ts.map +1 -0
  318. package/dist/core/omgToolManifest.js +59 -0
  319. package/dist/core/omgToolManifest.js.map +1 -0
  320. package/dist/core/orchestration/consensusEngine.d.ts +21 -0
  321. package/dist/core/orchestration/consensusEngine.d.ts.map +1 -0
  322. package/dist/core/orchestration/consensusEngine.js +116 -0
  323. package/dist/core/orchestration/consensusEngine.js.map +1 -0
  324. package/dist/core/orchestration/dag.d.ts +21 -0
  325. package/dist/core/orchestration/dag.d.ts.map +1 -0
  326. package/dist/core/orchestration/dag.js +71 -0
  327. package/dist/core/orchestration/dag.js.map +1 -0
  328. package/dist/core/orchestration/director.d.ts +11 -0
  329. package/dist/core/orchestration/director.d.ts.map +1 -0
  330. package/dist/core/orchestration/director.js +37 -0
  331. package/dist/core/orchestration/director.js.map +1 -0
  332. package/dist/core/orchestration/orchestrator.d.ts +32 -0
  333. package/dist/core/orchestration/orchestrator.d.ts.map +1 -0
  334. package/dist/core/orchestration/orchestrator.js +214 -0
  335. package/dist/core/orchestration/orchestrator.js.map +1 -0
  336. package/dist/core/orchestration/roleRouter.d.ts +28 -0
  337. package/dist/core/orchestration/roleRouter.d.ts.map +1 -0
  338. package/dist/core/orchestration/roleRouter.js +64 -0
  339. package/dist/core/orchestration/roleRouter.js.map +1 -0
  340. package/dist/core/orchestration/teamRunner.d.ts +69 -0
  341. package/dist/core/orchestration/teamRunner.d.ts.map +1 -0
  342. package/dist/core/orchestration/teamRunner.js +477 -0
  343. package/dist/core/orchestration/teamRunner.js.map +1 -0
  344. package/dist/core/orchestration/types.d.ts +115 -0
  345. package/dist/core/orchestration/types.d.ts.map +1 -0
  346. package/dist/core/orchestration/types.js +71 -0
  347. package/dist/core/orchestration/types.js.map +1 -0
  348. package/dist/core/orchestrator.d.ts +32 -0
  349. package/dist/core/orchestrator.d.ts.map +1 -0
  350. package/dist/core/orchestrator.js +214 -0
  351. package/dist/core/orchestrator.js.map +1 -0
  352. package/dist/core/permissionBroker.d.ts +7 -0
  353. package/dist/core/permissionBroker.d.ts.map +1 -0
  354. package/dist/core/permissionBroker.js +63 -0
  355. package/dist/core/permissionBroker.js.map +1 -0
  356. package/dist/core/planConfig.d.ts +15 -0
  357. package/dist/core/planConfig.d.ts.map +1 -0
  358. package/dist/core/planConfig.js +98 -0
  359. package/dist/core/planConfig.js.map +1 -0
  360. package/dist/core/presetPersistence.d.ts +4 -0
  361. package/dist/core/presetPersistence.d.ts.map +1 -0
  362. package/dist/core/presetPersistence.js +64 -0
  363. package/dist/core/presetPersistence.js.map +1 -0
  364. package/dist/core/roleRouter.d.ts +26 -0
  365. package/dist/core/roleRouter.d.ts.map +1 -0
  366. package/dist/core/roleRouter.js +62 -0
  367. package/dist/core/roleRouter.js.map +1 -0
  368. package/dist/core/sessionList.d.ts +26 -0
  369. package/dist/core/sessionList.d.ts.map +1 -0
  370. package/dist/core/sessionList.js +278 -0
  371. package/dist/core/sessionList.js.map +1 -0
  372. package/dist/core/slugify.d.ts +2 -0
  373. package/dist/core/slugify.d.ts.map +1 -0
  374. package/dist/core/slugify.js +17 -0
  375. package/dist/core/slugify.js.map +1 -0
  376. package/dist/core/socketBroker.d.ts +19 -0
  377. package/dist/core/socketBroker.d.ts.map +1 -0
  378. package/dist/core/socketBroker.js +48 -0
  379. package/dist/core/socketBroker.js.map +1 -0
  380. package/dist/core/state/agentsMdScaffold.d.ts +15 -0
  381. package/dist/core/state/agentsMdScaffold.d.ts.map +1 -0
  382. package/dist/core/state/agentsMdScaffold.js +118 -0
  383. package/dist/core/state/agentsMdScaffold.js.map +1 -0
  384. package/dist/core/state/atomicWrite.d.ts +5 -0
  385. package/dist/core/state/atomicWrite.d.ts.map +1 -0
  386. package/dist/core/state/atomicWrite.js +18 -0
  387. package/dist/core/state/atomicWrite.js.map +1 -0
  388. package/dist/core/state/handoff.d.ts +20 -0
  389. package/dist/core/state/handoff.d.ts.map +1 -0
  390. package/dist/core/state/handoff.js +71 -0
  391. package/dist/core/state/handoff.js.map +1 -0
  392. package/dist/core/state/mcpCatalog.d.ts +11 -0
  393. package/dist/core/state/mcpCatalog.d.ts.map +1 -0
  394. package/dist/core/state/mcpCatalog.js +51 -0
  395. package/dist/core/state/mcpCatalog.js.map +1 -0
  396. package/dist/core/state/mcpRecommendations.d.ts +7 -0
  397. package/dist/core/state/mcpRecommendations.d.ts.map +1 -0
  398. package/dist/core/state/mcpRecommendations.js +57 -0
  399. package/dist/core/state/mcpRecommendations.js.map +1 -0
  400. package/dist/core/state/memory.d.ts +22 -0
  401. package/dist/core/state/memory.d.ts.map +1 -0
  402. package/dist/core/state/memory.js +102 -0
  403. package/dist/core/state/memory.js.map +1 -0
  404. package/dist/core/state/planConfig.d.ts +15 -0
  405. package/dist/core/state/planConfig.d.ts.map +1 -0
  406. package/dist/core/state/planConfig.js +98 -0
  407. package/dist/core/state/planConfig.js.map +1 -0
  408. package/dist/core/state/presetPersistence.d.ts +4 -0
  409. package/dist/core/state/presetPersistence.d.ts.map +1 -0
  410. package/dist/core/state/presetPersistence.js +67 -0
  411. package/dist/core/state/presetPersistence.js.map +1 -0
  412. package/dist/core/state/sessionList.d.ts +26 -0
  413. package/dist/core/state/sessionList.d.ts.map +1 -0
  414. package/dist/core/state/sessionList.js +278 -0
  415. package/dist/core/state/sessionList.js.map +1 -0
  416. package/dist/core/state/stackDetect.d.ts +8 -0
  417. package/dist/core/state/stackDetect.d.ts.map +1 -0
  418. package/dist/core/state/stackDetect.js +40 -0
  419. package/dist/core/state/stackDetect.js.map +1 -0
  420. package/dist/core/state/tabPersistence.d.ts +29 -0
  421. package/dist/core/state/tabPersistence.d.ts.map +1 -0
  422. package/dist/core/state/tabPersistence.js +65 -0
  423. package/dist/core/state/tabPersistence.js.map +1 -0
  424. package/dist/core/tabPersistence.d.ts +29 -0
  425. package/dist/core/tabPersistence.d.ts.map +1 -0
  426. package/dist/core/tabPersistence.js +65 -0
  427. package/dist/core/tabPersistence.js.map +1 -0
  428. package/dist/core/teamRunner.d.ts +42 -0
  429. package/dist/core/teamRunner.d.ts.map +1 -0
  430. package/dist/core/teamRunner.js +248 -0
  431. package/dist/core/teamRunner.js.map +1 -0
  432. package/dist/core/toolGate.d.ts +23 -0
  433. package/dist/core/toolGate.d.ts.map +1 -0
  434. package/dist/core/toolGate.js +51 -0
  435. package/dist/core/toolGate.js.map +1 -0
  436. package/dist/core/toolInterceptor.d.ts +7 -0
  437. package/dist/core/toolInterceptor.d.ts.map +1 -0
  438. package/dist/core/toolInterceptor.js +108 -0
  439. package/dist/core/toolInterceptor.js.map +1 -0
  440. package/dist/core/tools/hookedToolBroker.d.ts +25 -0
  441. package/dist/core/tools/hookedToolBroker.d.ts.map +1 -0
  442. package/dist/core/tools/hookedToolBroker.js +95 -0
  443. package/dist/core/tools/hookedToolBroker.js.map +1 -0
  444. package/dist/core/tools/omgToolManifest.d.ts +42 -0
  445. package/dist/core/tools/omgToolManifest.d.ts.map +1 -0
  446. package/dist/core/tools/omgToolManifest.js +66 -0
  447. package/dist/core/tools/omgToolManifest.js.map +1 -0
  448. package/dist/core/tools/toolGate.d.ts +23 -0
  449. package/dist/core/tools/toolGate.d.ts.map +1 -0
  450. package/dist/core/tools/toolGate.js +51 -0
  451. package/dist/core/tools/toolGate.js.map +1 -0
  452. package/dist/core/tools/toolInterceptor.d.ts +7 -0
  453. package/dist/core/tools/toolInterceptor.d.ts.map +1 -0
  454. package/dist/core/tools/toolInterceptor.js +108 -0
  455. package/dist/core/tools/toolInterceptor.js.map +1 -0
  456. package/dist/core/tools/tools.d.ts +34 -0
  457. package/dist/core/tools/tools.d.ts.map +1 -0
  458. package/dist/core/tools/tools.js +328 -0
  459. package/dist/core/tools/tools.js.map +1 -0
  460. package/dist/core/tools.d.ts +34 -0
  461. package/dist/core/tools.d.ts.map +1 -0
  462. package/dist/core/tools.js +300 -0
  463. package/dist/core/tools.js.map +1 -0
  464. package/dist/core/types.d.ts +107 -0
  465. package/dist/core/types.d.ts.map +1 -0
  466. package/dist/core/types.js +55 -0
  467. package/dist/core/types.js.map +1 -0
  468. package/dist/core/usageCache.d.ts +19 -0
  469. package/dist/core/usageCache.d.ts.map +1 -0
  470. package/dist/core/usageCache.js +157 -0
  471. package/dist/core/usageCache.js.map +1 -0
  472. package/dist/core/usageWindow.d.ts +19 -0
  473. package/dist/core/usageWindow.d.ts.map +1 -0
  474. package/dist/core/usageWindow.js +73 -0
  475. package/dist/core/usageWindow.js.map +1 -0
  476. package/dist/core/util/bgProtocol.d.ts +5 -0
  477. package/dist/core/util/bgProtocol.d.ts.map +1 -0
  478. package/dist/core/util/bgProtocol.js +20 -0
  479. package/dist/core/util/bgProtocol.js.map +1 -0
  480. package/dist/core/util/clipboard.d.ts +4 -0
  481. package/dist/core/util/clipboard.d.ts.map +1 -0
  482. package/dist/core/util/clipboard.js +46 -0
  483. package/dist/core/util/clipboard.js.map +1 -0
  484. package/dist/core/util/clipboardImage.d.ts +3 -0
  485. package/dist/core/util/clipboardImage.d.ts.map +1 -0
  486. package/dist/core/util/clipboardImage.js +58 -0
  487. package/dist/core/util/clipboardImage.js.map +1 -0
  488. package/dist/core/util/langHint.d.ts +9 -0
  489. package/dist/core/util/langHint.d.ts.map +1 -0
  490. package/dist/core/util/langHint.js +33 -0
  491. package/dist/core/util/langHint.js.map +1 -0
  492. package/dist/core/util/slugify.d.ts +2 -0
  493. package/dist/core/util/slugify.d.ts.map +1 -0
  494. package/dist/core/util/slugify.js +28 -0
  495. package/dist/core/util/slugify.js.map +1 -0
  496. package/dist/hooks/hookedToolProxy.mjs +118 -0
  497. package/dist/index.d.ts +2 -0
  498. package/dist/index.d.ts.map +1 -0
  499. package/dist/index.js +8 -0
  500. package/dist/index.js.map +1 -0
  501. package/dist/ipc/dispatcher.d.ts +21 -0
  502. package/dist/ipc/dispatcher.d.ts.map +1 -0
  503. package/dist/ipc/dispatcher.js +160 -0
  504. package/dist/ipc/dispatcher.js.map +1 -0
  505. package/dist/ipc/events.d.ts +33 -0
  506. package/dist/ipc/events.d.ts.map +1 -0
  507. package/dist/ipc/events.js +42 -0
  508. package/dist/ipc/events.js.map +1 -0
  509. package/dist/ipc/rpc.d.ts +31 -0
  510. package/dist/ipc/rpc.d.ts.map +1 -0
  511. package/dist/ipc/rpc.js +110 -0
  512. package/dist/ipc/rpc.js.map +1 -0
  513. package/dist/ipc/stdio.d.ts +11 -0
  514. package/dist/ipc/stdio.d.ts.map +1 -0
  515. package/dist/ipc/stdio.js +52 -0
  516. package/dist/ipc/stdio.js.map +1 -0
  517. package/dist/mcp/askClient.d.ts +9 -0
  518. package/dist/mcp/askClient.d.ts.map +1 -0
  519. package/dist/mcp/askClient.js +70 -0
  520. package/dist/mcp/askClient.js.map +1 -0
  521. package/dist/mcp/constants.d.ts +6 -0
  522. package/dist/mcp/constants.d.ts.map +1 -0
  523. package/dist/mcp/constants.js +8 -0
  524. package/dist/mcp/constants.js.map +1 -0
  525. package/dist/mcp/permissionClient.d.ts +5 -0
  526. package/dist/mcp/permissionClient.d.ts.map +1 -0
  527. package/dist/mcp/permissionClient.js +71 -0
  528. package/dist/mcp/permissionClient.js.map +1 -0
  529. package/dist/mcp/schemas.d.ts +9 -0
  530. package/dist/mcp/schemas.d.ts.map +1 -0
  531. package/dist/mcp/schemas.js +121 -0
  532. package/dist/mcp/schemas.js.map +1 -0
  533. package/dist/mcp/server.d.ts +41 -0
  534. package/dist/mcp/server.d.ts.map +1 -0
  535. package/dist/mcp/server.js +204 -0
  536. package/dist/mcp/server.js.map +1 -0
  537. package/dist/policy/loader.d.ts +27 -0
  538. package/dist/policy/loader.d.ts.map +1 -0
  539. package/dist/policy/loader.js +89 -0
  540. package/dist/policy/loader.js.map +1 -0
  541. package/dist/policy/team-claude-only.yaml +46 -0
  542. package/dist/policy/team-codex-only.yaml +46 -0
  543. package/dist/policy/team-codex.yaml +54 -0
  544. package/dist/policy/team.yaml +104 -0
  545. package/dist/toolhook/hookedToolProxy.mjs +118 -0
  546. package/dist/ui/components/App.d.ts +14 -0
  547. package/dist/ui/components/App.d.ts.map +1 -0
  548. package/dist/ui/components/App.js +803 -0
  549. package/dist/ui/components/App.js.map +1 -0
  550. package/dist/ui/components/AskPicker.d.ts +8 -0
  551. package/dist/ui/components/AskPicker.d.ts.map +1 -0
  552. package/dist/ui/components/AskPicker.js +202 -0
  553. package/dist/ui/components/AskPicker.js.map +1 -0
  554. package/dist/ui/components/CommandInput.d.ts +63 -0
  555. package/dist/ui/components/CommandInput.d.ts.map +1 -0
  556. package/dist/ui/components/CommandInput.js +994 -0
  557. package/dist/ui/components/CommandInput.js.map +1 -0
  558. package/dist/ui/components/DiffView.d.ts +19 -0
  559. package/dist/ui/components/DiffView.d.ts.map +1 -0
  560. package/dist/ui/components/DiffView.js +93 -0
  561. package/dist/ui/components/DiffView.js.map +1 -0
  562. package/dist/ui/components/Dock.d.ts +49 -0
  563. package/dist/ui/components/Dock.d.ts.map +1 -0
  564. package/dist/ui/components/Dock.js +52 -0
  565. package/dist/ui/components/Dock.js.map +1 -0
  566. package/dist/ui/components/EventLog.d.ts +42 -0
  567. package/dist/ui/components/EventLog.d.ts.map +1 -0
  568. package/dist/ui/components/EventLog.js +450 -0
  569. package/dist/ui/components/EventLog.js.map +1 -0
  570. package/dist/ui/components/FileSuggest.d.ts +8 -0
  571. package/dist/ui/components/FileSuggest.d.ts.map +1 -0
  572. package/dist/ui/components/FileSuggest.js +19 -0
  573. package/dist/ui/components/FileSuggest.js.map +1 -0
  574. package/dist/ui/components/HRule.d.ts +27 -0
  575. package/dist/ui/components/HRule.d.ts.map +1 -0
  576. package/dist/ui/components/HRule.js +75 -0
  577. package/dist/ui/components/HRule.js.map +1 -0
  578. package/dist/ui/components/HintBar.d.ts +2 -0
  579. package/dist/ui/components/HintBar.d.ts.map +1 -0
  580. package/dist/ui/components/HintBar.js +19 -0
  581. package/dist/ui/components/HintBar.js.map +1 -0
  582. package/dist/ui/components/MarkdownText.d.ts +13 -0
  583. package/dist/ui/components/MarkdownText.d.ts.map +1 -0
  584. package/dist/ui/components/MarkdownText.js +255 -0
  585. package/dist/ui/components/MarkdownText.js.map +1 -0
  586. package/dist/ui/components/PermissionPrompt.d.ts +8 -0
  587. package/dist/ui/components/PermissionPrompt.d.ts.map +1 -0
  588. package/dist/ui/components/PermissionPrompt.js +37 -0
  589. package/dist/ui/components/PermissionPrompt.js.map +1 -0
  590. package/dist/ui/components/SessionPicker.d.ts +16 -0
  591. package/dist/ui/components/SessionPicker.d.ts.map +1 -0
  592. package/dist/ui/components/SessionPicker.js +116 -0
  593. package/dist/ui/components/SessionPicker.js.map +1 -0
  594. package/dist/ui/components/SlashPalette.d.ts +8 -0
  595. package/dist/ui/components/SlashPalette.d.ts.map +1 -0
  596. package/dist/ui/components/SlashPalette.js +41 -0
  597. package/dist/ui/components/SlashPalette.js.map +1 -0
  598. package/dist/ui/components/Spinner.d.ts +37 -0
  599. package/dist/ui/components/Spinner.d.ts.map +1 -0
  600. package/dist/ui/components/Spinner.js +139 -0
  601. package/dist/ui/components/Spinner.js.map +1 -0
  602. package/dist/ui/components/StatusBar.d.ts +92 -0
  603. package/dist/ui/components/StatusBar.d.ts.map +1 -0
  604. package/dist/ui/components/StatusBar.js +268 -0
  605. package/dist/ui/components/StatusBar.js.map +1 -0
  606. package/dist/ui/components/TabChip.d.ts +11 -0
  607. package/dist/ui/components/TabChip.d.ts.map +1 -0
  608. package/dist/ui/components/TabChip.js +23 -0
  609. package/dist/ui/components/TabChip.js.map +1 -0
  610. package/dist/ui/components/TeamIndicator.d.ts +6 -0
  611. package/dist/ui/components/TeamIndicator.d.ts.map +1 -0
  612. package/dist/ui/components/TeamIndicator.js +17 -0
  613. package/dist/ui/components/TeamIndicator.js.map +1 -0
  614. package/dist/ui/components/TeamStatusPanel.d.ts +14 -0
  615. package/dist/ui/components/TeamStatusPanel.d.ts.map +1 -0
  616. package/dist/ui/components/TeamStatusPanel.js +65 -0
  617. package/dist/ui/components/TeamStatusPanel.js.map +1 -0
  618. package/dist/ui/components/ThinkingBlock.d.ts +10 -0
  619. package/dist/ui/components/ThinkingBlock.d.ts.map +1 -0
  620. package/dist/ui/components/ThinkingBlock.js +21 -0
  621. package/dist/ui/components/ThinkingBlock.js.map +1 -0
  622. package/dist/ui/components/TodoIndicator.d.ts +11 -0
  623. package/dist/ui/components/TodoIndicator.d.ts.map +1 -0
  624. package/dist/ui/components/TodoIndicator.js +37 -0
  625. package/dist/ui/components/TodoIndicator.js.map +1 -0
  626. package/dist/ui/components/ToolCallCard.d.ts +16 -0
  627. package/dist/ui/components/ToolCallCard.d.ts.map +1 -0
  628. package/dist/ui/components/ToolCallCard.js +195 -0
  629. package/dist/ui/components/ToolCallCard.js.map +1 -0
  630. package/dist/ui/components/Welcome.d.ts +8 -0
  631. package/dist/ui/components/Welcome.d.ts.map +1 -0
  632. package/dist/ui/components/Welcome.js +53 -0
  633. package/dist/ui/components/Welcome.js.map +1 -0
  634. package/dist/ui/cursorState.d.ts +29 -0
  635. package/dist/ui/cursorState.d.ts.map +1 -0
  636. package/dist/ui/cursorState.js +49 -0
  637. package/dist/ui/cursorState.js.map +1 -0
  638. package/dist/ui/diff.d.ts +34 -0
  639. package/dist/ui/diff.d.ts.map +1 -0
  640. package/dist/ui/diff.js +184 -0
  641. package/dist/ui/diff.js.map +1 -0
  642. package/dist/ui/diffLang.d.ts +2 -0
  643. package/dist/ui/diffLang.d.ts.map +1 -0
  644. package/dist/ui/diffLang.js +36 -0
  645. package/dist/ui/diffLang.js.map +1 -0
  646. package/dist/ui/emoji.d.ts +4 -0
  647. package/dist/ui/emoji.d.ts.map +1 -0
  648. package/dist/ui/emoji.js +73 -0
  649. package/dist/ui/emoji.js.map +1 -0
  650. package/dist/ui/fileMentions.d.ts +41 -0
  651. package/dist/ui/fileMentions.d.ts.map +1 -0
  652. package/dist/ui/fileMentions.js +135 -0
  653. package/dist/ui/fileMentions.js.map +1 -0
  654. package/dist/ui/hooks/useLineEditor.d.ts +44 -0
  655. package/dist/ui/hooks/useLineEditor.d.ts.map +1 -0
  656. package/dist/ui/hooks/useLineEditor.js +142 -0
  657. package/dist/ui/hooks/useLineEditor.js.map +1 -0
  658. package/dist/ui/inputHistory.d.ts +8 -0
  659. package/dist/ui/inputHistory.d.ts.map +1 -0
  660. package/dist/ui/inputHistory.js +56 -0
  661. package/dist/ui/inputHistory.js.map +1 -0
  662. package/dist/ui/jsonrpc.d.ts +17 -0
  663. package/dist/ui/jsonrpc.d.ts.map +1 -0
  664. package/dist/ui/jsonrpc.js +41 -0
  665. package/dist/ui/jsonrpc.js.map +1 -0
  666. package/dist/ui/launcher.d.ts +20 -0
  667. package/dist/ui/launcher.d.ts.map +1 -0
  668. package/dist/ui/launcher.js +185 -0
  669. package/dist/ui/launcher.js.map +1 -0
  670. package/dist/ui/markdown.d.ts +104 -0
  671. package/dist/ui/markdown.d.ts.map +1 -0
  672. package/dist/ui/markdown.js +449 -0
  673. package/dist/ui/markdown.js.map +1 -0
  674. package/dist/ui/mouse.d.ts +22 -0
  675. package/dist/ui/mouse.d.ts.map +1 -0
  676. package/dist/ui/mouse.js +31 -0
  677. package/dist/ui/mouse.js.map +1 -0
  678. package/dist/ui/outbound.d.ts +20 -0
  679. package/dist/ui/outbound.d.ts.map +1 -0
  680. package/dist/ui/outbound.js +49 -0
  681. package/dist/ui/outbound.js.map +1 -0
  682. package/dist/ui/screenMode.d.ts +25 -0
  683. package/dist/ui/screenMode.d.ts.map +1 -0
  684. package/dist/ui/screenMode.js +43 -0
  685. package/dist/ui/screenMode.js.map +1 -0
  686. package/dist/ui/slashCatalog.d.ts +18 -0
  687. package/dist/ui/slashCatalog.d.ts.map +1 -0
  688. package/dist/ui/slashCatalog.js +243 -0
  689. package/dist/ui/slashCatalog.js.map +1 -0
  690. package/dist/ui/syntax.d.ts +11 -0
  691. package/dist/ui/syntax.d.ts.map +1 -0
  692. package/dist/ui/syntax.js +78 -0
  693. package/dist/ui/syntax.js.map +1 -0
  694. package/dist/ui/theme.d.ts +165 -0
  695. package/dist/ui/theme.d.ts.map +1 -0
  696. package/dist/ui/theme.js +394 -0
  697. package/dist/ui/theme.js.map +1 -0
  698. package/dist/ui/types.d.ts +203 -0
  699. package/dist/ui/types.d.ts.map +1 -0
  700. package/dist/ui/types.js +53 -0
  701. package/dist/ui/types.js.map +1 -0
  702. package/package.json +104 -0
@@ -0,0 +1,803 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useRef, useState } from "react";
3
+ import { Box, Text, useInput, useStdin, useStdout } from "ink";
4
+ import { EventLog } from "./EventLog.js";
5
+ import { CommandInput } from "./CommandInput.js";
6
+ import { Dock } from "./Dock.js";
7
+ import { StatusBar } from "./StatusBar.js";
8
+ import { HintBar } from "./HintBar.js";
9
+ import { HRule } from "./HRule.js";
10
+ import { Welcome } from "./Welcome.js";
11
+ import { shellActivityVerb } from "./Spinner.js";
12
+ import { TabChip } from "./TabChip.js";
13
+ import { setTheme, theme } from "../theme.js";
14
+ import { sendPickerClose } from "../outbound.js";
15
+ import { wantsAltScreen } from "../screenMode.js";
16
+ import { parseMouseWheel } from "../mouse.js";
17
+ import { isAskRequest, isPermissionRequest } from "../types.js";
18
+ const CURSOR_LAYOUT_SETTLE_MS = 120;
19
+ // Phase 248/295: cap the in-memory event log. Alt-screen front-trims its
20
+ // bounded viewport; transcript mode never front-trims (that corrupts the
21
+ // append-only <Static>) and instead checkpoints at idle — see
22
+ // shouldCheckpointTranscript.
23
+ const EVENTS_CAP = 5000;
24
+ const EVENTS_TRIM = 1000;
25
+ // Phase 310: transcript mode re-derives every group from the full events
26
+ // array on each 32ms flush (groupEvents is O(events) and uncached), so the
27
+ // repaint cost scales with events.length — the source of the "laggy after an
28
+ // hour" creep. In normal-screen mode settled rows already live in native
29
+ // scrollback, so we can checkpoint (drop the React log + remount <Static>)
30
+ // far below EVENTS_CAP without losing any visible history. A low softcap
31
+ // keeps N — and therefore per-flush cost — bounded across a long session.
32
+ // Alt-screen keeps the 5000 cap (its viewport front-trims and PageUp reads
33
+ // from this array, so it needs the deeper backlog).
34
+ const TRANSCRIPT_EVENTS_SOFTCAP = 1200;
35
+ // Phase 295: decide whether to checkpoint the transcript-mode event log.
36
+ // In normal-screen mode settled rows are owned by native terminal
37
+ // scrollback (Ink <Static> emitted them once), so once the React-side
38
+ // log crosses the cap at an IDLE boundary we drop it wholesale and remount
39
+ // <Static> with a fresh key: the old rows stay in scrollback (re-emitted
40
+ // nowhere → no duplicate, no scroll jump) and the array restarts empty so
41
+ // later appends stay strictly append-only. Never while streaming (the
42
+ // live tail isn't settled yet) and never in alt-screen (its viewport
43
+ // re-derives every frame and front-trims safely).
44
+ export function shouldCheckpointTranscript(opts) {
45
+ return (!opts.altScreenMode &&
46
+ !opts.streaming &&
47
+ opts.eventsLength > (opts.cap ?? EVENTS_CAP));
48
+ }
49
+ // Phase 277: cheap value-equality for a single event/status field.
50
+ // Status payloads are tiny (git info, tabsState, token counts) and the
51
+ // cli emits each object with stable key order, so a structural compare
52
+ // via JSON is sufficient to tell an unchanged 5s git refresh apart from
53
+ // a real status change.
54
+ function statusValueEqual(a, b) {
55
+ if (a === b)
56
+ return true;
57
+ if (typeof a !== "object" ||
58
+ typeof b !== "object" ||
59
+ a === null ||
60
+ b === null) {
61
+ return false;
62
+ }
63
+ return JSON.stringify(a) === JSON.stringify(b);
64
+ }
65
+ // Phase 67 layout (claude-code style):
66
+ // [ EventLog ] - scrolling event history
67
+ // [ Spinner ] - shown only while streaming
68
+ // [ Permission prompt? ] - blocks input when active
69
+ // [ ─── HRule ]
70
+ // [ CommandInput ] - ❯ prompt
71
+ // [ ─── HRule ]
72
+ // [ StatusBar ] - role/provider/model/session/cwd/tokens
73
+ // [ HintBar ] - key hints
74
+ export function App({ reader, onClose }) {
75
+ const [events, setEvents] = useState([]);
76
+ // Phase 305: repaint nonce. Toggled on every idle flush so the Ink
77
+ // output string changes even when the committed-group count doesn't
78
+ // grow (e.g. consecutive idle event/text events merge into the same
79
+ // Static group). A changed output string guarantees
80
+ // `output !== this.lastOutput` in Ink's else-if branch, which
81
+ // triggers throttledLog and redraws the dynamic chrome.
82
+ const [idleNonce, setIdleNonce] = useState(0);
83
+ const [pending, setPending] = useState([]);
84
+ const [asking, setAsking] = useState([]);
85
+ const [status, setStatus] = useState({ mode: "chat" });
86
+ // Phase 277: authoritative mirror of `status` for synchronous
87
+ // value-comparison in the event/status handler. setStatus is only
88
+ // ever called from that handler, so this ref stays in lockstep.
89
+ const statusRef = useRef(status);
90
+ // Phase 200a (F5.2): streaming label sits in state (changes on
91
+ // stream start/end only). The live char counter lives in a ref so
92
+ // each event/text chunk doesn't bump App's state — that used to
93
+ // re-render the whole tree per chunk and bypassed EventLog's memo.
94
+ // Spinner reads the ref on its own interval tick.
95
+ // Phase 200a (F5.2): streaming label sits in state (changes on
96
+ // stream start/end only). The live char counter lives in a ref so
97
+ // each event/text chunk doesn't bump App's state — that used to
98
+ // re-render the whole tree per chunk and bypassed EventLog's memo.
99
+ // Spinner reads the ref on its own interval tick.
100
+ //
101
+ // Phase 236c: this state still mirrors stream_start/end as before
102
+ // so single-tab callers and the stub renderer keep working without
103
+ // a tabsState snapshot. A follow-up useEffect (below, on
104
+ // status.activeTab change) cross-checks against tabsState — if the
105
+ // destination tab isn't actually running per the per-tab snapshot,
106
+ // we drop the stale streaming state so the spinner doesn't carry
107
+ // the previous tab's label and elapsed time across the switch.
108
+ const [streaming, setStreaming] = useState(null);
109
+ // Phase 304: mirror `streaming` into a ref so flushPending (a stable
110
+ // useCallback) can read the live value without a stale closure — it
111
+ // only nudges an idle redraw when no stream is active.
112
+ const streamingRef = useRef(false);
113
+ streamingRef.current = streaming !== null;
114
+ const streamingCharsRef = useRef(0);
115
+ // Phase 332: the Spinner's current work activity. A ref (like
116
+ // streamingCharsRef) so updating it as the turn moves through
117
+ // thinking → tool → streaming never re-renders App / disturbs the cursor.
118
+ const activityRef = useRef({ kind: "streaming" });
119
+ const [picker, setPicker] = useState(null);
120
+ // Phase 34: thinking visibility toggled by /think. Default visible.
121
+ const [thinkVisible, setThinkVisible] = useState(true);
122
+ // Phase 101: /verbose renders every tool card in full (no collapse).
123
+ const [verbose, setVerbose] = useState(false);
124
+ // Phase 308: /reasoning expands reasoning/thinking blocks inline (live
125
+ // progress) without the full /verbose tool-card blast. Off by default.
126
+ const [reasoningExpanded, setReasoningExpanded] = useState(false);
127
+ // Phase 270: EventLog uses append-only <Static> in normal-screen mode
128
+ // so settled transcript rows go to native terminal scrollback once,
129
+ // while only the live tail repaints. When the source log is replaced
130
+ // (/switch, /clear), bump this key because <Static> is intentionally
131
+ // append-only and indexes by item count.
132
+ const [eventLogResetKey, setEventLogResetKey] = useState(0);
133
+ // Phase 120: predicted next message (opt-in /predict). Shown as a
134
+ // ghost on the empty prompt; cleared when a new turn starts or the
135
+ // user submits.
136
+ const [prediction, setPrediction] = useState("");
137
+ // Phase 272: hardware cursor is safe only after the dynamic Ink
138
+ // layout has settled. In normal-screen transcript mode Ink writes
139
+ // <Static> rows outside the dynamic output, while useCursor
140
+ // positions are relative to that dynamic output. A child-measured
141
+ // cursor origin can therefore be one commit stale while EventLog,
142
+ // Dock, ask/permission pickers, or status chrome changes height.
143
+ // Hide the terminal cursor during those mutation windows and show
144
+ // it again only after one settled frame, matching full-screen TUIs'
145
+ // "draw frame, then place cursor" invariant.
146
+ const [cursorStable, setCursorStable] = useState(true);
147
+ const cursorSettleTimerRef = useRef(null);
148
+ const markCursorLayoutUnstable = useCallback(() => {
149
+ setCursorStable(false);
150
+ if (cursorSettleTimerRef.current) {
151
+ clearTimeout(cursorSettleTimerRef.current);
152
+ }
153
+ cursorSettleTimerRef.current = setTimeout(() => {
154
+ cursorSettleTimerRef.current = null;
155
+ setCursorStable(true);
156
+ }, CURSOR_LAYOUT_SETTLE_MS);
157
+ }, []);
158
+ useEffect(() => () => {
159
+ if (cursorSettleTimerRef.current) {
160
+ clearTimeout(cursorSettleTimerRef.current);
161
+ cursorSettleTimerRef.current = null;
162
+ }
163
+ }, []);
164
+ // Phase 186: latest active tab name in a ref so the reader handler
165
+ // (closure-captured at mount) can compare incoming predictions
166
+ // against the current tab without restating effect deps.
167
+ const activeTabRef = useRef(undefined);
168
+ useEffect(() => {
169
+ markCursorLayoutUnstable();
170
+ activeTabRef.current = status.activeTab;
171
+ // Switching tabs invalidates any in-flight prediction — the new
172
+ // tab will produce its own at its next turn end. Without this, the
173
+ // ghost from the tab we just left would linger on the new prompt.
174
+ setPrediction("");
175
+ // Phase 236c (audit): the streamed-char counter is a global ref.
176
+ // Pre-236c it only reset on `event/stream_start`; if the user
177
+ // switched tabs mid-stream, the counter kept the old tab's value
178
+ // and the new tab's chars piled on top — Spinner showed an
179
+ // inflated number that didn't match either tab. Reset on switch
180
+ // so each tab's spinner starts fresh.
181
+ streamingCharsRef.current = 0;
182
+ // Phase 236c (audit): TodoIndicator's source-of-truth is the most
183
+ // recent TodoWrite. event/tool_use_start from a background tab is
184
+ // already filtered out by pushNotif, but the previous tab's todos
185
+ // lingered after switching. Clear so the destination tab starts
186
+ // empty and re-populates when its next TodoWrite fires.
187
+ setTodos([]);
188
+ // Phase 250 (3rd-round audit): `streaming` (legacy) holds the
189
+ // last stream_start's label. When the user /switches to a tab
190
+ // whose stream_start they never saw (it fired while another tab
191
+ // was active and got filtered), the destination tab's spinner
192
+ // pulled the stale label from this ref. Drop it on every switch
193
+ // so Spinner falls back to its theme default until the next
194
+ // stream_start arrives for the now-active tab. Visibility +
195
+ // startedAt continue to come from tabsState (Phase 236c).
196
+ setStreaming(null);
197
+ // Phase 251 (3rd-round audit): session picker was App-level
198
+ // state (not per-tab). An open picker survived /switch and
199
+ // would render on the wrong tab — selecting a session there
200
+ // would rebuild THIS tab's adapter, not the originally-asking
201
+ // tab. Dismiss on switch + notify cli to clear its pending
202
+ // picker side-state.
203
+ setPicker((cur) => {
204
+ if (cur)
205
+ sendPickerClose();
206
+ return null;
207
+ });
208
+ }, [status.activeTab, markCursorLayoutUnstable]);
209
+ // Phase 81: active theme. The theme module owns the actual color
210
+ // state (components read theme.x.y at render); this state exists
211
+ // only to force the re-render after setTheme mutates the colors.
212
+ const [themeName, setThemeName] = useState("dark");
213
+ // Phase 98: latest TodoWrite tool input. The in-progress task is
214
+ // rendered above the prompt so the user can see what the agent is
215
+ // working on at a glance.
216
+ const [todos, setTodos] = useState([]);
217
+ const handleSetTheme = useCallback((next) => {
218
+ markCursorLayoutUnstable();
219
+ setTheme(next);
220
+ setThemeName(next);
221
+ }, [markCursorLayoutUnstable]);
222
+ const { isRawModeSupported } = useStdin();
223
+ const { stdout } = useStdout();
224
+ const rawModeSupported = Boolean(isRawModeSupported);
225
+ // Phase 236b: PageUp/PageDown slide a viewport over EventLog's
226
+ // grouped event list. `scrollOffset = 0` keeps the latest groups
227
+ // anchored at the bottom (default sticky-bottom). PageUp grows the
228
+ // offset → older groups come into view from the bottom of the
229
+ // window. Reset to 0 on tab switch (log_replace, below) so each tab
230
+ // starts at its newest event.
231
+ const [scrollOffset, setScrollOffset] = useState(0);
232
+ const SCROLL_PAGE = 10;
233
+ const SCROLL_WHEEL = 3;
234
+ useInput((input, key) => {
235
+ const mouseWheel = parseMouseWheel(input);
236
+ if (mouseWheel) {
237
+ markCursorLayoutUnstable();
238
+ setScrollOffset((offset) => mouseWheel.direction === "up"
239
+ ? offset + SCROLL_WHEEL
240
+ : Math.max(0, offset - SCROLL_WHEEL));
241
+ return;
242
+ }
243
+ if (key.pageUp) {
244
+ markCursorLayoutUnstable();
245
+ setScrollOffset((o) => o + SCROLL_PAGE);
246
+ return;
247
+ }
248
+ if (key.pageDown) {
249
+ markCursorLayoutUnstable();
250
+ setScrollOffset((o) => Math.max(0, o - SCROLL_PAGE));
251
+ return;
252
+ }
253
+ }, { isActive: rawModeSupported });
254
+ // Phase 148: batch streamed event appends. A turn emits many tiny
255
+ // event/text chunks; appending each one immediately re-rendered (and
256
+ // re-grouped) the whole log per chunk, and Ink repainted the live
257
+ // region in place — read as flicker. We coalesce appends and flush at
258
+ // ~30fps, so the heavy EventLog re-renders at most ~30×/s regardless
259
+ // of chunk rate.
260
+ const pendingRef = useRef([]);
261
+ const flushTimerRef = useRef(null);
262
+ // Phase 248 (2nd-round audit): mirror the cli-side EVENTS_CAP from
263
+ // Phase 240. The cli caps t.events for memory, but App.events grew
264
+ // unbounded between /switches because each batch flush only
265
+ // appends. A single-tab session that never switches would balloon
266
+ // App.events indefinitely and eat heap with every streamed chunk.
267
+ // Trim from the front when we cross the cap; matches cli-side
268
+ // behavior so /switch round-trips don't appear to "shrink" the
269
+ // displayed history compared to live state.
270
+ const flushPending = useCallback(() => {
271
+ if (flushTimerRef.current) {
272
+ clearTimeout(flushTimerRef.current);
273
+ flushTimerRef.current = null;
274
+ }
275
+ if (pendingRef.current.length === 0)
276
+ return;
277
+ const batch = pendingRef.current;
278
+ pendingRef.current = [];
279
+ setEvents((prev) => {
280
+ const next = [...prev, ...batch];
281
+ // Phase 295: only the alt-screen bounded viewport front-trims here.
282
+ // Transcript mode must NOT — front-trimming the array <Static> reads
283
+ // breaks its append-only watermark, so Ink re-emits the tail and the
284
+ // terminal jumps (worse the longer the session). Transcript memory is
285
+ // bounded by the idle checkpoint effect instead.
286
+ if (wantsAltScreen() && next.length > EVENTS_CAP) {
287
+ next.splice(0, EVENTS_TRIM);
288
+ }
289
+ return next;
290
+ });
291
+ // Phase 304: when IDLE (no active stream), nudge a dynamic-region
292
+ // redraw. A lone idle append renders only the <Static> rows — Ink's
293
+ // static path clears the dynamic region (input/status) and skips
294
+ // redrawing it because the dynamic output string is unchanged, so the
295
+ // new text shows but the chrome blanks until the next state change
296
+ // (which is why /preset output only appeared after the user typed).
297
+ // markCursorLayoutUnstable flips a flag that changes the dynamic
298
+ // output → forces the redraw. Skipped while streaming: the spinner's
299
+ // heartbeat already repaints, and flipping the cursor flag mid-stream
300
+ // reintroduces the IME-compose flicker appendEvent deliberately avoids.
301
+ if (!streamingRef.current) {
302
+ // Phase 305: increment the repaint nonce so the Ink output string
303
+ // changes unconditionally, ensuring throttledLog rewrites the
304
+ // dynamic chrome even when the committed-group count is unchanged
305
+ // (consecutive idle event/text events merge into the same group).
306
+ setIdleNonce((n) => n + 1);
307
+ // Keep the cursor settle: suppresses then restores the hardware
308
+ // cursor so useCursor's position is re-measured after the static
309
+ // write rather than holding a stale Yoga origin.
310
+ markCursorLayoutUnstable();
311
+ }
312
+ }, [markCursorLayoutUnstable]);
313
+ const appendEvent = useCallback((msg) => {
314
+ // Transcript-only appends must not continually invalidate the
315
+ // bottom cursor while the agent streams. In alt-screen mode the
316
+ // EventLog is a bounded viewport above the anchored composer, so
317
+ // text growth does not move the input row. Layout-affecting
318
+ // chrome transitions (stream start/end, status, pickers, todos,
319
+ // tab switches) call markCursorLayoutUnstable at their source.
320
+ pendingRef.current.push(msg);
321
+ if (!flushTimerRef.current) {
322
+ flushTimerRef.current = setTimeout(() => {
323
+ flushTimerRef.current = null;
324
+ flushPending();
325
+ }, 32);
326
+ }
327
+ }, [flushPending]);
328
+ // Flush any batched appends on unmount so nothing is lost.
329
+ useEffect(() => () => flushPending(), [flushPending]);
330
+ useEffect(() => {
331
+ reader.onMessage((msg) => {
332
+ if (isAskRequest(msg)) {
333
+ markCursorLayoutUnstable();
334
+ setAsking((prev) => [...prev, msg]);
335
+ return;
336
+ }
337
+ if (isPermissionRequest(msg)) {
338
+ markCursorLayoutUnstable();
339
+ setPending((prev) => [...prev, msg]);
340
+ return;
341
+ }
342
+ // Status updates merge in; never go into the log.
343
+ if (msg.method === "event/status") {
344
+ // Phase 277: status pushes must not gratuitously disturb the
345
+ // hardware cursor, or macOS IME drops the Hangul compose to the
346
+ // bottom info bar whenever one lands mid-keystroke.
347
+ //
348
+ // Two guards:
349
+ // 1. Skip entirely when the delta is value-identical (e.g. the
350
+ // 5s git refresh on an unchanged tree) — avoids a needless
351
+ // re-render + cursor settle while fully idle.
352
+ // 2. Only call markCursorLayoutUnstable() when a field that
353
+ // actually changes chrome HEIGHT changed. `plan`/`ask`
354
+ // toggle the TabChip row above the input, so they move it;
355
+ // everything else (git, tokensIn/Out, tabsState counts,
356
+ // model, ctx, sessionId…) renders into fixed-height chrome
357
+ // and leaves the input row put. During a stream the cli
358
+ // pushes token/tabsState updates constantly — marking on
359
+ // those hid the cursor over and over, which is exactly what
360
+ // bounced the IME compose to the info bar. Spinner/team
361
+ // panel height transitions are still settled by their own
362
+ // handlers (stream_start/stream_end, todos, pickers).
363
+ const params = msg.params;
364
+ const cur = statusRef.current;
365
+ let changed = false;
366
+ let layoutChanged = false;
367
+ for (const k of Object.keys(params)) {
368
+ if (statusValueEqual(cur[k], params[k]))
369
+ continue;
370
+ changed = true;
371
+ if (k === "plan" || k === "ask")
372
+ layoutChanged = true;
373
+ }
374
+ if (!changed)
375
+ return;
376
+ const next = { ...statusRef.current, ...msg.params };
377
+ statusRef.current = next;
378
+ if (layoutChanged)
379
+ markCursorLayoutUnstable();
380
+ setStatus(next);
381
+ // Phase 332: while a team pipeline runs, the spinner shows the team
382
+ // phase (the per-role TeamStatusPanel carries the detail). Cleared
383
+ // when teamPhase empties.
384
+ const tp = typeof next.teamPhase === "string" ? next.teamPhase : "";
385
+ if (tp)
386
+ activityRef.current = { kind: "team", detail: tp };
387
+ else if (activityRef.current.kind === "team")
388
+ activityRef.current = { kind: "streaming" };
389
+ return;
390
+ }
391
+ if (msg.method === "event/stream_start") {
392
+ markCursorLayoutUnstable();
393
+ streamingCharsRef.current = 0;
394
+ // Phase 332: seed the activity from the start label so the spinner
395
+ // shows the work type immediately (then tool/thinking events refine).
396
+ const lbl = msg.params.label;
397
+ activityRef.current =
398
+ lbl === "compacting"
399
+ ? { kind: "compacting" }
400
+ : lbl === "handing off"
401
+ ? { kind: "handoff" }
402
+ : { kind: "streaming" };
403
+ setStreaming({ label: msg.params.label });
404
+ // Phase 120: a new turn invalidates any pending prediction.
405
+ setPrediction("");
406
+ return;
407
+ }
408
+ if (msg.method === "event/predict") {
409
+ // Phase 120 + 186: transient — never recorded into the log.
410
+ // Drop predictions tagged with a tab that isn't the active one
411
+ // so a background tab's ghost can't leak into another tab's
412
+ // input prompt.
413
+ const owning = msg.params.tabName;
414
+ const active = activeTabRef.current;
415
+ if (owning && active && owning !== active)
416
+ return;
417
+ setPrediction(msg.params.text);
418
+ return;
419
+ }
420
+ if (msg.method === "event/stream_end" || msg.method === "event/end") {
421
+ markCursorLayoutUnstable();
422
+ setStreaming(null);
423
+ if (msg.method === "event/end") {
424
+ appendEvent(msg);
425
+ }
426
+ // Turn boundary — show the final state immediately, no lag.
427
+ flushPending();
428
+ return;
429
+ }
430
+ if (msg.method === "event/text") {
431
+ // Phase 94 / Phase 200a: tally streamed text for the Spinner's
432
+ // progress readout. Lives in a ref — the Spinner reads it on
433
+ // its own 80ms interval tick, so the per-chunk append doesn't
434
+ // need to bump App state.
435
+ const text = typeof msg.params?.text === "string" ? msg.params.text : "";
436
+ if (text)
437
+ streamingCharsRef.current += text.length;
438
+ // Phase 332: text arriving = the model is producing its reply.
439
+ // Don't clobber a non-turn activity (compaction streams text too).
440
+ // Phase 336: do NOT flip a running "tool" back to streaming on text
441
+ // — a long build keeps its "building…" label until tool_use_end
442
+ // resets it. (Pre-336 a stray text chunk mid-tool reset the label to
443
+ // the bare model name, so a 7-min docker build read as "codex-cli
444
+ // gpt-5.5…" instead of "building…".) thinking→streaming still flips.
445
+ if (text && activityRef.current.kind === "thinking") {
446
+ activityRef.current = { kind: "streaming" };
447
+ }
448
+ }
449
+ if (msg.method === "event/stream_progress") {
450
+ // Phase 318: compaction streams its summary in-process, so its
451
+ // output never hits event/text. Mirror the cumulative char count
452
+ // here so the "compacting…" Spinner shows real "↓ Ntok" motion.
453
+ // Set (not add) — the count is already cumulative. The Spinner
454
+ // reads the ref on its own tick, so no App re-render needed.
455
+ const chars = typeof msg.params?.chars === "number" ? msg.params.chars : 0;
456
+ streamingCharsRef.current = chars;
457
+ return;
458
+ }
459
+ // Phase 332: reflect the running tool in the spinner — esp. a long
460
+ // foreground build, which otherwise looks like a hang. TodoWrite is a
461
+ // meta tool (it has its own indicator) so it doesn't change activity.
462
+ if (msg.method === "event/tool_use_start") {
463
+ const tname = typeof msg.params?.name === "string" ? msg.params.name : "";
464
+ if (tname && tname !== "TodoWrite") {
465
+ // Phase 336: extract the command for ANY shell tool that carries
466
+ // one — not just claude's "Bash". codex's "shell"/run_shell and
467
+ // gemini's shell all put it in input.command, so before this they
468
+ // showed a bare "shell…" with no hint what was running.
469
+ const tin = msg.params?.input;
470
+ const cmd = typeof tin?.command === "string"
471
+ ? tin.command.replace(/\s+/g, " ").trim()
472
+ : "";
473
+ // Phase 336: a recognizable build/test/install/deploy reads as a
474
+ // verb ("building…") rather than a raw command — clearer while
475
+ // omg just waits on a long external build. Otherwise show the cmd.
476
+ const verb = cmd ? shellActivityVerb(cmd) : null;
477
+ const detail = verb
478
+ ? verb
479
+ : cmd
480
+ ? `${tname}: ${cmd.length > 48 ? cmd.slice(0, 47) + "…" : cmd}`
481
+ : tname;
482
+ activityRef.current = { kind: "tool", detail };
483
+ }
484
+ }
485
+ if (msg.method === "event/tool_use_end") {
486
+ // Tool finished → back to the model's reply (until the next signal).
487
+ if (activityRef.current.kind === "tool") {
488
+ activityRef.current = { kind: "streaming" };
489
+ }
490
+ }
491
+ if (msg.method === "event/thinking" &&
492
+ activityRef.current.kind !== "tool") {
493
+ activityRef.current = { kind: "thinking" };
494
+ }
495
+ // Phase 98: capture TodoWrite calls so the in-progress task
496
+ // can render under the spinner. The host CLI's tool name is
497
+ // "TodoWrite"; input shape is { todos: [{content, status, activeForm}] }.
498
+ if (msg.method === "event/tool_use_start" &&
499
+ msg.params?.name === "TodoWrite") {
500
+ const raw = msg.params.input?.todos;
501
+ if (Array.isArray(raw)) {
502
+ const parsed = [];
503
+ for (const t of raw) {
504
+ if (typeof t !== "object" || t === null)
505
+ continue;
506
+ const obj = t;
507
+ const content = typeof obj.content === "string" ? obj.content : "";
508
+ const status = obj.status;
509
+ const activeForm = typeof obj.activeForm === "string" ? obj.activeForm : undefined;
510
+ if (content &&
511
+ (status === "pending" ||
512
+ status === "in_progress" ||
513
+ status === "completed")) {
514
+ parsed.push({ content, status, activeForm });
515
+ }
516
+ }
517
+ markCursorLayoutUnstable();
518
+ setTodos(parsed);
519
+ }
520
+ }
521
+ if (msg.method === "event/session_picker") {
522
+ markCursorLayoutUnstable();
523
+ setPicker({
524
+ provider: msg.params.provider,
525
+ sessions: msg.params.sessions,
526
+ });
527
+ return;
528
+ }
529
+ if (msg.method === "event/log_replace") {
530
+ // Phase 47: a tab switch wants to swap the whole log. Replace
531
+ // wholesale in one render; Static commits past entries
532
+ // anyway, so this looks like one repaint.
533
+ // Phase 148: drop any batched appends queued for the tab we're
534
+ // leaving — the replacement is the new tab's full history.
535
+ // Phase 247 (2nd-round audit): clone the inbound array. The
536
+ // cli side passes `t.events` by reference. If we stored that
537
+ // reference in React state, the next pushNotif's
538
+ // `target.events.push(n)` would mutate the array React still
539
+ // believes is its state — and the very next flushPending's
540
+ // `setEvents(prev => [...prev, ...batch])` would see `prev`
541
+ // already containing `n` (from the mutation), then re-append
542
+ // `n` (from `batch`). Result: every event arriving within the
543
+ // first 32ms batch window after a /switch rendered TWICE in
544
+ // the chat. Cloning here decouples App.events from t.events
545
+ // so neither side mutates the other's view.
546
+ if (flushTimerRef.current) {
547
+ clearTimeout(flushTimerRef.current);
548
+ flushTimerRef.current = null;
549
+ }
550
+ markCursorLayoutUnstable();
551
+ pendingRef.current = [];
552
+ setEvents([...msg.params.events]);
553
+ setEventLogResetKey((k) => k + 1);
554
+ // Phase 236b: switching tabs resets the scroll viewport. The
555
+ // user's "where I was reading" is per-tab and Phase 236e will
556
+ // restore it; for now snap to the destination tab's latest.
557
+ setScrollOffset(0);
558
+ return;
559
+ }
560
+ appendEvent(msg);
561
+ });
562
+ if (onClose)
563
+ reader.onClose(onClose);
564
+ }, [reader, onClose, appendEvent, flushPending, markCursorLayoutUnstable]);
565
+ const addLocalText = useCallback((text) => {
566
+ markCursorLayoutUnstable();
567
+ flushPending(); // keep ordering with any batched stream output
568
+ setEvents((prev) => [
569
+ ...prev,
570
+ {
571
+ jsonrpc: "2.0",
572
+ method: "event/text",
573
+ params: { text },
574
+ },
575
+ ]);
576
+ }, [flushPending, markCursorLayoutUnstable]);
577
+ // Phase 115 → 225 (hotfix, root cause): the actual user_echo event
578
+ // now ships from cli.ts via pushNotif so tab.events is the source
579
+ // of truth — App still receives it through the normal ink stream
580
+ // and lands it via appendEvent. Pre-225 this callback inserted the
581
+ // echo into App's local events directly; tab.events never got it,
582
+ // and /switch's log_replace wiped the echo on return. We keep the
583
+ // hook so prediction is cleared on submit (transient UI concern
584
+ // that doesn't belong in cli.ts).
585
+ const addUserMessage = useCallback((_text) => {
586
+ markCursorLayoutUnstable();
587
+ flushPending();
588
+ setPrediction(""); // Phase 120: submitting consumes the prediction.
589
+ }, [flushPending, markCursorLayoutUnstable]);
590
+ const dequeueRequest = useCallback(() => {
591
+ markCursorLayoutUnstable();
592
+ setPending((prev) => prev.slice(1));
593
+ }, [markCursorLayoutUnstable]);
594
+ const dequeueAsk = useCallback(() => {
595
+ markCursorLayoutUnstable();
596
+ setAsking((prev) => prev.slice(1));
597
+ }, [markCursorLayoutUnstable]);
598
+ const clearEvents = useCallback(() => {
599
+ markCursorLayoutUnstable();
600
+ if (flushTimerRef.current) {
601
+ clearTimeout(flushTimerRef.current);
602
+ flushTimerRef.current = null;
603
+ }
604
+ pendingRef.current = [];
605
+ setEvents([]);
606
+ setTodos([]);
607
+ setEventLogResetKey((k) => k + 1);
608
+ }, [markCursorLayoutUnstable]);
609
+ const toggleThink = useCallback((force) => {
610
+ markCursorLayoutUnstable();
611
+ setThinkVisible((prev) => {
612
+ const next = force === undefined ? !prev : force;
613
+ // Echo state into the log so the change is visible in scrollback.
614
+ setEvents((es) => [
615
+ ...es,
616
+ {
617
+ jsonrpc: "2.0",
618
+ method: "event/text",
619
+ params: {
620
+ text: next
621
+ ? "[think] ON — reasoning blocks will render.\n"
622
+ : "[think] off — reasoning blocks hidden.\n",
623
+ },
624
+ },
625
+ ]);
626
+ return next;
627
+ });
628
+ }, [markCursorLayoutUnstable]);
629
+ const head = pending[0];
630
+ const askHead = asking[0];
631
+ // Phase 236c: tabsState is the per-tab source-of-truth for running
632
+ // state. Pre-236c App.streaming was a free-floating mirror of the
633
+ // last stream_start/end on this stdin; on a tab switch it kept the
634
+ // prior tab's label + (via a useRef) startedAt and the spinner
635
+ // showed "1m 13s" on a tab that just opened. We splice tabsState
636
+ // back in by:
637
+ // - reading the active tab's runningSince and forwarding it to
638
+ // Spinner so the elapsed counter resets per tab;
639
+ // - using `streamingFromTab` (below) when the local mirror is
640
+ // out of sync — if tabsState says the active tab isn't running,
641
+ // hide the spinner regardless of stale App.streaming. This
642
+ // handles the case where the destination tab is idle but the
643
+ // source tab is still emitting events App can't see.
644
+ const activeTabState = status.tabsState?.find((t) => t.name === status.activeTab);
645
+ const tabRunning = activeTabState?.running ?? null;
646
+ // If tabsState is unavailable (no status push yet, stub renderer,
647
+ // standalone unit tests) fall back to App.streaming — back-compat
648
+ // with the pre-236c mental model.
649
+ const streamingVisible = tabRunning === null ? streaming !== null : tabRunning;
650
+ const streamingForDock = streamingVisible
651
+ ? {
652
+ label: streaming?.label,
653
+ startedAt: activeTabState?.runningSince,
654
+ }
655
+ : null;
656
+ const altScreenMode = wantsAltScreen() && Boolean(stdout?.isTTY);
657
+ // Phase 295: transcript-mode memory checkpoint. Runs post-commit, so at
658
+ // an idle boundary the final group of the just-ended turn is already
659
+ // emitted to native scrollback (stream_end flushPending()s synchronously
660
+ // before this). Dropping the React log + remounting <Static> with a
661
+ // fresh key re-emits nothing (no dupe, no jump) and resets memory.
662
+ useEffect(() => {
663
+ if (!shouldCheckpointTranscript({
664
+ altScreenMode,
665
+ streaming: streaming !== null,
666
+ eventsLength: events.length,
667
+ cap: TRANSCRIPT_EVENTS_SOFTCAP,
668
+ })) {
669
+ return;
670
+ }
671
+ setEvents([]);
672
+ setEventLogResetKey((k) => k + 1);
673
+ }, [altScreenMode, streaming, events.length]);
674
+ const rootHeight = altScreenMode && typeof stdout?.rows === "number" && stdout.rows > 0
675
+ ? stdout.rows
676
+ : undefined;
677
+ // Cursor invariant: only place the terminal cursor after the final
678
+ // frame layout is stable. Codex/ratatui draws the frame and sets the
679
+ // cursor from the same resolved layout; Ink's useCursor needs the
680
+ // previous render's Yoga origin, so Dock/status/input-height
681
+ // transitions can be one frame stale. Hide during those short
682
+ // mutation windows in every screen mode.
683
+ //
684
+ // Phase 277: do NOT hard-hide the input cursor for the whole stream
685
+ // in normal-screen mode. The live tail grows while the agent works,
686
+ // nudging the input row down each frame — so the older code hid the
687
+ // cursor outright to avoid it chasing a stale row. But a user who
688
+ // types DURING a stream (queuing a message) needs the hardware
689
+ // cursor parked at the input, or macOS IME draws the Hangul compose
690
+ // preview at the cursor's resting position — below the HintBar.
691
+ // `suppressEmptyInputCursor` already hides the cursor while the input
692
+ // is empty (nothing to compose), so streaming-with-empty-input stays
693
+ // jitter-free; once the buffer is non-empty the cursor follows the
694
+ // input (origin is re-measured per render) so IME lands in the box.
695
+ const suppressInputHardwareCursor = !cursorStable;
696
+ const suppressEmptyInputCursor = !altScreenMode && streamingVisible;
697
+ const transcript = (_jsxs(_Fragment, { children: [events.length === 0 && (_jsx(Welcome, { provider: status.provider, model: status.model, cwd: status.cwd })), _jsx(EventLog, { events: events, thinkVisible: thinkVisible, reasoningExpanded: reasoningExpanded, streaming: streamingVisible, verbose: verbose, scrollOffset: scrollOffset, transcriptMode: !altScreenMode, transcriptResetKey: eventLogResetKey,
698
+ // Codex-style UX keeps the visible cursor owned by the bottom
699
+ // composer. A moving assistant-tail block in the transcript
700
+ // reads like the chat cursor jumping while the agent works.
701
+ showLiveCursor: false })] }));
702
+ return (_jsxs(Box, { flexDirection: "column", height: rootHeight, overflowY: altScreenMode ? "hidden" : "visible", children: [altScreenMode ? (_jsx(Box, { flexDirection: "column", flexGrow: 1, flexShrink: 1, justifyContent: "flex-end", overflowY: "hidden", children: transcript })) : (transcript), _jsx(Dock, { status: status, streaming: streamingForDock, streamedCharsRef: streamingCharsRef, activityRef: activityRef, todos: todos, askHead: askHead, permHead: head, sessionPicker: picker, isRawModeSupported: rawModeSupported, stableActivityHeight: altScreenMode, onAskResolved: dequeueAsk, onPermResolved: dequeueRequest, onSessionPickerClose: () => {
703
+ markCursorLayoutUnstable();
704
+ setPicker(null);
705
+ } }), _jsx(HRule, { ...upperRuleLabel(status) }), altScreenMode ? (_jsx(Box, { height: 1, overflowY: "hidden", children: _jsx(TabChip, { planMode: status.plan, askMode: status.ask, thinkVisible: thinkVisible }) })) : (_jsx(TabChip, { planMode: status.plan, askMode: status.ask, thinkVisible: thinkVisible })), rawModeSupported && !head && !askHead && !picker && (_jsx(CommandInput, { onLocalLine: addLocalText, onClearEvents: clearEvents, onToggleThink: toggleThink, cwd: status.cwd, onSetTheme: handleSetTheme, onUserMessage: addUserMessage, prediction: prediction, suppressCursorWhenEmpty: suppressEmptyInputCursor, suppressHardwareCursor: suppressInputHardwareCursor, fullscreenCursorMode: altScreenMode, onToggleVerbose: (force) => setVerbose((prev) => {
706
+ markCursorLayoutUnstable();
707
+ const next = force === undefined ? !prev : force;
708
+ addLocalText(next
709
+ ? "[verbose] ON — tool cards show full output."
710
+ : "[verbose] off — tool cards collapse again.");
711
+ return next;
712
+ }), onToggleReasoning: (force) => setReasoningExpanded((prev) => {
713
+ markCursorLayoutUnstable();
714
+ const next = force === undefined ? !prev : force;
715
+ addLocalText(next
716
+ ? "[reasoning] ON — reasoning shows expanded live (progress)."
717
+ : "[reasoning] off — reasoning collapses to a header.");
718
+ return next;
719
+ }) }, `input-${themeName}`)), _jsx(HRule, {}), altScreenMode ? (_jsx(Box, { height: 2, overflowY: "hidden", children: _jsx(StatusBar, { status: { ...status, thinkVisible } }) })) : (_jsx(StatusBar, { status: { ...status, thinkVisible } })), _jsxs(Box, { height: 1, overflowY: "hidden", children: [_jsx(HintBar, {}), _jsx(Text, { children: idleNonce % 2 ? "​" : "" })] })] }));
720
+ }
721
+ /** Phase 199 → 230: compose the upper-HRule chip from the status
722
+ * snapshot. Phase 230 redesign — show ALL tab names as colored
723
+ * segments (active = green, running = animated spinner glyph, ready
724
+ * = `▒`, asking = `?`), plus the ctx-pressure warning when active.
725
+ * Returns segment list for HRule's multi-color renderer. */
726
+ const TAB_NAME_MAX = 10;
727
+ function truncTab(name) {
728
+ if ([...name].length <= TAB_NAME_MAX)
729
+ return name;
730
+ return name.slice(0, TAB_NAME_MAX - 1) + "…";
731
+ }
732
+ function upperRuleLabel(status) {
733
+ const segs = [];
734
+ const tabs = status.tabsState ?? [];
735
+ const chipFg = theme.prompt.chipFg;
736
+ // Phase 230: every tab gets a segment. Active tab in green
737
+ // (status.tabColor / readyColor), running tabs prefixed by an
738
+ // animated spinner glyph, ready tabs by `▒`, asking by `?`. Idle
739
+ // background tabs render in default chip color so the eye still
740
+ // sees them but they don't compete for attention.
741
+ for (let i = 0; i < tabs.length; i++) {
742
+ if (i > 0) {
743
+ segs.push({ text: " · ", color: chipFg });
744
+ }
745
+ const t = tabs[i];
746
+ const isActive = t.name === status.activeTab;
747
+ if (t.running && !isActive) {
748
+ // Animated spinner glyph; HRule's own timer cycles it. We pass
749
+ // a placeholder text — HRule overrides with the current frame.
750
+ segs.push({
751
+ text: "⠋",
752
+ color: theme.spinner.color,
753
+ spinner: true,
754
+ });
755
+ segs.push({ text: " " + truncTab(t.name), color: chipFg });
756
+ }
757
+ else if (t.asking && !isActive) {
758
+ segs.push({ text: "? ", color: theme.status.askColor, bold: true });
759
+ segs.push({ text: truncTab(t.name), color: chipFg });
760
+ }
761
+ else if (t.ready && !isActive) {
762
+ segs.push({ text: "▒ ", color: theme.status.readyColor });
763
+ segs.push({ text: truncTab(t.name), color: chipFg });
764
+ }
765
+ else if (isActive) {
766
+ // Active tab in the readyColor green so "where am I" is the
767
+ // strongest visual signal in the chip. Bold further pops it.
768
+ segs.push({
769
+ text: truncTab(t.name),
770
+ color: theme.status.readyColor,
771
+ bold: true,
772
+ });
773
+ }
774
+ else {
775
+ // Idle non-active tab — dim color so the eye treats it as
776
+ // available-but-quiet.
777
+ segs.push({ text: truncTab(t.name), color: theme.status.labelColor });
778
+ }
779
+ }
780
+ // Phase 190/222: ctx warning piggybacks on the chip when occupancy
781
+ // is high. Cap display at "100%+" so a stale or wrongly-attributed
782
+ // token count doesn't surface "ctx 147%".
783
+ if (status.tokensIn && status.contextWindow && status.contextWindow > 0) {
784
+ const ratio = status.tokensIn / status.contextWindow;
785
+ if (ratio >= 0.7) {
786
+ const pct = Math.round(ratio * 100);
787
+ const label = pct > 100 ? "⚠ ctx 100%+" : `⚠ ctx ${pct}%`;
788
+ const ctxColor = ratio >= 0.9
789
+ ? theme.status.tokenCritColor
790
+ : theme.status.tokenWarnColor;
791
+ if (segs.length > 0)
792
+ segs.push({ text: " · ", color: chipFg });
793
+ segs.push({ text: label, color: ctxColor, bold: true });
794
+ }
795
+ }
796
+ if (segs.length === 0)
797
+ return {};
798
+ return {
799
+ rightSegments: segs,
800
+ rightLabelBg: theme.prompt.chipBg,
801
+ };
802
+ }
803
+ //# sourceMappingURL=App.js.map