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
@@ -3,8 +3,7 @@ import { config } from '../../config.js';
3
3
  import { getBot, getAllBots, getOwnerOpenId } from '../../bot-registry.js';
4
4
  import { canOperate, canTalk } from './event-dispatcher.js';
5
5
  import { updateMessage, deleteMessage, replyMessage, sendMessage, sendUserMessage, sendEphemeralCard, getMessageDetail, isHumanOpenId, resolveUserUnionId as defaultResolveUserUnionId } from './client.js';
6
- import { buildSessionCard, buildStreamingCard, buildTuiPromptCard, buildTuiPromptProcessingCard, buildTuiPromptResolvedCard, buildGrantResultCard, buildGrantNotifyCard, getCliDisplayName, truncateContent, buildConfigCard, buildConfigTextCard, CONFIG_UNSET, buildLandResultCard, buildRepoSelectCard } from './card-builder.js';
7
- import { computeSandboxDiff, applySandboxDiff } from '../../services/sandbox-land.js';
6
+ import { buildSessionCard, buildStreamingCard, buildTuiPromptCard, buildTuiPromptProcessingCard, buildTuiPromptResolvedCard, buildGrantResultCard, buildGrantNotifyCard, getCliDisplayName, truncateContent, buildConfigCard, buildConfigTextCard, CONFIG_UNSET, buildRepoSelectCard } from './card-builder.js';
8
7
  import { findConfigField, applyConfigField, coerceConfigValue, getConfigCardData } from '../../services/bot-config-store.js';
9
8
  import { updateBotGrantPrefs } from '../../services/grant-prefs-store.js';
10
9
  import { writeTeamRoleFile, deleteTeamRoleFile } from '../../core/role-resolver.js';
@@ -195,6 +194,17 @@ function duplicateMultiWorktreeChildNames(repoPaths, projects) {
195
194
  }
196
195
  return [...dupes];
197
196
  }
197
+ function deferRepoCardWithdraw(larkAppId, messageId) {
198
+ if (!larkAppId || !messageId)
199
+ return;
200
+ // Let the card-action promise resolve so the SDK can send its callback ACK
201
+ // before the original card disappears. A microtask is too early here: it may
202
+ // run before the SDK continuation that serializes and writes the ACK frame.
203
+ setImmediate(() => {
204
+ void deleteMessage(larkAppId, messageId)
205
+ .catch(err => logger.debug(`Repo card withdraw (post-callback) failed: ${err}`));
206
+ });
207
+ }
198
208
  /**
199
209
  * Commit a resolved working directory onto a repo-select session: pin it, then
200
210
  * either fork the pending CLI (first selection) or close + recreate the session
@@ -342,8 +352,9 @@ opts) {
342
352
  const cardToWithdraw = cardMessageId ?? ds.repoCardMessageId;
343
353
  markRepoCardConsumed(ds, cardToWithdraw);
344
354
  ds.repoCardMessageId = undefined;
345
- // Hold the claim through confirmation + best-effort card withdraw so a
346
- // concurrent in-flight select still sees pendingRepoCommitInFlight.
355
+ // Hold the claim through confirmation. Card withdrawal is deferred until
356
+ // after the callback can ACK; stale clicks are blocked by the local
357
+ // consume mark above rather than by the network request's lifetime.
347
358
  try {
348
359
  if (!opts?.suppressConfirmReply) {
349
360
  // A card click has no turn of its own — anchor the confirmation to the
@@ -358,12 +369,7 @@ opts) {
358
369
  catch (e) {
359
370
  logger.warn(`[${tag(ds)}] Confirm reply after pending repo commit failed: ${e instanceof Error ? e.message : e}`);
360
371
  }
361
- if (cardToWithdraw && larkAppId) {
362
- try {
363
- await deleteMessage(larkAppId, cardToWithdraw);
364
- }
365
- catch { /* card may already be gone */ }
366
- }
372
+ deferRepoCardWithdraw(larkAppId, cardToWithdraw);
367
373
  }
368
374
  finally {
369
375
  ds.pendingRepoCommitInFlight = false;
@@ -457,13 +463,9 @@ opts) {
457
463
  }
458
464
  }
459
465
  logger.info(`[${tag(ds)}] Repo switched to ${dirPath}, new session created`);
460
- // Best-effort withdraw card already claimed above.
461
- if (claimedCard && larkAppId) {
462
- try {
463
- await deleteMessage(larkAppId, claimedCard);
464
- }
465
- catch { /* best-effort */ }
466
- }
466
+ // The card was claimed locally above; withdraw it only after this callback
467
+ // can return its ACK so the delete request cannot race the callback frame.
468
+ deferRepoCardWithdraw(larkAppId, claimedCard);
467
469
  }
