botmux 2.49.0-canary.1 → 2.50.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 (515) hide show
  1. package/README.en.md +40 -32
  2. package/README.md +40 -31
  3. package/dist/adapters/adopt-route.d.ts +63 -0
  4. package/dist/adapters/adopt-route.d.ts.map +1 -0
  5. package/dist/adapters/adopt-route.js +195 -0
  6. package/dist/adapters/adopt-route.js.map +1 -0
  7. package/dist/adapters/backend/tmux-backend.d.ts +5 -3
  8. package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
  9. package/dist/adapters/backend/tmux-backend.js +48 -12
  10. package/dist/adapters/backend/tmux-backend.js.map +1 -1
  11. package/dist/adapters/backend/tmux-pipe-backend.d.ts +11 -0
  12. package/dist/adapters/backend/tmux-pipe-backend.d.ts.map +1 -1
  13. package/dist/adapters/backend/tmux-pipe-backend.js +17 -1
  14. package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -1
  15. package/dist/adapters/cli/aiden.js +2 -3
  16. package/dist/adapters/cli/aiden.js.map +1 -1
  17. package/dist/adapters/cli/antigravity.js +2 -2
  18. package/dist/adapters/cli/antigravity.js.map +1 -1
  19. package/dist/adapters/cli/claude-code.d.ts.map +1 -1
  20. package/dist/adapters/cli/claude-code.js +40 -15
  21. package/dist/adapters/cli/claude-code.js.map +1 -1
  22. package/dist/adapters/cli/coco.d.ts.map +1 -1
  23. package/dist/adapters/cli/coco.js +27 -3
  24. package/dist/adapters/cli/coco.js.map +1 -1
  25. package/dist/adapters/cli/codex-app.d.ts +4 -0
  26. package/dist/adapters/cli/codex-app.d.ts.map +1 -0
  27. package/dist/adapters/cli/codex-app.js +72 -0
  28. package/dist/adapters/cli/codex-app.js.map +1 -0
  29. package/dist/adapters/cli/codex.d.ts.map +1 -1
  30. package/dist/adapters/cli/codex.js +50 -18
  31. package/dist/adapters/cli/codex.js.map +1 -1
  32. package/dist/adapters/cli/cursor.d.ts.map +1 -1
  33. package/dist/adapters/cli/cursor.js +59 -13
  34. package/dist/adapters/cli/cursor.js.map +1 -1
  35. package/dist/adapters/cli/gemini.d.ts.map +1 -1
  36. package/dist/adapters/cli/gemini.js +6 -2
  37. package/dist/adapters/cli/gemini.js.map +1 -1
  38. package/dist/adapters/cli/hermes.d.ts +4 -0
  39. package/dist/adapters/cli/hermes.d.ts.map +1 -0
  40. package/dist/adapters/cli/hermes.js +40 -0
  41. package/dist/adapters/cli/hermes.js.map +1 -0
  42. package/dist/adapters/cli/mira.d.ts +4 -0
  43. package/dist/adapters/cli/mira.d.ts.map +1 -0
  44. package/dist/adapters/cli/mira.js +67 -0
  45. package/dist/adapters/cli/mira.js.map +1 -0
  46. package/dist/adapters/cli/mtr.d.ts +5 -0
  47. package/dist/adapters/cli/mtr.d.ts.map +1 -0
  48. package/dist/adapters/cli/mtr.js +62 -0
  49. package/dist/adapters/cli/mtr.js.map +1 -0
  50. package/dist/adapters/cli/opencode.d.ts.map +1 -1
  51. package/dist/adapters/cli/opencode.js +19 -1
  52. package/dist/adapters/cli/opencode.js.map +1 -1
  53. package/dist/adapters/cli/registry.d.ts +5 -1
  54. package/dist/adapters/cli/registry.d.ts.map +1 -1
  55. package/dist/adapters/cli/registry.js +22 -2
  56. package/dist/adapters/cli/registry.js.map +1 -1
  57. package/dist/adapters/cli/shared-hints.d.ts +1 -1
  58. package/dist/adapters/cli/shared-hints.d.ts.map +1 -1
  59. package/dist/adapters/cli/shared-hints.js +2 -1
  60. package/dist/adapters/cli/shared-hints.js.map +1 -1
  61. package/dist/adapters/cli/types.d.ts +36 -7
  62. package/dist/adapters/cli/types.d.ts.map +1 -1
  63. package/dist/adapters/hook-command.d.ts +18 -0
  64. package/dist/adapters/hook-command.d.ts.map +1 -0
  65. package/dist/adapters/hook-command.js +38 -0
  66. package/dist/adapters/hook-command.js.map +1 -0
  67. package/dist/adapters/hook-installer.d.ts +14 -0
  68. package/dist/adapters/hook-installer.d.ts.map +1 -0
  69. package/dist/adapters/hook-installer.js +192 -0
  70. package/dist/adapters/hook-installer.js.map +1 -0
  71. package/dist/bot-registry.d.ts +79 -3
  72. package/dist/bot-registry.d.ts.map +1 -1
  73. package/dist/bot-registry.js +74 -1
  74. package/dist/bot-registry.js.map +1 -1
  75. package/dist/cli/bots-list-output.d.ts +8 -0
  76. package/dist/cli/bots-list-output.d.ts.map +1 -1
  77. package/dist/cli/bots-list-output.js +9 -0
  78. package/dist/cli/bots-list-output.js.map +1 -1
  79. package/dist/cli.d.ts +15 -1
  80. package/dist/cli.d.ts.map +1 -1
  81. package/dist/cli.js +686 -116
  82. package/dist/cli.js.map +1 -1
  83. package/dist/codex-app-runner.d.ts +3 -0
  84. package/dist/codex-app-runner.d.ts.map +1 -0
  85. package/dist/codex-app-runner.js +512 -0
  86. package/dist/codex-app-runner.js.map +1 -0
  87. package/dist/config.d.ts +12 -2
  88. package/dist/config.d.ts.map +1 -1
  89. package/dist/config.js +21 -4
  90. package/dist/config.js.map +1 -1
  91. package/dist/core/ask-api.d.ts +47 -0
  92. package/dist/core/ask-api.d.ts.map +1 -0
  93. package/dist/core/ask-api.js +139 -0
  94. package/dist/core/ask-api.js.map +1 -0
  95. package/dist/core/ask-args.d.ts +53 -0
  96. package/dist/core/ask-args.d.ts.map +1 -0
  97. package/dist/core/ask-args.js +122 -0
  98. package/dist/core/ask-args.js.map +1 -0
  99. package/dist/core/ask-broker.d.ts +98 -0
  100. package/dist/core/ask-broker.d.ts.map +1 -0
  101. package/dist/core/ask-broker.js +329 -0
  102. package/dist/core/ask-broker.js.map +1 -0
  103. package/dist/core/ask-hook/claude-code.d.ts +50 -0
  104. package/dist/core/ask-hook/claude-code.d.ts.map +1 -0
  105. package/dist/core/ask-hook/claude-code.js +145 -0
  106. package/dist/core/ask-hook/claude-code.js.map +1 -0
  107. package/dist/core/ask-hook/codex.d.ts +43 -0
  108. package/dist/core/ask-hook/codex.d.ts.map +1 -0
  109. package/dist/core/ask-hook/codex.js +69 -0
  110. package/dist/core/ask-hook/codex.js.map +1 -0
  111. package/dist/core/ask-hook/opencode.d.ts +41 -0
  112. package/dist/core/ask-hook/opencode.d.ts.map +1 -0
  113. package/dist/core/ask-hook/opencode.js +108 -0
  114. package/dist/core/ask-hook/opencode.js.map +1 -0
  115. package/dist/core/ask-hook/registry.d.ts +3 -0
  116. package/dist/core/ask-hook/registry.d.ts.map +1 -0
  117. package/dist/core/ask-hook/registry.js +12 -0
  118. package/dist/core/ask-hook/registry.js.map +1 -0
  119. package/dist/core/ask-hook/types.d.ts +26 -0
  120. package/dist/core/ask-hook/types.d.ts.map +1 -0
  121. package/dist/core/ask-hook/types.js +2 -0
  122. package/dist/core/ask-hook/types.js.map +1 -0
  123. package/dist/core/ask-types.d.ts +146 -0
  124. package/dist/core/ask-types.d.ts.map +1 -0
  125. package/dist/core/ask-types.js +18 -0
  126. package/dist/core/ask-types.js.map +1 -0
  127. package/dist/core/auto-start.d.ts +61 -0
  128. package/dist/core/auto-start.d.ts.map +1 -0
  129. package/dist/core/auto-start.js +62 -0
  130. package/dist/core/auto-start.js.map +1 -0
  131. package/dist/core/command-handler.d.ts +29 -0
  132. package/dist/core/command-handler.d.ts.map +1 -1
  133. package/dist/core/command-handler.js +789 -313
  134. package/dist/core/command-handler.js.map +1 -1
  135. package/dist/core/dashboard-ipc-server.d.ts +2 -0
  136. package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
  137. package/dist/core/dashboard-ipc-server.js +232 -3
  138. package/dist/core/dashboard-ipc-server.js.map +1 -1
  139. package/dist/core/dashboard-rows.d.ts +3 -0
  140. package/dist/core/dashboard-rows.d.ts.map +1 -1
  141. package/dist/core/dashboard-rows.js +2 -0
  142. package/dist/core/dashboard-rows.js.map +1 -1
  143. package/dist/core/role-resolver.d.ts +17 -1
  144. package/dist/core/role-resolver.d.ts.map +1 -1
  145. package/dist/core/role-resolver.js +64 -10
  146. package/dist/core/role-resolver.js.map +1 -1
  147. package/dist/core/session-discovery.d.ts.map +1 -1
  148. package/dist/core/session-discovery.js +19 -5
  149. package/dist/core/session-discovery.js.map +1 -1
  150. package/dist/core/session-manager.d.ts +3 -3
  151. package/dist/core/session-manager.d.ts.map +1 -1
  152. package/dist/core/session-manager.js +84 -28
  153. package/dist/core/session-manager.js.map +1 -1
  154. package/dist/core/terminal-proxy.d.ts +32 -0
  155. package/dist/core/terminal-proxy.d.ts.map +1 -0
  156. package/dist/core/terminal-proxy.js +139 -0
  157. package/dist/core/terminal-proxy.js.map +1 -0
  158. package/dist/core/terminal-url.d.ts +27 -0
  159. package/dist/core/terminal-url.d.ts.map +1 -0
  160. package/dist/core/terminal-url.js +26 -0
  161. package/dist/core/terminal-url.js.map +1 -0
  162. package/dist/core/trigger-session.d.ts +9 -0
  163. package/dist/core/trigger-session.d.ts.map +1 -0
  164. package/dist/core/trigger-session.js +158 -0
  165. package/dist/core/trigger-session.js.map +1 -0
  166. package/dist/core/types.d.ts +5 -0
  167. package/dist/core/types.d.ts.map +1 -1
  168. package/dist/core/types.js.map +1 -1
  169. package/dist/core/worker-pool.d.ts +141 -0
  170. package/dist/core/worker-pool.d.ts.map +1 -1
  171. package/dist/core/worker-pool.js +550 -30
  172. package/dist/core/worker-pool.js.map +1 -1
  173. package/dist/daemon.d.ts.map +1 -1
  174. package/dist/daemon.js +459 -68
  175. package/dist/daemon.js.map +1 -1
  176. package/dist/dashboard/auth.d.ts +6 -1
  177. package/dist/dashboard/auth.d.ts.map +1 -1
  178. package/dist/dashboard/auth.js +9 -1
  179. package/dist/dashboard/auth.js.map +1 -1
  180. package/dist/dashboard/bot-onboarding.d.ts.map +1 -1
  181. package/dist/dashboard/bot-onboarding.js +24 -2
  182. package/dist/dashboard/bot-onboarding.js.map +1 -1
  183. package/dist/dashboard/connector-api.d.ts +3 -0
  184. package/dist/dashboard/connector-api.d.ts.map +1 -0
  185. package/dist/dashboard/connector-api.js +351 -0
  186. package/dist/dashboard/connector-api.js.map +1 -0
  187. package/dist/dashboard/federated-group-core.d.ts +54 -0
  188. package/dist/dashboard/federated-group-core.d.ts.map +1 -0
  189. package/dist/dashboard/federated-group-core.js +165 -0
  190. package/dist/dashboard/federated-group-core.js.map +1 -0
  191. package/dist/dashboard/federation-api.d.ts +42 -0
  192. package/dist/dashboard/federation-api.d.ts.map +1 -0
  193. package/dist/dashboard/federation-api.js +408 -0
  194. package/dist/dashboard/federation-api.js.map +1 -0
  195. package/dist/dashboard/federation-spoke-api.d.ts +82 -0
  196. package/dist/dashboard/federation-spoke-api.d.ts.map +1 -0
  197. package/dist/dashboard/federation-spoke-api.js +645 -0
  198. package/dist/dashboard/federation-spoke-api.js.map +1 -0
  199. package/dist/dashboard/team-group.d.ts +18 -0
  200. package/dist/dashboard/team-group.d.ts.map +1 -0
  201. package/dist/dashboard/team-group.js +7 -0
  202. package/dist/dashboard/team-group.js.map +1 -0
  203. package/dist/dashboard/trigger-api.d.ts +13 -0
  204. package/dist/dashboard/trigger-api.d.ts.map +1 -0
  205. package/dist/dashboard/trigger-api.js +77 -0
  206. package/dist/dashboard/trigger-api.js.map +1 -0
  207. package/dist/dashboard/web/app.d.ts +1 -1
  208. package/dist/dashboard/web/app.d.ts.map +1 -1
  209. package/dist/dashboard/web/app.js +44 -0
  210. package/dist/dashboard/web/app.js.map +1 -1
  211. package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
  212. package/dist/dashboard/web/bot-defaults.js +397 -20
  213. package/dist/dashboard/web/bot-defaults.js.map +1 -1
  214. package/dist/dashboard/web/connectors.d.ts +2 -0
  215. package/dist/dashboard/web/connectors.d.ts.map +1 -0
  216. package/dist/dashboard/web/connectors.js +187 -0
  217. package/dist/dashboard/web/connectors.js.map +1 -0
  218. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  219. package/dist/dashboard/web/i18n.js +75 -5
  220. package/dist/dashboard/web/i18n.js.map +1 -1
  221. package/dist/dashboard/web/sessions.d.ts.map +1 -1
  222. package/dist/dashboard/web/sessions.js +5 -1
  223. package/dist/dashboard/web/sessions.js.map +1 -1
  224. package/dist/dashboard/web/team-federation.d.ts +3 -0
  225. package/dist/dashboard/web/team-federation.d.ts.map +1 -0
  226. package/dist/dashboard/web/team-federation.js +485 -0
  227. package/dist/dashboard/web/team-federation.js.map +1 -0
  228. package/dist/dashboard/web/workflows.js +3 -3
  229. package/dist/dashboard/web/workflows.js.map +1 -1
  230. package/dist/dashboard/webhook-routes.d.ts +19 -0
  231. package/dist/dashboard/webhook-routes.d.ts.map +1 -0
  232. package/dist/dashboard/webhook-routes.js +321 -0
  233. package/dist/dashboard/webhook-routes.js.map +1 -0
  234. package/dist/dashboard/workflow-api.d.ts +8 -1
  235. package/dist/dashboard/workflow-api.d.ts.map +1 -1
  236. package/dist/dashboard/workflow-api.js +19 -4
  237. package/dist/dashboard/workflow-api.js.map +1 -1
  238. package/dist/dashboard-web/app.js +579 -377
  239. package/dist/dashboard-web/index.html +3 -1
  240. package/dist/dashboard-web/style.css +63 -1
  241. package/dist/dashboard.js +202 -2
  242. package/dist/dashboard.js.map +1 -1
  243. package/dist/i18n/en.d.ts.map +1 -1
  244. package/dist/i18n/en.js +120 -15
  245. package/dist/i18n/en.js.map +1 -1
  246. package/dist/i18n/zh.d.ts.map +1 -1
  247. package/dist/i18n/zh.js +120 -15
  248. package/dist/i18n/zh.js.map +1 -1
  249. package/dist/im/lark/ask-card.d.ts +55 -0
  250. package/dist/im/lark/ask-card.d.ts.map +1 -0
  251. package/dist/im/lark/ask-card.js +328 -0
  252. package/dist/im/lark/ask-card.js.map +1 -0
  253. package/dist/im/lark/card-builder.d.ts +122 -8
  254. package/dist/im/lark/card-builder.d.ts.map +1 -1
  255. package/dist/im/lark/card-builder.js +528 -56
  256. package/dist/im/lark/card-builder.js.map +1 -1
  257. package/dist/im/lark/card-handler.d.ts.map +1 -1
  258. package/dist/im/lark/card-handler.js +337 -36
  259. package/dist/im/lark/card-handler.js.map +1 -1
  260. package/dist/im/lark/client.d.ts +112 -0
  261. package/dist/im/lark/client.d.ts.map +1 -1
  262. package/dist/im/lark/client.js +385 -70
  263. package/dist/im/lark/client.js.map +1 -1
  264. package/dist/im/lark/event-dispatcher.d.ts +9 -2
  265. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  266. package/dist/im/lark/event-dispatcher.js +90 -19
  267. package/dist/im/lark/event-dispatcher.js.map +1 -1
  268. package/dist/im/lark/grant-command.d.ts +8 -1
  269. package/dist/im/lark/grant-command.d.ts.map +1 -1
  270. package/dist/im/lark/grant-command.js +53 -24
  271. package/dist/im/lark/grant-command.js.map +1 -1
  272. package/dist/im/lark/grant-pending.d.ts +3 -0
  273. package/dist/im/lark/grant-pending.d.ts.map +1 -1
  274. package/dist/im/lark/grant-pending.js +8 -1
  275. package/dist/im/lark/grant-pending.js.map +1 -1
  276. package/dist/im/lark/identity-cache.d.ts.map +1 -1
  277. package/dist/im/lark/identity-cache.js +3 -3
  278. package/dist/im/lark/identity-cache.js.map +1 -1
  279. package/dist/im/lark/md-card.d.ts +20 -2
  280. package/dist/im/lark/md-card.d.ts.map +1 -1
  281. package/dist/im/lark/md-card.js +49 -17
  282. package/dist/im/lark/md-card.js.map +1 -1
  283. package/dist/im/lark/message-parser.d.ts.map +1 -1
  284. package/dist/im/lark/message-parser.js +87 -31
  285. package/dist/im/lark/message-parser.js.map +1 -1
  286. package/dist/im/lark/workflow-card-handler.d.ts +2 -2
  287. package/dist/im/lark/workflow-card-handler.d.ts.map +1 -1
  288. package/dist/im/lark/workflow-card-handler.js +12 -1
  289. package/dist/im/lark/workflow-card-handler.js.map +1 -1
  290. package/dist/im/lark/workflow-progress-card.d.ts.map +1 -1
  291. package/dist/im/lark/workflow-progress-card.js +53 -0
  292. package/dist/im/lark/workflow-progress-card.js.map +1 -1
  293. package/dist/mira-output.d.ts +3 -0
  294. package/dist/mira-output.d.ts.map +1 -0
  295. package/dist/mira-output.js +136 -0
  296. package/dist/mira-output.js.map +1 -0
  297. package/dist/mira-runner.d.ts +3 -0
  298. package/dist/mira-runner.d.ts.map +1 -0
  299. package/dist/mira-runner.js +534 -0
  300. package/dist/mira-runner.js.map +1 -0
  301. package/dist/services/bot-owner-store.d.ts +28 -0
  302. package/dist/services/bot-owner-store.d.ts.map +1 -0
  303. package/dist/services/bot-owner-store.js +82 -0
  304. package/dist/services/bot-owner-store.js.map +1 -0
  305. package/dist/services/bot-profile-store.d.ts +16 -0
  306. package/dist/services/bot-profile-store.d.ts.map +1 -0
  307. package/dist/services/bot-profile-store.js +98 -0
  308. package/dist/services/bot-profile-store.js.map +1 -0
  309. package/dist/services/brand-store.d.ts +15 -0
  310. package/dist/services/brand-store.d.ts.map +1 -0
  311. package/dist/services/brand-store.js +47 -0
  312. package/dist/services/brand-store.js.map +1 -0
  313. package/dist/services/card-prefs-store.d.ts +26 -0
  314. package/dist/services/card-prefs-store.d.ts.map +1 -0
  315. package/dist/services/card-prefs-store.js +119 -0
  316. package/dist/services/card-prefs-store.js.map +1 -0
  317. package/dist/services/codex-bridge-queue.d.ts +1 -0
  318. package/dist/services/codex-bridge-queue.d.ts.map +1 -1
  319. package/dist/services/codex-bridge-queue.js +72 -19
  320. package/dist/services/codex-bridge-queue.js.map +1 -1
  321. package/dist/services/codex-transcript.d.ts +1 -0
  322. package/dist/services/codex-transcript.d.ts.map +1 -1
  323. package/dist/services/codex-transcript.js.map +1 -1
  324. package/dist/services/connector-store.d.ts +58 -0
  325. package/dist/services/connector-store.d.ts.map +1 -0
  326. package/dist/services/connector-store.js +79 -0
  327. package/dist/services/connector-store.js.map +1 -0
  328. package/dist/services/deployment-identity.d.ts +22 -0
  329. package/dist/services/deployment-identity.d.ts.map +1 -0
  330. package/dist/services/deployment-identity.js +67 -0
  331. package/dist/services/deployment-identity.js.map +1 -0
  332. package/dist/services/federation-membership-store.d.ts +23 -0
  333. package/dist/services/federation-membership-store.d.ts.map +1 -0
  334. package/dist/services/federation-membership-store.js +66 -0
  335. package/dist/services/federation-membership-store.js.map +1 -0
  336. package/dist/services/federation-roster.d.ts +54 -0
  337. package/dist/services/federation-roster.d.ts.map +1 -0
  338. package/dist/services/federation-roster.js +51 -0
  339. package/dist/services/federation-roster.js.map +1 -0
  340. package/dist/services/federation-store.d.ts +76 -0
  341. package/dist/services/federation-store.d.ts.map +1 -0
  342. package/dist/services/federation-store.js +133 -0
  343. package/dist/services/federation-store.js.map +1 -0
  344. package/dist/services/grant-store.d.ts +12 -2
  345. package/dist/services/grant-store.d.ts.map +1 -1
  346. package/dist/services/grant-store.js +51 -4
  347. package/dist/services/grant-store.js.map +1 -1
  348. package/dist/services/group-creator.d.ts +10 -0
  349. package/dist/services/group-creator.d.ts.map +1 -1
  350. package/dist/services/group-creator.js +26 -1
  351. package/dist/services/group-creator.js.map +1 -1
  352. package/dist/services/groups-store.d.ts +30 -0
  353. package/dist/services/groups-store.d.ts.map +1 -1
  354. package/dist/services/groups-store.js +85 -12
  355. package/dist/services/groups-store.js.map +1 -1
  356. package/dist/services/hermes-transcript.d.ts +7 -0
  357. package/dist/services/hermes-transcript.d.ts.map +1 -0
  358. package/dist/services/hermes-transcript.js +117 -0
  359. package/dist/services/hermes-transcript.js.map +1 -0
  360. package/dist/services/invite-store.d.ts +28 -0
  361. package/dist/services/invite-store.d.ts.map +1 -0
  362. package/dist/services/invite-store.js +85 -0
  363. package/dist/services/invite-store.js.map +1 -0
  364. package/dist/services/mtr-transcript.d.ts +14 -0
  365. package/dist/services/mtr-transcript.d.ts.map +1 -0
  366. package/dist/services/mtr-transcript.js +291 -0
  367. package/dist/services/mtr-transcript.js.map +1 -0
  368. package/dist/services/pairing-store.d.ts +47 -0
  369. package/dist/services/pairing-store.d.ts.map +1 -0
  370. package/dist/services/pairing-store.js +132 -0
  371. package/dist/services/pairing-store.js.map +1 -0
  372. package/dist/services/project-scanner.d.ts +10 -0
  373. package/dist/services/project-scanner.d.ts.map +1 -1
  374. package/dist/services/project-scanner.js +11 -0
  375. package/dist/services/project-scanner.js.map +1 -1
  376. package/dist/services/relay-picker.d.ts +22 -0
  377. package/dist/services/relay-picker.d.ts.map +1 -0
  378. package/dist/services/relay-picker.js +82 -0
  379. package/dist/services/relay-picker.js.map +1 -0
  380. package/dist/services/send-policy.d.ts +55 -0
  381. package/dist/services/send-policy.d.ts.map +1 -0
  382. package/dist/services/send-policy.js +47 -0
  383. package/dist/services/send-policy.js.map +1 -0
  384. package/dist/services/session-store.js +1 -1
  385. package/dist/services/session-store.js.map +1 -1
  386. package/dist/services/team-roster.d.ts +38 -0
  387. package/dist/services/team-roster.d.ts.map +1 -0
  388. package/dist/services/team-roster.js +82 -0
  389. package/dist/services/team-roster.js.map +1 -0
  390. package/dist/services/team-store.d.ts +54 -0
  391. package/dist/services/team-store.d.ts.map +1 -0
  392. package/dist/services/team-store.js +156 -0
  393. package/dist/services/team-store.js.map +1 -0
  394. package/dist/services/trigger-log-store.d.ts +46 -0
  395. package/dist/services/trigger-log-store.d.ts.map +1 -0
  396. package/dist/services/trigger-log-store.js +132 -0
  397. package/dist/services/trigger-log-store.js.map +1 -0
  398. package/dist/services/trigger-types.d.ts +57 -0
  399. package/dist/services/trigger-types.d.ts.map +1 -0
  400. package/dist/services/trigger-types.js +28 -0
  401. package/dist/services/trigger-types.js.map +1 -0
  402. package/dist/services/webhook-key.d.ts +16 -0
  403. package/dist/services/webhook-key.d.ts.map +1 -0
  404. package/dist/services/webhook-key.js +123 -0
  405. package/dist/services/webhook-key.js.map +1 -0
  406. package/dist/services/webhook-lifecycle-extractors.d.ts +15 -0
  407. package/dist/services/webhook-lifecycle-extractors.d.ts.map +1 -0
  408. package/dist/services/webhook-lifecycle-extractors.js +59 -0
  409. package/dist/services/webhook-lifecycle-extractors.js.map +1 -0
  410. package/dist/services/webhook-lifecycle-store.d.ts +45 -0
  411. package/dist/services/webhook-lifecycle-store.d.ts.map +1 -0
  412. package/dist/services/webhook-lifecycle-store.js +159 -0
  413. package/dist/services/webhook-lifecycle-store.js.map +1 -0
  414. package/dist/setup/bot-config-editor.d.ts +13 -3
  415. package/dist/setup/bot-config-editor.d.ts.map +1 -1
  416. package/dist/setup/bot-config-editor.js +27 -6
  417. package/dist/setup/bot-config-editor.js.map +1 -1
  418. package/dist/setup/ensure-tmux.d.ts +0 -22
  419. package/dist/setup/ensure-tmux.d.ts.map +1 -1
  420. package/dist/setup/ensure-tmux.js +25 -1
  421. package/dist/setup/ensure-tmux.js.map +1 -1
  422. package/dist/setup/open-platform-automation.d.ts +149 -0
  423. package/dist/setup/open-platform-automation.d.ts.map +1 -0
  424. package/dist/setup/open-platform-automation.js +845 -0
  425. package/dist/setup/open-platform-automation.js.map +1 -0
  426. package/dist/setup/verify-permissions.d.ts.map +1 -1
  427. package/dist/setup/verify-permissions.js +19 -2
  428. package/dist/setup/verify-permissions.js.map +1 -1
  429. package/dist/skills/definitions.d.ts +2 -0
  430. package/dist/skills/definitions.d.ts.map +1 -1
  431. package/dist/skills/definitions.js +178 -12
  432. package/dist/skills/definitions.js.map +1 -1
  433. package/dist/skills/installer.d.ts +34 -0
  434. package/dist/skills/installer.d.ts.map +1 -1
  435. package/dist/skills/installer.js +119 -2
  436. package/dist/skills/installer.js.map +1 -1
  437. package/dist/types.d.ts +29 -1
  438. package/dist/types.d.ts.map +1 -1
  439. package/dist/utils/bot-routing.d.ts +50 -0
  440. package/dist/utils/bot-routing.d.ts.map +1 -1
  441. package/dist/utils/bot-routing.js +83 -0
  442. package/dist/utils/bot-routing.js.map +1 -1
  443. package/dist/utils/child-env.d.ts +35 -0
  444. package/dist/utils/child-env.d.ts.map +1 -0
  445. package/dist/utils/child-env.js +40 -0
  446. package/dist/utils/child-env.js.map +1 -0
  447. package/dist/utils/daemon-discovery.d.ts +11 -0
  448. package/dist/utils/daemon-discovery.d.ts.map +1 -0
  449. package/dist/utils/daemon-discovery.js +59 -0
  450. package/dist/utils/daemon-discovery.js.map +1 -0
  451. package/dist/utils/user-token.d.ts.map +1 -1
  452. package/dist/utils/user-token.js +0 -2
  453. package/dist/utils/user-token.js.map +1 -1
  454. package/dist/worker.js +365 -77
  455. package/dist/worker.js.map +1 -1
  456. package/dist/workflows/attempt-resume.d.ts.map +1 -1
  457. package/dist/workflows/attempt-resume.js +2 -2
  458. package/dist/workflows/attempt-resume.js.map +1 -1
  459. package/dist/workflows/definition.d.ts +420 -17
  460. package/dist/workflows/definition.d.ts.map +1 -1
  461. package/dist/workflows/definition.js +238 -3
  462. package/dist/workflows/definition.js.map +1 -1
  463. package/dist/workflows/events/payloads.d.ts +122 -19
  464. package/dist/workflows/events/payloads.d.ts.map +1 -1
  465. package/dist/workflows/events/payloads.js +46 -0
  466. package/dist/workflows/events/payloads.js.map +1 -1
  467. package/dist/workflows/events/replay.d.ts +21 -0
  468. package/dist/workflows/events/replay.d.ts.map +1 -1
  469. package/dist/workflows/events/replay.js +103 -0
  470. package/dist/workflows/events/replay.js.map +1 -1
  471. package/dist/workflows/events/schema.d.ts +1752 -1057
  472. package/dist/workflows/events/schema.d.ts.map +1 -1
  473. package/dist/workflows/events/schema.js +37 -1
  474. package/dist/workflows/events/schema.js.map +1 -1
  475. package/dist/workflows/events/types.d.ts +5 -1
  476. package/dist/workflows/events/types.d.ts.map +1 -1
  477. package/dist/workflows/loader.d.ts +14 -0
  478. package/dist/workflows/loader.d.ts.map +1 -1
  479. package/dist/workflows/loader.js +27 -0
  480. package/dist/workflows/loader.js.map +1 -1
  481. package/dist/workflows/loop.js +58 -0
  482. package/dist/workflows/loop.js.map +1 -1
  483. package/dist/workflows/ops-projection.d.ts +58 -0
  484. package/dist/workflows/ops-projection.d.ts.map +1 -1
  485. package/dist/workflows/ops-projection.js +74 -0
  486. package/dist/workflows/ops-projection.js.map +1 -1
  487. package/dist/workflows/orchestrator.d.ts +65 -1
  488. package/dist/workflows/orchestrator.d.ts.map +1 -1
  489. package/dist/workflows/orchestrator.js +486 -74
  490. package/dist/workflows/orchestrator.js.map +1 -1
  491. package/dist/workflows/output-binding.d.ts +8 -1
  492. package/dist/workflows/output-binding.d.ts.map +1 -1
  493. package/dist/workflows/output-binding.js +75 -11
  494. package/dist/workflows/output-binding.js.map +1 -1
  495. package/dist/workflows/runtime.d.ts +1 -1
  496. package/dist/workflows/runtime.d.ts.map +1 -1
  497. package/dist/workflows/runtime.js +39 -4
  498. package/dist/workflows/runtime.js.map +1 -1
  499. package/dist/workflows/trigger-from-envelope.d.ts +13 -0
  500. package/dist/workflows/trigger-from-envelope.d.ts.map +1 -0
  501. package/dist/workflows/trigger-from-envelope.js +67 -0
  502. package/dist/workflows/trigger-from-envelope.js.map +1 -0
  503. package/dist/workflows/wait.d.ts +23 -2
  504. package/dist/workflows/wait.d.ts.map +1 -1
  505. package/dist/workflows/wait.js +39 -17
  506. package/dist/workflows/wait.js.map +1 -1
  507. package/package.json +1 -1
  508. package/dist/services/feishu-task-client.d.ts +0 -28
  509. package/dist/services/feishu-task-client.d.ts.map +0 -1
  510. package/dist/services/feishu-task-client.js +0 -123
  511. package/dist/services/feishu-task-client.js.map +0 -1
  512. package/dist/services/task-store.d.ts +0 -37
  513. package/dist/services/task-store.d.ts.map +0 -1
  514. package/dist/services/task-store.js +0 -115
  515. package/dist/services/task-store.js.map +0 -1
