botmux 3.4.2 → 3.5.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 (378) 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/session-backend-selector.d.ts +10 -1
  12. package/dist/adapters/backend/session-backend-selector.d.ts.map +1 -1
  13. package/dist/adapters/backend/session-backend-selector.js +73 -4
  14. package/dist/adapters/backend/session-backend-selector.js.map +1 -1
  15. package/dist/adapters/backend/types.d.ts +16 -0
  16. package/dist/adapters/backend/types.d.ts.map +1 -1
  17. package/dist/adapters/backend/types.js.map +1 -1
  18. package/dist/adapters/cli/pi-initial-prompt-extension.d.ts +27 -0
  19. package/dist/adapters/cli/pi-initial-prompt-extension.d.ts.map +1 -0
  20. package/dist/adapters/cli/pi-initial-prompt-extension.js +38 -0
  21. package/dist/adapters/cli/pi-initial-prompt-extension.js.map +1 -0
  22. package/dist/adapters/cli/pi-initial-prompt.d.ts +21 -0
  23. package/dist/adapters/cli/pi-initial-prompt.d.ts.map +1 -0
  24. package/dist/adapters/cli/pi-initial-prompt.js +59 -0
  25. package/dist/adapters/cli/pi-initial-prompt.js.map +1 -0
  26. package/dist/adapters/cli/pi.d.ts.map +1 -1
  27. package/dist/adapters/cli/pi.js +15 -4
  28. package/dist/adapters/cli/pi.js.map +1 -1
  29. package/dist/adapters/cli/read-isolation.d.ts.map +1 -1
  30. package/dist/adapters/cli/read-isolation.js +5 -0
  31. package/dist/adapters/cli/read-isolation.js.map +1 -1
  32. package/dist/adapters/cli/shared-hints.d.ts.map +1 -1
  33. package/dist/adapters/cli/shared-hints.js +8 -0
  34. package/dist/adapters/cli/shared-hints.js.map +1 -1
  35. package/dist/adapters/cli/traex.d.ts.map +1 -1
  36. package/dist/adapters/cli/traex.js +5 -0
  37. package/dist/adapters/cli/traex.js.map +1 -1
  38. package/dist/adapters/cli/types.d.ts +23 -3
  39. package/dist/adapters/cli/types.d.ts.map +1 -1
  40. package/dist/adapters/hook-installer.d.ts +7 -0
  41. package/dist/adapters/hook-installer.d.ts.map +1 -1
  42. package/dist/adapters/hook-installer.js +56 -0
  43. package/dist/adapters/hook-installer.js.map +1 -1
  44. package/dist/bot-registry.d.ts +13 -0
  45. package/dist/bot-registry.d.ts.map +1 -1
  46. package/dist/bot-registry.js +118 -2
  47. package/dist/bot-registry.js.map +1 -1
  48. package/dist/cli/capabilities.d.ts +24 -0
  49. package/dist/cli/capabilities.d.ts.map +1 -0
  50. package/dist/cli/capabilities.js +25 -0
  51. package/dist/cli/capabilities.js.map +1 -0
  52. package/dist/cli/create-group-resolver.d.ts +24 -0
  53. package/dist/cli/create-group-resolver.d.ts.map +1 -1
  54. package/dist/cli/create-group-resolver.js +23 -0
  55. package/dist/cli/create-group-resolver.js.map +1 -1
  56. package/dist/cli/daemon-lifecycle-env.d.ts +5 -7
  57. package/dist/cli/daemon-lifecycle-env.d.ts.map +1 -1
  58. package/dist/cli/daemon-lifecycle-env.js +13 -7
  59. package/dist/cli/daemon-lifecycle-env.js.map +1 -1
  60. package/dist/cli/exact-chat-grant-client.d.ts +48 -0
  61. package/dist/cli/exact-chat-grant-client.d.ts.map +1 -0
  62. package/dist/cli/exact-chat-grant-client.js +108 -0
  63. package/dist/cli/exact-chat-grant-client.js.map +1 -0
  64. package/dist/cli/exact-chat-grant.d.ts +18 -0
  65. package/dist/cli/exact-chat-grant.d.ts.map +1 -0
  66. package/dist/cli/exact-chat-grant.js +97 -0
  67. package/dist/cli/exact-chat-grant.js.map +1 -0
  68. package/dist/cli.d.ts +10 -1
  69. package/dist/cli.d.ts.map +1 -1
  70. package/dist/cli.js +770 -126
  71. package/dist/cli.js.map +1 -1
  72. package/dist/codex-rpc-engine.d.ts +26 -0
  73. package/dist/codex-rpc-engine.d.ts.map +1 -1
  74. package/dist/codex-rpc-engine.js +113 -2
  75. package/dist/codex-rpc-engine.js.map +1 -1
  76. package/dist/config.d.ts +16 -0
  77. package/dist/config.d.ts.map +1 -1
  78. package/dist/config.js +16 -0
  79. package/dist/config.js.map +1 -1
  80. package/dist/core/bot-live-control.d.ts +41 -0
  81. package/dist/core/bot-live-control.d.ts.map +1 -0
  82. package/dist/core/bot-live-control.js +135 -0
  83. package/dist/core/bot-live-control.js.map +1 -0
  84. package/dist/core/command-handler.d.ts.map +1 -1
  85. package/dist/core/command-handler.js +28 -8
  86. package/dist/core/command-handler.js.map +1 -1
  87. package/dist/core/daemon-config-fence.d.ts +8 -0
  88. package/dist/core/daemon-config-fence.d.ts.map +1 -0
  89. package/dist/core/daemon-config-fence.js +13 -0
  90. package/dist/core/daemon-config-fence.js.map +1 -0
  91. package/dist/core/dashboard-events.d.ts +5 -0
  92. package/dist/core/dashboard-events.d.ts.map +1 -1
  93. package/dist/core/dashboard-events.js.map +1 -1
  94. package/dist/core/dashboard-ipc-server.d.ts +21 -2
  95. package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
  96. package/dist/core/dashboard-ipc-server.js +232 -5
  97. package/dist/core/dashboard-ipc-server.js.map +1 -1
  98. package/dist/core/dispatch-registry.d.ts +12 -0
  99. package/dist/core/dispatch-registry.d.ts.map +1 -0
  100. package/dist/core/dispatch-registry.js +33 -0
  101. package/dist/core/dispatch-registry.js.map +1 -0
  102. package/dist/core/dispatch.d.ts +99 -0
  103. package/dist/core/dispatch.d.ts.map +1 -1
  104. package/dist/core/dispatch.js +136 -0
  105. package/dist/core/dispatch.js.map +1 -1
  106. package/dist/core/inflight-input-tracker.d.ts +1 -0
  107. package/dist/core/inflight-input-tracker.d.ts.map +1 -1
  108. package/dist/core/inflight-input-tracker.js.map +1 -1
  109. package/dist/core/maintenance.d.ts.map +1 -1
  110. package/dist/core/maintenance.js +10 -3
  111. package/dist/core/maintenance.js.map +1 -1
  112. package/dist/core/persistent-backend.d.ts +16 -2
  113. package/dist/core/persistent-backend.d.ts.map +1 -1
  114. package/dist/core/persistent-backend.js +40 -0
  115. package/dist/core/persistent-backend.js.map +1 -1
  116. package/dist/core/session-discovery.d.ts +8 -1
  117. package/dist/core/session-discovery.d.ts.map +1 -1
  118. package/dist/core/session-discovery.js +140 -8
  119. package/dist/core/session-discovery.js.map +1 -1
  120. package/dist/core/session-manager.d.ts.map +1 -1
  121. package/dist/core/session-manager.js +12 -8
  122. package/dist/core/session-manager.js.map +1 -1
  123. package/dist/core/session-title.d.ts +8 -0
  124. package/dist/core/session-title.d.ts.map +1 -1
  125. package/dist/core/session-title.js +54 -0
  126. package/dist/core/session-title.js.map +1 -1
  127. package/dist/core/terminal-write-auth.d.ts +15 -0
  128. package/dist/core/terminal-write-auth.d.ts.map +1 -1
  129. package/dist/core/terminal-write-auth.js +20 -0
  130. package/dist/core/terminal-write-auth.js.map +1 -1
  131. package/dist/core/trigger-session.d.ts.map +1 -1
  132. package/dist/core/trigger-session.js +3 -2
  133. package/dist/core/trigger-session.js.map +1 -1
  134. package/dist/core/types.d.ts +33 -0
  135. package/dist/core/types.d.ts.map +1 -1
  136. package/dist/core/types.js.map +1 -1
  137. package/dist/core/worker-pool.d.ts +27 -8
  138. package/dist/core/worker-pool.d.ts.map +1 -1
  139. package/dist/core/worker-pool.js +389 -19
  140. package/dist/core/worker-pool.js.map +1 -1
  141. package/dist/daemon.d.ts +4 -2
  142. package/dist/daemon.d.ts.map +1 -1
  143. package/dist/daemon.js +397 -26
  144. package/dist/daemon.js.map +1 -1
  145. package/dist/dashboard/bot-onboarding.d.ts +127 -1
  146. package/dist/dashboard/bot-onboarding.d.ts.map +1 -1
  147. package/dist/dashboard/bot-onboarding.js +1104 -25
  148. package/dist/dashboard/bot-onboarding.js.map +1 -1
  149. package/dist/dashboard/debug-terminal.d.ts +18 -0
  150. package/dist/dashboard/debug-terminal.d.ts.map +1 -0
  151. package/dist/dashboard/debug-terminal.js +338 -0
  152. package/dist/dashboard/debug-terminal.js.map +1 -0
  153. package/dist/dashboard/public-redact.d.ts +2 -0
  154. package/dist/dashboard/public-redact.d.ts.map +1 -1
  155. package/dist/dashboard/public-redact.js +12 -3
  156. package/dist/dashboard/public-redact.js.map +1 -1
  157. package/dist/dashboard/registry.d.ts +8 -0
  158. package/dist/dashboard/registry.d.ts.map +1 -1
  159. package/dist/dashboard/registry.js +13 -0
  160. package/dist/dashboard/registry.js.map +1 -1
  161. package/dist/dashboard/settings-write-applier.d.ts +47 -1
  162. package/dist/dashboard/settings-write-applier.d.ts.map +1 -1
  163. package/dist/dashboard/settings-write-applier.js +102 -1
  164. package/dist/dashboard/settings-write-applier.js.map +1 -1
  165. package/dist/dashboard/web/app.d.ts.map +1 -1
  166. package/dist/dashboard/web/app.js +2 -0
  167. package/dist/dashboard/web/app.js.map +1 -1
  168. package/dist/dashboard/web/bot-defaults-page.d.ts +1 -0
  169. package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -1
  170. package/dist/dashboard/web/bot-defaults-page.js +24 -5
  171. package/dist/dashboard/web/bot-defaults-page.js.map +1 -1
  172. package/dist/dashboard/web/bot-defaults.d.ts +15 -0
  173. package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
  174. package/dist/dashboard/web/bot-defaults.js +19 -0
  175. package/dist/dashboard/web/bot-defaults.js.map +1 -1
  176. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  177. package/dist/dashboard/web/i18n.js +76 -6
  178. package/dist/dashboard/web/i18n.js.map +1 -1
  179. package/dist/dashboard/web/icon-tooltip.d.ts +3 -0
  180. package/dist/dashboard/web/icon-tooltip.d.ts.map +1 -0
  181. package/dist/dashboard/web/icon-tooltip.js +108 -0
  182. package/dist/dashboard/web/icon-tooltip.js.map +1 -0
  183. package/dist/dashboard/web/sessions-kanban.js +2 -2
  184. package/dist/dashboard/web/sessions-kanban.js.map +1 -1
  185. package/dist/dashboard/web/sessions-page.d.ts.map +1 -1
  186. package/dist/dashboard/web/sessions-page.js +48 -9
  187. package/dist/dashboard/web/sessions-page.js.map +1 -1
  188. package/dist/dashboard/web/sessions.d.ts +2 -0
  189. package/dist/dashboard/web/sessions.d.ts.map +1 -1
  190. package/dist/dashboard/web/sessions.js +46 -2
  191. package/dist/dashboard/web/sessions.js.map +1 -1
  192. package/dist/dashboard/web/settings-page.d.ts +78 -0
  193. package/dist/dashboard/web/settings-page.d.ts.map +1 -1
  194. package/dist/dashboard/web/settings-page.js +88 -1
  195. package/dist/dashboard/web/settings-page.js.map +1 -1
  196. package/dist/dashboard/web/store.d.ts +2 -0
  197. package/dist/dashboard/web/store.d.ts.map +1 -1
  198. package/dist/dashboard/web/store.js +13 -1
  199. package/dist/dashboard/web/store.js.map +1 -1
  200. package/dist/dashboard-web/app.js +1 -1
  201. package/dist/dashboard-web/chunks/bot-defaults-page-O376WSER.js +5 -0
  202. package/dist/dashboard-web/chunks/{chunk-JNRSPKLS.js → chunk-EJDYUINZ.js} +1 -1
  203. package/dist/dashboard-web/chunks/{chunk-CUV65BIQ.js → chunk-H7P5UV4W.js} +6 -6
  204. package/dist/dashboard-web/chunks/{chunk-P6GO5KT4.js → chunk-QCPPKCX3.js} +1 -1
  205. package/dist/dashboard-web/chunks/{chunk-UBOLHQCK.js → chunk-WXPMNEYV.js} +1 -1
  206. package/dist/dashboard-web/chunks/{connectors-page-KTC2QWNW.js → connectors-page-IR54AOAI.js} +1 -1
  207. package/dist/dashboard-web/chunks/{groups-page-B3EKGOLY.js → groups-page-3P4TLUMF.js} +1 -1
  208. package/dist/dashboard-web/chunks/{insights-page-X6RXNCWX.js → insights-page-TDCZV56A.js} +1 -1
  209. package/dist/dashboard-web/chunks/{monitor-room-LLRA5LQW.js → monitor-room-QWCWL3SX.js} +1 -1
  210. package/dist/dashboard-web/chunks/{monitoring-page-7MT5FEOS.js → monitoring-page-IOWFSNVC.js} +1 -1
  211. package/dist/dashboard-web/chunks/{office-page-KD46D5TD.js → office-page-5AUPEHZP.js} +1 -1
  212. package/dist/dashboard-web/chunks/{overview-page-JUWNH32O.js → overview-page-QJMI6NLW.js} +1 -1
  213. package/dist/dashboard-web/chunks/{roles-page-P6F7NLOI.js → roles-page-WJVB52ET.js} +1 -1
  214. package/dist/dashboard-web/chunks/{schedules-page-XIHWZST4.js → schedules-page-RVRWHP4V.js} +1 -1
  215. package/dist/dashboard-web/chunks/sessions-page-KWLGBX6G.js +3 -0
  216. package/dist/dashboard-web/chunks/settings-page-TNZEPC7V.js +2 -0
  217. package/dist/dashboard-web/chunks/{skills-page-A46KVWBL.js → skills-page-7YT5TIX5.js} +1 -1
  218. package/dist/dashboard-web/chunks/{team-federation-page-SDUC56DF.js → team-federation-page-NJZKTU7A.js} +1 -1
  219. package/dist/dashboard-web/chunks/{v3-page-J5JOTUSQ.js → v3-page-NQ73UA2Q.js} +1 -1
  220. package/dist/dashboard-web/chunks/{whiteboards-page-U7LSOAWI.js → whiteboards-page-DSM3MDMN.js} +1 -1
  221. package/dist/dashboard-web/style.css +198 -7
  222. package/dist/dashboard.js +294 -7
  223. package/dist/dashboard.js.map +1 -1
  224. package/dist/features/codex-notifier/adoption.d.ts +11 -0
  225. package/dist/features/codex-notifier/adoption.d.ts.map +1 -0
  226. package/dist/features/codex-notifier/adoption.js +11 -0
  227. package/dist/features/codex-notifier/adoption.js.map +1 -0
  228. package/dist/features/codex-notifier/app-opener.d.ts +21 -0
  229. package/dist/features/codex-notifier/app-opener.d.ts.map +1 -0
  230. package/dist/features/codex-notifier/app-opener.js +33 -0
  231. package/dist/features/codex-notifier/app-opener.js.map +1 -0
  232. package/dist/features/codex-notifier/card-action.d.ts +27 -0
  233. package/dist/features/codex-notifier/card-action.d.ts.map +1 -0
  234. package/dist/features/codex-notifier/card-action.js +84 -0
  235. package/dist/features/codex-notifier/card-action.js.map +1 -0
  236. package/dist/features/codex-notifier/card.d.ts +12 -0
  237. package/dist/features/codex-notifier/card.d.ts.map +1 -0
  238. package/dist/features/codex-notifier/card.js +150 -0
  239. package/dist/features/codex-notifier/card.js.map +1 -0
  240. package/dist/features/codex-notifier/codex-context.d.ts +12 -0
  241. package/dist/features/codex-notifier/codex-context.d.ts.map +1 -0
  242. package/dist/features/codex-notifier/codex-context.js +161 -0
  243. package/dist/features/codex-notifier/codex-context.js.map +1 -0
  244. package/dist/features/codex-notifier/config.d.ts +9 -0
  245. package/dist/features/codex-notifier/config.d.ts.map +1 -0
  246. package/dist/features/codex-notifier/config.js +11 -0
  247. package/dist/features/codex-notifier/config.js.map +1 -0
  248. package/dist/features/codex-notifier/confirmed-turn.d.ts +20 -0
  249. package/dist/features/codex-notifier/confirmed-turn.d.ts.map +1 -0
  250. package/dist/features/codex-notifier/confirmed-turn.js +130 -0
  251. package/dist/features/codex-notifier/confirmed-turn.js.map +1 -0
  252. package/dist/features/codex-notifier/emitter.d.ts +13 -0
  253. package/dist/features/codex-notifier/emitter.d.ts.map +1 -0
  254. package/dist/features/codex-notifier/emitter.js +33 -0
  255. package/dist/features/codex-notifier/emitter.js.map +1 -0
  256. package/dist/features/codex-notifier/event-store.d.ts +29 -0
  257. package/dist/features/codex-notifier/event-store.d.ts.map +1 -0
  258. package/dist/features/codex-notifier/event-store.js +217 -0
  259. package/dist/features/codex-notifier/event-store.js.map +1 -0
  260. package/dist/features/codex-notifier/event.d.ts +46 -0
  261. package/dist/features/codex-notifier/event.d.ts.map +1 -0
  262. package/dist/features/codex-notifier/event.js +188 -0
  263. package/dist/features/codex-notifier/event.js.map +1 -0
  264. package/dist/features/codex-notifier/hook-cli.d.ts +23 -0
  265. package/dist/features/codex-notifier/hook-cli.d.ts.map +1 -0
  266. package/dist/features/codex-notifier/hook-cli.js +130 -0
  267. package/dist/features/codex-notifier/hook-cli.js.map +1 -0
  268. package/dist/features/codex-notifier/hook-installer.d.ts +19 -0
  269. package/dist/features/codex-notifier/hook-installer.d.ts.map +1 -0
  270. package/dist/features/codex-notifier/hook-installer.js +158 -0
  271. package/dist/features/codex-notifier/hook-installer.js.map +1 -0
  272. package/dist/features/codex-notifier/index.d.ts +21 -0
  273. package/dist/features/codex-notifier/index.d.ts.map +1 -0
  274. package/dist/features/codex-notifier/index.js +19 -0
  275. package/dist/features/codex-notifier/index.js.map +1 -0
  276. package/dist/features/codex-notifier/internal-turn.d.ts +5 -0
  277. package/dist/features/codex-notifier/internal-turn.d.ts.map +1 -0
  278. package/dist/features/codex-notifier/internal-turn.js +43 -0
  279. package/dist/features/codex-notifier/internal-turn.js.map +1 -0
  280. package/dist/features/codex-notifier/outbox-worker.d.ts +71 -0
  281. package/dist/features/codex-notifier/outbox-worker.d.ts.map +1 -0
  282. package/dist/features/codex-notifier/outbox-worker.js +290 -0
  283. package/dist/features/codex-notifier/outbox-worker.js.map +1 -0
  284. package/dist/features/codex-notifier/outbox.d.ts +25 -0
  285. package/dist/features/codex-notifier/outbox.d.ts.map +1 -0
  286. package/dist/features/codex-notifier/outbox.js +225 -0
  287. package/dist/features/codex-notifier/outbox.js.map +1 -0
  288. package/dist/features/codex-notifier/paths.d.ts +7 -0
  289. package/dist/features/codex-notifier/paths.d.ts.map +1 -0
  290. package/dist/features/codex-notifier/paths.js +20 -0
  291. package/dist/features/codex-notifier/paths.js.map +1 -0
  292. package/dist/features/codex-notifier/screen-lock.d.ts +12 -0
  293. package/dist/features/codex-notifier/screen-lock.d.ts.map +1 -0
  294. package/dist/features/codex-notifier/screen-lock.js +47 -0
  295. package/dist/features/codex-notifier/screen-lock.js.map +1 -0
  296. package/dist/features/codex-notifier/side-conversation-monitor.d.ts +102 -0
  297. package/dist/features/codex-notifier/side-conversation-monitor.d.ts.map +1 -0
  298. package/dist/features/codex-notifier/side-conversation-monitor.js +774 -0
  299. package/dist/features/codex-notifier/side-conversation-monitor.js.map +1 -0
  300. package/dist/features/codex-notifier/types.d.ts +42 -0
  301. package/dist/features/codex-notifier/types.d.ts.map +1 -0
  302. package/dist/features/codex-notifier/types.js +2 -0
  303. package/dist/features/codex-notifier/types.js.map +1 -0
  304. package/dist/features/codex-notifier/worker-lock.d.ts +8 -0
  305. package/dist/features/codex-notifier/worker-lock.d.ts.map +1 -0
  306. package/dist/features/codex-notifier/worker-lock.js +108 -0
  307. package/dist/features/codex-notifier/worker-lock.js.map +1 -0
  308. package/dist/global-config.d.ts +13 -0
  309. package/dist/global-config.d.ts.map +1 -1
  310. package/dist/global-config.js +30 -0
  311. package/dist/global-config.js.map +1 -1
  312. package/dist/im/lark/card-builder.js +2 -2
  313. package/dist/im/lark/card-builder.js.map +1 -1
  314. package/dist/im/lark/card-handler.d.ts +2 -0
  315. package/dist/im/lark/card-handler.d.ts.map +1 -1
  316. package/dist/im/lark/card-handler.js +165 -34
  317. package/dist/im/lark/card-handler.js.map +1 -1
  318. package/dist/im/lark/client.d.ts +62 -4
  319. package/dist/im/lark/client.d.ts.map +1 -1
  320. package/dist/im/lark/client.js +237 -29
  321. package/dist/im/lark/client.js.map +1 -1
  322. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  323. package/dist/im/lark/event-dispatcher.js +20 -30
  324. package/dist/im/lark/event-dispatcher.js.map +1 -1
  325. package/dist/platform/secure-host-file.d.ts.map +1 -1
  326. package/dist/platform/secure-host-file.js +173 -54
  327. package/dist/platform/secure-host-file.js.map +1 -1
  328. package/dist/services/codex-app-threads.d.ts +47 -0
  329. package/dist/services/codex-app-threads.d.ts.map +1 -1
  330. package/dist/services/codex-app-threads.js +502 -10
  331. package/dist/services/codex-app-threads.js.map +1 -1
  332. package/dist/services/exact-chat-grant.d.ts +83 -0
  333. package/dist/services/exact-chat-grant.d.ts.map +1 -0
  334. package/dist/services/exact-chat-grant.js +249 -0
  335. package/dist/services/exact-chat-grant.js.map +1 -0
  336. package/dist/services/group-creator.d.ts +11 -0
  337. package/dist/services/group-creator.d.ts.map +1 -1
  338. package/dist/services/group-creator.js +18 -9
  339. package/dist/services/group-creator.js.map +1 -1
  340. package/dist/services/local-cli-opener.d.ts.map +1 -1
  341. package/dist/services/local-cli-opener.js +10 -5
  342. package/dist/services/local-cli-opener.js.map +1 -1
  343. package/dist/services/traex-user-input.d.ts +19 -0
  344. package/dist/services/traex-user-input.d.ts.map +1 -0
  345. package/dist/services/traex-user-input.js +57 -0
  346. package/dist/services/traex-user-input.js.map +1 -0
  347. package/dist/setup/open-platform-automation.d.ts +24 -3
  348. package/dist/setup/open-platform-automation.d.ts.map +1 -1
  349. package/dist/setup/open-platform-automation.js +45 -8
  350. package/dist/setup/open-platform-automation.js.map +1 -1
  351. package/dist/setup/verify-permissions.d.ts +18 -0
  352. package/dist/setup/verify-permissions.d.ts.map +1 -1
  353. package/dist/setup/verify-permissions.js +60 -0
  354. package/dist/setup/verify-permissions.js.map +1 -1
  355. package/dist/types.d.ts +70 -4
  356. package/dist/types.d.ts.map +1 -1
  357. package/dist/utils/child-env.d.ts +1 -1
  358. package/dist/utils/child-env.d.ts.map +1 -1
  359. package/dist/utils/child-env.js +2 -0
  360. package/dist/utils/child-env.js.map +1 -1
  361. package/dist/utils/pending-input-queue.d.ts +19 -0
  362. package/dist/utils/pending-input-queue.d.ts.map +1 -1
  363. package/dist/utils/pending-input-queue.js +21 -1
  364. package/dist/utils/pending-input-queue.js.map +1 -1
  365. package/dist/utils/stuck-detector.d.ts +45 -0
  366. package/dist/utils/stuck-detector.d.ts.map +1 -0
  367. package/dist/utils/stuck-detector.js +188 -0
  368. package/dist/utils/stuck-detector.js.map +1 -0
  369. package/dist/utils/stuck-key-guard.d.ts +75 -0
  370. package/dist/utils/stuck-key-guard.d.ts.map +1 -0
  371. package/dist/utils/stuck-key-guard.js +77 -0
  372. package/dist/utils/stuck-key-guard.js.map +1 -0
  373. package/dist/worker.js +807 -117
  374. package/dist/worker.js.map +1 -1
  375. package/package.json +1 -1
  376. package/dist/dashboard-web/chunks/bot-defaults-page-B5AY4B2J.js +0 -5
  377. package/dist/dashboard-web/chunks/sessions-page-2VECQ27T.js +0 -3
  378. package/dist/dashboard-web/chunks/settings-page-HMIUE2JA.js +0 -2
