bazilion 0.12.2 → 0.14.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 (217) hide show
  1. package/README.md +2 -2
  2. package/dist/cli.js +795 -240
  3. package/dist/cli.js.map +1 -1
  4. package/dist/daemon.js +4555 -1280
  5. package/dist/daemon.js.map +1 -1
  6. package/dist/migrations/0001_init.sql +21 -0
  7. package/dist/web/client/assets/AgentTabs-BcmmwYJc.js +1 -0
  8. package/dist/web/client/assets/ConfigPage-BCLp-FUC.js +1 -0
  9. package/dist/web/client/assets/ConfirmDialog-CyL9A20V.js +1 -0
  10. package/dist/web/client/assets/FieldRow-D6REbYUa.js +1 -0
  11. package/dist/web/client/assets/Page-NV96O47A.js +1 -0
  12. package/dist/web/client/assets/ProductionTeamPolicyEditor-DBKnOezm.js +7 -0
  13. package/dist/web/client/assets/{ProfileCommunicationEditor-C43HvUe-.js → ProfileCommunicationEditor-4RK2laqO.js} +1 -1
  14. package/dist/web/client/assets/SectionTabs-4kCQXuFY.js +1 -0
  15. package/dist/web/client/assets/TeamTabs-CdtNEqt4.js +1 -0
  16. package/dist/web/client/assets/{TemplatesTabs-6Jd_xQj7.js → TemplatesTabs-CZyss2Y0.js} +1 -1
  17. package/dist/web/client/assets/UnsavedChangesGuard-CEoK-ZcN.js +1 -0
  18. package/dist/web/client/assets/_id-4ZS-w_Aj.js +1 -0
  19. package/dist/web/client/assets/{_id-AOAT0H_5.js → _id-DIqtdQij.js} +1 -1
  20. package/dist/web/client/assets/_id-DbcC2E7F.js +1 -0
  21. package/dist/web/client/assets/_id-f_r5M0p3.js +1 -0
  22. package/dist/web/client/assets/activity-CB9Ufth-.js +1 -0
  23. package/dist/web/client/assets/agents-D-JGXVg9.js +1 -0
  24. package/dist/web/client/assets/agents-DS2XafoA.js +1 -0
  25. package/dist/web/client/assets/approvals-Cke_mrJv.js +1 -0
  26. package/dist/web/client/assets/attention-PYwRM2wC.js +1 -0
  27. package/dist/web/client/assets/chevron-right-BG4OeFRQ.js +1 -0
  28. package/dist/web/client/assets/config-DF9Gqmfa.js +3 -0
  29. package/dist/web/client/assets/dm-sans-latin-400-normal-BwCSEQnW.woff +0 -0
  30. package/dist/web/client/assets/dm-sans-latin-400-normal-CW0RaeGs.woff2 +0 -0
  31. package/dist/web/client/assets/dm-sans-latin-500-normal-B9HHJjqV.woff2 +0 -0
  32. package/dist/web/client/assets/dm-sans-latin-500-normal-Dr3UlScf.woff +0 -0
  33. package/dist/web/client/assets/dm-sans-latin-600-normal-Aqo67rzb.woff2 +0 -0
  34. package/dist/web/client/assets/dm-sans-latin-600-normal-BmdmIIQ2.woff +0 -0
  35. package/dist/web/client/assets/dm-sans-latin-700-normal-CUSSCpQX.woff +0 -0
  36. package/dist/web/client/assets/dm-sans-latin-700-normal-DvUfVpUG.woff2 +0 -0
  37. package/dist/web/client/assets/dm-serif-display-latin-400-normal-C5_t9oOD.woff2 +0 -0
  38. package/dist/web/client/assets/dm-serif-display-latin-400-normal-_kVFYEpx.woff +0 -0
  39. package/dist/web/client/assets/{inbox-Bn1GbUsJ.js → inbox-DC_HdOfI.js} +1 -1
  40. package/dist/web/client/assets/index-Cofc7zhl.css +1 -0
  41. package/dist/web/client/assets/index-Cp6UHWr2.js +52 -0
  42. package/dist/web/client/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
  43. package/dist/web/client/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
  44. package/dist/web/client/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
  45. package/dist/web/client/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
  46. package/dist/web/client/assets/learning-BfrQ4YZY.js +1 -0
  47. package/dist/web/client/assets/login-D4n3AcBR.js +1 -0
  48. package/dist/web/client/assets/mcp-CnjQc_JJ.js +1 -0
  49. package/dist/web/client/assets/members-wxsVTJdW.js +1 -0
  50. package/dist/web/client/assets/memory-Du60O3pE.js +1 -0
  51. package/dist/web/client/assets/{policy-DaijITy7.js → policy-BOfnkJsL.js} +1 -1
  52. package/dist/web/client/assets/{preload-helper-mNuBjNXU.js → preload-helper-bztXdkDj.js} +1 -1
  53. package/dist/web/client/assets/routes-B9CuhzUW.js +1 -0
  54. package/dist/web/client/assets/services-DyvqJqM2.js +1 -0
  55. package/dist/web/client/assets/skills-DQo7ioW7.js +1 -0
  56. package/dist/web/client/assets/styles-B5vcgXln.css +2 -0
  57. package/dist/web/client/assets/{teams-D92R9Pb7.js → teams-DPggy97H.js} +1 -1
  58. package/dist/web/client/assets/teams-DdawcfNR.js +1 -0
  59. package/dist/web/client/assets/telegram-DcTeDpP5.js +1 -0
  60. package/dist/web/client/assets/tokens-CIEKwZXc.js +1 -0
  61. package/dist/web/client/assets/triggers-Bc2RrUPm.js +1 -0
  62. package/dist/web/client/assets/utils-B6KiDbIe.js +1 -0
  63. package/dist/web/client/assets/welcome-DlhNXUIa.js +1 -0
  64. package/dist/web/client/assets/wire-constants-BzdHSc6A.js +74 -0
  65. package/dist/web/client/assets/x-DAXGIe_Q.js +1 -0
  66. package/dist/web/server/assets/{AgentTabs-aXdsiiMp.js → AgentTabs-Dq8hDM2Q.js} +9 -2
  67. package/dist/web/server/assets/{ChatPane-Ba5wTsVk.js → ChatPane-CgSe7tsy.js} +81 -43
  68. package/dist/web/server/assets/{ConfigPage-BKlh5vOU.js → ConfigPage-CiQ-gxmJ.js} +3 -2
  69. package/dist/web/server/assets/ConfirmDialog-C-MPYYSU.js +99 -0
  70. package/dist/web/server/assets/FieldRow-DCOF07kl.js +160 -0
  71. package/dist/web/server/assets/{Page-LENulSXY.js → Page-Bz-ydB8j.js} +4 -10
  72. package/dist/web/server/assets/{ProductionTeamPolicyEditor-Y4mzFFvR.js → ProductionTeamPolicyEditor-DQSdP7Yx.js} +140 -123
  73. package/dist/web/server/assets/{SectionTabs-BJTPr5nU.js → SectionTabs-B2Yw81XN.js} +2 -2
  74. package/dist/web/server/assets/{Sidebar-DsRVCszF.js → Sidebar-DKyk7oIo.js} +563 -283
  75. package/dist/web/server/assets/{TeamTabs-zZzbP1t_.js → TeamTabs-Co3n2exj.js} +2 -6
  76. package/dist/web/server/assets/{TemplatesTabs-CcRxZhJe.js → TemplatesTabs-B0fA361R.js} +1 -1
  77. package/dist/web/server/assets/UnsavedChangesGuard-CiStXyBI.js +40 -0
  78. package/dist/web/server/assets/{_id-Dj1yZ3zJ.js → _id-BAA9KJBU.js} +4 -4
  79. package/dist/web/server/assets/{_id-LrvXU4Nr.js → _id-BM5m2FLT.js} +4 -4
  80. package/dist/web/server/assets/{_id-CwyGjJeP.js → _id-BYKpT2Tu.js} +4 -5
  81. package/dist/web/server/assets/{_id-BHYLL8M-.js → _id-BeKhPKw3.js} +350 -185
  82. package/dist/web/server/assets/{_id-C3HY4lWg.js → _id-BqWTB8Wl.js} +188 -86
  83. package/dist/web/server/assets/{_id-DinTp_7X.js → _id-BwvCtzlD.js} +3 -3
  84. package/dist/web/server/assets/{_id-D27T85mU.js → _id-DYU6uIBx.js} +4 -5
  85. package/dist/web/server/assets/{_id-IzadFZV9.js → _id-DvlDkk04.js} +4 -4
  86. package/dist/web/server/assets/{_id-BhOB8Umi.js → _id-DxCnEFpm.js} +4 -4
  87. package/dist/web/server/assets/{_id-tB47Vsfp.js → _id-HMy7jM3P.js} +3 -3
  88. package/dist/web/server/assets/{_id-D3Ap7zZA.js → _id-ndxFHx0t.js} +75 -71
  89. package/dist/web/server/assets/{_id-FcHdSocl.js → _id-sNu5aXZt.js} +5 -4
  90. package/dist/web/server/assets/{_tanstack-start-manifest_v-BGDBdnUs.js → _tanstack-start-manifest_v-C-OiOZeM.js} +118 -94
  91. package/dist/web/server/assets/{activity-DohitgwW.js → activity-9VP6QDTH.js} +3 -3
  92. package/dist/web/server/assets/{activity-BCI4mfNS.js → activity-BWv1goK6.js} +3 -3
  93. package/dist/web/server/assets/{activity-D9SMqBhy.js → activity-LjpblbDL.js} +3 -3
  94. package/dist/web/server/assets/{agents-C9xlWK0Z.js → agents-BDFGrU3o.js} +4 -4
  95. package/dist/web/server/assets/{agents-BY74v7fM.js → agents-BJAv919x.js} +3 -3
  96. package/dist/web/server/assets/{agents-BvttypqB.js → agents-CJk4pxKu.js} +3 -3
  97. package/dist/web/server/assets/{agents-CgZMHj80.js → agents-CYw1xHoY.js} +138 -16
  98. package/dist/web/server/assets/{agents-DZuFEj0D.js → agents-DfNKc_Q7.js} +52 -8
  99. package/dist/web/server/assets/{agents-BPKOshR5.js → agents-DjyQk94u.js} +4 -4
  100. package/dist/web/server/assets/{approvals-CWcFHlor.js → approvals-7JOoBchn.js} +3 -3
  101. package/dist/web/server/assets/{approvals-BGU-XGIO.js → approvals-BYi84gwl.js} +3 -3
  102. package/dist/web/server/assets/{approvals-DCaVw1Mz.js → approvals-Bz123liE.js} +59 -21
  103. package/dist/web/server/assets/{attention-BxkTf337.js → attention-B35JvhOL.js} +3 -3
  104. package/dist/web/server/assets/{attention-w21GQIGH.js → attention-C1pPWSXw.js} +3 -3
  105. package/dist/web/server/assets/{attention-CM-Ks1N9.js → attention-UhqPK_Ro.js} +3 -3
  106. package/dist/web/server/assets/{auth-byfSx6Ja.js → auth-7BHTH-KS.js} +5 -5
  107. package/dist/web/server/assets/{config-BDCJdtj2.js → config-BMiajTZP.js} +10 -5
  108. package/dist/web/server/assets/{config-1w2GiJUn.js → config-BlMkHStx.js} +3 -3
  109. package/dist/web/server/assets/config-ExacOzHX.js +958 -0
  110. package/dist/web/server/assets/{createServerRpc-pU-IQV2Y.js → createServerRpc-B7Yr1K8i.js} +1 -1
  111. package/dist/web/server/assets/{createSsrRpc-DFsIAfFd.js → createSsrRpc-6LHNEsSK.js} +1 -1
  112. package/dist/web/server/assets/{daemon-client-2NRMzlTr.js → daemon-client-CI5NHwNC.js} +16 -4
  113. package/dist/web/server/assets/{inbox-CzlKT9Wg.js → inbox-Dv55rGYq.js} +4 -4
  114. package/dist/web/server/assets/{inbox-BLUzA5sQ.js → inbox-RweGCV3D.js} +3 -3
  115. package/dist/web/server/assets/{inbox-ZvDNAjaM.js → inbox-cu3jLzNP.js} +4 -4
  116. package/dist/web/server/assets/{learning-B7PBkvER.js → learning-BaKM6qaw.js} +4 -4
  117. package/dist/web/server/assets/{learning-8zav4pIT.js → learning-C2upa1CE.js} +4 -4
  118. package/dist/web/server/assets/{learning-Cq7K2heb.js → learning-CbtNlqYo.js} +76 -23
  119. package/dist/web/server/assets/{login-CmWvxfTK.js → login-BNj3U6ok.js} +22 -12
  120. package/dist/web/server/assets/{login-Bx5LEyGP.js → login-Be8eP4Jp.js} +2 -2
  121. package/dist/web/server/assets/{mcp-DIWTogHM.js → mcp-B0goWO8Q.js} +3 -3
  122. package/dist/web/server/assets/{mcp-2pwT9HU8.js → mcp-BvnvlVFd.js} +3 -3
  123. package/dist/web/server/assets/mcp-CiBs8unU.js +332 -0
  124. package/dist/web/server/assets/members-BP3UTqu1.js +12 -0
  125. package/dist/web/server/assets/members-DHYTVgwb.js +100 -0
  126. package/dist/web/server/assets/members-DiYtr-zm.js +12 -0
  127. package/dist/web/server/assets/{memory-Dngc13Nw.js → memory-BqV-Afy1.js} +4 -4
  128. package/dist/web/server/assets/{memory-a8Kz57Kh.js → memory-CkXUgf5s.js} +150 -48
  129. package/dist/web/server/assets/{memory-pZ4pZT7p.js → memory-DTFEmfF3.js} +4 -4
  130. package/dist/web/server/assets/{policy-Bb-vEgqg.js → policy-18fdTFO4.js} +3 -3
  131. package/dist/web/server/assets/{policy-C30AeFIb.js → policy-BddK4xom.js} +3 -3
  132. package/dist/web/server/assets/{policy-BcGELcc9.js → policy-Bvvav8fh.js} +4 -4
  133. package/dist/web/server/assets/public-origin-xV0lm0Ty.js +25 -0
  134. package/dist/web/server/assets/router-pjH2t8Rl.js +813 -0
  135. package/dist/web/server/assets/{routes-B6cMLIPk.js → routes-BgHisAxH.js} +22 -5
  136. package/dist/web/server/assets/{routes-BrA-U_Hm.js → routes-COtkyZG1.js} +5 -5
  137. package/dist/web/server/assets/{routes-C19CMLZt.js → routes-DAU2g7Uz.js} +4 -4
  138. package/dist/web/server/assets/services-ClyGBU7W.js +83 -0
  139. package/dist/web/server/assets/{services-C4szdhPx.js → services-DgoU1udp.js} +3 -3
  140. package/dist/web/server/assets/{services-wG8I06oS.js → services-DozuJtzX.js} +3 -3
  141. package/dist/web/server/assets/{skills-BZdqiDig.js → skills-CYih9TJw.js} +47 -6
  142. package/dist/web/server/assets/{skills-a9VSWHWq.js → skills-DfGSJTCB.js} +3 -3
  143. package/dist/web/server/assets/{skills-C-UgkuCW.js → skills-Dw3cI3si.js} +3 -3
  144. package/dist/web/server/assets/start-D4Wq9iTa.js +70 -0
  145. package/dist/web/server/assets/{teams-OIkHuxy1.js → teams-BJuoNOTB.js} +3 -3
  146. package/dist/web/server/assets/{teams-CpQ0YgWf.js → teams-DF3RViAg.js} +3 -3
  147. package/dist/web/server/assets/{teams-DEpQR2QA.js → teams-DFnuc660.js} +3 -3
  148. package/dist/web/server/assets/{teams-DqfrEoH6.js → teams-DPnAX4wD.js} +4 -4
  149. package/dist/web/server/assets/{teams-jBtvnk59.js → teams-TV6nbEN_.js} +101 -10
  150. package/dist/web/server/assets/{teams-MjqgsmC3.js → teams-be05ci17.js} +3 -3
  151. package/dist/web/server/assets/{telegram-DNgCWebD.js → telegram-1AWL6lFw.js} +3 -3
  152. package/dist/web/server/assets/{telegram-XwyKSEtj.js → telegram-DbOFpTFm.js} +3 -3
  153. package/dist/web/server/assets/{telegram-CBF8SJzB.js → telegram-Dj4Wwhd6.js} +262 -43
  154. package/dist/web/server/assets/tokens-DDwtO15P.js +359 -0
  155. package/dist/web/server/assets/tokens-DjM8GsgS.js +19 -0
  156. package/dist/web/server/assets/{tokens-BnwFbV7T.js → tokens-_2hptHP6.js} +4 -4
  157. package/dist/web/server/assets/{triggers-BZPl5CHs.js → triggers-BvjYNmmY.js} +4 -4
  158. package/dist/web/server/assets/triggers-CHk9O3rU.js +367 -0
  159. package/dist/web/server/assets/{triggers-D79NoSXk.js → triggers-Nezfw-Bd.js} +4 -4
  160. package/dist/web/server/assets/utils-C_uf36nf.js +8 -0
  161. package/dist/web/server/assets/{welcome-DDB11L5j.js → welcome-B8nchXdF.js} +9 -8
  162. package/dist/web/server/server.js +29 -33
  163. package/dist/web-server.js +4 -0
  164. package/dist/web-server.js.map +1 -1
  165. package/dist/worker.js +1744 -362
  166. package/dist/worker.js.map +1 -1
  167. package/package.json +7 -6
  168. package/dist/web/client/assets/AgentTabs-R6gSjIj3.js +0 -1
  169. package/dist/web/client/assets/ConfigPage-BCwfgyjD.js +0 -1
  170. package/dist/web/client/assets/FieldRow-avAFLgYW.js +0 -1
  171. package/dist/web/client/assets/Page-CwNuDhWz.js +0 -1
  172. package/dist/web/client/assets/ProductionTeamPolicyEditor-CsWpTsy6.js +0 -7
  173. package/dist/web/client/assets/SectionTabs-DZzy01az.js +0 -1
  174. package/dist/web/client/assets/TeamTabs-DvqWieCq.js +0 -1
  175. package/dist/web/client/assets/_id-BUuz7Drv.js +0 -1
  176. package/dist/web/client/assets/_id-BegmVRmT.js +0 -1
  177. package/dist/web/client/assets/_id-BrA4Crh_.js +0 -1
  178. package/dist/web/client/assets/activity-n0Fw9_w3.js +0 -1
  179. package/dist/web/client/assets/agents-B33VQtbl.js +0 -1
  180. package/dist/web/client/assets/agents-C50pdxp7.js +0 -1
  181. package/dist/web/client/assets/approvals-DVW0hX8h.js +0 -1
  182. package/dist/web/client/assets/attention-B2490jcN.js +0 -1
  183. package/dist/web/client/assets/chevron-down-B0aNNOyn.js +0 -1
  184. package/dist/web/client/assets/config-CMMxxeX2.js +0 -3
  185. package/dist/web/client/assets/context-DcFzsfZ3.js +0 -1
  186. package/dist/web/client/assets/index-3nrK5iFr.js +0 -12
  187. package/dist/web/client/assets/learning-BUX1MFu2.js +0 -1
  188. package/dist/web/client/assets/login-CMWpGDKv.js +0 -1
  189. package/dist/web/client/assets/mcp-lZV08dqc.js +0 -1
  190. package/dist/web/client/assets/members-DAeaY2Cy.js +0 -1
  191. package/dist/web/client/assets/memory-HmMWxxdF.js +0 -1
  192. package/dist/web/client/assets/plus-CPzRJg1V.js +0 -1
  193. package/dist/web/client/assets/routes-BNk270AM.js +0 -1
  194. package/dist/web/client/assets/services-DtrpJrdo.js +0 -1
  195. package/dist/web/client/assets/skills-Cv93A3P3.js +0 -1
  196. package/dist/web/client/assets/styles-DMltY3su.css +0 -2
  197. package/dist/web/client/assets/teams-CCFnSNKi.js +0 -1
  198. package/dist/web/client/assets/telegram-BF1vdgDB.js +0 -1
  199. package/dist/web/client/assets/tokens-BXj6hWW-.js +0 -1
  200. package/dist/web/client/assets/triggers-NT24i4hZ.js +0 -1
  201. package/dist/web/client/assets/welcome-D0cy68eZ.js +0 -1
  202. package/dist/web/client/assets/wire-constants-BhVKOCQa.js +0 -74
  203. package/dist/web/server/assets/FieldRow-B4eTegH9.js +0 -94
  204. package/dist/web/server/assets/config-BmixCpz-.js +0 -372
  205. package/dist/web/server/assets/context-B-XDf6Ym.js +0 -12
  206. package/dist/web/server/assets/context-BXGo5Vfi.js +0 -12
  207. package/dist/web/server/assets/context-DrkrIWun.js +0 -47
  208. package/dist/web/server/assets/mcp-BJjLIdP0.js +0 -261
  209. package/dist/web/server/assets/members-CCv17cjQ.js +0 -46
  210. package/dist/web/server/assets/members-CW5aBe81.js +0 -12
  211. package/dist/web/server/assets/members-VdPwD6CE.js +0 -12
  212. package/dist/web/server/assets/router-CIVjTgNp.js +0 -537
  213. package/dist/web/server/assets/services-B9yBWDX0.js +0 -79
  214. package/dist/web/server/assets/start-WH8WzTL_.js +0 -4
  215. package/dist/web/server/assets/tokens-DPDMSN5O.js +0 -12
  216. package/dist/web/server/assets/tokens-yyTSfBSN.js +0 -186
  217. package/dist/web/server/assets/triggers-CSNNzRIi.js +0 -216
