botmux 3.16.0 → 3.17.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 (619) hide show
  1. package/dist/.runtime-build-id +1 -1
  2. package/dist/adapters/backend/riff-backend.d.ts +84 -1
  3. package/dist/adapters/backend/riff-backend.d.ts.map +1 -1
  4. package/dist/adapters/backend/riff-backend.js +202 -19
  5. package/dist/adapters/backend/riff-backend.js.map +1 -1
  6. package/dist/adapters/backend/sandbox.d.ts +8 -0
  7. package/dist/adapters/backend/sandbox.d.ts.map +1 -1
  8. package/dist/adapters/backend/sandbox.js +15 -0
  9. package/dist/adapters/backend/sandbox.js.map +1 -1
  10. package/dist/adapters/backend/tmux-backend.d.ts +61 -7
  11. package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
  12. package/dist/adapters/backend/tmux-backend.js +80 -9
  13. package/dist/adapters/backend/tmux-backend.js.map +1 -1
  14. package/dist/adapters/backend/tmux-pipe-backend.d.ts +62 -4
  15. package/dist/adapters/backend/tmux-pipe-backend.d.ts.map +1 -1
  16. package/dist/adapters/backend/tmux-pipe-backend.js +240 -27
  17. package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -1
  18. package/dist/adapters/cli/claude-code.d.ts.map +1 -1
  19. package/dist/adapters/cli/claude-code.js +4 -2
  20. package/dist/adapters/cli/claude-code.js.map +1 -1
  21. package/dist/adapters/cli/coco.d.ts.map +1 -1
  22. package/dist/adapters/cli/coco.js +27 -0
  23. package/dist/adapters/cli/coco.js.map +1 -1
  24. package/dist/adapters/cli/codex-app.d.ts.map +1 -1
  25. package/dist/adapters/cli/codex-app.js +28 -0
  26. package/dist/adapters/cli/codex-app.js.map +1 -1
  27. package/dist/adapters/cli/codex.d.ts.map +1 -1
  28. package/dist/adapters/cli/codex.js +51 -23
  29. package/dist/adapters/cli/codex.js.map +1 -1
  30. package/dist/adapters/cli/dsh-tui.d.ts +24 -0
  31. package/dist/adapters/cli/dsh-tui.d.ts.map +1 -0
  32. package/dist/adapters/cli/dsh-tui.js +99 -0
  33. package/dist/adapters/cli/dsh-tui.js.map +1 -0
  34. package/dist/adapters/cli/dsh.d.ts.map +1 -1
  35. package/dist/adapters/cli/dsh.js +15 -9
  36. package/dist/adapters/cli/dsh.js.map +1 -1
  37. package/dist/adapters/cli/fs-policy.d.ts +98 -1
  38. package/dist/adapters/cli/fs-policy.d.ts.map +1 -1
  39. package/dist/adapters/cli/fs-policy.js +182 -7
  40. package/dist/adapters/cli/fs-policy.js.map +1 -1
  41. package/dist/adapters/cli/grok.js +16 -18
  42. package/dist/adapters/cli/grok.js.map +1 -1
  43. package/dist/adapters/cli/model-catalog-json.d.ts +17 -0
  44. package/dist/adapters/cli/model-catalog-json.d.ts.map +1 -0
  45. package/dist/adapters/cli/model-catalog-json.js +43 -0
  46. package/dist/adapters/cli/model-catalog-json.js.map +1 -0
  47. package/dist/adapters/cli/oh-my-pi.d.ts +2 -0
  48. package/dist/adapters/cli/oh-my-pi.d.ts.map +1 -1
  49. package/dist/adapters/cli/oh-my-pi.js +45 -13
  50. package/dist/adapters/cli/oh-my-pi.js.map +1 -1
  51. package/dist/adapters/cli/opencode.js +1 -1
  52. package/dist/adapters/cli/opencode.js.map +1 -1
  53. package/dist/adapters/cli/registry.d.ts +2 -1
  54. package/dist/adapters/cli/registry.d.ts.map +1 -1
  55. package/dist/adapters/cli/registry.js +6 -1
  56. package/dist/adapters/cli/registry.js.map +1 -1
  57. package/dist/adapters/cli/relay.d.ts.map +1 -1
  58. package/dist/adapters/cli/relay.js +7 -0
  59. package/dist/adapters/cli/relay.js.map +1 -1
  60. package/dist/adapters/cli/seed.d.ts.map +1 -1
  61. package/dist/adapters/cli/seed.js +6 -0
  62. package/dist/adapters/cli/seed.js.map +1 -1
  63. package/dist/adapters/cli/shared-hints.d.ts.map +1 -1
  64. package/dist/adapters/cli/shared-hints.js +20 -14
  65. package/dist/adapters/cli/shared-hints.js.map +1 -1
  66. package/dist/adapters/cli/traex.d.ts +4 -0
  67. package/dist/adapters/cli/traex.d.ts.map +1 -1
  68. package/dist/adapters/cli/traex.js +153 -0
  69. package/dist/adapters/cli/traex.js.map +1 -1
  70. package/dist/adapters/cli/types.d.ts +42 -1
  71. package/dist/adapters/cli/types.d.ts.map +1 -1
  72. package/dist/autostart.d.ts +6 -0
  73. package/dist/autostart.d.ts.map +1 -1
  74. package/dist/autostart.js +21 -1
  75. package/dist/autostart.js.map +1 -1
  76. package/dist/bot-registry.d.ts +27 -0
  77. package/dist/bot-registry.d.ts.map +1 -1
  78. package/dist/bot-registry.js +62 -2
  79. package/dist/bot-registry.js.map +1 -1
  80. package/dist/cli/vc-agent.d.ts.map +1 -1
  81. package/dist/cli/vc-agent.js +21 -3
  82. package/dist/cli/vc-agent.js.map +1 -1
  83. package/dist/cli.d.ts.map +1 -1
  84. package/dist/cli.js +92 -1
  85. package/dist/cli.js.map +1 -1
  86. package/dist/codex-app-runner.js +28 -0
  87. package/dist/codex-app-runner.js.map +1 -1
  88. package/dist/core/bot-steer-directive.d.ts +25 -0
  89. package/dist/core/bot-steer-directive.d.ts.map +1 -0
  90. package/dist/core/bot-steer-directive.js +47 -0
  91. package/dist/core/bot-steer-directive.js.map +1 -0
  92. package/dist/core/command-handler.d.ts.map +1 -1
  93. package/dist/core/command-handler.js +102 -18
  94. package/dist/core/command-handler.js.map +1 -1
  95. package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
  96. package/dist/core/dashboard-ipc-server.js +53 -13
  97. package/dist/core/dashboard-ipc-server.js.map +1 -1
  98. package/dist/core/dashboard-rows.d.ts +3 -0
  99. package/dist/core/dashboard-rows.d.ts.map +1 -1
  100. package/dist/core/dashboard-rows.js +26 -5
  101. package/dist/core/dashboard-rows.js.map +1 -1
  102. package/dist/core/dashboard-url.d.ts +10 -1
  103. package/dist/core/dashboard-url.d.ts.map +1 -1
  104. package/dist/core/dashboard-url.js +12 -2
  105. package/dist/core/dashboard-url.js.map +1 -1
  106. package/dist/core/dispatch.d.ts.map +1 -1
  107. package/dist/core/dispatch.js +5 -4
  108. package/dist/core/dispatch.js.map +1 -1
  109. package/dist/core/existing-app-server.d.ts +22 -0
  110. package/dist/core/existing-app-server.d.ts.map +1 -0
  111. package/dist/core/existing-app-server.js +85 -0
  112. package/dist/core/existing-app-server.js.map +1 -0
  113. package/dist/core/native-topic-id.d.ts +9 -0
  114. package/dist/core/native-topic-id.d.ts.map +1 -0
  115. package/dist/core/native-topic-id.js +14 -0
  116. package/dist/core/native-topic-id.js.map +1 -0
  117. package/dist/core/per-bot-env.d.ts.map +1 -1
  118. package/dist/core/per-bot-env.js +10 -0
  119. package/dist/core/per-bot-env.js.map +1 -1
  120. package/dist/core/plugins/mcp/gateway.d.ts +27 -3
  121. package/dist/core/plugins/mcp/gateway.d.ts.map +1 -1
  122. package/dist/core/plugins/mcp/gateway.js +272 -26
  123. package/dist/core/plugins/mcp/gateway.js.map +1 -1
  124. package/dist/core/plugins/mcp/host.d.ts +18 -0
  125. package/dist/core/plugins/mcp/host.d.ts.map +1 -1
  126. package/dist/core/plugins/mcp/host.js +80 -16
  127. package/dist/core/plugins/mcp/host.js.map +1 -1
  128. package/dist/core/plugins/mcp/launch-record.d.ts +14 -0
  129. package/dist/core/plugins/mcp/launch-record.d.ts.map +1 -0
  130. package/dist/core/plugins/mcp/launch-record.js +63 -0
  131. package/dist/core/plugins/mcp/launch-record.js.map +1 -0
  132. package/dist/core/session-activity.d.ts +11 -0
  133. package/dist/core/session-activity.d.ts.map +1 -1
  134. package/dist/core/session-activity.js +23 -0
  135. package/dist/core/session-activity.js.map +1 -1
  136. package/dist/core/session-group-birth.d.ts.map +1 -1
  137. package/dist/core/session-group-birth.js +23 -8
  138. package/dist/core/session-group-birth.js.map +1 -1
  139. package/dist/core/session-manager.d.ts +1 -4
  140. package/dist/core/session-manager.d.ts.map +1 -1
  141. package/dist/core/session-manager.js +16 -20
  142. package/dist/core/session-manager.js.map +1 -1
  143. package/dist/core/shared-adopt.d.ts +20 -0
  144. package/dist/core/shared-adopt.d.ts.map +1 -0
  145. package/dist/core/shared-adopt.js +26 -0
  146. package/dist/core/shared-adopt.js.map +1 -0
  147. package/dist/core/skills/customize-command.d.ts +7 -0
  148. package/dist/core/skills/customize-command.d.ts.map +1 -0
  149. package/dist/core/skills/customize-command.js +303 -0
  150. package/dist/core/skills/customize-command.js.map +1 -0
  151. package/dist/core/terminal-write-auth.d.ts +15 -0
  152. package/dist/core/terminal-write-auth.d.ts.map +1 -1
  153. package/dist/core/terminal-write-auth.js +15 -0
  154. package/dist/core/terminal-write-auth.js.map +1 -1
  155. package/dist/core/terminal-write-frame.d.ts +30 -0
  156. package/dist/core/terminal-write-frame.d.ts.map +1 -0
  157. package/dist/core/terminal-write-frame.js +44 -0
  158. package/dist/core/terminal-write-frame.js.map +1 -0
  159. package/dist/core/types.d.ts +14 -4
  160. package/dist/core/types.d.ts.map +1 -1
  161. package/dist/core/types.js +6 -8
  162. package/dist/core/types.js.map +1 -1
  163. package/dist/core/worker-pool.d.ts +31 -6
  164. package/dist/core/worker-pool.d.ts.map +1 -1
  165. package/dist/core/worker-pool.js +444 -102
  166. package/dist/core/worker-pool.js.map +1 -1
  167. package/dist/core/worker-startup-retry.d.ts +52 -0
  168. package/dist/core/worker-startup-retry.d.ts.map +1 -0
  169. package/dist/core/worker-startup-retry.js +68 -0
  170. package/dist/core/worker-startup-retry.js.map +1 -0
  171. package/dist/daemon.d.ts +9 -8
  172. package/dist/daemon.d.ts.map +1 -1
  173. package/dist/daemon.js +467 -171
  174. package/dist/daemon.js.map +1 -1
  175. package/dist/dashboard/autostart-api.d.ts +26 -0
  176. package/dist/dashboard/autostart-api.d.ts.map +1 -0
  177. package/dist/dashboard/autostart-api.js +88 -0
  178. package/dist/dashboard/autostart-api.js.map +1 -0
  179. package/dist/dashboard/bot-payload.d.ts +5 -0
  180. package/dist/dashboard/bot-payload.d.ts.map +1 -1
  181. package/dist/dashboard/bot-payload.js +2 -0
  182. package/dist/dashboard/bot-payload.js.map +1 -1
  183. package/dist/dashboard/control-csrf.d.ts +29 -1
  184. package/dist/dashboard/control-csrf.d.ts.map +1 -1
  185. package/dist/dashboard/control-csrf.js +49 -10
  186. package/dist/dashboard/control-csrf.js.map +1 -1
  187. package/dist/dashboard/customization-api.d.ts +23 -0
  188. package/dist/dashboard/customization-api.d.ts.map +1 -0
  189. package/dist/dashboard/customization-api.js +198 -0
  190. package/dist/dashboard/customization-api.js.map +1 -0
  191. package/dist/dashboard/debug-terminal.d.ts +13 -1
  192. package/dist/dashboard/debug-terminal.d.ts.map +1 -1
  193. package/dist/dashboard/debug-terminal.js +18 -4
  194. package/dist/dashboard/debug-terminal.js.map +1 -1
  195. package/dist/dashboard/settings-write-applier.d.ts +0 -23
  196. package/dist/dashboard/settings-write-applier.d.ts.map +1 -1
  197. package/dist/dashboard/settings-write-applier.js +7 -28
  198. package/dist/dashboard/settings-write-applier.js.map +1 -1
  199. package/dist/dashboard/terminal-control-route.d.ts +32 -0
  200. package/dist/dashboard/terminal-control-route.d.ts.map +1 -0
  201. package/dist/dashboard/terminal-control-route.js +70 -0
  202. package/dist/dashboard/terminal-control-route.js.map +1 -0
  203. package/dist/dashboard/terminal-control.d.ts +64 -13
  204. package/dist/dashboard/terminal-control.d.ts.map +1 -1
  205. package/dist/dashboard/terminal-control.js +77 -14
  206. package/dist/dashboard/terminal-control.js.map +1 -1
  207. package/dist/dashboard/terminal-front-proxy.d.ts.map +1 -1
  208. package/dist/dashboard/terminal-front-proxy.js +41 -9
  209. package/dist/dashboard/terminal-front-proxy.js.map +1 -1
  210. package/dist/dashboard/vc-consumer-profiles-api.d.ts +69 -18
  211. package/dist/dashboard/vc-consumer-profiles-api.d.ts.map +1 -1
  212. package/dist/dashboard/vc-consumer-profiles-api.js +149 -29
  213. package/dist/dashboard/vc-consumer-profiles-api.js.map +1 -1
  214. package/dist/dashboard/web/agent-workbench-api.d.ts +34 -2
  215. package/dist/dashboard/web/agent-workbench-api.d.ts.map +1 -1
  216. package/dist/dashboard/web/agent-workbench-api.js +39 -4
  217. package/dist/dashboard/web/agent-workbench-api.js.map +1 -1
  218. package/dist/dashboard/web/agent-workbench-appearance.d.ts +6 -3
  219. package/dist/dashboard/web/agent-workbench-appearance.d.ts.map +1 -1
  220. package/dist/dashboard/web/agent-workbench-appearance.js +7 -4
  221. package/dist/dashboard/web/agent-workbench-appearance.js.map +1 -1
  222. package/dist/dashboard/web/agent-workbench-model.d.ts +2 -0
  223. package/dist/dashboard/web/agent-workbench-model.d.ts.map +1 -1
  224. package/dist/dashboard/web/agent-workbench-model.js.map +1 -1
  225. package/dist/dashboard/web/agent-workbench-page.js +2 -2
  226. package/dist/dashboard/web/agent-workbench-page.js.map +1 -1
  227. package/dist/dashboard/web/agent-workbench-panes.d.ts +59 -4
  228. package/dist/dashboard/web/agent-workbench-panes.d.ts.map +1 -1
  229. package/dist/dashboard/web/agent-workbench-panes.js +493 -85
  230. package/dist/dashboard/web/agent-workbench-panes.js.map +1 -1
  231. package/dist/dashboard/web/agent-workbench-session-list.d.ts +11 -7
  232. package/dist/dashboard/web/agent-workbench-session-list.d.ts.map +1 -1
  233. package/dist/dashboard/web/agent-workbench-session-list.js +24 -31
  234. package/dist/dashboard/web/agent-workbench-session-list.js.map +1 -1
  235. package/dist/dashboard/web/agent-workbench-terminal-control.d.ts +198 -0
  236. package/dist/dashboard/web/agent-workbench-terminal-control.d.ts.map +1 -0
  237. package/dist/dashboard/web/agent-workbench-terminal-control.js +292 -0
  238. package/dist/dashboard/web/agent-workbench-terminal-control.js.map +1 -0
  239. package/dist/dashboard/web/agent-workbench-view.d.ts +3 -2
  240. package/dist/dashboard/web/agent-workbench-view.d.ts.map +1 -1
  241. package/dist/dashboard/web/agent-workbench-view.js +69 -50
  242. package/dist/dashboard/web/agent-workbench-view.js.map +1 -1
  243. package/dist/dashboard/web/app.d.ts.map +1 -1
  244. package/dist/dashboard/web/app.js +58 -7
  245. package/dist/dashboard/web/app.js.map +1 -1
  246. package/dist/dashboard/web/bot-defaults-page.d.ts +24 -0
  247. package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -1
  248. package/dist/dashboard/web/bot-defaults-page.js +191 -16
  249. package/dist/dashboard/web/bot-defaults-page.js.map +1 -1
  250. package/dist/dashboard/web/bot-defaults.d.ts +17 -0
  251. package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
  252. package/dist/dashboard/web/bot-defaults.js +51 -2
  253. package/dist/dashboard/web/bot-defaults.js.map +1 -1
  254. package/dist/dashboard/web/bot-onboarding.d.ts.map +1 -1
  255. package/dist/dashboard/web/bot-onboarding.js +32 -8
  256. package/dist/dashboard/web/bot-onboarding.js.map +1 -1
  257. package/dist/dashboard/web/confirm-modal.d.ts +35 -0
  258. package/dist/dashboard/web/confirm-modal.d.ts.map +1 -0
  259. package/dist/dashboard/web/confirm-modal.js +111 -0
  260. package/dist/dashboard/web/confirm-modal.js.map +1 -0
  261. package/dist/dashboard/web/connectors-page.d.ts.map +1 -1
  262. package/dist/dashboard/web/connectors-page.js +2 -1
  263. package/dist/dashboard/web/connectors-page.js.map +1 -1
  264. package/dist/dashboard/web/customization-page.d.ts +3 -0
  265. package/dist/dashboard/web/customization-page.d.ts.map +1 -0
  266. package/dist/dashboard/web/customization-page.js +315 -0
  267. package/dist/dashboard/web/customization-page.js.map +1 -0
  268. package/dist/dashboard/web/dashboard-routes.d.ts.map +1 -1
  269. package/dist/dashboard/web/dashboard-routes.js +1 -0
  270. package/dist/dashboard/web/dashboard-routes.js.map +1 -1
  271. package/dist/dashboard/web/groups-page.d.ts.map +1 -1
  272. package/dist/dashboard/web/groups-page.js +11 -9
  273. package/dist/dashboard/web/groups-page.js.map +1 -1
  274. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  275. package/dist/dashboard/web/i18n.js +226 -42
  276. package/dist/dashboard/web/i18n.js.map +1 -1
  277. package/dist/dashboard/web/monitor-room.d.ts.map +1 -1
  278. package/dist/dashboard/web/monitor-room.js +3 -2
  279. package/dist/dashboard/web/monitor-room.js.map +1 -1
  280. package/dist/dashboard/web/overview-page.d.ts.map +1 -1
  281. package/dist/dashboard/web/overview-page.js +98 -63
  282. package/dist/dashboard/web/overview-page.js.map +1 -1
  283. package/dist/dashboard/web/roles-page.d.ts.map +1 -1
  284. package/dist/dashboard/web/roles-page.js +4 -3
  285. package/dist/dashboard/web/roles-page.js.map +1 -1
  286. package/dist/dashboard/web/schedules-page.d.ts.map +1 -1
  287. package/dist/dashboard/web/schedules-page.js +165 -18
  288. package/dist/dashboard/web/schedules-page.js.map +1 -1
  289. package/dist/dashboard/web/sessions-kanban.d.ts +2 -0
  290. package/dist/dashboard/web/sessions-kanban.d.ts.map +1 -1
  291. package/dist/dashboard/web/sessions-kanban.js +142 -24
  292. package/dist/dashboard/web/sessions-kanban.js.map +1 -1
  293. package/dist/dashboard/web/sessions-page.d.ts.map +1 -1
  294. package/dist/dashboard/web/sessions-page.js +177 -94
  295. package/dist/dashboard/web/sessions-page.js.map +1 -1
  296. package/dist/dashboard/web/sessions.d.ts.map +1 -1
  297. package/dist/dashboard/web/sessions.js +5 -4
  298. package/dist/dashboard/web/sessions.js.map +1 -1
  299. package/dist/dashboard/web/settings-page.d.ts +0 -8
  300. package/dist/dashboard/web/settings-page.d.ts.map +1 -1
  301. package/dist/dashboard/web/settings-page.js +185 -65
  302. package/dist/dashboard/web/settings-page.js.map +1 -1
  303. package/dist/dashboard/web/skills/skill-library-tab.d.ts +2 -0
  304. package/dist/dashboard/web/skills/skill-library-tab.d.ts.map +1 -1
  305. package/dist/dashboard/web/skills/skill-library-tab.js +15 -1
  306. package/dist/dashboard/web/skills/skill-library-tab.js.map +1 -1
  307. package/dist/dashboard/web/skills-page.d.ts.map +1 -1
  308. package/dist/dashboard/web/skills-page.js +5 -4
  309. package/dist/dashboard/web/skills-page.js.map +1 -1
  310. package/dist/dashboard/web/store.d.ts +5 -0
  311. package/dist/dashboard/web/store.d.ts.map +1 -1
  312. package/dist/dashboard/web/store.js +4 -0
  313. package/dist/dashboard/web/store.js.map +1 -1
  314. package/dist/dashboard/web/team-federation-page.d.ts.map +1 -1
  315. package/dist/dashboard/web/team-federation-page.js +3 -2
  316. package/dist/dashboard/web/team-federation-page.js.map +1 -1
  317. package/dist/dashboard/web/toast.d.ts +15 -0
  318. package/dist/dashboard/web/toast.d.ts.map +1 -0
  319. package/dist/dashboard/web/toast.js +70 -0
  320. package/dist/dashboard/web/toast.js.map +1 -0
  321. package/dist/dashboard/web/v3-components.d.ts.map +1 -1
  322. package/dist/dashboard/web/v3-components.js +2 -1
  323. package/dist/dashboard/web/v3-components.js.map +1 -1
  324. package/dist/dashboard/web/vc-consumer-profiles-section.d.ts +10 -12
  325. package/dist/dashboard/web/vc-consumer-profiles-section.d.ts.map +1 -1
  326. package/dist/dashboard/web/vc-consumer-profiles-section.js +219 -200
  327. package/dist/dashboard/web/vc-consumer-profiles-section.js.map +1 -1
  328. package/dist/dashboard/web/whiteboards-page.d.ts.map +1 -1
  329. package/dist/dashboard/web/whiteboards-page.js +2 -1
  330. package/dist/dashboard/web/whiteboards-page.js.map +1 -1
  331. package/dist/dashboard-web/app.js +1 -1
  332. package/dist/dashboard-web/chunks/agent-workbench-dock-page-LZSUOCEQ.js +1 -0
  333. package/dist/dashboard-web/chunks/agent-workbench-page-YONDRJU7.js +1 -0
  334. package/dist/dashboard-web/chunks/bot-defaults-page-X7LV6373.js +1 -0
  335. package/dist/dashboard-web/chunks/chunk-2PVRDXEL.js +1 -0
  336. package/dist/dashboard-web/chunks/chunk-53JUKBU2.js +10 -0
  337. package/dist/dashboard-web/chunks/{chunk-5CJMHTT4.js → chunk-5QX4OYOR.js} +1 -1
  338. package/dist/dashboard-web/chunks/{chunk-NACP7BMR.js → chunk-5VRVJFQR.js} +1 -1
  339. package/dist/dashboard-web/chunks/{chunk-FDZ7WOBW.js → chunk-6ROOZWYV.js} +1 -1
  340. package/dist/dashboard-web/chunks/{chunk-F6KNPF4R.js → chunk-CK22743G.js} +15 -19
  341. package/dist/dashboard-web/chunks/chunk-CVNIMUPY.js +25 -0
  342. package/dist/dashboard-web/chunks/chunk-GJC2TMWS.js +2 -0
  343. package/dist/dashboard-web/chunks/chunk-OT6L6G7R.js +1 -0
  344. package/dist/dashboard-web/chunks/chunk-QITAMHW6.js +1 -0
  345. package/dist/dashboard-web/chunks/chunk-RHVFZC5Z.js +1 -0
  346. package/dist/dashboard-web/chunks/chunk-SOBMN2VY.js +1 -0
  347. package/dist/dashboard-web/chunks/chunk-SZOB6VK2.js +1 -0
  348. package/dist/dashboard-web/chunks/chunk-XVIXNQGC.js +44 -0
  349. package/dist/dashboard-web/chunks/chunk-YUJF34ME.js +1 -0
  350. package/dist/dashboard-web/chunks/connectors-page-LB2HEJ7F.js +1 -0
  351. package/dist/dashboard-web/chunks/customization-page-4GXBYLG6.js +105 -0
  352. package/dist/dashboard-web/chunks/feedback-page-IZQ7VLDG.js +1 -0
  353. package/dist/dashboard-web/chunks/groups-page-4WCP5OEV.js +8 -0
  354. package/dist/dashboard-web/chunks/{insights-page-HJFDYR5N.js → insights-page-TXQHIPQL.js} +1 -1
  355. package/dist/dashboard-web/chunks/{monitor-room-V7PCP47V.js → monitor-room-VBRVWXCM.js} +8 -8
  356. package/dist/dashboard-web/chunks/monitoring-page-QDDZWERE.js +2 -0
  357. package/dist/dashboard-web/chunks/office-page-PENFNYPG.js +1 -0
  358. package/dist/dashboard-web/chunks/overview-page-BZQDP6MP.js +1 -0
  359. package/dist/dashboard-web/chunks/plugin-page-JX4GSWZS.js +1 -0
  360. package/dist/dashboard-web/chunks/roles-page-VPNINZNK.js +1 -0
  361. package/dist/dashboard-web/chunks/schedules-page-BITO6HEA.js +1 -0
  362. package/dist/dashboard-web/chunks/sessions-page-ZKCOVTD2.js +8 -0
  363. package/dist/dashboard-web/chunks/settings-page-UT6JDTS6.js +2 -0
  364. package/dist/dashboard-web/chunks/skills-page-GULXVAJY.js +4 -0
  365. package/dist/dashboard-web/chunks/team-federation-page-CUUJWGEG.js +1 -0
  366. package/dist/dashboard-web/chunks/v3-page-5WVJ5AUR.js +94 -0
  367. package/dist/dashboard-web/chunks/whiteboards-page-FZ2CME4H.js +1 -0
  368. package/dist/dashboard-web/design-tokens.css +236 -0
  369. package/dist/dashboard-web/index.html +1 -0
  370. package/dist/dashboard-web/style.css +1930 -114
  371. package/dist/dashboard.js +360 -279
  372. package/dist/dashboard.js.map +1 -1
  373. package/dist/desktop/renderer/app.js +6 -0
  374. package/dist/desktop/renderer/app.js.map +1 -1
  375. package/dist/dsh-runner.js +139 -17
  376. package/dist/dsh-runner.js.map +1 -1
  377. package/dist/global-config.d.ts +33 -2
  378. package/dist/global-config.d.ts.map +1 -1
  379. package/dist/global-config.js +62 -0
  380. package/dist/global-config.js.map +1 -1
  381. package/dist/i18n/en.d.ts.map +1 -1
  382. package/dist/i18n/en.js +13 -4
  383. package/dist/i18n/en.js.map +1 -1
  384. package/dist/i18n/index.d.ts +27 -3
  385. package/dist/i18n/index.d.ts.map +1 -1
  386. package/dist/i18n/index.js +33 -4
  387. package/dist/i18n/index.js.map +1 -1
  388. package/dist/i18n/zh.d.ts.map +1 -1
  389. package/dist/i18n/zh.js +13 -4
  390. package/dist/i18n/zh.js.map +1 -1
  391. package/dist/im/lark/card-builder.d.ts +2 -0
  392. package/dist/im/lark/card-builder.d.ts.map +1 -1
  393. package/dist/im/lark/card-builder.js +7 -4
  394. package/dist/im/lark/card-builder.js.map +1 -1
  395. package/dist/im/lark/card-handler.d.ts.map +1 -1
  396. package/dist/im/lark/card-handler.js +135 -20
  397. package/dist/im/lark/card-handler.js.map +1 -1
  398. package/dist/im/lark/event-dispatcher.d.ts +38 -3
  399. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  400. package/dist/im/lark/event-dispatcher.js +163 -13
  401. package/dist/im/lark/event-dispatcher.js.map +1 -1
  402. package/dist/im/lark/v3-blocked-card-handler.d.ts.map +1 -1
  403. package/dist/im/lark/v3-blocked-card-handler.js +2 -1
  404. package/dist/im/lark/v3-blocked-card-handler.js.map +1 -1
  405. package/dist/im/lark/v3-blocked-card.d.ts +1 -1
  406. package/dist/im/lark/v3-blocked-card.d.ts.map +1 -1
  407. package/dist/im/lark/v3-blocked-card.js +14 -0
  408. package/dist/im/lark/v3-blocked-card.js.map +1 -1
  409. package/dist/index-core-only.js +2 -0
  410. package/dist/index-core-only.js.map +1 -1
  411. package/dist/index-daemon.js +3 -0
  412. package/dist/index-daemon.js.map +1 -1
  413. package/dist/platform/binding.d.ts +37 -0
  414. package/dist/platform/binding.d.ts.map +1 -1
  415. package/dist/platform/binding.js +15 -0
  416. package/dist/platform/binding.js.map +1 -1
  417. package/dist/services/bridge-turn-journal.d.ts +63 -0
  418. package/dist/services/bridge-turn-journal.d.ts.map +1 -0
  419. package/dist/services/bridge-turn-journal.js +149 -0
  420. package/dist/services/bridge-turn-journal.js.map +1 -0
  421. package/dist/services/bridge-turn-queue.d.ts +8 -1
  422. package/dist/services/bridge-turn-queue.d.ts.map +1 -1
  423. package/dist/services/bridge-turn-queue.js +2 -1
  424. package/dist/services/bridge-turn-queue.js.map +1 -1
  425. package/dist/services/codex-app-runner-protocol.d.ts +5 -0
  426. package/dist/services/codex-app-runner-protocol.d.ts.map +1 -1
  427. package/dist/services/codex-app-runner-protocol.js +5 -0
  428. package/dist/services/codex-app-runner-protocol.js.map +1 -1
  429. package/dist/services/customization-store.d.ts +93 -0
  430. package/dist/services/customization-store.d.ts.map +1 -0
  431. package/dist/services/customization-store.js +542 -0
  432. package/dist/services/customization-store.js.map +1 -0
  433. package/dist/services/file-bridge-path.d.ts.map +1 -1
  434. package/dist/services/file-bridge-path.js +3 -0
  435. package/dist/services/file-bridge-path.js.map +1 -1
  436. package/dist/services/grok-transcript.d.ts.map +1 -1
  437. package/dist/services/grok-transcript.js +44 -9
  438. package/dist/services/grok-transcript.js.map +1 -1
  439. package/dist/services/local-cli-opener.d.ts.map +1 -1
  440. package/dist/services/local-cli-opener.js +12 -3
  441. package/dist/services/local-cli-opener.js.map +1 -1
  442. package/dist/services/model-catalog.d.ts +54 -0
  443. package/dist/services/model-catalog.d.ts.map +1 -0
  444. package/dist/services/model-catalog.js +147 -0
  445. package/dist/services/model-catalog.js.map +1 -0
  446. package/dist/services/omp-transcript.d.ts +27 -0
  447. package/dist/services/omp-transcript.d.ts.map +1 -0
  448. package/dist/services/omp-transcript.js +214 -0
  449. package/dist/services/omp-transcript.js.map +1 -0
  450. package/dist/services/platform-team-store.d.ts +16 -8
  451. package/dist/services/platform-team-store.d.ts.map +1 -1
  452. package/dist/services/platform-team-store.js +17 -10
  453. package/dist/services/platform-team-store.js.map +1 -1
  454. package/dist/services/project-scanner.d.ts.map +1 -1
  455. package/dist/services/project-scanner.js +13 -8
  456. package/dist/services/project-scanner.js.map +1 -1
  457. package/dist/services/resumable-session-discovery.d.ts.map +1 -1
  458. package/dist/services/resumable-session-discovery.js +117 -35
  459. package/dist/services/resumable-session-discovery.js.map +1 -1
  460. package/dist/services/structured-bridge-clis.d.ts +5 -3
  461. package/dist/services/structured-bridge-clis.d.ts.map +1 -1
  462. package/dist/services/structured-bridge-clis.js +5 -1
  463. package/dist/services/structured-bridge-clis.js.map +1 -1
  464. package/dist/services/vc-meeting-action-gate.d.ts.map +1 -1
  465. package/dist/services/vc-meeting-action-gate.js +15 -4
  466. package/dist/services/vc-meeting-action-gate.js.map +1 -1
  467. package/dist/services/vc-meeting-consumer-profile-bootstrap.d.ts +46 -66
  468. package/dist/services/vc-meeting-consumer-profile-bootstrap.d.ts.map +1 -1
  469. package/dist/services/vc-meeting-consumer-profile-bootstrap.js +33 -292
  470. package/dist/services/vc-meeting-consumer-profile-bootstrap.js.map +1 -1
  471. package/dist/services/vc-meeting-consumer-profile-templates.js +3 -3
  472. package/dist/services/vc-meeting-consumer-profile-templates.js.map +1 -1
  473. package/dist/services/vc-meeting-delivery-store.d.ts +18 -0
  474. package/dist/services/vc-meeting-delivery-store.d.ts.map +1 -1
  475. package/dist/services/vc-meeting-delivery-store.js +55 -0
  476. package/dist/services/vc-meeting-delivery-store.js.map +1 -1
  477. package/dist/services/vc-meeting-send-policy.d.ts +21 -1
  478. package/dist/services/vc-meeting-send-policy.d.ts.map +1 -1
  479. package/dist/services/vc-meeting-send-policy.js +30 -2
  480. package/dist/services/vc-meeting-send-policy.js.map +1 -1
  481. package/dist/services/vc-meeting-shared-consumer-catalog-store.d.ts +78 -0
  482. package/dist/services/vc-meeting-shared-consumer-catalog-store.d.ts.map +1 -0
  483. package/dist/services/vc-meeting-shared-consumer-catalog-store.js +227 -0
  484. package/dist/services/vc-meeting-shared-consumer-catalog-store.js.map +1 -0
  485. package/dist/services/vc-meeting-shared-consumer-catalog.d.ts +53 -0
  486. package/dist/services/vc-meeting-shared-consumer-catalog.d.ts.map +1 -0
  487. package/dist/services/vc-meeting-shared-consumer-catalog.js +161 -0
  488. package/dist/services/vc-meeting-shared-consumer-catalog.js.map +1 -0
  489. package/dist/setup/bot-config-editor.d.ts.map +1 -1
  490. package/dist/setup/bot-config-editor.js +1 -0
  491. package/dist/setup/bot-config-editor.js.map +1 -1
  492. package/dist/setup/open-platform-automation.d.ts +20 -0
  493. package/dist/setup/open-platform-automation.d.ts.map +1 -1
  494. package/dist/setup/open-platform-automation.js +27 -0
  495. package/dist/setup/open-platform-automation.js.map +1 -1
  496. package/dist/skills/customization-bundle.d.ts +83 -0
  497. package/dist/skills/customization-bundle.d.ts.map +1 -0
  498. package/dist/skills/customization-bundle.js +214 -0
  499. package/dist/skills/customization-bundle.js.map +1 -0
  500. package/dist/skills/definitions.d.ts.map +1 -1
  501. package/dist/skills/definitions.js +10 -3
  502. package/dist/skills/definitions.js.map +1 -1
  503. package/dist/skills/effective-builtins.d.ts +38 -0
  504. package/dist/skills/effective-builtins.d.ts.map +1 -0
  505. package/dist/skills/effective-builtins.js +96 -0
  506. package/dist/skills/effective-builtins.js.map +1 -0
  507. package/dist/skills/injection-mode.d.ts +4 -1
  508. package/dist/skills/injection-mode.d.ts.map +1 -1
  509. package/dist/skills/injection-mode.js +11 -3
  510. package/dist/skills/injection-mode.js.map +1 -1
  511. package/dist/skills/installer.d.ts.map +1 -1
  512. package/dist/skills/installer.js +24 -1
  513. package/dist/skills/installer.js.map +1 -1
  514. package/dist/skills/prompt-fragments.d.ts +58 -0
  515. package/dist/skills/prompt-fragments.d.ts.map +1 -0
  516. package/dist/skills/prompt-fragments.js +88 -0
  517. package/dist/skills/prompt-fragments.js.map +1 -0
  518. package/dist/types.d.ts +51 -0
  519. package/dist/types.d.ts.map +1 -1
  520. package/dist/utils/cli-usage-limit.d.ts +50 -0
  521. package/dist/utils/cli-usage-limit.d.ts.map +1 -1
  522. package/dist/utils/cli-usage-limit.js +43 -0
  523. package/dist/utils/cli-usage-limit.js.map +1 -1
  524. package/dist/utils/idle-detector.d.ts +12 -0
  525. package/dist/utils/idle-detector.d.ts.map +1 -1
  526. package/dist/utils/idle-detector.js +88 -2
  527. package/dist/utils/idle-detector.js.map +1 -1
  528. package/dist/utils/stuck-detector.d.ts +5 -0
  529. package/dist/utils/stuck-detector.d.ts.map +1 -1
  530. package/dist/utils/stuck-detector.js +41 -0
  531. package/dist/utils/stuck-detector.js.map +1 -1
  532. package/dist/utils/usage-limit-tracker.d.ts +46 -0
  533. package/dist/utils/usage-limit-tracker.d.ts.map +1 -0
  534. package/dist/utils/usage-limit-tracker.js +91 -0
  535. package/dist/utils/usage-limit-tracker.js.map +1 -0
  536. package/dist/utils/user-token.js +1 -1
  537. package/dist/utils/user-token.js.map +1 -1
  538. package/dist/worker.js +812 -125
  539. package/dist/worker.js.map +1 -1
  540. package/dist/workflows/definition.d.ts +14 -14
  541. package/dist/workflows/events/payloads.d.ts +12 -12
  542. package/dist/workflows/events/schema.d.ts +164 -164
  543. package/dist/workflows/migration/v2-to-v3.js +1 -1
  544. package/dist/workflows/migration/v2-to-v3.js.map +1 -1
  545. package/dist/workflows/v3/architect.d.ts.map +1 -1
  546. package/dist/workflows/v3/architect.js +11 -5
  547. package/dist/workflows/v3/architect.js.map +1 -1
  548. package/dist/workflows/v3/artifact-contract-declarations.d.ts +22 -0
  549. package/dist/workflows/v3/artifact-contract-declarations.d.ts.map +1 -0
  550. package/dist/workflows/v3/artifact-contract-declarations.js +95 -0
  551. package/dist/workflows/v3/artifact-contract-declarations.js.map +1 -0
  552. package/dist/workflows/v3/contract.d.ts +1 -0
  553. package/dist/workflows/v3/contract.d.ts.map +1 -1
  554. package/dist/workflows/v3/contract.js.map +1 -1
  555. package/dist/workflows/v3/daemon-run.d.ts +2 -2
  556. package/dist/workflows/v3/daemon-run.d.ts.map +1 -1
  557. package/dist/workflows/v3/daemon-run.js +4 -0
  558. package/dist/workflows/v3/daemon-run.js.map +1 -1
  559. package/dist/workflows/v3/dag.d.ts +7 -0
  560. package/dist/workflows/v3/dag.d.ts.map +1 -1
  561. package/dist/workflows/v3/dag.js +69 -8
  562. package/dist/workflows/v3/dag.js.map +1 -1
  563. package/dist/workflows/v3/ephemeral-pool.js +1 -1
  564. package/dist/workflows/v3/ephemeral-pool.js.map +1 -1
  565. package/dist/workflows/v3/event-contract.d.ts +3 -1
  566. package/dist/workflows/v3/event-contract.d.ts.map +1 -1
  567. package/dist/workflows/v3/host.d.ts.map +1 -1
  568. package/dist/workflows/v3/host.js +5 -1
  569. package/dist/workflows/v3/host.js.map +1 -1
  570. package/dist/workflows/v3/journal.d.ts +1 -1
  571. package/dist/workflows/v3/journal.d.ts.map +1 -1
  572. package/dist/workflows/v3/journal.js.map +1 -1
  573. package/dist/workflows/v3/library-materialize.d.ts.map +1 -1
  574. package/dist/workflows/v3/library-materialize.js +9 -1
  575. package/dist/workflows/v3/library-materialize.js.map +1 -1
  576. package/dist/workflows/v3/library-schema.d.ts +3 -1
  577. package/dist/workflows/v3/library-schema.d.ts.map +1 -1
  578. package/dist/workflows/v3/library-schema.js +20 -4
  579. package/dist/workflows/v3/library-schema.js.map +1 -1
  580. package/dist/workflows/v3/library-store.d.ts.map +1 -1
  581. package/dist/workflows/v3/library-store.js +15 -3
  582. package/dist/workflows/v3/library-store.js.map +1 -1
  583. package/dist/workflows/v3/run-envelope.d.ts +16 -16
  584. package/dist/workflows/v3/shared-node-runtime.d.ts +2 -1
  585. package/dist/workflows/v3/shared-node-runtime.d.ts.map +1 -1
  586. package/dist/workflows/v3/shared-node-runtime.js +48 -7
  587. package/dist/workflows/v3/shared-node-runtime.js.map +1 -1
  588. package/package.json +2 -1
  589. package/dist/dashboard-web/chunks/agent-workbench-dock-page-IKAC5CFL.js +0 -1
  590. package/dist/dashboard-web/chunks/agent-workbench-page-M53UN5EB.js +0 -1
  591. package/dist/dashboard-web/chunks/bot-defaults-page-YKE5SDZF.js +0 -10
  592. package/dist/dashboard-web/chunks/chunk-22WIADUT.js +0 -2
  593. package/dist/dashboard-web/chunks/chunk-24ONYQMR.js +0 -1
  594. package/dist/dashboard-web/chunks/chunk-2W6SCN3M.js +0 -1
  595. package/dist/dashboard-web/chunks/chunk-4XNJX6B3.js +0 -1
  596. package/dist/dashboard-web/chunks/chunk-5THX4DI2.js +0 -66
  597. package/dist/dashboard-web/chunks/chunk-7SZRL6FY.js +0 -1
  598. package/dist/dashboard-web/chunks/chunk-AGCPF6MT.js +0 -1
  599. package/dist/dashboard-web/chunks/chunk-FXW3V4JR.js +0 -1
  600. package/dist/dashboard-web/chunks/chunk-SYC6D5XU.js +0 -1
  601. package/dist/dashboard-web/chunks/connectors-page-VOISXXII.js +0 -1
  602. package/dist/dashboard-web/chunks/feedback-page-RN6HRZMS.js +0 -1
  603. package/dist/dashboard-web/chunks/groups-page-UQT6DCB7.js +0 -8
  604. package/dist/dashboard-web/chunks/monitoring-page-NKEKVQAP.js +0 -2
  605. package/dist/dashboard-web/chunks/office-page-GVJF73XW.js +0 -1
  606. package/dist/dashboard-web/chunks/overview-page-KHLV6VTI.js +0 -1
  607. package/dist/dashboard-web/chunks/plugin-page-J3OF5IY4.js +0 -1
  608. package/dist/dashboard-web/chunks/roles-page-WQIRSOLZ.js +0 -1
  609. package/dist/dashboard-web/chunks/schedules-page-J2DEY2X6.js +0 -1
  610. package/dist/dashboard-web/chunks/sessions-page-7BQFEA5P.js +0 -8
  611. package/dist/dashboard-web/chunks/settings-page-BJEIOFJH.js +0 -2
  612. package/dist/dashboard-web/chunks/skills-page-HGIFR3IU.js +0 -4
  613. package/dist/dashboard-web/chunks/team-federation-page-MR5ZPL4B.js +0 -1
  614. package/dist/dashboard-web/chunks/v3-page-GBR5JWPE.js +0 -94
  615. package/dist/dashboard-web/chunks/whiteboards-page-QAZM4BN3.js +0 -1
  616. package/dist/services/vc-meeting-consumer-profile-store.d.ts +0 -39
  617. package/dist/services/vc-meeting-consumer-profile-store.d.ts.map +0 -1
  618. package/dist/services/vc-meeting-consumer-profile-store.js +0 -191
  619. package/dist/services/vc-meeting-consumer-profile-store.js.map +0 -1
