botmux 3.9.2 → 3.10.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 (314) hide show
  1. package/README.en.md +1 -1
  2. package/README.md +1 -1
  3. package/dist/.runtime-build-id +1 -1
  4. package/dist/adapters/cli/codex.d.ts.map +1 -1
  5. package/dist/adapters/cli/codex.js +6 -0
  6. package/dist/adapters/cli/codex.js.map +1 -1
  7. package/dist/adapters/cli/opencode.d.ts.map +1 -1
  8. package/dist/adapters/cli/opencode.js +7 -1
  9. package/dist/adapters/cli/opencode.js.map +1 -1
  10. package/dist/adapters/cli/reasonix.d.ts +35 -0
  11. package/dist/adapters/cli/reasonix.d.ts.map +1 -0
  12. package/dist/adapters/cli/reasonix.js +236 -0
  13. package/dist/adapters/cli/reasonix.js.map +1 -0
  14. package/dist/adapters/cli/registry.d.ts +2 -1
  15. package/dist/adapters/cli/registry.d.ts.map +1 -1
  16. package/dist/adapters/cli/registry.js +4 -1
  17. package/dist/adapters/cli/registry.js.map +1 -1
  18. package/dist/adapters/cli/types.d.ts +5 -1
  19. package/dist/adapters/cli/types.d.ts.map +1 -1
  20. package/dist/cli.d.ts.map +1 -1
  21. package/dist/cli.js +168 -62
  22. package/dist/cli.js.map +1 -1
  23. package/dist/core/command-handler.d.ts +18 -4
  24. package/dist/core/command-handler.d.ts.map +1 -1
  25. package/dist/core/command-handler.js +234 -26
  26. package/dist/core/command-handler.js.map +1 -1
  27. package/dist/core/dashboard-ipc-server.d.ts +1 -0
  28. package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
  29. package/dist/core/dashboard-ipc-server.js +27 -3
  30. package/dist/core/dashboard-ipc-server.js.map +1 -1
  31. package/dist/core/dispatch.d.ts +54 -24
  32. package/dist/core/dispatch.d.ts.map +1 -1
  33. package/dist/core/dispatch.js +81 -27
  34. package/dist/core/dispatch.js.map +1 -1
  35. package/dist/core/input-turn-dedupe.d.ts +20 -0
  36. package/dist/core/input-turn-dedupe.d.ts.map +1 -0
  37. package/dist/core/input-turn-dedupe.js +57 -0
  38. package/dist/core/input-turn-dedupe.js.map +1 -0
  39. package/dist/core/local-terminal-opener.d.ts.map +1 -1
  40. package/dist/core/local-terminal-opener.js +10 -1
  41. package/dist/core/local-terminal-opener.js.map +1 -1
  42. package/dist/core/passthrough-commands.d.ts.map +1 -1
  43. package/dist/core/passthrough-commands.js +1 -1
  44. package/dist/core/passthrough-commands.js.map +1 -1
  45. package/dist/core/plugins/pm2.d.ts.map +1 -1
  46. package/dist/core/plugins/pm2.js +7 -1
  47. package/dist/core/plugins/pm2.js.map +1 -1
  48. package/dist/core/resource-monitor/attribution.d.ts.map +1 -1
  49. package/dist/core/resource-monitor/attribution.js +17 -1
  50. package/dist/core/resource-monitor/attribution.js.map +1 -1
  51. package/dist/core/resource-monitor/darwin.d.ts +145 -0
  52. package/dist/core/resource-monitor/darwin.d.ts.map +1 -0
  53. package/dist/core/resource-monitor/darwin.js +360 -0
  54. package/dist/core/resource-monitor/darwin.js.map +1 -0
  55. package/dist/core/resource-monitor/procfs.d.ts.map +1 -1
  56. package/dist/core/resource-monitor/procfs.js +6 -0
  57. package/dist/core/resource-monitor/procfs.js.map +1 -1
  58. package/dist/core/resource-monitor/types.d.ts +1 -1
  59. package/dist/core/resource-monitor/types.d.ts.map +1 -1
  60. package/dist/core/scheduler.d.ts.map +1 -1
  61. package/dist/core/scheduler.js +5 -2
  62. package/dist/core/scheduler.js.map +1 -1
  63. package/dist/core/session-discovery.d.ts.map +1 -1
  64. package/dist/core/session-discovery.js +3 -0
  65. package/dist/core/session-discovery.js.map +1 -1
  66. package/dist/core/session-manager.d.ts +3 -1
  67. package/dist/core/session-manager.d.ts.map +1 -1
  68. package/dist/core/session-manager.js +46 -0
  69. package/dist/core/session-manager.js.map +1 -1
  70. package/dist/core/session-marker.d.ts +1 -8
  71. package/dist/core/session-marker.d.ts.map +1 -1
  72. package/dist/core/session-marker.js +2 -50
  73. package/dist/core/session-marker.js.map +1 -1
  74. package/dist/core/types.d.ts +3 -1
  75. package/dist/core/types.d.ts.map +1 -1
  76. package/dist/core/types.js.map +1 -1
  77. package/dist/core/worker-pool.d.ts +17 -0
  78. package/dist/core/worker-pool.d.ts.map +1 -1
  79. package/dist/core/worker-pool.js +292 -9
  80. package/dist/core/worker-pool.js.map +1 -1
  81. package/dist/daemon.d.ts.map +1 -1
  82. package/dist/daemon.js +27 -12
  83. package/dist/daemon.js.map +1 -1
  84. package/dist/dashboard/daemon-internal-api.d.ts.map +1 -1
  85. package/dist/dashboard/daemon-internal-api.js +11 -2
  86. package/dist/dashboard/daemon-internal-api.js.map +1 -1
  87. package/dist/dashboard/groups-action-helpers.d.ts +2 -0
  88. package/dist/dashboard/groups-action-helpers.d.ts.map +1 -1
  89. package/dist/dashboard/groups-action-helpers.js +9 -0
  90. package/dist/dashboard/groups-action-helpers.js.map +1 -1
  91. package/dist/dashboard/groups-matrix-snapshot.d.ts +56 -0
  92. package/dist/dashboard/groups-matrix-snapshot.d.ts.map +1 -0
  93. package/dist/dashboard/groups-matrix-snapshot.js +127 -0
  94. package/dist/dashboard/groups-matrix-snapshot.js.map +1 -0
  95. package/dist/dashboard/resource-monitor-service.d.ts.map +1 -1
  96. package/dist/dashboard/resource-monitor-service.js +18 -2
  97. package/dist/dashboard/resource-monitor-service.js.map +1 -1
  98. package/dist/dashboard/web/app.d.ts.map +1 -1
  99. package/dist/dashboard/web/app.js +45 -4
  100. package/dist/dashboard/web/app.js.map +1 -1
  101. package/dist/dashboard/web/groups-api.js +1 -1
  102. package/dist/dashboard/web/groups-api.js.map +1 -1
  103. package/dist/dashboard/web/i18n.js +10 -10
  104. package/dist/dashboard/web/i18n.js.map +1 -1
  105. package/dist/dashboard/web/roles-page.d.ts.map +1 -1
  106. package/dist/dashboard/web/roles-page.js +26 -11
  107. package/dist/dashboard/web/roles-page.js.map +1 -1
  108. package/dist/dashboard-web/app.js +1 -1
  109. package/dist/dashboard-web/chunks/{bot-defaults-page-BHTQEWCH.js → bot-defaults-page-LTVOUDIS.js} +1 -1
  110. package/dist/dashboard-web/chunks/{chunk-KLZCQAHF.js → chunk-3UE7S77S.js} +1 -1
  111. package/dist/dashboard-web/chunks/{chunk-W77TPKZH.js → chunk-DCS35UMD.js} +1 -1
  112. package/dist/dashboard-web/chunks/{chunk-E3HZZXK5.js → chunk-MFQPCVHY.js} +4 -4
  113. package/dist/dashboard-web/chunks/{chunk-EZH56JCI.js → chunk-ZU3UUKAR.js} +1 -1
  114. package/dist/dashboard-web/chunks/{connectors-page-BP255CAX.js → connectors-page-5KWDIMKC.js} +1 -1
  115. package/dist/dashboard-web/chunks/{groups-page-CDHVXBUT.js → groups-page-FHOKYXMW.js} +1 -1
  116. package/dist/dashboard-web/chunks/{insights-page-57BFE6GT.js → insights-page-T2ZX2RWL.js} +1 -1
  117. package/dist/dashboard-web/chunks/{monitor-room-UTOYGQVF.js → monitor-room-YNVBAGR6.js} +1 -1
  118. package/dist/dashboard-web/chunks/{monitoring-page-WTHYAIUM.js → monitoring-page-LHM55YWN.js} +1 -1
  119. package/dist/dashboard-web/chunks/{office-page-JSMIB353.js → office-page-ATXVP7PW.js} +1 -1
  120. package/dist/dashboard-web/chunks/{overview-page-3VDBOH7L.js → overview-page-QYI3KBDD.js} +1 -1
  121. package/dist/dashboard-web/chunks/roles-page-56VWM6CD.js +1 -0
  122. package/dist/dashboard-web/chunks/{schedules-page-HHN736H6.js → schedules-page-S5K6U4EO.js} +1 -1
  123. package/dist/dashboard-web/chunks/{sessions-page-EIWOZD7A.js → sessions-page-WBP4N7D2.js} +1 -1
  124. package/dist/dashboard-web/chunks/{settings-page-2IUT5LS4.js → settings-page-QUZDQARR.js} +1 -1
  125. package/dist/dashboard-web/chunks/{skills-page-JKFKMUEM.js → skills-page-IFY7AEND.js} +1 -1
  126. package/dist/dashboard-web/chunks/{team-federation-page-Q2PXC3UY.js → team-federation-page-C7FJQPFZ.js} +1 -1
  127. package/dist/dashboard-web/chunks/{v3-page-EBQCD4AO.js → v3-page-2LMF3WWR.js} +1 -1
  128. package/dist/dashboard-web/chunks/{whiteboards-page-QZRMVNZN.js → whiteboards-page-3XC6QRMY.js} +1 -1
  129. package/dist/dashboard-web/style.css +2 -4
  130. package/dist/dashboard.js +65 -9
  131. package/dist/dashboard.js.map +1 -1
  132. package/dist/i18n/en.d.ts.map +1 -1
  133. package/dist/i18n/en.js +33 -7
  134. package/dist/i18n/en.js.map +1 -1
  135. package/dist/i18n/zh.d.ts.map +1 -1
  136. package/dist/i18n/zh.js +31 -7
  137. package/dist/i18n/zh.js.map +1 -1
  138. package/dist/im/lark/card-builder.d.ts +7 -0
  139. package/dist/im/lark/card-builder.d.ts.map +1 -1
  140. package/dist/im/lark/card-builder.js +56 -0
  141. package/dist/im/lark/card-builder.js.map +1 -1
  142. package/dist/im/lark/card-handler.d.ts.map +1 -1
  143. package/dist/im/lark/card-handler.js +42 -19
  144. package/dist/im/lark/card-handler.js.map +1 -1
  145. package/dist/im/lark/client.d.ts +10 -0
  146. package/dist/im/lark/client.d.ts.map +1 -1
  147. package/dist/im/lark/client.js +79 -0
  148. package/dist/im/lark/client.js.map +1 -1
  149. package/dist/im/lark/event-dispatcher.d.ts +14 -1
  150. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  151. package/dist/im/lark/event-dispatcher.js +171 -15
  152. package/dist/im/lark/event-dispatcher.js.map +1 -1
  153. package/dist/im/lark/lark-hosts.d.ts +5 -0
  154. package/dist/im/lark/lark-hosts.d.ts.map +1 -1
  155. package/dist/im/lark/lark-hosts.js +10 -0
  156. package/dist/im/lark/lark-hosts.js.map +1 -1
  157. package/dist/im/lark/message-parser.d.ts.map +1 -1
  158. package/dist/im/lark/message-parser.js +24 -7
  159. package/dist/im/lark/message-parser.js.map +1 -1
  160. package/dist/pm2-graceful-exit.d.ts +28 -0
  161. package/dist/pm2-graceful-exit.d.ts.map +1 -0
  162. package/dist/pm2-graceful-exit.js +39 -0
  163. package/dist/pm2-graceful-exit.js.map +1 -0
  164. package/dist/services/bridge-fallback-gate.d.ts +9 -2
  165. package/dist/services/bridge-fallback-gate.d.ts.map +1 -1
  166. package/dist/services/bridge-fallback-gate.js +31 -19
  167. package/dist/services/bridge-fallback-gate.js.map +1 -1
  168. package/dist/services/message-listener-store.d.ts +18 -0
  169. package/dist/services/message-listener-store.d.ts.map +1 -1
  170. package/dist/services/message-listener-store.js +35 -10
  171. package/dist/services/message-listener-store.js.map +1 -1
  172. package/dist/services/message-listener.d.ts +17 -0
  173. package/dist/services/message-listener.d.ts.map +1 -1
  174. package/dist/services/message-listener.js +26 -0
  175. package/dist/services/message-listener.js.map +1 -1
  176. package/dist/setup/bot-config-editor.d.ts.map +1 -1
  177. package/dist/setup/bot-config-editor.js +2 -0
  178. package/dist/setup/bot-config-editor.js.map +1 -1
  179. package/dist/setup/lark-scopes.json +1 -0
  180. package/dist/setup/verify-permissions.d.ts.map +1 -1
  181. package/dist/setup/verify-permissions.js +8 -0
  182. package/dist/setup/verify-permissions.js.map +1 -1
  183. package/dist/types.d.ts +34 -0
  184. package/dist/types.d.ts.map +1 -1
  185. package/dist/utils/child-env.d.ts +1 -1
  186. package/dist/utils/child-env.d.ts.map +1 -1
  187. package/dist/utils/child-env.js +13 -0
  188. package/dist/utils/child-env.js.map +1 -1
  189. package/dist/utils/file-lock.d.ts.map +1 -1
  190. package/dist/utils/file-lock.js +1 -1
  191. package/dist/utils/file-lock.js.map +1 -1
  192. package/dist/utils/global-install.d.ts.map +1 -1
  193. package/dist/utils/global-install.js +56 -10
  194. package/dist/utils/global-install.js.map +1 -1
  195. package/dist/utils/idle-detector.d.ts +4 -0
  196. package/dist/utils/idle-detector.d.ts.map +1 -1
  197. package/dist/utils/idle-detector.js +25 -0
  198. package/dist/utils/idle-detector.js.map +1 -1
  199. package/dist/utils/process-identity.d.ts +7 -0
  200. package/dist/utils/process-identity.d.ts.map +1 -0
  201. package/dist/utils/process-identity.js +62 -0
  202. package/dist/utils/process-identity.js.map +1 -0
  203. package/dist/worker.js +123 -9
  204. package/dist/worker.js.map +1 -1
  205. package/dist/workflows/events/payloads.d.ts +10 -10
  206. package/dist/workflows/events/schema.d.ts +28 -28
  207. package/dist/workflows/hostExecutors/registry.d.ts +2 -7
  208. package/dist/workflows/hostExecutors/registry.d.ts.map +1 -1
  209. package/dist/workflows/hostExecutors/registry.js.map +1 -1
  210. package/dist/workflows/shared/provider-reconciler.d.ts +1 -30
  211. package/dist/workflows/shared/provider-reconciler.d.ts.map +1 -1
  212. package/dist/workflows/shared/provider-reconciler.js.map +1 -1
  213. package/dist/workflows/v3/artifact-contract.d.ts +41 -0
  214. package/dist/workflows/v3/artifact-contract.d.ts.map +1 -0
  215. package/dist/workflows/v3/artifact-contract.js +20 -0
  216. package/dist/workflows/v3/artifact-contract.js.map +1 -0
  217. package/dist/workflows/v3/botmux-attempt-lease.d.ts +7 -0
  218. package/dist/workflows/v3/botmux-attempt-lease.d.ts.map +1 -0
  219. package/dist/workflows/v3/botmux-attempt-lease.js +189 -0
  220. package/dist/workflows/v3/botmux-attempt-lease.js.map +1 -0
  221. package/dist/workflows/v3/botmux-host-policy.d.ts +7 -0
  222. package/dist/workflows/v3/botmux-host-policy.d.ts.map +1 -0
  223. package/dist/workflows/v3/botmux-host-policy.js +34 -0
  224. package/dist/workflows/v3/botmux-host-policy.js.map +1 -0
  225. package/dist/workflows/v3/cli-run.d.ts +1 -1
  226. package/dist/workflows/v3/cli-run.d.ts.map +1 -1
  227. package/dist/workflows/v3/cli-run.js +1 -1
  228. package/dist/workflows/v3/cli-run.js.map +1 -1
  229. package/dist/workflows/v3/contract.d.ts +8 -89
  230. package/dist/workflows/v3/contract.d.ts.map +1 -1
  231. package/dist/workflows/v3/contract.js +2 -8
  232. package/dist/workflows/v3/contract.js.map +1 -1
  233. package/dist/workflows/v3/core-control.d.ts +16 -0
  234. package/dist/workflows/v3/core-control.d.ts.map +1 -0
  235. package/dist/workflows/v3/core-control.js +60 -0
  236. package/dist/workflows/v3/core-control.js.map +1 -0
  237. package/dist/workflows/v3/daemon-run.d.ts.map +1 -1
  238. package/dist/workflows/v3/daemon-run.js +2 -1
  239. package/dist/workflows/v3/daemon-run.js.map +1 -1
  240. package/dist/workflows/v3/dag-loader.d.ts +5 -0
  241. package/dist/workflows/v3/dag-loader.d.ts.map +1 -0
  242. package/dist/workflows/v3/dag-loader.js +22 -0
  243. package/dist/workflows/v3/dag-loader.js.map +1 -0
  244. package/dist/workflows/v3/dag.d.ts +2 -6
  245. package/dist/workflows/v3/dag.d.ts.map +1 -1
  246. package/dist/workflows/v3/dag.js +2 -24
  247. package/dist/workflows/v3/dag.js.map +1 -1
  248. package/dist/workflows/v3/ephemeral-pool.d.ts.map +1 -1
  249. package/dist/workflows/v3/ephemeral-pool.js +22 -12
  250. package/dist/workflows/v3/ephemeral-pool.js.map +1 -1
  251. package/dist/workflows/v3/event-contract.d.ts +273 -0
  252. package/dist/workflows/v3/event-contract.d.ts.map +1 -0
  253. package/dist/workflows/v3/event-contract.js +8 -0
  254. package/dist/workflows/v3/event-contract.js.map +1 -0
  255. package/dist/workflows/v3/gate-policy.d.ts +12 -0
  256. package/dist/workflows/v3/gate-policy.d.ts.map +1 -0
  257. package/dist/workflows/v3/gate-policy.js +20 -0
  258. package/dist/workflows/v3/gate-policy.js.map +1 -0
  259. package/dist/workflows/v3/gate-wait-store.d.ts +99 -0
  260. package/dist/workflows/v3/gate-wait-store.d.ts.map +1 -0
  261. package/dist/workflows/v3/gate-wait-store.js +263 -0
  262. package/dist/workflows/v3/gate-wait-store.js.map +1 -0
  263. package/dist/workflows/v3/host.js +1 -1
  264. package/dist/workflows/v3/host.js.map +1 -1
  265. package/dist/workflows/v3/human-gate.d.ts +4 -99
  266. package/dist/workflows/v3/human-gate.d.ts.map +1 -1
  267. package/dist/workflows/v3/human-gate.js +4 -275
  268. package/dist/workflows/v3/human-gate.js.map +1 -1
  269. package/dist/workflows/v3/in-process-attempt-lease.d.ts +10 -0
  270. package/dist/workflows/v3/in-process-attempt-lease.d.ts.map +1 -0
  271. package/dist/workflows/v3/in-process-attempt-lease.js +47 -0
  272. package/dist/workflows/v3/in-process-attempt-lease.js.map +1 -0
  273. package/dist/workflows/v3/journal.d.ts +2 -275
  274. package/dist/workflows/v3/journal.d.ts.map +1 -1
  275. package/dist/workflows/v3/journal.js.map +1 -1
  276. package/dist/workflows/v3/library-service.js +1 -1
  277. package/dist/workflows/v3/library-service.js.map +1 -1
  278. package/dist/workflows/v3/orchestrator.d.ts +1 -2
  279. package/dist/workflows/v3/orchestrator.d.ts.map +1 -1
  280. package/dist/workflows/v3/orchestrator.js.map +1 -1
  281. package/dist/workflows/v3/portable-artifact-snapshot.d.ts +15 -0
  282. package/dist/workflows/v3/portable-artifact-snapshot.d.ts.map +1 -0
  283. package/dist/workflows/v3/portable-artifact-snapshot.js +76 -0
  284. package/dist/workflows/v3/portable-artifact-snapshot.js.map +1 -0
  285. package/dist/workflows/v3/portable-final-outputs.d.ts +37 -0
  286. package/dist/workflows/v3/portable-final-outputs.d.ts.map +1 -0
  287. package/dist/workflows/v3/portable-final-outputs.js +137 -0
  288. package/dist/workflows/v3/portable-final-outputs.js.map +1 -0
  289. package/dist/workflows/v3/portable-run-snapshot.d.ts +14 -0
  290. package/dist/workflows/v3/portable-run-snapshot.d.ts.map +1 -0
  291. package/dist/workflows/v3/portable-run-snapshot.js +176 -0
  292. package/dist/workflows/v3/portable-run-snapshot.js.map +1 -0
  293. package/dist/workflows/v3/portable-runtime.d.ts +83 -0
  294. package/dist/workflows/v3/portable-runtime.d.ts.map +1 -0
  295. package/dist/workflows/v3/portable-runtime.js +135 -0
  296. package/dist/workflows/v3/portable-runtime.js.map +1 -0
  297. package/dist/workflows/v3/runtime-host-contract.d.ts +182 -0
  298. package/dist/workflows/v3/runtime-host-contract.d.ts.map +1 -0
  299. package/dist/workflows/v3/runtime-host-contract.js +9 -0
  300. package/dist/workflows/v3/runtime-host-contract.js.map +1 -0
  301. package/dist/workflows/v3/runtime.d.ts +12 -226
  302. package/dist/workflows/v3/runtime.d.ts.map +1 -1
  303. package/dist/workflows/v3/runtime.js +14 -3173
  304. package/dist/workflows/v3/runtime.js.map +1 -1
  305. package/dist/workflows/v3/shared-node-runtime.d.ts +203 -0
  306. package/dist/workflows/v3/shared-node-runtime.d.ts.map +1 -0
  307. package/dist/workflows/v3/shared-node-runtime.js +2978 -0
  308. package/dist/workflows/v3/shared-node-runtime.js.map +1 -0
  309. package/dist/workflows/v3/shared-runtime.d.ts +17 -0
  310. package/dist/workflows/v3/shared-runtime.d.ts.map +1 -0
  311. package/dist/workflows/v3/shared-runtime.js +12 -0
  312. package/dist/workflows/v3/shared-runtime.js.map +1 -0
  313. package/package.json +4 -1
  314. package/dist/dashboard-web/chunks/roles-page-LHVAU2BI.js +0 -1
