agim-cli 1.2.130 → 1.2.131

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 (183) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/dist/core/llm/plan-exit-dispatcher.d.ts +27 -0
  3. package/dist/core/llm/plan-exit-dispatcher.d.ts.map +1 -0
  4. package/dist/core/llm/plan-exit-dispatcher.js +210 -0
  5. package/dist/core/llm/plan-exit-dispatcher.js.map +1 -0
  6. package/dist/core/plan-history.d.ts +34 -0
  7. package/dist/core/plan-history.d.ts.map +1 -0
  8. package/dist/core/plan-history.js +89 -0
  9. package/dist/core/plan-history.js.map +1 -0
  10. package/dist/plugins/agents/native/index.d.ts.map +1 -1
  11. package/dist/plugins/agents/native/index.js +29 -2
  12. package/dist/plugins/agents/native/index.js.map +1 -1
  13. package/dist/web/public/assets/{a2a-Bp_OpTfW.js → a2a-Rq5d7Xk5.js} +2 -2
  14. package/dist/web/public/assets/{a2a-Bp_OpTfW.js.map → a2a-Rq5d7Xk5.js.map} +1 -1
  15. package/dist/web/public/assets/{activity-B5erGuWa.js → activity-FCJjBNRM.js} +2 -2
  16. package/dist/web/public/assets/{activity-B5erGuWa.js.map → activity-FCJjBNRM.js.map} +1 -1
  17. package/dist/web/public/assets/{admins-D3j7wkvL.js → admins-9fFdLRCv.js} +2 -2
  18. package/dist/web/public/assets/{admins-D3j7wkvL.js.map → admins-9fFdLRCv.js.map} +1 -1
  19. package/dist/web/public/assets/{agents-Cb3Vb2-8.js → agents-CiWiDAvY.js} +2 -2
  20. package/dist/web/public/assets/{agents-Cb3Vb2-8.js.map → agents-CiWiDAvY.js.map} +1 -1
  21. package/dist/web/public/assets/{approvals-BZULwrl5.js → approvals-4gNB4E5r.js} +2 -2
  22. package/dist/web/public/assets/{approvals-BZULwrl5.js.map → approvals-4gNB4E5r.js.map} +1 -1
  23. package/dist/web/public/assets/{arrow-down-OdSfpgG4.js → arrow-down-CL6JRd2c.js} +2 -2
  24. package/dist/web/public/assets/{arrow-down-OdSfpgG4.js.map → arrow-down-CL6JRd2c.js.map} +1 -1
  25. package/dist/web/public/assets/{arrow-up-DtrvOH7Z.js → arrow-up-B47-Pj-X.js} +2 -2
  26. package/dist/web/public/assets/{arrow-up-DtrvOH7Z.js.map → arrow-up-B47-Pj-X.js.map} +1 -1
  27. package/dist/web/public/assets/{asks-BaVT-eFe.js → asks-DPTxh_Os.js} +2 -2
  28. package/dist/web/public/assets/{asks-BaVT-eFe.js.map → asks-DPTxh_Os.js.map} +1 -1
  29. package/dist/web/public/assets/{audit-CSk2rv6z.js → audit-Dw3mL-g7.js} +2 -2
  30. package/dist/web/public/assets/{audit-CSk2rv6z.js.map → audit-Dw3mL-g7.js.map} +1 -1
  31. package/dist/web/public/assets/{bell-DifbuUaI.js → bell-ojwGPpS7.js} +2 -2
  32. package/dist/web/public/assets/{bell-DifbuUaI.js.map → bell-ojwGPpS7.js.map} +1 -1
  33. package/dist/web/public/assets/{bgjobs-D3wsuZBR.js → bgjobs-DDTjejCS.js} +2 -2
  34. package/dist/web/public/assets/{bgjobs-D3wsuZBR.js.map → bgjobs-DDTjejCS.js.map} +1 -1
  35. package/dist/web/public/assets/{brain-BH9ObIfA.js → brain-wzaKeCbt.js} +2 -2
  36. package/dist/web/public/assets/{brain-BH9ObIfA.js.map → brain-wzaKeCbt.js.map} +1 -1
  37. package/dist/web/public/assets/{briefcase-CZqK5oy3.js → briefcase-CCAq-ik6.js} +2 -2
  38. package/dist/web/public/assets/{briefcase-CZqK5oy3.js.map → briefcase-CCAq-ik6.js.map} +1 -1
  39. package/dist/web/public/assets/{chat-gOU1pe0E.js → chat-CbSvPFpG.js} +2 -2
  40. package/dist/web/public/assets/{chat-gOU1pe0E.js.map → chat-CbSvPFpG.js.map} +1 -1
  41. package/dist/web/public/assets/{chevron-left-BtuaBNRZ.js → chevron-left-bpKHh9Bu.js} +2 -2
  42. package/dist/web/public/assets/{chevron-left-BtuaBNRZ.js.map → chevron-left-bpKHh9Bu.js.map} +1 -1
  43. package/dist/web/public/assets/{chevron-right-uDVVnuGu.js → chevron-right-CUlLpETY.js} +2 -2
  44. package/dist/web/public/assets/{chevron-right-uDVVnuGu.js.map → chevron-right-CUlLpETY.js.map} +1 -1
  45. package/dist/web/public/assets/{circle-check-VgYKnBhy.js → circle-check-D98QQwz0.js} +2 -2
  46. package/dist/web/public/assets/{circle-check-VgYKnBhy.js.map → circle-check-D98QQwz0.js.map} +1 -1
  47. package/dist/web/public/assets/{circle-check-big-7idAFtyL.js → circle-check-big-BP-0K1le.js} +2 -2
  48. package/dist/web/public/assets/{circle-check-big-7idAFtyL.js.map → circle-check-big-BP-0K1le.js.map} +1 -1
  49. package/dist/web/public/assets/{circle-x-8dhkvHlT.js → circle-x-Et3rwVPd.js} +2 -2
  50. package/dist/web/public/assets/{circle-x-8dhkvHlT.js.map → circle-x-Et3rwVPd.js.map} +1 -1
  51. package/dist/web/public/assets/{confirm-dialog-_BtUs6oW.js → confirm-dialog-6dKowsEt.js} +2 -2
  52. package/dist/web/public/assets/{confirm-dialog-_BtUs6oW.js.map → confirm-dialog-6dKowsEt.js.map} +1 -1
  53. package/dist/web/public/assets/{copy-Ba1min4z.js → copy-kCWCP9Wu.js} +2 -2
  54. package/dist/web/public/assets/{copy-Ba1min4z.js.map → copy-kCWCP9Wu.js.map} +1 -1
  55. package/dist/web/public/assets/{data-table-BVcXWtPw.js → data-table-BbNkr6tW.js} +2 -2
  56. package/dist/web/public/assets/{data-table-BVcXWtPw.js.map → data-table-BbNkr6tW.js.map} +1 -1
  57. package/dist/web/public/assets/{dialog-BVYFRXlI.js → dialog-Cv87qelJ.js} +2 -2
  58. package/dist/web/public/assets/{dialog-BVYFRXlI.js.map → dialog-Cv87qelJ.js.map} +1 -1
  59. package/dist/web/public/assets/{download-DYc5g_1W.js → download-Cv8u9PxC.js} +2 -2
  60. package/dist/web/public/assets/{download-DYc5g_1W.js.map → download-Cv8u9PxC.js.map} +1 -1
  61. package/dist/web/public/assets/{email-6vlGBJXY.js → email-BS3f2y7i.js} +2 -2
  62. package/dist/web/public/assets/{email-6vlGBJXY.js.map → email-BS3f2y7i.js.map} +1 -1
  63. package/dist/web/public/assets/{empty-state-WHzNYVaT.js → empty-state-CRnid5FY.js} +2 -2
  64. package/dist/web/public/assets/{empty-state-WHzNYVaT.js.map → empty-state-CRnid5FY.js.map} +1 -1
  65. package/dist/web/public/assets/{external-link-CfQZDer8.js → external-link-CzQc-c_P.js} +2 -2
  66. package/dist/web/public/assets/{external-link-CfQZDer8.js.map → external-link-CzQc-c_P.js.map} +1 -1
  67. package/dist/web/public/assets/{eye-PzqPB6N6.js → eye-DEBkfJiC.js} +2 -2
  68. package/dist/web/public/assets/{eye-PzqPB6N6.js.map → eye-DEBkfJiC.js.map} +1 -1
  69. package/dist/web/public/assets/{facts-NmBeyMpC.js → facts-O3FFqdD1.js} +2 -2
  70. package/dist/web/public/assets/{facts-NmBeyMpC.js.map → facts-O3FFqdD1.js.map} +1 -1
  71. package/dist/web/public/assets/{goals-BfMwQtYm.js → goals-pr5ky9rG.js} +2 -2
  72. package/dist/web/public/assets/{goals-BfMwQtYm.js.map → goals-pr5ky9rG.js.map} +1 -1
  73. package/dist/web/public/assets/{health-D46iQ6Hj.js → health-D_rfBsgq.js} +2 -2
  74. package/dist/web/public/assets/{health-D46iQ6Hj.js.map → health-D_rfBsgq.js.map} +1 -1
  75. package/dist/web/public/assets/{heart-pulse-BHz53Ggd.js → heart-pulse-203oH09r.js} +2 -2
  76. package/dist/web/public/assets/{heart-pulse-BHz53Ggd.js.map → heart-pulse-203oH09r.js.map} +1 -1
  77. package/dist/web/public/assets/{heartbeat-DBpc9rKL.js → heartbeat-B5yJoH-X.js} +2 -2
  78. package/dist/web/public/assets/{heartbeat-DBpc9rKL.js.map → heartbeat-B5yJoH-X.js.map} +1 -1
  79. package/dist/web/public/assets/{hot-D_-tARKX.js → hot-CXGeh4Oo.js} +2 -2
  80. package/dist/web/public/assets/{hot-D_-tARKX.js.map → hot-CXGeh4Oo.js.map} +1 -1
  81. package/dist/web/public/assets/{index-DXI13nSQ.js → index-CuNnG-5O.js} +16 -16
  82. package/dist/web/public/assets/index-CuNnG-5O.js.map +1 -0
  83. package/dist/web/public/assets/{installed-BtOgT0Ea.js → installed-CQKXZNEU.js} +2 -2
  84. package/dist/web/public/assets/{installed-BtOgT0Ea.js.map → installed-CQKXZNEU.js.map} +1 -1
  85. package/dist/web/public/assets/{jobs-DUoPbupO.js → jobs-DPxN8Ko0.js} +2 -2
  86. package/dist/web/public/assets/{jobs-DUoPbupO.js.map → jobs-DPxN8Ko0.js.map} +1 -1
  87. package/dist/web/public/assets/{layout-BpS7td-S.js → layout-4C_GhacH.js} +2 -2
  88. package/dist/web/public/assets/{layout-BpS7td-S.js.map → layout-4C_GhacH.js.map} +1 -1
  89. package/dist/web/public/assets/{layout-wuoOyazR.js → layout-CQXWA5Ak.js} +2 -2
  90. package/dist/web/public/assets/{layout-wuoOyazR.js.map → layout-CQXWA5Ak.js.map} +1 -1
  91. package/dist/web/public/assets/{layout-C3e8vPrG.js → layout-CxQy-DtV.js} +2 -2
  92. package/dist/web/public/assets/{layout-C3e8vPrG.js.map → layout-CxQy-DtV.js.map} +1 -1
  93. package/dist/web/public/assets/{layout-C1EVvCs8.js → layout-VOwsqNph.js} +2 -2
  94. package/dist/web/public/assets/{layout-C1EVvCs8.js.map → layout-VOwsqNph.js.map} +1 -1
  95. package/dist/web/public/assets/{layout-DkoRqhBs.js → layout-tAyuz3-F.js} +2 -2
  96. package/dist/web/public/assets/{layout-DkoRqhBs.js.map → layout-tAyuz3-F.js.map} +1 -1
  97. package/dist/web/public/assets/{llm-iuvigJxr.js → llm-i15cVS6k.js} +2 -2
  98. package/dist/web/public/assets/{llm-iuvigJxr.js.map → llm-i15cVS6k.js.map} +1 -1
  99. package/dist/web/public/assets/{loader-circle-BS5FFFg-.js → loader-circle-CVEo3Hwx.js} +2 -2
  100. package/dist/web/public/assets/{loader-circle-BS5FFFg-.js.map → loader-circle-CVEo3Hwx.js.map} +1 -1
  101. package/dist/web/public/assets/{map-pin-CRS6YW4i.js → map-pin-BlmDrPGJ.js} +2 -2
  102. package/dist/web/public/assets/{map-pin-CRS6YW4i.js.map → map-pin-BlmDrPGJ.js.map} +1 -1
  103. package/dist/web/public/assets/{mcp-PWEuZOJ_.js → mcp-9MlUdHAS.js} +2 -2
  104. package/dist/web/public/assets/{mcp-PWEuZOJ_.js.map → mcp-9MlUdHAS.js.map} +1 -1
  105. package/dist/web/public/assets/{memos-C6i1hbv9.js → memos-MDYe436b.js} +2 -2
  106. package/dist/web/public/assets/{memos-C6i1hbv9.js.map → memos-MDYe436b.js.map} +1 -1
  107. package/dist/web/public/assets/{messengers-CZ3eL15d.js → messengers-D0F-cgJ0.js} +2 -2
  108. package/dist/web/public/assets/{messengers-CZ3eL15d.js.map → messengers-D0F-cgJ0.js.map} +1 -1
  109. package/dist/web/public/assets/{mobile-_rEEG_kX.js → mobile-Bezz5MnW.js} +2 -2
  110. package/dist/web/public/assets/{mobile-_rEEG_kX.js.map → mobile-Bezz5MnW.js.map} +1 -1
  111. package/dist/web/public/assets/{native-agent-B-Id8sOl.js → native-agent-bRS7DRfj.js} +2 -2
  112. package/dist/web/public/assets/{native-agent-B-Id8sOl.js.map → native-agent-bRS7DRfj.js.map} +1 -1
  113. package/dist/web/public/assets/{network-MVE8s4TA.js → network-3O1O1jsk.js} +2 -2
  114. package/dist/web/public/assets/{network-MVE8s4TA.js.map → network-3O1O1jsk.js.map} +1 -1
  115. package/dist/web/public/assets/{outbox-BRpgAP1d.js → outbox-D2iX9mcs.js} +2 -2
  116. package/dist/web/public/assets/{outbox-BRpgAP1d.js.map → outbox-D2iX9mcs.js.map} +1 -1
  117. package/dist/web/public/assets/{pagination-dm3r6K_2.js → pagination-79ms7QFI.js} +2 -2
  118. package/dist/web/public/assets/{pagination-dm3r6K_2.js.map → pagination-79ms7QFI.js.map} +1 -1
  119. package/dist/web/public/assets/{persona-Oq3C-gEw.js → persona-D37NzRbz.js} +2 -2
  120. package/dist/web/public/assets/{persona-Oq3C-gEw.js.map → persona-D37NzRbz.js.map} +1 -1
  121. package/dist/web/public/assets/{play-COQw7BqX.js → play-BedplEoY.js} +2 -2
  122. package/dist/web/public/assets/{play-COQw7BqX.js.map → play-BedplEoY.js.map} +1 -1
  123. package/dist/web/public/assets/{plus-CdOyGoU1.js → plus-4GdEpvTV.js} +2 -2
  124. package/dist/web/public/assets/{plus-CdOyGoU1.js.map → plus-4GdEpvTV.js.map} +1 -1
  125. package/dist/web/public/assets/{policy-docXezae.js → policy-Gmd4rmzp.js} +2 -2
  126. package/dist/web/public/assets/{policy-docXezae.js.map → policy-Gmd4rmzp.js.map} +1 -1
  127. package/dist/web/public/assets/{qr-code-8putJTrW.js → qr-code-DVgHWDky.js} +2 -2
  128. package/dist/web/public/assets/{qr-code-8putJTrW.js.map → qr-code-DVgHWDky.js.map} +1 -1
  129. package/dist/web/public/assets/{refresh-ccw-BPKXoMZa.js → refresh-ccw-DZHRYuFA.js} +2 -2
  130. package/dist/web/public/assets/{refresh-ccw-BPKXoMZa.js.map → refresh-ccw-DZHRYuFA.js.map} +1 -1
  131. package/dist/web/public/assets/{reminders-CP2qtNSr.js → reminders-C00V-Fs9.js} +2 -2
  132. package/dist/web/public/assets/{reminders-CP2qtNSr.js.map → reminders-C00V-Fs9.js.map} +1 -1
  133. package/dist/web/public/assets/{save-BXCmgeEj.js → save-DQlBAXAl.js} +2 -2
  134. package/dist/web/public/assets/{save-BXCmgeEj.js.map → save-DQlBAXAl.js.map} +1 -1
  135. package/dist/web/public/assets/{schedules-DVaY38v1.js → schedules-BtuWAAd7.js} +2 -2
  136. package/dist/web/public/assets/{schedules-DVaY38v1.js.map → schedules-BtuWAAd7.js.map} +1 -1
  137. package/dist/web/public/assets/{search-DzexDAbr.js → search-DJXxphzz.js} +2 -2
  138. package/dist/web/public/assets/{search-DzexDAbr.js.map → search-DJXxphzz.js.map} +1 -1
  139. package/dist/web/public/assets/{search-B-wDhzjs.js → search-dBGBHpnH.js} +2 -2
  140. package/dist/web/public/assets/{search-B-wDhzjs.js.map → search-dBGBHpnH.js.map} +1 -1
  141. package/dist/web/public/assets/{security-FHN-b43T.js → security-CP0MP_Gx.js} +2 -2
  142. package/dist/web/public/assets/{security-FHN-b43T.js.map → security-CP0MP_Gx.js.map} +1 -1
  143. package/dist/web/public/assets/{service-DXGUZTCp.js → service-BJFnNe7Y.js} +2 -2
  144. package/dist/web/public/assets/{service-DXGUZTCp.js.map → service-BJFnNe7Y.js.map} +1 -1
  145. package/dist/web/public/assets/{shield-alert-BM0-khVy.js → shield-alert-DRh8fC8Z.js} +2 -2
  146. package/dist/web/public/assets/{shield-alert-BM0-khVy.js.map → shield-alert-DRh8fC8Z.js.map} +1 -1
  147. package/dist/web/public/assets/{status-badge-DeESb2dc.js → status-badge-CTRG6Pb2.js} +2 -2
  148. package/dist/web/public/assets/{status-badge-DeESb2dc.js.map → status-badge-CTRG6Pb2.js.map} +1 -1
  149. package/dist/web/public/assets/{subtasks-DOwo6FnZ.js → subtasks-BiZ2mCPs.js} +2 -2
  150. package/dist/web/public/assets/{subtasks-DOwo6FnZ.js.map → subtasks-BiZ2mCPs.js.map} +1 -1
  151. package/dist/web/public/assets/{table-oUi0mGOn.js → table-Dbriy3Jz.js} +2 -2
  152. package/dist/web/public/assets/{table-oUi0mGOn.js.map → table-Dbriy3Jz.js.map} +1 -1
  153. package/dist/web/public/assets/{topn-D1LQXoLo.js → topn-BEi7Uvlg.js} +2 -2
  154. package/dist/web/public/assets/{topn-D1LQXoLo.js.map → topn-BEi7Uvlg.js.map} +1 -1
  155. package/dist/web/public/assets/{trash-2-CTkSvnZX.js → trash-2-BgltvQpz.js} +2 -2
  156. package/dist/web/public/assets/{trash-2-CTkSvnZX.js.map → trash-2-BgltvQpz.js.map} +1 -1
  157. package/dist/web/public/assets/{use-background-tasks-BkUIDOxX.js → use-background-tasks-DHo3Hnu9.js} +2 -2
  158. package/dist/web/public/assets/{use-background-tasks-BkUIDOxX.js.map → use-background-tasks-DHo3Hnu9.js.map} +1 -1
  159. package/dist/web/public/assets/{use-llm-admin-BrJMMEz5.js → use-llm-admin-EU1V1WQ5.js} +2 -2
  160. package/dist/web/public/assets/{use-llm-admin-BrJMMEz5.js.map → use-llm-admin-EU1V1WQ5.js.map} +1 -1
  161. package/dist/web/public/assets/{use-memory-CbTYEBTc.js → use-memory-D0FD5n0A.js} +2 -2
  162. package/dist/web/public/assets/{use-memory-CbTYEBTc.js.map → use-memory-D0FD5n0A.js.map} +1 -1
  163. package/dist/web/public/assets/{use-observability-Bum0mmDO.js → use-observability-CZg_sS2t.js} +2 -2
  164. package/dist/web/public/assets/{use-observability-Bum0mmDO.js.map → use-observability-CZg_sS2t.js.map} +1 -1
  165. package/dist/web/public/assets/{use-settings-DJlVLnjo.js → use-settings-D3vI1Dwg.js} +2 -2
  166. package/dist/web/public/assets/{use-settings-DJlVLnjo.js.map → use-settings-D3vI1Dwg.js.map} +1 -1
  167. package/dist/web/public/assets/{use-workspace-BJZUfkqw.js → use-workspace-DWm4dRVD.js} +2 -2
  168. package/dist/web/public/assets/{use-workspace-BJZUfkqw.js.map → use-workspace-DWm4dRVD.js.map} +1 -1
  169. package/dist/web/public/assets/{useQuery-CEwGD94N.js → useQuery-DIlm0vJ-.js} +2 -2
  170. package/dist/web/public/assets/{useQuery-CEwGD94N.js.map → useQuery-DIlm0vJ-.js.map} +1 -1
  171. package/dist/web/public/assets/{vector-BqffHZmp.js → vector-CaijGbpn.js} +2 -2
  172. package/dist/web/public/assets/{vector-BqffHZmp.js.map → vector-CaijGbpn.js.map} +1 -1
  173. package/dist/web/public/assets/{viewer-CKTTV-Wt.js → viewer-nU6uZJWq.js} +2 -2
  174. package/dist/web/public/assets/{viewer-CKTTV-Wt.js.map → viewer-nU6uZJWq.js.map} +1 -1
  175. package/dist/web/public/assets/{workspace-DQphgYwy.js → workspace-BluXJmIg.js} +2 -2
  176. package/dist/web/public/assets/{workspace-DQphgYwy.js.map → workspace-BluXJmIg.js.map} +1 -1
  177. package/dist/web/public/assets/{workspaces-BOA3TuDS.js → workspaces-B2nSpx9t.js} +2 -2
  178. package/dist/web/public/assets/{workspaces-BOA3TuDS.js.map → workspaces-B2nSpx9t.js.map} +1 -1
  179. package/dist/web/public/assets/{x-OHUicFfn.js → x-D_eFtxsK.js} +2 -2
  180. package/dist/web/public/assets/{x-OHUicFfn.js.map → x-D_eFtxsK.js.map} +1 -1
  181. package/dist/web/public/index.html +1 -1
  182. package/package.json +1 -1
  183. package/dist/web/public/assets/index-DXI13nSQ.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"persona-Oq3C-gEw.js","sources":["../../src/routes/memory/persona.tsx"],"sourcesContent":["/**\n * /memory/persona — view + edit the per-user persona summary +\n * trigger the consolidation pass.\n *\n * Layout: status strip (last consolidate run + button) on top, then\n * the persona editor (textarea + Save + Delete). The editor enters\n * an \"unsaved changes\" state when the textarea diverges from the\n * server-rendered summary; Save flips back to clean.\n *\n * Consolidate flow:\n * * Trigger button POSTs /api/memory/consolidate; the backend\n * replies 202 with a jobId.\n * * /api/memory/consolidate/status is polled every 3s by the\n * hook so the operator sees phase transitions live (running →\n * done / failed) without manual refresh.\n * * On `done`, the persona query is invalidated — the new\n * summary appears in the textarea automatically.\n */\n\nimport { useEffect, useState } from 'react'\nimport { useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { Brain, CheckCircle, Loader2, Play, RefreshCcw, Trash2, XCircle } from 'lucide-react'\n\nimport { EmptyState } from '@/components/common/empty-state'\nimport { ConfirmDialog } from '@/components/common/confirm-dialog'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Label } from '@/components/ui/label'\nimport {\n useMemoryPersona,\n useUpdatePersona,\n useDeletePersona,\n useConsolidateStatus,\n useTriggerConsolidate,\n} from '@/hooks/use-memory'\nimport { describeError } from '@/lib/api/errors'\nimport { cn } from '@/lib/utils'\nimport type { ConsolidateJob } from '@/types/api'\n\nexport default function MemoryPersonaRoute(): JSX.Element {\n const { t } = useTranslation(['memory', 'common'])\n const [params] = useSearchParams()\n const userKey = params.get('user') ?? ''\n\n if (!userKey) {\n return (\n <div className=\"mx-auto max-w-3xl\">\n <EmptyState\n icon={<Brain />}\n title={t('noUserSelected.title')}\n description={t('noUserSelected.description')}\n />\n </div>\n )\n }\n\n return <PersonaEditor userKey={userKey} />\n}\n\ninterface PersonaEditorProps {\n userKey: string\n}\n\nfunction PersonaEditor({ userKey }: PersonaEditorProps): JSX.Element {\n const { t } = useTranslation(['memory', 'common'])\n const personaQuery = useMemoryPersona(userKey)\n const persona = personaQuery.data\n\n const consolidate = useTriggerConsolidate()\n const status = useConsolidateStatus()\n const latestJob = status.data?.jobs[0]\n\n const updatePersona = useUpdatePersona()\n const deletePersona = useDeletePersona()\n const [confirmDelete, setConfirmDelete] = useState(false)\n\n /** Editor state — initialised from the server summary; tracks\n * dirtiness via reference comparison after each save. */\n const [draft, setDraft] = useState(persona?.summary ?? '')\n useEffect(() => {\n setDraft(persona?.summary ?? '')\n }, [persona?.summary])\n const dirty = draft !== (persona?.summary ?? '')\n\n async function onSave(): Promise<void> {\n const trimmed = draft.trim()\n if (!trimmed) return\n try {\n await updatePersona.mutateAsync({ user_key: userKey, body: { summary: trimmed } })\n toast.success(t('persona.saved'))\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n }\n }\n\n async function onConfirmDelete(): Promise<void> {\n try {\n await deletePersona.mutateAsync(userKey)\n toast.success(t('common:actions.delete'))\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n throw err\n }\n }\n\n async function onTrigger(): Promise<void> {\n try {\n await consolidate.mutateAsync()\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n }\n }\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('persona.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => personaQuery.refetch()}\n disabled={personaQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {personaQuery.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('persona.subtitle')}</p>\n </header>\n\n {/* Consolidate strip */}\n <div className=\"rounded-md border border-border bg-surface p-3\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <span className=\"font-medium text-sm text-text\">{t('persona.consolidate.trigger')}</span>\n <ConsolidateBadge job={latestJob} />\n <Button\n variant=\"default\"\n size=\"sm\"\n onClick={() => void onTrigger()}\n disabled={consolidate.isPending || latestJob?.phase === 'running'}\n className=\"ml-auto\"\n >\n {consolidate.isPending\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <Play className=\"h-4 w-4\" />}\n {consolidate.isPending\n ? t('persona.consolidate.triggering')\n : t('persona.consolidate.trigger')}\n </Button>\n </div>\n {latestJob?.phase === 'done' && (latestJob.result.users != null || latestJob.result.updated != null) && (\n <p className=\"mt-2 text-xs text-text-dim\">\n {t('persona.consolidate.result', {\n users: latestJob.result.users ?? 0,\n updated: latestJob.result.updated ?? 0,\n })}\n </p>\n )}\n {latestJob?.phase === 'failed' && latestJob.result.error && (\n <p className=\"mt-2 text-xs text-danger\">{latestJob.result.error}</p>\n )}\n </div>\n\n {/* Editor */}\n {personaQuery.isLoading ? (\n <div className=\"h-48 w-full rounded-md bg-surface-2 animate-pulse\" />\n ) : !persona ? (\n <>\n <EmptyState\n icon={<Brain />}\n title={t('persona.empty.title')}\n description={t('persona.empty.description')}\n />\n {/* Even with no persona, the operator can still type one in\n and save — the upsert handler creates a new row. */}\n <PersonaTextarea\n draft={draft}\n onChange={setDraft}\n onSave={() => void onSave()}\n saving={updatePersona.isPending}\n dirty={dirty}\n canDelete={false}\n onDelete={() => setConfirmDelete(true)}\n />\n </>\n ) : (\n <>\n {persona.updated_at > 0 && (\n <div className=\"text-xs text-text-dim\">\n {t('persona.updated', { at: formatEpoch(persona.updated_at) })}\n </div>\n )}\n <PersonaTextarea\n draft={draft}\n onChange={setDraft}\n onSave={() => void onSave()}\n saving={updatePersona.isPending}\n dirty={dirty}\n canDelete\n onDelete={() => setConfirmDelete(true)}\n />\n </>\n )}\n\n <ConfirmDialog\n open={confirmDelete}\n onOpenChange={setConfirmDelete}\n title={t('persona.confirmDelete')}\n description={t('persona.confirmDeleteDesc')}\n intent=\"danger\"\n confirmLabel={t('persona.delete')}\n onConfirm={onConfirmDelete}\n />\n </div>\n )\n}\n\ninterface PersonaTextareaProps {\n draft: string\n onChange: (next: string) => void\n onSave: () => void\n saving: boolean\n dirty: boolean\n canDelete: boolean\n onDelete: () => void\n}\n\nfunction PersonaTextarea({\n draft, onChange, onSave, saving, dirty, canDelete, onDelete,\n}: PersonaTextareaProps): JSX.Element {\n const { t } = useTranslation('memory')\n return (\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"persona-editor\" className=\"text-sm text-text-dim\">\n {t('persona.editorLabel')}\n </Label>\n <textarea\n id=\"persona-editor\"\n value={draft}\n onChange={(e) => onChange(e.target.value)}\n rows={12}\n className={cn(\n 'w-full resize-y rounded-md border bg-bg px-3 py-2',\n 'font-mono text-sm leading-6',\n 'focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-1 focus:ring-offset-bg',\n dirty ? 'border-accent' : 'border-border',\n )}\n />\n <div className=\"flex flex-wrap items-center gap-2\">\n {canDelete && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={onDelete}\n >\n <Trash2 className=\"h-3 w-3\" />\n {t('persona.delete')}\n </Button>\n )}\n <Button\n type=\"button\"\n size=\"sm\"\n className=\"ml-auto\"\n disabled={!dirty || saving || draft.trim().length === 0}\n onClick={onSave}\n >\n {saving ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : null}\n {t('persona.save')}\n </Button>\n </div>\n </div>\n )\n}\n\ninterface ConsolidateBadgeProps {\n job: ConsolidateJob | undefined\n}\n\nfunction ConsolidateBadge({ job }: ConsolidateBadgeProps): JSX.Element | null {\n const { t } = useTranslation('memory')\n if (!job) return null\n if (job.phase === 'running') {\n return (\n <Badge variant=\"info\">\n <Loader2 className=\"h-3 w-3 animate-spin\" />\n {t('persona.consolidate.running')}\n </Badge>\n )\n }\n if (job.phase === 'done') {\n return (\n <Badge variant=\"success\">\n <CheckCircle className=\"h-3 w-3\" />\n {t('persona.consolidate.lastRun', { at: formatEpoch(job.finishedAt ?? job.startedAt) })}\n </Badge>\n )\n }\n return (\n <Badge variant=\"danger\">\n <XCircle className=\"h-3 w-3\" />\n {t('persona.consolidate.doneFailed')}\n </Badge>\n )\n}\n\nfunction formatEpoch(ms: number): string {\n try {\n const d = new Date(ms)\n if (Number.isNaN(d.getTime())) return String(ms)\n return d.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })\n } catch {\n return String(ms)\n }\n}\n"],"names":["MemoryPersonaRoute","useTranslation","params","useSearchParams","userKey","jsx","PersonaEditor","EmptyState","Brain","t","personaQuery","useMemoryPersona","persona","consolidate","useTriggerConsolidate","latestJob","useConsolidateStatus","updatePersona","useUpdatePersona","deletePersona","useDeletePersona","confirmDelete","setConfirmDelete","useState","draft","setDraft","useEffect","dirty","onSave","trimmed","toast","err","message","describeError","onConfirmDelete","onTrigger","jsxs","Button","Loader2","RefreshCcw","ConsolidateBadge","Play","Fragment","formatEpoch","PersonaTextarea","ConfirmDialog","onChange","saving","canDelete","onDelete","Label","e","cn","Trash2","job","Badge","CheckCircle","XCircle","ms","d"],"mappings":"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"}