468
470
  }
469
471
  /**
@@ -535,34 +537,6 @@ export async function handleCardAction(data, deps, larkAppId) {
535
537
  // Use the receiving bot's allowedUsers — the operator open_id in card actions
536
538
  // is scoped to the app that received the callback.
537
539
  const operatorOpenId = data?.operator?.open_id;
538
- // ─── 沙盒落盘卡(land_apply / land_discard)──────────────────────────────────
539
- // 不绑 session(sessionId + workingDir 都在 value 里)。owner 强闸门:只有 owner 能把
540
- // 隔离副本的改动应用回真实磁盘。agent 在沙盒里无感,不参与。
541
- if (value?.action && (value.action === 'land_apply' || value.action === 'land_discard') && larkAppId) {
542
- const loc = localeForBot(larkAppId);
543
- const owner = getOwnerOpenId(larkAppId);
544
- if (!operatorOpenId || operatorOpenId !== owner) {
545
- logger.info(`Land action "${value.action}" blocked for non-owner: ${operatorOpenId}`);
546
- return { toast: { type: 'error', content: t('card.land.toast_owner_only', undefined, loc) } };
547
- }
548
- if (value.action === 'land_discard') {
549
- return JSON.parse(buildLandResultCard('discarded', '', loc));
550
- }
551
- const sid = value.sessionId;
552
- const wd = value.workingDir;
553
- if (!sid || !wd)
554
- return JSON.parse(buildLandResultCard('failed', t('card.land.stale', undefined, loc), loc));
555
- const d = computeSandboxDiff(config.session.dataDir, sid, loc);
556
- if (!d.ok)
557
- return JSON.parse(buildLandResultCard('failed', d.error, loc));
558
- if (d.empty)
559
- return JSON.parse(buildLandResultCard('discarded', '', loc));
560
- const a = applySandboxDiff(wd, config.session.dataDir, sid, loc);
561
- if (!a.ok)
562
- return JSON.parse(buildLandResultCard('failed', a.error, loc));
563
- logger.info(`Land applied: ${d.files} files (+${d.insertions}/-${d.deletions}) → ${wd}`);
564
- return JSON.parse(buildLandResultCard('applied', t('card.land.applied_body', { files: d.files, ins: d.insertions, del: d.deletions, dir: wd }, loc), loc));
565
- }
566
540
  // ─── 群内授权卡片动作(grant_chat / grant_global / grant_deny,talk-only)─────
567
541
  // 不绑定 session,必须在 session 解析之前处理。owner 强闸门 + nonce 校验。
568
542
  if (value?.action && (value.action === 'grant_chat' || value.action === 'grant_global' || value.action === 'grant_deny') && larkAppId) {
@@ -713,6 +687,17 @@ export async function handleCardAction(data, deps, larkAppId) {
713
687
  if (isAskCardAction(value?.action)) {
714
688
  return handleAskCardAction(data);
715
689
  }
690
+ if ((value?.action === 'codex_notifier_continue' || value?.action === 'codex_notifier_open_app')
691
+ && larkAppId) {
692
+ if (!operatorOpenId) {
693
+ logger.info(`${value.action} blocked because operator identity is missing`);
694
+ return { toast: { type: 'error', content: '只有机器人管理员可以操作此 Codex 任务' } };
695
+ }
696
+ if (!deps.codexNotifierCardAction) {
697
+ return { toast: { type: 'error', content: 'Codex 完成通知处理器未启用' } };
698
+ }
699
+ return deps.codexNotifierCardAction(data, larkAppId);
700
+ }
716
701
  if (typeof value?.action === 'string' &&
717
702
  value.action.startsWith('vc_meeting_') &&
718
703
  larkAppId) {
@@ -1547,6 +1532,17 @@ export async function handleCardAction(data, deps, larkAppId) {
1547
1532
  return;
1548
1533
  }
1549
1534
  if (actionType === 'tui_keys' && ds) {
1535
+ // Fail-closed: only act on a currently-active card (either the
1536
+ // ScreenAnalyzer TUI prompt card or our stuck-warning card). A stale
1537
+ // click from a resolved/replaced card must NOT send any IPC to the
1538
+ // worker — the CLI may have moved on or recovered. PATCH is UI only,
1539
+ // not an authorization check.
1540
+ const isActiveTuiCard = !!ds.tuiPromptCardId && cardMessageId === ds.tuiPromptCardId;
1541
+ const isActiveStuckCard = !!ds.stuckWarningCardId && cardMessageId === ds.stuckWarningCardId;
1542
+ if (!isActiveTuiCard && !isActiveStuckCard) {
1543
+ logger.info(`[${tag(ds)}] tui_keys from stale card ${cardMessageId} — ignored (active tui=${ds.tuiPromptCardId ?? 'none'} stuck=${ds.stuckWarningCardId ?? 'none'})`);
1544
+ return;
1545
+ }
1550
1546
  let keys = [];
1551
1547
  try {
1552
1548
  keys = JSON.parse(value?.keys ?? '[]');
@@ -1557,6 +1553,12 @@ export async function handleCardAction(data, deps, larkAppId) {
1557
1553
  const selectedIndex = Number(value?.selected_index ?? 0);
1558
1554
  const selectedText = value?.selected_text ?? `Option ${selectedIndex + 1}`;
1559
1555
  if (optionType === 'toggle') {
1556
+ // Only a ScreenAnalyzer TUI card may own toggle state. A stuck-warning
1557
+ // card must never read or mutate the other card's global selections.
1558
+ if (!isActiveTuiCard) {
1559
+ logger.info(`[${tag(ds)}] Ignored toggle from non-TUI card ${cardMessageId}`);
1560
+ return;
1561
+ }
1560
1562
  // Toggle: only update card UI, do NOT send keys to terminal yet.
1561
1563
  // Keys will be sent in batch when confirm is clicked.
1562
1564
  if (!ds.tuiToggledIndices)
@@ -1579,10 +1581,15 @@ export async function handleCardAction(data, deps, larkAppId) {
1579
1581
  }
1580
1582
  return;
1581
1583
  }
1582
- // For confirm: batch all toggled options' keys first, then confirm keys
1584
+ // For a normal TUI confirm: batch all toggled options' keys first.
1585
+ // For a stuck-warning card: derive the single allowed key from the
1586
+ // page type + selected index — NEVER trust value.keys from the card,
1587
+ // which could be tampered to inject arbitrary keys. The allowlist is
1588
+ // exactly the documented controls for each Codex hook-review screen.
1583
1589
  if (ds.worker) {
1584
1590
  let allKeys = [];
1585
- if (ds.tuiToggledIndices?.length && ds.tuiPromptOptions) {
1591
+ let isFinalStuck = false;
1592
+ if (isActiveTuiCard && ds.tuiToggledIndices?.length && ds.tuiPromptOptions) {
1586
1593
  // Send each toggled option's keys in sequence
1587
1594
  for (const ti of ds.tuiToggledIndices.sort((a, b) => a - b)) {
1588
1595
  const opt = ds.tuiPromptOptions[ti];
@@ -1590,29 +1597,116 @@ export async function handleCardAction(data, deps, larkAppId) {
1590
1597
  allKeys.push(...opt.keys);
1591
1598
  }
1592
1599
  }
1600
+ // Then the action's own keys (confirm/select)
1601
+ allKeys.push(...keys);
1602
+ }
1603
+ else if (isActiveStuckCard) {
1604
+ // P1-4: do NOT trust the callback's selected_index. Require it to be
1605
+ // present and a safe integer, then range-check against the page type's
1606
+ // option count. A missing/malformed index must NOT default to 0 (trust),
1607
+ // which is the highest-risk action.
1608
+ const rawIdx = value?.selected_index;
1609
+ if (rawIdx === undefined || rawIdx === null || rawIdx === '') {
1610
+ logger.info(`[${tag(ds)}] Stuck-warning card click missing selected_index — dropped`);
1611
+ return;
1612
+ }
1613
+ const idx = Number(rawIdx);
1614
+ if (!Number.isSafeInteger(idx)) {
1615
+ logger.info(`[${tag(ds)}] Stuck-warning card click with non-integer selected_index=${rawIdx} — dropped`);
1616
+ return;
1617
+ }
1618
+ // Allowlist: map (pageType, idx) → the one safe key.
1619
+ // Level 1: 0=t, 1=Enter, 2=Esc ; Level 2: 0=t, 1=Esc
1620
+ const pt = ds.stuckWarningPageType;
1621
+ const allowlist = pt === 'hook review level 1'
1622
+ ? ['t', 'Enter', 'Escape']
1623
+ : pt === 'hook review level 2'
1624
+ ? ['t', 'Escape']
1625
+ : null;
1626
+ if (!allowlist || idx < 0 || idx >= allowlist.length) {
1627
+ logger.info(`[${tag(ds)}] Stuck-warning card click with out-of-range index ${idx} for pageType=${pt ?? 'none'} — dropped`);
1628
+ return;
1629
+ }
1630
+ allKeys = [allowlist[idx]];
1631
+ // Stuck-card actions are always final (they resolve the current
1632
+ // hook-review screen). Define this server-side — do NOT trust
1633
+ // value.is_final from the callback.
1634
+ isFinalStuck = true;
1635
+ }
1636
+ else {
1637
+ // Non-stuck, non-TUI card (shouldn't happen given the active-card
1638
+ // guard above, but fail-closed).
1639
+ allKeys.push(...keys);
1593
1640
  }
1594
- // Then the action's own keys (confirm/select)
1595
- allKeys.push(...keys);
1596
1641
  if (allKeys.length > 0) {
1597
- ds.worker.send({ type: 'tui_keys', keys: allKeys, isFinal });
1598
- logger.info(`[${tag(ds)}] TUI keys: [${allKeys.join(',')}] final=${isFinal} "${selectedText}"`);
1642
+ // Atomic processing claim: if a previous click is already in flight
1643
+ // (waiting for tui_keys_delivered / stuck_warning_expired ACK), drop
1644
+ // this duplicate. Without this, two rapid clicks could both pass the
1645
+ // fresh-capture guard and inject keys twice.
1646
+ if (isActiveStuckCard) {
1647
+ if (ds.stuckWarningProcessing) {
1648
+ logger.info(`[${tag(ds)}] Duplicate stuck-warning card click — dropped (processing already in flight)`);
1649
+ return;
1650
+ }
1651
+ ds.stuckWarningProcessing = true;
1652
+ }
1653
+ // Only the stuck-warning card's Enter action re-arms the detector
1654
+ // (Enter advances from the hook list to a per-hook review). Match by
1655
+ // the actual keys sent — NOT by optionType, since t is typed 'confirm'
1656
+ // in the card definition. t/Esc and all ScreenAnalyzer cards never
1657
+ // set this flag. Also require the source card to be our own.
1658
+ const isStuckWarningEnter = isActiveStuckCard
1659
+ && allKeys.length === 1
1660
+ && allKeys[0] === 'Enter';
1661
+ // If this click is from a stuck-warning card, forward the nonce,
1662
+ // cliLifetime, and page type so the worker can re-verify the current
1663
+ // screen still matches before injecting keys. A stale click (CLI
1664
+ // recovered) will be dropped at the worker boundary.
1665
+ const stuckNonce = isActiveStuckCard ? ds.stuckWarningNonce : undefined;
1666
+ const stuckCliLifetime = isActiveStuckCard ? ds.stuckWarningCliLifetime : undefined;
1667
+ const stuckPage = isActiveStuckCard ? ds.stuckWarningPageType : undefined;
1668
+ const effectiveFinal = isFinal || isFinalStuck;
1669
+ ds.worker.send({ type: 'tui_keys', keys: allKeys, isFinal: effectiveFinal, rearmStuckDetector: isStuckWarningEnter, stuckNonce, stuckCliLifetime, stuckPageType: stuckPage });
1670
+ logger.info(`[${tag(ds)}] TUI keys: [${allKeys.join(',')}] final=${effectiveFinal} rearmStuck=${isStuckWarningEnter} stuckNonce=${stuckNonce ?? 'none'} — "${selectedText}"`);
1599
1671
  }
1600
- if (isFinal) {
1601
- const resolveText = ds.tuiToggledIndices?.length
1672
+ if (isFinal || isFinalStuck) {
1673
+ const resolveText = isActiveTuiCard && ds.tuiToggledIndices?.length
1602
1674
  ? ds.tuiToggledIndices.map(i => ds.tuiPromptOptions?.[i]?.text).filter(Boolean).join(', ')
1603
1675
  : selectedText;
1604
1676
  const finalText = resolveText || selectedText;
1605
1677
  const locDs = localeForBot(ds.larkAppId);
1678
+ // For a stuck-warning card, do NOT clear authority or render success
1679
+ // here. The worker may still reject the keys (stale screen). We show a
1680
+ // "processing" state to block duplicate clicks, and wait for the
1681
+ // worker's tui_keys_delivered (success) or stuck_warning_expired
1682
+ // ("page changed, not sent") ACK before resolving the card.
1683
+ if (isActiveStuckCard) {
1684
+ if (cardMessageId) {
1685
+ const processingCard = buildTuiPromptProcessingCard('处理中…', locDs);
1686
+ updateMessage(ds.larkAppId, cardMessageId, processingCard).catch(err => logger.debug(`[${tag(ds)}] Failed to set stuck-warning card to processing: ${err}`));
1687
+ }
1688
+ publishAttentionPatch(ds);
1689
+ try {
1690
+ return JSON.parse(buildTuiPromptProcessingCard('处理中…', locDs));
1691
+ }
1692
+ catch { /* fall through */ }
1693
+ }
1694
+ // Normal TUI prompt card (ScreenAnalyzer): resolve immediately.
1606
1695
  if (cardMessageId) {
1607
1696
  setTimeout(() => {
1608
1697
  const resolvedCard = buildTuiPromptResolvedCard(finalText, locDs);
1609
1698
  updateMessage(ds.larkAppId, cardMessageId, resolvedCard).catch(err => logger.debug(`[${tag(ds)}] Failed to update TUI prompt card: ${err}`));
1610
1699
  }, allKeys.length * 100 + 500);
1611
1700
  }
