botmux 3.14.0 → 3.16.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 (812) hide show
  1. package/README.en.md +2 -2
  2. package/README.md +2 -2
  3. package/dist/.runtime-build-id +1 -1
  4. package/dist/adapters/backend/destroy-result.d.ts +159 -0
  5. package/dist/adapters/backend/destroy-result.d.ts.map +1 -0
  6. package/dist/adapters/backend/destroy-result.js +223 -0
  7. package/dist/adapters/backend/destroy-result.js.map +1 -0
  8. package/dist/adapters/backend/herdr-backend.d.ts +4 -0
  9. package/dist/adapters/backend/herdr-backend.d.ts.map +1 -1
  10. package/dist/adapters/backend/herdr-backend.js +23 -1
  11. package/dist/adapters/backend/herdr-backend.js.map +1 -1
  12. package/dist/adapters/backend/mojo-backend.d.ts +577 -0
  13. package/dist/adapters/backend/mojo-backend.d.ts.map +1 -0
  14. package/dist/adapters/backend/mojo-backend.js +2471 -0
  15. package/dist/adapters/backend/mojo-backend.js.map +1 -0
  16. package/dist/adapters/backend/mojo-budgets.d.ts +21 -0
  17. package/dist/adapters/backend/mojo-budgets.d.ts.map +1 -0
  18. package/dist/adapters/backend/mojo-budgets.js +22 -0
  19. package/dist/adapters/backend/mojo-budgets.js.map +1 -0
  20. package/dist/adapters/backend/mojo-isolated-workspace.d.ts +69 -0
  21. package/dist/adapters/backend/mojo-isolated-workspace.d.ts.map +1 -0
  22. package/dist/adapters/backend/mojo-isolated-workspace.js +213 -0
  23. package/dist/adapters/backend/mojo-isolated-workspace.js.map +1 -0
  24. package/dist/adapters/backend/mojo-process-tree.d.ts +292 -0
  25. package/dist/adapters/backend/mojo-process-tree.d.ts.map +1 -0
  26. package/dist/adapters/backend/mojo-process-tree.js +486 -0
  27. package/dist/adapters/backend/mojo-process-tree.js.map +1 -0
  28. package/dist/adapters/backend/mojo-types.d.ts +542 -0
  29. package/dist/adapters/backend/mojo-types.d.ts.map +1 -0
  30. package/dist/adapters/backend/mojo-types.js +682 -0
  31. package/dist/adapters/backend/mojo-types.js.map +1 -0
  32. package/dist/adapters/backend/reproduce-command.js +3 -3
  33. package/dist/adapters/backend/reproduce-command.js.map +1 -1
  34. package/dist/adapters/backend/riff-backend.js +1 -1
  35. package/dist/adapters/backend/riff-backend.js.map +1 -1
  36. package/dist/adapters/backend/sandbox.d.ts +44 -7
  37. package/dist/adapters/backend/sandbox.d.ts.map +1 -1
  38. package/dist/adapters/backend/sandbox.js +30 -7
  39. package/dist/adapters/backend/sandbox.js.map +1 -1
  40. package/dist/adapters/backend/session-backend-selector.d.ts +14 -1
  41. package/dist/adapters/backend/session-backend-selector.d.ts.map +1 -1
  42. package/dist/adapters/backend/session-backend-selector.js +82 -10
  43. package/dist/adapters/backend/session-backend-selector.js.map +1 -1
  44. package/dist/adapters/backend/tmux-pipe-backend.d.ts +30 -0
  45. package/dist/adapters/backend/tmux-pipe-backend.d.ts.map +1 -1
  46. package/dist/adapters/backend/tmux-pipe-backend.js +60 -0
  47. package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -1
  48. package/dist/adapters/backend/types.d.ts +108 -6
  49. package/dist/adapters/backend/types.d.ts.map +1 -1
  50. package/dist/adapters/backend/types.js.map +1 -1
  51. package/dist/adapters/backend/zmx-backend.d.ts +11 -0
  52. package/dist/adapters/backend/zmx-backend.d.ts.map +1 -1
  53. package/dist/adapters/backend/zmx-backend.js +16 -1
  54. package/dist/adapters/backend/zmx-backend.js.map +1 -1
  55. package/dist/adapters/cli/codex-app.d.ts.map +1 -1
  56. package/dist/adapters/cli/codex-app.js +2 -2
  57. package/dist/adapters/cli/codex-app.js.map +1 -1
  58. package/dist/adapters/cli/codex.d.ts.map +1 -1
  59. package/dist/adapters/cli/codex.js +7 -0
  60. package/dist/adapters/cli/codex.js.map +1 -1
  61. package/dist/adapters/cli/copilot.d.ts +3 -1
  62. package/dist/adapters/cli/copilot.d.ts.map +1 -1
  63. package/dist/adapters/cli/copilot.js +23 -5
  64. package/dist/adapters/cli/copilot.js.map +1 -1
  65. package/dist/adapters/cli/cursor.d.ts.map +1 -1
  66. package/dist/adapters/cli/cursor.js +26 -4
  67. package/dist/adapters/cli/cursor.js.map +1 -1
  68. package/dist/adapters/cli/dsh.d.ts.map +1 -1
  69. package/dist/adapters/cli/dsh.js +5 -1
  70. package/dist/adapters/cli/dsh.js.map +1 -1
  71. package/dist/adapters/cli/grok.d.ts.map +1 -1
  72. package/dist/adapters/cli/grok.js +24 -5
  73. package/dist/adapters/cli/grok.js.map +1 -1
  74. package/dist/adapters/cli/kimi.d.ts.map +1 -1
  75. package/dist/adapters/cli/kimi.js +19 -1
  76. package/dist/adapters/cli/kimi.js.map +1 -1
  77. package/dist/adapters/cli/mojo.d.ts +28 -0
  78. package/dist/adapters/cli/mojo.d.ts.map +1 -0
  79. package/dist/adapters/cli/mojo.js +58 -0
  80. package/dist/adapters/cli/mojo.js.map +1 -0
  81. package/dist/adapters/cli/pi.d.ts +20 -5
  82. package/dist/adapters/cli/pi.d.ts.map +1 -1
  83. package/dist/adapters/cli/pi.js +27 -5
  84. package/dist/adapters/cli/pi.js.map +1 -1
  85. package/dist/adapters/cli/read-isolation.d.ts +251 -1
  86. package/dist/adapters/cli/read-isolation.d.ts.map +1 -1
  87. package/dist/adapters/cli/read-isolation.js +254 -1
  88. package/dist/adapters/cli/read-isolation.js.map +1 -1
  89. package/dist/adapters/cli/registry.d.ts +13 -1
  90. package/dist/adapters/cli/registry.d.ts.map +1 -1
  91. package/dist/adapters/cli/registry.js +19 -1
  92. package/dist/adapters/cli/registry.js.map +1 -1
  93. package/dist/adapters/cli/runner-input.d.ts +3 -3
  94. package/dist/adapters/cli/runner-input.d.ts.map +1 -1
  95. package/dist/adapters/cli/runner-input.js +4 -3
  96. package/dist/adapters/cli/runner-input.js.map +1 -1
  97. package/dist/adapters/cli/shared-hints.d.ts +3 -1
  98. package/dist/adapters/cli/shared-hints.d.ts.map +1 -1
  99. package/dist/adapters/cli/shared-hints.js +51 -30
  100. package/dist/adapters/cli/shared-hints.js.map +1 -1
  101. package/dist/adapters/cli/types.d.ts +33 -4
  102. package/dist/adapters/cli/types.d.ts.map +1 -1
  103. package/dist/bot-registry.d.ts +42 -0
  104. package/dist/bot-registry.d.ts.map +1 -1
  105. package/dist/bot-registry.js +54 -4
  106. package/dist/bot-registry.js.map +1 -1
  107. package/dist/cli/arg-utils.d.ts +5 -0
  108. package/dist/cli/arg-utils.d.ts.map +1 -1
  109. package/dist/cli/arg-utils.js +7 -0
  110. package/dist/cli/arg-utils.js.map +1 -1
  111. package/dist/cli/bots-list-output.d.ts +130 -2
  112. package/dist/cli/bots-list-output.d.ts.map +1 -1
  113. package/dist/cli/bots-list-output.js +173 -27
  114. package/dist/cli/bots-list-output.js.map +1 -1
  115. package/dist/cli/daemon-lifecycle-env.d.ts +10 -3
  116. package/dist/cli/daemon-lifecycle-env.d.ts.map +1 -1
  117. package/dist/cli/daemon-lifecycle-env.js +38 -11
  118. package/dist/cli/daemon-lifecycle-env.js.map +1 -1
  119. package/dist/cli/dashboard-command.d.ts +15 -0
  120. package/dist/cli/dashboard-command.d.ts.map +1 -1
  121. package/dist/cli/dashboard-command.js +22 -0
  122. package/dist/cli/dashboard-command.js.map +1 -1
  123. package/dist/cli/log-tail.d.ts +54 -0
  124. package/dist/cli/log-tail.d.ts.map +1 -0
  125. package/dist/cli/log-tail.js +167 -0
  126. package/dist/cli/log-tail.js.map +1 -0
  127. package/dist/cli/pm2-env.d.ts +16 -0
  128. package/dist/cli/pm2-env.d.ts.map +1 -0
  129. package/dist/cli/pm2-env.js +63 -0
  130. package/dist/cli/pm2-env.js.map +1 -0
  131. package/dist/cli/pm2-fleet-lock.d.ts +26 -0
  132. package/dist/cli/pm2-fleet-lock.d.ts.map +1 -0
  133. package/dist/cli/pm2-fleet-lock.js +50 -0
  134. package/dist/cli/pm2-fleet-lock.js.map +1 -0
  135. package/dist/cli/pm2-god-retirement.d.ts +59 -0
  136. package/dist/cli/pm2-god-retirement.d.ts.map +1 -0
  137. package/dist/cli/pm2-god-retirement.js +95 -0
  138. package/dist/cli/pm2-god-retirement.js.map +1 -0
  139. package/dist/cli/session-list-wake.d.ts +41 -0
  140. package/dist/cli/session-list-wake.d.ts.map +1 -0
  141. package/dist/cli/session-list-wake.js +102 -0
  142. package/dist/cli/session-list-wake.js.map +1 -0
  143. package/dist/cli/workflow.d.ts.map +1 -1
  144. package/dist/cli/workflow.js +26 -0
  145. package/dist/cli/workflow.js.map +1 -1
  146. package/dist/cli.d.ts.map +1 -1
  147. package/dist/cli.js +941 -118
  148. package/dist/cli.js.map +1 -1
  149. package/dist/codex-app-runner.js +261 -49
  150. package/dist/codex-app-runner.js.map +1 -1
  151. package/dist/core/cli-runtime-update.d.ts +8 -0
  152. package/dist/core/cli-runtime-update.d.ts.map +1 -1
  153. package/dist/core/cli-runtime-update.js +127 -8
  154. package/dist/core/cli-runtime-update.js.map +1 -1
  155. package/dist/core/close-residual.d.ts +64 -0
  156. package/dist/core/close-residual.d.ts.map +1 -0
  157. package/dist/core/close-residual.js +93 -0
  158. package/dist/core/close-residual.js.map +1 -0
  159. package/dist/core/closed-session-card.d.ts.map +1 -1
  160. package/dist/core/closed-session-card.js +11 -3
  161. package/dist/core/closed-session-card.js.map +1 -1
  162. package/dist/core/command-discovery.d.ts.map +1 -1
  163. package/dist/core/command-discovery.js +4 -1
  164. package/dist/core/command-discovery.js.map +1 -1
  165. package/dist/core/command-handler.d.ts.map +1 -1
  166. package/dist/core/command-handler.js +129 -27
  167. package/dist/core/command-handler.js.map +1 -1
  168. package/dist/core/cost-calculator.d.ts +3 -1
  169. package/dist/core/cost-calculator.d.ts.map +1 -1
  170. package/dist/core/cost-calculator.js +230 -1
  171. package/dist/core/cost-calculator.js.map +1 -1
  172. package/dist/core/daemon-background-close.d.ts +19 -0
  173. package/dist/core/daemon-background-close.d.ts.map +1 -0
  174. package/dist/core/daemon-background-close.js +39 -0
  175. package/dist/core/daemon-background-close.js.map +1 -0
  176. package/dist/core/dashboard-command/overview.d.ts +4 -0
  177. package/dist/core/dashboard-command/overview.d.ts.map +1 -1
  178. package/dist/core/dashboard-command/overview.js +8 -1
  179. package/dist/core/dashboard-command/overview.js.map +1 -1
  180. package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
  181. package/dist/core/dashboard-ipc-server.js +415 -42
  182. package/dist/core/dashboard-ipc-server.js.map +1 -1
  183. package/dist/core/dashboard-rows.d.ts +4 -0
  184. package/dist/core/dashboard-rows.d.ts.map +1 -1
  185. package/dist/core/dashboard-rows.js +3 -0
  186. package/dist/core/dashboard-rows.js.map +1 -1
  187. package/dist/core/dashboard-url.d.ts +37 -0
  188. package/dist/core/dashboard-url.d.ts.map +1 -1
  189. package/dist/core/dashboard-url.js +71 -0
  190. package/dist/core/dashboard-url.js.map +1 -1
  191. package/dist/core/deferred-schedule-settlement.d.ts +15 -1
  192. package/dist/core/deferred-schedule-settlement.d.ts.map +1 -1
  193. package/dist/core/deferred-schedule-settlement.js +4 -1
  194. package/dist/core/deferred-schedule-settlement.js.map +1 -1
  195. package/dist/core/device-isolation-daemon.d.ts +91 -1
  196. package/dist/core/device-isolation-daemon.d.ts.map +1 -1
  197. package/dist/core/device-isolation-daemon.js +346 -2
  198. package/dist/core/device-isolation-daemon.js.map +1 -1
  199. package/dist/core/local-terminal-opener.d.ts.map +1 -1
  200. package/dist/core/local-terminal-opener.js +5 -1
  201. package/dist/core/local-terminal-opener.js.map +1 -1
  202. package/dist/core/loopback-target.d.ts +14 -0
  203. package/dist/core/loopback-target.d.ts.map +1 -0
  204. package/dist/core/loopback-target.js +20 -0
  205. package/dist/core/loopback-target.js.map +1 -0
  206. package/dist/core/maintenance.d.ts.map +1 -1
  207. package/dist/core/maintenance.js +16 -2
  208. package/dist/core/maintenance.js.map +1 -1
  209. package/dist/core/mojo-containment-command.d.ts +20 -0
  210. package/dist/core/mojo-containment-command.d.ts.map +1 -0
  211. package/dist/core/mojo-containment-command.js +266 -0
  212. package/dist/core/mojo-containment-command.js.map +1 -0
  213. package/dist/core/mojo-containment.d.ts +575 -0
  214. package/dist/core/mojo-containment.d.ts.map +1 -0
  215. package/dist/core/mojo-containment.js +1158 -0
  216. package/dist/core/mojo-containment.js.map +1 -0
  217. package/dist/core/mojo-launcher-env-quarantine.d.ts +30 -0
  218. package/dist/core/mojo-launcher-env-quarantine.d.ts.map +1 -0
  219. package/dist/core/mojo-launcher-env-quarantine.js +175 -0
  220. package/dist/core/mojo-launcher-env-quarantine.js.map +1 -0
  221. package/dist/core/mojo-session-identity.d.ts +3 -0
  222. package/dist/core/mojo-session-identity.d.ts.map +1 -0
  223. package/dist/core/mojo-session-identity.js +126 -0
  224. package/dist/core/mojo-session-identity.js.map +1 -0
  225. package/dist/core/persistent-backend.d.ts +32 -8
  226. package/dist/core/persistent-backend.d.ts.map +1 -1
  227. package/dist/core/persistent-backend.js +55 -17
  228. package/dist/core/persistent-backend.js.map +1 -1
  229. package/dist/core/plugins/mcp/gateway.d.ts +14 -1
  230. package/dist/core/plugins/mcp/gateway.d.ts.map +1 -1
  231. package/dist/core/plugins/mcp/gateway.js +70 -3
  232. package/dist/core/plugins/mcp/gateway.js.map +1 -1
  233. package/dist/core/plugins/mcp/host.d.ts +2 -0
  234. package/dist/core/plugins/mcp/host.d.ts.map +1 -1
  235. package/dist/core/plugins/mcp/host.js +2 -0
  236. package/dist/core/plugins/mcp/host.js.map +1 -1
  237. package/dist/core/plugins/pm2.d.ts.map +1 -1
  238. package/dist/core/plugins/pm2.js +16 -3
  239. package/dist/core/plugins/pm2.js.map +1 -1
  240. package/dist/core/plugins/service-manager.d.ts +9 -0
  241. package/dist/core/plugins/service-manager.d.ts.map +1 -1
  242. package/dist/core/plugins/service-manager.js +33 -16
  243. package/dist/core/plugins/service-manager.js.map +1 -1
  244. package/dist/core/preview-port-owner.d.ts +109 -0
  245. package/dist/core/preview-port-owner.d.ts.map +1 -0
  246. package/dist/core/preview-port-owner.js +320 -0
  247. package/dist/core/preview-port-owner.js.map +1 -0
  248. package/dist/core/remote-cli-ids.d.ts +5 -0
  249. package/dist/core/remote-cli-ids.d.ts.map +1 -0
  250. package/dist/core/remote-cli-ids.js +24 -0
  251. package/dist/core/remote-cli-ids.js.map +1 -0
  252. package/dist/core/{riff-shutdown-detach.d.ts → remote-shutdown-detach.d.ts} +40 -39
  253. package/dist/core/remote-shutdown-detach.d.ts.map +1 -0
  254. package/dist/core/{riff-shutdown-detach.js → remote-shutdown-detach.js} +85 -83
  255. package/dist/core/remote-shutdown-detach.js.map +1 -0
  256. package/dist/core/{riff-worker-shutdown-readiness.d.ts → remote-worker-shutdown-readiness.d.ts} +5 -4
  257. package/dist/core/remote-worker-shutdown-readiness.d.ts.map +1 -0
  258. package/dist/core/{riff-worker-shutdown-readiness.js → remote-worker-shutdown-readiness.js} +4 -3
  259. package/dist/core/remote-worker-shutdown-readiness.js.map +1 -0
  260. package/dist/core/reply-target.d.ts +16 -1
  261. package/dist/core/reply-target.d.ts.map +1 -1
  262. package/dist/core/reply-target.js +61 -0
  263. package/dist/core/reply-target.js.map +1 -1
  264. package/dist/core/session-group-birth.d.ts +26 -0
  265. package/dist/core/session-group-birth.d.ts.map +1 -1
  266. package/dist/core/session-group-birth.js +81 -4
  267. package/dist/core/session-group-birth.js.map +1 -1
  268. package/dist/core/session-manager.d.ts +15 -2
  269. package/dist/core/session-manager.d.ts.map +1 -1
  270. package/dist/core/session-manager.js +259 -5
  271. package/dist/core/session-manager.js.map +1 -1
  272. package/dist/core/session-model.d.ts +46 -0
  273. package/dist/core/session-model.d.ts.map +1 -0
  274. package/dist/core/session-model.js +42 -0
  275. package/dist/core/session-model.js.map +1 -0
  276. package/dist/core/session-owner-reminder.d.ts +63 -0
  277. package/dist/core/session-owner-reminder.d.ts.map +1 -0
  278. package/dist/core/session-owner-reminder.js +196 -0
  279. package/dist/core/session-owner-reminder.js.map +1 -0
  280. package/dist/core/session-preview-registry.d.ts +53 -0
  281. package/dist/core/session-preview-registry.d.ts.map +1 -0
  282. package/dist/core/session-preview-registry.js +82 -0
  283. package/dist/core/session-preview-registry.js.map +1 -0
  284. package/dist/core/session-preview.d.ts +114 -0
  285. package/dist/core/session-preview.d.ts.map +1 -0
  286. package/dist/core/session-preview.js +184 -0
  287. package/dist/core/session-preview.js.map +1 -0
  288. package/dist/core/session-rename.d.ts.map +1 -1
  289. package/dist/core/session-rename.js +5 -3
  290. package/dist/core/session-rename.js.map +1 -1
  291. package/dist/core/session-wake-deadline.d.ts +5 -0
  292. package/dist/core/session-wake-deadline.d.ts.map +1 -0
  293. package/dist/core/session-wake-deadline.js +13 -0
  294. package/dist/core/session-wake-deadline.js.map +1 -0
  295. package/dist/core/shutdown-budgets.d.ts +7 -6
  296. package/dist/core/shutdown-budgets.d.ts.map +1 -1
  297. package/dist/core/shutdown-budgets.js +11 -10
  298. package/dist/core/shutdown-budgets.js.map +1 -1
  299. package/dist/core/skills/frontmatter.d.ts.map +1 -1
  300. package/dist/core/skills/frontmatter.js +6 -1
  301. package/dist/core/skills/frontmatter.js.map +1 -1
  302. package/dist/core/terminal-control-grant.d.ts +74 -0
  303. package/dist/core/terminal-control-grant.d.ts.map +1 -0
  304. package/dist/core/terminal-control-grant.js +183 -0
  305. package/dist/core/terminal-control-grant.js.map +1 -0
  306. package/dist/core/terminal-proxy.d.ts.map +1 -1
  307. package/dist/core/terminal-proxy.js +4 -5
  308. package/dist/core/terminal-proxy.js.map +1 -1
  309. package/dist/core/terminal-write-auth.d.ts +4 -11
  310. package/dist/core/terminal-write-auth.d.ts.map +1 -1
  311. package/dist/core/terminal-write-auth.js +19 -16
  312. package/dist/core/terminal-write-auth.js.map +1 -1
  313. package/dist/core/trigger-session.d.ts.map +1 -1
  314. package/dist/core/trigger-session.js +36 -29
  315. package/dist/core/trigger-session.js.map +1 -1
  316. package/dist/core/types.d.ts +88 -10
  317. package/dist/core/types.d.ts.map +1 -1
  318. package/dist/core/types.js +9 -7
  319. package/dist/core/types.js.map +1 -1
  320. package/dist/core/workbench-link.d.ts +81 -0
  321. package/dist/core/workbench-link.d.ts.map +1 -0
  322. package/dist/core/workbench-link.js +109 -0
  323. package/dist/core/workbench-link.js.map +1 -0
  324. package/dist/core/worker-pool.d.ts +312 -11
  325. package/dist/core/worker-pool.d.ts.map +1 -1
  326. package/dist/core/worker-pool.js +2515 -217
  327. package/dist/core/worker-pool.js.map +1 -1
  328. package/dist/daemon.d.ts +6 -0
  329. package/dist/daemon.d.ts.map +1 -1
  330. package/dist/daemon.js +447 -116
  331. package/dist/daemon.js.map +1 -1
  332. package/dist/dashboard/aggregator.d.ts +33 -3
  333. package/dist/dashboard/aggregator.d.ts.map +1 -1
  334. package/dist/dashboard/aggregator.js +93 -17
  335. package/dist/dashboard/aggregator.js.map +1 -1
  336. package/dist/dashboard/auth-session-connections.d.ts +59 -0
  337. package/dist/dashboard/auth-session-connections.d.ts.map +1 -0
  338. package/dist/dashboard/auth-session-connections.js +109 -0
  339. package/dist/dashboard/auth-session-connections.js.map +1 -0
  340. package/dist/dashboard/auth.d.ts +99 -1
  341. package/dist/dashboard/auth.d.ts.map +1 -1
  342. package/dist/dashboard/auth.js +176 -64
  343. package/dist/dashboard/auth.js.map +1 -1
  344. package/dist/dashboard/bot-payload.d.ts +5 -0
  345. package/dist/dashboard/bot-payload.d.ts.map +1 -1
  346. package/dist/dashboard/bot-payload.js +4 -0
  347. package/dist/dashboard/bot-payload.js.map +1 -1
  348. package/dist/dashboard/control-audit.d.ts +112 -0
  349. package/dist/dashboard/control-audit.d.ts.map +1 -0
  350. package/dist/dashboard/control-audit.js +195 -0
  351. package/dist/dashboard/control-audit.js.map +1 -0
  352. package/dist/dashboard/control-csrf.d.ts +123 -0
  353. package/dist/dashboard/control-csrf.d.ts.map +1 -0
  354. package/dist/dashboard/control-csrf.js +392 -0
  355. package/dist/dashboard/control-csrf.js.map +1 -0
  356. package/dist/dashboard/daemon-reconcile.d.ts +26 -0
  357. package/dist/dashboard/daemon-reconcile.d.ts.map +1 -0
  358. package/dist/dashboard/daemon-reconcile.js +46 -0
  359. package/dist/dashboard/daemon-reconcile.js.map +1 -0
  360. package/dist/dashboard/debug-terminal.d.ts.map +1 -1
  361. package/dist/dashboard/debug-terminal.js +18 -4
  362. package/dist/dashboard/debug-terminal.js.map +1 -1
  363. package/dist/dashboard/events-sse.d.ts +60 -0
  364. package/dist/dashboard/events-sse.d.ts.map +1 -0
  365. package/dist/dashboard/events-sse.js +63 -0
  366. package/dist/dashboard/events-sse.js.map +1 -0
  367. package/dist/dashboard/h5-auth.d.ts +256 -0
  368. package/dist/dashboard/h5-auth.d.ts.map +1 -0
  369. package/dist/dashboard/h5-auth.js +825 -0
  370. package/dist/dashboard/h5-auth.js.map +1 -0
  371. package/dist/dashboard/managed-spawn.d.ts +36 -0
  372. package/dist/dashboard/managed-spawn.d.ts.map +1 -0
  373. package/dist/dashboard/managed-spawn.js +169 -0
  374. package/dist/dashboard/managed-spawn.js.map +1 -0
  375. package/dist/dashboard/preview-content-capability.d.ts +41 -0
  376. package/dist/dashboard/preview-content-capability.d.ts.map +1 -0
  377. package/dist/dashboard/preview-content-capability.js +127 -0
  378. package/dist/dashboard/preview-content-capability.js.map +1 -0
  379. package/dist/dashboard/preview-contract.d.ts +85 -0
  380. package/dist/dashboard/preview-contract.d.ts.map +1 -0
  381. package/dist/dashboard/preview-contract.js +198 -0
  382. package/dist/dashboard/preview-contract.js.map +1 -0
  383. package/dist/dashboard/preview-guard-page.d.ts +52 -0
  384. package/dist/dashboard/preview-guard-page.d.ts.map +1 -0
  385. package/dist/dashboard/preview-guard-page.js +162 -0
  386. package/dist/dashboard/preview-guard-page.js.map +1 -0
  387. package/dist/dashboard/preview-interaction.d.ts +57 -0
  388. package/dist/dashboard/preview-interaction.d.ts.map +1 -0
  389. package/dist/dashboard/preview-interaction.js +198 -0
  390. package/dist/dashboard/preview-interaction.js.map +1 -0
  391. package/dist/dashboard/preview-proxy.d.ts +113 -0
  392. package/dist/dashboard/preview-proxy.d.ts.map +1 -0
  393. package/dist/dashboard/preview-proxy.js +543 -0
  394. package/dist/dashboard/preview-proxy.js.map +1 -0
  395. package/dist/dashboard/public-redact.d.ts +23 -0
  396. package/dist/dashboard/public-redact.d.ts.map +1 -1
  397. package/dist/dashboard/public-redact.js +90 -21
  398. package/dist/dashboard/public-redact.js.map +1 -1
  399. package/dist/dashboard/request-identity.d.ts +77 -0
  400. package/dist/dashboard/request-identity.d.ts.map +1 -0
  401. package/dist/dashboard/request-identity.js +72 -0
  402. package/dist/dashboard/request-identity.js.map +1 -0
  403. package/dist/dashboard/session-cleanup.d.ts +5 -0
  404. package/dist/dashboard/session-cleanup.d.ts.map +1 -1
  405. package/dist/dashboard/session-cleanup.js +4 -0
  406. package/dist/dashboard/session-cleanup.js.map +1 -1
  407. package/dist/dashboard/settings-write-applier.d.ts +5 -1
  408. package/dist/dashboard/settings-write-applier.d.ts.map +1 -1
  409. package/dist/dashboard/settings-write-applier.js +14 -0
  410. package/dist/dashboard/settings-write-applier.js.map +1 -1
  411. package/dist/dashboard/standing-link.d.ts +76 -0
  412. package/dist/dashboard/standing-link.d.ts.map +1 -0
  413. package/dist/dashboard/standing-link.js +111 -0
  414. package/dist/dashboard/standing-link.js.map +1 -0
  415. package/dist/dashboard/terminal-control.d.ts +105 -0
  416. package/dist/dashboard/terminal-control.d.ts.map +1 -0
  417. package/dist/dashboard/terminal-control.js +296 -0
  418. package/dist/dashboard/terminal-control.js.map +1 -0
  419. package/dist/dashboard/terminal-front-proxy.d.ts +55 -0
  420. package/dist/dashboard/terminal-front-proxy.d.ts.map +1 -0
  421. package/dist/dashboard/terminal-front-proxy.js +397 -0
  422. package/dist/dashboard/terminal-front-proxy.js.map +1 -0
  423. package/dist/dashboard/terminal-view-capability.d.ts +97 -0
  424. package/dist/dashboard/terminal-view-capability.d.ts.map +1 -0
  425. package/dist/dashboard/terminal-view-capability.js +145 -0
  426. package/dist/dashboard/terminal-view-capability.js.map +1 -0
  427. package/dist/dashboard/web/agent-workbench-api.d.ts +59 -0
  428. package/dist/dashboard/web/agent-workbench-api.d.ts.map +1 -0
  429. package/dist/dashboard/web/agent-workbench-api.js +227 -0
  430. package/dist/dashboard/web/agent-workbench-api.js.map +1 -0
  431. package/dist/dashboard/web/agent-workbench-appearance-menu.d.ts +59 -0
  432. package/dist/dashboard/web/agent-workbench-appearance-menu.d.ts.map +1 -0
  433. package/dist/dashboard/web/agent-workbench-appearance-menu.js +195 -0
  434. package/dist/dashboard/web/agent-workbench-appearance-menu.js.map +1 -0
  435. package/dist/dashboard/web/agent-workbench-appearance.d.ts +222 -0
  436. package/dist/dashboard/web/agent-workbench-appearance.d.ts.map +1 -0
  437. package/dist/dashboard/web/agent-workbench-appearance.js +499 -0
  438. package/dist/dashboard/web/agent-workbench-appearance.js.map +1 -0
  439. package/dist/dashboard/web/agent-workbench-capabilities.d.ts +13 -0
  440. package/dist/dashboard/web/agent-workbench-capabilities.d.ts.map +1 -0
  441. package/dist/dashboard/web/agent-workbench-capabilities.js +24 -0
  442. package/dist/dashboard/web/agent-workbench-capabilities.js.map +1 -0
  443. package/dist/dashboard/web/agent-workbench-chat.d.ts +90 -0
  444. package/dist/dashboard/web/agent-workbench-chat.d.ts.map +1 -0
  445. package/dist/dashboard/web/agent-workbench-chat.js +168 -0
  446. package/dist/dashboard/web/agent-workbench-chat.js.map +1 -0
  447. package/dist/dashboard/web/agent-workbench-dock-page.d.ts +3 -0
  448. package/dist/dashboard/web/agent-workbench-dock-page.d.ts.map +1 -0
  449. package/dist/dashboard/web/agent-workbench-dock-page.js +23 -0
  450. package/dist/dashboard/web/agent-workbench-dock-page.js.map +1 -0
  451. package/dist/dashboard/web/agent-workbench-dock-view.d.ts +22 -0
  452. package/dist/dashboard/web/agent-workbench-dock-view.d.ts.map +1 -0
  453. package/dist/dashboard/web/agent-workbench-dock-view.js +76 -0
  454. package/dist/dashboard/web/agent-workbench-dock-view.js.map +1 -0
  455. package/dist/dashboard/web/agent-workbench-model.d.ts +196 -0
  456. package/dist/dashboard/web/agent-workbench-model.d.ts.map +1 -0
  457. package/dist/dashboard/web/agent-workbench-model.js +529 -0
  458. package/dist/dashboard/web/agent-workbench-model.js.map +1 -0
  459. package/dist/dashboard/web/agent-workbench-page.d.ts +3 -0
  460. package/dist/dashboard/web/agent-workbench-page.d.ts.map +1 -0
  461. package/dist/dashboard/web/agent-workbench-page.js +27 -0
  462. package/dist/dashboard/web/agent-workbench-page.js.map +1 -0
  463. package/dist/dashboard/web/agent-workbench-panes.d.ts +49 -0
  464. package/dist/dashboard/web/agent-workbench-panes.d.ts.map +1 -0
  465. package/dist/dashboard/web/agent-workbench-panes.js +468 -0
  466. package/dist/dashboard/web/agent-workbench-panes.js.map +1 -0
  467. package/dist/dashboard/web/agent-workbench-session-list.d.ts +42 -0
  468. package/dist/dashboard/web/agent-workbench-session-list.d.ts.map +1 -0
  469. package/dist/dashboard/web/agent-workbench-session-list.js +353 -0
  470. package/dist/dashboard/web/agent-workbench-session-list.js.map +1 -0
  471. package/dist/dashboard/web/agent-workbench-storage.d.ts +49 -0
  472. package/dist/dashboard/web/agent-workbench-storage.d.ts.map +1 -0
  473. package/dist/dashboard/web/agent-workbench-storage.js +197 -0
  474. package/dist/dashboard/web/agent-workbench-storage.js.map +1 -0
  475. package/dist/dashboard/web/agent-workbench-touch.d.ts +46 -0
  476. package/dist/dashboard/web/agent-workbench-touch.d.ts.map +1 -0
  477. package/dist/dashboard/web/agent-workbench-touch.js +96 -0
  478. package/dist/dashboard/web/agent-workbench-touch.js.map +1 -0
  479. package/dist/dashboard/web/agent-workbench-view.d.ts +34 -0
  480. package/dist/dashboard/web/agent-workbench-view.d.ts.map +1 -0
  481. package/dist/dashboard/web/agent-workbench-view.js +439 -0
  482. package/dist/dashboard/web/agent-workbench-view.js.map +1 -0
  483. package/dist/dashboard/web/app.d.ts.map +1 -1
  484. package/dist/dashboard/web/app.js +63 -2
  485. package/dist/dashboard/web/app.js.map +1 -1
  486. package/dist/dashboard/web/bot-defaults-page.d.ts +18 -0
  487. package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -1
  488. package/dist/dashboard/web/bot-defaults-page.js +362 -36
  489. package/dist/dashboard/web/bot-defaults-page.js.map +1 -1
  490. package/dist/dashboard/web/bot-defaults.d.ts +8 -0
  491. package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
  492. package/dist/dashboard/web/bot-defaults.js.map +1 -1
  493. package/dist/dashboard/web/control-csrf.d.ts +4 -0
  494. package/dist/dashboard/web/control-csrf.d.ts.map +1 -0
  495. package/dist/dashboard/web/control-csrf.js +26 -0
  496. package/dist/dashboard/web/control-csrf.js.map +1 -0
  497. package/dist/dashboard/web/dashboard-routes.d.ts.map +1 -1
  498. package/dist/dashboard/web/dashboard-routes.js +2 -0
  499. package/dist/dashboard/web/dashboard-routes.js.map +1 -1
  500. package/dist/dashboard/web/groups-page.d.ts.map +1 -1
  501. package/dist/dashboard/web/groups-page.js +11 -2
  502. package/dist/dashboard/web/groups-page.js.map +1 -1
  503. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  504. package/dist/dashboard/web/i18n.js +140 -6
  505. package/dist/dashboard/web/i18n.js.map +1 -1
  506. package/dist/dashboard/web/overview-page.d.ts.map +1 -1
  507. package/dist/dashboard/web/overview-page.js +3 -2
  508. package/dist/dashboard/web/overview-page.js.map +1 -1
  509. package/dist/dashboard/web/sessions-page.d.ts.map +1 -1
  510. package/dist/dashboard/web/sessions-page.js +41 -1
  511. package/dist/dashboard/web/sessions-page.js.map +1 -1
  512. package/dist/dashboard/web/sessions.d.ts.map +1 -1
  513. package/dist/dashboard/web/sessions.js +5 -1
  514. package/dist/dashboard/web/sessions.js.map +1 -1
  515. package/dist/dashboard/web/settings-page.d.ts +3 -0
  516. package/dist/dashboard/web/settings-page.d.ts.map +1 -1
  517. package/dist/dashboard/web/settings-page.js +56 -10
  518. package/dist/dashboard/web/settings-page.js.map +1 -1
  519. package/dist/dashboard/web/skills-page.d.ts.map +1 -1
  520. package/dist/dashboard/web/skills-page.js +4 -2
  521. package/dist/dashboard/web/skills-page.js.map +1 -1
  522. package/dist/dashboard/web/store.d.ts +27 -2
  523. package/dist/dashboard/web/store.d.ts.map +1 -1
  524. package/dist/dashboard/web/store.js +43 -4
  525. package/dist/dashboard/web/store.js.map +1 -1
  526. package/dist/dashboard/web/ui.d.ts +3 -0
  527. package/dist/dashboard/web/ui.d.ts.map +1 -1
  528. package/dist/dashboard/web/ui.js +11 -0
  529. package/dist/dashboard/web/ui.js.map +1 -1
  530. package/dist/dashboard/web/update-action.d.ts +12 -0
  531. package/dist/dashboard/web/update-action.d.ts.map +1 -1
  532. package/dist/dashboard/web/update-action.js +11 -0
  533. package/dist/dashboard/web/update-action.js.map +1 -1
  534. package/dist/dashboard/workbench-doctor.d.ts +114 -0
  535. package/dist/dashboard/workbench-doctor.d.ts.map +1 -0
  536. package/dist/dashboard/workbench-doctor.js +620 -0
  537. package/dist/dashboard/workbench-doctor.js.map +1 -0
  538. package/dist/dashboard/workbench-ticket.d.ts +165 -0
  539. package/dist/dashboard/workbench-ticket.d.ts.map +1 -0
  540. package/dist/dashboard/workbench-ticket.js +495 -0
  541. package/dist/dashboard/workbench-ticket.js.map +1 -0
  542. package/dist/dashboard-web/app.js +1 -1
  543. package/dist/dashboard-web/chunks/agent-workbench-dock-page-IKAC5CFL.js +1 -0
  544. package/dist/dashboard-web/chunks/agent-workbench-page-M53UN5EB.js +1 -0
  545. package/dist/dashboard-web/chunks/bot-defaults-page-YKE5SDZF.js +10 -0
  546. package/dist/dashboard-web/chunks/chunk-22WIADUT.js +2 -0
  547. package/dist/dashboard-web/chunks/chunk-24ONYQMR.js +1 -0
  548. package/dist/dashboard-web/chunks/{chunk-6O7KXFD2.js → chunk-2W6SCN3M.js} +1 -1
  549. package/dist/dashboard-web/chunks/chunk-4XNJX6B3.js +1 -0
  550. package/dist/dashboard-web/chunks/{chunk-Q2MT4VWH.js → chunk-F6KNPF4R.js} +11 -9
  551. package/dist/dashboard-web/chunks/chunk-FXW3V4JR.js +1 -0
  552. package/dist/dashboard-web/chunks/chunk-G5ZS2YUS.js +1 -0
  553. package/dist/dashboard-web/chunks/chunk-KTQ7B6ZR.js +1 -0
  554. package/dist/dashboard-web/chunks/{chunk-U3ZFSO7E.js → chunk-NACP7BMR.js} +1 -1
  555. package/dist/dashboard-web/chunks/{connectors-page-2KZO5KSJ.js → connectors-page-VOISXXII.js} +1 -1
  556. package/dist/dashboard-web/chunks/{feedback-page-CLVTOLLO.js → feedback-page-RN6HRZMS.js} +1 -1
  557. package/dist/dashboard-web/chunks/groups-page-UQT6DCB7.js +8 -0
  558. package/dist/dashboard-web/chunks/{insights-page-4RPU2CRU.js → insights-page-HJFDYR5N.js} +3 -3
  559. package/dist/dashboard-web/chunks/{monitor-room-OTKQ2CXK.js → monitor-room-V7PCP47V.js} +1 -1
  560. package/dist/dashboard-web/chunks/{monitoring-page-IJPUB6JT.js → monitoring-page-NKEKVQAP.js} +1 -1
  561. package/dist/dashboard-web/chunks/{office-page-QSR3J44Y.js → office-page-GVJF73XW.js} +1 -1
  562. package/dist/dashboard-web/chunks/overview-page-KHLV6VTI.js +1 -0
  563. package/dist/dashboard-web/chunks/{plugin-page-VEGTCEAS.js → plugin-page-J3OF5IY4.js} +1 -1
  564. package/dist/dashboard-web/chunks/{roles-page-6NWJMOB5.js → roles-page-WQIRSOLZ.js} +1 -1
  565. package/dist/dashboard-web/chunks/{schedules-page-6I3LNXD4.js → schedules-page-J2DEY2X6.js} +1 -1
  566. package/dist/dashboard-web/chunks/sessions-page-7BQFEA5P.js +8 -0
  567. package/dist/dashboard-web/chunks/settings-page-BJEIOFJH.js +2 -0
  568. package/dist/dashboard-web/chunks/{skills-page-M2Q6L5CB.js → skills-page-HGIFR3IU.js} +2 -2
  569. package/dist/dashboard-web/chunks/{team-federation-page-7I7FDE3B.js → team-federation-page-MR5ZPL4B.js} +1 -1
  570. package/dist/dashboard-web/chunks/{v3-page-HQXRL65L.js → v3-page-GBR5JWPE.js} +2 -2
  571. package/dist/dashboard-web/chunks/{whiteboards-page-LQKC4TAZ.js → whiteboards-page-QAZM4BN3.js} +1 -1
  572. package/dist/dashboard-web/index.html +8 -1
  573. package/dist/dashboard-web/style.css +2006 -10
  574. package/dist/dashboard.js +1017 -264
  575. package/dist/dashboard.js.map +1 -1
  576. package/dist/dsh-runner.js +8 -1
  577. package/dist/dsh-runner.js.map +1 -1
  578. package/dist/global-config.d.ts +30 -0
  579. package/dist/global-config.d.ts.map +1 -1
  580. package/dist/global-config.js +33 -0
  581. package/dist/global-config.js.map +1 -1
  582. package/dist/i18n/en.d.ts.map +1 -1
  583. package/dist/i18n/en.js +46 -27
  584. package/dist/i18n/en.js.map +1 -1
  585. package/dist/i18n/zh.d.ts.map +1 -1
  586. package/dist/i18n/zh.js +43 -27
  587. package/dist/i18n/zh.js.map +1 -1
  588. package/dist/im/lark/card-builder.d.ts +1 -1
  589. package/dist/im/lark/card-builder.d.ts.map +1 -1
  590. package/dist/im/lark/card-builder.js +22 -6
  591. package/dist/im/lark/card-builder.js.map +1 -1
  592. package/dist/im/lark/card-handler.d.ts.map +1 -1
  593. package/dist/im/lark/card-handler.js +118 -24
  594. package/dist/im/lark/card-handler.js.map +1 -1
  595. package/dist/im/lark/client.d.ts +15 -0
  596. package/dist/im/lark/client.d.ts.map +1 -1
  597. package/dist/im/lark/client.js +30 -0
  598. package/dist/im/lark/client.js.map +1 -1
  599. package/dist/im/lark/event-dispatcher.d.ts +48 -0
  600. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  601. package/dist/im/lark/event-dispatcher.js +138 -41
  602. package/dist/im/lark/event-dispatcher.js.map +1 -1
  603. package/dist/im/lark/identity-cache.d.ts +14 -6
  604. package/dist/im/lark/identity-cache.d.ts.map +1 -1
  605. package/dist/im/lark/identity-cache.js +69 -26
  606. package/dist/im/lark/identity-cache.js.map +1 -1
  607. package/dist/im/lark/lark-hosts.d.ts +13 -0
  608. package/dist/im/lark/lark-hosts.d.ts.map +1 -1
  609. package/dist/im/lark/lark-hosts.js +16 -0
  610. package/dist/im/lark/lark-hosts.js.map +1 -1
  611. package/dist/im/lark/overview-card.d.ts +22 -0
  612. package/dist/im/lark/overview-card.d.ts.map +1 -1
  613. package/dist/im/lark/overview-card.js +53 -3
  614. package/dist/im/lark/overview-card.js.map +1 -1
  615. package/dist/im/lark/sessions-card.d.ts.map +1 -1
  616. package/dist/im/lark/sessions-card.js +26 -3
  617. package/dist/im/lark/sessions-card.js.map +1 -1
  618. package/dist/im/lark/workflow-slash-command.d.ts +6 -0
  619. package/dist/im/lark/workflow-slash-command.d.ts.map +1 -1
  620. package/dist/im/lark/workflow-slash-command.js +7 -0
  621. package/dist/im/lark/workflow-slash-command.js.map +1 -1
  622. package/dist/index-daemon.js +27 -4
  623. package/dist/index-daemon.js.map +1 -1
  624. package/dist/index-dashboard.d.ts +3 -0
  625. package/dist/index-dashboard.d.ts.map +1 -0
  626. package/dist/index-dashboard.js +94 -0
  627. package/dist/index-dashboard.js.map +1 -0
  628. package/dist/platform/team-agents-client.d.ts +199 -0
  629. package/dist/platform/team-agents-client.d.ts.map +1 -0
  630. package/dist/platform/team-agents-client.js +263 -0
  631. package/dist/platform/team-agents-client.js.map +1 -0
  632. package/dist/platform/tunnel-client.d.ts +6 -0
  633. package/dist/platform/tunnel-client.d.ts.map +1 -1
  634. package/dist/platform/tunnel-client.js.map +1 -1
  635. package/dist/services/async-trigger-state.d.ts +7 -3
  636. package/dist/services/async-trigger-state.d.ts.map +1 -1
  637. package/dist/services/async-trigger-state.js +28 -0
  638. package/dist/services/async-trigger-state.js.map +1 -1
  639. package/dist/services/async-trigger-store.d.ts +13 -4
  640. package/dist/services/async-trigger-store.d.ts.map +1 -1
  641. package/dist/services/async-trigger-store.js +55 -8
  642. package/dist/services/async-trigger-store.js.map +1 -1
  643. package/dist/services/bot-config-store.d.ts +1 -11
  644. package/dist/services/bot-config-store.d.ts.map +1 -1
  645. package/dist/services/bot-config-store.js +27 -3
  646. package/dist/services/bot-config-store.js.map +1 -1
  647. package/dist/services/bot-profile-store.d.ts +17 -2
  648. package/dist/services/bot-profile-store.d.ts.map +1 -1
  649. package/dist/services/bot-profile-store.js +93 -12
  650. package/dist/services/bot-profile-store.js.map +1 -1
  651. package/dist/services/bridge-fallback-gate.d.ts +15 -7
  652. package/dist/services/bridge-fallback-gate.d.ts.map +1 -1
  653. package/dist/services/bridge-fallback-gate.js +43 -16
  654. package/dist/services/bridge-fallback-gate.js.map +1 -1
  655. package/dist/services/bridge-turn-queue.d.ts +10 -1
  656. package/dist/services/bridge-turn-queue.d.ts.map +1 -1
  657. package/dist/services/bridge-turn-queue.js +29 -9
  658. package/dist/services/bridge-turn-queue.js.map +1 -1
  659. package/dist/services/claude-transcript.d.ts +19 -0
  660. package/dist/services/claude-transcript.d.ts.map +1 -1
  661. package/dist/services/claude-transcript.js +57 -5
  662. package/dist/services/claude-transcript.js.map +1 -1
  663. package/dist/services/codex-app-threads.d.ts +2 -0
  664. package/dist/services/codex-app-threads.d.ts.map +1 -1
  665. package/dist/services/codex-app-threads.js +1 -1
  666. package/dist/services/codex-app-threads.js.map +1 -1
  667. package/dist/services/codex-reasoning-effort.d.ts +8 -0
  668. package/dist/services/codex-reasoning-effort.d.ts.map +1 -1
  669. package/dist/services/codex-reasoning-effort.js +24 -0
  670. package/dist/services/codex-reasoning-effort.js.map +1 -1
  671. package/dist/services/cursor-resume-policy.d.ts.map +1 -1
  672. package/dist/services/cursor-resume-policy.js +15 -3
  673. package/dist/services/cursor-resume-policy.js.map +1 -1
  674. package/dist/services/open-platform-rename.d.ts.map +1 -1
  675. package/dist/services/open-platform-rename.js +3 -2
  676. package/dist/services/open-platform-rename.js.map +1 -1
  677. package/dist/services/ordinary-turn-recovery.d.ts +76 -0
  678. package/dist/services/ordinary-turn-recovery.d.ts.map +1 -0
  679. package/dist/services/ordinary-turn-recovery.js +349 -0
  680. package/dist/services/ordinary-turn-recovery.js.map +1 -0
  681. package/dist/services/peer-cross-ref-store.d.ts +8 -0
  682. package/dist/services/peer-cross-ref-store.d.ts.map +1 -0
  683. package/dist/services/peer-cross-ref-store.js +95 -0
  684. package/dist/services/peer-cross-ref-store.js.map +1 -0
  685. package/dist/services/pi-transcript.d.ts.map +1 -1
  686. package/dist/services/pi-transcript.js +10 -6
  687. package/dist/services/pi-transcript.js.map +1 -1
  688. package/dist/services/resume-fresh-policy.d.ts +17 -0
  689. package/dist/services/resume-fresh-policy.d.ts.map +1 -0
  690. package/dist/services/resume-fresh-policy.js +24 -0
  691. package/dist/services/resume-fresh-policy.js.map +1 -0
  692. package/dist/services/session-group-title.d.ts +1 -0
  693. package/dist/services/session-group-title.d.ts.map +1 -1
  694. package/dist/services/session-group-title.js +16 -1
  695. package/dist/services/session-group-title.js.map +1 -1
  696. package/dist/services/session-groups-store.d.ts +30 -0
  697. package/dist/services/session-groups-store.d.ts.map +1 -1
  698. package/dist/services/session-groups-store.js +26 -4
  699. package/dist/services/session-groups-store.js.map +1 -1
  700. package/dist/services/session-owner-notification.d.ts +9 -0
  701. package/dist/services/session-owner-notification.d.ts.map +1 -0
  702. package/dist/services/session-owner-notification.js +10 -0
  703. package/dist/services/session-owner-notification.js.map +1 -0
  704. package/dist/services/session-owner-reminder-config-store.d.ts +9 -0
  705. package/dist/services/session-owner-reminder-config-store.d.ts.map +1 -0
  706. package/dist/services/session-owner-reminder-config-store.js +24 -0
  707. package/dist/services/session-owner-reminder-config-store.js.map +1 -0
  708. package/dist/services/session-owner-reminder-store.d.ts +5 -0
  709. package/dist/services/session-owner-reminder-store.d.ts.map +1 -0
  710. package/dist/services/session-owner-reminder-store.js +54 -0
  711. package/dist/services/session-owner-reminder-store.js.map +1 -0
  712. package/dist/services/session-store.d.ts +98 -21
  713. package/dist/services/session-store.d.ts.map +1 -1
  714. package/dist/services/session-store.js +406 -48
  715. package/dist/services/session-store.js.map +1 -1
  716. package/dist/services/structured-bridge-clis.d.ts +15 -2
  717. package/dist/services/structured-bridge-clis.d.ts.map +1 -1
  718. package/dist/services/structured-bridge-clis.js +16 -1
  719. package/dist/services/structured-bridge-clis.js.map +1 -1
  720. package/dist/services/transcript-resolver.d.ts +1 -1
  721. package/dist/services/transcript-resolver.d.ts.map +1 -1
  722. package/dist/services/transcript-resolver.js +6 -1
  723. package/dist/services/transcript-resolver.js.map +1 -1
  724. package/dist/setup/bot-config-editor.d.ts.map +1 -1
  725. package/dist/setup/bot-config-editor.js +7 -2
  726. package/dist/setup/bot-config-editor.js.map +1 -1
  727. package/dist/setup/ensure-herdr-integrations.d.ts +13 -0
  728. package/dist/setup/ensure-herdr-integrations.d.ts.map +1 -1
  729. package/dist/setup/ensure-herdr-integrations.js +21 -3
  730. package/dist/setup/ensure-herdr-integrations.js.map +1 -1
  731. package/dist/setup/open-platform-automation.d.ts +1 -0
  732. package/dist/setup/open-platform-automation.d.ts.map +1 -1
  733. package/dist/setup/open-platform-automation.js +107 -7
  734. package/dist/setup/open-platform-automation.js.map +1 -1
  735. package/dist/skills/definitions.d.ts +17 -0
  736. package/dist/skills/definitions.d.ts.map +1 -1
  737. package/dist/skills/definitions.js +78 -8
  738. package/dist/skills/definitions.js.map +1 -1
  739. package/dist/skills/injection-mode.d.ts +24 -3
  740. package/dist/skills/injection-mode.d.ts.map +1 -1
  741. package/dist/skills/injection-mode.js +64 -15
  742. package/dist/skills/injection-mode.js.map +1 -1
  743. package/dist/skills/installer.d.ts +18 -0
  744. package/dist/skills/installer.d.ts.map +1 -1
  745. package/dist/skills/installer.js +45 -1
  746. package/dist/skills/installer.js.map +1 -1
  747. package/dist/types.d.ts +222 -10
  748. package/dist/types.d.ts.map +1 -1
  749. package/dist/utils/bot-routing.d.ts +1 -1
  750. package/dist/utils/bot-routing.d.ts.map +1 -1
  751. package/dist/utils/bot-routing.js.map +1 -1
  752. package/dist/utils/child-env.d.ts +92 -2
  753. package/dist/utils/child-env.d.ts.map +1 -1
  754. package/dist/utils/child-env.js +195 -1
  755. package/dist/utils/child-env.js.map +1 -1
  756. package/dist/utils/cli-usage-limit.d.ts +25 -14
  757. package/dist/utils/cli-usage-limit.d.ts.map +1 -1
  758. package/dist/utils/cli-usage-limit.js +25 -15
  759. package/dist/utils/cli-usage-limit.js.map +1 -1
  760. package/dist/utils/daemon-rejection-guard.d.ts +35 -0
  761. package/dist/utils/daemon-rejection-guard.d.ts.map +1 -0
  762. package/dist/utils/daemon-rejection-guard.js +101 -0
  763. package/dist/utils/daemon-rejection-guard.js.map +1 -0
  764. package/dist/utils/dashboard-env.d.ts +53 -0
  765. package/dist/utils/dashboard-env.d.ts.map +1 -0
  766. package/dist/utils/dashboard-env.js +116 -0
  767. package/dist/utils/dashboard-env.js.map +1 -0
  768. package/dist/utils/global-install.d.ts.map +1 -1
  769. package/dist/utils/global-install.js +61 -5
  770. package/dist/utils/global-install.js.map +1 -1
  771. package/dist/utils/install-diagnostics.d.ts +14 -7
  772. package/dist/utils/install-diagnostics.d.ts.map +1 -1
  773. package/dist/utils/install-diagnostics.js +20 -11
  774. package/dist/utils/install-diagnostics.js.map +1 -1
  775. package/dist/utils/local-dev-update.d.ts +132 -0
  776. package/dist/utils/local-dev-update.d.ts.map +1 -0
  777. package/dist/utils/local-dev-update.js +176 -0
  778. package/dist/utils/local-dev-update.js.map +1 -0
  779. package/dist/utils/pending-input-queue.d.ts +12 -1
  780. package/dist/utils/pending-input-queue.d.ts.map +1 -1
  781. package/dist/utils/pending-input-queue.js.map +1 -1
  782. package/dist/worker.js +1517 -236
  783. package/dist/worker.js.map +1 -1
  784. package/dist/workflows/definition.d.ts +68 -68
  785. package/dist/workflows/events/payloads.d.ts +14 -14
  786. package/dist/workflows/events/schema.d.ts +312 -312
  787. package/dist/workflows/migration/v2-run-archive-schema.d.ts +40 -40
  788. package/dist/workflows/v3/cli-run.d.ts.map +1 -1
  789. package/dist/workflows/v3/cli-run.js +7 -0
  790. package/dist/workflows/v3/cli-run.js.map +1 -1
  791. package/dist/workflows/v3/goal-cli.d.ts +3 -0
  792. package/dist/workflows/v3/goal-cli.d.ts.map +1 -1
  793. package/dist/workflows/v3/goal-cli.js +11 -0
  794. package/dist/workflows/v3/goal-cli.js.map +1 -1
  795. package/dist/workflows/v3/run-envelope.d.ts +144 -144
  796. package/package.json +7 -2
  797. package/dist/cli/pm2-god-admission.d.ts +0 -8
  798. package/dist/cli/pm2-god-admission.d.ts.map +0 -1
  799. package/dist/cli/pm2-god-admission.js +0 -25
  800. package/dist/cli/pm2-god-admission.js.map +0 -1
  801. package/dist/core/riff-shutdown-detach.d.ts.map +0 -1
  802. package/dist/core/riff-shutdown-detach.js.map +0 -1
  803. package/dist/core/riff-worker-shutdown-readiness.d.ts.map +0 -1
  804. package/dist/core/riff-worker-shutdown-readiness.js.map +0 -1
  805. package/dist/dashboard-web/chunks/bot-defaults-page-4RENHE7J.js +0 -10
  806. package/dist/dashboard-web/chunks/chunk-2WQDS65D.js +0 -1
  807. package/dist/dashboard-web/chunks/chunk-G5XGBCM6.js +0 -1
  808. package/dist/dashboard-web/chunks/chunk-WLIVBPJC.js +0 -1
  809. package/dist/dashboard-web/chunks/groups-page-HLASRTSY.js +0 -8
  810. package/dist/dashboard-web/chunks/overview-page-6OK63V4V.js +0 -1
  811. package/dist/dashboard-web/chunks/sessions-page-B2TXGJDO.js +0 -8
  812. package/dist/dashboard-web/chunks/settings-page-6KJADSC6.js +0 -2