1
+ {"version":3,"file":"persona-D37NzRbz.js","sources":["../../src/routes/memory/persona.tsx"],"sourcesContent":["/**\n * /memory/persona — view + edit the per-user persona summary +\n * trigger the consolidation pass.\n *\n * Layout: status strip (last consolidate run + button) on top, then\n * the persona editor (textarea + Save + Delete). The editor enters\n * an \"unsaved changes\" state when the textarea diverges from the\n * server-rendered summary; Save flips back to clean.\n *\n * Consolidate flow:\n * * Trigger button POSTs /api/memory/consolidate; the backend\n * replies 202 with a jobId.\n * * /api/memory/consolidate/status is polled every 3s by the\n * hook so the operator sees phase transitions live (running →\n * done / failed) without manual refresh.\n * * On `done`, the persona query is invalidated — the new\n * summary appears in the textarea automatically.\n */\n\nimport { useEffect, useState } from 'react'\nimport { useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { Brain, CheckCircle, Loader2, Play, RefreshCcw, Trash2, XCircle } from 'lucide-react'\n\nimport { EmptyState } from '@/components/common/empty-state'\nimport { ConfirmDialog } from '@/components/common/confirm-dialog'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Label } from '@/components/ui/label'\nimport {\n useMemoryPersona,\n useUpdatePersona,\n useDeletePersona,\n useConsolidateStatus,\n useTriggerConsolidate,\n} from '@/hooks/use-memory'\nimport { describeError } from '@/lib/api/errors'\nimport { cn } from '@/lib/utils'\nimport type { ConsolidateJob } from '@/types/api'\n\nexport default function MemoryPersonaRoute(): JSX.Element {\n const { t } = useTranslation(['memory', 'common'])\n const [params] = useSearchParams()\n const userKey = params.get('user') ?? ''\n\n if (!userKey) {\n return (\n <div className=\"mx-auto max-w-3xl\">\n <EmptyState\n icon={<Brain />}\n title={t('noUserSelected.title')}\n description={t('noUserSelected.description')}\n />\n </div>\n )\n }\n\n return <PersonaEditor userKey={userKey} />\n}\n\ninterface PersonaEditorProps {\n userKey: string\n}\n\nfunction PersonaEditor({ userKey }: PersonaEditorProps): JSX.Element {\n const { t } = useTranslation(['memory', 'common'])\n const personaQuery = useMemoryPersona(userKey)\n const persona = personaQuery.data\n\n const consolidate = useTriggerConsolidate()\n const status = useConsolidateStatus()\n const latestJob = status.data?.jobs[0]\n\n const updatePersona = useUpdatePersona()\n const deletePersona = useDeletePersona()\n const [confirmDelete, setConfirmDelete] = useState(false)\n\n /** Editor state — initialised from the server summary; tracks\n * dirtiness via reference comparison after each save. */\n const [draft, setDraft] = useState(persona?.summary ?? '')\n useEffect(() => {\n setDraft(persona?.summary ?? '')\n }, [persona?.summary])\n const dirty = draft !== (persona?.summary ?? '')\n\n async function onSave(): Promise<void> {\n const trimmed = draft.trim()\n if (!trimmed) return\n try {\n await updatePersona.mutateAsync({ user_key: userKey, body: { summary: trimmed } })\n toast.success(t('persona.saved'))\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n }\n }\n\n async function onConfirmDelete(): Promise<void> {\n try {\n await deletePersona.mutateAsync(userKey)\n toast.success(t('common:actions.delete'))\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n throw err\n }\n }\n\n async function onTrigger(): Promise<void> {\n try {\n await consolidate.mutateAsync()\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n }\n }\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('persona.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => personaQuery.refetch()}\n disabled={personaQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {personaQuery.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('persona.subtitle')}</p>\n </header>\n\n {/* Consolidate strip */}\n <div className=\"rounded-md border border-border bg-surface p-3\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <span className=\"font-medium text-sm text-text\">{t('persona.consolidate.trigger')}</span>\n <ConsolidateBadge job={latestJob} />\n <Button\n variant=\"default\"\n size=\"sm\"\n onClick={() => void onTrigger()}\n disabled={consolidate.isPending || latestJob?.phase === 'running'}\n className=\"ml-auto\"\n >\n {consolidate.isPending\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <Play className=\"h-4 w-4\" />}\n {consolidate.isPending\n ? t('persona.consolidate.triggering')\n : t('persona.consolidate.trigger')}\n </Button>\n </div>\n {latestJob?.phase === 'done' && (latestJob.result.users != null || latestJob.result.updated != null) && (\n <p className=\"mt-2 text-xs text-text-dim\">\n {t('persona.consolidate.result', {\n users: latestJob.result.users ?? 0,\n updated: latestJob.result.updated ?? 0,\n })}\n </p>\n )}\n {latestJob?.phase === 'failed' && latestJob.result.error && (\n <p className=\"mt-2 text-xs text-danger\">{latestJob.result.error}</p>\n )}\n </div>\n\n {/* Editor */}\n {personaQuery.isLoading ? (\n <div className=\"h-48 w-full rounded-md bg-surface-2 animate-pulse\" />\n ) : !persona ? (\n <>\n <EmptyState\n icon={<Brain />}\n title={t('persona.empty.title')}\n description={t('persona.empty.description')}\n />\n {/* Even with no persona, the operator can still type one in\n and save — the upsert handler creates a new row. */}\n <PersonaTextarea\n draft={draft}\n onChange={setDraft}\n onSave={() => void onSave()}\n saving={updatePersona.isPending}\n dirty={dirty}\n canDelete={false}\n onDelete={() => setConfirmDelete(true)}\n />\n </>\n ) : (\n <>\n {persona.updated_at > 0 && (\n <div className=\"text-xs text-text-dim\">\n {t('persona.updated', { at: formatEpoch(persona.updated_at) })}\n </div>\n )}\n <PersonaTextarea\n draft={draft}\n onChange={setDraft}\n onSave={() => void onSave()}\n saving={updatePersona.isPending}\n dirty={dirty}\n canDelete\n onDelete={() => setConfirmDelete(true)}\n />\n </>\n )}\n\n <ConfirmDialog\n open={confirmDelete}\n onOpenChange={setConfirmDelete}\n title={t('persona.confirmDelete')}\n description={t('persona.confirmDeleteDesc')}\n intent=\"danger\"\n confirmLabel={t('persona.delete')}\n onConfirm={onConfirmDelete}\n />\n </div>\n )\n}\n\ninterface PersonaTextareaProps {\n draft: string\n onChange: (next: string) => void\n onSave: () => void\n saving: boolean\n dirty: boolean\n canDelete: boolean\n onDelete: () => void\n}\n\nfunction PersonaTextarea({\n draft, onChange, onSave, saving, dirty, canDelete, onDelete,\n}: PersonaTextareaProps): JSX.Element {\n const { t } = useTranslation('memory')\n return (\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"persona-editor\" className=\"text-sm text-text-dim\">\n {t('persona.editorLabel')}\n </Label>\n <textarea\n id=\"persona-editor\"\n value={draft}\n onChange={(e) => onChange(e.target.value)}\n rows={12}\n className={cn(\n 'w-full resize-y rounded-md border bg-bg px-3 py-2',\n 'font-mono text-sm leading-6',\n 'focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-1 focus:ring-offset-bg',\n dirty ? 'border-accent' : 'border-border',\n )}\n />\n <div className=\"flex flex-wrap items-center gap-2\">\n {canDelete && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={onDelete}\n >\n <Trash2 className=\"h-3 w-3\" />\n {t('persona.delete')}\n </Button>\n )}\n <Button\n type=\"button\"\n size=\"sm\"\n className=\"ml-auto\"\n disabled={!dirty || saving || draft.trim().length === 0}\n onClick={onSave}\n >\n {saving ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : null}\n {t('persona.save')}\n </Button>\n </div>\n </div>\n )\n}\n\ninterface ConsolidateBadgeProps {\n job: ConsolidateJob | undefined\n}\n\nfunction ConsolidateBadge({ job }: ConsolidateBadgeProps): JSX.Element | null {\n const { t } = useTranslation('memory')\n if (!job) return null\n if (job.phase === 'running') {\n return (\n <Badge variant=\"info\">\n <Loader2 className=\"h-3 w-3 animate-spin\" />\n {t('persona.consolidate.running')}\n </Badge>\n )\n }\n if (job.phase === 'done') {\n return (\n <Badge variant=\"success\">\n <CheckCircle className=\"h-3 w-3\" />\n {t('persona.consolidate.lastRun', { at: formatEpoch(job.finishedAt ?? job.startedAt) })}\n </Badge>\n )\n }\n return (\n <Badge variant=\"danger\">\n <XCircle className=\"h-3 w-3\" />\n {t('persona.consolidate.doneFailed')}\n </Badge>\n )\n}\n\nfunction formatEpoch(ms: number): string {\n try {\n const d = new Date(ms)\n if (Number.isNaN(d.getTime())) return String(ms)\n return d.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })\n } catch {\n return String(ms)\n }\n}\n"],"names":["MemoryPersonaRoute","useTranslation","params","useSearchParams","userKey","jsx","PersonaEditor","EmptyState","Brain","t","personaQuery","useMemoryPersona","persona","consolidate","useTriggerConsolidate","latestJob","useConsolidateStatus","updatePersona","useUpdatePersona","deletePersona","useDeletePersona","confirmDelete","setConfirmDelete","useState","draft","setDraft","useEffect","dirty","onSave","trimmed","toast","err","message","describeError","onConfirmDelete","onTrigger","jsxs","Button","Loader2","RefreshCcw","ConsolidateBadge","Play","Fragment","formatEpoch","PersonaTextarea","ConfirmDialog","onChange","saving","canDelete","onDelete","Label","e","cn","Trash2","job","Badge","CheckCircle","XCircle","ms","d"],"mappings":"yrBAyCA,SAAwBA,IAAkC,CACxD,KAAM,CAAE,CAAA,EAAMC,EAAe,CAAC,SAAU,QAAQ,CAAC,EAC3C,CAACC,CAAM,EAAIC,EAAA,EACXC,EAAUF,EAAO,IAAI,MAAM,GAAK,GAEtC,OAAKE,EAYEC,MAACC,GAAc,QAAAF,EAAkB,EAVpCC,EAAAA,IAAC,MAAA,CAAI,UAAU,oBACb,SAAAA,EAAAA,IAACE,EAAA,CACC,WAAOC,EAAA,EAAM,EACb,MAAO,EAAE,sBAAsB,EAC/B,YAAa,EAAE,4BAA4B,CAAA,CAAA,EAE/C,CAKN,CAMA,SAASF,EAAc,CAAE,QAAAF,GAA4C,CACnE,KAAM,CAAE,EAAAK,CAAA,EAAMR,EAAe,CAAC,SAAU,QAAQ,CAAC,EAC3CS,EAAeC,EAAiBP,CAAO,EACvCQ,EAAUF,EAAa,KAEvBG,EAAcC,EAAA,EAEdC,EADSC,EAAA,EACU,MAAM,KAAK,CAAC,EAE/BC,EAAgBC,EAAA,EAChBC,EAAgBC,EAAA,EAChB,CAACC,EAAeC,CAAgB,EAAIC,EAAAA,SAAS,EAAK,EAIlD,CAACC,EAAOC,CAAQ,EAAIF,EAAAA,SAASX,GAAS,SAAW,EAAE,EACzDc,EAAAA,UAAU,IAAM,CACdD,EAASb,GAAS,SAAW,EAAE,CACjC,EAAG,CAACA,GAAS,OAAO,CAAC,EACrB,MAAMe,EAAQH,KAAWZ,GAAS,SAAW,IAE7C,eAAegB,GAAwB,CACrC,MAAMC,EAAUL,EAAM,KAAA,EACtB,GAAKK,EACL,GAAI,CACF,MAAMZ,EAAc,YAAY,CAAE,SAAUb,EAAS,KAAM,CAAE,QAASyB,CAAA,EAAW,EACjFC,EAAM,QAAQrB,EAAE,eAAe,CAAC,CAClC,OAASsB,EAAK,CACZ,KAAM,CAAE,QAAAC,CAAA,EAAYC,EAAcF,EAAKtB,CAAC,EACxCqB,EAAM,MAAME,CAAO,CACrB,CACF,CAEA,eAAeE,GAAiC,CAC9C,GAAI,CACF,MAAMf,EAAc,YAAYf,CAAO,EACvC0B,EAAM,QAAQrB,EAAE,uBAAuB,CAAC,CAC1C,OAASsB,EAAK,CACZ,KAAM,CAAE,QAAAC,CAAA,EAAYC,EAAcF,EAAKtB,CAAC,EACxCqB,MAAAA,EAAM,MAAME,CAAO,EACbD,CACR,CACF,CAEA,eAAeI,GAA2B,CACxC,GAAI,CACF,MAAMtB,EAAY,YAAA,CACpB,OAASkB,EAAK,CACZ,KAAM,CAAE,QAAAC,CAAA,EAAYC,EAAcF,EAAKtB,CAAC,EACxCqB,EAAM,MAAME,CAAO,CACrB,CACF,CAEA,OACEI,EAAAA,KAAC,MAAA,CAAI,UAAU,wCACb,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,sBAChB,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAA/B,MAAC,KAAA,CAAG,UAAU,wBAAyB,SAAAI,EAAE,eAAe,EAAE,EAC1D2B,EAAAA,KAACC,EAAA,CACC,QAAQ,QACR,KAAK,KACL,UAAU,UACV,QAAS,IAAM3B,EAAa,QAAA,EAC5B,SAAUA,EAAa,WACvB,aAAYD,EAAE,kBAAmB,CAAE,GAAI,SAAU,EAEhD,SAAA,CAAAC,EAAa,iBAAc4B,EAAA,CAAQ,UAAU,uBAAuB,EAAKjC,EAAAA,IAACkC,EAAA,CAAW,UAAU,SAAA,CAAU,EAC1GlC,EAAAA,IAAC,OAAA,CAAK,UAAU,mBAAoB,SAAAI,EAAE,kBAAmB,CAAE,GAAI,QAAA,CAAU,CAAA,CAAE,CAAA,CAAA,CAAA,CAC7E,EACF,QACC,IAAA,CAAE,UAAU,wBAAyB,SAAAA,EAAE,kBAAkB,CAAA,CAAE,CAAA,EAC9D,EAGA2B,EAAAA,KAAC,MAAA,CAAI,UAAU,iDACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAA/B,MAAC,OAAA,CAAK,UAAU,gCAAiC,SAAAI,EAAE,6BAA6B,EAAE,EAClFJ,EAAAA,IAACmC,EAAA,CAAiB,IAAKzB,CAAA,CAAW,EAClCqB,EAAAA,KAACC,EAAA,CACC,QAAQ,UACR,KAAK,KACL,QAAS,IAAM,KAAKF,EAAA,EACpB,SAAUtB,EAAY,WAAaE,GAAW,QAAU,UACxD,UAAU,UAET,SAAA,CAAAF,EAAY,gBACRyB,EAAA,CAAQ,UAAU,uBAAuB,EAC1CjC,EAAAA,IAACoC,EAAA,CAAK,UAAU,SAAA,CAAU,EAC7B5B,EAAY,UACTJ,EAAE,gCAAgC,EAClCA,EAAE,6BAA6B,CAAA,CAAA,CAAA,CACrC,EACF,EACCM,GAAW,QAAU,SAAWA,EAAU,OAAO,OAAS,MAAQA,EAAU,OAAO,SAAW,OAC7FV,EAAAA,IAAC,IAAA,CAAE,UAAU,6BACV,WAAE,6BAA8B,CAC/B,MAASU,EAAU,OAAO,OAAS,EACnC,QAASA,EAAU,OAAO,SAAW,CAAA,CACtC,EACH,EAEDA,GAAW,QAAU,UAAYA,EAAU,OAAO,OACjDV,EAAAA,IAAC,IAAA,CAAE,UAAU,2BAA4B,SAAAU,EAAU,OAAO,KAAA,CAAM,CAAA,EAEpE,EAGCL,EAAa,UACZL,EAAAA,IAAC,MAAA,CAAI,UAAU,oDAAoD,EAChEO,EAoBHwB,EAAAA,KAAAM,EAAAA,SAAA,CACG,SAAA,CAAA9B,EAAQ,WAAa,GACpBP,EAAAA,IAAC,MAAA,CAAI,UAAU,wBACZ,SAAAI,EAAE,kBAAmB,CAAE,GAAIkC,EAAY/B,EAAQ,UAAU,CAAA,CAAG,EAC/D,EAEFP,EAAAA,IAACuC,EAAA,CACC,MAAApB,EACA,SAAUC,EACV,OAAQ,IAAM,KAAKG,EAAA,EACnB,OAAQX,EAAc,UACtB,MAAAU,EACA,UAAS,GACT,SAAU,IAAML,EAAiB,EAAI,CAAA,CAAA,CACvC,EACF,EAlCAc,EAAAA,KAAAM,EAAAA,SAAA,CACE,SAAA,CAAArC,EAAAA,IAACE,EAAA,CACC,WAAOC,EAAA,EAAM,EACb,MAAOC,EAAE,qBAAqB,EAC9B,YAAaA,EAAE,2BAA2B,CAAA,CAAA,EAI5CJ,EAAAA,IAACuC,EAAA,CACC,MAAApB,EACA,SAAUC,EACV,OAAQ,IAAM,KAAKG,EAAA,EACnB,OAAQX,EAAc,UACtB,MAAAU,EACA,UAAW,GACX,SAAU,IAAML,EAAiB,EAAI,CAAA,CAAA,CACvC,CAAA,CACF,EAoBFjB,EAAAA,IAACwC,EAAA,CACC,KAAMxB,EACN,aAAcC,EACd,MAAOb,EAAE,uBAAuB,EAChC,YAAaA,EAAE,2BAA2B,EAC1C,OAAO,SACP,aAAcA,EAAE,gBAAgB,EAChC,UAAWyB,CAAA,CAAA,CACb,EACF,CAEJ,CAYA,SAASU,EAAgB,CACvB,MAAApB,EAAO,SAAAsB,EAAU,OAAAlB,EAAQ,OAAAmB,EAAQ,MAAApB,EAAO,UAAAqB,EAAW,SAAAC,CACrD,EAAsC,CACpC,KAAM,CAAE,EAAAxC,CAAA,EAAMR,EAAe,QAAQ,EACrC,OACEmC,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACb,SAAA,CAAA/B,EAAAA,IAAC6C,GAAM,QAAQ,iBAAiB,UAAU,wBACvC,SAAAzC,EAAE,qBAAqB,EAC1B,EACAJ,EAAAA,IAAC,WAAA,CACC,GAAG,iBACH,MAAOmB,EACP,SAAW2B,GAAML,EAASK,EAAE,OAAO,KAAK,EACxC,KAAM,GACN,UAAWC,EACT,oDACA,8BACA,6FACAzB,EAAQ,gBAAkB,eAAA,CAC5B,CAAA,EAEFS,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACZ,SAAA,CAAAY,GACCZ,EAAAA,KAACC,EAAA,CACC,KAAK,SACL,QAAQ,UACR,KAAK,KACL,QAASY,EAET,SAAA,CAAA5C,EAAAA,IAACgD,EAAA,CAAO,UAAU,SAAA,CAAU,EAC3B5C,EAAE,gBAAgB,CAAA,CAAA,CAAA,EAGvB2B,EAAAA,KAACC,EAAA,CACC,KAAK,SACL,KAAK,KACL,UAAU,UACV,SAAU,CAACV,GAASoB,GAAUvB,EAAM,KAAA,EAAO,SAAW,EACtD,QAASI,EAER,SAAA,CAAAmB,EAAS1C,EAAAA,IAACiC,EAAA,CAAQ,UAAU,sBAAA,CAAuB,EAAK,KACxD7B,EAAE,cAAc,CAAA,CAAA,CAAA,CACnB,CAAA,CACF,CAAA,EACF,CAEJ,CAMA,SAAS+B,EAAiB,CAAE,IAAAc,GAAkD,CAC5E,KAAM,CAAE,EAAA7C,CAAA,EAAMR,EAAe,QAAQ,EACrC,OAAKqD,EACDA,EAAI,QAAU,UAEdlB,EAAAA,KAACmB,EAAA,CAAM,QAAQ,OACb,SAAA,CAAAlD,EAAAA,IAACiC,EAAA,CAAQ,UAAU,sBAAA,CAAuB,EACzC7B,EAAE,6BAA6B,CAAA,EAClC,EAGA6C,EAAI,QAAU,OAEdlB,EAAAA,KAACmB,EAAA,CAAM,QAAQ,UACb,SAAA,CAAAlD,EAAAA,IAACmD,EAAA,CAAY,UAAU,SAAA,CAAU,EAChC/C,EAAE,8BAA+B,CAAE,GAAIkC,EAAYW,EAAI,YAAcA,EAAI,SAAS,CAAA,CAAG,CAAA,EACxF,EAIFlB,EAAAA,KAACmB,EAAA,CAAM,QAAQ,SACb,SAAA,CAAAlD,EAAAA,IAACoD,EAAA,CAAQ,UAAU,SAAA,CAAU,EAC5BhD,EAAE,gCAAgC,CAAA,EACrC,EArBe,IAuBnB,CAEA,SAASkC,EAAYe,EAAoB,CACvC,GAAI,CACF,MAAMC,EAAI,IAAI,KAAKD,CAAE,EACrB,OAAI,OAAO,MAAMC,EAAE,QAAA,CAAS,EAAU,OAAOD,CAAE,EACxCC,EAAE,eAAe,OAAW,CAAE,MAAO,QAAS,IAAK,UAAW,KAAM,UAAW,OAAQ,SAAA,CAAW,CAC3G,MAAQ,CACN,OAAO,OAAOD,CAAE,CAClB,CACF"}
@@ -1,7 +1,7 @@
1
- import{n as o}from"./index-DXI13nSQ.js";/**
1
+ import{n as o}from"./index-CuNnG-5O.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 e=o("Play",[["polygon",{points:"6 3 20 12 6 21 6 3",key:"1oa8hb"}]]);export{e as P};
7
- //# sourceMappingURL=play-COQw7BqX.js.map
7
+ //# sourceMappingURL=play-BedplEoY.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"play-COQw7BqX.js","sources":["../../node_modules/lucide-react/dist/esm/icons/play.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 Play = createLucideIcon(\"Play\", [\n [\"polygon\", { points: \"6 3 20 12 6 21 6 3\", key: \"1oa8hb\" }]\n]);\n\nexport { Play as default };\n//# sourceMappingURL=play.js.map\n"],"names":["Play","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAAOC,EAAiB,OAAQ,CACpC,CAAC,UAAW,CAAE,OAAQ,qBAAsB,IAAK,QAAQ,CAAE,CAC7D,CAAC","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"play-BedplEoY.js","sources":["../../node_modules/lucide-react/dist/esm/icons/play.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 Play = createLucideIcon(\"Play\", [\n [\"polygon\", { points: \"6 3 20 12 6 21 6 3\", key: \"1oa8hb\" }]\n]);\n\nexport { Play as default };\n//# sourceMappingURL=play.js.map\n"],"names":["Play","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAAOC,EAAiB,OAAQ,CACpC,CAAC,UAAW,CAAE,OAAQ,qBAAsB,IAAK,QAAQ,CAAE,CAC7D,CAAC","x_google_ignoreList":[0]}
@@ -1,7 +1,7 @@
1
- import{n as e}from"./index-DXI13nSQ.js";/**
1
+ import{n as e}from"./index-CuNnG-5O.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 a=e("Plus",[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"M12 5v14",key:"s699le"}]]);export{a as P};
7
- //# sourceMappingURL=plus-CdOyGoU1.js.map
7
+ //# sourceMappingURL=plus-4GdEpvTV.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"plus-CdOyGoU1.js","sources":["../../node_modules/lucide-react/dist/esm/icons/plus.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 Plus = createLucideIcon(\"Plus\", [\n [\"path\", { d: \"M5 12h14\", key: \"1ays0h\" }],\n [\"path\", { d: \"M12 5v14\", key: \"s699le\" }]\n]);\n\nexport { Plus as default };\n//# sourceMappingURL=plus.js.map\n"],"names":["Plus","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAAOC,EAAiB,OAAQ,CACpC,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,EACzC,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,CAC3C,CAAC","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"plus-4GdEpvTV.js","sources":["../../node_modules/lucide-react/dist/esm/icons/plus.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 Plus = createLucideIcon(\"Plus\", [\n [\"path\", { d: \"M5 12h14\", key: \"1ays0h\" }],\n [\"path\", { d: \"M12 5v14\", key: \"s699le\" }]\n]);\n\nexport { Plus as default };\n//# sourceMappingURL=plus.js.map\n"],"names":["Plus","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAAOC,EAAiB,OAAQ,CACpC,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,EACzC,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,CAC3C,CAAC","x_google_ignoreList":[0]}
@@ -1,2 +1,2 @@
1
- import{u as r,j as e,B as d,l as m,m as E,k as u,p as w,c as x,S as _,f as I,g as M,h as A,i as c}from"./index-DXI13nSQ.js";import{u as C,a as B}from"./use-settings-DJlVLnjo.js";import{L as S}from"./loader-circle-BS5FFFg-.js";import{R as U}from"./refresh-ccw-BPKXoMZa.js";import"./react-Cb2sDjhD.js";import"./useQuery-CEwGD94N.js";function o(s){if(s==null)return!1;const a=s.toLowerCase();return a==="1"||a==="true"||a==="yes"||a==="on"}function K(){const{t:s}=r(["settings","common"]),a=C(),i=B();async function t(n,v){try{await i.mutateAsync({updates:{[n]:v}}),m.success(s("policy.savingToast"))}catch(y){m.error(E(y,s).message)}}const l=a.data?.env??{},h=o(l.IMHUB_DANGEROUSLY_SKIP_PERMISSIONS),g=o(l.IMHUB_MEMORY_ENABLED),j=o(l.IMHUB_VIEWER_ENABLED),N=(l.IMHUB_TIMEOUT_DEFAULT??"").toLowerCase()==="allow",b=(l.IMHUB_A2A_NOTIFY_MODE??"essential").toLowerCase();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("policy.title")}),e.jsxs(d,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>a.refetch(),disabled:a.isFetching,"aria-label":s("actions.refresh",{ns:"common"}),children:[a.isFetching?e.jsx(S,{className:"h-4 w-4 animate-spin"}):e.jsx(U,{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("policy.subtitle")})]}),a.isLoading?e.jsx("div",{className:"h-96 rounded-md bg-surface-2 animate-pulse"}):e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsx(O,{value:h,disabled:i.isPending,onChange:n=>void t("IMHUB_DANGEROUSLY_SKIP_PERMISSIONS",n?"1":"0")}),e.jsx(L,{allowOnTimeout:N,disabled:i.isPending,onChange:n=>void t("IMHUB_TIMEOUT_DEFAULT",n)}),e.jsx(p,{sectionKey:"memory",value:g,disabled:i.isPending,onChange:n=>void t("IMHUB_MEMORY_ENABLED",n?"1":"0")}),e.jsx(p,{sectionKey:"viewer",value:j,disabled:i.isPending,onChange:n=>void t("IMHUB_VIEWER_ENABLED",n?"1":"0")}),e.jsx(T,{value:b,disabled:i.isPending,onChange:n=>void t("IMHUB_A2A_NOTIFY_MODE",n)})]})]})}function O({value:s,disabled:a,onChange:i}){const{t}=r("settings");return e.jsx("section",{className:x("rounded-md border p-4",s?"border-danger/60 bg-danger-bg/30":"border-border bg-surface"),children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("span",{className:"font-medium text-text",children:t("policy.safety.title")}),s&&e.jsxs(u,{variant:"danger",children:[e.jsx(w,{className:"h-3 w-3"}),"ON"]})]}),e.jsx("p",{className:"mt-1 text-sm text-text-dim",children:t("policy.safety.description")}),!s&&e.jsx("p",{className:"mt-1 text-xs text-text-muted",children:t("policy.safety.tagWarn")}),e.jsx("code",{className:"mt-2 inline-block rounded bg-surface-2 px-1.5 py-0.5 text-xs text-text-muted",children:t("policy.safety.envKey")})]}),e.jsx(f,{value:s,disabled:a,onChange:i})]})})}function L({allowOnTimeout:s,disabled:a,onChange:i}){const{t}=r("settings");return e.jsx("section",{className:"rounded-md border border-border bg-surface p-4",children:e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx("span",{className:"font-medium text-text",children:t("policy.approval.title")}),e.jsx("p",{className:"text-sm text-text-dim",children:t("policy.approval.description")}),e.jsx("code",{className:"self-start rounded bg-surface-2 px-1.5 py-0.5 text-xs text-text-muted",children:t("policy.approval.envKey")}),e.jsxs("div",{className:"mt-2 flex flex-wrap gap-2",children:[e.jsx(d,{type:"button",variant:s?"outline":"default",size:"sm",disabled:a,onClick:()=>i("deny"),children:t("policy.approval.valDeny")}),e.jsx(d,{type:"button",variant:s?"default":"outline",size:"sm",disabled:a,onClick:()=>i("allow"),children:t("policy.approval.valAllow")})]})]})})}function p({sectionKey:s,value:a,disabled:i,onChange:t}){const{t:l}=r("settings");return e.jsx("section",{className:"rounded-md border border-border bg-surface p-4",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("span",{className:"font-medium text-text",children:l(`policy.${s}.title`)}),e.jsx(u,{variant:a?"success":"outline",children:a?"ON":"OFF"})]}),e.jsx("p",{className:"mt-1 text-sm text-text-dim",children:l(`policy.${s}.description`)}),e.jsx("code",{className:"mt-2 inline-block rounded bg-surface-2 px-1.5 py-0.5 text-xs text-text-muted",children:l(`policy.${s}.envKey`)})]}),e.jsx(f,{value:a,disabled:i,onChange:t})]})})}function T({value:s,disabled:a,onChange:i}){const{t}=r("settings");return e.jsx("section",{className:"rounded-md border border-border bg-surface p-4",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsxs("div",{className:"flex-1",children:[e.jsx("span",{className:"font-medium text-text",children:t("policy.a2aNotify.title")}),e.jsx("p",{className:"mt-1 text-sm text-text-dim",children:t("policy.a2aNotify.description")}),e.jsx("code",{className:"mt-2 inline-block rounded bg-surface-2 px-1.5 py-0.5 text-xs text-text-muted",children:t("policy.a2aNotify.envKey")})]}),e.jsxs(_,{value:s,onValueChange:i,disabled:a,children:[e.jsx(I,{className:"w-36",children:e.jsx(M,{})}),e.jsxs(A,{children:[e.jsx(c,{value:"essential",children:t("policy.a2aNotify.valEssential")}),e.jsx(c,{value:"verbose",children:t("policy.a2aNotify.valVerbose")}),e.jsx(c,{value:"off",children:t("policy.a2aNotify.valOff")})]})]})]})})}function f({value:s,disabled:a,onChange:i}){return e.jsx("button",{type:"button",role:"switch","aria-checked":s,disabled:a,onClick:()=>i(!s),className:x("relative inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full transition-colors","focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-bg","disabled:cursor-not-allowed disabled:opacity-50",s?"bg-accent":"bg-surface-2 border border-border"),children:e.jsx("span",{className:x("inline-block h-5 w-5 rounded-full bg-white shadow transition-transform",s?"translate-x-5":"translate-x-0.5")})})}export{K as default};
2
- //# sourceMappingURL=policy-docXezae.js.map
1
+ import{u as r,j as e,B as d,l as m,m as E,k as u,p as w,c as x,S as _,f as I,g as M,h as A,i as c}from"./index-CuNnG-5O.js";import{u as C,a as B}from"./use-settings-D3vI1Dwg.js";import{L as S}from"./loader-circle-CVEo3Hwx.js";import{R as U}from"./refresh-ccw-DZHRYuFA.js";import"./react-Cb2sDjhD.js";import"./useQuery-DIlm0vJ-.js";function o(s){if(s==null)return!1;const a=s.toLowerCase();return a==="1"||a==="true"||a==="yes"||a==="on"}function K(){const{t:s}=r(["settings","common"]),a=C(),i=B();async function t(n,v){try{await i.mutateAsync({updates:{[n]:v}}),m.success(s("policy.savingToast"))}catch(y){m.error(E(y,s).message)}}const l=a.data?.env??{},h=o(l.IMHUB_DANGEROUSLY_SKIP_PERMISSIONS),g=o(l.IMHUB_MEMORY_ENABLED),j=o(l.IMHUB_VIEWER_ENABLED),N=(l.IMHUB_TIMEOUT_DEFAULT??"").toLowerCase()==="allow",b=(l.IMHUB_A2A_NOTIFY_MODE??"essential").toLowerCase();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("policy.title")}),e.jsxs(d,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>a.refetch(),disabled:a.isFetching,"aria-label":s("actions.refresh",{ns:"common"}),children:[a.isFetching?e.jsx(S,{className:"h-4 w-4 animate-spin"}):e.jsx(U,{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("policy.subtitle")})]}),a.isLoading?e.jsx("div",{className:"h-96 rounded-md bg-surface-2 animate-pulse"}):e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsx(O,{value:h,disabled:i.isPending,onChange:n=>void t("IMHUB_DANGEROUSLY_SKIP_PERMISSIONS",n?"1":"0")}),e.jsx(L,{allowOnTimeout:N,disabled:i.isPending,onChange:n=>void t("IMHUB_TIMEOUT_DEFAULT",n)}),e.jsx(p,{sectionKey:"memory",value:g,disabled:i.isPending,onChange:n=>void t("IMHUB_MEMORY_ENABLED",n?"1":"0")}),e.jsx(p,{sectionKey:"viewer",value:j,disabled:i.isPending,onChange:n=>void t("IMHUB_VIEWER_ENABLED",n?"1":"0")}),e.jsx(T,{value:b,disabled:i.isPending,onChange:n=>void t("IMHUB_A2A_NOTIFY_MODE",n)})]})]})}function O({value:s,disabled:a,onChange:i}){const{t}=r("settings");return e.jsx("section",{className:x("rounded-md border p-4",s?"border-danger/60 bg-danger-bg/30":"border-border bg-surface"),children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("span",{className:"font-medium text-text",children:t("policy.safety.title")}),s&&e.jsxs(u,{variant:"danger",children:[e.jsx(w,{className:"h-3 w-3"}),"ON"]})]}),e.jsx("p",{className:"mt-1 text-sm text-text-dim",children:t("policy.safety.description")}),!s&&e.jsx("p",{className:"mt-1 text-xs text-text-muted",children:t("policy.safety.tagWarn")}),e.jsx("code",{className:"mt-2 inline-block rounded bg-surface-2 px-1.5 py-0.5 text-xs text-text-muted",children:t("policy.safety.envKey")})]}),e.jsx(f,{value:s,disabled:a,onChange:i})]})})}function L({allowOnTimeout:s,disabled:a,onChange:i}){const{t}=r("settings");return e.jsx("section",{className:"rounded-md border border-border bg-surface p-4",children:e.jsxs("div",{className:"flex flex-col gap-2",children:[e.jsx("span",{className:"font-medium text-text",children:t("policy.approval.title")}),e.jsx("p",{className:"text-sm text-text-dim",children:t("policy.approval.description")}),e.jsx("code",{className:"self-start rounded bg-surface-2 px-1.5 py-0.5 text-xs text-text-muted",children:t("policy.approval.envKey")}),e.jsxs("div",{className:"mt-2 flex flex-wrap gap-2",children:[e.jsx(d,{type:"button",variant:s?"outline":"default",size:"sm",disabled:a,onClick:()=>i("deny"),children:t("policy.approval.valDeny")}),e.jsx(d,{type:"button",variant:s?"default":"outline",size:"sm",disabled:a,onClick:()=>i("allow"),children:t("policy.approval.valAllow")})]})]})})}function p({sectionKey:s,value:a,disabled:i,onChange:t}){const{t:l}=r("settings");return e.jsx("section",{className:"rounded-md border border-border bg-surface p-4",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("span",{className:"font-medium text-text",children:l(`policy.${s}.title`)}),e.jsx(u,{variant:a?"success":"outline",children:a?"ON":"OFF"})]}),e.jsx("p",{className:"mt-1 text-sm text-text-dim",children:l(`policy.${s}.description`)}),e.jsx("code",{className:"mt-2 inline-block rounded bg-surface-2 px-1.5 py-0.5 text-xs text-text-muted",children:l(`policy.${s}.envKey`)})]}),e.jsx(f,{value:a,disabled:i,onChange:t})]})})}function T({value:s,disabled:a,onChange:i}){const{t}=r("settings");return e.jsx("section",{className:"rounded-md border border-border bg-surface p-4",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsxs("div",{className:"flex-1",children:[e.jsx("span",{className:"font-medium text-text",children:t("policy.a2aNotify.title")}),e.jsx("p",{className:"mt-1 text-sm text-text-dim",children:t("policy.a2aNotify.description")}),e.jsx("code",{className:"mt-2 inline-block rounded bg-surface-2 px-1.5 py-0.5 text-xs text-text-muted",children:t("policy.a2aNotify.envKey")})]}),e.jsxs(_,{value:s,onValueChange:i,disabled:a,children:[e.jsx(I,{className:"w-36",children:e.jsx(M,{})}),e.jsxs(A,{children:[e.jsx(c,{value:"essential",children:t("policy.a2aNotify.valEssential")}),e.jsx(c,{value:"verbose",children:t("policy.a2aNotify.valVerbose")}),e.jsx(c,{value:"off",children:t("policy.a2aNotify.valOff")})]})]})]})})}function f({value:s,disabled:a,onChange:i}){return e.jsx("button",{type:"button",role:"switch","aria-checked":s,disabled:a,onClick:()=>i(!s),className:x("relative inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full transition-colors","focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-bg","disabled:cursor-not-allowed disabled:opacity-50",s?"bg-accent":"bg-surface-2 border border-border"),children:e.jsx("span",{className:x("inline-block h-5 w-5 rounded-full bg-white shadow transition-transform",s?"translate-x-5":"translate-x-0.5")})})}export{K as default};
2
+ //# sourceMappingURL=policy-Gmd4rmzp.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"policy-docXezae.js","sources":["../../src/routes/settings/policy.tsx"],"sourcesContent":["/**\n * /settings/policy — dedicated UI for the highest-frequency env\n * toggles. Each is a one-click switch (or 2-3 option select) that\n * persists to `~/.agim/.env` via PUT /api/env immediately.\n *\n * Surfaced here:\n * * IMHUB_DANGEROUSLY_SKIP_PERMISSIONS (safety)\n * * IMHUB_TIMEOUT_DEFAULT (approval bus default)\n * * IMHUB_MEMORY_ENABLED (memory subsystem)\n * * IMHUB_VIEWER_ENABLED (long-message viewer)\n * * IMHUB_A2A_NOTIFY_MODE (cross-agent notify verbosity)\n *\n * All five are still editable in /settings/env. This page exists\n * because:\n * 1. They're the ones operators flip most often\n * 2. The env editor's table doesn't communicate \"this is a\n * boolean / 2-state / 3-state value\" — operators have to\n * know the literal strings \"1\"/\"0\"/\"allow\"/\"deny\"/etc.\n * 3. Safety toggle deserves a visible warning + danger color\n */\n\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { AlertTriangle, Loader2, RefreshCcw } from 'lucide-react'\n\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport { useEnv, useUpdateEnv } from '@/hooks/use-settings'\nimport { describeError } from '@/lib/api/errors'\nimport { cn } from '@/lib/utils'\n\n/** Treat the env value as a boolean — '1' / 'true' / 'yes' / 'on'\n * → true; everything else → false. Matches the backend's casual\n * truthy parsing in core/* modules. */\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 SettingsPolicyRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const envQuery = useEnv()\n const updateEnv = useUpdateEnv()\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('policy.savingToast'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n const env = envQuery.data?.env ?? {}\n const skipPerms = envBool(env.IMHUB_DANGEROUSLY_SKIP_PERMISSIONS)\n const memEnabled = envBool(env.IMHUB_MEMORY_ENABLED)\n const viewerEnabled = envBool(env.IMHUB_VIEWER_ENABLED)\n const timeoutAllow = (env.IMHUB_TIMEOUT_DEFAULT ?? '').toLowerCase() === 'allow'\n const a2aMode = (env.IMHUB_A2A_NOTIFY_MODE ?? 'essential').toLowerCase()\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('policy.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => envQuery.refetch()}\n disabled={envQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {envQuery.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('policy.subtitle')}</p>\n </header>\n\n {envQuery.isLoading ? (\n <div className=\"h-96 rounded-md bg-surface-2 animate-pulse\" />\n ) : (\n <div className=\"flex flex-col gap-3\">\n <SafetyCard\n value={skipPerms}\n disabled={updateEnv.isPending}\n onChange={(v) => void setValue('IMHUB_DANGEROUSLY_SKIP_PERMISSIONS', v ? '1' : '0')}\n />\n <ApprovalCard\n allowOnTimeout={timeoutAllow}\n disabled={updateEnv.isPending}\n onChange={(v) => void setValue('IMHUB_TIMEOUT_DEFAULT', v)}\n />\n <ToggleCard\n sectionKey=\"memory\"\n value={memEnabled}\n disabled={updateEnv.isPending}\n onChange={(v) => void setValue('IMHUB_MEMORY_ENABLED', v ? '1' : '0')}\n />\n <ToggleCard\n sectionKey=\"viewer\"\n value={viewerEnabled}\n disabled={updateEnv.isPending}\n onChange={(v) => void setValue('IMHUB_VIEWER_ENABLED', v ? '1' : '0')}\n />\n <A2ANotifyCard\n value={a2aMode}\n disabled={updateEnv.isPending}\n onChange={(v) => void setValue('IMHUB_A2A_NOTIFY_MODE', v)}\n />\n </div>\n )}\n </div>\n )\n}\n\n/* ─────────────── Cards ─────────────── */\n\ninterface SafetyCardProps {\n value: boolean\n disabled: boolean\n onChange: (v: boolean) => void\n}\n\nfunction SafetyCard({ value, disabled, onChange }: SafetyCardProps): JSX.Element {\n const { t } = useTranslation('settings')\n return (\n <section\n className={cn(\n 'rounded-md border p-4',\n value ? 'border-danger/60 bg-danger-bg/30' : 'border-border bg-surface',\n )}\n >\n <div className=\"flex items-start gap-3\">\n <div className=\"flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-medium text-text\">{t('policy.safety.title')}</span>\n {value && (\n <Badge variant=\"danger\">\n <AlertTriangle className=\"h-3 w-3\" />\n ON\n </Badge>\n )}\n </div>\n <p className=\"mt-1 text-sm text-text-dim\">{t('policy.safety.description')}</p>\n {!value && (\n <p className=\"mt-1 text-xs text-text-muted\">{t('policy.safety.tagWarn')}</p>\n )}\n <code className=\"mt-2 inline-block rounded bg-surface-2 px-1.5 py-0.5 text-xs text-text-muted\">\n {t('policy.safety.envKey')}\n </code>\n </div>\n <Toggle value={value} disabled={disabled} onChange={onChange} />\n </div>\n </section>\n )\n}\n\ninterface ApprovalCardProps {\n allowOnTimeout: boolean\n disabled: boolean\n onChange: (value: 'allow' | 'deny') => void\n}\n\nfunction ApprovalCard({ allowOnTimeout, disabled, onChange }: ApprovalCardProps): JSX.Element {\n const { t } = useTranslation('settings')\n return (\n <section className=\"rounded-md border border-border bg-surface p-4\">\n <div className=\"flex flex-col gap-2\">\n <span className=\"font-medium text-text\">{t('policy.approval.title')}</span>\n <p className=\"text-sm text-text-dim\">{t('policy.approval.description')}</p>\n <code className=\"self-start rounded bg-surface-2 px-1.5 py-0.5 text-xs text-text-muted\">\n {t('policy.approval.envKey')}\n </code>\n <div className=\"mt-2 flex flex-wrap gap-2\">\n <Button\n type=\"button\"\n variant={!allowOnTimeout ? 'default' : 'outline'}\n size=\"sm\"\n disabled={disabled}\n onClick={() => onChange('deny')}\n >\n {t('policy.approval.valDeny')}\n </Button>\n <Button\n type=\"button\"\n variant={allowOnTimeout ? 'default' : 'outline'}\n size=\"sm\"\n disabled={disabled}\n onClick={() => onChange('allow')}\n >\n {t('policy.approval.valAllow')}\n </Button>\n </div>\n </div>\n </section>\n )\n}\n\ninterface ToggleCardProps {\n sectionKey: 'memory' | 'viewer'\n value: boolean\n disabled: boolean\n onChange: (v: boolean) => void\n}\n\nfunction ToggleCard({ sectionKey, value, disabled, onChange }: ToggleCardProps): JSX.Element {\n const { t } = useTranslation('settings')\n return (\n <section className=\"rounded-md border border-border bg-surface p-4\">\n <div className=\"flex items-start gap-3\">\n <div className=\"flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-medium text-text\">{t(`policy.${sectionKey}.title`)}</span>\n <Badge variant={value ? 'success' : 'outline'}>{value ? 'ON' : 'OFF'}</Badge>\n </div>\n <p className=\"mt-1 text-sm text-text-dim\">{t(`policy.${sectionKey}.description`)}</p>\n <code className=\"mt-2 inline-block rounded bg-surface-2 px-1.5 py-0.5 text-xs text-text-muted\">\n {t(`policy.${sectionKey}.envKey`)}\n </code>\n </div>\n <Toggle value={value} disabled={disabled} onChange={onChange} />\n </div>\n </section>\n )\n}\n\ninterface A2ANotifyCardProps {\n value: string\n disabled: boolean\n onChange: (v: string) => void\n}\n\nfunction A2ANotifyCard({ value, disabled, onChange }: A2ANotifyCardProps): JSX.Element {\n const { t } = useTranslation('settings')\n return (\n <section className=\"rounded-md border border-border bg-surface p-4\">\n <div className=\"flex items-start gap-3\">\n <div className=\"flex-1\">\n <span className=\"font-medium text-text\">{t('policy.a2aNotify.title')}</span>\n <p className=\"mt-1 text-sm text-text-dim\">{t('policy.a2aNotify.description')}</p>\n <code className=\"mt-2 inline-block rounded bg-surface-2 px-1.5 py-0.5 text-xs text-text-muted\">\n {t('policy.a2aNotify.envKey')}\n </code>\n </div>\n <Select value={value} onValueChange={onChange} disabled={disabled}>\n <SelectTrigger className=\"w-36\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"essential\">{t('policy.a2aNotify.valEssential')}</SelectItem>\n <SelectItem value=\"verbose\">{t('policy.a2aNotify.valVerbose')}</SelectItem>\n <SelectItem value=\"off\">{t('policy.a2aNotify.valOff')}</SelectItem>\n </SelectContent>\n </Select>\n </div>\n </section>\n )\n}\n\ninterface ToggleProps {\n value: boolean\n disabled: boolean\n onChange: (v: boolean) => void\n}\n\n/** Thumb-style switch styled to the agim accent. Tailwind-only,\n * no Radix dep — keeps the click feel snappy. */\nfunction Toggle({ value, disabled, onChange }: ToggleProps): JSX.Element {\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={value}\n disabled={disabled}\n onClick={() => onChange(!value)}\n className={cn(\n 'relative inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full transition-colors',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-bg',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n value ? 'bg-accent' : 'bg-surface-2 border border-border',\n )}\n >\n <span\n className={cn(\n 'inline-block h-5 w-5 rounded-full bg-white shadow transition-transform',\n value ? 'translate-x-5' : 'translate-x-0.5',\n )}\n />\n </button>\n )\n}\n"],"names":["envBool","v","t","SettingsPolicyRoute","useTranslation","envQuery","useEnv","updateEnv","useUpdateEnv","setValue","key","value","toast","err","describeError","env","skipPerms","memEnabled","viewerEnabled","timeoutAllow","a2aMode","jsxs","jsx","Button","Loader2","RefreshCcw","SafetyCard","ApprovalCard","ToggleCard","A2ANotifyCard","disabled","onChange","cn","Badge","AlertTriangle","Toggle","allowOnTimeout","sectionKey","Select","SelectTrigger","SelectValue","SelectContent","SelectItem"],"mappings":"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"}
1
+ {"version":3,"file":"policy-Gmd4rmzp.js","sources":["../../src/routes/settings/policy.tsx"],"sourcesContent":["/**\n * /settings/policy — dedicated UI for the highest-frequency env\n * toggles. Each is a one-click switch (or 2-3 option select) that\n * persists to `~/.agim/.env` via PUT /api/env immediately.\n *\n * Surfaced here:\n * * IMHUB_DANGEROUSLY_SKIP_PERMISSIONS (safety)\n * * IMHUB_TIMEOUT_DEFAULT (approval bus default)\n * * IMHUB_MEMORY_ENABLED (memory subsystem)\n * * IMHUB_VIEWER_ENABLED (long-message viewer)\n * * IMHUB_A2A_NOTIFY_MODE (cross-agent notify verbosity)\n *\n * All five are still editable in /settings/env. This page exists\n * because:\n * 1. They're the ones operators flip most often\n * 2. The env editor's table doesn't communicate \"this is a\n * boolean / 2-state / 3-state value\" — operators have to\n * know the literal strings \"1\"/\"0\"/\"allow\"/\"deny\"/etc.\n * 3. Safety toggle deserves a visible warning + danger color\n */\n\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { AlertTriangle, Loader2, RefreshCcw } from 'lucide-react'\n\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport { useEnv, useUpdateEnv } from '@/hooks/use-settings'\nimport { describeError } from '@/lib/api/errors'\nimport { cn } from '@/lib/utils'\n\n/** Treat the env value as a boolean — '1' / 'true' / 'yes' / 'on'\n * → true; everything else → false. Matches the backend's casual\n * truthy parsing in core/* modules. */\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 SettingsPolicyRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const envQuery = useEnv()\n const updateEnv = useUpdateEnv()\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('policy.savingToast'))\n } catch (err) {\n toast.error(describeError(err, t).message)\n }\n }\n\n const env = envQuery.data?.env ?? {}\n const skipPerms = envBool(env.IMHUB_DANGEROUSLY_SKIP_PERMISSIONS)\n const memEnabled = envBool(env.IMHUB_MEMORY_ENABLED)\n const viewerEnabled = envBool(env.IMHUB_VIEWER_ENABLED)\n const timeoutAllow = (env.IMHUB_TIMEOUT_DEFAULT ?? '').toLowerCase() === 'allow'\n const a2aMode = (env.IMHUB_A2A_NOTIFY_MODE ?? 'essential').toLowerCase()\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('policy.title')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => envQuery.refetch()}\n disabled={envQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {envQuery.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('policy.subtitle')}</p>\n </header>\n\n {envQuery.isLoading ? (\n <div className=\"h-96 rounded-md bg-surface-2 animate-pulse\" />\n ) : (\n <div className=\"flex flex-col gap-3\">\n <SafetyCard\n value={skipPerms}\n disabled={updateEnv.isPending}\n onChange={(v) => void setValue('IMHUB_DANGEROUSLY_SKIP_PERMISSIONS', v ? '1' : '0')}\n />\n <ApprovalCard\n allowOnTimeout={timeoutAllow}\n disabled={updateEnv.isPending}\n onChange={(v) => void setValue('IMHUB_TIMEOUT_DEFAULT', v)}\n />\n <ToggleCard\n sectionKey=\"memory\"\n value={memEnabled}\n disabled={updateEnv.isPending}\n onChange={(v) => void setValue('IMHUB_MEMORY_ENABLED', v ? '1' : '0')}\n />\n <ToggleCard\n sectionKey=\"viewer\"\n value={viewerEnabled}\n disabled={updateEnv.isPending}\n onChange={(v) => void setValue('IMHUB_VIEWER_ENABLED', v ? '1' : '0')}\n />\n <A2ANotifyCard\n value={a2aMode}\n disabled={updateEnv.isPending}\n onChange={(v) => void setValue('IMHUB_A2A_NOTIFY_MODE', v)}\n />\n </div>\n )}\n </div>\n )\n}\n\n/* ─────────────── Cards ─────────────── */\n\ninterface SafetyCardProps {\n value: boolean\n disabled: boolean\n onChange: (v: boolean) => void\n}\n\nfunction SafetyCard({ value, disabled, onChange }: SafetyCardProps): JSX.Element {\n const { t } = useTranslation('settings')\n return (\n <section\n className={cn(\n 'rounded-md border p-4',\n value ? 'border-danger/60 bg-danger-bg/30' : 'border-border bg-surface',\n )}\n >\n <div className=\"flex items-start gap-3\">\n <div className=\"flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-medium text-text\">{t('policy.safety.title')}</span>\n {value && (\n <Badge variant=\"danger\">\n <AlertTriangle className=\"h-3 w-3\" />\n ON\n </Badge>\n )}\n </div>\n <p className=\"mt-1 text-sm text-text-dim\">{t('policy.safety.description')}</p>\n {!value && (\n <p className=\"mt-1 text-xs text-text-muted\">{t('policy.safety.tagWarn')}</p>\n )}\n <code className=\"mt-2 inline-block rounded bg-surface-2 px-1.5 py-0.5 text-xs text-text-muted\">\n {t('policy.safety.envKey')}\n </code>\n </div>\n <Toggle value={value} disabled={disabled} onChange={onChange} />\n </div>\n </section>\n )\n}\n\ninterface ApprovalCardProps {\n allowOnTimeout: boolean\n disabled: boolean\n onChange: (value: 'allow' | 'deny') => void\n}\n\nfunction ApprovalCard({ allowOnTimeout, disabled, onChange }: ApprovalCardProps): JSX.Element {\n const { t } = useTranslation('settings')\n return (\n <section className=\"rounded-md border border-border bg-surface p-4\">\n <div className=\"flex flex-col gap-2\">\n <span className=\"font-medium text-text\">{t('policy.approval.title')}</span>\n <p className=\"text-sm text-text-dim\">{t('policy.approval.description')}</p>\n <code className=\"self-start rounded bg-surface-2 px-1.5 py-0.5 text-xs text-text-muted\">\n {t('policy.approval.envKey')}\n </code>\n <div className=\"mt-2 flex flex-wrap gap-2\">\n <Button\n type=\"button\"\n variant={!allowOnTimeout ? 'default' : 'outline'}\n size=\"sm\"\n disabled={disabled}\n onClick={() => onChange('deny')}\n >\n {t('policy.approval.valDeny')}\n </Button>\n <Button\n type=\"button\"\n variant={allowOnTimeout ? 'default' : 'outline'}\n size=\"sm\"\n disabled={disabled}\n onClick={() => onChange('allow')}\n >\n {t('policy.approval.valAllow')}\n </Button>\n </div>\n </div>\n </section>\n )\n}\n\ninterface ToggleCardProps {\n sectionKey: 'memory' | 'viewer'\n value: boolean\n disabled: boolean\n onChange: (v: boolean) => void\n}\n\nfunction ToggleCard({ sectionKey, value, disabled, onChange }: ToggleCardProps): JSX.Element {\n const { t } = useTranslation('settings')\n return (\n <section className=\"rounded-md border border-border bg-surface p-4\">\n <div className=\"flex items-start gap-3\">\n <div className=\"flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-medium text-text\">{t(`policy.${sectionKey}.title`)}</span>\n <Badge variant={value ? 'success' : 'outline'}>{value ? 'ON' : 'OFF'}</Badge>\n </div>\n <p className=\"mt-1 text-sm text-text-dim\">{t(`policy.${sectionKey}.description`)}</p>\n <code className=\"mt-2 inline-block rounded bg-surface-2 px-1.5 py-0.5 text-xs text-text-muted\">\n {t(`policy.${sectionKey}.envKey`)}\n </code>\n </div>\n <Toggle value={value} disabled={disabled} onChange={onChange} />\n </div>\n </section>\n )\n}\n\ninterface A2ANotifyCardProps {\n value: string\n disabled: boolean\n onChange: (v: string) => void\n}\n\nfunction A2ANotifyCard({ value, disabled, onChange }: A2ANotifyCardProps): JSX.Element {\n const { t } = useTranslation('settings')\n return (\n <section className=\"rounded-md border border-border bg-surface p-4\">\n <div className=\"flex items-start gap-3\">\n <div className=\"flex-1\">\n <span className=\"font-medium text-text\">{t('policy.a2aNotify.title')}</span>\n <p className=\"mt-1 text-sm text-text-dim\">{t('policy.a2aNotify.description')}</p>\n <code className=\"mt-2 inline-block rounded bg-surface-2 px-1.5 py-0.5 text-xs text-text-muted\">\n {t('policy.a2aNotify.envKey')}\n </code>\n </div>\n <Select value={value} onValueChange={onChange} disabled={disabled}>\n <SelectTrigger className=\"w-36\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"essential\">{t('policy.a2aNotify.valEssential')}</SelectItem>\n <SelectItem value=\"verbose\">{t('policy.a2aNotify.valVerbose')}</SelectItem>\n <SelectItem value=\"off\">{t('policy.a2aNotify.valOff')}</SelectItem>\n </SelectContent>\n </Select>\n </div>\n </section>\n )\n}\n\ninterface ToggleProps {\n value: boolean\n disabled: boolean\n onChange: (v: boolean) => void\n}\n\n/** Thumb-style switch styled to the agim accent. Tailwind-only,\n * no Radix dep — keeps the click feel snappy. */\nfunction Toggle({ value, disabled, onChange }: ToggleProps): JSX.Element {\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={value}\n disabled={disabled}\n onClick={() => onChange(!value)}\n className={cn(\n 'relative inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full transition-colors',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-bg',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n value ? 'bg-accent' : 'bg-surface-2 border border-border',\n )}\n >\n <span\n className={cn(\n 'inline-block h-5 w-5 rounded-full bg-white shadow transition-transform',\n value ? 'translate-x-5' : 'translate-x-0.5',\n )}\n />\n </button>\n )\n}\n"],"names":["envBool","v","t","SettingsPolicyRoute","useTranslation","envQuery","useEnv","updateEnv","useUpdateEnv","setValue","key","value","toast","err","describeError","env","skipPerms","memEnabled","viewerEnabled","timeoutAllow","a2aMode","jsxs","jsx","Button","Loader2","RefreshCcw","SafetyCard","ApprovalCard","ToggleCard","A2ANotifyCard","disabled","onChange","cn","Badge","AlertTriangle","Toggle","allowOnTimeout","sectionKey","Select","SelectTrigger","SelectValue","SelectContent","SelectItem"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import{n as t}from"./index-DXI13nSQ.js";/**
1
+ import{n as t}from"./index-CuNnG-5O.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 h=t("QrCode",[["rect",{width:"5",height:"5",x:"3",y:"3",rx:"1",key:"1tu5fj"}],["rect",{width:"5",height:"5",x:"16",y:"3",rx:"1",key:"1v8r4q"}],["rect",{width:"5",height:"5",x:"3",y:"16",rx:"1",key:"1x03jg"}],["path",{d:"M21 16h-3a2 2 0 0 0-2 2v3",key:"177gqh"}],["path",{d:"M21 21v.01",key:"ents32"}],["path",{d:"M12 7v3a2 2 0 0 1-2 2H7",key:"8crl2c"}],["path",{d:"M3 12h.01",key:"nlz23k"}],["path",{d:"M12 3h.01",key:"n36tog"}],["path",{d:"M12 16v.01",key:"133mhm"}],["path",{d:"M16 12h1",key:"1slzba"}],["path",{d:"M21 12v.01",key:"1lwtk9"}],["path",{d:"M12 21v-1",key:"1880an"}]]);export{h as Q};
7
- //# sourceMappingURL=qr-code-8putJTrW.js.map
7
+ //# sourceMappingURL=qr-code-DVgHWDky.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"qr-code-8putJTrW.js","sources":["../../node_modules/lucide-react/dist/esm/icons/qr-code.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 QrCode = createLucideIcon(\"QrCode\", [\n [\"rect\", { width: \"5\", height: \"5\", x: \"3\", y: \"3\", rx: \"1\", key: \"1tu5fj\" }],\n [\"rect\", { width: \"5\", height: \"5\", x: \"16\", y: \"3\", rx: \"1\", key: \"1v8r4q\" }],\n [\"rect\", { width: \"5\", height: \"5\", x: \"3\", y: \"16\", rx: \"1\", key: \"1x03jg\" }],\n [\"path\", { d: \"M21 16h-3a2 2 0 0 0-2 2v3\", key: \"177gqh\" }],\n [\"path\", { d: \"M21 21v.01\", key: \"ents32\" }],\n [\"path\", { d: \"M12 7v3a2 2 0 0 1-2 2H7\", key: \"8crl2c\" }],\n [\"path\", { d: \"M3 12h.01\", key: \"nlz23k\" }],\n [\"path\", { d: \"M12 3h.01\", key: \"n36tog\" }],\n [\"path\", { d: \"M12 16v.01\", key: \"133mhm\" }],\n [\"path\", { d: \"M16 12h1\", key: \"1slzba\" }],\n [\"path\", { d: \"M21 12v.01\", key: \"1lwtk9\" }],\n [\"path\", { d: \"M12 21v-1\", key: \"1880an\" }]\n]);\n\nexport { QrCode as default };\n//# sourceMappingURL=qr-code.js.map\n"],"names":["QrCode","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAASC,EAAiB,SAAU,CACxC,CAAC,OAAQ,CAAE,MAAO,IAAK,OAAQ,IAAK,EAAG,IAAK,EAAG,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC5E,CAAC,OAAQ,CAAE,MAAO,IAAK,OAAQ,IAAK,EAAG,KAAM,EAAG,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC7E,CAAC,OAAQ,CAAE,MAAO,IAAK,OAAQ,IAAK,EAAG,IAAK,EAAG,KAAM,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC7E,CAAC,OAAQ,CAAE,EAAG,4BAA6B,IAAK,QAAQ,CAAE,EAC1D,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,EAC3C,CAAC,OAAQ,CAAE,EAAG,0BAA2B,IAAK,QAAQ,CAAE,EACxD,CAAC,OAAQ,CAAE,EAAG,YAAa,IAAK,QAAQ,CAAE,EAC1C,CAAC,OAAQ,CAAE,EAAG,YAAa,IAAK,QAAQ,CAAE,EAC1C,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,EAC3C,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,EACzC,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,EAC3C,CAAC,OAAQ,CAAE,EAAG,YAAa,IAAK,QAAQ,CAAE,CAC5C,CAAC","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"qr-code-DVgHWDky.js","sources":["../../node_modules/lucide-react/dist/esm/icons/qr-code.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 QrCode = createLucideIcon(\"QrCode\", [\n [\"rect\", { width: \"5\", height: \"5\", x: \"3\", y: \"3\", rx: \"1\", key: \"1tu5fj\" }],\n [\"rect\", { width: \"5\", height: \"5\", x: \"16\", y: \"3\", rx: \"1\", key: \"1v8r4q\" }],\n [\"rect\", { width: \"5\", height: \"5\", x: \"3\", y: \"16\", rx: \"1\", key: \"1x03jg\" }],\n [\"path\", { d: \"M21 16h-3a2 2 0 0 0-2 2v3\", key: \"177gqh\" }],\n [\"path\", { d: \"M21 21v.01\", key: \"ents32\" }],\n [\"path\", { d: \"M12 7v3a2 2 0 0 1-2 2H7\", key: \"8crl2c\" }],\n [\"path\", { d: \"M3 12h.01\", key: \"nlz23k\" }],\n [\"path\", { d: \"M12 3h.01\", key: \"n36tog\" }],\n [\"path\", { d: \"M12 16v.01\", key: \"133mhm\" }],\n [\"path\", { d: \"M16 12h1\", key: \"1slzba\" }],\n [\"path\", { d: \"M21 12v.01\", key: \"1lwtk9\" }],\n [\"path\", { d: \"M12 21v-1\", key: \"1880an\" }]\n]);\n\nexport { QrCode as default };\n//# sourceMappingURL=qr-code.js.map\n"],"names":["QrCode","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAASC,EAAiB,SAAU,CACxC,CAAC,OAAQ,CAAE,MAAO,IAAK,OAAQ,IAAK,EAAG,IAAK,EAAG,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC5E,CAAC,OAAQ,CAAE,MAAO,IAAK,OAAQ,IAAK,EAAG,KAAM,EAAG,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC7E,CAAC,OAAQ,CAAE,MAAO,IAAK,OAAQ,IAAK,EAAG,IAAK,EAAG,KAAM,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC7E,CAAC,OAAQ,CAAE,EAAG,4BAA6B,IAAK,QAAQ,CAAE,EAC1D,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,EAC3C,CAAC,OAAQ,CAAE,EAAG,0BAA2B,IAAK,QAAQ,CAAE,EACxD,CAAC,OAAQ,CAAE,EAAG,YAAa,IAAK,QAAQ,CAAE,EAC1C,CAAC,OAAQ,CAAE,EAAG,YAAa,IAAK,QAAQ,CAAE,EAC1C,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,EAC3C,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,EACzC,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,EAC3C,CAAC,OAAQ,CAAE,EAAG,YAAa,IAAK,QAAQ,CAAE,CAC5C,CAAC","x_google_ignoreList":[0]}
@@ -1,7 +1,7 @@
1
- import{n as e}from"./index-DXI13nSQ.js";/**
1
+ import{n as e}from"./index-CuNnG-5O.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 a=e("RefreshCcw",[["path",{d:"M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",key:"14sxne"}],["path",{d:"M3 3v5h5",key:"1xhq8a"}],["path",{d:"M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16",key:"1hlbsb"}],["path",{d:"M16 16h5v5",key:"ccwih5"}]]);export{a as R};
7
- //# sourceMappingURL=refresh-ccw-BPKXoMZa.js.map
7
+ //# sourceMappingURL=refresh-ccw-DZHRYuFA.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"refresh-ccw-BPKXoMZa.js","sources":["../../node_modules/lucide-react/dist/esm/icons/refresh-ccw.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 RefreshCcw = createLucideIcon(\"RefreshCcw\", [\n [\"path\", { d: \"M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\", key: \"14sxne\" }],\n [\"path\", { d: \"M3 3v5h5\", key: \"1xhq8a\" }],\n [\"path\", { d: \"M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16\", key: \"1hlbsb\" }],\n [\"path\", { d: \"M16 16h5v5\", key: \"ccwih5\" }]\n]);\n\nexport { RefreshCcw as default };\n//# sourceMappingURL=refresh-ccw.js.map\n"],"names":["RefreshCcw","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAAaC,EAAiB,aAAc,CAChD,CAAC,OAAQ,CAAE,EAAG,qDAAsD,IAAK,QAAQ,CAAE,EACnF,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,EACzC,CAAC,OAAQ,CAAE,EAAG,sDAAuD,IAAK,QAAQ,CAAE,EACpF,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,CAC7C,CAAC","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"refresh-ccw-DZHRYuFA.js","sources":["../../node_modules/lucide-react/dist/esm/icons/refresh-ccw.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 RefreshCcw = createLucideIcon(\"RefreshCcw\", [\n [\"path\", { d: \"M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\", key: \"14sxne\" }],\n [\"path\", { d: \"M3 3v5h5\", key: \"1xhq8a\" }],\n [\"path\", { d: \"M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16\", key: \"1hlbsb\" }],\n [\"path\", { d: \"M16 16h5v5\", key: \"ccwih5\" }]\n]);\n\nexport { RefreshCcw as default };\n//# sourceMappingURL=refresh-ccw.js.map\n"],"names":["RefreshCcw","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAAaC,EAAiB,aAAc,CAChD,CAAC,OAAQ,CAAE,EAAG,qDAAsD,IAAK,QAAQ,CAAE,EACnF,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,EACzC,CAAC,OAAQ,CAAE,EAAG,sDAAuD,IAAK,QAAQ,CAAE,EACpF,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,CAC7C,CAAC","x_google_ignoreList":[0]}
@@ -1,4 +1,4 @@
1
- import{n as w,a as v,b as D,d as y,u as k,e as K,j as e,k as M,B as d,T as E,S as L,f as q,g as A,h as F,i as V,l as h,m as b}from"./index-DXI13nSQ.js";import{r as x}from"./react-Cb2sDjhD.js";import{D as _}from"./data-table-BVcXWtPw.js";import{E as Q}from"./empty-state-WHzNYVaT.js";import{S as $}from"./status-badge-DeESb2dc.js";import{C as H}from"./confirm-dialog-_BtUs6oW.js";import{D as U,a as Z,b as G,c as J,d as W,e as X}from"./dialog-BVYFRXlI.js";import{u as Y}from"./useQuery-CEwGD94N.js";import{L as ee}from"./loader-circle-BS5FFFg-.js";import{R as se}from"./refresh-ccw-BPKXoMZa.js";import{B as te}from"./bell-DifbuUaI.js";import"./table-oUi0mGOn.js";import"./arrow-up-DtrvOH7Z.js";import"./arrow-down-OdSfpgG4.js";import"./x-OHUicFfn.js";/**
1
+ import{n as w,a as v,b as D,d as y,u as k,e as K,j as e,k as M,B as d,T as E,S as L,f as q,g as A,h as F,i as V,l as h,m as b}from"./index-CuNnG-5O.js";import{r as x}from"./react-Cb2sDjhD.js";import{D as _}from"./data-table-BbNkr6tW.js";import{E as Q}from"./empty-state-CRnid5FY.js";import{S as $}from"./status-badge-CTRG6Pb2.js";import{C as H}from"./confirm-dialog-6dKowsEt.js";import{D as U,a as Z,b as G,c as J,d as W,e as X}from"./dialog-Cv87qelJ.js";import{u as Y}from"./useQuery-DIlm0vJ-.js";import{L as ee}from"./loader-circle-CVEo3Hwx.js";import{R as se}from"./refresh-ccw-DZHRYuFA.js";import{B as te}from"./bell-ojwGPpS7.js";import"./table-Dbriy3Jz.js";import"./arrow-up-B47-Pj-X.js";import"./arrow-down-CL6JRd2c.js";import"./x-D_eFtxsK.js";/**
2
2
  * @license lucide-react v0.469.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -9,4 +9,4 @@ import{n as w,a as v,b as D,d as y,u as k,e as K,j as e,k as M,B as d,T as E,S a
9
9
  * This source code is licensed under the ISC license.
10
10
  * See the LICENSE file in the root directory of this source tree.
11
11
  */const ne=w("Clock",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["polyline",{points:"12 6 12 12 16 14",key:"68esgv"}]]),C={all:["reminders"],list:s=>["reminders","list",s]};function ie(s){return Y({queryKey:C.list(s),queryFn:()=>y.listReminders(s),refetchInterval:5e3,refetchIntervalInBackground:!1})}function re(){const s=v();return D({mutationFn:a=>y.cancelReminder(a),onSuccess:()=>s.invalidateQueries({queryKey:C.all})})}function le(){const s=v();return D({mutationFn:({id:a,body:i})=>y.snoozeReminder(a,i),onSuccess:()=>s.invalidateQueries({queryKey:C.all})})}const oe=["pending","firing","fired","cancelled","failed"],ce=[{duration:"5m",i18nKey:"snooze.preset5m"},{duration:"30m",i18nKey:"snooze.preset30m"},{duration:"1h",i18nKey:"snooze.preset1h"},{duration:"1d",i18nKey:"snooze.preset1d"}];function ke(){const{t:s}=k(["reminders","common"]),[a,i]=K(),r=a.get("status")??"pending",l=x.useMemo(()=>({status:r,limit:200}),[r]),{data:o,isLoading:z,isFetching:N,refetch:T}=ie(l),P=o?.reminders??[],m=re(),c=le(),[f,S]=x.useState(null),[p,g]=x.useState(null);function R(t){const n=new URLSearchParams(a);for(const[u,j]of Object.entries(t))j==null||j===""?n.delete(u):n.set(u,j);i(n,{replace:!0})}async function O(){if(f!=null)try{await m.mutateAsync(f),h.success(s("toast.cancelled"))}catch(t){const{message:n}=b(t,s);throw h.error(n),t}}async function I(t){if(p!=null)try{await c.mutateAsync({id:p,body:{duration:t}}),h.success(s("snooze.toastOk",{duration:t})),g(null)}catch(n){const{message:u}=b(n,s);h.error(u)}}const B=x.useMemo(()=>[{id:"id",header:s("col.id"),cell:t=>e.jsxs("span",{className:"tabular-nums text-text-dim",children:["#",t.id]}),headClassName:"w-16"},{id:"fireAt",header:s("col.fireAt"),cell:t=>e.jsx("span",{className:"font-medium tabular-nums",children:me(t.fire_at)}),headClassName:"w-40"},{id:"text",header:s("col.text"),cell:t=>e.jsx("span",{className:"line-clamp-2 text-text-dim",children:t.text}),asCardTitle:!0},{id:"status",header:s("col.status"),cell:t=>e.jsx($,{status:t.status,children:s(`status.${t.status}`,{defaultValue:t.status})}),headClassName:"w-28"},{id:"platform",header:s("col.platform"),cell:t=>e.jsx("span",{className:"text-text-dim",children:t.platform}),headClassName:"w-24",hideOnMobile:!0},{id:"recurrence",header:s("col.recurrence"),cell:t=>t.recurrence_label?e.jsx(M,{variant:"info",children:t.recurrence_label}):e.jsx("span",{className:"text-text-muted",children:"—"}),headClassName:"w-36",hideOnMobile:!0},{id:"source",header:s("col.source"),cell:t=>e.jsx("span",{className:"text-text-dim",children:s(`source.${t.source}`,{defaultValue:t.source})}),headClassName:"w-24",hideOnMobile:!0},{id:"actions",header:"",cell:t=>t.status==="pending"?e.jsxs("div",{className:"flex justify-end gap-1",children:[e.jsxs(d,{variant:"ghost",size:"sm",onClick:n=>{n.stopPropagation(),g(t.id)},disabled:c.isPending||m.isPending,children:[e.jsx(ne,{className:"h-3 w-3"}),s("action.snooze")]}),e.jsxs(d,{variant:"outline",size:"sm",onClick:n=>{n.stopPropagation(),S(t.id)},disabled:m.isPending||c.isPending,children:[e.jsx(ae,{className:"h-3 w-3"}),s("action.cancel")]})]}):null,headClassName:"w-48"}],[s,m.isPending,c.isPending]);return e.jsxs("div",{className:"flex min-h-dvh flex-col bg-bg",children:[e.jsx(E,{}),e.jsxs("main",{className:"mx-auto flex w-full max-w-7xl flex-1 flex-col gap-4 px-3 py-4 sm:px-4 pb-safe",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("pageTitle")}),e.jsxs(d,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>T(),disabled:N,"aria-label":s("actions.refresh",{ns:"common"}),children:[N?e.jsx(ee,{className:"h-4 w-4 animate-spin"}):e.jsx(se,{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("subtitle")})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("label",{className:"text-sm text-text-dim",htmlFor:"status-filter",children:s("filter.status")}),e.jsxs(L,{value:r,onValueChange:t=>R({status:t}),children:[e.jsx(q,{id:"status-filter",className:"w-[160px]",children:e.jsx(A,{})}),e.jsx(F,{children:oe.map(t=>e.jsx(V,{value:t,children:s(`status.${t}`,{defaultValue:t})},t))})]})]}),e.jsx(_,{columns:B,rows:P,getRowId:t=>String(t.id),loading:z,emptyState:e.jsx(Q,{icon:e.jsx(te,{}),title:s("empty.title"),description:s("empty.description")})}),e.jsx(H,{open:f!=null,onOpenChange:t=>{t||S(null)},title:s("action.confirmCancel"),description:s("action.confirmCancelDesc"),intent:"danger",confirmLabel:s("action.cancel"),onConfirm:O}),e.jsx(de,{open:p!=null,busy:c.isPending,onOpenChange:t=>{t||g(null)},onPick:I})]})]})}function de({open:s,busy:a,onOpenChange:i,onPick:r}){const{t:l}=k(["reminders","common"]);return e.jsx(U,{open:s,onOpenChange:a?()=>{}:i,children:e.jsxs(Z,{children:[e.jsxs(G,{children:[e.jsx(J,{children:l("snooze.title")}),e.jsx(W,{children:l("snooze.description")})]}),e.jsx("div",{className:"grid grid-cols-2 gap-2",children:ce.map(o=>e.jsx(d,{type:"button",variant:"outline",disabled:a,onClick:()=>void r(o.duration),children:l(o.i18nKey)},o.duration))}),e.jsx(X,{children:e.jsx(d,{type:"button",variant:"secondary",disabled:a,onClick:()=>i(!1),children:l("actions.cancel",{ns:"common"})})})]})})}function me(s){try{const a=new Date(s);if(Number.isNaN(a.getTime()))return s;const i=new Date;return a.toDateString()===i.toDateString()?a.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit"}):a.toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return s}}export{ke as default};
12
- //# sourceMappingURL=reminders-CP2qtNSr.js.map
12
+ //# sourceMappingURL=reminders-C00V-Fs9.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"reminders-CP2qtNSr.js","sources":["../../node_modules/lucide-react/dist/esm/icons/bell-off.js","../../node_modules/lucide-react/dist/esm/icons/clock.js","../../src/hooks/use-reminders.ts","../../src/routes/reminders.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 BellOff = createLucideIcon(\"BellOff\", [\n [\"path\", { d: \"M10.268 21a2 2 0 0 0 3.464 0\", key: \"vwvbt9\" }],\n [\n \"path\",\n {\n d: \"M17 17H4a1 1 0 0 1-.74-1.673C4.59 13.956 6 12.499 6 8a6 6 0 0 1 .258-1.742\",\n key: \"178tsu\"\n }\n ],\n [\"path\", { d: \"m2 2 20 20\", key: \"1ooewy\" }],\n [\"path\", { d: \"M8.668 3.01A6 6 0 0 1 18 8c0 2.687.77 4.653 1.707 6.05\", key: \"1hqiys\" }]\n]);\n\nexport { BellOff as default };\n//# sourceMappingURL=bell-off.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 Clock = createLucideIcon(\"Clock\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"polyline\", { points: \"12 6 12 12 16 14\", key: \"68esgv\" }]\n]);\n\nexport { Clock as default };\n//# sourceMappingURL=clock.js.map\n","/**\n * useReminders — react-query wrappers for the reminders domain.\n *\n * useReminders(query) — list pending (default) or by status\n * useCancelReminder() — POST /api/reminders/:id/cancel\n * useSnoozeReminder() — POST /api/reminders/:id/snooze\n *\n * Reminders aren't on the SSE event-bus today; the page combines a\n * 5s react-query poll with a manual Refresh button. When a snooze\n * mutation lands, both the original AND the new reminder change\n * (one cancelled, one pending) — invalidating the full 'reminders'\n * key catches both.\n */\n\nimport { useQueryClient, useQuery, useMutation } from '@tanstack/react-query'\nimport { api } from '@/lib/api/endpoints'\nimport type {\n CancelReminderResponse,\n ListRemindersQuery,\n ListRemindersResponse,\n SnoozeReminderBody,\n SnoozeReminderResponse,\n} from '@/types/api'\n\nexport const remindersKeys = {\n all: ['reminders'] as const,\n list: (q: ListRemindersQuery) => ['reminders', 'list', q] as const,\n}\n\nexport function useReminders(query: ListRemindersQuery) {\n return useQuery<ListRemindersResponse>({\n queryKey: remindersKeys.list(query),\n queryFn: () => api.listReminders(query),\n refetchInterval: 5000,\n refetchIntervalInBackground: false,\n })\n}\n\nexport function useInvalidateReminders() {\n const qc = useQueryClient()\n return () => qc.invalidateQueries({ queryKey: remindersKeys.all })\n}\n\nexport function useCancelReminder() {\n const qc = useQueryClient()\n return useMutation<CancelReminderResponse, Error, number>({\n mutationFn: (id) => api.cancelReminder(id),\n onSuccess: () => qc.invalidateQueries({ queryKey: remindersKeys.all }),\n })\n}\n\nexport function useSnoozeReminder() {\n const qc = useQueryClient()\n return useMutation<\n SnoozeReminderResponse,\n Error,\n { id: number; body: SnoozeReminderBody }\n >({\n mutationFn: ({ id, body }) => api.snoozeReminder(id, body),\n onSuccess: () => qc.invalidateQueries({ queryKey: remindersKeys.all }),\n })\n}\n","/**\n * /reminders — queued-reminder list with cancel + snooze.\n *\n * Composition: Topbar + filter row + DataTable + ConfirmDialog\n * (cancel) + a custom <SnoozeDialog> with duration presets that\n * map to the backend's parseDuration vocabulary.\n *\n * Mutations only enabled on `pending` rows; firing/fired/cancelled/\n * failed stay read-only. The DataTable's last column is per-row\n * action buttons.\n *\n * No SSE channel for reminders — 5s react-query poll covers the\n * common case (reminders fire on minute boundaries; latency to\n * surface a firing transition is rarely UX-critical).\n */\n\nimport { useMemo, useState } from 'react'\nimport { useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { Bell, BellOff, Clock, Loader2, RefreshCcw } from 'lucide-react'\n\nimport { Topbar } from '@/components/shell/topbar'\nimport { DataTable, type DataTableColumn } from '@/components/common/data-table'\nimport { EmptyState } from '@/components/common/empty-state'\nimport { StatusBadge } from '@/components/common/status-badge'\nimport { ConfirmDialog } from '@/components/common/confirm-dialog'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@/components/ui/dialog'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport {\n useReminders,\n useCancelReminder,\n useSnoozeReminder,\n} from '@/hooks/use-reminders'\nimport { describeError } from '@/lib/api/errors'\nimport type { Reminder, ReminderStatus } from '@/types/api'\n\nconst STATUS_OPTIONS: ReminderStatus[] = ['pending', 'firing', 'fired', 'cancelled', 'failed']\n\ninterface SnoozePreset {\n /** Backend parseDuration string. */\n duration: string\n /** i18n key (inside the `snooze` section). */\n i18nKey: string\n}\n\nconst SNOOZE_PRESETS: SnoozePreset[] = [\n { duration: '5m', i18nKey: 'snooze.preset5m' },\n { duration: '30m', i18nKey: 'snooze.preset30m' },\n { duration: '1h', i18nKey: 'snooze.preset1h' },\n { duration: '1d', i18nKey: 'snooze.preset1d' },\n]\n\nexport default function RemindersRoute(): JSX.Element {\n const { t } = useTranslation(['reminders', 'common'])\n const [params, setParams] = useSearchParams()\n const status = (params.get('status') as ReminderStatus | null) ?? 'pending'\n\n const query = useMemo(\n () => ({ status, limit: 200 }),\n [status],\n )\n const { data, isLoading, isFetching, refetch } = useReminders(query)\n const reminders = data?.reminders ?? []\n\n const cancel = useCancelReminder()\n const snooze = useSnoozeReminder()\n\n const [confirmCancelId, setConfirmCancelId] = useState<number | null>(null)\n const [snoozeTargetId, setSnoozeTargetId] = useState<number | null>(null)\n\n function patchParams(patch: Record<string, string | null>): void {\n const next = new URLSearchParams(params)\n for (const [k, v] of Object.entries(patch)) {\n if (v == null || v === '') next.delete(k)\n else next.set(k, v)\n }\n setParams(next, { replace: true })\n }\n\n async function onConfirmCancel(): Promise<void> {\n if (confirmCancelId == null) return\n try {\n await cancel.mutateAsync(confirmCancelId)\n toast.success(t('toast.cancelled'))\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n throw err\n }\n }\n\n async function onConfirmSnooze(duration: string): Promise<void> {\n if (snoozeTargetId == null) return\n try {\n await snooze.mutateAsync({ id: snoozeTargetId, body: { duration } })\n toast.success(t('snooze.toastOk', { duration }))\n setSnoozeTargetId(null)\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n }\n }\n\n const columns: DataTableColumn<Reminder>[] = useMemo(\n () => [\n {\n id: 'id',\n header: t('col.id'),\n cell: (r) => <span className=\"tabular-nums text-text-dim\">#{r.id}</span>,\n headClassName: 'w-16',\n },\n {\n id: 'fireAt',\n header: t('col.fireAt'),\n cell: (r) => <span className=\"font-medium tabular-nums\">{formatTime(r.fire_at)}</span>,\n headClassName: 'w-40',\n },\n {\n id: 'text',\n header: t('col.text'),\n cell: (r) => <span className=\"line-clamp-2 text-text-dim\">{r.text}</span>,\n asCardTitle: true,\n },\n {\n id: 'status',\n header: t('col.status'),\n cell: (r) => (\n <StatusBadge status={r.status}>\n {t(`status.${r.status}`, { defaultValue: r.status })}\n </StatusBadge>\n ),\n headClassName: 'w-28',\n },\n {\n id: 'platform',\n header: t('col.platform'),\n cell: (r) => <span className=\"text-text-dim\">{r.platform}</span>,\n headClassName: 'w-24',\n hideOnMobile: true,\n },\n {\n id: 'recurrence',\n header: t('col.recurrence'),\n cell: (r) =>\n r.recurrence_label ? (\n <Badge variant=\"info\">{r.recurrence_label}</Badge>\n ) : (\n <span className=\"text-text-muted\">—</span>\n ),\n headClassName: 'w-36',\n hideOnMobile: true,\n },\n {\n id: 'source',\n header: t('col.source'),\n cell: (r) => (\n <span className=\"text-text-dim\">{t(`source.${r.source}`, { defaultValue: r.source })}</span>\n ),\n headClassName: 'w-24',\n hideOnMobile: true,\n },\n {\n id: 'actions',\n header: '',\n cell: (r) =>\n r.status === 'pending' ? (\n <div className=\"flex justify-end gap-1\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation()\n setSnoozeTargetId(r.id)\n }}\n disabled={snooze.isPending || cancel.isPending}\n >\n <Clock className=\"h-3 w-3\" />\n {t('action.snooze')}\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation()\n setConfirmCancelId(r.id)\n }}\n disabled={cancel.isPending || snooze.isPending}\n >\n <BellOff className=\"h-3 w-3\" />\n {t('action.cancel')}\n </Button>\n </div>\n ) : null,\n headClassName: 'w-48',\n },\n ],\n [t, cancel.isPending, snooze.isPending],\n )\n\n return (\n <div className=\"flex min-h-dvh flex-col bg-bg\">\n <Topbar />\n\n <main className=\"mx-auto flex w-full max-w-7xl flex-1 flex-col gap-4 px-3 py-4 sm:px-4 pb-safe\">\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('pageTitle')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => refetch()}\n disabled={isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {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('subtitle')}</p>\n </header>\n\n {/* Filter row */}\n <div className=\"flex flex-wrap items-center gap-2\">\n <label className=\"text-sm text-text-dim\" htmlFor=\"status-filter\">\n {t('filter.status')}\n </label>\n <Select\n value={status}\n onValueChange={(v) => patchParams({ status: v })}\n >\n <SelectTrigger id=\"status-filter\" className=\"w-[160px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {STATUS_OPTIONS.map((s) => (\n <SelectItem key={s} value={s}>\n {t(`status.${s}`, { defaultValue: s })}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <DataTable\n columns={columns}\n rows={reminders}\n getRowId={(r) => String(r.id)}\n loading={isLoading}\n emptyState={\n <EmptyState\n icon={<Bell />}\n title={t('empty.title')}\n description={t('empty.description')}\n />\n }\n />\n\n <ConfirmDialog\n open={confirmCancelId != null}\n onOpenChange={(open) => {\n if (!open) setConfirmCancelId(null)\n }}\n title={t('action.confirmCancel')}\n description={t('action.confirmCancelDesc')}\n intent=\"danger\"\n confirmLabel={t('action.cancel')}\n onConfirm={onConfirmCancel}\n />\n\n <SnoozeDialog\n open={snoozeTargetId != null}\n busy={snooze.isPending}\n onOpenChange={(open) => {\n if (!open) setSnoozeTargetId(null)\n }}\n onPick={onConfirmSnooze}\n />\n </main>\n </div>\n )\n}\n\ninterface SnoozeDialogProps {\n open: boolean\n busy: boolean\n onOpenChange: (open: boolean) => void\n onPick: (duration: string) => void | Promise<void>\n}\n\nfunction SnoozeDialog({ open, busy, onOpenChange, onPick }: SnoozeDialogProps): JSX.Element {\n const { t } = useTranslation(['reminders', 'common'])\n return (\n <Dialog open={open} onOpenChange={busy ? () => {} : onOpenChange}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>{t('snooze.title')}</DialogTitle>\n <DialogDescription>{t('snooze.description')}</DialogDescription>\n </DialogHeader>\n <div className=\"grid grid-cols-2 gap-2\">\n {SNOOZE_PRESETS.map((p) => (\n <Button\n key={p.duration}\n type=\"button\"\n variant=\"outline\"\n disabled={busy}\n onClick={() => void onPick(p.duration)}\n >\n {t(p.i18nKey)}\n </Button>\n ))}\n </div>\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"secondary\"\n disabled={busy}\n onClick={() => onOpenChange(false)}\n >\n {t('actions.cancel', { ns: 'common' })}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n\nfunction formatTime(iso: string): string {\n try {\n const d = new Date(iso)\n if (Number.isNaN(d.getTime())) return iso\n const now = new Date()\n const sameDay = d.toDateString() === now.toDateString()\n if (sameDay) {\n return d.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' })\n }\n return d.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })\n } catch {\n return iso\n }\n}\n"],"names":["BellOff","createLucideIcon","Clock","remindersKeys","q","useReminders","query","useQuery","api","useCancelReminder","qc","useQueryClient","useMutation","id","useSnoozeReminder","body","STATUS_OPTIONS","SNOOZE_PRESETS","RemindersRoute","t","useTranslation","params","setParams","useSearchParams","status","useMemo","data","isLoading","isFetching","refetch","reminders","cancel","snooze","confirmCancelId","setConfirmCancelId","useState","snoozeTargetId","setSnoozeTargetId","patchParams","patch","next","k","v","onConfirmCancel","toast","err","message","describeError","onConfirmSnooze","duration","columns","r","jsxs","jsx","formatTime","StatusBadge","Badge","Button","e","Topbar","Loader2","RefreshCcw","Select","SelectTrigger","SelectValue","SelectContent","s","SelectItem","DataTable","EmptyState","Bell","ConfirmDialog","open","SnoozeDialog","busy","onOpenChange","onPick","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","p","DialogFooter","iso","d","now"],"mappings":"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","x_google_ignoreList":[0,1]}
1
+ {"version":3,"file":"reminders-C00V-Fs9.js","sources":["../../node_modules/lucide-react/dist/esm/icons/bell-off.js","../../node_modules/lucide-react/dist/esm/icons/clock.js","../../src/hooks/use-reminders.ts","../../src/routes/reminders.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 BellOff = createLucideIcon(\"BellOff\", [\n [\"path\", { d: \"M10.268 21a2 2 0 0 0 3.464 0\", key: \"vwvbt9\" }],\n [\n \"path\",\n {\n d: \"M17 17H4a1 1 0 0 1-.74-1.673C4.59 13.956 6 12.499 6 8a6 6 0 0 1 .258-1.742\",\n key: \"178tsu\"\n }\n ],\n [\"path\", { d: \"m2 2 20 20\", key: \"1ooewy\" }],\n [\"path\", { d: \"M8.668 3.01A6 6 0 0 1 18 8c0 2.687.77 4.653 1.707 6.05\", key: \"1hqiys\" }]\n]);\n\nexport { BellOff as default };\n//# sourceMappingURL=bell-off.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 Clock = createLucideIcon(\"Clock\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"polyline\", { points: \"12 6 12 12 16 14\", key: \"68esgv\" }]\n]);\n\nexport { Clock as default };\n//# sourceMappingURL=clock.js.map\n","/**\n * useReminders — react-query wrappers for the reminders domain.\n *\n * useReminders(query) — list pending (default) or by status\n * useCancelReminder() — POST /api/reminders/:id/cancel\n * useSnoozeReminder() — POST /api/reminders/:id/snooze\n *\n * Reminders aren't on the SSE event-bus today; the page combines a\n * 5s react-query poll with a manual Refresh button. When a snooze\n * mutation lands, both the original AND the new reminder change\n * (one cancelled, one pending) — invalidating the full 'reminders'\n * key catches both.\n */\n\nimport { useQueryClient, useQuery, useMutation } from '@tanstack/react-query'\nimport { api } from '@/lib/api/endpoints'\nimport type {\n CancelReminderResponse,\n ListRemindersQuery,\n ListRemindersResponse,\n SnoozeReminderBody,\n SnoozeReminderResponse,\n} from '@/types/api'\n\nexport const remindersKeys = {\n all: ['reminders'] as const,\n list: (q: ListRemindersQuery) => ['reminders', 'list', q] as const,\n}\n\nexport function useReminders(query: ListRemindersQuery) {\n return useQuery<ListRemindersResponse>({\n queryKey: remindersKeys.list(query),\n queryFn: () => api.listReminders(query),\n refetchInterval: 5000,\n refetchIntervalInBackground: false,\n })\n}\n\nexport function useInvalidateReminders() {\n const qc = useQueryClient()\n return () => qc.invalidateQueries({ queryKey: remindersKeys.all })\n}\n\nexport function useCancelReminder() {\n const qc = useQueryClient()\n return useMutation<CancelReminderResponse, Error, number>({\n mutationFn: (id) => api.cancelReminder(id),\n onSuccess: () => qc.invalidateQueries({ queryKey: remindersKeys.all }),\n })\n}\n\nexport function useSnoozeReminder() {\n const qc = useQueryClient()\n return useMutation<\n SnoozeReminderResponse,\n Error,\n { id: number; body: SnoozeReminderBody }\n >({\n mutationFn: ({ id, body }) => api.snoozeReminder(id, body),\n onSuccess: () => qc.invalidateQueries({ queryKey: remindersKeys.all }),\n })\n}\n","/**\n * /reminders — queued-reminder list with cancel + snooze.\n *\n * Composition: Topbar + filter row + DataTable + ConfirmDialog\n * (cancel) + a custom <SnoozeDialog> with duration presets that\n * map to the backend's parseDuration vocabulary.\n *\n * Mutations only enabled on `pending` rows; firing/fired/cancelled/\n * failed stay read-only. The DataTable's last column is per-row\n * action buttons.\n *\n * No SSE channel for reminders — 5s react-query poll covers the\n * common case (reminders fire on minute boundaries; latency to\n * surface a firing transition is rarely UX-critical).\n */\n\nimport { useMemo, useState } from 'react'\nimport { useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { Bell, BellOff, Clock, Loader2, RefreshCcw } from 'lucide-react'\n\nimport { Topbar } from '@/components/shell/topbar'\nimport { DataTable, type DataTableColumn } from '@/components/common/data-table'\nimport { EmptyState } from '@/components/common/empty-state'\nimport { StatusBadge } from '@/components/common/status-badge'\nimport { ConfirmDialog } from '@/components/common/confirm-dialog'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@/components/ui/dialog'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport {\n useReminders,\n useCancelReminder,\n useSnoozeReminder,\n} from '@/hooks/use-reminders'\nimport { describeError } from '@/lib/api/errors'\nimport type { Reminder, ReminderStatus } from '@/types/api'\n\nconst STATUS_OPTIONS: ReminderStatus[] = ['pending', 'firing', 'fired', 'cancelled', 'failed']\n\ninterface SnoozePreset {\n /** Backend parseDuration string. */\n duration: string\n /** i18n key (inside the `snooze` section). */\n i18nKey: string\n}\n\nconst SNOOZE_PRESETS: SnoozePreset[] = [\n { duration: '5m', i18nKey: 'snooze.preset5m' },\n { duration: '30m', i18nKey: 'snooze.preset30m' },\n { duration: '1h', i18nKey: 'snooze.preset1h' },\n { duration: '1d', i18nKey: 'snooze.preset1d' },\n]\n\nexport default function RemindersRoute(): JSX.Element {\n const { t } = useTranslation(['reminders', 'common'])\n const [params, setParams] = useSearchParams()\n const status = (params.get('status') as ReminderStatus | null) ?? 'pending'\n\n const query = useMemo(\n () => ({ status, limit: 200 }),\n [status],\n )\n const { data, isLoading, isFetching, refetch } = useReminders(query)\n const reminders = data?.reminders ?? []\n\n const cancel = useCancelReminder()\n const snooze = useSnoozeReminder()\n\n const [confirmCancelId, setConfirmCancelId] = useState<number | null>(null)\n const [snoozeTargetId, setSnoozeTargetId] = useState<number | null>(null)\n\n function patchParams(patch: Record<string, string | null>): void {\n const next = new URLSearchParams(params)\n for (const [k, v] of Object.entries(patch)) {\n if (v == null || v === '') next.delete(k)\n else next.set(k, v)\n }\n setParams(next, { replace: true })\n }\n\n async function onConfirmCancel(): Promise<void> {\n if (confirmCancelId == null) return\n try {\n await cancel.mutateAsync(confirmCancelId)\n toast.success(t('toast.cancelled'))\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n throw err\n }\n }\n\n async function onConfirmSnooze(duration: string): Promise<void> {\n if (snoozeTargetId == null) return\n try {\n await snooze.mutateAsync({ id: snoozeTargetId, body: { duration } })\n toast.success(t('snooze.toastOk', { duration }))\n setSnoozeTargetId(null)\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n }\n }\n\n const columns: DataTableColumn<Reminder>[] = useMemo(\n () => [\n {\n id: 'id',\n header: t('col.id'),\n cell: (r) => <span className=\"tabular-nums text-text-dim\">#{r.id}</span>,\n headClassName: 'w-16',\n },\n {\n id: 'fireAt',\n header: t('col.fireAt'),\n cell: (r) => <span className=\"font-medium tabular-nums\">{formatTime(r.fire_at)}</span>,\n headClassName: 'w-40',\n },\n {\n id: 'text',\n header: t('col.text'),\n cell: (r) => <span className=\"line-clamp-2 text-text-dim\">{r.text}</span>,\n asCardTitle: true,\n },\n {\n id: 'status',\n header: t('col.status'),\n cell: (r) => (\n <StatusBadge status={r.status}>\n {t(`status.${r.status}`, { defaultValue: r.status })}\n </StatusBadge>\n ),\n headClassName: 'w-28',\n },\n {\n id: 'platform',\n header: t('col.platform'),\n cell: (r) => <span className=\"text-text-dim\">{r.platform}</span>,\n headClassName: 'w-24',\n hideOnMobile: true,\n },\n {\n id: 'recurrence',\n header: t('col.recurrence'),\n cell: (r) =>\n r.recurrence_label ? (\n <Badge variant=\"info\">{r.recurrence_label}</Badge>\n ) : (\n <span className=\"text-text-muted\">—</span>\n ),\n headClassName: 'w-36',\n hideOnMobile: true,\n },\n {\n id: 'source',\n header: t('col.source'),\n cell: (r) => (\n <span className=\"text-text-dim\">{t(`source.${r.source}`, { defaultValue: r.source })}</span>\n ),\n headClassName: 'w-24',\n hideOnMobile: true,\n },\n {\n id: 'actions',\n header: '',\n cell: (r) =>\n r.status === 'pending' ? (\n <div className=\"flex justify-end gap-1\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation()\n setSnoozeTargetId(r.id)\n }}\n disabled={snooze.isPending || cancel.isPending}\n >\n <Clock className=\"h-3 w-3\" />\n {t('action.snooze')}\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={(e) => {\n e.stopPropagation()\n setConfirmCancelId(r.id)\n }}\n disabled={cancel.isPending || snooze.isPending}\n >\n <BellOff className=\"h-3 w-3\" />\n {t('action.cancel')}\n </Button>\n </div>\n ) : null,\n headClassName: 'w-48',\n },\n ],\n [t, cancel.isPending, snooze.isPending],\n )\n\n return (\n <div className=\"flex min-h-dvh flex-col bg-bg\">\n <Topbar />\n\n <main className=\"mx-auto flex w-full max-w-7xl flex-1 flex-col gap-4 px-3 py-4 sm:px-4 pb-safe\">\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('pageTitle')}</h1>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"ml-auto\"\n onClick={() => refetch()}\n disabled={isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {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('subtitle')}</p>\n </header>\n\n {/* Filter row */}\n <div className=\"flex flex-wrap items-center gap-2\">\n <label className=\"text-sm text-text-dim\" htmlFor=\"status-filter\">\n {t('filter.status')}\n </label>\n <Select\n value={status}\n onValueChange={(v) => patchParams({ status: v })}\n >\n <SelectTrigger id=\"status-filter\" className=\"w-[160px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {STATUS_OPTIONS.map((s) => (\n <SelectItem key={s} value={s}>\n {t(`status.${s}`, { defaultValue: s })}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n <DataTable\n columns={columns}\n rows={reminders}\n getRowId={(r) => String(r.id)}\n loading={isLoading}\n emptyState={\n <EmptyState\n icon={<Bell />}\n title={t('empty.title')}\n description={t('empty.description')}\n />\n }\n />\n\n <ConfirmDialog\n open={confirmCancelId != null}\n onOpenChange={(open) => {\n if (!open) setConfirmCancelId(null)\n }}\n title={t('action.confirmCancel')}\n description={t('action.confirmCancelDesc')}\n intent=\"danger\"\n confirmLabel={t('action.cancel')}\n onConfirm={onConfirmCancel}\n />\n\n <SnoozeDialog\n open={snoozeTargetId != null}\n busy={snooze.isPending}\n onOpenChange={(open) => {\n if (!open) setSnoozeTargetId(null)\n }}\n onPick={onConfirmSnooze}\n />\n </main>\n </div>\n )\n}\n\ninterface SnoozeDialogProps {\n open: boolean\n busy: boolean\n onOpenChange: (open: boolean) => void\n onPick: (duration: string) => void | Promise<void>\n}\n\nfunction SnoozeDialog({ open, busy, onOpenChange, onPick }: SnoozeDialogProps): JSX.Element {\n const { t } = useTranslation(['reminders', 'common'])\n return (\n <Dialog open={open} onOpenChange={busy ? () => {} : onOpenChange}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>{t('snooze.title')}</DialogTitle>\n <DialogDescription>{t('snooze.description')}</DialogDescription>\n </DialogHeader>\n <div className=\"grid grid-cols-2 gap-2\">\n {SNOOZE_PRESETS.map((p) => (\n <Button\n key={p.duration}\n type=\"button\"\n variant=\"outline\"\n disabled={busy}\n onClick={() => void onPick(p.duration)}\n >\n {t(p.i18nKey)}\n </Button>\n ))}\n </div>\n <DialogFooter>\n <Button\n type=\"button\"\n variant=\"secondary\"\n disabled={busy}\n onClick={() => onOpenChange(false)}\n >\n {t('actions.cancel', { ns: 'common' })}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n\nfunction formatTime(iso: string): string {\n try {\n const d = new Date(iso)\n if (Number.isNaN(d.getTime())) return iso\n const now = new Date()\n const sameDay = d.toDateString() === now.toDateString()\n if (sameDay) {\n return d.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' })\n }\n return d.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })\n } catch {\n return iso\n }\n}\n"],"names":["BellOff","createLucideIcon","Clock","remindersKeys","q","useReminders","query","useQuery","api","useCancelReminder","qc","useQueryClient","useMutation","id","useSnoozeReminder","body","STATUS_OPTIONS","SNOOZE_PRESETS","RemindersRoute","t","useTranslation","params","setParams","useSearchParams","status","useMemo","data","isLoading","isFetching","refetch","reminders","cancel","snooze","confirmCancelId","setConfirmCancelId","useState","snoozeTargetId","setSnoozeTargetId","patchParams","patch","next","k","v","onConfirmCancel","toast","err","message","describeError","onConfirmSnooze","duration","columns","r","jsxs","jsx","formatTime","StatusBadge","Badge","Button","e","Topbar","Loader2","RefreshCcw","Select","SelectTrigger","SelectValue","SelectContent","s","SelectItem","DataTable","EmptyState","Bell","ConfirmDialog","open","SnoozeDialog","busy","onOpenChange","onPick","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","p","DialogFooter","iso","d","now"],"mappings":"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","x_google_ignoreList":[0,1]}
@@ -1,7 +1,7 @@
1
- import{n as a}from"./index-DXI13nSQ.js";/**
1
+ import{n as a}from"./index-CuNnG-5O.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=a("Save",[["path",{d:"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z",key:"1c8476"}],["path",{d:"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7",key:"1ydtos"}],["path",{d:"M7 3v4a1 1 0 0 0 1 1h7",key:"t51u73"}]]);export{t as S};
7
- //# sourceMappingURL=save-BXCmgeEj.js.map
7
+ //# sourceMappingURL=save-DQlBAXAl.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"save-BXCmgeEj.js","sources":["../../node_modules/lucide-react/dist/esm/icons/save.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 Save = createLucideIcon(\"Save\", [\n [\n \"path\",\n {\n d: \"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z\",\n key: \"1c8476\"\n }\n ],\n [\"path\", { d: \"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7\", key: \"1ydtos\" }],\n [\"path\", { d: \"M7 3v4a1 1 0 0 0 1 1h7\", key: \"t51u73\" }]\n]);\n\nexport { Save as default };\n//# sourceMappingURL=save.js.map\n"],"names":["Save","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAAOC,EAAiB,OAAQ,CACpC,CACE,OACA,CACE,EAAG,qGACH,IAAK,QACX,CACA,EACE,CAAC,OAAQ,CAAE,EAAG,4CAA6C,IAAK,QAAQ,CAAE,EAC1E,CAAC,OAAQ,CAAE,EAAG,yBAA0B,IAAK,QAAQ,CAAE,CACzD,CAAC","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"save-DQlBAXAl.js","sources":["../../node_modules/lucide-react/dist/esm/icons/save.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 Save = createLucideIcon(\"Save\", [\n [\n \"path\",\n {\n d: \"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z\",\n key: \"1c8476\"\n }\n ],\n [\"path\", { d: \"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7\", key: \"1ydtos\" }],\n [\"path\", { d: \"M7 3v4a1 1 0 0 0 1 1h7\", key: \"t51u73\" }]\n]);\n\nexport { Save as default };\n//# sourceMappingURL=save.js.map\n"],"names":["Save","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAAOC,EAAiB,OAAQ,CACpC,CACE,OACA,CACE,EAAG,qGACH,IAAK,QACX,CACA,EACE,CAAC,OAAQ,CAAE,EAAG,4CAA6C,IAAK,QAAQ,CAAE,EAC1E,CAAC,OAAQ,CAAE,EAAG,yBAA0B,IAAK,QAAQ,CAAE,CACzD,CAAC","x_google_ignoreList":[0]}
@@ -1,7 +1,7 @@
1
- import{n as f,d as g,u as N,e as j,j as s,k as r,B as y,L as w,I as b}from"./index-DXI13nSQ.js";import{r as C}from"./react-Cb2sDjhD.js";import{D as k}from"./data-table-BVcXWtPw.js";import{E as v}from"./empty-state-WHzNYVaT.js";import{u as R}from"./useQuery-CEwGD94N.js";import{L as S}from"./loader-circle-BS5FFFg-.js";import{R as L}from"./refresh-ccw-BPKXoMZa.js";import"./table-oUi0mGOn.js";import"./arrow-up-DtrvOH7Z.js";import"./arrow-down-OdSfpgG4.js";/**
1
+ import{n as f,d as g,u as N,e as j,j as s,k as r,B as y,L as w,I as b}from"./index-CuNnG-5O.js";import{r as C}from"./react-Cb2sDjhD.js";import{D as k}from"./data-table-BbNkr6tW.js";import{E as v}from"./empty-state-CRnid5FY.js";import{u as R}from"./useQuery-DIlm0vJ-.js";import{L as S}from"./loader-circle-CVEo3Hwx.js";import{R as L}from"./refresh-ccw-DZHRYuFA.js";import"./table-Dbriy3Jz.js";import"./arrow-up-B47-Pj-X.js";import"./arrow-down-CL6JRd2c.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 M=f("CalendarClock",[["path",{d:"M21 7.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h3.5",key:"1osxxc"}],["path",{d:"M16 2v4",key:"4m81vk"}],["path",{d:"M8 2v4",key:"1cmpym"}],["path",{d:"M3 10h5",key:"r794hk"}],["path",{d:"M17.5 17.5 16 16.3V14",key:"akvzfd"}],["circle",{cx:"16",cy:"16",r:"6",key:"qoo3c4"}]]),T={all:["schedules"],list:e=>["schedules","list",e]};function E(e){return R({queryKey:T.list(e),queryFn:()=>g.listSchedules(e)})}function V(){const{t:e}=N(["tasks","common"]),[t,i]=j(),l=t.get("agent")??"",{data:m,isLoading:o,isFetching:n,refetch:h}=E(l?{agent:l}:{}),u=m?.schedules??[];function x(a){const c=new URLSearchParams(t);a?c.set("agent",a):c.delete("agent"),i(c,{replace:!0})}const p=C.useMemo(()=>[{id:"id",header:e("schedules.col.id"),cell:a=>s.jsxs("span",{className:"tabular-nums text-text-dim",children:["#",a.id]}),headClassName:"w-16"},{id:"name",header:e("schedules.col.name"),cell:a=>s.jsx("span",{className:"font-medium",children:a.name}),asCardTitle:!0},{id:"agent",header:e("schedules.col.agent"),cell:a=>s.jsx("span",{className:"text-text-dim",children:a.agent}),headClassName:"w-32"},{id:"cron",header:e("schedules.col.cron"),cell:a=>s.jsx("code",{className:"rounded bg-surface-2 px-1.5 py-0.5 text-xs",children:a.cron}),headClassName:"w-32"},{id:"prompt",header:e("schedules.col.prompt"),cell:a=>s.jsx("span",{className:"line-clamp-2 text-text-dim",children:a.prompt}),hideOnMobile:!0},{id:"enabled",header:e("schedules.col.enabled"),cell:a=>a.enabled?s.jsx(r,{variant:"success",children:e("schedules.enabled")}):s.jsx(r,{variant:"outline",children:e("schedules.disabled")}),headClassName:"w-20"},{id:"nextRun",header:e("schedules.col.nextRun"),cell:a=>s.jsx("span",{className:"text-text-dim",children:d(a.next_run)}),headClassName:"w-40"},{id:"lastRun",header:e("schedules.col.lastRun"),cell:a=>s.jsx("span",{className:"text-text-dim",children:d(a.last_run)}),headClassName:"w-40",hideOnMobile:!0}],[e]);return s.jsxs("div",{className:"mx-auto flex max-w-7xl flex-col gap-4",children:[s.jsxs("header",{className:"flex flex-col gap-1",children:[s.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[s.jsx("h1",{className:"text-xl font-semibold",children:e("schedules.title")}),s.jsxs(y,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>h(),disabled:n,"aria-label":e("actions.refresh",{ns:"common"}),children:[n?s.jsx(S,{className:"h-4 w-4 animate-spin"}):s.jsx(L,{className:"h-4 w-4"}),s.jsx("span",{className:"hidden sm:inline",children:e("actions.refresh",{ns:"common"})})]})]}),s.jsx("p",{className:"text-sm text-text-dim",children:e("schedules.subtitle")})]}),s.jsx("div",{className:"flex flex-wrap items-end gap-2",children:s.jsxs("div",{className:"flex flex-col gap-1",children:[s.jsx(w,{htmlFor:"agent-filter",className:"text-xs text-text-dim",children:e("schedules.filter.agent")}),s.jsx(b,{id:"agent-filter",value:l,onChange:a=>x(a.target.value),placeholder:e("schedules.filter.agentAny"),className:"w-48"})]})}),s.jsx(k,{columns:p,rows:u,getRowId:a=>String(a.id),loading:o,emptyState:s.jsx(v,{icon:s.jsx(M,{}),title:e("schedules.empty.title"),description:e("schedules.empty.description")})})]})}function d(e){if(e==null)return"—";try{const t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return e}}export{V as default};
7
- //# sourceMappingURL=schedules-DVaY38v1.js.map
7
+ //# sourceMappingURL=schedules-BtuWAAd7.js.map