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
@@ -3,6 +3,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
3
  import { createPortal } from 'react-dom';
4
4
  import { openBotOnboarding } from './bot-onboarding.js';
5
5
  import { agentSelectionKey, cliIdOf, createRefreshGate, displayCliId, fallbackCliOptionsState, fetchBotDefaults, fetchCliOptions, fmtSince, modelSuggestionsForOption, resolveSubstituteTarget, selectedCliOption, } from './bot-defaults.js';
6
+ import { isRemoteCliId } from '../../core/remote-cli-ids.js';
6
7
  import { mountReactPage } from './react-mount.js';
7
8
  import { useT } from './react-hooks.js';
8
9
  import { store } from './store.js';
@@ -10,7 +11,7 @@ import { CreateActionButton, DropdownMenu, Html, InfoTip as BaseInfoTip, Loading
10
11
  import { botAvatarHtml, larkConsoleUrl, loadNameMaps, overrideBotAvatar, ui } from './ui.js';
11
12
  import { fetchGroupsSnapshot } from './groups-api.js';
12
13
  import { DEFAULT_GRANT_DURATION_MS, DEFAULT_GRANT_QUOTA, GRANT_DURATION_OPTIONS, MAX_GRANT_QUOTA, } from '../../services/grant-policy.js';
13
- import { codexReasoningEffortsForModel } from '../../services/codex-reasoning-effort.js';
14
+ import { reasoningEffortsForCliModel } from '../../services/codex-reasoning-effort.js';
14
15
  function runtimeDraftFromBot(bot) {
15
16
  const runtime = bot.cliRuntime;
16
17
  if (!runtime || typeof runtime !== 'object') {
@@ -176,6 +177,52 @@ export function BdTabGrid(props) {
176
177
  });
177
178
  return (_jsx("div", { ref: ref, className: props.className ? `bd-tab-grid ${props.className}` : 'bd-tab-grid', children: props.children }));
178
179
  }
180
+ /**
181
+ * Did this response come AFTER the irreversible agent-switch closes?
182
+ *
183
+ * Detected by the presence of the close-summary fields, deliberately NOT by
184
+ * enumerating error codes. The enumeration was the bug: the server grew a fourth
185
+ * post-close exit (`reasoning_effort_not_supported_by_model`) that carries the
186
+ * same summary, but the client only recognised the two it knew, so the surviving
187
+ * remote task ids were silently dropped and an operator had no handle to clean
188
+ * them up. Any future post-close exit is now rendered without touching this file.
189
+ */
190
+ function carriesAgentSwitchCloseSummary(body) {
191
+ if (!body || typeof body !== 'object')
192
+ return false;
193
+ const record = body;
194
+ return 'closedMismatchedSessions' in record
195
+ || 'closedMismatchedFailed' in record
196
+ || 'closedMismatchedResidual' in record
197
+ || 'closedMismatchedResidualTaskIds' in record;
198
+ }
199
+ function parseAgentSwitchSummary(body) {
200
+ const record = (body && typeof body === 'object' ? body : {});
201
+ const num = (v) => typeof v === 'number' && Number.isInteger(v) && v > 0 ? v : 0;
202
+ const closed = num(record.closedMismatchedSessions);
203
+ const failed = num(record.closedMismatchedFailed);
204
+ const residualCount = num(record.closedMismatchedResidual);
205
+ const rawIds = record.closedMismatchedResidualTaskIds;
206
+ const ids = Array.isArray(rawIds)
207
+ ? rawIds.map(id => (typeof id === 'string' && id.trim() ? id : 'unknown'))
208
+ : [];
209
+ const hasResidual = residualCount > 0 || ids.length > 0;
210
+ // A declared residual with no usable id must still be visible.
211
+ const residualIds = hasResidual && ids.length === 0 ? ['unknown'] : ids;
212
+ return {
213
+ closed,
214
+ failed,
215
+ residual: Math.max(residualCount, residualIds.length),
216
+ residualIds,
217
+ hasResidual,
218
+ };
219
+ }
220
+ /** Render residual remote ids; empty only when there is genuinely no residual. */
221
+ function residualIdText(summary, tr) {
222
+ if (summary.residualIds.length === 0)
223
+ return '';
224
+ return tr('botDefaults.agentResidualIds', { ids: summary.residualIds.join(', ') });
225
+ }
179
226
  function statusClass(status, extra = '') {
180
227
  const suffix = status ? ` ${status.ok ? 'hint-ok' : 'hint-warn-inline'}` : '';
181
228
  return `oncall-status${extra ? ` ${extra}` : ''}${suffix}`;
@@ -442,7 +489,7 @@ function BotDefaultsCard(props) {
442
489
  return (_jsxs("article", { className: "bd-card bd-profile", "data-appid": bot.larkAppId, children: [_jsxs("header", { className: "bd-profile-head", children: [_jsx(Html, { html: botAvatarHtml({ name, larkAppId: bot.larkAppId }) }), _jsxs("div", { className: "bd-profile-id", children: [_jsx("strong", { children: name }), _jsx("code", { children: bot.larkAppId })] })] }), _jsxs("p", { className: "hint-warn-inline", children: ["\u67E5\u8BE2\u5931\u8D25\uFF1A", bot.error] })] }));
443
490
  }
444
491
  const def = bot.defaultOncall ?? { enabled: false, workingDir: '', since: 0 };
445
- return (_jsxs("article", { className: "bd-card bd-profile", "data-appid": bot.larkAppId, children: [_jsxs("div", { className: "bd-profile-chrome", children: [_jsxs("header", { className: "bd-profile-head", children: [_jsx(BotAvatarControl, { bot: bot, name: name, patchBot: patchBot }), _jsx("div", { className: "bd-profile-main", children: _jsx(BotProfileIdentity, { bot: bot, cli: cli, patchBot: patchBot, meta: (_jsxs(_Fragment, { children: [_jsxs("small", { className: "bd-meta-ok", children: ["\u25CF ", tr('botDefaults.metaOnline')] }), (def.since ?? 0) > 0 ? _jsxs("small", { "data-oncall-since": true, children: [tr('botDefaults.lastEnabled'), ": ", fmtSince(def.since ?? 0)] }) : null, (bot.autoboundChatCount ?? 0) > 0 ? _jsx("small", { children: tr('botDefaults.autobound', { count: bot.autoboundChatCount ?? 0 }) }) : null] })) }) })] }), _jsx(BotDefaultsTabs, { active: props.activeTab, onChange: props.onTabChange })] }), _jsxs("div", { className: "bd-body bd-tab-panels", children: [_jsx("div", { id: "bd-panel-common", role: "tabpanel", "aria-labelledby": "bd-tab-common", className: "bd-tab-panel", hidden: props.activeTab !== 'common', children: _jsxs(BdTabGrid, { children: [_jsx("section", { className: "bd-tile", children: _jsx(BotAgentSection, { bot: bot, sessionFallback: cli, cliState: cliState, patchBot: patchBot }) }), _jsx("section", { className: "bd-tile", children: _jsx(WorkingDirSection, { bot: bot, patchBot: patchBot, putCardPref: putCardPref }) }), _jsx("section", { className: "bd-tile", children: _jsx(RoleSection, { bot: bot, patchBot: patchBot }) })] }) }), _jsx("div", { id: "bd-panel-sessions", role: "tabpanel", "aria-labelledby": "bd-tab-sessions", className: "bd-tab-panel", hidden: props.activeTab !== 'sessions', children: _jsxs(BdTabGrid, { children: [_jsx("section", { className: "bd-tile", children: _jsx(SessionModeSection, { bot: bot, patchBot: patchBot, putCardPref: putCardPref }) }), _jsx("section", { className: "bd-tile", children: _jsx(SubstituteModeSection, { bot: bot, patchBot: patchBot }) }), _jsx("section", { className: "bd-tile", children: _jsx(CrossBotSection, { bot: bot, putCardPref: putCardPref }) }), _jsx("section", { className: "bd-tile", children: _jsx(SessionCapSection, { bot: bot, patchBot: patchBot }) }), _jsx("section", { className: "bd-tile", children: _jsx(StartupCommandsSection, { bot: bot, patchBot: patchBot }) }), _jsx("section", { className: "bd-tile", children: _jsx(SummaryTriggerSection, { bot: bot, patchBot: patchBot, putCardPref: putCardPref }) })] }) }), _jsx("div", { id: "bd-panel-security", role: "tabpanel", "aria-labelledby": "bd-tab-security", className: "bd-tab-panel", hidden: props.activeTab !== 'security', children: _jsxs(BdTabGrid, { children: [bot.cliId !== 'riff' ? (_jsx("section", { className: "bd-tile", children: _jsx(SandboxSection, { bot: bot, patchBot: patchBot }) })) : null, bot.cliId !== 'riff' && bot.sandbox === true ? (_jsx("section", { className: "bd-tile bd-tile-wide", children: _jsx(SandboxPathsSection, { bot: bot, patchBot: patchBot }) })) : null, _jsx("section", { className: "bd-tile", children: _jsx(GrantSection, { bot: bot, patchBot: patchBot }) }), _jsx("section", { className: "bd-tile", children: _jsx(SlashCommandPermissionsSection, { bot: bot, patchBot: patchBot }) })] }) }), _jsx("div", { id: "bd-panel-cards", role: "tabpanel", "aria-labelledby": "bd-tab-cards", className: "bd-tab-panel", hidden: props.activeTab !== 'cards', children: _jsxs(BdTabGrid, { children: [_jsx("section", { className: "bd-tile bd-tile-wide", children: _jsx(CardBehaviorSection, { bot: bot, putCardPref: putCardPref }) }), _jsx("section", { className: "bd-tile bd-tile-wide", children: _jsx(FeedbackSettingsSection, { bot: bot, patchBot: patchBot }) }), _jsx("section", { className: "bd-tile", children: _jsx(BrandSection, { bot: bot, patchBot: patchBot }) })] }) }), _jsx("div", { id: "bd-panel-advanced", role: "tabpanel", "aria-labelledby": "bd-tab-advanced", className: "bd-tab-panel", hidden: props.activeTab !== 'advanced', children: _jsxs(BdTabGrid, { children: [bot.cliId !== 'riff' ? (_jsx("section", { className: "bd-tile", children: _jsx(BackendTypeSection, { bot: bot, patchBot: patchBot }) })) : null, bot.cliId === 'codex-app' ? (_jsx("section", { className: "bd-tile", children: _jsx(CodexAppDisplaySection, { bot: bot, putCardPref: putCardPref }) })) : null, bot.cliId === 'claude-code' ? (_jsx("section", { className: "bd-tile", children: _jsx(EnvelopeInjectionSection, { bot: bot, patchBot: patchBot }) })) : null, _jsx("section", { className: "bd-tile", children: _jsx(RuntimeEnvironmentSection, { bot: bot, patchBot: patchBot }) })] }) })] })] }));
492
+ return (_jsxs("article", { className: "bd-card bd-profile", "data-appid": bot.larkAppId, children: [_jsxs("div", { className: "bd-profile-chrome", children: [_jsxs("header", { className: "bd-profile-head", children: [_jsx(BotAvatarControl, { bot: bot, name: name, patchBot: patchBot }), _jsx("div", { className: "bd-profile-main", children: _jsx(BotProfileIdentity, { bot: bot, cli: cli, patchBot: patchBot, meta: (_jsxs(_Fragment, { children: [_jsxs("small", { className: "bd-meta-ok", children: ["\u25CF ", tr('botDefaults.metaOnline')] }), (def.since ?? 0) > 0 ? _jsxs("small", { "data-oncall-since": true, children: [tr('botDefaults.lastEnabled'), ": ", fmtSince(def.since ?? 0)] }) : null, (bot.autoboundChatCount ?? 0) > 0 ? _jsx("small", { children: tr('botDefaults.autobound', { count: bot.autoboundChatCount ?? 0 }) }) : null] })) }) })] }), _jsx(BotDefaultsTabs, { active: props.activeTab, onChange: props.onTabChange })] }), _jsxs("div", { className: "bd-body bd-tab-panels", children: [_jsx("div", { id: "bd-panel-common", role: "tabpanel", "aria-labelledby": "bd-tab-common", className: "bd-tab-panel", hidden: props.activeTab !== 'common', children: _jsxs(BdTabGrid, { children: [_jsx("section", { className: "bd-tile", children: _jsx(BotAgentSection, { bot: bot, sessionFallback: cli, cliState: cliState, patchBot: patchBot }) }), _jsx("section", { className: "bd-tile", children: _jsx(WorkingDirSection, { bot: bot, patchBot: patchBot, putCardPref: putCardPref }) }), _jsx("section", { className: "bd-tile", children: _jsx(RoleSection, { bot: bot, patchBot: patchBot }) })] }) }), _jsx("div", { id: "bd-panel-sessions", role: "tabpanel", "aria-labelledby": "bd-tab-sessions", className: "bd-tab-panel", hidden: props.activeTab !== 'sessions', children: _jsxs(BdTabGrid, { children: [_jsx("section", { className: "bd-tile", children: _jsx(SessionModeSection, { bot: bot, patchBot: patchBot, putCardPref: putCardPref }) }), _jsx("section", { className: "bd-tile", children: _jsx(SubstituteModeSection, { bot: bot, patchBot: patchBot }) }), _jsx("section", { className: "bd-tile", children: _jsx(CrossBotSection, { bot: bot, putCardPref: putCardPref }) }), _jsx("section", { className: "bd-tile", children: _jsx(SessionCapSection, { bot: bot, patchBot: patchBot }) }), _jsx("section", { className: "bd-tile", children: _jsx(StartupCommandsSection, { bot: bot, patchBot: patchBot }) }), _jsx("section", { className: "bd-tile", children: _jsx(SummaryTriggerSection, { bot: bot, patchBot: patchBot, putCardPref: putCardPref }) })] }) }), _jsx("div", { id: "bd-panel-security", role: "tabpanel", "aria-labelledby": "bd-tab-security", className: "bd-tab-panel", hidden: props.activeTab !== 'security', children: _jsxs(BdTabGrid, { children: [bot.cliId !== 'riff' ? (_jsx("section", { className: "bd-tile", children: _jsx(SandboxSection, { bot: bot, patchBot: patchBot }) })) : null, bot.cliId !== 'riff' && bot.sandbox === true ? (_jsx("section", { className: "bd-tile bd-tile-wide", children: _jsx(SandboxPathsSection, { bot: bot, patchBot: patchBot }) })) : null, _jsx("section", { className: "bd-tile", children: _jsx(GrantSection, { bot: bot, patchBot: patchBot }) }), _jsx("section", { className: "bd-tile", children: _jsx(SlashCommandPermissionsSection, { bot: bot, patchBot: patchBot }) })] }) }), _jsx("div", { id: "bd-panel-cards", role: "tabpanel", "aria-labelledby": "bd-tab-cards", className: "bd-tab-panel", hidden: props.activeTab !== 'cards', children: _jsxs(BdTabGrid, { children: [_jsx("section", { className: "bd-tile bd-tile-wide", children: _jsx(CardBehaviorSection, { bot: bot, putCardPref: putCardPref }) }), _jsx("section", { className: "bd-tile bd-tile-wide", children: _jsx(FeedbackSettingsSection, { bot: bot, patchBot: patchBot }) }), _jsx("section", { className: "bd-tile", children: _jsx(BrandSection, { bot: bot, patchBot: patchBot }) })] }) }), _jsx("div", { id: "bd-panel-advanced", role: "tabpanel", "aria-labelledby": "bd-tab-advanced", className: "bd-tab-panel", hidden: props.activeTab !== 'advanced', children: _jsxs(BdTabGrid, { children: [!isRemoteCliId(bot.cliId) ? (_jsx("section", { className: "bd-tile", children: _jsx(BackendTypeSection, { bot: bot, patchBot: patchBot }) })) : null, bot.cliId === 'codex-app' ? (_jsx("section", { className: "bd-tile", children: _jsx(CodexAppDisplaySection, { bot: bot, putCardPref: putCardPref }) })) : null, bot.cliId === 'claude-code' ? (_jsx("section", { className: "bd-tile", children: _jsx(EnvelopeInjectionSection, { bot: bot, patchBot: patchBot }) })) : null, _jsx("section", { className: "bd-tile", children: _jsx(RuntimeEnvironmentSection, { bot: bot, patchBot: patchBot }) }), _jsx("section", { className: "bd-tile", children: _jsx(SessionOwnerReminderSection, { bot: bot, patchBot: patchBot }) })] }) })] })] }));
446
493
  }
447
494
  function FeedbackSettingsSection(props) {
448
495
  const enabled = props.bot.feedback?.enabled === true;
@@ -514,12 +561,87 @@ function FeedbackSettingsSection(props) {
514
561
  setBusy(false);
515
562
  }
516
563
  }
517
- return (_jsxs("section", { className: "bd-section", "aria-busy": busy, children: [_jsx("h3", { className: "bd-section-title", children: "\u6700\u7EC8\u56DE\u7B54\u53CD\u9988" }), _jsx(ToggleRow, { checked: on, disabled: busy, title: "\u6700\u7EC8\u56DE\u7B54\u53CD\u9988", help: "\u9ED8\u8BA4\u5173\u95ED\uFF1B\u53EA\u5BF9\u8FD9\u4E2A bot \u7684\u6700\u7EC8\u56DE\u7B54\u751F\u6548", onChange: checked => { setOn(checked); void save(checked); } }), _jsxs("label", { className: "bd-row", children: [_jsx("span", { children: "\u9AD8\u7EA7 JSON" }), _jsx("textarea", { value: json, disabled: busy || !on, rows: 10, onChange: e => setJson(e.target.value) })] }), _jsxs("div", { className: "actions", children: [_jsx("button", { type: "button", className: "primary", disabled: busy || !on, onClick: () => void save(), children: "\u4FDD\u5B58\u53CD\u9988\u914D\u7F6E" }), _jsx(StatusSpan, { status: status })] }), _jsx("h4", { children: "\u6BCF\u804A\u5929\u8986\u76D6" }), _jsxs("label", { className: "bd-row", children: [_jsx("span", { children: "\u804A\u5929" }), _jsxs("select", { value: chatId, onChange: e => setChatId(e.target.value), children: [_jsx("option", { value: "", children: "\u9009\u62E9\u804A\u5929" }), chats.map(chat => _jsx("option", { value: chat.chatId, children: chat.name || chat.chatId }, chat.chatId))] })] }), _jsxs("div", { className: "actions", children: [_jsx("button", { type: "button", disabled: busy || !chatId.trim(), onClick: () => void saveChat(), children: "\u4FDD\u5B58\u804A\u5929\u8986\u76D6" }), _jsx("button", { type: "button", disabled: busy, onClick: () => void loadPreview(), children: "\u751F\u6548\u9884\u89C8" })] }), preview ? _jsx("pre", { className: "code-block", children: JSON.stringify(preview, null, 2) }) : null] }));
564
+ return (_jsxs("section", { className: "bd-section", "aria-busy": busy, children: [_jsx("h3", { className: "bd-section-title", children: _jsx(FieldTitle, { help: "\u5F00\u542F\u540E\uFF0C\u6700\u7EC8\u56DE\u7B54\u5361\u7247\u4F1A\u663E\u793A\u201C\u7ED3\u8BBA\u53EF\u7528 / \u6709\u6548\u63A8\u8FDB / \u7ED3\u8BBA\u6709\u8BEF\u201D\u7B49\u53CD\u9988\u6309\u94AE\uFF0C\u7528\u4E8E\u6536\u96C6\u56DE\u7B54\u8D28\u91CF\u8BC4\u4EF7\u3002\u9ED8\u8BA4\u5173\u95ED\uFF1B\u53EA\u5F71\u54CD\u8FD9\u4E2A bot \u7684\u6700\u7EC8\u56DE\u7B54\uFF0C\u4E0D\u5F71\u54CD\u8FC7\u7A0B\u6D88\u606F\u3002", children: "\u6700\u7EC8\u56DE\u7B54\u53CD\u9988" }) }), _jsx(ToggleRow, { checked: on, disabled: busy, title: "\u6700\u7EC8\u56DE\u7B54\u53CD\u9988", help: null, description: "\u5728\u6700\u7EC8\u56DE\u7B54\u5361\u7247\u4E2D\u6536\u96C6\u7528\u6237\u8BC4\u4EF7\u3002", onChange: checked => { setOn(checked); void save(checked); } }), _jsx(StatusSpan, { status: status }), on ? (_jsxs("details", { className: "bd-feedback-advanced", children: [_jsx("summary", { children: "\u9AD8\u7EA7\u914D\u7F6E\uFF08JSON \u4E0E\u804A\u5929\u8986\u76D6\uFF09" }), _jsxs("div", { className: "bd-feedback-advanced-body", children: [_jsxs("label", { className: "bd-row", children: [_jsx(FieldTitle, { help: "\u7528\u4E8E\u81EA\u5B9A\u4E49\u53CD\u9988\u6309\u94AE\u3001\u6587\u6848\u3001\u8D1F\u5411\u539F\u56E0\u548C\u662F\u5426\u5141\u8BB8\u6539\u9009\u3002\u4E0D\u4E86\u89E3 JSON \u914D\u7F6E\u65F6\u4FDD\u6301\u9ED8\u8BA4\u5373\u53EF\u3002", children: "\u9AD8\u7EA7 JSON" }), _jsx("textarea", { className: "bd-feedback-json", value: json, disabled: busy, rows: 6, onChange: e => setJson(e.target.value) })] }), _jsx("div", { className: "actions", children: _jsx("button", { type: "button", className: "primary", disabled: busy, onClick: () => void save(), children: "\u4FDD\u5B58\u53CD\u9988\u914D\u7F6E" }) }), _jsxs("div", { className: "bd-feedback-chat-override", children: [_jsx("h4", { children: _jsx(FieldTitle, { help: "\u8BA9\u540C\u4E00\u4E2A bot \u5728\u4E0D\u540C\u98DE\u4E66\u804A\u5929\u4E2D\u4F7F\u7528\u4E0D\u540C\u53CD\u9988\u89C4\u5219\uFF1B\u804A\u5929\u914D\u7F6E\u4F18\u5148\u4E8E bot \u9ED8\u8BA4\u914D\u7F6E\u3002\u53EA\u6709\u5404\u7FA4\u89C4\u5219\u4E0D\u540C\u65F6\u624D\u9700\u8981\u8BBE\u7F6E\u3002", children: "\u6BCF\u804A\u5929\u8986\u76D6" }) }), _jsx("p", { className: "hint", children: "\u4EC5\u5F53\u8FD9\u4E2A bot \u5728\u4E0D\u540C\u804A\u5929\u4E2D\u9700\u8981\u4E0D\u540C\u53CD\u9988\u89C4\u5219\u65F6\u8BBE\u7F6E\u3002" }), _jsxs("label", { className: "bd-row", children: [_jsx("span", { children: "\u804A\u5929" }), _jsxs("select", { value: chatId, onChange: e => { setChatId(e.target.value); setPreview(null); }, children: [_jsx("option", { value: "", children: "\u9009\u62E9\u804A\u5929" }), chats.map(chat => _jsx("option", { value: chat.chatId, children: chat.name || chat.chatId }, chat.chatId))] })] }), chatId.trim() ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "actions", children: [_jsx("button", { type: "button", disabled: busy, onClick: () => void saveChat(), children: "\u4FDD\u5B58\u804A\u5929\u8986\u76D6" }), _jsx("button", { type: "button", disabled: busy, onClick: () => void loadPreview(), children: "\u751F\u6548\u9884\u89C8" })] }), preview ? _jsx("pre", { className: "code-block", children: JSON.stringify(preview, null, 2) }) : null] })) : null] })] })] })) : null] }));
518
565
  }
