botmux 3.4.3 → 3.5.2

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 (415) hide show
  1. package/README.en.md +10 -7
  2. package/README.md +11 -6
  3. package/dist/adapters/backend/herdr-backend.d.ts +43 -6
  4. package/dist/adapters/backend/herdr-backend.d.ts.map +1 -1
  5. package/dist/adapters/backend/herdr-backend.js +362 -28
  6. package/dist/adapters/backend/herdr-backend.js.map +1 -1
  7. package/dist/adapters/backend/reproduce-command.d.ts +39 -0
  8. package/dist/adapters/backend/reproduce-command.d.ts.map +1 -0
  9. package/dist/adapters/backend/reproduce-command.js +63 -0
  10. package/dist/adapters/backend/reproduce-command.js.map +1 -0
  11. package/dist/adapters/backend/sandbox.d.ts +99 -279
  12. package/dist/adapters/backend/sandbox.d.ts.map +1 -1
  13. package/dist/adapters/backend/sandbox.js +424 -826
  14. package/dist/adapters/backend/sandbox.js.map +1 -1
  15. package/dist/adapters/backend/session-backend-selector.d.ts +10 -1
  16. package/dist/adapters/backend/session-backend-selector.d.ts.map +1 -1
  17. package/dist/adapters/backend/session-backend-selector.js +73 -4
  18. package/dist/adapters/backend/session-backend-selector.js.map +1 -1
  19. package/dist/adapters/backend/types.d.ts +16 -0
  20. package/dist/adapters/backend/types.d.ts.map +1 -1
  21. package/dist/adapters/backend/types.js.map +1 -1
  22. package/dist/adapters/cli/codex.d.ts.map +1 -1
  23. package/dist/adapters/cli/codex.js +4 -0
  24. package/dist/adapters/cli/codex.js.map +1 -1
  25. package/dist/adapters/cli/fs-policy.d.ts +244 -0
  26. package/dist/adapters/cli/fs-policy.d.ts.map +1 -0
  27. package/dist/adapters/cli/fs-policy.js +539 -0
  28. package/dist/adapters/cli/fs-policy.js.map +1 -0
  29. package/dist/adapters/cli/pi-initial-prompt.d.ts.map +1 -1
  30. package/dist/adapters/cli/pi-initial-prompt.js +5 -1
  31. package/dist/adapters/cli/pi-initial-prompt.js.map +1 -1
  32. package/dist/adapters/cli/read-isolation.d.ts +14 -200
  33. package/dist/adapters/cli/read-isolation.d.ts.map +1 -1
  34. package/dist/adapters/cli/read-isolation.js +18 -477
  35. package/dist/adapters/cli/read-isolation.js.map +1 -1
  36. package/dist/adapters/cli/traex.d.ts.map +1 -1
  37. package/dist/adapters/cli/traex.js +5 -0
  38. package/dist/adapters/cli/traex.js.map +1 -1
  39. package/dist/adapters/cli/types.d.ts +3 -3
  40. package/dist/adapters/cli/types.d.ts.map +1 -1
  41. package/dist/adapters/hook-installer.d.ts +7 -0
  42. package/dist/adapters/hook-installer.d.ts.map +1 -1
  43. package/dist/adapters/hook-installer.js +56 -0
  44. package/dist/adapters/hook-installer.js.map +1 -1
  45. package/dist/bot-registry.d.ts +39 -23
  46. package/dist/bot-registry.d.ts.map +1 -1
  47. package/dist/bot-registry.js +134 -2
  48. package/dist/bot-registry.js.map +1 -1
  49. package/dist/cli/capabilities.d.ts +24 -0
  50. package/dist/cli/capabilities.d.ts.map +1 -0
  51. package/dist/cli/capabilities.js +25 -0
  52. package/dist/cli/capabilities.js.map +1 -0
  53. package/dist/cli/create-group-resolver.d.ts +24 -0
  54. package/dist/cli/create-group-resolver.d.ts.map +1 -1
  55. package/dist/cli/create-group-resolver.js +23 -0
  56. package/dist/cli/create-group-resolver.js.map +1 -1
  57. package/dist/cli/daemon-lifecycle-env.d.ts +5 -7
  58. package/dist/cli/daemon-lifecycle-env.d.ts.map +1 -1
  59. package/dist/cli/daemon-lifecycle-env.js +13 -7
  60. package/dist/cli/daemon-lifecycle-env.js.map +1 -1
  61. package/dist/cli/exact-chat-grant-client.d.ts +48 -0
  62. package/dist/cli/exact-chat-grant-client.d.ts.map +1 -0
  63. package/dist/cli/exact-chat-grant-client.js +108 -0
  64. package/dist/cli/exact-chat-grant-client.js.map +1 -0
  65. package/dist/cli/exact-chat-grant.d.ts +18 -0
  66. package/dist/cli/exact-chat-grant.d.ts.map +1 -0
  67. package/dist/cli/exact-chat-grant.js +97 -0
  68. package/dist/cli/exact-chat-grant.js.map +1 -0
  69. package/dist/cli.d.ts +10 -1
  70. package/dist/cli.d.ts.map +1 -1
  71. package/dist/cli.js +795 -144
  72. package/dist/cli.js.map +1 -1
  73. package/dist/codex-rpc-engine.d.ts +26 -0
  74. package/dist/codex-rpc-engine.d.ts.map +1 -1
  75. package/dist/codex-rpc-engine.js +113 -2
  76. package/dist/codex-rpc-engine.js.map +1 -1
  77. package/dist/config.d.ts +16 -0
  78. package/dist/config.d.ts.map +1 -1
  79. package/dist/config.js +16 -0
  80. package/dist/config.js.map +1 -1
  81. package/dist/core/bot-live-control.d.ts +41 -0
  82. package/dist/core/bot-live-control.d.ts.map +1 -0
  83. package/dist/core/bot-live-control.js +135 -0
  84. package/dist/core/bot-live-control.js.map +1 -0
  85. package/dist/core/command-handler.d.ts.map +1 -1
  86. package/dist/core/command-handler.js +44 -66
  87. package/dist/core/command-handler.js.map +1 -1
  88. package/dist/core/daemon-config-fence.d.ts +8 -0
  89. package/dist/core/daemon-config-fence.d.ts.map +1 -0
  90. package/dist/core/daemon-config-fence.js +13 -0
  91. package/dist/core/daemon-config-fence.js.map +1 -0
  92. package/dist/core/dashboard-events.d.ts +5 -0
  93. package/dist/core/dashboard-events.d.ts.map +1 -1
  94. package/dist/core/dashboard-events.js.map +1 -1
  95. package/dist/core/dashboard-ipc-server.d.ts +21 -2
  96. package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
  97. package/dist/core/dashboard-ipc-server.js +258 -32
  98. package/dist/core/dashboard-ipc-server.js.map +1 -1
  99. package/dist/core/dispatch-registry.d.ts +12 -0
  100. package/dist/core/dispatch-registry.d.ts.map +1 -0
  101. package/dist/core/dispatch-registry.js +33 -0
  102. package/dist/core/dispatch-registry.js.map +1 -0
  103. package/dist/core/dispatch.d.ts +99 -0
  104. package/dist/core/dispatch.d.ts.map +1 -1
  105. package/dist/core/dispatch.js +136 -0
  106. package/dist/core/dispatch.js.map +1 -1
  107. package/dist/core/maintenance.d.ts.map +1 -1
  108. package/dist/core/maintenance.js +10 -3
  109. package/dist/core/maintenance.js.map +1 -1
  110. package/dist/core/passthrough-commands.d.ts.map +1 -1
  111. package/dist/core/passthrough-commands.js +1 -1
  112. package/dist/core/passthrough-commands.js.map +1 -1
  113. package/dist/core/persistent-backend.d.ts +16 -2
  114. package/dist/core/persistent-backend.d.ts.map +1 -1
  115. package/dist/core/persistent-backend.js +40 -0
  116. package/dist/core/persistent-backend.js.map +1 -1
  117. package/dist/core/plugins/mcp/gateway-installer.d.ts.map +1 -1
  118. package/dist/core/plugins/mcp/gateway-installer.js +14 -2
  119. package/dist/core/plugins/mcp/gateway-installer.js.map +1 -1
  120. package/dist/core/session-discovery.d.ts +8 -1
  121. package/dist/core/session-discovery.d.ts.map +1 -1
  122. package/dist/core/session-discovery.js +140 -8
  123. package/dist/core/session-discovery.js.map +1 -1
  124. package/dist/core/session-manager.d.ts.map +1 -1
  125. package/dist/core/session-manager.js +102 -68
  126. package/dist/core/session-manager.js.map +1 -1
  127. package/dist/core/session-title.d.ts +8 -0
  128. package/dist/core/session-title.d.ts.map +1 -1
  129. package/dist/core/session-title.js +54 -0
  130. package/dist/core/session-title.js.map +1 -1
  131. package/dist/core/terminal-write-auth.d.ts +15 -0
  132. package/dist/core/terminal-write-auth.d.ts.map +1 -1
  133. package/dist/core/terminal-write-auth.js +20 -0
  134. package/dist/core/terminal-write-auth.js.map +1 -1
  135. package/dist/core/trigger-session.d.ts.map +1 -1
  136. package/dist/core/trigger-session.js +3 -2
  137. package/dist/core/trigger-session.js.map +1 -1
  138. package/dist/core/types.d.ts +33 -0
  139. package/dist/core/types.d.ts.map +1 -1
  140. package/dist/core/types.js.map +1 -1
  141. package/dist/core/worker-pool.d.ts +51 -8
  142. package/dist/core/worker-pool.d.ts.map +1 -1
  143. package/dist/core/worker-pool.js +439 -25
  144. package/dist/core/worker-pool.js.map +1 -1
  145. package/dist/daemon.d.ts +4 -2
  146. package/dist/daemon.d.ts.map +1 -1
  147. package/dist/daemon.js +403 -26
  148. package/dist/daemon.js.map +1 -1
  149. package/dist/dashboard/bot-onboarding.d.ts +127 -1
  150. package/dist/dashboard/bot-onboarding.d.ts.map +1 -1
  151. package/dist/dashboard/bot-onboarding.js +1104 -25
  152. package/dist/dashboard/bot-onboarding.js.map +1 -1
  153. package/dist/dashboard/bot-payload.d.ts +5 -0
  154. package/dist/dashboard/bot-payload.d.ts.map +1 -1
  155. package/dist/dashboard/bot-payload.js +7 -0
  156. package/dist/dashboard/bot-payload.js.map +1 -1
  157. package/dist/dashboard/debug-terminal.d.ts +18 -0
  158. package/dist/dashboard/debug-terminal.d.ts.map +1 -0
  159. package/dist/dashboard/debug-terminal.js +338 -0
  160. package/dist/dashboard/debug-terminal.js.map +1 -0
  161. package/dist/dashboard/public-redact.d.ts +2 -0
  162. package/dist/dashboard/public-redact.d.ts.map +1 -1
  163. package/dist/dashboard/public-redact.js +12 -3
  164. package/dist/dashboard/public-redact.js.map +1 -1
  165. package/dist/dashboard/registry.d.ts +8 -0
  166. package/dist/dashboard/registry.d.ts.map +1 -1
  167. package/dist/dashboard/registry.js +13 -0
  168. package/dist/dashboard/registry.js.map +1 -1
  169. package/dist/dashboard/settings-write-applier.d.ts +47 -1
  170. package/dist/dashboard/settings-write-applier.d.ts.map +1 -1
  171. package/dist/dashboard/settings-write-applier.js +102 -1
  172. package/dist/dashboard/settings-write-applier.js.map +1 -1
  173. package/dist/dashboard/web/app.d.ts.map +1 -1
  174. package/dist/dashboard/web/app.js +2 -0
  175. package/dist/dashboard/web/app.js.map +1 -1
  176. package/dist/dashboard/web/bot-defaults-page.d.ts +17 -0
  177. package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -1
  178. package/dist/dashboard/web/bot-defaults-page.js +249 -11
  179. package/dist/dashboard/web/bot-defaults-page.js.map +1 -1
  180. package/dist/dashboard/web/bot-defaults.d.ts +22 -0
  181. package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
  182. package/dist/dashboard/web/bot-defaults.js +19 -0
  183. package/dist/dashboard/web/bot-defaults.js.map +1 -1
  184. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  185. package/dist/dashboard/web/i18n.js +114 -28
  186. package/dist/dashboard/web/i18n.js.map +1 -1
  187. package/dist/dashboard/web/icon-tooltip.d.ts +3 -0
  188. package/dist/dashboard/web/icon-tooltip.d.ts.map +1 -0
  189. package/dist/dashboard/web/icon-tooltip.js +108 -0
  190. package/dist/dashboard/web/icon-tooltip.js.map +1 -0
  191. package/dist/dashboard/web/sessions-kanban.js +2 -2
  192. package/dist/dashboard/web/sessions-kanban.js.map +1 -1
  193. package/dist/dashboard/web/sessions-page.d.ts.map +1 -1
  194. package/dist/dashboard/web/sessions-page.js +49 -53
  195. package/dist/dashboard/web/sessions-page.js.map +1 -1
  196. package/dist/dashboard/web/sessions.d.ts +2 -0
  197. package/dist/dashboard/web/sessions.d.ts.map +1 -1
  198. package/dist/dashboard/web/sessions.js +46 -2
  199. package/dist/dashboard/web/sessions.js.map +1 -1
  200. package/dist/dashboard/web/settings-page.d.ts +78 -0
  201. package/dist/dashboard/web/settings-page.d.ts.map +1 -1
  202. package/dist/dashboard/web/settings-page.js +88 -1
  203. package/dist/dashboard/web/settings-page.js.map +1 -1
  204. package/dist/dashboard/web/store.d.ts +2 -0
  205. package/dist/dashboard/web/store.d.ts.map +1 -1
  206. package/dist/dashboard/web/store.js +13 -1
  207. package/dist/dashboard/web/store.js.map +1 -1
  208. package/dist/dashboard-web/app.js +1 -1
  209. package/dist/dashboard-web/chunks/bot-defaults-page-AUKV7P4L.js +10 -0
  210. package/dist/dashboard-web/chunks/{chunk-P6GO5KT4.js → chunk-KPQAUX7V.js} +1 -1
  211. package/dist/dashboard-web/chunks/{chunk-UBOLHQCK.js → chunk-NRL6CVAS.js} +1 -1
  212. package/dist/dashboard-web/chunks/{chunk-JNRSPKLS.js → chunk-R7IAKAYX.js} +1 -1
  213. package/dist/dashboard-web/chunks/{chunk-CUV65BIQ.js → chunk-X2L65IOM.js} +8 -8
  214. package/dist/dashboard-web/chunks/{connectors-page-KTC2QWNW.js → connectors-page-HDQFEXZI.js} +1 -1
  215. package/dist/dashboard-web/chunks/{groups-page-B3EKGOLY.js → groups-page-6DKXBYOM.js} +1 -1
  216. package/dist/dashboard-web/chunks/{insights-page-X6RXNCWX.js → insights-page-NWARTJ6J.js} +1 -1
  217. package/dist/dashboard-web/chunks/{monitor-room-LLRA5LQW.js → monitor-room-AGX3XRJX.js} +1 -1
  218. package/dist/dashboard-web/chunks/{monitoring-page-7MT5FEOS.js → monitoring-page-GGGIWN4C.js} +1 -1
  219. package/dist/dashboard-web/chunks/{office-page-KD46D5TD.js → office-page-6SIVKSK3.js} +1 -1
  220. package/dist/dashboard-web/chunks/{overview-page-JUWNH32O.js → overview-page-FVR3NKAF.js} +1 -1
  221. package/dist/dashboard-web/chunks/{roles-page-P6F7NLOI.js → roles-page-WE2YB7KN.js} +1 -1
  222. package/dist/dashboard-web/chunks/{schedules-page-XIHWZST4.js → schedules-page-TB3I24XN.js} +1 -1
  223. package/dist/dashboard-web/chunks/sessions-page-KOOOASIL.js +2 -0
  224. package/dist/dashboard-web/chunks/settings-page-IEBR7TGN.js +2 -0
  225. package/dist/dashboard-web/chunks/{skills-page-A46KVWBL.js → skills-page-3QAT2IWD.js} +1 -1
  226. package/dist/dashboard-web/chunks/{team-federation-page-SDUC56DF.js → team-federation-page-K4VVAVAK.js} +1 -1
  227. package/dist/dashboard-web/chunks/{v3-page-J5JOTUSQ.js → v3-page-V6IOJR2B.js} +1 -1
  228. package/dist/dashboard-web/chunks/{whiteboards-page-U7LSOAWI.js → whiteboards-page-V6CGKRNX.js} +1 -1
  229. package/dist/dashboard-web/style.css +218 -10
  230. package/dist/dashboard.js +380 -8
  231. package/dist/dashboard.js.map +1 -1
  232. package/dist/features/codex-notifier/adoption.d.ts +11 -0
  233. package/dist/features/codex-notifier/adoption.d.ts.map +1 -0
  234. package/dist/features/codex-notifier/adoption.js +11 -0
  235. package/dist/features/codex-notifier/adoption.js.map +1 -0
  236. package/dist/features/codex-notifier/app-opener.d.ts +21 -0
  237. package/dist/features/codex-notifier/app-opener.d.ts.map +1 -0
  238. package/dist/features/codex-notifier/app-opener.js +33 -0
  239. package/dist/features/codex-notifier/app-opener.js.map +1 -0
  240. package/dist/features/codex-notifier/card-action.d.ts +27 -0
  241. package/dist/features/codex-notifier/card-action.d.ts.map +1 -0
  242. package/dist/features/codex-notifier/card-action.js +84 -0
  243. package/dist/features/codex-notifier/card-action.js.map +1 -0
  244. package/dist/features/codex-notifier/card.d.ts +12 -0
  245. package/dist/features/codex-notifier/card.d.ts.map +1 -0
  246. package/dist/features/codex-notifier/card.js +150 -0
  247. package/dist/features/codex-notifier/card.js.map +1 -0
  248. package/dist/features/codex-notifier/codex-context.d.ts +12 -0
  249. package/dist/features/codex-notifier/codex-context.d.ts.map +1 -0
  250. package/dist/features/codex-notifier/codex-context.js +161 -0
  251. package/dist/features/codex-notifier/codex-context.js.map +1 -0
  252. package/dist/features/codex-notifier/config.d.ts +9 -0
  253. package/dist/features/codex-notifier/config.d.ts.map +1 -0
  254. package/dist/features/codex-notifier/config.js +11 -0
  255. package/dist/features/codex-notifier/config.js.map +1 -0
  256. package/dist/features/codex-notifier/confirmed-turn.d.ts +20 -0
  257. package/dist/features/codex-notifier/confirmed-turn.d.ts.map +1 -0
  258. package/dist/features/codex-notifier/confirmed-turn.js +130 -0
  259. package/dist/features/codex-notifier/confirmed-turn.js.map +1 -0
  260. package/dist/features/codex-notifier/emitter.d.ts +13 -0
  261. package/dist/features/codex-notifier/emitter.d.ts.map +1 -0
  262. package/dist/features/codex-notifier/emitter.js +33 -0
  263. package/dist/features/codex-notifier/emitter.js.map +1 -0
  264. package/dist/features/codex-notifier/event-store.d.ts +29 -0
  265. package/dist/features/codex-notifier/event-store.d.ts.map +1 -0
  266. package/dist/features/codex-notifier/event-store.js +217 -0
  267. package/dist/features/codex-notifier/event-store.js.map +1 -0
  268. package/dist/features/codex-notifier/event.d.ts +46 -0
  269. package/dist/features/codex-notifier/event.d.ts.map +1 -0
  270. package/dist/features/codex-notifier/event.js +188 -0
  271. package/dist/features/codex-notifier/event.js.map +1 -0
  272. package/dist/features/codex-notifier/hook-cli.d.ts +23 -0
  273. package/dist/features/codex-notifier/hook-cli.d.ts.map +1 -0
  274. package/dist/features/codex-notifier/hook-cli.js +130 -0
  275. package/dist/features/codex-notifier/hook-cli.js.map +1 -0
  276. package/dist/features/codex-notifier/hook-installer.d.ts +19 -0
  277. package/dist/features/codex-notifier/hook-installer.d.ts.map +1 -0
  278. package/dist/features/codex-notifier/hook-installer.js +158 -0
  279. package/dist/features/codex-notifier/hook-installer.js.map +1 -0
  280. package/dist/features/codex-notifier/index.d.ts +21 -0
  281. package/dist/features/codex-notifier/index.d.ts.map +1 -0
  282. package/dist/features/codex-notifier/index.js +19 -0
  283. package/dist/features/codex-notifier/index.js.map +1 -0
  284. package/dist/features/codex-notifier/internal-turn.d.ts +5 -0
  285. package/dist/features/codex-notifier/internal-turn.d.ts.map +1 -0
  286. package/dist/features/codex-notifier/internal-turn.js +43 -0
  287. package/dist/features/codex-notifier/internal-turn.js.map +1 -0
  288. package/dist/features/codex-notifier/outbox-worker.d.ts +71 -0
  289. package/dist/features/codex-notifier/outbox-worker.d.ts.map +1 -0
  290. package/dist/features/codex-notifier/outbox-worker.js +290 -0
  291. package/dist/features/codex-notifier/outbox-worker.js.map +1 -0
  292. package/dist/features/codex-notifier/outbox.d.ts +25 -0
  293. package/dist/features/codex-notifier/outbox.d.ts.map +1 -0
  294. package/dist/features/codex-notifier/outbox.js +225 -0
  295. package/dist/features/codex-notifier/outbox.js.map +1 -0
  296. package/dist/features/codex-notifier/paths.d.ts +7 -0
  297. package/dist/features/codex-notifier/paths.d.ts.map +1 -0
  298. package/dist/features/codex-notifier/paths.js +20 -0
  299. package/dist/features/codex-notifier/paths.js.map +1 -0
  300. package/dist/features/codex-notifier/screen-lock.d.ts +12 -0
  301. package/dist/features/codex-notifier/screen-lock.d.ts.map +1 -0
  302. package/dist/features/codex-notifier/screen-lock.js +47 -0
  303. package/dist/features/codex-notifier/screen-lock.js.map +1 -0
  304. package/dist/features/codex-notifier/side-conversation-monitor.d.ts +102 -0
  305. package/dist/features/codex-notifier/side-conversation-monitor.d.ts.map +1 -0
  306. package/dist/features/codex-notifier/side-conversation-monitor.js +774 -0
  307. package/dist/features/codex-notifier/side-conversation-monitor.js.map +1 -0
  308. package/dist/features/codex-notifier/types.d.ts +42 -0
  309. package/dist/features/codex-notifier/types.d.ts.map +1 -0
  310. package/dist/features/codex-notifier/types.js +2 -0
  311. package/dist/features/codex-notifier/types.js.map +1 -0
  312. package/dist/features/codex-notifier/worker-lock.d.ts +8 -0
  313. package/dist/features/codex-notifier/worker-lock.d.ts.map +1 -0
  314. package/dist/features/codex-notifier/worker-lock.js +108 -0
  315. package/dist/features/codex-notifier/worker-lock.js.map +1 -0
  316. package/dist/global-config.d.ts +13 -0
  317. package/dist/global-config.d.ts.map +1 -1
  318. package/dist/global-config.js +34 -1
  319. package/dist/global-config.js.map +1 -1
  320. package/dist/i18n/en.d.ts.map +1 -1
  321. package/dist/i18n/en.js +1 -19
  322. package/dist/i18n/en.js.map +1 -1
  323. package/dist/i18n/zh.d.ts.map +1 -1
  324. package/dist/i18n/zh.js +1 -19
  325. package/dist/i18n/zh.js.map +1 -1
  326. package/dist/im/lark/card-builder.d.ts +0 -13
  327. package/dist/im/lark/card-builder.d.ts.map +1 -1
  328. package/dist/im/lark/card-builder.js +2 -36
  329. package/dist/im/lark/card-builder.js.map +1 -1
  330. package/dist/im/lark/card-handler.d.ts +2 -0
  331. package/dist/im/lark/card-handler.d.ts.map +1 -1
  332. package/dist/im/lark/card-handler.js +166 -64
  333. package/dist/im/lark/card-handler.js.map +1 -1
  334. package/dist/im/lark/client.d.ts +98 -4
  335. package/dist/im/lark/client.d.ts.map +1 -1
  336. package/dist/im/lark/client.js +317 -29
  337. package/dist/im/lark/client.js.map +1 -1
  338. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  339. package/dist/im/lark/event-dispatcher.js +48 -33
  340. package/dist/im/lark/event-dispatcher.js.map +1 -1
  341. package/dist/services/codex-app-threads.d.ts +47 -0
  342. package/dist/services/codex-app-threads.d.ts.map +1 -1
  343. package/dist/services/codex-app-threads.js +502 -10
  344. package/dist/services/codex-app-threads.js.map +1 -1
  345. package/dist/services/exact-chat-grant.d.ts +83 -0
  346. package/dist/services/exact-chat-grant.d.ts.map +1 -0
  347. package/dist/services/exact-chat-grant.js +249 -0
  348. package/dist/services/exact-chat-grant.js.map +1 -0
  349. package/dist/services/group-creator.d.ts +11 -0
  350. package/dist/services/group-creator.d.ts.map +1 -1
  351. package/dist/services/group-creator.js +18 -9
  352. package/dist/services/group-creator.js.map +1 -1
  353. package/dist/services/local-cli-opener.d.ts.map +1 -1
  354. package/dist/services/local-cli-opener.js +10 -5
  355. package/dist/services/local-cli-opener.js.map +1 -1
  356. package/dist/services/sandbox-migration.d.ts +14 -0
  357. package/dist/services/sandbox-migration.d.ts.map +1 -0
  358. package/dist/services/sandbox-migration.js +85 -0
  359. package/dist/services/sandbox-migration.js.map +1 -0
  360. package/dist/services/sandbox-store.d.ts +28 -0
  361. package/dist/services/sandbox-store.d.ts.map +1 -1
  362. package/dist/services/sandbox-store.js +82 -0
  363. package/dist/services/sandbox-store.js.map +1 -1
  364. package/dist/services/traex-user-input.d.ts +19 -0
  365. package/dist/services/traex-user-input.d.ts.map +1 -0
  366. package/dist/services/traex-user-input.js +57 -0
  367. package/dist/services/traex-user-input.js.map +1 -0
  368. package/dist/setup/open-platform-automation.d.ts +24 -3
  369. package/dist/setup/open-platform-automation.d.ts.map +1 -1
  370. package/dist/setup/open-platform-automation.js +45 -8
  371. package/dist/setup/open-platform-automation.js.map +1 -1
  372. package/dist/setup/verify-permissions.d.ts +18 -0
  373. package/dist/setup/verify-permissions.d.ts.map +1 -1
  374. package/dist/setup/verify-permissions.js +60 -0
  375. package/dist/setup/verify-permissions.js.map +1 -1
  376. package/dist/types.d.ts +83 -5
  377. package/dist/types.d.ts.map +1 -1
  378. package/dist/utils/child-env.d.ts +2 -2
  379. package/dist/utils/child-env.d.ts.map +1 -1
  380. package/dist/utils/child-env.js +14 -0
  381. package/dist/utils/child-env.js.map +1 -1
  382. package/dist/utils/stuck-detector.d.ts +45 -0
  383. package/dist/utils/stuck-detector.d.ts.map +1 -0
  384. package/dist/utils/stuck-detector.js +188 -0
  385. package/dist/utils/stuck-detector.js.map +1 -0
  386. package/dist/utils/stuck-key-guard.d.ts +75 -0
  387. package/dist/utils/stuck-key-guard.d.ts.map +1 -0
  388. package/dist/utils/stuck-key-guard.js +77 -0
  389. package/dist/utils/stuck-key-guard.js.map +1 -0
  390. package/dist/worker.js +1119 -588
  391. package/dist/worker.js.map +1 -1
  392. package/dist/workflows/events/payloads.d.ts +56 -0
  393. package/dist/workflows/events/payloads.d.ts.map +1 -1
  394. package/dist/workflows/events/payloads.js +9 -0
  395. package/dist/workflows/events/payloads.js.map +1 -1
  396. package/dist/workflows/events/schema.d.ts +86 -0
  397. package/dist/workflows/events/schema.d.ts.map +1 -1
  398. package/dist/workflows/shared/sandbox-policy.d.ts +10 -1
  399. package/dist/workflows/shared/sandbox-policy.d.ts.map +1 -1
  400. package/dist/workflows/shared/sandbox-policy.js +12 -0
  401. package/dist/workflows/shared/sandbox-policy.js.map +1 -1
  402. package/dist/workflows/v3/bot-resolve.d.ts.map +1 -1
  403. package/dist/workflows/v3/bot-resolve.js +36 -0
  404. package/dist/workflows/v3/bot-resolve.js.map +1 -1
  405. package/dist/workflows/v3/contract.d.ts +8 -0
  406. package/dist/workflows/v3/contract.d.ts.map +1 -1
  407. package/dist/workflows/v3/contract.js.map +1 -1
  408. package/package.json +1 -1
  409. package/dist/dashboard-web/chunks/bot-defaults-page-B5AY4B2J.js +0 -5
  410. package/dist/dashboard-web/chunks/sessions-page-2VECQ27T.js +0 -3
  411. package/dist/dashboard-web/chunks/settings-page-HMIUE2JA.js +0 -2
  412. package/dist/services/sandbox-land.d.ts +0 -45
  413. package/dist/services/sandbox-land.d.ts.map +0 -1
  414. package/dist/services/sandbox-land.js +0 -394
  415. package/dist/services/sandbox-land.js.map +0 -1
