botmux 2.107.0 → 2.108.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (515) hide show
  1. package/README.en.md +17 -14
  2. package/README.md +19 -14
  3. package/dist/adapters/backend/sandbox.d.ts +3 -1
  4. package/dist/adapters/backend/sandbox.d.ts.map +1 -1
  5. package/dist/adapters/backend/sandbox.js +19 -3
  6. package/dist/adapters/backend/sandbox.js.map +1 -1
  7. package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
  8. package/dist/adapters/backend/tmux-backend.js +16 -1
  9. package/dist/adapters/backend/tmux-backend.js.map +1 -1
  10. package/dist/adapters/backend/tmux-pipe-backend.d.ts +24 -15
  11. package/dist/adapters/backend/tmux-pipe-backend.d.ts.map +1 -1
  12. package/dist/adapters/backend/tmux-pipe-backend.js +75 -43
  13. package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -1
  14. package/dist/adapters/cli/genius.d.ts.map +1 -1
  15. package/dist/adapters/cli/genius.js +9 -15
  16. package/dist/adapters/cli/genius.js.map +1 -1
  17. package/dist/adapters/cli/grok.d.ts +73 -0
  18. package/dist/adapters/cli/grok.d.ts.map +1 -0
  19. package/dist/adapters/cli/grok.js +298 -0
  20. package/dist/adapters/cli/grok.js.map +1 -0
  21. package/dist/adapters/cli/oh-my-pi.d.ts.map +1 -1
  22. package/dist/adapters/cli/oh-my-pi.js +133 -12
  23. package/dist/adapters/cli/oh-my-pi.js.map +1 -1
  24. package/dist/adapters/cli/registry.d.ts +2 -1
  25. package/dist/adapters/cli/registry.d.ts.map +1 -1
  26. package/dist/adapters/cli/registry.js +3 -1
  27. package/dist/adapters/cli/registry.js.map +1 -1
  28. package/dist/adapters/cli/shared-hints.d.ts +8 -4
  29. package/dist/adapters/cli/shared-hints.d.ts.map +1 -1
  30. package/dist/adapters/cli/shared-hints.js +8 -4
  31. package/dist/adapters/cli/shared-hints.js.map +1 -1
  32. package/dist/adapters/cli/types.d.ts +18 -16
  33. package/dist/adapters/cli/types.d.ts.map +1 -1
  34. package/dist/adapters/hook-installer.d.ts +5 -4
  35. package/dist/adapters/hook-installer.d.ts.map +1 -1
  36. package/dist/adapters/hook-installer.js +42 -0
  37. package/dist/adapters/hook-installer.js.map +1 -1
  38. package/dist/cli/send-dispatch.d.ts +21 -0
  39. package/dist/cli/send-dispatch.d.ts.map +1 -1
  40. package/dist/cli/send-dispatch.js +159 -0
  41. package/dist/cli/send-dispatch.js.map +1 -1
  42. package/dist/cli/session-list-liveness.d.ts +22 -0
  43. package/dist/cli/session-list-liveness.d.ts.map +1 -0
  44. package/dist/cli/session-list-liveness.js +22 -0
  45. package/dist/cli/session-list-liveness.js.map +1 -0
  46. package/dist/cli.d.ts.map +1 -1
  47. package/dist/cli.js +182 -33
  48. package/dist/cli.js.map +1 -1
  49. package/dist/core/ask-types.d.ts +4 -0
  50. package/dist/core/ask-types.d.ts.map +1 -1
  51. package/dist/core/ask-types.js +10 -0
  52. package/dist/core/ask-types.js.map +1 -1
  53. package/dist/core/cost-calculator.d.ts.map +1 -1
  54. package/dist/core/cost-calculator.js +35 -13
  55. package/dist/core/cost-calculator.js.map +1 -1
  56. package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
  57. package/dist/core/dashboard-ipc-server.js +89 -16
  58. package/dist/core/dashboard-ipc-server.js.map +1 -1
  59. package/dist/core/dashboard-rows.d.ts.map +1 -1
  60. package/dist/core/dashboard-rows.js +6 -2
  61. package/dist/core/dashboard-rows.js.map +1 -1
  62. package/dist/core/dashboard-url.d.ts +6 -5
  63. package/dist/core/dashboard-url.d.ts.map +1 -1
  64. package/dist/core/dashboard-url.js +11 -8
  65. package/dist/core/dashboard-url.js.map +1 -1
  66. package/dist/core/maintenance.d.ts +11 -8
  67. package/dist/core/maintenance.d.ts.map +1 -1
  68. package/dist/core/maintenance.js +45 -20
  69. package/dist/core/maintenance.js.map +1 -1
  70. package/dist/core/per-bot-env.d.ts.map +1 -1
  71. package/dist/core/per-bot-env.js +4 -0
  72. package/dist/core/per-bot-env.js.map +1 -1
  73. package/dist/core/session-discovery.d.ts.map +1 -1
  74. package/dist/core/session-discovery.js +4 -0
  75. package/dist/core/session-discovery.js.map +1 -1
  76. package/dist/core/skills/cli-admin-command.d.ts.map +1 -1
  77. package/dist/core/skills/cli-admin-command.js +8 -2
  78. package/dist/core/skills/cli-admin-command.js.map +1 -1
  79. package/dist/core/skills/im-command.d.ts.map +1 -1
  80. package/dist/core/skills/im-command.js +3 -1
  81. package/dist/core/skills/im-command.js.map +1 -1
  82. package/dist/core/skills/sources.d.ts +33 -1
  83. package/dist/core/skills/sources.d.ts.map +1 -1
  84. package/dist/core/skills/sources.js +97 -0
  85. package/dist/core/skills/sources.js.map +1 -1
  86. package/dist/core/skills/types.d.ts +8 -0
  87. package/dist/core/skills/types.d.ts.map +1 -1
  88. package/dist/core/terminal-url.d.ts.map +1 -1
  89. package/dist/core/terminal-url.js +12 -2
  90. package/dist/core/terminal-url.js.map +1 -1
  91. package/dist/core/terminal-write-auth.d.ts +34 -0
  92. package/dist/core/terminal-write-auth.d.ts.map +1 -0
  93. package/dist/core/terminal-write-auth.js +76 -0
  94. package/dist/core/terminal-write-auth.js.map +1 -0
  95. package/dist/core/tmux-recovery.d.ts +11 -0
  96. package/dist/core/tmux-recovery.d.ts.map +1 -0
  97. package/dist/core/tmux-recovery.js +19 -0
  98. package/dist/core/tmux-recovery.js.map +1 -0
  99. package/dist/core/types.d.ts +10 -4
  100. package/dist/core/types.d.ts.map +1 -1
  101. package/dist/core/types.js.map +1 -1
  102. package/dist/core/update-check.d.ts +2 -2
  103. package/dist/core/update-check.js +2 -2
  104. package/dist/core/worker-pool.d.ts +3 -0
  105. package/dist/core/worker-pool.d.ts.map +1 -1
  106. package/dist/core/worker-pool.js +70 -3
  107. package/dist/core/worker-pool.js.map +1 -1
  108. package/dist/daemon.d.ts.map +1 -1
  109. package/dist/daemon.js +15 -8
  110. package/dist/daemon.js.map +1 -1
  111. package/dist/dashboard/auth.d.ts +1 -1
  112. package/dist/dashboard/auth.d.ts.map +1 -1
  113. package/dist/dashboard/auth.js +7 -2
  114. package/dist/dashboard/auth.js.map +1 -1
  115. package/dist/dashboard/bot-payload.d.ts +3 -0
  116. package/dist/dashboard/bot-payload.d.ts.map +1 -1
  117. package/dist/dashboard/bot-payload.js +3 -0
  118. package/dist/dashboard/bot-payload.js.map +1 -1
  119. package/dist/dashboard/connector-api.d.ts.map +1 -1
  120. package/dist/dashboard/connector-api.js +39 -13
  121. package/dist/dashboard/connector-api.js.map +1 -1
  122. package/dist/dashboard/history-senders.d.ts +37 -0
  123. package/dist/dashboard/history-senders.d.ts.map +1 -0
  124. package/dist/dashboard/history-senders.js +60 -0
  125. package/dist/dashboard/history-senders.js.map +1 -0
  126. package/dist/dashboard/roles-batch.d.ts +31 -0
  127. package/dist/dashboard/roles-batch.d.ts.map +1 -0
  128. package/dist/dashboard/roles-batch.js +87 -0
  129. package/dist/dashboard/roles-batch.js.map +1 -0
  130. package/dist/dashboard/settings-card-model.d.ts +4 -2
  131. package/dist/dashboard/settings-card-model.d.ts.map +1 -1
  132. package/dist/dashboard/settings-card-model.js +13 -5
  133. package/dist/dashboard/settings-card-model.js.map +1 -1
  134. package/dist/dashboard/settings-write-applier.d.ts +4 -1
  135. package/dist/dashboard/settings-write-applier.d.ts.map +1 -1
  136. package/dist/dashboard/settings-write-applier.js +6 -1
  137. package/dist/dashboard/settings-write-applier.js.map +1 -1
  138. package/dist/dashboard/skill-install-request.d.ts +4 -0
  139. package/dist/dashboard/skill-install-request.d.ts.map +1 -1
  140. package/dist/dashboard/skill-install-request.js +11 -1
  141. package/dist/dashboard/skill-install-request.js.map +1 -1
  142. package/dist/dashboard/trigger-api.d.ts +9 -1
  143. package/dist/dashboard/trigger-api.d.ts.map +1 -1
  144. package/dist/dashboard/trigger-api.js +48 -10
  145. package/dist/dashboard/trigger-api.js.map +1 -1
  146. package/dist/dashboard/web/app.d.ts.map +1 -1
  147. package/dist/dashboard/web/app.js +286 -271
  148. package/dist/dashboard/web/app.js.map +1 -1
  149. package/dist/dashboard/web/bot-defaults-page.d.ts +26 -0
  150. package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -1
  151. package/dist/dashboard/web/bot-defaults-page.js +1408 -12
  152. package/dist/dashboard/web/bot-defaults-page.js.map +1 -1
  153. package/dist/dashboard/web/bot-defaults.d.ts +91 -4
  154. package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
  155. package/dist/dashboard/web/bot-defaults.js +43 -2141
  156. package/dist/dashboard/web/bot-defaults.js.map +1 -1
  157. package/dist/dashboard/web/bot-onboarding.d.ts +6 -1
  158. package/dist/dashboard/web/bot-onboarding.d.ts.map +1 -1
  159. package/dist/dashboard/web/bot-onboarding.js +261 -306
  160. package/dist/dashboard/web/bot-onboarding.js.map +1 -1
  161. package/dist/dashboard/web/connectors-page.d.ts +4 -0
  162. package/dist/dashboard/web/connectors-page.d.ts.map +1 -1
  163. package/dist/dashboard/web/connectors-page.js +228 -48
  164. package/dist/dashboard/web/connectors-page.js.map +1 -1
  165. package/dist/dashboard/web/dashboard-api.d.ts +9 -0
  166. package/dist/dashboard/web/dashboard-api.d.ts.map +1 -0
  167. package/dist/dashboard/web/dashboard-api.js +18 -0
  168. package/dist/dashboard/web/dashboard-api.js.map +1 -0
  169. package/dist/dashboard/web/dashboard-components.d.ts +92 -0
  170. package/dist/dashboard/web/dashboard-components.d.ts.map +1 -0
  171. package/dist/dashboard/web/dashboard-components.js +250 -0
  172. package/dist/dashboard/web/dashboard-components.js.map +1 -0
  173. package/dist/dashboard/web/dashboard-routes.d.ts.map +1 -1
  174. package/dist/dashboard/web/dashboard-routes.js +30 -183
  175. package/dist/dashboard/web/dashboard-routes.js.map +1 -1
  176. package/dist/dashboard/web/floating-scrollbars.d.ts +2 -0
  177. package/dist/dashboard/web/floating-scrollbars.d.ts.map +1 -0
  178. package/dist/dashboard/web/floating-scrollbars.js +264 -0
  179. package/dist/dashboard/web/floating-scrollbars.js.map +1 -0
  180. package/dist/dashboard/web/groups-api.d.ts +36 -0
  181. package/dist/dashboard/web/groups-api.d.ts.map +1 -0
  182. package/dist/dashboard/web/groups-api.js +44 -0
  183. package/dist/dashboard/web/groups-api.js.map +1 -0
  184. package/dist/dashboard/web/groups-page.d.ts.map +1 -1
  185. package/dist/dashboard/web/groups-page.js +746 -15
  186. package/dist/dashboard/web/groups-page.js.map +1 -1
  187. package/dist/dashboard/web/groups.d.ts +51 -18
  188. package/dist/dashboard/web/groups.d.ts.map +1 -1
  189. package/dist/dashboard/web/groups.js +145 -1096
  190. package/dist/dashboard/web/groups.js.map +1 -1
  191. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  192. package/dist/dashboard/web/i18n.js +545 -255
  193. package/dist/dashboard/web/i18n.js.map +1 -1
  194. package/dist/dashboard/web/insights-page.d.ts.map +1 -1
  195. package/dist/dashboard/web/insights-page.js +1047 -14
  196. package/dist/dashboard/web/insights-page.js.map +1 -1
  197. package/dist/dashboard/web/insights.d.ts +177 -7
  198. package/dist/dashboard/web/insights.d.ts.map +1 -1
  199. package/dist/dashboard/web/insights.js +187 -1926
  200. package/dist/dashboard/web/insights.js.map +1 -1
  201. package/dist/dashboard/web/legacy-workflow-page.d.ts +3 -0
  202. package/dist/dashboard/web/legacy-workflow-page.d.ts.map +1 -0
  203. package/dist/dashboard/web/legacy-workflow-page.js +717 -0
  204. package/dist/dashboard/web/legacy-workflow-page.js.map +1 -0
  205. package/dist/dashboard/web/monitor-room.d.ts.map +1 -1
  206. package/dist/dashboard/web/monitor-room.js +10 -8
  207. package/dist/dashboard/web/monitor-room.js.map +1 -1
  208. package/dist/dashboard/web/monitoring-page.d.ts.map +1 -1
  209. package/dist/dashboard/web/monitoring-page.js +188 -14
  210. package/dist/dashboard/web/monitoring-page.js.map +1 -1
  211. package/dist/dashboard/web/office-page.d.ts.map +1 -1
  212. package/dist/dashboard/web/office-page.js +11 -23
  213. package/dist/dashboard/web/office-page.js.map +1 -1
  214. package/dist/dashboard/web/overview-page.d.ts.map +1 -1
  215. package/dist/dashboard/web/overview-page.js +141 -147
  216. package/dist/dashboard/web/overview-page.js.map +1 -1
  217. package/dist/dashboard/web/overview.d.ts +0 -1
  218. package/dist/dashboard/web/overview.d.ts.map +1 -1
  219. package/dist/dashboard/web/overview.js +3 -275
  220. package/dist/dashboard/web/overview.js.map +1 -1
  221. package/dist/dashboard/web/preferences.d.ts +1 -6
  222. package/dist/dashboard/web/preferences.d.ts.map +1 -1
  223. package/dist/dashboard/web/preferences.js +0 -21
  224. package/dist/dashboard/web/preferences.js.map +1 -1
  225. package/dist/dashboard/web/role-batch.d.ts +9 -0
  226. package/dist/dashboard/web/role-batch.d.ts.map +1 -0
  227. package/dist/dashboard/web/role-batch.js +42 -0
  228. package/dist/dashboard/web/role-batch.js.map +1 -0
  229. package/dist/dashboard/web/roles-page.d.ts.map +1 -1
  230. package/dist/dashboard/web/roles-page.js +538 -13
  231. package/dist/dashboard/web/roles-page.js.map +1 -1
  232. package/dist/dashboard/web/roles.d.ts +98 -1
  233. package/dist/dashboard/web/roles.d.ts.map +1 -1
  234. package/dist/dashboard/web/roles.js +117 -903
  235. package/dist/dashboard/web/roles.js.map +1 -1
  236. package/dist/dashboard/web/schedules-page.d.ts.map +1 -1
  237. package/dist/dashboard/web/schedules-page.js +82 -24
  238. package/dist/dashboard/web/schedules-page.js.map +1 -1
  239. package/dist/dashboard/web/sessions-kanban.d.ts +67 -0
  240. package/dist/dashboard/web/sessions-kanban.d.ts.map +1 -0
  241. package/dist/dashboard/web/sessions-kanban.js +481 -0
  242. package/dist/dashboard/web/sessions-kanban.js.map +1 -0
  243. package/dist/dashboard/web/sessions-page.d.ts +4 -0
  244. package/dist/dashboard/web/sessions-page.d.ts.map +1 -1
  245. package/dist/dashboard/web/sessions-page.js +1633 -18
  246. package/dist/dashboard/web/sessions-page.js.map +1 -1
  247. package/dist/dashboard/web/sessions.d.ts +45 -4
  248. package/dist/dashboard/web/sessions.d.ts.map +1 -1
  249. package/dist/dashboard/web/sessions.js +53 -2535
  250. package/dist/dashboard/web/sessions.js.map +1 -1
  251. package/dist/dashboard/web/settings-page.d.ts +0 -2
  252. package/dist/dashboard/web/settings-page.d.ts.map +1 -1
  253. package/dist/dashboard/web/settings-page.js +127 -117
  254. package/dist/dashboard/web/settings-page.js.map +1 -1
  255. package/dist/dashboard/web/skills-page.d.ts +10 -1
  256. package/dist/dashboard/web/skills-page.d.ts.map +1 -1
  257. package/dist/dashboard/web/skills-page.js +235 -93
  258. package/dist/dashboard/web/skills-page.js.map +1 -1
  259. package/dist/dashboard/web/team-federation-page.d.ts.map +1 -1
  260. package/dist/dashboard/web/team-federation-page.js +446 -28
  261. package/dist/dashboard/web/team-federation-page.js.map +1 -1
  262. package/dist/dashboard/web/team-federation.d.ts +91 -2
  263. package/dist/dashboard/web/team-federation.d.ts.map +1 -1
  264. package/dist/dashboard/web/team-federation.js +87 -474
  265. package/dist/dashboard/web/team-federation.js.map +1 -1
  266. package/dist/dashboard/web/theme-menu.d.ts +1 -0
  267. package/dist/dashboard/web/theme-menu.d.ts.map +1 -1
  268. package/dist/dashboard/web/theme-menu.js +79 -20
  269. package/dist/dashboard/web/theme-menu.js.map +1 -1
  270. package/dist/dashboard/web/ui.d.ts +1 -2
  271. package/dist/dashboard/web/ui.d.ts.map +1 -1
  272. package/dist/dashboard/web/ui.js +8 -20
  273. package/dist/dashboard/web/ui.js.map +1 -1
  274. package/dist/dashboard/web/v3-api.d.ts +16 -0
  275. package/dist/dashboard/web/v3-api.d.ts.map +1 -0
  276. package/dist/dashboard/web/v3-api.js +21 -0
  277. package/dist/dashboard/web/v3-api.js.map +1 -0
  278. package/dist/dashboard/web/v3-components.d.ts +2 -0
  279. package/dist/dashboard/web/v3-components.d.ts.map +1 -0
  280. package/dist/dashboard/web/v3-components.js +290 -0
  281. package/dist/dashboard/web/v3-components.js.map +1 -0
  282. package/dist/dashboard/web/v3-model.d.ts +80 -0
  283. package/dist/dashboard/web/v3-model.d.ts.map +1 -0
  284. package/dist/dashboard/web/v3-model.js +240 -0
  285. package/dist/dashboard/web/v3-model.js.map +1 -0
  286. package/dist/dashboard/web/v3-page.d.ts.map +1 -1
  287. package/dist/dashboard/web/v3-page.js +2 -22
  288. package/dist/dashboard/web/v3-page.js.map +1 -1
  289. package/dist/dashboard/web/v3-terminal.d.ts +14 -0
  290. package/dist/dashboard/web/v3-terminal.d.ts.map +1 -1
  291. package/dist/dashboard/web/v3-terminal.js +31 -19
  292. package/dist/dashboard/web/v3-terminal.js.map +1 -1
  293. package/dist/dashboard/web/webhook-logs-page.d.ts +16 -0
  294. package/dist/dashboard/web/webhook-logs-page.d.ts.map +1 -0
  295. package/dist/dashboard/web/webhook-logs-page.js +195 -0
  296. package/dist/dashboard/web/webhook-logs-page.js.map +1 -0
  297. package/dist/dashboard/web/whiteboards-page.d.ts.map +1 -1
  298. package/dist/dashboard/web/whiteboards-page.js +18 -23
  299. package/dist/dashboard/web/whiteboards-page.js.map +1 -1
  300. package/dist/dashboard/web/workflow-version-switch.d.ts +8 -0
  301. package/dist/dashboard/web/workflow-version-switch.d.ts.map +1 -0
  302. package/dist/dashboard/web/workflow-version-switch.js +9 -0
  303. package/dist/dashboard/web/workflow-version-switch.js.map +1 -0
  304. package/dist/dashboard/web/workflows.d.ts +272 -1
  305. package/dist/dashboard/web/workflows.d.ts.map +1 -1
  306. package/dist/dashboard/web/workflows.js +211 -1397
  307. package/dist/dashboard/web/workflows.js.map +1 -1
  308. package/dist/dashboard/webhook-routes.d.ts.map +1 -1
  309. package/dist/dashboard/webhook-routes.js +92 -39
  310. package/dist/dashboard/webhook-routes.js.map +1 -1
  311. package/dist/dashboard-web/app.js +1 -65
  312. package/dist/dashboard-web/brand-logo.png +0 -0
  313. package/dist/dashboard-web/chunks/bot-defaults-page-HSQ6HR3R.js +1 -0
  314. package/dist/dashboard-web/chunks/chunk-6TPODDDC.js +1 -0
  315. package/dist/dashboard-web/chunks/chunk-73EJP2MO.js +1 -0
  316. package/dist/dashboard-web/chunks/chunk-BRTZFELS.js +1 -0
  317. package/dist/dashboard-web/chunks/chunk-EVK77ASG.js +1 -0
  318. package/dist/dashboard-web/chunks/chunk-R3FXBFQH.js +1 -0
  319. package/dist/dashboard-web/chunks/chunk-VRLL7SNU.js +1 -0
  320. package/dist/dashboard-web/chunks/chunk-XCPSHD3G.js +37 -0
  321. package/dist/dashboard-web/chunks/chunk-XJ7BGPJH.js +1 -0
  322. package/dist/dashboard-web/chunks/chunk-YVRWYGXR.js +1 -0
  323. package/dist/dashboard-web/chunks/chunk-ZJING6FY.js +66 -0
  324. package/dist/dashboard-web/chunks/connectors-page-ODUA5UCW.js +1 -0
  325. package/dist/dashboard-web/chunks/groups-page-OYX5M6NK.js +8 -0
  326. package/dist/dashboard-web/chunks/insights-page-YCQO6OCR.js +22 -0
  327. package/dist/dashboard-web/chunks/legacy-workflow-page-XJAUNONP.js +2 -0
  328. package/dist/dashboard-web/chunks/{monitor-room-RFX4HPS5.js → monitor-room-WTZNYAFV.js} +17 -15
  329. package/dist/dashboard-web/chunks/monitoring-page-R6LJUK7G.js +2 -0
  330. package/dist/dashboard-web/chunks/office-page-4OXK3GNR.js +1 -0
  331. package/dist/dashboard-web/chunks/overview-page-4MVEJY6U.js +1 -0
  332. package/dist/dashboard-web/chunks/roles-page-NQDW27VV.js +1 -0
  333. package/dist/dashboard-web/chunks/schedules-page-JRNKYHOX.js +1 -0
  334. package/dist/dashboard-web/chunks/sessions-page-LF7UVI7B.js +3 -0
  335. package/dist/dashboard-web/chunks/settings-page-WGW7KQQS.js +2 -0
  336. package/dist/dashboard-web/chunks/skills-page-AMD4XP3T.js +3 -0
  337. package/dist/dashboard-web/chunks/team-federation-page-SYG3K4GG.js +1 -0
  338. package/dist/dashboard-web/chunks/v3-page-6NFFWNUK.js +94 -0
  339. package/dist/dashboard-web/chunks/whiteboards-page-FBRUK2AS.js +1 -0
  340. package/dist/dashboard-web/favicon.png +0 -0
  341. package/dist/dashboard-web/index.html +5 -69
  342. package/dist/dashboard-web/style.css +18835 -7211
  343. package/dist/dashboard.js +150 -32
  344. package/dist/dashboard.js.map +1 -1
  345. package/dist/global-config.d.ts +2 -2
  346. package/dist/global-config.d.ts.map +1 -1
  347. package/dist/i18n/en.d.ts.map +1 -1
  348. package/dist/i18n/en.js +3 -0
  349. package/dist/i18n/en.js.map +1 -1
  350. package/dist/i18n/zh.d.ts.map +1 -1
  351. package/dist/i18n/zh.js +3 -0
  352. package/dist/i18n/zh.js.map +1 -1
  353. package/dist/im/lark/card-builder.d.ts +7 -5
  354. package/dist/im/lark/card-builder.d.ts.map +1 -1
  355. package/dist/im/lark/card-builder.js +10 -7
  356. package/dist/im/lark/card-builder.js.map +1 -1
  357. package/dist/im/lark/card-handler.d.ts.map +1 -1
  358. package/dist/im/lark/card-handler.js +25 -1
  359. package/dist/im/lark/card-handler.js.map +1 -1
  360. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  361. package/dist/im/lark/event-dispatcher.js +84 -0
  362. package/dist/im/lark/event-dispatcher.js.map +1 -1
  363. package/dist/platform/binding.d.ts +9 -0
  364. package/dist/platform/binding.d.ts.map +1 -1
  365. package/dist/platform/binding.js +14 -0
  366. package/dist/platform/binding.js.map +1 -1
  367. package/dist/platform/tunnel-client.d.ts.map +1 -1
  368. package/dist/platform/tunnel-client.js +9 -0
  369. package/dist/platform/tunnel-client.js.map +1 -1
  370. package/dist/services/bot-config-store.d.ts +1 -1
  371. package/dist/services/bot-config-store.d.ts.map +1 -1
  372. package/dist/services/bot-config-store.js +11 -5
  373. package/dist/services/bot-config-store.js.map +1 -1
  374. package/dist/services/file-bridge-path.d.ts +8 -0
  375. package/dist/services/file-bridge-path.d.ts.map +1 -0
  376. package/dist/services/file-bridge-path.js +75 -0
  377. package/dist/services/file-bridge-path.js.map +1 -0
  378. package/dist/services/grok-paths.d.ts +27 -0
  379. package/dist/services/grok-paths.d.ts.map +1 -0
  380. package/dist/services/grok-paths.js +106 -0
  381. package/dist/services/grok-paths.js.map +1 -0
  382. package/dist/services/grok-transcript.d.ts +67 -0
  383. package/dist/services/grok-transcript.d.ts.map +1 -0
  384. package/dist/services/grok-transcript.js +630 -0
  385. package/dist/services/grok-transcript.js.map +1 -0
  386. package/dist/services/hermes-session-filter.d.ts +28 -0
  387. package/dist/services/hermes-session-filter.d.ts.map +1 -0
  388. package/dist/services/hermes-session-filter.js +53 -0
  389. package/dist/services/hermes-session-filter.js.map +1 -0
  390. package/dist/services/hermes-transcript.d.ts +3 -0
  391. package/dist/services/hermes-transcript.d.ts.map +1 -1
  392. package/dist/services/hermes-transcript.js +20 -2
  393. package/dist/services/hermes-transcript.js.map +1 -1
  394. package/dist/services/resumable-session-discovery.d.ts +3 -0
  395. package/dist/services/resumable-session-discovery.d.ts.map +1 -1
  396. package/dist/services/resumable-session-discovery.js +6 -1
  397. package/dist/services/resumable-session-discovery.js.map +1 -1
  398. package/dist/services/skill-registry-store.d.ts +9 -0
  399. package/dist/services/skill-registry-store.d.ts.map +1 -1
  400. package/dist/services/skill-registry-store.js +304 -1
  401. package/dist/services/skill-registry-store.js.map +1 -1
  402. package/dist/services/structured-bridge-clis.d.ts +29 -0
  403. package/dist/services/structured-bridge-clis.d.ts.map +1 -0
  404. package/dist/services/structured-bridge-clis.js +76 -0
  405. package/dist/services/structured-bridge-clis.js.map +1 -0
  406. package/dist/services/trigger-log-store.d.ts +59 -0
  407. package/dist/services/trigger-log-store.d.ts.map +1 -1
  408. package/dist/services/trigger-log-store.js +81 -10
  409. package/dist/services/trigger-log-store.js.map +1 -1
  410. package/dist/services/usage-ledger.d.ts +4 -1
  411. package/dist/services/usage-ledger.d.ts.map +1 -1
  412. package/dist/services/usage-ledger.js +48 -10
  413. package/dist/services/usage-ledger.js.map +1 -1
  414. package/dist/services/webhook-audit.d.ts +10 -0
  415. package/dist/services/webhook-audit.d.ts.map +1 -0
  416. package/dist/services/webhook-audit.js +116 -0
  417. package/dist/services/webhook-audit.js.map +1 -0
  418. package/dist/setup/bot-config-editor.d.ts.map +1 -1
  419. package/dist/setup/bot-config-editor.js +2 -0
  420. package/dist/setup/bot-config-editor.js.map +1 -1
  421. package/dist/setup/ensure-tmux.d.ts +26 -12
  422. package/dist/setup/ensure-tmux.d.ts.map +1 -1
  423. package/dist/setup/ensure-tmux.js +85 -18
  424. package/dist/setup/ensure-tmux.js.map +1 -1
  425. package/dist/skills/definitions.d.ts.map +1 -1
  426. package/dist/skills/definitions.js +14 -1
  427. package/dist/skills/definitions.js.map +1 -1
  428. package/dist/skills/injection-mode.d.ts +16 -0
  429. package/dist/skills/injection-mode.d.ts.map +1 -1
  430. package/dist/skills/injection-mode.js +25 -0
  431. package/dist/skills/injection-mode.js.map +1 -1
  432. package/dist/types.d.ts +9 -0
  433. package/dist/types.d.ts.map +1 -1
  434. package/dist/utils/global-install.d.ts +22 -0
  435. package/dist/utils/global-install.d.ts.map +1 -0
  436. package/dist/utils/global-install.js +106 -0
  437. package/dist/utils/global-install.js.map +1 -0
  438. package/dist/utils/install-diagnostics.d.ts +1 -1
  439. package/dist/utils/install-diagnostics.d.ts.map +1 -1
  440. package/dist/utils/install-diagnostics.js +6 -4
  441. package/dist/utils/install-diagnostics.js.map +1 -1
  442. package/dist/utils/install-info.d.ts +2 -0
  443. package/dist/utils/install-info.d.ts.map +1 -1
  444. package/dist/utils/install-info.js +10 -4
  445. package/dist/utils/install-info.js.map +1 -1
  446. package/dist/worker.js +293 -172
  447. package/dist/worker.js.map +1 -1
  448. package/dist/workflows/events/payloads.d.ts +10 -10
  449. package/dist/workflows/events/schema.d.ts +28 -28
  450. package/package.json +8 -7
  451. package/dist/dashboard/web/connectors.d.ts +0 -2
  452. package/dist/dashboard/web/connectors.d.ts.map +0 -1
  453. package/dist/dashboard/web/connectors.js +0 -2
  454. package/dist/dashboard/web/connectors.js.map +0 -1
  455. package/dist/dashboard/web/office.d.ts +0 -2
  456. package/dist/dashboard/web/office.d.ts.map +0 -1
  457. package/dist/dashboard/web/office.js +0 -2
  458. package/dist/dashboard/web/office.js.map +0 -1
  459. package/dist/dashboard/web/schedules.d.ts +0 -2
  460. package/dist/dashboard/web/schedules.d.ts.map +0 -1
  461. package/dist/dashboard/web/schedules.js +0 -2
  462. package/dist/dashboard/web/schedules.js.map +0 -1
  463. package/dist/dashboard/web/settings.d.ts +0 -2
  464. package/dist/dashboard/web/settings.d.ts.map +0 -1
  465. package/dist/dashboard/web/settings.js +0 -2
  466. package/dist/dashboard/web/settings.js.map +0 -1
  467. package/dist/dashboard/web/skills.d.ts +0 -2
  468. package/dist/dashboard/web/skills.d.ts.map +0 -1
  469. package/dist/dashboard/web/skills.js +0 -2
  470. package/dist/dashboard/web/skills.js.map +0 -1
  471. package/dist/dashboard/web/skin-intro.d.ts +0 -4
  472. package/dist/dashboard/web/skin-intro.d.ts.map +0 -1
  473. package/dist/dashboard/web/skin-intro.js +0 -49
  474. package/dist/dashboard/web/skin-intro.js.map +0 -1
  475. package/dist/dashboard/web/v3.d.ts +0 -3
  476. package/dist/dashboard/web/v3.d.ts.map +0 -1
  477. package/dist/dashboard/web/v3.js +0 -539
  478. package/dist/dashboard/web/v3.js.map +0 -1
  479. package/dist/dashboard/web/whiteboards.d.ts +0 -2
  480. package/dist/dashboard/web/whiteboards.d.ts.map +0 -1
  481. package/dist/dashboard/web/whiteboards.js +0 -2
  482. package/dist/dashboard/web/whiteboards.js.map +0 -1
  483. package/dist/dashboard-web/chunks/bot-defaults-page-OCIHPGEU.js +0 -438
  484. package/dist/dashboard-web/chunks/chunk-3N2PPQVD.js +0 -1
  485. package/dist/dashboard-web/chunks/chunk-3UJYRR2Q.js +0 -37
  486. package/dist/dashboard-web/chunks/chunk-5E3MJJL4.js +0 -1
  487. package/dist/dashboard-web/chunks/chunk-7SZRL6FY.js +0 -1
  488. package/dist/dashboard-web/chunks/chunk-JTSE5VP6.js +0 -54
  489. package/dist/dashboard-web/chunks/chunk-LXIK7OUJ.js +0 -1
  490. package/dist/dashboard-web/chunks/chunk-PE6W3C2C.js +0 -1
  491. package/dist/dashboard-web/chunks/chunk-QW54DWU3.js +0 -325
  492. package/dist/dashboard-web/chunks/connectors-IGETYWCP.js +0 -1
  493. package/dist/dashboard-web/chunks/groups-page-MYBS4ZYJ.js +0 -207
  494. package/dist/dashboard-web/chunks/insights-page-UPA32V2S.js +0 -309
  495. package/dist/dashboard-web/chunks/monitoring-page-7T3BESZ2.js +0 -1
  496. package/dist/dashboard-web/chunks/office-page-6DXYOG55.js +0 -1
  497. package/dist/dashboard-web/chunks/overview-page-LJSBCQW4.js +0 -1
  498. package/dist/dashboard-web/chunks/roles-page-ESURTVQH.js +0 -98
  499. package/dist/dashboard-web/chunks/schedules-LML2ISOT.js +0 -1
  500. package/dist/dashboard-web/chunks/sessions-YB73XOTU.js +0 -1
  501. package/dist/dashboard-web/chunks/sessions-page-MCO5QR7Z.js +0 -1
  502. package/dist/dashboard-web/chunks/settings-page-OSDKNVS3.js +0 -2
  503. package/dist/dashboard-web/chunks/skills-page-PXBZJ6P6.js +0 -2
  504. package/dist/dashboard-web/chunks/team-federation-page-TTPVHFPX.js +0 -10
  505. package/dist/dashboard-web/chunks/v3-page-FVPUL665.js +0 -149
  506. package/dist/dashboard-web/chunks/whiteboards-page-HLCTYSSV.js +0 -1
  507. package/dist/dashboard-web/chunks/workflows-FCPM4S4D.js +0 -184
  508. package/dist/dashboard-web/skins/bluearchive-hero.webp +0 -0
  509. package/dist/dashboard-web/skins/dragonball-goku.webp +0 -0
  510. package/dist/dashboard-web/skins/dragonball-wukong.webp +0 -0
  511. package/dist/dashboard-web/skins/genshin-breeze.webp +0 -0
  512. package/dist/dashboard-web/skins/ikun-hero.webp +0 -0
  513. package/dist/dashboard-web/skins/prts-priestess.webp +0 -0
  514. package/dist/dashboard-web/skins/zzz-hero.webp +0 -0
  515. package/dist/dashboard-web/skins/zzz-pattern.svg +0 -25
