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,13 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
- import { botAvatarHtml, loadingHtml } from './ui.js';
3
+ import { createPortal } from 'react-dom';
4
+ import { FieldTitle, Html, LoadingState, RefreshIconButton, SectionHeader } from './dashboard-components.js';
5
+ import { botAvatarHtml } from './ui.js';
4
6
  import { useT } from './react-hooks.js';
5
7
  import { mountReactPage } from './react-mount.js';
6
8
  const INSTALLED_SKILLS_ROWS_PER_PAGE = 2;
7
- function Html(props) {
8
- const Tag = props.as ?? 'span';
9
- return _jsx(Tag, { style: { display: 'contents' }, dangerouslySetInnerHTML: { __html: props.html } });
10
- }
11
9
  function nativeLibraryLabel(path, tr) {
12
10
  const p = String(path ?? '').replace(/\\/g, '/');
13
11
  if (p.includes('/.codex/skills/'))
@@ -76,6 +74,10 @@ async function jsonRequest(url, init) {
76
74
  function statusClass(status) {
77
75
  return `oncall-status${status ? ` ${status.ok ? 'hint-ok' : 'hint-warn-inline'}` : ''}`;
78
76
  }
77
+ function SkillSegmented(props) {
78
+ const current = props.options.find(option => option.value === props.value);
79
+ return (_jsxs("div", { className: "skills-segmented-control", children: [_jsx("div", { className: "segmented skills-segmented", role: "group", children: props.options.map(option => (_jsx("button", { type: "button", className: props.value === option.value ? 'active' : '', "aria-pressed": props.value === option.value ? 'true' : 'false', title: typeof option.help === 'string' ? option.help : undefined, disabled: props.disabled, onClick: () => props.onChange(option.value), children: option.label }, option.value))) }), current?.help ? _jsx("span", { className: "skills-setting-hint", children: current.help }) : null] }));
80
+ }
79
81
  export function SkillsInstallPanel(props) {
80
82
  const tr = useT();
81
83
  const selectionDialogRef = useRef(null);
@@ -97,14 +99,13 @@ export function SkillsInstallPanel(props) {
97
99
  dialog.close();
98
100
  }
99
101
  }, [props.installSelectionOpen, candidates.length]);
100
- return (_jsxs("article", { className: "bd-card skills-install-panel", children: [_jsxs("div", { className: "skills-install-title", children: [_jsx("h3", { className: "bd-section-title", children: tr('skills.install') }), _jsxs("span", { className: "skills-help-tip", children: [_jsx("button", { type: "button", className: "help-icon-button skills-help-button", "aria-label": tr('skills.installInfoLabel'), children: "?" }), _jsx("span", { className: "skills-help-popover", role: "tooltip", children: tr('skills.installInfo') })] })] }), _jsxs("div", { className: "skills-install-grid", children: [_jsxs("label", { className: "skills-source-label", children: [_jsx("span", { children: tr('skills.source') }), _jsx("div", { className: "skills-source-control", children: _jsx("input", { type: "text", "data-install": "source", "aria-label": tr('skills.source'), placeholder: tr('skills.sourcePlaceholder'), value: props.installSource, onChange: e => props.onInstallSourceChange(e.currentTarget.value) }) })] }), _jsxs("div", { className: "bd-section-note skills-install-note", children: [_jsxs("span", { children: [_jsx("strong", { children: tr('skills.sourceHelpRemoteLabel') }), tr('skills.sourceHelpRemote')] }), _jsxs("span", { children: [_jsx("strong", { children: tr('skills.sourceHelpLocalLabel') }), tr('skills.sourceHelpLocal')] })] }), _jsxs("div", { className: "skills-install-action-row", children: [_jsxs("details", { className: "skills-advanced-options", "data-skills-advanced": true, open: false, children: [_jsxs("summary", { children: [_jsx("span", { className: "skills-advanced-marker", "aria-hidden": "true" }), _jsx("span", { children: tr('skills.advanced') })] }), _jsxs("div", { className: "skills-advanced-fields", children: [_jsxs("label", { className: "skills-install-field-wide", children: [_jsx("span", { children: tr('skills.path') }), _jsx("input", { type: "text", "data-install": "path", placeholder: tr('skills.pathPlaceholder'), value: props.installPath, onChange: e => props.onInstallPathChange(e.currentTarget.value) })] }), _jsxs("label", { className: "skills-install-field-wide", children: [_jsx("span", { children: tr('skills.ref') }), _jsx("input", { type: "text", "data-install": "ref", placeholder: tr('skills.refPlaceholder'), value: props.installRef, onChange: e => props.onInstallRefChange(e.currentTarget.value) })] })] })] }), _jsx("div", { className: "skills-install-actions", children: _jsx("button", { type: "button", className: "primary", "data-action": "install", disabled: busy, onClick: () => props.onInstall(), children: props.installDiscovering ? tr('skills.scanning') : props.installBusy ? tr('skills.jobRunning') : tr('skills.installSubmit') }) })] }), _jsxs("div", { className: "skills-local-discovery-panel", children: [_jsxs("div", { children: [_jsx("strong", { children: tr('skills.localDiscoverTitle') }), _jsx("span", { children: tr('skills.localDiscoverHelp') })] }), _jsx("button", { type: "button", "data-action": "open-native-skill-discovery", onClick: () => props.onOpenNativeDiscovery(), children: tr('skills.localDiscover') })] })] }), _jsx("div", { className: "actions", children: _jsx("span", { className: statusClass(props.installStatus), "data-skills-status": true, children: props.installStatus?.text ?? '' }) }), _jsx("dialog", { className: "skills-discovery-dialog skills-install-selection-dialog", "data-install-selection-dialog": true, ref: selectionDialogRef, onClose: () => props.onCloseInstallSelection?.(), children: _jsxs("article", { children: [_jsxs("header", { children: [_jsx("h3", { children: tr('skills.installSelectionTitle') }), _jsx("p", { children: tr('skills.installSelectionHelp', { count: candidates.length }) })] }), _jsx("div", { className: "skills-discovery-body skills-install-selection-body", children: _jsxs("div", { className: "skills-candidate-list", "data-install-candidates": true, children: [_jsxs("div", { className: "skills-candidate-list-head", children: [_jsx("span", { children: tr('skills.scanFound', { count: candidates.length }) }), props.onSelectAllInstallSkills ? (_jsx("button", { type: "button", "data-action": "toggle-all-source-skills", disabled: props.installBusy, onClick: () => props.onSelectAllInstallSkills?.(!allSelected), children: allSelected ? tr('skills.discoverClearSelection') : tr('skills.discoverSelectAll') })) : null] }), candidates.map(candidate => (_jsxs("label", { className: "skills-candidate-row", children: [_jsx("input", { type: "checkbox", checked: selectedInstallSkills.has(candidate.name), disabled: props.installBusy, onChange: () => props.onToggleInstallSkill?.(candidate.name) }), _jsxs("span", { children: [_jsx("strong", { children: candidate.name }), _jsxs("small", { children: [candidate.path, candidate.description ? ` · ${candidate.description}` : ''] })] })] }, `${candidate.name}:${candidate.path}`)))] }) }), _jsxs("footer", { className: "actions", children: [_jsx("button", { type: "button", "data-action": "close-install-selection", disabled: props.installBusy, onClick: () => props.onCloseInstallSelection?.(), children: tr('skills.installSelectionCancel') }), _jsx("button", { type: "button", className: "primary", "data-action": "confirm-install-selection", disabled: props.installBusy || selectedInstallSkills.size === 0, onClick: () => props.onConfirmInstallSelection?.(), children: props.installBusy ? tr('skills.jobRunning') : tr('skills.installSelected') })] })] }) })] }));
102
+ return (_jsxs("article", { className: "bd-card skills-install-panel", children: [props.showTitle === false ? null : _jsx("div", { className: "skills-install-title", children: _jsx("h3", { className: "bd-section-title", children: _jsx(FieldTitle, { help: tr('skills.installInfo'), helpLabel: tr('skills.installInfoLabel'), children: tr('skills.install') }) }) }), _jsxs("div", { className: "skills-install-grid", children: [_jsxs("label", { className: "skills-source-label", children: [_jsx(FieldTitle, { help: (_jsxs("span", { className: "skills-source-help", children: [_jsxs("span", { children: [_jsx("strong", { children: tr('skills.sourceHelpRemoteLabel') }), tr('skills.sourceHelpRemote')] }), _jsxs("span", { children: [_jsx("strong", { children: tr('skills.sourceHelpLocalLabel') }), tr('skills.sourceHelpLocal')] }), _jsxs("span", { children: [_jsx("strong", { children: tr('skills.sourceHelpAgentbuddyLabel') }), tr('skills.sourceHelpAgentbuddy')] })] })), helpLabel: tr('skills.source'), children: tr('skills.source') }), _jsx("div", { className: "skills-source-control", children: _jsx("input", { type: "text", "data-install": "source", "aria-label": tr('skills.source'), placeholder: tr('skills.sourcePlaceholder'), value: props.installSource, onChange: e => props.onInstallSourceChange(e.currentTarget.value) }) })] }), _jsxs("label", { className: "skills-install-field-wide skills-install-path-field", children: [_jsx("span", { children: tr('skills.path') }), _jsx("input", { type: "text", "data-install": "path", placeholder: tr('skills.pathPlaceholder'), value: props.installPath, onChange: e => props.onInstallPathChange(e.currentTarget.value) })] }), _jsxs("label", { className: "skills-install-field-wide skills-install-ref-field", children: [_jsx("span", { children: tr('skills.ref') }), _jsx("input", { type: "text", "data-install": "ref", placeholder: tr('skills.refPlaceholder'), value: props.installRef, onChange: e => props.onInstallRefChange(e.currentTarget.value) })] }), _jsx("div", { className: "skills-install-actions", children: _jsx("button", { type: "button", "data-action": "install", disabled: busy, onClick: () => props.onInstall(), children: props.installDiscovering ? tr('skills.scanning') : props.installBusy ? tr('skills.jobRunning') : tr('skills.installSubmit') }) }), _jsx("div", { className: "skills-install-bottom-row", children: _jsxs("div", { className: "skills-local-discovery-panel", children: [_jsxs("div", { children: [_jsx("strong", { children: tr('skills.localDiscoverTitle') }), _jsx("span", { children: tr('skills.localDiscoverHelp') })] }), _jsx("button", { type: "button", "data-action": "open-native-skill-discovery", onClick: () => props.onOpenNativeDiscovery(), children: tr('skills.localDiscover') })] }) })] }), props.installStatus ? (_jsx("div", { className: "actions skills-install-status-row", children: _jsx("span", { className: statusClass(props.installStatus), "data-skills-status": true, children: props.installStatus.text }) })) : null, _jsx("dialog", { className: "skills-discovery-dialog skills-install-selection-dialog", "data-install-selection-dialog": true, ref: selectionDialogRef, onClose: () => props.onCloseInstallSelection?.(), children: _jsxs("article", { children: [_jsxs("header", { children: [_jsx("h3", { children: tr('skills.installSelectionTitle') }), _jsx("p", { children: tr('skills.installSelectionHelp', { count: candidates.length }) })] }), _jsx("div", { className: "skills-discovery-body skills-install-selection-body", children: _jsxs("div", { className: "skills-candidate-list", "data-install-candidates": true, children: [_jsxs("div", { className: "skills-candidate-list-head", children: [_jsx("span", { children: tr('skills.scanFound', { count: candidates.length }) }), props.onSelectAllInstallSkills ? (_jsx("button", { type: "button", "data-action": "toggle-all-source-skills", disabled: props.installBusy, onClick: () => props.onSelectAllInstallSkills?.(!allSelected), children: allSelected ? tr('skills.discoverClearSelection') : tr('skills.discoverSelectAll') })) : null] }), candidates.map(candidate => (_jsxs("label", { className: "skills-candidate-row", children: [_jsx("input", { type: "checkbox", checked: selectedInstallSkills.has(candidate.name), disabled: props.installBusy, onChange: () => props.onToggleInstallSkill?.(candidate.name) }), _jsxs("span", { children: [_jsx("strong", { children: candidate.name }), _jsxs("small", { children: [candidate.path, candidate.description ? ` · ${candidate.description}` : ''] })] })] }, `${candidate.name}:${candidate.path}`)))] }) }), _jsxs("footer", { className: "actions", children: [_jsx("button", { type: "button", "data-action": "close-install-selection", disabled: props.installBusy, onClick: () => props.onCloseInstallSelection?.(), children: tr('skills.installSelectionCancel') }), _jsx("button", { type: "button", className: "primary", "data-action": "confirm-install-selection", disabled: props.installBusy || selectedInstallSkills.size === 0, onClick: () => props.onConfirmInstallSelection?.(), children: props.installBusy ? tr('skills.jobRunning') : tr('skills.installSelected') })] })] }) })] }));
101
103
  }