@@ -4,7 +4,8 @@ import { execFileSync } from 'node:child_process';
4
4
  import { readFileSync, unlinkSync } from 'node:fs';
5
5
  import { join } from 'node:path';
6
6
  import { logger } from '../utils/logger.js';
7
- import { cliAuthBind, verifyHmac } from '../dashboard/auth.js';
7
+ import { cliAuthBind, loadDashboardSecret, verifyHmac } from '../dashboard/auth.js';
8
+ import { UnsafeHostAuthorityFileError } from '../platform/secure-host-file.js';
8
9
  import { WORKFLOW_DAEMON_IPC_ROUTE_PREFIX } from '../workflows/v3/daemon-ipc-auth.js';
9
10
  import { V3_SESSION_RUN_MUTATION_ROUTE_PREFIX } from '../workflows/v3/session-relay.js';
10
11
  import { REPORT_SESSION_RELAY_ROUTE } from './report-session-relay.js';
@@ -14,7 +15,7 @@ import { dashboardSecretPath } from './dashboard-secret.js';
14
15
  import { MANAGED_ORIGIN_ATTEST_ROUTE, MANAGED_ORIGIN_PROOF_DOMAIN, MANAGED_ORIGIN_PROOF_TTL_MS, writeManagedOriginAttestationProof, } from './managed-origin-attestation.js';
