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,21 +1,546 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useRef } from 'react';
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
3
+ import { DropdownMenu, Html, LoadingState, RefreshIconButton } from './dashboard-components.js';
3
4
  import { useT } from './react-hooks.js';
4
5
  import { mountReactPage } from './react-mount.js';
5
- import { wireRolesSurface } from './roles.js';
6
- // Render-once scaffold: React owns the translated shell, while wireRolesSurface
7
- // owns the role tree/editor subtrees with delegated events and innerHTML. Keep
8
- // ui-change rerenders as full remounts until the controller is split further.
6
+ import { hasExplicitChatRole, summarizeGroupProfileMatches, } from './role-profile-match.js';
7
+ import { applyRoleProfile, botInChatCount, botRoleCount, byteLength, deleteProfileEntry, deleteRole, entryForBot, filterRoleGroups, filterRoleProfiles, hashChatId, isValidProfileId, loadGroups, loadProfileEntries, loadProfileEntry, loadProfiles, loadRole, loadRoleProfileContext, MAX_ROLE_BYTES, roleKey, ROLE_WARN_BYTES, saveInjectMode, saveProfileEntry, saveRole, } from './roles.js';
8
+ import { botAvatarHtml, loadNameMaps } from './ui.js';
9
+ function useAliveRef() {
10
+ const alive = useRef(true);
11
+ useEffect(() => {
12
+ alive.current = true;
13
+ return () => { alive.current = false; };
14
+ }, []);
15
+ return alive;
16
+ }
17
+ function useTimers() {
18
+ const timers = useRef(new Set());
19
+ useEffect(() => () => {
20
+ for (const timer of timers.current)
21
+ window.clearTimeout(timer);
22
+ timers.current.clear();
23
+ }, []);
24
+ return useCallback((fn, ms) => {
25
+ const id = window.setTimeout(() => {
26
+ timers.current.delete(id);
27
+ fn();
28
+ }, ms);
29
+ timers.current.add(id);
30
+ return id;
31
+ }, []);
32
+ }
33
+ function BotAvatar(props) {
34
+ return (_jsx(Html, { html: botAvatarHtml({
35
+ name: props.bot.botName,
36
+ larkAppId: props.bot.larkAppId,
37
+ avatarUrl: props.bot.botAvatarUrl,
38
+ size: 'sm',
39
+ }) }));
40
+ }
9
41
  function RolesPage(props) {
10
42
  const tr = useT();
11
- const rootRef = useRef(null);
12
- const isProfiles = props.tab === 'profiles';
43
+ const alive = useAliveRef();
44
+ const scheduleTimer = useTimers();
45
+ const [groups, setGroups] = useState([]);
46
+ const [allBots, setAllBots] = useState([]);
47
+ const [profiles, setProfiles] = useState([]);
48
+ const [roleContext, setRoleContext] = useState({
49
+ entriesByProfile: new Map(),
50
+ effectiveRolesByBot: new Map(),
51
+ });
52
+ const [roleContextLoaded, setRoleContextLoaded] = useState(false);
53
+ const [loadingTree, setLoadingTree] = useState(true);
54
+ const [profileListLoading, setProfileListLoading] = useState(true);
55
+ const [groupsFilter, setGroupsFilter] = useState('');
56
+ const [profileFilter, setProfileFilter] = useState('');
57
+ const [expandedGroups, setExpandedGroups] = useState(() => new Set());
58
+ const [selectedGroupId, setSelectedGroupId] = useState(null);
59
+ const [selectedBotId, setSelectedBotId] = useState(null);
60
+ const [selectedRole, setSelectedRole] = useState(null);
61
+ const [editingContent, setEditingContent] = useState('');
62
+ const [editingInjectMode, setEditingInjectMode] = useState('every');
63
+ const [roleSaving, setRoleSaving] = useState(false);
64
+ const [roleDeleting, setRoleDeleting] = useState(false);
65
+ const [injectSaving, setInjectSaving] = useState(false);
66
+ const [roleFlash, setRoleFlash] = useState(null);
67
+ const [injectFlash, setInjectFlash] = useState(null);
68
+ const [selectedProfileId, setSelectedProfileId] = useState(null);
69
+ const [selectedProfileBotId, setSelectedProfileBotId] = useState(null);
70
+ const [profileEntries, setProfileEntries] = useState([]);
71
+ const [profileEditingContent, setProfileEditingContent] = useState('');
72
+ const [selectedApplyGroupId, setSelectedApplyGroupId] = useState(null);
73
+ const [applyForce, setApplyForce] = useState(false);
74
+ const [selectedApplyBotIds, setSelectedApplyBotIds] = useState(() => new Set());
75
+ const [profileSaving, setProfileSaving] = useState(false);
76
+ const [profileDeleting, setProfileDeleting] = useState(false);
77
+ const [profileFlash, setProfileFlash] = useState(null);
78
+ const [applyStatus, setApplyStatus] = useState({ kind: 'idle' });
79
+ const selectSerial = useRef(0);
80
+ const profileSelectSerial = useRef(0);
81
+ const profileIdInputRef = useRef(null);
82
+ const selectedGroup = selectedGroupId ? groups.find(group => group.chatId === selectedGroupId) : undefined;
83
+ const selectedBot = selectedGroup && selectedBotId
84
+ ? selectedGroup.memberBots.find(bot => bot.larkAppId === selectedBotId)
85
+ : undefined;
86
+ const selectedProfileBot = selectedProfileBotId
87
+ ? allBots.find(bot => bot.larkAppId === selectedProfileBotId)
88
+ : undefined;
89
+ const selectedProfileEntry = entryForBot(profileEntries, selectedProfileBotId);
90
+ const selectedApplyGroup = selectedApplyGroupId
91
+ ? groups.find(group => group.chatId === selectedApplyGroupId)
92
+ : undefined;
93
+ const selectedApplyBots = selectedApplyGroup?.memberBots.filter(bot => bot.inChat) ?? [];
94
+ const selectedApplyBotKey = selectedApplyBots.map(bot => bot.larkAppId).join('\u0000');
95
+ const profileEntryKey = profileEntries.map(entry => entry.larkAppId).sort().join('\u0000');
96
+ const filteredGroups = useMemo(() => filterRoleGroups(groups, groupsFilter), [groups, groupsFilter]);
97
+ const filteredProfiles = useMemo(() => filterRoleProfiles(profiles, profileFilter), [profiles, profileFilter]);
98
+ const roleByteLen = byteLength(editingContent);
99
+ const profileByteLen = byteLength(profileEditingContent);
100
+ const flash = useCallback((setter, text, isError = false) => {
101
+ const id = Date.now() + Math.random();
102
+ setter({ text, isError, id });
103
+ scheduleTimer(() => {
104
+ setter(current => current?.id === id ? null : current);
105
+ }, isError ? 3000 : 2000);
106
+ }, [scheduleTimer]);
107
+ const refreshRoleContext = useCallback(async (nextGroups, nextProfiles) => {
108
+ try {
109
+ const context = await loadRoleProfileContext(nextGroups, nextProfiles);
110
+ if (!alive.current)
111
+ return;
112
+ setRoleContext(context);
113
+ setRoleContextLoaded(true);
114
+ }
115
+ catch {
116
+ if (!alive.current)
117
+ return;
118
+ setRoleContext({ entriesByProfile: new Map(), effectiveRolesByBot: new Map() });
119
+ setRoleContextLoaded(true);
120
+ }
121
+ }, [alive]);
122
+ const refreshGroups = useCallback(async () => {
123
+ const snapshot = await loadGroups();
124
+ if (!alive.current)
125
+ return snapshot;
126
+ setGroups(snapshot.groups);
127
+ setAllBots(snapshot.bots);
128
+ return snapshot;
129
+ }, [alive]);
130
+ const refreshProfiles = useCallback(async () => {
131
+ const nextProfiles = await loadProfiles();
132
+ if (!alive.current)
133
+ return nextProfiles;
134
+ setProfiles(nextProfiles);
135
+ return nextProfiles;
136
+ }, [alive]);
137
+ const loadInitial = useCallback(async () => {
138
+ setLoadingTree(true);
139
+ setProfileListLoading(true);
140
+ setRoleContextLoaded(false);
141
+ try {
142
+ const snapshot = await refreshGroups();
143
+ if (!alive.current)
144
+ return;
145
+ const nextProfiles = await refreshProfiles();
146
+ if (!alive.current)
147
+ return;
148
+ await loadNameMaps();
149
+ if (!alive.current)
150
+ return;
151
+ setExpandedGroups(new Set(snapshot.groups.filter(group => botRoleCount(group) > 0).map(group => group.chatId)));
152
+ if (props.tab === 'profiles') {
153
+ const requestedChatId = hashChatId();
154
+ setSelectedApplyGroupId(current => {
155
+ if (current)
156
+ return current;
157
+ if (requestedChatId && snapshot.groups.some(group => group.chatId === requestedChatId))
158
+ return requestedChatId;
159
+ return snapshot.groups[0]?.chatId ?? null;
160
+ });
161
+ }
162
+ else {
163
+ setSelectedApplyGroupId(current => current ?? snapshot.groups[0]?.chatId ?? null);
164
+ }
165
+ setLoadingTree(false);
166
+ setProfileListLoading(false);
167
+ void refreshRoleContext(snapshot.groups, nextProfiles);
168
+ }
169
+ catch {
170
+ if (!alive.current)
171
+ return;
172
+ setLoadingTree(false);
173
+ setProfileListLoading(false);
174
+ setRoleContextLoaded(true);
175
+ }
176
+ }, [alive, props.tab, refreshGroups, refreshProfiles, refreshRoleContext]);
177
+ useEffect(() => {
178
+ void loadInitial();
179
+ }, [loadInitial]);
13
180
  useEffect(() => {
14
- if (!rootRef.current)
15
- return undefined;
16
- return wireRolesSurface(rootRef.current, props.tab);
17
- }, [props.tab]);
18
- return (_jsxs("section", { className: "page roles-page", ref: rootRef, children: [_jsx("div", { className: "page-heading roles-heading", children: _jsxs("div", { children: [_jsx("p", { className: "eyebrow", children: tr('nav.roles') }), _jsx("h1", { children: tr('roles.title') }), _jsx("p", { children: tr('roles.subtitle') })] }) }), _jsxs("nav", { className: "wf-subnav roles-subnav", children: [_jsx("a", { href: "#/roles", className: isProfiles ? undefined : 'active', children: tr('roles.tabGroups') }), _jsx("a", { href: "#/roles/profile", className: isProfiles ? 'active' : undefined, children: tr('roles.tabProfiles') })] }), _jsxs("div", { id: "roles-by-group-view", className: "roles-layout", hidden: isProfiles, children: [_jsxs("div", { className: "roles-tree-panel", children: [_jsxs("div", { className: "roles-tree-header", children: [_jsx("input", { type: "search", id: "roles-search", placeholder: tr('roles.search') }), _jsx("button", { type: "button", id: "roles-refresh", children: tr('roles.refresh') })] }), _jsx("div", { id: "roles-tree", className: "roles-tree" })] }), _jsxs("div", { className: "roles-editor-panel", children: [_jsx("div", { id: "roles-editor-empty", className: "roles-editor-empty", children: tr('roles.selectHint') }), _jsxs("div", { id: "roles-editor-form", className: "roles-editor-form", style: { display: 'none' }, children: [_jsxs("div", { className: "roles-editor-breadcrumb", children: [_jsx("span", { id: "roles-editor-group-name" }), _jsx("span", { className: "roles-breadcrumb-sep", children: "\u203A" }), _jsx("span", { id: "roles-editor-bot-name" })] }), _jsx("div", { className: "roles-editor-meta", children: _jsx("span", { id: "roles-editor-chat-id", className: "roles-editor-meta-line" }) }), _jsxs("div", { className: "roles-editor-inject", children: [_jsx("label", { htmlFor: "roles-editor-inject-mode", children: tr('roles.injectModeLabel') }), _jsxs("select", { id: "roles-editor-inject-mode", children: [_jsx("option", { value: "every", children: tr('roles.injectModeEvery') }), _jsx("option", { value: "once", children: tr('roles.injectModeOnce') })] }), _jsx("span", { className: "roles-editor-inject-hint", children: tr('roles.injectModeHint') })] }), _jsx("textarea", { id: "roles-editor-textarea", placeholder: tr('roles.editorPlaceholder'), rows: 14 }), _jsxs("div", { className: "roles-editor-footer", children: [_jsx("span", { id: "roles-editor-bytecount", className: "roles-bytecount" }), _jsxs("div", { className: "roles-editor-actions", children: [_jsx("button", { type: "button", id: "roles-delete", className: "danger", children: tr('roles.delete') }), _jsx("button", { type: "button", id: "roles-save", className: "primary", children: tr('roles.save') })] })] }), _jsx("div", { id: "roles-preview", className: "roles-preview" })] })] })] }), _jsxs("div", { id: "roles-profiles-view", className: "roles-layout roles-profiles-layout", hidden: !isProfiles, children: [_jsxs("div", { className: "roles-tree-panel", children: [_jsxs("div", { className: "roles-tree-header roles-profile-create", children: [_jsx("input", { type: "text", id: "roles-profile-id", placeholder: tr('roles.profileIdPlaceholder'), maxLength: 64 }), _jsx("button", { type: "button", id: "roles-profile-select", children: tr('roles.openProfile') })] }), _jsxs("div", { className: "roles-tree-header", children: [_jsx("input", { type: "search", id: "roles-profile-search", placeholder: tr('roles.profileSearch') }), _jsx("button", { type: "button", id: "roles-profile-refresh", children: tr('roles.refresh') })] }), _jsx("div", { id: "roles-profile-list", className: "roles-tree" })] }), _jsxs("div", { className: "roles-editor-panel", children: [_jsx("div", { id: "roles-profile-empty", className: "roles-editor-empty", children: tr('roles.profileSelectHint') }), _jsx("div", { id: "roles-profile-detail", className: "roles-editor-form roles-profile-detail", style: { display: 'none' } })] })] })] }));
181
+ if (selectedApplyGroupId || groups.length === 0)
182
+ return;
183
+ setSelectedApplyGroupId(groups[0].chatId);
184
+ }, [groups, selectedApplyGroupId]);
185
+ useEffect(() => {
186
+ const defaults = new Set(selectedApplyBots
187
+ .filter(bot => !!entryForBot(profileEntries, bot.larkAppId))
188
+ .map(bot => bot.larkAppId));
189
+ setSelectedApplyBotIds(defaults);
190
+ setApplyStatus({ kind: 'idle' });
191
+ }, [profileEntryKey, selectedApplyBotKey]); // Re-default only when available bots/entries change.
192
+ async function handleSelectBot(groupId, botId) {
193
+ const serial = ++selectSerial.current;
194
+ setSelectedGroupId(groupId);
195
+ setSelectedBotId(botId);
196
+ const role = await loadRole(botId, groupId);
197
+ if (!alive.current || serial !== selectSerial.current)
198
+ return;
199
+ setSelectedRole(role);
200
+ setEditingContent(role.content ?? '');
201
+ setEditingInjectMode(role.injectMode === 'once' ? 'once' : 'every');
202
+ setRoleFlash(null);
203
+ setInjectFlash(null);
204
+ }
205
+ async function handleGroupRefresh() {
206
+ const snapshot = await refreshGroups();
207
+ if (!alive.current)
208
+ return;
209
+ void refreshRoleContext(snapshot.groups, profiles);
210
+ if (selectedGroupId && selectedBotId) {
211
+ const role = await loadRole(selectedBotId, selectedGroupId);
212
+ if (!alive.current)
213
+ return;
214
+ setSelectedRole(role);
215
+ setEditingContent(role.content ?? '');
216
+ setEditingInjectMode(role.injectMode === 'once' ? 'once' : 'every');
217
+ }
218
+ }
219
+ async function handleSaveRole() {
220
+ if (!selectedGroupId || !selectedBotId)
221
+ return;
222
+ setRoleSaving(true);
223
+ try {
224
+ const ok = await saveRole(selectedBotId, selectedGroupId, editingContent, editingInjectMode);
225
+ if (!alive.current)
226
+ return;
227
+ if (ok) {
228
+ const snapshot = await refreshGroups();
229
+ if (!alive.current)
230
+ return;
231
+ setSelectedRole(prev => prev ? { ...prev, content: editingContent, hasRole: true, injectMode: editingInjectMode } : prev);
232
+ void refreshRoleContext(snapshot.groups, profiles);
233
+ flash(setRoleFlash, tr('roles.saved'));
234
+ }
235
+ else {
236
+ flash(setRoleFlash, editingContent.trim().length === 0 ? tr('roles.emptyError') : tr('roles.saveFailed'), true);
237
+ }
238
+ }
239
+ finally {
240
+ if (alive.current)
241
+ setRoleSaving(false);
242
+ }
243
+ }
244
+ async function handleDeleteRole() {
245
+ if (!selectedGroupId || !selectedBotId)
246
+ return;
247
+ if (!confirm(tr('roles.confirmDelete')))
248
+ return;
249
+ setRoleDeleting(true);
250
+ try {
251
+ const ok = await deleteRole(selectedBotId, selectedGroupId);
252
+ if (!alive.current)
253
+ return;
254
+ if (ok) {
255
+ const snapshot = await refreshGroups();
256
+ if (!alive.current)
257
+ return;
258
+ setSelectedGroupId(null);
259
+ setSelectedBotId(null);
260
+ setSelectedRole(null);
261
+ setEditingContent('');
262
+ setEditingInjectMode('every');
263
+ void refreshRoleContext(snapshot.groups, profiles);
264
+ }
265
+ }
266
+ finally {
267
+ if (alive.current)
268
+ setRoleDeleting(false);
269
+ }
270
+ }
271
+ async function handleInjectModeChange(mode) {
272
+ if (!selectedGroupId || !selectedBotId)
273
+ return;
274
+ const prev = editingInjectMode;
275
+ setEditingInjectMode(mode);
276
+ setInjectSaving(true);
277
+ try {
278
+ const ok = await saveInjectMode(selectedBotId, selectedGroupId, mode);
279
+ if (!alive.current)
280
+ return;
281
+ if (!ok)
282
+ setEditingInjectMode(prev);
283
+ flash(setInjectFlash, ok ? tr('roles.saved') : tr('roles.saveFailed'), !ok);
284
+ }
285
+ finally {
286
+ if (alive.current)
287
+ setInjectSaving(false);
288
+ }
289
+ }
290
+ async function handleSelectProfile(profileId) {
291
+ const clean = profileId.trim();
292
+ if (!isValidProfileId(clean))
293
+ return;
294
+ const serial = ++profileSelectSerial.current;
295
+ setSelectedProfileId(clean);
296
+ setSelectedProfileBotId(null);
297
+ setProfileEditingContent('');
298
+ setApplyStatus({ kind: 'idle' });
299
+ setSelectedApplyGroupId(current => current ?? groups[0]?.chatId ?? null);
300
+ const entries = await loadProfileEntries(clean);
301
+ if (!alive.current || serial !== profileSelectSerial.current)
302
+ return;
303
+ setProfileEntries(entries);
304
+ setProfileFlash(null);
305
+ }
306
+ async function handleSelectProfileBot(botId) {
307
+ if (!selectedProfileId)
308
+ return;
309
+ const serial = ++profileSelectSerial.current;
310
+ setSelectedProfileBotId(botId);
311
+ const entry = await loadProfileEntry(selectedProfileId, botId);
312
+ if (!alive.current || serial !== profileSelectSerial.current)
313
+ return;
314
+ setProfileEditingContent(entry.content ?? '');
315
+ const entries = await loadProfileEntries(selectedProfileId);
316
+ if (!alive.current || serial !== profileSelectSerial.current)
317
+ return;
318
+ setProfileEntries(entries);
319
+ setProfileFlash(null);
320
+ }
321
+ async function handleProfileRefresh() {
322
+ const snapshot = await refreshGroups();
323
+ if (!alive.current)
324
+ return;
325
+ const nextProfiles = await refreshProfiles();
326
+ if (!alive.current)
327
+ return;
328
+ if (selectedProfileId) {
329
+ const entries = await loadProfileEntries(selectedProfileId);
330
+ if (!alive.current)
331
+ return;
332
+ setProfileEntries(entries);
333
+ }
334
+ void refreshRoleContext(snapshot.groups, nextProfiles);
335
+ }
336
+ async function handleOpenProfile() {
337
+ const input = profileIdInputRef.current;
338
+ const profileId = input?.value.trim() ?? '';
339
+ if (!profileId)
340
+ return;
341
+ if (!isValidProfileId(profileId)) {
342
+ input?.setCustomValidity(tr('roles.profileIdInvalid'));
343
+ input?.reportValidity();
344
+ return;
345
+ }
346
+ input?.setCustomValidity('');
347
+ await handleSelectProfile(profileId);
348
+ if (!alive.current)
349
+ return;
350
+ if (!location.hash.startsWith('#/roles/profile')) {
351
+ location.hash = '#/roles/profile';
352
+ }
353
+ }
354
+ async function handleSaveProfileEntry() {
355
+ if (!selectedProfileId || !selectedProfileBotId)
356
+ return;
357
+ setProfileSaving(true);
358
+ try {
359
+ const ok = await saveProfileEntry(selectedProfileId, selectedProfileBotId, profileEditingContent);
360
+ if (!alive.current)
361
+ return;
362
+ const nextProfiles = await refreshProfiles();
363
+ if (!alive.current)
364
+ return;
365
+ const entries = await loadProfileEntries(selectedProfileId);
366
+ if (!alive.current)
367
+ return;
368
+ setProfileEntries(entries);
369
+ void refreshRoleContext(groups, nextProfiles);
370
+ flash(setProfileFlash, ok ? tr('roles.saved') : tr('roles.saveFailed'), !ok);
371
+ }
372
+ finally {
373
+ if (alive.current)
374
+ setProfileSaving(false);
375
+ }
376
+ }
377
+ async function handleDeleteProfileEntry() {
378
+ if (!selectedProfileId || !selectedProfileBotId)
379
+ return;
380
+ if (!confirm(tr('roles.confirmDeleteProfileEntry')))
381
+ return;
382
+ setProfileDeleting(true);
383
+ try {
384
+ await deleteProfileEntry(selectedProfileId, selectedProfileBotId);
385
+ if (!alive.current)
386
+ return;
387
+ setProfileEditingContent('');
388
+ const nextProfiles = await refreshProfiles();
389
+ if (!alive.current)
390
+ return;
391
+ const entries = await loadProfileEntries(selectedProfileId);
392
+ if (!alive.current)
393
+ return;
394
+ setProfileEntries(entries);
395
+ void refreshRoleContext(groups, nextProfiles);
396
+ }
397
+ finally {
398
+ if (alive.current)
399
+ setProfileDeleting(false);
400
+ }
401
+ }
402
+ function toggleApplyBot(botId, checked) {
403
+ setSelectedApplyBotIds(prev => {
404
+ const next = new Set(prev);
405
+ if (checked)
406
+ next.add(botId);
407
+ else
408
+ next.delete(botId);
409
+ return next;
410
+ });
411
+ }
412
+ async function runProfileApply(preview) {
413
+ if (!selectedProfileId)
414
+ return;
415
+ const groupId = selectedApplyGroupId ?? groups[0]?.chatId;
416
+ if (!groupId)
417
+ return;
418
+ const selected = [...selectedApplyBotIds];
419
+ if (selected.length === 0) {
420
+ setApplyStatus({ kind: 'text', text: tr('roles.applyPickBots') });
421
+ return;
422
+ }
423
+ setApplyStatus({ kind: 'text', text: '...' });
424
+ const results = await Promise.all(selected.map(larkAppId => applyRoleProfile({
425
+ profileId: selectedProfileId,
426
+ chatId: groupId,
427
+ larkAppId,
428
+ force: applyForce,
429
+ preview,
430
+ })));
431
+ if (!alive.current)
432
+ return;
433
+ setApplyStatus({ kind: 'results', preview, results });
434
+ if (!preview) {
435
+ const snapshot = await refreshGroups();
436
+ if (!alive.current)
437
+ return;
438
+ void refreshRoleContext(snapshot.groups, profiles);
439
+ }
440
+ }
441
+ const roleSaveDisabled = roleSaving || roleByteLen > MAX_ROLE_BYTES || editingContent.trim().length === 0;
442
+ const profileSaveDisabled = profileSaving || profileByteLen > MAX_ROLE_BYTES || profileEditingContent.trim().length === 0;
443
+ const isProfiles = props.tab === 'profiles';
444
+ const tabs = (_jsxs("nav", { className: "roles-subnav insight-tabs", role: "tablist", "aria-label": tr('roles.title'), children: [_jsx("a", { href: "#/roles", className: `itab${isProfiles ? '' : ' on'}`, role: "tab", "aria-selected": !isProfiles, children: tr('roles.tabGroups') }), _jsx("a", { href: "#/roles/profile", className: `itab${isProfiles ? ' on' : ''}`, role: "tab", "aria-selected": isProfiles, children: tr('roles.tabProfiles') })] }));
445
+ return (_jsxs("section", { className: "page roles-page", children: [_jsxs("div", { className: "page-heading roles-heading", children: [_jsxs("div", { children: [_jsx("p", { className: "eyebrow", children: tr('nav.roles') }), _jsx("h1", { children: tr('roles.title') })] }), _jsx("div", { className: "page-heading-actions", children: tabs })] }), _jsxs("div", { id: "roles-by-group-view", className: "roles-layout", hidden: isProfiles, children: [_jsxs("div", { className: "roles-tree-panel", children: [_jsxs("div", { className: "roles-tree-header dashboard-toolbar", children: [_jsx("input", { type: "search", id: "roles-search", placeholder: tr('roles.search'), value: groupsFilter, onChange: ev => setGroupsFilter(ev.target.value) }), _jsx(RefreshIconButton, { id: "roles-refresh", label: tr('roles.refresh'), onClick: () => void handleGroupRefresh() })] }), _jsx("div", { id: "roles-tree", className: "roles-tree", children: loadingTree ? _jsx(LoadingState, { label: tr('common.loading') }) : (_jsx(GroupsTree, { groups: filteredGroups, profiles: profiles, context: roleContext, contextLoaded: roleContextLoaded, expandedGroups: expandedGroups, selectedGroupId: selectedGroupId, selectedBotId: selectedBotId, tr: tr, onToggleGroup: groupId => setExpandedGroups(prev => toggleSet(prev, groupId)), onSelectBot: (groupId, botId) => void handleSelectBot(groupId, botId) })) })] }), _jsx("div", { className: "roles-editor-panel", children: !selectedGroupId || !selectedBotId ? (_jsx("div", { id: "roles-editor-empty", className: "roles-editor-empty", children: tr('roles.selectHint') })) : (_jsxs("div", { id: "roles-editor-form", className: "roles-editor-form", children: [_jsxs("div", { className: "roles-editor-head", children: [_jsxs("div", { children: [_jsxs("div", { className: "roles-editor-breadcrumb", children: [_jsx("span", { id: "roles-editor-group-name", children: selectedGroup?.name ?? selectedGroupId }), _jsx("span", { className: "roles-breadcrumb-sep", children: "\u203A" }), _jsx("span", { id: "roles-editor-bot-name", children: selectedBot?.botName ?? selectedBotId })] }), _jsx("div", { className: "roles-editor-meta", children: _jsxs("span", { id: "roles-editor-chat-id", className: "roles-editor-meta-line", children: [selectedGroupId, " \u00B7 ", selectedBotId] }) })] }), _jsxs("div", { className: "roles-editor-actions roles-editor-head-actions", children: [_jsx("button", { type: "button", id: "roles-delete", className: "danger", style: { display: selectedRole?.hasRole ? '' : 'none' }, disabled: roleDeleting, onClick: () => void handleDeleteRole(), children: roleDeleting ? '...' : tr('roles.delete') }), _jsx("button", { type: "button", id: "roles-save", className: "primary", disabled: roleSaveDisabled, onClick: () => void handleSaveRole(), children: roleSaving ? '...' : tr('roles.save') })] })] }), _jsxs("div", { className: "roles-editor-inject", children: [_jsx("span", { className: "roles-field-label", children: tr('roles.injectModeLabel') }), _jsx(DropdownMenu, { id: "roles-editor-inject-mode", className: "roles-inline-menu", ariaLabel: tr('roles.injectModeLabel'), disabled: injectSaving, label: editingInjectMode === 'once' ? tr('roles.injectModeOnce') : tr('roles.injectModeEvery'), value: editingInjectMode, options: [
446
+ { value: 'every', label: tr('roles.injectModeEvery') },
447
+ { value: 'once', label: tr('roles.injectModeOnce') },
448
+ ], onChange: mode => void handleInjectModeChange(mode === 'once' ? 'once' : 'every') }), _jsx("span", { className: "roles-editor-inject-hint", children: tr('roles.injectModeHint') }), _jsx(Flash, { flash: injectFlash })] }), _jsx("textarea", { id: "roles-editor-textarea", placeholder: tr('roles.editorPlaceholder'), rows: 14, value: editingContent, onChange: ev => setEditingContent(ev.target.value) }), _jsxs("div", { className: "roles-editor-footer", children: [_jsxs("span", { id: "roles-editor-bytecount", className: byteCountClass(roleByteLen), children: [roleByteLen, " / ", MAX_ROLE_BYTES, " bytes"] }), _jsx(Flash, { flash: roleFlash })] }), _jsx(RolePreview, { content: editingContent, tr: tr, id: "roles-preview" })] })) })] }), _jsxs("div", { id: "roles-profiles-view", className: "roles-layout roles-profiles-layout", hidden: !isProfiles, children: [_jsxs("div", { className: "roles-tree-panel", children: [_jsxs("div", { className: "roles-tree-header roles-profile-create dashboard-toolbar", children: [_jsx("input", { type: "text", id: "roles-profile-id", placeholder: tr('roles.profileIdPlaceholder'), maxLength: 64, ref: profileIdInputRef, onChange: ev => ev.currentTarget.setCustomValidity('') }), _jsx("button", { type: "button", id: "roles-profile-select", onClick: () => void handleOpenProfile(), children: tr('roles.openProfile') })] }), _jsxs("div", { className: "roles-tree-header dashboard-toolbar", children: [_jsx("input", { type: "search", id: "roles-profile-search", placeholder: tr('roles.profileSearch'), value: profileFilter, onChange: ev => setProfileFilter(ev.target.value) }), _jsx(RefreshIconButton, { id: "roles-profile-refresh", label: tr('roles.refresh'), onClick: () => void handleProfileRefresh() })] }), _jsx("div", { id: "roles-profile-list", className: "roles-tree", children: profileListLoading ? _jsx(LoadingState, { label: tr('common.loading') }) : (_jsx(ProfileList, { profiles: filteredProfiles, selectedProfileId: selectedProfileId, tr: tr, onSelect: profileId => void handleSelectProfile(profileId) })) })] }), _jsx("div", { className: "roles-editor-panel", children: !selectedProfileId ? (_jsx("div", { id: "roles-profile-empty", className: "roles-editor-empty", children: tr('roles.profileSelectHint') })) : (_jsxs("div", { id: "roles-profile-detail", className: "roles-editor-form roles-profile-detail", children: [_jsx("div", { className: "roles-profile-title", children: _jsxs("div", { children: [_jsxs("div", { className: "roles-editor-breadcrumb", children: [_jsx("span", { children: selectedProfileId }), selectedProfileBot ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "roles-breadcrumb-sep", children: "\u203A" }), _jsx("span", { children: selectedProfileBot.botName ?? selectedProfileBot.larkAppId })] })) : null] }), _jsx("div", { className: "roles-editor-meta-line", children: tr('roles.profileRuntimeHint') })] }) }), _jsxs("div", { className: "roles-profile-grid", children: [_jsxs("div", { className: "roles-profile-bots", children: [_jsx("div", { className: "roles-profile-section-title", children: tr('roles.profileBots') }), _jsx("div", { className: "roles-profile-bot-list", children: allBots.map(bot => {
449
+ const hasEntry = !!entryForBot(profileEntries, bot.larkAppId);
450
+ const selected = selectedProfileBotId === bot.larkAppId;
451
+ return (_jsxs("div", { className: `roles-bot-row roles-profile-bot-row ${selected ? 'selected' : ''}`, "data-profile-bot-id": bot.larkAppId, onClick: () => void handleSelectProfileBot(bot.larkAppId), children: [_jsx(BotAvatar, { bot: bot }), _jsxs("div", { className: "roles-bot-info", children: [_jsx("div", { className: "roles-bot-name", children: bot.botName ?? bot.larkAppId }), _jsx("div", { className: "roles-bot-id", children: bot.larkAppId })] }), _jsx("span", { className: `roles-badge ${hasEntry ? 'has-role' : 'no-role'}`, children: hasEntry ? tr('roles.configured') : tr('roles.unconfigured') })] }, bot.larkAppId));
452
+ }) })] }), _jsx("div", { className: "roles-profile-editor", children: selectedProfileBotId ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "roles-profile-editor-head", children: [_jsxs("span", { id: "roles-profile-bytecount", className: byteCountClass(profileByteLen), children: [profileByteLen, " / ", MAX_ROLE_BYTES, " bytes"] }), _jsxs("div", { className: "roles-editor-actions roles-editor-head-actions", children: [_jsx("button", { type: "button", id: "roles-profile-delete", className: "danger", style: { display: selectedProfileEntry ? '' : 'none' }, disabled: profileDeleting, onClick: () => void handleDeleteProfileEntry(), children: profileDeleting ? '...' : tr('roles.delete') }), _jsx("button", { type: "button", id: "roles-profile-save", className: "primary", disabled: profileSaveDisabled, onClick: () => void handleSaveProfileEntry(), children: profileSaving ? '...' : tr('roles.saveEntry') })] })] }), _jsx("textarea", { id: "roles-profile-textarea", placeholder: tr('roles.profileEditorPlaceholder'), rows: 12, value: profileEditingContent, onChange: ev => setProfileEditingContent(ev.target.value) }), _jsx("div", { className: "roles-editor-footer", children: _jsx(Flash, { flash: profileFlash }) }), _jsx(RolePreview, { content: profileEditingContent, tr: tr, id: "roles-profile-preview" })] })) : (_jsx("div", { className: "roles-editor-empty roles-profile-inline-empty", children: tr('roles.profileBotSelectHint') })) })] }), _jsxs("div", { className: "roles-profile-apply", children: [_jsx("div", { className: "roles-profile-section-title", children: tr('roles.applyToGroup') }), _jsxs("div", { className: "roles-profile-apply-controls", children: [_jsx(DropdownMenu, { id: "roles-profile-apply-group", className: "roles-apply-group-menu", ariaLabel: tr('roles.applyToGroup'), disabled: groups.length === 0, label: selectedApplyGroup?.name ?? selectedApplyGroupId ?? tr('roles.noChats'), value: selectedApplyGroupId ?? '', options: groups.map(group => ({
453
+ value: group.chatId,
454
+ label: group.name ?? group.chatId,
455
+ })), onChange: groupId => setSelectedApplyGroupId(groupId) }), _jsxs("label", { className: "roles-profile-force", children: [_jsx("input", { type: "checkbox", id: "roles-profile-apply-force", checked: applyForce, onChange: ev => setApplyForce(ev.target.checked) }), " ", tr('roles.applyForce')] })] }), _jsx("div", { id: "roles-profile-apply-bots", children: !selectedApplyGroup || selectedApplyBots.length === 0 ? (_jsx("div", { className: "roles-empty", children: tr('roles.noChats') })) : selectedApplyBots.map(bot => {
456
+ const hasEntry = !!entryForBot(profileEntries, bot.larkAppId);
457
+ return (_jsxs("label", { className: "checkbox-row roles-profile-apply-bot", children: [_jsx("input", { type: "checkbox", name: "profile-apply-bot", value: bot.larkAppId, checked: selectedApplyBotIds.has(bot.larkAppId), onChange: ev => toggleApplyBot(bot.larkAppId, ev.target.checked) }), _jsx("span", { children: bot.botName ?? bot.larkAppId }), _jsx("small", { children: hasEntry ? tr('roles.configured') : tr('roles.profileMissing') })] }, bot.larkAppId));
458
+ }) }), _jsxs("div", { className: "roles-editor-actions", children: [_jsx("button", { type: "button", id: "roles-profile-preview-apply", onClick: () => void runProfileApply(true), children: tr('roles.previewApply') }), _jsx("button", { type: "button", id: "roles-profile-apply", className: "primary", onClick: () => void runProfileApply(false), children: tr('roles.applyProfile') })] }), _jsx("div", { id: "roles-profile-apply-status", className: "roles-profile-status", children: _jsx(ApplyStatusView, { status: applyStatus, bots: allBots, tr: tr }) })] })] })) })] })] }));
459
+ }
460
+ function toggleSet(prev, value) {
461
+ const next = new Set(prev);
462
+ if (next.has(value))
463
+ next.delete(value);
464
+ else
465
+ next.add(value);
466
+ return next;
467
+ }
468
+ function byteCountClass(len) {
469
+ return `roles-bytecount ${len > ROLE_WARN_BYTES ? 'warn' : ''} ${len > MAX_ROLE_BYTES ? 'over' : ''}`;
470
+ }
471
+ function Flash(props) {
472
+ if (!props.flash)
473
+ return null;
474
+ return (_jsxs("span", { className: `roles-saved-flash ${props.flash.isError ? 'roles-save-error' : ''}`, children: [' ', props.flash.text] }));
475
+ }
476
+ function GroupsTree(props) {
477
+ const { tr } = props;
478
+ if (props.groups.length === 0)
479
+ return _jsx("div", { className: "roles-empty", children: tr('roles.noChats') });
480
+ return (_jsx(_Fragment, { children: props.groups.map(group => {
481
+ const expanded = props.expandedGroups.has(group.chatId);
482
+ const inChatBots = group.memberBots.filter(bot => bot.inChat);
483
+ const roleCount = botRoleCount(group);
484
+ const totalInChat = botInChatCount(group);
485
+ return (_jsxs("div", { className: "roles-group-section", children: [_jsxs("div", { className: `roles-group-row ${expanded ? 'expanded' : ''} ${props.selectedGroupId === group.chatId && !props.selectedBotId ? 'selected' : ''}`, "data-group-id": group.chatId, onClick: () => props.onToggleGroup(group.chatId), children: [_jsx("span", { className: "roles-group-arrow", children: expanded ? '▾' : '▸' }), _jsx("span", { className: "roles-group-icon", "aria-hidden": "true", children: _jsxs("svg", { viewBox: "0 0 16 16", children: [_jsx("circle", { cx: "5.6", cy: "5.8", r: "2.4" }), _jsx("path", { d: "M1.8 13.2c.5-2.4 2-3.6 3.8-3.6s3.3 1.2 3.8 3.6" }), _jsx("circle", { cx: "11", cy: "6.8", r: "1.9" }), _jsx("path", { d: "M9.8 12.6c.4-1.7 1.5-2.6 2.8-2.6 1 0 1.9.5 2.4 1.6" })] }) }), _jsxs("div", { className: "roles-group-info", children: [_jsx("div", { className: "roles-group-name", children: group.name ?? group.chatId }), _jsxs("div", { className: "roles-group-meta", children: [roleCount, "/", totalInChat, " ", tr('roles.botsWithRoles')] }), _jsx(GroupProfileStatus, { group: group, profiles: props.profiles, context: props.context, loaded: props.contextLoaded, tr: tr })] }), _jsx("span", { className: "roles-group-chevron" })] }), _jsx("div", { className: "roles-bot-list", children: expanded ? inChatBots.map(bot => {
486
+ const selected = props.selectedGroupId === group.chatId && props.selectedBotId === bot.larkAppId;
487
+ return (_jsxs("div", { className: `roles-bot-row ${selected ? 'selected' : ''}`, "data-group-id": group.chatId, "data-bot-id": bot.larkAppId, onClick: ev => {
488
+ ev.stopPropagation();
489
+ props.onSelectBot(group.chatId, bot.larkAppId);
490
+ }, children: [_jsx("span", { className: "roles-bot-indent" }), _jsx(BotAvatar, { bot: bot }), _jsxs("div", { className: "roles-bot-info", children: [_jsx("div", { className: "roles-bot-name", children: bot.botName }), _jsx("div", { className: "roles-bot-id", children: bot.larkAppId })] }), _jsx("span", { className: `roles-badge ${bot.hasRole ? 'has-role' : 'no-role'}`, children: bot.hasRole ? tr('roles.configured') : tr('roles.unconfigured') })] }, bot.larkAppId));
491
+ }) : null })] }, group.chatId));
492
+ }) }));
493
+ }
494
+ function GroupProfileStatus(props) {
495
+ const { group, profiles, context, loaded, tr } = props;
496
+ if (!profiles.length || !loaded)
497
+ return null;
498
+ const rolesByBot = new Map();
499
+ for (const bot of group.memberBots) {
500
+ if (!bot.inChat)
501
+ continue;
502
+ rolesByBot.set(bot.larkAppId, context.effectiveRolesByBot.get(roleKey(bot.larkAppId, group.chatId)) ?? null);
503
+ }
504
+ if (!hasExplicitChatRole(rolesByBot))
505
+ return null;
506
+ const best = summarizeGroupProfileMatches(group.memberBots, profiles, context.entriesByProfile, rolesByBot)[0];
507
+ if (!best)
508
+ return _jsx("div", { className: "roles-profile-match muted", children: tr('groups.profileStatusUnmatched') });
509
+ const key = best.kind === 'full' ? 'groups.profileStatusFullChat' : 'groups.profileStatusPartial';
510
+ return (_jsx("div", { className: `roles-profile-match ${best.kind}`, children: tr(key, {
511
+ name: best.profileId,
512
+ matched: best.matched,
513
+ total: best.total,
514
+ chat: best.chatMatched,
515
+ }) }));
516
+ }
517
+ function RolePreview(props) {
518
+ return (_jsx("div", { id: props.id, className: "roles-preview", children: props.content.trim() ? (_jsxs(_Fragment, { children: [_jsx("strong", { children: props.tr('roles.preview') }), _jsx("pre", { children: props.content })] })) : (_jsx("small", { children: props.tr('roles.previewEmpty') })) }));
519
+ }
520
+ function ProfileList(props) {
521
+ const { tr } = props;
522
+ if (props.profiles.length === 0)
523
+ return _jsx("div", { className: "roles-empty", children: tr('roles.profileEmpty') });
524
+ return (_jsx(_Fragment, { children: props.profiles.map(profile => {
525
+ const selected = props.selectedProfileId === profile.profileId;
526
+ const hasAnyLocal = (profile.botEntries ?? []).some(entry => entry.hasEntry);
527
+ return (_jsxs("div", { className: `roles-profile-row ${selected ? 'selected' : ''}`, "data-profile-id": profile.profileId, onClick: () => props.onSelect(profile.profileId), children: [_jsxs("div", { className: "roles-profile-row-main", children: [_jsx("div", { className: "roles-profile-name", children: profile.profileId }), _jsxs("div", { className: "roles-group-meta", children: [profile.entryCount, " ", tr('roles.profileEntries')] })] }), _jsx("span", { className: `roles-badge ${hasAnyLocal ? 'has-role' : 'no-role'}`, children: hasAnyLocal ? tr('roles.configured') : tr('roles.profileMissing') })] }, profile.profileId));
528
+ }) }));
529
+ }
530
+ function ApplyStatusView(props) {
531
+ const { status, bots, tr } = props;
532
+ if (status.kind === 'idle')
533
+ return null;
534
+ if (status.kind === 'text')
535
+ return _jsx(_Fragment, { children: status.text });
536
+ return (_jsx(_Fragment, { children: status.results.map(result => {
537
+ const bot = bots.find(b => b.larkAppId === result.larkAppId);
538
+ const label = bot?.botName ?? result.larkAppId;
539
+ const outcome = result.ok
540
+ ? (status.preview ? (result.wouldRefuse ? tr('roles.applyWouldRefuse') : tr('roles.applyPreviewOk')) : tr('roles.applyOk'))
541
+ : `${tr('roles.applyFailed')}: ${String(result.error ?? `HTTP ${result.status}`)}`;
542
+ return _jsxs("div", { children: [label, ": ", outcome] }, result.larkAppId);
543
+ }) }));
19
544
  }
20
545
  export function renderRolesPage(root) {
21
546
  return mountReactPage(root, _jsx(RolesPage, { tab: "groups" }));