package/dist/dashboard.js CHANGED
@@ -11,8 +11,9 @@ import { logger } from './utils/logger.js';
11
11
  import { config } from './config.js';
12
12
  import { listenWithProbe } from './utils/listen-with-probe.js';
13
13
  import { generateToken, parseCookie, buildSetCookie, verifyHmac, cliAuthBind, decideDashboardAuth, loadPersistedToken, persistToken, loadDashboardSecret, loadOrCreateDashboardSecret, } from './dashboard/auth.js';
14
- import { DaemonRegistry } from './dashboard/registry.js';
14
+ import { DaemonRegistry, botsRosterSignature } from './dashboard/registry.js';
15
15
  import { Aggregator, subscribeDaemon } from './dashboard/aggregator.js';
16
+ import { createDebugTerminalManager } from './dashboard/debug-terminal.js';
16
17
  import { pickCreatorForGroup } from './dashboard/operator-selector.js';
17
18
  import { buildTeamGroupCreatePayload, planGroupCreator } from './dashboard/team-group.js';
18
19
  import { jsonRes } from './dashboard/http.js';
@@ -21,7 +22,7 @@ import { defaultRunsDir as v3RunsDir } from './workflows/v3/ops-projection.js';
21
22
  import { verifyWorkflowDaemonIpcResponse, workflowDaemonIpcHeaders, WORKFLOW_DAEMON_IPC_ROUTE_PREFIX, } from './workflows/v3/daemon-ipc-auth.js';