15
16
  import * as sessionStore from '../services/session-store.js';
16
17
  import { cliSupportsNativeUsage } from '../services/transcript-resolver.js';
17
- import { codexModelSupportsReasoningEffort, isCodexReasoningCliId, isCodexReasoningEffort, } from '../services/codex-reasoning-effort.js';
18
+ import { cliModelSupportsReasoningEffort, isConfigurableReasoningCliId, isCodexReasoningEffort, } from '../services/codex-reasoning-effort.js';
18
19
  import * as asyncTriggerStore from '../services/async-trigger-store.js';
19
20
  import { resolveAsyncTriggerState, decideAsyncOwnership } from '../services/async-trigger-state.js';
20
21
  import * as scheduleStore from '../services/schedule-store.js';
@@ -78,10 +79,10 @@ import { readGlobalConfig } from '../global-config.js';
78
79
  import { normalizeChatReplyMode, setChatReplyMode } from '../services/chat-reply-mode-store.js';
79
80
  import * as chatFirstSeenStore from '../services/chat-first-seen-store.js';
80
81
  import * as scheduler from './scheduler.js';
81
- import { listActiveSessions, findActiveBySessionId, closeSession, getActiveSessionsRegistry, transferSession, deliverWriteLinkCardToOwners, forkWorker, suspendWorker, killWorker, latestPerBotEnvForRestart, getDaemonReplyCardUsageSnapshot, sessionSupportsWebTerminal, sendWorkerSessionInput, isSessionTransferring } from './worker-pool.js';
82
+ import { listActiveSessions, findActiveBySessionId, closeSession, getActiveSessionsRegistry, transferSession, deliverWriteLinkCardToOwners, forkWorker, suspendWorker, killWorker, latestPerBotEnvForRestart, latestModelForRespawn, getDaemonReplyCardUsageSnapshot, sessionSupportsWebTerminal, sendWorkerSessionInput, isSessionTransferring, mojoCloseResidualForRow } from './worker-pool.js';
82
83
  import { listOnlineDaemons } from '../utils/daemon-discovery.js';
