botmux 3.5.2 → 3.6.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 (458) hide show
  1. package/README.en.md +56 -396
  2. package/README.md +55 -396
  3. package/dist/.runtime-build-id +1 -0
  4. package/dist/adapters/cli/claude-code.d.ts +6 -0
  5. package/dist/adapters/cli/claude-code.d.ts.map +1 -1
  6. package/dist/adapters/cli/claude-code.js +197 -11
  7. package/dist/adapters/cli/claude-code.js.map +1 -1
  8. package/dist/adapters/cli/coco.js +4 -4
  9. package/dist/adapters/cli/coco.js.map +1 -1
  10. package/dist/adapters/cli/codex-app.d.ts.map +1 -1
  11. package/dist/adapters/cli/codex-app.js +9 -6
  12. package/dist/adapters/cli/codex-app.js.map +1 -1
  13. package/dist/adapters/cli/codex.js +5 -5
  14. package/dist/adapters/cli/codex.js.map +1 -1
  15. package/dist/adapters/cli/fs-policy.d.ts.map +1 -1
  16. package/dist/adapters/cli/fs-policy.js +5 -7
  17. package/dist/adapters/cli/fs-policy.js.map +1 -1
  18. package/dist/adapters/cli/grok.d.ts +2 -1
  19. package/dist/adapters/cli/grok.d.ts.map +1 -1
  20. package/dist/adapters/cli/grok.js +2 -1
  21. package/dist/adapters/cli/grok.js.map +1 -1
  22. package/dist/adapters/cli/hermes.d.ts.map +1 -1
  23. package/dist/adapters/cli/hermes.js +8 -4
  24. package/dist/adapters/cli/hermes.js.map +1 -1
  25. package/dist/adapters/cli/mtr.d.ts.map +1 -1
  26. package/dist/adapters/cli/mtr.js +3 -2
  27. package/dist/adapters/cli/mtr.js.map +1 -1
  28. package/dist/adapters/cli/opencode.d.ts.map +1 -1
  29. package/dist/adapters/cli/opencode.js +5 -4
  30. package/dist/adapters/cli/opencode.js.map +1 -1
  31. package/dist/adapters/cli/relay.js +2 -2
  32. package/dist/adapters/cli/relay.js.map +1 -1
  33. package/dist/adapters/cli/runner-input.d.ts +2 -2
  34. package/dist/adapters/cli/runner-input.d.ts.map +1 -1
  35. package/dist/adapters/cli/runner-input.js +9 -6
  36. package/dist/adapters/cli/runner-input.js.map +1 -1
  37. package/dist/adapters/cli/seed.d.ts.map +1 -1
  38. package/dist/adapters/cli/seed.js +2 -1
  39. package/dist/adapters/cli/seed.js.map +1 -1
  40. package/dist/adapters/cli/traex.d.ts.map +1 -1
  41. package/dist/adapters/cli/traex.js +3 -2
  42. package/dist/adapters/cli/traex.js.map +1 -1
  43. package/dist/adapters/cli/types.d.ts +25 -18
  44. package/dist/adapters/cli/types.d.ts.map +1 -1
  45. package/dist/bot-registry.d.ts +28 -0
  46. package/dist/bot-registry.d.ts.map +1 -1
  47. package/dist/bot-registry.js +75 -0
  48. package/dist/bot-registry.js.map +1 -1
  49. package/dist/cli.d.ts.map +1 -1
  50. package/dist/cli.js +272 -86
  51. package/dist/cli.js.map +1 -1
  52. package/dist/codex-app-runner.js +85 -192
  53. package/dist/codex-app-runner.js.map +1 -1
  54. package/dist/config.d.ts +0 -16
  55. package/dist/config.d.ts.map +1 -1
  56. package/dist/config.js +0 -30
  57. package/dist/config.js.map +1 -1
  58. package/dist/core/ask-broker.d.ts +12 -0
  59. package/dist/core/ask-broker.d.ts.map +1 -1
  60. package/dist/core/ask-broker.js +41 -0
  61. package/dist/core/ask-broker.js.map +1 -1
  62. package/dist/core/bot-turn-mutation-gate.d.ts +24 -0
  63. package/dist/core/bot-turn-mutation-gate.d.ts.map +1 -0
  64. package/dist/core/bot-turn-mutation-gate.js +369 -0
  65. package/dist/core/bot-turn-mutation-gate.js.map +1 -0
  66. package/dist/core/command-handler.d.ts +5 -0
  67. package/dist/core/command-handler.d.ts.map +1 -1
  68. package/dist/core/command-handler.js +38 -16
  69. package/dist/core/command-handler.js.map +1 -1
  70. package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
  71. package/dist/core/dashboard-ipc-server.js +330 -57
  72. package/dist/core/dashboard-ipc-server.js.map +1 -1
  73. package/dist/core/dashboard-rows.d.ts +8 -0
  74. package/dist/core/dashboard-rows.d.ts.map +1 -1
  75. package/dist/core/dashboard-rows.js.map +1 -1
  76. package/dist/core/host-overload-alert.d.ts +157 -0
  77. package/dist/core/host-overload-alert.d.ts.map +1 -0
  78. package/dist/core/host-overload-alert.js +251 -0
  79. package/dist/core/host-overload-alert.js.map +1 -0
  80. package/dist/core/passthrough-commands.d.ts +8 -0
  81. package/dist/core/passthrough-commands.d.ts.map +1 -1
  82. package/dist/core/passthrough-commands.js +19 -0
  83. package/dist/core/passthrough-commands.js.map +1 -1
  84. package/dist/core/restart-coordinator.d.ts +28 -0
  85. package/dist/core/restart-coordinator.d.ts.map +1 -0
  86. package/dist/core/restart-coordinator.js +82 -0
  87. package/dist/core/restart-coordinator.js.map +1 -0
  88. package/dist/core/restart-followup-policy.d.ts +112 -0
  89. package/dist/core/restart-followup-policy.d.ts.map +1 -0
  90. package/dist/core/restart-followup-policy.js +49 -0
  91. package/dist/core/restart-followup-policy.js.map +1 -0
  92. package/dist/core/role-library.d.ts +1 -1
  93. package/dist/core/role-library.js +1 -1
  94. package/dist/core/session-cwd.d.ts.map +1 -1
  95. package/dist/core/session-cwd.js +8 -0
  96. package/dist/core/session-cwd.js.map +1 -1
  97. package/dist/core/session-discovery.d.ts +14 -0
  98. package/dist/core/session-discovery.d.ts.map +1 -1
  99. package/dist/core/session-discovery.js +25 -0
  100. package/dist/core/session-discovery.js.map +1 -1
  101. package/dist/core/session-liveness.d.ts +15 -0
  102. package/dist/core/session-liveness.d.ts.map +1 -0
  103. package/dist/core/session-liveness.js +76 -0
  104. package/dist/core/session-liveness.js.map +1 -0
  105. package/dist/core/session-row-enrichment.d.ts +15 -0
  106. package/dist/core/session-row-enrichment.d.ts.map +1 -0
  107. package/dist/core/session-row-enrichment.js +93 -0
  108. package/dist/core/session-row-enrichment.js.map +1 -0
  109. package/dist/core/slash-inject.js +1 -1
  110. package/dist/core/slash-inject.js.map +1 -1
  111. package/dist/core/trigger-final-suppression.d.ts +24 -0
  112. package/dist/core/trigger-final-suppression.d.ts.map +1 -0
  113. package/dist/core/trigger-final-suppression.js +97 -0
  114. package/dist/core/trigger-final-suppression.js.map +1 -0
  115. package/dist/core/trigger-session.d.ts.map +1 -1
  116. package/dist/core/trigger-session.js +64 -4
  117. package/dist/core/trigger-session.js.map +1 -1
  118. package/dist/core/types.d.ts +6 -0
  119. package/dist/core/types.d.ts.map +1 -1
  120. package/dist/core/types.js.map +1 -1
  121. package/dist/core/worker-pool.d.ts +20 -0
  122. package/dist/core/worker-pool.d.ts.map +1 -1
  123. package/dist/core/worker-pool.js +283 -32
  124. package/dist/core/worker-pool.js.map +1 -1
  125. package/dist/daemon.d.ts +5 -1
  126. package/dist/daemon.d.ts.map +1 -1
  127. package/dist/daemon.js +520 -35
  128. package/dist/daemon.js.map +1 -1
  129. package/dist/dashboard/aggregator.d.ts +1 -0
  130. package/dist/dashboard/aggregator.d.ts.map +1 -1
  131. package/dist/dashboard/aggregator.js +34 -6
  132. package/dist/dashboard/aggregator.js.map +1 -1
  133. package/dist/dashboard/bot-payload.d.ts +3 -0
  134. package/dist/dashboard/bot-payload.d.ts.map +1 -1
  135. package/dist/dashboard/bot-payload.js +3 -0
  136. package/dist/dashboard/bot-payload.js.map +1 -1
  137. package/dist/dashboard/compat.d.ts +102 -2
  138. package/dist/dashboard/compat.d.ts.map +1 -1
  139. package/dist/dashboard/compat.js +78 -14
  140. package/dist/dashboard/compat.js.map +1 -1
  141. package/dist/dashboard/connector-api.d.ts.map +1 -1
  142. package/dist/dashboard/connector-api.js +1 -0
  143. package/dist/dashboard/connector-api.js.map +1 -1
  144. package/dist/dashboard/desktop-asks.d.ts +21 -0
  145. package/dist/dashboard/desktop-asks.d.ts.map +1 -0
  146. package/dist/dashboard/desktop-asks.js +49 -0
  147. package/dist/dashboard/desktop-asks.js.map +1 -0
  148. package/dist/dashboard/public-redact.d.ts +7 -0
  149. package/dist/dashboard/public-redact.d.ts.map +1 -1
  150. package/dist/dashboard/public-redact.js +35 -3
  151. package/dist/dashboard/public-redact.js.map +1 -1
  152. package/dist/dashboard/session-presentation.d.ts +16 -0
  153. package/dist/dashboard/session-presentation.d.ts.map +1 -0
  154. package/dist/dashboard/session-presentation.js +62 -0
  155. package/dist/dashboard/session-presentation.js.map +1 -0
  156. package/dist/dashboard/settings-write-applier.d.ts +2 -1
  157. package/dist/dashboard/settings-write-applier.d.ts.map +1 -1
  158. package/dist/dashboard/settings-write-applier.js +19 -1
  159. package/dist/dashboard/settings-write-applier.js.map +1 -1
  160. package/dist/dashboard/trigger-api.d.ts.map +1 -1
  161. package/dist/dashboard/trigger-api.js +19 -1
  162. package/dist/dashboard/trigger-api.js.map +1 -1
  163. package/dist/dashboard/vc-consumer-profiles-api.d.ts +7 -2
  164. package/dist/dashboard/vc-consumer-profiles-api.d.ts.map +1 -1
  165. package/dist/dashboard/vc-consumer-profiles-api.js +13 -0
  166. package/dist/dashboard/vc-consumer-profiles-api.js.map +1 -1
  167. package/dist/dashboard/web/app.d.ts.map +1 -1
  168. package/dist/dashboard/web/app.js +18 -5
  169. package/dist/dashboard/web/app.js.map +1 -1
  170. package/dist/dashboard/web/bot-defaults-page.d.ts +1 -1
  171. package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -1
  172. package/dist/dashboard/web/bot-defaults-page.js +97 -35
  173. package/dist/dashboard/web/bot-defaults-page.js.map +1 -1
  174. package/dist/dashboard/web/bot-defaults.d.ts +3 -0
  175. package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
  176. package/dist/dashboard/web/bot-defaults.js.map +1 -1
  177. package/dist/dashboard/web/client-shell.d.ts +29 -0
  178. package/dist/dashboard/web/client-shell.d.ts.map +1 -0
  179. package/dist/dashboard/web/client-shell.js +89 -0
  180. package/dist/dashboard/web/client-shell.js.map +1 -0
  181. package/dist/dashboard/web/connectors-page.d.ts.map +1 -1
  182. package/dist/dashboard/web/connectors-page.js +5 -1
  183. package/dist/dashboard/web/connectors-page.js.map +1 -1
  184. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  185. package/dist/dashboard/web/i18n.js +100 -8
  186. package/dist/dashboard/web/i18n.js.map +1 -1
  187. package/dist/dashboard/web/preferences.d.ts +7 -0
  188. package/dist/dashboard/web/preferences.d.ts.map +1 -1
  189. package/dist/dashboard/web/preferences.js +32 -0
  190. package/dist/dashboard/web/preferences.js.map +1 -1
  191. package/dist/dashboard/web/sessions-kanban.d.ts +1 -1
  192. package/dist/dashboard/web/sessions-kanban.d.ts.map +1 -1
  193. package/dist/dashboard/web/sessions-kanban.js +1 -1
  194. package/dist/dashboard/web/sessions-kanban.js.map +1 -1
  195. package/dist/dashboard/web/sessions-page.d.ts.map +1 -1
  196. package/dist/dashboard/web/sessions-page.js +77 -23
  197. package/dist/dashboard/web/sessions-page.js.map +1 -1
  198. package/dist/dashboard/web/sessions.d.ts +4 -0
  199. package/dist/dashboard/web/sessions.d.ts.map +1 -1
  200. package/dist/dashboard/web/sessions.js +14 -1
  201. package/dist/dashboard/web/sessions.js.map +1 -1
  202. package/dist/dashboard/web/settings-page.d.ts +6 -0
  203. package/dist/dashboard/web/settings-page.d.ts.map +1 -1
  204. package/dist/dashboard/web/settings-page.js +55 -30
  205. package/dist/dashboard/web/settings-page.js.map +1 -1
  206. package/dist/dashboard/web/store.d.ts +1 -2
  207. package/dist/dashboard/web/store.d.ts.map +1 -1
  208. package/dist/dashboard/web/store.js +69 -20
  209. package/dist/dashboard/web/store.js.map +1 -1
  210. package/dist/dashboard/web/vc-consumer-profiles-section.d.ts.map +1 -1
  211. package/dist/dashboard/web/vc-consumer-profiles-section.js +128 -42
  212. package/dist/dashboard/web/vc-consumer-profiles-section.js.map +1 -1
  213. package/dist/dashboard/webhook-routes.d.ts.map +1 -1
  214. package/dist/dashboard/webhook-routes.js +9 -2
  215. package/dist/dashboard/webhook-routes.js.map +1 -1
  216. package/dist/dashboard-web/app.js +1 -1
  217. package/dist/dashboard-web/chunks/bot-defaults-page-VQMPUJ4Y.js +10 -0
  218. package/dist/dashboard-web/chunks/chunk-AGCPF6MT.js +1 -0
  219. package/dist/dashboard-web/chunks/{chunk-KPQAUX7V.js → chunk-JMRGZQDB.js} +1 -1
  220. package/dist/dashboard-web/chunks/{chunk-R7IAKAYX.js → chunk-NP4JUBGS.js} +1 -1
  221. package/dist/dashboard-web/chunks/{chunk-NRL6CVAS.js → chunk-P327LXOT.js} +1 -1
  222. package/dist/dashboard-web/chunks/{chunk-X2L65IOM.js → chunk-SNKATZWK.js} +15 -15
  223. package/dist/dashboard-web/chunks/connectors-page-DOY4J3ZL.js +1 -0
  224. package/dist/dashboard-web/chunks/{groups-page-6DKXBYOM.js → groups-page-74TS2DIH.js} +1 -1
  225. package/dist/dashboard-web/chunks/{insights-page-NWARTJ6J.js → insights-page-AYCO65JC.js} +1 -1
  226. package/dist/dashboard-web/chunks/{monitor-room-AGX3XRJX.js → monitor-room-YKYLTSAN.js} +1 -1
  227. package/dist/dashboard-web/chunks/{monitoring-page-GGGIWN4C.js → monitoring-page-QBIUNRBR.js} +1 -1
  228. package/dist/dashboard-web/chunks/{office-page-6SIVKSK3.js → office-page-4PH2A26P.js} +1 -1
  229. package/dist/dashboard-web/chunks/overview-page-H73D5UT4.js +1 -0
  230. package/dist/dashboard-web/chunks/{roles-page-WE2YB7KN.js → roles-page-U4BTOQ7F.js} +1 -1
  231. package/dist/dashboard-web/chunks/{schedules-page-TB3I24XN.js → schedules-page-RHRHX7R7.js} +1 -1
  232. package/dist/dashboard-web/chunks/sessions-page-VSC6AM5G.js +2 -0
  233. package/dist/dashboard-web/chunks/settings-page-LF3RKM5P.js +2 -0
  234. package/dist/dashboard-web/chunks/{skills-page-3QAT2IWD.js → skills-page-SYOIGGXH.js} +1 -1
  235. package/dist/dashboard-web/chunks/{team-federation-page-K4VVAVAK.js → team-federation-page-RMBLASTW.js} +1 -1
  236. package/dist/dashboard-web/chunks/{v3-page-V6IOJR2B.js → v3-page-XJXKKJRN.js} +1 -1
  237. package/dist/dashboard-web/chunks/{whiteboards-page-V6CGKRNX.js → whiteboards-page-K3YVSTHJ.js} +1 -1
  238. package/dist/dashboard-web/style.css +551 -0
  239. package/dist/dashboard.js +153 -9
  240. package/dist/dashboard.js.map +1 -1
  241. package/dist/global-config.d.ts +11 -0
  242. package/dist/global-config.d.ts.map +1 -1
  243. package/dist/global-config.js +23 -0
  244. package/dist/global-config.js.map +1 -1
  245. package/dist/i18n/en.d.ts.map +1 -1
  246. package/dist/i18n/en.js +5 -0
  247. package/dist/i18n/en.js.map +1 -1
  248. package/dist/i18n/zh.d.ts.map +1 -1
  249. package/dist/i18n/zh.js +5 -0
  250. package/dist/i18n/zh.js.map +1 -1
  251. package/dist/im/lark/card-builder.d.ts +1 -1
  252. package/dist/im/lark/card-builder.js +1 -1
  253. package/dist/im/lark/card-handler.d.ts +10 -0
  254. package/dist/im/lark/card-handler.d.ts.map +1 -1
  255. package/dist/im/lark/card-handler.js +163 -17
  256. package/dist/im/lark/card-handler.js.map +1 -1
  257. package/dist/im/lark/client.d.ts +11 -0
  258. package/dist/im/lark/client.d.ts.map +1 -1
  259. package/dist/im/lark/client.js +47 -18
  260. package/dist/im/lark/client.js.map +1 -1
  261. package/dist/im/lark/event-dispatcher.d.ts +13 -0
  262. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  263. package/dist/im/lark/event-dispatcher.js +20 -0
  264. package/dist/im/lark/event-dispatcher.js.map +1 -1
  265. package/dist/im/lark/identity-cache.d.ts +25 -1
  266. package/dist/im/lark/identity-cache.d.ts.map +1 -1
  267. package/dist/im/lark/identity-cache.js +47 -1
  268. package/dist/im/lark/identity-cache.js.map +1 -1
  269. package/dist/im/lark/overload-nonce.d.ts +19 -0
  270. package/dist/im/lark/overload-nonce.d.ts.map +1 -0
  271. package/dist/im/lark/overload-nonce.js +72 -0
  272. package/dist/im/lark/overload-nonce.js.map +1 -0
  273. package/dist/im/lark/v3-progress-card.d.ts.map +1 -1
  274. package/dist/im/lark/v3-progress-card.js +5 -0
  275. package/dist/im/lark/v3-progress-card.js.map +1 -1
  276. package/dist/services/async-trigger-state.d.ts +82 -0
  277. package/dist/services/async-trigger-state.d.ts.map +1 -0
  278. package/dist/services/async-trigger-state.js +95 -0
  279. package/dist/services/async-trigger-state.js.map +1 -0
  280. package/dist/services/async-trigger-store.d.ts +28 -0
  281. package/dist/services/async-trigger-store.d.ts.map +1 -0
  282. package/dist/services/async-trigger-store.js +120 -0
  283. package/dist/services/async-trigger-store.js.map +1 -0
  284. package/dist/services/bot-config-store.d.ts.map +1 -1
  285. package/dist/services/bot-config-store.js +34 -2
  286. package/dist/services/bot-config-store.js.map +1 -1
  287. package/dist/services/bridge-fallback-gate.d.ts +32 -0
  288. package/dist/services/bridge-fallback-gate.d.ts.map +1 -1
  289. package/dist/services/bridge-fallback-gate.js +39 -0
  290. package/dist/services/bridge-fallback-gate.js.map +1 -1
  291. package/dist/services/bridge-turn-queue.d.ts.map +1 -1
  292. package/dist/services/bridge-turn-queue.js +15 -1
  293. package/dist/services/bridge-turn-queue.js.map +1 -1
  294. package/dist/services/card-prefs-store.d.ts +4 -0
  295. package/dist/services/card-prefs-store.d.ts.map +1 -1
  296. package/dist/services/card-prefs-store.js +8 -0
  297. package/dist/services/card-prefs-store.js.map +1 -1
  298. package/dist/services/claude-transcript.d.ts +23 -0
  299. package/dist/services/claude-transcript.d.ts.map +1 -1
  300. package/dist/services/claude-transcript.js +33 -0
  301. package/dist/services/claude-transcript.js.map +1 -1
  302. package/dist/services/codex-app-runner-protocol.d.ts +61 -0
  303. package/dist/services/codex-app-runner-protocol.d.ts.map +1 -0
  304. package/dist/services/codex-app-runner-protocol.js +170 -0
  305. package/dist/services/codex-app-runner-protocol.js.map +1 -0
  306. package/dist/services/codex-app-turn-controller.d.ts +72 -0
  307. package/dist/services/codex-app-turn-controller.d.ts.map +1 -0
  308. package/dist/services/codex-app-turn-controller.js +524 -0
  309. package/dist/services/codex-app-turn-controller.js.map +1 -0
  310. package/dist/services/codex-runner-freshness.d.ts +39 -0
  311. package/dist/services/codex-runner-freshness.d.ts.map +1 -0
  312. package/dist/services/codex-runner-freshness.js +78 -0
  313. package/dist/services/codex-runner-freshness.js.map +1 -0
  314. package/dist/services/connector-store.d.ts +6 -0
  315. package/dist/services/connector-store.d.ts.map +1 -1
  316. package/dist/services/connector-store.js.map +1 -1
  317. package/dist/services/grant-store.d.ts.map +1 -1
  318. package/dist/services/grant-store.js +16 -0
  319. package/dist/services/grant-store.js.map +1 -1
  320. package/dist/services/hermes-transcript.d.ts +1 -0
  321. package/dist/services/hermes-transcript.d.ts.map +1 -1
  322. package/dist/services/hermes-transcript.js +49 -0
  323. package/dist/services/hermes-transcript.js.map +1 -1
  324. package/dist/services/schedule-split-migration.d.ts +2 -0
  325. package/dist/services/schedule-split-migration.d.ts.map +1 -0
  326. package/dist/services/schedule-split-migration.js +159 -0
  327. package/dist/services/schedule-split-migration.js.map +1 -0
  328. package/dist/services/schedule-store.d.ts +28 -4
  329. package/dist/services/schedule-store.d.ts.map +1 -1
  330. package/dist/services/schedule-store.js +118 -33
  331. package/dist/services/schedule-store.js.map +1 -1
  332. package/dist/services/trigger-types.d.ts +18 -1
  333. package/dist/services/trigger-types.d.ts.map +1 -1
  334. package/dist/services/trigger-types.js +3 -0
  335. package/dist/services/trigger-types.js.map +1 -1
  336. package/dist/services/vc-meeting-consumer-profile-store.d.ts.map +1 -1
  337. package/dist/services/vc-meeting-consumer-profile-store.js +1 -0
  338. package/dist/services/vc-meeting-consumer-profile-store.js.map +1 -1
  339. package/dist/services/vc-meeting-consumer-profile-templates.d.ts +32 -0
  340. package/dist/services/vc-meeting-consumer-profile-templates.d.ts.map +1 -0
  341. package/dist/services/vc-meeting-consumer-profile-templates.js +106 -0
  342. package/dist/services/vc-meeting-consumer-profile-templates.js.map +1 -0
  343. package/dist/services/vc-meeting-delivery-feed.d.ts +1 -1
  344. package/dist/services/vc-meeting-delivery-feed.d.ts.map +1 -1
  345. package/dist/services/vc-meeting-delivery-feed.js +2 -1
  346. package/dist/services/vc-meeting-delivery-feed.js.map +1 -1
  347. package/dist/services/vc-meeting-delivery-hub-store.d.ts +3 -1
  348. package/dist/services/vc-meeting-delivery-hub-store.d.ts.map +1 -1
  349. package/dist/services/vc-meeting-delivery-hub-store.js +11 -0
  350. package/dist/services/vc-meeting-delivery-hub-store.js.map +1 -1
  351. package/dist/services/vc-meeting-delivery-protocol.d.ts +9 -2
  352. package/dist/services/vc-meeting-delivery-protocol.d.ts.map +1 -1
  353. package/dist/services/vc-meeting-delivery-protocol.js +10 -1
  354. package/dist/services/vc-meeting-delivery-protocol.js.map +1 -1
  355. package/dist/services/vc-meeting-delivery-receiver.d.ts.map +1 -1
  356. package/dist/services/vc-meeting-delivery-receiver.js +10 -1
  357. package/dist/services/vc-meeting-delivery-receiver.js.map +1 -1
  358. package/dist/services/vc-meeting-delivery-store.d.ts +12 -2
  359. package/dist/services/vc-meeting-delivery-store.d.ts.map +1 -1
  360. package/dist/services/vc-meeting-delivery-store.js +14 -2
  361. package/dist/services/vc-meeting-delivery-store.js.map +1 -1
  362. package/dist/services/vc-meeting-im-reply.d.ts +2 -1
  363. package/dist/services/vc-meeting-im-reply.d.ts.map +1 -1
  364. package/dist/services/vc-meeting-im-reply.js +19 -3
  365. package/dist/services/vc-meeting-im-reply.js.map +1 -1
  366. package/dist/services/vc-meeting-listener-output-protocol.d.ts +27 -0
  367. package/dist/services/vc-meeting-listener-output-protocol.d.ts.map +1 -0
  368. package/dist/services/vc-meeting-listener-output-protocol.js +58 -0
  369. package/dist/services/vc-meeting-listener-output-protocol.js.map +1 -0
  370. package/dist/services/vc-meeting-listener-topic-store.d.ts +31 -0
  371. package/dist/services/vc-meeting-listener-topic-store.d.ts.map +1 -0
  372. package/dist/services/vc-meeting-listener-topic-store.js +120 -0
  373. package/dist/services/vc-meeting-listener-topic-store.js.map +1 -0
  374. package/dist/services/vc-meeting-runtime-store.d.ts +2 -1
  375. package/dist/services/vc-meeting-runtime-store.d.ts.map +1 -1
  376. package/dist/services/vc-meeting-runtime-store.js +8 -0
  377. package/dist/services/vc-meeting-runtime-store.js.map +1 -1
  378. package/dist/services/vc-meeting-send-policy.d.ts +8 -1
  379. package/dist/services/vc-meeting-send-policy.d.ts.map +1 -1
  380. package/dist/services/vc-meeting-send-policy.js +8 -0
  381. package/dist/services/vc-meeting-send-policy.js.map +1 -1
  382. package/dist/types.d.ts +40 -3
  383. package/dist/types.d.ts.map +1 -1
  384. package/dist/utils/allowed-users-apply.d.ts +76 -0
  385. package/dist/utils/allowed-users-apply.d.ts.map +1 -0
  386. package/dist/utils/allowed-users-apply.js +123 -0
  387. package/dist/utils/allowed-users-apply.js.map +1 -0
  388. package/dist/utils/allowed-users-cache.d.ts +29 -0
  389. package/dist/utils/allowed-users-cache.d.ts.map +1 -0
  390. package/dist/utils/allowed-users-cache.js +82 -0
  391. package/dist/utils/allowed-users-cache.js.map +1 -0
  392. package/dist/utils/child-env.d.ts +2 -1
  393. package/dist/utils/child-env.d.ts.map +1 -1
  394. package/dist/utils/child-env.js +2 -1
  395. package/dist/utils/child-env.js.map +1 -1
  396. package/dist/utils/cli-usage-limit.d.ts +27 -1
  397. package/dist/utils/cli-usage-limit.d.ts.map +1 -1
  398. package/dist/utils/cli-usage-limit.js +92 -20
  399. package/dist/utils/cli-usage-limit.js.map +1 -1
  400. package/dist/utils/input-gate.d.ts +2 -0
  401. package/dist/utils/input-gate.d.ts.map +1 -1
  402. package/dist/utils/input-gate.js +2 -0
  403. package/dist/utils/input-gate.js.map +1 -1
  404. package/dist/utils/runtime-build-id.d.ts +21 -0
  405. package/dist/utils/runtime-build-id.d.ts.map +1 -0
  406. package/dist/utils/runtime-build-id.js +83 -0
  407. package/dist/utils/runtime-build-id.js.map +1 -0
  408. package/dist/utils/terminal-renderer.d.ts +3 -3
  409. package/dist/utils/terminal-renderer.js +3 -3
  410. package/dist/vc-agent/cards.d.ts.map +1 -1
  411. package/dist/vc-agent/cards.js +21 -1
  412. package/dist/vc-agent/cards.js.map +1 -1
  413. package/dist/worker.js +601 -179
  414. package/dist/worker.js.map +1 -1
  415. package/dist/workflows/hostExecutors/botmux-schedule.d.ts.map +1 -1
  416. package/dist/workflows/hostExecutors/botmux-schedule.js +13 -1
  417. package/dist/workflows/hostExecutors/botmux-schedule.js.map +1 -1
  418. package/dist/workflows/migration/v2-run-archive-schema.d.ts +20 -20
  419. package/dist/workflows/migration/v2-to-v3.d.ts.map +1 -1
  420. package/dist/workflows/migration/v2-to-v3.js +5 -1
  421. package/dist/workflows/migration/v2-to-v3.js.map +1 -1
  422. package/dist/workflows/v3/architect.d.ts.map +1 -1
  423. package/dist/workflows/v3/architect.js +1 -0
  424. package/dist/workflows/v3/architect.js.map +1 -1
  425. package/dist/workflows/v3/cli-run.d.ts +9 -0
  426. package/dist/workflows/v3/cli-run.d.ts.map +1 -1
  427. package/dist/workflows/v3/cli-run.js +17 -2
  428. package/dist/workflows/v3/cli-run.js.map +1 -1
  429. package/dist/workflows/v3/goal-cli.d.ts +58 -0
  430. package/dist/workflows/v3/goal-cli.d.ts.map +1 -0
  431. package/dist/workflows/v3/goal-cli.js +430 -0
  432. package/dist/workflows/v3/goal-cli.js.map +1 -0
  433. package/dist/workflows/v3/library-materialize.d.ts.map +1 -1
  434. package/dist/workflows/v3/library-materialize.js +5 -1
  435. package/dist/workflows/v3/library-materialize.js.map +1 -1
  436. package/dist/workflows/v3/library-schema.d.ts +21 -0
  437. package/dist/workflows/v3/library-schema.d.ts.map +1 -1
  438. package/dist/workflows/v3/library-schema.js +95 -1
  439. package/dist/workflows/v3/library-schema.js.map +1 -1
  440. package/dist/workflows/v3/progress-projection.d.ts +3 -0
  441. package/dist/workflows/v3/progress-projection.d.ts.map +1 -1
  442. package/dist/workflows/v3/progress-projection.js +23 -1
  443. package/dist/workflows/v3/progress-projection.js.map +1 -1
  444. package/dist/workflows/v3/run-envelope.d.ts +46 -1
  445. package/dist/workflows/v3/run-envelope.d.ts.map +1 -1
  446. package/dist/workflows/v3/run-envelope.js +32 -1
  447. package/dist/workflows/v3/run-envelope.js.map +1 -1
  448. package/package.json +2 -2
  449. package/dist/dashboard-web/chunks/bot-defaults-page-AUKV7P4L.js +0 -10
  450. package/dist/dashboard-web/chunks/chunk-SZOB6VK2.js +0 -1
  451. package/dist/dashboard-web/chunks/connectors-page-HDQFEXZI.js +0 -1
  452. package/dist/dashboard-web/chunks/overview-page-FVR3NKAF.js +0 -1
  453. package/dist/dashboard-web/chunks/sessions-page-KOOOASIL.js +0 -2
  454. package/dist/dashboard-web/chunks/settings-page-IEBR7TGN.js +0 -2
  455. package/dist/utils/screen-analyzer.d.ts +0 -75
  456. package/dist/utils/screen-analyzer.d.ts.map +0 -1
  457. package/dist/utils/screen-analyzer.js +0 -333
  458. package/dist/utils/screen-analyzer.js.map +0 -1