@@ -0,0 +1,774 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { existsSync, readdirSync, statSync, } from 'node:fs';
3
+ import { createConnection } from 'node:net';
4
+ import { homedir } from 'node:os';
5
+ import { join } from 'node:path';
6
+ import { createCodexNotifierCompletionEvent } from './event.js';
7
+ import { resolveCodexNotifierConfig } from './config.js';
8
+ import { enqueueCodexNotifierEvent } from './outbox.js';
9
+ import { detectScreenLock, shouldNotifyForLockState, } from './screen-lock.js';
10
+ const THREAD_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
11
+ const IPC_MAX_FRAME_BYTES = 16 * 1024 * 1024;
12
+ const MAX_TRACKED_STATE_BYTES = 32 * 1024 * 1024;
13
+ const IPC_RETRY_MS = 1_000;
14
+ const SCAN_INTERVAL_MS = 500;
15
+ const IPC_CONNECT_TIMEOUT_MS = 5_000;
16
+ const IPC_INITIALIZE_TIMEOUT_MS = 5_000;
17
+ const MAX_RECENT_THREAD_IDS = 64;
18
+ const MAX_TRACKED_CONVERSATIONS = 128;
19
+ const MAX_PENDING_SIDE_EVENTS = 256;
20
+ const MAX_PENDING_SIDE_BYTES = 2 * 1024 * 1024;
21
+ const THREAD_STREAM_FOLLOWING_VERSION = 1;
22
+ const MIN_DATE_MS = -8_640_000_000_000_000;
23
+ const MAX_DATE_MS = 8_640_000_000_000_000;
24
+ function plainObject(value) {
25
+ return !!value && typeof value === 'object' && !Array.isArray(value);
26
+ }
27
+ function forbiddenPatchSegment(value) {
28
+ return typeof value === 'string'
29
+ && (value === '__proto__' || value === 'prototype' || value === 'constructor');
30
+ }
31
+ /** 应用 Codex Desktop 发出的 Immer 风格 JSON Patch。 */
32
+ export function applyCodexConversationPatches(state, patches) {
33
+ if (patches.length > 20_000)
34
+ throw new Error('codex_side_chat_patch_count_exceeded');
35
+ let root = state;
36
+ for (const patch of patches) {
37
+ if ((patch.op !== 'add' && patch.op !== 'replace' && patch.op !== 'remove')
38
+ || !Array.isArray(patch.path)
39
+ || patch.path.length > 64
40
+ || patch.path.some(forbiddenPatchSegment)) {
41
+ throw new Error('codex_side_chat_patch_path_invalid');
42
+ }
43
+ if (patch.path.length === 0) {
44
+ if (patch.op === 'remove' || !plainObject(patch.value)) {
45
+ throw new Error('codex_side_chat_root_patch_invalid');
46
+ }
47
+ root = patch.value;
48
+ continue;
49
+ }
50
+ let parent = root;
51
+ for (const segment of patch.path.slice(0, -1)) {
52
+ if (!parent || typeof parent !== 'object') {
53
+ throw new Error('codex_side_chat_patch_parent_invalid');
54
+ }
55
+ parent = parent[segment];
56
+ }
57
+ if (!parent || typeof parent !== 'object') {
58
+ throw new Error('codex_side_chat_patch_parent_invalid');
59
+ }
60
+ const key = patch.path.at(-1);
61
+ if (Array.isArray(parent)) {
62
+ const index = key === '-' ? parent.length : Number(key);
63
+ if (!Number.isSafeInteger(index) || index < 0 || index > parent.length) {
64
+ throw new Error('codex_side_chat_patch_index_invalid');
65
+ }
66
+ if (patch.op === 'add')
67
+ parent.splice(index, 0, patch.value);
68
+ else if (patch.op === 'replace' && index < parent.length)
69
+ parent[index] = patch.value;
70
+ else if (patch.op === 'remove' && index < parent.length)
71
+ parent.splice(index, 1);
72
+ else
73
+ throw new Error('codex_side_chat_patch_index_invalid');
74
+ continue;
75
+ }
76
+ if (typeof key !== 'string')
77
+ throw new Error('codex_side_chat_patch_key_invalid');
78
+ if (patch.op === 'remove')
79
+ delete parent[key];
80
+ else
81
+ parent[key] = patch.value;
82
+ }
83
+ if (!plainObject(root))
84
+ throw new Error('codex_side_chat_state_invalid');
85
+ return root;
86
+ }
87
+ function turnEntities(state) {
88
+ const entities = state.turnHistory?.history?.entitiesByKey;
89
+ if (!plainObject(entities))
90
+ return [];
91
+ return Object.values(entities).filter(plainObject);
92
+ }
93
+ function terminalStatus(value) {
94
+ if (value === 'completed')
95
+ return 'completed';
96
+ if (value === 'failed')
97
+ return 'failed';
98
+ if (value === 'interrupted' || value === 'cancelled')
99
+ return 'cancelled';
100
+ return undefined;
101
+ }
102
+ function turnStatusById(state) {
103
+ const result = new Map();
104
+ for (const turn of turnEntities(state)) {
105
+ if (typeof turn.turnId === 'string' && turn.turnId)
106
+ result.set(turn.turnId, turn.status);
107
+ }
108
+ return result;
109
+ }
110
+ function turnPrompt(turn) {
111
+ const input = turn.params?.input;
112
+ if (Array.isArray(input)) {
113
+ const text = input
114
+ .filter(item => plainObject(item) && item.type === 'text' && typeof item.text === 'string')
115
+ .map(item => item.text.trim())
116
+ .filter(Boolean)
117
+ .join('\n\n');
118
+ if (text)
119
+ return text;
120
+ }
121
+ for (const item of Array.isArray(turn.items) ? turn.items : []) {
122
+ if (!plainObject(item) || item.type !== 'userMessage' || !Array.isArray(item.content))
123
+ continue;
124
+ const text = item.content
125
+ .filter(part => plainObject(part) && part.type === 'text' && typeof part.text === 'string')
126
+ .map(part => part.text.trim())
127
+ .filter(Boolean)
128
+ .join('\n\n');
129
+ if (text)
130
+ return text;
131
+ }
132
+ return undefined;
133
+ }
134
+ function turnFinalPreview(turn) {
135
+ const items = Array.isArray(turn.items) ? turn.items : [];
136
+ for (let index = items.length - 1; index >= 0; index -= 1) {
137
+ const item = items[index];
138
+ if (plainObject(item)
139
+ && item.type === 'agentMessage'
140
+ && typeof item.text === 'string'
141
+ && item.text.trim()) {
142
+ return item.text;
143
+ }
144
+ }
145
+ return undefined;
146
+ }
147
+ function validDateMs(value) {
148
+ const number = Number(value);
149
+ return Number.isFinite(number) && number >= MIN_DATE_MS && number <= MAX_DATE_MS
150
+ ? number
151
+ : undefined;
152
+ }
153
+ function turnCompletionMs(turn) {
154
+ const startedAt = Number(turn.turnStartedAtMs);
155
+ const duration = Number(turn.durationMs);
156
+ const completedAt = Number.isFinite(startedAt) && Number.isFinite(duration)
157
+ ? startedAt + duration
158
+ : Number.NaN;
159
+ return validDateMs(completedAt);
160
+ }
161
+ function observedCompletionMs(state, turn) {
162
+ return turnCompletionMs(turn) ?? validDateMs(state.updatedAt);
163
+ }
164
+ function completedAt(state, turn, now) {
165
+ const value = observedCompletionMs(state, turn)
166
+ ?? validDateMs(now)
167
+ ?? validDateMs(Date.now())
168
+ ?? 0;
169
+ return new Date(value).toISOString();
170
+ }
171
+ /** 从 Side Chat 内存态提取跨进程完成事件;结构不完整时 fail closed。 */
172
+ export function createSideConversationCompletionEvent(state, turn, now = Date.now()) {
173
+ if (state.sideConversation !== true || state.ephemeral !== true)
174
+ return undefined;
175
+ const status = terminalStatus(turn.status);
176
+ if (!status
177
+ || typeof state.id !== 'string'
178
+ || !THREAD_ID_PATTERN.test(state.id)
179
+ || typeof turn.turnId !== 'string'
180
+ || !turn.turnId) {
181
+ return undefined;
182
+ }
183
+ const cwd = typeof turn.params?.cwd === 'string' && turn.params.cwd.trim()
184
+ ? turn.params.cwd
185
+ : typeof state.cwd === 'string' && state.cwd.trim()
186
+ ? state.cwd
187
+ : undefined;
188
+ if (!cwd)
189
+ return undefined;
190
+ try {
191
+ return createCodexNotifierCompletionEvent({
192
+ threadId: state.id,
193
+ nativeTurnId: turn.turnId,
194
+ status,
195
+ cwd,
196
+ clientSurface: 'codex-app',
197
+ conversationKind: 'side',
198
+ title: turnPrompt(turn) ?? (typeof state.title === 'string' ? state.title : undefined),
199
+ finalPreview: turnFinalPreview(turn),
200
+ completedAt: completedAt(state, turn, now),
201
+ });
202
+ }
203
+ catch {
204
+ return undefined;
205
+ }
206
+ }
207
+ function transitionedEvents(previous, state, now) {
208
+ if (state.sideConversation !== true || state.ephemeral !== true)
209
+ return [];
210
+ const events = [];
211
+ for (const turn of turnEntities(state)) {
212
+ if (typeof turn.turnId !== 'string'
213
+ || previous.get(turn.turnId) !== 'inProgress'
214
+ || !terminalStatus(turn.status)) {
215
+ continue;
216
+ }
217
+ const event = createSideConversationCompletionEvent(state, turn, now);
218
+ if (event)
219
+ events.push(event);
220
+ }
221
+ return events;
222
+ }
223
+ function latestTerminalEvent(state, now, terminalNotBeforeMs) {
224
+ const turns = turnEntities(state)
225
+ .filter(turn => terminalStatus(turn.status))
226
+ .sort((left, right) => Number(left.turnStartedAtMs ?? 0) - Number(right.turnStartedAtMs ?? 0));
227
+ const latest = turns.at(-1);
228
+ if (latest
229
+ && terminalNotBeforeMs !== undefined
230
+ && (turnCompletionMs(latest) ?? Number.NEGATIVE_INFINITY) < terminalNotBeforeMs) {
231
+ return undefined;
232
+ }
233
+ return latest ? createSideConversationCompletionEvent(state, latest, now) : undefined;
234
+ }
235
+ /**
236
+ * 维护 IPC snapshot + patch revision,并且只把 inProgress → 终态识别为新完成。
237
+ * 首个 snapshot 默认只建立基线,避免 Dashboard 启动时补发历史 Side Chat。
238
+ */
239
+ export class CodexSideConversationTracker {
240
+ maxConversations;
241
+ maxStateBytes;
242
+ conversations = new Map();
243
+ totalStateBytes = 0;
244
+ constructor(maxConversations = MAX_TRACKED_CONVERSATIONS, maxStateBytes = MAX_TRACKED_STATE_BYTES) {
245
+ this.maxConversations = maxConversations;
246
+ this.maxStateBytes = maxStateBytes;
247
+ if (!Number.isSafeInteger(maxConversations) || maxConversations <= 0) {
248
+ throw new Error('codex_side_chat_tracker_limit_invalid');
249
+ }
250
+ if (!Number.isSafeInteger(maxStateBytes) || maxStateBytes <= 0) {
251
+ throw new Error('codex_side_chat_tracker_bytes_invalid');
252
+ }
253
+ }
254
+ has(conversationId) {
255
+ return this.conversations.has(conversationId);
256
+ }
257
+ clear() {
258
+ this.conversations.clear();
259
+ this.totalStateBytes = 0;
260
+ }
261
+ delete(conversationId) {
262
+ const tracked = this.conversations.get(conversationId);
263
+ if (!tracked)
264
+ return;
265
+ this.totalStateBytes -= tracked.bytes;
266
+ this.conversations.delete(conversationId);
267
+ }
268
+ save(conversationId, tracked) {
269
+ let bytes;
270
+ try {
271
+ bytes = Buffer.byteLength(JSON.stringify(tracked.state), 'utf8');
272
+ }
273
+ catch {
274
+ this.delete(conversationId);
275
+ return;
276
+ }
277
+ this.delete(conversationId);
278
+ if (bytes > this.maxStateBytes)
279
+ return;
280
+ this.conversations.set(conversationId, { ...tracked, bytes });
281
+ this.totalStateBytes += bytes;
282
+ while (this.conversations.size > this.maxConversations
283
+ || this.totalStateBytes > this.maxStateBytes) {
284
+ const oldest = this.conversations.keys().next().value;
285
+ if (!oldest)
286
+ break;
287
+ this.delete(oldest);
288
+ }
289
+ }
290
+ observeSnapshot(conversationId, revision, state, options = {}) {
291
+ if (!plainObject(state) || state.id !== conversationId || !Number.isSafeInteger(revision)) {
292
+ return { events: [], needsSnapshot: true };
293
+ }
294
+ if (state.sideConversation !== true || state.ephemeral !== true) {
295
+ this.delete(conversationId);
296
+ return { events: [], needsSnapshot: false };
297
+ }
298
+ const previous = this.conversations.get(conversationId);
299
+ const events = previous
300
+ ? transitionedEvents(turnStatusById(previous.state), state, options.now ?? Date.now())
301
+ : options.notifyTerminalOnFirstSnapshot
302
+ ? [latestTerminalEvent(state, options.now ?? Date.now(), options.terminalNotBeforeMs)].filter((event) => !!event)
303
+ : [];
304
+ this.save(conversationId, { revision, state });
305
+ return { events, needsSnapshot: false };
306
+ }
307
+ observePatches(conversationId, baseRevision, revision, patches, now = Date.now()) {
308
+ const tracked = this.conversations.get(conversationId);
309
+ if (!tracked
310
+ || tracked.revision !== baseRevision
311
+ || !Number.isSafeInteger(revision)
312
+ || !Array.isArray(patches)) {
313
+ return { events: [], needsSnapshot: true };
314
+ }
315
+ const previous = turnStatusById(tracked.state);
316
+ try {
317
+ const state = applyCodexConversationPatches(structuredClone(tracked.state), patches);
318
+ this.save(conversationId, { state, revision });
319
+ return {
320
+ events: transitionedEvents(previous, state, now),
321
+ needsSnapshot: false,
322
+ };
323
+ }
324
+ catch {
325
+ return { events: [], needsSnapshot: true };
326
+ }
327
+ }
328
+ }
329
+ function localDatePath(root, date) {
330
+ return join(root, String(date.getFullYear()).padStart(4, '0'), String(date.getMonth() + 1).padStart(2, '0'), String(date.getDate()).padStart(2, '0'));
331
+ }
332
+ /** 视觉产物目录由 Codex 为每个本地线程预创建,可用于发现不落 rollout 的 Side Chat。 */
333
+ export function listRecentCodexVisualizationThreads(codexHome, now = Date.now(), limit = MAX_RECENT_THREAD_IDS) {
334
+ const root = join(codexHome, 'visualizations');
335
+ const datePaths = new Set([
336
+ localDatePath(root, new Date(now)),
337
+ localDatePath(root, new Date(now - 24 * 60 * 60_000)),
338
+ ]);
339
+ const result = [];
340
+ for (const path of datePaths) {
341
+ if (!existsSync(path))
342
+ continue;
343
+ let entries;
344
+ try {
345
+ entries = readdirSync(path, { withFileTypes: true });
346
+ }
347
+ catch {
348
+ continue;
349
+ }
350
+ for (const entry of entries) {
351
+ if (!entry.isDirectory() || !THREAD_ID_PATTERN.test(entry.name))
352
+ continue;
353
+ try {
354
+ result.push({ id: entry.name, mtimeMs: statSync(join(path, entry.name)).mtimeMs });
355
+ }
356
+ catch {
357
+ // 目录可能在扫描期间被 Codex 清理。
358
+ }
359
+ }
360
+ }
361
+ return result
362
+ .sort((left, right) => right.mtimeMs - left.mtimeMs || left.id.localeCompare(right.id))
363
+ .slice(0, Math.max(0, limit));
364
+ }
365
+ function delay(ms, signal) {
366
+ return new Promise(resolve => {
367
+ if (signal?.aborted)
368
+ return resolve();
369
+ const finish = () => {
370
+ clearTimeout(timer);
371
+ signal?.removeEventListener('abort', finish);
372
+ resolve();
373
+ };
374
+ const timer = setTimeout(finish, ms);
375
+ signal?.addEventListener('abort', finish, { once: true });
376
+ });
377
+ }
378
+ function encodeIpcFrame(message) {
379
+ const payload = Buffer.from(JSON.stringify(message));
380
+ const header = Buffer.allocUnsafe(4);
381
+ header.writeUInt32LE(payload.length);
382
+ return Buffer.concat([header, payload]);
383
+ }
384
+ /** 监听 Codex Desktop 内部线程流,补齐原生 Hook 不覆盖的 Side Chat。 */
385
+ export class CodexSideConversationMonitor {
386
+ options;
387
+ platform;
388
+ codexHome;
389
+ socketPath;
390
+ now;
391
+ scanIntervalMs;
392
+ retryMs;
393
+ connectTimeoutMs;
394
+ initializeTimeoutMs;
395
+ maxPendingEvents;
396
+ maxPendingBytes;
397
+ logger;
398
+ readConfig;
399
+ detectLockState;
400
+ enqueue;
401
+ listThreads;
402
+ connect;
403
+ tracker = new CodexSideConversationTracker();
404
+ candidates = new Map();
405
+ pending = new Map();
406
+ pendingBytes = 0;
407
+ observationStartedAt;
408
+ constructor(options) {
409
+ this.options = options;
410
+ this.platform = options.platform ?? process.platform;
411
+ const env = options.env ?? process.env;
412
+ const userHome = options.userHome ?? homedir();
413
+ this.codexHome = typeof env.CODEX_HOME === 'string' && env.CODEX_HOME.trim()
414
+ ? env.CODEX_HOME.trim()
415
+ : join(userHome, '.codex');
416
+ this.socketPath = join(this.codexHome, 'ipc', 'ipc.sock');
417
+ this.now = options.now ?? Date.now;
418
+ this.scanIntervalMs = options.scanIntervalMs ?? SCAN_INTERVAL_MS;
419
+ this.retryMs = options.retryMs ?? IPC_RETRY_MS;
420
+ this.connectTimeoutMs = options.connectTimeoutMs ?? IPC_CONNECT_TIMEOUT_MS;
421
+ this.initializeTimeoutMs = options.initializeTimeoutMs ?? IPC_INITIALIZE_TIMEOUT_MS;
422
+ this.maxPendingEvents = options.maxPendingEvents ?? MAX_PENDING_SIDE_EVENTS;
423
+ this.maxPendingBytes = options.maxPendingBytes ?? MAX_PENDING_SIDE_BYTES;
424
+ if (!Number.isSafeInteger(this.maxPendingEvents) || this.maxPendingEvents <= 0) {
425
+ throw new Error('codex_side_chat_pending_limit_invalid');
426
+ }
427
+ if (!Number.isSafeInteger(this.maxPendingBytes) || this.maxPendingBytes <= 0) {
428
+ throw new Error('codex_side_chat_pending_bytes_invalid');
429
+ }
430
+ this.logger = options.logger ?? console;
431
+ this.readConfig = options.readConfig ?? resolveCodexNotifierConfig;
432
+ this.detectLockState = options.detectLockState ?? detectScreenLock;
433
+ this.enqueue = options.enqueue ?? enqueueCodexNotifierEvent;
434
+ this.listThreads = options.listThreads ?? listRecentCodexVisualizationThreads;
435
+ this.connect = options.connect ?? (path => createConnection(path));
436
+ }
437
+ enabled() {
438
+ const config = this.readConfig();
439
+ return config.enabled && !!config.targetBotAppId;
440
+ }
441
+ startObservation() {
442
+ if (this.observationStartedAt !== undefined)
443
+ return;
444
+ this.tracker.clear();
445
+ this.candidates.clear();
446
+ this.observationStartedAt = this.now();
447
+ }
448
+ stopObservation() {
449
+ this.tracker.clear();
450
+ this.candidates.clear();
451
+ this.observationStartedAt = undefined;
452
+ }
453
+ queueEvents(events) {
454
+ for (const event of events) {
455
+ const config = this.readConfig();
456
+ if (!config.enabled || !config.targetBotAppId)
457
+ continue;
458
+ const lockState = config.notifyWhen === 'always'
459
+ ? 'unlocked'
460
+ : this.detectLockState();
461
+ if (!shouldNotifyForLockState(config.notifyWhen, lockState))
462
+ continue;
463
+ if (this.pending.has(event.eventId))
464
+ continue;
465
+ const item = {
466
+ event,
467
+ targetBotAppId: config.targetBotAppId,
468
+ };
469
+ const bytes = Buffer.byteLength(JSON.stringify(item), 'utf8');
470
+ if (this.pending.size >= this.maxPendingEvents
471
+ || this.pendingBytes + bytes > this.maxPendingBytes) {
472
+ this.logger.warn(`[codex-notifier] Side Chat 内存待入队已达上限,跳过事件: ${event.eventId.slice(0, 12)}`);
473
+ continue;
474
+ }
475
+ this.pending.set(event.eventId, { ...item, bytes });
476
+ this.pendingBytes += bytes;
477
+ }
478
+ this.flushPending();
479
+ }
480
+ flushPending() {
481
+ for (const [eventId, item] of this.pending) {
482
+ try {
483
+ this.enqueue(this.options.dataDir, item.targetBotAppId, item.event);
484
+ this.pending.delete(eventId);
485
+ this.pendingBytes = Math.max(0, this.pendingBytes - item.bytes);
486
+ this.logger.debug(`[codex-notifier] Side Chat 完成事件已入队: ${eventId.slice(0, 12)}`);
487
+ }
488
+ catch (error) {
489
+ this.logger.warn(`[codex-notifier] Side Chat 完成事件入队失败,将重试: ${error instanceof Error ? error.message : String(error)}`);
490
+ }
491
+ }
492
+ }
493
+ async connectOnce(signal) {
494
+ if (this.enabled())
495
+ this.startObservation();
496
+ await new Promise((resolve) => {
497
+ let socket;
498
+ try {
499
+ socket = this.connect(this.socketPath);
500
+ }
501
+ catch (error) {
502
+ this.logger.debug(`[codex-notifier] Codex Desktop IPC 连接失败: ${error instanceof Error ? error.message : String(error)}`);
503
+ resolve();
504
+ return;
505
+ }
506
+ const header = Buffer.allocUnsafe(4);
507
+ let headerOffset = 0;
508
+ let frame;
509
+ let frameOffset = 0;
510
+ let clientId;
511
+ let scanTimer;
512
+ let connectTimer;
513
+ let initializeTimer;
514
+ const followed = new Set();
515
+ const ignored = new Set();
516
+ let settled = false;
517
+ const finish = () => {
518
+ if (settled)
519
+ return;
520
+ settled = true;
521
+ if (scanTimer)
522
+ clearInterval(scanTimer);
523
+ if (connectTimer)
524
+ clearTimeout(connectTimer);
525
+ if (initializeTimer)
526
+ clearTimeout(initializeTimer);
527
+ signal?.removeEventListener('abort', abort);
528
+ if (!socket.destroyed)
529
+ socket.destroy();
530
+ resolve();
531
+ };
532
+ const abort = () => finish();
533
+ const send = (message) => {
534
+ if (!socket.destroyed && socket.writable)
535
+ socket.write(encodeIpcFrame(message));
536
+ };
537
+ const follow = (conversationId, force = false) => {
538
+ if (!clientId || !THREAD_ID_PATTERN.test(conversationId))
539
+ return;
540
+ if (!force && followed.has(conversationId))
541
+ return;
542
+ followed.add(conversationId);
543
+ send({
544
+ type: 'broadcast',
545
+ method: 'thread-stream-following-changed',
546
+ sourceClientId: clientId,
547
+ params: { conversationId, hostId: 'local', following: true },
548
+ version: THREAD_STREAM_FOLLOWING_VERSION,
549
+ });
550
+ };
551
+ const unfollow = (conversationId) => {
552
+ if (!clientId || !followed.delete(conversationId))
553
+ return;
554
+ send({
555
+ type: 'broadcast',
556
+ method: 'thread-stream-following-changed',
557
+ sourceClientId: clientId,
558
+ params: { conversationId, hostId: 'local', following: false },
559
+ version: THREAD_STREAM_FOLLOWING_VERSION,
560
+ });
561
+ };
562
+ const ignore = (conversationId) => {
563
+ ignored.delete(conversationId);
564
+ ignored.add(conversationId);
565
+ while (ignored.size > MAX_TRACKED_CONVERSATIONS) {
566
+ const oldest = ignored.values().next().value;
567
+ if (!oldest)
568
+ break;
569
+ ignored.delete(oldest);
570
+ }
571
+ };
572
+ const scan = () => {
573
+ if (!this.enabled()) {
574
+ this.stopObservation();
575
+ finish();
576
+ return;
577
+ }
578
+ this.startObservation();
579
+ this.flushPending();
580
+ for (const thread of this.listThreads(this.codexHome, this.now())) {
581
+ if (ignored.has(thread.id))
582
+ continue;
583
+ if (!followed.has(thread.id)
584
+ && !this.tracker.has(thread.id)
585
+ && !this.candidates.has(thread.id)) {
586
+ this.candidates.set(thread.id, {
587
+ notifyTerminalOnFirstSnapshot: this.observationStartedAt !== undefined,
588
+ ...(this.observationStartedAt !== undefined
589
+ ? { terminalNotBeforeMs: this.observationStartedAt }
590
+ : {}),
591
+ });
592
+ }
593
+ follow(thread.id);
594
+ }
595
+ };
596
+ const handleState = (message) => {
597
+ if (!this.enabled()) {
598
+ this.stopObservation();
599
+ finish();
600
+ return;
601
+ }
602
+ const params = message.params;
603
+ if (!params
604
+ || params.hostId !== 'local'
605
+ || typeof params.conversationId !== 'string'
606
+ || !plainObject(params.change)) {
607
+ return;
608
+ }
609
+ const change = params.change;
610
+ let result;
611
+ if (change.type === 'snapshot') {
612
+ const candidate = this.candidates.get(params.conversationId);
613
+ result = this.tracker.observeSnapshot(params.conversationId, change.revision, change.conversationState, {
614
+ notifyTerminalOnFirstSnapshot: candidate?.notifyTerminalOnFirstSnapshot,
615
+ terminalNotBeforeMs: candidate?.terminalNotBeforeMs,
616
+ now: this.now(),
617
+ });
618
+ this.candidates.delete(params.conversationId);
619
+ if (plainObject(change.conversationState)
620
+ && (change.conversationState.sideConversation !== true
621
+ || change.conversationState.ephemeral !== true)) {
622
+ ignore(params.conversationId);
623
+ unfollow(params.conversationId);
624
+ return;
625
+ }
626
+ }
627
+ else if (change.type === 'patches') {
628
+ result = this.tracker.observePatches(params.conversationId, change.baseRevision, change.revision, change.patches, this.now());
629
+ }
630
+ else {
631
+ return;
632
+ }
633
+ if (result.needsSnapshot)
634
+ follow(params.conversationId, true);
635
+ this.queueEvents(result.events);
636
+ };
637
+ const handleMessage = (message) => {
638
+ if (message.type === 'response'
639
+ && message.method === 'initialize'
640
+ && message.resultType === 'success'
641
+ && typeof message.result?.clientId === 'string') {
642
+ if (initializeTimer) {
643
+ clearTimeout(initializeTimer);
644
+ initializeTimer = undefined;
645
+ }
646
+ clientId = message.result.clientId;
647
+ scan();
648
+ if (settled)
649
+ return;
650
+ for (const conversationId of this.candidates.keys())
651
+ follow(conversationId);
652
+ scanTimer = setInterval(scan, this.scanIntervalMs);
653
+ return;
654
+ }
655
+ if (message.type === 'client-discovery-request' && typeof message.requestId === 'string') {
656
+ send({
657
+ type: 'client-discovery-response',
658
+ requestId: message.requestId,
659
+ response: { canHandle: false },
660
+ });
661
+ return;
662
+ }
663
+ if (message.type !== 'broadcast')
664
+ return;
665
+ if (message.method === 'thread-stream-state-changed') {
666
+ handleState(message);
667
+ return;
668
+ }
669
+ if (message.method === 'thread-stream-following-changed'
670
+ && message.params?.hostId === 'local'
671
+ && message.params.following === true
672
+ && typeof message.params.conversationId === 'string') {
673
+ if (ignored.has(message.params.conversationId))
674
+ return;
675
+ if (!this.tracker.has(message.params.conversationId)
676
+ && !this.candidates.has(message.params.conversationId)) {
677
+ this.candidates.set(message.params.conversationId, {
678
+ notifyTerminalOnFirstSnapshot: this.observationStartedAt !== undefined,
679
+ ...(this.observationStartedAt !== undefined
680
+ ? { terminalNotBeforeMs: this.observationStartedAt }
681
+ : {}),
682
+ });
683
+ }
684
+ follow(message.params.conversationId);
685
+ }
686
+ };
687
+ socket.on('connect', () => {
688
+ if (connectTimer) {
689
+ clearTimeout(connectTimer);
690
+ connectTimer = undefined;
691
+ }
692
+ initializeTimer = setTimeout(() => {
693
+ this.logger.warn('[codex-notifier] Codex Desktop IPC 初始化超时,将重连');
694
+ finish();
695
+ }, this.initializeTimeoutMs);
696
+ initializeTimer.unref?.();
697
+ send({
698
+ type: 'request',
699
+ requestId: randomUUID(),
700
+ method: 'initialize',
701
+ params: { clientType: 'botmux-codex-notifier' },
702
+ });
703
+ });
704
+ socket.on('data', (chunk) => {
705
+ let chunkOffset = 0;
706
+ while (chunkOffset < chunk.length && !settled) {
707
+ if (!frame) {
708
+ const headerBytes = Math.min(4 - headerOffset, chunk.length - chunkOffset);
709
+ chunk.copy(header, headerOffset, chunkOffset, chunkOffset + headerBytes);
710
+ headerOffset += headerBytes;
711
+ chunkOffset += headerBytes;
712
+ if (headerOffset < 4)
713
+ continue;
714
+ const frameLength = header.readUInt32LE(0);
715
+ headerOffset = 0;
716
+ if (frameLength === 0 || frameLength > IPC_MAX_FRAME_BYTES) {
717
+ this.logger.warn(`[codex-notifier] Codex Desktop IPC 帧长度无效: ${frameLength}`);
718
+ finish();
719
+ return;
720
+ }
721
+ frame = Buffer.allocUnsafe(frameLength);
722
+ frameOffset = 0;
723
+ }
724
+ const frameBytes = Math.min(frame.length - frameOffset, chunk.length - chunkOffset);
725
+ chunk.copy(frame, frameOffset, chunkOffset, chunkOffset + frameBytes);
726
+ frameOffset += frameBytes;
727
+ chunkOffset += frameBytes;
728
+ if (frameOffset < frame.length)
729
+ continue;
730
+ const completedFrame = frame;
731
+ frame = undefined;
732
+ frameOffset = 0;
733
+ try {
734
+ handleMessage(JSON.parse(completedFrame.toString('utf8')));
735
+ }
736
+ catch (error) {
737
+ this.logger.warn(`[codex-notifier] Codex Desktop IPC 消息解析失败: ${error instanceof Error ? error.message : String(error)}`);
738
+ }
739
+ }
740
+ });
741
+ socket.on('error', (error) => {
742
+ this.logger.debug(`[codex-notifier] Codex Desktop IPC 暂不可用: ${error.message}`);
743
+ });
744
+ socket.on('close', finish);
745
+ signal?.addEventListener('abort', abort, { once: true });
746
+ connectTimer = setTimeout(() => {
747
+ this.logger.warn('[codex-notifier] Codex Desktop IPC 连接超时,将重连');
748
+ finish();
749
+ }, this.connectTimeoutMs);
750
+ connectTimer.unref?.();
751
+ if (signal?.aborted)
752
+ abort();
753
+ });
754
+ }
755
+ async run() {
756
+ if (this.platform !== 'darwin')
757
+ return;
758
+ while (!this.options.signal?.aborted) {
759
+ if (!this.enabled()) {
760
+ this.stopObservation();
761
+ await delay(this.scanIntervalMs, this.options.signal);
762
+ continue;
763
+ }
764
+ this.startObservation();
765
+ await this.connectOnce(this.options.signal);
766
+ if (!this.options.signal?.aborted)
767
+ await delay(this.retryMs, this.options.signal);
768
+ }
769
+ }
770
+ }
771
+ export async function runCodexSideConversationMonitor(options) {
772
+ await new CodexSideConversationMonitor(options).run();
773
+ }
774
+ //# sourceMappingURL=side-conversation-monitor.js.map