83
84
  import { isSessionStopped } from './session-liveness.js';
84
- import { isSuspendableBackendType } from './persistent-backend.js';
85
+ import { isRemoteBackendType, isRemoteCliId, isSuspendableBackendType } from './persistent-backend.js';
85
86
  import { getChatMode, replyMessage, sendMessage, resolveUnionIdFromOpenId, listThreadMessages, listChatMessages, listChatMessagesUntil, listChatBotMembers, getUserProfile, getUserProfileStrict, resolveAllowedUsersWithMap } from '../im/lark/client.js';
86
87
  import { parseApiMessage, cardContentHasUpgradeFallback, resolveMergedCardContent, messageMentionsBot } from '../im/lark/message-parser.js';
87
88
  import { resumeSession, spawnDashboardSession, activateQueuedSession, closeCliMismatchedSessionsForBot } from './session-manager.js';
@@ -90,6 +91,9 @@ import { cleanupMaterializedDashboardImages, materializeDashboardImages } from '
90
91
  import { getCliDisplayName } from '../im/lark/card-builder.js';
91
92
  import { sessionConfiguredRuntimeDisplayName } from './cli-runtime-display.js';
92
93
  import { locateLimiter } from './dashboard-locate.js';
94
+ import { DEFAULT_SESSION_OWNER_REMINDER } from './session-owner-reminder.js';
95
+ import { updateSessionOwnerReminderConfig } from '../services/session-owner-reminder-config-store.js';
96
+ import { sendSessionOwnerThreadNotification } from '../services/session-owner-notification.js';
93
97
  import { buildTerminalUrl } from './terminal-url.js';