102
104
  function SkillsPage() {
103
105
  const tr = useT();
104
106
  const mountedRef = useRef(true);
105
107
  const timersRef = useRef(new Set());
106
108
  const discoveryDialogRef = useRef(null);
107
- const botGridRef = useRef(null);
108
109
  const [skills, setSkills] = useState([]);
109
110
  const [nativeSkillGroups, setNativeSkillGroups] = useState([]);
110
111
  const [bots, setBots] = useState([]);
@@ -304,17 +305,39 @@ function SkillsPage() {
304
305
  body: JSON.stringify(sourceRequestBody()),
305
306
  });
306
307
  if (!mountedRef.current)
307
- return [];
308
+ return { skills: [], directInstall: false };
309
+ const directInstall = body.discovery?.directInstall === true;
308
310
  const skills = Array.isArray(body.discovery?.skills) ? body.discovery.skills : [];
309
311
  setInstallCandidates(skills);
310
312
  setSelectedInstallSkills(new Set(skills.map(skill => skill.name)));
311
- return skills;
313
+ return { skills, directInstall };
312
314
  }
313
315
  finally {
314
316
  if (mountedRef.current)
315
317
  setInstallDiscovering(false);
316
318
  }
317
319
  }
320
+ // Translate the backend's terse install error codes into actionable messages.
321
+ // agentbuddy runs on the deploy host, so its failures (missing CLI, not logged
322
+ // in) need host-side guidance the operator can act on. Non-agentbuddy codes
323
+ // fall through unchanged.
324
+ function mapInstallError(raw) {
325
+ const msg = raw || '';
326
+ if (msg.startsWith('agentbuddy_not_found'))
327
+ return tr('skills.agentbuddyNotFound');
328
+ if (msg.startsWith('agentbuddy_command_failed')) {
329
+ return /login|credential|unauthor|not logged|401|403/i.test(msg)
330
+ ? tr('skills.agentbuddyNeedsLogin')
331
+ : tr('skills.agentbuddyCommandFailed');
332
+ }
333
+ if (msg.startsWith('agentbuddy_clear_telemetry_failed') || msg.startsWith('agentbuddy_telemetry_not_stripped'))
334
+ return tr('skills.agentbuddyTelemetryFailed');
335
+ if (msg.startsWith('agentbuddy_no_skill_produced'))
336
+ return tr('skills.agentbuddyNoSkill');
337
+ if (msg.startsWith('invalid_agentbuddy'))
338
+ return tr('skills.agentbuddyInvalid');
339
+ return msg;
340
+ }
318
341
  async function submitSkillInstall(skillNames) {
319
342
  setInstallBusy(true);
320
343
  try {
@@ -330,7 +353,7 @@ function SkillsPage() {
330
353
  }
331
354
  catch (err) {
332
355
  if (mountedRef.current)
333
- setInstallStatus({ text: `${tr('skills.failed')}: ${err?.message ?? err}`, ok: false });
356
+ setInstallStatus({ text: `${tr('skills.failed')}: ${mapInstallError(err?.message ?? String(err))}`, ok: false });
334
357
  }
335
358
  finally {
336
359
  if (mountedRef.current)
@@ -357,9 +380,17 @@ function SkillsPage() {
357
380
  }
358
381
  try {
359
382
  setInstallSelectionOpen(false);
360
- const skills = await discoverInstallCandidates();
383
+ const { skills, directInstall } = await discoverInstallCandidates();
361
384
  if (!mountedRef.current)
362
385
  return;
386
+ // agentbuddy sources — a pasted `agentbuddy:<id>` OR a marketplace URL the
387
+ // backend recognized — resolve their own skill set, so install directly
388
+ // (no candidate selection). The server decides this so the client needn't
389
+ // know the identifier prefix or the configured marketplace hosts.
390
+ if (directInstall) {
391
+ await submitSkillInstall();
392
+ return;
393
+ }
363
394
  if (skills.length === 0) {
364
395
  setInstallStatus({ text: tr('skills.scanEmpty'), ok: false });
365
396
  return;
@@ -373,7 +404,7 @@ function SkillsPage() {
373
404
  }
374
405
  catch (err) {
375
406
  if (mountedRef.current)
376
- setInstallStatus({ text: `${tr('skills.failed')}: ${err?.message ?? err}`, ok: false });
407
+ setInstallStatus({ text: `${tr('skills.failed')}: ${mapInstallError(err?.message ?? String(err))}`, ok: false });
377
408
  }
378
409
  }
379
410
  async function confirmInstallSelection() {
@@ -406,7 +437,7 @@ function SkillsPage() {
406
437
  }
407
438
  catch (err) {
408
439
  if (mountedRef.current)
409
- setInstallStatus({ text: `${tr('skills.failed')}: ${err?.message ?? err}`, ok: false });
440
+ setInstallStatus({ text: `${tr('skills.failed')}: ${mapInstallError(err?.message ?? String(err))}`, ok: false });
410
441
  }
411
442
  finally {
412
443
  if (mountedRef.current)
@@ -428,7 +459,7 @@ function SkillsPage() {
428
459
  }
429
460
  catch (err) {
430
461
  if (mountedRef.current)
431
- window.alert(`${tr('skills.failed')}: ${err?.message ?? err}`);
462
+ window.alert(`${tr('skills.failed')}: ${mapInstallError(err?.message ?? String(err))}`);
432
463
  }
433
464
  finally {
434
465
  if (mountedRef.current)
@@ -450,22 +481,13 @@ function SkillsPage() {
450
481
  }
451
482
  catch (err) {
452
483
  if (mountedRef.current)
453
- window.alert(`${tr('skills.failed')}: ${err?.message ?? err}`);
484
+ window.alert(`${tr('skills.failed')}: ${mapInstallError(err?.message ?? String(err))}`);
454
485
  }
455
486
  finally {
456
487
  if (mountedRef.current)
457
488
  setGlobalBusy(null);
458
489
  }
459
490
  }
460
- function scrollBots(dir) {
461
- const grid = botGridRef.current;
462
- const card = grid?.querySelector('.skills-bot-card');
463
- if (!grid || !card)
464
- return;
465
- const style = window.getComputedStyle(grid);
466
- const gap = Number.parseFloat(style.columnGap || style.gap || '0') || 0;
467
- grid.scrollBy({ left: dir * (card.getBoundingClientRect().width + gap), behavior: 'smooth' });
468
- }
469
491
  async function updateSkill(name) {
470
492
  setSkillBusy(`${name}:update`);
471
493
  try {
@@ -476,7 +498,7 @@ function SkillsPage() {
476
498
  }
477
499
  catch (err) {
478
500
  if (mountedRef.current)
479
- window.alert(`${tr('skills.failed')}: ${err?.message ?? err}`);
501
+ window.alert(`${tr('skills.failed')}: ${mapInstallError(err?.message ?? String(err))}`);
480
502
  }
481
503
  finally {
482
504
  if (mountedRef.current)
@@ -519,33 +541,41 @@ function SkillsPage() {
519
541
  return;
520
542
  }
521
543
  }
522
- window.alert(`${tr('skills.failed')}: ${err?.message ?? err}`);
544
+ window.alert(`${tr('skills.failed')}: ${mapInstallError(err?.message ?? String(err))}`);
523
545
  }
524
546
  finally {
525
547
  if (mountedRef.current)
526
548
  setSkillBusy(null);
527
549
  }
528
550
  }
529
- async function updateBotSkill(appId, action, name) {
530
- const busyKey = `${appId}:${action}:${name}`;
551
+ async function setBotSkills(appId, names) {
552
+ const busyKey = `${appId}:set`;
531
553
  setBotBusy(busyKey);
532
554
  setBotStatuses(statuses => ({ ...statuses, [appId]: null }));
533
555
  try {
534
556
  const body = await jsonRequest(`/api/bots/${encodeURIComponent(appId)}/skills`, {
535
557
  method: 'PUT',
536
- body: JSON.stringify({ action, name }),
558
+ body: JSON.stringify({
559
+ action: 'set',
560
+ policy: names.length > 0 ? { include: names.map(name => `skill:${name}`) } : null,
561
+ }),
537
562
  });
538
563
  if (!mountedRef.current)
539
564
  return;
540
565
  setBots(rows => rows.map(bot => bot.larkAppId === appId ? { ...bot, skills: body.skills ?? null } : bot));
566
+ setBotStatuses(statuses => ({
567
+ ...statuses,
568
+ [appId]: { text: tr('skills.policySaved'), ok: true },
569
+ }));
541
570
  }
542
571
  catch (err) {
543
572
  if (mountedRef.current) {
544
573
  setBotStatuses(statuses => ({
545
574
  ...statuses,
546
- [appId]: { text: `${tr('skills.failed')}: ${err?.message ?? err}`, ok: false },
575
+ [appId]: { text: `${tr('skills.failed')}: ${mapInstallError(err?.message ?? String(err))}`, ok: false },
547
576
  }));
548
577
  }
578
+ throw err;
549
579
  }
550
580
  finally {
551
581
  if (mountedRef.current)
@@ -554,80 +584,192 @@ function SkillsPage() {
554
584
  }
555
585
  const configuredBotCount = bots.filter(bot => policyConfigured(bot.skills)).length;
556
586
  const attachedSkillRefCount = bots.reduce((sum, bot) => sum + policyReferenceCount(bot.skills), 0);
557
- const body = loading
558
- ? _jsx(Html, { html: loadingHtml(), as: "div" })
559
- : loadError
560
- ? _jsx("p", { className: "hint-warn", children: loadError })
561
- : (_jsxs("div", { className: "skills-page-grid", children: [_jsxs("aside", { className: "skills-side-rail", children: [_jsxs("article", { className: "bd-card skills-defaults-panel", children: [_jsx("h3", { className: "bd-section-title", children: tr('skills.globalDefaults') }), _jsxs("div", { className: "skills-control-block", children: [_jsx("span", { className: "skills-control-label", children: tr('skills.globalProject') }), _jsx("div", { className: "skills-choice-group skills-choice-group-compact skills-project-group", children: [
562
- ['off', tr('skills.globalProjectOff'), tr('skills.globalProjectOffHelp')],
563
- ['all', tr('skills.globalProjectAll'), tr('skills.globalProjectAllHelp')],
564
- ].map(([value, label, help]) => (_jsxs("button", { type: "button", className: `skills-choice${trustProjectSkills === value ? ' selected' : ''}`, "data-global-project-value": value, "aria-pressed": trustProjectSkills === value ? 'true' : 'false', disabled: globalBusy === 'project', onClick: () => void updateGlobalProject(value), children: [_jsx("strong", { children: label }), _jsx("small", { children: help })] }, value))) })] }), _jsxs("div", { className: "skills-control-block", children: [_jsx("span", { className: "skills-control-label", children: tr('skills.globalDelivery') }), _jsx("div", { className: "skills-choice-group skills-delivery-group", children: [
565
- ['auto', tr('skills.deliveryAuto'), tr('skills.deliveryAutoHelp')],
566
- ['prompt', tr('skills.deliveryPrompt'), tr('skills.deliveryPromptHelp')],
567
- ['native', tr('skills.deliveryNative'), tr('skills.deliveryNativeHelp')],
568
- ].map(([value, label, help]) => (_jsxs("button", { type: "button", className: `skills-choice${delivery === value ? ' selected' : ''}`, "data-global-delivery-value": value, "aria-pressed": delivery === value ? 'true' : 'false', disabled: globalBusy === 'delivery', onClick: () => void updateGlobalDelivery(value), children: [_jsx("strong", { children: label }), _jsx("small", { children: help })] }, value))) })] })] }), _jsx(SkillsInstallPanel, { installSource: installSource, installPath: installPath, installRef: installRef, installStatus: installStatus, installBusy: installBusy, installDiscovering: installDiscovering, installSelectionOpen: installSelectionOpen, installCandidates: installCandidates, selectedInstallSkills: selectedInstallSkills, onInstallSourceChange: (value) => {
569
- setInstallSource(value);
570
- clearInstallDiscovery();
571
- }, onInstallPathChange: (value) => {
572
- setInstallPath(value);
573
- clearInstallDiscovery();
574
- }, onInstallRefChange: (value) => {
575
- setInstallRef(value);
576
- clearInstallDiscovery();
577
- }, onToggleInstallSkill: toggleInstallCandidate, onSelectAllInstallSkills: selectAllInstallCandidates, onConfirmInstallSelection: () => void confirmInstallSelection(), onCloseInstallSelection: () => setInstallSelectionOpen(false), onInstall: () => void installSkill(), onOpenNativeDiscovery: () => setDiscoveryOpen(true) })] }), _jsxs("section", { className: "skills-main-panel", children: [_jsxs("section", { className: "skills-overview", children: [_jsxs("div", { className: "skills-overview-copy", children: [_jsx("h2", { children: tr('skills.overviewTitle') }), _jsx("p", { children: tr('skills.overviewBody') })] }), _jsxs("div", { className: "skills-metric-strip", children: [_jsxs("span", { children: [_jsx("small", { children: tr('skills.metricInstalled') }), _jsx("strong", { children: skills.length })] }), _jsxs("span", { children: [_jsx("small", { children: tr('skills.metricBots') }), _jsxs("strong", { children: [configuredBotCount, "/", bots.length] })] }), _jsxs("span", { children: [_jsx("small", { children: tr('skills.metricAttached') }), _jsx("strong", { children: attachedSkillRefCount })] })] })] }), _jsxs("section", { className: "skills-bots-panel", children: [_jsxs("div", { className: "skills-section-head skills-section-head-row", children: [_jsxs("div", { children: [_jsx("h2", { children: tr('skills.bots') }), _jsx("p", { children: tr('skills.botsHelp') })] }), bots.length > 3 ? (_jsxs("div", { className: "skills-bot-rail-actions", children: [_jsx("button", { type: "button", className: "skills-rail-button", "data-action": "scroll-bots", "data-dir": "-1", "aria-label": tr('skills.scrollBotsPrev'), title: tr('skills.scrollBotsPrev'), onClick: () => scrollBots(-1), children: "\u2039" }), _jsx("span", { className: "skills-count-pill", children: tr('skills.botCount', { count: bots.length }) }), _jsx("button", { type: "button", className: "skills-rail-button", "data-action": "scroll-bots", "data-dir": "1", "aria-label": tr('skills.scrollBotsNext'), title: tr('skills.scrollBotsNext'), onClick: () => scrollBots(1), children: "\u203A" })] })) : _jsx("span", { className: "skills-count-pill", children: tr('skills.botCount', { count: bots.length }) })] }), _jsx("div", { className: "skills-bot-grid", ref: botGridRef, children: bots.map(bot => (_jsx(BotPolicyCard, { bot: bot, installedNames: installedNames, skills: skills, status: botStatuses[bot.larkAppId] ?? null, busyKey: botBusy, onUpdate: updateBotSkill }, bot.larkAppId))) })] }), _jsxs("section", { className: "bd-card skills-installed-panel", children: [_jsxs("div", { className: "skills-section-head skills-section-head-row", children: [_jsxs("div", { children: [_jsx("h2", { children: tr('skills.installed') }), _jsx("p", { children: tr('skills.installedHelp') })] }), installedPageCount <= 1 ? (_jsx("span", { className: "skills-count-pill", children: tr('skills.skillCount', { count: skills.length }) })) : (_jsxs("div", { className: "skills-installed-toolbar", children: [_jsx("span", { className: "skills-count-pill", children: tr('skills.skillCount', { count: skills.length }) }), _jsxs("div", { className: "skills-pager", children: [_jsx("button", { type: "button", className: "skills-pager-button", "data-action": "page-installed-skills", "data-dir": "-1", "aria-label": tr('skills.prevPage'), title: tr('skills.prevPage'), disabled: installedSkillsPage === 0, onClick: () => setInstalledSkillsPage(page => Math.max(0, page - 1)), children: "\u2039" }), _jsx("span", { children: tr('skills.pageStatus', { page: installedSkillsPage + 1, pages: installedPageCount }) }), _jsx("button", { type: "button", className: "skills-pager-button", "data-action": "page-installed-skills", "data-dir": "1", "aria-label": tr('skills.nextPage'), title: tr('skills.nextPage'), disabled: installedSkillsPage >= installedPageCount - 1, onClick: () => setInstalledSkillsPage(page => Math.min(installedPageCount - 1, page + 1)), children: "\u203A" })] })] }))] }), skills.length === 0 ? _jsx("p", { className: "empty", children: tr('skills.empty') }) : (_jsx("div", { className: "skills-list", children: visibleSkills.map(skill => (_jsxs("article", { className: "skills-row skills-installed-card", "data-skill": skill.name, children: [_jsxs("div", { className: "skills-row-body", children: [_jsx("strong", { children: skill.name }), skill.description ? _jsx("p", { children: skill.description }) : null, _jsx("small", { className: "skills-source-badge", children: sourceLabel(skill, tr) })] }), _jsxs("div", { className: "skills-card-actions", children: [_jsx("button", { type: "button", "data-action": "update-skill", disabled: skillBusy === `${skill.name}:update`, onClick: () => void updateSkill(skill.name), children: tr('skills.update') }), _jsx("button", { type: "button", "data-action": "remove-skill", disabled: skillBusy === `${skill.name}:remove`, onClick: () => void removeSkill(skill.name), children: tr('skills.remove') })] })] }, skill.name))) }))] })] }), _jsx("dialog", { className: "skills-discovery-dialog", id: "skills-discovery-dialog", ref: discoveryDialogRef, onClose: () => setDiscoveryOpen(false), children: _jsxs("article", { children: [_jsxs("header", { children: [_jsx("h3", { children: tr('skills.discoverTitle') }), _jsx("p", { children: tr('skills.discoverHelp') })] }), _jsx("div", { className: "skills-discovery-body", children: !activeDiscoveryGroup ? _jsx("p", { className: "empty", children: tr('skills.discoverEmpty') }) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "skills-discovery-tabs", role: "tablist", "aria-label": tr('skills.discoverTitle'), children: nativeSkillGroups.map(group => {
587
+ const headingActions = (_jsxs("div", { className: "page-heading-actions skills-heading-actions", children: [_jsxs("div", { className: "skills-metric-strip", children: [_jsxs("span", { children: [_jsx("small", { children: tr('skills.metricInstalled') }), _jsx("strong", { children: skills.length })] }), _jsxs("span", { children: [_jsx("small", { children: tr('skills.metricBots') }), _jsxs("strong", { children: [configuredBotCount, "/", bots.length] })] }), _jsxs("span", { children: [_jsx("small", { children: tr('skills.metricAttached') }), _jsx("strong", { children: attachedSkillRefCount })] })] }), _jsx(RefreshIconButton, { id: "skills-refresh", label: tr('skills.refresh'), busy: loading, disabled: loading, onClick: () => void refresh() })] }));
588
+ const body = (_jsx("div", { className: "skills-page-stack", children: loading ? _jsx(LoadingState, { label: tr('common.loading') }) : loadError ? _jsx("p", { className: "hint-warn", children: loadError }) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "skills-config-row", children: [_jsxs("section", { className: "skills-config-block", children: [_jsx(SectionHeader, { title: tr('skills.globalDefaults') }), _jsxs("article", { className: "bd-card skills-defaults-panel skills-config-card", children: [_jsxs("div", { className: "skills-control-block", children: [_jsx("span", { className: "skills-control-label", children: tr('skills.globalProject') }), _jsx(SkillSegmented, { value: trustProjectSkills, disabled: globalBusy === 'project', options: [
589
+ { value: 'off', label: tr('skills.globalProjectOff'), help: tr('skills.globalProjectOffHelp') },
590
+ { value: 'all', label: tr('skills.globalProjectAll'), help: tr('skills.globalProjectAllHelp') },
591
+ ], onChange: value => void updateGlobalProject(value) })] }), _jsxs("div", { className: "skills-control-block", children: [_jsx("span", { className: "skills-control-label", children: tr('skills.globalDelivery') }), _jsx(SkillSegmented, { value: delivery, disabled: globalBusy === 'delivery', options: [
592
+ { value: 'auto', label: tr('skills.deliveryAuto'), help: tr('skills.deliveryAutoHelp') },
593
+ { value: 'prompt', label: tr('skills.deliveryPrompt'), help: tr('skills.deliveryPromptHelp') },
594
+ { value: 'native', label: tr('skills.deliveryNative'), help: tr('skills.deliveryNativeHelp') },
595
+ ], onChange: value => void updateGlobalDelivery(value) })] })] })] }), _jsxs("section", { className: "skills-config-block", children: [_jsx(SectionHeader, { title: _jsx(FieldTitle, { help: tr('skills.installInfo'), helpLabel: tr('skills.installInfoLabel'), children: tr('skills.install') }) }), _jsx(SkillsInstallPanel, { showTitle: false, installSource: installSource, installPath: installPath, installRef: installRef, installStatus: installStatus, installBusy: installBusy, installDiscovering: installDiscovering, installSelectionOpen: installSelectionOpen, installCandidates: installCandidates, selectedInstallSkills: selectedInstallSkills, onInstallSourceChange: (value) => {
596
+ setInstallSource(value);
597
+ clearInstallDiscovery();
598
+ }, onInstallPathChange: (value) => {
599
+ setInstallPath(value);
600
+ clearInstallDiscovery();
601
+ }, onInstallRefChange: (value) => {
602
+ setInstallRef(value);
603
+ clearInstallDiscovery();
604
+ }, onToggleInstallSkill: toggleInstallCandidate, onSelectAllInstallSkills: selectAllInstallCandidates, onConfirmInstallSelection: () => void confirmInstallSelection(), onCloseInstallSelection: () => setInstallSelectionOpen(false), onInstall: () => void installSkill(), onOpenNativeDiscovery: () => setDiscoveryOpen(true) })] }), _jsxs("section", { className: "skills-config-block", children: [_jsx(SectionHeader, { title: tr('skills.bots'), count: tr('skills.botCount', { count: bots.length }), hint: tr('skills.botsHelp') }), _jsx("section", { className: "bd-card skills-bots-panel skills-config-card", children: _jsx("div", { className: "skills-bot-grid", children: bots.map(bot => (_jsx(BotPolicyCard, { bot: bot, installedNames: installedNames, skills: skills, status: botStatuses[bot.larkAppId] ?? null, busyKey: botBusy, onSave: setBotSkills }, bot.larkAppId))) }) })] })] }), _jsxs("section", { className: "skills-installed-block", children: [_jsx(SectionHeader, { title: tr('skills.installed'), count: tr('skills.skillCount', { count: skills.length }), hint: tr('skills.installedHelp'), children: installedPageCount > 1 ? (_jsx("div", { className: "skills-installed-toolbar", children: _jsxs("div", { className: "skills-pager", children: [_jsx("button", { type: "button", className: "skills-pager-button", "data-action": "page-installed-skills", "data-dir": "-1", "aria-label": tr('skills.prevPage'), title: tr('skills.prevPage'), disabled: installedSkillsPage === 0, onClick: () => setInstalledSkillsPage(page => Math.max(0, page - 1)), children: "\u2039" }), _jsx("span", { children: tr('skills.pageStatus', { page: installedSkillsPage + 1, pages: installedPageCount }) }), _jsx("button", { type: "button", className: "skills-pager-button", "data-action": "page-installed-skills", "data-dir": "1", "aria-label": tr('skills.nextPage'), title: tr('skills.nextPage'), disabled: installedSkillsPage >= installedPageCount - 1, onClick: () => setInstalledSkillsPage(page => Math.min(installedPageCount - 1, page + 1)), children: "\u203A" })] }) })) : null }), _jsx("section", { className: "bd-card skills-installed-panel", children: skills.length === 0 ? _jsx("p", { className: "empty", children: tr('skills.empty') }) : (_jsx("div", { className: "skills-list", children: visibleSkills.map(skill => (_jsxs("article", { className: "skills-row skills-installed-card", "data-skill": skill.name, children: [_jsxs("div", { className: "skills-row-body", children: [_jsx("strong", { children: skill.name }), skill.description ? _jsx("p", { children: skill.description }) : null, _jsx("small", { className: "skills-source-badge", children: sourceLabel(skill, tr) })] }), _jsxs("div", { className: "skills-card-actions", children: [_jsx("button", { type: "button", "data-action": "update-skill", disabled: skillBusy === `${skill.name}:update`, onClick: () => void updateSkill(skill.name), children: tr('skills.update') }), _jsx("button", { type: "button", "data-action": "remove-skill", disabled: skillBusy === `${skill.name}:remove`, onClick: () => void removeSkill(skill.name), children: tr('skills.remove') })] })] }, skill.name))) })) })] }), _jsx("dialog", { className: "skills-discovery-dialog", id: "skills-discovery-dialog", ref: discoveryDialogRef, onClose: () => setDiscoveryOpen(false), onClick: event => {
605
+ if (event.target === event.currentTarget)
606
+ setDiscoveryOpen(false);
607
+ }, children: _jsxs("article", { children: [_jsxs("header", { children: [_jsx("h3", { children: tr('skills.discoverTitle') }), _jsx("p", { children: tr('skills.discoverHelp') }), _jsx("button", { type: "button", className: "skills-discovery-close", "data-action": "close-discovery", "aria-label": tr('skills.discoverClose'), title: tr('skills.discoverClose'), onClick: () => setDiscoveryOpen(false) })] }), _jsx("div", { className: "skills-discovery-body", children: !activeDiscoveryGroup ? _jsx("p", { className: "empty", children: tr('skills.discoverEmpty') }) : (_jsx(_Fragment, { children: _jsxs("div", { className: "skills-discovery-layout", children: [_jsx("div", { className: "skills-discovery-tabs", role: "tablist", "aria-label": tr('skills.discoverTitle'), children: nativeSkillGroups.map(group => {
578
608
  const key = discoveryGroupKey(group);
579
609
  const selected = key === activeKey;
580
610
  return (_jsxs("button", { type: "button", role: "tab", "data-discovery-tab": key, className: selected ? 'selected' : '', "aria-selected": selected ? 'true' : 'false', onClick: () => setActiveDiscoveryKey(key), children: [_jsx("strong", { children: group.label ?? group.cliId }), _jsx("small", { children: tr('skills.skillCount', { count: group.skills.length }) })] }, key));
581
- }) }), _jsx("div", { className: "skills-discovery-path", children: _jsx("code", { children: activeDiscoveryGroup.rootDir }) }), nativeSkillGroups.map(group => {
582
- const key = discoveryGroupKey(group);
583
- const selected = key === activeKey;
584
- return (_jsx("section", { className: "skills-discovery-group", "data-discovery-panel": key, hidden: !selected, children: group.skills.length === 0 ? _jsx("p", { className: "empty", children: tr('skills.discoverGroupEmpty') }) : (_jsx("div", { className: "skills-discovery-list", children: group.skills.map(skill => {
585
- const already = installedNames.has(skill.name);
586
- const path = skill.rootDir ?? skill.source?.root ?? '';
587
- return (_jsxs("label", { className: `skills-discovery-row${already ? ' installed' : ''}`, children: [_jsx("input", { type: "checkbox", "data-discovered-skill": true, value: path, disabled: already, checked: !already && selectedDiscovered.has(path), onChange: e => {
588
- const checked = e.currentTarget.checked;
589
- setSelectedDiscovered(prev => {
590
- const next = new Set(prev);
591
- if (checked)
592
- next.add(path);
593
- else
594
- next.delete(path);
595
- return next;
596
- });
597
- } }), _jsxs("span", { children: [_jsx("strong", { children: skill.name }), skill.description ? _jsx("small", { children: skill.description }) : null] }), already ? _jsx("em", { children: tr('skills.discoverRegistered') }) : null] }, `${skill.name}:${path}`));
598
- }) })) }, key));
599
- })] })) }), _jsxs("footer", { className: "actions", children: [_jsx("button", { type: "button", "data-action": "toggle-discovered-skills", disabled: activeGroupSelectable.length === 0, onClick: () => {
600
- setSelectedDiscovered(prev => {
601
- const next = new Set(prev);
602
- if (activeAllSelected)
603
- activeGroupSelectable.forEach(path => next.delete(path));
604
- else
605
- activeGroupSelectable.forEach(path => next.add(path));
606
- return next;
607
- });
608
- }, children: activeAllSelected ? tr('skills.discoverClearSelection') : tr('skills.discoverSelectAll') }), _jsx("button", { type: "button", className: "primary", "data-action": "register-discovered-skills", disabled: discoveryBusy, onClick: () => void registerDiscoveredSkills(), children: tr('skills.discoverRegister') }), _jsx("button", { type: "button", "data-action": "close-discovery", onClick: () => setDiscoveryOpen(false), children: tr('skills.discoverClose') })] })] }) })] }));
609
- return (_jsxs("section", { className: "page", children: [_jsxs("div", { className: "page-heading", children: [_jsxs("div", { children: [_jsx("p", { className: "eyebrow", children: tr('nav.skills') }), _jsx("h1", { children: tr('skills.title') }), _jsx("p", { children: tr('skills.subtitle') })] }), _jsx("button", { type: "button", id: "skills-refresh", disabled: loading, onClick: () => void refresh(), children: tr('skills.refresh') })] }), _jsx("div", { id: "skills-body", children: body })] }));
611
+ }) }), _jsxs("div", { className: "skills-discovery-main", children: [_jsx("div", { className: "skills-discovery-path", children: _jsx("code", { children: activeDiscoveryGroup.rootDir }) }), nativeSkillGroups.map(group => {
612
+ const key = discoveryGroupKey(group);
613
+ const selected = key === activeKey;
614
+ return (_jsx("section", { className: "skills-discovery-group", "data-discovery-panel": key, hidden: !selected, children: group.skills.length === 0 ? _jsx("p", { className: "empty", children: tr('skills.discoverGroupEmpty') }) : (_jsx("div", { className: "skills-discovery-list", children: group.skills.map(skill => {
615
+ const already = installedNames.has(skill.name);
616
+ const path = skill.rootDir ?? skill.source?.root ?? '';
617
+ return (_jsxs("label", { className: `skills-discovery-row${already ? ' installed' : ''}`, children: [_jsx("input", { type: "checkbox", "data-discovered-skill": true, value: path, disabled: already, checked: !already && selectedDiscovered.has(path), onChange: e => {
618
+ const checked = e.currentTarget.checked;
619
+ setSelectedDiscovered(prev => {
620
+ const next = new Set(prev);
621
+ if (checked)
622
+ next.add(path);
623
+ else
624
+ next.delete(path);
625
+ return next;
626
+ });
627
+ } }), _jsxs("span", { children: [_jsx("strong", { children: skill.name }), skill.description ? _jsx("small", { children: skill.description }) : null] }), already ? _jsx("em", { children: tr('skills.discoverRegistered') }) : null] }, `${skill.name}:${path}`));
628
+ }) })) }, key));
629
+ })] })] }) })) }), _jsxs("footer", { className: "actions", children: [_jsx("button", { type: "button", "data-action": "toggle-discovered-skills", disabled: activeGroupSelectable.length === 0, onClick: () => {
630
+ setSelectedDiscovered(prev => {
631
+ const next = new Set(prev);
632
+ if (activeAllSelected)
633
+ activeGroupSelectable.forEach(path => next.delete(path));
634
+ else
635
+ activeGroupSelectable.forEach(path => next.add(path));
636
+ return next;
637
+ });
638
+ }, children: activeAllSelected ? tr('skills.discoverClearSelection') : tr('skills.discoverSelectAll') }), _jsx("button", { type: "button", className: "primary", "data-action": "register-discovered-skills", disabled: discoveryBusy, onClick: () => void registerDiscoveredSkills(), children: tr('skills.discoverRegister') })] })] }) })] })) }));
639
+ return (_jsxs("section", { className: "page skills-page", children: [_jsxs("div", { className: "page-heading", children: [_jsxs("div", { children: [_jsx("p", { className: "eyebrow", children: tr('nav.skills') }), _jsx("h1", { children: tr('skills.title') })] }), headingActions] }), _jsx("div", { id: "skills-body", children: body })] }));
640
+ }
641
+ function sameSkillSelection(left, right) {
642
+ return left.size === right.length && right.every(name => left.has(name));
643
+ }
644
+ export function SkillMultiPicker(props) {
645
+ const tr = useT();
646
+ const rootRef = useRef(null);
647
+ const triggerRef = useRef(null);
648
+ const popoverRef = useRef(null);
649
+ const [open, setOpen] = useState(false);
650
+ const [query, setQuery] = useState('');
651
+ const [draft, setDraft] = useState(() => new Set(props.names));
652
+ const [position, setPosition] = useState(null);
653
+ const currentNamesKey = props.names.join('\n');
654
+ const normalizedQuery = query.trim().toLocaleLowerCase();
655
+ const options = useMemo(() => {
656
+ const byName = new Map(props.skills.map(skill => [skill.name, skill]));
657
+ for (const name of props.names) {
658
+ if (!byName.has(name))
659
+ byName.set(name, { name });
660
+ }
661
+ return [...byName.values()].sort((left, right) => left.name.localeCompare(right.name));
662
+ }, [props.names, props.skills]);
663
+ const filteredOptions = useMemo(() => {
664
+ if (!normalizedQuery)
665
+ return options;
666
+ return options.filter(skill => `${skill.name} ${skill.description || ''}`.toLocaleLowerCase().includes(normalizedQuery));
667
+ }, [normalizedQuery, options]);
668
+ const dirty = !sameSkillSelection(draft, props.names);
669
+ const updatePosition = useCallback(() => {
670
+ const trigger = triggerRef.current;
671
+ if (!trigger || typeof window === 'undefined')
672
+ return;
673
+ const rect = trigger.getBoundingClientRect();
674
+ const edge = 12;
675
+ const gap = 7;
676
+ const width = Math.min(370, Math.max(260, window.innerWidth - edge * 2));
677
+ const left = Math.min(Math.max(edge, rect.left), Math.max(edge, window.innerWidth - width - edge));
678
+ const spaceAbove = Math.max(0, rect.top - gap - edge);
679
+ const spaceBelow = Math.max(0, window.innerHeight - rect.bottom - gap - edge);
680
+ const placeAbove = spaceAbove > spaceBelow;
681
+ const available = placeAbove ? spaceAbove : spaceBelow;
682
+ const desired = 118 + Math.min(options.length, 5) * 42;
683
+ const height = Math.max(180, Math.min(desired, available));
684
+ setPosition({
685
+ left,
686
+ top: placeAbove ? Math.max(edge, rect.top - gap - height) : rect.bottom + gap,
687
+ width,
688
+ height,
689
+ });
690
+ }, [options.length]);
691
+ useEffect(() => {
692
+ if (!open)
693
+ setDraft(new Set(props.names));
694
+ }, [currentNamesKey, open]);
695
+ useEffect(() => {
696
+ if (!open || typeof document === 'undefined')
697
+ return undefined;
698
+ const closeOnOutsideClick = (event) => {
699
+ if (rootRef.current?.contains(event.target) || popoverRef.current?.contains(event.target))
700
+ return;
701
+ setOpen(false);
702
+ setQuery('');
703
+ setDraft(new Set(props.names));
704
+ };
705
+ document.addEventListener('pointerdown', closeOnOutsideClick);
706
+ window.addEventListener('resize', updatePosition);
707
+ window.addEventListener('scroll', updatePosition, true);
708
+ updatePosition();
709
+ return () => {
710
+ document.removeEventListener('pointerdown', closeOnOutsideClick);
711
+ window.removeEventListener('resize', updatePosition);
712
+ window.removeEventListener('scroll', updatePosition, true);
713
+ };
714
+ }, [currentNamesKey, open, updatePosition]);
715
+ function openPicker() {
716
+ setDraft(new Set(props.names));
717
+ setQuery('');
718
+ updatePosition();
719
+ setOpen(true);
720
+ }
721
+ function cancel() {
722
+ setDraft(new Set(props.names));
723
+ setQuery('');
724
+ setOpen(false);
725
+ }
726
+ function toggle(name) {
727
+ setDraft(current => {
728
+ const next = new Set(current);
729
+ if (next.has(name))
730
+ next.delete(name);
731
+ else
732
+ next.add(name);
733
+ return next;
734
+ });
735
+ }
736
+ async function save() {
737
+ const names = [...draft].sort((left, right) => left.localeCompare(right));
738
+ try {
739
+ await props.onSave(names);
740
+ setQuery('');
741
+ setOpen(false);
742
+ }
743
+ catch {
744
+ // The card-level status message explains the failure; keep the draft open for retry.
745
+ }
746
+ }
747
+ const triggerLabel = props.names.length === 0
748
+ ? tr('skills.pickerPlaceholder')
749
+ : props.names.length === 1
750
+ ? props.names[0]
751
+ : tr('skills.pickerSelectedCount', { count: props.names.length });
752
+ const popover = open ? (_jsxs("div", { ref: popoverRef, className: "skills-multi-picker-popover", style: position ? { left: position.left, top: position.top, width: position.width, height: position.height } : undefined, children: [_jsxs("div", { className: "skills-multi-picker-head", children: [_jsxs("label", { className: "skills-multi-picker-search", children: [_jsx("span", { className: "skills-multi-picker-search-icon", "aria-hidden": "true" }), _jsx("input", { type: "search", "data-action": "search-skills", autoFocus: true, autoComplete: "off", value: query, placeholder: tr('skills.pickerSearchPlaceholder'), onChange: event => setQuery(event.currentTarget.value), onKeyDown: event => {
753
+ if (event.key === 'Escape') {
754
+ event.preventDefault();
755
+ cancel();
756
+ }
757
+ } })] }), _jsxs("div", { className: "skills-multi-picker-meta", children: [_jsx("span", { children: tr('skills.pickerSelectionMeta', { selected: draft.size, total: options.length }) }), draft.size > 0 ? (_jsx("button", { type: "button", className: "skills-multi-picker-clear", "data-action": "clear-skill-selection", onClick: () => setDraft(new Set()), children: tr('skills.pickerClear') })) : null] })] }), _jsxs("div", { className: "skills-multi-picker-options", role: "listbox", "aria-label": tr('skills.priority'), "aria-multiselectable": "true", children: [filteredOptions.map(skill => {
758
+ const selected = draft.has(skill.name);
759
+ const dangling = !props.installedNames.has(skill.name);
760
+ return (_jsxs("button", { type: "button", className: `skills-multi-picker-option${selected ? ' selected' : ''}${dangling ? ' dangling' : ''}`, role: "option", "aria-selected": selected, "data-skill-name": skill.name, onClick: () => toggle(skill.name), children: [_jsx("span", { className: "skills-multi-picker-check", "aria-hidden": "true" }), _jsxs("span", { className: "skills-multi-picker-option-copy", children: [_jsxs("span", { children: [_jsx("b", { children: skill.name }), dangling ? _jsx("em", { children: tr('skills.dangling') }) : null] }), skill.description ? _jsx("small", { children: skill.description }) : null] })] }, skill.name));
761
+ }), filteredOptions.length === 0 ? _jsx("p", { className: "skills-multi-picker-empty", children: tr('skills.pickerNoResults') }) : null] }), _jsxs("footer", { className: "skills-multi-picker-actions", children: [_jsx("button", { type: "button", className: "ghost", "data-action": "cancel-skill-selection", disabled: props.busy, onClick: cancel, children: tr('skills.cancel') }), _jsx("button", { type: "button", className: "primary", "data-action": "save-skill-selection", disabled: !dirty || props.busy, onClick: () => void save(), children: props.busy ? tr('skills.saving') : tr('skills.saveSelection') })] })] })) : null;
762
+ return (_jsxs("div", { ref: rootRef, className: `skills-multi-picker${open ? ' open' : ''}`, "data-skill-picker": props.botId, children: [_jsxs("button", { ref: triggerRef, type: "button", className: "skills-multi-picker-trigger", "data-action": "open-skill-picker", "aria-haspopup": "listbox", "aria-expanded": open, disabled: props.busy, onClick: () => open ? cancel() : openPicker(), children: [_jsxs("span", { className: "skills-multi-picker-trigger-copy", children: [_jsx("b", { children: triggerLabel }), _jsx("small", { children: tr('skills.pickerTriggerHint') })] }), _jsx("span", { className: "skills-multi-picker-chevron", "aria-hidden": "true" })] }), popover && typeof document !== 'undefined' ? createPortal(popover, document.body) : popover] }));
610
763
  }
