botmux 2.86.0 → 2.88.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 (247) hide show
  1. package/README.en.md +27 -0
  2. package/README.md +27 -0
  3. package/dist/adapters/backend/herdr-backend.d.ts.map +1 -1
  4. package/dist/adapters/backend/herdr-backend.js +12 -1
  5. package/dist/adapters/backend/herdr-backend.js.map +1 -1
  6. package/dist/adapters/backend/liveness-gate.d.ts +38 -0
  7. package/dist/adapters/backend/liveness-gate.d.ts.map +1 -0
  8. package/dist/adapters/backend/liveness-gate.js +53 -0
  9. package/dist/adapters/backend/liveness-gate.js.map +1 -0
  10. package/dist/adapters/backend/pty-backend.d.ts.map +1 -1
  11. package/dist/adapters/backend/pty-backend.js +4 -1
  12. package/dist/adapters/backend/pty-backend.js.map +1 -1
  13. package/dist/adapters/backend/tmux-backend.d.ts +22 -1
  14. package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
  15. package/dist/adapters/backend/tmux-backend.js +124 -36
  16. package/dist/adapters/backend/tmux-backend.js.map +1 -1
  17. package/dist/adapters/backend/tmux-pipe-backend.d.ts +20 -0
  18. package/dist/adapters/backend/tmux-pipe-backend.d.ts.map +1 -1
  19. package/dist/adapters/backend/tmux-pipe-backend.js +86 -20
  20. package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -1
  21. package/dist/adapters/backend/types.d.ts +9 -0
  22. package/dist/adapters/backend/types.d.ts.map +1 -1
  23. package/dist/adapters/backend/types.js.map +1 -1
  24. package/dist/adapters/backend/zellij-backend.js +1 -1
  25. package/dist/adapters/backend/zellij-backend.js.map +1 -1
  26. package/dist/adapters/backend/zellij-observe-backend.d.ts +13 -0
  27. package/dist/adapters/backend/zellij-observe-backend.d.ts.map +1 -1
  28. package/dist/adapters/backend/zellij-observe-backend.js +51 -12
  29. package/dist/adapters/backend/zellij-observe-backend.js.map +1 -1
  30. package/dist/adapters/cli/codex.d.ts.map +1 -1
  31. package/dist/adapters/cli/codex.js +8 -5
  32. package/dist/adapters/cli/codex.js.map +1 -1
  33. package/dist/adapters/cli/shared-hints.d.ts +2 -1
  34. package/dist/adapters/cli/shared-hints.d.ts.map +1 -1
  35. package/dist/adapters/cli/shared-hints.js +25 -3
  36. package/dist/adapters/cli/shared-hints.js.map +1 -1
  37. package/dist/adapters/cli/traex.d.ts.map +1 -1
  38. package/dist/adapters/cli/traex.js +4 -0
  39. package/dist/adapters/cli/traex.js.map +1 -1
  40. package/dist/adapters/cli/types.d.ts +6 -0
  41. package/dist/adapters/cli/types.d.ts.map +1 -1
  42. package/dist/bot-registry.d.ts +23 -0
  43. package/dist/bot-registry.d.ts.map +1 -1
  44. package/dist/bot-registry.js +9 -0
  45. package/dist/bot-registry.js.map +1 -1
  46. package/dist/cli.d.ts.map +1 -1
  47. package/dist/cli.js +368 -16
  48. package/dist/cli.js.map +1 -1
  49. package/dist/core/command-handler.d.ts.map +1 -1
  50. package/dist/core/command-handler.js +7 -5
  51. package/dist/core/command-handler.js.map +1 -1
  52. package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
  53. package/dist/core/dashboard-ipc-server.js +210 -5
  54. package/dist/core/dashboard-ipc-server.js.map +1 -1
  55. package/dist/core/dashboard-rows.d.ts +3 -0
  56. package/dist/core/dashboard-rows.d.ts.map +1 -1
  57. package/dist/core/dashboard-rows.js +4 -1
  58. package/dist/core/dashboard-rows.js.map +1 -1
  59. package/dist/core/maintenance.d.ts +18 -0
  60. package/dist/core/maintenance.d.ts.map +1 -1
  61. package/dist/core/maintenance.js +58 -30
  62. package/dist/core/maintenance.js.map +1 -1
  63. package/dist/core/per-bot-env.d.ts +38 -0
  64. package/dist/core/per-bot-env.d.ts.map +1 -0
  65. package/dist/core/per-bot-env.js +79 -0
  66. package/dist/core/per-bot-env.js.map +1 -0
  67. package/dist/core/session-activity.d.ts +1 -0
  68. package/dist/core/session-activity.d.ts.map +1 -1
  69. package/dist/core/session-activity.js +7 -4
  70. package/dist/core/session-activity.js.map +1 -1
  71. package/dist/core/session-create.d.ts +62 -0
  72. package/dist/core/session-create.d.ts.map +1 -0
  73. package/dist/core/session-create.js +131 -0
  74. package/dist/core/session-create.js.map +1 -0
  75. package/dist/core/session-manager.d.ts +43 -0
  76. package/dist/core/session-manager.d.ts.map +1 -1
  77. package/dist/core/session-manager.js +306 -8
  78. package/dist/core/session-manager.js.map +1 -1
  79. package/dist/core/skills/discovery.d.ts +7 -0
  80. package/dist/core/skills/discovery.d.ts.map +1 -1
  81. package/dist/core/skills/discovery.js +51 -0
  82. package/dist/core/skills/discovery.js.map +1 -1
  83. package/dist/core/trigger-session.d.ts.map +1 -1
  84. package/dist/core/trigger-session.js +5 -2
  85. package/dist/core/trigger-session.js.map +1 -1
  86. package/dist/core/update-check.d.ts +67 -0
  87. package/dist/core/update-check.d.ts.map +1 -0
  88. package/dist/core/update-check.js +159 -0
  89. package/dist/core/update-check.js.map +1 -0
  90. package/dist/core/worker-pool.d.ts.map +1 -1
  91. package/dist/core/worker-pool.js +82 -4
  92. package/dist/core/worker-pool.js.map +1 -1
  93. package/dist/daemon.d.ts.map +1 -1
  94. package/dist/daemon.js +40 -11
  95. package/dist/daemon.js.map +1 -1
  96. package/dist/dashboard/bot-payload.d.ts +2 -0
  97. package/dist/dashboard/bot-payload.d.ts.map +1 -1
  98. package/dist/dashboard/bot-payload.js +2 -0
  99. package/dist/dashboard/bot-payload.js.map +1 -1
  100. package/dist/dashboard/session-cleanup.d.ts +30 -0
  101. package/dist/dashboard/session-cleanup.d.ts.map +1 -0
  102. package/dist/dashboard/session-cleanup.js +47 -0
  103. package/dist/dashboard/session-cleanup.js.map +1 -0
  104. package/dist/dashboard/skill-install-request.d.ts +10 -0
  105. package/dist/dashboard/skill-install-request.d.ts.map +1 -1
  106. package/dist/dashboard/skill-install-request.js +17 -0
  107. package/dist/dashboard/skill-install-request.js.map +1 -1
  108. package/dist/dashboard/web/app.d.ts.map +1 -1
  109. package/dist/dashboard/web/app.js +29 -1
  110. package/dist/dashboard/web/app.js.map +1 -1
  111. package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
  112. package/dist/dashboard/web/bot-defaults.js +82 -6
  113. package/dist/dashboard/web/bot-defaults.js.map +1 -1
  114. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  115. package/dist/dashboard/web/i18n.js +312 -2
  116. package/dist/dashboard/web/i18n.js.map +1 -1
  117. package/dist/dashboard/web/insights.d.ts.map +1 -1
  118. package/dist/dashboard/web/insights.js +355 -30
  119. package/dist/dashboard/web/insights.js.map +1 -1
  120. package/dist/dashboard/web/sessions.d.ts +2 -0
  121. package/dist/dashboard/web/sessions.d.ts.map +1 -1
  122. package/dist/dashboard/web/sessions.js +457 -30
  123. package/dist/dashboard/web/sessions.js.map +1 -1
  124. package/dist/dashboard/web/settings.d.ts.map +1 -1
  125. package/dist/dashboard/web/settings.js +289 -0
  126. package/dist/dashboard/web/settings.js.map +1 -1
  127. package/dist/dashboard/web/skills.d.ts.map +1 -1
  128. package/dist/dashboard/web/skills.js +183 -10
  129. package/dist/dashboard/web/skills.js.map +1 -1
  130. package/dist/dashboard/web/whiteboards.d.ts +2 -0
  131. package/dist/dashboard/web/whiteboards.d.ts.map +1 -0
  132. package/dist/dashboard/web/whiteboards.js +267 -0
  133. package/dist/dashboard/web/whiteboards.js.map +1 -0
  134. package/dist/dashboard-web/app.js +879 -591
  135. package/dist/dashboard-web/index.html +1 -0
  136. package/dist/dashboard-web/style.css +528 -8
  137. package/dist/dashboard.js +472 -5
  138. package/dist/dashboard.js.map +1 -1
  139. package/dist/global-config.d.ts +6 -0
  140. package/dist/global-config.d.ts.map +1 -1
  141. package/dist/global-config.js +12 -0
  142. package/dist/global-config.js.map +1 -1
  143. package/dist/i18n/en.d.ts.map +1 -1
  144. package/dist/i18n/en.js +21 -1
  145. package/dist/i18n/en.js.map +1 -1
  146. package/dist/i18n/zh.d.ts.map +1 -1
  147. package/dist/i18n/zh.js +21 -1
  148. package/dist/i18n/zh.js.map +1 -1
  149. package/dist/im/lark/card-builder.d.ts +4 -5
  150. package/dist/im/lark/card-builder.d.ts.map +1 -1
  151. package/dist/im/lark/card-builder.js +113 -11
  152. package/dist/im/lark/card-builder.js.map +1 -1
  153. package/dist/im/lark/card-handler.d.ts +3 -2
  154. package/dist/im/lark/card-handler.d.ts.map +1 -1
  155. package/dist/im/lark/card-handler.js +174 -14
  156. package/dist/im/lark/card-handler.js.map +1 -1
  157. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  158. package/dist/im/lark/event-dispatcher.js +19 -5
  159. package/dist/im/lark/event-dispatcher.js.map +1 -1
  160. package/dist/im/lark/grant-pending.d.ts.map +1 -1
  161. package/dist/im/lark/grant-pending.js +9 -2
  162. package/dist/im/lark/grant-pending.js.map +1 -1
  163. package/dist/index-daemon.js +5 -0
  164. package/dist/index-daemon.js.map +1 -1
  165. package/dist/platform/bind.d.ts +2 -0
  166. package/dist/platform/bind.d.ts.map +1 -0
  167. package/dist/platform/bind.js +91 -0
  168. package/dist/platform/bind.js.map +1 -0
  169. package/dist/platform/binding.d.ts +22 -0
  170. package/dist/platform/binding.d.ts.map +1 -0
  171. package/dist/platform/binding.js +33 -0
  172. package/dist/platform/binding.js.map +1 -0
  173. package/dist/platform/tunnel-client.d.ts +15 -0
  174. package/dist/platform/tunnel-client.d.ts.map +1 -0
  175. package/dist/platform/tunnel-client.js +193 -0
  176. package/dist/platform/tunnel-client.js.map +1 -0
  177. package/dist/services/bot-config-store.d.ts.map +1 -1
  178. package/dist/services/bot-config-store.js +20 -0
  179. package/dist/services/bot-config-store.js.map +1 -1
  180. package/dist/services/git-worktree.d.ts +10 -0
  181. package/dist/services/git-worktree.d.ts.map +1 -1
  182. package/dist/services/git-worktree.js +71 -26
  183. package/dist/services/git-worktree.js.map +1 -1
  184. package/dist/services/grant-prefs-store.d.ts +3 -0
  185. package/dist/services/grant-prefs-store.d.ts.map +1 -1
  186. package/dist/services/grant-prefs-store.js +17 -2
  187. package/dist/services/grant-prefs-store.js.map +1 -1
  188. package/dist/services/insight/claude-span-reader.d.ts.map +1 -1
  189. package/dist/services/insight/claude-span-reader.js +18 -2
  190. package/dist/services/insight/claude-span-reader.js.map +1 -1
  191. package/dist/services/insight/codex-span-reader.d.ts.map +1 -1
  192. package/dist/services/insight/codex-span-reader.js +17 -1
  193. package/dist/services/insight/codex-span-reader.js.map +1 -1
  194. package/dist/services/insight/report.d.ts.map +1 -1
  195. package/dist/services/insight/report.js +48 -6
  196. package/dist/services/insight/report.js.map +1 -1
  197. package/dist/services/insight/types.d.ts +9 -0
  198. package/dist/services/insight/types.d.ts.map +1 -1
  199. package/dist/services/insight/types.js.map +1 -1
  200. package/dist/services/resumable-session-discovery.d.ts.map +1 -1
  201. package/dist/services/resumable-session-discovery.js +21 -4
  202. package/dist/services/resumable-session-discovery.js.map +1 -1
  203. package/dist/services/skill-registry-store.d.ts +1 -0
  204. package/dist/services/skill-registry-store.d.ts.map +1 -1
  205. package/dist/services/skill-registry-store.js +32 -0
  206. package/dist/services/skill-registry-store.js.map +1 -1
  207. package/dist/services/whiteboard-store.d.ts +67 -0
  208. package/dist/services/whiteboard-store.d.ts.map +1 -0
  209. package/dist/services/whiteboard-store.js +450 -0
  210. package/dist/services/whiteboard-store.js.map +1 -0
  211. package/dist/services/worktree-slug-ai.d.ts.map +1 -1
  212. package/dist/services/worktree-slug-ai.js +3 -1
  213. package/dist/services/worktree-slug-ai.js.map +1 -1
  214. package/dist/setup/bot-config-editor.d.ts +8 -0
  215. package/dist/setup/bot-config-editor.d.ts.map +1 -1
  216. package/dist/setup/bot-config-editor.js +9 -0
  217. package/dist/setup/bot-config-editor.js.map +1 -1
  218. package/dist/skills/definitions.d.ts.map +1 -1
  219. package/dist/skills/definitions.js +118 -0
  220. package/dist/skills/definitions.js.map +1 -1
  221. package/dist/types.d.ts +15 -0
  222. package/dist/types.d.ts.map +1 -1
  223. package/dist/utils/crash-log.d.ts +22 -0
  224. package/dist/utils/crash-log.d.ts.map +1 -0
  225. package/dist/utils/crash-log.js +37 -0
  226. package/dist/utils/crash-log.js.map +1 -0
  227. package/dist/utils/input-gate.d.ts +10 -0
  228. package/dist/utils/input-gate.d.ts.map +1 -1
  229. package/dist/utils/input-gate.js +7 -0
  230. package/dist/utils/input-gate.js.map +1 -1
  231. package/dist/utils/install-diagnostics.d.ts +52 -0
  232. package/dist/utils/install-diagnostics.d.ts.map +1 -0
  233. package/dist/utils/install-diagnostics.js +155 -0
  234. package/dist/utils/install-diagnostics.js.map +1 -0
  235. package/dist/utils/install-info.d.ts +4 -0
  236. package/dist/utils/install-info.d.ts.map +1 -1
  237. package/dist/utils/install-info.js +6 -0
  238. package/dist/utils/install-info.js.map +1 -1
  239. package/dist/utils/stdio-epipe-guard.d.ts +39 -0
  240. package/dist/utils/stdio-epipe-guard.d.ts.map +1 -0
  241. package/dist/utils/stdio-epipe-guard.js +67 -0
  242. package/dist/utils/stdio-epipe-guard.js.map +1 -0
  243. package/dist/worker.js +222 -26
  244. package/dist/worker.js.map +1 -1
  245. package/dist/workflows/daemon-spawn.d.ts +2 -0
  246. package/dist/workflows/daemon-spawn.d.ts.map +1 -1
  247. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-ipc-server.d.ts","sourceRoot":"","sources":["../../src/core/dashboard-ipc-server.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,eAAe,EAAE,KAAK,cAAc,EAAe,MAAM,WAAW,CAAC;AAqDjG,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAM/E,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI,CAE3F;AACD,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EAIpB,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,KAAK,EAAiB,cAAc,EAAW,MAAM,aAAa,CAAC;AAI1E,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED,MAAM,MAAM,OAAO,GAAG,CACpB,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC3B,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAW1B,0FAA0F;AAC1F,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAM7E;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAGhF;AAED,wBAAsB,YAAY,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,CAAC,CAAC,CAKhF;AAiBD,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAgC;AAyB7F,YAAY,EAAE,UAAU,EAAE,CAAC;AAC3B,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,CAAC;AAMtD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAA0B;AAKxE,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAA0B;AAwhBxE,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,WAAW,CAAC;IAC3C,cAAc,EAAE,MAAM,CAAC;CACxB;AAuvBD,wBAAgB,cAAc,CAAC,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAiC7F"}