519
566
  function RuntimeEnvironmentSection(props) {
520
567
  const tr = useT();
521
568
  return (_jsxs("section", { className: "bd-section bd-runtime-env", children: [_jsx("h3", { className: "bd-section-title", children: tr('botDefaults.sectionRuntimeEnv') }), _jsx(LaunchShellSection, { bot: props.bot, patchBot: props.patchBot }), _jsx(EnvSection, { bot: props.bot, patchBot: props.patchBot })] }));
522
569
  }
570
+ const OWNER_REMINDER_STATE_OPTIONS = [
571
+ { value: 'idle', labelKey: 'botDefaults.ownerReminderStateIdle' },
572
+ { value: 'dormant', labelKey: 'botDefaults.ownerReminderStateDormant' },
573
+ { value: 'pending_repo', labelKey: 'botDefaults.ownerReminderStatePendingRepo' },
574
+ { value: 'tui_prompt', labelKey: 'botDefaults.ownerReminderStateTuiPrompt' },
575
+ { value: 'agent_attention', labelKey: 'botDefaults.ownerReminderStateAgentAttention' },
576
+ { value: 'limited', labelKey: 'botDefaults.ownerReminderStateLimited' },
577
+ ];
578
+ // Offline/error rows can lack the daemon-provided default payload. Keep this
579
+ // browser fallback aligned with DEFAULT_SESSION_OWNER_REMINDER.
580
+ const DEFAULT_OWNER_REMINDER = {
581
+ enabled: false,
582
+ intervalMinutes: 30,
583
+ text: '该会话已等待处理,请继续跟进。',
584
+ states: OWNER_REMINDER_STATE_OPTIONS.map(option => option.value),
585
+ };
586
+ function SessionOwnerReminderSection(props) {
587
+ const tr = useT();
588
+ const initial = props.bot.sessionOwnerReminder ?? DEFAULT_OWNER_REMINDER;
589
+ const [enabled, setEnabled] = useState(initial.enabled === true);
590
+ const [interval, setIntervalValue] = useState(String(initial.intervalMinutes));
591
+ const [text, setText] = useState(initial.text);
592
+ const [states, setStates] = useState([...initial.states]);
593
+ const [status, setStatus] = useState(null);
594
+ const [busy, setBusy] = useState(false);
595
+ useEffect(() => {
596
+ const next = props.bot.sessionOwnerReminder ?? DEFAULT_OWNER_REMINDER;
597
+ setEnabled(next.enabled === true);
598
+ setIntervalValue(String(next.intervalMinutes));
599
+ setText(next.text);
600
+ setStates([...next.states]);
601
+ }, [props.bot.sessionOwnerReminder]);
602
+ function toggleState(state, checked) {
603
+ setStates(current => checked
604
+ ? (current.includes(state) ? current : [...current, state])
605
+ : current.filter(item => item !== state));
606
+ }
607
+ async function save() {
608
+ const minutes = Number(interval);
609
+ const cleanText = text.trim();
610
+ if (!Number.isInteger(minutes) || minutes < 1 || minutes > 10_080) {
611
+ setStatus({ text: `✗ ${tr('botDefaults.ownerReminderIntervalInvalid')}` });
612
+ return;
613
+ }
614
+ if (!cleanText || Array.from(cleanText).length > 500 || /<\s*at\b/i.test(cleanText)) {
615
+ setStatus({ text: `✗ ${tr('botDefaults.ownerReminderTextInvalid')}` });
616
+ return;
617
+ }
618
+ if (enabled && states.length === 0) {
619
+ setStatus({ text: `✗ ${tr('botDefaults.ownerReminderStatesInvalid')}` });
620
+ return;
621
+ }
622
+ setBusy(true);
623
+ setStatus(null);
624
+ try {
625
+ const payload = { enabled, intervalMinutes: minutes, text: cleanText, states };
626
+ const res = await sendJson('PUT', `/api/bots/${encodeURIComponent(props.bot.larkAppId)}/session-owner-reminder`, payload);
627
+ if (res.ok && res.body.ok) {
628
+ const next = res.body.sessionOwnerReminder ?? payload;
629
+ props.patchBot(props.bot.larkAppId, { sessionOwnerReminder: next });
630
+ setStatus({ text: `✓ ${tr('botDefaults.cardPrefSaved')}`, ok: true });
631
+ }
632
+ else {
633
+ setStatus({ text: `✗ ${responseErrorText(res)}` });
634
+ }
635
+ }
636
+ catch (error) {
637
+ setStatus({ text: `✗ ${caughtErrorText(error)}` });
638
+ }
639
+ finally {
640
+ setBusy(false);
641
+ }
642
+ }
643
+ return (_jsxs("section", { className: "bd-section bd-owner-reminder", children: [_jsx("h3", { className: "bd-section-title", children: _jsx(FieldTitle, { help: tr('botDefaults.ownerReminderHelp'), children: tr('botDefaults.ownerReminderTitle') }) }), _jsx(ToggleRow, { checked: enabled, disabled: busy, dataAction: "toggle-owner-reminder", title: tr('botDefaults.ownerReminderEnabled'), help: tr('botDefaults.ownerReminderEnabledHelp'), onChange: setEnabled }), _jsx("div", { className: "bd-row", children: _jsxs("label", { children: [_jsx("span", { children: tr('botDefaults.ownerReminderInterval') }), _jsx("input", { type: "number", min: 1, max: 10080, step: 1, "data-input": "ownerReminderInterval", value: interval, disabled: busy, onChange: event => setIntervalValue(event.currentTarget.value) })] }) }), _jsxs("div", { className: "bd-subsection", children: [_jsx("h4", { className: "bd-subsection-title", children: tr('botDefaults.ownerReminderStates') }), _jsx("div", { className: "bd-owner-reminder-states", children: OWNER_REMINDER_STATE_OPTIONS.map(option => (_jsxs("label", { children: [_jsx("input", { type: "checkbox", checked: states.includes(option.value), disabled: busy, onChange: event => toggleState(option.value, event.currentTarget.checked) }), _jsx("span", { children: tr(option.labelKey) })] }, option.value))) })] }), _jsx("div", { className: "bd-row", children: _jsxs("label", { children: [_jsx("span", { children: _jsx(FieldTitle, { help: tr('botDefaults.ownerReminderTextHelp'), children: tr('botDefaults.ownerReminderText') }) }), _jsx("textarea", { rows: 3, maxLength: 500, "data-input": "ownerReminderText", value: text, disabled: busy, onChange: event => setText(event.currentTarget.value) })] }) }), _jsxs("div", { className: "actions", children: [_jsx("button", { type: "button", className: "primary", "data-action": "save-owner-reminder", disabled: busy, onClick: () => void save(), children: tr('botDefaults.ownerReminderSave') }), _jsx(StatusSpan, { status: status, attr: { 'data-owner-reminder-status': '' } })] })] }));
644
+ }
523
645
  /** console 头像上传只实测过 512×512 PNG,前端统一归一化成这一形态再上传。 */