611
764
  export function BotPolicyCard(props) {
612
765
  const tr = useT();
613
- const { bot, installedNames, skills, status, busyKey, onUpdate } = props;
766
+ const { bot, installedNames, skills, status, busyKey, onSave } = props;
614
767
  const label = bot.botName ?? bot.larkAppId;
615
768
  const names = priorityNames(bot.skills);
616
- const attached = new Set(names);
617
- const attachOptions = skills.filter(skill => !attached.has(skill.name));
618
- const [selected, setSelected] = useState(attachOptions[0]?.name ?? '');
619
- useEffect(() => {
620
- if (!selected || !attachOptions.some(skill => skill.name === selected)) {
621
- setSelected(attachOptions[0]?.name ?? '');
622
- }
623
- }, [attachOptions, selected]);
624
769
  if (bot.error) {
625
770
  return (_jsxs("article", { className: "bd-card skills-bot-card", "data-appid": bot.larkAppId, children: [_jsxs("header", { children: [_jsx(Html, { html: botAvatarHtml({ name: label, larkAppId: bot.larkAppId, size: 'sm' }) }), _jsx("strong", { children: label })] }), _jsx("p", { className: "hint-warn-inline", children: bot.error })] }));
626
771
  }
627
- return (_jsxs("article", { className: "bd-card skills-bot-card", "data-appid": bot.larkAppId, children: [_jsxs("header", { className: "skills-bot-head", children: [_jsx(Html, { html: botAvatarHtml({ name: label, larkAppId: bot.larkAppId, size: 'sm', dot: 'ok' }) }), _jsxs("div", { children: [_jsx("strong", { children: label }), _jsx("code", { children: bot.larkAppId })] }), _jsx("span", { className: "skills-count-pill", children: tr('skills.skillCount', { count: names.length }) })] }), _jsxs("section", { className: "bd-section", children: [_jsx("h3", { className: "bd-section-title", children: tr('skills.priority') }), names.length === 0 ? _jsx("p", { className: "bd-section-note", children: tr('skills.noPriority') }) : (_jsx("div", { className: "skills-chip-list", children: names.map(name => {
628
- const dangling = !installedNames.has(name);
629
- return (_jsxs("span", { className: `skills-priority-row${dangling ? ' skills-priority-dangling' : ''}`, title: dangling ? tr('skills.dangling') : '', children: [_jsxs("span", { className: "skills-priority-name", children: [name, dangling ? _jsx("small", { children: tr('skills.dangling') }) : null] }), _jsx("button", { type: "button", className: "skills-priority-remove", "data-action": "detach-skill", "data-name": name, "aria-label": tr('skills.detachNamed', { skill: name }), disabled: busyKey === `${bot.larkAppId}:detach:${name}`, onClick: () => void onUpdate(bot.larkAppId, 'detach', name), children: "\u00D7" })] }, name));
630
- }) })), _jsx("div", { className: "actions skills-attach-row", children: attachOptions.length === 0 ? _jsx("button", { type: "button", disabled: true, children: tr('skills.attach') }) : (_jsxs(_Fragment, { children: [_jsx("select", { "data-attach-picker": true, value: selected, onChange: e => setSelected(e.currentTarget.value), children: attachOptions.map(skill => _jsx("option", { value: skill.name, children: skill.name }, skill.name)) }), _jsx("button", { type: "button", "data-action": "attach-skill", disabled: !selected || busyKey === `${bot.larkAppId}:attach:${selected}`, onClick: () => selected && void onUpdate(bot.larkAppId, 'attach', selected), children: tr('skills.attach') })] })) })] }), _jsx("span", { className: statusClass(status), "data-bot-status": true, children: status?.text ?? '' })] }));
772
+ return (_jsxs("article", { className: "bd-card skills-bot-card", "data-appid": bot.larkAppId, children: [_jsxs("header", { className: "skills-bot-head", children: [_jsx(Html, { html: botAvatarHtml({ name: label, larkAppId: bot.larkAppId, size: 'sm', dot: 'ok' }) }), _jsxs("div", { className: "skills-bot-title-line", children: [_jsx("strong", { children: label }), _jsx("span", { className: "skills-count-pill", children: tr('skills.skillCount', { count: names.length }) })] })] }), _jsxs("section", { className: "skills-policy-panel", children: [_jsx("div", { className: "skills-priority-head", children: _jsx("h3", { className: "skills-priority-title", children: tr('skills.priority') }) }), _jsx(SkillMultiPicker, { botId: bot.larkAppId, names: names, installedNames: installedNames, skills: skills, busy: busyKey === `${bot.larkAppId}:set`, onSave: next => onSave(bot.larkAppId, next) })] }), _jsx("span", { className: statusClass(status), "data-bot-status": true, children: status?.text ?? '' })] }));
631
773
  }
632
774
  export function renderSkillsPage(root) {
633
775
  return mountReactPage(root, _jsx(SkillsPage, {}));