1612
- ds.tuiPromptCardId = undefined;
1613
- ds.tuiPromptOptions = undefined;
1614
- ds.tuiPromptMultiSelect = undefined;
1615
- ds.tuiToggledIndices = undefined;
1701
+ // Clear state only for the card that was actually clicked — a stuck
1702
+ // card click must NOT wipe the ScreenAnalyzer TUI prompt state (or
1703
+ // vice versa) if both coexist / race.
1704
+ if (cardMessageId === ds.tuiPromptCardId) {
1705
+ ds.tuiPromptCardId = undefined;
1706
+ ds.tuiPromptOptions = undefined;
1707
+ ds.tuiPromptMultiSelect = undefined;
1708
+ ds.tuiToggledIndices = undefined;
1709
+ }
1616
1710
  publishAttentionPatch(ds);
1617
1711
  try {
1618
1712
  return JSON.parse(buildTuiPromptProcessingCard(finalText, locDs));
@@ -1883,8 +1977,7 @@ export async function handleCardAction(data, deps, larkAppId) {
1883
1977
  }
1884
1978
  else {
1885
1979
  await sessionReply(rootId, t('card.action.continue_using_current_repo', { cwd: getSessionWorkingDir(ds) }, locDs));
1886
- if (cardMessageId && larkAppId)
1887
- deleteMessage(larkAppId, cardMessageId);
1980
+ deferRepoCardWithdraw(larkAppId, cardMessageId);
1888
1981
  ds.repoCardMessageId = undefined;
1889
1982
  }
1890
1983
  }
