agim-cli 1.2.133 → 1.2.135

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 (189) hide show
  1. package/CHANGELOG.md +111 -0
  2. package/dist/core/commands/plan.d.ts.map +1 -1
  3. package/dist/core/commands/plan.js +27 -8
  4. package/dist/core/commands/plan.js.map +1 -1
  5. package/dist/core/plan-intent.d.ts +14 -0
  6. package/dist/core/plan-intent.d.ts.map +1 -0
  7. package/dist/core/plan-intent.js +112 -0
  8. package/dist/core/plan-intent.js.map +1 -0
  9. package/dist/core/router.d.ts.map +1 -1
  10. package/dist/core/router.js +27 -1
  11. package/dist/core/router.js.map +1 -1
  12. package/dist/web/public/assets/{a2a-TmaKRhXV.js → a2a-oYRz4syc.js} +2 -2
  13. package/dist/web/public/assets/{a2a-TmaKRhXV.js.map → a2a-oYRz4syc.js.map} +1 -1
  14. package/dist/web/public/assets/{activity-Cckc7fGG.js → activity-CbMd52BC.js} +2 -2
  15. package/dist/web/public/assets/{activity-Cckc7fGG.js.map → activity-CbMd52BC.js.map} +1 -1
  16. package/dist/web/public/assets/{admins-1hMCDolP.js → admins-BtuJdXZX.js} +2 -2
  17. package/dist/web/public/assets/{admins-1hMCDolP.js.map → admins-BtuJdXZX.js.map} +1 -1
  18. package/dist/web/public/assets/{agents-3sUHlKzx.js → agents-Dm8fTAks.js} +2 -2
  19. package/dist/web/public/assets/{agents-3sUHlKzx.js.map → agents-Dm8fTAks.js.map} +1 -1
  20. package/dist/web/public/assets/{approvals-CY-_Lg4Y.js → approvals-Y7FCBVQR.js} +2 -2
  21. package/dist/web/public/assets/{approvals-CY-_Lg4Y.js.map → approvals-Y7FCBVQR.js.map} +1 -1
  22. package/dist/web/public/assets/{arrow-down-BkZ50IzL.js → arrow-down-BpfVJViL.js} +2 -2
  23. package/dist/web/public/assets/{arrow-down-BkZ50IzL.js.map → arrow-down-BpfVJViL.js.map} +1 -1
  24. package/dist/web/public/assets/{arrow-up-NWC5K6Jw.js → arrow-up-BQxFty9k.js} +2 -2
  25. package/dist/web/public/assets/{arrow-up-NWC5K6Jw.js.map → arrow-up-BQxFty9k.js.map} +1 -1
  26. package/dist/web/public/assets/{asks-VzAmpsEh.js → asks-CzeX-NCb.js} +2 -2
  27. package/dist/web/public/assets/{asks-VzAmpsEh.js.map → asks-CzeX-NCb.js.map} +1 -1
  28. package/dist/web/public/assets/{audit-fOn2LH4D.js → audit-DDonnB7I.js} +2 -2
  29. package/dist/web/public/assets/{audit-fOn2LH4D.js.map → audit-DDonnB7I.js.map} +1 -1
  30. package/dist/web/public/assets/{bell-FF7PJo1N.js → bell-QusEl0TB.js} +2 -2
  31. package/dist/web/public/assets/{bell-FF7PJo1N.js.map → bell-QusEl0TB.js.map} +1 -1
  32. package/dist/web/public/assets/{bgjobs-L0v-UwPW.js → bgjobs-BIx5fZe2.js} +2 -2
  33. package/dist/web/public/assets/{bgjobs-L0v-UwPW.js.map → bgjobs-BIx5fZe2.js.map} +1 -1
  34. package/dist/web/public/assets/{brain-CdkDpFr1.js → brain-CC9HwFtI.js} +2 -2
  35. package/dist/web/public/assets/{brain-CdkDpFr1.js.map → brain-CC9HwFtI.js.map} +1 -1
  36. package/dist/web/public/assets/{briefcase-BXbOdl7E.js → briefcase-DueOcW1K.js} +2 -2
  37. package/dist/web/public/assets/{briefcase-BXbOdl7E.js.map → briefcase-DueOcW1K.js.map} +1 -1
  38. package/dist/web/public/assets/{chat-BazMi-ik.js → chat-DahEFTcT.js} +2 -2
  39. package/dist/web/public/assets/{chat-BazMi-ik.js.map → chat-DahEFTcT.js.map} +1 -1
  40. package/dist/web/public/assets/{chevron-left-Di1Tz64J.js → chevron-left-CaGOVECz.js} +2 -2
  41. package/dist/web/public/assets/{chevron-left-Di1Tz64J.js.map → chevron-left-CaGOVECz.js.map} +1 -1
  42. package/dist/web/public/assets/{chevron-right-BLjhBkqs.js → chevron-right-BX3t8KY3.js} +2 -2
  43. package/dist/web/public/assets/{chevron-right-BLjhBkqs.js.map → chevron-right-BX3t8KY3.js.map} +1 -1
  44. package/dist/web/public/assets/{circle-check-BaxzYLlE.js → circle-check-BGjJhA0M.js} +2 -2
  45. package/dist/web/public/assets/{circle-check-BaxzYLlE.js.map → circle-check-BGjJhA0M.js.map} +1 -1
  46. package/dist/web/public/assets/{circle-check-big-C4BGLUvw.js → circle-check-big-CkxzVtPL.js} +2 -2
  47. package/dist/web/public/assets/{circle-check-big-C4BGLUvw.js.map → circle-check-big-CkxzVtPL.js.map} +1 -1
  48. package/dist/web/public/assets/{circle-x-THl-PO3_.js → circle-x-BziROBzb.js} +2 -2
  49. package/dist/web/public/assets/{circle-x-THl-PO3_.js.map → circle-x-BziROBzb.js.map} +1 -1
  50. package/dist/web/public/assets/{clock-iitpdQjZ.js → clock-80yAmtz6.js} +2 -2
  51. package/dist/web/public/assets/{clock-iitpdQjZ.js.map → clock-80yAmtz6.js.map} +1 -1
  52. package/dist/web/public/assets/{confirm-dialog-r9HgkIYf.js → confirm-dialog-DAfv5d0M.js} +2 -2
  53. package/dist/web/public/assets/{confirm-dialog-r9HgkIYf.js.map → confirm-dialog-DAfv5d0M.js.map} +1 -1
  54. package/dist/web/public/assets/{copy-DwyF4MOL.js → copy-CDQUdNjG.js} +2 -2
  55. package/dist/web/public/assets/{copy-DwyF4MOL.js.map → copy-CDQUdNjG.js.map} +1 -1
  56. package/dist/web/public/assets/{data-table-B80M8zdu.js → data-table-B_sUmaE2.js} +2 -2
  57. package/dist/web/public/assets/{data-table-B80M8zdu.js.map → data-table-B_sUmaE2.js.map} +1 -1
  58. package/dist/web/public/assets/{dialog-fGS0IXOo.js → dialog-DGdHPiTV.js} +2 -2
  59. package/dist/web/public/assets/{dialog-fGS0IXOo.js.map → dialog-DGdHPiTV.js.map} +1 -1
  60. package/dist/web/public/assets/{download-5ihiF2Gj.js → download-CTWGQ8nD.js} +2 -2
  61. package/dist/web/public/assets/{download-5ihiF2Gj.js.map → download-CTWGQ8nD.js.map} +1 -1
  62. package/dist/web/public/assets/{email-LmRMqLRU.js → email-D0CbEk1s.js} +2 -2
  63. package/dist/web/public/assets/{email-LmRMqLRU.js.map → email-D0CbEk1s.js.map} +1 -1
  64. package/dist/web/public/assets/{empty-state-CrPnUC6d.js → empty-state-CtWM3HCj.js} +2 -2
  65. package/dist/web/public/assets/{empty-state-CrPnUC6d.js.map → empty-state-CtWM3HCj.js.map} +1 -1
  66. package/dist/web/public/assets/{external-link-DIJK1MAH.js → external-link-eCDEU3zh.js} +2 -2
  67. package/dist/web/public/assets/{external-link-DIJK1MAH.js.map → external-link-eCDEU3zh.js.map} +1 -1
  68. package/dist/web/public/assets/{eye-DJJw0Ald.js → eye-BwZbiu9G.js} +2 -2
  69. package/dist/web/public/assets/{eye-DJJw0Ald.js.map → eye-BwZbiu9G.js.map} +1 -1
  70. package/dist/web/public/assets/{facts-BzImxpJD.js → facts-CilmUyo5.js} +2 -2
  71. package/dist/web/public/assets/{facts-BzImxpJD.js.map → facts-CilmUyo5.js.map} +1 -1
  72. package/dist/web/public/assets/{goals-C6p21B9N.js → goals-ClMqJOcZ.js} +2 -2
  73. package/dist/web/public/assets/{goals-C6p21B9N.js.map → goals-ClMqJOcZ.js.map} +1 -1
  74. package/dist/web/public/assets/{health-D-ugz2Gp.js → health-2Gc6vytU.js} +2 -2
  75. package/dist/web/public/assets/{health-D-ugz2Gp.js.map → health-2Gc6vytU.js.map} +1 -1
  76. package/dist/web/public/assets/{heart-pulse-DlZXcdL0.js → heart-pulse-f2ZP4fOw.js} +2 -2
  77. package/dist/web/public/assets/{heart-pulse-DlZXcdL0.js.map → heart-pulse-f2ZP4fOw.js.map} +1 -1
  78. package/dist/web/public/assets/{heartbeat-DSasg-3y.js → heartbeat-T5ecNv9f.js} +2 -2
  79. package/dist/web/public/assets/{heartbeat-DSasg-3y.js.map → heartbeat-T5ecNv9f.js.map} +1 -1
  80. package/dist/web/public/assets/{hot-D67pYtaV.js → hot-hTf3IoT7.js} +2 -2
  81. package/dist/web/public/assets/{hot-D67pYtaV.js.map → hot-hTf3IoT7.js.map} +1 -1
  82. package/dist/web/public/assets/{index-CqwhfPlr.js → index-D4Np2s3l.js} +23 -23
  83. package/dist/web/public/assets/{index-CqwhfPlr.js.map → index-D4Np2s3l.js.map} +1 -1
  84. package/dist/web/public/assets/{installed-CrIsSoQE.js → installed-3B4RqrKw.js} +2 -2
  85. package/dist/web/public/assets/{installed-CrIsSoQE.js.map → installed-3B4RqrKw.js.map} +1 -1
  86. package/dist/web/public/assets/{jobs-yAwphb1W.js → jobs-rdZMVduE.js} +2 -2
  87. package/dist/web/public/assets/{jobs-yAwphb1W.js.map → jobs-rdZMVduE.js.map} +1 -1
  88. package/dist/web/public/assets/{layout-cacmfseo.js → layout-CwEKQhrq.js} +2 -2
  89. package/dist/web/public/assets/{layout-cacmfseo.js.map → layout-CwEKQhrq.js.map} +1 -1
  90. package/dist/web/public/assets/{layout-BXZKGQAk.js → layout-DdSyLqXe.js} +2 -2
  91. package/dist/web/public/assets/{layout-BXZKGQAk.js.map → layout-DdSyLqXe.js.map} +1 -1
  92. package/dist/web/public/assets/{layout-awbFImGg.js → layout-DwNsrPtD.js} +2 -2
  93. package/dist/web/public/assets/{layout-awbFImGg.js.map → layout-DwNsrPtD.js.map} +1 -1
  94. package/dist/web/public/assets/{layout-CrtmlC8G.js → layout-cfySH7sc.js} +2 -2
  95. package/dist/web/public/assets/{layout-CrtmlC8G.js.map → layout-cfySH7sc.js.map} +1 -1
  96. package/dist/web/public/assets/{layout-CL5HFvHN.js → layout-ofBlvFCx.js} +2 -2
  97. package/dist/web/public/assets/{layout-CL5HFvHN.js.map → layout-ofBlvFCx.js.map} +1 -1
  98. package/dist/web/public/assets/{llm-C19AX6q2.js → llm-CBLl38AB.js} +2 -2
  99. package/dist/web/public/assets/{llm-C19AX6q2.js.map → llm-CBLl38AB.js.map} +1 -1
  100. package/dist/web/public/assets/{loader-circle-U-jPjmeD.js → loader-circle-BfXi9R6u.js} +2 -2
  101. package/dist/web/public/assets/{loader-circle-U-jPjmeD.js.map → loader-circle-BfXi9R6u.js.map} +1 -1
  102. package/dist/web/public/assets/{map-pin-4rE1NK87.js → map-pin-E83IWTEe.js} +2 -2
  103. package/dist/web/public/assets/{map-pin-4rE1NK87.js.map → map-pin-E83IWTEe.js.map} +1 -1
  104. package/dist/web/public/assets/{mcp-B94wc6Vi.js → mcp-B-NKHX-f.js} +2 -2
  105. package/dist/web/public/assets/{mcp-B94wc6Vi.js.map → mcp-B-NKHX-f.js.map} +1 -1
  106. package/dist/web/public/assets/{memos-CrG4zgfI.js → memos-CuY8Ai7a.js} +2 -2
  107. package/dist/web/public/assets/{memos-CrG4zgfI.js.map → memos-CuY8Ai7a.js.map} +1 -1
  108. package/dist/web/public/assets/{messengers-UWarJd_C.js → messengers-DGnu7I6n.js} +2 -2
  109. package/dist/web/public/assets/{messengers-UWarJd_C.js.map → messengers-DGnu7I6n.js.map} +1 -1
  110. package/dist/web/public/assets/{mobile-QhAUKqcJ.js → mobile-o-Aa_7VP.js} +2 -2
  111. package/dist/web/public/assets/{mobile-QhAUKqcJ.js.map → mobile-o-Aa_7VP.js.map} +1 -1
  112. package/dist/web/public/assets/native-agent-Ivct8avv.js +22 -0
  113. package/dist/web/public/assets/native-agent-Ivct8avv.js.map +1 -0
  114. package/dist/web/public/assets/{network-l6l5gLHO.js → network-B48dL6Y7.js} +2 -2
  115. package/dist/web/public/assets/{network-l6l5gLHO.js.map → network-B48dL6Y7.js.map} +1 -1
  116. package/dist/web/public/assets/{outbox-BenX_yUQ.js → outbox-CQutJNfH.js} +2 -2
  117. package/dist/web/public/assets/{outbox-BenX_yUQ.js.map → outbox-CQutJNfH.js.map} +1 -1
  118. package/dist/web/public/assets/{pagination-B4g1CBsi.js → pagination-rJwdesRS.js} +2 -2
  119. package/dist/web/public/assets/{pagination-B4g1CBsi.js.map → pagination-rJwdesRS.js.map} +1 -1
  120. package/dist/web/public/assets/{persona--3cjtl9q.js → persona-DJO6f_q5.js} +2 -2
  121. package/dist/web/public/assets/{persona--3cjtl9q.js.map → persona-DJO6f_q5.js.map} +1 -1
  122. package/dist/web/public/assets/{plans-DsHtDRlS.js → plans-D-Nf-jL2.js} +2 -2
  123. package/dist/web/public/assets/{plans-DsHtDRlS.js.map → plans-D-Nf-jL2.js.map} +1 -1
  124. package/dist/web/public/assets/{play-BG0hyTnO.js → play-DqmSNGi8.js} +2 -2
  125. package/dist/web/public/assets/{play-BG0hyTnO.js.map → play-DqmSNGi8.js.map} +1 -1
  126. package/dist/web/public/assets/{plus-Dof9AQvU.js → plus-CxClG9H0.js} +2 -2
  127. package/dist/web/public/assets/{plus-Dof9AQvU.js.map → plus-CxClG9H0.js.map} +1 -1
  128. package/dist/web/public/assets/{policy-BzHy4WbV.js → policy-Mqe38uiR.js} +2 -2
  129. package/dist/web/public/assets/{policy-BzHy4WbV.js.map → policy-Mqe38uiR.js.map} +1 -1
  130. package/dist/web/public/assets/{qr-code-yD_ztCf6.js → qr-code-BAEZ2Sel.js} +2 -2
  131. package/dist/web/public/assets/{qr-code-yD_ztCf6.js.map → qr-code-BAEZ2Sel.js.map} +1 -1
  132. package/dist/web/public/assets/{refresh-ccw-CBiHL1tY.js → refresh-ccw-C7VT3MFu.js} +2 -2
  133. package/dist/web/public/assets/{refresh-ccw-CBiHL1tY.js.map → refresh-ccw-C7VT3MFu.js.map} +1 -1
  134. package/dist/web/public/assets/{reminders-CDJlFR2Y.js → reminders--pCTIhTv.js} +2 -2
  135. package/dist/web/public/assets/{reminders-CDJlFR2Y.js.map → reminders--pCTIhTv.js.map} +1 -1
  136. package/dist/web/public/assets/{save-DVHI3V6o.js → save-B18KQmEd.js} +2 -2
  137. package/dist/web/public/assets/{save-DVHI3V6o.js.map → save-B18KQmEd.js.map} +1 -1
  138. package/dist/web/public/assets/{schedules-DYf64Fpr.js → schedules-CA4eHggo.js} +2 -2
  139. package/dist/web/public/assets/{schedules-DYf64Fpr.js.map → schedules-CA4eHggo.js.map} +1 -1
  140. package/dist/web/public/assets/{search-BYPDbBkC.js → search-CA_pO63g.js} +2 -2
  141. package/dist/web/public/assets/{search-BYPDbBkC.js.map → search-CA_pO63g.js.map} +1 -1
  142. package/dist/web/public/assets/{search-aw0y39Qs.js → search-ChcW6uXM.js} +2 -2
  143. package/dist/web/public/assets/{search-aw0y39Qs.js.map → search-ChcW6uXM.js.map} +1 -1
  144. package/dist/web/public/assets/{security-DhN1kRac.js → security-CeW9WxQO.js} +2 -2
  145. package/dist/web/public/assets/{security-DhN1kRac.js.map → security-CeW9WxQO.js.map} +1 -1
  146. package/dist/web/public/assets/{service-BhvI7Mb5.js → service-CJRR2q7Q.js} +2 -2
  147. package/dist/web/public/assets/{service-BhvI7Mb5.js.map → service-CJRR2q7Q.js.map} +1 -1
  148. package/dist/web/public/assets/{shield-alert-DjqqnTMk.js → shield-alert-0q3ul8GH.js} +2 -2
  149. package/dist/web/public/assets/{shield-alert-DjqqnTMk.js.map → shield-alert-0q3ul8GH.js.map} +1 -1
  150. package/dist/web/public/assets/{status-badge-nSFUUEfy.js → status-badge-CN17QMv6.js} +2 -2
  151. package/dist/web/public/assets/{status-badge-nSFUUEfy.js.map → status-badge-CN17QMv6.js.map} +1 -1
  152. package/dist/web/public/assets/{subtasks-C_x1RLJA.js → subtasks-gjO9Hf1a.js} +2 -2
  153. package/dist/web/public/assets/{subtasks-C_x1RLJA.js.map → subtasks-gjO9Hf1a.js.map} +1 -1
  154. package/dist/web/public/assets/{table-BNqo2xb8.js → table-C4P3KPbF.js} +2 -2
  155. package/dist/web/public/assets/{table-BNqo2xb8.js.map → table-C4P3KPbF.js.map} +1 -1
  156. package/dist/web/public/assets/{topn-NGtwNz38.js → topn-BMw-Uy1R.js} +2 -2
  157. package/dist/web/public/assets/{topn-NGtwNz38.js.map → topn-BMw-Uy1R.js.map} +1 -1
  158. package/dist/web/public/assets/{trash-2-BoFq2ZOF.js → trash-2-DOV8CHL9.js} +2 -2
  159. package/dist/web/public/assets/{trash-2-BoFq2ZOF.js.map → trash-2-DOV8CHL9.js.map} +1 -1
  160. package/dist/web/public/assets/{use-background-tasks-CY2gWPBZ.js → use-background-tasks-CgZBaDBR.js} +2 -2
  161. package/dist/web/public/assets/{use-background-tasks-CY2gWPBZ.js.map → use-background-tasks-CgZBaDBR.js.map} +1 -1
  162. package/dist/web/public/assets/{use-llm-admin-CA5tUbEU.js → use-llm-admin-BNwZKmJ9.js} +2 -2
  163. package/dist/web/public/assets/{use-llm-admin-CA5tUbEU.js.map → use-llm-admin-BNwZKmJ9.js.map} +1 -1
  164. package/dist/web/public/assets/{use-memory-CxasvYqR.js → use-memory-D4ViUoXw.js} +2 -2
  165. package/dist/web/public/assets/{use-memory-CxasvYqR.js.map → use-memory-D4ViUoXw.js.map} +1 -1
  166. package/dist/web/public/assets/{use-observability-BOepIjX5.js → use-observability-DJYRVPKp.js} +2 -2
  167. package/dist/web/public/assets/{use-observability-BOepIjX5.js.map → use-observability-DJYRVPKp.js.map} +1 -1
  168. package/dist/web/public/assets/{use-settings-DBXvAYm9.js → use-settings-XXVWFAv6.js} +2 -2
  169. package/dist/web/public/assets/{use-settings-DBXvAYm9.js.map → use-settings-XXVWFAv6.js.map} +1 -1
  170. package/dist/web/public/assets/{use-workspace-dw_69jpb.js → use-workspace-BgEM7e1m.js} +2 -2
  171. package/dist/web/public/assets/{use-workspace-dw_69jpb.js.map → use-workspace-BgEM7e1m.js.map} +1 -1
  172. package/dist/web/public/assets/{useQuery-Ds6-WURB.js → useQuery-B25CPtUF.js} +2 -2
  173. package/dist/web/public/assets/{useQuery-Ds6-WURB.js.map → useQuery-B25CPtUF.js.map} +1 -1
  174. package/dist/web/public/assets/{vector-C5WBAtlL.js → vector-Dh4Sp_ea.js} +2 -2
  175. package/dist/web/public/assets/{vector-C5WBAtlL.js.map → vector-Dh4Sp_ea.js.map} +1 -1
  176. package/dist/web/public/assets/{viewer-DQG9P7-t.js → viewer-B1vINzWu.js} +2 -2
  177. package/dist/web/public/assets/{viewer-DQG9P7-t.js.map → viewer-B1vINzWu.js.map} +1 -1
  178. package/dist/web/public/assets/{workspace-Dku83Qqr.js → workspace-uGVMiBxd.js} +2 -2
  179. package/dist/web/public/assets/{workspace-Dku83Qqr.js.map → workspace-uGVMiBxd.js.map} +1 -1
  180. package/dist/web/public/assets/{workspaces-ClLQ253x.js → workspaces-C8PjcrCq.js} +2 -2
  181. package/dist/web/public/assets/{workspaces-ClLQ253x.js.map → workspaces-C8PjcrCq.js.map} +1 -1
  182. package/dist/web/public/assets/{x-ClXUlQDe.js → x-CGfY-U_P.js} +2 -2
  183. package/dist/web/public/assets/{x-ClXUlQDe.js.map → x-CGfY-U_P.js.map} +1 -1
  184. package/dist/web/public/index.html +1 -1
  185. package/dist/web/server.js +3 -0
  186. package/dist/web/server.js.map +1 -1
  187. package/package.json +1 -1
  188. package/dist/web/public/assets/native-agent-DMf0u4dm.js +0 -22
  189. package/dist/web/public/assets/native-agent-DMf0u4dm.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import{n as T,u as E,j as e,B as g,k as j,l as v,L as D,I}from"./index-CqwhfPlr.js";import{r as w}from"./react-Cb2sDjhD.js";import{u as L,s as _,a as z,t as F}from"./use-settings-DBXvAYm9.js";import{L as K}from"./loader-circle-U-jPjmeD.js";import{R as U}from"./refresh-ccw-CBiHL1tY.js";import{X as M}from"./x-ClXUlQDe.js";import{S as V}from"./save-DVHI3V6o.js";import{A as q}from"./arrow-up-NWC5K6Jw.js";import{A as J}from"./arrow-down-BkZ50IzL.js";import{C as W}from"./circle-check-BaxzYLlE.js";import{C as G}from"./circle-x-THl-PO3_.js";import"./useQuery-Ds6-WURB.js";/**
1
+ import{n as T,u as E,j as e,B as g,k as j,l as v,L as D,I}from"./index-D4Np2s3l.js";import{r as w}from"./react-Cb2sDjhD.js";import{u as L,s as _,a as z,t as F}from"./use-settings-XXVWFAv6.js";import{L as K}from"./loader-circle-BfXi9R6u.js";import{R as U}from"./refresh-ccw-C7VT3MFu.js";import{X as M}from"./x-CGfY-U_P.js";import{S as V}from"./save-B18KQmEd.js";import{A as q}from"./arrow-up-BQxFty9k.js";import{A as J}from"./arrow-down-BpfVJViL.js";import{C as W}from"./circle-check-BGjJhA0M.js";import{C as G}from"./circle-x-BziROBzb.js";import"./useQuery-B25CPtUF.js";/**
2
2
  * @license lucide-react v0.469.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -14,4 +14,4 @@ import{n as T,u as E,j as e,B as g,k as j,l as v,L as D,I}from"./index-CqwhfPlr.
14
14
  * This source code is licensed under the ISC license.
15
15
  * See the LICENSE file in the root directory of this source tree.
16
16
  */const Y=T("Key",[["path",{d:"m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4",key:"g0fldk"}],["path",{d:"m21 2-9.6 9.6",key:"1j0ho8"}],["circle",{cx:"7.5",cy:"15.5",r:"5.5",key:"yqb3hr"}]]);function Z(r,a){const o=(r??"").split(",").map(i=>i.trim()).filter(Boolean),h=new Set(a.map(i=>i.name)),m=new Set,x=[];for(const i of o)!h.has(i)||m.has(i)||(x.push({name:i,enabled:!0}),m.add(i));for(const i of a)m.has(i.name)||x.push({name:i.name,enabled:!1});return x}function B(r){return r.filter(a=>a.enabled).map(a=>a.name).join(",")}function ue(){const{t:r}=E(["settings","common"]),a=L({reveal:!1}),o=_(),h=z(),m=F(),x=a.data?.env??{},i=o.data?.providers??[],y=o.data?.chain??[],d=w.useMemo(()=>({chain:Z(x.IMHUB_WEB_SEARCH_PROVIDERS,i),keys:{},keysTouched:{}}),[x.IMHUB_WEB_SEARCH_PROVIDERS,i]),[l,u]=w.useState(d),[b,C]=w.useState("");w.useEffect(()=>{const s=JSON.stringify(d);s!==b&&(u(d),C(s))},[d,b]);const k=JSON.stringify(l.chain)!==JSON.stringify(d.chain)||Object.keys(l.keysTouched).length>0;function N(s,t){u(c=>{const n=[...c.chain],f=s+t;return f<0||f>=n.length?c:([n[s],n[f]]=[n[f],n[s]],{...c,chain:n})})}function S(s,t){u(c=>{const n=[...c.chain];return n[s]={...n[s],enabled:t},{...c,chain:n}})}function p(s,t){u(c=>({...c,keys:{...c.keys,[s]:t},keysTouched:{...c.keysTouched,[s]:!0}}))}function P(s){u(t=>({...t,keys:{...t.keys,[s]:""},keysTouched:{...t.keysTouched,[s]:!0}}))}async function A(){const s={},t=B(l.chain),c=B(d.chain);t!==c&&(s.IMHUB_WEB_SEARCH_PROVIDERS=t||null);for(const[n,f]of Object.entries(l.keysTouched)){if(!f)continue;const R=l.keys[n]??"";s[n]=R.trim()===""?null:R}if(Object.keys(s).length!==0)try{await h.mutateAsync({updates:s}),o.refetch(),v.success(r("search.savedToast")),u(n=>({...n,keys:{},keysTouched:{}}))}catch(n){v.error(n?.message??String(n))}}function H(){u(d)}async function O(s){try{const t=await m.mutateAsync({provider:s,query:"agim ping"});t.ok?v.success(r("search.testOk",{provider:s,hits:t.hits,ms:t.latencyMs})):v.error(r("search.testFail",{provider:s,error:t.error??"unknown error"}))}catch(t){v.error(t?.message??String(t))}}return e.jsxs("div",{className:"mx-auto flex max-w-4xl flex-col gap-6",children:[e.jsxs("header",{className:"flex items-center gap-3",children:[e.jsx("h1",{className:"text-xl font-semibold",children:r("search.title")}),e.jsxs(g,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>{a.refetch(),o.refetch()},disabled:a.isFetching||o.isFetching,"aria-label":r("actions.refresh",{ns:"common"}),children:[a.isFetching||o.isFetching?e.jsx(K,{className:"h-4 w-4 animate-spin"}):e.jsx(U,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:r("search.refresh")})]})]}),e.jsx("p",{className:"text-sm text-text-dim",children:r("search.subtitle")}),e.jsx($,{live:y}),a.isLoading||o.isLoading?e.jsx("div",{className:"h-64 rounded-md bg-surface-2 animate-pulse"}):e.jsx("section",{className:"flex flex-col gap-2",children:l.chain.map((s,t)=>{const c=i.find(n=>n.name===s.name);return e.jsx(ee,{info:c,entry:s,idx:t,count:l.chain.length,keyValue:c?.envKey?l.keys[c.envKey]:void 0,keyTouched:c?.envKey?!!l.keysTouched[c.envKey]:!1,onMove:n=>N(t,n),onToggle:n=>S(t,n),onSetKey:n=>c?.envKey&&p(c.envKey,n),onClearKey:()=>c?.envKey&&P(c.envKey),onTest:()=>O(s.name),testing:m.isPending},s.name)})}),k&&e.jsxs("div",{className:"sticky bottom-2 flex items-center gap-2 rounded-md border border-border bg-surface px-4 py-3 shadow",children:[e.jsx(j,{variant:"info",children:r("search.unsaved")}),e.jsxs(g,{variant:"ghost",size:"sm",className:"ml-auto",onClick:H,disabled:h.isPending,children:[e.jsx(M,{className:"h-4 w-4"})," ",r("search.discard")]}),e.jsxs(g,{size:"sm",onClick:()=>void A(),disabled:h.isPending,children:[h.isPending?e.jsx(K,{className:"h-4 w-4 animate-spin"}):e.jsx(V,{className:"h-4 w-4"}),r("search.save")]})]})]})}function $({live:r}){const{t:a}=E("settings");return e.jsxs("section",{className:"rounded-md border border-border bg-surface px-4 py-3",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx(X,{className:"h-4 w-4 text-text-dim"}),e.jsx("span",{className:"text-text-dim",children:a("search.chainLabel")}),r.length===0?e.jsx(j,{variant:"outline",children:a("search.chainEmpty")}):e.jsx("span",{className:"font-mono text-xs",children:r.join(" → ")})]}),e.jsx("p",{className:"mt-1 text-[11px] text-text-dim",children:a("search.chainHint")})]})}function ee(r){const{t:a}=E("settings"),{info:o,entry:h,idx:m,count:x,keyValue:i,keyTouched:y,onMove:d,onToggle:l,onSetKey:u,onClearKey:b,onTest:C,testing:k}=r,N=!!o?.envKey,S=!!o?.available||y&&!!i;return e.jsxs("div",{className:"rounded-md border border-border bg-surface p-3",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("div",{className:"flex flex-col",children:[e.jsx("button",{type:"button",className:"h-5 w-5 rounded text-text-dim hover:bg-surface-hover disabled:opacity-30",onClick:()=>d(-1),disabled:m===0,"aria-label":a("search.moveUp"),children:e.jsx(q,{className:"h-4 w-4"})}),e.jsx("button",{type:"button",className:"h-5 w-5 rounded text-text-dim hover:bg-surface-hover disabled:opacity-30",onClick:()=>d(1),disabled:m===x-1,"aria-label":a("search.moveDown"),children:e.jsx(J,{className:"h-4 w-4"})})]}),e.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:h.enabled,onChange:p=>l(p.target.checked),className:"h-4 w-4 accent-accent cursor-pointer"}),e.jsx("span",{className:"font-mono text-sm",children:h.name})]}),N?S?e.jsxs(j,{variant:"success",children:[e.jsx(W,{className:"mr-1 h-3 w-3"})," ",a("search.configured")]}):e.jsxs(j,{variant:"warning",children:[e.jsx(G,{className:"mr-1 h-3 w-3"})," ",a("search.missingKey")]}):e.jsx(j,{variant:"outline",children:a("search.noKey")}),e.jsx("div",{className:"ml-auto flex items-center gap-1",children:e.jsxs(g,{size:"sm",variant:"ghost",onClick:C,disabled:k||!h.enabled,"aria-label":a("search.testBtn"),children:[k?e.jsx(K,{className:"h-4 w-4 animate-spin"}):e.jsx(Q,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:a("search.testBtn")})]})})]}),N&&e.jsxs("div",{className:"mt-3 flex flex-col gap-1",children:[e.jsxs(D,{className:"text-xs font-medium",children:[e.jsx(Y,{className:"mr-1 inline h-3 w-3"}),o?.envKey]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(I,{type:"password",value:i??"",onChange:p=>u(p.target.value),placeholder:o?.available&&!y?a("search.placeholderConfigured"):a("search.placeholderEnter"),className:"font-mono text-xs"}),o?.available&&!y&&e.jsx(g,{size:"sm",variant:"ghost",onClick:b,"aria-label":a("search.clearKey"),children:e.jsx(M,{className:"h-4 w-4"})})]}),e.jsx("p",{className:"text-[11px] text-text-dim",children:a("search.keyHint",{envKey:o?.envKey})})]})]})}export{ue as default};