524
646
  const AVATAR_UPLOAD_SIDE = 512;
525
647
  /** 任意用户图片 → 512×512 PNG dataURL(短边 cover 裁剪居中)。 */
@@ -809,6 +931,13 @@ export function BotAgentSection(props) {
809
931
  const [cliSelectionTouched, setCliSelectionTouched] = useState(false);
810
932
  const [model, setModel] = useState(typeof bot.model === 'string' ? bot.model : '');
811
933
  const [reasoningEffort, setReasoningEffort] = useState(bot.reasoningEffort ?? '');
934
+ // dsh-only turn timeout, edited in minutes (bots.json stores ms). Empty = use
935
+ // the runner default (10 min). `touched` gates whether a save sends the field
936
+ // at all: an untouched field is omitted so the daemon preserves the exact
937
+ // stored ms (including legal non-whole-minute values) instead of clearing it.
938
+ const [turnTimeoutMin, setTurnTimeoutMin] = useState(turnTimeoutMinFromMs(bot.turnTimeoutMs));
939
+ const [turnTimeoutTouched, setTurnTimeoutTouched] = useState(false);
940
+ const [turnTimeoutError, setTurnTimeoutError] = useState(null);
812
941
  const [runtimeDraft, setRuntimeDraft] = useState(() => runtimeDraftFromBot(bot));
813
942
  const [runtimeTouched, setRuntimeTouched] = useState(false);
814
943
  const [runtimeStatus, setRuntimeStatus] = useState(null);
@@ -822,6 +951,9 @@ export function BotAgentSection(props) {
822
951
  setCliSelectionTouched(false);
823
952
  setModel(typeof bot.model === 'string' ? bot.model : '');
824
953
  setReasoningEffort(bot.reasoningEffort ?? '');
954
+ setTurnTimeoutMin(turnTimeoutMinFromMs(bot.turnTimeoutMs));
955
+ setTurnTimeoutTouched(false);
956
+ setTurnTimeoutError(null);
825
957
  setRuntimeDraft(runtimeDraftFromBot(bot));
826
958
  setRuntimeTouched(false);
827
959
  setSkillValue(skillInjectionResolved(bot));
@@ -831,6 +963,7 @@ export function BotAgentSection(props) {
831
963
  bot.larkAppId,
832
964
  bot.model,
833
965
  bot.reasoningEffort,
966
+ bot.turnTimeoutMs,
834
967
  runtimeConfigKey,
835
968
  bot.wrapperCli,
836
969
  bot.skillInjection,
@@ -913,25 +1046,64 @@ export function BotAgentSection(props) {
913
1046
  : { provider: runtimeDraft.updateProvider },
914
1047
  };
915
1048
  }
1049
+ // dsh-only turn timeout: validate the (touched) minutes input before saving
1050
+ // so an illegal value surfaces an inline error instead of silently clearing
1051
+ // the config. Untouched → omitted below so the daemon preserves the stored
1052
+ // ms exactly (including legal non-whole-minute values).
1053
+ let turnTimeoutField;
1054
+ if (cliKey === 'dsh' && turnTimeoutTouched) {
1055
+ const parsed = parseTurnTimeoutMinInput(turnTimeoutMin);
1056
+ if (parsed === 'invalid') {
1057
+ const text = tr('botDefaults.agentTurnTimeoutInvalid');
1058
+ setTurnTimeoutError(text);
1059
+ setAgentStatus({ text: `✗ ${text}` });
1060
+ return;
1061
+ }
1062
+ setTurnTimeoutError(null);
1063
+ turnTimeoutField = parsed; // number (minutes→ms) or '' (clear)
1064
+ }
916
1065
  setAgentBusy(true);
917
1066
  try {
918
1067
  const body = {
919
1068
  cliId: cliKey,
920
1069
  model,
921
- reasoningEffort: (cliKey === 'codex' || cliKey === 'codex-app' || cliKey.endsWith('-codex')) ? reasoningEffort : '',
1070
+ reasoningEffort: (cliKey === 'grok' || cliKey === 'codex' || cliKey === 'codex-app' || cliKey.endsWith('-codex')) ? reasoningEffort : '',
1071
+ // dsh-only: only send when the user actually edited the field. Omitting
1072
+ // it makes the daemon preserve the current value; non-dsh selections
1073
+ // never send it (the daemon drops any stored value for non-dsh CLIs).
1074
+ ...(cliKey === 'dsh' && turnTimeoutField !== undefined ? { turnTimeoutMs: turnTimeoutField } : {}),
922
1075
  ...(runtimeTouched ? { cliRuntime } : {}),
923
1076
  };
924
1077
  const res = await sendJson('PUT', `/api/bots/${encodeURIComponent(bot.larkAppId)}/agent`, body);
925
1078
  if (res.ok && res.body.ok) {
926
- const closedCount = Number.isInteger(res.body.closedMismatchedSessions) && res.body.closedMismatchedSessions > 0
927
- ? res.body.closedMismatchedSessions
928
- : 0;
929
- const closedText = closedCount > 0
930
- ? tr('botDefaults.agentClosedCount', { count: closedCount })
931
- : '';
1079
+ const summary = parseAgentSwitchSummary(res.body);
1080
+ const closedCount = summary.closed;
1081
+ const residualCount = summary.residual;
1082
+ const failedCount = summary.failed;
1083
+ // Localised, not hardcoded: this component is already tr()-driven, so a
1084
+ // raw Chinese string would reach an English dashboard.
1085
+ const notes = [
1086
+ closedCount > 0 ? tr('botDefaults.agentClosedCount', { count: closedCount }) : '',
1087
+ // Closed, but their remote sessions are still running.
1088
+ residualCount > 0 ? tr('botDefaults.agentClosedResidual', { count: residualCount }) : '',
1089
+ // Not closed at all — the rows are still active.
1090
+ failedCount > 0 ? tr('botDefaults.agentCloseFailed', { count: failedCount }) : '',
1091
+ // The ids are the ONLY handle for manual cleanup; a count alone is not
1092
+ // actionable. Malformed/blank entries render as `unknown` rather than
1093
+ // silently disappearing.
1094
+ residualIdText(summary, tr),
1095
+ ].filter(Boolean);
1096
+ const closedText = notes.join(' · ');
1097
+ // `hasResidual` (count OR ids), not the count alone — a payload carrying
1098
+ // only ids must still lose the green tick.
1099
+ const hadProblem = summary.hasResidual || failedCount > 0;
932
1100
  setAgentStatus(res.body.availabilityWarning
933
1101
  ? { text: `⚠️ ${res.body.availabilityWarning}${closedText ? ` · ${closedText}` : ''}` }
934
- : { text: `✓ ${closedText || tr('botDefaults.agentSaved')}`, ok: true });
1102
+ : hadProblem
1103
+ // Never the green tick when a session is still active or a remote
1104
+ // session survived: that is what made this invisible.
1105
+ ? { text: `⚠️ ${closedText}` }
1106
+ : { text: `✓ ${closedText || tr('botDefaults.agentSaved')}`, ok: true });
935
1107
  patchBot(bot.larkAppId, {
936
1108
  cliId: res.body.cliId,
937
1109
  cliRuntime: res.body.cliRuntime === undefined
@@ -943,8 +1115,14 @@ export function BotAgentSection(props) {
943
1115
  wrapperCli: res.body.wrapperCli ?? null,
944
1116
  model: res.body.model ?? '',
945
1117
  reasoningEffort: res.body.reasoningEffort ?? undefined,
1118
+ turnTimeoutMs: typeof res.body.turnTimeoutMs === 'number' ? res.body.turnTimeoutMs : undefined,
946
1119
  agentSelectionKey: res.body.selectionKey ?? cliKey,
947
1120
  });
1121
+ // Re-sync the minutes input from the authoritative saved ms and clear
1122
+ // the dirty flag so a subsequent unrelated save won't touch the field.
1123
+ setTurnTimeoutMin(turnTimeoutMinFromMs(typeof res.body.turnTimeoutMs === 'number' ? res.body.turnTimeoutMs : undefined));
1124
+ setTurnTimeoutTouched(false);
1125
+ setTurnTimeoutError(null);
948
1126
  setRuntimeTouched(false);
949
1127
  if (cliRuntime) {
950
1128
  const probe = res.body.runtimeProbe;
@@ -963,9 +1141,25 @@ export function BotAgentSection(props) {
963
1141
  }
964
1142
  }
965
1143
  else {
966
- const detail = typeof res.body?.message === 'string' && res.body.message
967
- ? res.body.message
968
- : responseErrorText(res);
1144
+ // The switch transaction refused: say what actually happened rather than
1145
+ // surfacing a bare error code — the config is unchanged, some rows closed,
1146
+ // and some remote sessions may need manual cleanup.
1147
+ // ANY post-close exit, detected by the summary fields rather than a list of
1148
+ // error codes — see carriesAgentSwitchCloseSummary. Some rows are closed
1149
+ // and their remote ids are only ever reported here.
1150
+ const aborted = carriesAgentSwitchCloseSummary(res.body);
1151
+ const abortSummary = parseAgentSwitchSummary(res.body);
1152
+ const detail = aborted
1153
+ ? [
1154
+ tr('botDefaults.agentSwitchAborted', {
1155
+ closed: abortSummary.closed,
1156
+ failed: abortSummary.failed,
1157
+ }),
1158
+ residualIdText(abortSummary, tr),
1159
+ ].filter(Boolean).join(' · ')
1160
+ : typeof res.body?.message === 'string' && res.body.message
1161
+ ? res.body.message
1162
+ : responseErrorText(res);
969
1163
  const text = `✗ ${detail}`;
970
1164
  setAgentStatus({ text });
971
1165
  if (cliKey === 'codex' && runtimeDraft.mode === 'custom')
@@ -989,11 +1183,19 @@ export function BotAgentSection(props) {
989
1183
  * reach PUT /agent — the bot would stay on its old CLI and backendType
990
1184
  * would never auto-flip to riff. Returns false when persisting failed.
991
1185
  */
1186
+ /**
1187
+ * Riff's save reuses PUT /agent, so it inherits the SAME close transaction —
1188
+ * including a residual (rows closed, remote still running) and an aborted
1189
+ * switch. It must return that to the caller instead of a bare boolean:
1190
+ * `setAgentStatus` is rendered in the `!isRiff` branch, so anything written
1191
+ * there while Riff is selected is invisible.
1192
+ */
992
1193
  async function persistRiffCliSelection() {
993
1194
  if (bot.cliId === 'riff')
994
- return true; // already persisted
1195
+ return { ok: true, hadProblem: false, note: '' };
995
1196
  try {
996
1197
  const res = await sendJson('PUT', `/api/bots/${encodeURIComponent(bot.larkAppId)}/agent`, { cliId: 'riff', model: '' });
1198
+ const summary = parseAgentSwitchSummary(res.body);
997
1199
  if (res.ok && res.body.ok) {
998
1200
  patchBot(bot.larkAppId, {
999
1201
  cliId: res.body.cliId,
@@ -1002,14 +1204,28 @@ export function BotAgentSection(props) {
1002
1204
  model: res.body.model ?? '',
1003
1205
  agentSelectionKey: res.body.selectionKey ?? 'riff',
1004
1206
  });
1005
- return true;
1006
- }
1007
- setAgentStatus({ text: `✗ ${responseErrorText(res)}` });
1008
- return false;
1207
+ const note = [
1208
+ summary.residual > 0 ? tr('botDefaults.agentClosedResidual', { count: summary.residual }) : '',
1209
+ residualIdText(summary, tr),
1210
+ ].filter(Boolean).join(' · ');
1211
+ return { ok: true, hadProblem: summary.hasResidual, note };
1212
+ }
1213
+ // Aborted switch (close refused, or commit failed after closes ran): the
1214
+ // config did NOT change and some remote sessions may need manual cleanup.
1215
+ const aborted = carriesAgentSwitchCloseSummary(res.body);
1216
+ const note = aborted
1217
+ ? [
1218
+ // Riff-specific wording: by this point the /riff write already
1219
+ // succeeded, so "config unchanged" would be false here — only the
1220
+ // Agent selection failed to switch.
1221
+ tr('botDefaults.riffAgentSwitchAborted', { closed: summary.closed, failed: summary.failed }),
1222
+ residualIdText(summary, tr),
1223
+ ].filter(Boolean).join(' · ')
1224
+ : responseErrorText(res);
1225
+ return { ok: false, hadProblem: true, note };
1009
1226
  }
1010
1227
  catch (e) {
1011
- setAgentStatus({ text: `✗ ${caughtErrorText(e)}` });
1012
- return false;
1228
+ return { ok: false, hadProblem: true, note: caughtErrorText(e) };
1013
1229
  }
1014
1230
  }
1015
1231
  async function saveSkillInjection(next) {
@@ -1036,7 +1252,10 @@ export function BotAgentSection(props) {
1036
1252
  const siSupport = bot.skillInjectionSupport === 'dynamic' ? 'dynamic' : bot.skillInjectionSupport === 'global' ? 'global' : 'none';
1037
1253
  const isRiff = cliKey === 'riff';
1038
1254
  const isCodexSelection = cliKey === 'codex' || cliKey === 'codex-app' || cliKey.endsWith('-codex');
1039
- const reasoningEffortOptions = useMemo(() => codexReasoningEffortsForModel(model), [model]);
1255
+ const isReasoningSelection = isCodexSelection || cliKey === 'grok';
1256
+ // The dsh adapter is the only one that forwards a runner turn timeout.
1257
+ const isDsh = cliKey === 'dsh';
1258
+ const reasoningEffortOptions = useMemo(() => reasoningEffortsForCliModel(cliKey === 'grok' ? 'grok' : isCodexSelection ? 'codex' : undefined, model), [cliKey, isCodexSelection, model]);
1040
1259
  useEffect(() => {
1041
1260
  if (reasoningEffort && !reasoningEffortOptions.includes(reasoningEffort))
1042
1261
  setReasoningEffort('');
@@ -1075,14 +1294,77 @@ export function BotAgentSection(props) {
1075
1294
  ? 'botDefaults.runtimeOfficialNote'
1076
1295
  : runtimeDraft.mode === 'legacy'
1077
1296
  ? 'botDefaults.runtimeLegacyNote'
1078
- : 'botDefaults.runtimeCustomNote') }), runtimeDraft.mode === 'legacy' ? (_jsx("div", { className: "bd-runtime-fields", "data-runtime-legacy": "", children: _jsxs("label", { className: "bd-runtime-wide", children: [_jsx("span", { children: tr('botDefaults.runtimeLegacyPath') }), _jsx("input", { type: "text", value: runtimeDraft.legacyPath, readOnly: true, "aria-readonly": "true", "data-input": "agentRuntimeLegacyPath" })] }) })) : null, runtimeDraft.mode === 'custom' ? (_jsxs("div", { className: "bd-runtime-fields", children: [_jsxs("label", { children: [_jsx(FieldTitle, { help: tr('botDefaults.runtimeIdHelp'), children: tr('botDefaults.runtimeId') }), _jsx("input", { type: "text", "data-input": "agentRuntimeId", value: runtimeDraft.id, disabled: agentBusy, autoComplete: "off", onChange: event => updateRuntimeDraft({ id: event.currentTarget.value }) })] }), _jsxs("label", { children: [_jsx("span", { children: tr('botDefaults.runtimeDisplayName') }), _jsx("input", { type: "text", "data-input": "agentRuntimeDisplayName", placeholder: tr('botDefaults.runtimeDisplayNamePlaceholder'), value: runtimeDraft.displayName, disabled: agentBusy, autoComplete: "off", onChange: event => updateRuntimeDraft({ displayName: event.currentTarget.value }) })] }), _jsxs("label", { className: "bd-runtime-wide", children: [_jsx(FieldTitle, { help: tr('botDefaults.runtimeExecutableHelp'), children: tr('botDefaults.runtimeExecutable') }), _jsx("input", { type: "text", "data-input": "agentRuntimeExecutable", value: runtimeDraft.executable, disabled: agentBusy, autoCapitalize: "none", autoComplete: "off", spellCheck: false, onChange: event => updateRuntimeDraft({ executable: event.currentTarget.value }) })] }), _jsxs("div", { className: "bd-field", children: [_jsx("span", { children: tr('botDefaults.runtimeUpdateProvider') }), _jsx(DropdownField, { dataInput: "agentRuntimeUpdateProvider", ariaLabel: tr('botDefaults.runtimeUpdateProvider'), value: runtimeDraft.updateProvider, disabled: agentBusy, options: runtimeProviderOptions, onChange: updateProvider => updateRuntimeDraft({ updateProvider }) })] }), runtimeDraft.updateProvider === 'npm' ? (_jsxs("label", { children: [_jsx(FieldTitle, { help: tr('botDefaults.runtimePackageHelp'), children: tr('botDefaults.runtimePackageName') }), _jsx("input", { type: "text", "data-input": "agentRuntimePackageName", value: runtimeDraft.packageName, disabled: agentBusy, autoCapitalize: "none", autoComplete: "off", spellCheck: false, onChange: event => updateRuntimeDraft({ packageName: event.currentTarget.value }) })] })) : null] })) : null, _jsx(StatusSpan, { status: runtimeStatus, attr: { 'data-runtime-status': '' } })] })) : null, !isRiff && (_jsx("div", { className: "bd-row", children: _jsxs("label", { children: [_jsx(FieldTitle, { help: tr('botDefaults.agentHelp'), children: tr('botDefaults.agentModel') }), _jsx("input", { type: "text", "data-input": "agentModel", list: `agent-model-suggestions-${bot.larkAppId}`, placeholder: modelPlaceholder, value: model, disabled: agentBusy || modelDisabledByCli, onChange: event => setModel(event.currentTarget.value) }), _jsx("datalist", { id: `agent-model-suggestions-${bot.larkAppId}`, children: suggestions.map(item => _jsx("option", { value: item }, item)) })] }) })), isCodexSelection && (_jsx("div", { className: "bd-row", children: _jsxs("div", { className: "bd-field", children: [_jsx(FieldTitle, { help: tr('botDefaults.agentReasoningEffortHelp'), children: tr('botDefaults.agentReasoningEffort') }), _jsx(DropdownField, { dataInput: "agentReasoningEffort", ariaLabel: tr('botDefaults.agentReasoningEffort'), value: reasoningEffort, disabled: agentBusy, options: [
1079
- { value: '', label: tr('botDefaults.agentReasoningEffortDefault') },
1297
+ : 'botDefaults.runtimeCustomNote') }), runtimeDraft.mode === 'legacy' ? (_jsx("div", { className: "bd-runtime-fields", "data-runtime-legacy": "", children: _jsxs("label", { className: "bd-runtime-wide", children: [_jsx("span", { children: tr('botDefaults.runtimeLegacyPath') }), _jsx("input", { type: "text", value: runtimeDraft.legacyPath, readOnly: true, "aria-readonly": "true", "data-input": "agentRuntimeLegacyPath" })] }) })) : null, runtimeDraft.mode === 'custom' ? (_jsxs("div", { className: "bd-runtime-fields", children: [_jsxs("label", { children: [_jsx(FieldTitle, { help: tr('botDefaults.runtimeIdHelp'), children: tr('botDefaults.runtimeId') }), _jsx("input", { type: "text", "data-input": "agentRuntimeId", value: runtimeDraft.id, disabled: agentBusy, autoComplete: "off", onChange: event => updateRuntimeDraft({ id: event.currentTarget.value }) })] }), _jsxs("label", { children: [_jsx("span", { children: tr('botDefaults.runtimeDisplayName') }), _jsx("input", { type: "text", "data-input": "agentRuntimeDisplayName", placeholder: tr('botDefaults.runtimeDisplayNamePlaceholder'), value: runtimeDraft.displayName, disabled: agentBusy, autoComplete: "off", onChange: event => updateRuntimeDraft({ displayName: event.currentTarget.value }) })] }), _jsxs("label", { className: "bd-runtime-wide", children: [_jsx(FieldTitle, { help: tr('botDefaults.runtimeExecutableHelp'), children: tr('botDefaults.runtimeExecutable') }), _jsx("input", { type: "text", "data-input": "agentRuntimeExecutable", value: runtimeDraft.executable, disabled: agentBusy, autoCapitalize: "none", autoComplete: "off", spellCheck: false, onChange: event => updateRuntimeDraft({ executable: event.currentTarget.value }) })] }), _jsxs("div", { className: "bd-field", children: [_jsx("span", { children: tr('botDefaults.runtimeUpdateProvider') }), _jsx(DropdownField, { dataInput: "agentRuntimeUpdateProvider", ariaLabel: tr('botDefaults.runtimeUpdateProvider'), value: runtimeDraft.updateProvider, disabled: agentBusy, options: runtimeProviderOptions, onChange: updateProvider => updateRuntimeDraft({ updateProvider }) })] }), runtimeDraft.updateProvider === 'npm' ? (_jsxs("label", { children: [_jsx(FieldTitle, { help: tr('botDefaults.runtimePackageHelp'), children: tr('botDefaults.runtimePackageName') }), _jsx("input", { type: "text", "data-input": "agentRuntimePackageName", value: runtimeDraft.packageName, disabled: agentBusy, autoCapitalize: "none", autoComplete: "off", spellCheck: false, onChange: event => updateRuntimeDraft({ packageName: event.currentTarget.value }) })] })) : null] })) : null, _jsx(StatusSpan, { status: runtimeStatus, attr: { 'data-runtime-status': '' } })] })) : null, !isRiff && (_jsx("div", { className: "bd-row", children: _jsxs("label", { children: [_jsx(FieldTitle, { help: tr('botDefaults.agentHelp'), children: tr('botDefaults.agentModel') }), _jsx("input", { type: "text", "data-input": "agentModel", list: `agent-model-suggestions-${bot.larkAppId}`, placeholder: modelPlaceholder, value: model, disabled: agentBusy || modelDisabledByCli, onChange: event => setModel(event.currentTarget.value) }), _jsx("datalist", { id: `agent-model-suggestions-${bot.larkAppId}`, children: suggestions.map(item => _jsx("option", { value: item }, item)) })] }) })), isDsh && (_jsx("div", { className: "bd-row", children: _jsxs("label", { children: [_jsx(FieldTitle, { help: tr('botDefaults.agentTurnTimeoutHelp'), children: tr('botDefaults.agentTurnTimeout') }), _jsx("input", { type: "number", min: 0,
1298
+ // Allow non-whole minutes so a legal non-60000-multiple ms value
1299
+ // (e.g. 90001ms ≈ 1.50002min) can be shown and edited losslessly.
1300
+ step: "any", inputMode: "decimal", "data-input": "agentTurnTimeout", placeholder: tr('botDefaults.agentTurnTimeoutPlaceholder'), value: turnTimeoutMin, disabled: agentBusy, onChange: event => {
1301
+ setTurnTimeoutMin(event.currentTarget.value);
1302
+ setTurnTimeoutTouched(true);
1303
+ setTurnTimeoutError(null);
1304
+ } }), turnTimeoutError ? _jsx("small", { className: "hint-warn", "data-turn-timeout-error": "", children: turnTimeoutError }) : null] }) })), isReasoningSelection && (_jsx("div", { className: "bd-row", children: _jsxs("div", { className: "bd-field", children: [_jsx(FieldTitle, { help: tr('botDefaults.agentReasoningEffortHelp'), children: tr('botDefaults.agentReasoningEffort') }), _jsx(DropdownField, { dataInput: "agentReasoningEffort", ariaLabel: tr('botDefaults.agentReasoningEffort'), value: reasoningEffort, disabled: agentBusy, options: [
1305
+ {
1306
+ value: '',
1307
+ label: tr(cliKey === 'grok'
1308
+ ? 'botDefaults.agentReasoningEffortDefaultGrok'
1309
+ : isCodexSelection
1310
+ ? 'botDefaults.agentReasoningEffortDefaultCodex'
1311
+ : 'botDefaults.agentReasoningEffortDefault'),
1312
+ },
1080
1313
  ...reasoningEffortOptions.map(value => ({
1081
1314
  value,
1082
1315
  label: tr(`botDefaults.agentReasoningEffort${value === 'xhigh' ? 'Xhigh' : value[0].toUpperCase() + value.slice(1)}`),
1083
1316
  })),
1084
1317
  ], onChange: next => setReasoningEffort(next) })] }) })), isRiff && _jsx(RiffSection, { bot: bot, patchBot: patchBot, persistCliSelection: persistRiffCliSelection }), !isRiff && siSupport === 'dynamic' ? (_jsx("div", { className: "bd-row", children: _jsxs("div", { className: "bd-field", children: [_jsx(FieldTitle, { help: tr('botDefaults.skillInjectionHelpDynamic'), children: tr('botDefaults.skillInjection') }), _jsx(DropdownField, { dataInput: "skillInjection", ariaLabel: tr('botDefaults.skillInjection'), value: "dynamic", disabled: true, options: dynamicSkillOptions, onChange: () => undefined })] }) })) : !isRiff && siSupport === 'global' ? (_jsxs("div", { className: "bd-row", children: [_jsxs("div", { className: "bd-field", children: [_jsx(FieldTitle, { help: tr('botDefaults.skillInjectionHelp'), children: tr('botDefaults.skillInjection') }), _jsx(DropdownField, { dataInput: "skillInjection", ariaLabel: tr('botDefaults.skillInjection'), value: skillValue, disabled: skillBusy, options: skillOptions, onChange: next => void saveSkillInjection(next) })] }), _jsx("div", { className: "actions", children: _jsx(StatusSpan, { status: skillStatus, attr: { 'data-skill-injection-status': '' } }) })] })) : null, !isRiff && (_jsxs("div", { className: "actions bd-section-actions", children: [_jsx("button", { type: "button", className: "primary", "data-action": "save-agent", disabled: agentBusy, onClick: () => void saveAgent(), children: tr('botDefaults.agentSave') }), _jsx(StatusSpan, { status: agentStatus, attr: { 'data-agent-status': '' } })] }))] }));
1085
1318
  }
1319
+ /**
1320
+ * Node's setTimeout delay caps at a 32-bit signed int of ms; a larger value
1321
+ * wraps to ~1ms. Kept in lockstep with `MAX_TURN_TIMEOUT_MS` in bot-registry
1322
+ * (a browser bundle can't import that Node-side module); a unit test asserts the
1323
+ * two stay equal so this copy can't silently drift.
1324
+ */
1325
+ export const DASHBOARD_MAX_TURN_TIMEOUT_MS = 2_147_483_647;
1326
+ /**
1327
+ * Convert a stored dsh turn timeout (ms) into the minutes string shown in the
1328
+ * input. Absent / non-positive / non-integer / over-bound → empty (the field
1329
+ * then means "use the runner default"). A legal value that is not a whole
1330
+ * number of minutes is shown as its decimal minutes (trimmed of any float
1331
+ * tail) rather than hidden as empty; `parseTurnTimeoutMinInput` re-rounds it to
1332
+ * the nearest whole ms, so the displayed value round-trips back to the same ms.
1333
+ */
1334
+ function turnTimeoutMinFromMs(ms) {
1335
+ if (typeof ms !== 'number' || !Number.isInteger(ms) || ms <= 0 || ms > DASHBOARD_MAX_TURN_TIMEOUT_MS)
1336
+ return '';
1337
+ const minutes = ms / 60_000;
1338
+ // Trim any floating-point tail; parseTurnTimeoutMinInput re-rounds to ms.
1339
+ return Number.isInteger(minutes) ? String(minutes) : String(Number(minutes.toFixed(10)));
1340
+ }
1341
+ /**
1342
+ * Parse the minutes input for the PUT body. Returns:
1343
+ * - `''` → cleared (empty input) → daemon reverts to the runner default,
1344
+ * - a number → minutes → ms, rounded to the nearest whole ms, a positive
1345
+ * integer within the arm-able bound,
1346
+ * - `'invalid'` → the operator typed something that is not a clearable blank
1347
+ * and not a representable positive timeout (0, negative, NaN,
1348
+ * or a minutes value whose nearest ms is ≤0 / over-bound).
1349
+ * Rounding to the nearest whole ms makes the value shown by
1350
+ * `turnTimeoutMinFromMs` (a possibly-decimal minutes figure) round-trip back to
1351
+ * the exact stored ms; invalid input is surfaced inline, never silently cleared.
1352
+ */
1353
+ function parseTurnTimeoutMinInput(minutes) {
1354
+ const trimmed = minutes.trim();
1355
+ if (!trimmed)
1356
+ return '';
1357
+ const asMinutes = Number(trimmed);
1358
+ if (!Number.isFinite(asMinutes) || asMinutes <= 0)
1359
+ return 'invalid';
1360
+ // Round to the nearest whole ms: the minutes field is a lossy display of a
1361
+ // ms value, so snapping back to an integer ms is the safe, non-destructive
1362
+ // interpretation (e.g. 1.5000166667 min → 90001 ms).
1363
+ const ms = Math.round(asMinutes * 60_000);
1364
+ if (ms <= 0 || ms > DASHBOARD_MAX_TURN_TIMEOUT_MS)
1365
+ return 'invalid';
1366
+ return ms;
1367
+ }
1086
1368
  function skillInjectionResolved(bot) {
1087
1369
  const override = bot.skillInjection === 'global' || bot.skillInjection === 'prompt' || bot.skillInjection === 'off' ? bot.skillInjection : '';
1088
1370
  const def = bot.skillInjectionDefault === 'global' || bot.skillInjectionDefault === 'off' ? bot.skillInjectionDefault : 'prompt';
@@ -2240,16 +2522,17 @@ function normalizeP2pMode(value) {
2240
2522
  * - off:不打标签
2241
2523
  * 一键授权 → 新标签页打开飞书授权 → 回跳 dashboard /oauth/callback 自动完成
2242
2524
  * → 本行轮询到 authorized 后徽标变绿。 */
2243
- function SessionGroupTagRow(props) {
2525
+ export function SessionGroupTagRow(props) {
2244
2526
  const tr = useT();
2245
2527
  const [status, setStatus] = useState(null);
2246
2528
  const [authBusy, setAuthBusy] = useState(false);
2247
2529
  const [modeBusy, setModeBusy] = useState(false);
2248
2530
  const [err, setErr] = useState(null);
2249
- const fetchStatus = async () => {
2531
+ const lifecycle = useRef({ generation: 0, mounted: true });
2532
+ const fetchStatus = async (generation = lifecycle.current.generation) => {
2250
2533
  try {
2251
2534
  const res = await sendJson('GET', `/api/bots/${encodeURIComponent(props.bot.larkAppId)}/session-group-tag-status`);
2252
- if (res.ok && res.body.ok) {
2535
+ if (lifecycle.current.mounted && generation === lifecycle.current.generation && res.ok && res.body.ok) {
2253
2536
  setStatus({ authorized: !!res.body.authorized, tagMode: String(res.body.tagMode ?? 'feed-group') });
2254
2537
  return !!res.body.authorized;
2255
2538
  }
@@ -2257,12 +2540,32 @@ function SessionGroupTagRow(props) {
2257
2540
  catch { /* transient */ }
2258
2541
  return false;
2259
2542
  };
2260
- useEffect(() => { void fetchStatus(); }, [props.bot.larkAppId]);
2543
+ useEffect(() => {
2544
+ lifecycle.current.mounted = true;
2545
+ const generation = ++lifecycle.current.generation;
2546
+ // The row instance can survive a bot switch. Clear the previous bot's
2547
+ // in-flight UI state as well as invalidating its polling generation.
2548
+ setStatus(null);
2549
+ setAuthBusy(false);
2550
+ setModeBusy(false);
2551
+ setErr(null);
2552
+ void fetchStatus(generation);
2553
+ return () => {
2554
+ lifecycle.current.mounted = false;
2555
+ lifecycle.current.generation += 1;
2556
+ };
2557
+ }, [props.bot.larkAppId]);
2261
2558
  async function saveMode(next) {
2559
+ // Capture the row's generation: a bot switch bumps it (see the effect
2560
+ // above), and a slow response for the previous bot must not overwrite the
2561
+ // new bot's row state — drop it silently instead.
2562
+ const generation = lifecycle.current.generation;
2262
2563
  setModeBusy(true);
2263
2564
  setErr(null);
2264
2565
  try {
2265
2566
  const res = await sendJson('PUT', `/api/bots/${encodeURIComponent(props.bot.larkAppId)}/session-group-tag-config`, { mode: next });
2567
+ if (!lifecycle.current.mounted || generation !== lifecycle.current.generation)
2568
+ return;
2266
2569
  if (res.ok && res.body.ok) {
2267
2570
  setStatus(s => ({ authorized: s?.authorized ?? false, tagMode: String(res.body.tagMode) }));
2268
2571
  }
@@ -2271,17 +2574,25 @@ function SessionGroupTagRow(props) {
2271
2574
  }
2272
2575
  }
2273
2576
  catch (e) {
2274
- setErr(caughtErrorText(e));
2577
+ if (lifecycle.current.mounted && generation === lifecycle.current.generation) {
2578
+ setErr(caughtErrorText(e));
2579
+ }
2275
2580
  }
2276
2581
  finally {
2277
- setModeBusy(false);
2582
+ if (lifecycle.current.mounted && generation === lifecycle.current.generation)
2583
+ setModeBusy(false);
2278
2584
  }
2279
2585
  }
2280
2586
  async function startAuth() {
2587
+ const generation = ++lifecycle.current.generation;
2281
2588
  setAuthBusy(true);
2282
2589
  setErr(null);
2283
2590
  try {
2284
2591
  const res = await sendJson('POST', `/api/bots/${encodeURIComponent(props.bot.larkAppId)}/session-group-tag-auth`, {});
2592
+ // A bot switch while the POST was in flight must neither surface the old
2593
+ // bot's error nor open the old bot's authorization page in a new tab.
2594
+ if (!lifecycle.current.mounted || generation !== lifecycle.current.generation)
2595
+ return;
2285
2596
  if (!res.ok || !res.body.ok || !res.body.authUrl) {
2286
2597
  setErr(responseErrorText(res));
2287
2598
  return;
@@ -2290,16 +2601,23 @@ function SessionGroupTagRow(props) {
2290
2601
  // 轮询授权结果:3s × 60 次(授权链接 5 分钟有效期同量级)。
2291
2602
  for (let i = 0; i < 60; i++) {
2292
2603
  await new Promise(r => setTimeout(r, 3000));
2293
- if (await fetchStatus())
2604
+ if (!lifecycle.current.mounted || generation !== lifecycle.current.generation)
2605
+ return;
2606
+ if (await fetchStatus(generation))
2294
2607
  return;
2295
2608
  }
2296
- setErr(tr('botDefaults.sgTagAuthTimeout'));
2609
+ if (lifecycle.current.mounted && generation === lifecycle.current.generation) {
2610
+ setErr(tr('botDefaults.sgTagAuthTimeout'));
2611
+ }
2297
2612
  }
2298
2613
  catch (e) {
2299
- setErr(caughtErrorText(e));
2614
+ if (lifecycle.current.mounted && generation === lifecycle.current.generation) {
2615
+ setErr(caughtErrorText(e));
2616
+ }
2300
2617
  }
2301
2618
  finally {
2302
- setAuthBusy(false);
2619
+ if (lifecycle.current.mounted && generation === lifecycle.current.generation)
2620
+ setAuthBusy(false);
2303
2621
  }
2304
2622
  }
2305
2623
  const tagMode = status?.tagMode ?? 'feed-group';
@@ -2585,8 +2903,16 @@ function RiffSection(props) {
2585
2903
  if (res.ok && res.body.ok) {
2586
2904
  const next = typeof res.body.riff === 'string' && res.body.riff ? JSON.parse(res.body.riff) : null;
2587
2905
  props.patchBot(props.bot.larkAppId, { riff: next });
2588
- if (props.persistCliSelection && !(await props.persistCliSelection())) {
2589
- setStatus({ text: `✗ ${tr('botDefaults.riffCliPersistFailed')}` });
2906
+ const persisted = await props.persistCliSelection?.();
2907
+ if (persisted && !persisted.ok) {
2908
+ // Show the transaction's own detail (Agent NOT switched + surviving
2909
+ // remote ids) in THIS section's visible status, not the generic text.
2910
+ setStatus({ text: `✗ ${persisted.note || tr('botDefaults.riffCliPersistFailed')}` });
2911
+ return;
2912
+ }
2913
+ if (persisted?.hadProblem) {
2914
+ // Saved, but a remote session survived — never the green tick.
2915
+ setStatus({ text: `⚠️ ${persisted.note}` });
2590
2916
  return;
2591
2917
  }
2592
2918
  setStatus({ text: `✓ ${tr('botDefaults.cardPrefSaved')}`, ok: true });