package/dist/worker.js CHANGED
@@ -52,6 +52,7 @@ import { deriveTerminalViewToken, deriveTerminalWriteToken, resolveTerminalAcces
52
52
  import { readPlatformBinding } from './platform/binding.js';
53
53
  import { loadDashboardSecret, loadPersistedToken } from './dashboard/auth.js';
54
54
  import { InflightInputTracker } from './core/inflight-input-tracker.js';
55
+ import { InputTurnDeduper } from './core/input-turn-dedupe.js';
55
56
  import { shouldRunQuietRotation, evaluatePidResolverPullback, decideFingerprintSwitch, shouldHealAbsentBaseline, sessionIdFromJsonlPath, SESSION_ID_FILENAME_RE, } from './services/bridge-rotation-policy.js';
56
57
  import { CodexBridgeQueue } from './services/codex-bridge-queue.js';
57
58
  import { detectCodexComposerState } from './services/codex-composer-state.js';
@@ -1160,7 +1161,7 @@ let closeRequested = false;
1160
1161
  let capturedSpawnCommand = null;
1161
1162
  let deferredTopicOutputTail = '';
1162
1163
  const reportedDeferredTopicRoots = new Set();
1163
- const CLI_DISPLAY_NAMES = { 'claude-code': 'Claude', seed: 'Seed', relay: 'Relay', aiden: 'Aiden', coco: 'CoCo', codex: 'Codex', 'codex-app': 'Codex App', cursor: 'Cursor', gemini: 'Gemini', genius: 'Genius', opencode: 'OpenCode', antigravity: 'Antigravity', mtr: 'MTR', hermes: 'Hermes', mira: 'Mira', mir: 'Mir CLI', traex: 'TRAE', pi: 'Pi', copilot: 'Copilot', 'oh-my-pi': 'Oh My Pi', kimi: 'Kimi', grok: 'Grok Build', 'kiro-cli': 'Kiro', riff: 'Riff' };
1164
+ const CLI_DISPLAY_NAMES = { 'claude-code': 'Claude', seed: 'Seed', relay: 'Relay', aiden: 'Aiden', coco: 'CoCo', codex: 'Codex', 'codex-app': 'Codex App', cursor: 'Cursor', gemini: 'Gemini', genius: 'Genius', opencode: 'OpenCode', antigravity: 'Antigravity', mtr: 'MTR', hermes: 'Hermes', mira: 'Mira', mir: 'Mir CLI', traex: 'TRAE', pi: 'Pi', copilot: 'Copilot', 'oh-my-pi': 'Oh My Pi', kimi: 'Kimi', grok: 'Grok Build', 'kiro-cli': 'Kiro', riff: 'Riff', reasonix: 'Reasonix' };
1164
1165
  function cliName() {
1165
1166
  return (lastInitConfig?.cliRuntime?.source === 'configured'
1166
1167
  ? (lastInitConfig.cliRuntime.displayName?.trim() || lastInitConfig.cliRuntime.id)
@@ -1171,6 +1172,10 @@ function cliName() {
1171
1172
  let isPromptReady = false;
1172
1173
  /** Mutex for async flushPending — prevents concurrent flush loops. */
1173
1174
  let isFlushing = false;
1175
+ /** An init prompt exists but spawn/RPC policy has not yet established whether
1176
+ * it is argv-baked, RPC-owned, or queued. Concurrent follow-ups may enter the
1177
+ * queue during async init, but must not flush ahead of this first turn. */
1178
+ let initialInputOwnershipPending = false;
1174
1179
  /** True from the moment an owned CLI restart begins until the replacement
1175
1180
  * backend has been synchronously installed. Async backends (notably Riff)
1176
1181
  * keep the old backend object alive while destroySession() awaits remote
@@ -1476,6 +1481,13 @@ async function runStartupCommands() {
1476
1481
  }
1477
1482
  const freshnessInputQueue = new CodexRunnerFreshnessInputQueue(() => codexRunnerFreshness, state => { codexRunnerFreshness = state; });
1478
1483
  const pendingMessages = freshnessInputQueue.normal;
1484
+ /** Ordinary Lark IM turns may be retransmitted by the daemon when the exact
1485
+ * receipt ACK times out. Fence those retries before any renderer / adapter side
1486
+ * effects so one Lark message can enter the CLI input queue at most once per
1487
+ * worker generation. Durable receiver attempts already have their own lease
1488
+ * protocol and adopt writes have an ambiguity journal, so this gate stays on
1489
+ * non-adopt `om_` turns without dispatchAttempt. */
1490
+ const ordinaryImTurnDedupe = new InputTurnDeduper(256);
1479
1491
  /** Correlation ids that this worker actually wrote into the owned Codex App
1480
1492
  * runner. Runner lifecycle/final markers may route only to ids in this bounded
1481
1493
  * local set; model/user display bytes cannot add entries. */
@@ -6519,6 +6531,8 @@ async function flushPending() {
6519
6531
  // backend's idle/task-done callback) write across that restart boundary.
6520
6532
  if (cliRestartInProgress)
6521
6533
  return;
6534
+ if (initialInputOwnershipPending)
6535
+ return;
6522
6536
  if (shouldHoldCodexRunnerInput(codexRunnerFreshness))
6523
6537
  return;
6524
6538
  if (isFlushing)
@@ -6923,8 +6937,6 @@ async function flushPending() {
6923
6937
  }
6924
6938
  }
6925
6939
  function sendToPty(content, turnId, opts = {}) {
6926
- if (!cliAdapter)
6927
- return false;
6928
6940
  const next = {
6929
6941
  content,
6930
6942
  turnId,
@@ -6943,6 +6955,8 @@ function sendToPty(content, turnId, opts = {}) {
6943
6955
  log(`Queued message while CLI backend is restarting (${pendingMessages.length} pending)`);
6944
6956
  return true;
6945
6957
  }
6958
+ if (!cliAdapter)
6959
+ return false;
6946
6960
  const supportsTypeAhead = pendingInputAllowsTypeAhead(cliAdapter.supportsTypeAhead === true, durableTurnInFlight, next);
6947
6961
  const shouldMergeQueued = opts.dispatchAttempt === undefined && !durableTurnInFlight
6948
6962
  && !isFlushing && !shouldWriteNow({
@@ -7272,8 +7286,18 @@ function setupAdoptInputAdapter(cfg) {
7272
7286
  cliAdapter = createCliAdapterSync(cfg.cliId, cfg.cliPathOverride);
7273
7287
  }
7274
7288
  }
7289
+ function wireIdleDetectorBusyTransition(detector, label) {
7290
+ detector.onBusy(() => {
7291
+ if (!isPromptReady)
7292
+ return;
7293
+ isPromptReady = false;
7294
+ log(`Explicit busy marker detected — ${label}`);
7295
+ publishScreenStatus('working', { force: true });
7296
+ });
7297
+ }
7275
7298
  function setupAdoptIdleDetection(cfg, label) {
7276
7299
  idleDetector = new IdleDetector(adoptIdleAdapter(cfg));
7300
+ wireIdleDetectorBusyTransition(idleDetector, `${label} adopt mode`);
7277
7301
  idleDetector.onIdle(() => {
7278
7302
  if (backend && deferPromptReadyWhileBusy(`${label} adopt-idle`, backend))
7279
7303
  return;
@@ -9482,11 +9506,12 @@ async function spawnCli(cfg, opts = {}) {
9482
9506
  // `ps -A` ppid links) so the ownership gate can actually admit the id;
9483
9507
  // it fails closed to the launcher pid when no leaf is found yet (the async
9484
9508
  // retry below re-resolves once bwrap has forked traex).
9509
+ // - reasonix: identify the lease owned by this process tree
9485
9510
  // Claude's sessionId is set ONCE at process start (2.1.123); a `--resume`
9486
9511
  // lookup will surface here, but in-pane `/clear` won't. The pinned
9487
9512
  // claudeJsonlPath above is still the initial guess; the resolver corrects
9488
9513
  // it on first write when Claude was started with `--resume`.
9489
- if (cliPid && (claudeDataDir || cfg.cliId === 'grok' || cfg.cliId === 'traex')) {
9514
+ if (cliPid && (claudeDataDir || cfg.cliId === 'grok' || cfg.cliId === 'traex' || cfg.cliId === 'reasonix')) {
9490
9515
  // TRAE under outer bwrap: best-effort immediate resolve (leaf may already be
9491
9516
  // forked), then a bounded retry below covers the not-yet-forked case.
9492
9517
  const wiredPid = cfg.cliId === 'traex' ? resolveTraexOwnershipPid(cliPid, outerBwrapActive) : cliPid;
@@ -9522,7 +9547,7 @@ async function spawnCli(cfg, opts = {}) {
9522
9547
  log(`Failed to write CLI PID marker (async): ${err.message}`);
9523
9548
  }
9524
9549
  }
9525
- if (claudeDataDir || cfg.cliId === 'grok' || cfg.cliId === 'traex') {
9550
+ if (claudeDataDir || cfg.cliId === 'grok' || cfg.cliId === 'traex' || cfg.cliId === 'reasonix') {
9526
9551
  const wiredPid = cfg.cliId === 'traex' ? resolveTraexOwnershipPid(pid, outerBwrapActive) : pid;
9527
9552
  backend.cliPid = wiredPid;
9528
9553
  backend.cliCwd = cfg.workingDir;
@@ -9754,6 +9779,7 @@ async function spawnCli(cfg, opts = {}) {
9754
9779
  // quiescence, repeatedly triggering markPromptReady() and duplicate cards.
9755
9780
  if (effectiveBackendType !== 'riff') {
9756
9781
  idleDetector = new IdleDetector(cliAdapter);
9782
+ wireIdleDetectorBusyTransition(idleDetector, `${cliName()} PTY`);
9757
9783
  idleDetector.onIdle(async (evidenceSource) => {
9758
9784
  log('Prompt detected (idle)');
9759
9785
  // Snapshot-only backends (ZMX) must complete one authoritative refresh
@@ -11527,8 +11553,23 @@ function send(msg) {
11527
11553
  process.send?.(payload);
11528
11554
  }
11529
11555
  function acknowledgeTurnInputCommitted(turnId) {
11556
+ if (!turnId)
11557
+ return;
11558
+ ordinaryImTurnDedupe.commit(turnId);
11559
+ send({ type: 'turn_input_committed', turnId });
11560
+ }
11561
+ function acknowledgeTurnInputReceived(turnId) {
11530
11562
  if (turnId)
11531
- send({ type: 'turn_input_committed', turnId });
11563
+ send({ type: 'turn_input_received', turnId });
11564
+ }
11565
+ function receiveOrdinaryImTurn(turnId) {
11566
+ const state = ordinaryImTurnDedupe.begin(turnId);
11567
+ acknowledgeTurnInputReceived(turnId);
11568
+ return state;
11569
+ }
11570
+ function rejectOrdinaryImTurn(turnId, reason) {
11571
+ ordinaryImTurnDedupe.release(turnId);
11572
+ send({ type: 'turn_input_rejected', turnId, reason });
11532
11573
  }
11533
11574
  function publishLocalProcessAttestation(cliPid) {
11534
11575
  const cliProcStart = cliPid ? readProcessStartIdentity(cliPid) : undefined;
@@ -11618,9 +11659,44 @@ process.on('message', async (raw) => {
11618
11659
  switch (msg.type) {
11619
11660
  case 'init': {
11620
11661
  const initStartedAtMs = Date.now();
11621
- if (lastInitConfig)
11622
- return; // already initialized
11662
+ const ordinaryImTurnId = !msg.adoptMode
11663
+ && msg.dispatchAttempt === undefined
11664
+ && !!msg.prompt
11665
+ && msg.turnId?.startsWith('om_')
11666
+ ? msg.turnId
11667
+ : undefined;
11668
+ if (lastInitConfig) {
11669
+ // Only an exact retry of this generation's init may be acknowledged.
11670
+ // A different init is still rejected as an invalid re-initialization.
11671
+ if (ordinaryImTurnId && lastInitConfig.turnId === ordinaryImTurnId) {
11672
+ const duplicateState = receiveOrdinaryImTurn(ordinaryImTurnId);
11673
+ if (duplicateState === 'committed') {
11674
+ log(`Re-ACKing committed duplicate init turn ${ordinaryImTurnId.substring(0, 16)}`);
11675
+ acknowledgeTurnInputCommitted(ordinaryImTurnId);
11676
+ }
11677
+ else {
11678
+ log(`Re-ACKing received duplicate init turn ${ordinaryImTurnId.substring(0, 16)}`);
11679
+ }
11680
+ }
11681
+ return;
11682
+ }
11683
+ if (ordinaryImTurnId) {
11684
+ const duplicateState = receiveOrdinaryImTurn(ordinaryImTurnId);
11685
+ // Receipt is the daemon ↔ worker transport boundary. Publish it before
11686
+ // startup work can await a slow backend, plugin gateway, or Codex
11687
+ // metadata read. The later committed ACK keeps its existing meaning.
11688
+ if (duplicateState === 'committed') {
11689
+ log(`Re-ACKing committed duplicate init turn ${ordinaryImTurnId.substring(0, 16)}`);
11690
+ acknowledgeTurnInputCommitted(ordinaryImTurnId);
11691
+ break;
11692
+ }
11693
+ if (duplicateState === 'inflight') {
11694
+ log(`Re-ACKing received duplicate init turn ${ordinaryImTurnId.substring(0, 16)}`);
11695
+ break;
11696
+ }
11697
+ }
11623
11698
  lastInitConfig = msg;
11699
+ initialInputOwnershipPending = !!msg.prompt;
11624
11700
  activeRestartAttemptId = msg.restartAttemptId;
11625
11701
  sessionId = msg.sessionId;
11626
11702
  refreshTerminalViewToken();
@@ -11775,7 +11851,10 @@ process.on('message', async (raw) => {
11775
11851
  passesInitialPromptViaArgs: cliAdapter?.passesInitialPromptViaArgs === true,
11776
11852
  deferInitialPrompt,
11777
11853
  })) {
11778
- pendingMessages.push({
11854
+ // Follow-up IPC handlers can run while this async init is awaiting
11855
+ // backend startup. They queue safely behind !backend above, but the
11856
+ // original init prompt must remain first in logical turn order.
11857
+ pendingMessages.unshift({
11779
11858
  content: lastSpawnQueuedInitialPrompt ?? msg.prompt,
11780
11859
  ...(lastSpawnQueuedInitialPromptLogicalContent
11781
11860
  ? { logicalContent: lastSpawnQueuedInitialPromptLogicalContent }
@@ -11792,6 +11871,10 @@ process.on('message', async (raw) => {
11792
11871
  // it into argv or the RPC engine already accepted it.
11793
11872
  initialInputCommitted = true;
11794
11873
  }
11874
+ // The first turn is now either at queue head or already owned by the
11875
+ // argv/RPC startup path. Only now may an early idle edge drain
11876
+ // follow-ups that arrived while init was awaiting slow startup work.
11877
+ initialInputOwnershipPending = false;
11795
11878
  if (initialInputCommitted)
11796
11879
  acknowledgeTurnInputCommitted(msg.turnId);
11797
11880
  // A backend may become prompt-ready before spawnCli() returns. The
@@ -11818,6 +11901,7 @@ process.on('message', async (raw) => {
11818
11901
  });
11819
11902
  }
11820
11903
  catch (err) {
11904
+ initialInputOwnershipPending = false;
11821
11905
  await sendFatalWorkerErrorAndExit(err);
11822
11906
  return;
11823
11907
  }
@@ -11825,6 +11909,25 @@ process.on('message', async (raw) => {
11825
11909
  }
11826
11910
  case 'message': {
11827
11911
  const messageAdoptMode = lastInitConfig?.adoptMode === true;
11912
+ const ordinaryImTurnId = !messageAdoptMode
11913
+ && msg.dispatchAttempt === undefined
11914
+ && msg.turnId?.startsWith('om_')
11915
+ ? msg.turnId
11916
+ : undefined;
11917
+ if (ordinaryImTurnId) {
11918
+ const duplicateState = receiveOrdinaryImTurn(ordinaryImTurnId);
11919
+ // ACK process ownership synchronously, before crash recovery or any
11920
+ // other awaited work. Actual queue ownership remains committed below.
11921
+ if (duplicateState === 'committed') {
11922
+ log(`Re-ACKing committed duplicate IM turn ${ordinaryImTurnId.substring(0, 16)}`);
11923
+ acknowledgeTurnInputCommitted(ordinaryImTurnId);
11924
+ break;
11925
+ }
11926
+ if (duplicateState === 'inflight') {
11927
+ log(`Re-ACKing received duplicate IM turn ${ordinaryImTurnId.substring(0, 16)}`);
11928
+ break;
11929
+ }
11930
+ }
11828
11931
  // Adopt IPC handlers can overlap. Delay their turn baseline until the
11829
11932
  // submission mutex is held so a queued message cannot steal attribution
11830
11933
  // from the write/verification already in flight.
@@ -11872,6 +11975,8 @@ process.on('message', async (raw) => {
11872
11975
  await prepareCodexNativeTitleGeneration(restartCfg, codexRpcEngine);
11873
11976
  }
11874
11977
  catch (err) {
11978
+ if (ordinaryImTurnId)
11979
+ ordinaryImTurnDedupe.release(ordinaryImTurnId);
11875
11980
  // Pass the message's own attempt (not the stale currentBotmux* from a
11876
11981
  // prior IM turn) so a durable delivery relaunch failure carries the
11877
11982
  // right attribution for the daemon's receipt/lease gate.
@@ -12062,6 +12167,8 @@ process.on('message', async (raw) => {
12062
12167
  });
12063
12168
  if (inputCommitted)
12064
12169
  acknowledgeTurnInputCommitted(msg.turnId);
12170
+ else if (ordinaryImTurnId)
12171
+ rejectOrdinaryImTurn(ordinaryImTurnId, 'cli_input_unavailable');
12065
12172
  }
12066
12173
  break;
12067
12174
  }
@@ -12509,6 +12616,13 @@ process.on('message', async (raw) => {
12509
12616
  killCli({ preserveSandbox: true });
12510
12617
  cleanup();
12511
12618
  await flushTransferDetachAck(msg.requestId);
12619
+ // NOTE: process.exit(0) can wedge in node-pty's native teardown when a
12620
+ // web-terminal client PTY was attached (the reader-thread join blocks and
12621
+ // the JS event loop is already stopped, so this process cannot self-kill
12622
+ // via a timer). killCli() above already detached the observer and the ACK
12623
+ // just flushed, so the daemon force-kills this now-disposable process
12624
+ // shortly after the ACK (see detachWorkerForTransfer's post-ACK kill).
12625
+ // We still request a clean exit; the daemon SIGKILL is the hard backstop.
12512
12626
  process.exit(0);
12513
12627
  }
12514
12628
  case 'suspend': {