@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,994 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
3
+ import { Box, Text, useApp, useCursor, useInput, useStdin } from "ink";
4
+ import stringWidth from "string-width";
5
+ import { sendCancel, sendInput, sendQuit, sendSlashCommand, } from "../outbound.js";
6
+ import { theme } from "../theme.js";
7
+ import { activeMention, expandFileMentions, extractImageMentions, scanDir, } from "../fileMentions.js";
8
+ import { captureClipboardImage } from "../../core/util/clipboardImage.js";
9
+ import { FileSuggest } from "./FileSuggest.js";
10
+ import { matchSlash, renderHelp } from "../slashCatalog.js";
11
+ import { SlashPalette } from "./SlashPalette.js";
12
+ import { appendInputHistory, loadInputHistory } from "../inputHistory.js";
13
+ import { useLineEditor } from "../hooks/useLineEditor.js";
14
+ import { isMouseSequence } from "../mouse.js";
15
+ // Phase 65: the slash catalog (src/ui/slashCatalog.ts) is the single
16
+ // source of truth for available command names + their descriptions.
17
+ // Phase 135: a paste this big (lines OR chars) collapses to a chip.
18
+ const PASTE_MIN_LINES = 4;
19
+ const PASTE_MIN_CHARS = 300;
20
+ const PROMPT_COLS = 2;
21
+ const MAX_INPUT_VISIBLE_LINES = 6;
22
+ export function absoluteElementOrigin(node) {
23
+ let x = 0;
24
+ let y = 0;
25
+ let cur = node;
26
+ while (cur) {
27
+ x += cur.yogaNode?.getComputedLeft() ?? 0;
28
+ y += cur.yogaNode?.getComputedTop() ?? 0;
29
+ cur = cur.parentNode;
30
+ }
31
+ return { x, y };
32
+ }
33
+ export function inputCursorColumn(leftOfCursor) {
34
+ return PROMPT_COLS + stringWidth(leftOfCursor);
35
+ }
36
+ export function inputViewportStart(totalLines, cursorLine, maxVisibleLines = MAX_INPUT_VISIBLE_LINES) {
37
+ if (totalLines <= maxVisibleLines)
38
+ return 0;
39
+ const maxStart = Math.max(0, totalLines - maxVisibleLines);
40
+ return Math.max(0, Math.min(cursorLine - maxVisibleLines + 1, maxStart));
41
+ }
42
+ export function shouldShowInputHardwareCursor(buffer, suppressCursorWhenEmpty = false, suppressHardwareCursor = false) {
43
+ // Phase 277: compose protection. Once there is text in the buffer the
44
+ // user may be mid-IME-composition, and any hide drops the macOS
45
+ // Hangul compose preview to the bottom of the screen. So never hide
46
+ // the cursor while the buffer is non-empty — a 1-frame stale position
47
+ // during a layout settle is invisible next to a bounced compose box.
48
+ // The layout-settle hide (suppressHardwareCursor) and the
49
+ // hide-while-empty path only apply to the empty input, where there is
50
+ // nothing to compose.
51
+ if (buffer.length > 0)
52
+ return true;
53
+ if (suppressHardwareCursor)
54
+ return false;
55
+ return !suppressCursorWhenEmpty;
56
+ }
57
+ export function inputHardwareCursorPosition(origin, column, visibleLine, fullscreenCursorMode = false) {
58
+ // Ink's log-update normally renders `output + "\n"`, leaving the
59
+ // terminal cursor on the row just below the visible output. Its
60
+ // buildCursorSuffix therefore uses `visibleLineCount - y`.
61
+ //
62
+ // In fullscreen mode Ink deliberately renders `output` without the
63
+ // trailing newline, so the terminal cursor starts on the last visible
64
+ // row instead. Without this +1, every hardware cursor target appears
65
+ // one row above the measured Yoga origin in the alternate screen.
66
+ return {
67
+ x: origin.x + column,
68
+ y: origin.y + visibleLine + (fullscreenCursorMode ? 1 : 0),
69
+ };
70
+ }
71
+ // Phase 289: macOS 2-set (두벌식) Hangul keyboard. When a Korean input
72
+ // source is active, a held Ctrl still arrives with key.ctrl set, but
73
+ // `input` is the jamo the physical key produces in the Korean layout
74
+ // (Ctrl+P → "ㅔ", Ctrl+O → "ㅐ", Ctrl+N → "ㅜ") rather than the Latin
75
+ // letter. So every `input === "p"` shortcut check silently fails and
76
+ // tab-switch / search / undo die under a Korean source. Evidence
77
+ // (OMG_DEBUG_KEYS): Ctrl+P → input="ㅔ" hex=[e3 85 94] flags=[ctrl].
78
+ // Map each jamo back to its QWERTY base key so the existing ctrl-letter
79
+ // bindings work regardless of the active input source.
80
+ const HANGUL_CTRL_TO_QWERTY = {
81
+ "ㅂ": "q", "ㅈ": "w", "ㄷ": "e", "ㄱ": "r", "ㅅ": "t",
82
+ "ㅛ": "y", "ㅕ": "u", "ㅑ": "i", "ㅐ": "o", "ㅔ": "p",
83
+ "ㅁ": "a", "ㄴ": "s", "ㅇ": "d", "ㄹ": "f", "ㅎ": "g",
84
+ "ㅗ": "h", "ㅓ": "j", "ㅏ": "k", "ㅣ": "l",
85
+ "ㅋ": "z", "ㅌ": "x", "ㅊ": "c", "ㅍ": "v", "ㅠ": "b",
86
+ "ㅜ": "n", "ㅡ": "m",
87
+ };
88
+ /** Phase 289: when Ctrl is held, fold a 두벌식 Hangul jamo back to the
89
+ * Latin key that physically produced it so ctrl-letter shortcuts match.
90
+ * Only rewrites while `ctrl` is true — a bare jamo is intended text. */
91
+ export function normalizeCtrlInput(input, ctrl) {
92
+ if (!ctrl)
93
+ return input;
94
+ return HANGUL_CTRL_TO_QWERTY[input] ?? input;
95
+ }
96
+ function paletteFor(value) {
97
+ if (!value.startsWith("/"))
98
+ return [];
99
+ if (value.includes(" "))
100
+ return [];
101
+ const prefix = value.slice(1).toLowerCase();
102
+ return matchSlash(prefix);
103
+ }
104
+ // Phase 39 word boundary helpers. Word = run of alnum/_/. The
105
+ // classic readline behavior: jump over whitespace, then over the
106
+ // word, stopping at the far boundary.
107
+ function isWordChar(ch) {
108
+ return /[A-Za-z0-9_]/.test(ch);
109
+ }
110
+ function prevWordIdx(s, idx) {
111
+ let i = idx;
112
+ while (i > 0 && !isWordChar(s[i - 1]))
113
+ i--;
114
+ while (i > 0 && isWordChar(s[i - 1]))
115
+ i--;
116
+ return i;
117
+ }
118
+ function nextWordIdx(s, idx) {
119
+ let i = idx;
120
+ while (i < s.length && !isWordChar(s[i]))
121
+ i++;
122
+ while (i < s.length && isWordChar(s[i]))
123
+ i++;
124
+ return i;
125
+ }
126
+ function startOfLine(s, idx) {
127
+ const nl = s.lastIndexOf("\n", Math.max(0, idx - 1));
128
+ return nl === -1 ? 0 : nl + 1;
129
+ }
130
+ function endOfLine(s, idx) {
131
+ const nl = s.indexOf("\n", idx);
132
+ return nl === -1 ? s.length : nl;
133
+ }
134
+ const CSI_ARROW_MODIFIER_RE = /^\x1b\[1;(\d+)([CD])$/;
135
+ const MODIFIED_ARROW_DIRECTION = {
136
+ D: "left",
137
+ C: "right",
138
+ };
139
+ function arrowModifier(rawInput, direction) {
140
+ const match = CSI_ARROW_MODIFIER_RE.exec(rawInput);
141
+ if (!match)
142
+ return null;
143
+ if (MODIFIED_ARROW_DIRECTION[match[2]] !== direction)
144
+ return null;
145
+ return Number(match[1]);
146
+ }
147
+ function isWordArrowSequence(rawInput, direction) {
148
+ const modifier = arrowModifier(rawInput, direction);
149
+ // xterm modifier values: 3/4 = Alt(+Shift), 5/6 = Ctrl(+Shift),
150
+ // 7/8 = Ctrl+Alt(+Shift). All are readline-style word movement.
151
+ return modifier !== null && modifier >= 3 && modifier <= 8;
152
+ }
153
+ function isLineArrowSequence(rawInput, direction) {
154
+ const modifier = arrowModifier(rawInput, direction);
155
+ // macOS terminals commonly encode Cmd+Arrow as CSI 1;9C/D (with
156
+ // adjacent shifted/control-combined variants). Kitty exposes Cmd as
157
+ // key.super; this raw CSI fallback covers terminals that only report
158
+ // a meta-modified arrow to Ink's parser.
159
+ return (modifier !== null &&
160
+ ((modifier >= 9 && modifier <= 16) || modifier === 17 || modifier === 18));
161
+ }
162
+ // Phase 63: vertical cursor motion inside a multi-line buffer.
163
+ //
164
+ // Move up: jump to the previous line, preserving the visual column.
165
+ // Returns -1 if the cursor is already on the first line (caller falls
166
+ // back to history).
167
+ function lineUpIdx(s, idx) {
168
+ const lineStart = startOfLine(s, idx);
169
+ if (lineStart === 0)
170
+ return -1;
171
+ const col = idx - lineStart;
172
+ const prevLineEnd = lineStart - 1; // the '\n' itself
173
+ const prevLineStart = startOfLine(s, prevLineEnd);
174
+ const prevLineLen = prevLineEnd - prevLineStart;
175
+ return prevLineStart + Math.min(col, prevLineLen);
176
+ }
177
+ function lineDownIdx(s, idx) {
178
+ const lineEnd = endOfLine(s, idx);
179
+ if (lineEnd === s.length)
180
+ return -1;
181
+ const lineStart = startOfLine(s, idx);
182
+ const col = idx - lineStart;
183
+ const nextLineStart = lineEnd + 1;
184
+ const nextLineEnd = endOfLine(s, nextLineStart);
185
+ const nextLineLen = nextLineEnd - nextLineStart;
186
+ return nextLineStart + Math.min(col, nextLineLen);
187
+ }
188
+ // Phase 39: full-fledged line editor.
189
+ //
190
+ // Keys:
191
+ // printable → insert at cursor; multi-char input from a
192
+ // terminal paste lands as one chunk
193
+ // Enter → submit, unless trailing `\` or Shift/Alt+Enter
194
+ // (then insert newline)
195
+ // Backspace / Delete → delete char before / at cursor
196
+ // ← / → → move cursor by one char
197
+ // Home / End → cursor to start / end of line
198
+ // Cmd-← / Cmd-→ → cursor to start / end of line where supported
199
+ // Opt-← / Opt-→ → move cursor by one word (ESC b / ESC f bytes)
200
+ // Ctrl-A / Ctrl-E → cursor to start / end of line
201
+ // Ctrl-W → delete previous word
202
+ // Ctrl-U → delete from start of line to cursor
203
+ // Ctrl-K → delete from cursor to end of line
204
+ // ↑ / ↓ → history navigation (single-line buffer only)
205
+ // Tab → autocomplete first slash suggestion
206
+ // Ctrl-C → quit
207
+ // Esc → cancel the in-flight stream
208
+ export function CommandInput({ onLocalLine, onClearEvents, onToggleThink, cwd, onSetTheme, onToggleVerbose, onToggleReasoning, onUserMessage, prediction, suppressCursorWhenEmpty, suppressHardwareCursor, fullscreenCursorMode, }) {
209
+ // Phase 205: editor core (buffer/cursor/undo/paste) lives in a hook.
210
+ // History navigation, palette, mention popup, and search remain here
211
+ // because they're intertwined with rendering and external IO.
212
+ const editor = useLineEditor();
213
+ const { buffer, cursor } = editor;
214
+ const { exit } = useApp();
215
+ const { internal_eventEmitter: inputEmitter } = useStdin();
216
+ const rawInputRef = useRef("");
217
+ useEffect(() => {
218
+ const captureRawInput = (input) => {
219
+ rawInputRef.current = input;
220
+ };
221
+ // Capture Ink's unparsed event before `useInput` strips ESC and
222
+ // collapses several CSI modifier variants into the same key shape.
223
+ // This is what lets us distinguish Cmd+Arrow (line movement) from
224
+ // Opt/Ctrl+Arrow (word movement) across macOS terminals.
225
+ inputEmitter.on("input", captureRawInput);
226
+ return () => {
227
+ inputEmitter.removeListener("input", captureRawInput);
228
+ };
229
+ }, [inputEmitter]);
230
+ const historyRef = useRef([]);
231
+ const [historyIdx, setHistoryIdx] = useState(-1);
232
+ const draftRef = useRef("");
233
+ // Phase 114: seed the in-memory ring from persisted history once, so
234
+ // ↑/↓ recall and ghost suggestions span sessions.
235
+ const historyLoadedRef = useRef(false);
236
+ if (!historyLoadedRef.current) {
237
+ historyLoadedRef.current = true;
238
+ // Don't touch the real ~/.omg history file under the test runner.
239
+ if (!process.env.VITEST) {
240
+ try {
241
+ historyRef.current = loadInputHistory();
242
+ }
243
+ catch {
244
+ /* non-persisted fallback */
245
+ }
246
+ }
247
+ }
248
+ // Phase 125: Ctrl-R reverse history search. `null` when inactive;
249
+ // otherwise the live query + which match (0 = most recent) is shown.
250
+ const [search, setSearch] = useState(null);
251
+ const reverseMatches = (q) => {
252
+ const hist = historyRef.current;
253
+ const seen = new Set();
254
+ const res = [];
255
+ for (let i = hist.length - 1; i >= 0; i--) {
256
+ const h = hist[i];
257
+ if ((q === "" || h.includes(q)) && !seen.has(h)) {
258
+ seen.add(h);
259
+ res.push(h);
260
+ }
261
+ }
262
+ return res;
263
+ };
264
+ // Phase 135 + 126 + paste store now belong to `editor` (Phase 205).
265
+ const palette = useMemo(() => paletteFor(buffer), [buffer]);
266
+ const [paletteSel, setPaletteSel] = useState(0);
267
+ const paletteOpen = palette.length > 0;
268
+ useEffect(() => {
269
+ if (paletteSel >= palette.length)
270
+ setPaletteSel(0);
271
+ }, [palette.length, paletteSel]);
272
+ const acceptPalette = () => {
273
+ if (!paletteOpen)
274
+ return false;
275
+ const choice = palette[paletteSel];
276
+ if (!choice)
277
+ return false;
278
+ const filled = "/" + choice.name + (choice.args ? " " : "");
279
+ setBufAndCursor(filled, filled.length);
280
+ return true;
281
+ };
282
+ const isMultiLine = buffer.includes("\n");
283
+ // Phase 186: ghost is now ONLY the model-predicted next message on
284
+ // an empty prompt (opt-in /predict). The fish-style history-prefix
285
+ // autosuggestion that used to fill mid-buffer was confusing — it
286
+ // ghosted the user's own past lines, which they rarely wanted
287
+ // re-suggested. ↑/↓ history recall is unchanged.
288
+ const ghostMatch = useMemo(() => {
289
+ if (buffer)
290
+ return "";
291
+ if (isMultiLine || historyIdx !== -1 || cursor !== 0)
292
+ return "";
293
+ return prediction ?? "";
294
+ }, [buffer, cursor, isMultiLine, historyIdx, prediction]);
295
+ // Phase 64: @file autocomplete. When the cursor sits inside an
296
+ // `@<token>`, scan the active tab's cwd and show a popup. Selection
297
+ // index is owned here; arrow keys cycle, Tab/Enter accept, Esc
298
+ // closes.
299
+ const mention = useMemo(() => activeMention(buffer, cursor), [buffer, cursor]);
300
+ const fileSuggestions = useMemo(() => {
301
+ if (!mention)
302
+ return [];
303
+ return scanDir(cwd ?? process.cwd(), mention.query);
304
+ }, [mention, cwd]);
305
+ const [mentionSel, setMentionSel] = useState(0);
306
+ // Set to the mention's `start` when the user dismisses the popup
307
+ // with Esc, so the popup stays hidden until they move away from
308
+ // that mention. Comparing by `start` index means a fresh `@` later
309
+ // in the buffer still opens its own popup.
310
+ const [dismissedStart, setDismissedStart] = useState(null);
311
+ const popupOpen = fileSuggestions.length > 0 &&
312
+ (mention?.start ?? -1) !== (dismissedStart ?? -2);
313
+ // Clamp selection when the candidate set shrinks under us.
314
+ useEffect(() => {
315
+ if (mentionSel >= fileSuggestions.length)
316
+ setMentionSel(0);
317
+ }, [fileSuggestions.length, mentionSel]);
318
+ // Phase 113/116: the ghost only shows when no slash palette / @file
319
+ // popup is claiming the completion. Gating here (rather than on the
320
+ // raw prefix) means `/team <prior prompt>` and `!cmd` still get a
321
+ // history ghost once the palette/popup has closed.
322
+ const ghostSuffix = paletteOpen || popupOpen || search ? "" : ghostMatch;
323
+ const acceptGhost = () => {
324
+ if (!ghostSuffix)
325
+ return false;
326
+ const next = buffer + ghostSuffix;
327
+ setBufAndCursor(next, next.length);
328
+ return true;
329
+ };
330
+ const acceptMention = () => {
331
+ if (!mention || !popupOpen)
332
+ return false;
333
+ const choice = fileSuggestions[mentionSel];
334
+ if (!choice)
335
+ return false;
336
+ // Replace the mention's body (everything after `@`) with the
337
+ // selected path. For directories we leave the trailing `/` so
338
+ // the user can keep typing into them; for files we add a single
339
+ // trailing space so the mention is "done".
340
+ const before = buffer.slice(0, mention.start + 1); // include `@`
341
+ const after = buffer.slice(mention.end);
342
+ const inserted = choice.display + (choice.isDir ? "" : " ");
343
+ const next = before + inserted + after;
344
+ const nextCursor = before.length + inserted.length;
345
+ setBufAndCursor(next, nextCursor);
346
+ setMentionSel(0);
347
+ return true;
348
+ };
349
+ const setBufAndCursor = editor.setBuffer;
350
+ const setCursor = editor.setCursor;
351
+ // Phase 205: `insertAt` keeps the history-draft tie-in (any keystroke
352
+ // while scrolled into history snaps back to a fresh draft). The
353
+ // editor returns the new buffer so we don't have to wait a render
354
+ // for the state to settle.
355
+ const insertAt = (text) => {
356
+ const next = editor.insert(text);
357
+ if (historyIdx !== -1) {
358
+ setHistoryIdx(-1);
359
+ draftRef.current = next;
360
+ }
361
+ };
362
+ const deleteRange = editor.deleteRange;
363
+ const pushHistory = (entry) => {
364
+ const hist = historyRef.current;
365
+ if (hist.length > 0 && hist[hist.length - 1] === entry)
366
+ return;
367
+ hist.push(entry);
368
+ if (hist.length > 500)
369
+ hist.shift();
370
+ // Phase 114: persist so the entry survives into the next session.
371
+ // Skipped under the test runner so suites don't write to the real
372
+ // ~/.omg history file.
373
+ if (!process.env.VITEST)
374
+ appendInputHistory(entry);
375
+ };
376
+ const handleSlash = (trimmed) => {
377
+ if (!trimmed.startsWith("/"))
378
+ return false;
379
+ const [head, ...rest] = trimmed.slice(1).split(" ");
380
+ const name = head ?? "";
381
+ const args = rest.join(" ");
382
+ if (name === "quit" || name === "q") {
383
+ sendQuit();
384
+ exit();
385
+ return true;
386
+ }
387
+ if (name === "help" || name === "?") {
388
+ onLocalLine?.(renderHelp());
389
+ return true;
390
+ }
391
+ if (name === "clear") {
392
+ onClearEvents?.();
393
+ sendSlashCommand(name, args);
394
+ return true;
395
+ }
396
+ if (name === "reset") {
397
+ onClearEvents?.();
398
+ sendSlashCommand(name, args);
399
+ return true;
400
+ }
401
+ if (name === "theme") {
402
+ // Phase 81: UI-only toggle. cli.ts never sees this slash.
403
+ const arg = args.trim().toLowerCase();
404
+ const next = arg === "light"
405
+ ? "light"
406
+ : arg === "dark"
407
+ ? "dark"
408
+ : // No arg = toggle. Default state is dark; pressing once
409
+ // flips to light.
410
+ "light";
411
+ onSetTheme?.(next);
412
+ onLocalLine?.(`[theme] ${next}`);
413
+ return true;
414
+ }
415
+ if (name === "think") {
416
+ const arg = args.trim().toLowerCase();
417
+ const force = arg === "on" || arg === "true" || arg === "1"
418
+ ? true
419
+ : arg === "off" || arg === "false" || arg === "0"
420
+ ? false
421
+ : undefined;
422
+ onToggleThink?.(force);
423
+ return true;
424
+ }
425
+ if (name === "verbose") {
426
+ // Phase 101: UI-only — full tool-card output, no collapse.
427
+ const arg = args.trim().toLowerCase();
428
+ const force = arg === "on" || arg === "true" || arg === "1"
429
+ ? true
430
+ : arg === "off" || arg === "false" || arg === "0"
431
+ ? false
432
+ : undefined;
433
+ onToggleVerbose?.(force);
434
+ return true;
435
+ }
436
+ if (name === "reasoning") {
437
+ // Phase 308: UI-only — expand reasoning/thinking inline (live
438
+ // progress), independent of /verbose.
439
+ const arg = args.trim().toLowerCase();
440
+ const force = arg === "on" || arg === "true" || arg === "1"
441
+ ? true
442
+ : arg === "off" || arg === "false" || arg === "0"
443
+ ? false
444
+ : undefined;
445
+ onToggleReasoning?.(force);
446
+ return true;
447
+ }
448
+ sendSlashCommand(name, args);
449
+ return true;
450
+ };
451
+ const submit = () => {
452
+ const trimmed = buffer.trim();
453
+ // Phase 135: capture the paste-expanded form before the store is
454
+ // cleared by editor.reset().
455
+ const trimmedExpanded = editor.expandPastes(trimmed);
456
+ editor.reset();
457
+ setHistoryIdx(-1);
458
+ draftRef.current = "";
459
+ if (!trimmed)
460
+ return;
461
+ pushHistory(trimmed);
462
+ // Phase 83: claude-code-style shell prefix. A leading `!` routes
463
+ // the rest of the line to /sh — the cli runs it against the
464
+ // active tab's cwd, streams output as a tool card, and the
465
+ // model never sees the input.
466
+ if (trimmed.startsWith("!")) {
467
+ // Phase 233: paste chips are expanded before the shell command
468
+ // is dispatched. Pre-233 a paste in `!cmd` would have stayed as
469
+ // `[paste#1: N lines]` literally and the shell would have run
470
+ // the chip text instead of the pasted content.
471
+ const cmd = editor.expandPastes(trimmed.slice(1)).trim();
472
+ if (cmd)
473
+ sendSlashCommand("sh", cmd);
474
+ return;
475
+ }
476
+ // Phase 233: slash commands also need paste expansion. /team and
477
+ // similar commands take a free-form prompt as their argument; a
478
+ // pasted block must reach the slash dispatcher as full text, not
479
+ // the `[paste#N: M lines]` collapsed chip. Pre-233 the chip
480
+ // stayed literal in slash args, so `/team <pasted prompt>`
481
+ // forwarded only the chip token to the team adapter and the
482
+ // model saw nothing useful.
483
+ if (handleSlash(trimmedExpanded))
484
+ return;
485
+ // Phase 115: echo the user's own message into the log first, so
486
+ // the scrollback reads as a conversation. Uses the paste-expanded
487
+ // text but keeps @file mentions as raw tokens — the user typed the
488
+ // paste content themselves and expects to see it in scrollback,
489
+ // but a `@README.md` should not dump the file body into the log
490
+ // (Phase 196 refinement of the Phase 115 echo).
491
+ onUserMessage?.(trimmedExpanded);
492
+ // Phase 340: pull image attachments BEFORE @file/text handling.
493
+ // 1) `[image#N]` chips from a clipboard paste → editor.expandImages
494
+ // strips the chip tokens and returns their paths.
495
+ // 2) `@photo.png` mentions → extractImageMentions removes the tokens
496
+ // and resolves them to absolute paths (so expandFileMentions below
497
+ // never tries to binary-load an image as text).
498
+ const { text: afterChips, images: chipImages } = editor.expandImages(trimmedExpanded);
499
+ const { text: afterImageMentions, images: atImages, missing: missingImages, } = extractImageMentions(afterChips, { cwd });
500
+ const attachments = [...chipImages, ...atImages];
501
+ if (missingImages.length > 0) {
502
+ onLocalLine?.(`[image] not found: ${missingImages.join(", ")}`);
503
+ }
504
+ if (attachments.length > 0) {
505
+ onLocalLine?.(`[image] attached ${attachments.length} image${attachments.length === 1 ? "" : "s"}`);
506
+ }
507
+ // Phase 55: resolve @path mentions against the active tab's
508
+ // cwd, not the omg process cwd. With per-tab cwd (Phase 54)
509
+ // typing `@README.md` should pull the README from whichever
510
+ // project this tab is rooted in. Paste chips were already spliced
511
+ // back into `trimmedExpanded` (Phase 135).
512
+ const { expanded, loaded, failed } = expandFileMentions(afterImageMentions, {
513
+ cwd,
514
+ });
515
+ if (loaded.length > 0) {
516
+ onLocalLine?.(`[@] loaded ${loaded.length} file${loaded.length === 1 ? "" : "s"}: ${loaded.join(", ")}`);
517
+ }
518
+ if (failed.length > 0) {
519
+ onLocalLine?.(`[@] failed: ${failed.join("; ")}`);
520
+ }
521
+ // Phase 340: never send an empty prompt with an image — codex's exec
522
+ // would fall back to reading (empty) stdin. Give a neutral instruction.
523
+ const outText = expanded.trim().length === 0 && attachments.length > 0
524
+ ? "Look at the attached image(s)."
525
+ : expanded;
526
+ sendInput(outText, attachments);
527
+ };
528
+ useInput((input, key) => {
529
+ const rawInput = rawInputRef.current;
530
+ if (isMouseSequence(rawInput) || isMouseSequence(input)) {
531
+ return;
532
+ }
533
+ // Phase 61: opt-in key dump. Set OMG_DEBUG_KEYS=1 and a file at
534
+ // ~/.omg/keylog.txt records every keystroke with its raw bytes
535
+ // + ink's parsed flags. Used to diagnose terminal-specific
536
+ // mismatches (e.g. Warp delivering Opt-N without key.meta).
537
+ if (process.env.OMG_DEBUG_KEYS) {
538
+ try {
539
+ const hex = [...Buffer.from(input, "utf-8")]
540
+ .map((b) => b.toString(16).padStart(2, "0"))
541
+ .join(" ");
542
+ const flags = Object.entries(key)
543
+ .filter(([, v]) => v)
544
+ .map(([k]) => k)
545
+ .join(",");
546
+ process.stderr.write(`[omg-keys] input=${JSON.stringify(input)} hex=[${hex}] flags=[${flags}]\n`);
547
+ }
548
+ catch {
549
+ /* logging must never throw */
550
+ }
551
+ }
552
+ // Phase 289: fold a Korean (2-set) jamo back to its Latin key while
553
+ // Ctrl is held so the shortcut comparisons below match under a
554
+ // Hangul input source (Ctrl+P arrives as "ㅔ", not "p").
555
+ const ck = normalizeCtrlInput(input, key.ctrl);
556
+ if (key.ctrl && ck === "c") {
557
+ sendQuit();
558
+ exit();
559
+ return;
560
+ }
561
+ // ---------------- Ctrl-R reverse history search (Phase 125) ------
562
+ // Ctrl-R opens the search (or, when already open, steps to the next
563
+ // older match). While open, typing edits the query, Enter accepts
564
+ // the current match into the buffer, Esc cancels; any other control
565
+ // key closes the search and falls through to its normal action.
566
+ if (key.ctrl && ck === "r") {
567
+ setSearch((s) => {
568
+ if (!s)
569
+ return { query: "", idx: 0 };
570
+ const matches = reverseMatches(s.query);
571
+ const nextIdx = matches.length === 0 ? 0 : Math.min(s.idx + 1, matches.length - 1);
572
+ return { query: s.query, idx: nextIdx };
573
+ });
574
+ return;
575
+ }
576
+ if (search) {
577
+ if (key.return) {
578
+ const m = reverseMatches(search.query)[search.idx];
579
+ setSearch(null);
580
+ if (m)
581
+ setBufAndCursor(m, m.length);
582
+ return;
583
+ }
584
+ if (key.escape) {
585
+ setSearch(null);
586
+ return;
587
+ }
588
+ if (key.backspace || key.delete || input === "\x7f" || input === "\b") {
589
+ setSearch((s) => (s ? { query: s.query.slice(0, -1), idx: 0 } : s));
590
+ return;
591
+ }
592
+ if (input && !key.ctrl && !key.meta) {
593
+ setSearch((s) => (s ? { query: s.query + input, idx: 0 } : s));
594
+ return;
595
+ }
596
+ // Unhandled control key — leave search and let it act normally.
597
+ setSearch(null);
598
+ }
599
+ // ---------------- Undo / redo (Phase 126) ----------------------
600
+ // Ctrl-_ (0x1f) or Ctrl-Z undo; Ctrl-Y redo. (Ctrl-Z may be eaten
601
+ // by the shell as SIGTSTP in some terminals, so Ctrl-_ is the
602
+ // reliable binding.)
603
+ if (input === "\x1f" || (key.ctrl && ck === "z")) {
604
+ editor.undo();
605
+ return;
606
+ }
607
+ if (key.ctrl && ck === "y") {
608
+ editor.redo();
609
+ return;
610
+ }
611
+ if (key.escape && input.length <= 1) {
612
+ // Phase 64: when the @file popup is up, Esc closes it instead
613
+ // of cancelling the in-flight stream.
614
+ if (popupOpen && mention) {
615
+ setDismissedStart(mention.start);
616
+ return;
617
+ }
618
+ // A plain ESC keypress means cancel. Multi-byte ESC sequences
619
+ // (arrow keys, Opt-letter) still set key.escape, but their
620
+ // input is longer — those fall through to the matchers below.
621
+ sendCancel();
622
+ return;
623
+ }
624
+ // ---------------- Tab shortcuts (Phase 49 / 68) ---------------
625
+ // Ctrl-N → /new (default-named tab on the same provider).
626
+ // (Ctrl-T would be more "browsery" but macOS PTYs interpret it
627
+ // as SIGINFO before ink can see the byte.)
628
+ if (key.ctrl && ck === "n") {
629
+ sendSlashCommand("new", "");
630
+ return;
631
+ }
632
+ // Phase 68: cycle keys for users whose terminal eats Opt-N.
633
+ // Ctrl-P → previous tab
634
+ // Ctrl-O → next tab
635
+ // The cli's /switch supports the "+1" / "-1" syntax for relative
636
+ // movement.
637
+ if (key.ctrl && ck === "p") {
638
+ sendSlashCommand("switch", "-1");
639
+ return;
640
+ }
641
+ if (key.ctrl && ck === "o") {
642
+ sendSlashCommand("switch", "+1");
643
+ return;
644
+ }
645
+ // Opt-1 .. Opt-9 → /switch <N>. Terminals send Esc + digit.
646
+ // Ink surfaces them as key.meta + input=digit on a typical
647
+ // setup; Warp sometimes delivers the raw two-byte ESC+digit
648
+ // sequence without setting key.meta. Match both shapes.
649
+ if (key.meta && /^[1-9]$/.test(input)) {
650
+ sendSlashCommand("switch", input);
651
+ return;
652
+ }
653
+ if (/^\x1b[1-9]$/.test(input)) {
654
+ sendSlashCommand("switch", input[1]);
655
+ return;
656
+ }
657
+ // ---------------- Cursor motion -----------------------------
658
+ // Home / End — terminals often deliver macOS Cmd+← / Cmd+→ as
659
+ // Home / End while in the alternate screen buffer.
660
+ if (key.home) {
661
+ setCursor(startOfLine(buffer, cursor));
662
+ return;
663
+ }
664
+ if (key.end) {
665
+ setCursor(endOfLine(buffer, cursor));
666
+ return;
667
+ }
668
+ // Kitty keyboard protocol can report Cmd as `super`. Other
669
+ // terminals encode Cmd+Arrow as CSI 1;9D / CSI 1;9C. Ink's
670
+ // high-level key object collapses those together with Opt+Arrow,
671
+ // so use the raw sequence captured above to keep macOS text-field
672
+ // semantics: Cmd = line boundary, Opt/Ctrl = word boundary.
673
+ if (key.leftArrow && (key.super || isLineArrowSequence(rawInput, "left"))) {
674
+ setCursor(startOfLine(buffer, cursor));
675
+ return;
676
+ }
677
+ if (key.rightArrow &&
678
+ (key.super || isLineArrowSequence(rawInput, "right"))) {
679
+ setCursor(endOfLine(buffer, cursor));
680
+ return;
681
+ }
682
+ if (key.leftArrow &&
683
+ (key.ctrl ||
684
+ isWordArrowSequence(rawInput, "left") ||
685
+ (key.meta && !key.super))) {
686
+ setCursor(prevWordIdx(buffer, cursor));
687
+ return;
688
+ }
689
+ if (key.rightArrow &&
690
+ (key.ctrl ||
691
+ isWordArrowSequence(rawInput, "right") ||
692
+ (key.meta && !key.super))) {
693
+ setCursor(nextWordIdx(buffer, cursor));
694
+ return;
695
+ }
696
+ if (key.leftArrow) {
697
+ setCursor(Math.max(0, cursor - 1));
698
+ return;
699
+ }
700
+ if (key.rightArrow) {
701
+ // Phase 113: → at end-of-line accepts the ghost suggestion
702
+ // (fish-style). Mid-line it just moves the cursor.
703
+ if (cursor === buffer.length && acceptGhost())
704
+ return;
705
+ setCursor(Math.min(buffer.length, cursor + 1));
706
+ return;
707
+ }
708
+ // Option/Alt + ← / → — terminals send ESC b / ESC f for word
709
+ // motion. ink usually surfaces them as key.meta + input='b'/'f',
710
+ // but Warp sometimes delivers the raw two-byte ESC sequence
711
+ // without setting key.meta. Match both shapes.
712
+ if ((key.meta && input === "b") || input === "\x1bb") {
713
+ setCursor(prevWordIdx(buffer, cursor));
714
+ return;
715
+ }
716
+ if ((key.meta && input === "f") || input === "\x1bf") {
717
+ setCursor(nextWordIdx(buffer, cursor));
718
+ return;
719
+ }
720
+ if (key.ctrl && input === "a") {
721
+ setCursor(startOfLine(buffer, cursor));
722
+ return;
723
+ }
724
+ if (key.ctrl && input === "e") {
725
+ setCursor(endOfLine(buffer, cursor));
726
+ return;
727
+ }
728
+ // ---------------- Deletions ---------------------------------
729
+ if (key.ctrl && input === "w") {
730
+ deleteRange(prevWordIdx(buffer, cursor), cursor);
731
+ return;
732
+ }
733
+ if (key.ctrl && input === "u") {
734
+ deleteRange(startOfLine(buffer, cursor), cursor);
735
+ return;
736
+ }
737
+ if (key.ctrl && input === "k") {
738
+ deleteRange(cursor, endOfLine(buffer, cursor));
739
+ return;
740
+ }
741
+ // Backspace — terminals send a confusing mix:
742
+ // 0x7F (DEL) - the traditional unix Backspace byte
743
+ // 0x08 (BS) - older terminals + Ctrl-H
744
+ // ESC[3~ → key.delete - macOS "Delete" key (the smaller one)
745
+ // Apple keyboards label the larger key "Delete" but it functions
746
+ // as Backspace, and Warp / a handful of other terminals report
747
+ // *that* key as key.delete with empty input. The user-visible
748
+ // intent is unambiguous: delete the char before the cursor. So
749
+ // we route key.delete to Backspace too. True forward-delete is
750
+ // surfaced through Ctrl-D below, the standard emacs binding.
751
+ if (key.backspace ||
752
+ key.delete ||
753
+ input === "\x7f" ||
754
+ input === "\x08" ||
755
+ (key.ctrl && input === "h")) {
756
+ if (cursor > 0)
757
+ deleteRange(cursor - 1, cursor);
758
+ return;
759
+ }
760
+ // Forward-delete — Ctrl-D. Rarely needed in a single-line input
761
+ // but standard emacs / readline behaviour; cheap to keep.
762
+ if (key.ctrl && input === "d") {
763
+ if (cursor < buffer.length)
764
+ deleteRange(cursor, cursor + 1);
765
+ return;
766
+ }
767
+ // ---------------- @file popup navigation (Phase 64) ----------
768
+ // When the popup is up, ↑/↓ cycle candidates and Tab/Enter
769
+ // accepts. This must run before the multi-line ↑/↓ / history
770
+ // handlers below.
771
+ if (popupOpen) {
772
+ if (key.upArrow) {
773
+ setMentionSel((mentionSel - 1 + fileSuggestions.length) % fileSuggestions.length);
774
+ return;
775
+ }
776
+ if (key.downArrow) {
777
+ setMentionSel((mentionSel + 1) % fileSuggestions.length);
778
+ return;
779
+ }
780
+ if (key.tab) {
781
+ if (acceptMention())
782
+ return;
783
+ }
784
+ // Enter intentionally falls through: if the user typed a full
785
+ // path the popup may still match it; we don't want to swallow
786
+ // their submit. The popup closes naturally once submit fires.
787
+ }
788
+ // ---------------- Slash palette navigation (Phase 65) ---------
789
+ // While typing `/<prefix>` the palette shows candidates with
790
+ // descriptions. ↑/↓ select, Tab/Enter accept. Like the @file
791
+ // popup we don't hijack Enter — submit still wins if the buffer
792
+ // already names a valid slash on its own.
793
+ if (paletteOpen) {
794
+ if (key.upArrow) {
795
+ setPaletteSel((paletteSel - 1 + palette.length) % palette.length);
796
+ return;
797
+ }
798
+ if (key.downArrow) {
799
+ setPaletteSel((paletteSel + 1) % palette.length);
800
+ return;
801
+ }
802
+ if (key.tab) {
803
+ if (acceptPalette())
804
+ return;
805
+ }
806
+ }
807
+ // Phase 186: Tab accepts the predicted-next-message ghost when
808
+ // the prompt is empty. History cycling was removed alongside the
809
+ // fish-style autosuggestion.
810
+ if (key.tab && !popupOpen && !paletteOpen) {
811
+ if (acceptGhost())
812
+ return;
813
+ }
814
+ // ---------------- Vertical motion / history ----------------
815
+ // Phase 63: ↑/↓ behave like a real editor inside a multi-line
816
+ // buffer — move the cursor between lines, preserving column. At
817
+ // the top/bottom edge, fall through to history navigation so the
818
+ // single-line UX still works.
819
+ if (key.upArrow) {
820
+ if (isMultiLine) {
821
+ const next = lineUpIdx(buffer, cursor);
822
+ if (next >= 0) {
823
+ setCursor(next);
824
+ return;
825
+ }
826
+ // Top line — fall through to history.
827
+ }
828
+ const hist = historyRef.current;
829
+ if (hist.length === 0)
830
+ return;
831
+ const next = historyIdx === -1 ? hist.length - 1 : Math.max(0, historyIdx - 1);
832
+ if (historyIdx === -1)
833
+ draftRef.current = buffer;
834
+ setHistoryIdx(next);
835
+ setBufAndCursor(hist[next], hist[next].length);
836
+ return;
837
+ }
838
+ if (key.downArrow) {
839
+ if (isMultiLine) {
840
+ const next = lineDownIdx(buffer, cursor);
841
+ if (next >= 0) {
842
+ setCursor(next);
843
+ return;
844
+ }
845
+ // Bottom line — fall through to history.
846
+ }
847
+ if (historyIdx === -1)
848
+ return;
849
+ const hist = historyRef.current;
850
+ const next = historyIdx + 1;
851
+ if (next >= hist.length) {
852
+ setHistoryIdx(-1);
853
+ setBufAndCursor(draftRef.current, draftRef.current.length);
854
+ }
855
+ else {
856
+ setHistoryIdx(next);
857
+ setBufAndCursor(hist[next], hist[next].length);
858
+ }
859
+ return;
860
+ }
861
+ // ---------------- Enter -------------------------------------
862
+ if (key.return) {
863
+ // Trailing backslash continues the line as a newline.
864
+ if (buffer.slice(0, cursor).endsWith("\\")) {
865
+ const next = buffer.slice(0, cursor - 1) + "\n" + buffer.slice(cursor);
866
+ setBufAndCursor(next, cursor);
867
+ return;
868
+ }
869
+ // Shift/Alt+Enter — explicit newline.
870
+ if (key.meta || key.shift) {
871
+ insertAt("\n");
872
+ return;
873
+ }
874
+ submit();
875
+ return;
876
+ }
877
+ // ---------------- Printable input ---------------------------
878
+ if (input && !key.ctrl && !key.meta) {
879
+ // Strip bracketed-paste markers if a terminal sent them.
880
+ // Also strip ESC-prefixed control sequences that fell through
881
+ // the matchers above (otherwise an unhandled meta-key would
882
+ // insert its raw ESC byte as literal text).
883
+ const cleaned = input
884
+ .replace(/\x1b\[200~/g, "")
885
+ .replace(/\x1b\[201~/g, "")
886
+ // Phase 146: terminals separate pasted lines with CR (\r), not
887
+ // LF. Left in, the \r survives the control-strip below and makes
888
+ // the cursor jump to column 0 at render, overwriting earlier
889
+ // lines so only the last shows. Normalize CR / CRLF → LF first
890
+ // so multi-line pastes become a real multi-line buffer (and the
891
+ // line count below triggers the paste chip correctly).
892
+ .replace(/\r\n?/g, "\n")
893
+ .replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "");
894
+ if (cleaned) {
895
+ // Phase 135: a big multi-line paste collapses to a chip; the
896
+ // text is stashed and restored at submit. Small input (typing,
897
+ // short pastes) inserts as-is.
898
+ const lineCount = cleaned.split("\n").length;
899
+ if (lineCount >= PASTE_MIN_LINES || cleaned.length > PASTE_MIN_CHARS) {
900
+ insertAt(editor.storePaste(cleaned, lineCount));
901
+ }
902
+ else {
903
+ insertAt(cleaned);
904
+ }
905
+ }
906
+ else if (/\x1b\[20[01]~/.test(input) || /\x1b\[20[01]~/.test(rawInput ?? "")) {
907
+ // Phase 340: an EMPTY bracketed paste = a non-text paste (most
908
+ // often an image on the clipboard — terminals don't deliver image
909
+ // bytes via the TTY). Probe the OS clipboard; if an image is there,
910
+ // save it and splice an [image#N] chip. Best-effort + terminal-
911
+ // dependent (some terminals send nothing at all on image paste);
912
+ // the @path flow is the guaranteed alternative.
913
+ const img = captureClipboardImage();
914
+ if (img) {
915
+ insertAt(editor.storeImage(img));
916
+ onLocalLine?.("[image] captured from clipboard");
917
+ }
918
+ }
919
+ }
920
+ });
921
+ // Render — split the buffer at the cursor boundary. The real
922
+ // terminal cursor is positioned by Ink's `useCursor`; we no longer
923
+ // render an inline ▌ glyph here because it overlaps the hardware
924
+ // cursor during IME composition.
925
+ const before = buffer.slice(0, cursor);
926
+ const after = buffer.slice(cursor);
927
+ const beforeLines = before.split("\n");
928
+ const afterLines = after.split("\n");
929
+ // Phase 268/269: Ink 6.7+ exposes a cursor API that handles
930
+ // trailing-`\n` math and cursor visibility, but its position must be
931
+ // relative to the Ink output origin and available before Ink's
932
+ // render commit. `getComputedTop()` is only parent-relative, so
933
+ // summing the wrapper's ancestor Yoga offsets is what prevents IME
934
+ // compose from appearing at row 0 when CommandInput itself is nested
935
+ // below EventLog/Dock/HRule. Column uses `stringWidth` so CJK wide
936
+ // chars (한글, 漢字) count 2 cols each like the terminal renders them.
937
+ const wrapperRef = useRef(null);
938
+ const { setCursorPosition } = useCursor();
939
+ const [cursorOrigin, setCursorOrigin] = useState(null);
940
+ // Visible column of the cursor on its line: prompt + display
941
+ // width of all chars to the left of the cursor on that line.
942
+ const cursorCol = inputCursorColumn(beforeLines[beforeLines.length - 1]);
943
+ const showHardwareCursor = shouldShowInputHardwareCursor(buffer, suppressCursorWhenEmpty, suppressHardwareCursor);
944
+ useLayoutEffect(() => {
945
+ const node = wrapperRef.current;
946
+ if (!node) {
947
+ setCursorOrigin((prev) => (prev === null ? prev : null));
948
+ return;
949
+ }
950
+ const next = absoluteElementOrigin(node);
951
+ setCursorOrigin((prev) => prev && prev.x === next.x && prev.y === next.y ? prev : next);
952
+ });
953
+ // The "cursor line" merges the last line of `before` with the
954
+ // first line of `after`; surrounding lines render as-is.
955
+ const renderLines = [];
956
+ // Lines before the cursor line.
957
+ for (let i = 0; i < beforeLines.length - 1; i++) {
958
+ renderLines.push({ kind: "plain", text: beforeLines[i] });
959
+ }
960
+ // Cursor line.
961
+ renderLines.push({
962
+ kind: "cursor",
963
+ left: beforeLines[beforeLines.length - 1],
964
+ right: afterLines[0],
965
+ });
966
+ // Lines after the cursor line.
967
+ for (let i = 1; i < afterLines.length; i++) {
968
+ renderLines.push({ kind: "plain", text: afterLines[i] });
969
+ }
970
+ const cursorLineInBuffer = beforeLines.length - 1;
971
+ const inputWindowStart = inputViewportStart(renderLines.length, cursorLineInBuffer);
972
+ const visibleRenderLines = renderLines.slice(inputWindowStart, inputWindowStart + MAX_INPUT_VISIBLE_LINES);
973
+ const hiddenTop = inputWindowStart > 0;
974
+ const hiddenBottom = inputWindowStart + visibleRenderLines.length < renderLines.length;
975
+ const hiddenBottomCount = renderLines.length - inputWindowStart - visibleRenderLines.length;
976
+ // Lines within the visible input viewport above the cursor's line.
977
+ const cursorLineWithinInput = (hiddenTop ? 1 : 0) + cursorLineInBuffer - inputWindowStart;
978
+ setCursorPosition(showHardwareCursor && cursorOrigin
979
+ ? inputHardwareCursorPosition(cursorOrigin, cursorCol, cursorLineWithinInput, fullscreenCursorMode)
980
+ : undefined);
981
+ // Phase 83 / 85: surface shell-prefix mode by recoloring the
982
+ // prompt arrow magenta (pink) while the buffer leads with `!`.
983
+ // Red read like an error; magenta reads as "different mode".
984
+ const shellMode = buffer.startsWith("!");
985
+ const promptColor = shellMode
986
+ ? theme.prompt.shellColor
987
+ : theme.prompt.arrowColor;
988
+ const promptGlyph = theme.prompt.arrow;
989
+ return (_jsxs(Box, { flexDirection: "column", children: [popupOpen && (_jsx(FileSuggest, { items: fileSuggestions, selectedIdx: mentionSel })), paletteOpen && _jsx(SlashPalette, { items: palette, selectedIdx: paletteSel }), search && (_jsxs(Box, { children: [_jsxs(Text, { color: theme.hint.color, children: ["(reverse-i-search)`", search.query, "`: "] }), _jsx(Text, { children: reverseMatches(search.query)[search.idx] ?? "" })] })), _jsxs(Box, { flexDirection: "column", ref: wrapperRef, children: [hiddenTop && (_jsx(Box, { children: _jsxs(Text, { color: theme.hint.color, dimColor: true, children: [" ⋮ ", inputWindowStart, " line", inputWindowStart === 1 ? "" : "s", " above"] }) })), visibleRenderLines.map((row, i) => {
990
+ const absoluteLine = inputWindowStart + i;
991
+ return (_jsxs(Box, { children: [_jsx(Text, { color: promptColor, children: absoluteLine === 0 ? promptGlyph : " " }), row.kind === "plain" ? (_jsx(Text, { children: row.text })) : (_jsxs(_Fragment, { children: [_jsx(Text, { children: row.left }), _jsx(Text, { children: row.right }), ghostSuffix && (_jsx(Text, { color: theme.status.labelColor, dimColor: true, children: ghostSuffix }))] }))] }, absoluteLine));
992
+ }), hiddenBottom && (_jsx(Box, { children: _jsxs(Text, { color: theme.hint.color, dimColor: true, children: [" ⋮ ", hiddenBottomCount, " line", hiddenBottomCount === 1 ? "" : "s", " ", "below"] }) }))] }), isMultiLine && (_jsx(Box, { children: _jsxs(Text, { color: theme.hint.color, children: [" ", "(multi-line \u2014 Enter submits; Shift/Alt+Enter or trailing \\\\ for newline)"] }) })), shellMode && !isMultiLine && (_jsx(Box, { children: _jsxs(Text, { color: theme.prompt.shellColor, children: [" ", "shell mode \u2014 Enter runs the command in the active tab's cwd, model not invoked"] }) }))] }));
993
+ }
994
+ //# sourceMappingURL=CommandInput.js.map