22
23
  import { handleDashboardTriggerApi } from './dashboard/trigger-api.js';
23
24
  import { handleConnectorApi } from './dashboard/connector-api.js';
24
- import { redactGroupsForPublic, redactSchedulesForPublic } from './dashboard/public-redact.js';
25
+ import { redactGroupsForPublic, redactSchedulesForPublic, redactSettingsForPublic, } from './dashboard/public-redact.js';
25
26
  import { handleWebhookRoute } from './dashboard/webhook-routes.js';
26
27
  import { handleFederationApi } from './dashboard/federation-api.js';
27
28
  import { handleFederationSpokeApi, syncAllMemberships, autoBindOwnerIfUnambiguous } from './dashboard/federation-spoke-api.js';
@@ -46,7 +47,7 @@ import { listCliRuntimeUpdateEntries } from './core/cli-runtime-update.js';
46
47
  import { claimRestartLease, clearRestartIntent, clearRestartLease, hasActiveRestartLease, writeManualIntentIfAbsent, writeRestartIntent, } from './services/restart-intent-store.js';
47
48
  import { withFileLock } from './utils/file-lock.js';
48
49
  import { spawn } from 'node:child_process';
49
- import { applySettingsWrite, defaultSettingsWriteApplierDeps, } from './dashboard/settings-write-applier.js';
50
+ import { applySettingsWrite, defaultSettingsWriteApplierDeps, hasResolvedCodexNotifierRecipient, resolveCodexNotifierRecipientView, } from './dashboard/settings-write-applier.js';
50
51
  import { addBotsToGroup, bindOncall, disbandGroup, leaveGroup, unbindOncall, } from './dashboard/groups-action-helpers.js';