17
- //# sourceMappingURL=search-BYPDbBkC.js.map
17
+ //# sourceMappingURL=search-CA_pO63g.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"search-BYPDbBkC.js","sources":["../../node_modules/lucide-react/dist/esm/icons/flask-conical.js","../../node_modules/lucide-react/dist/esm/icons/globe.js","../../node_modules/lucide-react/dist/esm/icons/key.js","../../src/routes/settings/search.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FlaskConical = createLucideIcon(\"FlaskConical\", [\n [\n \"path\",\n {\n d: \"M14 2v6a2 2 0 0 0 .245.96l5.51 10.08A2 2 0 0 1 18 22H6a2 2 0 0 1-1.755-2.96l5.51-10.08A2 2 0 0 0 10 8V2\",\n key: \"18mbvz\"\n }\n ],\n [\"path\", { d: \"M6.453 15h11.094\", key: \"3shlmq\" }],\n [\"path\", { d: \"M8.5 2h7\", key: \"csnxdl\" }]\n]);\n\nexport { FlaskConical as default };\n//# sourceMappingURL=flask-conical.js.map\n","/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Globe = createLucideIcon(\"Globe\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\", key: \"13o1zl\" }],\n [\"path\", { d: \"M2 12h20\", key: \"9i4pu4\" }]\n]);\n\nexport { Globe as default };\n//# sourceMappingURL=globe.js.map\n","/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Key = createLucideIcon(\"Key\", [\n [\"path\", { d: \"m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4\", key: \"g0fldk\" }],\n [\"path\", { d: \"m21 2-9.6 9.6\", key: \"1j0ho8\" }],\n [\"circle\", { cx: \"7.5\", cy: \"15.5\", r: \"5.5\", key: \"yqb3hr\" }]\n]);\n\nexport { Key as default };\n//# sourceMappingURL=key.js.map\n","/**\n * /settings/search — web_search provider config (v1.2.126).\n *\n * One row per registered provider (Tavily / Brave / Serper / Exa /\n * DuckDuckGo / Metaso): API-key input (masked-by-default), enable\n * toggle (= \"is this name in the chain?\"), reorder via up / down,\n * one-shot test button. The chain preview at the top shows what\n * IMHUB_WEB_SEARCH_PROVIDERS resolves to right now.\n *\n * Persistence: API keys go via PUT /api/env (which masks GET +\n * refuses echoed masks on PUT); the chain order is a single CSV\n * env key — same endpoint. Save is one round-trip per dirty key.\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport {\n ArrowDown, ArrowUp, CheckCircle2, FlaskConical, Globe, Key,\n Loader2, RefreshCcw, Save, X, XCircle,\n} from 'lucide-react'\n\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport {\n useEnv,\n useSearchProviders,\n useTestSearchProvider,\n useUpdateEnv,\n} from '@/hooks/use-settings'\nimport type { SearchProviderInfo } from '@/types/api'\n\ninterface ChainEntry {\n name: string\n enabled: boolean\n}\n\ninterface Draft {\n /** Provider chain — every known provider, with `enabled`\n * reflecting \"is name in the CSV\". Order is the row order. */\n chain: ChainEntry[]\n /** Each provider's API-key input. Keyed by envKey (e.g.\n * TAVILY_API_KEY). Holds either '' (clear) or the new plaintext\n * the operator typed. We never load values back from the server. */\n keys: Record<string, string>\n /** Tracks which key fields the operator actually touched — so\n * Save only sends the diff and untouched masked keys are left\n * alone. */\n keysTouched: Record<string, boolean>\n}\n\nfunction envChainOrder(envValue: string | undefined, providers: SearchProviderInfo[]): ChainEntry[] {\n // Parse the CSV chain; preserve operator order; tail-append any\n // provider not in the CSV as disabled so they remain renderable.\n const raw = (envValue ?? '').split(',').map((s) => s.trim()).filter(Boolean)\n const known = new Set(providers.map((p) => p.name))\n const seen = new Set<string>()\n const out: ChainEntry[] = []\n for (const name of raw) {\n if (!known.has(name) || seen.has(name)) continue\n out.push({ name, enabled: true })\n seen.add(name)\n }\n for (const p of providers) {\n if (seen.has(p.name)) continue\n out.push({ name: p.name, enabled: false })\n }\n return out\n}\n\nfunction chainToCsv(chain: ChainEntry[]): string {\n return chain.filter((c) => c.enabled).map((c) => c.name).join(',')\n}\n\nexport default function SettingsSearchRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const envQuery = useEnv({ reveal: false })\n const providersQuery = useSearchProviders()\n const updateEnv = useUpdateEnv()\n const testProvider = useTestSearchProvider()\n\n const envData = envQuery.data?.env ?? {}\n const providers = providersQuery.data?.providers ?? []\n const live = providersQuery.data?.chain ?? []\n\n const initial = useMemo<Draft>(\n () => ({\n chain: envChainOrder(envData.IMHUB_WEB_SEARCH_PROVIDERS, providers),\n keys: {},\n keysTouched: {},\n }),\n [envData.IMHUB_WEB_SEARCH_PROVIDERS, providers],\n )\n\n const [draft, setDraft] = useState<Draft>(initial)\n const [syncedHash, setSyncedHash] = useState('')\n\n useEffect(() => {\n const hash = JSON.stringify(initial)\n if (hash !== syncedHash) {\n setDraft(initial)\n setSyncedHash(hash)\n }\n }, [initial, syncedHash])\n\n const isDirty =\n JSON.stringify(draft.chain) !== JSON.stringify(initial.chain) ||\n Object.keys(draft.keysTouched).length > 0\n\n function moveRow(idx: number, delta: -1 | 1): void {\n setDraft((d) => {\n const next = [...d.chain]\n const swap = idx + delta\n if (swap < 0 || swap >= next.length) return d\n ;[next[idx], next[swap]] = [next[swap], next[idx]]\n return { ...d, chain: next }\n })\n }\n\n function toggleRow(idx: number, enabled: boolean): void {\n setDraft((d) => {\n const next = [...d.chain]\n next[idx] = { ...next[idx], enabled }\n return { ...d, chain: next }\n })\n }\n\n function setKey(envKey: string, value: string): void {\n setDraft((d) => ({\n ...d,\n keys: { ...d.keys, [envKey]: value },\n keysTouched: { ...d.keysTouched, [envKey]: true },\n }))\n }\n\n function clearKey(envKey: string): void {\n setDraft((d) => ({\n ...d,\n keys: { ...d.keys, [envKey]: '' },\n keysTouched: { ...d.keysTouched, [envKey]: true },\n }))\n }\n\n async function onSave(): Promise<void> {\n const updates: Record<string, string | null> = {}\n const nextCsv = chainToCsv(draft.chain)\n const initialCsv = chainToCsv(initial.chain)\n if (nextCsv !== initialCsv) {\n updates.IMHUB_WEB_SEARCH_PROVIDERS = nextCsv || null\n }\n for (const [envKey, touched] of Object.entries(draft.keysTouched)) {\n if (!touched) continue\n const v = draft.keys[envKey] ?? ''\n updates[envKey] = v.trim() === '' ? null : v\n }\n if (Object.keys(updates).length === 0) return\n try {\n await updateEnv.mutateAsync({ updates })\n // Refetch both — env keys changed availability, chain order changed.\n void providersQuery.refetch()\n toast.success(t('search.savedToast'))\n setDraft((d) => ({ ...d, keys: {}, keysTouched: {} }))\n } catch (err) {\n toast.error(((err as Error)?.message ?? String(err)))\n }\n }\n\n function onDiscard(): void {\n setDraft(initial)\n }\n\n async function onTest(provider: string): Promise<void> {\n try {\n const result = await testProvider.mutateAsync({\n provider,\n // Short, harmless probe — the dispatcher only needs to\n // verify the upstream auth + transport.\n query: 'agim ping',\n })\n if (result.ok) {\n toast.success(\n t('search.testOk', { provider, hits: result.hits, ms: result.latencyMs }),\n )\n } else {\n toast.error(\n t('search.testFail', { provider, error: result.error ?? 'unknown error' }),\n )\n }\n } catch (err) {\n toast.error((err as Error)?.message ?? String(err))\n }\n }\n\n return (\n <div className=\"mx-auto flex max-w-4xl flex-col gap-6\">\n <header className=\"flex items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('search.title')}</h1>\n <Button\n variant=\"ghost\" size=\"sm\" className=\"ml-auto\"\n onClick={() => {\n void envQuery.refetch()\n void providersQuery.refetch()\n }}\n disabled={envQuery.isFetching || providersQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {envQuery.isFetching || providersQuery.isFetching\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('search.refresh')}</span>\n </Button>\n </header>\n <p className=\"text-sm text-text-dim\">{t('search.subtitle')}</p>\n\n <ChainPreview live={live} />\n\n {envQuery.isLoading || providersQuery.isLoading ? (\n <div className=\"h-64 rounded-md bg-surface-2 animate-pulse\" />\n ) : (\n <section className=\"flex flex-col gap-2\">\n {draft.chain.map((entry, idx) => {\n const info = providers.find((p) => p.name === entry.name)\n return (\n <ProviderRow\n key={entry.name}\n info={info}\n entry={entry}\n idx={idx}\n count={draft.chain.length}\n keyValue={info?.envKey ? draft.keys[info.envKey] : undefined}\n keyTouched={info?.envKey ? !!draft.keysTouched[info.envKey] : false}\n onMove={(d) => moveRow(idx, d)}\n onToggle={(v) => toggleRow(idx, v)}\n onSetKey={(v) => info?.envKey && setKey(info.envKey, v)}\n onClearKey={() => info?.envKey && clearKey(info.envKey)}\n onTest={() => onTest(entry.name)}\n testing={testProvider.isPending}\n />\n )\n })}\n </section>\n )}\n\n {isDirty && (\n <div className=\"sticky bottom-2 flex items-center gap-2 rounded-md border border-border bg-surface px-4 py-3 shadow\">\n <Badge variant=\"info\">{t('search.unsaved')}</Badge>\n <Button\n variant=\"ghost\" size=\"sm\" className=\"ml-auto\"\n onClick={onDiscard}\n disabled={updateEnv.isPending}\n >\n <X className=\"h-4 w-4\" /> {t('search.discard')}\n </Button>\n <Button\n size=\"sm\"\n onClick={() => void onSave()}\n disabled={updateEnv.isPending}\n >\n {updateEnv.isPending\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <Save className=\"h-4 w-4\" />}\n {t('search.save')}\n </Button>\n </div>\n )}\n </div>\n )\n}\n\nfunction ChainPreview({ live }: { live: string[] }): JSX.Element {\n const { t } = useTranslation('settings')\n return (\n <section className=\"rounded-md border border-border bg-surface px-4 py-3\">\n <div className=\"flex items-center gap-2 text-sm\">\n <Globe className=\"h-4 w-4 text-text-dim\" />\n <span className=\"text-text-dim\">{t('search.chainLabel')}</span>\n {live.length === 0 ? (\n <Badge variant=\"outline\">{t('search.chainEmpty')}</Badge>\n ) : (\n <span className=\"font-mono text-xs\">{live.join(' → ')}</span>\n )}\n </div>\n <p className=\"mt-1 text-[11px] text-text-dim\">{t('search.chainHint')}</p>\n </section>\n )\n}\n\ninterface ProviderRowProps {\n info: SearchProviderInfo | undefined\n entry: ChainEntry\n idx: number\n count: number\n keyValue: string | undefined\n keyTouched: boolean\n onMove: (delta: -1 | 1) => void\n onToggle: (v: boolean) => void\n onSetKey: (v: string) => void\n onClearKey: () => void\n onTest: () => void\n testing: boolean\n}\n\nfunction ProviderRow(props: ProviderRowProps): JSX.Element {\n const { t } = useTranslation('settings')\n const { info, entry, idx, count, keyValue, keyTouched, onMove, onToggle,\n onSetKey, onClearKey, onTest, testing } = props\n const needsKey = !!info?.envKey\n const available = !!info?.available || (keyTouched && !!keyValue)\n return (\n <div className=\"rounded-md border border-border bg-surface p-3\">\n <div className=\"flex items-center gap-2\">\n <div className=\"flex flex-col\">\n <button\n type=\"button\"\n className=\"h-5 w-5 rounded text-text-dim hover:bg-surface-hover disabled:opacity-30\"\n onClick={() => onMove(-1)}\n disabled={idx === 0}\n aria-label={t('search.moveUp')}\n >\n <ArrowUp className=\"h-4 w-4\" />\n </button>\n <button\n type=\"button\"\n className=\"h-5 w-5 rounded text-text-dim hover:bg-surface-hover disabled:opacity-30\"\n onClick={() => onMove(1)}\n disabled={idx === count - 1}\n aria-label={t('search.moveDown')}\n >\n <ArrowDown className=\"h-4 w-4\" />\n </button>\n </div>\n\n <label className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={entry.enabled}\n onChange={(e) => onToggle(e.target.checked)}\n className=\"h-4 w-4 accent-accent cursor-pointer\"\n />\n <span className=\"font-mono text-sm\">{entry.name}</span>\n </label>\n\n {!needsKey ? (\n <Badge variant=\"outline\">{t('search.noKey')}</Badge>\n ) : available ? (\n <Badge variant=\"success\">\n <CheckCircle2 className=\"mr-1 h-3 w-3\" /> {t('search.configured')}\n </Badge>\n ) : (\n <Badge variant=\"warning\">\n <XCircle className=\"mr-1 h-3 w-3\" /> {t('search.missingKey')}\n </Badge>\n )}\n\n <div className=\"ml-auto flex items-center gap-1\">\n <Button\n size=\"sm\" variant=\"ghost\"\n onClick={onTest}\n disabled={testing || !entry.enabled}\n aria-label={t('search.testBtn')}\n >\n {testing\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <FlaskConical className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('search.testBtn')}</span>\n </Button>\n </div>\n </div>\n\n {needsKey && (\n <div className=\"mt-3 flex flex-col gap-1\">\n <Label className=\"text-xs font-medium\">\n <Key className=\"mr-1 inline h-3 w-3\" />\n {info?.envKey}\n </Label>\n <div className=\"flex items-center gap-2\">\n <Input\n type=\"password\"\n value={keyValue ?? ''}\n onChange={(e) => onSetKey(e.target.value)}\n placeholder={\n info?.available && !keyTouched\n ? t('search.placeholderConfigured')\n : t('search.placeholderEnter')\n }\n className=\"font-mono text-xs\"\n />\n {info?.available && !keyTouched && (\n <Button\n size=\"sm\" variant=\"ghost\"\n onClick={onClearKey}\n aria-label={t('search.clearKey')}\n >\n <X className=\"h-4 w-4\" />\n </Button>\n )}\n </div>\n <p className=\"text-[11px] text-text-dim\">\n {t('search.keyHint', { envKey: info?.envKey })}\n </p>\n </div>\n )}\n </div>\n )\n}\n"],"names":["FlaskConical","createLucideIcon","Globe","Key","envChainOrder","envValue","providers","raw","s","known","p","seen","out","name","chainToCsv","chain","c","SettingsSearchRoute","t","useTranslation","envQuery","useEnv","providersQuery","useSearchProviders","updateEnv","useUpdateEnv","testProvider","useTestSearchProvider","envData","live","initial","useMemo","draft","setDraft","useState","syncedHash","setSyncedHash","useEffect","hash","isDirty","moveRow","idx","delta","d","next","swap","toggleRow","enabled","setKey","envKey","value","clearKey","onSave","updates","nextCsv","initialCsv","touched","v","toast","err","onDiscard","onTest","provider","result","jsxs","jsx","Button","Loader2","RefreshCcw","ChainPreview","entry","info","ProviderRow","Badge","X","Save","props","count","keyValue","keyTouched","onMove","onToggle","onSetKey","onClearKey","testing","needsKey","available","ArrowUp","ArrowDown","e","CheckCircle2","XCircle","Label","Input"],"mappings":"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","x_google_ignoreList":[0,1,2]}
1
+ {"version":3,"file":"search-CA_pO63g.js","sources":["../../node_modules/lucide-react/dist/esm/icons/flask-conical.js","../../node_modules/lucide-react/dist/esm/icons/globe.js","../../node_modules/lucide-react/dist/esm/icons/key.js","../../src/routes/settings/search.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FlaskConical = createLucideIcon(\"FlaskConical\", [\n [\n \"path\",\n {\n d: \"M14 2v6a2 2 0 0 0 .245.96l5.51 10.08A2 2 0 0 1 18 22H6a2 2 0 0 1-1.755-2.96l5.51-10.08A2 2 0 0 0 10 8V2\",\n key: \"18mbvz\"\n }\n ],\n [\"path\", { d: \"M6.453 15h11.094\", key: \"3shlmq\" }],\n [\"path\", { d: \"M8.5 2h7\", key: \"csnxdl\" }]\n]);\n\nexport { FlaskConical as default };\n//# sourceMappingURL=flask-conical.js.map\n","/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Globe = createLucideIcon(\"Globe\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\", key: \"13o1zl\" }],\n [\"path\", { d: \"M2 12h20\", key: \"9i4pu4\" }]\n]);\n\nexport { Globe as default };\n//# sourceMappingURL=globe.js.map\n","/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Key = createLucideIcon(\"Key\", [\n [\"path\", { d: \"m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4\", key: \"g0fldk\" }],\n [\"path\", { d: \"m21 2-9.6 9.6\", key: \"1j0ho8\" }],\n [\"circle\", { cx: \"7.5\", cy: \"15.5\", r: \"5.5\", key: \"yqb3hr\" }]\n]);\n\nexport { Key as default };\n//# sourceMappingURL=key.js.map\n","/**\n * /settings/search — web_search provider config (v1.2.126).\n *\n * One row per registered provider (Tavily / Brave / Serper / Exa /\n * DuckDuckGo / Metaso): API-key input (masked-by-default), enable\n * toggle (= \"is this name in the chain?\"), reorder via up / down,\n * one-shot test button. The chain preview at the top shows what\n * IMHUB_WEB_SEARCH_PROVIDERS resolves to right now.\n *\n * Persistence: API keys go via PUT /api/env (which masks GET +\n * refuses echoed masks on PUT); the chain order is a single CSV\n * env key — same endpoint. Save is one round-trip per dirty key.\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport {\n ArrowDown, ArrowUp, CheckCircle2, FlaskConical, Globe, Key,\n Loader2, RefreshCcw, Save, X, XCircle,\n} from 'lucide-react'\n\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport {\n useEnv,\n useSearchProviders,\n useTestSearchProvider,\n useUpdateEnv,\n} from '@/hooks/use-settings'\nimport type { SearchProviderInfo } from '@/types/api'\n\ninterface ChainEntry {\n name: string\n enabled: boolean\n}\n\ninterface Draft {\n /** Provider chain — every known provider, with `enabled`\n * reflecting \"is name in the CSV\". Order is the row order. */\n chain: ChainEntry[]\n /** Each provider's API-key input. Keyed by envKey (e.g.\n * TAVILY_API_KEY). Holds either '' (clear) or the new plaintext\n * the operator typed. We never load values back from the server. */\n keys: Record<string, string>\n /** Tracks which key fields the operator actually touched — so\n * Save only sends the diff and untouched masked keys are left\n * alone. */\n keysTouched: Record<string, boolean>\n}\n\nfunction envChainOrder(envValue: string | undefined, providers: SearchProviderInfo[]): ChainEntry[] {\n // Parse the CSV chain; preserve operator order; tail-append any\n // provider not in the CSV as disabled so they remain renderable.\n const raw = (envValue ?? '').split(',').map((s) => s.trim()).filter(Boolean)\n const known = new Set(providers.map((p) => p.name))\n const seen = new Set<string>()\n const out: ChainEntry[] = []\n for (const name of raw) {\n if (!known.has(name) || seen.has(name)) continue\n out.push({ name, enabled: true })\n seen.add(name)\n }\n for (const p of providers) {\n if (seen.has(p.name)) continue\n out.push({ name: p.name, enabled: false })\n }\n return out\n}\n\nfunction chainToCsv(chain: ChainEntry[]): string {\n return chain.filter((c) => c.enabled).map((c) => c.name).join(',')\n}\n\nexport default function SettingsSearchRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const envQuery = useEnv({ reveal: false })\n const providersQuery = useSearchProviders()\n const updateEnv = useUpdateEnv()\n const testProvider = useTestSearchProvider()\n\n const envData = envQuery.data?.env ?? {}\n const providers = providersQuery.data?.providers ?? []\n const live = providersQuery.data?.chain ?? []\n\n const initial = useMemo<Draft>(\n () => ({\n chain: envChainOrder(envData.IMHUB_WEB_SEARCH_PROVIDERS, providers),\n keys: {},\n keysTouched: {},\n }),\n [envData.IMHUB_WEB_SEARCH_PROVIDERS, providers],\n )\n\n const [draft, setDraft] = useState<Draft>(initial)\n const [syncedHash, setSyncedHash] = useState('')\n\n useEffect(() => {\n const hash = JSON.stringify(initial)\n if (hash !== syncedHash) {\n setDraft(initial)\n setSyncedHash(hash)\n }\n }, [initial, syncedHash])\n\n const isDirty =\n JSON.stringify(draft.chain) !== JSON.stringify(initial.chain) ||\n Object.keys(draft.keysTouched).length > 0\n\n function moveRow(idx: number, delta: -1 | 1): void {\n setDraft((d) => {\n const next = [...d.chain]\n const swap = idx + delta\n if (swap < 0 || swap >= next.length) return d\n ;[next[idx], next[swap]] = [next[swap], next[idx]]\n return { ...d, chain: next }\n })\n }\n\n function toggleRow(idx: number, enabled: boolean): void {\n setDraft((d) => {\n const next = [...d.chain]\n next[idx] = { ...next[idx], enabled }\n return { ...d, chain: next }\n })\n }\n\n function setKey(envKey: string, value: string): void {\n setDraft((d) => ({\n ...d,\n keys: { ...d.keys, [envKey]: value },\n keysTouched: { ...d.keysTouched, [envKey]: true },\n }))\n }\n\n function clearKey(envKey: string): void {\n setDraft((d) => ({\n ...d,\n keys: { ...d.keys, [envKey]: '' },\n keysTouched: { ...d.keysTouched, [envKey]: true },\n }))\n }\n\n async function onSave(): Promise<void> {\n const updates: Record<string, string | null> = {}\n const nextCsv = chainToCsv(draft.chain)\n const initialCsv = chainToCsv(initial.chain)\n if (nextCsv !== initialCsv) {\n updates.IMHUB_WEB_SEARCH_PROVIDERS = nextCsv || null\n }\n for (const [envKey, touched] of Object.entries(draft.keysTouched)) {\n if (!touched) continue\n const v = draft.keys[envKey] ?? ''\n updates[envKey] = v.trim() === '' ? null : v\n }\n if (Object.keys(updates).length === 0) return\n try {\n await updateEnv.mutateAsync({ updates })\n // Refetch both — env keys changed availability, chain order changed.\n void providersQuery.refetch()\n toast.success(t('search.savedToast'))\n setDraft((d) => ({ ...d, keys: {}, keysTouched: {} }))\n } catch (err) {\n toast.error(((err as Error)?.message ?? String(err)))\n }\n }\n\n function onDiscard(): void {\n setDraft(initial)\n }\n\n async function onTest(provider: string): Promise<void> {\n try {\n const result = await testProvider.mutateAsync({\n provider,\n // Short, harmless probe — the dispatcher only needs to\n // verify the upstream auth + transport.\n query: 'agim ping',\n })\n if (result.ok) {\n toast.success(\n t('search.testOk', { provider, hits: result.hits, ms: result.latencyMs }),\n )\n } else {\n toast.error(\n t('search.testFail', { provider, error: result.error ?? 'unknown error' }),\n )\n }\n } catch (err) {\n toast.error((err as Error)?.message ?? String(err))\n }\n }\n\n return (\n <div className=\"mx-auto flex max-w-4xl flex-col gap-6\">\n <header className=\"flex items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('search.title')}</h1>\n <Button\n variant=\"ghost\" size=\"sm\" className=\"ml-auto\"\n onClick={() => {\n void envQuery.refetch()\n void providersQuery.refetch()\n }}\n disabled={envQuery.isFetching || providersQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {envQuery.isFetching || providersQuery.isFetching\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('search.refresh')}</span>\n </Button>\n </header>\n <p className=\"text-sm text-text-dim\">{t('search.subtitle')}</p>\n\n <ChainPreview live={live} />\n\n {envQuery.isLoading || providersQuery.isLoading ? (\n <div className=\"h-64 rounded-md bg-surface-2 animate-pulse\" />\n ) : (\n <section className=\"flex flex-col gap-2\">\n {draft.chain.map((entry, idx) => {\n const info = providers.find((p) => p.name === entry.name)\n return (\n <ProviderRow\n key={entry.name}\n info={info}\n entry={entry}\n idx={idx}\n count={draft.chain.length}\n keyValue={info?.envKey ? draft.keys[info.envKey] : undefined}\n keyTouched={info?.envKey ? !!draft.keysTouched[info.envKey] : false}\n onMove={(d) => moveRow(idx, d)}\n onToggle={(v) => toggleRow(idx, v)}\n onSetKey={(v) => info?.envKey && setKey(info.envKey, v)}\n onClearKey={() => info?.envKey && clearKey(info.envKey)}\n onTest={() => onTest(entry.name)}\n testing={testProvider.isPending}\n />\n )\n })}\n </section>\n )}\n\n {isDirty && (\n <div className=\"sticky bottom-2 flex items-center gap-2 rounded-md border border-border bg-surface px-4 py-3 shadow\">\n <Badge variant=\"info\">{t('search.unsaved')}</Badge>\n <Button\n variant=\"ghost\" size=\"sm\" className=\"ml-auto\"\n onClick={onDiscard}\n disabled={updateEnv.isPending}\n >\n <X className=\"h-4 w-4\" /> {t('search.discard')}\n </Button>\n <Button\n size=\"sm\"\n onClick={() => void onSave()}\n disabled={updateEnv.isPending}\n >\n {updateEnv.isPending\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <Save className=\"h-4 w-4\" />}\n {t('search.save')}\n </Button>\n </div>\n )}\n </div>\n )\n}\n\nfunction ChainPreview({ live }: { live: string[] }): JSX.Element {\n const { t } = useTranslation('settings')\n return (\n <section className=\"rounded-md border border-border bg-surface px-4 py-3\">\n <div className=\"flex items-center gap-2 text-sm\">\n <Globe className=\"h-4 w-4 text-text-dim\" />\n <span className=\"text-text-dim\">{t('search.chainLabel')}</span>\n {live.length === 0 ? (\n <Badge variant=\"outline\">{t('search.chainEmpty')}</Badge>\n ) : (\n <span className=\"font-mono text-xs\">{live.join(' → ')}</span>\n )}\n </div>\n <p className=\"mt-1 text-[11px] text-text-dim\">{t('search.chainHint')}</p>\n </section>\n )\n}\n\ninterface ProviderRowProps {\n info: SearchProviderInfo | undefined\n entry: ChainEntry\n idx: number\n count: number\n keyValue: string | undefined\n keyTouched: boolean\n onMove: (delta: -1 | 1) => void\n onToggle: (v: boolean) => void\n onSetKey: (v: string) => void\n onClearKey: () => void\n onTest: () => void\n testing: boolean\n}\n\nfunction ProviderRow(props: ProviderRowProps): JSX.Element {\n const { t } = useTranslation('settings')\n const { info, entry, idx, count, keyValue, keyTouched, onMove, onToggle,\n onSetKey, onClearKey, onTest, testing } = props\n const needsKey = !!info?.envKey\n const available = !!info?.available || (keyTouched && !!keyValue)\n return (\n <div className=\"rounded-md border border-border bg-surface p-3\">\n <div className=\"flex items-center gap-2\">\n <div className=\"flex flex-col\">\n <button\n type=\"button\"\n className=\"h-5 w-5 rounded text-text-dim hover:bg-surface-hover disabled:opacity-30\"\n onClick={() => onMove(-1)}\n disabled={idx === 0}\n aria-label={t('search.moveUp')}\n >\n <ArrowUp className=\"h-4 w-4\" />\n </button>\n <button\n type=\"button\"\n className=\"h-5 w-5 rounded text-text-dim hover:bg-surface-hover disabled:opacity-30\"\n onClick={() => onMove(1)}\n disabled={idx === count - 1}\n aria-label={t('search.moveDown')}\n >\n <ArrowDown className=\"h-4 w-4\" />\n </button>\n </div>\n\n <label className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={entry.enabled}\n onChange={(e) => onToggle(e.target.checked)}\n className=\"h-4 w-4 accent-accent cursor-pointer\"\n />\n <span className=\"font-mono text-sm\">{entry.name}</span>\n </label>\n\n {!needsKey ? (\n <Badge variant=\"outline\">{t('search.noKey')}</Badge>\n ) : available ? (\n <Badge variant=\"success\">\n <CheckCircle2 className=\"mr-1 h-3 w-3\" /> {t('search.configured')}\n </Badge>\n ) : (\n <Badge variant=\"warning\">\n <XCircle className=\"mr-1 h-3 w-3\" /> {t('search.missingKey')}\n </Badge>\n )}\n\n <div className=\"ml-auto flex items-center gap-1\">\n <Button\n size=\"sm\" variant=\"ghost\"\n onClick={onTest}\n disabled={testing || !entry.enabled}\n aria-label={t('search.testBtn')}\n >\n {testing\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <FlaskConical className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('search.testBtn')}</span>\n </Button>\n </div>\n </div>\n\n {needsKey && (\n <div className=\"mt-3 flex flex-col gap-1\">\n <Label className=\"text-xs font-medium\">\n <Key className=\"mr-1 inline h-3 w-3\" />\n {info?.envKey}\n </Label>\n <div className=\"flex items-center gap-2\">\n <Input\n type=\"password\"\n value={keyValue ?? ''}\n onChange={(e) => onSetKey(e.target.value)}\n placeholder={\n info?.available && !keyTouched\n ? t('search.placeholderConfigured')\n : t('search.placeholderEnter')\n }\n className=\"font-mono text-xs\"\n />\n {info?.available && !keyTouched && (\n <Button\n size=\"sm\" variant=\"ghost\"\n onClick={onClearKey}\n aria-label={t('search.clearKey')}\n >\n <X className=\"h-4 w-4\" />\n </Button>\n )}\n </div>\n <p className=\"text-[11px] text-text-dim\">\n {t('search.keyHint', { envKey: info?.envKey })}\n </p>\n </div>\n )}\n </div>\n )\n}\n"],"names":["FlaskConical","createLucideIcon","Globe","Key","envChainOrder","envValue","providers","raw","s","known","p","seen","out","name","chainToCsv","chain","c","SettingsSearchRoute","t","useTranslation","envQuery","useEnv","providersQuery","useSearchProviders","updateEnv","useUpdateEnv","testProvider","useTestSearchProvider","envData","live","initial","useMemo","draft","setDraft","useState","syncedHash","setSyncedHash","useEffect","hash","isDirty","moveRow","idx","delta","d","next","swap","toggleRow","enabled","setKey","envKey","value","clearKey","onSave","updates","nextCsv","initialCsv","touched","v","toast","err","onDiscard","onTest","provider","result","jsxs","jsx","Button","Loader2","RefreshCcw","ChainPreview","entry","info","ProviderRow","Badge","X","Save","props","count","keyValue","keyTouched","onMove","onToggle","onSetKey","onClearKey","testing","needsKey","available","ArrowUp","ArrowDown","e","CheckCircle2","XCircle","Label","Input"],"mappings":"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","x_google_ignoreList":[0,1,2]}
@@ -1,7 +1,7 @@
1
- import{n as e}from"./index-CqwhfPlr.js";/**
1
+ import{n as e}from"./index-D4Np2s3l.js";/**
2
2
  * @license lucide-react v0.469.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
5
5
  * See the LICENSE file in the root directory of this source tree.
6
6
  */const r=e("Search",[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["path",{d:"m21 21-4.3-4.3",key:"1qie3q"}]]);export{r as S};