package/dist/dashboard.js CHANGED
@@ -15,7 +15,7 @@ import { parseCookie, buildSetCookie, verifyHmac, cliAuthBind, projectWorkbenchO
15
15
  import { resolveDashboardIdentity, resolveDashboardRequestGate, } from './dashboard/request-identity.js';
16
16
  import { AuthSessionConnectionRegistry } from './dashboard/auth-session-connections.js';
17
17
  import { createDashboardEventsStream } from './dashboard/events-sse.js';
18
- import { ControlCsrfTokens, guardControlRequest, injectControlCsrfMeta, managementUpgradeOrigin, } from './dashboard/control-csrf.js';
18
+ import { ControlCsrfTokens, classifyManagementUpgrade, guardControlRequest, injectControlCsrfMeta, managementUpgradeOrigin, } from './dashboard/control-csrf.js';
19
19
  import { DaemonRegistry, botsRosterSignature } from './dashboard/registry.js';
20
20
  import { Aggregator, subscribeDaemon } from './dashboard/aggregator.js';
21
21
  import { reconcileDaemonSnapshot } from './dashboard/daemon-reconcile.js';
@@ -30,6 +30,7 @@ import { sameSessionPreviewTarget, sessionPreviewTargetStillOwned, } from './cor
30
30
  import { pickCreatorForGroup } from './dashboard/operator-selector.js';
31
31
  import { buildTeamGroupCreatePayload, planGroupCreator } from './dashboard/team-group.js';
32
32
  import { jsonRes } from './dashboard/http.js';
33
+ import { handleCustomizationApi } from './dashboard/customization-api.js';
33
34
  import { handleV3RunsApi } from './dashboard/v3-runs-api.js';
34
35
  import { defaultRunsDir as v3RunsDir } from './workflows/v3/ops-projection.js';
35
36
  import { verifyWorkflowDaemonIpcResponse, workflowDaemonIpcHeaders, WORKFLOW_DAEMON_IPC_ROUTE_PREFIX, } from './workflows/v3/daemon-ipc-auth.js';
@@ -48,6 +49,7 @@ import { FeishuLoginManager } from './dashboard/feishu-login.js';
48
49
  import { createDashboardH5AuthController, DashboardSessionStore, resolveDashboardH5AuthConfig, } from './dashboard/h5-auth.js';
49
50
  import { FileControlAuditSink } from './dashboard/control-audit.js';
50
51
  import { TerminalControlManager, terminalControlTtlFromEnv, } from './dashboard/terminal-control.js';
52
+ import { matchTerminalControlRoute, resolveTerminalControlAction, } from './dashboard/terminal-control-route.js';
51
53
  import { PreviewInteractionManager } from './dashboard/preview-interaction.js';
52
54
  import { createPreviewGuardPage } from './dashboard/preview-guard-page.js';
53
55
  import { handleWorkbenchDoctor } from './dashboard/workbench-doctor.js';
@@ -56,6 +58,7 @@ import { handleWorkbenchStandingLink } from './dashboard/standing-link.js';
56
58
  import { createTerminalFrontProxy } from './dashboard/terminal-front-proxy.js';
57
59
  import { centralViewLinkPath, mintTerminalViewCapability, terminalViewCapabilityAuthSession, terminalViewForwardProof, upstreamWorkerViewGeneration, } from './dashboard/terminal-view-capability.js';
58
60
  import { CLI_SELECT_OPTIONS, resolveCliSelection, isTtadkWrapper, ttadkAcceptsModel, TTADK_DEFAULT_MODEL, TTADK_MODEL_SUGGESTIONS, } from './setup/cli-selection.js';
61
+ import { staticModelChoices, isKnownSelectionKey, buildModelChoicesResponse, } from './services/model-catalog.js';
59
62
  import { checkCliAvailability } from './setup/cli-availability.js';
60
63
  import { invalidWorkingDirs } from './utils/working-dir.js';
61
64
  import { invalidateGlobalConfigCache, mergeDashboardConfig, mergeGlobalConfig, readGlobalConfig } from './global-config.js';
@@ -97,17 +100,16 @@ import { enrichPackForDashboard, enrichPacksForDashboard, sanitizeSkillForDashbo
97
100
  import { effectiveDefaultWorkingDir, getBot, loadBotConfigs, parseBotConfigsFromText } from './bot-registry.js';
98
101
  import { addChatToFeedGroup, createFeedGroup, FEED_GROUP_SCOPES, FeedGroupApiError, listFeedGroups } from './dashboard/feed-groups.js';
99
102
  import { generateAuthUrl, handleCallbackUrl, isCallbackUrl } from './utils/user-token.js';
100
- import { findEntryIndex, readRawConfig, requireConfigPath, writeRawConfigAtomic } from './services/config-store.js';
103
+ import { findEntryIndex, readRawConfig, requireConfigPath, rmwBotEntry, writeRawConfigAtomic } from './services/config-store.js';
101
104
  import { emitCodexNotifierOutboxItem, installCodexNotifierHook, isCodexNotifierWorkerStateFresh, isCodexNotifierHookInstalled, listCodexNotifierOutbox, readCodexNotifierWorkerState, resolveCodexNotifierConfig, runCodexSideConversationMonitor, runCodexNotifierWorkerSupervisor, } from './features/codex-notifier/index.js';
102
105
  import { discoverNativeCliSkillGroups } from './core/skills/discovery.js';
103
106
  import { analyzeSkillReferences, packsContainingSkill } from './core/skills/references.js';
104
107
  import { discoverDashboardSkills, installDashboardSkill, parseDashboardSkillInstallRequest, parseInstallLocalLinksSources, MAX_LOCAL_LINK_SOURCES } from './dashboard/skill-install-request.js';
105
108
  import { botDefaultsPayload, botSummaryPayload, brandMapByAppId } from './dashboard/bot-payload.js';
106
109
  import { handleVcMeetingConsumerProfilesGet, handleVcMeetingConsumerProfilesPut, } from './dashboard/vc-consumer-profiles-api.js';
107
- import { buildVcMeetingConsumerBootstrapAgents, seedVcMeetingDefaultConsumerProfile, } from './services/vc-meeting-consumer-profile-bootstrap.js';
108
110
  import { evaluateVcMeetingConsumerIsolation } from './services/vc-meeting-consumer-isolation.js';
109
111
  import { resolvePairedSpawnBackendType } from './core/persistent-backend.js';
110
- import { readVcMeetingConsumerProfiles, updateVcMeetingConsumerProfiles, } from './services/vc-meeting-consumer-profile-store.js';
112
+ import { readVcMeetingSharedConsumerCatalogSnapshot, updateVcMeetingSharedConsumerCatalog, } from './services/vc-meeting-shared-consumer-catalog-store.js';
111
113
  import { isValidRoleProfileId } from './services/role-profile-store.js';
112
114
  import { mergeSafeInsightOverviews } from './services/insight/report.js';
113
115
  import { readPlatformBinding } from './platform/binding.js';
@@ -138,6 +140,7 @@ import { inspectGatewayEntry } from './core/plugins/mcp/gateway-installer.js';
138
140
  import { fetchDaemonIpc } from './core/daemon-ipc-auth.js';
139
141
  import { buildDashboardSummary, parseDashboardSummaryRows, } from './dashboard/dashboard-summary.js';
140
142
  import { createDashboardSummaryEndpoint } from './dashboard/dashboard-summary-endpoint.js';
143
+ import { createDashboardAutostartController, DashboardAutostartError, dashboardAutostartErrorStatus, parseAutostartWrite, } from './dashboard/autostart-api.js';
141
144
  import { scrubWorkflowWorkerEnv } from './utils/child-env.js';
142
145
  // The dashboard is an independent long-lived PM2 app and can be resurrected
143
146
  // from a stale dump.pm2 without passing through cli.ts pm2Env(). Its start/stop
@@ -147,6 +150,14 @@ import { scrubWorkflowWorkerEnv } from './utils/child-env.js';
147
150
  scrubWorkflowWorkerEnv(process.env);
148
151
  const SECRET_PATH = dashboardSecretPath();
149
152
  const TOKEN_PATH = join(homedir(), '.botmux', '.dashboard-token');
153
+ const AUTOSTART_CONFIG_DIR = join(homedir(), '.botmux');
154
+ const dashboardAutostart = createDashboardAutostartController({
155
+ opts: {
156
+ pkgRoot: botmuxInstallRoot(),
157
+ configDir: AUTOSTART_CONFIG_DIR,
158
+ logDir: join(AUTOSTART_CONFIG_DIR, 'logs'),
159
+ },
160
+ });
150
161
  /** Per-daemon budget for the cross-daemon insight overview fan-out — bounds
151
162
  * aggregate latency when one daemon's insight parse is slow or hung. */
152
163
  const INSIGHT_FANOUT_TIMEOUT_MS = 10_000;
@@ -527,6 +538,11 @@ aggregator.on(sessionPresentation.onEvent);
527
538
  // 让 owner 从熟悉的目录起终端复现问题;都没有时模块内退回 homedir。
528
539
  const debugTerminalManager = createDebugTerminalManager({
529
540
  getActiveToken: currentDashboardToken,
541
+ // WS 升级不经 HTTP auth gate,所以在这里把 `/api/debug-terminal` 那条 `legacyAuthed`
542
+ // 门禁原样喂进去:解析出的身份必须是本机 legacy 管理身份,平台隧道注入的角色
543
+ // (X-Botmux-Role)不算——它带的也是本机活跃 cookie,只比 cookie 会把裸 shell
544
+ // 开放给平台上的任何人。
545
+ isLegacyManagementRequest: (req) => dashboardRequestIdentity(req)?.kind === 'legacy-dashboard',
530
546
  defaultWorkingDirs: () => {
531
547
  const dirs = new Set();
532
548
  for (const s of aggregator.getSessions()) {
@@ -621,44 +637,6 @@ const botOnboarding = new BotOnboardingManager({
621
637
  const feishuLogin = new FeishuLoginManager();
622
638
  const subs = new Map();
623
639
  const attaching = new Set(); // dedup concurrent attaches per appId
624
- function vcMeetingListenerBotOptions() {
625
- try {
626
- const onlineByAppId = new Map(registry.list().map(bot => [bot.larkAppId, bot]));
627
- // Exclude core-only (apiOnly) bots: a VC listener attends real Feishu
628
- // meetings and needs open-platform scopes + a live Lark connection, which a
629
- // no-Feishu bot categorically cannot have. Offering it would let setup
630
- // raw-fetch token/application APIs with its synthetic/empty credentials.
631
- return loadBotConfigs().filter(bot => bot.apiOnly !== true).map(bot => ({
632
- larkAppId: bot.larkAppId,
633
- botName: bot.displayName ?? onlineByAppId.get(bot.larkAppId)?.botName ?? bot.name ?? null,
634
- cliId: onlineByAppId.get(bot.larkAppId)?.cliId ?? bot.cliId,
635
- vcMeetingAgentEnabled: bot.vcMeetingAgent?.enabled === true,
636
- hasLarkCliProfile: typeof bot.vcMeetingAgent?.larkCliProfile === 'string' && bot.vcMeetingAgent.larkCliProfile.trim().length > 0,
637
- }));
638
- }
639
- catch {
640
- return [];
641
- }
642
- }
643
- async function validateVcMeetingListenerBotAppId(appId) {
644
- let bots;
645
- try {
646
- bots = loadBotConfigs();
647
- }
648
- catch (err) {
649
- return { ok: false, error: `vcMeetingAgent_listenerBot_config_unavailable: ${err?.message ?? err}` };
650
- }
651
- const bot = bots.find(b => b.larkAppId === appId);
652
- if (!bot)
653
- return { ok: false, error: 'vcMeetingAgent_listenerBot_unknown' };
654
- // Core-only (apiOnly) bots cannot attend Feishu meetings (no Feishu connection,
655
- // no open-platform scopes). Reject at the settings WRITE boundary so a manual
656
- // PUT can't select one and drive syncVcMeetingListenerBotConfig →
657
- // automateOpenPlatformSetup against the open platform with synthetic creds.
658
- if (bot.apiOnly === true)
659
- return { ok: false, error: 'vcMeetingAgent_listenerBot_api_only' };
660
- return { ok: true };
661
- }
662
640
  async function validateCodexNotifierTargetBotAppId(appId, options = {}) {
663
641
  try {
664
642
  const bot = loadBotConfigs().find(candidate => candidate.larkAppId === appId);
@@ -774,13 +752,38 @@ function refreshLocalVcMeetingAgentConfig(appId) {
774
752
  // This dashboard process may not host the target bot daemon.
775
753
  }
776
754
  }
755
+ /** Map appId → persisted Feishu-probed botName from bots-info.json (offline
756
+ * bots keep a friendly name in the dashboard). Best-effort; empty on any error. */
757
+ function readPersistedBotNames() {
758
+ const out = new Map();
759
+ try {
760
+ const fp = join(config.session.dataDir, 'bots-info.json');
761
+ if (!existsSync(fp))
762
+ return out;
763
+ const entries = JSON.parse(readFileSync(fp, 'utf8'));
764
+ if (!Array.isArray(entries))
765
+ return out;
766
+ for (const e of entries) {
767
+ if (typeof e?.larkAppId === 'string' && typeof e?.botName === 'string' && e.botName.trim()) {
768
+ out.set(e.larkAppId, e.botName.trim());
769
+ }
770
+ }
771
+ }
772
+ catch { /* best-effort */ }
773
+ return out;
774
+ }
777
775
  function vcMeetingConsumerProfilesApiDeps() {
776
+ // Persisted Feishu-probed names, so an OFFLINE bot still shows its friendly
777
+ // name in the agent dropdown instead of falling back to the raw appId. The
778
+ // live registry only knows online bots; bots-info.json is written when a bot
779
+ // is probed and survives across restarts. Built once per deps construction.
780
+ const persistedBotNames = readPersistedBotNames();
778
781
  return {
779
- readSnapshot: readVcMeetingConsumerProfiles,
780
- updateSnapshot: updateVcMeetingConsumerProfiles,
782
+ readCatalog: readVcMeetingSharedConsumerCatalogSnapshot,
783
+ updateCatalog: updateVcMeetingSharedConsumerCatalog,
781
784
  loadBotConfigs,
782
785
  effectiveDefaultWorkingDir,
783
- onlineBotName: appId => registry.getByAppId(appId)?.botName,
786
+ onlineBotName: appId => registry.getByAppId(appId)?.botName ?? persistedBotNames.get(appId),
784
787
  isOnline: appId => !!registry.getByAppId(appId),
785
788
  adapterReliableTurnTerminal: (cliId, cliPathOverride) => {
786
789
  if (!cliId)
@@ -806,6 +809,60 @@ function vcMeetingConsumerProfilesApiDeps() {
806
809
  return decision.ok && decision.isolated;
807
810
  },
808
811
  reloadDaemons: reloadVcMeetingBotConfigOnDaemons,
812
+ applyBotOutputPolicy: async (patch) => {
813
+ const res = await rmwBotEntry(patch.appId, (entry) => {
814
+ const vc = (entry.vcMeetingAgent && typeof entry.vcMeetingAgent === 'object' && !Array.isArray(entry.vcMeetingAgent))
815
+ ? entry.vcMeetingAgent
816
+ : {};
817
+ // 「接收会议事件」开关。VC 对每个连着飞书的 bot 默认可用,`enabled: false`
818
+ // 才是显式退出——所以打开时删掉这个 key 回到默认,而不是写 `enabled: true`。
819
+ if (patch.vcEnabled)
820
+ delete vc.enabled;
821
+ else
822
+ vc.enabled = false;
823
+ const consumer = (vc.meetingConsumer && typeof vc.meetingConsumer === 'object' && !Array.isArray(vc.meetingConsumer))
824
+ ? vc.meetingConsumer
825
+ : {};
826
+ if (patch.textOutputPolicy === null)
827
+ delete consumer.textOutputPolicy;
828
+ else
829
+ consumer.textOutputPolicy = patch.textOutputPolicy;
830
+ if (patch.voiceOutputPolicy === null)
831
+ delete consumer.voiceOutputPolicy;
832
+ else
833
+ consumer.voiceOutputPolicy = patch.voiceOutputPolicy;
834
+ // per-bot 默认角色:null/空 = 跟随全局默认(删 key);否则写 catalogDefaultConsumerId。
835
+ if (patch.catalogDefaultConsumerId === null || patch.catalogDefaultConsumerId === '') {
836
+ delete consumer.catalogDefaultConsumerId;
837
+ }
838
+ else {
839
+ consumer.catalogDefaultConsumerId = patch.catalogDefaultConsumerId;
840
+ }
841
+ if (Object.keys(consumer).length > 0)
842
+ vc.meetingConsumer = consumer;
843
+ else
844
+ delete vc.meetingConsumer;
845
+ const rtv = (vc.realtimeVoice && typeof vc.realtimeVoice === 'object' && !Array.isArray(vc.realtimeVoice))
846
+ ? vc.realtimeVoice
847
+ : {};
848
+ // 实时语音能力默认开启(未配 = 开)。所以「勾上」= 回到默认,删掉 enabled key
849
+ // (避免写死 true,与其它默认字段的处理一致);「取消勾选」= 必须写显式 false
850
+ // 才能真正关掉(保留其它 realtimeVoice 设置如采样率)。
851
+ if (patch.realtimeVoiceEnabled) {
852
+ delete rtv.enabled;
853
+ }
854
+ else {
855
+ rtv.enabled = false;
856
+ }
857
+ if (Object.keys(rtv).length > 0)
858
+ vc.realtimeVoice = rtv;
859
+ else
860
+ delete vc.realtimeVoice;
861
+ entry.vcMeetingAgent = vc;
862
+ return { write: true, result: undefined };
863
+ });
864
+ return res.ok ? { ok: true } : { ok: false, reason: res.reason };
865
+ },
809
866
  };
810
867
  }
811
868
  async function reloadVcMeetingBotConfigOnDaemons(appIds) {
@@ -913,226 +970,165 @@ async function waitForFeishuLoginQr(timeoutMs = 8_000, intervalMs = 200) {
913
970
  }
914
971
  return null;
915
972
  }
916
- async function syncVcMeetingListenerBotConfig(listenerBotAppId, previousListenerBotAppId) {
917
- const nextAppId = listenerBotAppId?.trim() || null;
918
- const prevAppId = previousListenerBotAppId?.trim() || null;
919
- if (!nextAppId && !prevAppId)
920
- return { ok: true };
921
- // Defense-in-depth: even though the settings validator rejects apiOnly, guard
922
- // the sync entry too so no caller reaches automateOpenPlatformSetup / the
923
- // open-platform raw fetches for a core-only bot.
924
- if (nextAppId) {
925
- try {
926
- const bot = loadBotConfigs().find(b => b.larkAppId === nextAppId);
927
- if (bot?.apiOnly === true) {
928
- return { ok: false, error: 'vcMeetingAgent_listenerBot_api_only' };
929
- }
930
- }
931
- catch { /* fall through to normal errors below */ }
973
+ /**
974
+ * 让某个 bot 具备「收会议事件 + 以 bot 身份入会」的开放平台前置条件。
975
+ *
976
+ * 这是全局「会议事件接收 Bot」下拉退役后留下的唯一实质工作:那个下拉真正干的事
977
+ * 不是「选一个人来监听」(daemon 侧早已改成谁收到谁处理),而是顺手替被选中的 bot
978
+ * 开权限、订事件、装 larkCliProfile。所以下拉删掉,这段保留,改成按 bot 手动触发
979
+ * 的一次性动作(Dashboard 的「配置权限」按钮)——不能在勾选开关时自动跑:
980
+ * 「接收会议事件」默认就是开的,压根没有 off→on 的跃迁可挂;也不能在页面加载时
981
+ * 对整个 fleet 跑,47 个 bot 就是 94 次开放平台调用。
982
+ *
983
+ * 与旧实现的关键差异:这里**只做前置条件**,绝不再往 meetingConsumer 里塞默认角色。
984
+ * 旧的 seedVcMeetingDefaultConsumerProfile 会把「另一个 bot」的 appId 焊进预设,
985
+ * 正是「拉 A 进会却把 B 拉进群」的源头。
986
+ */
987
+ async function preflightVcMeetingBot(appId) {
988
+ const targetAppId = appId?.trim() || null;
989
+ if (!targetAppId)
990
+ return { ok: false, error: 'vcMeetingBot_preflight_missing_appId' };
991
+ let bots;
992
+ try {
993
+ bots = loadBotConfigs();
932
994
  }
933
- // Require lark-cli >= MIN_LARK_CLI_VERSION_FOR_VC_BOT for VC bot meeting commands
934
- // (vc +meeting-join/events/message-send --as bot). Earlier versions silently reject
935
- // `--as bot` with "this command only supports: user", so the listener bot can
936
- // never actually join a meeting.
937
- if (nextAppId) {
938
- const larkCli = checkLarkCliVersion();
939
- if (!larkCli) {
940
- return { ok: false, error: 'vcMeetingAgent_listenerBot_larkCli_not_found: 未检测到 lark-cli,请先安装 `npm i -g @larksuite/cli`' };
941
- }
942
- if (!larkCli.meetsVcBotRequirement) {
943
- return {
944
- ok: false,
945
- error: `vcMeetingAgent_listenerBot_larkCli_too_old: 当前 lark-cli ${larkCli.version} 不支持 VC bot 入会,需要 >= ${MIN_LARK_CLI_VERSION_FOR_VC_BOT}。请运行 \`npm i -g @larksuite/cli@latest\` 升级`,
946
- };
995
+ catch (err) {
996
+ return { ok: false, error: `vcMeetingBot_preflight_config_unavailable: ${err?.message ?? err}` };
997
+ }
998
+ const bot = bots.find(b => b.larkAppId === targetAppId);
999
+ if (!bot)
1000
+ return { ok: false, error: 'vcMeetingBot_preflight_bot_not_found' };
1001
+ // apiOnly bot 结构上就收不到飞书事件,别让它把 automateOpenPlatformSetup /
1002
+ // 开放平台裸 fetch 跑起来(写边界拦住,手搓 POST 也进不去)。
1003
+ if (bot.apiOnly === true)
1004
+ return { ok: false, error: 'vcMeetingBot_preflight_api_only' };
1005
+ // VC bot 入会命令(vc +meeting-join/events/message-send --as bot)要求
1006
+ // lark-cli >= MIN_LARK_CLI_VERSION_FOR_VC_BOT;更老的版本会以
1007
+ // "this command only supports: user" 静默拒绝 `--as bot`。
1008
+ const larkCli = checkLarkCliVersion();
1009
+ if (!larkCli) {
1010
+ return { ok: false, error: 'vcMeetingBot_preflight_larkCli_not_found: 未检测到 lark-cli,请先安装 `npm i -g @larksuite/cli`' };
1011
+ }
1012
+ if (!larkCli.meetsVcBotRequirement) {
1013
+ return {
1014
+ ok: false,
1015
+ error: `vcMeetingBot_preflight_larkCli_too_old: 当前 lark-cli ${larkCli.version} 不支持 VC bot 入会,需要 >= ${MIN_LARK_CLI_VERSION_FOR_VC_BOT}。请运行 \`npm i -g @larksuite/cli@latest\` 升级`,
1016
+ };
1017
+ }
1018
+ // 开放平台自动化只支持 feishu.cn;`brand: 'lark'` 的 bot 跳过自动化,但仍然校验
1019
+ // 权限是否已具备,免得报「配置好了」其实收不到事件。
1020
+ const brand = bot.brand === 'lark' ? 'lark' : 'feishu';
1021
+ if (brand === 'lark') {
1022
+ logger.info(`[vc-agent] skipping open-platform automation for lark-brand bot ${targetAppId} (feishu.cn only)`);
1023
+ const scopeCheck = await validateVcMeetingScopesForBot(bot);
1024
+ if (!scopeCheck.ok) {
1025
+ return { ok: false, error: `vcMeetingBot_preflight_missing_scopes: ${scopeCheck.error}` };
947
1026
  }
948
1027
  }
949
- // Best-effort auto-import VC meeting scopes via Open Platform automation.
950
- // Run BEFORE writing bots.json so that hard failures (missing session, needs QR)
951
- // don't leave per-bot vcMeetingAgent in a half-configured state.
952
- // For `brand: 'lark'` bots the open-platform automation only supports feishu.cn;
953
- // skip it silently and let the user configure manually.
954
- if (nextAppId) {
955
- const bots = loadBotConfigs();
956
- const bot = bots.find(b => b.larkAppId === nextAppId);
957
- const brand = bot?.brand === 'lark' ? 'lark' : 'feishu';
958
- if (brand === 'lark') {
959
- logger.info(`[vc-agent] skipping open-platform automation for lark-brand bot ${nextAppId} (feishu.cn only)`);
960
- // For lark brand, still validate that required scopes exist before saving
961
- if (bot) {
1028
+ else {
1029
+ try {
1030
+ const result = await automateOpenPlatformSetup({
1031
+ appId: targetAppId,
1032
+ brand,
1033
+ maxWaitMs: 5_000,
1034
+ onStatus: (msg) => logger.info(`[vc-agent] scope auto-import: ${msg}`),
1035
+ });
1036
+ if (result.ok) {
1037
+ logger.info(`[vc-agent] auto-imported ${result.scopeCount} scopes, subscribed ${result.subscribedEventCount} events for bot ${targetAppId}`);
1038
+ if (result.scopeWarning)
1039
+ logger.warn(`[vc-agent] scope import warning: ${result.scopeWarning}`);
1040
+ if (result.eventWarning)
1041
+ logger.warn(`[vc-agent] event subscription warning: ${result.eventWarning}`);
1042
+ // 自动化「成功」不等于权限真开了:internal scope/update 可能静默跳过本租户
1043
+ // 不可用的 scope。必须回读一次,否则会给用户一个「已配置」的假绿灯。
962
1044
  const scopeCheck = await validateVcMeetingScopesForBot(bot);
963
1045
  if (!scopeCheck.ok) {
964
- return { ok: false, error: `vcMeetingAgent_listenerBot_missing_scopes: ${scopeCheck.error}` };
1046
+ return {
1047
+ ok: false,
1048
+ error: `vcMeetingBot_preflight_missing_scopes_after_auto: ${scopeCheck.error}。请到开放平台手动开通 VC 会议权限后重试。`,
1049
+ };
1050
+ }
1051
+ // 事件订阅同样关键:缺任一 VC 事件都收不到会议邀请(用 missingVcEvents 判定,
1052
+ // 总 count 无法区分缺的是不是 VC)。
1053
+ const eventGateError = vcListenerEventGateError(result);
1054
+ if (eventGateError) {
1055
+ return {
1056
+ ok: false,
1057
+ error: `vcMeetingBot_preflight_event_subscribe_failed: ${eventGateError},bot 无法接收会议邀请事件。请到开放平台手动订阅 VC 会议事件后重试。`,
1058
+ };
965
1059
  }
966
1060
  }
967
- }
968
- else {
969
- try {
970
- const result = await automateOpenPlatformSetup({
971
- appId: nextAppId,
972
- brand,
973
- maxWaitMs: 5_000,
974
- onStatus: (msg) => logger.info(`[vc-agent] scope auto-import: ${msg}`),
975
- });
976
- if (result.ok) {
977
- logger.info(`[vc-agent] auto-imported ${result.scopeCount} scopes, subscribed ${result.subscribedEventCount} events for listener bot ${nextAppId}`);
978
- if (result.scopeWarning)
979
- logger.warn(`[vc-agent] scope import warning: ${result.scopeWarning}`);
980
- if (result.eventWarning)
981
- logger.warn(`[vc-agent] event subscription warning: ${result.eventWarning}`);
982
- // Post-validation: verify VC meeting scopes are actually granted after automation.
983
- // The internal scope/update may silently skip some scopes (e.g. not available
984
- // in this tenant). Without this check, a bot without VC scopes could be saved
985
- // as global listener and silently drop all meeting events.
986
- if (bot) {
987
- const scopeCheck = await validateVcMeetingScopesForBot(bot);
988
- if (!scopeCheck.ok) {
989
- return {
990
- ok: false,
991
- error: `vcMeetingAgent_listenerBot_missing_scopes_after_auto: ${scopeCheck.error}。请到开放平台手动开通 VC 会议权限后重试。`,
992
- };
993
- }
994
- }
995
- // Event subscription is also critical: listener 缺任一 VC 事件都收不到
996
- // 会议邀请(missingVcEvents 判定,总 count 无法区分缺的是不是 VC)。
997
- const eventGateError = vcListenerEventGateError(result);
998
- if (eventGateError) {
999
- return {
1000
- ok: false,
1001
- error: `vcMeetingAgent_listenerBot_event_subscribe_failed: ${eventGateError},bot 无法接收会议邀请事件。请到开放平台手动订阅 VC 会议事件后重试。`,
1002
- };
1003
- }
1061
+ else {
1062
+ const reason = result.reason;
1063
+ // 登录/会话类失败是硬失败:没有有效的开放平台会话就无从自动配置,直接把
1064
+ // 扫码二维码回给前端。
1065
+ if (reason === 'missing_session'
1066
+ || reason === 'invalid_session'
1067
+ || reason === 'missing_csrf'
1068
+ || reason === 'qr_expired'
1069
+ || reason === 'timeout'
1070
+ || reason === 'login_failed') {
1071
+ feishuLogin.start();
1072
+ // start() 立刻返回 status='starting',二维码是在 onQrCode 里异步塞进去的;
1073
+ // 稍等一下拿到再回,前端才能直接内联展示而不是只给一句错误。
1074
+ const qrDataUrl = await waitForFeishuLoginQr();
1075
+ const hint = '请用飞书扫码完成开放平台登录,登录后重新点「配置权限」即可自动开通';
1076
+ return {
1077
+ ok: false,
1078
+ error: `vcMeetingBot_preflight_scope_auto_import_failed: ${reason}: ${hint}`,
1079
+ feishuLoginQr: qrDataUrl ?? undefined,
1080
+ };
1004
1081
  }
1005
- else {
1006
- const reason = result.reason;
1007
- // Session/login-related failures are hard failures return QR so user can re-login.
1008
- // Without a valid Open Platform session, scope/event auto-import is impossible.
1009
- if (reason === 'missing_session'
1010
- || reason === 'invalid_session'
1011
- || reason === 'missing_csrf'
1012
- || reason === 'qr_expired'
1013
- || reason === 'timeout'
1014
- || reason === 'login_failed') {
1015
- feishuLogin.start();
1016
- // feishuLogin.start() returns immediately with status='starting'; the QR
1017
- // code is set asynchronously in onQrCode. Wait briefly for it to be ready
1018
- // so the frontend can display it inline instead of showing an error without
1019
- // a scan entry.
1020
- const qrDataUrl = await waitForFeishuLoginQr();
1021
- const hint = '请用飞书扫码完成开放平台登录,登录后重新选择监听 bot 即可自动配置权限';
1022
- return {
1023
- ok: false,
1024
- error: `vcMeetingAgent_listenerBot_scope_auto_import_failed: ${reason}: ${hint}`,
1025
- feishuLoginQr: qrDataUrl ?? undefined,
1026
- };
1027
- }
1028
- // Non-login failures (network, api_error, etc.) are best-effort — don't
1029
- // block the save. The user can fix scopes manually in the console.
1030
- logger.warn(`[vc-agent] open-platform automation failed for ${nextAppId}: ${reason}: ${result.message}`);
1031
- // Even on non-login automation failure, verify scopes before saving —
1032
- // if the bot genuinely lacks VC permissions, don't silently make it listener.
1033
- if (bot) {
1034
- const scopeCheck = await validateVcMeetingScopesForBot(bot);
1035
- if (!scopeCheck.ok) {
1036
- return {
1037
- ok: false,
1038
- error: `vcMeetingAgent_listenerBot_missing_scopes: ${scopeCheck.error}。自动化配置失败(${reason})且权限未满足,请手动开通后重试。`,
1039
- };
1040
- }
1041
- }
1042
- // Also check event subscription status — automation 走到订阅阶段时
1043
- // missingVcEvents 会带回来;listener 缺任一 VC 事件都不能保存。
1044
- const eventGateError = vcListenerEventGateError(result);
1045
- if (eventGateError) {
1046
- return {
1047
- ok: false,
1048
- error: `vcMeetingAgent_listenerBot_event_subscribe_failed: ${eventGateError},bot 无法接收会议邀请事件。自动化配置失败(${reason}),请手动订阅 VC 会议事件后重试。`,
1049
- };
1050
- }
1082
+ // 非登录类失败(网络、api_error 等)是 best-effort,不因此判死;但权限与事件
1083
+ // 订阅仍然要回读确认,否则等于谎报配置成功。
1084
+ logger.warn(`[vc-agent] open-platform automation failed for ${targetAppId}: ${reason}: ${result.message}`);
1085
+ const scopeCheck = await validateVcMeetingScopesForBot(bot);
1086
+ if (!scopeCheck.ok) {
1087
+ return {
1088
+ ok: false,
1089
+ error: `vcMeetingBot_preflight_missing_scopes: ${scopeCheck.error}。自动化配置失败(${reason})且权限未满足,请手动开通后重试。`,
1090
+ };
1091
+ }
1092
+ const eventGateError = vcListenerEventGateError(result);
1093
+ if (eventGateError) {
1094
+ return {
1095
+ ok: false,
1096
+ error: `vcMeetingBot_preflight_event_subscribe_failed: ${eventGateError},bot 无法接收会议邀请事件。自动化配置失败(${reason}),请手动订阅 VC 会议事件后重试。`,
1097
+ };
1051
1098
  }
1052
- }
1053
- catch (err) {
1054
- logger.warn(`[vc-agent] open-platform automation error for ${nextAppId}: ${err?.message ?? err}`);
1055
1099
  }
1056
1100
  }
1101
+ catch (err) {
1102
+ logger.warn(`[vc-agent] open-platform automation error for ${targetAppId}: ${err?.message ?? err}`);
1103
+ }
1057
1104
  }
1058
- const changedAppIds = new Set();
1105
+ // 唯一的落盘:补一个默认 larkCliProfile。既不写 enabled(默认就是接收),也不碰
1106
+ // meetingConsumer——角色预设归 fleet 共享目录管,这里不产生任何 per-bot 预设。
1107
+ let changed = false;
1059
1108
  try {
1060
1109
  const path = requireConfigPath();
1061
1110
  await withFileLock(path, async () => {
1062
1111
  const raw = await readRawConfig(path);
1063
- let changed = false;
1064
- if (nextAppId) {
1065
- const idx = findEntryIndex(raw, nextAppId);
1066
- if (idx < 0)
1067
- throw new Error('bot_not_in_config');
1068
- const entry = raw[idx];
1069
- const next = normalizeVcMeetingAgentRecord(entry.vcMeetingAgent);
1070
- let entryChanged = false;
1071
- const firstEnable = next.enabled !== true;
1072
- if (firstEnable) {
1073
- next.enabled = true;
1074
- next.dashboardManagedListener = true;
1075
- entryChanged = true;
1076
- }
1077
- if (!next.larkCliProfile) {
1078
- next.larkCliProfile = nextAppId;
1079
- entryChanged = true;
1080
- }
1081
- const mc = next.meetingConsumer;
1082
- const mcRec = mc && typeof mc === 'object' && !Array.isArray(mc)
1083
- ? { ...mc }
1084
- : {};
1085
- // Selecting a global listener is the Dashboard's explicit opt-in to the
1086
- // complete meeting pipeline. It intentionally re-enables the listener's
1087
- // consumer surface; profile/default ownership is still preserved by the
1088
- // own-property gates in seedVcMeetingDefaultConsumerProfile below.
1089
- if (mcRec.enabled !== true) {
1090
- mcRec.enabled = true;
1091
- entryChanged = true;
1092
- }
1093
- if (seedVcMeetingDefaultConsumerProfile(mcRec, nextAppId,
1094
- // Resolve against the latest locked bots.json snapshot, not a stale
1095
- // pre-lock load. This also makes fallback selection independent of
1096
- // the order in which bot entries happen to be stored.
1097
- buildVcMeetingConsumerBootstrapAgents(parseBotConfigsFromText(JSON.stringify(raw))))) {
1098
- entryChanged = true;
1099
- }
1100
- next.meetingConsumer = mcRec;
1101
- if (entryChanged) {
1102
- compactVcMeetingAgentEntry(entry, next);
1103
- changed = true;
1104
- changedAppIds.add(nextAppId);
1105
- }
1106
- }
1107
- if (prevAppId && prevAppId !== nextAppId) {
1108
- const idx = findEntryIndex(raw, prevAppId);
1109
- if (idx >= 0) {
1110
- const entry = raw[idx];
1111
- const next = normalizeVcMeetingAgentRecord(entry.vcMeetingAgent);
1112
- if (next.dashboardManagedListener === true) {
1113
- delete next.dashboardManagedListener;
1114
- if (next.enabled === true)
1115
- delete next.enabled;
1116
- compactVcMeetingAgentEntry(entry, next);
1117
- changed = true;
1118
- changedAppIds.add(prevAppId);
1119
- }
1120
- }
1121
- }
1122
- if (changed) {
1123
- // Validate the complete post-mutation file before replacing bots.json.
1124
- // Keep this path symmetric with daemon bootstrap so a future generated
1125
- // default cannot make the Dashboard persist an invalid registry.
1126
- parseBotConfigsFromText(JSON.stringify(raw));
1127
- await writeRawConfigAtomic(path, raw);
1128
- }
1112
+ const idx = findEntryIndex(raw, targetAppId);
1113
+ if (idx < 0)
1114
+ throw new Error('bot_not_in_config');
1115
+ const entry = raw[idx];
1116
+ const next = normalizeVcMeetingAgentRecord(entry.vcMeetingAgent);
1117
+ if (next.larkCliProfile)
1118
+ return;
1119
+ next.larkCliProfile = targetAppId;
1120
+ compactVcMeetingAgentEntry(entry, next);
1121
+ // 落盘前整份校验,和 daemon bootstrap 保持对称,避免 Dashboard 写出非法 registry。
1122
+ parseBotConfigsFromText(JSON.stringify(raw));
1123
+ await writeRawConfigAtomic(path, raw);
1124
+ changed = true;
1129
1125
  });
1130
1126
  }
1131
1127
  catch (err) {
1132
- return { ok: false, error: `vcMeetingAgent_listenerBot_config_write_failed: ${err?.message ?? err}` };
1128
+ return { ok: false, error: `vcMeetingBot_preflight_config_write_failed: ${err?.message ?? err}` };
1133
1129
  }
1134
- if (changedAppIds.size > 0)
1135
- await reloadVcMeetingBotConfigOnDaemons([...changedAppIds]);
1130
+ if (changed)
1131
+ await reloadVcMeetingBotConfigOnDaemons([targetAppId]);
1136
1132
  return { ok: true };
1137
1133
  }
1138
1134
  function resolveDashboardSettings() {
@@ -1184,8 +1180,6 @@ function resolveDashboardSettings() {
1184
1180
  noVisibleOutputHint: dashboard.noVisibleOutputHint === true, // default OFF; opt-in anti-resend guidance
1185
1181
  vcMeetingAgent: {
1186
1182
  enabled: global.vcMeetingAgent?.enabled !== false,
1187
- listenerBotAppId: global.vcMeetingAgent?.listenerBotAppId ?? null,
1188
- listenerBotOptions: vcMeetingListenerBotOptions(),
1189
1183
  larkCliVersion: larkCli?.version ?? null,
1190
1184
  larkCliMeetsRequirement: larkCli?.meetsVcBotRequirement ?? false,
1191
1185
  larkCliMinVersion: MIN_LARK_CLI_VERSION_FOR_VC_BOT,
@@ -1209,8 +1203,6 @@ async function reloadLocaleOnAllDaemons() {
1209
1203
  await Promise.all(registry.list().map(d => fetchDaemonIpc(d.ipcPort, '/api/locale/reload', { method: 'POST' }).catch(() => undefined)));
1210
1204
  }
1211
1205
  const settingsWriteApplierDeps = defaultSettingsWriteApplierDeps(resolveDashboardSettings, reloadLocaleOnAllDaemons);
1212
- settingsWriteApplierDeps.syncVcMeetingListenerBotConfig = syncVcMeetingListenerBotConfig;
1213
- settingsWriteApplierDeps.validateVcMeetingListenerBotAppId = validateVcMeetingListenerBotAppId;
1214
1206
  settingsWriteApplierDeps.validateCodexNotifierTargetBotAppId = validateCodexNotifierTargetBotAppId;
1215
1207
  settingsWriteApplierDeps.validateHostOverloadAlertTargetBotAppId = validateHostOverloadAlertTargetBotAppId;
1216
1208
  /** Helper to render a {status, body} HandlerResult through `res`. */
@@ -2140,6 +2132,7 @@ function configuredBotAgentFields() {
2140
2132
  model: b.model,
2141
2133
  reasoningEffort: b.reasoningEffort,
2142
2134
  turnTimeoutMs: b.turnTimeoutMs,
2135
+ dshRuntime: b.dshRuntime,
2143
2136
  }]));
2144
2137
  }
2145
2138
  catch {
@@ -2158,6 +2151,7 @@ function withConfiguredCliId(bot, ids) {
2158
2151
  model: bot.model || fallback?.model,
2159
2152
  reasoningEffort: bot.reasoningEffort || fallback?.reasoningEffort,
2160
2153
  turnTimeoutMs: bot.turnTimeoutMs ?? fallback?.turnTimeoutMs,
2154
+ dshRuntime: bot.dshRuntime ?? fallback?.dshRuntime,
2161
2155
  };
2162
2156
  }
2163
2157
  function liveBots() {
@@ -3159,46 +3153,41 @@ const server = createServer(async (req, res) => {
3159
3153
  // Server-authoritative terminal control lease. The API returns only mode
3160
3154
  // and timestamps; its signed read/write grant stays inside the central
3161
3155
  // proxy and is never placed in a URL or response body.
3162
- let controlMatch = url.pathname.match(/^\/api\/sessions\/([^/]+)\/control(?:\/(takeover|release))?$/);
3163
- if (controlMatch) {
3156
+ //
3157
+ // The dispatch itself lives in dashboard/terminal-control-route.ts — the ONE
3158
+ // implementation that the acceptance scripts drive as well. It used to be
3159
+ // inlined here, and the copy in the scripts drifted: they read the `?expect=`
3160
+ // compare-and-swap condition while this one did not, so conditional release
3161
+ // never actually applied in production.
3162
+ const terminalControlMatch = matchTerminalControlRoute(url.pathname);
3163
+ if (terminalControlMatch) {
3164
3164
  if (!requestIdentity) {
3165
3165
  return dashboardControlJson(res, 401, { ok: false, error: 'authentication_required' });
3166
3166
  }
3167
3167
  if (!enforceControlCsrf(req, res, requestIdentity))
3168
3168
  return;
3169
- let sessionId;
3170
- try {
3171
- sessionId = decodeURIComponent(controlMatch[1]);
3172
- }
3173
- catch {
3174
- return dashboardControlJson(res, 400, { ok: false, error: 'invalid_session_id' });
3169
+ if (!terminalControlMatch.ok) {
3170
+ return dashboardControlJson(res, 400, { ok: false, error: terminalControlMatch.error });
3175
3171
  }
3172
+ const sessionId = terminalControlMatch.sessionId;
3176
3173
  const availability = terminalControlAvailability(sessionId);
3177
3174
  if (!availability.ok) {
3178
3175
  return dashboardControlJson(res, availability.status, { ok: false, error: availability.error });
3179
3176
  }
3180
- const action = controlMatch[2];
3181
- if (req.method === 'GET' && !action) {
3182
- return dashboardControlJson(res, 200, { ok: true, ...terminalControl.state(requestIdentity, sessionId) });
3183
- }
3184
- if (requestIdentity.terminalCapability === 'readonly') {
3185
- return dashboardControlJson(res, 403, { ok: false, error: 'terminal_operation_forbidden' });
3186
- }
3187
- if (req.method === 'POST' && action === 'takeover') {
3188
- const result = terminalControl.takeover(requestIdentity, sessionId);
3189
- const status = result.ok ? 200 : result.error === 'control_busy' ? 409 : 401;
3190
- return dashboardControlJson(res, status, result.ok ? { ...result, owned: true } : { ok: false, error: result.error });
3191
- }
3192
- if (req.method === 'POST' && action === 'release') {
3193
- const result = terminalControl.release(requestIdentity, sessionId);
3194
- return dashboardControlJson(res, result.ok ? 200 : 403, result.ok ? { ...result, owned: false } : { ok: false, error: result.error });
3195
- }
3196
- return dashboardControlJson(res, 405, { ok: false, error: 'method_not_allowed' });
3177
+ const answer = resolveTerminalControlAction({
3178
+ method: req.method ?? 'GET',
3179
+ action: terminalControlMatch.action,
3180
+ sessionId,
3181
+ search: url.searchParams,
3182
+ identity: requestIdentity,
3183
+ control: terminalControl,
3184
+ });
3185
+ return dashboardControlJson(res, answer.status, answer.body);
3197
3186
  }
3198
3187
  // Preview interaction is separately scoped per authenticated browser
3199
3188
  // session. Default is always the visibly labelled preview overlay; unlock
3200
3189
  // and activity are explicit, and the server hard-relocks after 15m idle.
3201
- controlMatch = url.pathname.match(/^\/api\/sessions\/([^/]+)\/preview-interaction(?:\/(unlock|activity|lock))?$/);
3190
+ const controlMatch = url.pathname.match(/^\/api\/sessions\/([^/]+)\/preview-interaction(?:\/(unlock|activity|lock))?$/);
3202
3191
  if (controlMatch) {
3203
3192
  if (!requestIdentity) {
3204
3193
  return dashboardControlJson(res, 401, { ok: false, error: 'authentication_required' });
@@ -3598,6 +3587,41 @@ const server = createServer(async (req, res) => {
3598
3587
  ? { ok: true, settings: result.settings, herdrTraexInstall }
3599
3588
  : { ok: true, settings: result.settings });
3600
3589
  }
3590
+ if (req.method === 'GET' && url.pathname === '/api/autostart') {
3591
+ if (!authed)
3592
+ return jsonRes(res, 401, { ok: false, error: 'unauthorized' });
3593
+ res.setHeader('cache-control', 'no-store');
3594
+ return jsonRes(res, 200, { ok: true, state: await dashboardAutostart.getState() });
3595
+ }
3596
+ if (req.method === 'PUT' && url.pathname === '/api/autostart') {
3597
+ if (!authed)
3598
+ return jsonRes(res, 401, { ok: false, error: 'unauthorized' });
3599
+ res.setHeader('cache-control', 'no-store');
3600
+ let body;
3601
+ try {
3602
+ body = await readJsonBody(req);
3603
+ }
3604
+ catch {
3605
+ return jsonRes(res, 400, { ok: false, error: 'bad_json' });
3606
+ }
3607
+ const parsed = parseAutostartWrite(body);
3608
+ if (!parsed.ok)
3609
+ return jsonRes(res, 400, { ok: false, error: 'invalid_body' });
3610
+ try {
3611
+ const state = await dashboardAutostart.setEnabled(parsed.enabled);
3612
+ return jsonRes(res, 200, { ok: true, state });
3613
+ }
3614
+ catch (error) {
3615
+ if (error instanceof DashboardAutostartError) {
3616
+ logger.warn(`[dashboard-autostart] ${error.code}: ${error.message}`);
3617
+ return jsonRes(res, dashboardAutostartErrorStatus(error), {
3618
+ ok: false,
3619
+ error: error.code,
3620
+ });
3621
+ }
3622
+ throw error;
3623
+ }
3624
+ }
3601
3625
  // ─── Version & manual update ─────────────────────────────────────────────
3602
3626
  // Global package updates and a host restart are privileged: none of these paths
3603
3627
  // are on PUBLIC_READ_PATHS, so decideDashboardAuth already 401s an
@@ -4407,6 +4431,12 @@ const server = createServer(async (req, res) => {
4407
4431
  return jsonRes(res, 400, { ok: false, error: err?.message ?? 'whiteboard_delete_failed' });
4408
4432
  }
4409
4433
  }
4434
+ // ─── Customization center (built-in prompt/skill overrides) ──────────────
4435
+ // GET is a public read (overview only, no secrets); all mutations are
4436
+ // owner-gated (not on PUBLIC_READ_PATHS → decideDashboardAuth 401s guests).
4437
+ if (await handleCustomizationApi(req, res, url)) {
4438
+ return;
4439
+ }
4410
4440
  if (await handleConnectorApi(req, res, url)) {
4411
4441
  return;
4412
4442
  }
@@ -4431,12 +4461,23 @@ const server = createServer(async (req, res) => {
4431
4461
  cliId: o.cliId,
4432
4462
  wrapperCli: o.wrapperCli,
4433
4463
  }, { shellFallback: false });
4464
+ // 静态模型候选(shell-free):模型下拉的初始选项;live 增量由
4465
+ // /api/cli-options/models 按需探测。staticModelChoices 自身 fail-soft,
4466
+ // 这里再包一层 try/catch 兜底,保证选项列表永不因模型目录异常而整包失败。
4467
+ let modelChoices = [];
4468
+ try {
4469
+ modelChoices = [...staticModelChoices(o.key)];
4470
+ }
4471
+ catch {
4472
+ modelChoices = [];
4473
+ }
4434
4474
  return {
4435
4475
  id: o.key,
4436
4476
  label: o.label,
4437
4477
  available: availability.available,
4438
4478
  command: availability.command,
4439
4479
  availabilityReason: availability.reason,
4480
+ modelChoices,
4440
4481
  // ttadk 网关项: 前端据此把模型框默认成 glm-5.1 并挂候选下拉; CoCo 不接受 -m.
4441
4482
  ...(isTtadkWrapper(o.wrapperCli)
4442
4483
  ? { gateway: 'ttadk', acceptsModel: ttadkAcceptsModel(o.wrapperCli) }
@@ -4450,6 +4491,17 @@ const server = createServer(async (req, res) => {
4450
4491
  webSession,
4451
4492
  });
4452
4493
  }
4494
+ // On-demand 模型探测:只探测当前选中的单个 CLI(用户在模型下拉旁点「刷新」时),
4495
+ // 不做全量扫描——20+ CLI 各自 shell out 会让表单打开即卡。静态候选已随
4496
+ // /api/cli-options 的 modelChoices 字段下发,本端点只补 live 增量并合并去重。
4497
+ if (req.method === 'GET' && url.pathname === '/api/cli-options/models') {
4498
+ const key = (url.searchParams.get('key') ?? '').trim();
4499
+ if (!isKnownSelectionKey(key)) {
4500
+ return jsonRes(res, 400, { ok: false, error: 'unknown_selection_key' });
4501
+ }
4502
+ const body = await buildModelChoicesResponse(key);
4503
+ return jsonRes(res, 200, body);
4504
+ }
4453
4505
  if (req.method === 'POST' && url.pathname === '/api/bot-onboarding/start') {
4454
4506
  let parsed;
4455
4507
  try {
@@ -5187,7 +5239,7 @@ const server = createServer(async (req, res) => {
5187
5239
  // ─── 会议角色预设(私有 API:不在 PUBLIC_READ_PATHS,未认证已被 401) ───
5188
5240
  if (url.pathname === '/api/vc-meeting/consumer-profiles') {
5189
5241
  if (req.method === 'GET') {
5190
- const out = await handleVcMeetingConsumerProfilesGet(url.searchParams.get('listenerBotAppId') ?? '', vcMeetingConsumerProfilesApiDeps());
5242
+ const out = await handleVcMeetingConsumerProfilesGet(vcMeetingConsumerProfilesApiDeps());
5191
5243
  return jsonRes(res, out.status, out.body);
5192
5244
  }
5193
5245
  if (req.method === 'PUT') {
@@ -5203,6 +5255,29 @@ const server = createServer(async (req, res) => {
5203
5255
  }
5204
5256
  return jsonRes(res, 405, { ok: false, error: 'method_not_allowed' });
5205
5257
  }
5258
+ // 按 bot 手动触发的开放平台前置配置(开权限 + 订 VC 事件 + 补 larkCliProfile)。
5259
+ // 私有 API,同样不在 PUBLIC_READ_PATHS。做成显式动作而不是随勾选自动跑:
5260
+ // 「接收会议事件」默认就是开的,没有 off→on 跃迁可挂;页面加载时对整个 fleet
5261
+ // 跑一遍则是几十上百次开放平台调用。
5262
+ if (url.pathname === '/api/vc-meeting/bot-preflight') {
5263
+ if (req.method !== 'POST')
5264
+ return jsonRes(res, 405, { ok: false, error: 'method_not_allowed' });
5265
+ let parsed;
5266
+ try {
5267
+ parsed = await readJsonBody(req);
5268
+ }
5269
+ catch {
5270
+ return jsonRes(res, 400, { ok: false, error: 'bad_json' });
5271
+ }
5272
+ const appId = parsed?.appId;
5273
+ if (typeof appId !== 'string' || !appId.trim()) {
5274
+ return jsonRes(res, 400, { ok: false, error: 'missing_appId' });
5275
+ }
5276
+ const out = await preflightVcMeetingBot(appId);
5277
+ if (out.ok)
5278
+ return jsonRes(res, 200, { ok: true });
5279
+ return jsonRes(res, 400, { ok: false, error: out.error, feishuLoginQr: out.feishuLoginQr });
5280
+ }
5206
5281
  if (req.method === 'GET' && url.pathname === '/api/role-profiles') {
5207
5282
  const merged = new Map();
5208
5283
  await Promise.all(registry.list().map(async (d) => {
@@ -5447,6 +5522,7 @@ const server = createServer(async (req, res) => {
5447
5522
  model: j.model || d.model,
5448
5523
  reasoningEffort: j.reasoningEffort || d.reasoningEffort,
5449
5524
  turnTimeoutMs: typeof j.turnTimeoutMs === 'number' ? j.turnTimeoutMs : d.turnTimeoutMs,
5525
+ dshRuntime: typeof j.dshRuntime === 'string' ? j.dshRuntime : d.dshRuntime,
5450
5526
  }, j);
5451
5527
  }
5452
5528
  catch (e) {
@@ -6508,7 +6584,12 @@ server.on('upgrade', (req, clientSocket, head) => {
6508
6584
  // P1-11:管理类 WS(终端 / 调试终端)升级不经 HTTP 门禁,浏览器对 WS 握手
6509
6585
  // 一定带 Origin,所以「带了但对不上(含 null)」一律拒——同站兄弟子域和
6510
6586
  // localhost 其它端口正是 SameSite=Lax 挡不住的那一类。
6511
- const upgradeOrigin = managementUpgradeOrigin(req.headers);
6587
+ //
6588
+ // 判之前**先按 path 分流**可信来源档位:会话终端 `/s/*` 认平台 `m-`+`t-`(分享
6589
+ // 出去的终端页就住在 `t-`),而 `/debug-terminal/*` 的另一头是宿主裸 bash,只认
6590
+ // management 档。合在一起判的话,`t-` 就连带成了裸 bash 那条 WS 的可信 Origin。
6591
+ const upgradeRoute = classifyManagementUpgrade(rawUrl);
6592
+ const upgradeOrigin = managementUpgradeOrigin(req.headers, upgradeRoute.surface);
6512
6593
  if (!upgradeOrigin.ok) {
6513
6594
  const body = JSON.stringify({ ok: false, error: upgradeOrigin.error });
6514
6595
  clientSocket.end([
@@ -6522,8 +6603,8 @@ server.on('upgrade', (req, clientSocket, head) => {
6522
6603
  ].join('\r\n'));
6523
6604
  return;
6524
6605
  }
6525
- // 调试终端 WS(owner-only):manager 内部自校验管理 cookie。命中即接管。
6526
- if (rawUrl.startsWith('/debug-terminal/')) {
6606
+ // 调试终端 WS(owner-only):manager 内部再自校验管理 cookie + legacy 管理身份。
6607
+ if (upgradeRoute.route === 'debug-terminal') {
6527
6608
  if (debugTerminalManager.handleUpgrade(req, clientSocket, head))
6528
6609
  return;
6529
6610
  }