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
@@ -1,325 +0,0 @@
1
- import{b as Ft,g as zt,h as Wt}from"./chunk-3N2PPQVD.js";import{a as O}from"./chunk-LXIK7OUJ.js";import{A as Ne,b as Nt,c as Ot,d as Qe,e as Pt,f as et,g as Dt,h as _t,i as tt,j as qt,k as Ut,n as we,o as n,p as l,q as ce,r as se,s as Kt,t as jt,v as G,w as de,x as z}from"./chunk-3UJYRR2Q.js";var Gt=["backlog","todo","in_progress","in_review","done"];function Vt(r){return typeof r=="string"&&Gt.includes(r)?r:null}function Jt(r){if(r.status==="closed")return"done";let d=Vt(r.kanbanColumn);return d||(r.pendingRepo||r.tuiPromptActive||r.agentAttention||r.status==="limited"?"in_review":r.status==="starting"||r.status==="working"||r.status==="analyzing"||r.status==="active"?"in_progress":"todo")}var Dn=1e15;function oe(r){if(typeof r.kanbanPosition=="number"&&Number.isFinite(r.kanbanPosition))return r.kanbanPosition;let d=typeof r.lastMessageAt=="number"&&Number.isFinite(r.lastMessageAt)?r.lastMessageAt:0;return Dn-d}function nt(r,d){return r!==null&&d!==null?(r+d)/2:r!==null?r+1024:d!==null?d-1024:1024}var st=[24,72,168],_n=new Set(st);function ot(r){let d=r==="7d"?168:Number(r);return!Number.isFinite(d)||!_n.has(d)?null:d}function qn(r){let d=Number(r);return Number.isFinite(d)&&d>0?d:null}function Un(r,d=Date.now()){return d-r*60*60*1e3}function Kn(r,d,m=Date.now()){if(!r.sessionId||r.status!=="idle"||r.locked||r.pendingRepo||r.tuiPromptActive||r.agentAttention)return!1;let b=qn(r.lastMessageAt);return b!==null&&b<Un(d,m)}function Yt(r,d,m=Date.now()){return r.filter(b=>Kn(b,d,m))}var Xt={1:"claude-code",2:"aiden",3:"coco",4:"codex",5:"cursor",6:"gemini",7:"opencode",8:"antigravity",9:"mtr",10:"hermes",11:"codex-app",12:"mira",13:"seed",14:"traex",15:"pi",16:"copilot",17:"oh-my-pi",18:"relay",19:"mir",20:"kimi",21:"genius"},cs=new Set(Object.values(Xt)),jn={"claude-code":"Claude",aiden:"Aiden",coco:"CoCo",codex:"Codex",cursor:"Cursor",gemini:"Gemini",genius:"Genius",opencode:"OpenCode",antigravity:"Antigravity",mtr:"MTR",hermes:"Hermes","codex-app":"Codex App",mira:"Mira",seed:"Seed",traex:"TRAE",pi:"Pi",copilot:"Copilot","oh-my-pi":"Oh My Pi",relay:"Relay",mir:"Mir CLI",kimi:"Kimi"},Zt=Object.values(Xt).map(r=>({id:r,label:jn[r]??r}));function W(r,d){return`<th data-sort="${r}" data-label="${l(d)}">${l(d)}</th>`}function lt(r){return typeof r=="number"&&Number.isFinite(r)?r:null}function Qt(r){let d=lt(r);return d===null?"-":d.toLocaleString("en-US")}var ln=[...Zt.map(r=>r.id),"unknown"],en=[{id:"needs-you",labelKey:"sessions.board.needsYou",hintKey:"sessions.board.needsYouHint"},{id:"starting",labelKey:"sessions.board.starting",hintKey:"sessions.board.startingHint"},{id:"working",labelKey:"sessions.board.working",hintKey:"sessions.board.workingHint"},{id:"idle",labelKey:"sessions.board.idle",hintKey:"sessions.board.idleHint"}],tn=[{id:"backlog",labelKey:"sessions.kanban.backlog"},{id:"todo",labelKey:"sessions.kanban.todo"},{id:"in_progress",labelKey:"sessions.kanban.inProgress"},{id:"in_review",labelKey:"sessions.kanban.inReview"},{id:"done",labelKey:"sessions.kanban.done"}],at=50;function Fn(r){let d=(m="")=>`<svg viewBox="0 0 14 14" aria-hidden="true"><circle cx="7" cy="7" r="5.4" fill="none" stroke="currentColor" stroke-width="1.6"${m}/>`;switch(r){case"backlog":return`${d(' stroke-dasharray="1.6 2.1"')}</svg>`;case"in_progress":return`${d()}<path d="M7,7 L7,3.6 A3.4,3.4 0 0 1 7,10.4 Z" fill="currentColor"/></svg>`;case"in_review":return`${d()}<path d="M7,7 L7,3.6 A3.4,3.4 0 1 1 3.6,7 Z" fill="currentColor"/></svg>`;case"done":return'<svg viewBox="0 0 14 14" aria-hidden="true"><circle cx="7" cy="7" r="6.2" fill="currentColor"/><path d="M4.4 7.2 6.2 9 9.7 5.4" fill="none" stroke="var(--surface)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>';default:return`${d()}</svg>`}}function Oe(r){return String(r??"unknown").toLowerCase().replace(/[^a-z0-9_-]/g,"-")}var zn=["starting","working","idle","dormant","analyzing","active","limited","closed"];function Pe(r){let d=String(r??"unknown"),m=`sessions.status.${d}`,b=n(m);return b===m?d:b}function ve(r){let d=String(r??"unknown");return`<span class="status status-${l(Oe(d))}">${l(Pe(d))}</span>`}function nn(r){let d=String(r??"").trim();return d?d.replace(/\\/g,"/").split("/").filter(Boolean).at(-1)??d:"-"}function sn(r){return r?.chatType==="p2p"?n("sessions.directChat"):n("sessions.groupChat")}function ue(r){let d=String(r?.chatId??"").trim(),m=de(r);return m?`${sn(r)} \xB7 ${m}`:d?`${sn(r)} \xB7 ${d}`:n("sessions.chatUnknown")}function on(r,d=de){return!!String(r?.chatId??"").trim()&&!d(r)}function cn(r){let d=ue(r),m=String(r?.chatId??"").trim();return m&&!d.includes(m)?`${d} \xB7 ${m}`:d}function Wn(r){return`${JSON.stringify(r)} ${ue(r)} ${cn(r)}`.toLowerCase()}var it=Wt,L={pin:'<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M8 14.3s4.2-3.9 4.2-7.3A4.2 4.2 0 0 0 8 2.9a4.2 4.2 0 0 0-4.2 4.1C3.8 10.4 8 14.3 8 14.3z"/><circle cx="8" cy="6.9" r="1.5"/></svg>',openChat:'<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M9.4 2.8h3.8v3.8"/><path d="M13.2 2.8 7.3 8.7"/><path d="M11.5 9.3v2.9a1.2 1.2 0 0 1-1.2 1.2H3.8a1.2 1.2 0 0 1-1.2-1.2V5.7a1.2 1.2 0 0 1 1.2-1.2h2.9"/></svg>',details:'<svg viewBox="0 0 16 16" aria-hidden="true"><rect x="2.2" y="2.9" width="11.6" height="10.2" rx="1.8"/><path d="M9.9 2.9v10.2"/></svg>',terminal:'<svg viewBox="0 0 16 16" aria-hidden="true"><rect x="1.7" y="2.7" width="12.6" height="10.6" rx="2"/><path d="M4.4 6.3 6.4 8.1 4.4 9.9"/><path d="M8.2 10.2h3.4"/></svg>',key:'<svg viewBox="0 0 16 16" aria-hidden="true"><circle cx="6" cy="6.1" r="3"/><path d="M8.1 8.2 13 13.1"/><path d="M11.3 11.4 12.6 10.1"/><path d="M12.7 12.8 13.7 11.8"/></svg>',lock:'<svg viewBox="0 0 16 16" aria-hidden="true"><rect x="3.2" y="7" width="9.6" height="6.2" rx="1.4"/><path d="M5.2 7V5.2a2.8 2.8 0 0 1 5.6 0V7"/></svg>',unlock:'<svg viewBox="0 0 16 16" aria-hidden="true"><rect x="3.2" y="7" width="9.6" height="6.2" rx="1.4"/><path d="M5.2 7V5.2a2.8 2.8 0 0 1 5.2-1.4"/></svg>',close:'<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M4.2 4.2 11.8 11.8"/><path d="M11.8 4.2 4.2 11.8"/></svg>',edit:'<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M10.7 3.3 12.7 5.3 6.3 11.7 3.7 12.3 4.3 9.7 10.7 3.3z"/></svg>',history:'<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M2.2 4.8a2 2 0 0 1 2-2h7.6a2 2 0 0 1 2 2v4.6a2 2 0 0 1-2 2H6.6l-2.9 2.4v-2.4h-.5a2 2 0 0 1-2-2z"/><path d="M5.2 6.2h5.6M5.2 8.4h3.6"/></svg>',restart:'<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M12.4 6.2a4.8 4.8 0 1 0 1.1 3.1"/><path d="M12.4 2.9v3.3H9.1"/></svg>',feishu:'<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M2.6 4.4C6.4 4 10.4 5.4 13.4 8.2 9.8 7 6.4 6.6 3.4 7.4"/><path d="M13.4 8.2C9.6 8.7 6 10 2.9 12 5.6 9 8.8 7.6 13.4 8.2"/></svg>'};function Se(r,d,m,b=""){return`<button type="button" class="card-act${b?" "+b:""}" data-action="${r}" title="${l(m)}" aria-label="${l(m)}">${d}</button>`}function Ce(r){return r.locked?n("sessions.unlock"):n("sessions.lock")}function Te(r){return r.locked?`<span class="session-lock-badge" title="${l(n("sessions.locked"))}">${l(n("sessions.locked"))}</span>`:""}function an(r){if(!r)return"";let d=`<a class="term-btn term-open" href="${l(r)}" target="_blank" rel="noopener" title="${l(n("sessions.openTerminal"))}" aria-label="${l(n("sessions.openTerminal"))}">${L.terminal}</a>`;if(!we.authed)return`<span class="term-pill solo">${d}</span>`;let m=`<button type="button" class="term-btn term-write" data-action="write-link" title="${l(n("sessions.writeLinkHint"))}" aria-label="${l(n("sessions.writeLink"))}">${L.key}</button>`;return`<span class="term-pill">${d}${m}</span>`}async function rn(r,d){let m=window.open("about:blank","_blank");m&&(m.opener=null),d&&(d.disabled=!0);try{let b=await fetch(`/api/sessions/${encodeURIComponent(r.sessionId)}/write-link`),M=await b.json().catch(()=>({}));if(!b.ok||M?.ok===!1||!M?.url){m?.close(),b.status!==401&&alert(`${n("sessions.writeLinkFail")}: ${M?.error??b.status}`);return}m?m.location.href=M.url:window.open(M.url,"_blank","noopener")}catch(b){m?.close(),alert(`${n("sessions.writeLinkFail")}: ${b}`)}finally{d&&(d.disabled=!1)}}function Gn(r){return r.status==="closed"?null:r.pendingRepo||r.tuiPromptActive||r.agentAttention||r.status==="limited"?"needs-you":r.status==="starting"?"starting":r.status==="working"||r.status==="analyzing"||r.status==="active"?"working":(r.status==="dormant","idle")}function Vn(){return`<details class="filter-cli">
2
- <summary>${n("sessions.cli")} \xB7 <b id="cli-filter-count">${n("common.all")}</b></summary>
3
- <div class="filter-cli-pop" role="group" aria-label="${n("sessions.cli")}">
4
- ${ln.map(r=>`
5
- <label class="filter-check">
6
- <input type="checkbox" name="cli" value="${l(r)}" checked>
7
- <span>${l(r)}</span>
8
- </label>
9
- `).join("")}
10
- </div>
11
- </details>`}function Jn(r){let d=String(r.status??"unknown"),m=String(r.cliId??"unknown"),b=we.locale==="zh"?"\uFF1A":": ";return[n("sessions.restartConfirmIntro"),"",`${n("sessions.restartConfirmStatus")}${b}${Pe(d)}`,`${n("sessions.restartConfirmCli")}${b}${m}`,"",n("sessions.restartConfirmQuestion")].join(`
12
- `)}function rt(r){return r.status!=="closed"&&!r.adopt&&!r.pendingRepo}function Yn(){let r=Qe(typeof window>"u"?void 0:window.localStorage)?" checked":"";return`<section class="page">
13
- <div class="page-heading">
14
- <div>
15
- <p class="eyebrow">${n("nav.sessions")}</p>
16
- <h1>${n("sessions.title")}</h1>
17
- <p>${n("sessions.subtitle")}</p>
18
- </div>
19
- <div class="sessions-view-controls">
20
- <span id="kanban-team-stats" class="kanban-team-stats" hidden></span>
21
- <select id="kanban-team" class="kanban-team-select" aria-label="${n("sessions.kanban.groupTeam")}" hidden></select>
22
- <div class="segmented kanban-groupby" id="kanban-groupby" role="group" aria-label="${n("sessions.kanban.groupBy")}" hidden>
23
- <button type="button" data-groupby="flow">${n("sessions.kanban.groupFlow")}</button>
24
- <button type="button" data-groupby="team">${n("sessions.kanban.groupTeam")}</button>
25
- <button type="button" data-groupby="bot">${n("sessions.kanban.groupBot")}</button>
26
- </div>
27
- <div class="segmented sessions-view-toggle" role="group" aria-label="${n("sessions.viewMode")}">
28
- <button type="button" data-view="kanban">${n("sessions.viewKanban")}</button>
29
- <button type="button" data-view="board">${n("sessions.viewBoard")}</button>
30
- <button type="button" data-view="table">${n("sessions.viewTable")}</button>
31
- </div>
32
- <button type="button" id="monitor-room-open" class="monitor-room-open">${n("sessions.monitorRoom")}</button>
33
- </div>
34
- </div>
35
- <form id="filters" class="filters sessions-filters">
36
- <input type="search" name="q" placeholder="${n("sessions.search")}" />
37
- <select name="status">
38
- <option value="">${n("sessions.anyStatus")}</option>
39
- ${zn.map(d=>`<option value="${l(d)}">${l(Pe(d))}</option>`).join("")}
40
- </select>
41
- <select name="adopt">
42
- <option value="">${n("sessions.adoptAny")}</option>
43
- <option value="yes">${n("sessions.adoptYes")}</option>
44
- <option value="no">${n("sessions.adoptNo")}</option>
45
- </select>
46
- <select name="chat" aria-label="${n("sessions.location")}">
47
- <option value="">${n("sessions.chatAny")}</option>
48
- </select>
49
- ${Vn()}
50
- <label class="filter-toggle"><input type="checkbox" name="showUnknownChats"${r}> <span>${n("sessions.showUnknownChats")}</span></label>
51
- <label class="filter-toggle"><input type="checkbox" name="active" checked> <span>${n("sessions.activeOnly")}</span></label>
52
- </form>
53
- <div id="idle-cleanup-bar" class="idle-cleanup-bar">
54
- <div class="idle-cleanup-summary">
55
- <span class="idle-cleanup-dot" aria-hidden="true"></span>
56
- <span id="idle-cleanup-count" class="idle-cleanup-count"></span>
57
- </div>
58
- <div class="idle-cleanup-controls">
59
- <span class="idle-cleanup-label">${n("sessions.idleCleanupOlderThan")}</span>
60
- <div id="idle-cleanup-threshold" class="idle-cleanup-thresholds" role="group" aria-label="${n("sessions.idleCleanupThreshold")}">
61
- ${st.map(d=>`<button type="button" data-hours="${d}" aria-pressed="${d===24?"true":"false"}">${d===168?"7d":`${d}H`}</button>`).join("")}
62
- </div>
63
- <button type="button" id="idle-cleanup-run" class="contrast idle-cleanup-run">${n("sessions.idleCleanupRun")}</button>
64
- </div>
65
- <span id="idle-cleanup-status" class="idle-cleanup-status" aria-live="polite"></span>
66
- </div>
67
- <div id="bulk-bar" class="bulk-bar" hidden>
68
- <span id="bulk-count"></span>
69
- <button type="button" id="bulk-monitor-room">${n("sessions.addToMonitorRoom")}</button>
70
- <button type="button" id="bulk-lock">${n("sessions.lockSelected")}</button>
71
- <button type="button" id="bulk-unlock">${n("sessions.unlockSelected")}</button>
72
- <button type="button" id="bulk-close" class="contrast">${n("sessions.closeSelected")}</button>
73
- <button type="button" id="bulk-clear">${n("sessions.clearSelection")}</button>
74
- </div>
75
- <table id="sessions-table">
76
- <thead><tr>
77
- <th><input type="checkbox" id="select-all" title="${n("sessions.activeOnly")}"></th>
78
- ${W("botName",n("sessions.bot"))}
79
- ${W("cliId",n("sessions.cli"))}
80
- ${W("status",n("sessions.status"))}
81
- ${W("chat",n("sessions.location"))}
82
- ${W("tokenIn",n("sessions.tokenIn"))}
83
- ${W("tokenOut",n("sessions.tokenOut"))}
84
- ${W("title",n("sessions.titleCol"))}
85
- ${W("workingDir",n("sessions.workingDir"))}
86
- ${W("spawnedAt",n("sessions.created"))}
87
- ${W("lastMessageAt",n("sessions.last"))}
88
- ${W("adopt",n("sessions.adopt"))}
89
- <th>${n("sessions.actions")}</th>
90
- </tr></thead>
91
- <tbody></tbody>
92
- </table>
93
- <div id="sessions-board" class="sessions-board" hidden></div>
94
- <div id="sessions-kanban" class="sessions-kanban" hidden></div>
95
- <dialog id="drawer"></dialog>
96
- <dialog id="term-modal" class="term-modal"></dialog>
97
- <dialog id="history-modal" class="history-modal"></dialog>
98
- </section>`}async function Xn(){try{let r=await fetch("/api/groups");if(!r.ok)return[];let d=await r.json();return(Array.isArray(d?.bots)?d.bots:[]).filter(b=>b&&typeof b.larkAppId=="string").map(b=>({larkAppId:b.larkAppId,botName:typeof b.botName=="string"&&b.botName?b.botName:b.larkAppId}))}catch{return[]}}function Zn(r){let d=r.map(m=>`
99
- <label class="cs-bot"><input type="checkbox" name="bot" value="${l(m.larkAppId)}"> <span>${l(m.botName)}</span></label>`).join("");return`
100
- <article class="cs-card">
101
- <header><h3>${n("sessions.create.title")}</h3></header>
102
- <form id="cs-form">
103
- <label class="form-row">
104
- <span>${n("sessions.create.content")}</span>
105
- <textarea name="content" rows="5" placeholder="${l(n("sessions.create.contentPlaceholder"))}" required></textarea>
106
- </label>
107
- <fieldset class="cs-bots">
108
- <legend>${n("sessions.create.bots")}</legend>
109
- ${d||`<p class="cs-empty">${n("sessions.create.noBots")}</p>`}
110
- </fieldset>
111
- <fieldset class="cs-mode">
112
- <legend>${n("sessions.create.mode")}</legend>
113
- <label><input type="radio" name="mode" value="lead" checked> ${n("sessions.create.modeLead")}</label>
114
- <label><input type="radio" name="mode" value="all"> ${n("sessions.create.modeAll")}</label>
115
- <small>${n("sessions.create.modeHelp")}</small>
116
- </fieldset>
117
- <div class="cs-lead-row form-row" hidden>
118
- <span>${n("sessions.create.lead")}</span>
119
- <select name="lead"></select>
120
- <small>${n("sessions.create.leadHelp")}</small>
121
- </div>
122
- <fieldset class="cs-column">
123
- <legend>${n("sessions.create.column")}</legend>
124
- <label><input type="radio" name="column" value="in_progress" checked> ${n("sessions.create.columnInProgress")}</label>
125
- <label><input type="radio" name="column" value="backlog"> ${n("sessions.create.columnBacklog")}</label>
126
- <small>${n("sessions.create.columnHelp")}</small>
127
- </fieldset>
128
- <details class="cs-advanced">
129
- <summary>${n("sessions.create.advanced")}</summary>
130
- <label class="form-row">
131
- <span>${n("sessions.create.groupName")}</span>
132
- <input type="text" name="name" maxlength="60" placeholder="${l(n("sessions.create.groupNamePlaceholder"))}">
133
- </label>
134
- <label class="form-row">
135
- <span>${n("sessions.create.workingDir")}</span>
136
- <input type="text" name="bindWorkingDir" placeholder="e.g. ~/projects/foo">
137
- <small>${n("sessions.create.workingDirHelp")}</small>
138
- </label>
139
- </details>
140
- <div class="actions cs-actions">
141
- <button type="submit" class="primary">${n("sessions.create.submit")}</button>
142
- <button type="button" id="cs-cancel">${n("sessions.create.cancel")}</button>
143
- </div>
144
- </form>
145
- </article>`}async function ks(){let r=document.getElementById("create-session-modal");if(!r)return;let d=await Xn();if(d.length===0){alert(n("sessions.create.noBots"));return}r.innerHTML=Zn(d),r.showModal(),Qn(r,d)}function Qn(r,d){let m=r.querySelector("#cs-form"),b=r.querySelector(".cs-lead-row"),M=r.querySelector("select[name=lead]"),$=S=>d.find(H=>H.larkAppId===S)?.botName??S,P=()=>Array.from(m.querySelectorAll("input[name=bot]:checked")).map(S=>S.value),pe=()=>m.querySelector("input[name=mode]:checked")?.value??"all";function Le(){let S=P(),H=M.value;if(S.length===0){M.innerHTML=`<option value="" disabled selected>${l(n("sessions.create.leadPickFirst"))}</option>`,M.disabled=!0;return}M.disabled=!1,M.innerHTML=S.map(D=>`<option value="${l(D)}">${l($(D))}</option>`).join(""),S.includes(H)&&(M.value=H)}function Y(){pe()==="lead"?(b.hidden=!1,Le()):b.hidden=!0}m.querySelectorAll("input[name=mode]").forEach(S=>S.addEventListener("change",Y)),m.querySelectorAll("input[name=bot]").forEach(S=>S.addEventListener("change",()=>{pe()==="lead"&&Le()})),Y(),r.querySelector("#cs-cancel").onclick=()=>r.close(),m.onsubmit=async S=>{S.preventDefault();let H=new FormData(m),D=(H.get("content")??"").trim(),ee=P(),me=pe(),Ie=H.get("column")??"in_progress",fe=(H.get("name")??"").trim(),De=(H.get("bindWorkingDir")??"").trim(),V=H.get("lead")??"";if(!D){alert(n("sessions.create.errContent"));return}if(ee.length===0){alert(n("sessions.create.errNoBot"));return}if(me==="lead"&&(!V||!ee.includes(V))){alert(n("sessions.create.errLead"));return}let _=m.querySelector("button[type=submit]");_&&(_.disabled=!0,_.textContent=n("sessions.create.submitting"));try{let E=await fetch("/api/sessions/create",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({content:D,larkAppIds:ee,mode:me,column:Ie,leadLarkAppId:me==="lead"?V:void 0,name:fe||void 0,bindWorkingDir:De||void 0})}),C=await E.json().catch(()=>null);E.ok&&C?.ok?es(r,C):E.status!==401&&(alert(`${n("sessions.create.failed")}: ${C?.error??E.status}`),_&&(_.disabled=!1,_.textContent=n("sessions.create.submit")))}catch(E){alert(`${n("sessions.create.failed")}: ${E}`),_&&(_.disabled=!1,_.textContent=n("sessions.create.submit"))}}}function es(r,d){let m=typeof d.shareLink=="string"&&d.shareLink?d.shareLink:"",b=Array.isArray(d.failed)?d.failed.length:0,M=Array.isArray(d.spawned)?d.spawned.length:0,$=d.column==="backlog"?n("sessions.create.doneBacklog"):n("sessions.create.doneInProgress"),P=b>0?`<p class="cs-warn">${n("sessions.create.partialFail",{n:String(b)})}</p>`:"";r.innerHTML=`
146
- <article class="cs-card">
147
- <header><h3>${n("sessions.create.doneTitle")}</h3></header>
148
- <p>${l($)}\uFF08${M}\uFF09</p>
149
- ${P}
150
- ${m?`<p><a href="${l(m)}" target="_blank" rel="noopener">${n("sessions.create.openChat")}</a></p>`:""}
151
- <div class="actions"><button type="button" id="cs-done" class="primary">${n("sessions.create.close")}</button></div>
152
- </article>`,r.querySelector("#cs-done").onclick=()=>r.close()}function $s(r){return r.innerHTML=Yn(),ts(r)}function ts(r){let d=r.querySelector("#sessions-table tbody"),m=r.querySelector("#filters"),b=r.querySelector('select[name="chat"]'),M=r.querySelector('input[name="showUnknownChats"]'),$=r.querySelector("#drawer"),P=r.querySelector("#select-all"),pe=r.querySelector("#bulk-bar"),Le=r.querySelector("#bulk-count"),Y=r.querySelector("#bulk-monitor-room"),S=r.querySelector("#bulk-lock"),H=r.querySelector("#bulk-unlock"),D=r.querySelector("#bulk-close"),ee=r.querySelector("#bulk-clear"),me=r.querySelector("#idle-cleanup-bar"),Ie=r.querySelector("#idle-cleanup-threshold"),fe=r.querySelector("#idle-cleanup-run"),De=r.querySelector("#idle-cleanup-count"),V=r.querySelector("#idle-cleanup-status"),_=r.querySelector("#sessions-table"),E=r.querySelector("#sessions-board"),C=r.querySelector("#sessions-kanban"),x=r.querySelector("#term-modal"),B=r.querySelector("#history-modal"),_e=r.querySelector("#kanban-groupby"),j=r.querySelector("#kanban-team"),ct=r.querySelector("#kanban-team-stats"),dt=r.querySelectorAll(".sessions-view-toggle [data-view]"),dn=r.querySelector("#monitor-room-open"),w=new Set,be="lastMessageAt",ae="desc",A=Ot(window.localStorage),F=Pt(window.localStorage),X=null,qe="",Ue="",T="",ut="",pt=!1,te=null,Ke=!1,ge=null,ie=new Map,K=qt(window.localStorage),ne=null,Me=null,q=[],je=null,Ee=!1,Fe=!1,Z=(()=>{try{return window.localStorage.getItem(tt)??""}catch{return""}})(),He=!1,xe=24;M&&(M.checked=Qe(window.localStorage));function mt(){return xe}function un(e){return e===168?"7d":`${e}H`}function ft(e){let t=new Set;if(!e)return t;for(let o of e.groupChats)t.add(o);if(je)for(let[o,s]of je){if(t.has(o))continue;let a=!1;for(let i of e.botIds)if(s.botIds.has(i)){a=!0;break}if(a){for(let i of s.observedNames)if(e.botNames.has(i)){t.add(o);break}}}return t}function pn(){let e=he();if(A==="kanban"&&K==="team"){let t=q.find(s=>s.key===Z)??q[0],o=ft(t);return e.filter(s=>o.has(String(s.chatId)))}return e}function bt(){return Yt(pn(),mt())}function mn(){Ie.querySelectorAll("button[data-hours]").forEach(e=>{let t=ot(e.dataset.hours)===xe;e.classList.toggle("active",t),e.setAttribute("aria-pressed",t?"true":"false")})}async function fn(){if(!(Fe||Ee)){Fe=!0;try{let[e,t,o]=await Promise.all([fetch("/api/team/hosted").then(i=>i.json()).catch(()=>null),fetch("/api/team/remote-roster").then(i=>i.json()).catch(()=>null),fetch("/api/groups").then(i=>i.json()).catch(()=>null)]);Array.isArray(o?.chats)&&(je=new Map(o.chats.map(i=>[String(i.chatId),{botIds:new Set((i.memberBots??[]).filter(c=>c.inChat).map(c=>String(c.larkAppId))),observedNames:new Set((i.observedBotNames??[]).map(c=>String(c)))}])));let s=i=>({ids:new Set(i.map(c=>String(c.larkAppId))),names:new Set(i.map(c=>String(c.name??"")).filter(Boolean))}),a=[];for(let i of e?.teams??[]){let{ids:c,names:u}=s(i.bots??[]);a.push({key:`local:${i.teamId}`,label:i.isDefault?n("team.myHostedTeam"):String(i.name??i.teamId),botIds:c,botNames:u,groupChats:new Set((i.groupChatIds??[]).map(p=>String(p)))})}for(let i of t?.memberships??[]){let{ids:c,names:u}=s(i.roster?.bots??[]);a.push({key:`${i.hubUrl}::${i.teamId}`,label:String(i.teamName??i.teamId??i.hubUrl),botIds:c,botNames:u,groupChats:new Set})}q=a}finally{Ee=!0,Fe=!1}q.length&&!q.some(e=>e.key===Z)&&(Z=q[0].key),delete j.dataset.loading,j.disabled=q.length===0,j.innerHTML=q.length?q.map(e=>`<option value="${l(e.key)}"${e.key===Z?" selected":""}>${l(e.label)}</option>`).join(""):`<option value="">${l(n("sessions.kanban.noTeam"))}</option>`,T="",g()}}let R=null,re="",gt=0,ze=!1,We=new Map;async function bn(e){let t=re===e.key&&Date.now()-gt<3e4;if(!(ze||t)){ze=!0;try{let s=e.key.startsWith("local:")?`/api/team/board/local/${encodeURIComponent(e.key.slice(6))}`:`/api/team/remote-board?key=${encodeURIComponent(e.key)}`,a=await fetch(s),i=await a.json().catch(()=>({}));if(!a.ok||i?.ok===!1)return;let c=typeof i.deploymentId=="string"?i.deploymentId:null,u=[];We=new Map;for(let p of Array.isArray(i.reports)?i.reports:[])if(!(c&&p.deploymentId===c))for(let f of Array.isArray(p.sessions)?p.sessions:[]){let v={...f,remoteDeployment:p.deploymentName||p.deploymentId};u.push(v),We.set(String(f.sessionId),v)}R={board:i.board&&typeof i.board=="object"?i.board:{},remoteRows:u},re=e.key,gt=Date.now(),T="",g()}catch{}finally{ze=!1}}}async function gn(e,t,o,s,a){try{let c=e.startsWith("local:")?await fetch(`/api/team/board/local/${encodeURIComponent(e.slice(6))}/move`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({sessionId:t,column:o,position:s})}):await fetch("/api/team/remote-board-move",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({key:e,sessionId:t,column:o,position:s})}),u=await c.json().catch(()=>({}));(!c.ok||u?.ok===!1)&&(R&&(a?R.board[t]=a:delete R.board[t]),T="",g(),c.status!==401&&alert(`${n("sessions.kanban.moveFail")}: ${u?.error??c.status}`))}catch(i){R&&(a?R.board[t]=a:delete R.board[t]),T="",g(),alert(`${n("sessions.kanban.moveFail")}: ${i}`)}}function ht(e,t,o){let s=q.find(i=>i.key===Z)??q[0];if(!s)return;(!R||re!==s.key)&&(R={board:{},remoteRows:R?.remoteRows??[]},re=s.key);let a=R.board[e];R.board[e]={column:t,position:o},gn(s.key,e,t,o,a)}function hn(){return F.map(e=>en.find(t=>t.id===e)).filter(e=>!!e)}function yn(e,t){let o=F.indexOf(e),s=o+t;if(o<0||s<0||s>=F.length)return;let a=[...F];a.splice(o,1),a.splice(s,0,e),F=a,et(window.localStorage,F),g()}function kn(e,t){if(e===t)return;let o=F.indexOf(e),s=F.indexOf(t);if(o<0||s<0)return;let a=[...F];a.splice(o,1),a.splice(s,0,e),F=a,et(window.localStorage,F),g()}function $n(e){let t=e.status==="closed",o=w.has(e.sessionId)?"checked":"",s=ue(e);return`<tr data-id="${l(e.sessionId)}">
153
- <td><input type="checkbox" class="row-select" ${o} ${t?"disabled":""}></td>
154
- <td>${l(G(e))}</td>
155
- <td><span class="badge cli-${Oe(e.cliId)}">${l(e.cliId??"unknown")}</span></td>
156
- <td>${ve(e.status)}${Te(e)}</td>
157
- <td class="session-location-cell" title="${l(cn(e))}">${l(s)}</td>
158
- <td class="token-cell">${Qt(e.tokenUsage?.in)}</td>
159
- <td class="token-cell">${Qt(e.tokenUsage?.out)}</td>
160
- <td title="${l(String(e.title??""))}">${l(z(e.title??"").slice(0,48))}</td>
161
- <td title="${l(e.workingDir??"")}">${l((e.workingDir??"").slice(-34))}</td>
162
- <td>${ce(e.spawnedAt)}</td>
163
- <td>${ce(e.lastMessageAt)}</td>
164
- <td>${e.adopt?'<span class="badge">adopt</span>':""}</td>
165
- <td><button class="open" type="button">${n("sessions.details")}</button></td>
166
- </tr>`}function yt(e){if(e.scope!=="chat"||!e.feishuChatLink)return null;let t=n("sessions.openChat");return`<a class="card-act" href="${l(e.feishuChatLink)}" target="_blank" rel="noopener" title="${l(t)}" aria-label="${l(t)}">${L.feishu}</a>`}function kt(e){return e.agentAttention?.reason?e.agentAttention.reason:e.agentAttention?n("sessions.board.signalAgent"):e.pendingRepo?n("sessions.board.signalRepo"):e.tuiPromptActive?n("sessions.board.signalPrompt"):e.status==="limited"?n("sessions.board.signalLimited"):""}function wn(e){let t=w.has(e.sessionId),o=z(e.title)||e.sessionId,s=G(e),a=de(e),i=it(e),c=kt(e),u=nn(e.workingDir);return`<article class="session-card${t?" selected":""}${e.locked?" locked":""}" data-id="${l(e.sessionId)}" aria-pressed="${t}">
167
- <div class="session-card-top">
168
- ${se({name:s,larkAppId:e.larkAppId,size:"sm"})}
169
- <div class="session-card-title">
170
- <strong title="${l(String(e.title??o))}">${l(String(o).slice(0,72))}</strong>
171
- <span>${l(s)} \xB7 ${l(a??e.cliId??"unknown")}</span>
172
- </div>
173
- <span class="session-card-status-group">
174
- ${ve(e.status)}
175
- ${Te(e)}
176
- </span>
177
- </div>
178
- ${u!=="-"||e.adopt?`<div class="session-card-meta">
179
- ${u!=="-"?`<span title="${l(e.workingDir??"")}">${l(u)}</span>`:""}
180
- ${e.adopt?'<span class="badge">adopt</span>':""}
181
- </div>`:""}
182
- <div class="session-card-time">
183
- <span>${e.agentAttention?.at?`${l(n("sessions.board.waiting"))} ${ce(Ne(e))}`:`${l(n("sessions.last"))}: ${ce(e.lastMessageAt)}`}</span>
184
- </div>
185
- ${c?`<div class="session-signal" title="${l(c)}">${l(c)}</div>`:""}
186
- <div class="session-card-actions">
187
- ${yt(e)??Se("locate",L.pin,n("sessions.locate"))}
188
- ${Se("details",L.details,n("sessions.details"))}
189
- ${rt(e)?Se("restart",L.restart,n("sessions.restart")):""}
190
- ${an(i)}
191
- ${Se("lock",e.locked?L.unlock:L.lock,Ce(e),e.locked?"locked":"")}
192
- ${Se("close",L.close,n("sessions.close"),"danger")}
193
- </div>
194
- </article>`}function vn(e,t,o){let s=o==="needs-you"?Ne(e):Number(e.lastMessageAt??0),a=o==="needs-you"?Ne(t):Number(t.lastMessageAt??0);return s!==a?o==="needs-you"?s-a:a-s:String(e.title??e.sessionId).localeCompare(String(t.title??t.sessionId))}function Sn(e){let t=new Map(en.map(a=>[a.id,[]]));for(let a of e){let i=Gn(a);i&&t.get(i).push(a)}let o=hn(),s=o.map((a,i)=>{let c=(t.get(a.id)??[]).sort((u,p)=>vn(u,p,a.id));return`<section class="session-board-column session-board-${a.id}" data-col="${a.id}">
195
- <header draggable="true" title="${l(n("sessions.board.dragHint"))}">
196
- <div>
197
- <h2>${l(n(a.labelKey))}</h2>
198
- <p>${l(n(a.hintKey))}</p>
199
- </div>
200
- <span class="session-board-head-right">
201
- <span class="session-board-move">
202
- <button type="button" data-move-col="${a.id}" data-dir="-1"
203
- aria-label="${l(n("sessions.board.moveLeft"))}" ${i===0?"disabled":""}>\u2039</button>
204
- <button type="button" data-move-col="${a.id}" data-dir="1"
205
- aria-label="${l(n("sessions.board.moveRight"))}" ${i===o.length-1?"disabled":""}>\u203A</button>
206
- </span>
207
- <span class="session-board-count">${c.length}</span>
208
- </span>
209
- </header>
210
- <div class="session-board-list">
211
- ${c.length?c.map(wn).join(""):`<div class="session-board-empty">${n("sessions.board.emptyColumn")}</div>`}
212
- </div>
213
- </section>`}).join("");s!==qe&&(qe=s,E.innerHTML=s,E.classList.toggle("board-enter",!pt),pt=!0)}function $t(e){let t=z(e.title)||e.sessionId,o=G(e),s=de(e),a=nn(e.workingDir),i=kt(e),c=[s,a!=="-"?a:null].filter(Boolean).join(" \xB7 "),u=String(e.status??"unknown"),p=typeof e.remoteDeployment=="string"?e.remoteDeployment:"";return`<article class="kanban-card${p?" kanban-card-remote":""}${e.locked?" locked":""}" data-id="${l(e.sessionId)}" tabindex="0" role="button" draggable="true">
214
- <div class="kanban-card-top">
215
- <span class="badge cli-${Oe(e.cliId)}">${l(e.cliId??"unknown")}</span>
216
- ${e.adopt?'<span class="badge">adopt</span>':""}
217
- ${Te(e)}
218
- ${p?`<span class="badge kanban-remote-badge" title="${l(n("sessions.kanban.remoteHint",{name:p}))}">${l(p)}</span>`:""}
219
- <span class="kanban-card-top-right">
220
- <span class="kanban-card-dot" data-status="${l(Oe(u))}" title="${l(Pe(u))}"></span>
221
- ${p?"":`<button type="button" class="card-act kanban-card-act" data-action="history" title="${l(n("sessions.history.title"))}" aria-label="${l(n("sessions.history.title"))}">${L.history}</button>
222
- ${e.feishuChatLink?`<a class="card-act kanban-card-act" href="${l(e.feishuChatLink)}" target="_blank" rel="noopener" title="${l(n("sessions.kanban.openFeishu"))}" aria-label="${l(n("sessions.kanban.openFeishu"))}">${L.feishu}</a>`:""}
223
- <button type="button" class="card-act kanban-card-act${e.locked?" locked":""}" data-action="lock" title="${l(Ce(e))}" aria-label="${l(Ce(e))}">${e.locked?L.unlock:L.lock}</button>
224
- <button type="button" class="card-act kanban-card-act" data-action="details" title="${l(n("sessions.details"))}" aria-label="${l(n("sessions.details"))}">${L.details}</button>
225
- ${rt(e)?`<button type="button" class="card-act kanban-card-act" data-action="restart" title="${l(n("sessions.restart"))}" aria-label="${l(n("sessions.restart"))}">${L.restart}</button>`:""}`}
226
- </span>
227
- </div>
228
- <p class="kanban-card-title" title="${l(String(e.title??t))}">${l(String(t).slice(0,140))}</p>
229
- ${c?`<p class="kanban-card-desc" title="${l(c)}">${l(c)}</p>`:""}
230
- ${i?`<div class="session-signal" title="${l(i)}">${l(i)}</div>`:""}
231
- <div class="kanban-card-foot">
232
- <span class="kanban-card-owner">${se({name:o,larkAppId:e.larkAppId,size:"sm"})}<span>${l(o)}</span></span>
233
- <span class="kanban-card-updated">${l(n("sessions.kanban.updated",{time:ce(e.lastMessageAt)}))}</span>
234
- </div>
235
- </article>`}function wt(e){let t=[],o=new Map;for(let i of e){let c=String(i.chatId??i.sessionId),u=o.get(c);u||(u={chatId:c,rows:[]},o.set(c,u),t.push(u)),u.rows.push(i)}let s=[];return{html:t.map(i=>{if(s.push(...i.rows),i.rows.length<2)return $t(i.rows[0]);let c=de(i.rows[0])??i.chatId;return`<div class="kanban-cluster" data-chat="${l(i.chatId)}">
236
- <header draggable="true" title="${l(c)} \xB7 ${l(n("sessions.kanban.clusterDragHint"))}">
237
- ${Kt({chatId:i.chatId,name:c,size:"sm"})}
238
- <span class="kanban-cluster-name">${l(c)}</span>
239
- <span class="kanban-cluster-count">${i.rows.length}</span>
240
- </header>
241
- ${i.rows.map($t).join("")}
242
- </div>`}).join(""),flat:s}}function Cn(e){let t=new Map;for(let s of e){if(s.status==="closed")continue;let a=String(s.larkAppId||s.botName||"unknown"),i=t.get(a);i||(i={name:G(s),larkAppId:s.larkAppId,rows:[]},t.set(a,i)),i.rows.push(s)}let o=[...t.values()].sort((s,a)=>s.name.localeCompare(a.name));return o.length?o.map(s=>{let a=s.rows.sort((c,u)=>Number(u.lastMessageAt??0)-Number(c.lastMessageAt??0)),{html:i}=wt(a);return`<section class="kanban-column kanban-bot-col" data-bot="${l(s.larkAppId??s.name)}">
243
- <header>
244
- <span class="kanban-col-avatar">${se({name:s.name,larkAppId:s.larkAppId,size:"sm"})}</span>
245
- <h2>${l(s.name)}</h2>
246
- <span class="kanban-col-count">${a.length}</span>
247
- </header>
248
- <div class="kanban-col-list">${i}</div>
249
- </section>`}).join(""):`<div class="kanban-col-empty">${n("sessions.board.emptyColumn")}</div>`}function vt(e){let t=new Map(tn.map(s=>[s.id,[]]));for(let s of e)t.get(Jt(s)).push(s);let o=tn.map(s=>{let a=(t.get(s.id)??[]).sort((p,f)=>oe(p)-oe(f)),i=0;s.id==="done"&&a.length>at&&(i=a.length-at,a=a.slice(0,at));let{html:c,flat:u}=wt(a);return t.set(s.id,u),`<section class="kanban-column kanban-${s.id}" data-col="${s.id}">
250
- <header>
251
- <span class="kanban-col-icon">${Fn(s.id)}</span>
252
- <h2>${l(n(s.labelKey))}</h2>
253
- <span class="kanban-col-count">${a.length+i}</span>
254
- </header>
255
- <div class="kanban-col-list">
256
- ${a.length?c:`<div class="kanban-col-empty">${n("sessions.board.emptyColumn")}</div>`}
257
- ${i?`<div class="kanban-col-more">${l(n("sessions.kanban.moreHidden",{count:i}))}</div>`:""}
258
- </div>
259
- </section>`}).join("");return ie=t,o}function Tn(e){if(te||ne||Ke)return;C.classList.toggle("kanban-mode-bot",K==="bot");let t;if(K==="bot")t=Cn(e),ie=new Map;else if(K==="team")if(!Ee)t=`<div class="kanban-loading">${n("sessions.kanban.teamLoading")}</div>`,ie=new Map,j.dataset.loading||(j.dataset.loading="1",j.disabled=!0,j.innerHTML=`<option>${l(n("sessions.kanban.teamLoading"))}</option>`),fn();else{let s=q.find(f=>f.key===Z)??q[0],a=ft(s),i=s?e.filter(f=>a.has(String(f.chatId))):[];s&&bn(s);let c=(re===s?.key?R?.board:null)??{},u=(re===s?.key?R?.remoteRows:null)??[],p=[...i,...u].map(f=>{let v=c[f.sessionId];return v?{...f,kanbanColumn:v.column,kanbanPosition:v.position}:f});ct.textContent=n("sessions.kanban.teamScope",{chats:a.size,sessions:p.length}),t=vt(p)}else t=vt(e);if(t===T)return;T=t;let o=new Map;C.querySelectorAll(".kanban-col-list").forEach(s=>{let a=s.closest(".kanban-column")?.dataset.col;a&&s.scrollTop&&o.set(a,s.scrollTop)}),C.innerHTML=t,o.size&&C.querySelectorAll(".kanban-col-list").forEach(s=>{let a=s.closest(".kanban-column")?.dataset.col,i=a?o.get(a):void 0;i&&(s.scrollTop=i)})}async function St(e,t,o,s){try{let a=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/board`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({column:t,position:o})}),i=await a.json().catch(()=>({}));(!a.ok||i?.ok===!1)&&(e.kanbanColumn=s.column,e.kanbanPosition=s.position,T="",g(),a.status!==401&&alert(`${n("sessions.kanban.moveFail")}: ${i?.error??a.status}`))}catch(a){e.kanbanColumn=s.column,e.kanbanPosition=s.position,T="",g(),alert(`${n("sessions.kanban.moveFail")}: ${a}`)}}async function Ct(e,t){let o=e.title;e.title=t,T="",g();try{let s=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/rename`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({title:t})}),a=await s.json().catch(()=>({}));(!s.ok||a?.ok===!1)&&(e.title=o,T="",g(),s.status!==401&&alert(`${n("sessions.kanban.renameFail")}: ${a?.error??s.status}`))}catch(s){e.title=o,T="",g(),alert(`${n("sessions.kanban.renameFail")}: ${s}`)}}function Ln(e){if(e==null||e==="")return"";let t=Number(e),o=Number.isFinite(t)&&t>0?new Date(t):new Date(String(e));return Number.isNaN(o.getTime())?"":o.toLocaleString()}function In(e,t,o){let s=t.senderType==="user",a=s?t.senderName||(o&&t.senderId===o?n("sessions.history.owner"):n("sessions.history.user")):G(e),i=Ln(t.createTime),c=String(t.content??"").trim()||`[${t.msgType??"message"}]`,u=s?t.senderAvatar?`<img class="history-avatar-img" src="${l(String(t.senderAvatar))}" alt="" decoding="async" referrerpolicy="no-referrer">`:`<span class="history-avatar-user" aria-hidden="true">${l(String(a).slice(0,1))}</span>`:se({name:G(e),larkAppId:e.larkAppId,size:"sm"});return`<div class="history-msg${s?" mine":""}">
260
- ${u}
261
- <div class="history-msg-main">
262
- <div class="history-msg-meta"><span>${l(a)}</span><time>${l(i)}</time></div>
263
- <div class="history-bubble">${l(c)}</div>
264
- </div>
265
- </div>`}async function Tt(e){let t=G(e);B.innerHTML=`<div class="term-modal-head">
266
- <span class="term-modal-title">
267
- ${se({name:t,larkAppId:e.larkAppId,size:"sm"})}
268
- <strong title="${l(String(e.title??""))}">${l((z(e.title)||e.sessionId).slice(0,60))}</strong>
269
- <span class="history-scope-tag">${l(n("sessions.history.title"))}</span>
270
- </span>
271
- <span class="term-modal-actions">
272
- <button type="button" id="history-close" class="card-act" title="${l(n("sessions.dismiss"))}" aria-label="${l(n("sessions.dismiss"))}">${L.close}</button>
273
- </span>
274
- </div>
275
- <div class="history-body"><div class="term-modal-loading">${n("sessions.history.loading")}</div></div>`,B.showModal(),B.querySelector("#history-close").onclick=()=>B.close();try{let o=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/history?limit=80`),s=await o.json().catch(()=>({}));if(!B.open)return;let a=B.querySelector(".history-body");if(!o.ok||s?.ok===!1){let c=String(s?.error??o.status),u=c==="not_found_yet"||c==="not_found";a.innerHTML=`<div class="history-error">${l(n("sessions.history.fail"))}: ${l(c)}${u?`<br><span>${l(n("sessions.history.staleHint"))}</span>`:""}</div>`;return}let i=Array.isArray(s.messages)?s.messages:[];if(!i.length){a.innerHTML=`<div class="history-error">${n("sessions.history.empty")}</div>`;return}a.innerHTML=`<div class="history-list">${i.map(c=>In(e,c,s.ownerOpenId)).join("")}</div>`,a.scrollTop=a.scrollHeight}catch(o){if(!B.open)return;let s=B.querySelector(".history-body");s&&(s.innerHTML=`<div class="history-error">${l(n("sessions.history.fail"))}: ${l(String(o))}</div>`)}}function Lt(e,t){let o=e.querySelector(".kanban-card-title");if(!o||e.querySelector(".kanban-rename-input"))return;Ke=!0;let s=document.createElement("input");s.type="text",s.className="kanban-rename-input",s.maxLength=200,s.value=z(t.title)||"",o.replaceWith(s),s.focus(),s.select();let a=!1,i=c=>{if(a)return;a=!0,Ke=!1;let u=s.value.trim();c&&u&&u!==(z(t.title)||"")?Ct(t,u):(T="",g())};s.addEventListener("keydown",c=>{c.stopPropagation(),c.key==="Enter"?(c.preventDefault(),i(!0)):c.key==="Escape"&&(c.preventDefault(),i(!1))}),s.addEventListener("blur",()=>i(!0)),s.addEventListener("click",c=>c.stopPropagation())}function It(e,t){for(let o of e.querySelectorAll(".kanban-card:not(.dragging)")){if(o.closest(".kanban-cluster.dragging"))continue;let s=o.getBoundingClientRect();if(t<s.top+s.height/2)return o}return null}function Mt(){C.querySelectorAll(".drag-over, .dragging, .drop-before").forEach(e=>e.classList.remove("drag-over","dragging","drop-before"))}function Mn(e){let t=x.querySelector(".term-modal-name");if(!t||x.querySelector(".term-modal-name-input"))return;let o=document.createElement("input");o.type="text",o.className="term-modal-name-input",o.maxLength=200,o.value=z(e.title)||"",t.replaceWith(o);let s=()=>{let c=getComputedStyle(o),u=document.createElement("span");u.style.cssText="position:absolute;visibility:hidden;white-space:pre",u.style.fontSize=c.fontSize,u.style.fontFamily=c.fontFamily,u.style.fontWeight=c.fontWeight,u.style.letterSpacing=c.letterSpacing,u.textContent=o.value||" ",document.body.appendChild(u);let p=u.offsetWidth;u.remove();let f=Math.round(window.innerWidth*.6);o.style.width=`${Math.min(Math.max(p+22,80),f)}px`};s(),o.addEventListener("input",s),o.focus(),o.select();let a=!1,i=c=>{if(a)return;a=!0;let u=o.value.trim(),p=z(e.title)||"";if(c&&u&&u!==p){e.title=u;let f=document.createElement("strong");f.className="term-modal-name",f.title=u,f.textContent=u.slice(0,60),o.replaceWith(f),Ct(e,u)}else{let f=document.createElement("strong");f.className="term-modal-name",f.title=String(e.title??p),f.textContent=p.slice(0,60),o.replaceWith(f)}};o.addEventListener("keydown",c=>{c.stopPropagation(),c.key==="Enter"?(c.preventDefault(),i(!0)):c.key==="Escape"&&(c.preventDefault(),i(!1))}),o.addEventListener("blur",()=>i(!0))}async function Et(e){let t=it(e);if(!t){Ae(e);return}let o=z(e.title)||e.sessionId,s=e.feishuChatLink?`<a class="card-act" href="${l(e.feishuChatLink)}" target="_blank" rel="noopener" title="${l(n("sessions.kanban.openFeishu"))}" aria-label="${l(n("sessions.kanban.openFeishu"))}">${L.feishu}</a>`:"";x.innerHTML=`<div class="term-modal-head">
276
- <span class="term-modal-title">
277
- ${se({name:G(e),larkAppId:e.larkAppId,size:"sm"})}
278
- <strong class="term-modal-name" title="${l(String(e.title??o))}">${l(String(o).slice(0,60))}</strong>
279
- <button type="button" id="term-modal-edit" class="card-act" title="${l(n("sessions.kanban.rename"))}" aria-label="${l(n("sessions.kanban.rename"))}">${L.edit}</button>
280
- ${ve(e.status)}
281
- </span>
282
- <span class="term-modal-actions">
283
- ${s}
284
- <a id="term-modal-tab" class="card-act" href="${l(t)}" target="_blank" rel="noopener" title="${l(n("sessions.kanban.openTab"))}" aria-label="${l(n("sessions.kanban.openTab"))}">${L.terminal}</a>
285
- <button type="button" id="term-modal-close" class="card-act" title="${l(n("sessions.dismiss"))}" aria-label="${l(n("sessions.dismiss"))}">${L.close}</button>
286
- </span>
287
- </div>
288
- <div class="term-modal-body"><div class="term-modal-loading">${n("sessions.kanban.terminalLoading")}</div></div>`,x.showModal(),x.querySelector("#term-modal-close").onclick=()=>x.close(),x.querySelector("#term-modal-edit").onclick=()=>Mn(e);let a=t;if(we.authed)try{let u=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/write-link`),p=await u.json().catch(()=>({}));u.ok&&p?.ok!==!1&&p?.url&&(a=p.url)}catch{}if(!x.open)return;let i=x.querySelector(".term-modal-body");i.innerHTML=`<iframe class="term-modal-frame" src="${l(a)}" allow="clipboard-read; clipboard-write"></iframe>`;let c=x.querySelector("#term-modal-tab");c&&(c.href=a)}function he(){let e=new FormData(m),t=(e.get("q")??"").toLowerCase(),o=e.getAll("cli"),s=o.length>0&&o.length<ln.length,a=e.get("status"),i=e.get("adopt"),c=e.get("chat"),u=!!e.get("active"),p=!!e.get("showUnknownChats"),f=A==="kanban",v=[...O.sessions.values()].filter(k=>!s||o.includes(k.cliId??"unknown")).filter(k=>p||!on(k)).filter(k=>!a||k.status===a).filter(k=>!i||i==="yes"==!!k.adopt).filter(k=>!c||String(k.chatId??"")===c).filter(k=>!u||f||k.status!=="closed").filter(k=>!t||Wn(k).includes(t));return v.sort(En),v}function Ht(e,t){return t==="spawnedAt"||t==="lastMessageAt"?Number(e[t]??0):t==="tokenIn"?lt(e.tokenUsage?.in)??-1:t==="tokenOut"?lt(e.tokenUsage?.out)??-1:t==="adopt"?!!e.adopt:t==="chat"?ue(e).toLowerCase():String(e[t]??"").toLowerCase()}function En(e,t){let o=Ht(e,be),s=Ht(t,be),a=0;return typeof o=="number"&&typeof s=="number"?a=o-s:typeof o=="boolean"&&typeof s=="boolean"?a=Number(o)-Number(s):a=String(o).localeCompare(String(s)),a===0&&(a=Number(e.lastMessageAt??0)-Number(t.lastMessageAt??0)),ae==="asc"?a:-a}function Hn(){_.querySelectorAll("th[data-sort]").forEach(e=>{let t=e.dataset.sort===be;e.classList.toggle("sorted",t),e.setAttribute("aria-sort",t?ae==="asc"?"ascending":"descending":"none");let o=e.dataset.label??e.textContent?.trim()??"";e.textContent=t?`${o} ${ae==="asc"?"\u25B2":"\u25BC"}`:o})}function Ge(e){pe.hidden=w.size===0,Le.textContent=n("sessions.selectedCount",{count:w.size});let t=[...w].map(a=>O.sessions.get(a)).filter(a=>!!a&&a.status!=="closed");Y.disabled=t.length===0,S.disabled=!t.some(a=>!a.locked),H.disabled=!t.some(a=>!!a.locked);let o=e.filter(a=>a.status!=="closed");if(o.length===0){P.checked=!1,P.indeterminate=!1,P.disabled=!0;return}P.disabled=!1;let s=o.filter(a=>w.has(a.sessionId)).length;P.checked=s===o.length,P.indeterminate=s>0&&s<o.length}function Ve(){let e=bt().length;De.textContent=n("sessions.idleCleanupCount",{count:e}),fe.disabled=He||e===0,me.classList.toggle("is-empty",e===0),mn()}function xn(){dt.forEach(e=>{let t=e.dataset.view===A;e.classList.toggle("active",t),e.setAttribute("aria-pressed",String(t))}),_e.hidden=A!=="kanban",j.hidden=!(A==="kanban"&&K==="team"),ct.hidden=j.hidden||!Ee,_e.querySelectorAll("[data-groupby]").forEach(e=>{let t=e.dataset.groupby===K;e.classList.toggle("active",t),e.setAttribute("aria-pressed",String(t))})}function An(){let e=m.querySelector("#cli-filter-count");if(!e)return;let t=[...m.querySelectorAll('input[name="cli"]')],o=t.filter(s=>s.checked).length;e.textContent=o===t.length?n("common.all"):`${o}/${t.length}`,e.classList.toggle("cli-filter-active",o!==t.length)}function Bn(){let e=b.value,t=!!m.querySelector('input[name="showUnknownChats"]')?.checked,o=new Map;for(let i of O.sessions.values()){let c=String(i.chatId??"").trim();if(!c||!t&&on(i))continue;let u=ue(i),p=o.get(c);(!p||u<p)&&o.set(c,u)}let s=[...o.entries()].sort((i,c)=>i[1].localeCompare(c[1])),a=`<option value="">${l(n("sessions.chatAny"))}</option>${s.map(([i,c])=>`<option value="${l(i)}">${l(c)}</option>`).join("")}`;a!==ut&&(b.innerHTML=a,ut=a),b.value=e&&o.has(e)?e:""}function g(){Bn();let e=he();for(let s of[...w]){let a=O.sessions.get(s);(!a||a.status==="closed")&&w.delete(s)}let t=e.filter(s=>s.status!=="closed"),o=A==="table"?e:t;if(_.hidden=A!=="table",E.hidden=A!=="board",C.hidden=A!=="kanban",A==="table"){let s=e.length?e.map($n).join(""):`<tr><td colspan="13" class="empty">${n("sessions.empty")}</td></tr>`;s!==Ue&&(Ue=s,d.innerHTML=s)}else A==="kanban"?Tn(e):Sn(t);xn(),Hn(),An(),Ge(o),Ve()}async function xt(e,t){t&&(t.disabled=!0,t.textContent=n("sessions.locating"));try{let o=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/locate`,{method:"POST"}),s=await o.json();if(s.ok){if(!t)return;let a=30;t.textContent=n("sessions.cooldown",{seconds:a});let i=setInterval(()=>{a-=1,a<=0?(clearInterval(i),t.disabled=!1,t.textContent=n("sessions.locate")):t.textContent=n("sessions.cooldown",{seconds:a})},1e3)}else alert(`Locate failed: ${s.error??o.status}`),t&&(t.disabled=!1,t.textContent=n("sessions.locate"))}catch(o){alert(`Locate error: ${o}`),t&&(t.disabled=!1,t.textContent=n("sessions.locate"))}}async function At(e,t){if(!confirm(n("sessions.closeConfirm")))return!1;t&&(t.disabled=!0);try{let o=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/close`,{method:"POST"}),s=await o.json().catch(()=>({}));return!o.ok||s?.ok===!1?(o.status!==401&&alert(`Close failed: ${s?.error??o.status}`),!1):!0}catch(o){return alert(`Close error: ${o}`),!1}finally{t&&(t.disabled=!1)}}function ye(){qe="",Ue="",T=""}async function Je(e,t,o){let s=!!e.locked;if(s===t)return!0;e.locked=t,ye(),g(),o&&(o.disabled=!0);try{let a=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/lock`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({locked:t})}),i=await a.json().catch(()=>({}));return!a.ok||i?.ok===!1?(e.locked=s,ye(),g(),a.status!==401&&alert(`${n("sessions.lockFailed")}: ${i?.error??a.status}`),!1):(e.locked=!!i.locked,ye(),g(),!0)}catch(a){return e.locked=s,ye(),g(),alert(`${n("sessions.lockFailed")}: ${a}`),!1}finally{o&&(o.disabled=!1)}}let Ye=new Set;async function Xe(e,t){if(Ye.has(e.sessionId)||!confirm(Jn(e)))return!1;t&&(t.disabled=!0);try{let o=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/restart`,{method:"POST"}),s=await o.json().catch(()=>({}));return!o.ok||s?.ok===!1?(o.status!==401&&alert(`${n("sessions.restartFailed")}: ${s?.error??o.status}`),!1):(Ye.add(e.sessionId),setTimeout(()=>Ye.delete(e.sessionId),5e3),!0)}catch(o){return alert(`${n("sessions.restartFailed")}: ${o}`),!1}finally{t&&(t.disabled=!1)}}function Rn(e){return e===void 0?"\u2014":e<1e3?`${e}ms`:e<6e4?`${(e/1e3).toFixed(1)}s`:`${Math.floor(e/6e4)}m${Math.round(e%6e4/1e3)}s`}function Nn(e){if(!e||e.status!=="ok"){let i=e?.error?.message?l(String(e.error.message)):l(String(e?.status??"error"));return`<p>${n("sessions.insightUnavailable")}: ${i}</p>`}let t=e.agg??{};if(!t.totalSpans)return`<p>${n("sessions.insightEmpty")}</p>`;let o="color:var(--muted,#8f959e)",s=[],a=[];if(e.meta?.asOf&&a.push(l(n("sessions.insightAsOf",{asOf:String(e.meta.asOf)}))),e.meta?.partial&&a.push(l(n("sessions.insightPartial"))),a.length&&s.push(`<p style="font-size:12px;${o}">${a.join(" \xB7 ")}</p>`),s.push(`<p>${l(n("sessions.insightMetrics",{total:String(t.totalSpans??0),failed:String(t.failedSpans??0),slow:String(t.slowSpans??0),rw:t.readWriteRatio===null||t.readWriteRatio===void 0?"\u2014":String(t.readWriteRatio),compactions:String(t.compactions??0)}))}</p>`),Array.isArray(e.suggestions)&&e.suggestions.length){let i=u=>u==="bad"?"\u{1F534}":u==="warn"?"\u{1F7E1}":"\u2139\uFE0F",c=e.suggestions.map(u=>`<li>${i(u.severity)} <b>${l(String(u.title??""))}</b> \u2014 ${l(String(u.action??""))}`+(Array.isArray(u.evidence)&&u.evidence.length?`<br><small style="${o}">${l(u.evidence.join("\uFF1B"))}</small>`:"")+"</li>").join("");s.push(`<details open><summary>${n("sessions.insightSuggestions")}</summary><ul style="padding-left:18px;margin:6px 0">${c}</ul></details>`)}if(Array.isArray(e.spans)&&e.spans.length){let i=p=>p==="error"?"\u{1F534}":p==="running"?"\u23F3":"\u2705",c=[...e.spans].sort((p,f)=>(p.relStartMs??0)-(f.relStartMs??0)).map(p=>{let f=[p.inputSummary,p.outputSummary].filter(Boolean).map(k=>l(String(k))).join(" \u2192 ");return`<tr${p.status==="error"?' style="color:var(--danger,#d33)"':""}><td>${i(p.status)}</td><td><code>${l(String(p.tool??""))}</code></td><td>${l(String(p.phase??""))}</td><td>${Rn(p.durationMs)}</td><td>#${l(String(p.turnIndex??0))}</td><td>${f}</td></tr>`}).join(""),u=e.meta?.capped?`<p style="font-size:12px;${o}">${l(n("sessions.insightCapped",{shown:String(e.meta.spansReturned??e.spans.length),total:String(e.meta.spansTotal??e.spans.length)}))}</p>`:"";s.push(`<details><summary>${n("sessions.insightSpans")} (${e.spans.length})</summary>${u}<div style="max-height:320px;overflow:auto"><table style="width:100%;font-size:12px"><tbody>${c}</tbody></table></div></details>`)}return s.join("")}function Ae(e){let t=e.status==="closed",o=it(e);$.innerHTML=`<article>
289
- <header>
290
- <h3>${l(z(e.title)||e.sessionId)}</h3>
291
- <span class="drawer-status-line">
292
- ${ve(e.status)}
293
- ${Te(e)}
294
- </span>
295
- <p><code>${l(e.sessionId)}</code> <button data-copy="${l(e.sessionId)}">${n("sessions.copy")}</button></p>
296
- </header>
297
- <p><b>${n("sessions.bot")}:</b> ${l(G(e))} \xB7 <b>${n("sessions.cli")}:</b> ${l(e.cliId??"?")}</p>
298
- <p><b>${n("sessions.location")}:</b> ${l(ue(e))}</p>
299
- <p><b>chatId:</b> <code>${l(e.chatId??"")}</code> <button data-copy="${l(e.chatId??"")}">${n("sessions.copy")}</button></p>
300
- <p><b>rootMessageId:</b> <code>${l(e.rootMessageId??"")}</code> <button data-copy="${l(e.rootMessageId??"")}">${n("sessions.copy")}</button></p>
301
- ${e.threadId?`<p><b>threadId:</b> <code>${l(e.threadId)}</code></p>`:""}
302
- <p><b>${n("sessions.workingDir")}:</b> ${l(e.workingDir??"-")}</p>
303
- <div class="actions">
304
- ${yt(e)??`<button id="locate-btn" type="button">${n("sessions.locate")}</button>`}
305
- <button id="history-drawer-btn" type="button">${n("sessions.history.title")}</button>
306
- ${an(o)}
307
- ${rt(e)?`<button id="restart-btn" type="button">${n("sessions.restart")}</button>`:""}
308
- ${t?"":`<button id="lock-btn" type="button">${l(Ce(e))}</button>`}
309
- ${e.queued&&!t?`<button id="start-btn" type="button" class="primary">${n("sessions.create.start")}</button>`:""}
310
- ${t?`<button id="resume-btn" type="button" class="primary">${n("sessions.resume")}</button>`:""}
311
- ${t?"":`<button id="close-btn" type="button" class="contrast">${n("sessions.close")}</button>`}
312
- <button id="land-btn" type="button">${n("sessions.land")}</button>
313
- ${we.authed?`<button id="insight-btn" type="button">${n("sessions.insight")}</button>`:""}
314
- </div>
315
- <div id="land-area"></div>
316
- <div id="insight-area"></div>
317
- <form method="dialog"><button>${n("sessions.dismiss")}</button></form>
318
- </article>`,$.querySelectorAll("[data-copy]").forEach(h=>{h.onclick=()=>{navigator.clipboard.writeText(h.dataset.copy??""),h.textContent=n("sessions.copied"),setTimeout(()=>{h.textContent=n("sessions.copy")},800)}});let s=$.querySelector("#locate-btn");s&&(s.onclick=()=>{xt(e,s)});let a=$.querySelector("#history-drawer-btn");a&&(a.onclick=()=>{Tt(e)});let i=$.querySelector(".term-write");i&&(i.onclick=()=>{rn(e,i)});let c=$.querySelector("#resume-btn");c&&(c.onclick=async()=>{c.disabled=!0;try{let h=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/resume`,{method:"POST"}),y=await h.json().catch(()=>({}));if(!h.ok||y.ok===!1){alert(`${n("sessions.resumeFailed")}: ${y?.error??h.status}`),c.disabled=!1;return}$.close()}catch(h){alert(`${n("sessions.resumeFailed")}: ${h}`),c.disabled=!1}});let u=$.querySelector("#restart-btn");u&&(u.onclick=async()=>{await Xe(e,u)&&$.close()});let p=$.querySelector("#close-btn");p&&(p.onclick=async()=>{await At(e,p)&&$.close()});let f=$.querySelector("#lock-btn");f&&(f.onclick=async()=>{let h=!e.locked;if(await Je(e,h,f)){f.textContent=Ce(e);let y=$.querySelector(".drawer-status-line");y&&(y.innerHTML=`${ve(e.status)}${Te(e)}`)}});let v=$.querySelector("#start-btn");v&&(v.onclick=async()=>{v.disabled=!0;try{let h=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/start`,{method:"POST"}),y=await h.json().catch(()=>({}));if(!h.ok||y.ok===!1){h.status!==401&&alert(`${n("sessions.create.startFailed")}: ${y?.error??h.status}`),v.disabled=!1;return}$.close()}catch(h){alert(`${n("sessions.create.startFailed")}: ${h}`),v.disabled=!1}});let k=$.querySelector("#land-btn"),N=$.querySelector("#land-area");k&&N&&(k.onclick=async()=>{k.disabled=!0,N.innerHTML=`<p>${n("sessions.landLoading")}</p>`;try{let h=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/sandbox-diff`),y=await h.json().catch(()=>({}));if(!y.ok){N.innerHTML=`<p>${n("sessions.landUnavailable")}: ${l(y.error??String(h.status))}</p>`,k.disabled=!1;return}if(y.empty){N.innerHTML=`<p>${n("sessions.landEmpty")}</p>`,k.disabled=!1;return}let J=String(y.patch??""),Be=J.slice(0,2e4)+(J.length>2e4?`
319
- \u2026(truncated)`:"");N.innerHTML=`
320
- <p><b>${y.files}</b> files (+${y.insertions}/-${y.deletions}) \u2192 <code>${l(String(y.workingDir??""))}</code></p>
321
- <pre style="max-height:320px;overflow:auto;white-space:pre-wrap">${l(Be)}</pre>
322
- <div class="actions">
323
- <button id="land-apply" type="button" class="primary">${n("sessions.landApply")}</button>
324
- <button id="land-discard" type="button" class="contrast">${n("sessions.landDiscard")}</button>
325
- </div>`;let $e=N.querySelector("#land-apply"),Re=N.querySelector("#land-discard");$e.onclick=async()=>{$e.disabled=!0,Re.disabled=!0;let I=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/sandbox-land/apply`,{method:"POST"}),Q=await I.json().catch(()=>({}));N.innerHTML=Q.ok?`<p>\u2705 ${n("sessions.landApplied")}: ${Q.files} files (+${Q.insertions}/-${Q.deletions}) \u2192 <code>${l(String(Q.workingDir??""))}</code></p>`:`<p>\u274C ${n("sessions.landFailed")}: ${l(Q.error??String(I.status))}</p>`},Re.onclick=async()=>{await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/sandbox-land/discard`,{method:"POST"}),N.innerHTML=`<p>\u{1F5D1} ${n("sessions.landDiscarded")}</p>`}}catch(h){N.innerHTML=`<p>${n("sessions.landUnavailable")}: ${l(String(h))}</p>`,k.disabled=!1}});let le=$.querySelector("#insight-btn"),U=$.querySelector("#insight-area");le&&U&&(le.onclick=async()=>{le.disabled=!0,U.innerHTML=`<p>${n("sessions.insightLoading")}</p>`;try{let h=await fetch(`/api/sessions/${encodeURIComponent(e.sessionId)}/insight?detail=spans`),y=await h.json().catch(()=>({}));!y.ok||!y.report?U.innerHTML=`<p>${n("sessions.insightUnavailable")}: ${l(String(y.error??h.status))}</p>`:U.innerHTML=Nn(y.report)}catch(h){U.innerHTML=`<p>${n("sessions.insightUnavailable")}: ${l(String(h))}</p>`}le.disabled=!1}),$.showModal()}d.addEventListener("click",e=>{let t=e.target;if(t.classList.contains("row-select")){let i=t.closest("tr[data-id]");if(!i)return;t.checked?w.add(i.dataset.id):w.delete(i.dataset.id),Ge(he());return}let o=t.closest("td");if(o&&o.querySelector(".row-select"))return;let s=t.closest("tr[data-id]");if(!s)return;let a=O.sessions.get(s.dataset.id);a&&Ae(a)}),E.addEventListener("click",e=>{let t=e.target,o=t.closest("button[data-move-col]");if(o){yn(o.dataset.moveCol,Number(o.dataset.dir));return}let s=t.closest(".session-card[data-id]");if(!s)return;let a=O.sessions.get(s.dataset.id);if(!a)return;let i=t.closest("button[data-action]");if(i){let c=i.dataset.action;c==="details"?Ae(a):c==="write-link"?rn(a,i):c==="locate"?xt(a,i):c==="restart"?Xe(a,i):c==="lock"?Je(a,!a.locked,i):c==="close"&&At(a,i).then(u=>{u&&(w.delete(a.sessionId),g())});return}t.closest("a, button, input, label")||(w.has(a.sessionId)?w.delete(a.sessionId):w.add(a.sessionId),s.classList.toggle("selected",w.has(a.sessionId)),s.setAttribute("aria-pressed",String(w.has(a.sessionId))),Ge(he().filter(c=>c.status!=="closed")))}),E.addEventListener("dragstart",e=>{let o=e.target.closest(".session-board-column > header[draggable]")?.closest(".session-board-column");o?.dataset.col&&(X=o.dataset.col,o.classList.add("dragging"),e.dataTransfer&&(e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",X)))}),E.addEventListener("dragover",e=>{if(!X)return;e.preventDefault(),e.dataTransfer&&(e.dataTransfer.dropEffect="move");let t=e.target.closest(".session-board-column");E.querySelectorAll(".drag-over").forEach(o=>o.classList.remove("drag-over")),t&&t.dataset.col!==X&&t.classList.add("drag-over")}),E.addEventListener("drop",e=>{if(!X)return;e.preventDefault();let t=e.target.closest(".session-board-column"),o=X;X=null,t?.dataset.col&&kn(o,t.dataset.col)}),E.addEventListener("dragend",()=>{X=null,E.querySelectorAll(".drag-over, .dragging").forEach(e=>e.classList.remove("drag-over","dragging"))}),dt.forEach(e=>{e.addEventListener("click",()=>{let t=Nt(e.dataset.view)??"board";t!==A&&(A=t,Dt(window.localStorage,A),g())})}),dn.addEventListener("click",()=>{window.location.href=zt()}),_e.querySelectorAll("[data-groupby]").forEach(e=>{e.addEventListener("click",()=>{let t=e.dataset.groupby,o=t==="bot"?"bot":t==="team"?"team":"flow";o!==K&&(K=o,Ut(window.localStorage,o),T="",g())})}),j.addEventListener("change",()=>{Z=j.value;try{window.localStorage.setItem(tt,Z)}catch{}T="",g()});function ke(){ge!==null&&(clearTimeout(ge),ge=null)}C.addEventListener("click",e=>{let t=e.target,o=t.closest(".kanban-card[data-id]");if(!o)return;let s=O.sessions.get(o.dataset.id);if(!s)return;let a=t.closest("button[data-action]");if(a){a.dataset.action==="details"?Ae(s):a.dataset.action==="rename"?Lt(o,s):a.dataset.action==="history"?Tt(s):a.dataset.action==="restart"?Xe(s,a):a.dataset.action==="lock"&&Je(s,!s.locked,a);return}t.closest("a, button, input, label")||(ke(),ge=setTimeout(()=>{ge=null,Et(s)},220))}),C.addEventListener("dblclick",e=>{let t=e.target,o=t.closest(".kanban-card-title"),s=t.closest(".kanban-card[data-id]");if(!o||!s)return;ke();let a=O.sessions.get(s.dataset.id);a&&Lt(s,a)}),C.addEventListener("keydown",e=>{if(e.key!=="Enter"&&e.key!==" ")return;let t=e.target;if(!t.classList?.contains("kanban-card"))return;e.preventDefault();let o=O.sessions.get(t.dataset.id);o&&Et(o)}),C.addEventListener("dragstart",e=>{if(K==="bot")return;let t=e.target,o=t.closest(".kanban-cluster > header[draggable]");if(o){let a=o.closest(".kanban-cluster"),i=a.closest(".kanban-column")?.dataset.col;if(!a.dataset.chat||!i)return;ke(),ne=a.dataset.chat,Me=i,a.classList.add("dragging"),e.dataTransfer&&(e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",`cluster:${ne}`));return}let s=t.closest(".kanban-card[data-id]");s&&(ke(),te=s.dataset.id,s.classList.add("dragging"),e.dataTransfer&&(e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",te)))}),C.addEventListener("dragover",e=>{if(!te&&!ne)return;e.preventDefault(),e.dataTransfer&&(e.dataTransfer.dropEffect="move");let t=e.target.closest(".kanban-column");C.querySelectorAll(".drag-over").forEach(o=>o.classList.remove("drag-over")),C.querySelectorAll(".drop-before").forEach(o=>o.classList.remove("drop-before")),t&&(t.classList.add("drag-over"),It(t,e.clientY)?.classList.add("drop-before"))}),C.addEventListener("drop",e=>{let t=ne,o=Me,s=te;if(!s&&!t)return;e.preventDefault(),te=null,ne=null,Me=null,Mt();let a=e.target.closest(".kanban-column"),i=a?.dataset.col;if(!a||!i)return;let c=It(a,e.clientY);if(t&&o){let U=(ie.get(o)??[]).filter(I=>String(I.chatId)===t).filter(I=>!(I.status==="closed"&&i!=="done"));if(!U.length)return;let h=new Set(U.map(I=>I.sessionId)),y=(ie.get(i)??[]).filter(I=>!h.has(I.sessionId)),J=c?y.findIndex(I=>I.sessionId===c.dataset.id):y.length;J<0&&(J=y.length);let Be=J>0?y[J-1]:null,$e=J<y.length?y[J]:null,Re=nt(Be?oe(Be):null,$e?oe($e):null);U.forEach((I,Q)=>{let Ze=Re+Q*.001;if(K==="team")ht(String(I.sessionId),i,Ze);else{let Pn={column:I.kanbanColumn,position:I.kanbanPosition};I.kanbanColumn=i,I.kanbanPosition=Ze,St(I,i,Ze,Pn)}}),T="",g();return}let u=O.sessions.get(s)??We.get(s);if(!u||u.status==="closed"&&i!=="done")return;let p=(ie.get(i)??[]).filter(U=>U.sessionId!==s),f=c?p.findIndex(U=>U.sessionId===c.dataset.id):p.length;f<0&&(f=p.length);let v=f>0?p[f-1]:null,k=f<p.length?p[f]:null,N=nt(v?oe(v):null,k?oe(k):null);if(K==="team"){ht(String(u.sessionId),i,N),T="",g();return}let le={column:u.kanbanColumn,position:u.kanbanPosition};u.kanbanColumn=i,u.kanbanPosition=N,T="",g(),St(u,i,N,le)}),C.addEventListener("dragend",()=>{te=null,ne=null,Me=null,Mt(),T="",g()}),x.addEventListener("click",e=>{e.target===x&&x.close()}),x.addEventListener("close",()=>{x.innerHTML=""}),B.addEventListener("click",e=>{e.target===B&&B.close()}),B.addEventListener("close",()=>{B.innerHTML=""}),P.addEventListener("change",()=>{let e=he().filter(t=>t.status!=="closed");for(let t of e)P.checked?w.add(t.sessionId):w.delete(t.sessionId);g()}),ee.addEventListener("click",()=>{w.clear(),g()}),Y.addEventListener("click",()=>{let e=[...w].filter(s=>!!O.sessions.get(s)),t=Ft(e),o=Y.textContent;Y.textContent=n("sessions.monitorRoomAdded",{added:t.added,total:t.total}),window.setTimeout(()=>{Y.textContent=o},1800)}),D.addEventListener("click",async()=>{let e=[...w];if(e.length===0||!confirm(n("sessions.closeBulkConfirm",{count:e.length})))return;D.disabled=!0,ee.disabled=!0;let t=D.textContent,o=0,s=0,a=[...e];D.textContent=`0/${e.length}`;async function i(){for(;a.length;){let c=a.shift();try{let u=await fetch(`/api/sessions/${encodeURIComponent(c)}/close`,{method:"POST"}),p=await u.json().catch(()=>({}));(!u.ok||p?.ok===!1)&&(s+=1)}catch{s+=1}finally{o+=1,D.textContent=`${o}/${e.length}`}}}await Promise.all(Array.from({length:Math.min(6,e.length)},()=>i())),D.textContent=t,D.disabled=!1,ee.disabled=!1,w.clear(),g(),s>0&&alert(`Failed: ${s}/${e.length}`)});async function Bt(e){let t=[...w].map(p=>O.sessions.get(p)).filter(p=>!!p&&p.status!=="closed"&&!!p.locked!==e);if(t.length===0)return;S.disabled=!0,H.disabled=!0;let o=e?S.textContent:H.textContent,s=e?S:H,a=0,i=0,c=[...t];s.textContent=`0/${t.length}`;async function u(){for(;c.length;){let p=c.shift(),f=!!p.locked;try{let v=await fetch(`/api/sessions/${encodeURIComponent(p.sessionId)}/lock`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({locked:e})}),k=await v.json().catch(()=>({}));!v.ok||k?.ok===!1?(i+=1,p.locked=f):p.locked=!!k.locked}catch{i+=1,p.locked=f}finally{a+=1,s.textContent=`${a}/${t.length}`}}}await Promise.all(Array.from({length:Math.min(6,t.length)},()=>u())),s.textContent=o,ye(),g(),i>0&&alert(`${n("sessions.lockFailed")}: ${i}/${t.length}`)}S.addEventListener("click",()=>{Bt(!0)}),H.addEventListener("click",()=>{Bt(!1)}),Ie.addEventListener("click",e=>{if(He)return;let t=e.target?.closest("button[data-hours]");if(!t)return;let o=ot(t.dataset.hours);!o||o===xe||(xe=o,V.textContent="",Ve())}),fe.addEventListener("click",async()=>{let e=mt(),t=bt();if(t.length===0)return;let o=un(e);if(confirm(n("sessions.idleCleanupConfirm",{count:t.length,threshold:o}))){He=!0,fe.disabled=!0,V.textContent=n("sessions.idleCleanupRunning");try{let s=await fetch("/api/sessions/cleanup-idle",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({olderThanHours:e,sessionIds:t.map(i=>i.sessionId)})}),a=await s.json().catch(()=>({}));if(!s.ok){s.status!==401&&alert(`${n("sessions.idleCleanupFailed")}: ${a?.error??s.status}`),V.textContent="";return}for(let i of a?.results??[])i?.ok&&i?.sessionId&&w.delete(String(i.sessionId));V.textContent=n("sessions.idleCleanupDone",{closed:Number(a?.closed??0),failed:Number(a?.failed??0)}),g()}catch(s){alert(`${n("sessions.idleCleanupFailed")}: ${s}`),V.textContent=""}finally{He=!1,Ve()}}}),_.querySelectorAll("th[data-sort]").forEach(e=>{e.addEventListener("click",()=>{let t=e.dataset.sort;be===t?ae=ae==="asc"?"desc":"asc":(be=t,ae=t==="spawnedAt"||t==="lastMessageAt"?"desc":"asc"),g()})}),m.addEventListener("input",g),m.addEventListener("change",e=>{let t=e.target;t?.name==="showUnknownChats"&&(_t(window.localStorage,t.checked),g())});let On=O.on(g),Rt=setInterval(()=>{if(!document.body.contains(C)){clearInterval(Rt);return}A==="kanban"&&K==="team"&&(T="",g())},3e4);return g(),jt().then(g),()=>{On(),clearInterval(Rt),ke(),$.close(),x.close(),B.close()}}export{st as a,zn as b,Pe as c,ue as d,on as e,it as f,Vn as g,Jn as h,rt as i,ks as j,$s as k,ts as l};
@@ -1 +0,0 @@
1
- import{b as S}from"./chunk-PE6W3C2C.js";import"./chunk-LXIK7OUJ.js";import"./chunk-3UJYRR2Q.js";import{a as se,b as R,c as $}from"./chunk-JTSE5VP6.js";import{c as D}from"./chunk-7SZRL6FY.js";var c=D(se(),1);var e=D($(),1),ce={name:"",botId:"",kind:"turn",workflowId:"",mode:"dynamic",chatId:"",manualChat:!1,manualChatId:"",allowChats:[],dedup:"",instruction:"",verify:"token",secret:""};async function M(t){let a=await fetch(t);return{status:a.status,body:await a.json().catch(()=>({}))}}async function z(t,a,o){let m=await fetch(a,{method:t,headers:{"content-type":"application/json"},body:o?JSON.stringify(o):void 0});return{status:m.status,body:await m.json().catch(()=>({}))}}function K(t,a){return{promptEnvelope:{sourceName:t.promptEnvelope?.sourceName||t.name,instruction:a}}}function B(t){return`${location.origin}/webhook/${encodeURIComponent(t)}`}function j(t,a){return t.filter(o=>o.bots.includes(a))}function le(){let t=S(),a=(0,c.useRef)(!1),o=(0,c.useRef)(null),[m,C]=(0,c.useState)([]),[g,L]=(0,c.useState)([]),[k,E]=(0,c.useState)([]),[w,h]=(0,c.useState)(!0),[r,N]=(0,c.useState)(ce),[F,f]=(0,c.useState)(null),[H,O]=(0,c.useState)(null),[X,A]=(0,c.useState)(!1),[q,P]=(0,c.useState)(null),[G,T]=(0,c.useState)(""),[J,x]=(0,c.useState)(null),[V,W]=(0,c.useState)(null),v=(0,c.useMemo)(()=>j(g,r.botId),[g,r.botId]),_=(0,c.useCallback)(n=>g.find(i=>i.chatId===n)?.name||n,[g]),U=(0,c.useCallback)((n,s)=>{N(i=>{let y=i.botId&&n.some(p=>p.larkAppId===i.botId)?i.botId:n[0]?.larkAppId??"",l=j(s,y),u=i.chatId&&l.some(p=>p.chatId===i.chatId)?i.chatId:l[0]?.chatId??"",b=new Set(l.map(p=>p.chatId));return{...i,botId:y,chatId:u,allowChats:i.allowChats.filter(p=>b.has(p))}})},[]),I=(0,c.useCallback)(async()=>{h(!0);try{let[n,s,i]=await Promise.all([M("/api/bots"),M("/api/connectors"),M("/api/groups")]);if(!a.current)return;let y=(n.body?.bots||[]).map(u=>({larkAppId:u.larkAppId,botName:u.botName||u.larkAppId})),l=(i.body?.chats||[]).map(u=>({chatId:u.chatId,name:u.name||"",bots:(u.memberBots||[]).filter(b=>b.inChat).map(b=>b.larkAppId)}));C(y),L(l),E(Array.isArray(s.body?.connectors)?s.body.connectors:[]),U(y,l)}finally{a.current&&h(!1)}},[U]);(0,c.useEffect)(()=>(a.current=!0,I(),()=>{a.current=!1,o.current&&clearTimeout(o.current)}),[I]),(0,c.useEffect)(()=>{let n=new Set(v.map(s=>s.chatId));N(s=>({...s,chatId:s.chatId&&n.has(s.chatId)?s.chatId:v[0]?.chatId??"",allowChats:s.allowChats.filter(i=>n.has(i))}))},[v]);function Q(n){return t(n==="fixed"?"connectors.modeLabelFixed":n==="new-group"?"connectors.modeLabelNewGroup":"connectors.modeLabelDynamic")}function Y(n){return t(n==="workflow"?"connectors.kindLabelWorkflow":"connectors.kindLabelTurn")}function d(n){N(s=>({...s,...n}))}function Z(n){d({allowChats:Array.from(n.selectedOptions).map(s=>s.value).filter(Boolean)})}async function ee(){f(null),O(null);let n=r.name.trim(),s=r.botId;if(!n){f({text:t("connectors.errName"),error:!0});return}if(!s){f({text:t("connectors.errBot"),error:!0});return}let i={name:n,enabled:!0,target:{kind:r.kind,mode:r.mode,botId:s},promptEnvelope:{sourceName:n},verify:{type:r.verify}},y=r.instruction.trim();if(y&&(i.promptEnvelope.instruction=y),r.kind==="workflow"){if(!r.workflowId.trim()){f({text:t("connectors.errWf"),error:!0});return}i.target.workflowId=r.workflowId.trim()}if(r.mode==="fixed"){let l=r.manualChat?r.manualChatId.trim():r.chatId;if(!l){f({text:t("connectors.errChat"),error:!0});return}i.target.chatId=l}else r.allowChats.length&&(i.target.allowChats=r.allowChats);if(r.mode==="new-group"){let l=r.dedup.trim();i.lifecycleExtractors=l?{dedupKey:l}:null}r.secret.trim()&&(i.secret=r.secret.trim()),A(!0),f({text:t("connectors.creating")});try{let l=await z("POST","/api/connectors",i);if(!a.current)return;if(l.status===201&&l.body?.ok){let u=l.body.webhookUrl||B(l.body.connector.id),b=(l.body.connector?.verify?.type??"token")==="token",p=r.mode==="dynamic",re=p?i.target.allowChats?.[0]||"<chatId>":"";f(null),O({name:n,mode:r.mode,chatId:i.target.chatId,url:u,secret:l.body.secret,isToken:b,isDynamic:p,exampleChat:re}),N(ie=>({...ie,name:"",workflowId:"",manualChatId:"",dedup:"",secret:"",instruction:"",allowChats:[]})),await I()}else{let u=l.body?.error||l.status;f({text:t("connectors.createFailed",{error:String(u)}),error:!0})}}finally{a.current&&A(!1)}}async function te(n){x({id:n.id,text:t("connectors.saving")});let s=await z("PUT",`/api/connectors/${encodeURIComponent(n.id)}`,K(n,G));if(a.current)if(s.status===200&&s.body?.ok)P(null),T(""),x(null),await I();else{let i=s.body?.error||s.status;x({id:n.id,text:t("connectors.saveFailed",{error:String(i)}),error:!0})}}async function ne(n){await z("PATCH",`/api/connectors/${encodeURIComponent(n.id)}`,{enabled:!n.enabled}),a.current&&await I()}async function oe(n){confirm(t("connectors.delConfirm"))&&(await z("DELETE",`/api/connectors/${encodeURIComponent(n.id)}`),a.current&&await I())}function ae(n){navigator.clipboard?.writeText(B(n.id)),W(n.id),o.current&&clearTimeout(o.current),o.current=setTimeout(()=>{a.current&&W(null)},1200)}return(0,e.jsxs)("section",{className:"page",children:[(0,e.jsx)("div",{className:"page-heading",children:(0,e.jsxs)("div",{children:[(0,e.jsx)("p",{className:"eyebrow",children:"Webhook"}),(0,e.jsx)("h1",{children:"Webhook"}),(0,e.jsx)("p",{children:t("connectors.lede")})]})}),(0,e.jsxs)("div",{className:"card",style:{marginBottom:16},children:[(0,e.jsx)("h2",{style:{marginTop:0},children:t("connectors.createTitle")}),(0,e.jsxs)("div",{className:"cn-form",style:{display:"grid",gridTemplateColumns:"140px 1fr",gap:"10px 14px",alignItems:"center",maxWidth:680},children:[(0,e.jsx)("label",{htmlFor:"cn-name",children:t("connectors.fName")}),(0,e.jsx)("input",{id:"cn-name",value:r.name,onChange:n=>d({name:n.currentTarget.value}),placeholder:t("connectors.fNamePh")}),(0,e.jsx)("label",{htmlFor:"cn-bot",children:t("connectors.fBot")}),(0,e.jsx)("select",{id:"cn-bot",value:r.botId,onChange:n=>d({botId:n.currentTarget.value}),children:m.length?m.map(n=>(0,e.jsx)("option",{value:n.larkAppId,children:n.botName},n.larkAppId)):(0,e.jsx)("option",{value:"",children:t("connectors.noOnlineBots")})}),(0,e.jsx)("label",{htmlFor:"cn-kind",children:t("connectors.fKind")}),(0,e.jsxs)("select",{id:"cn-kind",value:r.kind,onChange:n=>d({kind:n.currentTarget.value}),children:[(0,e.jsx)("option",{value:"turn",children:t("connectors.kindTurn")}),(0,e.jsx)("option",{value:"workflow",children:t("connectors.kindWorkflow")})]}),r.kind==="workflow"?(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("label",{htmlFor:"cn-wf",children:t("connectors.fWf")}),(0,e.jsx)("input",{id:"cn-wf",value:r.workflowId,onChange:n=>d({workflowId:n.currentTarget.value}),placeholder:"workflowId"})]}):null,(0,e.jsx)("label",{htmlFor:"cn-mode",children:t("connectors.fMode")}),(0,e.jsxs)("select",{id:"cn-mode",value:r.mode,onChange:n=>d({mode:n.currentTarget.value}),children:[(0,e.jsx)("option",{value:"dynamic",children:t("connectors.modeDynamic")}),(0,e.jsx)("option",{value:"fixed",children:t("connectors.modeFixed")}),(0,e.jsx)("option",{value:"new-group",children:t("connectors.modeNewGroup")})]}),r.mode==="fixed"?(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("label",{children:t("connectors.fFixedChat")}),(0,e.jsxs)("div",{children:[r.manualChat?(0,e.jsx)("input",{id:"cn-chat",value:r.manualChatId,onChange:n=>d({manualChatId:n.currentTarget.value}),placeholder:t("connectors.fChatManualPh"),style:{width:"100%",boxSizing:"border-box",marginTop:6}}):(0,e.jsx)("select",{id:"cn-chat-sel",value:r.chatId,onChange:n=>d({chatId:n.currentTarget.value}),style:{width:"100%",boxSizing:"border-box"},children:v.length?v.map(n=>(0,e.jsx)("option",{value:n.chatId,children:n.name||n.chatId},n.chatId)):(0,e.jsx)("option",{value:"",children:t("connectors.noBotGroups")})}),(0,e.jsx)("a",{href:"#",onClick:n=>{n.preventDefault(),d({manualChat:!r.manualChat})},style:{fontSize:12,display:"inline-block",marginTop:4},children:r.manualChat?t("connectors.chatListLink"):t("connectors.chatManualLink")})]})]}):(0,e.jsxs)(e.Fragment,{children:[(0,e.jsxs)("label",{children:[t("connectors.fAllow"),(0,e.jsx)("span",{className:"muted",style:{fontWeight:400},children:t("connectors.optional")})]}),(0,e.jsxs)("div",{children:[(0,e.jsx)("select",{multiple:!0,size:4,value:r.allowChats,onChange:n=>Z(n.currentTarget),style:{width:"100%",boxSizing:"border-box"},children:v.map(n=>(0,e.jsx)("option",{value:n.chatId,children:n.name||n.chatId},n.chatId))}),(0,e.jsx)("div",{className:"muted",style:{fontSize:12,marginTop:4},children:t("connectors.allowHint")})]})]}),r.mode==="dynamic"?(0,e.jsx)("div",{style:{gridColumn:"1 / -1"},children:(0,e.jsx)("div",{className:"muted",style:{fontSize:12,lineHeight:1.7,background:"var(--bg-soft,#f6f7f9)",padding:"8px 10px",borderRadius:6},dangerouslySetInnerHTML:{__html:t("connectors.dynamicHint")}})}):null,r.mode==="new-group"?(0,e.jsxs)(e.Fragment,{children:[(0,e.jsxs)("label",{htmlFor:"cn-dedup",children:[t("connectors.fDedup"),(0,e.jsx)("span",{className:"muted",style:{fontWeight:400},children:t("connectors.optional")})]}),(0,e.jsxs)("div",{children:[(0,e.jsx)("input",{id:"cn-dedup",value:r.dedup,onChange:n=>d({dedup:n.currentTarget.value}),placeholder:t("connectors.fDedupPh"),style:{width:"100%",boxSizing:"border-box"}}),(0,e.jsx)("div",{className:"muted",style:{fontSize:12,marginTop:4},dangerouslySetInnerHTML:{__html:t("connectors.dedupHint")}})]})]}):null,(0,e.jsxs)("label",{htmlFor:"cn-instruction",style:{alignSelf:"start"},children:[t("connectors.fInstruction"),(0,e.jsx)("span",{className:"muted",style:{fontWeight:400},children:t("connectors.optional")})]}),(0,e.jsx)("textarea",{id:"cn-instruction",rows:3,value:r.instruction,onChange:n=>d({instruction:n.currentTarget.value}),placeholder:t("connectors.fInstructionPh"),style:{width:"100%",boxSizing:"border-box",fontFamily:"inherit",fontSize:13}}),(0,e.jsx)("label",{htmlFor:"cn-verify",children:t("connectors.fVerify")}),(0,e.jsxs)("select",{id:"cn-verify",value:r.verify,onChange:n=>d({verify:n.currentTarget.value}),children:[(0,e.jsx)("option",{value:"token",children:t("connectors.verifyToken")}),(0,e.jsx)("option",{value:"hmac-sha256",children:t("connectors.verifyHmac")})]}),(0,e.jsx)("label",{htmlFor:"cn-secret",children:t("connectors.fSecret")}),(0,e.jsx)("input",{id:"cn-secret",value:r.secret,onChange:n=>d({secret:n.currentTarget.value}),placeholder:t("connectors.fSecretPh")})]}),(0,e.jsxs)("div",{style:{marginTop:14},children:[(0,e.jsx)("button",{id:"cn-create",type:"button",className:"primary",disabled:X,onClick:()=>{ee()},children:t("connectors.btnCreate")}),F?(0,e.jsx)("span",{className:F.error?"err":"muted",style:{marginLeft:10,fontSize:13},children:F.text}):null]}),H?(0,e.jsx)(de,{created:H,groupName:_}):null]}),(0,e.jsxs)("div",{className:"card",children:[(0,e.jsxs)("h2",{style:{marginTop:0},children:[t("connectors.listTitle")," ",(0,e.jsx)("span",{className:"muted",style:{fontSize:13},children:k.length?t("connectors.count",{count:k.length}):""})]}),w?(0,e.jsx)("div",{children:t("connectors.loading")}):(0,e.jsx)(ue,{connectors:k,bots:m,copiedId:V,editingId:q,editInstruction:G,editMsg:J,groupName:_,modeLabel:Q,kindLabel:Y,onCopy:ae,onEdit:n=>{P(n.id),T(n.promptEnvelope?.instruction||""),x(null)},onCancelEdit:()=>{P(null),T(""),x(null)},onEditInstruction:T,onSaveInstruction:n=>{te(n)},onToggle:n=>{ne(n)},onDelete:n=>{oe(n)}})]})]})}function de(t){let a=S(),o=t.created,m=o.isDynamic?`${o.url}?chatId=${o.exampleChat}`:o.url,C=o.exampleChat!=="<chatId>"?`\uFF08${t.groupName(o.exampleChat)}\uFF09`:"";return(0,e.jsx)("div",{style:{marginTop:12},children:(0,e.jsxs)("div",{className:"card",style:{padding:"12px 14px",background:"var(--bg-soft,#f6f7f9)"},children:[(0,e.jsxs)("p",{className:"ok",style:{margin:"0 0 6px"},children:[a("connectors.createdPrefix",{name:o.name}),o.mode==="fixed"&&o.chatId?(0,e.jsxs)("span",{className:"muted",style:{fontWeight:400,fontSize:13},children:[" \xB7 ",a("connectors.createdDest",{name:t.groupName(o.chatId)})]}):null]}),(0,e.jsxs)("p",{style:{margin:"4px 0",fontSize:13},children:[(0,e.jsx)("span",{className:"muted",children:a("connectors.webhookUrl")}),(0,e.jsx)("code",{style:{wordBreak:"break-all"},children:o.url})]}),o.secret?(0,e.jsxs)("p",{style:{margin:"4px 0",fontSize:13},children:[(0,e.jsxs)("span",{className:"muted",children:[o.isToken?a("connectors.tokenLabel"):a("connectors.signLabel"),a("connectors.secretOnce")]}),(0,e.jsx)("code",{children:o.secret})]}):null,o.isToken&&o.isDynamic?(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("p",{className:"muted",style:{fontSize:12,margin:"6px 0 0"},children:a("connectors.usageDynamicLede",{gn:C})}),(0,e.jsx)("pre",{style:{margin:"6px 0 0",fontSize:12,whiteSpace:"pre-wrap",wordBreak:"break-all"},children:(0,e.jsx)("code",{children:`curl -X POST '${m}' -H 'content-type: application/json' -d '{}'`})}),(0,e.jsx)("p",{className:"muted",style:{fontSize:12,margin:"6px 0 0"},dangerouslySetInnerHTML:{__html:a("connectors.usageDynamicNote")}})]}):o.isToken?(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("p",{className:"muted",style:{fontSize:12,margin:"6px 0 0"},children:a("connectors.usageTokenLede")}),(0,e.jsx)("pre",{style:{margin:"6px 0 0",fontSize:12,whiteSpace:"pre-wrap",wordBreak:"break-all"},children:(0,e.jsx)("code",{children:`curl -X POST '${m}' -H 'content-type: application/json' -d '{}'`})}),(0,e.jsx)("p",{className:"muted",style:{fontSize:12,margin:"6px 0 0"},dangerouslySetInnerHTML:{__html:a("connectors.usageTokenNote")}})]}):(0,e.jsx)("p",{className:"muted",style:{fontSize:12,margin:"6px 0 0"},dangerouslySetInnerHTML:{__html:a("connectors.usageHmac")+(o.isDynamic?a("connectors.usageHmacDynamic"):"")}})]})})}function ue(t){let a=S();return t.connectors.length?(0,e.jsx)(e.Fragment,{children:t.connectors.map(o=>{let m=t.bots.find(h=>h.larkAppId===o.target.botId),C=B(o.id),g=(o.verify?.type??"token")==="token",L=a(g?"connectors.badgeToken":"connectors.badgeSign"),k=o.target.mode==="fixed"&&o.target.chatId?` \xB7 ${a("connectors.dest",{name:t.groupName(o.target.chatId)})}`:"",E=t.editingId===o.id,w=t.editMsg?.id===o.id?t.editMsg:null;return(0,e.jsxs)("div",{className:"card",style:{margin:"0 0 10px",padding:"12px 14px",background:"var(--bg-soft,#f6f7f9)"},children:[(0,e.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:8,flexWrap:"wrap"},children:[(0,e.jsx)("b",{style:{fontSize:15},children:o.name}),(0,e.jsx)("span",{className:o.enabled?"ok":"muted",style:{fontSize:12},children:o.enabled?a("connectors.enabled"):a("connectors.disabled")}),(0,e.jsxs)("span",{className:"muted",style:{fontSize:12},children:["\xB7 ",m?.botName||o.target.botId," \xB7 ",t.kindLabel(o.target.kind)," \xB7 ",t.modeLabel(o.target.mode),k," \xB7 ",L]}),(0,e.jsxs)("span",{style:{marginLeft:"auto",display:"flex",gap:6},children:[(0,e.jsx)("button",{className:"ghost",type:"button",style:{fontSize:12},onClick:()=>t.onEdit(o),children:a("connectors.btnEdit")}),(0,e.jsx)("button",{className:"ghost",type:"button",style:{fontSize:12},onClick:()=>t.onToggle(o),children:o.enabled?a("connectors.btnDisable"):a("connectors.btnEnable")}),(0,e.jsx)("button",{className:"ghost",type:"button",style:{fontSize:12},onClick:()=>t.onDelete(o),children:a("connectors.btnDel")})]})]}),(0,e.jsxs)("div",{style:{marginTop:6,fontSize:13,display:"flex",alignItems:"center",gap:8,flexWrap:"wrap"},children:[(0,e.jsx)("span",{className:"muted",children:a("connectors.webhookUrl")}),(0,e.jsxs)("code",{style:{fontSize:12,wordBreak:"break-all"},children:[C,g?"/<token>":""]}),(0,e.jsx)("button",{className:"ghost",type:"button",style:{fontSize:12},onClick:()=>t.onCopy(o),children:t.copiedId===o.id?a("connectors.copied"):a("connectors.copy")})]}),g?(0,e.jsx)("div",{className:"muted",style:{fontSize:12,marginTop:4},dangerouslySetInnerHTML:{__html:a("connectors.tokenHint")}}):null,o.target.mode==="dynamic"?(0,e.jsx)("div",{className:"muted",style:{fontSize:12,marginTop:4},dangerouslySetInnerHTML:{__html:a("connectors.dynamicReqHint")}}):null,o.promptEnvelope?.instruction?(0,e.jsxs)("div",{className:"muted",style:{fontSize:12,marginTop:4},children:[a("connectors.instructionPrefix"),o.promptEnvelope.instruction]}):null,E?(0,e.jsxs)("div",{className:"cn-edit-box",style:{marginTop:8},children:[(0,e.jsx)("textarea",{className:"cn-edit-instruction",rows:3,value:t.editInstruction,onChange:h=>t.onEditInstruction(h.currentTarget.value),style:{width:"100%",boxSizing:"border-box",fontFamily:"inherit",fontSize:13},placeholder:a("connectors.fInstructionPh")}),(0,e.jsxs)("div",{style:{marginTop:8,display:"flex",alignItems:"center",gap:8,flexWrap:"wrap"},children:[(0,e.jsx)("button",{className:"primary",type:"button",style:{fontSize:12},onClick:()=>t.onSaveInstruction(o),children:a("connectors.btnSave")}),(0,e.jsx)("button",{className:"ghost",type:"button",style:{fontSize:12},onClick:t.onCancelEdit,children:a("connectors.btnCancel")}),w?(0,e.jsx)("span",{className:w.error?"err":"muted",style:{fontSize:12},children:w.text}):null]})]}):null]},o.id)})}):(0,e.jsx)("p",{className:"muted",children:a("connectors.empty")})}function me(t){return R(t,(0,e.jsx)(le,{}))}export{K as buildConnectorInstructionUpdateBody,me as renderConnectorsPage};