7
- //# sourceMappingURL=search-aw0y39Qs.js.map
7
+ //# sourceMappingURL=search-ChcW6uXM.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"search-aw0y39Qs.js","sources":["../../node_modules/lucide-react/dist/esm/icons/search.js"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Search = createLucideIcon(\"Search\", [\n [\"circle\", { cx: \"11\", cy: \"11\", r: \"8\", key: \"4ej97u\" }],\n [\"path\", { d: \"m21 21-4.3-4.3\", key: \"1qie3q\" }]\n]);\n\nexport { Search as default };\n//# sourceMappingURL=search.js.map\n"],"names":["Search","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAASC,EAAiB,SAAU,CACxC,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,IAAK,IAAK,SAAU,EACxD,CAAC,OAAQ,CAAE,EAAG,iBAAkB,IAAK,QAAQ,CAAE,CACjD,CAAC","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"search-ChcW6uXM.js","sources":["../../node_modules/lucide-react/dist/esm/icons/search.js"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Search = createLucideIcon(\"Search\", [\n [\"circle\", { cx: \"11\", cy: \"11\", r: \"8\", key: \"4ej97u\" }],\n [\"path\", { d: \"m21 21-4.3-4.3\", key: \"1qie3q\" }]\n]);\n\nexport { Search as default };\n//# sourceMappingURL=search.js.map\n"],"names":["Search","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAASC,EAAiB,SAAU,CACxC,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,IAAK,IAAK,SAAU,EACxD,CAAC,OAAQ,CAAE,EAAG,iBAAkB,IAAK,QAAQ,CAAE,CACjD,CAAC","x_google_ignoreList":[0]}
@@ -1,2 +1,2 @@
1
- import{u as N,j as e,B as I,I as d,S as h,f as _,g as f,h as p,i as u,o as T,l as j,m as E,p as M,c as w,k as U}from"./index-CqwhfPlr.js";import{r as v}from"./react-Cb2sDjhD.js";import{u as S,a as L}from"./use-settings-DBXvAYm9.js";import{L as C}from"./loader-circle-U-jPjmeD.js";import{R as O}from"./refresh-ccw-CBiHL1tY.js";import{S as H}from"./shield-alert-DjqqnTMk.js";import{C as R}from"./circle-check-BaxzYLlE.js";import"./useQuery-Ds6-WURB.js";function V(s){if(s==null)return!1;const a=s.toLowerCase();return a==="1"||a==="true"||a==="yes"||a==="on"}function $(){const{t:s}=N(["settings","common"]),a=S(),o=L(),[i,B]=v.useState(null),[b,y]=v.useState(!1);async function g(){y(!0);try{const t=await T.get("/api/security/diagnostics");B(t.diagnostics)}catch(t){j.error(E(t,s).message)}finally{y(!1)}}v.useEffect(()=>{g()},[]);async function r(t,l){try{await o.mutateAsync({updates:{[t]:l}}),j.success(s("security.savingToast")),await g()}catch(A){j.error(E(A,s).message)}}const n=a.data?.env??{};return e.jsxs("div",{className:"mx-auto flex max-w-4xl flex-col gap-4",children:[e.jsxs("header",{className:"flex flex-col gap-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx("h1",{className:"text-xl font-semibold",children:s("security.title")}),e.jsx(I,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>{a.refetch(),g()},disabled:a.isFetching||b,"aria-label":s("actions.refresh",{ns:"common"}),children:a.isFetching||b?e.jsx(C,{className:"h-4 w-4 animate-spin"}):e.jsx(O,{className:"h-4 w-4"})})]}),e.jsx("p",{className:"text-sm text-muted",children:s("security.subtitle")})]}),e.jsxs("section",{className:"rounded-lg border border-border bg-card p-4",children:[e.jsxs("h2",{className:"mb-3 flex items-center gap-2 text-sm font-semibold",children:[e.jsx(H,{className:"h-4 w-4"}),s("security.diagnostics.title")]}),i?e.jsxs("ul",{className:"grid gap-2 text-sm sm:grid-cols-2",children:[e.jsx(x,{label:s("security.diagnostics.runningAsRoot"),ok:i.runningAsRoot===!1,text:i.runningAsRoot===!0?s("security.diagnostics.runningAsRootHelp"):"OK"}),e.jsx(x,{label:s("security.diagnostics.envFilePerms"),ok:i.envFile.exists&&!i.envFile.tooPermissive,text:i.envFile.exists?i.envFile.tooPermissive?`${i.envFile.mode} — ${s("security.diagnostics.envFilePermsLax")}`:s("security.diagnostics.envFilePermsOk"):"—"}),e.jsx(x,{label:s("security.diagnostics.bwrapAvailable"),ok:i.bwrapAvailable,text:i.bwrapAvailable?"/usr/bin/bwrap":s("security.diagnostics.bwrapMissing")}),e.jsx(x,{label:s("security.diagnostics.senderAllowlist"),ok:i.senderAllowlistConfigured,text:i.senderAllowlistConfigured?s("security.diagnostics.senderAllowlistOn"):s("security.diagnostics.senderAllowlistOff")}),e.jsx(x,{label:s("security.diagnostics.adminAllowlist"),ok:i.adminAllowlistConfigured,text:i.adminAllowlistConfigured?s("security.diagnostics.adminAllowlistOn"):s("security.diagnostics.adminAllowlistOff")}),e.jsx(x,{label:s("security.diagnosticsPlatformBlacklist"),ok:i.platformBlacklist.length===0,text:i.platformBlacklist.length===0?"—":i.platformBlacklist.join(", ")})]}):e.jsx("p",{className:"text-sm text-muted",children:"…"})]}),e.jsx(m,{title:s("security.sender.title"),description:s("security.sender.description"),envKey:"IMHUB_ALLOWED_USERS",children:e.jsx(d,{defaultValue:n.IMHUB_ALLOWED_USERS??"",placeholder:s("security.sender.placeholder"),onBlur:t=>{const l=t.target.value.trim();r("IMHUB_ALLOWED_USERS",l===""?null:l)}})}),e.jsx(m,{title:s("security.exec.title"),description:s("security.exec.description"),children:e.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[e.jsx(c,{label:s("security.exec.sandbox"),children:e.jsxs(h,{value:(n.IMHUB_EXEC_SANDBOX??"").toLowerCase()==="bwrap"?"bwrap":"__none__",onValueChange:t=>void r("IMHUB_EXEC_SANDBOX",t==="__none__"?null:t),children:[e.jsx(_,{children:e.jsx(f,{})}),e.jsxs(p,{children:[e.jsx(u,{value:"__none__",children:s("security.exec.sandboxNone")}),e.jsxs(u,{value:"bwrap",disabled:!i?.bwrapAvailable,children:[s("security.exec.sandboxBwrap"),!i?.bwrapAvailable&&e.jsxs("span",{className:"ml-2 text-xs text-muted",children:["(",s("security.exec.sandboxBwrapMissing"),")"]})]})]})]})}),e.jsx(c,{label:s("security.exec.sandboxNet"),children:e.jsxs(h,{value:(n.IMHUB_EXEC_SANDBOX_NET??"").toLowerCase()==="off"?"off":"on",onValueChange:t=>void r("IMHUB_EXEC_SANDBOX_NET",t==="off"?"off":null),children:[e.jsx(_,{children:e.jsx(f,{})}),e.jsxs(p,{children:[e.jsx(u,{value:"on",children:s("security.exec.sandboxNetOn")}),e.jsx(u,{value:"off",children:s("security.exec.sandboxNetOff")})]})]})}),e.jsx(c,{label:s("security.exec.timeoutMs"),children:e.jsx(d,{type:"number",defaultValue:n.IMHUB_EXEC_TIMEOUT_MS??"",placeholder:"60000",onBlur:t=>{const l=t.target.value.trim();r("IMHUB_EXEC_TIMEOUT_MS",l===""?null:l)}})}),e.jsx(c,{label:s("security.exec.maxOutput"),children:e.jsx(d,{type:"number",defaultValue:n.IMHUB_EXEC_MAX_OUTPUT??"",placeholder:"32768",onBlur:t=>{const l=t.target.value.trim();r("IMHUB_EXEC_MAX_OUTPUT",l===""?null:l)}})})]})}),e.jsx(m,{title:s("security.web.title"),description:s("security.web.description"),children:e.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[e.jsx(c,{label:s("security.web.allowPrivate"),hint:s("security.web.allowPrivateHelp"),children:e.jsxs(h,{value:V(n.IMHUB_NATIVE_WEB_ALLOW_PRIVATE)?"1":"0",onValueChange:t=>void r("IMHUB_NATIVE_WEB_ALLOW_PRIVATE",t==="1"?"1":null),children:[e.jsx(_,{children:e.jsx(f,{})}),e.jsxs(p,{children:[e.jsx(u,{value:"0",children:"OFF"}),e.jsx(u,{value:"1",children:"ON"})]})]})}),e.jsx(c,{label:s("security.web.timeoutMs"),children:e.jsx(d,{type:"number",defaultValue:n.IMHUB_NATIVE_WEB_TIMEOUT_MS??"",placeholder:"30000",onBlur:t=>{const l=t.target.value.trim();r("IMHUB_NATIVE_WEB_TIMEOUT_MS",l===""?null:l)}})}),e.jsx("div",{className:"sm:col-span-2",children:e.jsx(c,{label:s("security.web.ssrfWhitelist"),children:e.jsx(d,{defaultValue:n.IMHUB_NATIVE_WEB_SSRF_WHITELIST??"",placeholder:s("security.web.ssrfWhitelistPlaceholder"),onBlur:t=>{const l=t.target.value.trim();r("IMHUB_NATIVE_WEB_SSRF_WHITELIST",l===""?null:l)}})})})]})}),e.jsx(m,{title:s("security.fs.title"),description:s("security.fs.description"),children:e.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[e.jsx(c,{label:s("security.fs.restrict"),children:e.jsxs(h,{value:(n.IMHUB_NATIVE_FS_RESTRICT??"1")==="0"?"0":"1",onValueChange:t=>void r("IMHUB_NATIVE_FS_RESTRICT",t==="0"?"0":null),children:[e.jsx(_,{children:e.jsx(f,{})}),e.jsxs(p,{children:[e.jsx(u,{value:"1",children:s("security.fs.restrictOn")}),e.jsx(u,{value:"0",children:s("security.fs.restrictOff")})]})]})}),e.jsx(c,{label:s("security.fs.timeoutMs"),children:e.jsx(d,{type:"number",defaultValue:n.IMHUB_NATIVE_FS_TIMEOUT_MS??"",placeholder:"60000",onBlur:t=>{const l=t.target.value.trim();r("IMHUB_NATIVE_FS_TIMEOUT_MS",l===""?null:l)}})})]})}),e.jsx(m,{title:s("security.delegation.title"),description:s("security.delegation.description"),envKey:"IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN",children:e.jsx(d,{type:"number",defaultValue:n.IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN??"",placeholder:"2",onBlur:t=>{const l=t.target.value.trim();r("IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN",l===""?null:l)}})}),e.jsxs(m,{title:s("security.platformBlacklist.title"),description:s("security.platformBlacklist.description"),envKey:"IMHUB_PLATFORM_BLACKLIST",children:[e.jsx(d,{defaultValue:n.IMHUB_PLATFORM_BLACKLIST??"",placeholder:s("security.platformBlacklist.placeholder"),onBlur:t=>{const l=t.target.value.trim();r("IMHUB_PLATFORM_BLACKLIST",l===""?null:l)}}),i?.platformBlacklist&&i.platformBlacklist.length>0&&e.jsxs("p",{className:"mt-2 text-[10px] text-muted",children:[s("security.platformBlacklist.currentLabel"),": ",i.platformBlacklist.join(", ")]})]})]})}function x({label:s,ok:a,text:o}){return e.jsxs("li",{className:"flex items-start gap-2",children:[a?e.jsx(R,{className:"mt-0.5 h-4 w-4 shrink-0 text-success"}):e.jsx(M,{className:"mt-0.5 h-4 w-4 shrink-0 text-warning"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("div",{className:"font-medium",children:s}),e.jsx("div",{className:w("text-xs",a?"text-muted":"text-warning"),children:o})]})]})}function m({title:s,description:a,envKey:o,children:i}){return e.jsxs("section",{className:"rounded-lg border border-border bg-card p-4",children:[e.jsxs("div",{className:"mb-2 flex flex-wrap items-baseline gap-2",children:[e.jsx("h2",{className:"text-sm font-semibold",children:s}),o&&e.jsx(U,{variant:"outline",className:"font-mono text-[10px]",children:o})]}),e.jsx("p",{className:"mb-3 text-xs text-muted",children:a}),i]})}function c({label:s,hint:a,children:o}){return e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("label",{className:"text-xs font-medium text-muted",children:s}),o,a&&e.jsx("p",{className:"text-[10px] text-muted",children:a})]})}export{$ as default};
2
- //# sourceMappingURL=security-DhN1kRac.js.map
1
+ import{u as N,j as e,B as I,I as d,S as h,f as _,g as f,h as p,i as u,o as T,l as j,m as E,p as M,c as w,k as U}from"./index-D4Np2s3l.js";import{r as v}from"./react-Cb2sDjhD.js";import{u as S,a as L}from"./use-settings-XXVWFAv6.js";import{L as C}from"./loader-circle-BfXi9R6u.js";import{R as O}from"./refresh-ccw-C7VT3MFu.js";import{S as H}from"./shield-alert-0q3ul8GH.js";import{C as R}from"./circle-check-BGjJhA0M.js";import"./useQuery-B25CPtUF.js";function V(s){if(s==null)return!1;const a=s.toLowerCase();return a==="1"||a==="true"||a==="yes"||a==="on"}function $(){const{t:s}=N(["settings","common"]),a=S(),o=L(),[i,B]=v.useState(null),[b,y]=v.useState(!1);async function g(){y(!0);try{const t=await T.get("/api/security/diagnostics");B(t.diagnostics)}catch(t){j.error(E(t,s).message)}finally{y(!1)}}v.useEffect(()=>{g()},[]);async function r(t,l){try{await o.mutateAsync({updates:{[t]:l}}),j.success(s("security.savingToast")),await g()}catch(A){j.error(E(A,s).message)}}const n=a.data?.env??{};return e.jsxs("div",{className:"mx-auto flex max-w-4xl flex-col gap-4",children:[e.jsxs("header",{className:"flex flex-col gap-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx("h1",{className:"text-xl font-semibold",children:s("security.title")}),e.jsx(I,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>{a.refetch(),g()},disabled:a.isFetching||b,"aria-label":s("actions.refresh",{ns:"common"}),children:a.isFetching||b?e.jsx(C,{className:"h-4 w-4 animate-spin"}):e.jsx(O,{className:"h-4 w-4"})})]}),e.jsx("p",{className:"text-sm text-muted",children:s("security.subtitle")})]}),e.jsxs("section",{className:"rounded-lg border border-border bg-card p-4",children:[e.jsxs("h2",{className:"mb-3 flex items-center gap-2 text-sm font-semibold",children:[e.jsx(H,{className:"h-4 w-4"}),s("security.diagnostics.title")]}),i?e.jsxs("ul",{className:"grid gap-2 text-sm sm:grid-cols-2",children:[e.jsx(x,{label:s("security.diagnostics.runningAsRoot"),ok:i.runningAsRoot===!1,text:i.runningAsRoot===!0?s("security.diagnostics.runningAsRootHelp"):"OK"}),e.jsx(x,{label:s("security.diagnostics.envFilePerms"),ok:i.envFile.exists&&!i.envFile.tooPermissive,text:i.envFile.exists?i.envFile.tooPermissive?`${i.envFile.mode} — ${s("security.diagnostics.envFilePermsLax")}`:s("security.diagnostics.envFilePermsOk"):"—"}),e.jsx(x,{label:s("security.diagnostics.bwrapAvailable"),ok:i.bwrapAvailable,text:i.bwrapAvailable?"/usr/bin/bwrap":s("security.diagnostics.bwrapMissing")}),e.jsx(x,{label:s("security.diagnostics.senderAllowlist"),ok:i.senderAllowlistConfigured,text:i.senderAllowlistConfigured?s("security.diagnostics.senderAllowlistOn"):s("security.diagnostics.senderAllowlistOff")}),e.jsx(x,{label:s("security.diagnostics.adminAllowlist"),ok:i.adminAllowlistConfigured,text:i.adminAllowlistConfigured?s("security.diagnostics.adminAllowlistOn"):s("security.diagnostics.adminAllowlistOff")}),e.jsx(x,{label:s("security.diagnosticsPlatformBlacklist"),ok:i.platformBlacklist.length===0,text:i.platformBlacklist.length===0?"—":i.platformBlacklist.join(", ")})]}):e.jsx("p",{className:"text-sm text-muted",children:"…"})]}),e.jsx(m,{title:s("security.sender.title"),description:s("security.sender.description"),envKey:"IMHUB_ALLOWED_USERS",children:e.jsx(d,{defaultValue:n.IMHUB_ALLOWED_USERS??"",placeholder:s("security.sender.placeholder"),onBlur:t=>{const l=t.target.value.trim();r("IMHUB_ALLOWED_USERS",l===""?null:l)}})}),e.jsx(m,{title:s("security.exec.title"),description:s("security.exec.description"),children:e.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[e.jsx(c,{label:s("security.exec.sandbox"),children:e.jsxs(h,{value:(n.IMHUB_EXEC_SANDBOX??"").toLowerCase()==="bwrap"?"bwrap":"__none__",onValueChange:t=>void r("IMHUB_EXEC_SANDBOX",t==="__none__"?null:t),children:[e.jsx(_,{children:e.jsx(f,{})}),e.jsxs(p,{children:[e.jsx(u,{value:"__none__",children:s("security.exec.sandboxNone")}),e.jsxs(u,{value:"bwrap",disabled:!i?.bwrapAvailable,children:[s("security.exec.sandboxBwrap"),!i?.bwrapAvailable&&e.jsxs("span",{className:"ml-2 text-xs text-muted",children:["(",s("security.exec.sandboxBwrapMissing"),")"]})]})]})]})}),e.jsx(c,{label:s("security.exec.sandboxNet"),children:e.jsxs(h,{value:(n.IMHUB_EXEC_SANDBOX_NET??"").toLowerCase()==="off"?"off":"on",onValueChange:t=>void r("IMHUB_EXEC_SANDBOX_NET",t==="off"?"off":null),children:[e.jsx(_,{children:e.jsx(f,{})}),e.jsxs(p,{children:[e.jsx(u,{value:"on",children:s("security.exec.sandboxNetOn")}),e.jsx(u,{value:"off",children:s("security.exec.sandboxNetOff")})]})]})}),e.jsx(c,{label:s("security.exec.timeoutMs"),children:e.jsx(d,{type:"number",defaultValue:n.IMHUB_EXEC_TIMEOUT_MS??"",placeholder:"60000",onBlur:t=>{const l=t.target.value.trim();r("IMHUB_EXEC_TIMEOUT_MS",l===""?null:l)}})}),e.jsx(c,{label:s("security.exec.maxOutput"),children:e.jsx(d,{type:"number",defaultValue:n.IMHUB_EXEC_MAX_OUTPUT??"",placeholder:"32768",onBlur:t=>{const l=t.target.value.trim();r("IMHUB_EXEC_MAX_OUTPUT",l===""?null:l)}})})]})}),e.jsx(m,{title:s("security.web.title"),description:s("security.web.description"),children:e.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[e.jsx(c,{label:s("security.web.allowPrivate"),hint:s("security.web.allowPrivateHelp"),children:e.jsxs(h,{value:V(n.IMHUB_NATIVE_WEB_ALLOW_PRIVATE)?"1":"0",onValueChange:t=>void r("IMHUB_NATIVE_WEB_ALLOW_PRIVATE",t==="1"?"1":null),children:[e.jsx(_,{children:e.jsx(f,{})}),e.jsxs(p,{children:[e.jsx(u,{value:"0",children:"OFF"}),e.jsx(u,{value:"1",children:"ON"})]})]})}),e.jsx(c,{label:s("security.web.timeoutMs"),children:e.jsx(d,{type:"number",defaultValue:n.IMHUB_NATIVE_WEB_TIMEOUT_MS??"",placeholder:"30000",onBlur:t=>{const l=t.target.value.trim();r("IMHUB_NATIVE_WEB_TIMEOUT_MS",l===""?null:l)}})}),e.jsx("div",{className:"sm:col-span-2",children:e.jsx(c,{label:s("security.web.ssrfWhitelist"),children:e.jsx(d,{defaultValue:n.IMHUB_NATIVE_WEB_SSRF_WHITELIST??"",placeholder:s("security.web.ssrfWhitelistPlaceholder"),onBlur:t=>{const l=t.target.value.trim();r("IMHUB_NATIVE_WEB_SSRF_WHITELIST",l===""?null:l)}})})})]})}),e.jsx(m,{title:s("security.fs.title"),description:s("security.fs.description"),children:e.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[e.jsx(c,{label:s("security.fs.restrict"),children:e.jsxs(h,{value:(n.IMHUB_NATIVE_FS_RESTRICT??"1")==="0"?"0":"1",onValueChange:t=>void r("IMHUB_NATIVE_FS_RESTRICT",t==="0"?"0":null),children:[e.jsx(_,{children:e.jsx(f,{})}),e.jsxs(p,{children:[e.jsx(u,{value:"1",children:s("security.fs.restrictOn")}),e.jsx(u,{value:"0",children:s("security.fs.restrictOff")})]})]})}),e.jsx(c,{label:s("security.fs.timeoutMs"),children:e.jsx(d,{type:"number",defaultValue:n.IMHUB_NATIVE_FS_TIMEOUT_MS??"",placeholder:"60000",onBlur:t=>{const l=t.target.value.trim();r("IMHUB_NATIVE_FS_TIMEOUT_MS",l===""?null:l)}})})]})}),e.jsx(m,{title:s("security.delegation.title"),description:s("security.delegation.description"),envKey:"IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN",children:e.jsx(d,{type:"number",defaultValue:n.IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN??"",placeholder:"2",onBlur:t=>{const l=t.target.value.trim();r("IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN",l===""?null:l)}})}),e.jsxs(m,{title:s("security.platformBlacklist.title"),description:s("security.platformBlacklist.description"),envKey:"IMHUB_PLATFORM_BLACKLIST",children:[e.jsx(d,{defaultValue:n.IMHUB_PLATFORM_BLACKLIST??"",placeholder:s("security.platformBlacklist.placeholder"),onBlur:t=>{const l=t.target.value.trim();r("IMHUB_PLATFORM_BLACKLIST",l===""?null:l)}}),i?.platformBlacklist&&i.platformBlacklist.length>0&&e.jsxs("p",{className:"mt-2 text-[10px] text-muted",children:[s("security.platformBlacklist.currentLabel"),": ",i.platformBlacklist.join(", ")]})]})]})}function x({label:s,ok:a,text:o}){return e.jsxs("li",{className:"flex items-start gap-2",children:[a?e.jsx(R,{className:"mt-0.5 h-4 w-4 shrink-0 text-success"}):e.jsx(M,{className:"mt-0.5 h-4 w-4 shrink-0 text-warning"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("div",{className:"font-medium",children:s}),e.jsx("div",{className:w("text-xs",a?"text-muted":"text-warning"),children:o})]})]})}function m({title:s,description:a,envKey:o,children:i}){return e.jsxs("section",{className:"rounded-lg border border-border bg-card p-4",children:[e.jsxs("div",{className:"mb-2 flex flex-wrap items-baseline gap-2",children:[e.jsx("h2",{className:"text-sm font-semibold",children:s}),o&&e.jsx(U,{variant:"outline",className:"font-mono text-[10px]",children:o})]}),e.jsx("p",{className:"mb-3 text-xs text-muted",children:a}),i]})}function c({label:s,hint:a,children:o}){return e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("label",{className:"text-xs font-medium text-muted",children:s}),o,a&&e.jsx("p",{className:"text-[10px] text-muted",children:a})]})}export{$ as default};
2
+ //# sourceMappingURL=security-CeW9WxQO.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"security-DhN1kRac.js","sources":["../../src/routes/settings/security.tsx"],"sourcesContent":["/**\n * /settings/security — central console for v1.2.66 security controls.\n *\n * Lays out:\n * • Diagnostics card (read-only) — uid 0? env file perms? bwrap? allowlists configured?\n * • Sender allowlist (IMHUB_ALLOWED_USERS)\n * • Native exec (IMHUB_EXEC_SANDBOX, IMHUB_EXEC_SANDBOX_NET, IMHUB_EXEC_TIMEOUT_MS, IMHUB_EXEC_MAX_OUTPUT)\n * • Native web (IMHUB_NATIVE_WEB_ALLOW_PRIVATE, IMHUB_NATIVE_WEB_SSRF_WHITELIST, IMHUB_NATIVE_WEB_TIMEOUT_MS)\n * • Native fs (IMHUB_NATIVE_FS_RESTRICT, IMHUB_NATIVE_FS_TIMEOUT_MS)\n * • Delegation (IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN)\n *\n * All writes go through PUT /api/env (admin-gated). Most knobs are\n * hot-reloaded (read process.env per tool call); the exec sandbox +\n * sender allowlist apply at boot — service restart required.\n */\n\nimport { useEffect, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { AlertTriangle, CheckCircle2, Loader2, RefreshCcw, ShieldAlert } from 'lucide-react'\n\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport { useEnv, useUpdateEnv } from '@/hooks/use-settings'\nimport { client } from '@/lib/api/client'\nimport { describeError } from '@/lib/api/errors'\nimport { cn } from '@/lib/utils'\n\ninterface Diagnostics {\n runningAsRoot: boolean | null\n envFile: { exists: boolean; mode: string | null; tooPermissive: boolean }\n bwrapAvailable: boolean\n senderAllowlistConfigured: boolean\n adminAllowlistConfigured: boolean\n platformBlacklist: string[]\n liveEnv: Record<string, string | null>\n}\n\nfunction envBool(v: string | undefined): boolean {\n if (v == null) return false\n const t = v.toLowerCase()\n return t === '1' || t === 'true' || t === 'yes' || t === 'on'\n}\n\nexport default function SettingsSecurityRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const envQuery = useEnv()\n const updateEnv = useUpdateEnv()\n const [diagnostics, setDiagnostics] = useState<Diagnostics | null>(null)\n const [diagLoading, setDiagLoading] = useState(false)\n\n async function loadDiagnostics(): Promise<void> {\n setDiagLoading(true)\n try {\n const res = await client.get<{ diagnostics: Diagnostics }>('/api/security/diagnostics')\n setDiagnostics(res.diagnostics)\n } catch (err) {\n toast.error(describeError(err, t).message)\n } finally {\n setDiagLoading(false)\n }\n }\n\n useEffect(() => { void loadDiagnostics() }, [])\n\n async function setValue(key: string, value: string | null): Promise<void> {\n try {\n await updateEnv.mutateAsync({ updates: { [key]: value } })\n toast.success(t('security.savingToast'))\n await loadDiagnostics()\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n const env = envQuery.data?.env ?? {}\n\n return (\n <div className=\"mx-auto flex max-w-4xl flex-col gap-4\">\n <header className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('security.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => { void envQuery.refetch(); void loadDiagnostics() }}\n disabled={envQuery.isFetching || diagLoading}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {envQuery.isFetching || diagLoading\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <RefreshCcw className=\"h-4 w-4\" />\n }\n </Button>\n </div>\n <p className=\"text-sm text-muted\">{t('security.subtitle')}</p>\n </header>\n\n {/* Diagnostics card */}\n <section className=\"rounded-lg border border-border bg-card p-4\">\n <h2 className=\"mb-3 flex items-center gap-2 text-sm font-semibold\">\n <ShieldAlert className=\"h-4 w-4\" />\n {t('security.diagnostics.title')}\n </h2>\n {diagnostics ? (\n <ul className=\"grid gap-2 text-sm sm:grid-cols-2\">\n <DiagRow\n label={t('security.diagnostics.runningAsRoot')}\n ok={diagnostics.runningAsRoot === false}\n text={diagnostics.runningAsRoot === true ? t('security.diagnostics.runningAsRootHelp') : 'OK'}\n />\n <DiagRow\n label={t('security.diagnostics.envFilePerms')}\n ok={diagnostics.envFile.exists && !diagnostics.envFile.tooPermissive}\n text={\n !diagnostics.envFile.exists\n ? '—'\n : diagnostics.envFile.tooPermissive\n ? `${diagnostics.envFile.mode} — ${t('security.diagnostics.envFilePermsLax')}`\n : t('security.diagnostics.envFilePermsOk')\n }\n />\n <DiagRow\n label={t('security.diagnostics.bwrapAvailable')}\n ok={diagnostics.bwrapAvailable}\n text={diagnostics.bwrapAvailable ? '/usr/bin/bwrap' : t('security.diagnostics.bwrapMissing')}\n />\n <DiagRow\n label={t('security.diagnostics.senderAllowlist')}\n ok={diagnostics.senderAllowlistConfigured}\n text={diagnostics.senderAllowlistConfigured\n ? t('security.diagnostics.senderAllowlistOn')\n : t('security.diagnostics.senderAllowlistOff')\n }\n />\n <DiagRow\n label={t('security.diagnostics.adminAllowlist')}\n ok={diagnostics.adminAllowlistConfigured}\n text={diagnostics.adminAllowlistConfigured\n ? t('security.diagnostics.adminAllowlistOn')\n : t('security.diagnostics.adminAllowlistOff')\n }\n />\n <DiagRow\n label={t('security.diagnosticsPlatformBlacklist')}\n ok={diagnostics.platformBlacklist.length === 0}\n text={diagnostics.platformBlacklist.length === 0\n ? '—'\n : diagnostics.platformBlacklist.join(', ')\n }\n />\n </ul>\n ) : (\n <p className=\"text-sm text-muted\">…</p>\n )}\n </section>\n\n {/* Sender allowlist */}\n <ControlCard\n title={t('security.sender.title')}\n description={t('security.sender.description')}\n envKey=\"IMHUB_ALLOWED_USERS\"\n >\n <Input\n defaultValue={env.IMHUB_ALLOWED_USERS ?? ''}\n placeholder={t('security.sender.placeholder')}\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_ALLOWED_USERS', v === '' ? null : v)\n }}\n />\n </ControlCard>\n\n {/* Exec sandbox */}\n <ControlCard\n title={t('security.exec.title')}\n description={t('security.exec.description')}\n >\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <LabeledField label={t('security.exec.sandbox')}>\n <Select\n value={(env.IMHUB_EXEC_SANDBOX ?? '').toLowerCase() === 'bwrap' ? 'bwrap' : '__none__'}\n onValueChange={(v) => void setValue('IMHUB_EXEC_SANDBOX', v === '__none__' ? null : v)}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__none__\">{t('security.exec.sandboxNone')}</SelectItem>\n <SelectItem\n value=\"bwrap\"\n disabled={!diagnostics?.bwrapAvailable}\n >\n {t('security.exec.sandboxBwrap')}\n {!diagnostics?.bwrapAvailable && (\n <span className=\"ml-2 text-xs text-muted\">\n ({t('security.exec.sandboxBwrapMissing')})\n </span>\n )}\n </SelectItem>\n </SelectContent>\n </Select>\n </LabeledField>\n\n <LabeledField label={t('security.exec.sandboxNet')}>\n <Select\n value={(env.IMHUB_EXEC_SANDBOX_NET ?? '').toLowerCase() === 'off' ? 'off' : 'on'}\n onValueChange={(v) => void setValue('IMHUB_EXEC_SANDBOX_NET', v === 'off' ? 'off' : null)}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"on\">{t('security.exec.sandboxNetOn')}</SelectItem>\n <SelectItem value=\"off\">{t('security.exec.sandboxNetOff')}</SelectItem>\n </SelectContent>\n </Select>\n </LabeledField>\n\n <LabeledField label={t('security.exec.timeoutMs')}>\n <Input\n type=\"number\"\n defaultValue={env.IMHUB_EXEC_TIMEOUT_MS ?? ''}\n placeholder=\"60000\"\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_EXEC_TIMEOUT_MS', v === '' ? null : v)\n }}\n />\n </LabeledField>\n\n <LabeledField label={t('security.exec.maxOutput')}>\n <Input\n type=\"number\"\n defaultValue={env.IMHUB_EXEC_MAX_OUTPUT ?? ''}\n placeholder=\"32768\"\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_EXEC_MAX_OUTPUT', v === '' ? null : v)\n }}\n />\n </LabeledField>\n </div>\n </ControlCard>\n\n {/* Web SSRF */}\n <ControlCard\n title={t('security.web.title')}\n description={t('security.web.description')}\n >\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <LabeledField label={t('security.web.allowPrivate')} hint={t('security.web.allowPrivateHelp')}>\n <Select\n value={envBool(env.IMHUB_NATIVE_WEB_ALLOW_PRIVATE) ? '1' : '0'}\n onValueChange={(v) => void setValue('IMHUB_NATIVE_WEB_ALLOW_PRIVATE', v === '1' ? '1' : null)}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"0\">OFF</SelectItem>\n <SelectItem value=\"1\">ON</SelectItem>\n </SelectContent>\n </Select>\n </LabeledField>\n\n <LabeledField label={t('security.web.timeoutMs')}>\n <Input\n type=\"number\"\n defaultValue={env.IMHUB_NATIVE_WEB_TIMEOUT_MS ?? ''}\n placeholder=\"30000\"\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_NATIVE_WEB_TIMEOUT_MS', v === '' ? null : v)\n }}\n />\n </LabeledField>\n\n <div className=\"sm:col-span-2\">\n <LabeledField label={t('security.web.ssrfWhitelist')}>\n <Input\n defaultValue={env.IMHUB_NATIVE_WEB_SSRF_WHITELIST ?? ''}\n placeholder={t('security.web.ssrfWhitelistPlaceholder')}\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_NATIVE_WEB_SSRF_WHITELIST', v === '' ? null : v)\n }}\n />\n </LabeledField>\n </div>\n </div>\n </ControlCard>\n\n {/* FS */}\n <ControlCard\n title={t('security.fs.title')}\n description={t('security.fs.description')}\n >\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <LabeledField label={t('security.fs.restrict')}>\n <Select\n value={(env.IMHUB_NATIVE_FS_RESTRICT ?? '1') === '0' ? '0' : '1'}\n onValueChange={(v) => void setValue('IMHUB_NATIVE_FS_RESTRICT', v === '0' ? '0' : null)}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"1\">{t('security.fs.restrictOn')}</SelectItem>\n <SelectItem value=\"0\">{t('security.fs.restrictOff')}</SelectItem>\n </SelectContent>\n </Select>\n </LabeledField>\n\n <LabeledField label={t('security.fs.timeoutMs')}>\n <Input\n type=\"number\"\n defaultValue={env.IMHUB_NATIVE_FS_TIMEOUT_MS ?? ''}\n placeholder=\"60000\"\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_NATIVE_FS_TIMEOUT_MS', v === '' ? null : v)\n }}\n />\n </LabeledField>\n </div>\n </ControlCard>\n\n {/* Delegation cap */}\n <ControlCard\n title={t('security.delegation.title')}\n description={t('security.delegation.description')}\n envKey=\"IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN\"\n >\n <Input\n type=\"number\"\n defaultValue={env.IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN ?? ''}\n placeholder=\"2\"\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN', v === '' ? null : v)\n }}\n />\n </ControlCard>\n\n {/* IM platform blacklist */}\n <ControlCard\n title={t('security.platformBlacklist.title')}\n description={t('security.platformBlacklist.description')}\n envKey=\"IMHUB_PLATFORM_BLACKLIST\"\n >\n <Input\n defaultValue={env.IMHUB_PLATFORM_BLACKLIST ?? ''}\n placeholder={t('security.platformBlacklist.placeholder')}\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_PLATFORM_BLACKLIST', v === '' ? null : v)\n }}\n />\n {diagnostics?.platformBlacklist && diagnostics.platformBlacklist.length > 0 && (\n <p className=\"mt-2 text-[10px] text-muted\">\n {t('security.platformBlacklist.currentLabel')}: {diagnostics.platformBlacklist.join(', ')}\n </p>\n )}\n </ControlCard>\n </div>\n )\n}\n\nfunction DiagRow({ label, ok, text }: { label: string; ok: boolean; text: string }): JSX.Element {\n return (\n <li className=\"flex items-start gap-2\">\n {ok\n ? <CheckCircle2 className=\"mt-0.5 h-4 w-4 shrink-0 text-success\" />\n : <AlertTriangle className=\"mt-0.5 h-4 w-4 shrink-0 text-warning\" />\n }\n <div className=\"flex-1\">\n <div className=\"font-medium\">{label}</div>\n <div className={cn('text-xs', ok ? 'text-muted' : 'text-warning')}>{text}</div>\n </div>\n </li>\n )\n}\n\nfunction ControlCard({\n title, description, envKey, children,\n}: { title: string; description: string; envKey?: string; children: React.ReactNode }): JSX.Element {\n return (\n <section className=\"rounded-lg border border-border bg-card p-4\">\n <div className=\"mb-2 flex flex-wrap items-baseline gap-2\">\n <h2 className=\"text-sm font-semibold\">{title}</h2>\n {envKey && <Badge variant=\"outline\" className=\"font-mono text-[10px]\">{envKey}</Badge>}\n </div>\n <p className=\"mb-3 text-xs text-muted\">{description}</p>\n {children}\n </section>\n )\n}\n\nfunction LabeledField({\n label, hint, children,\n}: { label: string; hint?: string; children: React.ReactNode }): JSX.Element {\n return (\n <div className=\"flex flex-col gap-1\">\n <label className=\"text-xs font-medium text-muted\">{label}</label>\n {children}\n {hint && <p className=\"text-[10px] text-muted\">{hint}</p>}\n </div>\n )\n}\n"],"names":["envBool","v","t","SettingsSecurityRoute","useTranslation","envQuery","useEnv","updateEnv","useUpdateEnv","diagnostics","setDiagnostics","useState","diagLoading","setDiagLoading","loadDiagnostics","res","client","err","toast","describeError","useEffect","setValue","key","value","env","jsxs","jsx","Button","Loader2","RefreshCcw","ShieldAlert","DiagRow","ControlCard","Input","e","LabeledField","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","label","ok","text","CheckCircle2","AlertTriangle","cn","title","description","envKey","children","Badge","hint"],"mappings":"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"}
1
+ {"version":3,"file":"security-CeW9WxQO.js","sources":["../../src/routes/settings/security.tsx"],"sourcesContent":["/**\n * /settings/security — central console for v1.2.66 security controls.\n *\n * Lays out:\n * • Diagnostics card (read-only) — uid 0? env file perms? bwrap? allowlists configured?\n * • Sender allowlist (IMHUB_ALLOWED_USERS)\n * • Native exec (IMHUB_EXEC_SANDBOX, IMHUB_EXEC_SANDBOX_NET, IMHUB_EXEC_TIMEOUT_MS, IMHUB_EXEC_MAX_OUTPUT)\n * • Native web (IMHUB_NATIVE_WEB_ALLOW_PRIVATE, IMHUB_NATIVE_WEB_SSRF_WHITELIST, IMHUB_NATIVE_WEB_TIMEOUT_MS)\n * • Native fs (IMHUB_NATIVE_FS_RESTRICT, IMHUB_NATIVE_FS_TIMEOUT_MS)\n * • Delegation (IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN)\n *\n * All writes go through PUT /api/env (admin-gated). Most knobs are\n * hot-reloaded (read process.env per tool call); the exec sandbox +\n * sender allowlist apply at boot — service restart required.\n */\n\nimport { useEffect, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { AlertTriangle, CheckCircle2, Loader2, RefreshCcw, ShieldAlert } from 'lucide-react'\n\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport { useEnv, useUpdateEnv } from '@/hooks/use-settings'\nimport { client } from '@/lib/api/client'\nimport { describeError } from '@/lib/api/errors'\nimport { cn } from '@/lib/utils'\n\ninterface Diagnostics {\n runningAsRoot: boolean | null\n envFile: { exists: boolean; mode: string | null; tooPermissive: boolean }\n bwrapAvailable: boolean\n senderAllowlistConfigured: boolean\n adminAllowlistConfigured: boolean\n platformBlacklist: string[]\n liveEnv: Record<string, string | null>\n}\n\nfunction envBool(v: string | undefined): boolean {\n if (v == null) return false\n const t = v.toLowerCase()\n return t === '1' || t === 'true' || t === 'yes' || t === 'on'\n}\n\nexport default function SettingsSecurityRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const envQuery = useEnv()\n const updateEnv = useUpdateEnv()\n const [diagnostics, setDiagnostics] = useState<Diagnostics | null>(null)\n const [diagLoading, setDiagLoading] = useState(false)\n\n async function loadDiagnostics(): Promise<void> {\n setDiagLoading(true)\n try {\n const res = await client.get<{ diagnostics: Diagnostics }>('/api/security/diagnostics')\n setDiagnostics(res.diagnostics)\n } catch (err) {\n toast.error(describeError(err, t).message)\n } finally {\n setDiagLoading(false)\n }\n }\n\n useEffect(() => { void loadDiagnostics() }, [])\n\n async function setValue(key: string, value: string | null): Promise<void> {\n try {\n await updateEnv.mutateAsync({ updates: { [key]: value } })\n toast.success(t('security.savingToast'))\n await loadDiagnostics()\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n const env = envQuery.data?.env ?? {}\n\n return (\n <div className=\"mx-auto flex max-w-4xl flex-col gap-4\">\n <header className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('security.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => { void envQuery.refetch(); void loadDiagnostics() }}\n disabled={envQuery.isFetching || diagLoading}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {envQuery.isFetching || diagLoading\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <RefreshCcw className=\"h-4 w-4\" />\n }\n </Button>\n </div>\n <p className=\"text-sm text-muted\">{t('security.subtitle')}</p>\n </header>\n\n {/* Diagnostics card */}\n <section className=\"rounded-lg border border-border bg-card p-4\">\n <h2 className=\"mb-3 flex items-center gap-2 text-sm font-semibold\">\n <ShieldAlert className=\"h-4 w-4\" />\n {t('security.diagnostics.title')}\n </h2>\n {diagnostics ? (\n <ul className=\"grid gap-2 text-sm sm:grid-cols-2\">\n <DiagRow\n label={t('security.diagnostics.runningAsRoot')}\n ok={diagnostics.runningAsRoot === false}\n text={diagnostics.runningAsRoot === true ? t('security.diagnostics.runningAsRootHelp') : 'OK'}\n />\n <DiagRow\n label={t('security.diagnostics.envFilePerms')}\n ok={diagnostics.envFile.exists && !diagnostics.envFile.tooPermissive}\n text={\n !diagnostics.envFile.exists\n ? '—'\n : diagnostics.envFile.tooPermissive\n ? `${diagnostics.envFile.mode} — ${t('security.diagnostics.envFilePermsLax')}`\n : t('security.diagnostics.envFilePermsOk')\n }\n />\n <DiagRow\n label={t('security.diagnostics.bwrapAvailable')}\n ok={diagnostics.bwrapAvailable}\n text={diagnostics.bwrapAvailable ? '/usr/bin/bwrap' : t('security.diagnostics.bwrapMissing')}\n />\n <DiagRow\n label={t('security.diagnostics.senderAllowlist')}\n ok={diagnostics.senderAllowlistConfigured}\n text={diagnostics.senderAllowlistConfigured\n ? t('security.diagnostics.senderAllowlistOn')\n : t('security.diagnostics.senderAllowlistOff')\n }\n />\n <DiagRow\n label={t('security.diagnostics.adminAllowlist')}\n ok={diagnostics.adminAllowlistConfigured}\n text={diagnostics.adminAllowlistConfigured\n ? t('security.diagnostics.adminAllowlistOn')\n : t('security.diagnostics.adminAllowlistOff')\n }\n />\n <DiagRow\n label={t('security.diagnosticsPlatformBlacklist')}\n ok={diagnostics.platformBlacklist.length === 0}\n text={diagnostics.platformBlacklist.length === 0\n ? '—'\n : diagnostics.platformBlacklist.join(', ')\n }\n />\n </ul>\n ) : (\n <p className=\"text-sm text-muted\">…</p>\n )}\n </section>\n\n {/* Sender allowlist */}\n <ControlCard\n title={t('security.sender.title')}\n description={t('security.sender.description')}\n envKey=\"IMHUB_ALLOWED_USERS\"\n >\n <Input\n defaultValue={env.IMHUB_ALLOWED_USERS ?? ''}\n placeholder={t('security.sender.placeholder')}\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_ALLOWED_USERS', v === '' ? null : v)\n }}\n />\n </ControlCard>\n\n {/* Exec sandbox */}\n <ControlCard\n title={t('security.exec.title')}\n description={t('security.exec.description')}\n >\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <LabeledField label={t('security.exec.sandbox')}>\n <Select\n value={(env.IMHUB_EXEC_SANDBOX ?? '').toLowerCase() === 'bwrap' ? 'bwrap' : '__none__'}\n onValueChange={(v) => void setValue('IMHUB_EXEC_SANDBOX', v === '__none__' ? null : v)}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__none__\">{t('security.exec.sandboxNone')}</SelectItem>\n <SelectItem\n value=\"bwrap\"\n disabled={!diagnostics?.bwrapAvailable}\n >\n {t('security.exec.sandboxBwrap')}\n {!diagnostics?.bwrapAvailable && (\n <span className=\"ml-2 text-xs text-muted\">\n ({t('security.exec.sandboxBwrapMissing')})\n </span>\n )}\n </SelectItem>\n </SelectContent>\n </Select>\n </LabeledField>\n\n <LabeledField label={t('security.exec.sandboxNet')}>\n <Select\n value={(env.IMHUB_EXEC_SANDBOX_NET ?? '').toLowerCase() === 'off' ? 'off' : 'on'}\n onValueChange={(v) => void setValue('IMHUB_EXEC_SANDBOX_NET', v === 'off' ? 'off' : null)}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"on\">{t('security.exec.sandboxNetOn')}</SelectItem>\n <SelectItem value=\"off\">{t('security.exec.sandboxNetOff')}</SelectItem>\n </SelectContent>\n </Select>\n </LabeledField>\n\n <LabeledField label={t('security.exec.timeoutMs')}>\n <Input\n type=\"number\"\n defaultValue={env.IMHUB_EXEC_TIMEOUT_MS ?? ''}\n placeholder=\"60000\"\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_EXEC_TIMEOUT_MS', v === '' ? null : v)\n }}\n />\n </LabeledField>\n\n <LabeledField label={t('security.exec.maxOutput')}>\n <Input\n type=\"number\"\n defaultValue={env.IMHUB_EXEC_MAX_OUTPUT ?? ''}\n placeholder=\"32768\"\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_EXEC_MAX_OUTPUT', v === '' ? null : v)\n }}\n />\n </LabeledField>\n </div>\n </ControlCard>\n\n {/* Web SSRF */}\n <ControlCard\n title={t('security.web.title')}\n description={t('security.web.description')}\n >\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <LabeledField label={t('security.web.allowPrivate')} hint={t('security.web.allowPrivateHelp')}>\n <Select\n value={envBool(env.IMHUB_NATIVE_WEB_ALLOW_PRIVATE) ? '1' : '0'}\n onValueChange={(v) => void setValue('IMHUB_NATIVE_WEB_ALLOW_PRIVATE', v === '1' ? '1' : null)}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"0\">OFF</SelectItem>\n <SelectItem value=\"1\">ON</SelectItem>\n </SelectContent>\n </Select>\n </LabeledField>\n\n <LabeledField label={t('security.web.timeoutMs')}>\n <Input\n type=\"number\"\n defaultValue={env.IMHUB_NATIVE_WEB_TIMEOUT_MS ?? ''}\n placeholder=\"30000\"\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_NATIVE_WEB_TIMEOUT_MS', v === '' ? null : v)\n }}\n />\n </LabeledField>\n\n <div className=\"sm:col-span-2\">\n <LabeledField label={t('security.web.ssrfWhitelist')}>\n <Input\n defaultValue={env.IMHUB_NATIVE_WEB_SSRF_WHITELIST ?? ''}\n placeholder={t('security.web.ssrfWhitelistPlaceholder')}\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_NATIVE_WEB_SSRF_WHITELIST', v === '' ? null : v)\n }}\n />\n </LabeledField>\n </div>\n </div>\n </ControlCard>\n\n {/* FS */}\n <ControlCard\n title={t('security.fs.title')}\n description={t('security.fs.description')}\n >\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <LabeledField label={t('security.fs.restrict')}>\n <Select\n value={(env.IMHUB_NATIVE_FS_RESTRICT ?? '1') === '0' ? '0' : '1'}\n onValueChange={(v) => void setValue('IMHUB_NATIVE_FS_RESTRICT', v === '0' ? '0' : null)}\n >\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"1\">{t('security.fs.restrictOn')}</SelectItem>\n <SelectItem value=\"0\">{t('security.fs.restrictOff')}</SelectItem>\n </SelectContent>\n </Select>\n </LabeledField>\n\n <LabeledField label={t('security.fs.timeoutMs')}>\n <Input\n type=\"number\"\n defaultValue={env.IMHUB_NATIVE_FS_TIMEOUT_MS ?? ''}\n placeholder=\"60000\"\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_NATIVE_FS_TIMEOUT_MS', v === '' ? null : v)\n }}\n />\n </LabeledField>\n </div>\n </ControlCard>\n\n {/* Delegation cap */}\n <ControlCard\n title={t('security.delegation.title')}\n description={t('security.delegation.description')}\n envKey=\"IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN\"\n >\n <Input\n type=\"number\"\n defaultValue={env.IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN ?? ''}\n placeholder=\"2\"\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN', v === '' ? null : v)\n }}\n />\n </ControlCard>\n\n {/* IM platform blacklist */}\n <ControlCard\n title={t('security.platformBlacklist.title')}\n description={t('security.platformBlacklist.description')}\n envKey=\"IMHUB_PLATFORM_BLACKLIST\"\n >\n <Input\n defaultValue={env.IMHUB_PLATFORM_BLACKLIST ?? ''}\n placeholder={t('security.platformBlacklist.placeholder')}\n onBlur={(e) => {\n const v = e.target.value.trim()\n void setValue('IMHUB_PLATFORM_BLACKLIST', v === '' ? null : v)\n }}\n />\n {diagnostics?.platformBlacklist && diagnostics.platformBlacklist.length > 0 && (\n <p className=\"mt-2 text-[10px] text-muted\">\n {t('security.platformBlacklist.currentLabel')}: {diagnostics.platformBlacklist.join(', ')}\n </p>\n )}\n </ControlCard>\n </div>\n )\n}\n\nfunction DiagRow({ label, ok, text }: { label: string; ok: boolean; text: string }): JSX.Element {\n return (\n <li className=\"flex items-start gap-2\">\n {ok\n ? <CheckCircle2 className=\"mt-0.5 h-4 w-4 shrink-0 text-success\" />\n : <AlertTriangle className=\"mt-0.5 h-4 w-4 shrink-0 text-warning\" />\n }\n <div className=\"flex-1\">\n <div className=\"font-medium\">{label}</div>\n <div className={cn('text-xs', ok ? 'text-muted' : 'text-warning')}>{text}</div>\n </div>\n </li>\n )\n}\n\nfunction ControlCard({\n title, description, envKey, children,\n}: { title: string; description: string; envKey?: string; children: React.ReactNode }): JSX.Element {\n return (\n <section className=\"rounded-lg border border-border bg-card p-4\">\n <div className=\"mb-2 flex flex-wrap items-baseline gap-2\">\n <h2 className=\"text-sm font-semibold\">{title}</h2>\n {envKey && <Badge variant=\"outline\" className=\"font-mono text-[10px]\">{envKey}</Badge>}\n </div>\n <p className=\"mb-3 text-xs text-muted\">{description}</p>\n {children}\n </section>\n )\n}\n\nfunction LabeledField({\n label, hint, children,\n}: { label: string; hint?: string; children: React.ReactNode }): JSX.Element {\n return (\n <div className=\"flex flex-col gap-1\">\n <label className=\"text-xs font-medium text-muted\">{label}</label>\n {children}\n {hint && <p className=\"text-[10px] text-muted\">{hint}</p>}\n </div>\n )\n}\n"],"names":["envBool","v","t","SettingsSecurityRoute","useTranslation","envQuery","useEnv","updateEnv","useUpdateEnv","diagnostics","setDiagnostics","useState","diagLoading","setDiagLoading","loadDiagnostics","res","client","err","toast","describeError","useEffect","setValue","key","value","env","jsxs","jsx","Button","Loader2","RefreshCcw","ShieldAlert","DiagRow","ControlCard","Input","e","LabeledField","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","label","ok","text","CheckCircle2","AlertTriangle","cn","title","description","envKey","children","Badge","hint"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import{n as z,u as P,j as e,B as f,k as L,R as T,c as w,l as m,m as v,L as U,I as _}from"./index-CqwhfPlr.js";import{r as p}from"./react-Cb2sDjhD.js";import{C as y}from"./confirm-dialog-r9HgkIYf.js";import{j as O,k as B,l as W,m as q,b as M,c as H}from"./use-settings-DBXvAYm9.js";import{L as S}from"./loader-circle-U-jPjmeD.js";import{R as Q}from"./refresh-ccw-CBiHL1tY.js";import{P as V}from"./play-BG0hyTnO.js";import{N as X}from"./network-l6l5gLHO.js";import{X as $}from"./x-ClXUlQDe.js";import{S as G}from"./save-DVHI3V6o.js";import"./dialog-fGS0IXOo.js";import"./useQuery-Ds6-WURB.js";/**
1
+ import{n as z,u as P,j as e,B as f,k as L,R as T,c as w,l as m,m as v,L as U,I as _}from"./index-D4Np2s3l.js";import{r as p}from"./react-Cb2sDjhD.js";import{C as y}from"./confirm-dialog-DAfv5d0M.js";import{j as O,k as B,l as W,m as q,b as M,c as H}from"./use-settings-XXVWFAv6.js";import{L as S}from"./loader-circle-BfXi9R6u.js";import{R as Q}from"./refresh-ccw-C7VT3MFu.js";import{P as V}from"./play-DqmSNGi8.js";import{N as X}from"./network-B48dL6Y7.js";import{X as $}from"./x-CGfY-U_P.js";import{S as G}from"./save-B18KQmEd.js";import"./dialog-DGdHPiTV.js";import"./useQuery-B25CPtUF.js";/**
2
2
  * @license lucide-react v0.469.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
5
5
  * See the LICENSE file in the root directory of this source tree.
6
6
  */const J=z("Square",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]]),K={systemd:"success",background:"info",foreground:"warning",none:"default"},C=3e3,k=9090;function me(){const{t:s}=P(["settings","common"]),r=O(),t=r.data,a=t&&t.mode!=="none",i=B(),n=W(),o=q(),[u,x]=p.useState(!1),[h,g]=p.useState(!1);async function b(){try{await i.mutateAsync(),m.success(s("service.toast.started"))}catch(c){m.error(v(c,s).message)}}async function d(){try{await n.mutateAsync(),m.success(s("service.toast.stopped"))}catch(c){throw m.error(v(c,s).message),c}}async function l(){try{await o.mutateAsync(),m.success(s("service.toast.restarted"))}catch(c){throw m.error(v(c,s).message),c}}return e.jsxs("div",{className:"mx-auto flex max-w-3xl flex-col gap-4",children:[e.jsxs("header",{className:"flex flex-col gap-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx("h1",{className:"text-xl font-semibold",children:s("service.title")}),e.jsxs(f,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>r.refetch(),disabled:r.isFetching,"aria-label":s("actions.refresh",{ns:"common"}),children:[r.isFetching?e.jsx(S,{className:"h-4 w-4 animate-spin"}):e.jsx(Q,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:s("actions.refresh",{ns:"common"})})]})]}),e.jsx("p",{className:"text-sm text-text-dim",children:s("service.subtitle")})]}),e.jsx(Y,{}),r.isLoading?e.jsx("div",{className:"h-48 rounded-md bg-surface-2 animate-pulse"}):t?e.jsxs("div",{className:"rounded-md border border-border bg-surface p-4",children:[e.jsxs("dl",{className:"grid grid-cols-[max-content_1fr] gap-x-4 gap-y-2 text-sm",children:[e.jsx("dt",{className:"text-text-dim",children:s("service.modeLabel")}),e.jsx("dd",{children:e.jsx(L,{variant:K[t.mode],children:s(`service.mode.${t.mode}`)})}),t.pid!=null&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{className:"text-text-dim",children:s("service.pidLabel")}),e.jsx("dd",{className:"tabular-nums font-mono",children:t.pid})]}),t.uptime&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{className:"text-text-dim",children:s("service.uptimeLabel")}),e.jsx("dd",{className:"tabular-nums",children:t.uptime})]}),t.web&&e.jsxs(e.Fragment,{children:[e.jsx("dt",{className:"text-text-dim",children:s("service.webLabel")}),e.jsxs("dd",{className:"font-mono text-xs",children:[t.web.bind,":",t.web.port]})]}),e.jsx("dt",{className:"text-text-dim",children:s("service.bootPhaseLabel")}),e.jsx("dd",{children:e.jsx("code",{className:"rounded bg-surface-2 px-1.5 py-0.5 text-xs",children:t.bootPhase})})]}),e.jsxs("div",{className:"mt-4 flex flex-wrap gap-2",children:[e.jsxs(f,{type:"button",variant:"default",size:"sm",disabled:a||i.isPending,onClick:()=>void b(),children:[i.isPending?e.jsx(S,{className:"h-4 w-4 animate-spin"}):e.jsx(V,{className:"h-4 w-4"}),s("service.actions.start")]}),e.jsxs(f,{type:"button",variant:"outline",size:"sm",disabled:!a||o.isPending,onClick:()=>g(!0),children:[e.jsx(T,{className:w("h-4 w-4",o.isPending&&"animate-spin")}),s("service.actions.restart")]}),e.jsxs(f,{type:"button",variant:"destructive",size:"sm",disabled:!a||n.isPending,onClick:()=>x(!0),children:[e.jsx(J,{className:"h-4 w-4"}),s("service.actions.stop")]})]})]}):null,e.jsx(y,{open:u,onOpenChange:x,title:s("service.actions.confirmStop"),description:s("service.actions.confirmStopDesc"),intent:"danger",confirmLabel:s("service.actions.stop"),onConfirm:d}),e.jsx(y,{open:h,onOpenChange:g,title:s("service.actions.confirmRestart"),description:s("service.actions.confirmRestartDesc"),intent:"danger",confirmLabel:s("service.actions.restart"),onConfirm:l})]})}function A(s){const r=s.trim();if(!r)return{ok:!0,value:void 0};const t=Number.parseInt(r,10);return!Number.isFinite(t)||t<1||t>65535?{ok:!1}:{ok:!0,value:t}}function Y(){const{t:s}=P(["settings","common"]),r=M(),t=H(),a=r.data,i=a?.webPort,n=a?.acpPort,[o,u]=p.useState(""),[x,h]=p.useState(""),[g,b]=p.useState(0);p.useEffect(()=>{a&&r.dataUpdatedAt!==g&&(u(i!=null?String(i):""),h(n!=null?String(n):""),b(r.dataUpdatedAt))},[a,r.dataUpdatedAt,i,n,g]);const d=A(o),l=A(x),c=!d.ok,j=!l.ok,D=p.useMemo(()=>{if(!a)return!1;const N=d.ok?d.value:void 0,I=l.ok?l.value:void 0;return N!==i||I!==n},[a,d,l,i,n]);function F(){u(i!=null?String(i):""),h(n!=null?String(n):"")}async function E(){if(!(!a||c||j))try{await t.mutateAsync({...a,webPort:d.ok?d.value:void 0,acpPort:l.ok?l.value:void 0}),m.success(s("service.ports.toast.saved"))}catch(N){m.error(v(N,s).message)}}return r.isLoading?e.jsx("div",{className:"h-32 rounded-md bg-surface-2 animate-pulse"}):e.jsxs("section",{className:"rounded-md border border-border bg-surface",children:[e.jsxs("header",{className:"flex items-center gap-2 border-b border-border px-4 py-3",children:[e.jsx(X,{className:"h-4 w-4 text-text-dim"}),e.jsx("h2",{className:"text-sm font-semibold",children:s("service.ports.title")})]}),e.jsx("p",{className:"px-4 pt-2 text-xs text-text-dim",children:s("service.ports.subtitle")}),e.jsxs("div",{className:"grid grid-cols-1 gap-3 px-4 py-3 sm:grid-cols-2",children:[e.jsx(R,{id:"web-port",label:s("service.ports.webPort"),hint:s("service.ports.webPortHint",{default:C}),value:o,onChange:u,invalid:c,placeholder:String(C)}),a?.features?.remoteAgent?e.jsx(R,{id:"acp-port",label:s("service.ports.acpPort"),hint:s("service.ports.acpPortHint",{default:k}),value:x,onChange:h,invalid:j,placeholder:String(k)}):null]}),D&&e.jsxs("div",{className:"flex items-center gap-2 border-t border-border px-4 py-3",children:[e.jsx(L,{variant:"warning",children:s("service.ports.restartRequired")}),e.jsxs(f,{variant:"ghost",size:"sm",className:"ml-auto",onClick:F,disabled:t.isPending,children:[e.jsx($,{className:"h-4 w-4"}),s("service.ports.discard")]}),e.jsxs(f,{size:"sm",onClick:()=>void E(),disabled:t.isPending||c||j,children:[t.isPending?e.jsx(S,{className:"h-4 w-4 animate-spin"}):e.jsx(G,{className:"h-4 w-4"}),t.isPending?s("service.ports.saving"):s("service.ports.save")]})]})]})}function R({id:s,label:r,hint:t,value:a,onChange:i,invalid:n,placeholder:o}){const{t:u}=P("settings");return e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(U,{htmlFor:s,className:"text-xs font-medium",children:r}),e.jsx(_,{id:s,type:"number",inputMode:"numeric",min:1,max:65535,value:a,onChange:x=>i(x.target.value),placeholder:o,"aria-invalid":n,className:w("font-mono",n&&"border-danger focus:ring-danger")}),e.jsx("p",{className:w("text-[11px]",n?"text-danger":"text-text-dim"),children:n?u("service.ports.invalidPort"):t})]})}export{me as default};
7
- //# sourceMappingURL=service-BhvI7Mb5.js.map
7
+ //# sourceMappingURL=service-CJRR2q7Q.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"service-BhvI7Mb5.js","sources":["../../node_modules/lucide-react/dist/esm/icons/square.js","../../src/routes/settings/service.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Square = createLucideIcon(\"Square\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }]\n]);\n\nexport { Square as default };\n//# sourceMappingURL=square.js.map\n","/**\n * /settings/service — operator-facing process control: see the\n * running agim daemon's mode/pid/uptime + start, stop, or restart it.\n *\n * R8 (this round) added a dedicated \"Ports\" card at the top covering\n * webPort + acpPort. They live in `~/.agim/config.json` (PUT /api/config),\n * and take effect on the next service restart — handled by the\n * Start/Restart buttons immediately below.\n *\n * Stop and restart go through ConfirmDialog because they\n * permanently interrupt every messenger adapter + in-flight job;\n * Start is one-click since it's safe to invoke even when already\n * running (backend short-circuits to alreadyRunning:true).\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport {\n Loader2, Network, Play, RefreshCcw, RotateCcw, Save, Square, X,\n} from 'lucide-react'\n\nimport { ConfirmDialog } from '@/components/common/confirm-dialog'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport {\n useConfig,\n useRestartService,\n useServiceStatus,\n useStartService,\n useStopService,\n useUpdateConfig,\n} from '@/hooks/use-settings'\nimport { describeError } from '@/lib/api/errors'\nimport type { ServiceMode } from '@/types/api'\nimport { cn } from '@/lib/utils'\n\nconst MODE_VARIANT: Record<ServiceMode, 'success' | 'info' | 'warning' | 'default'> = {\n systemd: 'success',\n background: 'info',\n foreground: 'warning',\n none: 'default',\n}\n\nconst DEFAULT_WEB_PORT = 3000\nconst DEFAULT_ACP_PORT = 9090\n\nexport default function SettingsServiceRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const status = useServiceStatus()\n const data = status.data\n const isRunning = data && data.mode !== 'none'\n\n const start = useStartService()\n const stop = useStopService()\n const restart = useRestartService()\n\n const [confirmStop, setConfirmStop] = useState(false)\n const [confirmRestart, setConfirmRestart] = useState(false)\n\n async function onStart(): Promise<void> {\n try {\n await start.mutateAsync()\n toast.success(t('service.toast.started'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n async function onConfirmStop(): Promise<void> {\n try {\n await stop.mutateAsync()\n toast.success(t('service.toast.stopped'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n throw err\n }\n }\n async function onConfirmRestart(): Promise<void> {\n try {\n await restart.mutateAsync()\n toast.success(t('service.toast.restarted'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n throw err\n }\n }\n\n return (\n <div className=\"mx-auto flex max-w-3xl flex-col gap-4\">\n <header className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('service.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => status.refetch()}\n disabled={status.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {status.isFetching ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('actions.refresh', { ns: 'common' })}</span>\n </Button>\n </div>\n <p className=\"text-sm text-text-dim\">{t('service.subtitle')}</p>\n </header>\n\n <PortsCard />\n\n {status.isLoading ? (\n <div className=\"h-48 rounded-md bg-surface-2 animate-pulse\" />\n ) : data ? (\n <div className=\"rounded-md border border-border bg-surface p-4\">\n <dl className=\"grid grid-cols-[max-content_1fr] gap-x-4 gap-y-2 text-sm\">\n <dt className=\"text-text-dim\">{t('service.modeLabel')}</dt>\n <dd>\n <Badge variant={MODE_VARIANT[data.mode]}>\n {t(`service.mode.${data.mode}`)}\n </Badge>\n </dd>\n {data.pid != null && (\n <>\n <dt className=\"text-text-dim\">{t('service.pidLabel')}</dt>\n <dd className=\"tabular-nums font-mono\">{data.pid}</dd>\n </>\n )}\n {data.uptime && (\n <>\n <dt className=\"text-text-dim\">{t('service.uptimeLabel')}</dt>\n <dd className=\"tabular-nums\">{data.uptime}</dd>\n </>\n )}\n {data.web && (\n <>\n <dt className=\"text-text-dim\">{t('service.webLabel')}</dt>\n <dd className=\"font-mono text-xs\">{data.web.bind}:{data.web.port}</dd>\n </>\n )}\n <dt className=\"text-text-dim\">{t('service.bootPhaseLabel')}</dt>\n <dd>\n <code className=\"rounded bg-surface-2 px-1.5 py-0.5 text-xs\">{data.bootPhase}</code>\n </dd>\n </dl>\n\n {/* Action buttons */}\n <div className=\"mt-4 flex flex-wrap gap-2\">\n <Button\n type=\"button\"\n variant=\"default\"\n size=\"sm\"\n disabled={isRunning || start.isPending}\n onClick={() => void onStart()}\n >\n {start.isPending ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <Play className=\"h-4 w-4\" />}\n {t('service.actions.start')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={!isRunning || restart.isPending}\n onClick={() => setConfirmRestart(true)}\n >\n <RotateCcw className={cn('h-4 w-4', restart.isPending && 'animate-spin')} />\n {t('service.actions.restart')}\n </Button>\n <Button\n type=\"button\"\n variant=\"destructive\"\n size=\"sm\"\n disabled={!isRunning || stop.isPending}\n onClick={() => setConfirmStop(true)}\n >\n <Square className=\"h-4 w-4\" />\n {t('service.actions.stop')}\n </Button>\n </div>\n </div>\n ) : null}\n\n <ConfirmDialog\n open={confirmStop}\n onOpenChange={setConfirmStop}\n title={t('service.actions.confirmStop')}\n description={t('service.actions.confirmStopDesc')}\n intent=\"danger\"\n confirmLabel={t('service.actions.stop')}\n onConfirm={onConfirmStop}\n />\n <ConfirmDialog\n open={confirmRestart}\n onOpenChange={setConfirmRestart}\n title={t('service.actions.confirmRestart')}\n description={t('service.actions.confirmRestartDesc')}\n intent=\"danger\"\n confirmLabel={t('service.actions.restart')}\n onConfirm={onConfirmRestart}\n />\n </div>\n )\n}\n\n/* ─────────────── Ports card (webPort + acpPort) ─────────────── */\n\n/** Validate a port string. Empty = \"use the default\", which we\n * represent on the wire as `undefined` (omitted field). Non-empty\n * must parse to 1..65535. */\nfunction parsePort(s: string): { ok: true; value: number | undefined } | { ok: false } {\n const trimmed = s.trim()\n if (!trimmed) return { ok: true, value: undefined }\n const n = Number.parseInt(trimmed, 10)\n if (!Number.isFinite(n) || n < 1 || n > 65535) return { ok: false }\n return { ok: true, value: n }\n}\n\nfunction PortsCard(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const cfgQuery = useConfig()\n const updateCfg = useUpdateConfig()\n\n const cfg = cfgQuery.data\n const currentWeb = cfg?.webPort\n const currentAcp = cfg?.acpPort\n\n const [webDraft, setWebDraft] = useState<string>('')\n const [acpDraft, setAcpDraft] = useState<string>('')\n // Tracks the cfg snapshot we last synced from, so post-save refetch\n // re-hydrates the drafts cleanly (and so local edits don't get\n // clobbered by background refetches).\n const [syncedAt, setSyncedAt] = useState<number>(0)\n\n useEffect(() => {\n if (!cfg) return\n if (cfgQuery.dataUpdatedAt === syncedAt) return\n setWebDraft(currentWeb != null ? String(currentWeb) : '')\n setAcpDraft(currentAcp != null ? String(currentAcp) : '')\n setSyncedAt(cfgQuery.dataUpdatedAt)\n }, [cfg, cfgQuery.dataUpdatedAt, currentWeb, currentAcp, syncedAt])\n\n const webParsed = parsePort(webDraft)\n const acpParsed = parsePort(acpDraft)\n const webInvalid = !webParsed.ok\n const acpInvalid = !acpParsed.ok\n\n const isDirty = useMemo(() => {\n if (!cfg) return false\n const nextWeb = webParsed.ok ? webParsed.value : undefined\n const nextAcp = acpParsed.ok ? acpParsed.value : undefined\n return nextWeb !== currentWeb || nextAcp !== currentAcp\n }, [cfg, webParsed, acpParsed, currentWeb, currentAcp])\n\n function onDiscard(): void {\n setWebDraft(currentWeb != null ? String(currentWeb) : '')\n setAcpDraft(currentAcp != null ? String(currentAcp) : '')\n }\n\n async function onSave(): Promise<void> {\n if (!cfg || webInvalid || acpInvalid) return\n try {\n await updateCfg.mutateAsync({\n ...cfg,\n webPort: webParsed.ok ? webParsed.value : undefined,\n acpPort: acpParsed.ok ? acpParsed.value : undefined,\n })\n toast.success(t('service.ports.toast.saved'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n if (cfgQuery.isLoading) {\n return <div className=\"h-32 rounded-md bg-surface-2 animate-pulse\" />\n }\n\n return (\n <section className=\"rounded-md border border-border bg-surface\">\n <header className=\"flex items-center gap-2 border-b border-border px-4 py-3\">\n <Network className=\"h-4 w-4 text-text-dim\" />\n <h2 className=\"text-sm font-semibold\">{t('service.ports.title')}</h2>\n </header>\n <p className=\"px-4 pt-2 text-xs text-text-dim\">{t('service.ports.subtitle')}</p>\n\n <div className=\"grid grid-cols-1 gap-3 px-4 py-3 sm:grid-cols-2\">\n <PortField\n id=\"web-port\"\n label={t('service.ports.webPort')}\n hint={t('service.ports.webPortHint', { default: DEFAULT_WEB_PORT })}\n value={webDraft}\n onChange={setWebDraft}\n invalid={webInvalid}\n placeholder={String(DEFAULT_WEB_PORT)}\n />\n {/* R15 — acpPort hidden when remote-agent feature is off (same\n gate as the ACP card in /settings/agents). Server already\n strips acpPort from GET /api/config and drops it from\n incoming PUT in the off state. */}\n {cfg?.features?.remoteAgent ? (\n <PortField\n id=\"acp-port\"\n label={t('service.ports.acpPort')}\n hint={t('service.ports.acpPortHint', { default: DEFAULT_ACP_PORT })}\n value={acpDraft}\n onChange={setAcpDraft}\n invalid={acpInvalid}\n placeholder={String(DEFAULT_ACP_PORT)}\n />\n ) : null}\n </div>\n\n {isDirty && (\n <div className=\"flex items-center gap-2 border-t border-border px-4 py-3\">\n <Badge variant=\"warning\">{t('service.ports.restartRequired')}</Badge>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={onDiscard}\n disabled={updateCfg.isPending}\n >\n <X className=\"h-4 w-4\" />\n {t('service.ports.discard')}\n </Button>\n <Button\n size=\"sm\"\n onClick={() => void onSave()}\n disabled={updateCfg.isPending || webInvalid || acpInvalid}\n >\n {updateCfg.isPending\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <Save className=\"h-4 w-4\" />}\n {updateCfg.isPending ? t('service.ports.saving') : t('service.ports.save')}\n </Button>\n </div>\n )}\n </section>\n )\n}\n\ninterface PortFieldProps {\n id: string\n label: string\n hint: string\n value: string\n onChange: (v: string) => void\n invalid: boolean\n placeholder: string\n}\n\nfunction PortField({\n id, label, hint, value, onChange, invalid, placeholder,\n}: PortFieldProps): JSX.Element {\n const { t } = useTranslation('settings')\n return (\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor={id} className=\"text-xs font-medium\">{label}</Label>\n <Input\n id={id}\n type=\"number\"\n inputMode=\"numeric\"\n min={1}\n max={65535}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder={placeholder}\n aria-invalid={invalid}\n className={cn('font-mono', invalid && 'border-danger focus:ring-danger')}\n />\n <p className={cn('text-[11px]', invalid ? 'text-danger' : 'text-text-dim')}>\n {invalid ? t('service.ports.invalidPort') : hint}\n </p>\n </div>\n )\n}\n"],"names":["Square","createLucideIcon","MODE_VARIANT","DEFAULT_WEB_PORT","DEFAULT_ACP_PORT","SettingsServiceRoute","t","useTranslation","status","useServiceStatus","data","isRunning","start","useStartService","stop","useStopService","restart","useRestartService","confirmStop","setConfirmStop","useState","confirmRestart","setConfirmRestart","onStart","toast","err","describeError","onConfirmStop","onConfirmRestart","jsxs","jsx","Button","Loader2","RefreshCcw","PortsCard","Badge","Fragment","Play","RotateCcw","cn","ConfirmDialog","parsePort","trimmed","n","cfgQuery","useConfig","updateCfg","useUpdateConfig","cfg","currentWeb","currentAcp","webDraft","setWebDraft","acpDraft","setAcpDraft","syncedAt","setSyncedAt","useEffect","webParsed","acpParsed","webInvalid","acpInvalid","isDirty","useMemo","nextWeb","nextAcp","onDiscard","onSave","Network","PortField","X","Save","id","label","hint","value","onChange","invalid","placeholder","Label","Input","e"],"mappings":"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","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"service-CJRR2q7Q.js","sources":["../../node_modules/lucide-react/dist/esm/icons/square.js","../../src/routes/settings/service.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Square = createLucideIcon(\"Square\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }]\n]);\n\nexport { Square as default };\n//# sourceMappingURL=square.js.map\n","/**\n * /settings/service — operator-facing process control: see the\n * running agim daemon's mode/pid/uptime + start, stop, or restart it.\n *\n * R8 (this round) added a dedicated \"Ports\" card at the top covering\n * webPort + acpPort. They live in `~/.agim/config.json` (PUT /api/config),\n * and take effect on the next service restart — handled by the\n * Start/Restart buttons immediately below.\n *\n * Stop and restart go through ConfirmDialog because they\n * permanently interrupt every messenger adapter + in-flight job;\n * Start is one-click since it's safe to invoke even when already\n * running (backend short-circuits to alreadyRunning:true).\n */\n\nimport { useEffect, useMemo, useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport {\n Loader2, Network, Play, RefreshCcw, RotateCcw, Save, Square, X,\n} from 'lucide-react'\n\nimport { ConfirmDialog } from '@/components/common/confirm-dialog'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport {\n useConfig,\n useRestartService,\n useServiceStatus,\n useStartService,\n useStopService,\n useUpdateConfig,\n} from '@/hooks/use-settings'\nimport { describeError } from '@/lib/api/errors'\nimport type { ServiceMode } from '@/types/api'\nimport { cn } from '@/lib/utils'\n\nconst MODE_VARIANT: Record<ServiceMode, 'success' | 'info' | 'warning' | 'default'> = {\n systemd: 'success',\n background: 'info',\n foreground: 'warning',\n none: 'default',\n}\n\nconst DEFAULT_WEB_PORT = 3000\nconst DEFAULT_ACP_PORT = 9090\n\nexport default function SettingsServiceRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const status = useServiceStatus()\n const data = status.data\n const isRunning = data && data.mode !== 'none'\n\n const start = useStartService()\n const stop = useStopService()\n const restart = useRestartService()\n\n const [confirmStop, setConfirmStop] = useState(false)\n const [confirmRestart, setConfirmRestart] = useState(false)\n\n async function onStart(): Promise<void> {\n try {\n await start.mutateAsync()\n toast.success(t('service.toast.started'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n async function onConfirmStop(): Promise<void> {\n try {\n await stop.mutateAsync()\n toast.success(t('service.toast.stopped'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n throw err\n }\n }\n async function onConfirmRestart(): Promise<void> {\n try {\n await restart.mutateAsync()\n toast.success(t('service.toast.restarted'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n throw err\n }\n }\n\n return (\n <div className=\"mx-auto flex max-w-3xl flex-col gap-4\">\n <header className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('service.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => status.refetch()}\n disabled={status.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {status.isFetching ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('actions.refresh', { ns: 'common' })}</span>\n </Button>\n </div>\n <p className=\"text-sm text-text-dim\">{t('service.subtitle')}</p>\n </header>\n\n <PortsCard />\n\n {status.isLoading ? (\n <div className=\"h-48 rounded-md bg-surface-2 animate-pulse\" />\n ) : data ? (\n <div className=\"rounded-md border border-border bg-surface p-4\">\n <dl className=\"grid grid-cols-[max-content_1fr] gap-x-4 gap-y-2 text-sm\">\n <dt className=\"text-text-dim\">{t('service.modeLabel')}</dt>\n <dd>\n <Badge variant={MODE_VARIANT[data.mode]}>\n {t(`service.mode.${data.mode}`)}\n </Badge>\n </dd>\n {data.pid != null && (\n <>\n <dt className=\"text-text-dim\">{t('service.pidLabel')}</dt>\n <dd className=\"tabular-nums font-mono\">{data.pid}</dd>\n </>\n )}\n {data.uptime && (\n <>\n <dt className=\"text-text-dim\">{t('service.uptimeLabel')}</dt>\n <dd className=\"tabular-nums\">{data.uptime}</dd>\n </>\n )}\n {data.web && (\n <>\n <dt className=\"text-text-dim\">{t('service.webLabel')}</dt>\n <dd className=\"font-mono text-xs\">{data.web.bind}:{data.web.port}</dd>\n </>\n )}\n <dt className=\"text-text-dim\">{t('service.bootPhaseLabel')}</dt>\n <dd>\n <code className=\"rounded bg-surface-2 px-1.5 py-0.5 text-xs\">{data.bootPhase}</code>\n </dd>\n </dl>\n\n {/* Action buttons */}\n <div className=\"mt-4 flex flex-wrap gap-2\">\n <Button\n type=\"button\"\n variant=\"default\"\n size=\"sm\"\n disabled={isRunning || start.isPending}\n onClick={() => void onStart()}\n >\n {start.isPending ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <Play className=\"h-4 w-4\" />}\n {t('service.actions.start')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={!isRunning || restart.isPending}\n onClick={() => setConfirmRestart(true)}\n >\n <RotateCcw className={cn('h-4 w-4', restart.isPending && 'animate-spin')} />\n {t('service.actions.restart')}\n </Button>\n <Button\n type=\"button\"\n variant=\"destructive\"\n size=\"sm\"\n disabled={!isRunning || stop.isPending}\n onClick={() => setConfirmStop(true)}\n >\n <Square className=\"h-4 w-4\" />\n {t('service.actions.stop')}\n </Button>\n </div>\n </div>\n ) : null}\n\n <ConfirmDialog\n open={confirmStop}\n onOpenChange={setConfirmStop}\n title={t('service.actions.confirmStop')}\n description={t('service.actions.confirmStopDesc')}\n intent=\"danger\"\n confirmLabel={t('service.actions.stop')}\n onConfirm={onConfirmStop}\n />\n <ConfirmDialog\n open={confirmRestart}\n onOpenChange={setConfirmRestart}\n title={t('service.actions.confirmRestart')}\n description={t('service.actions.confirmRestartDesc')}\n intent=\"danger\"\n confirmLabel={t('service.actions.restart')}\n onConfirm={onConfirmRestart}\n />\n </div>\n )\n}\n\n/* ─────────────── Ports card (webPort + acpPort) ─────────────── */\n\n/** Validate a port string. Empty = \"use the default\", which we\n * represent on the wire as `undefined` (omitted field). Non-empty\n * must parse to 1..65535. */\nfunction parsePort(s: string): { ok: true; value: number | undefined } | { ok: false } {\n const trimmed = s.trim()\n if (!trimmed) return { ok: true, value: undefined }\n const n = Number.parseInt(trimmed, 10)\n if (!Number.isFinite(n) || n < 1 || n > 65535) return { ok: false }\n return { ok: true, value: n }\n}\n\nfunction PortsCard(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const cfgQuery = useConfig()\n const updateCfg = useUpdateConfig()\n\n const cfg = cfgQuery.data\n const currentWeb = cfg?.webPort\n const currentAcp = cfg?.acpPort\n\n const [webDraft, setWebDraft] = useState<string>('')\n const [acpDraft, setAcpDraft] = useState<string>('')\n // Tracks the cfg snapshot we last synced from, so post-save refetch\n // re-hydrates the drafts cleanly (and so local edits don't get\n // clobbered by background refetches).\n const [syncedAt, setSyncedAt] = useState<number>(0)\n\n useEffect(() => {\n if (!cfg) return\n if (cfgQuery.dataUpdatedAt === syncedAt) return\n setWebDraft(currentWeb != null ? String(currentWeb) : '')\n setAcpDraft(currentAcp != null ? String(currentAcp) : '')\n setSyncedAt(cfgQuery.dataUpdatedAt)\n }, [cfg, cfgQuery.dataUpdatedAt, currentWeb, currentAcp, syncedAt])\n\n const webParsed = parsePort(webDraft)\n const acpParsed = parsePort(acpDraft)\n const webInvalid = !webParsed.ok\n const acpInvalid = !acpParsed.ok\n\n const isDirty = useMemo(() => {\n if (!cfg) return false\n const nextWeb = webParsed.ok ? webParsed.value : undefined\n const nextAcp = acpParsed.ok ? acpParsed.value : undefined\n return nextWeb !== currentWeb || nextAcp !== currentAcp\n }, [cfg, webParsed, acpParsed, currentWeb, currentAcp])\n\n function onDiscard(): void {\n setWebDraft(currentWeb != null ? String(currentWeb) : '')\n setAcpDraft(currentAcp != null ? String(currentAcp) : '')\n }\n\n async function onSave(): Promise<void> {\n if (!cfg || webInvalid || acpInvalid) return\n try {\n await updateCfg.mutateAsync({\n ...cfg,\n webPort: webParsed.ok ? webParsed.value : undefined,\n acpPort: acpParsed.ok ? acpParsed.value : undefined,\n })\n toast.success(t('service.ports.toast.saved'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n if (cfgQuery.isLoading) {\n return <div className=\"h-32 rounded-md bg-surface-2 animate-pulse\" />\n }\n\n return (\n <section className=\"rounded-md border border-border bg-surface\">\n <header className=\"flex items-center gap-2 border-b border-border px-4 py-3\">\n <Network className=\"h-4 w-4 text-text-dim\" />\n <h2 className=\"text-sm font-semibold\">{t('service.ports.title')}</h2>\n </header>\n <p className=\"px-4 pt-2 text-xs text-text-dim\">{t('service.ports.subtitle')}</p>\n\n <div className=\"grid grid-cols-1 gap-3 px-4 py-3 sm:grid-cols-2\">\n <PortField\n id=\"web-port\"\n label={t('service.ports.webPort')}\n hint={t('service.ports.webPortHint', { default: DEFAULT_WEB_PORT })}\n value={webDraft}\n onChange={setWebDraft}\n invalid={webInvalid}\n placeholder={String(DEFAULT_WEB_PORT)}\n />\n {/* R15 — acpPort hidden when remote-agent feature is off (same\n gate as the ACP card in /settings/agents). Server already\n strips acpPort from GET /api/config and drops it from\n incoming PUT in the off state. */}\n {cfg?.features?.remoteAgent ? (\n <PortField\n id=\"acp-port\"\n label={t('service.ports.acpPort')}\n hint={t('service.ports.acpPortHint', { default: DEFAULT_ACP_PORT })}\n value={acpDraft}\n onChange={setAcpDraft}\n invalid={acpInvalid}\n placeholder={String(DEFAULT_ACP_PORT)}\n />\n ) : null}\n </div>\n\n {isDirty && (\n <div className=\"flex items-center gap-2 border-t border-border px-4 py-3\">\n <Badge variant=\"warning\">{t('service.ports.restartRequired')}</Badge>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={onDiscard}\n disabled={updateCfg.isPending}\n >\n <X className=\"h-4 w-4\" />\n {t('service.ports.discard')}\n </Button>\n <Button\n size=\"sm\"\n onClick={() => void onSave()}\n disabled={updateCfg.isPending || webInvalid || acpInvalid}\n >\n {updateCfg.isPending\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <Save className=\"h-4 w-4\" />}\n {updateCfg.isPending ? t('service.ports.saving') : t('service.ports.save')}\n </Button>\n </div>\n )}\n </section>\n )\n}\n\ninterface PortFieldProps {\n id: string\n label: string\n hint: string\n value: string\n onChange: (v: string) => void\n invalid: boolean\n placeholder: string\n}\n\nfunction PortField({\n id, label, hint, value, onChange, invalid, placeholder,\n}: PortFieldProps): JSX.Element {\n const { t } = useTranslation('settings')\n return (\n <div className=\"flex flex-col gap-1\">\n <Label htmlFor={id} className=\"text-xs font-medium\">{label}</Label>\n <Input\n id={id}\n type=\"number\"\n inputMode=\"numeric\"\n min={1}\n max={65535}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n placeholder={placeholder}\n aria-invalid={invalid}\n className={cn('font-mono', invalid && 'border-danger focus:ring-danger')}\n />\n <p className={cn('text-[11px]', invalid ? 'text-danger' : 'text-text-dim')}>\n {invalid ? t('service.ports.invalidPort') : hint}\n </p>\n </div>\n )\n}\n"],"names":["Square","createLucideIcon","MODE_VARIANT","DEFAULT_WEB_PORT","DEFAULT_ACP_PORT","SettingsServiceRoute","t","useTranslation","status","useServiceStatus","data","isRunning","start","useStartService","stop","useStopService","restart","useRestartService","confirmStop","setConfirmStop","useState","confirmRestart","setConfirmRestart","onStart","toast","err","describeError","onConfirmStop","onConfirmRestart","jsxs","jsx","Button","Loader2","RefreshCcw","PortsCard","Badge","Fragment","Play","RotateCcw","cn","ConfirmDialog","parsePort","trimmed","n","cfgQuery","useConfig","updateCfg","useUpdateConfig","cfg","currentWeb","currentAcp","webDraft","setWebDraft","acpDraft","setAcpDraft","syncedAt","setSyncedAt","useEffect","webParsed","acpParsed","webInvalid","acpInvalid","isDirty","useMemo","nextWeb","nextAcp","onDiscard","onSave","Network","PortField","X","Save","id","label","hint","value","onChange","invalid","placeholder","Label","Input","e"],"mappings":"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","x_google_ignoreList":[0]}
@@ -1,7 +1,7 @@
1
- import{n as e}from"./index-CqwhfPlr.js";/**
1
+ import{n as e}from"./index-D4Np2s3l.js";/**
2
2
  * @license lucide-react v0.469.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
5
5
  * See the LICENSE file in the root directory of this source tree.
6
6
  */const t=e("ShieldAlert",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"M12 8v4",key:"1got3b"}],["path",{d:"M12 16h.01",key:"1drbdi"}]]);export{t as S};
7
- //# sourceMappingURL=shield-alert-DjqqnTMk.js.map
7
+ //# sourceMappingURL=shield-alert-0q3ul8GH.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shield-alert-DjqqnTMk.js","sources":["../../node_modules/lucide-react/dist/esm/icons/shield-alert.js"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ShieldAlert = createLucideIcon(\"ShieldAlert\", [\n [\n \"path\",\n {\n d: \"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\",\n key: \"oel41y\"\n }\n ],\n [\"path\", { d: \"M12 8v4\", key: \"1got3b\" }],\n [\"path\", { d: \"M12 16h.01\", key: \"1drbdi\" }]\n]);\n\nexport { ShieldAlert as default };\n//# sourceMappingURL=shield-alert.js.map\n"],"names":["ShieldAlert","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAAcC,EAAiB,cAAe,CAClD,CACE,OACA,CACE,EAAG,qKACH,IAAK,QACX,CACA,EACE,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAQ,CAAE,EACxC,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,CAC7C,CAAC","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"shield-alert-0q3ul8GH.js","sources":["../../node_modules/lucide-react/dist/esm/icons/shield-alert.js"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ShieldAlert = createLucideIcon(\"ShieldAlert\", [\n [\n \"path\",\n {\n d: \"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\",\n key: \"oel41y\"\n }\n ],\n [\"path\", { d: \"M12 8v4\", key: \"1got3b\" }],\n [\"path\", { d: \"M12 16h.01\", key: \"1drbdi\" }]\n]);\n\nexport { ShieldAlert as default };\n//# sourceMappingURL=shield-alert.js.map\n"],"names":["ShieldAlert","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAAcC,EAAiB,cAAe,CAClD,CACE,OACA,CACE,EAAG,qKACH,IAAK,QACX,CACA,EACE,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAQ,CAAE,EACxC,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,CAC7C,CAAC","x_google_ignoreList":[0]}
@@ -1,2 +1,2 @@
1
- import{j as r,k as c}from"./index-CqwhfPlr.js";const i={succeeded:"success",completed:"success",done:"success",approved:"success",allowed:"success",delivered:"success",active:"success",running:"info",in_progress:"info",pending:"info",queued:"info",scheduled:"info",open:"info",paused:"warning",awaiting:"warning",timeout:"warning",expired:"warning",failed:"danger",error:"danger",denied:"danger",rejected:"danger",cancelled:"danger",canceled:"danger",finished:"default",closed:"default",archived:"default"};function o({status:e,variant:n,children:d,...s}){const a=n??i[e.toLowerCase()]??"default";return r.jsx(c,{variant:a,...s,children:d??e})}o.displayName="StatusBadge";export{o as S};
2
- //# sourceMappingURL=status-badge-nSFUUEfy.js.map
1
+ import{j as r,k as c}from"./index-D4Np2s3l.js";const i={succeeded:"success",completed:"success",done:"success",approved:"success",allowed:"success",delivered:"success",active:"success",running:"info",in_progress:"info",pending:"info",queued:"info",scheduled:"info",open:"info",paused:"warning",awaiting:"warning",timeout:"warning",expired:"warning",failed:"danger",error:"danger",denied:"danger",rejected:"danger",cancelled:"danger",canceled:"danger",finished:"default",closed:"default",archived:"default"};function o({status:e,variant:n,children:d,...s}){const a=n??i[e.toLowerCase()]??"default";return r.jsx(c,{variant:a,...s,children:d??e})}o.displayName="StatusBadge";export{o as S};
2
+ //# sourceMappingURL=status-badge-CN17QMv6.js.map