@@ -1,8 +1,10 @@
1
- import { t as Route } from "./_id-FcHdSocl.js";
2
- import { r as PageShell } from "./Page-LENulSXY.js";
3
- import { t as AgentTabs } from "./AgentTabs-aXdsiiMp.js";
1
+ import { t as Route } from "./_id-sNu5aXZt.js";
2
+ import { i as SectionCard, r as PageShell } from "./Page-Bz-ydB8j.js";
3
+ import { t as AgentTabs } from "./AgentTabs-Dq8hDM2Q.js";
4
4
  import { t as AgentAvatar } from "./AgentAvatar-8gTAy_tP.js";
5
- import { t as ChatPane } from "./ChatPane-Ba5wTsVk.js";
5
+ import { t as Button } from "./Button-Dsnw22OF.js";
6
+ import { t as ChatPane } from "./ChatPane-CgSe7tsy.js";
7
+ import { t as ConfirmDialog } from "./ConfirmDialog-C-MPYYSU.js";
6
8
  import { r as REASONING_LEVELS } from "./wire-constants-C8nBJcU3.js";
7
9
  import { useState } from "react";
8
10
  import { useRouter } from "@tanstack/react-router";
@@ -53,27 +55,40 @@ function AgentDetailPage() {
53
55
  const { resolved, initialMessages, sessionHead, teams, skills, modelGroups, telegramConfigured } = Route.useLoaderData();
54
56
  const search = Route.useSearch();
55
57
  const router = useRouter();
58
+ const [confirmAction, setConfirmAction] = useState(null);
59
+ const [actionError, setActionError] = useState(null);
60
+ const settingsMode = search.mode === "settings";
56
61
  async function archive() {
57
- if (!confirm(`archive "${resolved.agent.name}"? (reversible)`)) return;
58
- await fetch(`/api/agents/${resolved.agent.id}/archive`, { method: "POST" });
62
+ const response = await fetch(`/api/agents/${encodeURIComponent(resolved.agent.id)}/archive`, { method: "POST" });
63
+ if (!response.ok && response.status !== 204) {
64
+ const body = await response.json().catch(() => null);
65
+ throw new Error(body?.error ?? `Could not archive Agent (${response.status})`);
66
+ }
59
67
  await router.invalidate();
60
68
  }
61
69
  async function unarchive() {
62
- await fetch(`/api/agents/${resolved.agent.id}/unarchive`, { method: "POST" });
63
- await router.invalidate();
70
+ setActionError(null);
71
+ try {
72
+ const response = await fetch(`/api/agents/${encodeURIComponent(resolved.agent.id)}/unarchive`, { method: "POST" });
73
+ if (!response.ok && response.status !== 204) {
74
+ const body = await response.json().catch(() => null);
75
+ throw new Error(body?.error ?? `Could not restore Agent (${response.status})`);
76
+ }
77
+ await router.invalidate();
78
+ } catch (error) {
79
+ setActionError(error instanceof Error ? error.message : String(error));
80
+ }
64
81
  }
65
82
  async function del() {
66
- const msg = `Permanently delete agent "${resolved.agent.name}"?\n\nThis removes the DB rows (messages, triggers, skill attachments) AND the agent's on-disk directory (memory, templates, state, sessions). This cannot be undone.`;
67
- if (!confirm(msg)) return;
68
83
  const policyResponse = await fetch(`/api/teams/${encodeURIComponent(resolved.team.id)}/policy`);
69
- if (!policyResponse.ok) {
70
- alert("The current Team policy is unavailable. Nothing was deleted.");
71
- return;
72
- }
84
+ if (!policyResponse.ok) throw new Error("The current Team policy is unavailable. Nothing was deleted.");
73
85
  const current = await policyResponse.json();
74
86
  const res = await fetch(`/api/agents/${resolved.agent.id}?expectedTeamRevision=${current.teamPolicy.revision}`, { method: "DELETE" });
75
87
  if (res.ok || res.status === 204) window.location.assign("/agents");
76
- else alert(`failed: ${res.statusText}`);
88
+ else {
89
+ const body = await res.json().catch(() => null);
90
+ throw new Error(body?.error ?? `Could not delete Agent (${res.status})`);
91
+ }
77
92
  }
78
93
  return /* @__PURE__ */ jsxs(PageShell, { children: [
79
94
  /* @__PURE__ */ jsxs("header", {
@@ -91,23 +106,26 @@ function AgentDetailPage() {
91
106
  })]
92
107
  }),
93
108
  /* @__PURE__ */ jsxs("div", {
94
- className: "flex items-center gap-3",
109
+ className: "flex min-w-0 items-center gap-3",
95
110
  children: [/* @__PURE__ */ jsx(AgentAvatar, {
96
111
  identity: resolved.agent.identity,
97
112
  size: 44
98
- }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h1", {
99
- className: "mb-0",
100
- children: resolved.agent.name
101
- }), (resolved.agent.identity?.creature || resolved.agent.identity?.vibe) && /* @__PURE__ */ jsx("p", {
102
- className: "muted mt-0.5 text-sm",
103
- children: [resolved.agent.identity?.creature, resolved.agent.identity?.vibe].filter(Boolean).join(" · ")
104
- })] })]
113
+ }), /* @__PURE__ */ jsxs("div", {
114
+ className: "min-w-0",
115
+ children: [/* @__PURE__ */ jsx("h1", {
116
+ className: "mb-0 break-words",
117
+ children: resolved.agent.name
118
+ }), (resolved.agent.identity?.creature || resolved.agent.identity?.vibe) && /* @__PURE__ */ jsx("p", {
119
+ className: "muted mt-0.5 text-sm",
120
+ children: [resolved.agent.identity?.creature, resolved.agent.identity?.vibe].filter(Boolean).join(" · ")
121
+ })]
122
+ })]
105
123
  }),