1
+ {"version":3,"file":"dashboard-ipc-server.d.ts","sourceRoot":"","sources":["../../src/core/dashboard-ipc-server.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,eAAe,EAAE,KAAK,cAAc,EAAe,MAAM,WAAW,CAAC;AAsDjG,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAM/E,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI,CAE3F;AACD,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EAIpB,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,KAAK,EAAiC,cAAc,EAAW,MAAM,aAAa,CAAC;AAK1F,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED,MAAM,MAAM,OAAO,GAAG,CACpB,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC3B,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAW1B,0FAA0F;AAC1F,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAM7E;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAGhF;AAED,wBAAsB,YAAY,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,CAAC,CAAC,CAKhF;AAiBD,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAgC;AAyB7F,YAAY,EAAE,UAAU,EAAE,CAAC;AAC3B,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,CAAC;AAMtD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAA0B;AAKxE,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAA0B;AAkpBxE,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,WAAW,CAAC;IAC3C,cAAc,EAAE,MAAM,CAAC;CACxB;AAozBD,wBAAgB,cAAc,CAAC,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAiC7F"}
@@ -28,11 +28,12 @@ import { readGlobalConfig } from '../global-config.js';
28
28
  import { normalizeChatReplyMode } from '../services/chat-reply-mode-store.js';
29
29
  import * as chatFirstSeenStore from '../services/chat-first-seen-store.js';
30
30
  import * as scheduler from './scheduler.js';
31
- import { listActiveSessions, findActiveBySessionId, closeSession, getActiveSessionsRegistry, transferSession, deliverWriteLinkCardToOwners } from './worker-pool.js';
31
+ import { listActiveSessions, findActiveBySessionId, closeSession, getActiveSessionsRegistry, transferSession, deliverWriteLinkCardToOwners, forkWorker } from './worker-pool.js';
32
32
  import { listOnlineDaemons } from '../utils/daemon-discovery.js';
33
33
  import { getChatMode, replyMessage, sendMessage, resolveUnionIdFromOpenId, listThreadMessages, listChatMessages, getUserProfile } from '../im/lark/client.js';
34
34
  import { parseApiMessage, cardContentHasUpgradeFallback, resolveMergedCardContent } from '../im/lark/message-parser.js';
35
- import { resumeSession } from './session-manager.js';
35
+ import { resumeSession, spawnDashboardSession, activateQueuedSession } from './session-manager.js';
36
+ import { parseSpawnRequest } from './session-create.js';
36
37
  import { getCliDisplayName } from '../im/lark/card-builder.js';
37
38
  import { locateLimiter } from './dashboard-locate.js';
38
39
  import { buildTerminalUrl } from './terminal-url.js';
@@ -146,6 +147,63 @@ ipcRoute('POST', '/api/sessions/:sessionId/close', async (_req, res, params) =>
146
147
  const r = await closeSession(params.sessionId);
147
148
  jsonRes(res, 200, r);
148
149
  });