@@ -0,0 +1,717 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Fragment, useCallback, useEffect, useMemo, useRef, useState, } from 'react';
3
+ import { DropdownMenu, LoadingState } from './dashboard-components.js';
4
+ import { mountReactPage } from './react-mount.js';
5
+ import { useT } from './react-hooks.js';
6
+ import { WorkflowVersionSwitch } from './workflow-version-switch.js';
7
+ import { LEGACY_WORKFLOW_DETAIL_POLL_MS, LEGACY_WORKFLOW_POLL_MS, buildAttemptTimeline, buildCardDescriptors, cancelLegacyWorkflowRun, clamp, cliRequiresNativeSessionId, computeTerminalSurface, danglingSummary, endLegacyWorkflowResumeSession, eventSeqFromId, extractEventContext, fetchLegacyWorkflowEvents, fetchLegacyWorkflowRuns, fetchLegacyWorkflowSnapshot, fmtUpdated, formatClock, isOpenHumanGateAttempt, isResumeCapableCli, isTerminalWorkflowStatus, latestAttempt, legacyWorkflowStatusFilters, maxConcurrency, parseLegacyWorkflowHash, previewBody, previewMetaParts, resolveLegacyWorkflowWait, short, shortText, startLegacyWorkflowResumeSession, statusLabel, terminalMetaParts, terminalOpenInTabLabel, terminalSurfaceLabel, } from './workflows.js';
8
+ const EMPTY_EVENT_STATE = {
9
+ events: [],
10
+ oldestSeq: null,
11
+ newestSeq: null,
12
+ hasOlder: false,
13
+ totalCount: 0,
14
+ };
15
+ function isDocumentHidden() {
16
+ return typeof document !== 'undefined' && document.hidden;
17
+ }
18
+ function statusClassToken(status) {
19
+ return status.replace(/[^A-Za-z0-9_-]/g, '-');
20
+ }
21
+ function errMessage(err) {
22
+ return err instanceof Error ? err.message : String(err);
23
+ }
24
+ function ioBlockKey(keyPrefix, label) {
25
+ return `${keyPrefix}:${label}`;
26
+ }
27
+ function StatusBadge(props) {
28
+ const terminal = isTerminalWorkflowStatus(props.status) ? ' terminal' : ' live';
29
+ return (_jsx("span", { className: `wf-status${terminal} wf-status-${statusClassToken(props.status)}`, children: statusLabel(props.status) }));
30
+ }
31
+ function useLegacyWorkflowRuns(status) {
32
+ const [rows, setRows] = useState([]);
33
+ const [lastErr, setLastErr] = useState(null);
34
+ const [lastLoadedAt, setLastLoadedAt] = useState(null);
35
+ useEffect(() => {
36
+ let disposed = false;
37
+ let inflight = false;
38
+ let timer = null;
39
+ async function poll() {
40
+ if (disposed || inflight || isDocumentHidden())
41
+ return;
42
+ inflight = true;
43
+ try {
44
+ const nextRows = await fetchLegacyWorkflowRuns(status);
45
+ if (disposed)
46
+ return;
47
+ setRows(nextRows);
48
+ setLastErr(null);
49
+ setLastLoadedAt(new Date());
50
+ }
51
+ catch (err) {
52
+ if (disposed)
53
+ return;
54
+ setRows([]);
55
+ setLastErr(errMessage(err));
56
+ setLastLoadedAt(new Date());
57
+ }
58
+ finally {
59
+ inflight = false;
60
+ }
61
+ }
62
+ function scheduleNext() {
63
+ if (timer !== null)
64
+ window.clearTimeout(timer);
65
+ timer = window.setTimeout(async () => {
66
+ await poll();
67
+ if (!disposed)
68
+ scheduleNext();
69
+ }, LEGACY_WORKFLOW_POLL_MS);
70
+ }
71
+ function onVisibility() {
72
+ if (document.hidden)
73
+ return;
74
+ void poll();
75
+ }
76
+ document.addEventListener('visibilitychange', onVisibility);
77
+ void poll().then(() => {
78
+ if (!disposed)
79
+ scheduleNext();
80
+ });
81
+ return () => {
82
+ disposed = true;
83
+ if (timer !== null)
84
+ window.clearTimeout(timer);
85
+ document.removeEventListener('visibilitychange', onVisibility);
86
+ };
87
+ }, [status]);
88
+ return { rows, lastErr, lastLoadedAt };
89
+ }
90
+ function LegacyWorkflowListPage() {
91
+ const tr = useT();
92
+ const [query, setQuery] = useState('');
93
+ const [status, setStatus] = useState('');
94
+ const { rows, lastErr, lastLoadedAt } = useLegacyWorkflowRuns(status);
95
+ const statusFilters = legacyWorkflowStatusFilters();
96
+ const statusFilterLabel = statusFilters.find(option => option.value === status)?.label ?? status;
97
+ const filteredRows = useMemo(() => {
98
+ const q = query.trim().toLowerCase();
99
+ if (!q)
100
+ return rows;
101
+ return rows.filter((row) => row.runId.toLowerCase().includes(q) ||
102
+ row.workflowId.toLowerCase().includes(q) ||
103
+ (row.chatId ?? '').toLowerCase().includes(q));
104
+ }, [query, rows]);
105
+ const loadText = lastErr
106
+ ? tr('workflow.list.error', { error: lastErr })
107
+ : lastLoadedAt
108
+ ? tr('workflow.list.loaded', { count: rows.length, time: lastLoadedAt.toLocaleTimeString() })
109
+ : '';
110
+ const emptyText = lastErr
111
+ ? tr('workflow.list.failedLoad', { error: lastErr })
112
+ : rows.length === 0
113
+ ? tr('workflow.list.noRuns')
114
+ : tr('workflow.list.noFilterMatch');
115
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "page-heading", children: [_jsxs("div", { children: [_jsx("p", { className: "eyebrow", children: tr('nav.workflows') }), _jsx("h1", { children: tr('nav.workflows') })] }), _jsx("div", { className: "page-heading-actions", children: _jsx(WorkflowVersionSwitch, { active: "legacy" }) })] }), _jsxs("form", { className: "filters dashboard-toolbar", onSubmit: (event) => event.preventDefault(), children: [_jsx("input", { type: "search", name: "q", value: query, placeholder: tr('workflow.searchPlaceholder'), onChange: (event) => setQuery(event.currentTarget.value) }), _jsx(DropdownMenu, { id: "legacy-workflow-status", className: "legacy-workflow-status-menu", ariaLabel: tr('workflow.table.status'), label: statusFilterLabel, value: status, options: statusFilters, onChange: setStatus }), _jsx("span", { className: `toolbar-status${lastErr ? ' error' : ''}`, children: loadText })] }), _jsx("div", { className: "workflow-runs-table-wrap", children: _jsxs("table", { className: "data-table workflow-runs-table", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: tr('workflow.table.run') }), _jsx("th", { children: tr('workflow.table.workflow') }), _jsx("th", { children: tr('workflow.table.status') }), _jsx("th", { children: tr('workflow.table.lastSeq') }), _jsx("th", { children: tr('workflow.table.dangling') }), _jsx("th", { children: tr('workflow.table.updated') }), _jsx("th", { children: tr('workflow.table.chatApp') })] }) }), _jsx("tbody", { children: filteredRows.length > 0 ? filteredRows.map((row) => (_jsx(RunListRow, { row: row }, row.runId))) : (_jsx("tr", { children: _jsx("td", { colSpan: 7, className: "empty", children: emptyText }) })) })] }) })] }));
116
+ }
117
+ function RunListRow(props) {
118
+ const row = props.row;
119
+ const dangling = `${row.dEf}/${row.dAct}/${row.dWait}`;
120
+ const danglingClass = row.dEf + row.dAct + row.dWait > 0 ? 'wf-dangling has' : 'wf-dangling none';
121
+ return (_jsxs("tr", { "data-runid": row.runId, children: [_jsx("td", { children: _jsx("a", { href: `#/legacy-workflow/${encodeURIComponent(row.runId)}`, children: _jsx("code", { children: row.runId }) }) }), _jsx("td", { children: row.workflowId }), _jsxs("td", { children: [_jsx(StatusBadge, { status: row.status }), row.failedNodeId ? _jsxs("span", { className: "muted", children: [" (", row.failedNodeId, ")"] }) : null, _jsx(RunErrorSummary, { row: row })] }), _jsx("td", { children: row.lastSeq }), _jsx("td", { className: danglingClass, children: dangling }), _jsx("td", { title: new Date(row.updatedAt).toISOString(), children: fmtUpdated(row.updatedAt) }), _jsxs("td", { children: [row.chatId ? row.chatId : null, row.chatId && row.larkAppId ? _jsx("br", {}) : null, row.larkAppId ? _jsx("span", { className: "muted", children: row.larkAppId }) : null, !row.chatId && !row.larkAppId ? '—' : null] })] }));
122
+ }
123
+ function RunErrorSummary(props) {
124
+ const { row } = props;
125
+ if (!row.errorCode)
126
+ return null;
127
+ const message = row.errorMessage ? ` - ${shortText(row.errorMessage, 96)}` : '';
128
+ return (_jsxs("div", { className: "wf-run-error", children: [_jsx("span", { className: "muted error", children: row.errorCode }), message] }));
129
+ }
130
+ function mergeEventWindow(current, win, direction) {
131
+ const base = direction === 'reset' ? [] : current.events;
132
+ const eventIds = new Set(base.map((event) => event.eventId));
133
+ const fresh = win.events.filter((event) => {
134
+ if (eventIds.has(event.eventId))
135
+ return false;
136
+ eventIds.add(event.eventId);
137
+ return true;
138
+ });
139
+ const events = (direction === 'prepend' ? [...fresh, ...base] : [...base, ...fresh])
140
+ .sort((a, b) => eventSeqFromId(a.eventId) - eventSeqFromId(b.eventId));
141
+ if (direction === 'reset') {
142
+ return {
143
+ events,
144
+ oldestSeq: win.oldestSeq,
145
+ newestSeq: win.newestSeq,
146
+ hasOlder: win.hasOlder,
147
+ totalCount: win.totalCount,
148
+ };
149
+ }
150
+ if (direction === 'prepend') {
151
+ return {
152
+ events,
153
+ oldestSeq: win.oldestSeq ?? current.oldestSeq,
154
+ newestSeq: current.newestSeq,
155
+ hasOlder: win.hasOlder,
156
+ totalCount: win.totalCount,
157
+ };
158
+ }
159
+ return {
160
+ events,
161
+ oldestSeq: current.oldestSeq ?? win.oldestSeq,
162
+ newestSeq: win.newestSeq ?? current.newestSeq,
163
+ hasOlder: current.hasOlder,
164
+ totalCount: win.totalCount,
165
+ };
166
+ }
167
+ function LegacyWorkflowDetailPage(props) {
168
+ const tr = useT();
169
+ const [snapshot, setSnapshot] = useState(null);
170
+ const snapshotRef = useRef(null);
171
+ const [eventState, setEventState] = useState(EMPTY_EVENT_STATE);
172
+ const eventStateRef = useRef(EMPTY_EVENT_STATE);
173
+ const [detailError, setDetailError] = useState(null);
174
+ const [cancelStatus, setCancelStatus] = useState(null);
175
+ const [canceling, setCanceling] = useState(false);
176
+ const [loadingFailed, setLoadingFailed] = useState(false);
177
+ const [loadingOlder, setLoadingOlder] = useState(false);
178
+ const [focusAttemptId, setFocusAttemptId] = useState(props.focusAttemptId);
179
+ const [approvalComments, setApprovalComments] = useState(() => new Map());
180
+ const [approvalStatuses, setApprovalStatuses] = useState(() => new Map());
181
+ const [resolvingWaits, setResolvingWaits] = useState(() => new Set());
182
+ const [resumeSessions, setResumeSessions] = useState(() => new Map());
183
+ const [resumePending, setResumePending] = useState(() => new Set());
184
+ const [resumeErrors, setResumeErrors] = useState(() => new Map());
185
+ const [openBlocks, setOpenBlocks] = useState(() => new Set());
186
+ const scrollTopsRef = useRef(new Map());
187
+ const disposedRef = useRef(false);
188
+ const inflightRef = useRef(false);
189
+ const applyEventWindow = useCallback((win, direction) => {
190
+ const next = mergeEventWindow(eventStateRef.current, win, direction);
191
+ eventStateRef.current = next;
192
+ setEventState(next);
193
+ }, []);
194
+ const setSnapshotBoth = useCallback((next) => {
195
+ snapshotRef.current = next;
196
+ setSnapshot(next);
197
+ }, []);
198
+ const poll = useCallback(async (options = {}) => {
199
+ if (disposedRef.current || inflightRef.current)
200
+ return;
201
+ if (!options.allowHidden && isDocumentHidden())
202
+ return;
203
+ inflightRef.current = true;
204
+ try {
205
+ const nextSnapshot = await fetchLegacyWorkflowSnapshot(props.runId);
206
+ if (disposedRef.current)
207
+ return;
208
+ setSnapshotBoth(nextSnapshot);
209
+ const currentEvents = eventStateRef.current;
210
+ if (currentEvents.newestSeq !== null) {
211
+ const win = await fetchLegacyWorkflowEvents(props.runId, new URLSearchParams({ afterSeq: String(currentEvents.newestSeq), limit: '200' }));
212
+ if (!disposedRef.current)
213
+ applyEventWindow(win, 'append');
214
+ }
215
+ else {
216
+ const win = await fetchLegacyWorkflowEvents(props.runId, new URLSearchParams({ tail: '1' }));
217
+ if (!disposedRef.current)
218
+ applyEventWindow(win, 'reset');
219
+ }
220
+ if (!disposedRef.current) {
221
+ setDetailError(null);
222
+ setLoadingFailed(false);
223
+ }
224
+ }
225
+ catch (err) {
226
+ if (!disposedRef.current)
227
+ setDetailError(errMessage(err));
228
+ }
229
+ finally {
230
+ inflightRef.current = false;
231
+ }
232
+ }, [applyEventWindow, props.runId, setSnapshotBoth]);
233
+ const initialLoad = useCallback(async () => {
234
+ const nextSnapshot = await fetchLegacyWorkflowSnapshot(props.runId);
235
+ if (disposedRef.current)
236
+ return;
237
+ setSnapshotBoth(nextSnapshot);
238
+ const win = await fetchLegacyWorkflowEvents(props.runId, new URLSearchParams({ tail: '100' }));
239
+ if (disposedRef.current)
240
+ return;
241
+ applyEventWindow(win, 'reset');
242
+ }, [applyEventWindow, props.runId, setSnapshotBoth]);
243
+ useEffect(() => {
244
+ disposedRef.current = false;
245
+ inflightRef.current = false;
246
+ snapshotRef.current = null;
247
+ eventStateRef.current = EMPTY_EVENT_STATE;
248
+ let timer = null;
249
+ function scheduleNext() {
250
+ if (timer !== null)
251
+ window.clearTimeout(timer);
252
+ if (snapshotRef.current && isTerminalWorkflowStatus(snapshotRef.current.run.status)) {
253
+ timer = null;
254
+ return;
255
+ }
256
+ timer = window.setTimeout(async () => {
257
+ await poll();
258
+ if (!disposedRef.current)
259
+ scheduleNext();
260
+ }, LEGACY_WORKFLOW_DETAIL_POLL_MS);
261
+ }
262
+ function onVisibility() {
263
+ if (document.hidden)
264
+ return;
265
+ void poll({ allowHidden: true }).then(() => {
266
+ if (!disposedRef.current && timer === null)
267
+ scheduleNext();
268
+ });
269
+ }
270
+ document.addEventListener('visibilitychange', onVisibility);
271
+ void initialLoad()
272
+ .then(() => {
273
+ if (disposedRef.current)
274
+ return;
275
+ setDetailError(null);
276
+ setLoadingFailed(false);
277
+ scheduleNext();
278
+ })
279
+ .catch((err) => {
280
+ if (disposedRef.current)
281
+ return;
282
+ setDetailError(errMessage(err));
283
+ setLoadingFailed(true);
284
+ });
285
+ return () => {
286
+ disposedRef.current = true;
287
+ if (timer !== null)
288
+ window.clearTimeout(timer);
289
+ document.removeEventListener('visibilitychange', onVisibility);
290
+ };
291
+ }, [initialLoad, poll]);
292
+ useEffect(() => {
293
+ if (snapshot && isTerminalWorkflowStatus(snapshot.run.status))
294
+ setCancelStatus(null);
295
+ }, [snapshot]);
296
+ const loadOlderEvents = useCallback(async () => {
297
+ const current = eventStateRef.current;
298
+ if (current.oldestSeq === null || !current.hasOlder || loadingOlder)
299
+ return;
300
+ setLoadingOlder(true);
301
+ try {
302
+ const win = await fetchLegacyWorkflowEvents(props.runId, new URLSearchParams({ beforeSeq: String(current.oldestSeq), limit: '100' }));
303
+ if (!disposedRef.current) {
304
+ applyEventWindow(win, 'prepend');
305
+ setDetailError(null);
306
+ }
307
+ }
308
+ catch (err) {
309
+ if (!disposedRef.current)
310
+ setDetailError(errMessage(err));
311
+ }
312
+ finally {
313
+ if (!disposedRef.current)
314
+ setLoadingOlder(false);
315
+ }
316
+ }, [applyEventWindow, loadingOlder, props.runId]);
317
+ const cancelRun = useCallback(async () => {
318
+ const current = snapshotRef.current;
319
+ if (!current || isTerminalWorkflowStatus(current.run.status) || canceling)
320
+ return;
321
+ if (!current.chatBinding?.larkAppId) {
322
+ setDetailError(tr('workflow.detail.cancelUnavailable', { runId: props.runId }));
323
+ return;
324
+ }
325
+ const dangling = danglingSummary(current);
326
+ const message = tr('workflow.detail.cancelConfirm', { runId: props.runId, ...dangling });
327
+ if (!window.confirm(message))
328
+ return;
329
+ setCanceling(true);
330
+ try {
331
+ const body = await cancelLegacyWorkflowRun(props.runId);
332
+ setCancelStatus(body.pending ? tr('workflow.detail.cancelPending') : null);
333
+ setDetailError(null);
334
+ await poll({ allowHidden: true });
335
+ }
336
+ catch (err) {
337
+ setDetailError(errMessage(err));
338
+ }
339
+ finally {
340
+ setCanceling(false);
341
+ }
342
+ }, [canceling, poll, props.runId, tr]);
343
+ const resolveHumanGate = useCallback(async (attemptId, action) => {
344
+ if (resolvingWaits.has(attemptId))
345
+ return;
346
+ setResolvingWaits((prev) => new Set(prev).add(attemptId));
347
+ setApprovalStatuses((prev) => {
348
+ const next = new Map(prev);
349
+ next.delete(attemptId);
350
+ return next;
351
+ });
352
+ try {
353
+ const comment = approvalComments.get(attemptId)?.trim() || undefined;
354
+ const body = await resolveLegacyWorkflowWait(props.runId, action, comment);
355
+ const label = action === 'approve' ? tr('workflow.detail.approved') : tr('workflow.detail.rejected');
356
+ const text = body.alreadyTerminal
357
+ ? tr('workflow.detail.alreadyTerminal', { label })
358
+ : body.pending
359
+ ? tr('workflow.detail.workflowContinue', { label })
360
+ : tr('workflow.detail.workflowRefreshing', { label });
361
+ setApprovalStatuses((prev) => new Map(prev).set(attemptId, { kind: 'ok', text }));
362
+ setDetailError(null);
363
+ await poll({ allowHidden: true });
364
+ }
365
+ catch (err) {
366
+ const message = errMessage(err);
367
+ setApprovalStatuses((prev) => new Map(prev).set(attemptId, { kind: 'error', text: message }));
368
+ setDetailError(message);
369
+ }
370
+ finally {
371
+ setResolvingWaits((prev) => {
372
+ const next = new Set(prev);
373
+ next.delete(attemptId);
374
+ return next;
375
+ });
376
+ }
377
+ }, [approvalComments, poll, props.runId, resolvingWaits, tr]);
378
+ const startResumeSession = useCallback(async (attemptId, activityId) => {
379
+ if (resumePending.has(attemptId))
380
+ return;
381
+ setResumePending((prev) => new Set(prev).add(attemptId));
382
+ setResumeErrors((prev) => {
383
+ const next = new Map(prev);
384
+ next.delete(attemptId);
385
+ return next;
386
+ });
387
+ try {
388
+ const session = await startLegacyWorkflowResumeSession(props.runId, activityId, attemptId);
389
+ setResumeSessions((prev) => new Map(prev).set(attemptId, session));
390
+ }
391
+ catch (err) {
392
+ setResumeErrors((prev) => new Map(prev).set(attemptId, errMessage(err)));
393
+ }
394
+ finally {
395
+ setResumePending((prev) => {
396
+ const next = new Set(prev);
397
+ next.delete(attemptId);
398
+ return next;
399
+ });
400
+ }
401
+ }, [props.runId, resumePending]);
402
+ const endResumeSession = useCallback(async (attemptId, activityId) => {
403
+ if (resumePending.has(attemptId))
404
+ return;
405
+ setResumePending((prev) => new Set(prev).add(attemptId));
406
+ setResumeErrors((prev) => {
407
+ const next = new Map(prev);
408
+ next.delete(attemptId);
409
+ return next;
410
+ });
411
+ try {
412
+ await endLegacyWorkflowResumeSession(props.runId, activityId, attemptId);
413
+ setResumeSessions((prev) => {
414
+ const next = new Map(prev);
415
+ next.delete(attemptId);
416
+ return next;
417
+ });
418
+ }
419
+ catch (err) {
420
+ setResumeErrors((prev) => new Map(prev).set(attemptId, errMessage(err)));
421
+ }
422
+ finally {
423
+ setResumePending((prev) => {
424
+ const next = new Set(prev);
425
+ next.delete(attemptId);
426
+ return next;
427
+ });
428
+ }
429
+ }, [props.runId, resumePending]);
430
+ const blockState = useMemo(() => ({
431
+ openBlocks,
432
+ scrollTops: scrollTopsRef.current,
433
+ setBlockOpen: (key, open) => {
434
+ setOpenBlocks((prev) => {
435
+ const next = new Set(prev);
436
+ if (open)
437
+ next.add(key);
438
+ else
439
+ next.delete(key);
440
+ return next;
441
+ });
442
+ },
443
+ // Ref, not state: scrolling an IO preview shouldn't setState → re-render the whole detail
444
+ // page on every scroll tick. The value is only read imperatively to restore preRef.scrollTop.
445
+ setBlockScrollTop: (key, top) => {
446
+ scrollTopsRef.current.set(key, top);
447
+ },
448
+ }), [openBlocks]);
449
+ const approvalState = useMemo(() => ({
450
+ comments: approvalComments,
451
+ statuses: approvalStatuses,
452
+ resolving: resolvingWaits,
453
+ }), [approvalComments, approvalStatuses, resolvingWaits]);
454
+ const resumeState = useMemo(() => ({
455
+ sessions: resumeSessions,
456
+ pending: resumePending,
457
+ errors: resumeErrors,
458
+ }), [resumeErrors, resumePending, resumeSessions]);
459
+ const run = snapshot?.run;
460
+ const isTerminal = run ? isTerminalWorkflowStatus(run.status) : false;
461
+ const canCancelInDashboard = !!snapshot?.chatBinding?.larkAppId;
462
+ const cancelLabel = canCancelInDashboard ? tr('workflow.detail.cancel') : tr('workflow.detail.cliCancelOnly');
463
+ const cancelTitle = canCancelInDashboard
464
+ ? tr('workflow.detail.cancelTitle')
465
+ : tr('workflow.detail.cliCancelTitle', { runId: props.runId });
466
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "page-heading wf-detail-head", children: [_jsxs("div", { children: [_jsx("p", { className: "eyebrow", children: tr('nav.workflows') }), _jsx("h1", { children: _jsx("code", { children: props.runId }) }), _jsx("p", { className: "muted", children: snapshot ? (_jsxs(_Fragment, { children: [run?.workflowId ?? '?', " \u00B7 ", _jsx(StatusBadge, { status: run?.status ?? 'unknown' }), " \u00B7 lastSeq ", snapshot.lastSeq] })) : loadingFailed ? tr('workflow.detail.loadFailed') : tr('workflow.detail.loading') })] }), _jsxs("div", { className: "page-heading-actions", children: [_jsx("span", { className: "toolbar-status", children: snapshot ? tr('workflow.detail.refreshed', { time: new Date().toLocaleTimeString() }) : '' }), _jsx("button", { type: "button", className: "contrast", hidden: !snapshot || isTerminal, disabled: canceling || !canCancelInDashboard, title: cancelTitle, onClick: () => void cancelRun(), children: cancelLabel }), _jsx("a", { className: "btn-link", href: "#/legacy-workflow", children: tr('workflow.detail.back') }), _jsx(WorkflowVersionSwitch, { active: "legacy" })] })] }), detailError ? _jsx("section", { className: "hint-warn", children: detailError }) : null, cancelStatus ? _jsx("section", { className: "hint-ok", children: cancelStatus }) : null, !snapshot && !loadingFailed && !detailError ? _jsx(LoadingState, { label: tr('workflow.detail.loading') }) : null, snapshot ? (_jsxs(_Fragment, { children: [_jsx(SummaryGrid, { snapshot: snapshot }), _jsx(DanglingPanel, { snapshot: snapshot }), _jsx(ParallelPanel, { snapshot: snapshot, events: eventState.events }), _jsx(NodeActivityPanel, { snapshot: snapshot }), _jsx(NodeIOPanel, { runId: props.runId, snapshot: snapshot, approval: approvalState, resume: resumeState, blockState: blockState, focusAttemptId: focusAttemptId, onCommentChange: (attemptId, value) => {
467
+ setApprovalComments((prev) => new Map(prev).set(attemptId, value));
468
+ }, onResolve: resolveHumanGate, onResumeStart: startResumeSession, onResumeEnd: endResumeSession, onFocusConsumed: () => setFocusAttemptId(undefined) }), _jsx(TimelinePanel, { events: eventState.events, totalCount: eventState.totalCount, hasOlder: eventState.hasOlder, loadingOlder: loadingOlder, onLoadOlder: loadOlderEvents })] })) : null] }));
469
+ }
470
+ function SummaryGrid(props) {
471
+ const tr = useT();
472
+ const snap = props.snapshot;
473
+ const run = snap.run;
474
+ const items = [
475
+ { label: tr('workflow.summary.workflow'), value: run.workflowId ?? '?' },
476
+ { label: tr('workflow.summary.status'), value: _jsx(StatusBadge, { status: run.status }) },
477
+ { label: tr('workflow.summary.lastSeq'), value: snap.lastSeq },
478
+ { label: tr('workflow.summary.updated'), value: new Date(snap.updatedAt).toLocaleString() },
479
+ { label: tr('workflow.summary.revision'), value: short(run.revisionId) },
480
+ { label: tr('workflow.summary.initiator'), value: run.initiator ?? '-' },
481
+ ];
482
+ if (run.failedNodeId)
483
+ items.push({ label: tr('workflow.summary.failedNode'), value: run.failedNodeId });
484
+ if (run.cancelOriginEventId)
485
+ items.push({ label: tr('workflow.summary.cancelOrigin'), value: run.cancelOriginEventId });
486
+ if (snap.chatBinding) {
487
+ items.push({ label: tr('workflow.summary.chat'), value: _jsx("code", { children: snap.chatBinding.chatId }) });
488
+ items.push({ label: tr('workflow.summary.app'), value: _jsx("code", { children: snap.chatBinding.larkAppId }) });
489
+ }
490
+ return (_jsx("section", { className: "wf-summary-grid", children: items.map((item) => (_jsxs("div", { className: "wf-summary-item", children: [_jsx("span", { children: item.label }), _jsx("strong", { children: item.value })] }, item.label))) }));
491
+ }
492
+ function DanglingPanel(props) {
493
+ const tr = useT();
494
+ const d = props.snapshot.dangling;
495
+ const groups = [
496
+ [tr('workflow.dangling.activities'), d.activities],
497
+ [tr('workflow.dangling.effects'), d.effectAttempted],
498
+ [tr('workflow.dangling.waits'), d.waits],
499
+ [tr('workflow.dangling.cancels'), d.cancels],
500
+ ];
501
+ const total = new Set(groups.flatMap(([, items]) => items)).size;
502
+ return (_jsxs("section", { className: `wf-panel wf-dangling-panel${total > 0 ? ' has' : ''}`, children: [_jsxs("div", { className: "wf-panel-title", children: [_jsx("h3", { children: tr('workflow.detail.dangling') }), total > 0 ? _jsx("span", { className: "wf-dangling has", children: total }) : null] }), total === 0 ? (_jsx("div", { className: "muted", children: tr('workflow.detail.noDangling') })) : (_jsx("div", { className: "wf-dangling-grid", children: groups.map(([label, items]) => (_jsxs("div", { children: [_jsx("strong", { children: label }), items.length === 0 ? (_jsx("div", { className: "muted", children: tr('workflow.detail.none') })) : (_jsx("ul", { children: items.map((item) => _jsx("li", { children: _jsx("code", { children: item }) }, item)) }))] }, label))) }))] }));
503
+ }
504
+ function ParallelPanel(props) {
505
+ const tr = useT();
506
+ const items = useMemo(() => buildAttemptTimeline(props.events, props.snapshot), [props.events, props.snapshot]);
507
+ const now = Date.now();
508
+ if (items.length === 0) {
509
+ return (_jsxs("section", { className: "wf-panel", children: [_jsxs("div", { className: "wf-panel-title", children: [_jsx("h3", { children: tr('workflow.detail.parallel') }), _jsx("span", { className: "muted" })] }), _jsx("div", { className: "empty", children: tr('workflow.detail.noParallelData') })] }));
510
+ }
511
+ const start = Math.min(...items.map((item) => item.startedAt));
512
+ const end = Math.max(...items.map((item) => item.endedAt ?? now), start + 1000);
513
+ const duration = Math.max(1, end - start);
514
+ const running = items.filter((item) => !item.endedAt && (item.status === 'running' || item.status === 'effectAttempting')).length;
515
+ const meta = tr('workflow.detail.parallelMeta', {
516
+ count: items.length,
517
+ max: maxConcurrency(items, now),
518
+ running,
519
+ });
520
+ return (_jsxs("section", { className: "wf-panel", children: [_jsxs("div", { className: "wf-panel-title", children: [_jsx("h3", { children: tr('workflow.detail.parallel') }), _jsx("span", { className: "muted", children: meta })] }), _jsxs("div", { children: [_jsxs("div", { className: "wf-parallel-axis", children: [_jsx("span", { title: new Date(start).toISOString(), children: formatClock(start) }), _jsx("span", { title: new Date(end).toISOString(), children: formatClock(end) })] }), _jsx("div", { className: "wf-parallel-list", children: [...items]
521
+ .sort((a, b) => a.startedAt - b.startedAt || a.activityId.localeCompare(b.activityId))
522
+ .map((item) => (_jsx(ParallelRow, { item: item, start: start, duration: duration, now: now }, item.attemptId))) })] })] }));
523
+ }
524
+ function ParallelRow(props) {
525
+ const tr = useT();
526
+ const { item } = props;
527
+ const end = item.endedAt ?? props.now;
528
+ const left = clamp(((item.startedAt - props.start) / props.duration) * 100, 0, 100);
529
+ const width = clamp(((Math.max(end, item.startedAt + 1) - item.startedAt) / props.duration) * 100, 0.7, 100 - left);
530
+ const label = item.nodeId ?? item.activityId;
531
+ const attempt = item.attemptNumber !== undefined ? `#${item.attemptNumber}` : short(item.attemptId);
532
+ const title = [
533
+ `${label} ${item.status}`,
534
+ `${new Date(item.startedAt).toISOString()} -> ${item.endedAt ? new Date(item.endedAt).toISOString() : tr('workflow.detail.parallelNow')}`,
535
+ item.endType ? `end: ${item.endType}` : undefined,
536
+ ].filter(Boolean).join('\n');
537
+ return (_jsxs("div", { className: "wf-parallel-row", children: [_jsxs("div", { className: "wf-parallel-label", children: [_jsx("code", { children: label }), _jsxs("span", { className: "muted", children: [item.activityId, " \u00B7 ", attempt] })] }), _jsx("div", { className: "wf-parallel-track", children: _jsx("div", { className: `wf-parallel-bar wf-parallel-${statusClassToken(item.status)}`, style: { left: `${left.toFixed(3)}%`, width: `${width.toFixed(3)}%` }, title: title, children: _jsx("span", { children: statusLabel(item.status) }) }) })] }));
538
+ }
539
+ function NodeActivityPanel(props) {
540
+ const tr = useT();
541
+ const rows = useMemo(() => buildNodeActivityRows(props.snapshot), [props.snapshot]);
542
+ return (_jsxs("section", { className: "wf-panel", children: [_jsx("div", { className: "wf-panel-title", children: _jsx("h3", { children: tr('workflow.detail.nodes') }) }), _jsx("div", { className: "wf-table-scroll", children: _jsxs("table", { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: tr('workflow.detail.node') }), _jsx("th", { children: tr('workflow.detail.nodeStatus') }), _jsx("th", { children: tr('workflow.detail.activity') }), _jsx("th", { children: tr('workflow.detail.activityStatus') }), _jsx("th", { children: tr('workflow.detail.attempts') }), _jsx("th", { children: tr('workflow.detail.current') }), _jsx("th", { children: tr('workflow.detail.detail') })] }) }), _jsx("tbody", { children: rows.length > 0 ? rows.map((row) => (_jsx(NodeActivityRow, { ...row }, `${row.node?.nodeId ?? 'activity'}:${row.activity?.activityId ?? 'idle'}`))) : (_jsx("tr", { children: _jsx("td", { colSpan: 7, className: "empty", children: tr('workflow.detail.noNodes') }) })) })] }) })] }));
543
+ }
544
+ function buildNodeActivityRows(snap) {
545
+ const byId = new Map(snap.activities.map((activity) => [activity.activityId, activity]));
546
+ const used = new Set();
547
+ const rows = [];
548
+ for (const node of snap.nodes) {
549
+ const activity = (node.activityId ? byId.get(node.activityId) : undefined) ??
550
+ snap.activities.find((candidate) => candidate.ownerNodeId === node.nodeId);
551
+ if (activity)
552
+ used.add(activity.activityId);
553
+ rows.push({ node, activity });
554
+ }
555
+ for (const activity of snap.activities) {
556
+ if (!used.has(activity.activityId))
557
+ rows.push({ activity });
558
+ }
559
+ return rows;
560
+ }
561
+ function NodeActivityRow(props) {
562
+ const tr = useT();
563
+ const latest = latestAttempt(props.activity);
564
+ return (_jsxs("tr", { children: [_jsx("td", { children: props.node ? _jsx("code", { children: props.node.nodeId }) : _jsx("span", { className: "muted", children: "-" }) }), _jsx("td", { children: props.node ? _jsx(StatusBadge, { status: props.node.status }) : _jsx("span", { className: "muted", children: "-" }) }), _jsx("td", { children: props.activity ? _jsx("code", { children: props.activity.activityId }) : _jsx("span", { className: "muted", children: "-" }) }), _jsx("td", { children: props.activity ? _jsx(StatusBadge, { status: props.activity.status }) : _jsx("span", { className: "muted", children: "-" }) }), _jsx("td", { children: props.activity?.attempts.length ?? 0 }), _jsx("td", { children: latest ? _jsx("code", { children: latest.attemptId }) : _jsx("span", { className: "muted", children: "-" }) }), _jsx("td", { children: latest ? _jsx(AttemptDetail, { attempt: latest }) : _jsx("span", { className: "muted", children: tr('workflow.detail.idle') }) })] }));
565
+ }
566
+ function AttemptDetail(props) {
567
+ const tr = useT();
568
+ const parts = [];
569
+ const attempt = props.attempt;
570
+ if (attempt.effectAttempted) {
571
+ parts.push(_jsxs(Fragment, { children: [tr('workflow.detail.effect'), " ", attempt.effectAttempted.provider] }, "effect"));
572
+ }
573
+ if (attempt.wait) {
574
+ const resolution = attempt.wait.resolution
575
+ ? `${attempt.wait.resolution.kind}${attempt.wait.resolution.resolution ? ':' + attempt.wait.resolution.resolution : ''}`
576
+ : tr('workflow.detail.open');
577
+ parts.push(_jsxs(Fragment, { children: [tr('workflow.detail.wait'), " ", attempt.wait.waitKind, " ", resolution] }, "wait"));
578
+ if (attempt.wait.deadlineAt !== undefined) {
579
+ parts.push(_jsxs(Fragment, { children: [tr('workflow.detail.deadline'), " ", formatClock(attempt.wait.deadlineAt)] }, "deadline"));
580
+ }
581
+ }
582
+ if (attempt.error) {
583
+ const tag = `${attempt.error.errorCode}${attempt.error.errorClass ? ` · ${attempt.error.errorClass}` : ''}`;
584
+ parts.push(_jsx("span", { className: "muted error", children: tag }, "error-tag"));
585
+ if (attempt.error.errorMessage) {
586
+ parts.push(_jsx("span", { className: "error wf-error-msg", children: attempt.error.errorMessage }, "error-message"));
587
+ }
588
+ }
589
+ if (attempt.output)
590
+ parts.push(_jsxs(Fragment, { children: [tr('workflow.detail.output'), " ", short(attempt.output.outputHash)] }, "output"));
591
+ if (attempt.runningMs !== undefined)
592
+ parts.push(_jsxs(Fragment, { children: [attempt.runningMs, "ms"] }, "running"));
593
+ if (parts.length === 0)
594
+ return _jsx("span", { className: "muted", children: "-" });
595
+ return (_jsx(_Fragment, { children: parts.map((part, index) => (_jsxs(Fragment, { children: [index > 0 ? _jsx("br", {}) : null, part] }, index))) }));
596
+ }
597
+ function NodeIOPanel(props) {
598
+ const tr = useT();
599
+ const descriptors = useMemo(() => buildCardDescriptors(props.snapshot), [props.snapshot]);
600
+ return (_jsxs("section", { className: "wf-panel", children: [_jsx("div", { className: "wf-panel-title", children: _jsx("h3", { children: tr('workflow.detail.nodeIO') }) }), _jsx("div", { className: "wf-io-list", children: descriptors.length > 0 ? descriptors.map((desc) => (_jsx(AttemptIOCard, { desc: desc, ...props }, desc.key))) : (_jsx("div", { className: "empty", children: tr('workflow.detail.noNodeIO') })) })] }));
601
+ }
602
+ function AttemptIOCard(props) {
603
+ const tr = useT();
604
+ const cardRef = useRef(null);
605
+ const attempt = latestAttempt(props.desc.activity);
606
+ const title = props.desc.node?.nodeId ?? props.desc.activity?.ownerNodeId ?? props.desc.activity?.activityId ?? 'unknown';
607
+ const keyPrefix = attempt?.attemptId ?? props.desc.activity?.activityId ?? props.desc.node?.nodeId ?? 'unknown';
608
+ const focusMatch = !!attempt && attempt.attemptId === props.focusAttemptId;
609
+ const terminalSurface = computeTerminalSurface({
610
+ runId: props.runId,
611
+ activity: props.desc.activity,
612
+ attempt,
613
+ terminal: props.desc.io?.terminal,
614
+ resumeSession: attempt ? props.resume.sessions.get(attempt.attemptId) : undefined,
615
+ });
616
+ const terminalBlockKey = terminalSurface
617
+ ? ioBlockKey(keyPrefix, terminalSurfaceLabel(terminalSurface.kind))
618
+ : null;
619
+ const scrolledRef = useRef(false);
620
+ useEffect(() => {
621
+ if (!focusMatch) {
622
+ scrolledRef.current = false;
623
+ return;
624
+ }
625
+ // Scroll the focused card into view once as soon as it exists — don't wait for the terminal
626
+ // sidecar (it may arrive a detail-poll later, or never for a terminal-less attempt).
627
+ if (!scrolledRef.current) {
628
+ scrolledRef.current = true;
629
+ cardRef.current?.scrollIntoView({ block: 'center' });
630
+ }
631
+ // Expand the terminal block + consume the deep-link focus once the surface is available.
632
+ if (terminalSurface && terminalBlockKey) {
633
+ props.blockState.setBlockOpen(terminalBlockKey, true);
634
+ props.onFocusConsumed();
635
+ }
636
+ }, [focusMatch, props, terminalBlockKey, terminalSurface]);
637
+ return (_jsxs("article", { ref: cardRef, className: `wf-io-card${focusMatch ? ' is-focused' : ''}`, "data-wf-card-key": props.desc.key, "data-wf-attempt-card": attempt?.attemptId, children: [_jsxs("div", { className: "wf-io-card-head", children: [_jsxs("header", { children: [_jsxs("div", { children: [_jsx("strong", { children: _jsx("code", { children: title }) }), _jsx("span", { className: "muted", children: props.desc.activity ? props.desc.activity.activityId : tr('workflow.detail.notDispatched') })] }), _jsxs("div", { children: [props.desc.node ? _jsx(StatusBadge, { status: props.desc.node.status }) : null, props.desc.node && props.desc.activity ? ' ' : null, props.desc.activity ? _jsx(StatusBadge, { status: props.desc.activity.status }) : null] })] }), _jsx("div", { className: "wf-io-meta", children: attempt ? _jsxs(_Fragment, { children: [tr('workflow.detail.attempt'), " ", _jsx("code", { children: attempt.attemptId })] }) : tr('workflow.detail.noAttempt') }), _jsx(ApprovalControls, { attempt: attempt, approval: props.approval, onCommentChange: props.onCommentChange, onResolve: props.onResolve })] }), _jsx("div", { className: "wf-io-terminal-slot", children: terminalSurface && props.desc.io?.terminal ? (_jsx(TerminalBlock, { runId: props.runId, keyPrefix: keyPrefix, attempt: attempt, activity: props.desc.activity, terminal: props.desc.io.terminal, surface: terminalSurface, resume: props.resume, blockState: props.blockState, onResumeStart: props.onResumeStart, onResumeEnd: props.onResumeEnd })) : null }), _jsxs("div", { className: "wf-io-grid", children: [_jsx(PreviewBlock, { keyPrefix: keyPrefix, label: tr('workflow.detail.authoredInput'), preview: props.desc.io?.input, blockState: props.blockState }), _jsx(PreviewBlock, { keyPrefix: keyPrefix, label: tr('workflow.detail.resolvedInput'), preview: props.desc.io?.resolvedInput, blockState: props.blockState }), _jsx(PreviewBlock, { keyPrefix: keyPrefix, label: tr('workflow.detail.output'), preview: props.desc.io?.output, blockState: props.blockState }), _jsx(PreviewBlock, { keyPrefix: keyPrefix, label: tr('workflow.detail.executionLog'), preview: props.desc.io?.log, blockState: props.blockState }), props.desc.io?.waitPrompt ? (_jsx(PreviewBlock, { keyPrefix: keyPrefix, label: tr('workflow.detail.waitPrompt'), preview: props.desc.io.waitPrompt, blockState: props.blockState })) : null] })] }));
638
+ }
639
+ function ApprovalControls(props) {
640
+ const tr = useT();
641
+ const attempt = props.attempt;
642
+ if (!isOpenHumanGateAttempt(attempt))
643
+ return null;
644
+ const comment = props.approval.comments.get(attempt.attemptId) ?? '';
645
+ const resolving = props.approval.resolving.has(attempt.attemptId);
646
+ const status = props.approval.statuses.get(attempt.attemptId);
647
+ return (_jsxs("div", { className: "wf-approval-box", "data-wf-approval": attempt.attemptId, children: [_jsxs("label", { children: [_jsx("span", { children: tr('workflow.detail.approvalComment') }), _jsx("textarea", { className: "wf-approval-comment", rows: 2, value: comment, placeholder: tr('workflow.detail.optionalComment'), disabled: resolving, onChange: (event) => props.onCommentChange(attempt.attemptId, event.currentTarget.value) })] }), _jsxs("div", { className: "wf-approval-actions", children: [_jsx("button", { type: "button", className: "primary", disabled: resolving, onClick: () => void props.onResolve(attempt.attemptId, 'approve'), children: tr('workflow.detail.approve') }), _jsx("button", { type: "button", disabled: resolving, onClick: () => void props.onResolve(attempt.attemptId, 'reject'), children: tr('workflow.detail.reject') }), resolving ? _jsx("span", { className: "muted", children: tr('workflow.detail.submitting') }) : null] }), status ? (_jsx("div", { className: `${status.kind === 'error' ? 'hint-warn' : 'hint-ok'} wf-approval-status`, children: status.text })) : null] }));
648
+ }
649
+ function TerminalBlock(props) {
650
+ const tr = useT();
651
+ const label = terminalSurfaceLabel(props.surface.kind);
652
+ const key = ioBlockKey(props.keyPrefix, label);
653
+ const open = props.blockState.openBlocks.has(key);
654
+ const meta = terminalMetaParts(props.attempt, props.terminal).join(' · ');
655
+ return (_jsxs("details", { className: "wf-io-block wf-terminal-block", "data-io-key": key, open: open, onToggle: (event) => props.blockState.setBlockOpen(key, event.currentTarget.open), children: [_jsxs("summary", { children: [label, " ", _jsx("span", { className: "muted", children: meta })] }), _jsxs("div", { className: "wf-terminal-actions", children: [_jsx("a", { className: "btn-link", href: props.surface.url, target: "_blank", rel: "noreferrer", children: terminalOpenInTabLabel(props.surface.kind) }), props.surface.kind === 'replay' || props.surface.kind === 'resume' ? (_jsx("a", { className: "btn-link", href: props.surface.downloadUrl, download: true, children: tr('workflow.detail.downloadFullLog') })) : null, _jsx(ResumeAction, { ...props })] }), props.attempt && props.resume.errors.has(props.attempt.attemptId) ? (_jsx("div", { className: "hint-warn wf-resume-status", children: props.resume.errors.get(props.attempt.attemptId) })) : null, _jsx("iframe", { className: "wf-terminal-frame", src: props.surface.url, title: label, loading: "lazy" })] }));
656
+ }
657
+ function ResumeAction(props) {
658
+ const tr = useT();
659
+ const { activity, attempt, surface, terminal } = props;
660
+ if (!attempt || !activity || surface.kind === 'live')
661
+ return null;
662
+ const pending = props.resume.pending.has(attempt.attemptId);
663
+ if (surface.kind === 'resume') {
664
+ return (_jsx("button", { type: "button", className: "btn-link", disabled: pending, onClick: () => void props.onResumeEnd(attempt.attemptId, activity.activityId), children: pending ? tr('workflow.detail.resumeEnding') : tr('workflow.detail.endResumeSession') }));
665
+ }
666
+ if (!isResumeCapableCli(terminal.cliId)) {
667
+ return (_jsx("button", { type: "button", className: "btn-link", disabled: true, title: tr('workflow.detail.resumeUnsupportedCli', { cliId: terminal.cliId ?? '?' }), children: tr('workflow.detail.resumeSession') }));
668
+ }
669
+ if (cliRequiresNativeSessionId(terminal.cliId) && !terminal.cliSessionId) {
670
+ return (_jsx("button", { type: "button", className: "btn-link", disabled: true, title: tr('workflow.detail.resumeMissingCliSession'), children: tr('workflow.detail.resumeSession') }));
671
+ }
672
+ return (_jsx("button", { type: "button", className: "btn-link", disabled: pending, onClick: () => void props.onResumeStart(attempt.attemptId, activity.activityId), children: pending ? tr('workflow.detail.resumeStarting') : tr('workflow.detail.resumeSession') }));
673
+ }
674
+ function PreviewBlock(props) {
675
+ const key = ioBlockKey(props.keyPrefix, props.label);
676
+ const open = props.blockState.openBlocks.has(key);
677
+ const meta = previewMetaParts(props.preview).join(' · ');
678
+ return (_jsxs("details", { className: "wf-io-block", "data-io-key": key, open: open, onToggle: (event) => props.blockState.setBlockOpen(key, event.currentTarget.open), children: [_jsxs("summary", { children: [props.label, " ", _jsx("span", { className: "muted", children: meta })] }), _jsx(PreviewContent, { preview: props.preview, blockKey: key, blockState: props.blockState })] }));
679
+ }
680
+ function PreviewContent(props) {
681
+ const tr = useT();
682
+ const preRef = useRef(null);
683
+ const body = previewBody(props.preview);
684
+ useEffect(() => {
685
+ const top = props.blockState.scrollTops.get(props.blockKey);
686
+ if (top !== undefined && preRef.current)
687
+ preRef.current.scrollTop = top;
688
+ });
689
+ if (!props.preview)
690
+ return _jsx("div", { className: "muted wf-io-empty", children: tr('workflow.detail.noData') });
691
+ return (_jsxs(_Fragment, { children: [props.preview.error ? _jsx("div", { className: "muted error", children: props.preview.error }) : null, body ? (_jsx("pre", { ref: preRef, className: "wf-io-pre", onScroll: (event) => props.blockState.setBlockScrollTop(props.blockKey, event.currentTarget.scrollTop), children: body })) : (_jsx("div", { className: "muted wf-io-empty", children: tr('workflow.detail.noPreview') }))] }));
692
+ }
693
+ function TimelinePanel(props) {
694
+ const tr = useT();
695
+ const scrollRef = useRef(null);
696
+ const scrollTopRef = useRef(0);
697
+ useEffect(() => {
698
+ if (scrollRef.current)
699
+ scrollRef.current.scrollTop = scrollTopRef.current;
700
+ }, [props.events]);
701
+ return (_jsxs("section", { className: "wf-panel", children: [_jsxs("div", { className: "wf-panel-title", children: [_jsx("h3", { children: tr('workflow.detail.timeline') }), _jsx("button", { type: "button", hidden: !props.hasOlder, disabled: props.loadingOlder, onClick: () => void props.onLoadOlder(), children: tr('workflow.detail.loadOlder') })] }), _jsx("div", { ref: scrollRef, className: "wf-table-scroll wf-timeline-scroll", onScroll: (event) => { scrollTopRef.current = event.currentTarget.scrollTop; }, children: _jsxs("table", { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: tr('workflow.detail.seq') }), _jsx("th", { children: tr('workflow.detail.event') }), _jsx("th", { children: tr('workflow.detail.actor') }), _jsx("th", { children: tr('workflow.detail.node') }), _jsx("th", { children: tr('workflow.detail.activity') }), _jsx("th", { children: tr('workflow.detail.error') }), _jsx("th", { children: tr('workflow.detail.time') })] }) }), _jsx("tbody", { children: props.events.length > 0 ? props.events.map((event) => (_jsx(EventRow, { event: event }, event.eventId))) : (_jsx("tr", { children: _jsx("td", { colSpan: 7, className: "empty", children: tr('workflow.detail.noEvents') }) })) })] }) }), _jsx("div", { className: "muted", children: tr('workflow.detail.eventsLoaded', { loaded: props.events.length, total: props.totalCount }) })] }));
702
+ }
703
+ function EventRow(props) {
704
+ const ctx = extractEventContext(props.event.payload);
705
+ return (_jsxs("tr", { children: [_jsx("td", { children: eventSeqFromId(props.event.eventId) }), _jsx("td", { children: _jsx("code", { children: props.event.type }) }), _jsx("td", { children: props.event.actor }), _jsx("td", { children: ctx.nodeId ? _jsx("code", { children: ctx.nodeId }) : '-' }), _jsx("td", { children: ctx.activityId ? _jsx("code", { children: ctx.activityId }) : '-' }), _jsx("td", { children: ctx.errorCode ? _jsx("span", { className: "muted error", children: ctx.errorCode }) : '-' }), _jsx("td", { title: new Date(props.event.timestamp).toISOString(), children: formatClock(props.event.timestamp) })] }));
706
+ }
707
+ function LegacyWorkflowPage() {
708
+ useT();
709
+ const route = parseLegacyWorkflowHash(location.hash);
710
+ return (_jsx("section", { className: "page workflows-page legacy-workflow-page", children: route.kind === 'detail'
711
+ ? _jsx(LegacyWorkflowDetailPage, { runId: route.runId, focusAttemptId: route.focusAttemptId })
712
+ : _jsx(LegacyWorkflowListPage, {}) }));
713
+ }
714
+ export function renderLegacyWorkflowPage(root) {
715
+ return mountReactPage(root, _jsx(LegacyWorkflowPage, {}));
716
+ }
717
+ //# sourceMappingURL=legacy-workflow-page.js.map