94
98
  import { dashboardEventBus } from './dashboard-events.js';
95
99
  import { validateWorkingDir } from './working-dir.js';
@@ -101,7 +105,8 @@ import { resolveCliSelection, selectionKeyForBot } from '../setup/cli-selection.
101
105
  import { checkCliAvailability } from '../setup/cli-availability.js';
102
106
  import { enrichHistorySenders } from '../dashboard/history-senders.js';
103
107
  import { validateCodexAppManagedSendOrigin, } from '../utils/codex-app-dispatch-ledger.js';
104
- import { withBotTurnAdmission, withBotTurnMutation } from './bot-turn-mutation-gate.js';
108
+ import { tryWithBotTurnMutation, withBotTurnAdmission, withBotTurnMutation } from './bot-turn-mutation-gate.js';
109
+ import { SESSION_WAKE_DEADLINE_HEADER, sessionWakeAcquireTimeoutMs, } from './session-wake-deadline.js';
105
110
  import { protectedSessionMutationReasons, } from './session-mutation-guard.js';
106
111
  import { listPendingAsks, submitAskFromDesktop } from './ask-broker.js';
107
112
  import { getMessageListenerConfig, sanitizeMessageListenerUpdate, updateMessageListenerConfig, validateMessageListenerUpdate } from '../services/message-listener-store.js';
@@ -128,7 +133,7 @@ export function setSupervisorShutdownHandler(registration) {
128
133
  supervisorShutdownRegistration = registration;
129
134
  }
130
135
  import { composeRowFromActive, composeRowFromClosed, composeRowFromPersistedActive, feishuChatLink, setBotName as setRowsBotName, getBotName, } from './dashboard-rows.js';
131
- import { getBotBrand, getBot, getBotOpenId, loadBotConfigs, readBotSkillPolicy, getBotTuiSlashAllow } from '../bot-registry.js';
136
+ import { getBotBrand, getBot, getBotOpenId, loadBotConfigs, readBotSkillPolicy, getBotTuiSlashAllow, MAX_TURN_TIMEOUT_MS } from '../bot-registry.js';
132
137
  import { generateAuthUrl, tryHandleCallbackUrl, getFeedGroupAuthStatus, FEED_GROUP_OAUTH_SCOPES } from '../utils/user-token.js';
133
138
  import { normalizeBrand } from '../im/lark/lark-hosts.js';
134
139
  import { normalizeKanbanColumn, normalizeKanbanPosition, normalizeSessionTitle } from './session-board.js';
@@ -138,9 +143,11 @@ import { repinSessionWorkingDir } from './session-cwd.js';
138
143
  import { authorizeSessionScopedIpc } from './daemon-ipc-session-auth.js';
139
144
  import { normalizeSessionTitleSource, updateSessionTitle } from './session-title.js';
140
145
  import { requestAgentSessionRename } from './session-rename.js';
146
+ import { isPreviewLoopbackHost, isPreviewPort, previewBackendSupported, probeSessionPreviewTarget, sessionPreviewDescriptor, } from './session-preview.js';
147
+ import { clearSessionPreviewTarget } from './session-preview-registry.js';
141
148
  import { ChatRenameCooldown, ChatRenameSerialQueue, normalizeLarkChatName } from './chat-rename.js';
142
149
  import { sessionAnchorId, larkTransportEnabled } from './types.js';
143
- import { isRiffBackendSession } from './persistent-backend.js';
150
+ import { isRemoteBackendSession } from './persistent-backend.js';
144
151
  import { attachSkillPolicy, detachSkillPolicy } from './skills/im-command.js';
145
152
  import { readSkillRegistry } from '../services/skill-registry-store.js';
146
153
  import { isSessionGroup } from '../services/session-groups-store.js';