150
+ /** Post a scope-aware "restarting" notice into the session's Lark thread/chat,
151
+ * mirroring the /resume route — so a Feishu-side observer sees why the CLI just
152
+ * restarted under them (the IM `/restart` command and the card button notify
153
+ * too; the dashboard was the lone silent path). `fresh` = the worker was gone
154
+ * and we re-forked it (revive) rather than doing an in-place CLI restart.
155
+ * Best-effort and fire-and-forget; never blocks the HTTP response. */
156
+ function postRestartNotice(ds, fresh) {
157
+ if (!ds.larkAppId)
158
+ return;
159
+ const loc = localeForBot(ds.larkAppId);
160
+ const cliName = getCliDisplayName(ds.session.cliId ?? 'claude-code');
161
+ const text = fresh
162
+ ? t('card.action.restarted_fresh', { cliName }, loc)
163
+ : t('cmd.restart.in_progress', { cliName }, loc);
164
+ const notice = JSON.stringify({ text });
165
+ if (ds.scope === 'chat' && ds.chatId) {
166
+ getChatMode(ds.larkAppId, ds.chatId, { forceRefresh: true })
167
+ .then((mode) => mode === 'topic' && ds.session.rootMessageId
168
+ ? replyMessage(ds.larkAppId, ds.session.rootMessageId, notice, 'text', true)
169
+ : sendMessage(ds.larkAppId, ds.chatId, notice, 'text'))
170
+ .catch(err => logger.debug(`[restart] failed to post chat-scope restart notice: ${err}`));
171
+ }
172
+ else if (ds.session.rootMessageId) {
173
+ replyMessage(ds.larkAppId, ds.session.rootMessageId, notice, 'text', true)
174
+ .catch(err => logger.debug(`[restart] failed to post thread-scope restart notice: ${err}`));
175
+ }
176
+ }
177
+ ipcRoute('POST', '/api/sessions/:sessionId/restart', (_req, res, params) => {
178
+ const ds = findActiveBySessionId(params.sessionId);
179
+ if (!ds)
180
+ return jsonRes(res, 404, { ok: false, error: 'session_not_active' });
181
+ // Adopt/observed sessions: botmux never owned the CLI — restarting would kill
182
+ // the user's real tmux/zellij pane. Hard-reject (the worker self-guards too).
183
+ if (ds.adoptedFrom || ds.initConfig?.adoptMode) {
184
+ return jsonRes(res, 409, { ok: false, error: 'adopt_restart_unsupported' });
185
+ }
186
+ const cliId = ds.session.cliId ?? 'unknown';
187
+ if (ds.worker && !ds.worker.killed) {
188
+ // Live worker → in-place CLI restart (kills the CLI, respawns with --resume).
189
+ try {
190
+ ds.worker.send({ type: 'restart' });
191
+ }
192
+ catch (err) {
193
+ return jsonRes(res, 502, { ok: false, error: String(err) });
194
+ }
195
+ postRestartNotice(ds, false);
196
+ return jsonRes(res, 200, { ok: true, sessionId: params.sessionId, cliId, revived: false });
197
+ }
198
+ // Worker is gone but the session is still active — idle-suspended (over the
199
+ // per-bot cap), lazy-restored after a daemon restart, or crash-loop-stopped.
200
+ // Revive it the same way the Feishu card restart does (forkWorker), so the
201
+ // dashboard isn't a dead-end: a 409 here would leave NO working control to
202
+ // bring the CLI back (the resume button only shows for closed sessions).
203
+ forkWorker(ds, '', ds.hasHistory);
204
+ postRestartNotice(ds, true);
205
+ jsonRes(res, 200, { ok: true, sessionId: params.sessionId, cliId, revived: true });
206
+ });
149
207
  /** 解析 session(活跃优先,已关闭兜底)。活跃会话取 ds.session —— registry 与
150
208
  * store 持有同一对象,改字段后 updateSession 即落盘。 */