51
52
  import { createDaemonInternalApi } from './dashboard/daemon-internal-api.js';
52
53
  import { listTeamReports, readTeamBoard, setTeamBoardEntry } from './services/team-board-store.js';
@@ -56,6 +57,7 @@ import { buildSkillInstallAuditSummary, installLocalSkillLinks, readSkillRegistr
56
57
  import { redactGitUrlCredentials } from './core/skills/sources.js';
57
58
  import { effectiveDefaultWorkingDir, getBot, loadBotConfigs, parseBotConfigsFromText } from './bot-registry.js';
58
59
  import { findEntryIndex, readRawConfig, requireConfigPath, writeRawConfigAtomic } from './services/config-store.js';
60
+ import { emitCodexNotifierOutboxItem, installCodexNotifierHook, isCodexNotifierWorkerStateFresh, isCodexNotifierHookInstalled, listCodexNotifierOutbox, readCodexNotifierWorkerState, resolveCodexNotifierConfig, runCodexSideConversationMonitor, runCodexNotifierWorkerSupervisor, } from './features/codex-notifier/index.js';
59
61
  import { discoverNativeCliSkillGroups } from './core/skills/discovery.js';
60
62
  import { analyzeSkillReferences } from './core/skills/references.js';
61
63
  import { discoverDashboardSkills, installDashboardSkill, parseDashboardSkillInstallRequest, parseInstallLocalLinksSources, MAX_LOCAL_LINK_SOURCES } from './dashboard/skill-install-request.js';
@@ -189,6 +191,20 @@ function verifyDashboardBinding(port) {
189
191
  mkdirSync(REGISTRY_DIR, { recursive: true });
190
192
  const registry = new DaemonRegistry(REGISTRY_DIR);
191
193
  const aggregator = new Aggregator();
194
+ // 调试终端(owner-only 裸 bash)。默认工作目录取当前所有 session 的工作目录去重,
195
+ // 让 owner 从熟悉的目录起终端复现问题;都没有时模块内退回 homedir。
196
+ const debugTerminalManager = createDebugTerminalManager({
197
+ getActiveToken: () => activeToken,
198
+ defaultWorkingDirs: () => {
199
+ const dirs = new Set();
200
+ for (const s of aggregator.getSessions()) {
201
+ const wd = s.workingDir;
202
+ if (typeof wd === 'string' && wd.trim())
203
+ dirs.add(wd.trim());
204
+ }
205
+ return [...dirs];
206
+ },
207
+ });
192
208
  /**
193
209
  * Resolve which daemon owns a schedule row. For rows with an explicit
194
210
  * `larkAppId`, returns that. For legacy rows (no owner stamp), falls back to
@@ -269,8 +285,58 @@ function spawnStartBotLive(appId) {
269
285
  }
270
286
  });
271
287
  }
288
+ function spawnStopBotLive(appId) {
289
+ return new Promise((resolve) => {
290
+ let out = '';
291
+ let err = '';
292
+ let settled = false;
293
+ const done = (r) => { if (!settled) {
294
+ settled = true;
295
+ resolve(r);
296
+ } };
297
+ try {
298
+ const child = spawn(process.execPath, [botmuxCliEntry(), 'stop-bot', appId, '--json'], {
299
+ stdio: ['ignore', 'pipe', 'pipe'],
300
+ env: process.env,
301
+ cwd: globalInstallUpdateCwd(),
302
+ });
303
+ const timer = setTimeout(() => {
304
+ try {
305
+ child.kill('SIGKILL');
306
+ }
307
+ catch { /* already gone */ }
308
+ done({ ok: false, message: 'stop-bot 超时(30s)' });
309
+ }, 30_000);
310
+ timer.unref?.();
311
+ child.stdout?.on('data', (d) => { out += String(d); });
312
+ child.stderr?.on('data', (d) => { err += String(d); });
313
+ child.on('error', (e) => {
314
+ clearTimeout(timer);
315
+ done({ ok: false, message: e instanceof Error ? e.message : String(e) });
316
+ });
317
+ child.on('exit', (code) => {
318
+ clearTimeout(timer);
319
+ let parsed;
320
+ try {
321
+ parsed = JSON.parse(out.trim());
322
+ }
323
+ catch { /* non-JSON */ }
324
+ if (code === 0) {
325
+ done({ ok: true, message: parsed?.processName ? `${parsed.processName} 已停止` : undefined });
326
+ }
327
+ else {
328
+ done({ ok: false, message: parsed?.message || err.trim() || `stop-bot 退出码 ${code}` });
329
+ }
330
+ });
331
+ }
332
+ catch (e) {
333
+ done({ ok: false, message: e instanceof Error ? e.message : String(e) });
334
+ }
335
+ });
336
+ }
272
337
  const botOnboarding = new BotOnboardingManager({
273
338
  botsJsonPath: BOTS_JSON_PATH,
339
+ stopBotLive: spawnStopBotLive,
274
340
  startBotLive: spawnStartBotLive,
275
341
  });