@@ -459,13 +466,40 @@ function closeUntrustedRequestAfterResponse(req, res) {
459
466
  let injectedIpcSecret = null;
460
467
  /** Test seam: override the secret used to verify token-route HMAC. */
461
468
  export function setIpcAuthSecret(secret) { injectedIpcSecret = secret; }
469
+ let loggedUnsafeIpcSecretAt = 0;
470
+ /**
471
+ * Load the machine-local dashboard secret used to verify token-route HMAC.
472
+ *
473
+ * Goes through {@link loadDashboardSecret} — the same strict host-authority
474
+ * reader the dashboard and daemon startup use — instead of a bare
475
+ * `readFileSync`: the leaf must be a regular 0600 file owned by the current
476
+ * user and must NOT be a symlink, and `~/.botmux` must not be
477
+ * group/other-writable. This is a per-request verifier on ~96 daemon IPC routes,
478
+ * so an attacker who can plant a symlink or loose-perms `.dashboard-secret` after
479
+ * boot must not have that content trusted as the HMAC key here (the dashboard
480
+ * caches its secret once at startup; this path re-reads every request, so it is
481
+ * the more exposed reader).
482
+ *
483
+ * Fail-closed either way: an unsafe shape returns `null` (→ nobody can sign →
484
+ * 401) rather than being followed. We log it — throttled, since this runs per
485
+ * request — so a planted/misconfigured credential is diagnosable instead of
486
+ * looking identical to "no secret on disk".
487
+ */
462
488
  function ipcAuthSecret() {
463
489
  if (injectedIpcSecret)
464
490
  return injectedIpcSecret;
465
491
  try {
466
- return readFileSync(dashboardSecretPath(), 'utf8').trim() || null;
492
+ return loadDashboardSecret(dashboardSecretPath());
467
493
  }
468
- catch {
494
+ catch (err) {
495
+ if (err instanceof UnsafeHostAuthorityFileError) {
496
+ const now = Date.now();
497
+ if (now - loggedUnsafeIpcSecretAt > 60_000) {
498
+ loggedUnsafeIpcSecretAt = now;
499
+ logger.error(`[dashboard-ipc] 拒绝使用不安全的 .dashboard-secret:${err.message}(IPC 鉴权 fail-closed)`);
500
+ }
501
+ return null;
502
+ }
469
503
  return null;
470
504
  }
471
505
  }
@@ -536,7 +570,7 @@ function routeHasNarrowUntrustedAuth(method, pathname) {
536
570
  // 该会话的 rotating per-turn
537
571
  // capability 并绑定到 URL 里的 sessionId(同 /api/asks 姿势)——capability 只
538
572
  // 证明「我是这个会话当前这一轮的 CLI」,选不了别的会话。
539
- if (method === 'POST' && /^\/api\/sessions\/[^/]+\/(?:slash|cd|close|chat-rename)$/.test(pathname))
573
+ if (method === 'POST' && /^\/api\/sessions\/[^/]+\/(?:slash|cd|close|preview|chat-rename)$/.test(pathname))
540
574
  return true;
541
575
  // UserPromptSubmit hook 的 envelope claim:沙箱内 hook 读不到 host secret,
542
576
  // 走 body 里的 per-turn capability;handler 内 sessionCliIpcAuth 绑定到 URL 的
@@ -903,7 +937,14 @@ ipcRoute('POST', '/api/sessions/:sessionId/close', async (req, res, params) => {
903
937
  // never clear a stale pre-drain snapshot while a turn is still preparing.
904
938
  const current = findSessionRecord(params.sessionId);
905
939
  if (current && current.status === 'closed') {
906
- return jsonRes(res, 200, { ok: true, alreadyClosed: true });
940
+ // A closed row can still carry an UNCANCELLED remote session (a quarantined
941
+ // lineage is parked, not cancelled). Short-circuiting to a bare success here
942
+ // meant a retry — or any client that lost the first response — could never
943
+ // learn about it, so replay the same outcome the close itself would report.
944
+ const residual = mojoCloseResidualForRow(current);
945
+ return jsonRes(res, 200, residual
946
+ ? { ok: true, outcome: 'closed_with_residual', residual, alreadyClosed: true }
947
+ : { ok: true, outcome: 'closed', alreadyClosed: true });
907
948
  }
908
949
  const r = await closeSession(params.sessionId);
909
950
  jsonRes(res, r.ok ? 200 : 502, r);
@@ -1017,14 +1058,16 @@ ipcRoute('POST', '/api/sessions/:sessionId/restart', async (_req, res, params) =
1017
1058
  if (ds.adoptedFrom || ds.initConfig?.adoptMode) {
1018
1059
  return jsonRes(res, 409, { ok: false, error: 'adopt_restart_unsupported' });
1019
1060
  }
1020
- // Riff owns a remote task lineage. Its worker deliberately refuses restart
1021
- // because destroy + respawn would sever or replace that lineage. Reject at
1022
- // the daemon boundary so the dashboard never reports HTTP 200 for a no-op.
1023
- if (isRiffBackendSession(ds)) {
1061
+ // Every REMOTE backend owns a remote lineage that destroy + respawn would
1062
+ // sever or replace (for mojo the worker restart actively cancels the remote
1063
+ // session and cold-boots a context-less replacement). Reject at the daemon
1064
+ // boundary so the dashboard never reports HTTP 200 for a lineage-destroying
1065
+ // restart.
1066
+ if (isRemoteBackendSession(ds)) {
1024
1067
  return jsonRes(res, 409, {
1025
1068
  ok: false,
1026
- error: 'riff_restart_unsupported',
1027
- message: t('cmd.restart.riff_unsupported', undefined, localeForBot(ds.larkAppId)),
1069
+ error: 'remote_restart_unsupported',
1070
+ message: t('cmd.restart.remote_unsupported', undefined, localeForBot(ds.larkAppId)),
1028
1071
  });
1029
1072
  }
1030
1073
  if (rejectProtectedSessionMutation(res, [ds]))
@@ -1035,7 +1078,7 @@ ipcRoute('POST', '/api/sessions/:sessionId/restart', async (_req, res, params) =
1035
1078
  // 捎带最新 per-bot env:dashboard 改完 env 后重启才真正生效(与 /restart 同逻辑)。
1036
1079
  try {
1037
1080
  ds.workerReady = false;
1038
- ds.worker.send({ type: 'restart', reason: 'operator', env: latestPerBotEnvForRestart(ds) });
1081
+ ds.worker.send({ type: 'restart', reason: 'operator', env: latestPerBotEnvForRestart(ds), model: latestModelForRespawn(ds) });
1039
1082
  }
1040
1083
  catch (err) {
1041
1084
  return jsonRes(res, 502, { ok: false, error: String(err) });
@@ -1053,6 +1096,57 @@ ipcRoute('POST', '/api/sessions/:sessionId/restart', async (_req, res, params) =
1053
1096
  jsonRes(res, 200, { ok: true, sessionId: params.sessionId, cliId, revived: true });
1054
1097
  });
1055
1098
  });
1099
+ /** Materialize a dormant active session for a local `botmux list` attach.
1100
+ * Unlike restart, this is idempotent when a live worker already exists: a Lark
1101
+ * message may race the local picker, and that race must never restart an active
1102
+ * turn. Empty input re-attaches/cold-resumes without creating a model turn. */
1103
+ ipcRoute('POST', '/api/sessions/:sessionId/wake', async (req, res, params) => {
1104
+ const initial = findActiveBySessionId(params.sessionId);
1105
+ if (!initial)
1106
+ return jsonRes(res, 404, { ok: false, error: 'session_not_active' });
1107
+ const acquireTimeoutMs = sessionWakeAcquireTimeoutMs(req.headers[SESSION_WAKE_DEADLINE_HEADER]);
1108
+ const mutation = await tryWithBotTurnMutation(initial.larkAppId, acquireTimeoutMs, () => {
1109
+ // A picker that exits aborts its fetch. If the request was queued behind an
1110
+ // admitted turn, never materialize the session after that caller is gone.
1111
+ if (req.aborted || res.destroyed)
1112
+ return;
1113
+ const ds = findActiveBySessionId(params.sessionId);
1114
+ if (!ds)
1115
+ return jsonRes(res, 404, { ok: false, error: 'session_not_active' });
1116
+ if (isSessionTransferring(ds)) {
1117
+ return jsonRes(res, 409, { ok: false, error: 'session_transferring' });
1118
+ }
1119
+ if (ds.adoptedFrom || ds.initConfig?.adoptMode) {
1120
+ return jsonRes(res, 409, { ok: false, error: 'adopt_wake_unsupported' });
1121
+ }
1122
+ // Every REMOTE backend (riff / mojo) owns a remote lineage that a local
1123
+ // forkWorker cold-boot would sever or replace — the same reason /restart
1124
+ // rejects them. A dormant remote session cold-resumes from its own lineage
1125
+ // on the next message, never from a picker-driven local wake.
1126
+ if (isRemoteBackendSession(ds)) {
1127
+ return jsonRes(res, 409, { ok: false, error: 'remote_wake_unsupported' });
1128
+ }
1129
+ if (rejectProtectedSessionMutation(res, [ds]))
1130
+ return;
1131
+ const cliId = ds.session.cliId ?? 'unknown';
1132
+ if (ds.worker && !ds.worker.killed) {
1133
+ return jsonRes(res, 200, {
1134
+ ok: true,
1135
+ sessionId: params.sessionId,
1136
+ cliId,
1137
+ woke: false,
1138
+ reason: 'already_running',
1139
+ });
1140
+ }
1141
+ if (!forkWorker(ds, '', ds.hasHistory)) {
1142
+ return jsonRes(res, 409, { ok: false, error: 'wake_refused' });
1143
+ }
1144
+ jsonRes(res, 200, { ok: true, sessionId: params.sessionId, cliId, woke: true });
1145
+ });
1146
+ if (!mutation.acquired && !res.destroyed) {
1147
+ jsonRes(res, 409, { ok: false, error: 'wake_mutation_timeout' });
1148
+ }
1149
+ });
1056
1150
  /** Manually suspend one active session: kill the worker + CLI/pane, session
1057
1151
  * stays active and cold-resumes from its transcript on the next message —
1058
1152
  * the same semantics the idle-worker sweeper applies over the live cap.
@@ -1223,6 +1317,164 @@ function sessionCliIpcAuth(req, ds, sessionId, body, opts = {}) {
1223
1317
  });
1224
1318
  return decision.ok ? { ok: true } : { ok: false, error: decision.error };
1225
1319
  }
1320
+ /**
1321
+ * P1-12:会话血缘的根 pid——「谁有资格持有预览端口」的起点。
1322
+ *
1323
+ * worker fork 出来的进程树覆盖 pty 后端;tmux / zellij / herdr 这类后端的 CLI 是复用
1324
+ * 器服务端的子进程、不在 worker 树下,所以 worker 通过私有 IPC 上报的 cliPid(以及
1325
+ * adopt 会话接管的那个 CLI pid)必须单独作根,否则这些后端会被误判成「来路不明」。
1326
+ */
1327
+ function previewOwnerPids(ds) {
1328
+ return [
1329
+ ds.worker?.pid,
1330
+ ds.localProcessAttestation?.cliPid,
1331
+ ds.session.pid,
1332
+ ds.adoptedFrom?.originalCliPid,
1333
+ ];
1334
+ }
1335
+ /** 当前权威代次。CAS 与 target 落盘都以它为准。 */
1336
+ function previewWorkerGeneration(ds) {
1337
+ return ds.workerGeneration ?? ds.session.workerGeneration ?? 0;
1338
+ }
1339
+ /** Register one reachable loopback Web service for the exact calling session.
1340
+ * This is the only route that can create preview routing state. An isolated CLI
1341
+ * enters through the narrow capability aperture; a trusted host call is still
1342
+ * path/port-bound by the outer daemon HMAC. The requested host is never DNS —
1343
+ * only literal IPv4/IPv6 loopback is accepted, and the daemon connects before
1344
+ * persisting the target. */
1345
+ ipcRoute('POST', '/api/sessions/:sessionId/preview', async (req, res, params) => {
1346
+ let body;
1347
+ try {
1348
+ body = await readJsonBody(req, 4_096);
1349
+ }
1350
+ catch (error) {
1351
+ return jsonRes(res, error instanceof JsonBodyTooLargeError ? 413 : 400, { ok: false, error: error instanceof JsonBodyTooLargeError ? 'body_too_large' : 'bad_json' });
1352
+ }
1353
+ const ds = findActiveBySessionId(params.sessionId);
1354
+ const auth = sessionCliIpcAuth(req, ds, params.sessionId, body);
1355
+ if (!auth.ok)
1356
+ return jsonRes(res, 403, { ok: false, error: auth.error });
1357
+ if (!ds)
1358
+ return jsonRes(res, 404, { ok: false, error: 'session_not_active' });
1359
+ // Riff 矩阵:远端 sandbox 的 Web 服务跑在远程主机上,daemon 这侧的 loopback 上
1360
+ // 永远不会有它的监听。明确回 `preview_unsupported`,不要让它落进
1361
+ // `preview_unreachable` 冒充「偶发故障」让 agent 反复重试。
1362
+ if (!previewBackendSupported(ds.initConfig?.backendType ?? ds.session.backendType)) {
1363
+ return jsonRes(res, 501, { ok: false, error: 'preview_unsupported' });
1364
+ }
1365
+ if (!isPreviewPort(body.port)) {
1366
+ return jsonRes(res, 400, { ok: false, error: 'invalid_port' });
1367
+ }
1368
+ if (body.host !== undefined && !isPreviewLoopbackHost(body.host)) {
1369
+ return jsonRes(res, 403, { ok: false, error: 'remote_host_forbidden' });
1370
+ }
1371
+ // P1-13:probe 是一次 await。鉴权发生在 await **之前**,而 await 期间这个会话可能
1372
+ // 已经被 close、被 refork、切了 CLI——那些路径都会推进代次并清掉 previewTarget。
1373
+ // 捕获本次请求看到的对象与代次,回填前做 CAS 复核,不一致就整条丢弃:否则一个属于
1374
+ // 上一代 CLI 的注册会被写进新一代(甚至已关闭)的会话里。
1375
+ const generationAtEntry = previewWorkerGeneration(ds);
1376
+ const workerAtEntry = ds.worker;
1377
+ // P1-3:previewTarget 自己也得进 CAS 锚点。上面那四件只覆盖「跨代次/跨生命周期」,
1378
+ // **同代次内的并发注册**不在它们的射程里:这条路由没有 per-session 串行化,agent
1379
+ // 完全可以 `botmux preview 3000 & botmux preview 4000 &`,或者在 stale 清理在途时
1380
+ // 重注册。而谁先落地由 probe 耗时决定,不是由请求先后决定——单 host 超时 750ms,
1381
+ // 不带 host 时 127.0.0.1 与 ::1 串行试,「A 慢一秒、B 快一毫秒」是常规而非极端。
1382
+ // 没有这一条,后 settle 的旧请求会无条件盖掉先落地的新值,两条 CLI 都打印
1383
+ // 「✓ Web 预览已注册」,实际生效的却是哪一个不确定。
1384
+ const previewAtEntry = ds.session.previewTarget;
1385
+ const probe = await probeSessionPreviewTarget({
1386
+ port: body.port,
1387
+ ...(isPreviewLoopbackHost(body.host) ? { host: body.host } : {}),
1388
+ ownerPids: previewOwnerPids(ds),
1389
+ workerGeneration: generationAtEntry,
1390
+ });
1391
+ if (!probe.ok) {
1392
+ if (probe.error === 'invalid_port') {
1393
+ return jsonRes(res, 400, { ok: false, error: 'invalid_port' });
1394
+ }
1395
+ if (probe.error === 'preview_owner_unverified') {
1396
+ // fail closed:有人在监听,但证明不了是本会话的进程(血缘外、procfs 不可读、
1397
+ // 非 Linux 平台)。宁可没有预览,也不给出一条指向不明进程的代理路由。
1398
+ return jsonRes(res, 422, {
1399
+ ok: false,
1400
+ error: 'preview_owner_unverified',
1401
+ ...(probe.reason ? { reason: probe.reason } : {}),
1402
+ });
1403
+ }
1404
+ return jsonRes(res, 422, { ok: false, error: 'preview_unreachable' });
1405
+ }
1406
+ const target = probe.target;
1407
+ const current = findActiveBySessionId(params.sessionId);
1408
+ const recheck = sessionCliIpcAuth(req, current, params.sessionId, body);
1409
+ if (current !== ds
1410
+ || ds.session.status === 'closed'
1411
+ || previewWorkerGeneration(ds) !== generationAtEntry
1412
+ || ds.worker !== workerAtEntry
1413
+ || !recheck.ok) {
1414
+ return jsonRes(res, 409, { ok: false, error: 'preview_generation_changed' });
1415
+ }
1416
+ // 引用比较即「我 await 期间有没有别人写过这个字段」:注册整体替换对象,清理写
1417
+ // undefined,两者都会改变引用。
1418
+ if (ds.session.previewTarget !== previewAtEntry) {
1419
+ return jsonRes(res, 409, { ok: false, error: 'preview_target_changed' });
1420
+ }
1421
+ const previous = ds.session.previewTarget;
1422
+ ds.session.previewTarget = target;
1423
+ try {
1424
+ sessionStore.updateSession(ds.session);
1425
+ }
1426
+ catch {
1427
+ ds.session.previewTarget = previous;
1428
+ return jsonRes(res, 500, { ok: false, error: 'preview_persist_failed' });
1429
+ }
1430
+ dashboardEventBus.publish({
1431
+ type: 'session.update',
1432
+ body: { sessionId: params.sessionId, patch: { previewTarget: target } },
1433
+ });
1434
+ return jsonRes(res, 200, {
1435
+ ok: true,
1436
+ preview: sessionPreviewDescriptor(params.sessionId, target),
1437
+ });
1438
+ });
1439
+ /**
1440
+ * P1-12/P1-13:作废一个会话的预览目标。
1441
+ *
1442
+ * 由中央 Dashboard 在**代理落地前**发现归属已变(端口换了进程持有)时调用:代理侧
1443
+ * 只有本机 procfs 的只读视角,改不了会话行,必须由持有会话的 daemon 来清字段 + 落盘
1444
+ * + 广播 `preview: null`。仅 trusted host / HMAC 可用;幂等——本来就没有目标时回 200。
1445
+ *
1446
+ * P1-3:`?expectedRegisteredAt=` 指名要作废的是哪一次注册。判定失效发生在代理进程,
1447
+ * 这条 DELETE 落地在 daemon 进程,中间隔着一次跨进程往返;那段窗口里会话完全可以合法
1448
+ * 地重注册一个新目标,无条件清空会把它一起抹掉(fail-closed 方向没错,但 agent 刚拿到
1449
+ * 的「✓ 已注册」会莫名其妙失效)。revision 不匹配时整条 no-op,回 `cleared: false`,
1450
+ * 幂等语义不变。不带参数时保持原来的无条件语义。
1451
+ */
1452
+ ipcRoute('DELETE', '/api/sessions/:sessionId/preview', (req, res, params) => {
1453
+ if (!isTrustedHostIpcRequest(req) && !ipcHmacAuthorized(req)) {
1454
+ return jsonRes(res, 401, { ok: false, error: 'unauthorized' });
1455
+ }
1456
+ const ds = findActiveBySessionId(params.sessionId);
1457
+ if (!ds)
1458
+ return jsonRes(res, 404, { ok: false, error: 'session_not_active' });
1459
+ const expectedRegisteredAt = new URL(req.url ?? '/', 'http://localhost')
1460
+ .searchParams.get('expectedRegisteredAt') ?? undefined;
1461
+ const cleared = clearSessionPreviewTarget(ds.session, 'listener ownership changed', expectedRegisteredAt);
1462
+ return jsonRes(res, 200, { ok: true, cleared });
1463
+ });
1464
+ /** Host-only daemon read API. It intentionally returns the browser-safe
1465
+ * descriptor, not the literal loopback host/port used inside daemon SSE. */
1466
+ ipcRoute('GET', '/api/sessions/:sessionId/preview', (req, res, params) => {
1467
+ if (!isTrustedHostIpcRequest(req) && !ipcHmacAuthorized(req)) {
1468
+ return jsonRes(res, 401, { ok: false, error: 'unauthorized' });
1469
+ }
1470
+ const ds = findActiveBySessionId(params.sessionId);
1471
+ if (!ds)
1472
+ return jsonRes(res, 404, { ok: false, error: 'session_not_active' });
1473
+ const preview = sessionPreviewDescriptor(params.sessionId, ds.session.previewTarget);
1474
+ if (!preview)
1475
+ return jsonRes(res, 404, { ok: false, error: 'preview_not_registered' });
1476
+ return jsonRes(res, 200, { ok: true, preview });
1477
+ });
1226
1478
  /** 向本会话 CLI 注入一条 allowlist 内的原生斜杠命令(idle 后生效)。
1227
1479
  * 鉴权双路径(见 sessionCliIpcAuth):trusted-host 签名或本会话 rotating
1228
1480
  * capability;命令面由 allowlist(默认空=全拒)承担。 */
@@ -1240,6 +1492,17 @@ ipcRoute('POST', '/api/sessions/:sessionId/slash', async (req, res, params) => {
1240
1492
  if (ds.adoptedFrom || ds.initConfig?.adoptMode) {
1241
1493
  return jsonRes(res, 409, { ok: false, error: 'adopt_inject_unsupported' });
1242
1494
  }
1495
+ // Remote backends (riff / mojo) have no TUI to inject a slash line into. For mojo
1496
+ // the injection does not no-op either: MojoBackend.write() starts a REAL remote
1497
+ // turn, and this IPC carries no credential snapshot (unlike message / raw_input),
1498
+ // so an allowlisted slash sent after a JWT rotation or clear would run the turn
1499
+ // on the worker's stale token. Refused rather than wired up: this is a TUI-only
1500
+ // channel, and the same reasoning already hides the PTY quick-action keys for
1501
+ // these backends.
1502
+ const injectFrozenType = ds.initConfig?.backendType ?? ds.session.backendType;
1503
+ if (injectFrozenType && isRemoteBackendType(injectFrozenType)) {
1504
+ return jsonRes(res, 409, { ok: false, error: 'remote_backend_inject_unsupported' });
1505
+ }
1243
1506
  if ((!ds.worker || ds.worker.killed) && !isSessionTransferring(ds)) {
1244
1507
  return jsonRes(res, 409, { ok: false, error: 'no_live_worker' });
1245
1508
  }
@@ -1363,14 +1626,17 @@ ipcRoute('POST', '/api/sessions/:sessionId/cd', async (req, res, params) => {
1363
1626
  if (ds.adoptedFrom || ds.initConfig?.adoptMode) {
1364
1627
  return jsonRes(res, 409, { ok: false, error: 'adopt_cd_unsupported' });
1365
1628
  }
1366
- // Riff restart/kill is intentionally refused to preserve remote task
1367
- // lineage. Reject before validation/repin so the persisted cwd cannot drift
1368
- // from the still-running sandbox.
1369
- if (isRiffBackendSession(ds)) {
1629
+ // Remote retirement (Riff AND Mojo) is intentionally refused without
1630
+ // prepare/commit, so a cold restart cannot follow a repin here. Reject
1631
+ // before validation/repin so the persisted cwd cannot drift from the
1632
+ // still-running remote lineage — mojo used to slip past the riff-only
1633
+ // guard, repin, and then killWorker's refusal left the live worker on the
1634
+ // old cwd while the route reported cold-restart (P1-a split brain).
1635
+ if (isRemoteBackendSession(ds)) {
1370
1636
  return jsonRes(res, 409, {
1371
1637
  ok: false,
1372
- error: 'riff_cd_unsupported',
1373
- message: t('cmd.cd.riff_unsupported', undefined, localeForBot(ds.larkAppId)),
1638
+ error: 'remote_cd_unsupported',
1639
+ message: t('cmd.cd.remote_unsupported', undefined, localeForBot(ds.larkAppId)),
1374
1640
  });
1375
1641
  }
1376
1642
  // ownAppId 收窄到本 bot 自己的角色库子树:不收窄就能切进别的 bot 的角色目录,
@@ -1404,7 +1670,7 @@ ipcRoute('POST', '/api/sessions/:sessionId/cd', async (req, res, params) => {
1404
1670
  // 陈旧的 lastInitConfig.workingDir(daemon 侧 initConfig 已在上面同步)。
1405
1671
  try {
1406
1672
  ds.workerReady = false;
1407
- ds.worker.send({ type: 'restart', updateWorkingDir: v.resolvedPath, env: latestPerBotEnvForRestart(ds) });
1673
+ ds.worker.send({ type: 'restart', updateWorkingDir: v.resolvedPath, env: latestPerBotEnvForRestart(ds), model: latestModelForRespawn(ds) });
1408
1674
  }
1409
1675
  catch {
1410
1676
  // send() 抛异常:worker 进程实际上已经不可达(管道已断),但 above 的
@@ -1549,7 +1815,15 @@ function buildAsyncTriggerLookupResponse(sessionId, triggerId) {
1549
1815
  sessionId,
1550
1816
  liveActive: !!ds,
1551
1817
  chatId: ds?.chatId ?? stored?.chatId,
1552
- memResult: memResult ? { status: memResult.status, content: memResult.content, completedAt: memResult.completedAt, usage: memResult.usage } : undefined,
1818
+ memResult: memResult ? {
1819
+ status: memResult.status,
1820
+ content: memResult.content,
1821
+ completedAt: memResult.completedAt,
1822
+ failedAt: memResult.failedAt,
1823
+ errorCode: memResult.errorCode,
1824
+ terminalErrorCode: memResult.terminalErrorCode,
1825
+ usage: memResult.usage,
1826
+ } : undefined,
1553
1827
  memTriggerId: memResult ? memTriggerId : undefined,
1554
1828
  persisted,
1555
1829
  storedStatus: stored ? (stored.status === 'closed' ? 'closed' : 'open') : undefined,
@@ -2061,6 +2335,33 @@ ipcRoute('GET', '/api/sessions/:sessionId/write-link', (req, res, params) => {
2061
2335
  return jsonRes(res, 409, { ok: false, error: 'terminal_unavailable' });
2062
2336
  jsonRes(res, 200, { ok: true, url: buildTerminalUrl(ds, { write: true }) });
2063
2337
  });
2338
+ /**
2339
+ * Read-only twin of write-link: the base capability URL the Feishu card's
2340
+ * 「打开 Web 终端」button also hands out (viewToken, never the write token).
2341
+ * The viewToken here is the worker's PER-BOOT card token — it dies with the
2342
+ * worker generation and is deliberately not bound to any dashboard auth
2343
+ * session. The central dashboard therefore REPLACES it with a short-lived
2344
+ * signed read grant bound to the requesting identity before answering its own
2345
+ * /api/sessions/:id/view-link (P1-5); this loopback-HMAC route never reaches a
2346
+ * browser directly. That grant is also PINNED to the boot generation derived
2347
+ * from this very token, so the value must be present and current — a live port
2348
+ * left over from a previous boot (persisted `session.webPort` outliving the
2349
+ * worker) is not enough. Same guard shape as write-link.
2350
+ *
2351
+ * Knowing any view capability never grants terminal input, so the link stays
2352
+ * read-only by construction rather than by UI convention.
2353
+ */
2354
+ ipcRoute('GET', '/api/sessions/:sessionId/view-link', (req, res, params) => {
2355
+ if (!ipcHmacAuthorized(req))
2356
+ return jsonRes(res, 401, { ok: false, error: 'unauthorized' });
2357
+ const ds = findActiveBySessionId(params.sessionId);
2358
+ if (!ds)
2359
+ return jsonRes(res, 404, { ok: false, error: 'session_not_active' });
2360
+ const port = ds.workerPort ?? ds.session.webPort;
2361
+ if (!port || !ds.workerViewToken)
2362
+ return jsonRes(res, 409, { ok: false, error: 'terminal_unavailable' });
2363
+ jsonRes(res, 200, { ok: true, url: buildTerminalUrl(ds) });
2364
+ });
2064
2365
  /**
2065
2366
  * Dashboard「复现命令」:返回该 active session 本次冷启的**近似**可复现 CLI 调用
2066
2367
  * (bin + argv + cwd + 权威注入 env),供用户粘到调试终端改参数复现。命令原样保留
@@ -2352,7 +2653,11 @@ ipcRoute('POST', '/api/sessions/:sessionId/locate', async (_req, res, params) =>
2352
2653
  return jsonRes(res, 200, { ok: false, error: 'no_feishu_transport' });
2353
2654
  }
2354
2655
  try {
2355
- const messageId = await replyMessage(ctx.larkAppId, ctx.rootMessageId, `<at user_id="${ctx.ownerOpenId}"></at>`, 'text', true);
2656
+ const messageId = await sendSessionOwnerThreadNotification({
2657
+ larkAppId: ctx.larkAppId,
2658
+ rootMessageId: ctx.rootMessageId,
2659
+ ownerOpenId: ctx.ownerOpenId,
2660
+ });
2356
2661
  jsonRes(res, 200, { ok: true, messageId });
2357
2662
  }
2358
2663
  catch (err) {
@@ -3489,6 +3794,9 @@ ipcRoute('GET', '/api/bot-default-oncall', async (_req, res) => {
3489
3794
  let wrapperCli = null;
3490
3795
  let model = null;
3491
3796
  let reasoningEffort = null;
3797
+ // dsh runner turn timeout (ms). Only meaningful for the dsh adapter; exposed
3798
+ // so the dashboard can render the dsh-only field with its current value.
3799
+ let turnTimeoutMs = null;
3492
3800
  let agentSelectionKey = '';
3493
3801
  try {
3494
3802
  const cfg = getBot(cachedLarkAppId).config;
@@ -3504,14 +3812,21 @@ ipcRoute('GET', '/api/bot-default-oncall', async (_req, res) => {
3504
3812
  wrapperCli = typeof cfg.wrapperCli === 'string' && cfg.wrapperCli.trim() ? cfg.wrapperCli : null;
3505
3813
  model = typeof cfg.model === 'string' && cfg.model.trim() ? cfg.model : null;
3506
3814
  reasoningEffort = cfg.reasoningEffort ?? null;
3815
+ turnTimeoutMs = typeof cfg.turnTimeoutMs === 'number'
3816
+ && Number.isInteger(cfg.turnTimeoutMs) && cfg.turnTimeoutMs > 0
3817
+ ? cfg.turnTimeoutMs
3818
+ : null;
3507
3819
  agentSelectionKey = selectionKeyForBot(cliId, wrapperCli ?? undefined);
3508
3820
  }
3509
3821
  catch { /* no registered bot */ }
3510
3822
  let maxLiveWorkers = null;
3823
+ let sessionOwnerReminder = DEFAULT_SESSION_OWNER_REMINDER;
3511
3824
  try {
3512
- const m = getBot(cachedLarkAppId).config.maxLiveWorkers;
3825
+ const botConfig = getBot(cachedLarkAppId).config;
3826
+ const m = botConfig.maxLiveWorkers;
3513
3827
  if (typeof m === 'number' && Number.isInteger(m) && m > 0)
3514
3828
  maxLiveWorkers = m;
3829
+ sessionOwnerReminder = botConfig.sessionOwnerReminder ?? DEFAULT_SESSION_OWNER_REMINDER;
3515
3830
  }
3516
3831
  catch { /* default unlimited */ }
3517
3832
  let logicalSessionCount = 0;
@@ -3592,6 +3907,7 @@ ipcRoute('GET', '/api/bot-default-oncall', async (_req, res) => {
3592
3907
  wrapperCli,
3593
3908
  model,
3594
3909
  reasoningEffort,
3910
+ turnTimeoutMs,
3595
3911
  agentSelectionKey,
3596
3912
  defaultOncall: defaultOncall ?? { enabled: false, workingDir: '', since: 0 },
3597
3913
  defaultWorkingDir,
@@ -3643,6 +3959,7 @@ ipcRoute('GET', '/api/bot-default-oncall', async (_req, res) => {
3643
3959
  // value when this bot has no explicit override (prompt/global/off).
3644
3960
  skillInjectionDefault: globalBuiltinSkillInjectionDefault(),
3645
3961
  maxLiveWorkers,
3962
+ sessionOwnerReminder,
3646
3963
  logicalSessionCount,
3647
3964
  residentSessionCount,
3648
3965
  dormantSessionCount,
@@ -3992,7 +4309,23 @@ ipcRoute('PUT', '/api/bot-agent', async (req, res) => {
3992
4309
  return jsonRes(res, 400, { ok: false, error: 'invalid_reasoning_effort' });
3993
4310
  }
3994
4311
  const currentBotConfig = getBot(larkAppId).config;
3995
- const supportsReasoningEffort = isCodexReasoningCliId(selected.cliId);
4312
+ const supportsReasoningEffort = isConfigurableReasoningCliId(selected.cliId);
4313
+ // Per-bot dsh runner turn timeout. Only the dsh adapter forwards it
4314
+ // (`--turn-timeout-ms`); the dashboard exposes the field for dsh only. The
4315
+ // field is optional in the body, so distinguish absent (preserve) from
4316
+ // present-but-empty (clear → runner default) like reasoningEffort does.
4317
+ const supportsTurnTimeout = selected.cliId === 'dsh';
4318
+ const turnTimeoutFieldPresent = Object.prototype.hasOwnProperty.call(body, 'turnTimeoutMs');
4319
+ let nextTurnTimeoutMs;
4320
+ if (turnTimeoutFieldPresent && body.turnTimeoutMs !== null && body.turnTimeoutMs !== '') {
4321
+ const n = Number(body.turnTimeoutMs);
4322
+ // Positive integer within the arm-able bound; reject anything else so an
4323
+ // over-bound value can't wrap to ~1ms in the runner's setTimeout.
4324
+ if (!Number.isInteger(n) || n <= 0 || n > MAX_TURN_TIMEOUT_MS) {
4325
+ return jsonRes(res, 400, { ok: false, error: 'invalid_turn_timeout_ms' });
4326
+ }
4327
+ nextTurnTimeoutMs = n;
4328
+ }
3996
4329
  const runtimeFieldPresent = Object.prototype.hasOwnProperty.call(body, 'cliRuntime');
3997
4330
  const currentSelectionKey = selectionKeyForBot(currentBotConfig.cliId, currentBotConfig.wrapperCli);
3998
4331
  const selectionChanged = key !== currentSelectionKey;
@@ -4090,7 +4423,7 @@ ipcRoute('PUT', '/api/bot-agent', async (req, res) => {
4090
4423
  const nextReasoningEffort = supportsReasoningEffort
4091
4424
  ? (reasoningEffortFieldPresent ? reasoningEffort ?? undefined : entry.reasoningEffort)
4092
4425
  : undefined;
4093
- if (nextReasoningEffort && !codexModelSupportsReasoningEffort(model || undefined, nextReasoningEffort)) {
4426
+ if (nextReasoningEffort && !cliModelSupportsReasoningEffort(selected.cliId, model || undefined, nextReasoningEffort)) {
4094
4427
  return { write: false, result: { error: 'reasoning_effort_not_supported_by_model' } };
4095
4428
  }
4096
4429
  entry.cliId = selected.cliId;
@@ -4124,19 +4457,31 @@ ipcRoute('PUT', '/api/bot-agent', async (req, res) => {
4124
4457
  else
4125
4458
  delete entry.reasoningEffort;
4126
4459
  }
4460
+ // dsh-only turn timeout: non-dsh always drops it; on dsh, an explicit
4461
+ // field value writes/clears it, absence preserves the current value.
4462
+ if (!supportsTurnTimeout)
4463
+ delete entry.turnTimeoutMs;
4464
+ else if (turnTimeoutFieldPresent) {
4465
+ if (nextTurnTimeoutMs !== undefined)
4466
+ entry.turnTimeoutMs = nextTurnTimeoutMs;
4467
+ else
4468
+ delete entry.turnTimeoutMs;
4469
+ }
4127
4470
  if (entry.readIsolation === true &&
4128
4471
  !readIsolationEnforceableFor({ cliId: selected.cliId, cliPathOverride: effectivePath, wrapperCli: selected.wrapperCli })) {
4129
4472
  delete entry.readIsolation;
4130
4473
  readIsolationCleared = true;
4131
4474
  }
4132
- // cliId=riff backendType 自动设为 riff(否则 spawn 走 pty 后端找不到本地二进制)。
4133
- if (selected.cliId === 'riff') {
4134
- entry.backendType = 'riff';
4475
+ // 远端 CLI(riff / mojo)→ backendType 自动设为同名后端(否则 spawn 走 pty 后端,
4476
+ // 而它们的 resolvedBin 是空串)。mojo 加入后这里必须按「是否远端」判断,不能再
4477
+ // 硬编码 riff
4478
+ if (isRemoteCliId(selected.cliId)) {
4479
+ entry.backendType = selected.cliId;
4135
4480
  }
4136
- else if (entry.backendType === 'riff') {
4137
- // riff 切回其它 CLI:清掉这个自动配对的 backend override,回落 daemon
4138
- // 默认后端——否则新 CLI 会跑在 RiffBackend 上(PTY 分块输入被当成一串 riff
4139
- // 任务)。手动的 pty/tmux/herdr/zellij override 不受影响(它们不会是 riff)。
4481
+ else if (entry.backendType && isRemoteBackendType(entry.backendType)) {
4482
+ // 从远端 CLI 切回其它 CLI:清掉这个自动配对的 backend override,回落 daemon
4483
+ // 默认后端——否则新 CLI 会跑在远端 Backend 上(PTY 分块输入被当成一串远端
4484
+ // turn)。手动的 pty/tmux/herdr/zellij override 不受影响(它们不是远端后端)。
4140
4485
  delete entry.backendType;
4141
4486
  }
4142
4487
  return { write: true, result: { nextReasoningEffort } };
@@ -4147,7 +4492,7 @@ ipcRoute('PUT', '/api/bot-agent', async (req, res) => {
4147
4492
  return jsonRes(res, 400, {
4148
4493
  ok: false,
4149
4494
  error: r.result.error,
4150
- message: `模型 ${model || '(Codex 默认模型)'} 不支持当前思考强度`,
4495
+ message: `模型 ${model || '(Agent 默认模型)'} 不支持当前思考强度`,
4151
4496
  });
4152
4497
  }
4153
4498
  const bot = getBot(larkAppId);
@@ -4163,12 +4508,18 @@ ipcRoute('PUT', '/api/bot-agent', async (req, res) => {
4163
4508
  bot.config.reasoningEffort = undefined;
4164
4509
  else
4165
4510
  bot.config.reasoningEffort = r.result.nextReasoningEffort ?? undefined;
4511
+ // Mirror the entry write: non-dsh clears it, dsh with an explicit field
4512
+ // takes the parsed value, dsh without the field preserves the existing one.
4513
+ if (!supportsTurnTimeout)
4514
+ bot.config.turnTimeoutMs = undefined;
4515
+ else if (turnTimeoutFieldPresent)
4516
+ bot.config.turnTimeoutMs = nextTurnTimeoutMs;
4166
4517
  if (readIsolationCleared)
4167
4518
  bot.config.readIsolation = false;
4168
- if (selected.cliId === 'riff') {
4169
- bot.config.backendType = 'riff';
4519
+ if (isRemoteCliId(selected.cliId)) {
4520
+ bot.config.backendType = selected.cliId;
4170
4521
  }
4171
- else if (bot.config.backendType === 'riff') {
4522
+ else if (bot.config.backendType && isRemoteBackendType(bot.config.backendType)) {
4172
4523
  bot.config.backendType = undefined;
4173
4524
  }
4174
4525
  // 热切后立刻清掉本 bot 名下失配的存量会话——否则它们冻结的旧 CLI 会被下一条
@@ -4183,8 +4534,15 @@ ipcRoute('PUT', '/api/bot-agent', async (req, res) => {
4183
4534
  wrapperCli: selected.wrapperCli ?? null,
4184
4535
  model: model || null,
4185
4536
  reasoningEffort: supportsReasoningEffort ? bot.config.reasoningEffort ?? null : null,
4537
+ turnTimeoutMs: supportsTurnTimeout ? bot.config.turnTimeoutMs ?? null : null,
4186
4538
  selectionKey,
4187
- closedMismatchedSessions,
4539
+ // Number kept for compatibility with an older dashboard bundle; the residual
4540
+ // count rides alongside so a hot CLI switch cannot silently strand a remote
4541
+ // session behind a plain "closed N". (mojo/riff sessions live off-box, so a
4542
+ // local row can close while the remote one survives.)
4543
+ closedMismatchedSessions: closedMismatchedSessions.closed,
4544
+ closedMismatchedResidual: closedMismatchedSessions.residual,
4545
+ closedMismatchedFailed: closedMismatchedSessions.failed,
4188
4546
  // Report the (possibly auto-cleared) read-isolation state + whether the new
4189
4547
  // agent can still enforce it, so the dashboard updates its toggle immediately
4190
4548
  // instead of showing a stale enabled/supported state until a full refetch.
@@ -4675,6 +5033,21 @@ ipcRoute('PUT', '/api/bot-max-live-workers', async (req, res) => {
4675
5033
  return jsonRes(res, 400, { ok: false, error: r.reason });
4676
5034
  jsonRes(res, 200, { ok: true, maxLiveWorkers: value });
4677
5035
  });
5036
+ ipcRoute('PUT', '/api/bot-session-owner-reminder', async (req, res) => {
5037
+ if (!cachedLarkAppId)
5038
+ return jsonRes(res, 503, { error: 'larkAppId_not_set' });
5039
+ let raw;
5040
+ try {
5041
+ raw = await readJsonBody(req);
5042
+ }
5043
+ catch {
5044
+ return jsonRes(res, 400, { ok: false, error: 'bad_json' });
5045
+ }
5046
+ const result = await updateSessionOwnerReminderConfig(cachedLarkAppId, raw);
5047
+ if (!result.ok)
5048
+ return jsonRes(res, 400, { ok: false, error: result.reason });
5049
+ return jsonRes(res, 200, { ok: true, sessionOwnerReminder: result.config });
5050
+ });
4678
5051
  // Per-bot skill policy. Dashboard uses this for attach/detach; JSON policy
4679
5052
  // still shares the same applyConfigField path as /botconfig.
4680
5053
  ipcRoute('PUT', '/api/bot-skills', async (req, res) => {