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
@@ -0,0 +1,958 @@
1
+ import { t as Route } from "./config-BlMkHStx.js";
2
+ import { a as StatusBadge$1, t as EmptyState } from "./Page-Bz-ydB8j.js";
3
+ import { t as Button } from "./Button-Dsnw22OF.js";
4
+ import { t as ConfirmDialog } from "./ConfirmDialog-C-MPYYSU.js";
5
+ import { t as ConfigPage } from "./ConfigPage-CiQ-gxmJ.js";
6
+ import { t as FieldRow } from "./FieldRow-DCOF07kl.js";
7
+ import { useEffect, useMemo, useRef, useState } from "react";
8
+ import { useRouter } from "@tanstack/react-router";
9
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
+ import { CheckCircle2, ChevronDown, ChevronRight, Search, Server, ShieldCheck } from "lucide-react";
11
+ //#region src/components/ExecutionSecurityCard.tsx
12
+ function ExecutionSecurityCard({ status }) {
13
+ const configured = status.configuredOperatorHttp;
14
+ const protectedTurns = status.protectedUnattendedTurns;
15
+ return /* @__PURE__ */ jsxs("section", {
16
+ className: "overflow-hidden rounded-lg border bg-card",
17
+ children: [/* @__PURE__ */ jsxs("header", {
18
+ className: "border-b px-4 py-3",
19
+ children: [/* @__PURE__ */ jsx("h2", {
20
+ className: "font-semibold",
21
+ children: "Execution security"
22
+ }), /* @__PURE__ */ jsx("p", {
23
+ className: "mt-1 text-xs text-muted-foreground",
24
+ children: "Operator HTTP requests keep their configured compatibility behavior. Unattended sources use a separate mandatory protected baseline."
25
+ })]
26
+ }), /* @__PURE__ */ jsxs("div", {
27
+ className: "grid gap-4 p-4 lg:grid-cols-2",
28
+ children: [/* @__PURE__ */ jsxs("section", {
29
+ className: "rounded-md border bg-muted/20 p-3",
30
+ children: [
31
+ /* @__PURE__ */ jsxs("div", {
32
+ className: "mb-3 flex flex-wrap items-center justify-between gap-2",
33
+ children: [/* @__PURE__ */ jsx("h3", {
34
+ className: "font-semibold",
35
+ children: "Configured operator HTTP"
36
+ }), /* @__PURE__ */ jsx(StatusBadge, {
37
+ ok: false,
38
+ children: "legacy · unprotected"
39
+ })]
40
+ }),
41
+ /* @__PURE__ */ jsxs("dl", {
42
+ className: "space-y-2 text-sm",
43
+ children: [
44
+ /* @__PURE__ */ jsx(StatusRow, {
45
+ label: "Coding surface",
46
+ value: codingSurfaceLabel(configured.codingSurface)
47
+ }),
48
+ /* @__PURE__ */ jsx(StatusRow, {
49
+ label: "Docker image",
50
+ value: configured.dockerImage,
51
+ mono: true
52
+ }),
53
+ /* @__PURE__ */ jsx(StatusRow, {
54
+ label: "Browser",
55
+ value: configured.browser
56
+ }),
57
+ /* @__PURE__ */ jsx(StatusRow, {
58
+ label: "MCP",
59
+ value: configured.mcp
60
+ })
61
+ ]
62
+ }),
63
+ /* @__PURE__ */ jsx("p", {
64
+ className: "mt-3 text-xs text-muted-foreground",
65
+ children: "This compatibility branch is for operator requests; Telegram and unattended delivery never select it."
66
+ })
67
+ ]
68
+ }), /* @__PURE__ */ jsxs("section", {
69
+ className: `rounded-md border p-3 ${protectedTurns.baseRuntimeReady ? "border-success/25 bg-success/5" : "border-warning/25 bg-warning/10"}`,
70
+ children: [
71
+ /* @__PURE__ */ jsxs("div", {
72
+ className: "mb-3 flex flex-wrap items-center justify-between gap-2",
73
+ children: [/* @__PURE__ */ jsx("h3", {
74
+ className: "font-semibold",
75
+ children: "Protected unattended turns"
76
+ }), /* @__PURE__ */ jsx(StatusBadge, {
77
+ ok: protectedTurns.baseRuntimeReady,
78
+ children: protectedTurns.baseRuntimeReady ? "base runtime ready" : "base runtime unavailable"
79
+ })]
80
+ }),
81
+ /* @__PURE__ */ jsx("p", {
82
+ className: "mb-3 text-xs text-muted-foreground",
83
+ children: "Telegram, schedules, inbox wake-ups, and approval delivery cannot select the legacy surface."
84
+ }),
85
+ /* @__PURE__ */ jsxs("dl", {
86
+ className: "space-y-2 text-sm",
87
+ children: [
88
+ /* @__PURE__ */ jsx(StatusRow, {
89
+ label: "Coding surface",
90
+ value: "Docker only"
91
+ }),
92
+ /* @__PURE__ */ jsx(StatusRow, {
93
+ label: "Docker",
94
+ value: protectedTurns.docker.ready ? "ready" : "unavailable",
95
+ ok: protectedTurns.docker.ready
96
+ }),
97
+ /* @__PURE__ */ jsx(StatusRow, {
98
+ label: "Docker image",
99
+ value: protectedTurns.docker.image,
100
+ mono: true
101
+ }),
102
+ protectedTurns.docker.reason && /* @__PURE__ */ jsx(StatusRow, {
103
+ label: "Docker reason",
104
+ value: protectedTurns.docker.reason
105
+ }),
106
+ /* @__PURE__ */ jsx(StatusRow, {
107
+ label: "OpenAI Codex enabled",
108
+ value: yesNo(protectedTurns.openaiCodex.enabled),
109
+ ok: protectedTurns.openaiCodex.enabled
110
+ }),
111
+ /* @__PURE__ */ jsx(StatusRow, {
112
+ label: "ChatGPT connected",
113
+ value: yesNo(protectedTurns.openaiCodex.connected),
114
+ ok: protectedTurns.openaiCodex.connected
115
+ }),
116
+ /* @__PURE__ */ jsx(StatusRow, {
117
+ label: "OpenAI access",
118
+ value: openAIAccessLabel(protectedTurns.openaiCodex),
119
+ ok: protectedTurns.openaiCodex.accessCurrent || protectedTurns.openaiCodex.refreshOnNextTurn
120
+ }),
121
+ /* @__PURE__ */ jsx(StatusRow, {
122
+ label: "OpenAI Codex baseline eligible",
123
+ value: yesNo(protectedTurns.openaiCodex.baselineEligible),
124
+ ok: protectedTurns.openaiCodex.baselineEligible
125
+ }),
126
+ /* @__PURE__ */ jsx(StatusRow, {
127
+ label: "Browser",
128
+ value: protectedTurns.browser,
129
+ ok: true
130
+ }),
131
+ /* @__PURE__ */ jsx(StatusRow, {
132
+ label: "MCP",
133
+ value: protectedTurns.mcp,
134
+ ok: true
135
+ })
136
+ ]
137
+ }),
138
+ protectedTurns.remediation && /* @__PURE__ */ jsxs("p", {
139
+ className: "mt-3 rounded-md border border-warning/25 bg-background/60 px-3 py-2 text-xs text-warning",
140
+ children: [
141
+ /* @__PURE__ */ jsx("strong", { children: "Remediation:" }),
142
+ " ",
143
+ protectedTurns.remediation
144
+ ]
145
+ }),
146
+ /* @__PURE__ */ jsx("p", {
147
+ className: "mt-3 text-xs text-muted-foreground",
148
+ children: "Every turn separately validates its selected normal/review model, bound OAuth refresh, and Team/input/memory/skill mounts and paths before execution."
149
+ })
150
+ ]
151
+ })]
152
+ })]
153
+ });
154
+ }
155
+ function StatusBadge({ ok, children }) {
156
+ return /* @__PURE__ */ jsx("span", {
157
+ className: `rounded-full px-2 py-0.5 text-xs font-semibold uppercase ${ok ? "bg-success/10 text-success" : "bg-warning/10 text-warning"}`,
158
+ children
159
+ });
160
+ }
161
+ function StatusRow({ label, value, ok, mono = false }) {
162
+ return /* @__PURE__ */ jsxs("div", {
163
+ className: "flex items-start justify-between gap-3",
164
+ children: [/* @__PURE__ */ jsx("dt", {
165
+ className: "text-muted-foreground",
166
+ children: label
167
+ }), /* @__PURE__ */ jsx("dd", {
168
+ className: `${mono ? "font-mono" : "font-medium"} text-right ${ok === void 0 ? "" : ok ? "text-success" : "text-warning"}`,
169
+ children: value
170
+ })]
171
+ });
172
+ }
173
+ function codingSurfaceLabel(surface) {
174
+ if (surface === "host") return "Host tools";
175
+ if (surface === "docker") return "Docker only";
176
+ return "Unavailable";
177
+ }
178
+ function yesNo(value) {
179
+ return value ? "yes" : "no";
180
+ }
181
+ function openAIAccessLabel(status) {
182
+ if (status.accessCurrent) return "current";
183
+ if (status.refreshOnNextTurn) return "refresh on next turn";
184
+ return "unavailable";
185
+ }
186
+ //#endregion
187
+ //#region src/lib/provider-presentation.ts
188
+ var RECOMMENDED = new Set([
189
+ "openai-codex",
190
+ "openai",
191
+ "anthropic",
192
+ "google"
193
+ ]);
194
+ var LOCAL = new Set([
195
+ "ollama",
196
+ "lmstudio",
197
+ "llamacpp"
198
+ ]);
199
+ function providerHasConfiguration(provider) {
200
+ return provider.enabled || provider.curated.length > 0 || provider.fields.some((field) => field.set);
201
+ }
202
+ function providerMatches(provider, query) {
203
+ const needle = query.trim().toLocaleLowerCase();
204
+ if (!needle) return true;
205
+ return [
206
+ provider.id,
207
+ provider.displayName,
208
+ provider.hint ?? "",
209
+ provider.envHint,
210
+ ...provider.fields.flatMap((field) => [field.label, field.envVar]),
211
+ ...provider.curated,
212
+ ...provider.catalog
213
+ ].some((value) => value.toLocaleLowerCase().includes(needle));
214
+ }
215
+ function groupProviders(providers, query = "") {
216
+ const visible = providers.filter((provider) => providerMatches(provider, query));
217
+ const configured = visible.filter(providerHasConfiguration);
218
+ const configuredIds = new Set(configured.map((provider) => provider.id));
219
+ const remaining = visible.filter((provider) => !configuredIds.has(provider.id));
220
+ return [
221
+ {
222
+ key: "configured",
223
+ title: "Configured",
224
+ description: "Providers you enabled, added models to, or saved credentials for.",
225
+ providers: configured
226
+ },
227
+ {
228
+ key: "recommended",
229
+ title: "Recommended starting points",
230
+ description: "The simplest hosted options for a first Bazilion conversation.",
231
+ providers: remaining.filter((provider) => RECOMMENDED.has(provider.id))
232
+ },
233
+ {
234
+ key: "local",
235
+ title: "Local models",
236
+ description: "Use a model server on the same machine without exposing the daemon.",
237
+ providers: remaining.filter((provider) => LOCAL.has(provider.id))
238
+ },
239
+ {
240
+ key: "more",
241
+ title: "More providers",
242
+ description: "Specialist, regional, enterprise, and subscription endpoints.",
243
+ providers: remaining.filter((provider) => !RECOMMENDED.has(provider.id) && !LOCAL.has(provider.id))
244
+ }
245
+ ].filter((section) => section.providers.length > 0);
246
+ }
247
+ function providerReadiness(provider) {
248
+ if (!provider.enabled) return providerHasConfiguration(provider) ? {
249
+ label: "Saved, disabled",
250
+ tone: "neutral"
251
+ } : {
252
+ label: "Not configured",
253
+ tone: "neutral"
254
+ };
255
+ if (provider.curated.length === 0) return {
256
+ label: "Needs a model",
257
+ tone: "warning"
258
+ };
259
+ return {
260
+ label: "Configured, unverified",
261
+ tone: "warning"
262
+ };
263
+ }
264
+ //#endregion
265
+ //#region src/routes/config/index.tsx?tsr-split=component
266
+ function ProvidersPage() {
267
+ const { providers, openaiCodex, executionSecurity } = Route.useLoaderData();
268
+ const setupComplete = providers.some((p) => p.enabled && p.curated.length > 0);
269
+ const startedComplete = useRef(setupComplete);
270
+ const [showCompletion, setShowCompletion] = useState(false);
271
+ const [query, setQuery] = useState("");
272
+ const sections = useMemo(() => groupProviders(providers, query), [providers, query]);
273
+ const configured = providers.filter(providerHasConfiguration).length;
274
+ const enabled = providers.filter((provider) => provider.enabled).length;
275
+ useEffect(() => {
276
+ if (!startedComplete.current && setupComplete) setShowCompletion(true);
277
+ }, [setupComplete]);
278
+ return /* @__PURE__ */ jsxs(ConfigPage, {
279
+ active: "providers",
280
+ title: "Providers",
281
+ description: /* @__PURE__ */ jsx(Fragment, { children: "Connect the model services your agents may use. Credentials stay encrypted; advanced endpoint and environment names remain available inside each provider." }),
282
+ children: [
283
+ /* @__PURE__ */ jsxs("div", {
284
+ className: "grid gap-3 sm:grid-cols-3",
285
+ "aria-label": "Provider summary",
286
+ children: [
287
+ /* @__PURE__ */ jsx(SummaryStat, {
288
+ label: "Configured",
289
+ value: configured,
290
+ detail: "credentials, models, or toggle"
291
+ }),
292
+ /* @__PURE__ */ jsx(SummaryStat, {
293
+ label: "Enabled",
294
+ value: enabled,
295
+ detail: "available to agent runtime"
296
+ }),
297
+ /* @__PURE__ */ jsx(SummaryStat, {
298
+ label: "Selected models",
299
+ value: providers.reduce((count, provider) => count + (provider.enabled ? provider.curated.length : 0), 0),
300
+ detail: "configured; test connectivity separately"
301
+ })
302
+ ]
303
+ }),
304
+ /* @__PURE__ */ jsxs("details", {
305
+ className: "rounded-2xl border border-border bg-card shadow-baziu-sm",
306
+ children: [/* @__PURE__ */ jsxs("summary", {
307
+ className: "flex min-h-12 cursor-pointer list-none items-center gap-3 px-4 py-3 text-sm font-semibold text-foreground marker:hidden sm:px-5",
308
+ children: [
309
+ /* @__PURE__ */ jsx(ShieldCheck, {
310
+ className: "size-4 text-primary",
311
+ "aria-hidden": "true"
312
+ }),
313
+ "Execution security",
314
+ /* @__PURE__ */ jsx("span", {
315
+ className: "ml-auto text-xs font-normal text-muted-foreground",
316
+ children: "Inspect host and protected-turn posture"
317
+ }),
318
+ /* @__PURE__ */ jsx(ChevronDown, {
319
+ className: "size-4 text-muted-foreground",
320
+ "aria-hidden": "true"
321
+ })
322
+ ]
323
+ }), /* @__PURE__ */ jsx("div", {
324
+ className: "border-t border-border p-3 sm:p-4",
325
+ children: /* @__PURE__ */ jsx(ExecutionSecurityCard, { status: executionSecurity })
326
+ })]
327
+ }),
328
+ !setupComplete && /* @__PURE__ */ jsx(SetupBlockerBanner, {
329
+ providers,
330
+ openaiCodex
331
+ }),
332
+ showCompletion && /* @__PURE__ */ jsx("section", {
333
+ role: "status",
334
+ className: "rounded-2xl border border-success/30 bg-success/10 p-5 text-sm",
335
+ children: /* @__PURE__ */ jsxs("div", {
336
+ className: "flex items-start gap-3",
337
+ children: [/* @__PURE__ */ jsx(CheckCircle2, {
338
+ className: "mt-0.5 size-5 shrink-0 text-success",
339
+ "aria-hidden": "true"
340
+ }), /* @__PURE__ */ jsxs("div", {
341
+ className: "min-w-0 flex-1",
342
+ children: [
343
+ /* @__PURE__ */ jsx("h2", {
344
+ className: "m-0 font-body text-base font-semibold text-foreground",
345
+ children: "Your default workspace is ready"
346
+ }),
347
+ /* @__PURE__ */ jsx("p", {
348
+ className: "mt-1 text-muted-foreground",
349
+ children: "Bazilion created the default Agent template and Team. Test the selected model below before relying on it, or continue to spawn your first agent."
350
+ }),
351
+ /* @__PURE__ */ jsxs("div", {
352
+ className: "mt-3 flex flex-wrap gap-2",
353
+ children: [/* @__PURE__ */ jsxs("a", {
354
+ href: "/agents",
355
+ className: "btn-primary no-underline",
356
+ children: ["Spawn your first agent", /* @__PURE__ */ jsx(ChevronRight, {
357
+ className: "size-4",
358
+ "aria-hidden": "true"
359
+ })]
360
+ }), /* @__PURE__ */ jsx(Button, {
361
+ variant: "ghost",
362
+ onClick: () => setShowCompletion(false),
363
+ children: "Keep configuring"
364
+ })]
365
+ })
366
+ ]
367
+ })]
368
+ })
369
+ }),
370
+ /* @__PURE__ */ jsxs("div", {
371
+ className: "rounded-2xl border border-border bg-card p-4 shadow-baziu-sm sm:p-5",
372
+ children: [
373
+ /* @__PURE__ */ jsx("label", {
374
+ htmlFor: "provider-search",
375
+ className: "m-0 text-sm font-semibold text-foreground",
376
+ children: "Find a provider"
377
+ }),
378
+ /* @__PURE__ */ jsxs("div", {
379
+ className: "relative mt-2",
380
+ children: [/* @__PURE__ */ jsx(Search, {
381
+ className: "pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground",
382
+ "aria-hidden": "true"
383
+ }), /* @__PURE__ */ jsx("input", {
384
+ id: "provider-search",
385
+ type: "search",
386
+ value: query,
387
+ onChange: (event) => setQuery(event.target.value),
388
+ placeholder: "Search by service, model, or advanced key",
389
+ className: "pl-9"
390
+ })]
391
+ }),
392
+ /* @__PURE__ */ jsx("p", {
393
+ className: "mt-2 text-xs leading-5 text-muted-foreground",
394
+ children: "Start with one provider. Everything else stays collapsed until you need it."
395
+ })
396
+ ]
397
+ }),
398
+ sections.length === 0 ? /* @__PURE__ */ jsx(EmptyState, {
399
+ icon: /* @__PURE__ */ jsx(Search, {
400
+ className: "size-4",
401
+ "aria-hidden": "true"
402
+ }),
403
+ title: "No providers match",
404
+ description: `Try another search instead of “${query}”.`,
405
+ actions: /* @__PURE__ */ jsx(Button, {
406
+ variant: "ghost",
407
+ onClick: () => setQuery(""),
408
+ children: "Clear search"
409
+ })
410
+ }) : /* @__PURE__ */ jsx("div", {
411
+ className: "space-y-4",
412
+ children: sections.map((section) => /* @__PURE__ */ jsxs("details", {
413
+ open: Boolean(query) || section.key === "configured" || !setupComplete && section.key === "recommended",
414
+ className: "group/providers overflow-hidden rounded-2xl border border-border bg-card shadow-baziu-sm",
415
+ children: [/* @__PURE__ */ jsxs("summary", {
416
+ className: "flex cursor-pointer list-none items-center gap-3 px-4 py-4 marker:hidden sm:px-5",
417
+ children: [
418
+ /* @__PURE__ */ jsx("span", {
419
+ className: "flex size-9 shrink-0 items-center justify-center rounded-xl bg-accent text-accent-foreground",
420
+ children: /* @__PURE__ */ jsx(Server, {
421
+ className: "size-4",
422
+ "aria-hidden": "true"
423
+ })
424
+ }),
425
+ /* @__PURE__ */ jsxs("span", {
426
+ className: "min-w-0 flex-1",
427
+ children: [/* @__PURE__ */ jsx("span", {
428
+ className: "block text-sm font-semibold text-foreground",
429
+ children: section.title
430
+ }), /* @__PURE__ */ jsx("span", {
431
+ className: "mt-0.5 block text-xs leading-5 text-muted-foreground",
432
+ children: section.description
433
+ })]
434
+ }),
435
+ /* @__PURE__ */ jsx("span", {
436
+ className: "rounded-full border border-border bg-muted px-2 py-0.5 text-xs font-semibold text-muted-foreground",
437
+ children: section.providers.length
438
+ }),
439
+ /* @__PURE__ */ jsx(ChevronDown, {
440
+ className: "size-4 shrink-0 text-muted-foreground transition-transform group-open/providers:rotate-180",
441
+ "aria-hidden": "true"
442
+ })
443
+ ]
444
+ }), /* @__PURE__ */ jsx("div", {
445
+ className: "space-y-2 border-t border-border bg-muted/20 p-2 sm:p-3",
446
+ children: section.providers.map((provider) => /* @__PURE__ */ jsx(ProviderCard, {
447
+ p: provider,
448
+ initiallyOpen: provider.enabled || Boolean(query) || !setupComplete && provider.id === "openai-codex",
449
+ openaiCodexStatus: provider.id === "openai-codex" ? openaiCodex : void 0
450
+ }, provider.id))
451
+ })]
452
+ }, `${section.key}:${query}`))
453
+ })
454
+ ]
455
+ });
456
+ }
457
+ function SummaryStat({ label, value, detail }) {
458
+ return /* @__PURE__ */ jsxs("div", {
459
+ className: "min-w-0 rounded-2xl border border-border bg-card p-4 shadow-baziu-sm",
460
+ children: [
461
+ /* @__PURE__ */ jsx("div", {
462
+ className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground",
463
+ children: label
464
+ }),
465
+ /* @__PURE__ */ jsx("div", {
466
+ className: "mt-1 text-2xl font-semibold text-foreground",
467
+ children: value
468
+ }),
469
+ /* @__PURE__ */ jsx("div", {
470
+ className: "mt-0.5 text-xs leading-5 text-muted-foreground",
471
+ children: detail
472
+ })
473
+ ]
474
+ });
475
+ }
476
+ function SetupBlockerBanner({ providers, openaiCodex }) {
477
+ const issues = [];
478
+ for (const p of providers) {
479
+ if (!p.enabled) continue;
480
+ if (p.id === "openai-codex" && !openaiCodex.connected) issues.push(`${p.id}: enabled but ChatGPT is not connected — click "Connect ChatGPT" below`);
481
+ if (p.curated.length === 0) issues.push(`${p.id}: enabled but no curated models — add at least one name in the "curated models" box below and save`);
482
+ }
483
+ const enabledCount = providers.filter((p) => p.enabled).length;
484
+ return /* @__PURE__ */ jsxs("div", {
485
+ role: "status",
486
+ className: "rounded-2xl border border-warning/30 bg-warning/10 p-5 text-sm",
487
+ children: [
488
+ /* @__PURE__ */ jsx("div", {
489
+ className: "font-semibold text-foreground mb-1",
490
+ children: "Finish your first provider"
491
+ }),
492
+ /* @__PURE__ */ jsx("p", {
493
+ className: "text-muted-foreground mb-2",
494
+ children: "Enable one provider, save at least one exact model id, then send the small test request. Saving the model creates your default resources; a successful test confirms that the credential and model actually work."
495
+ }),
496
+ issues.length > 0 ? /* @__PURE__ */ jsx("ul", {
497
+ className: "list-disc space-y-1 pl-5 text-warning",
498
+ children: issues.map((i) => /* @__PURE__ */ jsx("li", { children: i }, i))
499
+ }) : enabledCount === 0 ? /* @__PURE__ */ jsx("p", {
500
+ className: "text-warning",
501
+ children: "No provider is enabled. Open a recommended option below and follow its steps."
502
+ }) : null
503
+ ]
504
+ });
505
+ }
506
+ function ProviderCard({ p, openaiCodexStatus, initiallyOpen }) {
507
+ const router = useRouter();
508
+ const [enabled, setEnabled] = useState(p.enabled);
509
+ const [expanded, setExpanded] = useState(initiallyOpen);
510
+ const [models, setModels] = useState(p.curated.join("\n"));
511
+ const [savingModels, setSavingModels] = useState(false);
512
+ const [modelStatus, setModelStatus] = useState(null);
513
+ const [toggleError, setToggleError] = useState(null);
514
+ const [testModel, setTestModel] = useState(p.curated[0] ?? "");
515
+ const [testing, setTesting] = useState(false);
516
+ const [testResult, setTestResult] = useState(null);
517
+ const readiness = providerReadiness({
518
+ ...p,
519
+ enabled
520
+ });
521
+ async function toggle(next) {
522
+ setEnabled(next);
523
+ setToggleError(null);
524
+ try {
525
+ const response = await fetch(`/api/config/providers/${encodeURIComponent(p.id)}/enabled`, {
526
+ method: "PUT",
527
+ headers: { "content-type": "application/json" },
528
+ body: JSON.stringify({ enabled: next })
529
+ });
530
+ if (!response.ok) {
531
+ const body = await response.json().catch(() => null);
532
+ throw new Error(body?.error ?? `Could not update provider (${response.status})`);
533
+ }
534
+ if (next) setExpanded(true);
535
+ await router.invalidate();
536
+ } catch (error) {
537
+ setEnabled(!next);
538
+ setToggleError(error instanceof Error ? error.message : String(error));
539
+ }
540
+ }
541
+ async function saveModels(e) {
542
+ e.preventDefault();
543
+ setSavingModels(true);
544
+ setModelStatus(null);
545
+ try {
546
+ const list = models.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
547
+ const res = await fetch(`/api/config/providers/${encodeURIComponent(p.id)}/models`, {
548
+ method: "PUT",
549
+ headers: { "content-type": "application/json" },
550
+ body: JSON.stringify({ models: list })
551
+ });
552
+ if (!res.ok) {
553
+ const j = await res.json().catch(() => ({}));
554
+ throw new Error(j.error ?? `${res.status} ${res.statusText}`);
555
+ }
556
+ setModelStatus({
557
+ kind: "success",
558
+ message: "Models saved. Run the connection test before relying on them."
559
+ });
560
+ setTestModel(list[0] ?? "");
561
+ setTestResult(null);
562
+ await router.invalidate();
563
+ } catch (e) {
564
+ setModelStatus({
565
+ kind: "error",
566
+ message: e.message
567
+ });
568
+ } finally {
569
+ setSavingModels(false);
570
+ }
571
+ }
572
+ async function testConnection() {
573
+ if (!testModel) return;
574
+ setTesting(true);
575
+ setTestResult(null);
576
+ try {
577
+ const response = await fetch("/api/providers/test", {
578
+ method: "POST",
579
+ headers: { "content-type": "application/json" },
580
+ body: JSON.stringify({
581
+ model: `${p.id}:${testModel}`,
582
+ message: "Reply with exactly: Bazilion connection verified."
583
+ })
584
+ });
585
+ const body = await response.json().catch(() => null);
586
+ if (!response.ok) throw new Error(body?.error ?? `Connection test failed (${response.status})`);
587
+ setTestResult({
588
+ kind: "success",
589
+ message: `Verified ${p.displayName} with ${testModel}.`
590
+ });
591
+ await router.invalidate();
592
+ } catch (error) {
593
+ setTestResult({
594
+ kind: "error",
595
+ message: error instanceof Error ? error.message : String(error)
596
+ });
597
+ } finally {
598
+ setTesting(false);
599
+ }
600
+ }
601
+ return /* @__PURE__ */ jsxs("section", {
602
+ className: "overflow-hidden rounded-xl border border-border bg-card",
603
+ children: [
604
+ /* @__PURE__ */ jsxs("header", {
605
+ className: "flex min-w-0 flex-wrap items-center gap-2 px-3 py-3 sm:px-4",
606
+ children: [
607
+ /* @__PURE__ */ jsxs("button", {
608
+ type: "button",
609
+ className: "unstyled flex min-w-0 flex-1 items-center gap-2 rounded-lg text-left",
610
+ "aria-expanded": expanded,
611
+ "aria-controls": `provider-${p.id}`,
612
+ onClick: () => setExpanded((value) => !value),
613
+ children: [/* @__PURE__ */ jsx(ChevronRight, {
614
+ className: `size-4 shrink-0 text-muted-foreground transition-transform ${expanded ? "rotate-90" : ""}`,
615
+ "aria-hidden": "true"
616
+ }), /* @__PURE__ */ jsxs("span", {
617
+ className: "min-w-0",
618
+ children: [/* @__PURE__ */ jsx("span", {
619
+ className: "block truncate text-sm font-semibold text-foreground",
620
+ children: p.displayName
621
+ }), /* @__PURE__ */ jsx("span", {
622
+ className: "block truncate font-mono text-xs text-muted-foreground",
623
+ children: p.id
624
+ })]
625
+ })]
626
+ }),
627
+ /* @__PURE__ */ jsx(StatusBadge$1, {
628
+ variant: readiness.tone === "success" ? "success" : readiness.tone === "warning" ? "warning" : "neutral",
629
+ children: readiness.label
630
+ }),
631
+ /* @__PURE__ */ jsxs("label", {
632
+ className: "m-0 flex cursor-pointer items-center gap-1.5 rounded-lg px-1 text-xs font-semibold",
633
+ children: [/* @__PURE__ */ jsx("input", {
634
+ type: "checkbox",
635
+ checked: enabled,
636
+ onChange: (e) => toggle(e.target.checked),
637
+ className: "size-4",
638
+ "aria-label": `${enabled ? "Disable" : "Enable"} ${p.displayName}`
639
+ }), /* @__PURE__ */ jsx("span", {
640
+ className: enabled ? "text-success" : "text-muted-foreground",
641
+ children: enabled ? "enabled" : "disabled"
642
+ })]
643
+ }),
644
+ /* @__PURE__ */ jsxs("span", {
645
+ className: "w-full pl-6 text-xs text-muted-foreground sm:w-auto sm:pl-0",
646
+ children: [
647
+ p.curated.length > 0 && /* @__PURE__ */ jsxs("span", { children: [p.curated.length, " curated"] }),
648
+ p.catalog.length > 0 && /* @__PURE__ */ jsxs("span", { children: [
649
+ " · ",
650
+ p.catalog.length,
651
+ " catalog"
652
+ ] }),
653
+ p.live && !p.live.error && /* @__PURE__ */ jsxs("span", { children: [
654
+ " · ",
655
+ p.live.models.length,
656
+ " live"
657
+ ] })
658
+ ]
659
+ })
660
+ ]
661
+ }),
662
+ toggleError && /* @__PURE__ */ jsx("p", {
663
+ role: "alert",
664
+ className: "mx-4 mb-3 text-sm text-danger",
665
+ children: toggleError
666
+ }),
667
+ expanded && /* @__PURE__ */ jsxs("div", {
668
+ id: `provider-${p.id}`,
669
+ className: "border-t border-dashed px-3 py-4 sm:px-4",
670
+ children: [
671
+ p.hint && /* @__PURE__ */ jsx("p", {
672
+ className: "text-xs text-muted-foreground mb-2",
673
+ children: p.hint
674
+ }),
675
+ p.id === "openai-codex" && openaiCodexStatus && /* @__PURE__ */ jsx(OpenAICodexCard, { status: openaiCodexStatus }),
676
+ p.fields.length === 0 && p.envHint && p.id !== "openai-codex" && /* @__PURE__ */ jsxs("p", {
677
+ className: "text-xs text-muted-foreground",
678
+ children: ["Credentials come from the process env: ", /* @__PURE__ */ jsx("code", {
679
+ className: "font-mono",
680
+ children: p.envHint
681
+ })]
682
+ }),
683
+ p.fields.map((f) => /* @__PURE__ */ jsx(FieldRow, { field: f }, f.envVar)),
684
+ /* @__PURE__ */ jsx("h4", {
685
+ id: `provider-${p.id}-models-label`,
686
+ className: "mt-4 mb-1 font-body text-xs font-semibold uppercase tracking-wide text-muted-foreground",
687
+ children: "Models available to agents"
688
+ }),
689
+ p.curated.length === 0 && /* @__PURE__ */ jsxs("p", {
690
+ className: "mb-2 text-xs font-medium text-warning",
691
+ children: [
692
+ "First-run setup needs at least one model name here — type one (e.g.",
693
+ " ",
694
+ /* @__PURE__ */ jsx("code", {
695
+ className: "font-mono",
696
+ children: exampleModelFor(p.id)
697
+ }),
698
+ ") and click",
699
+ " ",
700
+ /* @__PURE__ */ jsx("em", { children: "save models" }),
701
+ ". Catalog chips below are the safest source when available."
702
+ ]
703
+ }),
704
+ /* @__PURE__ */ jsxs("form", {
705
+ onSubmit: saveModels,
706
+ children: [/* @__PURE__ */ jsx("textarea", {
707
+ id: `provider-${p.id}-models`,
708
+ "aria-labelledby": `provider-${p.id}-models-label`,
709
+ value: models,
710
+ onChange: (e) => setModels(e.target.value),
711
+ rows: Math.max(3, Math.min(8, models.split("\n").length)),
712
+ className: "w-full rounded-md border bg-background px-2 py-1.5 font-mono text-sm outline-none focus:ring-2 focus:ring-ring/30",
713
+ placeholder: p.catalog.length === 0 && !p.live ? "Type model names one per line, e.g. qwen3-coder-30b" : "Click catalog chips below, or type names one per line"
714
+ }), /* @__PURE__ */ jsxs("div", {
715
+ className: "flex items-center gap-3 mt-2",
716
+ children: [/* @__PURE__ */ jsx("button", {
717
+ type: "submit",
718
+ disabled: savingModels,
719
+ className: "rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground disabled:opacity-50",
720
+ children: savingModels ? "Saving…" : "Save models"
721
+ }), modelStatus && /* @__PURE__ */ jsx("span", {
722
+ role: modelStatus.kind === "error" ? "alert" : "status",
723
+ className: `text-xs ${modelStatus.kind === "error" ? "text-danger" : "text-success"}`,
724
+ children: modelStatus.message
725
+ })]
726
+ })]
727
+ }),
728
+ p.catalog.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("h4", {
729
+ className: "mt-4 mb-1 text-xs uppercase tracking-wide text-muted-foreground",
730
+ children: "catalog"
731
+ }), /* @__PURE__ */ jsx(ChipList, {
732
+ items: p.catalog,
733
+ onPick: (name) => setModels((m) => m.includes(name) ? m : `${m}\n${name}`.trim())
734
+ })] }),
735
+ p.live && !p.live.error && p.live.models.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("h4", {
736
+ className: "mt-4 mb-1 text-xs uppercase tracking-wide text-muted-foreground",
737
+ children: "live"
738
+ }), /* @__PURE__ */ jsx(ChipList, {
739
+ items: p.live.models,
740
+ onPick: (name) => setModels((m) => m.includes(name) ? m : `${m}\n${name}`.trim())
741
+ })] }),
742
+ p.live?.error && /* @__PURE__ */ jsxs("p", {
743
+ role: "alert",
744
+ className: "text-xs text-danger mt-2",
745
+ children: ["Could not fetch live models: ", p.live.error]
746
+ }),
747
+ enabled && p.curated.length > 0 && /* @__PURE__ */ jsxs("div", {
748
+ className: "mt-4 rounded-xl border border-border bg-muted/30 p-3",
749
+ children: [
750
+ /* @__PURE__ */ jsx("h4", {
751
+ className: "m-0 font-body text-sm font-semibold text-foreground",
752
+ children: "Test the connection"
753
+ }),
754
+ /* @__PURE__ */ jsx("p", {
755
+ className: "mt-1 text-xs leading-5 text-muted-foreground",
756
+ children: "Sends one short real request. Your provider may charge its normal token cost."
757
+ }),
758
+ /* @__PURE__ */ jsxs("div", {
759
+ className: "mt-3 flex flex-col gap-2 sm:flex-row sm:items-end",
760
+ children: [/* @__PURE__ */ jsxs("label", {
761
+ className: "m-0 min-w-0 flex-1 text-xs font-semibold text-foreground",
762
+ children: ["Model", /* @__PURE__ */ jsx("select", {
763
+ className: "mt-1",
764
+ value: testModel,
765
+ onChange: (event) => setTestModel(event.target.value),
766
+ children: p.curated.map((model) => /* @__PURE__ */ jsx("option", {
767
+ value: model,
768
+ children: model
769
+ }, model))
770
+ })]
771
+ }), /* @__PURE__ */ jsx(Button, {
772
+ variant: "ghost",
773
+ disabled: testing || !testModel,
774
+ onClick: () => void testConnection(),
775
+ children: testing ? "Testing…" : "Send test request"
776
+ })]
777
+ }),
778
+ testResult && /* @__PURE__ */ jsx("p", {
779
+ role: testResult.kind === "error" ? "alert" : "status",
780
+ className: `mt-3 rounded-lg px-3 py-2 text-sm ${testResult.kind === "error" ? "bg-danger/10 text-danger" : "bg-success/10 text-success"}`,
781
+ children: testResult.message
782
+ })
783
+ ]
784
+ })
785
+ ]
786
+ })
787
+ ]
788
+ });
789
+ }
790
+ function exampleModelFor(providerId) {
791
+ switch (providerId) {
792
+ case "openai-codex": return "gpt-5.6-luna";
793
+ case "openai": return "gpt-5.6-luna";
794
+ case "anthropic": return "claude-opus-5";
795
+ case "google": return "gemini-3.6-flash";
796
+ case "google-vertex": return "gemini-3.6-flash";
797
+ case "xai": return "grok-4.5";
798
+ case "groq": return "llama-3.3-70b-versatile";
799
+ case "cerebras": return "gpt-oss-120b";
800
+ case "mistral": return "mistral-large-latest";
801
+ case "zai": return "glm-5.2";
802
+ case "huggingface": return "Qwen/Qwen3.5-397B-A17B";
803
+ case "openrouter": return "anthropic/claude-opus-5";
804
+ case "vercel-ai-gateway": return "anthropic/claude-opus-5";
805
+ case "deepseek": return "deepseek-v4-pro";
806
+ case "fireworks": return "accounts/fireworks/models/kimi-k3";
807
+ case "together": return "moonshotai/Kimi-K3";
808
+ case "baseten": return "moonshotai/Kimi-K3";
809
+ case "moonshotai": return "kimi-k3";
810
+ case "moonshotai-cn": return "kimi-k3";
811
+ case "kimi-coding": return "kimi-for-coding";
812
+ case "minimax": return "MiniMax-M2.7";
813
+ case "minimax-cn": return "MiniMax-M3";
814
+ case "qwen-token-plan": return "qwen3.8-max";
815
+ case "qwen-token-plan-cn":
816
+ case "qwen-token-plan-individual": return "qwen3.8-max";
817
+ case "ant-ling": return "Ling-2.6-1T";
818
+ case "nvidia": return "nvidia/nemotron-3-super-120b-a12b";
819
+ case "cloudflare-workers-ai": return "@cf/moonshotai/kimi-k2.6";
820
+ case "cloudflare-ai-gateway": return "claude-opus-5";
821
+ case "github-copilot": return "claude-opus-5";
822
+ case "xiaomi": return "mimo-v2.5";
823
+ case "xiaomi-token-plan-ams":
824
+ case "xiaomi-token-plan-cn":
825
+ case "xiaomi-token-plan-sgp": return "mimo-v2.5-pro";
826
+ case "opencode": return "claude-opus-5";
827
+ case "opencode-go": return "kimi-k2.7-code";
828
+ case "zai-coding-cn": return "glm-5.2";
829
+ case "azure-openai": return "gpt-5.6-luna";
830
+ case "bedrock": return "global.anthropic.claude-opus-5";
831
+ case "ollama": return "llama3.3";
832
+ case "lmstudio": return "qwen3-coder-30b";
833
+ case "llamacpp": return "unsloth/Qwen3.6-35B-A3B-MTP-GGUF:MXFP4_MOE";
834
+ default: return "model-name";
835
+ }
836
+ }
837
+ function ChipList({ items, onPick }) {
838
+ return /* @__PURE__ */ jsx("div", {
839
+ className: "flex flex-wrap gap-1.5 max-h-40 overflow-y-auto rounded-md border bg-background p-1.5",
840
+ children: items.map((m) => /* @__PURE__ */ jsx("button", {
841
+ type: "button",
842
+ onClick: () => onPick(m),
843
+ "aria-label": `Add ${m} to selected models`,
844
+ className: "rounded border bg-card px-2 py-0.5 font-mono text-xs hover:border-primary hover:bg-accent",
845
+ children: m
846
+ }, m))
847
+ });
848
+ }
849
+ function OpenAICodexCard({ status }) {
850
+ const router = useRouter();
851
+ const [busy, setBusy] = useState(false);
852
+ const [err, setErr] = useState(null);
853
+ const [confirmDisconnect, setConfirmDisconnect] = useState(false);
854
+ async function connect() {
855
+ setBusy(true);
856
+ setErr(null);
857
+ try {
858
+ const res = await fetch("/api/auth/openai/login", { method: "POST" });
859
+ if (!res.ok) {
860
+ const j = await res.json().catch(() => ({}));
861
+ throw new Error(j.error ?? `${res.status} ${res.statusText}`);
862
+ }
863
+ await router.invalidate();
864
+ } catch (e) {
865
+ setErr(e.message);
866
+ } finally {
867
+ setBusy(false);
868
+ }
869
+ }
870
+ async function disconnect() {
871
+ setBusy(true);
872
+ setErr(null);
873
+ try {
874
+ const response = await fetch("/api/auth/openai", { method: "DELETE" });
875
+ if (!response.ok && response.status !== 204) {
876
+ const body = await response.json().catch(() => null);
877
+ throw new Error(body?.error ?? `Could not disconnect ChatGPT (${response.status})`);
878
+ }
879
+ await router.invalidate();
880
+ } catch (e) {
881
+ setErr(e instanceof Error ? e.message : String(e));
882
+ throw e;
883
+ } finally {
884
+ setBusy(false);
885
+ }
886
+ }
887
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
888
+ className: "rounded-md border bg-muted/30 p-3 mb-3",
889
+ children: [status.connected ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
890
+ className: "flex flex-wrap gap-2 items-center mb-2",
891
+ children: [
892
+ /* @__PURE__ */ jsx("span", {
893
+ className: "rounded-full bg-success/10 text-success px-2 py-0.5 text-xs font-semibold uppercase",
894
+ children: "connected"
895
+ }),
896
+ status.accountId && /* @__PURE__ */ jsxs("span", {
897
+ className: "text-xs text-muted-foreground",
898
+ children: ["account ", /* @__PURE__ */ jsx("code", {
899
+ className: "font-mono",
900
+ children: status.accountId
901
+ })]
902
+ }),
903
+ status.expiresAt && /* @__PURE__ */ jsxs("span", {
904
+ className: "text-xs text-muted-foreground",
905
+ children: [
906
+ "token expires",
907
+ " ",
908
+ new Date(status.expiresAt).toISOString().replace(/\.\d+Z$/, "Z")
909
+ ]
910
+ })
911
+ ]
912
+ }), /* @__PURE__ */ jsx(Button, {
913
+ variant: "danger",
914
+ onClick: () => setConfirmDisconnect(true),
915
+ disabled: busy,
916
+ children: "Disconnect ChatGPT"
917
+ })] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("p", {
918
+ className: "text-xs text-muted-foreground mb-2",
919
+ children: [
920
+ "Sign in with your ChatGPT account — the OAuth flow opens a new browser tab. The loopback callback at ",
921
+ /* @__PURE__ */ jsx("code", {
922
+ className: "font-mono",
923
+ children: "localhost:1455"
924
+ }),
925
+ " only works when you're using the web UI on the same machine as the daemon. For remote setups, run ",
926
+ /* @__PURE__ */ jsx("code", {
927
+ className: "font-mono",
928
+ children: "bazilion auth openai login"
929
+ }),
930
+ " on the client."
931
+ ]
932
+ }), /* @__PURE__ */ jsx("button", {
933
+ type: "button",
934
+ onClick: connect,
935
+ disabled: busy,
936
+ className: "rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground disabled:opacity-50",
937
+ children: busy ? "opening browser…" : "Connect ChatGPT →"
938
+ })] }), err && /* @__PURE__ */ jsx("p", {
939
+ role: "alert",
940
+ className: "text-sm text-danger mt-2",
941
+ children: err
942
+ })]
943
+ }), /* @__PURE__ */ jsx(ConfirmDialog, {
944
+ open: confirmDisconnect,
945
+ onOpenChange: setConfirmDisconnect,
946
+ title: "Disconnect ChatGPT?",
947
+ description: /* @__PURE__ */ jsxs("p", { children: [
948
+ "This removes the saved OpenAI Codex OAuth credentials. Agents using an",
949
+ " ",
950
+ /* @__PURE__ */ jsx("code", { children: "openai-codex" }),
951
+ " model will stop working until you connect again."
952
+ ] }),
953
+ confirmLabel: "Disconnect ChatGPT",
954
+ onConfirm: disconnect
955
+ })] });
956
+ }
957
+ //#endregion
958
+ export { ProvidersPage as component };