276
342
  // 飞书 Web 登录态刷新(机器人改名缺登录态时的 dashboard 扫码入口)。机器级单例,
@@ -306,6 +372,51 @@ async function validateVcMeetingListenerBotAppId(appId) {
306
372
  return { ok: false, error: 'vcMeetingAgent_listenerBot_unknown' };
307
373
  return { ok: true };
308
374
  }
375
+ async function validateCodexNotifierTargetBotAppId(appId, options = {}) {
376
+ try {
377
+ const bot = loadBotConfigs().find(candidate => candidate.larkAppId === appId);
378
+ if (!bot)
379
+ return { ok: false, error: 'codexNotifier_target_unknown' };
380
+ if (bot.cliId !== 'codex' && bot.cliId !== 'codex-app') {
381
+ return { ok: false, error: 'codexNotifier_target_cli_unsupported' };
382
+ }
383
+ if (!(bot.allowedUsers ?? []).some(user => typeof user === 'string' && user.trim())) {
384
+ return { ok: false, error: 'codexNotifier_target_owner_missing' };
385
+ }
386
+ if (options.requireReady !== true)
387
+ return { ok: true };
388
+ const daemon = registry.list().find(candidate => candidate.larkAppId === appId);
389
+ if (!daemon)
390
+ return { ok: false, error: 'codexNotifier_target_daemon_offline' };
391
+ const resolvedOwners = daemon.resolvedAllowedUsers ?? [];
392
+ if (!hasResolvedCodexNotifierRecipient(resolvedOwners)) {
393
+ return { ok: false, error: 'codexNotifier_target_owner_unverified' };
394
+ }
395
+ return { ok: true };
396
+ }
397
+ catch {
398
+ return { ok: false, error: 'codexNotifier_target_unknown' };
399
+ }
400
+ }
401
+ function codexNotifierBotOptions() {
402
+ try {
403
+ const onlineByAppId = new Map(registry.list().map(bot => [bot.larkAppId, bot]));
404
+ return loadBotConfigs()
405
+ .filter(bot => bot.cliId === 'codex' || bot.cliId === 'codex-app')
406
+ .map(bot => {
407
+ const resolvedOwners = onlineByAppId.get(bot.larkAppId)?.resolvedAllowedUsers ?? [];
408
+ return {
409
+ larkAppId: bot.larkAppId,
410
+ botName: bot.displayName ?? onlineByAppId.get(bot.larkAppId)?.botName ?? bot.name ?? null,
411
+ cliId: onlineByAppId.get(bot.larkAppId)?.cliId ?? bot.cliId,
412
+ ...resolveCodexNotifierRecipientView(bot.allowedUsers, resolvedOwners),
413
+ };
414
+ });
415
+ }
416
+ catch {
417
+ return [];
418
+ }
419
+ }
309
420
  function normalizeVcMeetingAgentRecord(raw) {
310
421
  return raw && typeof raw === 'object' && !Array.isArray(raw)
311
422
  ? { ...raw }
@@ -664,6 +775,9 @@ async function syncVcMeetingListenerBotConfig(listenerBotAppId, previousListener
664
775
  function resolveDashboardSettings() {
665
776
  const global = readGlobalConfig();
666
777
  const dashboard = global.dashboard ?? {};
778
+ const codexNotifier = resolveCodexNotifierConfig();
779
+ const codexNotifierBots = codexNotifierBotOptions();
780
+ const codexNotifierState = readCodexNotifierWorkerState(config.session.dataDir);
667
781
  const larkCli = checkLarkCliVersion();
668
782
  return {
669
783
  publicReadOnly: dashboard.publicReadOnly ?? config.dashboard.publicReadOnly,
@@ -679,6 +793,19 @@ function resolveDashboardSettings() {
679
793
  recommendedRef: TRAEX_RECOMMENDED_REF,
680
794
  },
681
795
  codexRpcInput: dashboard.codexRpcInput === true, // default OFF until live-verified
796
+ codexNotifier: {
797
+ enabled: codexNotifier.enabled,
798
+ targetBotAppId: codexNotifier.targetBotAppId ?? null,
799
+ notifyWhen: codexNotifier.notifyWhen,
800
+ platformSupported: process.platform === 'darwin',
801
+ hookInstalled: isCodexNotifierHookInstalled(),
802
+ botOptions: codexNotifierBots,
803
+ targetDaemonOnline: !!codexNotifier.targetBotAppId
804
+ && registry.list().some(bot => bot.larkAppId === codexNotifier.targetBotAppId),
805
+ pendingCount: listCodexNotifierOutbox(config.session.dataDir).length,
806
+ workerOnline: isCodexNotifierWorkerStateFresh(codexNotifierState),
807
+ lastError: codexNotifierState?.lastError ?? null,
808
+ },
682
809
  vcMeetingAgent: {
683
810
  enabled: global.vcMeetingAgent?.enabled !== false,
684
811
  listenerBotAppId: global.vcMeetingAgent?.listenerBotAppId ?? null,
@@ -707,6 +834,7 @@ async function reloadLocaleOnAllDaemons() {
707
834
  const settingsWriteApplierDeps = defaultSettingsWriteApplierDeps(resolveDashboardSettings, reloadLocaleOnAllDaemons);
708
835
  settingsWriteApplierDeps.syncVcMeetingListenerBotConfig = syncVcMeetingListenerBotConfig;
709
836
  settingsWriteApplierDeps.validateVcMeetingListenerBotAppId = validateVcMeetingListenerBotAppId;
837
+ settingsWriteApplierDeps.validateCodexNotifierTargetBotAppId = validateCodexNotifierTargetBotAppId;
710
838
  /** Helper to render a {status, body} HandlerResult through `res`. */
711
839
  function writeHandlerResult(res, result) {
712
840
  const headers = { 'content-type': 'application/json', ...(result.headers ?? {}) };
@@ -940,6 +1068,29 @@ registry.on(syncSubscriptions);
940
1068
  // Initial attach for every daemon already known. Run in parallel so a slow
941
1069
  // daemon doesn't block the others.
942
1070
  await Promise.all(registry.list().map(attachDaemon));
1071
+ const codexNotifierAbort = new AbortController();
1072
+ if (resolveCodexNotifierConfig().enabled) {
1073
+ try {
1074
+ installCodexNotifierHook();
1075
+ }
1076
+ catch (error) {
1077
+ logger.warn(`[codex-notifier] Hook reconcile failed: ${error instanceof Error ? error.message : String(error)}`);
1078
+ }
1079
+ }
1080
+ void runCodexNotifierWorkerSupervisor({
1081
+ dataDir: config.session.dataDir,
1082
+ signal: codexNotifierAbort.signal,
1083
+ emit: item => emitCodexNotifierOutboxItem(item, { signal: codexNotifierAbort.signal }),
1084
+ runProducer: signal => runCodexSideConversationMonitor({
1085
+ dataDir: config.session.dataDir,
1086
+ signal,
1087
+ logger,
1088
+ }),
1089
+ logger,
1090
+ onLeaseUnavailable: path => {
1091
+ logger.warn(`[codex-notifier] outbox worker 已由另一 Dashboard 持有,等待接管:${path}`);
1092
+ },
1093
+ });
943
1094
  const resourceMonitor = createResourceMonitorService({
944
1095
  intervalMs: 10_000,
945
1096
  topSessionLimit: 30,
@@ -2104,14 +2255,15 @@ const server = createServer(async (req, res) => {
2104
2255
  return jsonRes(res, 200, { ok: true });
2105
2256
  }
2106
2257
  const presentedToken = authedToken(req, url);
2107
- const dashboardSettings = resolveDashboardSettings();
2258
+ const globalDashboardConfig = readGlobalConfig().dashboard;
2108
2259
  const decision = decideDashboardAuth({
2109
2260
  method: req.method ?? 'GET',
2110
2261
  pathname: url.pathname,
2111
2262
  hasTokenParam: url.searchParams.has('t'),
2112
2263
  presentedToken,
2113
2264
  activeToken: activeToken ?? '',
2114
- publicReadOnly: dashboardSettings.publicReadOnly,
2265
+ publicReadOnly: globalDashboardConfig?.publicReadOnly
2266
+ ?? config.dashboard.publicReadOnly,
2115
2267
  });
2116
2268
  // `authed` is consumed by route handlers that distinguish the public-read
2117
2269
  // carve-out from a valid management cookie (notably v3 run details).
@@ -2160,6 +2312,16 @@ const server = createServer(async (req, res) => {
2160
2312
  && await handlePluginManagementApi(req, res, url)) {
2161
2313
  return;
2162
2314
  }
2315
+ // 调试终端(owner-only):HTTP 路由挂在 auth gate 之后 → 已确保是管理 token。
2316
+ // /api/debug-terminal(创建/关闭)+ /debug-terminal/<id>(xterm 页面)。
2317
+ // WS 升级 /debug-terminal/<id>/ws 在下方 server.on('upgrade') 里由本 manager
2318
+ // 自行校验 cookie(upgrade 不经这段 gate)。
2319
+ if (url.pathname === '/api/debug-terminal'
2320
+ || url.pathname.startsWith('/api/debug-terminal/')
2321
+ || url.pathname.startsWith('/debug-terminal/')) {
2322
+ if (debugTerminalManager.handleHttp(req, res, url))
2323
+ return;
2324
+ }
2163
2325
  if (req.method === 'GET' && url.pathname === '/api/plugins/dashboard') {
2164
2326
  return jsonRes(res, 200, { plugins: listDashboardPluginEntries() });
2165
2327
  }
@@ -2326,6 +2488,7 @@ const server = createServer(async (req, res) => {
2326
2488
  return jsonRes(res, 200, { schedules, timezone: scheduleTimeZone() });
2327
2489
  }
2328
2490
  if (req.method === 'GET' && url.pathname === '/api/settings') {
2491
+ const dashboardSettings = resolveDashboardSettings();
2329
2492
  // `authed` lets the Settings page disable toggles for read-only
2330
2493
  // visitors up front, instead of letting them flip a switch that
2331
2494
  // 401s + rolls back on save.
@@ -2335,7 +2498,7 @@ const server = createServer(async (req, res) => {
2335
2498
  // `bound` reflects central-platform binding; the Settings UI only shows the
2336
2499
  // 远程访问 toggle when bound (the central URLs are meaningless otherwise).
2337
2500
  return jsonRes(res, 200, {
2338
- settings: dashboardSettings,
2501
+ settings: authed ? dashboardSettings : redactSettingsForPublic(dashboardSettings),
2339
2502
  lang: readGlobalConfig().lang ?? null,
2340
2503
  authed,
2341
2504
  bound: readPlatformBinding() !== null,
@@ -3053,6 +3216,14 @@ const server = createServer(async (req, res) => {
3053
3216
  return jsonRes(res, 400, { ok: false, error: 'missing_expected_identity', message: '免扫码添加前必须确认当前账号与企业' });
3054
3217
  }
3055
3218
  const sessionMode = sessionModeRaw === 'reuse' ? 'reuse' : 'qr';
3219
+ if (parsed.requireCriticalScopesBeforeActivation !== undefined
3220
+ && typeof parsed.requireCriticalScopesBeforeActivation !== 'boolean') {
3221
+ return jsonRes(res, 400, {
3222
+ ok: false,
3223
+ error: 'invalid_critical_scope_activation_gate',
3224
+ message: 'requireCriticalScopesBeforeActivation 必须是 boolean',
3225
+ });
3226
+ }
3056
3227
  const job = botOnboarding.start({
3057
3228
  appName,
3058
3229
  registrationMode,
@@ -3062,9 +3233,93 @@ const server = createServer(async (req, res) => {
3062
3233
  workingDir,
3063
3234
  dirMode,
3064
3235
  model,
3236
+ ...(parsed.requireCriticalScopesBeforeActivation === true
3237
+ ? { requireCriticalScopesBeforeActivation: true }
3238
+ : {}),
3065
3239
  });
3066
3240
  return jsonRes(res, 202, { job: botOnboarding.get(job.id) });
3067
3241
  }
3242
+ if (req.method === 'POST' && url.pathname === '/api/bot-onboarding/recover-permissions') {
3243
+ let parsed;
3244
+ try {
3245
+ const chunks = [];
3246
+ for await (const c of req)
3247
+ chunks.push(c);
3248
+ const raw = Buffer.concat(chunks).toString('utf8');
3249
+ parsed = raw ? JSON.parse(raw) : {};
3250
+ }
3251
+ catch {
3252
+ return jsonRes(res, 400, { ok: false, error: 'bad_json' });
3253
+ }
3254
+ const workingDir = typeof parsed.workingDir === 'string' ? parsed.workingDir.trim() : '';
3255
+ const predecessorJobId = typeof parsed.predecessorJobId === 'string' ? parsed.predecessorJobId.trim() : '';
3256
+ const expectedAppId = typeof parsed.expectedAppId === 'string' ? parsed.expectedAppId.trim() : '';
3257
+ const priorRecoveryJobId = typeof parsed.priorRecoveryJobId === 'string' ? parsed.priorRecoveryJobId.trim() : undefined;
3258
+ if (parsed.requireCriticalScopesBeforeActivation !== undefined
3259
+ && typeof parsed.requireCriticalScopesBeforeActivation !== 'boolean') {
3260
+ return jsonRes(res, 400, {
3261
+ ok: false,
3262
+ error: 'invalid_critical_scope_activation_gate',
3263
+ message: 'requireCriticalScopesBeforeActivation 必须是 boolean',
3264
+ });
3265
+ }
3266
+ if (!workingDir || !predecessorJobId || !expectedAppId || invalidWorkingDirs({ workingDir }).length > 0) {
3267
+ return jsonRes(res, 400, { ok: false, error: 'permission_recovery_target_invalid' });
3268
+ }
3269
+ const recovered = botOnboarding.startPermissionRecovery({
3270
+ workingDir,
3271
+ predecessorJobId,
3272
+ expectedAppId,
3273
+ priorRecoveryJobId,
3274
+ ...(parsed.requireCriticalScopesBeforeActivation === true
3275
+ ? { requireCriticalScopesBeforeActivation: true }
3276
+ : {}),
3277
+ });
3278
+ if (!recovered.ok) {
3279
+ const status = recovered.error === 'permission_recovery_target_missing' ? 404
3280
+ : recovered.error === 'permission_recovery_target_ambiguous' ? 409
3281
+ : recovered.error === 'permission_recovery_state_unavailable' ? 503
3282
+ : 400;
3283
+ return jsonRes(res, status, recovered);
3284
+ }
3285
+ return jsonRes(res, 202, { job: botOnboarding.get(recovered.job.id) });
3286
+ }
3287
+ let mScopePropagation;
3288
+ if (req.method === 'POST'
3289
+ && (mScopePropagation = url.pathname.match(/^\/api\/bot-onboarding\/([^/]+)\/complete-scope-propagation$/))) {
3290
+ const onboardingId = decodeURIComponent(mScopePropagation[1]);
3291
+ let parsed;
3292
+ try {
3293
+ const chunks = [];
3294
+ for await (const c of req)
3295
+ chunks.push(c);
3296
+ const raw = Buffer.concat(chunks).toString('utf8');
3297
+ parsed = raw ? JSON.parse(raw) : {};
3298
+ }
3299
+ catch {
3300
+ return jsonRes(res, 400, { ok: false, error: 'bad_json' });
3301
+ }
3302
+ const workingDir = typeof parsed.workingDir === 'string' ? parsed.workingDir.trim() : '';
3303
+ const expectedAppId = typeof parsed.expectedAppId === 'string' ? parsed.expectedAppId.trim() : '';
3304
+ if (!workingDir || !expectedAppId || invalidWorkingDirs({ workingDir }).length > 0) {
3305
+ return jsonRes(res, 400, { ok: false, error: 'permission_recovery_target_invalid' });
3306
+ }
3307
+ const completed = await botOnboarding.completeScopePropagation({
3308
+ jobId: onboardingId,
3309
+ workingDir,
3310
+ expectedAppId,
3311
+ });
3312
+ if (!completed.ok) {
3313
+ const status = completed.error === 'permission_recovery_target_missing' ? 404
3314
+ : completed.error === 'permission_recovery_target_ambiguous' ? 409
3315
+ : completed.error === 'permission_recovery_scopes_pending' ? 425
3316
+ : (completed.error === 'permission_recovery_state_unavailable'
3317
+ || completed.error === 'permission_recovery_activation_failed') ? 503
3318
+ : 400;
3319
+ return jsonRes(res, status, completed);
3320
+ }
3321
+ return jsonRes(res, 200, { job: botOnboarding.get(onboardingId) });
3322
+ }
3068
3323
  let mOwner;
3069
3324
  if (req.method === 'POST' && (mOwner = url.pathname.match(/^\/api\/bot-onboarding\/([^/]+)\/owner$/))) {
3070
3325
  // needs_owner 状态下用户手动提交 owner:扫码人身份验证不了时的兜底入口。
@@ -3219,6 +3474,18 @@ const server = createServer(async (req, res) => {
3219
3474
  res.end(await upstream.text());
3220
3475
  return;
3221
3476
  }
3477
+ // Dashboard「复现命令」:透传到 owning daemon 取该 session 的真实 CLI 调用。
3478
+ // 与 write-link 同样只在管理 cookie(写权限)下可达:命令含 token/凭证。
3479
+ if (req.method === 'GET' && (m = url.pathname.match(/^\/api\/sessions\/([^/]+)\/spawn-command$/))) {
3480
+ const sid = decodeURIComponent(m[1]);
3481
+ const owner = aggregator.ownerOf(sid);
3482
+ if (!owner)
3483
+ return jsonRes(res, 404, { ok: false, error: 'unknown_session' });
3484
+ const upstream = await proxyToDaemon(owner, `/api/sessions/${sid}/spawn-command`, { method: 'GET' });
3485
+ res.writeHead(upstream.status, { 'content-type': 'application/json' });
3486
+ res.end(await upstream.text());
3487
+ return;
3488
+ }
3222
3489
  // Sandbox landing: review the clone's diff (GET) then apply/discard (POST).
3223
3490
  if (req.method === 'GET' && (m = url.pathname.match(/^\/api\/sessions\/([^/]+)\/sandbox-diff$/))) {
3224
3491
  const sid = decodeURIComponent(m[1]);
@@ -4325,7 +4592,20 @@ const server = createServer(async (req, res) => {
4325
4592
  const hb = setInterval(() => {
4326
4593
  res.write(`event: heartbeat\ndata: ${JSON.stringify({ ts: Date.now() })}\n\n`);
4327
4594
  }, 15_000);
4328
- res.on('close', () => { off(); clearInterval(hb); });
4595
+ // Push a bots.changed frame whenever the online bot roster actually
4596
+ // changes (bot added / removed / renamed / re-indexed) so the Bot 配置
4597
+ // page can auto-refresh without a manual reload. registry.on fires on
4598
+ // every 15s poll and 30s heartbeat rewrite, so gate on a roster signature
4599
+ // that ignores lastHeartbeat — otherwise we'd spam a frame every poll.
4600
+ let lastRoster = botsRosterSignature(registry.list());
4601
+ const offRoster = registry.on(online => {
4602
+ const sig = botsRosterSignature(online);
4603
+ if (sig === lastRoster)
4604
+ return;
4605
+ lastRoster = sig;
4606
+ res.write(`event: bots.changed\ndata: ${JSON.stringify({ body: { signature: sig } })}\n\n`);
4607
+ });
4608
+ res.on('close', () => { off(); offRoster(); clearInterval(hb); });
4329
4609
  return;
4330
4610
  }
4331
4611
  // Public API + static frontend land in Task 17 / 18. For now: 404.
@@ -4346,6 +4626,11 @@ const server = createServer(async (req, res) => {
4346
4626
  server.on('upgrade', (req, clientSocket, head) => {
4347
4627
  try {
4348
4628
  const rawUrl = req.url ?? '/';
4629
+ // 调试终端 WS(owner-only):manager 内部自校验管理 cookie。命中即接管。
4630
+ if (rawUrl.startsWith('/debug-terminal/')) {
4631
+ if (debugTerminalManager.handleUpgrade(req, clientSocket, head))
4632
+ return;
4633
+ }
4349
4634
  if (!(rawUrl === '/s' || rawUrl.startsWith('/s/') || rawUrl.startsWith('/s?'))) {
4350
4635
  return clientSocket.destroy();
4351
4636
  }
@@ -4671,12 +4956,14 @@ async function maybeAnnounceHallPresence() {
4671
4956
  }
4672
4957
  // Graceful shutdown
4673
4958
  function shutdown() {
4959
+ codexNotifierAbort.abort();
4674
4960
  for (const off of subs.values())
4675
4961
  off();
4676
4962
  subs.clear();
4677
4963
  registry.stop();
4678
4964
  resourceMonitor.stop();
4679
4965
  platformTunnel?.stop();
4966
+ debugTerminalManager.shutdown();
4680
4967
  server.close(() => process.exit(0));
4681
4968
  // Hard-exit fallback after 5s
4682
4969
  setTimeout(() => process.exit(0), 5_000).unref();