151
209
  function findSessionRecord(sessionId) {
@@ -168,8 +226,15 @@ ipcRoute('POST', '/api/sessions/:sessionId/board', async (req, res, params) => {
168
226
  const session = findSessionRecord(params.sessionId);
169
227
  if (!session)
170
228
  return jsonRes(res, 404, { ok: false, error: 'session_not_found' });
171
- if (column)
229
+ // 待办池(queued)会话被拖到「进行中」= 激活:把暂存内容当首轮发给 CLI 开跑。
230
+ // activateQueuedSession 内部会清 queued + 把列设成 in_progress + forkWorker。
231
+ const activeDs = findActiveBySessionId(params.sessionId);
232
+ if (column === 'in_progress' && activeDs?.session.queued) {
233
+ await activateQueuedSession(activeDs);
234
+ }
235
+ else if (column) {
172
236
  session.kanbanColumn = column;
237
+ }
173
238
  if (position !== null)
174
239
  session.kanbanPosition = position;
175
240
  sessionStore.updateSession(session);
@@ -177,11 +242,65 @@ ipcRoute('POST', '/api/sessions/:sessionId/board', async (req, res, params) => {
177
242
  type: 'session.update',
178
243
  body: {
179
244
  sessionId: params.sessionId,
180
- patch: { kanbanColumn: session.kanbanColumn, kanbanPosition: session.kanbanPosition },
245
+ // queued 一并下发:激活后 session.queued 已为 false,前端浅合并若不带这个字段
246
+ // 会残留 queued=true(卡片仍显示「开始」、再点 409)。!!session.queued 始终反映现态。
247
+ patch: { kanbanColumn: session.kanbanColumn, kanbanPosition: session.kanbanPosition, queued: !!session.queued },
181
248
  },
182
249
  });
183
250
  jsonRes(res, 200, { ok: true });
184
251
  });
252
+ // 待办池会话「开始」:把 parked 会话激活(发首轮、起 CLI),与拖到「进行中」同义。
253
+ ipcRoute('POST', '/api/sessions/:sessionId/start', async (_req, res, params) => {
254
+ const ds = findActiveBySessionId(params.sessionId);
255
+ if (!ds)
256
+ return jsonRes(res, 404, { ok: false, error: 'session_not_found' });
257
+ if (!ds.session.queued)
258
+ return jsonRes(res, 409, { ok: false, error: 'not_queued' });
259
+ const r = await activateQueuedSession(ds);
260
+ if (!r.ok)
261
+ return jsonRes(res, 500, r);
262
+ sessionStore.updateSession(ds.session);
263
+ dashboardEventBus.publish({
264
+ type: 'session.update',
265
+ body: { sessionId: params.sessionId, patch: { kanbanColumn: ds.session.kanbanColumn, queued: false } },
266
+ });
267
+ jsonRes(res, 200, { ok: true });
268
+ });
269
+ // Dashboard「创建会话」spawn:在新建的群里为本 daemon 的 bot 拉起/暂存一条 chat-scope
270
+ // 会话。aggregator 建完群后按模式(一起开工/lead 分配)对每个目标 bot 的 daemon 调一次。
271
+ ipcRoute('POST', '/api/sessions/spawn', async (req, res) => {
272
+ if (!cachedLarkAppId)
273
+ return jsonRes(res, 503, { ok: false, error: 'bot_not_found' });
274
+ const activeSessions = getActiveSessionsRegistry();
275
+ if (!activeSessions)
276
+ return jsonRes(res, 503, { ok: false, error: 'registry_unavailable' });
277
+ let body;
278
+ try {
279
+ body = await readJsonBody(req);
280
+ }
281
+ catch {
282
+ return jsonRes(res, 400, { ok: false, error: 'invalid_json' });
283
+ }
284
+ const parsed = parseSpawnRequest(body);
285
+ if (!parsed.ok)
286
+ return jsonRes(res, 400, { ok: false, error: parsed.error });
287
+ const postBanner = !!body.postBanner;
288
+ const r = await spawnDashboardSession(activeSessions, undefined, {
289
+ larkAppId: cachedLarkAppId,
290
+ chatId: parsed.value.chatId,
291
+ content: parsed.value.content,
292
+ column: parsed.value.column,
293
+ role: parsed.value.role,
294
+ coworkers: parsed.value.coworkers,
295
+ title: parsed.value.title,
296
+ postBanner,
297
+ ownerOpenId: parsed.value.ownerOpenId,
298
+ ownerUnionId: parsed.value.ownerUnionId,
299
+ });
300
+ if (!r.ok)
301
+ return jsonRes(res, r.error === 'session_exists' ? 409 : 500, r);
302
+ jsonRes(res, 200, r);
303
+ });
185
304
  // 会话历史:实时拉取该会话所在话题/群的飞书消息(与 botmux history 同链路,
186
305
  // 消息体不落盘),给 dashboard 的会话历史弹窗。复杂卡片的「请升级」兜底文本
187
306
  // 用 message.get 的完整表示补齐;merge_forward 保持占位符(原型不展开)。
@@ -454,7 +573,7 @@ ipcRoute('POST', '/api/sessions/:sessionId/sandbox-land/:action', (_req, res, pa
454
573
  * CLI command (via this HTTP route). The CLI route also drops a notice into
455
574
  * the original Lark thread so users see why the session is alive again.
456
575
  */
457
- ipcRoute('POST', '/api/sessions/:sessionId/resume', async (_req, res, params) => {
576
+ ipcRoute('POST', '/api/sessions/:sessionId/resume', async (req, res, params) => {
458
577
  const sessionId = params.sessionId;
459
578
  const reg = getActiveSessionsRegistry();
460
579
  if (!reg)
@@ -465,6 +584,12 @@ ipcRoute('POST', '/api/sessions/:sessionId/resume', async (_req, res, params) =>
465
584
  return jsonRes(res, status, { ok: false, error: result.error, activeSessionId: result.activeSessionId });
466
585
  }
467
586
  const ds = result.ds;
587
+ // `?wake=1` is an opt-in operational hook (no UI/CLI caller wires it today —
588
+ // it's meant for direct `curl` recovery): instead of the default lazy
589
+ // cold-resume on the next inbound message, fork the worker immediately so the
590
+ // session is usable right away. Off by default keeps every existing caller's
591
+ // behaviour unchanged.
592
+ const wake = new URL(req.url ?? '/', 'http://localhost').searchParams.get('wake') === '1';
468
593
  // Tell the dashboard the row flipped back to active (mirror of session.update
469
594
  // emitted by closeSession). Use `null` for closedAt — `undefined` would be
470
595
  // dropped by JSON.stringify on the SSE wire and the aggregator's spread
@@ -496,9 +621,18 @@ ipcRoute('POST', '/api/sessions/:sessionId/resume', async (_req, res, params) =>
496
621
  .catch(err => logger.debug(`[resume] failed to post thread-scope resume notice: ${err}`));
497
622
  }
498
623
  }
624
+ // Report the EFFECTIVE action, not the raw request flag: only fork when wake
625
+ // was asked AND there's no live worker to clobber. (resumeSession always hands
626
+ // back a worker:null ds today, so this matches `wake` in practice — but
627
+ // reporting the action keeps the response honest if the guard ever broadens.)
628
+ const woke = wake && (!ds.worker || ds.worker.killed);
629
+ if (woke) {
630
+ forkWorker(ds, '', true);
631
+ }
499
632
  jsonRes(res, 200, {
500
633
  ok: true,
501
634
  sessionId,
635
+ wake: woke,
502
636
  title: ds.session.title,
503
637
  chatId: ds.chatId,
504
638
  rootMessageId: ds.session.rootMessageId,
@@ -1061,6 +1195,16 @@ ipcRoute('GET', '/api/bot-default-oncall', async (_req, res) => {
1061
1195
  startupCommands = sc.join('\n');
1062
1196
  }
1063
1197
  catch { /* none */ }
1198
+ // Per-bot env → pretty JSON for the dashboard textarea. The dashboard is
1199
+ // owner-authenticated, so showing the real values here is acceptable (same
1200
+ // as editing bots.json directly); the chat-facing /config get masks them.
1201
+ let env = '';
1202
+ try {
1203
+ const e = getBot(cachedLarkAppId).config.env;
1204
+ if (e && typeof e === 'object' && Object.keys(e).length)
1205
+ env = JSON.stringify(e, null, 2);
1206
+ }
1207
+ catch { /* none */ }
1064
1208
  jsonRes(res, 200, {
1065
1209
  larkAppId: cachedLarkAppId,
1066
1210
  botName: getBotName(),
@@ -1078,10 +1222,12 @@ ipcRoute('GET', '/api/bot-default-oncall', async (_req, res) => {
1078
1222
  regularGroupMentionMode: cardPrefs.regularGroupMentionMode,
1079
1223
  docSubscribeDefaultMode: cardPrefs.docSubscribeDefaultMode,
1080
1224
  restrictGrantCommands: grantPrefs.restrictGrantCommands,
1225
+ autoGrantRequestCards: grantPrefs.autoGrantRequestCards,
1081
1226
  messageQuotaDefaultLimit: grantPrefs.messageQuotaDefaultLimit,
1082
1227
  p2pMode,
1083
1228
  maxLiveWorkers,
1084
1229
  startupCommands,
1230
+ env,
1085
1231
  skills: getBot(cachedLarkAppId).config.skills ?? null,
1086
1232
  });
1087
1233
  });
@@ -1130,6 +1276,7 @@ ipcRoute('PUT', '/api/bot-card-prefs', async (req, res) => {
1130
1276
  });
1131
1277
  // Per-bot 授权偏好。Body 任意子集:
1132
1278
  // • restrictGrantCommands: boolean — 限制被授权人只能纯对话
1279
+ // • autoGrantRequestCards: boolean — 未授权 @ 被挡住时是否发 grant 申请卡
1133
1280
  // • messageQuotaDefaultLimit: number|null — 默认消息额度(null = 关闭,正整数 = 启用)
1134
1281
  ipcRoute('PUT', '/api/bot-grant-prefs', async (req, res) => {
1135
1282
  if (!cachedLarkAppId)
@@ -1149,6 +1296,8 @@ ipcRoute('PUT', '/api/bot-grant-prefs', async (req, res) => {
1149
1296
  const patch = {};
1150
1297
  if (typeof body.restrictGrantCommands === 'boolean')
1151
1298
  patch.restrictGrantCommands = body.restrictGrantCommands;
1299
+ if (typeof body.autoGrantRequestCards === 'boolean')
1300
+ patch.autoGrantRequestCards = body.autoGrantRequestCards;
1152
1301
  // null(含 JSON null)= 关闭默认额度;number = 设定(store 内再校验正整数)。
1153
1302
  if (body.messageQuotaDefaultLimit === null)
1154
1303
  patch.messageQuotaDefaultLimit = null;
@@ -1237,6 +1386,40 @@ ipcRoute('PUT', '/api/bot-startup-commands', async (req, res) => {
1237
1386
  return jsonRes(res, 400, { ok: false, error: r.reason });
1238
1387
  jsonRes(res, 200, { ok: true, startupCommands: (value ?? []).join('\n') });
1239
1388
  });
1389
+ // Per-bot 环境变量 env。Body `{ env: string }`(原始 JSON 文本,如
1390
+ // `{"ANTHROPIC_BASE_URL":"…","ANTHROPIC_AUTH_TOKEN":"…"}` 让本 bot 走 GLM/第三方
1391
+ // 服务商):空白 → 清除;否则按 json kind 解析 + sanitizePerBotEnv 过滤后落盘。
1392
+ // 走 applyConfigField(与 /botconfig 同一写盘 + 内存热更新路径),next-session 生效
1393
+ // (下个会话起注入到 CLI 进程)。回包返回脱敏后的 pretty JSON 供 textarea 回填。
1394
+ ipcRoute('PUT', '/api/bot-env', async (req, res) => {
1395
+ if (!cachedLarkAppId)
1396
+ return jsonRes(res, 503, { error: 'larkAppId_not_set' });
1397
+ let body;
1398
+ try {
1399
+ body = await readJsonBody(req);
1400
+ }
1401
+ catch {
1402
+ return jsonRes(res, 400, { ok: false, error: 'bad_json' });
1403
+ }
1404
+ const spec = findConfigField('env');
1405
+ if (!spec)
1406
+ return jsonRes(res, 500, { ok: false, error: 'spec_missing' });
1407
+ const raw = typeof body.env === 'string' ? body.env : '';
1408
+ let value;
1409
+ if (!raw.trim()) {
1410
+ value = null; // 清除
1411
+ }
1412
+ else {
1413
+ const coerced = coerceConfigValue(spec, raw);
1414
+ if (!coerced.ok)
1415
+ return jsonRes(res, 400, { ok: false, error: coerced.reason });
1416
+ value = coerced.value;
1417
+ }
1418
+ const r = await applyConfigField(cachedLarkAppId, spec, value);
1419
+ if (!r.ok)
1420
+ return jsonRes(res, 400, { ok: false, error: r.reason });
1421
+ jsonRes(res, 200, { ok: true, env: value ? JSON.stringify(value, null, 2) : '' });
1422
+ });
1240
1423
  // Per-bot 最大同时活跃会话数 maxLiveWorkers。Body `{ maxLiveWorkers: number | null }`:
1241
1424
  // • 正整数 → 设上限;超过后 idle-worker sweeper 把最久未用的会话休眠到上限内
1242
1425
  // • null → 清除(回落到内置默认 30)
@@ -1491,9 +1674,31 @@ ipcRoute('GET', '/api/events', (_req, res) => {
1491
1674
  });
1492
1675
  // Initial flush so the client sees the connection alive immediately.
1493
1676
  res.write('retry: 5000\n\n');
1677
+ // Subscribe BEFORE snapshotting so no event published in the gap is missed.
1494
1678
  const off = dashboardEventBus.subscribe(ev => {
1495
1679
  res.write(`event: ${ev.type}\ndata: ${JSON.stringify(ev.body)}\n\n`);
1496
1680
  });
1681
+ // Replay the current active sessions as `session.spawned` right after
1682
+ // subscribing. `DashboardEventBus` has no buffer/replay, and the daemon
1683
+ // publishes its discovery descriptor BEFORE restoreActiveSessions() runs
1684
+ // (daemon.ts) — so a dashboard that hydrates (GET /api/sessions) during the
1685
+ // descriptor→restore window gets an EMPTY snapshot, and any restore-time
1686
+ // `announceSessionRow()` that fires before THIS subscription is established is
1687
+ // dropped. Without this replay the aggregator would then have neither a
1688
+ // snapshot row nor a spawned row, and later session.update/close patches would
1689
+ // be discarded as unknown-row. Replaying here makes SSE attach deterministic:
1690
+ // a row registered before subscribe arrives via this snapshot; one registered
1691
+ // after arrives via the live subscription above. Idempotent — both the
1692
+ // aggregator and the browser store upsert by sessionId, so any row also
1693
+ // delivered live just refreshes the same entry.
1694
+ try {
1695
+ for (const ds of listActiveSessions()) {
1696
+ res.write(`event: session.spawned\ndata: ${JSON.stringify({ session: composeRowFromActive(ds) })}\n\n`);
1697
+ }
1698
+ }
1699
+ catch (err) {
1700
+ logger.warn(`[dashboard-ipc] /api/events snapshot replay failed: ${err}`);
1701
+ }
1497
1702
  const hb = setInterval(() => {
1498
1703
  res.write(`event: heartbeat\ndata: ${JSON.stringify({ ts: Date.now() })}\n\n`);
1499
1704
  }, 15_000);