@@ -2065,8 +2158,9 @@ export async function handleCardAction(data, deps, larkAppId) {
2065
2158
  catch {
2066
2159
  return;
2067
2160
  }
2068
- // Re-discover to get full session info and validate. Backend determines
2069
- // which discovery to run (re-confirms the pane + pid are still alive).
2161
+ // Re-discover to get full session info and validate. Keep the same CLI
2162
+ // filter used to build the card so a stale/tampered option cannot switch
2163
+ // this bot to a different agent implementation.
2070
2164
  const botCfg = getBot(ds.larkAppId).config;
2071
2165
  let target;
2072
2166
  async function resolveAdoptTarget() {
@@ -2080,9 +2174,17 @@ export async function handleCardAction(data, deps, larkAppId) {
2080
2174
  return discoverAdoptableZellijSessions(botCfg.cliId)
2081
2175
  .find(s => s.zellijSession === selected.zellijSession && s.zellijPaneId === selected.zellijPaneId);
2082
2176
  }
2083
- const { discoverAdoptableSessions, adoptTargetKey } = await import('../../core/session-discovery.js');
2084
- return discoverAdoptableSessions(botCfg.cliId)
2085
- .find(s => selected.key
2177
+ const { discoverAdoptableSessions, excludeOwnedHerdrAdoptTargets, adoptTargetKey } = await import('../../core/session-discovery.js');
2178
+ const ownedHerdrTargets = [...activeSessions.values()].flatMap(active => {
2179
+ const target = active.session.persistentBackendTarget;
2180
+ return active.session.status === 'active'
2181
+ && !active.adoptedFrom
2182
+ && target?.backendType === 'herdr'
2183
+ && !!target.agentName
2184
+ ? [{ sessionName: target.sessionName, agentName: target.agentName }]
2185
+ : [];
2186
+ });
2187
+ return excludeOwnedHerdrAdoptTargets(discoverAdoptableSessions(botCfg.cliId), ownedHerdrTargets).find(s => selected.key
2086
2188
  ? adoptTargetKey(s) === selected.key
2087
2189
  : s.tmuxTarget === selected.tmuxTarget && s.cliPid === selected.cliPid);
2088
2190
  }