package/README.en.md CHANGED
@@ -62,7 +62,8 @@ Compared to OpenClaw-style approaches built on Agent SDKs:
62
62
  ## Prerequisites
63
63
 
64
64
  - **Node.js** >= 20
65
- - **AI coding CLI** installed and authenticated (`claude`, `codex`, `cursor-agent`, `gemini`, `opencode`, or `agy` (Antigravity) in PATH)
65
+ - **AI coding CLI / local agent app** installed and authenticated (`claude`, `codex`, `coco`, `cursor-agent`, `gemini`, `opencode`, `hermes`, or `agy` (Antigravity) in PATH)
66
+ - **CoCo requires `0.120.32+`**: type-ahead (sending a new message while a turn is still running, parked in CoCo's own message queue) relies on 0.120.32+ behavior; earlier versions may drop or serialize input while busy — upgrade before use
66
67
  - **tmux** >= 3.x (optional — auto-enabled when installed for persistent CLI sessions)
67
68
  - **CJK fonts** (only needed for screenshot rendering of Chinese text / emoji):
68
69
  - macOS: ships with PingFang / Hiragino, no action needed
@@ -71,43 +72,46 @@ Compared to OpenClaw-style approaches built on Agent SDKs:
71
72
 
72
73
  ## 5-Minute Setup
73
74
 
74
- > 💡 **TL;DR**: run `botmux setup` and pick "scan-to-create" to finish Steps 1+2 in one shot (the official `@larksuiteoapi/node-sdk` device flow gives you the AppID/AppSecret). PersonalAgent apps come with event subscriptions and bot capability pre-configured, so only Step 4 (permissions) + Step 5 (optional redirect URL) + Step 6 (publish) require browser clicks; the setup wizard writes a JSON file with a one-line clipboard copy command and prints deep-links to each remaining step.
75
+ > 💡 **TL;DR**: `npm i -g botmux` → `botmux setup` and **scan two QR codes** to get a working bot `botmux start`. The 1st scan creates the app and saves the AppID/AppSecret (event subscriptions + bot capability pre-configured); the 2nd scan lets botmux's built-in Feishu Web login **import permissions, configure the redirect URL, and create + submit a publish version automatically**. Steps 4 (permissions) / 5 (redirect) / 6 (publish) below are all done automatically by setup and folded as a manual fallback; pass `--no-open-platform-auto` to skip the second auto-config step.
75
76
 
76
- ### Step 1: Create a Lark App
77
+ ### Step 1: Install botmux
77
78
 
78
- **Recommended**: `botmux setup` → pick "1) Scan-to-create app". Scan with the Lark mobile app and the AppID/AppSecret are persisted automatically; no manual browser navigation. Falls back to manual paste on cancel/timeout/network error.
79
+ ```bash
80
+ npm install -g botmux
81
+ ```
79
82
 
80
- > ⚠️ **Currently only Feishu (feishu.cn) tenants are supported.** If scan detects a Lark international (larksuite.com) tenant, setup aborts — the daemon runtime (Lark Client/WSClient/event-dispatcher) hasn't been wired up for the `larksuite.com` domain yet, so accepting Lark credentials would land users in a half-working state. A follow-up PR will add full Lark support.
83
+ > Requires **Node.js 20**, with at least one AI coding CLI installed and authenticated (`claude` / `codex` / `cursor-agent` / `gemini` / `opencode` / `coco` / `agy` on your PATH). Installing **tmux** too is recommended (enables session persistence automatically).
81
84
 
82
- **Manual**: go to the [Lark Open Platform](https://open.larkoffice.com/app) and click "Create Custom App".
85
+ ### Step 2: Create the App & Configure (`botmux setup`)
83
86
 
84
- ![Create App](docs/setup/create-app.png)
87
+ Run `botmux setup` and follow the interactive menu:
85
88
 
86
- ### Step 2: Get Credentials
89
+ 1. **New config**: type `1` and press Enter (with an existing config, type `2` to add a bot).
90
+ 2. **Create the bot**:
91
+ - Type `1` → **Scan-to-create (recommended)**: scan with the Lark mobile app and a PersonalAgent app is created with AppID/AppSecret persisted automatically, **with event subscriptions + bot capability pre-configured** — no manual browser navigation. Uses the official `@larksuiteoapi/node-sdk` device flow.
92
+ - Type `2` → **Manual**: go to the [Lark Open Platform](https://open.larkoffice.com/app), create a "Custom App", copy **App ID / App Secret** from "Credentials & Basic Info", and paste them back.
93
+ 3. **Pick the CLI**: choose the CLI to bridge (e.g. type `1` for Claude Code).
94
+ 4. **Default working dir**: usually the **parent directory** of your git projects (e.g. `~/projects`); new topics scan **downward** for git repos (up to 3 levels). Avoid `~` (too many folders to traverse).
87
95
 
88
- > The scan-to-create path completes this step automatically; skip to Step 3.
96
+ > ⚠️ **Currently only Feishu (feishu.cn) tenants are supported.** If scan detects a Lark international (larksuite.com) tenant, setup aborts — the daemon runtime (Lark Client/WSClient/event-dispatcher) hasn't been wired up for the `larksuite.com` domain yet. A follow-up PR will add full Lark support.
89
97
 
90
- Open the app details page "Credentials & Basic Info", and copy the **App ID** and **App Secret**.
98
+ At the end, setup validates credentials with a `tenant_access_token` call (only writing `bots.json` on success), writes the full scope JSON to `~/.botmux/lark-scopes.json`, and prints a one-line clipboard copy command plus deep-links to each remaining step.
91
99
 
92
- ![Get Credentials](docs/setup/credentials.png)
100
+ ![Create App](docs/setup/create-app.png)
93
101
 
94
- ### Step 3: Install & Start botmux
102
+ ### Step 3: Start
95
103
 
96
104
  ```bash
97
- # Install
98
- npm install -g botmux
99
-
100
- # Interactive setup — pick "1) Scan-to-create app" or "2) Paste AppID/Secret manually".
101
- # Credentials are validated with a tenant_access_token call before bots.json is written.
102
- # At the end of setup the wizard writes the full scope JSON to ~/.botmux/lark-scopes.json
103
- # and prints a one-line clipboard copy command for your platform.
104
- botmux setup
105
-
106
- # Start (if you ever need to verify the event subscription, Lark requires the daemon to be running so it can detect the WebSocket connection)
107
- # Re-validates credentials before forking workers; missing scopes only WARN, do not block the daemon.
108
105
  botmux start
109
106
  ```
110
107
 
108
+ > `start` re-validates credentials before forking workers; missing scopes only WARN, they don't block the daemon. If you later need to verify the event subscription, Lark requires the daemon to be running so it can detect the WebSocket connection.
109
+
110
+ <details>
111
+ <summary><b>Manual Open Platform config: permissions / redirect / publish (fallback)</b> —— botmux setup does these automatically (during the 2nd scan); expand only if auto-config failed or you want to verify manually</summary>
112
+
113
+ <br>
114
+
111
115
  ### Step 4: Add Permissions
112
116
 
113
117
  Run the copy-to-clipboard command setup printed, then go to "Permissions & Scopes" → "Batch Import/Export" and paste. Submit for review — visibility "only me" auto-approves.
@@ -145,6 +149,8 @@ Go to "Version Management & Release", click "Create Version" and publish. Set av
145
149
 
146
150
  ![Publish](docs/setup/publish.png)
147
151
 
152
+ </details>
153
+
148
154
  ### Step 7: Create a Group and Start Chatting
149
155
 
150
156
  1. Create a **topic-enabled group** in Lark
@@ -306,9 +312,9 @@ Send these straight into a topic — the daemon intercepts them (no clash with t
306
312
 
307
313
  | Command | Description |
308
314
  |---------|-------------|
309
- | `/repo` | Show project selector card (interactive dropdown + text list) |
315
+ | `/repo` | While a repo is pending selection, launch in the default workingDir; mid-session, show the project selector card (interactive dropdown + text list) |
310
316
  | `/repo <N>` | Switch to Nth project from last scan |
311
- | `/skip` | Skip the repo selector card, start the session in the default dir |
317
+ | `/repo <path\|name>` | Skip the selector card; pass a path (relative/absolute) or a first-level project name under workingDir |
312
318
  | `/cd <path>` | Change working directory and restart the CLI process |
313
319
  | `/status` | Show session info (uptime, terminal URL, etc.) |
314
320
  | `/restart` | Restart CLI process (keeps the session context) |
@@ -355,8 +361,8 @@ Send these straight into a topic — the daemon intercepts them (no clash with t
355
361
 
356
362
  | Command | Description |
357
363
  |---------|-------------|
358
- | `@bot /grant @someone` | Pop an authorization card to add the user to the "this chat" or "global" allowlist; also auto-pops (and @s the owner) when an unauthorized user @-mentions the bot |
359
- | `@bot /revoke @someone` | Revoke the user's this-chat + global access |
364
+ | `@bot /grant @someone` | Pop an authorization card to add the user to the "this chat" or "global" allowlist; you can @ several people/bots at once (one card lists every target, one scope click applies to all); if a granted target is a bot, it's auto-registered into the roster on success (an implicit `/introduce`) for cross-bot collaboration; also auto-pops (and @s the owner) when an unauthorized user @-mentions the bot |
365
+ | `@bot /revoke @someone` | Revoke the user's this-chat + global access; you can @ several people/bots at once |
360
366
 
361
367
  **🆕 One-shot session group**
362
368
 
@@ -369,7 +375,7 @@ Send these straight into a topic — the daemon intercepts them (no clash with t
369
375
  | Command | Description |
370
376
  |---------|-------------|
371
377
  | `@botA @botB /t <prompt>` | With multiple bots, each @-mentioned bot opens its own independent topic from the same message |
372
- | `@botA @botB /introduce` | Bots register each other's open_id so they can later explicitly @-mention one another across sessions (any @ order, extra text allowed) |
378
+ | `@botA @botB /introduce` | Bots register each other's open_id so they can later explicitly @-mention one another across sessions (any @ order, extra text allowed; roster-only, grants no permission — **anyone in the chat can run it, no authorization needed**) |
373
379
 
374
380
  **❓ Help**
375
381
 
@@ -414,7 +420,7 @@ Configure bots via `~/.botmux/bots.json`. Run `botmux setup` to create it intera
414
420
  botmux setup
415
421
  ```
416
422
 
417
- When `~/.botmux/bots.json` already exists, `botmux setup` can add a bot, reconfigure from scratch, edit an existing bot, or delete a bot config. The edit/delete flow accepts the process name shown by `botmux status` (e.g. `botmux-1` or a custom `botmux-claude-main`) or the `larkAppId`; empty input keeps the current value, and `-` clears optional fields such as `name`, `backendType`, `workingDir`, and `allowedUsers`. Changing `larkAppId` asks for confirmation because historical session/chat state under the old app ID is not migrated automatically. Deleting a bot only removes one local `bots.json` entry; it does not delete the Lark app, historical messages, or local session data. Run `botmux restart` for changes to take effect.
423
+ When `~/.botmux/bots.json` already exists, `botmux setup` can add a bot, reconfigure from scratch, edit an existing bot, or delete a bot config. The edit/delete flow accepts the process name shown by `botmux status` (e.g. `botmux-1` or a custom `botmux-claude-main`) or the `larkAppId`; empty input keeps the current value, and `-` clears optional fields such as `name`, `model`, `backendType`, `workingDir`, and `allowedUsers`. Changing `larkAppId` asks for confirmation because historical session/chat state under the old app ID is not migrated automatically. Deleting a bot only removes one local `bots.json` entry; it does not delete the Lark app, historical messages, or local session data. Run `botmux restart` for changes to take effect.
418
424
 
419
425
  **bots.json format:**
420
426
 
@@ -425,7 +431,7 @@ When `~/.botmux/bots.json` already exists, `botmux setup` can add a bot, reconfi
425
431
  "larkAppSecret": "secret_1",
426
432
  "name": "claude-main",
427
433
  "cliId": "claude-code",
428
- "disableCliBypass": true,
434
+ "model": "sonnet",
429
435
  "workingDir": "~/projects",
430
436
  "allowedUsers": ["alice@company.com"],
431
437
  "allowedChatGroups": ["oc_xxx_team"]
@@ -434,6 +440,7 @@ When `~/.botmux/bots.json` already exists, `botmux setup` can add a bot, reconfi
434
440
  "larkAppId": "cli_xxx_bot2",
435
441
  "larkAppSecret": "secret_2",
436
442
  "cliId": "codex",
443
+ "model": "gpt-5-codex",
437
444
  "workingDir": "~/work"
438
445
  }
439
446
  ]
@@ -444,14 +451,15 @@ When `~/.botmux/bots.json` already exists, `botmux setup` can add a bot, reconfi
444
451
  | `larkAppId` | Yes | Lark app ID |
445
452
  | `larkAppSecret` | Yes | Lark app secret |
446
453
  | `name` | No | Process name suffix shown by `botmux status`; e.g. `claude-main` appears as `botmux-claude-main`, defaults to `botmux-<index>` |
447
- | `cliId` | No | CLI adapter, defaults to `claude-code` (options: `aiden`, `coco`, `codex`, `cursor`, `gemini`, `opencode`, `antigravity`) |
454
+ | `cliId` | No | CLI adapter, defaults to `claude-code` (options: `aiden`, `coco`, `codex`, `codex-app`, `cursor`, `gemini`, `opencode`, `antigravity`, `hermes`) |
455
+ | `model` | No | Model name used when spawning the CLI. Currently honored by: `claude-code`, `codex`, `coco`, `cursor`, `gemini`, `opencode`; other adapters ignore the field. Leave empty to use the CLI default. `botmux setup` proposes per-CLI candidates plus a free-form Other option. |
448
456
  | `cliPathOverride` | No | Absolute path to the CLI entry, for wrappers / routers; typical use: `ccr`, `claude-w`, `aiden-x-claude`, etc. |
449
- | `disableCliBypass` | No | Whether to disable botmux's default CLI bypass / weak-sandbox flag injection. Missing or `false` keeps the legacy behavior: botmux still adds flags such as `--yolo`, `--dangerously-*`, `--force`, or `--permission-mode agentFull`. When `true`, botmux stops adding those flags |
450
457
  | `backendType` | No | Session backend: `pty` or `tmux` (auto-detected by default) |
451
458
  | `workingDir` | No | Default working directory, supports comma-separated. The new-topic repo-select card scans for git repos **from this directory downward** (recursive, up to 3 levels), no longer climbing to the parent: point it at a repos root (e.g. `~/projects`) to list every repo beneath it, or at a single repo to list just that repo (and its linked worktrees) |
452
459
  | `defaultWorkingDir` | No | Single-repo default: new topics with no oncall binding and no peer-session inheritance spawn directly here, skipping the repo-select card. `/cd <path>` still switches mid-session; the next new topic falls back to this default. **Difference from `defaultOncall`:** does NOT write `oncallChats` and does NOT change the `canTalk` / `canOperate` permission model |
453
460
  | `allowedUsers` | No | Allowed users (**full emails** like `alice@example.com`, or open_ids `ou_xxx`). Email prefixes can't be resolved and are dropped. Required (at least one entry, as owner) when `allowedChatGroups` is set |
454
461
  | `allowedChatGroups` | No | Talk-open chats (`chat_id`, for example `oc_xxx`). Any member talking **inside these chats** can use the bot (decided by the message's chat — new members work immediately, removed members lose access, no restart needed); grants `canTalk` only, sensitive ops still require `allowedUsers`. Equivalent to the owner running `/grant` (no target) in that chat. |
462
+ | `globalGrants` | No | Global talk allowlist (`open_id` list, e.g. `ou_xxx`; humans or bots). Listed entries can talk to the bot in **any** chat; grants `canTalk` only, sensitive ops still require `allowedUsers`. Usually written via the owner's `/grant` card (the "grant talk globally" button); can also be set manually here. |
455
463
  | `oncallChats` | No | Oncall bindings (written by `/oncall bind`), e.g. `[{ "chatId": "oc_xxx", "workingDir": "~/projects/foo" }]`; any group member can @ the bot |
456
464
 
457
465
  **Config priority:** `BOTS_CONFIG` env var > `~/.botmux/bots.json`
package/README.md CHANGED
@@ -169,7 +169,8 @@ CLI 进入 botmux 会话时自动获得 `~/.botmux/bin` 在 PATH 中,以及一
169
169
  ## 前置要求
170
170
 
171
171
  - **Node.js** >= 20
172
- - **AI 编程 CLI** 已安装并完成认证(`claude`、`codex`、`cursor-agent`、`gemini`、`opencode` 或 `agy`(Antigravity)在 PATH 中)
172
+ - **AI 编程 CLI / 本地 Agent 应用** 已安装并完成认证(`claude`、`codex`、`coco`、`cursor-agent`、`gemini`、`opencode`、`hermes` 或 `agy`(Antigravity)在 PATH 中)
173
+ - **CoCo 最低版本 `0.120.32`**:type-ahead(会话忙时即可发新消息,由 CoCo 自己的消息队列接住)依赖 0.120.32+ 的行为;更早版本忙时输入可能丢失或串行,请升级后再用
173
174
  - **tmux** >= 3.x(可选,安装后自动启用会话常驻)
174
175
  - **CJK 字体**(用于截图渲染中文/emoji):
175
176
  - macOS 自带 PingFang/Hiragino,无需配置
@@ -178,42 +179,46 @@ CLI 进入 botmux 会话时自动获得 `~/.botmux/bin` 在 PATH 中,以及一
178
179
 
179
180
  ## 5 分钟快速接入
180
181
 
181
- > 💡 **TL;DR**:跑 `botmux setup` 选「扫码建应用」一步完成 Step 1+2(拿 AppID/AppSecret)。PersonalAgent 应用建出来时事件订阅和 bot 能力都已默认配好,只剩 Step 4 权限申请 + Step 5(按需)重定向 URL + Step 6 发版三步要在浏览器手动点;setup 完成后会自动写 JSON 文件 + 打印一键复制命令 + 各步骤的深链。
182
+ > 💡 **TL;DR**:`npm i -g botmux` → `botmux setup`,**扫两次码**就能建好一个可用机器人 → `botmux start`。第 1 次扫码建应用、拿到 AppID/AppSecret(事件订阅 + bot 能力默认已配好);第 2 次扫码让 botmux 内置的飞书 Web 登录**自动导入权限、配置重定向 URL、创建并提交发布版本**。下面的 Step 4 权限 / Step 5 重定向 / Step 6 发版都已由 setup 默认自动完成、折叠为手动备用;加 `--no-open-platform-auto` 可跳过第二次自动配置、改走手动。
182
183
 
183
- ### Step 1: 创建飞书应用
184
+ ### Step 1: 安装 botmux
184
185
 
185
- **推荐路径**:`botmux setup` 选「1) 扫码建应用」,飞书扫码完成后自动落盘 AppID/AppSecret,无需手动浏览器创建。底层走 `@larksuiteoapi/node-sdk` 的官方 device flow。
186
+ ```bash
187
+ npm install -g botmux
188
+ ```
186
189
 
187
- > ⚠️ **目前仅支持飞书 (feishu.cn) 租户**。扫码检测到 Lark 国际版 (larksuite.com) 会中止 setup —— daemon runtime (Lark Client/WSClient/event-dispatcher 等) 需要一并接入 lark 域,会在单独 PR 跟进。
190
+ > 要求 **Node.js 20**,且本地已装好并登录至少一种 AI 编程 CLI(`claude` / `codex` / `cursor-agent` / `gemini` / `opencode` / `coco` / `agy` 等在 PATH 中)。推荐顺手装 **tmux**(装了自动启用会话常驻)。
188
191
 
189
- **手动路径**:打开 [飞书开放平台](https://open.larkoffice.com/app),点击「创建企业自建应用」。
192
+ ### Step 2: 创建应用并配置(`botmux setup`)
190
193
 
191
- ![创建应用](docs/setup/create-app.png)
194
+ 跑 `botmux setup`,按交互菜单一步步选:
192
195
 
193
- ### Step 2: 获取凭证
196
+ 1. **新建配置**:输入 `1` 回车(已有配置时输入 `2` 添加机器人)。
197
+ 2. **创建机器人**:
198
+ - 输入 `1` → **扫码创建(推荐)**:飞书扫码完成后自动建出 PersonalAgent 应用并落盘 AppID/AppSecret,**事件订阅 + bot 能力默认已配好**,无需手动浏览器创建。底层走 `@larksuiteoapi/node-sdk` 官方 device flow。
199
+ - 输入 `2` → **手动创建**:去 [飞书开放平台](https://open.larkoffice.com/app) 建「企业自建应用」,在「凭证与基础信息」复制 **App ID / App Secret** 回来粘贴。
200
+ 3. **选择 CLI**:选本次要接入的 CLI(如接 Claude Code 就选 `1`)。
201
+ 4. **默认工作目录**:通常填 git 项目的**父级目录**(如 `~/projects`),新话题会从该目录**向下**查找 git 仓库(最多 3 层);尽量别填 `~`(要遍历太多文件夹)。
194
202
 
195
- > 扫码路径自动完成此步,可直接跳到 Step 3。
203
+ > ⚠️ **目前仅支持飞书 (feishu.cn) 租户**。扫码检测到 Lark 国际版 (larksuite.com) 会中止 setup —— daemon runtime (Lark Client/WSClient/event-dispatcher 等) 需要一并接入 lark 域,会在单独 PR 跟进。
196
204
 
197
- 进入应用详情 →「凭证与基础信息」,复制 **App ID** **App Secret**。
205
+ setup 末尾会用 `tenant_access_token` 校验凭证(通过才落盘 `bots.json`),并把完整权限 JSON 写到 `~/.botmux/lark-scopes.json` + 打印一键复制命令 + 各步骤深链。
198
206
 
199
- ![获取凭证](docs/setup/credentials.png)
207
+ ![扫码建应用](docs/setup/create-app.png)
200
208
 
201
- ### Step 3: 安装 & 启动 botmux
209
+ ### Step 3: 启动
202
210
 
203
211
  ```bash
204
- # 安装
205
- npm install -g botmux
206
-
207
- # 交互式配置 — 选「1) 扫码建应用」或「2) 手动粘 AppID/Secret」
208
- # 凭证拿到后自动取一次 tenant_access_token 校验,通过才落盘 bots.json
209
- # setup 末尾会把完整权限 JSON 写到 ~/.botmux/lark-scopes.json 并打印一键复制命令
210
- botmux setup
211
-
212
- # 启动(如果之后需要确认事件订阅,飞书后台会要求 daemon 已在跑才能识别长连接)
213
- # start 前再校验一次凭证;权限未配齐不会阻塞 daemon,只 WARN
214
212
  botmux start
215
213
  ```
216
214
 
215
+ > start 前再校验一次凭证;权限未配齐不会阻塞 daemon,只 WARN。如果之后需要确认事件订阅,飞书后台会要求 daemon 已在跑才能识别长连接。
216
+
217
+ <details>
218
+ <summary><b>手动配置开放平台:权限 / 重定向 / 发版(备用)</b> —— 这三步 botmux setup 默认已自动完成(扫第二次码时),仅在自动配置失败、或想手动核对时展开</summary>
219
+
220
+ <br>
221
+
217
222
  ### Step 4: 添加权限
218
223
 
219
224
  setup 完成后,按 terminal 提示的一键复制命令把权限 JSON 复制到剪贴板,进入「权限管理」→「批量导入/导出权限」粘贴 → 提交审批。可用性范围选「仅自己可见」会自动通过:
@@ -251,6 +256,8 @@ http://127.0.0.1:9768/callback
251
256
 
252
257
  ![发版](docs/setup/publish.png)
253
258
 
259
+ </details>
260
+
254
261
  ### Step 7: 建群开聊
255
262
 
256
263
  1. 飞书中创建一个**话题群**
@@ -300,9 +307,9 @@ botmux autostart enable
300
307
 
301
308
  | 命令 | 说明 |
302
309
  |------|------|
303
- | `/repo` | 显示项目选择卡片(交互式下拉 + 文本列表) |
310
+ | `/repo` | 仓库待选时直接用默认 workingDir 启动会话;会话进行中则弹出项目选择卡片(交互式下拉 + 文本列表) |
304
311
  | `/repo <N>` | 切换到上次扫描的第 N 个项目 |
305
- | `/skip` | 跳过仓库选择卡片,直接用默认目录开启会话 |
312
+ | `/repo <路径\|项目名>` | 跳过选择卡片,直接指定路径(相对/绝对)或 workingDir 下的一级项目名 |
306
313
  | `/cd <路径>` | 切换工作目录并重启 CLI 进程 |
307
314
  | `/status` | 查看会话信息(运行时间、终端地址等) |
308
315
  | `/restart` | 重启 CLI 进程(保留 session 上下文) |
@@ -349,8 +356,8 @@ botmux autostart enable
349
356
 
350
357
  | 命令 | 说明 |
351
358
  |------|------|
352
- | `@机器人 /grant @某人` | 弹授权卡片,把对方加进「本群使用」或「全局」白名单;无权限者 @ 机器人时也会自动弹这张卡并 @owner |
353
- | `@机器人 /revoke @某人` | 撤销对方的本群 + 全局授权 |
359
+ | `@机器人 /grant @某人` | 弹授权卡片,把对方加进「本群使用」或「全局」白名单;可一次 @ 多人/多 bot(一张卡列出全部目标、点一次范围对全部生效);被授权的若是 bot,授权成功后会自动登记进花名册(等于顺带 `/introduce` 一次)便于跨 bot 协作;无权限者 @ 机器人时也会自动弹这张卡并 @owner |
360
+ | `@机器人 /revoke @某人` | 撤销对方的本群 + 全局授权;可一次 @ 多人/多 bot |
354
361
 
355
362
  **🆕 一键新建会话群**
356
363
 
@@ -363,7 +370,7 @@ botmux autostart enable
363
370
  | 命令 | 说明 |
364
371
  |------|------|
365
372
  | `@botA @botB /t <prompt>` | 多机器人时,让每个被 @ 的机器人在同一条消息上各自独立开新话题 |
366
- | `@botA @botB /introduce` | 互相登记彼此的 open_id,便于后续跨 bot 显式 @mention 协作(@ 顺序任意,可带额外文本) |
373
+ | `@botA @botB /introduce` | 互相登记彼此的 open_id,便于后续跨 bot 显式 @mention 协作(@ 顺序任意,可带额外文本;只记花名册、不授予任何权限,**群内任何人都可用、无需授权**) |
367
374
 
368
375
  **❓ 帮助**
369
376
 
@@ -518,7 +525,7 @@ dashboard 走单独 pm2 进程 `botmux-dashboard`,跟着 `pnpm daemon:restart`
518
525
  botmux setup
519
526
  ```
520
527
 
521
- 已有 `~/.botmux/bots.json` 时,`botmux setup` 支持添加新机器人、重新配置、编辑现有机器人,以及删除机器人配置。编辑或删除时用 `botmux status` 里的进程名(如 `botmux-1` 或自定义的 `botmux-claude-main`)或 `larkAppId` 选择目标;字段留空表示保留当前值,`name`、`cliPathOverride`、`backendType`、`workingDir`、`allowedUsers` 等可选字段输入 `-` 表示清空。修改 `larkAppId` 会提示确认,因为旧 appId 下的历史会话和群聊状态数据不会自动迁移。删除机器人只移除本机 `bots.json` 中的一项,不删除飞书开放平台应用、历史消息或本地会话数据;修改完成后运行 `botmux restart` 生效。
528
+ 已有 `~/.botmux/bots.json` 时,`botmux setup` 支持添加新机器人、重新配置、编辑现有机器人,以及删除机器人配置。编辑或删除时用 `botmux status` 里的进程名(如 `botmux-1` 或自定义的 `botmux-claude-main`)或 `larkAppId` 选择目标;字段留空表示保留当前值,`name`、`model`、`cliPathOverride`、`backendType`、`workingDir`、`allowedUsers` 等可选字段输入 `-` 表示清空。修改 `larkAppId` 会提示确认,因为旧 appId 下的历史会话和群聊状态数据不会自动迁移。删除机器人只移除本机 `bots.json` 中的一项,不删除飞书开放平台应用、历史消息或本地会话数据;修改完成后运行 `botmux restart` 生效。
522
529
 
523
530
  **bots.json 格式:**
524
531
 
@@ -529,7 +536,7 @@ botmux setup
529
536
  "larkAppSecret": "secret_1",
530
537
  "name": "claude-main",
531
538
  "cliId": "claude-code",
532
- "disableCliBypass": true,
539
+ "model": "sonnet",
533
540
  "workingDir": "~/projects",
534
541
  "allowedUsers": ["alice@company.com"],
535
542
  "allowedChatGroups": ["oc_xxx_team"]
@@ -538,6 +545,7 @@ botmux setup
538
545
  "larkAppId": "cli_xxx_bot2",
539
546
  "larkAppSecret": "secret_2",
540
547
  "cliId": "codex",
548
+ "model": "gpt-5-codex",
541
549
  "workingDir": "~/work"
542
550
  }
543
551
  ]
@@ -548,14 +556,15 @@ botmux setup
548
556
  | `larkAppId` | 是 | 飞书应用 App ID |
549
557
  | `larkAppSecret` | 是 | 飞书应用 App Secret |
550
558
  | `name` | 否 | `botmux status` 中的进程名后缀;例如 `claude-main` 会显示为 `botmux-claude-main`,留空默认 `botmux-<序号>` |
551
- | `cliId` | 否 | CLI 适配器,默认 `claude-code`(可选:`aiden`、`coco`、`codex`、`cursor`、`gemini`、`opencode`、`antigravity`) |
559
+ | `cliId` | 否 | CLI 适配器,默认 `claude-code`(可选:`aiden`、`coco`、`codex`、`codex-app`、`cursor`、`gemini`、`opencode`、`antigravity`、`hermes`) |
560
+ | `model` | 否 | 启动 CLI 时使用的模型名;留空走 CLI 默认。当前会注入到支持模型参数的适配器:`claude-code` / `codex` / `coco` / `cursor` / `gemini` / `opencode`;其它适配器会忽略该字段 |
552
561
  | `cliPathOverride` | 否 | CLI 入口的绝对路径,用于套 wrapper / router;典型场景:ccr、claude-w、aiden-x-claude 等自定义入口 |
553
- | `disableCliBypass` | 否 | 是否禁用 botmux 默认注入的 CLI bypass / 弱沙箱参数。未配置或 `false` 时保持兼容旧逻辑,botmux 会继续添加 `--yolo`、`--dangerously-*`、`--force`、`--permission-mode agentFull` 等参数;设为 `true` 时不再自动添加这些参数 |
554
562
  | `backendType` | 否 | 会话后端:`pty` 或 `tmux`(默认自动检测) |
555
563
  | `workingDir` | 否 | 默认工作目录,支持逗号分隔多个目录。新话题的 repo 选择卡片会**从该目录自身向下**递归查找 git 仓库(最多 3 层),不再向上扫父目录:指向仓库集合根目录(如 `~/projects`)即列出其下所有仓库,指向单个仓库则只列该仓库(及其 linked worktrees) |
556
564
  | `defaultWorkingDir` | 否 | 单仓库默认目录:新话题在无 oncall 绑定 / 无同群兄弟 session 时直接进入该目录,跳过 repo 选择卡片。`/cd <path>` 仍可临时切换;下一个新话题回到该默认值。**与 `defaultOncall` 的区别**:不写 `oncallChats`、不修改 `canTalk`/`canOperate` 权限模型 |
557
565
  | `allowedUsers` | 否 | 允许的用户列表(**完整邮箱**如 `alice@example.com`,或 open_id `ou_xxx`)。邮箱前缀无法解析、会被丢弃。配置了 `allowedChatGroups` 时此项必须至少有一个条目作为 owner |
558
566
  | `allowedChatGroups` | 否 | 可对话群列表(飞书 `chat_id`,如 `oc_xxx`)。**在这些群里**任何成员都能与机器人对话(按消息所在群判断,新人进群即生效、退群即失权,无需重启);仅授对话权(`canTalk`),敏感操作仍由 `allowedUsers` 控制。等价于 owner 在该群发 `/grant`(不带 @)。 |
567
+ | `globalGrants` | 否 | 全局可对话名单(`open_id` 列表,如 `ou_xxx`;人或 bot 均可)。名单内的对象可在**任意群**与机器人对话;仅授对话权(`canTalk`),敏感操作仍由 `allowedUsers` 控制。通常由 owner 在授权卡上点「全局授权对话」写入,也可在此手动配置。 |
559
568
  | `oncallChats` | 否 | oncall 绑定(`/oncall bind` 写入),形如 `[{ "chatId": "oc_xxx", "workingDir": "~/projects/foo" }]`,群内任何成员可 @ 提问 |
560
569
 
561
570
  **配置优先级:** `BOTS_CONFIG` 环境变量 → `~/.botmux/bots.json`
@@ -0,0 +1,63 @@
1
+ /**
2
+ * adopt-route.ts
3
+ *
4
+ * 为没有 BOTMUX_* 环境变量的"孤立" Claude 进程(即通过 /adopt 接管的外部 CLI)
5
+ * 提供 askUserQuestion hook 的路由解析逻辑。
6
+ *
7
+ * 通过以下步骤确定目标 Lark 会话:
8
+ * 1. 收集 hook 进程的祖先 PID 链
9
+ * 2. 遍历在线 daemon,查询每个 daemon 是否有以某祖先 PID 启动的 adopt 会话
10
+ * 3. 首个命中即返回路由信息
11
+ */
12
+ /** 从 daemon 取回的 adopt 会话路由信息 */
13
+ export interface AdoptRoute {
14
+ sessionId: string;
15
+ chatId: string;
16
+ larkAppId: string;
17
+ rootMessageId: string;
18
+ }
19
+ /**
20
+ * 沿进程祖先链向上收集 PID(不含 startPid 自己)。
21
+ *
22
+ * @param startPid 起始进程 PID(自身不包含在结果中)
23
+ * @param readParent 注入式父 PID 读取函数(默认使用 /proc 或 ps)
24
+ * @param maxDepth 最大深度,防止意外无限循环(默认 40)
25
+ * @returns 祖先 PID 数组,从最近父进程到最远祖先
26
+ */
27
+ export declare function getAncestorPids(startPid: number, readParent?: (pid: number) => number | null, maxDepth?: number): number[];
28
+ /**
29
+ * 查询某个 daemon 是否有以指定 PID 启动的活跃 adopt 会话。
30
+ *
31
+ * GET http://127.0.0.1:<ipcPort>/api/adopt-session/<pid>
32
+ * 200 → 解析 AdoptRoute;其它状态码或异常 → null(不抛)。
33
+ * 超时:2 秒(AbortController)。
34
+ */
35
+ export declare function queryAdoptSession(ipcPort: number, pid: number): Promise<AdoptRoute | null>;
36
+ /**
37
+ * 通过祖先 PID 匹配在线 adopt 会话。
38
+ *
39
+ * **并发 + 全局 budget 封顶**:候选 = daemon 列表序 × 祖先链序(由近及远)逐个编号;
40
+ * 全部并发查询(每请求各自带 2s 超时),整体不超过 `budgetMs`。命中按候选 index 取
41
+ * 最小,保持确定性。
42
+ *
43
+ * 为何要全局 budget:runHook 在缺 BOTMUX_* 时同步 await 本函数,而全局 hook 会覆盖
44
+ * 非 botmux 的 Claude 会话;若某 daemon still-online 但 IPC 不响应,顺序 await 会
45
+ * `祖先数 × 2s × daemon 数` 线性叠加(可达几十秒),把真·非 botmux 的 ask 卡死。
46
+ * 并发让总耗时收敛到单请求量级,budget 再封顶,保证快速 passthrough。
47
+ *
48
+ * @param deps.startPid hook 进程自身的 PID
49
+ * @param deps.listDaemons 列出在线 daemon(ipcPort)
50
+ * @param deps.queryDaemon 查询某 daemon 是否有该 pid 的活跃 adopt 会话
51
+ * @param deps.getAncestors 取祖先 PID(默认使用 getAncestorPids)
52
+ * @param deps.budgetMs 整体耗时上限(默认 1500ms;可注入便于测试)
53
+ */
54
+ export declare function resolveAdoptRoute(deps: {
55
+ startPid: number;
56
+ listDaemons: () => Array<{
57
+ ipcPort: number;
58
+ }>;
59
+ queryDaemon: (ipcPort: number, pid: number) => Promise<AdoptRoute | null>;
60
+ getAncestors?: (startPid: number) => number[];
61
+ budgetMs?: number;
62
+ }): Promise<AdoptRoute | null>;
63
+ //# sourceMappingURL=adopt-route.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adopt-route.d.ts","sourceRoot":"","sources":["../../src/adapters/adopt-route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,gCAAgC;AAChC,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AA8CD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,EAC3C,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,EAAE,CAiBV;AAID;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAgC5B;AAID;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9C,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAC1E,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CA+C7B"}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * adopt-route.ts
3
+ *
4
+ * 为没有 BOTMUX_* 环境变量的"孤立" Claude 进程(即通过 /adopt 接管的外部 CLI)
5
+ * 提供 askUserQuestion hook 的路由解析逻辑。
6
+ *
7
+ * 通过以下步骤确定目标 Lark 会话:
8
+ * 1. 收集 hook 进程的祖先 PID 链
9
+ * 2. 遍历在线 daemon,查询每个 daemon 是否有以某祖先 PID 启动的 adopt 会话
10
+ * 3. 首个命中即返回路由信息
11
+ */
12
+ import { execFileSync } from 'node:child_process';
13
+ import { readFileSync } from 'node:fs';
14
+ // ── 祖先 PID 收集 ──────────────────────────────────────────────────────────────
15
+ /**
16
+ * 读取某进程的父 PID。
17
+ *
18
+ * 默认实现:
19
+ * 1. 优先从 /proc/<pid>/stat 读取(Linux),第 4 字段(0-based)是 ppid。
20
+ * 注意 stat 第 2 字段 comm 可以含括号和空格,所以从最后一个 `)` 之后的子串解析。
21
+ * 2. 失败时回退到 `ps -o ppid= -p <pid>`(macOS/Linux 通用)。
22
+ *
23
+ * 失败/进程不存在 → 返回 null。
24
+ */
25
+ function defaultReadParent(pid) {
26
+ // 先尝试 /proc(Linux 最快)
27
+ try {
28
+ const stat = readFileSync(`/proc/${pid}/stat`, 'utf-8');
29
+ // stat 格式: "<pid> (<comm>) <state> <ppid> ..."
30
+ // comm 字段可能含空格和括号,取最后一个 ')' 之后的部分
31
+ const lastParen = stat.lastIndexOf(')');
32
+ if (lastParen === -1)
33
+ throw new Error('unexpected /proc stat format');
34
+ const tail = stat.slice(lastParen + 1).trim();
35
+ // tail: "<state> <ppid> ..."
36
+ const parts = tail.split(' ');
37
+ // parts[0] = state, parts[1] = ppid
38
+ const ppid = parseInt(parts[1], 10);
39
+ if (Number.isInteger(ppid) && ppid > 0)
40
+ return ppid;
41
+ }
42
+ catch {
43
+ // /proc 不可用或解析失败,回退到 ps
44
+ }
45
+ // 回退到 ps(macOS / 无 /proc 的 Linux)
46
+ try {
47
+ const out = execFileSync('ps', ['-o', 'ppid=', '-p', String(pid)], {
48
+ encoding: 'utf-8',
49
+ });
50
+ const ppid = parseInt(out.trim(), 10);
51
+ if (Number.isInteger(ppid) && ppid > 0)
52
+ return ppid;
53
+ }
54
+ catch {
55
+ // 进程不存在或 ps 调用失败
56
+ }
57
+ return null;
58
+ }
59
+ /**
60
+ * 沿进程祖先链向上收集 PID(不含 startPid 自己)。
61
+ *
62
+ * @param startPid 起始进程 PID(自身不包含在结果中)
63
+ * @param readParent 注入式父 PID 读取函数(默认使用 /proc 或 ps)
64
+ * @param maxDepth 最大深度,防止意外无限循环(默认 40)
65
+ * @returns 祖先 PID 数组,从最近父进程到最远祖先
66
+ */
67
+ export function getAncestorPids(startPid, readParent, maxDepth) {
68
+ const reader = readParent ?? defaultReadParent;
69
+ const depth = maxDepth ?? 40;
70
+ const ancestors = [];
71
+ const visited = new Set([startPid]);
72
+ let current = startPid;
73
+ for (let i = 0; i < depth; i++) {
74
+ const parent = reader(current);
75
+ if (parent === null || parent <= 1)
76
+ break; // 到 init 或读不到,停止
77
+ if (visited.has(parent))
78
+ break; // 防环
79
+ visited.add(parent);
80
+ ancestors.push(parent);
81
+ current = parent;
82
+ }
83
+ return ancestors;
84
+ }
85
+ // ── Daemon 查询辅助 ─────────────────────────────────────────────────────────────
86
+ /**
87
+ * 查询某个 daemon 是否有以指定 PID 启动的活跃 adopt 会话。
88
+ *
89
+ * GET http://127.0.0.1:<ipcPort>/api/adopt-session/<pid>
90
+ * 200 → 解析 AdoptRoute;其它状态码或异常 → null(不抛)。
91
+ * 超时:2 秒(AbortController)。
92
+ */
93
+ export async function queryAdoptSession(ipcPort, pid) {
94
+ const controller = new AbortController();
95
+ const timer = setTimeout(() => controller.abort(), 2000);
96
+ try {
97
+ const res = await fetch(`http://127.0.0.1:${ipcPort}/api/adopt-session/${pid}`, { signal: controller.signal });
98
+ if (!res.ok)
99
+ return null;
100
+ const body = (await res.json());
101
+ if (!body || typeof body !== 'object')
102
+ return null;
103
+ const b = body;
104
+ if (typeof b.sessionId !== 'string' ||
105
+ typeof b.chatId !== 'string' ||
106
+ typeof b.larkAppId !== 'string' ||
107
+ typeof b.rootMessageId !== 'string') {
108
+ return null;
109
+ }
110
+ return {
111
+ sessionId: b.sessionId,
112
+ chatId: b.chatId,
113
+ larkAppId: b.larkAppId,
114
+ rootMessageId: b.rootMessageId,
115
+ };
116
+ }
117
+ catch {
118
+ // 超时、网络错误、JSON 解析失败等 → null
119
+ return null;
120
+ }
121
+ finally {
122
+ clearTimeout(timer);
123
+ }
124
+ }
125
+ // ── 主逻辑 ─────────────────────────────────────────────────────────────────────
126
+ /**
127
+ * 通过祖先 PID 匹配在线 adopt 会话。
128
+ *
129
+ * **并发 + 全局 budget 封顶**:候选 = daemon 列表序 × 祖先链序(由近及远)逐个编号;
130
+ * 全部并发查询(每请求各自带 2s 超时),整体不超过 `budgetMs`。命中按候选 index 取
131
+ * 最小,保持确定性。
132
+ *
133
+ * 为何要全局 budget:runHook 在缺 BOTMUX_* 时同步 await 本函数,而全局 hook 会覆盖
134
+ * 非 botmux 的 Claude 会话;若某 daemon still-online 但 IPC 不响应,顺序 await 会
135
+ * `祖先数 × 2s × daemon 数` 线性叠加(可达几十秒),把真·非 botmux 的 ask 卡死。
136
+ * 并发让总耗时收敛到单请求量级,budget 再封顶,保证快速 passthrough。
137
+ *
138
+ * @param deps.startPid hook 进程自身的 PID
139
+ * @param deps.listDaemons 列出在线 daemon(ipcPort)
140
+ * @param deps.queryDaemon 查询某 daemon 是否有该 pid 的活跃 adopt 会话
141
+ * @param deps.getAncestors 取祖先 PID(默认使用 getAncestorPids)
142
+ * @param deps.budgetMs 整体耗时上限(默认 1500ms;可注入便于测试)
143
+ */
144
+ export async function resolveAdoptRoute(deps) {
145
+ const { startPid, listDaemons, queryDaemon } = deps;
146
+ const getAncestors = deps.getAncestors ?? ((pid) => getAncestorPids(pid));
147
+ const budgetMs = deps.budgetMs ?? 1500;
148
+ const ancestors = getAncestors(startPid);
149
+ if (ancestors.length === 0)
150
+ return null;
151
+ const daemons = listDaemons();
152
+ if (daemons.length === 0)
153
+ return null;
154
+ // 候选编号:daemon 列表序 × 祖先链序(由近及远),index 决定确定性优先级。
155
+ const candidates = [];
156
+ let idx = 0;
157
+ for (const daemon of daemons) {
158
+ for (const pid of ancestors) {
159
+ candidates.push({ index: idx++, ipcPort: daemon.ipcPort, pid });
160
+ }
161
+ }
162
+ // 并发发起全部查询,命中按 index 记入 hits;整体被 budget 封顶。
163
+ const hits = new Map();
164
+ const queries = candidates.map(async (c) => {
165
+ const route = await queryDaemon(c.ipcPort, c.pid);
166
+ if (route)
167
+ hits.set(c.index, route);
168
+ });
169
+ let timer;
170
+ const budget = new Promise((resolve) => {
171
+ timer = setTimeout(resolve, budgetMs);
172
+ timer.unref?.();
173
+ });
174
+ try {
175
+ await Promise.race([Promise.allSettled(queries), budget]);
176
+ }
177
+ finally {
178
+ if (timer)
179
+ clearTimeout(timer);
180
+ }
181
+ // 在「budget 内已 settle 的命中」里按候选 index 升序取最早的一个(确定性)。
182
+ let best = null;
183
+ let bestIdx = Infinity;
184
+ for (const [i, route] of hits) {
185
+ if (i < bestIdx) {
186
+ bestIdx = i;
187
+ best = route;
188
+ }
189
+ }
190
+ if (best && process.env.BOTMUX_HOOK_DEBUG === '1') {
191
+ process.stderr.write(`[adopt-route] matched candidate#${bestIdx} session=${best.sessionId}\n`);
192
+ }
193
+ return best;
194
+ }
195
+ //# sourceMappingURL=adopt-route.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adopt-route.js","sourceRoot":"","sources":["../../src/adapters/adopt-route.ts"],"names":[],"mappings":"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"}
@@ -115,13 +115,15 @@ export declare function buildBotmuxEnvAssignments(env: NodeJS.ProcessEnv | undef
115
115
  * $0 = '_' (placeholder), $1 = cwd, $2..N = KEY=VAL... bin args...
116
116
  *
117
117
  * The `cd` step makes the CLI's cwd survive a wayward `cd` in the user's
118
- * rcfile. The `exec /usr/bin/env` step injects botmux's per-bot/per-session
119
- * overrides AFTER rcfile load so they can't be shadowed by leftover exports.
118
+ * rcfile. The `unset` step removes bare creds the pane inherited from the tmux
119
+ * server's global env (REDACTED_ENV_UNSET_CLAUSE). The `exec /usr/bin/env` step
120
+ * injects botmux's per-bot/per-session overrides AFTER rcfile load so they
121
+ * can't be shadowed by leftover exports.
120
122
  *
121
123
  * POSIX-syntax (works in bash/zsh/sh); fish/csh/nu users get remapped to
122
124
  * bash/zsh/sh by resolveUserShell() so they hit the same SCRIPT path.
123
125
  */
124
- export declare const SHELL_WRAPPER_SCRIPT = "cd -- \"$1\" && shift && exec /usr/bin/env \"$@\"";
126
+ export declare const SHELL_WRAPPER_SCRIPT: string;
125
127
  /**
126
128
  * Debug variant of the wrapper script — same prelude, but the CLI runs as
127
129
  * a *child* (no `exec`) and the wrapper hands off to an interactive shell