106
124
  /* @__PURE__ */ jsxs("div", {
107
125
  className: "mt-2 flex flex-wrap items-center gap-x-5 gap-y-2",
108
126
  children: [
109
127
  /* @__PURE__ */ jsxs(Tag, { children: [/* @__PURE__ */ jsx("span", {
110
- className: "px-1.5 font-mono text-[0.95em] text-mocha select-all",
128
+ className: "min-w-0 break-all px-1.5 font-mono text-[0.95em] text-mocha select-all",
111
129
  children: resolved.agent.id
112
130
  }), /* @__PURE__ */ jsx(CopyButton, {
113
131
  value: resolved.agent.id,
@@ -118,16 +136,20 @@ function AgentDetailPage() {
118
136
  className: "ml-1",
119
137
  children: resolved.agent.status
120
138
  })] }),
121
- /* @__PURE__ */ jsxs(Tag, { children: ["profile: ", /* @__PURE__ */ jsx("code", {
122
- className: "ml-1 bg-transparent px-0",
123
- children: resolved.profile.id
124
- })] }),
139
+ /* @__PURE__ */ jsxs(Tag, { children: [
140
+ "profile:",
141
+ " ",
142
+ /* @__PURE__ */ jsx("code", {
143
+ className: "ml-1 min-w-0 break-all bg-transparent px-0",
144
+ children: resolved.profile.id
145
+ })
146
+ ] }),
125
147
  /* @__PURE__ */ jsxs(Tag, { children: [
126
148
  "team:",
127
149
  " ",
128
150
  /* @__PURE__ */ jsx("a", {
129
151
  href: `/teams/${encodeURIComponent(resolved.team.id)}`,
130
- className: "ml-1 bg-transparent px-0 font-mono underline",
152
+ className: "ml-1 min-w-0 break-all bg-transparent px-0 font-mono underline",
131
153
  children: resolved.team.id
132
154
  }),
133
155
  " ",
@@ -139,10 +161,14 @@ function AgentDetailPage() {
139
161
  children: "shared memory →"
140
162
  })
141
163
  ] }),
142
- /* @__PURE__ */ jsxs(Tag, { children: ["model: ", /* @__PURE__ */ jsx("code", {
143
- className: "ml-1 bg-transparent px-0",
144
- children: resolved.model
145
- })] }),
164
+ /* @__PURE__ */ jsxs(Tag, { children: [
165
+ "model:",
166
+ " ",
167
+ /* @__PURE__ */ jsx("code", {
168
+ className: "ml-1 min-w-0 break-all bg-transparent px-0",
169
+ children: resolved.model
170
+ })
171
+ ] }),
146
172
  /* @__PURE__ */ jsxs(Tag, { children: [
147
173
  "reasoning:",
148
174
  " ",
@@ -155,32 +181,27 @@ function AgentDetailPage() {
155
181
  }),
156
182
  /* @__PURE__ */ jsxs("div", {
157
183
  className: "mt-3 flex flex-wrap gap-2",
158
- children: [resolved.agent.status === "archived" ? /* @__PURE__ */ jsx("button", {
159
- type: "button",
160
- onClick: unarchive,
161
- className: "ghost-btn",
162
- children: "unarchive"
163
- }) : /* @__PURE__ */ jsx("button", {
164
- type: "button",
165
- onClick: archive,
166
- className: "ghost-btn",
167
- children: "archive"
168
- }), /* @__PURE__ */ jsx("button", {
169
- type: "button",
170
- onClick: del,
171
- className: "ghost-btn border-[rgba(196,135,138,0.4)] text-danger hover:bg-[rgba(196,135,138,0.08)]",
172
- children: "delete permanently"
184
+ children: [resolved.agent.status === "archived" ? /* @__PURE__ */ jsx(Button, {
185
+ variant: "ghost",
186
+ onClick: () => void unarchive(),
187
+ children: "Restore"
188
+ }) : /* @__PURE__ */ jsx(Button, {
189
+ variant: "ghost",
190
+ onClick: () => setConfirmAction("archive"),
191
+ children: "Archive"
192
+ }), /* @__PURE__ */ jsx(Button, {
193
+ variant: "danger",
194
+ onClick: () => setConfirmAction("delete"),
195
+ children: "Delete permanently"
173
196
  })]
174
- }),
175
- /* @__PURE__ */ jsx(SettingsDetails, {
176
- agentId: resolved.agent.id,
177
- currentModelOverride: resolved.agent.modelOverride ?? null,
178
- profileDefaultModel: resolved.profile.defaultModel,
179
- currentReasoning: resolved.reasoningLevel,
180
- modelGroups
181
197
  })
182
198
  ]
183
199
  }),
200
+ actionError && /* @__PURE__ */ jsx("p", {
201
+ role: "alert",
202
+ className: "err",
203
+ children: actionError
204
+ }),
184
205
  resolved.agent.status === "archived" && /* @__PURE__ */ jsxs("div", {
185
206
  className: "mb-4 rounded-md border border-frost bg-fawn/35 px-4 py-2 text-[0.9em] text-chocolate",
186
207
  children: [
@@ -198,63 +219,99 @@ function AgentDetailPage() {
198
219
  }),
199
220
  /* @__PURE__ */ jsx(AgentTabs, {
200
221
  agentId: resolved.agent.id,
201
- active: "chat",
222
+ active: settingsMode ? "settings" : "chat",
202
223
  archived: resolved.agent.status === "archived"
203
224
  }),
204
- /* @__PURE__ */ jsx(SectionTitle, { children: "Chat" }),
205
- /* @__PURE__ */ jsx("div", {
206
- className: "h-[70vh]",
207
- children: /* @__PURE__ */ jsx(ChatPane, {
208
- agentId: resolved.agent.id,
209
- agentName: resolved.agent.name,
210
- initialMessages,
211
- initialSessionHead: sessionHead
225
+ !settingsMode ? /* @__PURE__ */ jsxs(Fragment, { children: [
226
+ /* @__PURE__ */ jsx(SectionTitle, { children: "Chat" }),
227
+ /* @__PURE__ */ jsx("div", {
228
+ className: "h-[70vh]",
229
+ children: /* @__PURE__ */ jsx(ChatPane, {
230
+ agentId: resolved.agent.id,
231
+ agentName: resolved.agent.name,
232
+ initialMessages,
233
+ initialSessionHead: sessionHead
234
+ })
235
+ }),
236
+ /* @__PURE__ */ jsx("p", {
237
+ className: "mt-2 text-[0.82em] text-mocha-light",
238
+ children: "chat history persists in bazilion across navigation and restarts."
212
239
  })
213
- }),
214
- /* @__PURE__ */ jsx("p", {
215
- className: "mt-2 text-[0.82em] text-mocha-light",
216
- children: "chat history persists in bazilion across navigation and restarts."
217
- }),
218
- /* @__PURE__ */ jsxs("section", {
219
- className: "mt-10",
240
+ ] }) : /* @__PURE__ */ jsxs("div", {
241
+ className: "space-y-6",
220
242
  children: [
221
- /* @__PURE__ */ jsx(SectionTitle, { children: "Team" }),
222
- /* @__PURE__ */ jsxs("p", {
223
- className: "text-[0.9em] text-mocha-light",
243
+ /* @__PURE__ */ jsx(SettingsDetails, {
244
+ agentId: resolved.agent.id,
245
+ currentModelOverride: resolved.agent.modelOverride ?? null,
246
+ profileDefaultModel: resolved.profile.defaultModel,
247
+ currentReasoning: resolved.reasoningLevel,
248
+ modelGroups
249
+ }),
250
+ /* @__PURE__ */ jsxs(SectionCard, {
251
+ title: "Team",
252
+ description: "Move this permanent Agent between Team workspaces with an exact policy preview.",
224
253
  children: [
225
- "Current team: ",
226
- /* @__PURE__ */ jsx("code", { children: resolved.team.id }),
227
- " (",
228
- resolved.team.name,
229
- ") —",
230
- " ",
231
- /* @__PURE__ */ jsx("code", { children: resolved.team.path }),
232
- ".",
233
- " ",
234
- /* @__PURE__ */ jsx("a", {
235
- href: `/teams/${resolved.team.id}`,
236
- children: "view / edit USER.md"
254
+ /* @__PURE__ */ jsx(SectionTitle, { children: "Team" }),
255
+ /* @__PURE__ */ jsxs("p", {
256
+ className: "text-[0.9em] text-mocha-light",
257
+ children: [
258
+ "Current team: ",
259
+ /* @__PURE__ */ jsx("code", { children: resolved.team.id }),
260
+ " (",
261
+ resolved.team.name,
262
+ ") —",
263
+ " ",
264
+ /* @__PURE__ */ jsx("code", { children: resolved.team.path }),
265
+ ".",
266
+ " ",
267
+ /* @__PURE__ */ jsx("a", {
268
+ href: `/teams/${resolved.team.id}`,
269
+ children: "view / edit USER.md"
270
+ })
271
+ ]
272
+ }),
273
+ /* @__PURE__ */ jsx(MoveGroupForm, {
274
+ agentId: resolved.agent.id,
275
+ currentTeamId: resolved.team.id,
276
+ teams
237
277
  })
238
278
  ]
239
279
  }),
240
- /* @__PURE__ */ jsx(MoveGroupForm, {
241
- agentId: resolved.agent.id,
242
- currentTeamId: resolved.team.id,
243
- teams
280
+ /* @__PURE__ */ jsx(SectionCard, {
281
+ title: "Skills",
282
+ description: "Attach or detach prompt skills for this Agent.",
283
+ children: /* @__PURE__ */ jsx(SkillsTable, {
284
+ agentId: resolved.agent.id,
285
+ attached: new Set(resolved.skills),
286
+ all: skills
287
+ })
288
+ }),
289
+ telegramConfigured && /* @__PURE__ */ jsx(SectionCard, {
290
+ title: "Telegram",
291
+ description: "Bind this Agent to its Telegram topic and control mirroring.",
292
+ children: /* @__PURE__ */ jsx(TelegramSection, { agent: resolved.agent })
244
293
  })
245
294
  ]
246
295
  }),
247
- /* @__PURE__ */ jsxs("section", {
248
- className: "mt-10",
249
- children: [/* @__PURE__ */ jsx(SectionTitle, { children: "Skills" }), /* @__PURE__ */ jsx(SkillsTable, {
250
- agentId: resolved.agent.id,
251
- attached: new Set(resolved.skills),
252
- all: skills
253
- })]
254
- }),
255
- telegramConfigured && /* @__PURE__ */ jsxs("section", {
256
- className: "mt-10",
257
- children: [/* @__PURE__ */ jsx(SectionTitle, { children: "Telegram" }), /* @__PURE__ */ jsx(TelegramSection, { agent: resolved.agent })]
296
+ /* @__PURE__ */ jsx(ConfirmDialog, {
297
+ open: confirmAction !== null,
298
+ onOpenChange: (open) => {
299
+ if (!open) setConfirmAction(null);
300
+ },
301
+ title: confirmAction === "delete" ? `Delete ${resolved.agent.name} permanently?` : `Archive ${resolved.agent.name}?`,
302
+ description: confirmAction === "delete" ? /* @__PURE__ */ jsx("p", { children: "This permanently removes messages, triggers, skill attachments, sessions, and the Agent's private on-disk directory. This cannot be undone." }) : /* @__PURE__ */ jsx("p", { children: "The Agent will stop receiving normal work and disappear from current lists. You can restore it later from “Show archived”." }),
303
+ confirmLabel: confirmAction === "delete" ? "Delete permanently" : "Archive Agent",
304
+ confirmVariant: confirmAction === "delete" ? "danger" : "primary",
305
+ onConfirm: async () => {
306
+ setActionError(null);
307
+ try {
308
+ if (confirmAction === "delete") await del();
309
+ else await archive();
310
+ } catch (error) {
311
+ setActionError(error instanceof Error ? error.message : String(error));
312
+ throw error;
313
+ }
314
+ }
258
315
  })
259
316
  ] });
260
317
  }
@@ -266,7 +323,7 @@ function SectionTitle({ children }) {
266
323
  }
267
324
  function Tag({ children }) {
268
325
  return /* @__PURE__ */ jsx("span", {
269
- className: "inline-flex items-center gap-1 rounded-full border border-frost bg-ivory px-3 py-0.5 text-[0.84em] text-mocha-light",
326
+ className: "inline-flex max-w-full min-w-0 flex-wrap items-center gap-1 break-all rounded-full border border-frost bg-ivory px-3 py-0.5 text-[0.84em] text-mocha-light",
270
327
  children
271
328
  });
272
329
  }
@@ -304,22 +361,20 @@ function SettingsDetails({ agentId, currentModelOverride, profileDefaultModel, c
304
361
  setSaving(false);
305
362
  }
306
363
  }
307
- return /* @__PURE__ */ jsxs("details", {
308
- className: "mt-3 text-[0.9em]",
309
- children: [/* @__PURE__ */ jsx("summary", {
310
- className: "cursor-pointer text-mocha-light",
311
- children: "settings"
312
- }), /* @__PURE__ */ jsxs("form", {
364
+ return /* @__PURE__ */ jsx(SectionCard, {
365
+ title: "Model and reasoning",
366
+ description: "Override the Agent template defaults for this Agent only.",
367
+ children: /* @__PURE__ */ jsxs("form", {
313
368
  onSubmit: save,
314
- className: "mt-2 flex flex-wrap items-end gap-3 border-t border-dashed border-frost py-3",
369
+ className: "grid gap-4 sm:grid-cols-2",
315
370
  children: [
316
371
  /* @__PURE__ */ jsxs("label", {
317
- className: "flex flex-col gap-1 text-[0.85em] text-mocha-light",
318
- children: ["model override", /* @__PURE__ */ jsxs("select", {
372
+ className: "m-0 flex min-w-0 flex-col gap-1 text-sm text-foreground",
373
+ children: ["Model override", /* @__PURE__ */ jsxs("select", {
319
374
  name: "modelOverride",
320
375
  value: modelOverride,
321
376
  onChange: (e) => setModelOverride(e.target.value),
322
- className: "min-w-[16rem] rounded-sm border border-frost bg-snow px-2 py-1.5",
377
+ className: "min-w-0",
323
378
  children: [
324
379
  /* @__PURE__ */ jsxs("option", {
325
380
  value: "",
@@ -347,33 +402,41 @@ function SettingsDetails({ agentId, currentModelOverride, profileDefaultModel, c
347
402
  })]
348
403
  }),
349
404
  /* @__PURE__ */ jsxs("label", {
350
- className: "flex flex-col gap-1 text-[0.85em] text-mocha-light",
351
- children: ["reasoning level", /* @__PURE__ */ jsx("select", {
405
+ className: "m-0 flex min-w-0 flex-col gap-1 text-sm text-foreground",
406
+ children: ["Reasoning level", /* @__PURE__ */ jsx("select", {
352
407
  name: "reasoningLevel",
353
408
  value: reasoning,
354
409
  onChange: (e) => setReasoning(e.target.value),
355
- className: "min-w-[16rem] rounded-sm border border-frost bg-snow px-2 py-1.5",
410
+ className: "min-w-0",
356
411
  children: REASONING_LEVELS.map((lvl) => /* @__PURE__ */ jsx("option", {
357
412
  value: lvl,
358
413
  children: lvl
359
414
  }, lvl))
360
415
  })]
361
416
  }),
362
- /* @__PURE__ */ jsx("button", {
363
- type: "submit",
364
- disabled: saving,
365
- children: saving ? "saving…" : "save"
366
- }),
367
- savedFlash && /* @__PURE__ */ jsx("span", {
368
- className: "text-[0.85em] text-[#3b7a3b]",
369
- children: "saved ✓"
370
- }),
371
- error && /* @__PURE__ */ jsx("span", {
372
- className: "text-[0.85em] text-danger",
373
- children: error
417
+ /* @__PURE__ */ jsxs("div", {
418
+ className: "flex flex-wrap items-center gap-3 sm:col-span-2",
419
+ children: [
420
+ /* @__PURE__ */ jsx(Button, {
421
+ variant: "primary",
422
+ type: "submit",
423
+ disabled: saving,
424
+ children: saving ? "Saving…" : "Save model settings"
425
+ }),
426
+ savedFlash && /* @__PURE__ */ jsx("span", {
427
+ role: "status",
428
+ className: "text-sm text-success",
429
+ children: "Saved"
430
+ }),
431
+ error && /* @__PURE__ */ jsx("span", {
432
+ role: "alert",
433
+ className: "text-sm text-danger",
434
+ children: error
435
+ })
436
+ ]
374
437
  })
375
438
  ]
376
- })]
439
+ })
377
440
  });
378
441
  }
379
442
  function MoveGroupForm({ agentId, currentTeamId, teams }) {
@@ -437,14 +500,14 @@ function MoveGroupForm({ agentId, currentTeamId, teams }) {
437
500
  className: "mt-2 flex flex-wrap items-end gap-2",
438
501
  children: [
439
502
  /* @__PURE__ */ jsxs("label", {
440
- className: "flex flex-col gap-1 text-[0.85em] text-mocha-light",
503
+ className: "flex min-w-0 flex-1 flex-col gap-1 text-[0.85em] text-mocha-light",
441
504
  children: ["move to:", /* @__PURE__ */ jsx("select", {
442
505
  value: teamId,
443
506
  onChange: (e) => {
444
507
  setTeamId(e.target.value);
445
508
  setPreview(null);
446
509
  },
447
- className: "min-w-[18rem] rounded-sm border border-frost bg-snow px-2 py-1.5",
510
+ className: "w-full min-w-0 rounded-sm border border-frost bg-snow px-2 py-1.5 sm:min-w-[18rem]",
448
511
  children: teams.map((g) => /* @__PURE__ */ jsxs("option", {
449
512
  value: g.id,
450
513
  children: [
@@ -473,13 +536,15 @@ function MoveGroupForm({ agentId, currentTeamId, teams }) {
473
536
  })]
474
537
  })]
475
538
  }),
476
- /* @__PURE__ */ jsx("button", {
539
+ /* @__PURE__ */ jsx(Button, {
540
+ variant: "primary",
477
541
  type: "submit",
478
542
  disabled: moving || teamId === currentTeamId,
479
543
  children: moving ? "working…" : preview ? "commit reviewed move" : "review move"
480
544
  }),
481
545
  err && /* @__PURE__ */ jsx("span", {
482
- className: "text-[0.85em] text-danger",
546
+ role: "alert",
547
+ className: "basis-full text-[0.85em] text-danger",
483
548
  children: err
484
549
  }),
485
550
  preview && /* @__PURE__ */ jsxs("div", {
@@ -512,9 +577,14 @@ function SkillsTable({ agentId, attached, all }) {
512
577
  const router = useRouter();
513
578
  const [pending, setPending] = useState(null);
514
579
  const [err, setErr] = useState(null);
515
- async function attach(skill) {
580
+ const [riskySkill, setRiskySkill] = useState(null);
581
+ const [detachSkill, setDetachSkill] = useState(null);
582
+ async function attach(skill, findingsConfirmed = false) {
516
583
  const findings = skill.scanFindings ?? [];
517
- if (!(findings.length === 0 || confirm(`Skill "${skill.name}" has ${findings.length} scan finding${findings.length === 1 ? "" : "s"}. Attach it anyway?`))) return;
584
+ if (findings.length > 0 && !findingsConfirmed) {
585
+ setRiskySkill(skill);
586
+ return;
587
+ }
518
588
  setPending(skill.name);
519
589
  setErr(null);
520
590
  try {
@@ -532,7 +602,8 @@ function SkillsTable({ agentId, attached, all }) {
532
602
  }
533
603
  await router.invalidate();
534
604
  } catch (e) {
535
- setErr(e.message);
605
+ setErr(e instanceof Error ? e.message : String(e));
606
+ throw e;
536
607
  } finally {
537
608
  setPending(null);
538
609
  }
@@ -549,6 +620,7 @@ function SkillsTable({ agentId, attached, all }) {
549
620
  await router.invalidate();
550
621
  } catch (e) {
551
622
  setErr(e.message);
623
+ throw e;
552
624
  } finally {
553
625
  setPending(null);
554
626
  }
@@ -557,39 +629,121 @@ function SkillsTable({ agentId, attached, all }) {
557
629
  className: "text-[0.9em] text-mocha-light",
558
630
  children: "no skills installed"
559
631
  });
560
- return /* @__PURE__ */ jsxs(Fragment, { children: [err && /* @__PURE__ */ jsx("p", {
561
- className: "mb-2 text-[0.85em] text-danger",
562
- children: err
563
- }), /* @__PURE__ */ jsxs("table", { children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
564
- /* @__PURE__ */ jsx("th", { children: "name" }),
565
- /* @__PURE__ */ jsx("th", { children: "description" }),
566
- /* @__PURE__ */ jsx("th", { children: "scan" }),
567
- /* @__PURE__ */ jsx("th", {})
568
- ] }) }), /* @__PURE__ */ jsx("tbody", { children: all.map((s) => {
569
- const isAttached = attached.has(s.name);
570
- const busy = pending === s.name;
571
- return /* @__PURE__ */ jsxs("tr", { children: [
572
- /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx("code", { children: s.name }) }),
573
- /* @__PURE__ */ jsx("td", { children: s.description || /* @__PURE__ */ jsx("span", {
574
- className: "text-mocha-light",
575
- children: "—"
576
- }) }),
577
- /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(SkillFindingSummary, { findings: s.scanFindings ?? [] }) }),
578
- /* @__PURE__ */ jsx("td", { children: isAttached ? /* @__PURE__ */ jsx("button", {
579
- type: "button",
580
- className: "ghost-btn",
581
- disabled: busy,
582
- onClick: () => detach(s.name),
583
- children: busy ? "…" : "detach"
584
- }) : /* @__PURE__ */ jsx("button", {
585
- type: "button",
586
- className: "ghost-btn",
587
- disabled: busy,
588
- onClick: () => attach(s),
589
- children: busy ? "…" : "attach"
590
- }) })
591
- ] }, s.name);
592
- }) })] })] });
632
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
633
+ err && /* @__PURE__ */ jsx("p", {
634
+ role: "alert",
635
+ className: "mb-2 text-[0.85em] text-danger",
636
+ children: err
637
+ }),
638
+ /* @__PURE__ */ jsxs("table", {
639
+ className: "hidden md:table",
640
+ children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
641
+ /* @__PURE__ */ jsx("th", { children: "name" }),
642
+ /* @__PURE__ */ jsx("th", { children: "description" }),
643
+ /* @__PURE__ */ jsx("th", { children: "scan" }),
644
+ /* @__PURE__ */ jsx("th", {})
645
+ ] }) }), /* @__PURE__ */ jsx("tbody", { children: all.map((s) => {
646
+ const isAttached = attached.has(s.name);
647
+ const busy = pending === s.name;
648
+ return /* @__PURE__ */ jsxs("tr", { children: [
649
+ /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx("code", { children: s.name }) }),
650
+ /* @__PURE__ */ jsx("td", { children: s.description || /* @__PURE__ */ jsx("span", {
651
+ className: "text-mocha-light",
652
+ children: "—"
653
+ }) }),
654
+ /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(SkillFindingSummary, { findings: s.scanFindings ?? [] }) }),
655
+ /* @__PURE__ */ jsx("td", { children: isAttached ? /* @__PURE__ */ jsx(Button, {
656
+ variant: "ghost",
657
+ disabled: busy,
658
+ onClick: () => setDetachSkill(s.name),
659
+ children: busy ? "…" : "detach"
660
+ }) : /* @__PURE__ */ jsx(Button, {
661
+ variant: "ghost",
662
+ disabled: busy,
663
+ onClick: () => void attach(s).catch(() => {}),
664
+ children: busy ? "…" : "attach"
665
+ }) })
666
+ ] }, s.name);
667
+ }) })]
668
+ }),
669
+ /* @__PURE__ */ jsx("div", {
670
+ className: "grid gap-3 md:hidden",
671
+ children: all.map((skill) => {
672
+ const isAttached = attached.has(skill.name);
673
+ const busy = pending === skill.name;
674
+ return /* @__PURE__ */ jsxs("article", {
675
+ className: "min-w-0 rounded-xl border border-border bg-muted/20 p-4",
676
+ children: [
677
+ /* @__PURE__ */ jsxs("div", {
678
+ className: "flex min-w-0 items-start justify-between gap-3",
679
+ children: [/* @__PURE__ */ jsx("code", {
680
+ className: "min-w-0 break-all font-mono text-sm",
681
+ children: skill.name
682
+ }), /* @__PURE__ */ jsx("span", {
683
+ className: `shrink-0 text-xs font-semibold ${isAttached ? "text-success" : "text-muted-foreground"}`,
684
+ children: isAttached ? "Attached" : "Available"
685
+ })]
686
+ }),
687
+ /* @__PURE__ */ jsx("p", {
688
+ className: "mt-2 text-sm text-muted-foreground",
689
+ children: skill.description || "No description provided."
690
+ }),
691
+ /* @__PURE__ */ jsx("div", {
692
+ className: "mt-2",
693
+ children: /* @__PURE__ */ jsx(SkillFindingSummary, { findings: skill.scanFindings ?? [] })
694
+ }),
695
+ /* @__PURE__ */ jsx("div", {
696
+ className: "mt-3",
697
+ children: isAttached ? /* @__PURE__ */ jsx(Button, {
698
+ variant: "ghost",
699
+ disabled: busy,
700
+ onClick: () => setDetachSkill(skill.name),
701
+ children: busy ? "Detaching…" : "Detach"
702
+ }) : /* @__PURE__ */ jsx(Button, {
703
+ variant: "ghost",
704
+ disabled: busy,
705
+ onClick: () => void attach(skill).catch(() => {}),
706
+ children: busy ? "Attaching…" : "Attach"
707
+ })
708
+ })
709
+ ]
710
+ }, skill.name);
711
+ })
712
+ }),
713
+ /* @__PURE__ */ jsx(ConfirmDialog, {
714
+ open: riskySkill !== null,
715
+ onOpenChange: (open) => {
716
+ if (!open) setRiskySkill(null);
717
+ },
718
+ title: `Attach ${riskySkill?.name ?? "skill"} despite scan findings?`,
719
+ description: /* @__PURE__ */ jsxs("div", {
720
+ className: "space-y-2",
721
+ children: [/* @__PURE__ */ jsxs("p", { children: [
722
+ "Static scanning found ",
723
+ riskySkill?.scanFindings?.length ?? 0,
724
+ " potentially unsafe instruction",
725
+ riskySkill?.scanFindings?.length === 1 ? "" : "s",
726
+ ". Review the findings before allowing this skill into the Agent's prompt."
727
+ ] }), /* @__PURE__ */ jsx(SkillFindingSummary, { findings: riskySkill?.scanFindings ?? [] })]
728
+ }),
729
+ confirmLabel: "Attach despite findings",
730
+ onConfirm: async () => {
731
+ if (riskySkill) await attach(riskySkill, true);
732
+ }
733
+ }),
734
+ /* @__PURE__ */ jsx(ConfirmDialog, {
735
+ open: detachSkill !== null,
736
+ onOpenChange: (open) => {
737
+ if (!open) setDetachSkill(null);
738
+ },
739
+ title: `Detach ${detachSkill ?? "skill"}?`,
740
+ description: /* @__PURE__ */ jsx("p", { children: "This removes the skill's instructions from this Agent's future turns. It does not uninstall the skill, and you can attach it again later." }),
741
+ confirmLabel: "Detach skill",
742
+ onConfirm: async () => {
743
+ if (detachSkill) await detach(detachSkill);
744
+ }
745
+ })
746
+ ] });
593
747
  }
594
748
  function SkillFindingSummary({ findings }) {
595
749
  if (findings.length === 0) return /* @__PURE__ */ jsx("span", {
@@ -627,6 +781,7 @@ function TelegramSection({ agent }) {
627
781
  const [error, setError] = useState(null);
628
782
  const [mirrorMode, setMirrorMode] = useState(agent.telegramMirrorMode);
629
783
  const [iconEmoji, setIconEmoji] = useState(agent.telegramIconEmoji ?? "");
784
+ const [confirmUnbind, setConfirmUnbind] = useState(false);
630
785
  const isBound = agent.telegramTopicId !== null;
631
786
  async function bind() {
632
787
  setBusy(true);
@@ -647,15 +802,18 @@ function TelegramSection({ agent }) {
647
802
  }
648
803
  }
649
804
  async function unbind() {
650
- if (!confirm("Unbind this agent from its Telegram topic? The topic stays in Telegram as an orphan.")) return;
651
805
  setBusy(true);
652
806
  setError(null);
653
807
  try {
654
808
  const res = await fetch(`/api/agents/${encodeURIComponent(agent.id)}/telegram/binding`, { method: "DELETE" });
655
- if (!res.ok) throw new Error(res.statusText);
809
+ if (!res.ok && res.status !== 204) {
810
+ const body = await res.json().catch(() => null);
811
+ throw new Error(body?.error ?? `Could not unbind Telegram topic (${res.status})`);
812
+ }
656
813
  await router.invalidate();
657
814
  } catch (e) {
658
- setError(e.message);
815
+ setError(e instanceof Error ? e.message : String(e));
816
+ throw e;
659
817
  } finally {
660
818
  setBusy(false);
661
819
  }
@@ -689,11 +847,11 @@ function TelegramSection({ agent }) {
689
847
  setError(e.message);
690
848
  }
691
849
  }
692
- return /* @__PURE__ */ jsxs("div", {
850
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
693
851
  className: "text-[0.9em]",
694
852
  children: [
695
853
  /* @__PURE__ */ jsx("div", {
696
- className: "mb-3 flex items-center gap-3",
854
+ className: "mb-3 flex flex-wrap items-center gap-3",
697
855
  children: isBound ? /* @__PURE__ */ jsxs(Fragment, { children: [
698
856
  /* @__PURE__ */ jsx("span", {
699
857
  className: "rounded-full bg-success/10 px-2 py-0.5 text-xs font-semibold text-success",
@@ -711,12 +869,11 @@ function TelegramSection({ agent }) {
711
869
  title: "Open the topic in Telegram (works on desktop/Android; iOS shows the topic list)",
712
870
  children: "open in Telegram"
713
871
  }),
714
- /* @__PURE__ */ jsx("button", {
715
- type: "button",
716
- onClick: unbind,
872
+ /* @__PURE__ */ jsx(Button, {
873
+ variant: "danger",
874
+ onClick: () => setConfirmUnbind(true),
717
875
  disabled: busy,
718
- className: "ghost-btn border-[rgba(196,135,138,0.4)] text-danger hover:bg-[rgba(196,135,138,0.08)]",
719
- children: "unbind"
876
+ children: "Unbind"
720
877
  })
721
878
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
722
879
  className: "rounded-full bg-warning/10 px-2 py-0.5 text-xs font-semibold text-warning",
@@ -731,11 +888,11 @@ function TelegramSection({ agent }) {
731
888
  })] })
732
889
  }),
733
890
  /* @__PURE__ */ jsxs("div", {
734
- className: "flex items-center gap-2",
891
+ className: "flex flex-col gap-1 sm:flex-row sm:items-center sm:gap-2",
735
892
  children: [/* @__PURE__ */ jsx("label", {
736
893
  htmlFor: "mirror-mode",
737
- className: "text-mocha-light",
738
- children: "mirror mode:"
894
+ className: "m-0 text-mocha-light",
895
+ children: "Mirror mode"
739
896
  }), /* @__PURE__ */ jsxs("select", {
740
897
  id: "mirror-mode",
741
898
  value: mirrorMode,
@@ -752,12 +909,12 @@ function TelegramSection({ agent }) {
752
909
  })]
753
910
  }),
754
911
  /* @__PURE__ */ jsxs("div", {
755
- className: "mt-2 flex items-center gap-2",
912
+ className: "mt-3 flex flex-wrap items-end gap-2",
756
913
  children: [
757
914
  /* @__PURE__ */ jsx("label", {
758
915
  htmlFor: "topic-icon",
759
- className: "text-mocha-light",
760
- children: "topic icon:"
916
+ className: "m-0 text-mocha-light",
917
+ children: "Topic icon"
761
918
  }),
762
919
  /* @__PURE__ */ jsx("input", {
763
920
  id: "topic-icon",
@@ -778,6 +935,7 @@ function TelegramSection({ agent }) {
778
935
  ]
779
936
  }),
780
937
  error && /* @__PURE__ */ jsx("p", {
938
+ role: "alert",
781
939
  className: "mt-2 text-sm text-danger",
782
940
  children: error
783
941
  }),
@@ -786,7 +944,14 @@ function TelegramSection({ agent }) {
786
944
  children: "When bound, every assistant turn for this agent gets mirrored to the topic. Typing in the topic triggers a new turn. iOS Telegram clients have a known limitation that prevents inline link deep-links from opening directly into a topic — bound state is still functional; navigate via the topic list manually."
787
945
  })
788
946
  ]
789
- });
947
+ }), /* @__PURE__ */ jsx(ConfirmDialog, {
948
+ open: confirmUnbind,
949
+ onOpenChange: setConfirmUnbind,
950
+ title: `Unbind ${agent.name} from Telegram?`,
951
+ description: /* @__PURE__ */ jsx("p", { children: "Telegram ingress and mirroring stop for this Agent. The existing forum topic remains in Telegram as an orphan until you remove it there." }),
952
+ confirmLabel: "Unbind Telegram topic",
953
+ onConfirm: unbind
954
+ })] });
790
955
  }
791
956
  //#endregion
792
957
  export { AgentDetailPage as component };