package/dist/cli.js CHANGED
@@ -3158,6 +3158,79 @@ function adoptedCliPid(s) {
3158
3158
  const pid = isAdoptedSession(s) ? s.adoptedFrom.originalCliPid : undefined;
3159
3159
  return typeof pid === 'number' && pid > 0 ? pid : undefined;
3160
3160
  }
3161
+ /** Offline-only fallback for `botmux delete`. When the owning daemon is live,
3162
+ * it must own the whole close transition so its activeSessions registry,
3163
+ * persistent row, lifecycle hooks, subscriptions, and backend teardown stay
3164
+ * coherent. This legacy local path is safe only when there is no daemon
3165
+ * process whose in-memory state could be stranded. */
3166
+ function closeSessionOffline(s) {
3167
+ const originalPid = adoptedCliPid(s);
3168
+ // Adopted sessions own only the botmux worker/viewer, never the user's CLI.
3169
+ if (s.pid && s.pid !== originalPid && isProcessAlive(s.pid)) {
3170
+ killProcess(s.pid);
3171
+ }
3172
+ // Adopted panes belong to the user. Ordinary bmx-* sessions are botmux-owned
3173
+ // and still need direct cleanup when no daemon exists to run killWorker().
3174
+ if (!isAdoptedSession(s)) {
3175
+ const tmuxName = `bmx-${s.sessionId.substring(0, 8)}`;
3176
+ try {
3177
+ execSync(`tmux kill-session -t '${tmuxName}' 2>/dev/null`, {
3178
+ stdio: 'ignore',
3179
+ env: tmuxEnv(),
3180
+ });
3181
+ }
3182
+ catch { /* no tmux session */ }
3183
+ }
3184
+ s.status = 'closed';
3185
+ s.closedAt = new Date().toISOString();
3186
+ saveSession(s);
3187
+ }
3188
+ /** Close through the owning daemon whenever it is online. The IPC request is
3189
+ * deliberately sent BEFORE any local kill: deleting the current bmx-* tmux
3190
+ * first would terminate this very CLI before it can evict daemon memory.
3191
+ *
3192
+ * Trusted host callers use the dashboard HMAC. A sandboxed/read-isolated CLI
3193
+ * can only authorize the exact current session with its rotating per-turn
3194
+ * capability, so `delete <other-id>` remains fail-closed. */
3195
+ async function closeSessionForDelete(s, online = listOnlineDaemons()) {
3196
+ // Legacy sessions without larkAppId live in sessions.json. A per-bot daemon
3197
+ // writes only its own sessions-<appId>.json and silently no-ops on close
3198
+ // (sessionStore.closeSession only touches the current file), so routing a
3199
+ // legacy session to it yields "200 OK" with no actual state change. This must
3200
+ // hold on BOTH ways a daemon port is discovered — the descriptor lookup AND
3201
+ // the injected-port current-session fallback below — so gate the whole daemon
3202
+ // path on larkAppId with one authoritative guard. A live daemon-spawned
3203
+ // session always carries larkAppId, so this never diverts the legitimate
3204
+ // sandboxed current-session close (which reaches its daemon via the injected
3205
+ // port); it only keeps larkAppId-less legacy records on the offline fallback,
3206
+ // whose saveSession() persists to the legacy file correctly.
3207
+ if (!s.larkAppId) {
3208
+ closeSessionOffline(s);
3209
+ return { ok: true, via: 'offline' };
3210
+ }
3211
+ const daemon = online.find(d => d.larkAppId === s.larkAppId);
3212
+ const isCurrentSession = process.env.BOTMUX_SESSION_ID === s.sessionId;
3213
+ const injectedPort = isCurrentSession
3214
+ ? resolveDaemonIpcPort(undefined, process.env.BOTMUX_DAEMON_IPC_PORT)
3215
+ : undefined;
3216
+ const ipcPort = daemon?.ipcPort ?? injectedPort;
3217
+ if (ipcPort) {
3218
+ try {
3219
+ const res = await postSessionCliIpc(ipcPort, s.sessionId, 'close', {});
3220
+ const body = await res.json().catch(() => ({}));
3221
+ if (res.ok && body?.ok)
3222
+ return { ok: true, via: 'daemon' };
3223
+ return { ok: false, error: body?.error ?? `HTTP ${res.status}` };
3224
+ }
3225
+ catch (err) {
3226
+ // A fresh daemon descriptor means there may still be authoritative
3227
+ // in-memory state. Never fall back to a partial local kill in this case.
3228
+ return { ok: false, error: `连接 daemon 失败: ${err?.message ?? err}` };
3229
+ }
3230
+ }
3231
+ closeSessionOffline(s);
3232
+ return { ok: true, via: 'offline' };
3233
+ }
3161
3234
  function adoptTargetLabel(s) {
3162
3235
  if (!isAdoptedSession(s))
3163
3236
  return '';
@@ -3337,26 +3410,15 @@ function interactiveSessionPicker(active) {
3337
3410
  process.stdout.write('\x1b[?25h'); // show cursor
3338
3411
  process.stdout.write('\x1b[?1049l'); // leave alt screen
3339
3412
  }
3340
- function deleteSession(idx) {
3413
+ let deleteInFlight = false;
3414
+ async function deleteSession(idx) {
3341
3415
  const r = rows[idx];
3342
3416
  const s = r.session;
3343
- // Kill botmux's worker process. For adopted sessions, never kill the
3344
- // user's original CLI pid if an old record stored it in `pid`.
3345
- const originalPid = adoptedCliPid(s);
3346
- if (s.pid && s.pid !== originalPid && isProcessAlive(s.pid)) {
3347
- killProcess(s.pid);
3348
- }
3349
- // Kill only botmux-owned tmux sessions. Adopted panes belong to the user.
3350
- if (!r.isAdopt && r.hasTmux) {
3351
- try {
3352
- execSync(`tmux kill-session -t '${r.tmuxName}' 2>/dev/null`, { stdio: 'ignore', env: tmuxEnv() });
3353
- }
3354
- catch { /* */ }
3417
+ const result = await closeSessionForDelete(s);
3418
+ if (!result.ok) {
3419
+ flashMsg = `\x1b[31m✗ 删除失败: ${result.error}\x1b[0m`;
3420
+ return;
3355
3421
  }
3356
- // Mark closed & persist
3357
- s.status = 'closed';
3358
- s.closedAt = new Date().toISOString();
3359
- saveSession(s);
3360
3422
  // Remove from active list and TUI rows
3361
3423
  const activeIdx = active.indexOf(s);
3362
3424
  if (activeIdx >= 0)
@@ -3364,14 +3426,24 @@ function interactiveSessionPicker(active) {
3364
3426
  rows.splice(idx, 1);
3365
3427
  if (cursor >= rows.length)
3366
3428
  cursor = Math.max(0, rows.length - 1);
3367
- flashMsg = `\x1b[32m✓ 已删除 ${s.sessionId.substring(0, 8)}\x1b[0m`;
3429
+ flashMsg = result.via === 'daemon'
3430
+ ? `\x1b[32m✓ 已删除 ${s.sessionId.substring(0, 8)}\x1b[0m`
3431
+ : `\x1b[33m✓ 已离线删除 ${s.sessionId.substring(0, 8)}\x1b[0m`;
3368
3432
  }
3369
- process.stdin.on('data', (key) => {
3433
+ process.stdin.on('data', async (key) => {
3434
+ if (deleteInFlight)
3435
+ return;
3370
3436
  // Delete confirmation mode
3371
3437
  if (confirmDelete) {
3372
3438
  confirmDelete = false;
3373
3439
  if (key === 'y' || key === 'Y') {
3374
- deleteSession(cursor);
3440
+ deleteInFlight = true;
3441
+ try {
3442
+ await deleteSession(cursor);
3443
+ }
3444
+ finally {
3445
+ deleteInFlight = false;
3446
+ }
3375
3447
  }
3376
3448
  else {
3377
3449
  flashMsg = '\x1b[2m取消删除\x1b[0m';
@@ -3500,7 +3572,7 @@ async function cmdList() {
3500
3572
  // Interactive TUI
3501
3573
  await interactiveSessionPicker(live);
3502
3574
  }
3503
- function cmdDelete() {
3575
+ async function cmdDelete() {
3504
3576
  const target = process.argv[3];
3505
3577
  if (!target) {
3506
3578
  console.error('用法: botmux delete <session-id|all>');
@@ -3518,6 +3590,13 @@ function cmdDelete() {
3518
3590
  }
3519
3591
  else if (target === 'stopped') {
3520
3592
  toDelete = active.filter(s => {
3593
+ // A deliberately cap-suspended session has neither pid nor backing pane
3594
+ // (that's how its memory is reclaimed) but must cold-resume on the next
3595
+ // message — never a zombie. Mirrors the server-side isSessionStopped guard
3596
+ // and the `list` prune disposition; without it `delete stopped` (which the
3597
+ // overload alert text recommends) would drop a live-but-parked session.
3598
+ if (isColdResumeDormant(s))
3599
+ return false;
3521
3600
  if (isAdoptedSession(s)) {
3522
3601
  const pid = adoptedCliPid(s);
3523
3602
  return pid ? !isProcessAlive(pid) : !(s.pid && isProcessAlive(s.pid));
@@ -3547,31 +3626,31 @@ function cmdDelete() {
3547
3626
  process.exit(1);
3548
3627
  }
3549
3628
  }
3629
+ // A self-delete may tear down the process running this loop. Put it last so
3630
+ // `delete all` still closes every other target before the current session.
3631
+ const currentSessionId = process.env.BOTMUX_SESSION_ID;
3632
+ if (currentSessionId && toDelete.length > 1) {
3633
+ toDelete.sort((a, b) => Number(a.sessionId === currentSessionId) - Number(b.sessionId === currentSessionId));
3634
+ }
3635
+ const online = listOnlineDaemons();
3636
+ let closed = 0;
3637
+ let offline = 0;
3638
+ let failed = 0;
3550
3639
  for (const s of toDelete) {
3551
- const originalPid = adoptedCliPid(s);
3552
- // Kill botmux's worker process if running. For adopted sessions, never
3553
- // kill the user's original CLI pid.
3554
- if (s.pid && s.pid !== originalPid && isProcessAlive(s.pid)) {
3555
- killProcess(s.pid);
3556
- console.log(` killed pid ${s.pid}`);
3557
- }
3558
- // Kill associated botmux-owned tmux session if it exists. Adopted panes
3559
- // belong to the user and must be left untouched.
3560
- const tmuxName = `bmx-${s.sessionId.substring(0, 8)}`;
3561
- if (!isAdoptedSession(s)) {
3562
- try {
3563
- execSync(`tmux kill-session -t '${tmuxName}' 2>/dev/null`, { stdio: 'ignore', env: tmuxEnv() });
3564
- console.log(` killed tmux ${tmuxName}`);
3565
- }
3566
- catch { /* no tmux session */ }
3640
+ const result = await closeSessionForDelete(s, online);
3641
+ if (!result.ok) {
3642
+ console.error(`✗ ${s.sessionId.substring(0, 8)} ${s.title}: ${result.error}`);
3643
+ failed++;
3644
+ continue;
3567
3645
  }
3568
- // Mark session as closed
3569
- s.status = 'closed';
3570
- s.closedAt = new Date().toISOString();
3571
- saveSession(s);
3572
- console.log(`✓ ${s.sessionId.substring(0, 8)} ${s.title}`);
3646
+ closed++;
3647
+ if (result.via === 'offline')
3648
+ offline++;
3649
+ console.log(`✓ ${s.sessionId.substring(0, 8)} ${s.title}${result.via === 'offline' ? '(daemon 离线,本地收口)' : ''}`);
3573
3650
  }
3574
- console.log(`\n已关闭 ${toDelete.length} 个会话`);
3651
+ console.log(`\n已关闭 ${closed} 个会话${offline ? `(${offline} 个离线收口)` : ''}${failed ? `,${failed} 个失败` : ''}`);
3652
+ if (failed > 0)
3653
+ process.exitCode = 1;
3575
3654
  }
3576
3655
  /**
3577
3656
  * `botmux suspend` — 手动挂起活跃会话:杀掉 worker + CLI/pane,但会话保持
@@ -3681,7 +3760,7 @@ async function cmdSuspend() {
3681
3760
  if (failed > 0)
3682
3761
  process.exitCode = 1;
3683
3762
  }
3684
- /** 会话级 CLI IPC(slash/cd)的 POST:与 postAsk 同款双路径——能读 host secret
3763
+ /** 会话级 CLI IPC(slash/cd/close)的 POST:与 postAsk 同款双路径——能读 host secret
3685
3764
  * (非隔离进程)走 trusted-host HMAC 签名;读不到(沙箱 BOTMUX_SEND_RELAY /
3686
3765
  * macOS 读隔离 carve-out)改带本会话当前轮换的 origin capability,由 daemon
3687
3766
  * handler 与活跃记录比对。两条路都不读 bots.json。 */
@@ -3753,18 +3832,18 @@ async function cmdSlash() {
3753
3832
  console.error(`✗ 被拒绝: ${body?.error ?? `HTTP ${res.status}`}`);
3754
3833
  process.exit(1);
3755
3834
  }
3756
- /** botmux cd <角色目录>:请求 daemon 重钉本话题工作目录(角色切换)。
3757
- * daemon 侧校验目录必须在 ~/botmux-roles 下;Claude 家族 idle 注入 /cd 不重启,
3758
- * 其余 CLI 杀进程冷启动。协议要求本命令是该轮最后一个动作。 */
3759
- async function cmdCd() {
3760
- const argv = process.argv.slice(3);
3835
+ /** 角色切换(`botmux role switch <角色目录>`,唯一入口)。daemon 侧硬校验目录必须在
3836
+ * ~/botmux-roles 下。名字→目录的解析由调用方(模型读 _role-protocol.md)完成,本命令
3837
+ * 只透传解析出的目标目录。argv dispatch 传入 `process.argv.slice(4)`(跳过 `switch`
3838
+ * 子命令词)。 */
3839
+ async function cmdRoleSwitch(argv) {
3761
3840
  const sIdx = argv.indexOf('--session');
3762
3841
  const explicitSid = sIdx >= 0 ? argv[sIdx + 1] : undefined;
3763
3842
  // 所有非 flag 位置参数 join(' '),而不是只取第一个——路径含空格且未加引号时
3764
- // (如 `botmux cd ~/botmux-roles/我的 角色`)此前会被截断。
3843
+ // (如 `botmux role switch ~/botmux-roles/我的 角色`)此前会被截断。
3765
3844
  const dir = argv.filter((a, i) => !a.startsWith('--') && !(sIdx >= 0 && i === sIdx + 1)).join(' ');
3766
3845
  if (!dir) {
3767
- console.error('用法: botmux cd <目标目录(含空格建议加引号)> [--session <id>]');
3846
+ console.error(`用法: botmux role switch <目标角色目录(含空格建议加引号)> [--session <id>]`);
3768
3847
  process.exit(1);
3769
3848
  }
3770
3849
  const ctx = explicitSid ? null : findAncestorSessionContext();
@@ -3787,9 +3866,11 @@ async function cmdCd() {
3787
3866
  const res = await postSessionCliIpc(daemon.ipcPort, s.sessionId, 'cd', { dir });
3788
3867
  const body = await res.json().catch(() => ({}));
3789
3868
  if (res.ok && body?.ok) {
3790
- console.log(body.mode === 'inject'
3791
- ? `✓ 已切换到 ${body.dir}(会话空闲时生效,进程不重启)`
3792
- : `✓ 已切换到 ${body.dir}(下条消息在新目录冷启动)`);
3869
+ console.log(body.mode === 'respawn-resume'
3870
+ ? `✓ 已切换到 ${body.dir}(进程即将在新目录重启并续回上下文)`
3871
+ : body.mode === 'inject' // 兼容旧 daemon 的注入模式
3872
+ ? `✓ 已切换到 ${body.dir}(会话空闲时生效,进程不重启)`
3873
+ : `✓ 已切换到 ${body.dir}(下条消息在新目录冷启动)`);
3793
3874
  return;
3794
3875
  }
3795
3876
  console.error(`✗ 切换被拒绝: ${body?.error ?? `HTTP ${res.status}`}`);
@@ -4403,7 +4484,7 @@ botmux v${getVersion()} — IM ↔ AI 编程 CLI 桥接
4403
4484
  --isolated 挂起所有读隔离 bot(凭证轮换后用;下次冷启动自动同步最新凭证)
4404
4485
  --dry-run 只列出目标,不执行
4405
4486
  slash "<斜杠命令>" 会话空闲后向本会话 CLI 注入一条原生斜杠命令(需 bots.json 配 tuiSlashAllow;/cd 恒被拒)
4406
- cd <目录> (会话内)切换本话题工作目录到角色库内的目录——角色切换用;
4487
+ role switch <目录> (会话内)切换本话题到角色库内的角色目录——角色切换用;
4407
4488
  目录必须位于 ~/botmux-roles 之下
4408
4489
  term-link [id] 获取活跃会话的「可操作终端」(带写 token)。不回显链接,改由
4409
4490
  daemon 把可操作卡片私密发给 owner(群内仅你可见,话题/单聊回退 DM)。
@@ -4488,6 +4569,10 @@ botmux v${getVersion()} — IM ↔ AI 编程 CLI 桥接
4488
4569
  skill show <name> 读取某技能的完整 SKILL.md 说明(prompt 注入模式下按需拉取内置技能全文)
4489
4570
 
4490
4571
  编排 / workflow(v3):
4572
+ goal run <goal> [--run-id <id>] [--bot <id|name>] [--working-dir <dir>]
4573
+ [--timeout <seconds>] [--json]
4574
+ 在现有 v3 沙箱/worker 路径运行一个 headless goal;
4575
+ 同一 run-id 可安全重放终态或接续崩溃运行
4491
4576
  workflow save [last|runId] [名称]
4492
4577
  把成功 run 固化为 chat scope Saved Workflow;
4493
4578
  发布当前 Bot 全局版本 / 确认 unsafe lint 请由用户在飞书显式发送 /workflow save ...
@@ -4901,8 +4986,41 @@ async function cmdSchedule(sub, rest) {
4901
4986
  process.env.SESSION_DATA_DIR ??= resolveDataDir();
4902
4987
  const scheduler = await import('./core/scheduler.js');
4903
4988
  const scheduleStore = await import('./services/schedule-store.js');
4989
+ // Per-bot stores: bind this invocation to one bot's store — explicit
4990
+ // --lark-app-id wins, else the surrounding session's bot (env/marker-derived;
4991
+ // always present inside sandboxed sessions). A bare terminal without either
4992
+ // binds to the primary bot (bots.json[0]) so mutations keep the legacy
4993
+ // "ownerless task runs on bot-0" semantics; `list` without a bound bot
4994
+ // aggregates every readable store instead.
4995
+ const cliScopeAppId = argValue(rest, '--lark-app-id')
4996
+ ?? detectCurrentSession()?.larkAppId
4997
+ ?? process.env.BOTMUX_LARK_APP_ID;
4998
+ // LAZY + sandbox-safe bots.json read: sandboxed sessions always carry a
4999
+ // scope (env-injected appId) and must never touch bots.json — it is denied
5000
+ // and `loadBotsJson()` process.exit(1)s on the read error. Only the bare
5001
+ // unsandboxed terminal (aggregate list / cross-store id lookup) reads it,
5002
+ // and even then failure degrades to "no other stores visible".
5003
+ const allBotAppIds = () => {
5004
+ try {
5005
+ return parseBotConfigsJson(readFileSync(BOTS_JSON_FILE, 'utf-8'), BOTS_JSON_FILE)
5006
+ .map((b) => b?.larkAppId)
5007
+ .filter((x) => typeof x === 'string');
5008
+ }
5009
+ catch {
5010
+ return [];
5011
+ } // absent OR sandbox-denied → own scope only
5012
+ };
5013
+ if (cliScopeAppId)
5014
+ scheduleStore.setScheduleScope(cliScopeAppId);
5015
+ else {
5016
+ const first = allBotAppIds()[0];
5017
+ if (first)
5018
+ scheduleStore.setScheduleScope(first);
5019
+ }
4904
5020
  if (!sub || sub === 'list' || sub === 'ls') {
4905
- const tasks = scheduleStore.listTasks();
5021
+ const tasks = cliScopeAppId
5022
+ ? scheduleStore.listTasks()
5023
+ : scheduleStore.listTasksForBots(allBotAppIds());
4906
5024
  if (tasks.length === 0) {
4907
5025
  console.log('暂无定时任务。\n\n用法:\n botmux schedule add "每日17:50" "帮我看AI新闻"\n botmux schedule add "every 2h" "检查构建"\n botmux schedule add "0 9 * * *" "每天早安"');
4908
5026
  return;
@@ -4943,7 +5061,12 @@ async function cmdSchedule(sub, rest) {
4943
5061
  const explicitRootMessageId = argValue(rest, '--root-msg-id');
4944
5062
  const rootMessageId = explicitRootMessageId
4945
5063
  ?? (chatId && chatId === cur?.chatId ? cur.rootMessageId : undefined);
4946
- const larkAppId = argValue(rest, '--lark-app-id') ?? cur?.larkAppId;
5064
+ // Owner resolution mirrors the store-scope resolution above (flag →
5065
+ // session marker → daemon-injected env): a sandboxed session without a
5066
+ // readable marker must still stamp its own bot as owner, or the task
5067
+ // would land in this bot's store as OWNERLESS — which only the primary
5068
+ // daemon executes — and never fire (codex review P1).
5069
+ const larkAppId = cliScopeAppId;
4947
5070
  const workingDir = argValue(rest, '--workdir') ?? cur?.workingDir ?? process.cwd();
4948
5071
  const name = argValue(rest, '--name') ?? (promptArg.length > 20 ? promptArg.slice(0, 20) + '…' : promptArg);
4949
5072
  const legacyDeliver = argValue(rest, '--deliver');
@@ -4992,25 +5115,37 @@ async function cmdSchedule(sub, rest) {
4992
5115
  console.error(`无法解析 schedule "${rawSchedule}": ${err.message}`);
4993
5116
  process.exit(1);
4994
5117
  }
4995
- const task = scheduler.addTask({
4996
- name,
4997
- schedule: rawSchedule,
4998
- parsed,
4999
- prompt: promptArg,
5000
- workingDir,
5001
- chatId,
5002
- rootMessageId,
5003
- larkAppId,
5004
- creatorChatId: cur?.chatId,
5005
- creatorRootMessageId: cur?.rootMessageId,
5006
- creatorLarkAppId: cur?.larkAppId,
5007
- chatType: cur?.chatType === 'p2p' ? 'p2p' : 'topic_group',
5008
- scope,
5009
- executionPosition,
5010
- topicTitle,
5011
- deliver,
5012
- silent,
5013
- });
5118
+ let task;
5119
+ try {
5120
+ task = scheduler.addTask({
5121
+ name,
5122
+ schedule: rawSchedule,
5123
+ parsed,
5124
+ prompt: promptArg,
5125
+ workingDir,
5126
+ chatId,
5127
+ rootMessageId,
5128
+ larkAppId,
5129
+ creatorChatId: cur?.chatId,
5130
+ creatorRootMessageId: cur?.rootMessageId,
5131
+ creatorLarkAppId: cur?.larkAppId,
5132
+ chatType: cur?.chatType === 'p2p' ? 'p2p' : 'topic_group',
5133
+ scope,
5134
+ executionPosition,
5135
+ topicTitle,
5136
+ deliver,
5137
+ silent,
5138
+ });
5139
+ }
5140
+ catch (err) {
5141
+ // Sandboxed sessions can only write their OWN bot's store — a cross-bot
5142
+ // `--lark-app-id` (or a scope pointing at another bot) fails closed here.
5143
+ if (/EPERM|EACCES|not permitted/i.test(String(err))) {
5144
+ console.error(`无法写入目标 bot 的定时任务存储(${larkAppId ?? '未指定'}):沙盒会话只能管理自己 bot 的任务。`);
5145
+ process.exit(1);
5146
+ }
5147
+ throw err;
5148
+ }
5014
5149
  const next = task.nextRunAt ? new Date(task.nextRunAt).toLocaleString('zh-CN', { timeZone: scheduleTimeZone() }) : '—';
5015
5150
  console.log(`✅ 已创建定时任务 [${task.id}] ${task.name}`);
5016
5151
  console.log(` 规则: ${parsed.display}`);
@@ -5028,41 +5163,67 @@ async function cmdSchedule(sub, rest) {
5028
5163
  console.error(`用法: botmux schedule ${sub} <id>`);
5029
5164
  process.exit(1);
5030
5165
  }
5166
+ // Id-addressed op missed the bound store: locate the id across every
5167
+ // READABLE bot store (bare-terminal admin usage) and rebind the scope to the
5168
+ // owning bot for this one-shot process. Sandboxed callers cannot read
5169
+ // sibling stores, so they stay confined to their own tasks by construction.
5170
+ const retargetIfElsewhere = () => {
5171
+ const hit = scheduleStore.findTaskAcrossBots(id, allBotAppIds());
5172
+ if (!hit || hit.appId === scheduleStore.getScheduleScope())
5173
+ return false;
5174
+ scheduleStore.setScheduleScope(hit.appId);
5175
+ console.log(`(任务属于 bot ${hit.appId} 的存储)`);
5176
+ return true;
5177
+ };
5031
5178
  switch (sub) {
5032
5179
  case 'remove':
5033
5180
  case 'rm':
5034
5181
  case 'delete':
5035
- case 'del':
5036
- if (scheduler.removeTask(id))
5182
+ case 'del': {
5183
+ let ok = scheduler.removeTask(id);
5184
+ if (!ok && retargetIfElsewhere())
5185
+ ok = scheduler.removeTask(id);
5186
+ if (ok)
5037
5187
  console.log(`已删除任务 ${id}`);
5038
5188
  else {
5039
5189
  console.error(`未找到任务 ${id}`);
5040
5190
  process.exit(1);
5041
5191
  }
5042
5192
  break;
5193
+ }
5043
5194
  case 'pause':
5044
- case 'disable':
5045
- if (scheduler.disableTask(id))
5195
+ case 'disable': {
5196
+ let ok = scheduler.disableTask(id);
5197
+ if (!ok && retargetIfElsewhere())
5198
+ ok = scheduler.disableTask(id);
5199
+ if (ok)
5046
5200
  console.log(`已暂停任务 ${id}`);
5047
5201
  else {
5048
5202
  console.error(`未找到任务 ${id}`);
5049
5203
  process.exit(1);
5050
5204
  }
5051
5205
  break;
5206
+ }
5052
5207
  case 'resume':
5053
- case 'enable':
5054
- if (scheduler.enableTask(id))
5208
+ case 'enable': {
5209
+ let ok = scheduler.enableTask(id);
5210
+ if (!ok && retargetIfElsewhere())
5211
+ ok = scheduler.enableTask(id);
5212
+ if (ok)
5055
5213
  console.log(`已恢复任务 ${id}`);
5056
5214
  else {
5057
5215
  console.error(`未找到任务 ${id}`);
5058
5216
  process.exit(1);
5059
5217
  }
5060
5218
  break;
5219
+ }
5061
5220
  case 'run':
5062
5221
  // Running requires the daemon (executeCallback is daemon-side).
5063
5222
  // CLI can only mark a task to run ASAP; daemon's next tick picks it up.
5064
5223
  {
5065
- const task = scheduleStore.getTask(id);
5224
+ let task = scheduleStore.getTask(id);
5225
+ if (!task && retargetIfElsewhere())
5226
+ task = scheduleStore.getTask(id);
5066
5227
  if (!task) {
5067
5228
  console.error(`未找到任务 ${id}`);
5068
5229
  process.exit(1);
@@ -9390,7 +9551,7 @@ switch (command) {
9390
9551
  case 'delete':
9391
9552
  case 'del':
9392
9553
  case 'rm':
9393
- cmdDelete();
9554
+ await cmdDelete();
9394
9555
  break;
9395
9556
  case 'resume':
9396
9557
  await cmdResume();
@@ -9401,9 +9562,29 @@ switch (command) {
9401
9562
  case 'slash':
9402
9563
  await cmdSlash();
9403
9564
  break;
9404
- case 'cd':
9405
- await cmdCd();
9565
+ case 'cd': {
9566
+ // Tombstone for the removed `botmux cd`(改名为 `botmux role switch`)。**必须
9567
+ // fail-loud**:存量部署里 _role-protocol.md 若还没刷新、模型仍发 `botmux cd`,
9568
+ // 静默 exit 0 会让它以为切换成功(实际什么都没做)——「假切换成功」比明确报错
9569
+ // 危险得多。所以这里打印迁移提示、退 1、绝不执行任何切换。
9570
+ console.error('✗ `botmux cd` 已移除,改用 `botmux role switch <角色目录>`(同一切换语义)。');
9571
+ console.error(' 本次未执行任何切换。若你是角色协议(_role-protocol.md)触发的,请把命令刷新为 `botmux role switch`。');
9572
+ process.exit(1);
9573
+ break;
9574
+ }
9575
+ case 'role': {
9576
+ // `botmux role switch <角色目录>` — 角色切换(唯一入口)。名字→目录的解析由
9577
+ // 调用方(模型读 _role-protocol.md)完成,本命令只透传解析出的目标目录,daemon
9578
+ // 侧硬校验目录必须在 ~/botmux-roles 下。
9579
+ const sub = process.argv[3] ?? '';
9580
+ if (sub === 'switch') {
9581
+ await cmdRoleSwitch(process.argv.slice(4));
9582
+ break;
9583
+ }
9584
+ console.error(`用法: botmux role switch <目标角色目录(含空格建议加引号)> [--session <id>]`);
9585
+ process.exit(1);
9406
9586
  break;
9587
+ }
9407
9588
  case 'term-link':
9408
9589
  await cmdTermLink(process.argv.slice(3));
9409
9590
  break;
@@ -9542,6 +9723,11 @@ switch (command) {
9542
9723
  await cmdV3(process.argv[3] ?? '', process.argv.slice(4));
9543
9724
  break;
9544
9725
  }
9726
+ case 'goal': {
9727
+ const { cmdGoal } = await import('./workflows/v3/goal-cli.js');
9728
+ process.exitCode = await cmdGoal(process.argv[3] ?? '', process.argv.slice(4));
9729
+ break;
9730
+ }
9545
9731
  case 'send':
9546
9732
  await cmdSend(process.argv.slice(3));
9547
9733
  break;