agim-cli 1.3.4 → 1.3.7

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 (257) hide show
  1. package/CHANGELOG.md +20 -6
  2. package/dist/cli-ui/tui/app.js +1 -1
  3. package/dist/cli-ui/tui/app.js.map +1 -1
  4. package/dist/cli.js +25 -4
  5. package/dist/cli.js.map +1 -1
  6. package/dist/core/a2a.d.ts.map +1 -1
  7. package/dist/core/a2a.js +6 -0
  8. package/dist/core/a2a.js.map +1 -1
  9. package/dist/core/access-token.d.ts.map +1 -1
  10. package/dist/core/access-token.js +16 -4
  11. package/dist/core/access-token.js.map +1 -1
  12. package/dist/core/approval-bus.d.ts +5 -0
  13. package/dist/core/approval-bus.d.ts.map +1 -1
  14. package/dist/core/approval-bus.js +32 -0
  15. package/dist/core/approval-bus.js.map +1 -1
  16. package/dist/core/commands/job.d.ts.map +1 -1
  17. package/dist/core/commands/job.js +10 -3
  18. package/dist/core/commands/job.js.map +1 -1
  19. package/dist/core/goal-rpc.d.ts +7 -0
  20. package/dist/core/goal-rpc.d.ts.map +1 -1
  21. package/dist/core/goal-rpc.js +47 -3
  22. package/dist/core/goal-rpc.js.map +1 -1
  23. package/dist/core/llm/exec-dispatcher.d.ts +2 -0
  24. package/dist/core/llm/exec-dispatcher.d.ts.map +1 -1
  25. package/dist/core/llm/exec-dispatcher.js +60 -6
  26. package/dist/core/llm/exec-dispatcher.js.map +1 -1
  27. package/dist/core/llm/fs-dispatcher.d.ts +3 -0
  28. package/dist/core/llm/fs-dispatcher.d.ts.map +1 -1
  29. package/dist/core/llm/fs-dispatcher.js +31 -12
  30. package/dist/core/llm/fs-dispatcher.js.map +1 -1
  31. package/dist/core/llm/imhub-dispatcher.d.ts.map +1 -1
  32. package/dist/core/llm/imhub-dispatcher.js +9 -5
  33. package/dist/core/llm/imhub-dispatcher.js.map +1 -1
  34. package/dist/core/llm/model-catalog.js +1 -1
  35. package/dist/core/llm/model-catalog.js.map +1 -1
  36. package/dist/core/llm/policy-approval-gate.d.ts.map +1 -1
  37. package/dist/core/llm/policy-approval-gate.js +17 -4
  38. package/dist/core/llm/policy-approval-gate.js.map +1 -1
  39. package/dist/core/llm/registry.d.ts +2 -2
  40. package/dist/core/llm/registry.js +1 -1
  41. package/dist/core/llm/web-dispatcher.d.ts +20 -0
  42. package/dist/core/llm/web-dispatcher.d.ts.map +1 -1
  43. package/dist/core/llm/web-dispatcher.js +70 -5
  44. package/dist/core/llm/web-dispatcher.js.map +1 -1
  45. package/dist/core/registry.d.ts.map +1 -1
  46. package/dist/core/registry.js +5 -19
  47. package/dist/core/registry.js.map +1 -1
  48. package/dist/core/router.js +1 -1
  49. package/dist/core/router.js.map +1 -1
  50. package/dist/core/schedule.d.ts.map +1 -1
  51. package/dist/core/schedule.js +6 -2
  52. package/dist/core/schedule.js.map +1 -1
  53. package/dist/core/skills/loader.js +3 -3
  54. package/dist/core/skills/loader.js.map +1 -1
  55. package/dist/core/types.d.ts +3 -0
  56. package/dist/core/types.d.ts.map +1 -1
  57. package/dist/plugins/agents/native/index.d.ts +0 -146
  58. package/dist/plugins/agents/native/index.d.ts.map +1 -1
  59. package/dist/plugins/agents/native/index.js +41 -1291
  60. package/dist/plugins/agents/native/index.js.map +1 -1
  61. package/dist/plugins/agents/pi-native/approval.d.ts.map +1 -1
  62. package/dist/plugins/agents/pi-native/approval.js +2 -3
  63. package/dist/plugins/agents/pi-native/approval.js.map +1 -1
  64. package/dist/plugins/agents/pi-native/factory.d.ts +3 -4
  65. package/dist/plugins/agents/pi-native/factory.d.ts.map +1 -1
  66. package/dist/plugins/agents/pi-native/factory.js +8 -14
  67. package/dist/plugins/agents/pi-native/factory.js.map +1 -1
  68. package/dist/plugins/agents/pi-native/index.d.ts +8 -8
  69. package/dist/plugins/agents/pi-native/index.d.ts.map +1 -1
  70. package/dist/plugins/agents/pi-native/index.js +78 -13
  71. package/dist/plugins/agents/pi-native/index.js.map +1 -1
  72. package/dist/plugins/agents/pi-native/provider-resolver.d.ts +4 -4
  73. package/dist/plugins/agents/pi-native/provider-resolver.d.ts.map +1 -1
  74. package/dist/plugins/agents/pi-native/provider-resolver.js +1 -1
  75. package/dist/plugins/agents/pi-native/provider-resolver.js.map +1 -1
  76. package/dist/plugins/agents/pi-native/tool-bridge.js +1 -1
  77. package/dist/plugins/agents/pi-native/tool-bridge.js.map +1 -1
  78. package/dist/plugins/agents/pi-native/tools.d.ts +3 -4
  79. package/dist/plugins/agents/pi-native/tools.d.ts.map +1 -1
  80. package/dist/plugins/agents/pi-native/tools.js +7 -9
  81. package/dist/plugins/agents/pi-native/tools.js.map +1 -1
  82. package/dist/plugins/messengers/discord/discord-adapter.d.ts.map +1 -1
  83. package/dist/plugins/messengers/discord/discord-adapter.js +14 -2
  84. package/dist/plugins/messengers/discord/discord-adapter.js.map +1 -1
  85. package/dist/web/public/assets/{a2a-Y30Sn8pc.js → a2a-Bk51ozUt.js} +2 -2
  86. package/dist/web/public/assets/{a2a-Y30Sn8pc.js.map → a2a-Bk51ozUt.js.map} +1 -1
  87. package/dist/web/public/assets/{activity--oN7qxFJ.js → activity-DzKONPpA.js} +2 -2
  88. package/dist/web/public/assets/{activity--oN7qxFJ.js.map → activity-DzKONPpA.js.map} +1 -1
  89. package/dist/web/public/assets/{admins-DONiT3ld.js → admins-CmZ4eQnt.js} +2 -2
  90. package/dist/web/public/assets/{admins-DONiT3ld.js.map → admins-CmZ4eQnt.js.map} +1 -1
  91. package/dist/web/public/assets/{agents-DRbQOH0K.js → agents-lj76gn9U.js} +2 -2
  92. package/dist/web/public/assets/{agents-DRbQOH0K.js.map → agents-lj76gn9U.js.map} +1 -1
  93. package/dist/web/public/assets/{approvals-C5jd7Wf9.js → approvals-C5-3WBcb.js} +2 -2
  94. package/dist/web/public/assets/{approvals-C5jd7Wf9.js.map → approvals-C5-3WBcb.js.map} +1 -1
  95. package/dist/web/public/assets/{arrow-down-x-Lq92tn.js → arrow-down-DAjYgwW2.js} +2 -2
  96. package/dist/web/public/assets/{arrow-down-x-Lq92tn.js.map → arrow-down-DAjYgwW2.js.map} +1 -1
  97. package/dist/web/public/assets/{arrow-up-Cc28qbjN.js → arrow-up-Cba9TuAO.js} +2 -2
  98. package/dist/web/public/assets/{arrow-up-Cc28qbjN.js.map → arrow-up-Cba9TuAO.js.map} +1 -1
  99. package/dist/web/public/assets/{asks-CeVcu8SD.js → asks-qlttx_de.js} +2 -2
  100. package/dist/web/public/assets/{asks-CeVcu8SD.js.map → asks-qlttx_de.js.map} +1 -1
  101. package/dist/web/public/assets/{audit-Dc9_FDkW.js → audit-CSjpfK6P.js} +2 -2
  102. package/dist/web/public/assets/{audit-Dc9_FDkW.js.map → audit-CSjpfK6P.js.map} +1 -1
  103. package/dist/web/public/assets/{bell-CxPf_Xzs.js → bell-Dm9oEZR5.js} +2 -2
  104. package/dist/web/public/assets/{bell-CxPf_Xzs.js.map → bell-Dm9oEZR5.js.map} +1 -1
  105. package/dist/web/public/assets/{bgjobs-CYjmAJgs.js → bgjobs-IOX_MrKV.js} +2 -2
  106. package/dist/web/public/assets/{bgjobs-CYjmAJgs.js.map → bgjobs-IOX_MrKV.js.map} +1 -1
  107. package/dist/web/public/assets/{brain-DjCfwBAT.js → brain-D24bSBeM.js} +2 -2
  108. package/dist/web/public/assets/{brain-DjCfwBAT.js.map → brain-D24bSBeM.js.map} +1 -1
  109. package/dist/web/public/assets/{briefcase-Br1bd_VG.js → briefcase-BrIzC9EZ.js} +2 -2
  110. package/dist/web/public/assets/{briefcase-Br1bd_VG.js.map → briefcase-BrIzC9EZ.js.map} +1 -1
  111. package/dist/web/public/assets/{chat-uqxuXn2X.js → chat-DXki5zbL.js} +2 -2
  112. package/dist/web/public/assets/{chat-uqxuXn2X.js.map → chat-DXki5zbL.js.map} +1 -1
  113. package/dist/web/public/assets/{chevron-left-CN-4SIfi.js → chevron-left-C8Ha_lMZ.js} +2 -2
  114. package/dist/web/public/assets/{chevron-left-CN-4SIfi.js.map → chevron-left-C8Ha_lMZ.js.map} +1 -1
  115. package/dist/web/public/assets/{chevron-right-BhSTLH2K.js → chevron-right-LF_j8BGd.js} +2 -2
  116. package/dist/web/public/assets/{chevron-right-BhSTLH2K.js.map → chevron-right-LF_j8BGd.js.map} +1 -1
  117. package/dist/web/public/assets/{circle-check-B4UdHmdJ.js → circle-check-CpSR3rJi.js} +2 -2
  118. package/dist/web/public/assets/{circle-check-B4UdHmdJ.js.map → circle-check-CpSR3rJi.js.map} +1 -1
  119. package/dist/web/public/assets/{circle-check-big-CvXnDqiF.js → circle-check-big-Dbz0XziN.js} +2 -2
  120. package/dist/web/public/assets/{circle-check-big-CvXnDqiF.js.map → circle-check-big-Dbz0XziN.js.map} +1 -1
  121. package/dist/web/public/assets/{circle-x-B8y8mLHr.js → circle-x-XWMjbfp5.js} +2 -2
  122. package/dist/web/public/assets/{circle-x-B8y8mLHr.js.map → circle-x-XWMjbfp5.js.map} +1 -1
  123. package/dist/web/public/assets/{clock-CK2KO_Rc.js → clock-BjVFYz37.js} +2 -2
  124. package/dist/web/public/assets/{clock-CK2KO_Rc.js.map → clock-BjVFYz37.js.map} +1 -1
  125. package/dist/web/public/assets/{confirm-dialog-GZyIzSwj.js → confirm-dialog-C8nuBNh3.js} +2 -2
  126. package/dist/web/public/assets/{confirm-dialog-GZyIzSwj.js.map → confirm-dialog-C8nuBNh3.js.map} +1 -1
  127. package/dist/web/public/assets/{copy-CDCgL5Yq.js → copy-BUxvUnbP.js} +2 -2
  128. package/dist/web/public/assets/{copy-CDCgL5Yq.js.map → copy-BUxvUnbP.js.map} +1 -1
  129. package/dist/web/public/assets/{data-table-1cGunUIX.js → data-table-BHctKsHM.js} +2 -2
  130. package/dist/web/public/assets/{data-table-1cGunUIX.js.map → data-table-BHctKsHM.js.map} +1 -1
  131. package/dist/web/public/assets/{download-CuLP0G-q.js → download-C0hikBL7.js} +2 -2
  132. package/dist/web/public/assets/{download-CuLP0G-q.js.map → download-C0hikBL7.js.map} +1 -1
  133. package/dist/web/public/assets/{email-Q-SY9qC9.js → email-D940p9kF.js} +2 -2
  134. package/dist/web/public/assets/{email-Q-SY9qC9.js.map → email-D940p9kF.js.map} +1 -1
  135. package/dist/web/public/assets/{empty-state-BRsb30K6.js → empty-state-BzzUgjlL.js} +2 -2
  136. package/dist/web/public/assets/{empty-state-BRsb30K6.js.map → empty-state-BzzUgjlL.js.map} +1 -1
  137. package/dist/web/public/assets/{external-link-D-E90Kfw.js → external-link-Cjuz11n7.js} +2 -2
  138. package/dist/web/public/assets/{external-link-D-E90Kfw.js.map → external-link-Cjuz11n7.js.map} +1 -1
  139. package/dist/web/public/assets/{eye-DSu_4mW2.js → eye-DVQjbb2Z.js} +2 -2
  140. package/dist/web/public/assets/{eye-DSu_4mW2.js.map → eye-DVQjbb2Z.js.map} +1 -1
  141. package/dist/web/public/assets/{facts-pmGTfGmv.js → facts-C4hVaO6t.js} +2 -2
  142. package/dist/web/public/assets/{facts-pmGTfGmv.js.map → facts-C4hVaO6t.js.map} +1 -1
  143. package/dist/web/public/assets/{goals-DpRm9-av.js → goals-89sYO75m.js} +2 -2
  144. package/dist/web/public/assets/{goals-DpRm9-av.js.map → goals-89sYO75m.js.map} +1 -1
  145. package/dist/web/public/assets/{health-mqoH7KDV.js → health-CKfZBddX.js} +2 -2
  146. package/dist/web/public/assets/{health-mqoH7KDV.js.map → health-CKfZBddX.js.map} +1 -1
  147. package/dist/web/public/assets/{heart-pulse-CrCHhXtC.js → heart-pulse-BfYs3KFD.js} +2 -2
  148. package/dist/web/public/assets/{heart-pulse-CrCHhXtC.js.map → heart-pulse-BfYs3KFD.js.map} +1 -1
  149. package/dist/web/public/assets/{heartbeat-EGjLHWU0.js → heartbeat-oKkyHWgV.js} +2 -2
  150. package/dist/web/public/assets/{heartbeat-EGjLHWU0.js.map → heartbeat-oKkyHWgV.js.map} +1 -1
  151. package/dist/web/public/assets/{hot-B9x1_5yx.js → hot-Cas_nZv9.js} +2 -2
  152. package/dist/web/public/assets/{hot-B9x1_5yx.js.map → hot-Cas_nZv9.js.map} +1 -1
  153. package/dist/web/public/assets/{index-BIBWEKxu.js → index-B795P_3p.js} +34 -34
  154. package/dist/web/public/assets/index-B795P_3p.js.map +1 -0
  155. package/dist/web/public/assets/{index-Bc0H0I1S.css → index-CokfQGcz.css} +1 -1
  156. package/dist/web/public/assets/{injection-CDx5n-mk.js → injection-DksSjIsi.js} +2 -2
  157. package/dist/web/public/assets/{injection-CDx5n-mk.js.map → injection-DksSjIsi.js.map} +1 -1
  158. package/dist/web/public/assets/{installed-DV7X4wfv.js → installed-DWq0Eluy.js} +2 -2
  159. package/dist/web/public/assets/{installed-DV7X4wfv.js.map → installed-DWq0Eluy.js.map} +1 -1
  160. package/dist/web/public/assets/{jobs-zAigElCl.js → jobs-CqY-xtBr.js} +2 -2
  161. package/dist/web/public/assets/{jobs-zAigElCl.js.map → jobs-CqY-xtBr.js.map} +1 -1
  162. package/dist/web/public/assets/{layout-B0RjH6M2.js → layout-BiAVhWgU.js} +2 -2
  163. package/dist/web/public/assets/{layout-B0RjH6M2.js.map → layout-BiAVhWgU.js.map} +1 -1
  164. package/dist/web/public/assets/{layout-DOSpVfND.js → layout-BodTIhhE.js} +2 -2
  165. package/dist/web/public/assets/{layout-DOSpVfND.js.map → layout-BodTIhhE.js.map} +1 -1
  166. package/dist/web/public/assets/{layout-CzjqlPxW.js → layout-Cltp3ikG.js} +2 -2
  167. package/dist/web/public/assets/{layout-CzjqlPxW.js.map → layout-Cltp3ikG.js.map} +1 -1
  168. package/dist/web/public/assets/{layout-C6q-GbBZ.js → layout-CqgDOB5t.js} +2 -2
  169. package/dist/web/public/assets/{layout-C6q-GbBZ.js.map → layout-CqgDOB5t.js.map} +1 -1
  170. package/dist/web/public/assets/{layout-7wcifbsm.js → layout-DsoDxB0i.js} +2 -2
  171. package/dist/web/public/assets/{layout-7wcifbsm.js.map → layout-DsoDxB0i.js.map} +1 -1
  172. package/dist/web/public/assets/{llm-DwZX5fwY.js → llm-D3Kd9gqa.js} +2 -2
  173. package/dist/web/public/assets/{llm-DwZX5fwY.js.map → llm-D3Kd9gqa.js.map} +1 -1
  174. package/dist/web/public/assets/{loader-circle-BQkLEJZw.js → loader-circle-DsLQMvHE.js} +2 -2
  175. package/dist/web/public/assets/{loader-circle-BQkLEJZw.js.map → loader-circle-DsLQMvHE.js.map} +1 -1
  176. package/dist/web/public/assets/{map-pin-B-IMY07m.js → map-pin-e694Eet6.js} +2 -2
  177. package/dist/web/public/assets/{map-pin-B-IMY07m.js.map → map-pin-e694Eet6.js.map} +1 -1
  178. package/dist/web/public/assets/{mcp-K0P3-b6q.js → mcp-BoWJqog4.js} +2 -2
  179. package/dist/web/public/assets/{mcp-K0P3-b6q.js.map → mcp-BoWJqog4.js.map} +1 -1
  180. package/dist/web/public/assets/{memos-DcpDEVN8.js → memos-C81bimPJ.js} +2 -2
  181. package/dist/web/public/assets/{memos-DcpDEVN8.js.map → memos-C81bimPJ.js.map} +1 -1
  182. package/dist/web/public/assets/{messengers-DmrNvPMS.js → messengers-CGcjXUeJ.js} +2 -2
  183. package/dist/web/public/assets/{messengers-DmrNvPMS.js.map → messengers-CGcjXUeJ.js.map} +1 -1
  184. package/dist/web/public/assets/{mobile-a-oUiAoR.js → mobile-Duy_If5A.js} +2 -2
  185. package/dist/web/public/assets/{mobile-a-oUiAoR.js.map → mobile-Duy_If5A.js.map} +1 -1
  186. package/dist/web/public/assets/{network-Bbh3j5ew.js → network-DnBhCncp.js} +2 -2
  187. package/dist/web/public/assets/{network-Bbh3j5ew.js.map → network-DnBhCncp.js.map} +1 -1
  188. package/dist/web/public/assets/{outbox-BP_hfANb.js → outbox-DrReVtHr.js} +2 -2
  189. package/dist/web/public/assets/{outbox-BP_hfANb.js.map → outbox-DrReVtHr.js.map} +1 -1
  190. package/dist/web/public/assets/{pagination-CPLj3V0r.js → pagination-DgS8vaZM.js} +2 -2
  191. package/dist/web/public/assets/{pagination-CPLj3V0r.js.map → pagination-DgS8vaZM.js.map} +1 -1
  192. package/dist/web/public/assets/{persona-CT38dLd4.js → persona-NTg-RuPa.js} +2 -2
  193. package/dist/web/public/assets/{persona-CT38dLd4.js.map → persona-NTg-RuPa.js.map} +1 -1
  194. package/dist/web/public/assets/{plans-Msw85XkI.js → plans-CUsr4aMb.js} +2 -2
  195. package/dist/web/public/assets/{plans-Msw85XkI.js.map → plans-CUsr4aMb.js.map} +1 -1
  196. package/dist/web/public/assets/{play-tH2nb1Kt.js → play-G96k2QBR.js} +2 -2
  197. package/dist/web/public/assets/{play-tH2nb1Kt.js.map → play-G96k2QBR.js.map} +1 -1
  198. package/dist/web/public/assets/{plus-6MNGQidu.js → plus-6RZ3XScp.js} +2 -2
  199. package/dist/web/public/assets/{plus-6MNGQidu.js.map → plus-6RZ3XScp.js.map} +1 -1
  200. package/dist/web/public/assets/{policy-BJ7zORVG.js → policy-BFlQnPo5.js} +2 -2
  201. package/dist/web/public/assets/{policy-BJ7zORVG.js.map → policy-BFlQnPo5.js.map} +1 -1
  202. package/dist/web/public/assets/{qr-code-DfsxFxoa.js → qr-code-L7ClZ31U.js} +2 -2
  203. package/dist/web/public/assets/{qr-code-DfsxFxoa.js.map → qr-code-L7ClZ31U.js.map} +1 -1
  204. package/dist/web/public/assets/{refresh-ccw-CFPE6zD1.js → refresh-ccw-S3sFYfDb.js} +2 -2
  205. package/dist/web/public/assets/{refresh-ccw-CFPE6zD1.js.map → refresh-ccw-S3sFYfDb.js.map} +1 -1
  206. package/dist/web/public/assets/{reminders-CAUNAuDy.js → reminders-DVzHdBpK.js} +2 -2
  207. package/dist/web/public/assets/{reminders-CAUNAuDy.js.map → reminders-DVzHdBpK.js.map} +1 -1
  208. package/dist/web/public/assets/{save-CNUmUMEf.js → save-DetwgDjo.js} +2 -2
  209. package/dist/web/public/assets/{save-CNUmUMEf.js.map → save-DetwgDjo.js.map} +1 -1
  210. package/dist/web/public/assets/{schedules-C25NyoGh.js → schedules-CslP2Ntr.js} +2 -2
  211. package/dist/web/public/assets/{schedules-C25NyoGh.js.map → schedules-CslP2Ntr.js.map} +1 -1
  212. package/dist/web/public/assets/{search-D9TZs0bG.js → search-Bx2TNvqF.js} +2 -2
  213. package/dist/web/public/assets/{search-D9TZs0bG.js.map → search-Bx2TNvqF.js.map} +1 -1
  214. package/dist/web/public/assets/{search-CaRTqZw1.js → search-ByHc__pY.js} +2 -2
  215. package/dist/web/public/assets/{search-CaRTqZw1.js.map → search-ByHc__pY.js.map} +1 -1
  216. package/dist/web/public/assets/{security-BMGGzEwr.js → security-B4dw2-ZU.js} +2 -2
  217. package/dist/web/public/assets/{security-BMGGzEwr.js.map → security-B4dw2-ZU.js.map} +1 -1
  218. package/dist/web/public/assets/{service-BQBoddcT.js → service-LujRx8DT.js} +2 -2
  219. package/dist/web/public/assets/{service-BQBoddcT.js.map → service-LujRx8DT.js.map} +1 -1
  220. package/dist/web/public/assets/{shield-alert-eOBoc2yc.js → shield-alert-BM2sbwiD.js} +2 -2
  221. package/dist/web/public/assets/{shield-alert-eOBoc2yc.js.map → shield-alert-BM2sbwiD.js.map} +1 -1
  222. package/dist/web/public/assets/{status-badge-CF1Cya26.js → status-badge-Bz0a-nE1.js} +2 -2
  223. package/dist/web/public/assets/{status-badge-CF1Cya26.js.map → status-badge-Bz0a-nE1.js.map} +1 -1
  224. package/dist/web/public/assets/{subtasks-CEPB2TSV.js → subtasks-BEAppda9.js} +2 -2
  225. package/dist/web/public/assets/{subtasks-CEPB2TSV.js.map → subtasks-BEAppda9.js.map} +1 -1
  226. package/dist/web/public/assets/{table-Dww-k14l.js → table-Dl8Faxz-.js} +2 -2
  227. package/dist/web/public/assets/{table-Dww-k14l.js.map → table-Dl8Faxz-.js.map} +1 -1
  228. package/dist/web/public/assets/{topn-DwgKlIxc.js → topn-CXTn3Qdn.js} +2 -2
  229. package/dist/web/public/assets/{topn-DwgKlIxc.js.map → topn-CXTn3Qdn.js.map} +1 -1
  230. package/dist/web/public/assets/{trash-2-BF98SY8M.js → trash-2-DUSLukqd.js} +2 -2
  231. package/dist/web/public/assets/{trash-2-BF98SY8M.js.map → trash-2-DUSLukqd.js.map} +1 -1
  232. package/dist/web/public/assets/{use-agim-skills-kDpiSMBP.js → use-agim-skills-BD1AIi8d.js} +2 -2
  233. package/dist/web/public/assets/{use-agim-skills-kDpiSMBP.js.map → use-agim-skills-BD1AIi8d.js.map} +1 -1
  234. package/dist/web/public/assets/{use-background-tasks-B1Pxq3JU.js → use-background-tasks-FuodO-_C.js} +2 -2
  235. package/dist/web/public/assets/{use-background-tasks-B1Pxq3JU.js.map → use-background-tasks-FuodO-_C.js.map} +1 -1
  236. package/dist/web/public/assets/{use-memory-w-EY79Zm.js → use-memory-4xOyJX4L.js} +2 -2
  237. package/dist/web/public/assets/{use-memory-w-EY79Zm.js.map → use-memory-4xOyJX4L.js.map} +1 -1
  238. package/dist/web/public/assets/{use-observability-Cd2dUHb7.js → use-observability-DMebP5-1.js} +2 -2
  239. package/dist/web/public/assets/{use-observability-Cd2dUHb7.js.map → use-observability-DMebP5-1.js.map} +1 -1
  240. package/dist/web/public/assets/{use-settings-DG1rm9KU.js → use-settings-GPajsGBB.js} +2 -2
  241. package/dist/web/public/assets/{use-settings-DG1rm9KU.js.map → use-settings-GPajsGBB.js.map} +1 -1
  242. package/dist/web/public/assets/{use-workspace-DvW_xOmj.js → use-workspace-C6qix-sY.js} +2 -2
  243. package/dist/web/public/assets/{use-workspace-DvW_xOmj.js.map → use-workspace-C6qix-sY.js.map} +1 -1
  244. package/dist/web/public/assets/{vector-CDJ4p6UI.js → vector-hGc2RFNQ.js} +2 -2
  245. package/dist/web/public/assets/{vector-CDJ4p6UI.js.map → vector-hGc2RFNQ.js.map} +1 -1
  246. package/dist/web/public/assets/{viewer-Bje5-HtQ.js → viewer-YkLMRkmd.js} +2 -2
  247. package/dist/web/public/assets/{viewer-Bje5-HtQ.js.map → viewer-YkLMRkmd.js.map} +1 -1
  248. package/dist/web/public/assets/{workspace-B7QYGLix.js → workspace-0GRMLd5j.js} +2 -2
  249. package/dist/web/public/assets/{workspace-B7QYGLix.js.map → workspace-0GRMLd5j.js.map} +1 -1
  250. package/dist/web/public/assets/{workspaces-BlodF0DP.js → workspaces-DPa7ByRm.js} +2 -2
  251. package/dist/web/public/assets/{workspaces-BlodF0DP.js.map → workspaces-DPa7ByRm.js.map} +1 -1
  252. package/dist/web/public/index.html +2 -2
  253. package/dist/web/server.d.ts.map +1 -1
  254. package/dist/web/server.js +4 -2
  255. package/dist/web/server.js.map +1 -1
  256. package/package.json +1 -1
  257. package/dist/web/public/assets/index-BIBWEKxu.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"jobs-zAigElCl.js","sources":["../../src/hooks/use-jobs.ts","../../src/routes/tasks/jobs.tsx"],"sourcesContent":["/**\n * useJobs — react-query wrappers for the jobs domain.\n *\n * useJobs(query) — list with filter / pagination\n * useBatchCancelJobs() — bulk cancel mutation\n * useBatchRunJobs() — bulk re-run mutation\n *\n * Query keys: `['jobs', 'list', stableQuery]` so SSE invalidation\n * via useEventStream({ job: () => qc.invalidateQueries(['jobs']) })\n * clears every list view at once. The serialised query object is\n * stable across renders (react-query handles deep equality), so\n * keying on it directly is safe.\n *\n * Why hooks not raw `useQuery`: every route hits the same listJobs\n * endpoint with similar shapes; centralising the key + error toast\n * (caller-supplied) here keeps the route files focused on layout.\n */\n\nimport { useQueryClient, useMutation, useQuery } from '@tanstack/react-query'\nimport { api } from '@/lib/api/endpoints'\nimport type { BatchJobBody, ListJobsQuery, ListJobsResponse } from '@/types/api'\n\nexport const jobsKeys = {\n all: ['jobs'] as const,\n list: (q: ListJobsQuery) => ['jobs', 'list', q] as const,\n}\n\nexport function useJobs(query: ListJobsQuery) {\n return useQuery<ListJobsResponse>({\n queryKey: jobsKeys.list(query),\n queryFn: () => api.listJobs(query),\n })\n}\n\n/** Force-refresh every jobs list view. Call this from the SSE\n * `job` handler in route files. */\nexport function useInvalidateJobs() {\n const qc = useQueryClient()\n return () => qc.invalidateQueries({ queryKey: jobsKeys.all })\n}\n\nexport function useBatchCancelJobs() {\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (body: BatchJobBody) => api.batchCancelJobs(body),\n onSuccess: () => qc.invalidateQueries({ queryKey: jobsKeys.all }),\n })\n}\n\nexport function useBatchRunJobs() {\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (body: BatchJobBody) => api.batchRunJobs(body),\n onSuccess: () => qc.invalidateQueries({ queryKey: jobsKeys.all }),\n })\n}\n","/**\n * /tasks/jobs — the long-running agent invocations list.\n *\n * Composes every PR-8/9 primitive: DataTable + StatusBadge + Pagination\n * + ConfirmDialog + EmptyState + useEventStream. The route is a thin\n * presenter: data via useJobs (react-query), URL state via useSearchParams,\n * live refresh via the SSE `job` event invalidating the jobs query key.\n *\n * URL contract (all params optional):\n * ?page=2&per_page=20&status=running\n *\n * Why URL state rather than zustand:\n * * deep-link friendly (\"show me failed jobs page 3\")\n * * back/forward browser history navigates filter state\n * * no risk of a leftover filter showing wrong rows after route swap\n *\n * Mobile: the DataTable already swaps to a card view below md. The\n * stats strip wraps; the filter row stacks vertically.\n */\n\nimport { useMemo, useState } from 'react'\nimport { useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { Briefcase, Loader2, RefreshCcw, XCircle } from 'lucide-react'\n\nimport { DataTable, type DataTableColumn } from '@/components/common/data-table'\nimport { EmptyState } from '@/components/common/empty-state'\nimport { StatusBadge } from '@/components/common/status-badge'\nimport { Pagination } from '@/components/common/pagination'\nimport { ConfirmDialog } from '@/components/common/confirm-dialog'\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 {\n useJobs,\n useInvalidateJobs,\n useBatchCancelJobs,\n} from '@/hooks/use-jobs'\nimport { useEventStream, type SseStatus } from '@/hooks/use-event-stream'\nimport type { Job, JobStatus, ListJobsQuery } from '@/types/api'\nimport { describeError } from '@/lib/api/errors'\nimport { cn } from '@/lib/utils'\n\nconst PER_PAGE_OPTIONS = [10, 20, 50, 100]\nconst DEFAULT_PER_PAGE = 20\n\nconst STATUS_OPTIONS: JobStatus[] = [\n 'pending',\n 'running',\n 'completed',\n 'delivered',\n 'failed',\n 'cancelled',\n 'interrupted',\n 'replaced',\n 'abandoned',\n]\n\nconst LIVE_STATUS_CLASS: Record<SseStatus, string> = {\n connected: 'text-success',\n connecting: 'text-text-dim',\n reconnecting: 'text-warning',\n closed: 'text-text-muted',\n}\n\nexport default function JobsRoute(): JSX.Element {\n const { t } = useTranslation(['tasks', 'common'])\n const [params, setParams] = useSearchParams()\n const invalidateJobs = useInvalidateJobs()\n\n // ─── URL state ───\n const page = Math.max(1, Number(params.get('page')) || 1)\n const perPage = Number(params.get('per_page')) || DEFAULT_PER_PAGE\n const status = (params.get('status') as JobStatus | null) ?? null\n\n const query: ListJobsQuery = useMemo(\n () => ({\n limit: perPage,\n offset: (page - 1) * perPage,\n ...(status ? { status } : {}),\n }),\n [page, perPage, status],\n )\n\n const { data, isLoading, isFetching, refetch } = useJobs(query)\n const jobs = data?.jobs ?? []\n const stats = data?.stats\n\n // ─── Live refresh via SSE ───\n const live = useEventStream({\n job: () => invalidateJobs(),\n })\n\n // ─── Selection ───\n const [selection, setSelection] = useState<Set<string>>(new Set())\n\n // ─── Confirm dialog ───\n const [confirmCancelOpen, setConfirmCancelOpen] = useState(false)\n const batchCancel = useBatchCancelJobs()\n\n async function onConfirmBatchCancel(): Promise<void> {\n const ids = Array.from(selection).map(Number).filter(Number.isFinite)\n if (ids.length === 0) return\n try {\n await batchCancel.mutateAsync({ ids })\n setSelection(new Set())\n toast.success(t('states.saved', { ns: 'common' }))\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n throw err // keep dialog open\n }\n }\n\n // ─── URL writers (single source of truth for filter state) ───\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 // Any filter change implicitly resets to page 1.\n if (Object.keys(patch).some((k) => k !== 'page')) next.delete('page')\n setParams(next, { replace: false })\n }\n\n // ─── Derived ───\n // The backend doesn't ship a true total-count field. Until it does\n // we infer pagination from the page itself: if a page returns a\n // full page, assume there's at least one more; otherwise this is\n // the last one. Stats give an exact total of pending/running but\n // not \"all kinds\", so the page label stays \"Page X of N\" with N\n // derived conservatively.\n const totalRows = stats\n ? (stats.pending + stats.running + stats.completed + stats.failed + (stats.delivered ?? 0))\n : undefined\n const totalPages = totalRows\n ? Math.max(1, Math.ceil(totalRows / perPage))\n : jobs.length === perPage ? page + 1 : page\n\n // ─── Columns ───\n const columns: DataTableColumn<Job>[] = useMemo(\n () => [\n {\n id: 'id',\n header: t('jobs.col.id'),\n cell: (r) => <span className=\"tabular-nums text-text-dim\">#{r.id}</span>,\n headClassName: 'w-16',\n hideOnMobile: false,\n },\n {\n id: 'agent',\n header: t('jobs.col.agent'),\n cell: (r) => <span className=\"font-medium\">{r.agent}</span>,\n headClassName: 'w-32',\n },\n {\n id: 'prompt',\n header: t('jobs.col.prompt'),\n cell: (r) => (\n <span className=\"line-clamp-2 text-text-dim\">{r.prompt}</span>\n ),\n asCardTitle: true,\n },\n {\n id: 'status',\n header: t('jobs.col.status'),\n cell: (r) => (\n <StatusBadge status={r.status}>\n {t(`jobs.status.${r.status}`, { defaultValue: r.status })}\n </StatusBadge>\n ),\n headClassName: 'w-32',\n },\n {\n id: 'createdAt',\n header: t('jobs.col.createdAt'),\n cell: (r) => <span className=\"text-text-dim\">{formatTime(r.created_at)}</span>,\n headClassName: 'w-40',\n hideOnMobile: true,\n },\n {\n id: 'duration',\n header: t('jobs.col.duration'),\n cell: (r) => (\n <span className=\"tabular-nums text-text-dim\">{formatDuration(r.duration_ms)}</span>\n ),\n headClassName: 'w-24',\n hideOnMobile: true,\n },\n {\n id: 'cost',\n header: t('jobs.col.cost'),\n cell: (r) => (\n <span className=\"tabular-nums text-text-dim\">\n {r.cost != null ? `$${r.cost.toFixed(4)}` : '—'}\n </span>\n ),\n headClassName: 'w-24',\n hideOnMobile: true,\n },\n ],\n [t],\n )\n\n const selectedCount = selection.size\n\n return (\n <div className=\"mx-auto flex max-w-7xl flex-col gap-4\">\n {/* Page header */}\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('jobs.title')}</h1>\n <span className={cn('text-xs font-medium tabular-nums', LIVE_STATUS_CLASS[live])}>\n {t(`jobs.live.${live}`)}\n </span>\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('jobs.subtitle')}</p>\n </header>\n\n {/* Stats KPI strip */}\n {stats && (\n <div className=\"grid grid-cols-2 gap-2 sm:grid-cols-4\">\n <StatCard label={t('jobs.stats.pending')} value={stats.pending} tone=\"info\" />\n <StatCard label={t('jobs.stats.running')} value={stats.running} tone=\"warning\" />\n <StatCard label={t('jobs.stats.completed')} value={stats.completed} tone=\"success\" />\n <StatCard label={t('jobs.stats.failed')} value={stats.failed} tone=\"danger\" />\n </div>\n )}\n\n {/* Filter row */}\n <div className=\"flex flex-wrap items-center gap-2\">\n <div className=\"flex items-center gap-2\">\n <label className=\"text-sm text-text-dim\" htmlFor=\"status-filter\">\n {t('jobs.filter.status')}\n </label>\n <Select\n value={status ?? '__any__'}\n onValueChange={(v) => patchParams({ status: v === '__any__' ? null : v })}\n >\n <SelectTrigger id=\"status-filter\" className=\"w-[160px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__any__\">{t('jobs.filter.statusAny')}</SelectItem>\n {STATUS_OPTIONS.map((s) => (\n <SelectItem key={s} value={s}>\n {t(`jobs.status.${s}`, { defaultValue: s })}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {/* Bulk action bar — appears when rows are selected. */}\n {selectedCount > 0 && (\n <div className=\"ml-auto flex items-center gap-2\">\n <Badge variant=\"secondary\">\n {t('jobs.batch.selected', { count: selectedCount })}\n </Badge>\n <Button\n variant=\"destructive\"\n size=\"sm\"\n onClick={() => setConfirmCancelOpen(true)}\n disabled={batchCancel.isPending}\n >\n <XCircle className=\"h-4 w-4\" />\n {t('jobs.batch.cancel')}\n </Button>\n </div>\n )}\n </div>\n\n {/* Table */}\n <DataTable\n columns={columns}\n rows={jobs}\n getRowId={(r) => String(r.id)}\n loading={isLoading}\n selection={selection}\n onSelectionChange={setSelection}\n emptyState={\n <EmptyState\n icon={<Briefcase />}\n title={t('jobs.empty.title')}\n description={t('jobs.empty.description')}\n />\n }\n />\n\n {/* Footer pagination */}\n {(jobs.length > 0 || page > 1) && (\n <Pagination\n page={page}\n totalPages={totalPages}\n totalRows={totalRows}\n perPage={perPage}\n perPageOptions={PER_PAGE_OPTIONS}\n onPageChange={(p) => patchParams({ page: p === 1 ? null : String(p) })}\n onPerPageChange={(pp) => patchParams({ per_page: pp === DEFAULT_PER_PAGE ? null : String(pp) })}\n />\n )}\n\n <ConfirmDialog\n open={confirmCancelOpen}\n onOpenChange={setConfirmCancelOpen}\n title={t('jobs.batch.confirmCancel', { count: selectedCount })}\n description={t('jobs.batch.confirmCancelDesc')}\n intent=\"danger\"\n confirmLabel={t('jobs.batch.cancel')}\n onConfirm={onConfirmBatchCancel}\n />\n </div>\n )\n}\n\n// ─── Helpers ───\n\ninterface StatCardProps {\n label: string\n value: number\n tone: 'info' | 'success' | 'warning' | 'danger'\n}\n\nconst TONE_STYLES: Record<StatCardProps['tone'], string> = {\n info: 'border-info/30 text-info',\n success: 'border-success/30 text-success',\n warning: 'border-warning/30 text-warning',\n danger: 'border-danger/30 text-danger',\n}\n\nfunction StatCard({ label, value, tone }: StatCardProps): JSX.Element {\n return (\n <div\n className={cn(\n 'rounded-md border bg-surface px-3 py-2',\n TONE_STYLES[tone],\n )}\n >\n <div className=\"text-xs uppercase tracking-wide text-text-dim\">{label}</div>\n <div className=\"text-2xl font-semibold tabular-nums\">{value}</div>\n </div>\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', second: '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\nfunction formatDuration(ms: number | undefined): string {\n if (ms == null) return '—'\n if (ms < 1000) return `${ms}ms`\n const s = ms / 1000\n if (s < 60) return `${s.toFixed(1)}s`\n const m = Math.floor(s / 60)\n const rs = Math.round(s - m * 60)\n return `${m}m${rs}s`\n}\n"],"names":["jobsKeys","q","useJobs","query","useQuery","api","useInvalidateJobs","qc","useQueryClient","useBatchCancelJobs","useMutation","body","PER_PAGE_OPTIONS","DEFAULT_PER_PAGE","STATUS_OPTIONS","LIVE_STATUS_CLASS","JobsRoute","t","useTranslation","params","setParams","useSearchParams","invalidateJobs","page","perPage","status","useMemo","data","isLoading","isFetching","refetch","jobs","stats","live","useEventStream","selection","setSelection","useState","confirmCancelOpen","setConfirmCancelOpen","batchCancel","onConfirmBatchCancel","ids","toast","err","message","describeError","patchParams","patch","next","k","v","totalRows","totalPages","columns","r","jsxs","jsx","StatusBadge","formatTime","formatDuration","selectedCount","cn","Button","Loader2","RefreshCcw","StatCard","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","Badge","XCircle","DataTable","EmptyState","Briefcase","Pagination","p","pp","ConfirmDialog","TONE_STYLES","label","value","tone","iso","d","now","ms","s","m","rs"],"mappings":"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"}
1
+ {"version":3,"file":"jobs-CqY-xtBr.js","sources":["../../src/hooks/use-jobs.ts","../../src/routes/tasks/jobs.tsx"],"sourcesContent":["/**\n * useJobs — react-query wrappers for the jobs domain.\n *\n * useJobs(query) — list with filter / pagination\n * useBatchCancelJobs() — bulk cancel mutation\n * useBatchRunJobs() — bulk re-run mutation\n *\n * Query keys: `['jobs', 'list', stableQuery]` so SSE invalidation\n * via useEventStream({ job: () => qc.invalidateQueries(['jobs']) })\n * clears every list view at once. The serialised query object is\n * stable across renders (react-query handles deep equality), so\n * keying on it directly is safe.\n *\n * Why hooks not raw `useQuery`: every route hits the same listJobs\n * endpoint with similar shapes; centralising the key + error toast\n * (caller-supplied) here keeps the route files focused on layout.\n */\n\nimport { useQueryClient, useMutation, useQuery } from '@tanstack/react-query'\nimport { api } from '@/lib/api/endpoints'\nimport type { BatchJobBody, ListJobsQuery, ListJobsResponse } from '@/types/api'\n\nexport const jobsKeys = {\n all: ['jobs'] as const,\n list: (q: ListJobsQuery) => ['jobs', 'list', q] as const,\n}\n\nexport function useJobs(query: ListJobsQuery) {\n return useQuery<ListJobsResponse>({\n queryKey: jobsKeys.list(query),\n queryFn: () => api.listJobs(query),\n })\n}\n\n/** Force-refresh every jobs list view. Call this from the SSE\n * `job` handler in route files. */\nexport function useInvalidateJobs() {\n const qc = useQueryClient()\n return () => qc.invalidateQueries({ queryKey: jobsKeys.all })\n}\n\nexport function useBatchCancelJobs() {\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (body: BatchJobBody) => api.batchCancelJobs(body),\n onSuccess: () => qc.invalidateQueries({ queryKey: jobsKeys.all }),\n })\n}\n\nexport function useBatchRunJobs() {\n const qc = useQueryClient()\n return useMutation({\n mutationFn: (body: BatchJobBody) => api.batchRunJobs(body),\n onSuccess: () => qc.invalidateQueries({ queryKey: jobsKeys.all }),\n })\n}\n","/**\n * /tasks/jobs — the long-running agent invocations list.\n *\n * Composes every PR-8/9 primitive: DataTable + StatusBadge + Pagination\n * + ConfirmDialog + EmptyState + useEventStream. The route is a thin\n * presenter: data via useJobs (react-query), URL state via useSearchParams,\n * live refresh via the SSE `job` event invalidating the jobs query key.\n *\n * URL contract (all params optional):\n * ?page=2&per_page=20&status=running\n *\n * Why URL state rather than zustand:\n * * deep-link friendly (\"show me failed jobs page 3\")\n * * back/forward browser history navigates filter state\n * * no risk of a leftover filter showing wrong rows after route swap\n *\n * Mobile: the DataTable already swaps to a card view below md. The\n * stats strip wraps; the filter row stacks vertically.\n */\n\nimport { useMemo, useState } from 'react'\nimport { useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { Briefcase, Loader2, RefreshCcw, XCircle } from 'lucide-react'\n\nimport { DataTable, type DataTableColumn } from '@/components/common/data-table'\nimport { EmptyState } from '@/components/common/empty-state'\nimport { StatusBadge } from '@/components/common/status-badge'\nimport { Pagination } from '@/components/common/pagination'\nimport { ConfirmDialog } from '@/components/common/confirm-dialog'\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 {\n useJobs,\n useInvalidateJobs,\n useBatchCancelJobs,\n} from '@/hooks/use-jobs'\nimport { useEventStream, type SseStatus } from '@/hooks/use-event-stream'\nimport type { Job, JobStatus, ListJobsQuery } from '@/types/api'\nimport { describeError } from '@/lib/api/errors'\nimport { cn } from '@/lib/utils'\n\nconst PER_PAGE_OPTIONS = [10, 20, 50, 100]\nconst DEFAULT_PER_PAGE = 20\n\nconst STATUS_OPTIONS: JobStatus[] = [\n 'pending',\n 'running',\n 'completed',\n 'delivered',\n 'failed',\n 'cancelled',\n 'interrupted',\n 'replaced',\n 'abandoned',\n]\n\nconst LIVE_STATUS_CLASS: Record<SseStatus, string> = {\n connected: 'text-success',\n connecting: 'text-text-dim',\n reconnecting: 'text-warning',\n closed: 'text-text-muted',\n}\n\nexport default function JobsRoute(): JSX.Element {\n const { t } = useTranslation(['tasks', 'common'])\n const [params, setParams] = useSearchParams()\n const invalidateJobs = useInvalidateJobs()\n\n // ─── URL state ───\n const page = Math.max(1, Number(params.get('page')) || 1)\n const perPage = Number(params.get('per_page')) || DEFAULT_PER_PAGE\n const status = (params.get('status') as JobStatus | null) ?? null\n\n const query: ListJobsQuery = useMemo(\n () => ({\n limit: perPage,\n offset: (page - 1) * perPage,\n ...(status ? { status } : {}),\n }),\n [page, perPage, status],\n )\n\n const { data, isLoading, isFetching, refetch } = useJobs(query)\n const jobs = data?.jobs ?? []\n const stats = data?.stats\n\n // ─── Live refresh via SSE ───\n const live = useEventStream({\n job: () => invalidateJobs(),\n })\n\n // ─── Selection ───\n const [selection, setSelection] = useState<Set<string>>(new Set())\n\n // ─── Confirm dialog ───\n const [confirmCancelOpen, setConfirmCancelOpen] = useState(false)\n const batchCancel = useBatchCancelJobs()\n\n async function onConfirmBatchCancel(): Promise<void> {\n const ids = Array.from(selection).map(Number).filter(Number.isFinite)\n if (ids.length === 0) return\n try {\n await batchCancel.mutateAsync({ ids })\n setSelection(new Set())\n toast.success(t('states.saved', { ns: 'common' }))\n } catch (err) {\n const { message } = describeError(err, t)\n toast.error(message)\n throw err // keep dialog open\n }\n }\n\n // ─── URL writers (single source of truth for filter state) ───\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 // Any filter change implicitly resets to page 1.\n if (Object.keys(patch).some((k) => k !== 'page')) next.delete('page')\n setParams(next, { replace: false })\n }\n\n // ─── Derived ───\n // The backend doesn't ship a true total-count field. Until it does\n // we infer pagination from the page itself: if a page returns a\n // full page, assume there's at least one more; otherwise this is\n // the last one. Stats give an exact total of pending/running but\n // not \"all kinds\", so the page label stays \"Page X of N\" with N\n // derived conservatively.\n const totalRows = stats\n ? (stats.pending + stats.running + stats.completed + stats.failed + (stats.delivered ?? 0))\n : undefined\n const totalPages = totalRows\n ? Math.max(1, Math.ceil(totalRows / perPage))\n : jobs.length === perPage ? page + 1 : page\n\n // ─── Columns ───\n const columns: DataTableColumn<Job>[] = useMemo(\n () => [\n {\n id: 'id',\n header: t('jobs.col.id'),\n cell: (r) => <span className=\"tabular-nums text-text-dim\">#{r.id}</span>,\n headClassName: 'w-16',\n hideOnMobile: false,\n },\n {\n id: 'agent',\n header: t('jobs.col.agent'),\n cell: (r) => <span className=\"font-medium\">{r.agent}</span>,\n headClassName: 'w-32',\n },\n {\n id: 'prompt',\n header: t('jobs.col.prompt'),\n cell: (r) => (\n <span className=\"line-clamp-2 text-text-dim\">{r.prompt}</span>\n ),\n asCardTitle: true,\n },\n {\n id: 'status',\n header: t('jobs.col.status'),\n cell: (r) => (\n <StatusBadge status={r.status}>\n {t(`jobs.status.${r.status}`, { defaultValue: r.status })}\n </StatusBadge>\n ),\n headClassName: 'w-32',\n },\n {\n id: 'createdAt',\n header: t('jobs.col.createdAt'),\n cell: (r) => <span className=\"text-text-dim\">{formatTime(r.created_at)}</span>,\n headClassName: 'w-40',\n hideOnMobile: true,\n },\n {\n id: 'duration',\n header: t('jobs.col.duration'),\n cell: (r) => (\n <span className=\"tabular-nums text-text-dim\">{formatDuration(r.duration_ms)}</span>\n ),\n headClassName: 'w-24',\n hideOnMobile: true,\n },\n {\n id: 'cost',\n header: t('jobs.col.cost'),\n cell: (r) => (\n <span className=\"tabular-nums text-text-dim\">\n {r.cost != null ? `$${r.cost.toFixed(4)}` : '—'}\n </span>\n ),\n headClassName: 'w-24',\n hideOnMobile: true,\n },\n ],\n [t],\n )\n\n const selectedCount = selection.size\n\n return (\n <div className=\"mx-auto flex max-w-7xl flex-col gap-4\">\n {/* Page header */}\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('jobs.title')}</h1>\n <span className={cn('text-xs font-medium tabular-nums', LIVE_STATUS_CLASS[live])}>\n {t(`jobs.live.${live}`)}\n </span>\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('jobs.subtitle')}</p>\n </header>\n\n {/* Stats KPI strip */}\n {stats && (\n <div className=\"grid grid-cols-2 gap-2 sm:grid-cols-4\">\n <StatCard label={t('jobs.stats.pending')} value={stats.pending} tone=\"info\" />\n <StatCard label={t('jobs.stats.running')} value={stats.running} tone=\"warning\" />\n <StatCard label={t('jobs.stats.completed')} value={stats.completed} tone=\"success\" />\n <StatCard label={t('jobs.stats.failed')} value={stats.failed} tone=\"danger\" />\n </div>\n )}\n\n {/* Filter row */}\n <div className=\"flex flex-wrap items-center gap-2\">\n <div className=\"flex items-center gap-2\">\n <label className=\"text-sm text-text-dim\" htmlFor=\"status-filter\">\n {t('jobs.filter.status')}\n </label>\n <Select\n value={status ?? '__any__'}\n onValueChange={(v) => patchParams({ status: v === '__any__' ? null : v })}\n >\n <SelectTrigger id=\"status-filter\" className=\"w-[160px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__any__\">{t('jobs.filter.statusAny')}</SelectItem>\n {STATUS_OPTIONS.map((s) => (\n <SelectItem key={s} value={s}>\n {t(`jobs.status.${s}`, { defaultValue: s })}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {/* Bulk action bar — appears when rows are selected. */}\n {selectedCount > 0 && (\n <div className=\"ml-auto flex items-center gap-2\">\n <Badge variant=\"secondary\">\n {t('jobs.batch.selected', { count: selectedCount })}\n </Badge>\n <Button\n variant=\"destructive\"\n size=\"sm\"\n onClick={() => setConfirmCancelOpen(true)}\n disabled={batchCancel.isPending}\n >\n <XCircle className=\"h-4 w-4\" />\n {t('jobs.batch.cancel')}\n </Button>\n </div>\n )}\n </div>\n\n {/* Table */}\n <DataTable\n columns={columns}\n rows={jobs}\n getRowId={(r) => String(r.id)}\n loading={isLoading}\n selection={selection}\n onSelectionChange={setSelection}\n emptyState={\n <EmptyState\n icon={<Briefcase />}\n title={t('jobs.empty.title')}\n description={t('jobs.empty.description')}\n />\n }\n />\n\n {/* Footer pagination */}\n {(jobs.length > 0 || page > 1) && (\n <Pagination\n page={page}\n totalPages={totalPages}\n totalRows={totalRows}\n perPage={perPage}\n perPageOptions={PER_PAGE_OPTIONS}\n onPageChange={(p) => patchParams({ page: p === 1 ? null : String(p) })}\n onPerPageChange={(pp) => patchParams({ per_page: pp === DEFAULT_PER_PAGE ? null : String(pp) })}\n />\n )}\n\n <ConfirmDialog\n open={confirmCancelOpen}\n onOpenChange={setConfirmCancelOpen}\n title={t('jobs.batch.confirmCancel', { count: selectedCount })}\n description={t('jobs.batch.confirmCancelDesc')}\n intent=\"danger\"\n confirmLabel={t('jobs.batch.cancel')}\n onConfirm={onConfirmBatchCancel}\n />\n </div>\n )\n}\n\n// ─── Helpers ───\n\ninterface StatCardProps {\n label: string\n value: number\n tone: 'info' | 'success' | 'warning' | 'danger'\n}\n\nconst TONE_STYLES: Record<StatCardProps['tone'], string> = {\n info: 'border-info/30 text-info',\n success: 'border-success/30 text-success',\n warning: 'border-warning/30 text-warning',\n danger: 'border-danger/30 text-danger',\n}\n\nfunction StatCard({ label, value, tone }: StatCardProps): JSX.Element {\n return (\n <div\n className={cn(\n 'rounded-md border bg-surface px-3 py-2',\n TONE_STYLES[tone],\n )}\n >\n <div className=\"text-xs uppercase tracking-wide text-text-dim\">{label}</div>\n <div className=\"text-2xl font-semibold tabular-nums\">{value}</div>\n </div>\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', second: '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\nfunction formatDuration(ms: number | undefined): string {\n if (ms == null) return '—'\n if (ms < 1000) return `${ms}ms`\n const s = ms / 1000\n if (s < 60) return `${s.toFixed(1)}s`\n const m = Math.floor(s / 60)\n const rs = Math.round(s - m * 60)\n return `${m}m${rs}s`\n}\n"],"names":["jobsKeys","q","useJobs","query","useQuery","api","useInvalidateJobs","qc","useQueryClient","useBatchCancelJobs","useMutation","body","PER_PAGE_OPTIONS","DEFAULT_PER_PAGE","STATUS_OPTIONS","LIVE_STATUS_CLASS","JobsRoute","t","useTranslation","params","setParams","useSearchParams","invalidateJobs","page","perPage","status","useMemo","data","isLoading","isFetching","refetch","jobs","stats","live","useEventStream","selection","setSelection","useState","confirmCancelOpen","setConfirmCancelOpen","batchCancel","onConfirmBatchCancel","ids","toast","err","message","describeError","patchParams","patch","next","k","v","totalRows","totalPages","columns","r","jsxs","jsx","StatusBadge","formatTime","formatDuration","selectedCount","cn","Button","Loader2","RefreshCcw","StatCard","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","Badge","XCircle","DataTable","EmptyState","Briefcase","Pagination","p","pp","ConfirmDialog","TONE_STYLES","label","value","tone","iso","d","now","ms","s","m","rs"],"mappings":"0zBAsBO,MAAMA,EAAW,CACtB,IAAM,CAAC,MAAM,EACb,KAAOC,GAAqB,CAAC,OAAQ,OAAQA,CAAC,CAChD,EAEO,SAASC,GAAQC,EAAsB,CAC5C,OAAOC,EAA2B,CAChC,SAAUJ,EAAS,KAAKG,CAAK,EAC7B,QAAS,IAAME,EAAI,SAASF,CAAK,CAAA,CAClC,CACH,CAIO,SAASG,IAAoB,CAClC,MAAMC,EAAKC,EAAA,EACX,MAAO,IAAMD,EAAG,kBAAkB,CAAE,SAAUP,EAAS,IAAK,CAC9D,CAEO,SAASS,IAAqB,CACnC,MAAMF,EAAKC,EAAA,EACX,OAAOE,EAAY,CACjB,WAAaC,GAAuBN,EAAI,gBAAgBM,CAAI,EAC5D,UAAW,IAAMJ,EAAG,kBAAkB,CAAE,SAAUP,EAAS,IAAK,CAAA,CACjE,CACH,CCGA,MAAMY,GAAmB,CAAC,GAAI,GAAI,GAAI,GAAG,EACnCC,EAAmB,GAEnBC,GAA8B,CAClC,UACA,UACA,YACA,YACA,SACA,YACA,cACA,WACA,WACF,EAEMC,GAA+C,CACnD,UAAc,eACd,WAAc,gBACd,aAAc,eACd,OAAc,iBAChB,EAEA,SAAwBC,IAAyB,CAC/C,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAe,CAAC,QAAS,QAAQ,CAAC,EAC1C,CAACC,EAAQC,CAAS,EAAIC,EAAA,EACtBC,EAAiBhB,GAAA,EAGjBiB,EAAW,KAAK,IAAI,EAAG,OAAOJ,EAAO,IAAI,MAAM,CAAC,GAAS,CAAC,EAC1DK,EAAW,OAAOL,EAAO,IAAI,UAAU,CAAC,GAAKN,EAC7CY,EAAYN,EAAO,IAAI,QAAQ,GAA0B,KAEzDhB,EAAuBuB,EAAAA,QAC3B,KAAO,CACL,MAAQF,EACR,QAASD,EAAO,GAAKC,EACrB,GAAIC,EAAS,CAAE,OAAAA,GAAW,CAAA,CAAC,GAE7B,CAACF,EAAMC,EAASC,CAAM,CAAA,EAGlB,CAAE,KAAAE,EAAM,UAAAC,EAAW,WAAAC,EAAY,QAAAC,CAAA,EAAY5B,GAAQC,CAAK,EACxD4B,EAAOJ,GAAM,MAAQ,CAAA,EACrBK,EAAQL,GAAM,MAGdM,EAAOC,GAAe,CAC1B,IAAK,IAAMZ,EAAA,CAAe,CAC3B,EAGK,CAACa,EAAWC,CAAY,EAAIC,EAAAA,SAAsB,IAAI,GAAK,EAG3D,CAACC,EAAmBC,CAAoB,EAAIF,EAAAA,SAAS,EAAK,EAC1DG,EAAc/B,GAAA,EAEpB,eAAegC,GAAsC,CACnD,MAAMC,EAAM,MAAM,KAAKP,CAAS,EAAE,IAAI,MAAM,EAAE,OAAO,OAAO,QAAQ,EACpE,GAAIO,EAAI,SAAW,EACnB,GAAI,CACF,MAAMF,EAAY,YAAY,CAAE,IAAAE,EAAK,EACrCN,EAAa,IAAI,GAAK,EACtBO,EAAM,QAAQ1B,EAAE,eAAgB,CAAE,GAAI,QAAA,CAAU,CAAC,CACnD,OAAS2B,EAAK,CACZ,KAAM,CAAE,QAAAC,CAAA,EAAYC,EAAcF,EAAK3B,CAAC,EACxC0B,MAAAA,EAAM,MAAME,CAAO,EACbD,CACR,CACF,CAGA,SAASG,EAAYC,EAA4C,CAC/D,MAAMC,EAAO,IAAI,gBAAgB9B,CAAM,EACvC,SAAW,CAAC+B,EAAGC,CAAC,IAAK,OAAO,QAAQH,CAAK,EACnCG,GAAK,MAAQA,IAAM,GAAIF,EAAK,OAAOC,CAAC,EACnCD,EAAK,IAAIC,EAAGC,CAAC,EAGhB,OAAO,KAAKH,CAAK,EAAE,KAAME,GAAMA,IAAM,MAAM,GAAGD,EAAK,OAAO,MAAM,EACpE7B,EAAU6B,EAAM,CAAE,QAAS,EAAA,CAAO,CACpC,CASA,MAAMG,EAAYpB,EACbA,EAAM,QAAUA,EAAM,QAAUA,EAAM,UAAYA,EAAM,QAAUA,EAAM,WAAa,GACtF,OACEqB,EAAaD,EACf,KAAK,IAAI,EAAG,KAAK,KAAKA,EAAY5B,CAAO,CAAC,EAC1CO,EAAK,SAAWP,EAAUD,EAAO,EAAIA,EAGnC+B,EAAkC5B,EAAAA,QACtC,IAAM,CACJ,CACE,GAAI,KACJ,OAAQT,EAAE,aAAa,EACvB,KAAOsC,GAAMC,EAAAA,KAAC,OAAA,CAAK,UAAU,6BAA6B,SAAA,CAAA,IAAED,EAAE,EAAA,EAAG,EACjE,cAAe,OACf,aAAc,EAAA,EAEhB,CACE,GAAI,QACJ,OAAQtC,EAAE,gBAAgB,EAC1B,KAAOsC,GAAME,EAAAA,IAAC,QAAK,UAAU,cAAe,WAAE,MAAM,EACpD,cAAe,MAAA,EAEjB,CACE,GAAI,SACJ,OAAQxC,EAAE,iBAAiB,EAC3B,KAAOsC,GACLE,EAAAA,IAAC,QAAK,UAAU,6BAA8B,WAAE,OAAO,EAEzD,YAAa,EAAA,EAEf,CACE,GAAI,SACJ,OAAQxC,EAAE,iBAAiB,EAC3B,KAAOsC,SACJG,EAAA,CAAY,OAAQH,EAAE,OACpB,SAAAtC,EAAE,eAAesC,EAAE,MAAM,GAAI,CAAE,aAAcA,EAAE,MAAA,CAAQ,EAC1D,EAEF,cAAe,MAAA,EAEjB,CACE,GAAI,YACJ,OAAQtC,EAAE,oBAAoB,EAC9B,KAAOsC,GAAME,EAAAA,IAAC,OAAA,CAAK,UAAU,gBAAiB,SAAAE,GAAWJ,EAAE,UAAU,CAAA,CAAE,EACvE,cAAe,OACf,aAAc,EAAA,EAEhB,CACE,GAAI,WACJ,OAAQtC,EAAE,mBAAmB,EAC7B,KAAOsC,GACLE,EAAAA,IAAC,OAAA,CAAK,UAAU,6BAA8B,SAAAG,GAAeL,EAAE,WAAW,CAAA,CAAE,EAE9E,cAAe,OACf,aAAc,EAAA,EAEhB,CACE,GAAI,OACJ,OAAQtC,EAAE,eAAe,EACzB,KAAOsC,GACLE,MAAC,OAAA,CAAK,UAAU,6BACb,SAAAF,EAAE,MAAQ,KAAO,IAAIA,EAAE,KAAK,QAAQ,CAAC,CAAC,GAAK,IAC9C,EAEF,cAAe,OACf,aAAc,EAAA,CAChB,EAEF,CAACtC,CAAC,CAAA,EAGE4C,EAAgB1B,EAAU,KAEhC,OACEqB,EAAAA,KAAC,MAAA,CAAI,UAAU,wCAEb,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,sBAChB,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAC,MAAC,KAAA,CAAG,UAAU,wBAAyB,SAAAxC,EAAE,YAAY,EAAE,EACvDwC,EAAAA,IAAC,OAAA,CAAK,UAAWK,EAAG,mCAAoC/C,GAAkBkB,CAAI,CAAC,EAC5E,SAAAhB,EAAE,aAAagB,CAAI,EAAE,EACxB,EACAuB,EAAAA,KAACO,EAAA,CACC,QAAQ,QACR,KAAK,KACL,UAAU,UACV,QAAS,IAAMjC,EAAA,EACf,SAAUD,EACV,aAAYZ,EAAE,kBAAmB,CAAE,GAAI,SAAU,EAEhD,SAAA,CAAAY,EAAa4B,EAAAA,IAACO,IAAQ,UAAU,sBAAA,CAAuB,EAAKP,EAAAA,IAACQ,GAAA,CAAW,UAAU,SAAA,CAAU,EAC7FR,EAAAA,IAAC,OAAA,CAAK,UAAU,mBAAoB,SAAAxC,EAAE,kBAAmB,CAAE,GAAI,QAAA,CAAU,CAAA,CAAE,CAAA,CAAA,CAAA,CAC7E,EACF,QACC,IAAA,CAAE,UAAU,wBAAyB,SAAAA,EAAE,eAAe,CAAA,CAAE,CAAA,EAC3D,EAGCe,GACCwB,EAAAA,KAAC,MAAA,CAAI,UAAU,wCACb,SAAA,CAAAC,EAAAA,IAACS,EAAA,CAAS,MAAOjD,EAAE,oBAAoB,EAAK,MAAOe,EAAM,QAAW,KAAK,MAAA,CAAO,EAChFyB,EAAAA,IAACS,EAAA,CAAS,MAAOjD,EAAE,oBAAoB,EAAK,MAAOe,EAAM,QAAW,KAAK,SAAA,CAAU,EACnFyB,EAAAA,IAACS,EAAA,CAAS,MAAOjD,EAAE,sBAAsB,EAAG,MAAOe,EAAM,UAAW,KAAK,SAAA,CAAU,EACnFyB,EAAAA,IAACS,EAAA,CAAS,MAAOjD,EAAE,mBAAmB,EAAM,MAAOe,EAAM,OAAW,KAAK,QAAA,CAAS,CAAA,EACpF,EAIFwB,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAAC,EAAAA,IAAC,SAAM,UAAU,wBAAwB,QAAQ,gBAC9C,SAAAxC,EAAE,oBAAoB,EACzB,EACAuC,EAAAA,KAACW,EAAA,CACC,MAAO1C,GAAU,UACjB,cAAgB0B,GAAMJ,EAAY,CAAE,OAAQI,IAAM,UAAY,KAAOA,EAAG,EAExE,SAAA,CAAAM,EAAAA,IAACW,GAAc,GAAG,gBAAgB,UAAU,YAC1C,SAAAX,EAAAA,IAACY,IAAY,CAAA,CACf,SACCC,EAAA,CACC,SAAA,CAAAb,MAACc,EAAA,CAAW,MAAM,UAAW,SAAAtD,EAAE,uBAAuB,EAAE,EACvDH,GAAe,IAAK,GACnB2C,EAAAA,IAACc,EAAA,CAAmB,MAAO,EACxB,SAAAtD,EAAE,eAAe,CAAC,GAAI,CAAE,aAAc,EAAG,CAAA,EAD3B,CAEjB,CACD,CAAA,CAAA,CACH,CAAA,CAAA,CAAA,CACF,EACF,EAGC4C,EAAgB,GACfL,OAAC,MAAA,CAAI,UAAU,kCACb,SAAA,CAAAC,EAAAA,IAACe,EAAA,CAAM,QAAQ,YACZ,SAAAvD,EAAE,sBAAuB,CAAE,MAAO4C,CAAA,CAAe,CAAA,CACpD,EACAL,EAAAA,KAACO,EAAA,CACC,QAAQ,cACR,KAAK,KACL,QAAS,IAAMxB,EAAqB,EAAI,EACxC,SAAUC,EAAY,UAEtB,SAAA,CAAAiB,EAAAA,IAACgB,GAAA,CAAQ,UAAU,SAAA,CAAU,EAC5BxD,EAAE,mBAAmB,CAAA,CAAA,CAAA,CACxB,CAAA,CACF,CAAA,EAEJ,EAGAwC,EAAAA,IAACiB,EAAA,CACC,QAAApB,EACA,KAAMvB,EACN,SAAWwB,GAAM,OAAOA,EAAE,EAAE,EAC5B,QAAS3B,EACT,UAAAO,EACA,kBAAmBC,EACnB,WACEqB,EAAAA,IAACkB,EAAA,CACC,WAAOC,GAAA,EAAU,EACjB,MAAO3D,EAAE,kBAAkB,EAC3B,YAAaA,EAAE,wBAAwB,CAAA,CAAA,CACzC,CAAA,GAKFc,EAAK,OAAS,GAAKR,EAAO,IAC1BkC,EAAAA,IAACoB,GAAA,CACC,KAAAtD,EACA,WAAA8B,EACA,UAAAD,EACA,QAAA5B,EACA,eAAgBZ,GAChB,aAAekE,GAAM/B,EAAY,CAAE,KAAM+B,IAAM,EAAI,KAAO,OAAOA,CAAC,CAAA,CAAG,EACrE,gBAAkBC,GAAOhC,EAAY,CAAE,SAAUgC,IAAOlE,EAAmB,KAAO,OAAOkE,CAAE,CAAA,CAAG,CAAA,CAAA,EAIlGtB,EAAAA,IAACuB,GAAA,CACC,KAAM1C,EACN,aAAcC,EACd,MAAOtB,EAAE,2BAA4B,CAAE,MAAO4C,EAAe,EAC7D,YAAa5C,EAAE,8BAA8B,EAC7C,OAAO,SACP,aAAcA,EAAE,mBAAmB,EACnC,UAAWwB,CAAA,CAAA,CACb,EACF,CAEJ,CAUA,MAAMwC,GAAqD,CACzD,KAAS,8BACT,QAAS,iCACT,QAAS,iCACT,OAAS,+BACX,EAEA,SAASf,EAAS,CAAE,MAAAgB,EAAO,MAAAC,EAAO,KAAAC,GAAoC,CACpE,OACE5B,EAAAA,KAAC,MAAA,CACC,UAAWM,EACT,yCACAmB,GAAYG,CAAI,CAAA,EAGlB,SAAA,CAAA3B,EAAAA,IAAC,MAAA,CAAI,UAAU,gDAAiD,SAAAyB,EAAM,EACtEzB,EAAAA,IAAC,MAAA,CAAI,UAAU,sCAAuC,SAAA0B,CAAA,CAAM,CAAA,CAAA,CAAA,CAGlE,CAEA,SAASxB,GAAW0B,EAAqB,CACvC,GAAI,CACF,MAAMC,EAAI,IAAI,KAAKD,CAAG,EACtB,GAAI,OAAO,MAAMC,EAAE,QAAA,CAAS,EAAG,OAAOD,EACtC,MAAME,MAAU,KAEhB,OADgBD,EAAE,aAAA,IAAmBC,EAAI,aAAA,EAEhCD,EAAE,mBAAmB,OAAW,CAAE,KAAM,UAAW,OAAQ,UAAW,OAAQ,SAAA,CAAW,EAE3FA,EAAE,eAAe,OAAW,CAAE,MAAO,QAAS,IAAK,UAAW,KAAM,UAAW,OAAQ,SAAA,CAAW,CAC3G,MAAQ,CACN,OAAOD,CACT,CACF,CAEA,SAASzB,GAAe4B,EAAgC,CACtD,GAAIA,GAAM,KAAM,MAAO,IACvB,GAAIA,EAAK,IAAM,MAAO,GAAGA,CAAE,KAC3B,MAAMC,EAAID,EAAK,IACf,GAAIC,EAAI,GAAI,MAAO,GAAGA,EAAE,QAAQ,CAAC,CAAC,IAClC,MAAMC,EAAI,KAAK,MAAMD,EAAI,EAAE,EACrBE,EAAK,KAAK,MAAMF,EAAIC,EAAI,EAAE,EAChC,MAAO,GAAGA,CAAC,IAAIC,CAAE,GACnB"}
@@ -1,2 +1,2 @@
1
- import{u as n,j as e,T as u,N as r,c as a,O as i}from"./index-BIBWEKxu.js";import"./react-DlP5eolq.js";const b=[{to:"jobs",i18nKey:"subnav.jobs",mounted:!0},{to:"subtasks",i18nKey:"subnav.subtasks",mounted:!0},{to:"bgjobs",i18nKey:"subnav.bgjobs",mounted:!0},{to:"schedules",i18nKey:"subnav.schedules",mounted:!0},{to:"outbox",i18nKey:"subnav.outbox",mounted:!0},{to:"a2a",i18nKey:"subnav.a2a",mounted:!0},{to:"heartbeat",i18nKey:"subnav.heartbeat",mounted:!0},{to:"goals",i18nKey:"subnav.goals",mounted:!0},{to:"asks",i18nKey:"subnav.asks",mounted:!0},{to:"plans",i18nKey:"subnav.plans",mounted:!0}];function l(){const{t:s}=n("tasks");return e.jsxs("div",{className:"flex min-h-dvh flex-col bg-bg",children:[e.jsx(u,{}),e.jsx("nav",{className:a("sticky top-[var(--topbar-h,0)] z-10","flex items-center gap-1","border-b border-border bg-surface","px-3 sm:px-4 py-1","overflow-x-auto"),"aria-label":s("pageTitle"),children:b.filter(t=>t.mounted).map(t=>e.jsx(r,{to:t.to,className:({isActive:o})=>a("shrink-0 rounded-md px-3 py-1.5 text-sm no-underline","transition-colors tap-target",o?"bg-accent-bg text-accent font-medium":"text-text-dim hover:bg-surface-hover hover:text-text"),children:s(t.i18nKey)},t.to))}),e.jsx("main",{className:"flex-1 px-3 sm:px-4 py-4 pb-safe",children:e.jsx(i,{})})]})}export{l as default};
2
- //# sourceMappingURL=layout-B0RjH6M2.js.map
1
+ import{u as n,j as e,T as u,N as r,c as a,O as i}from"./index-B795P_3p.js";import"./react-DlP5eolq.js";const b=[{to:"jobs",i18nKey:"subnav.jobs",mounted:!0},{to:"subtasks",i18nKey:"subnav.subtasks",mounted:!0},{to:"bgjobs",i18nKey:"subnav.bgjobs",mounted:!0},{to:"schedules",i18nKey:"subnav.schedules",mounted:!0},{to:"outbox",i18nKey:"subnav.outbox",mounted:!0},{to:"a2a",i18nKey:"subnav.a2a",mounted:!0},{to:"heartbeat",i18nKey:"subnav.heartbeat",mounted:!0},{to:"goals",i18nKey:"subnav.goals",mounted:!0},{to:"asks",i18nKey:"subnav.asks",mounted:!0},{to:"plans",i18nKey:"subnav.plans",mounted:!0}];function l(){const{t:s}=n("tasks");return e.jsxs("div",{className:"flex min-h-dvh flex-col bg-bg",children:[e.jsx(u,{}),e.jsx("nav",{className:a("sticky top-[var(--topbar-h,0)] z-10","flex items-center gap-1","border-b border-border bg-surface","px-3 sm:px-4 py-1","overflow-x-auto"),"aria-label":s("pageTitle"),children:b.filter(t=>t.mounted).map(t=>e.jsx(r,{to:t.to,className:({isActive:o})=>a("shrink-0 rounded-md px-3 py-1.5 text-sm no-underline","transition-colors tap-target",o?"bg-accent-bg text-accent font-medium":"text-text-dim hover:bg-surface-hover hover:text-text"),children:s(t.i18nKey)},t.to))}),e.jsx("main",{className:"flex-1 px-3 sm:px-4 py-4 pb-safe",children:e.jsx(i,{})})]})}export{l as default};
2
+ //# sourceMappingURL=layout-BiAVhWgU.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"layout-B0RjH6M2.js","sources":["../../src/routes/tasks/layout.tsx"],"sourcesContent":["/**\n * /tasks — layout shell shared by every sub-tab.\n *\n * Renders the application Topbar plus a sub-tab strip below it. The\n * actual sub-tab body comes from <Outlet /> — one file per tab under\n * routes/tasks/.\n *\n * Sub-tab order matches plan: jobs / subtasks / bgjobs / schedules /\n * outbox / a2a. Each sub-tab is gated on its route being mounted; in\n * PR-10a only `/tasks/jobs` is wired up so the others stay out of the\n * nav until their PRs land.\n */\n\nimport { NavLink, Outlet } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { Topbar } from '@/components/shell/topbar'\nimport { cn } from '@/lib/utils'\n\ninterface SubTab {\n to: string\n i18nKey: string\n mounted: boolean\n}\n\nconst SUB_TABS: SubTab[] = [\n { to: 'jobs', i18nKey: 'subnav.jobs', mounted: true },\n { to: 'subtasks', i18nKey: 'subnav.subtasks', mounted: true },\n { to: 'bgjobs', i18nKey: 'subnav.bgjobs', mounted: true },\n { to: 'schedules', i18nKey: 'subnav.schedules', mounted: true },\n { to: 'outbox', i18nKey: 'subnav.outbox', mounted: true },\n { to: 'a2a', i18nKey: 'subnav.a2a', mounted: true },\n // P1 follow-up — per-thread background primitives.\n { to: 'heartbeat', i18nKey: 'subnav.heartbeat', mounted: true },\n { to: 'goals', i18nKey: 'subnav.goals', mounted: true },\n { to: 'asks', i18nKey: 'subnav.asks', mounted: true },\n // v1.2.133 — native_exit_plan_mode audit log.\n { to: 'plans', i18nKey: 'subnav.plans', mounted: true },\n]\n\nexport default function TasksLayout(): JSX.Element {\n const { t } = useTranslation('tasks')\n return (\n <div className=\"flex min-h-dvh flex-col bg-bg\">\n <Topbar />\n\n <nav\n className={cn(\n 'sticky top-[var(--topbar-h,0)] z-10',\n 'flex items-center gap-1',\n 'border-b border-border bg-surface',\n 'px-3 sm:px-4 py-1',\n 'overflow-x-auto',\n )}\n aria-label={t('pageTitle')}\n >\n {SUB_TABS.filter((tab) => tab.mounted).map((tab) => (\n <NavLink\n key={tab.to}\n to={tab.to}\n className={({ isActive }) =>\n cn(\n 'shrink-0 rounded-md px-3 py-1.5 text-sm no-underline',\n 'transition-colors tap-target',\n isActive\n ? 'bg-accent-bg text-accent font-medium'\n : 'text-text-dim hover:bg-surface-hover hover:text-text',\n )\n }\n >\n {t(tab.i18nKey)}\n </NavLink>\n ))}\n </nav>\n\n <main className=\"flex-1 px-3 sm:px-4 py-4 pb-safe\">\n <Outlet />\n </main>\n </div>\n )\n}\n"],"names":["SUB_TABS","TasksLayout","t","useTranslation","jsxs","jsx","Topbar","cn","tab","NavLink","isActive","Outlet"],"mappings":"uGAwBA,MAAMA,EAAqB,CACzB,CAAE,GAAI,OAAa,QAAS,cAAoB,QAAS,EAAA,EACzD,CAAE,GAAI,WAAa,QAAS,kBAAoB,QAAS,EAAA,EACzD,CAAE,GAAI,SAAa,QAAS,gBAAoB,QAAS,EAAA,EACzD,CAAE,GAAI,YAAa,QAAS,mBAAoB,QAAS,EAAA,EACzD,CAAE,GAAI,SAAa,QAAS,gBAAoB,QAAS,EAAA,EACzD,CAAE,GAAI,MAAa,QAAS,aAAoB,QAAS,EAAA,EAEzD,CAAE,GAAI,YAAa,QAAS,mBAAoB,QAAS,EAAA,EACzD,CAAE,GAAI,QAAa,QAAS,eAAoB,QAAS,EAAA,EACzD,CAAE,GAAI,OAAa,QAAS,cAAoB,QAAS,EAAA,EAEzD,CAAE,GAAI,QAAa,QAAS,eAAoB,QAAS,EAAA,CAC3D,EAEA,SAAwBC,GAA2B,CACjD,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAe,OAAO,EACpC,OACEC,EAAAA,KAAC,MAAA,CAAI,UAAU,gCACb,SAAA,CAAAC,EAAAA,IAACC,EAAA,EAAO,EAERD,EAAAA,IAAC,MAAA,CACC,UAAWE,EACT,sCACA,0BACA,oCACA,oBACA,iBAAA,EAEF,aAAYL,EAAE,WAAW,EAExB,SAAAF,EAAS,OAAQQ,GAAQA,EAAI,OAAO,EAAE,IAAKA,GAC1CH,EAAAA,IAACI,EAAA,CAEC,GAAID,EAAI,GACR,UAAW,CAAC,CAAE,SAAAE,CAAA,IACZH,EACE,uDACA,+BACAG,EACI,uCACA,sDAAA,EAIP,SAAAR,EAAEM,EAAI,OAAO,CAAA,EAZTA,EAAI,EAAA,CAcZ,CAAA,CAAA,QAGF,OAAA,CAAK,UAAU,mCACd,SAAAH,EAAAA,IAACM,IAAO,CAAA,CACV,CAAA,EACF,CAEJ"}
1
+ {"version":3,"file":"layout-BiAVhWgU.js","sources":["../../src/routes/tasks/layout.tsx"],"sourcesContent":["/**\n * /tasks — layout shell shared by every sub-tab.\n *\n * Renders the application Topbar plus a sub-tab strip below it. The\n * actual sub-tab body comes from <Outlet /> — one file per tab under\n * routes/tasks/.\n *\n * Sub-tab order matches plan: jobs / subtasks / bgjobs / schedules /\n * outbox / a2a. Each sub-tab is gated on its route being mounted; in\n * PR-10a only `/tasks/jobs` is wired up so the others stay out of the\n * nav until their PRs land.\n */\n\nimport { NavLink, Outlet } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { Topbar } from '@/components/shell/topbar'\nimport { cn } from '@/lib/utils'\n\ninterface SubTab {\n to: string\n i18nKey: string\n mounted: boolean\n}\n\nconst SUB_TABS: SubTab[] = [\n { to: 'jobs', i18nKey: 'subnav.jobs', mounted: true },\n { to: 'subtasks', i18nKey: 'subnav.subtasks', mounted: true },\n { to: 'bgjobs', i18nKey: 'subnav.bgjobs', mounted: true },\n { to: 'schedules', i18nKey: 'subnav.schedules', mounted: true },\n { to: 'outbox', i18nKey: 'subnav.outbox', mounted: true },\n { to: 'a2a', i18nKey: 'subnav.a2a', mounted: true },\n // P1 follow-up — per-thread background primitives.\n { to: 'heartbeat', i18nKey: 'subnav.heartbeat', mounted: true },\n { to: 'goals', i18nKey: 'subnav.goals', mounted: true },\n { to: 'asks', i18nKey: 'subnav.asks', mounted: true },\n // v1.2.133 — native_exit_plan_mode audit log.\n { to: 'plans', i18nKey: 'subnav.plans', mounted: true },\n]\n\nexport default function TasksLayout(): JSX.Element {\n const { t } = useTranslation('tasks')\n return (\n <div className=\"flex min-h-dvh flex-col bg-bg\">\n <Topbar />\n\n <nav\n className={cn(\n 'sticky top-[var(--topbar-h,0)] z-10',\n 'flex items-center gap-1',\n 'border-b border-border bg-surface',\n 'px-3 sm:px-4 py-1',\n 'overflow-x-auto',\n )}\n aria-label={t('pageTitle')}\n >\n {SUB_TABS.filter((tab) => tab.mounted).map((tab) => (\n <NavLink\n key={tab.to}\n to={tab.to}\n className={({ isActive }) =>\n cn(\n 'shrink-0 rounded-md px-3 py-1.5 text-sm no-underline',\n 'transition-colors tap-target',\n isActive\n ? 'bg-accent-bg text-accent font-medium'\n : 'text-text-dim hover:bg-surface-hover hover:text-text',\n )\n }\n >\n {t(tab.i18nKey)}\n </NavLink>\n ))}\n </nav>\n\n <main className=\"flex-1 px-3 sm:px-4 py-4 pb-safe\">\n <Outlet />\n </main>\n </div>\n )\n}\n"],"names":["SUB_TABS","TasksLayout","t","useTranslation","jsxs","jsx","Topbar","cn","tab","NavLink","isActive","Outlet"],"mappings":"uGAwBA,MAAMA,EAAqB,CACzB,CAAE,GAAI,OAAa,QAAS,cAAoB,QAAS,EAAA,EACzD,CAAE,GAAI,WAAa,QAAS,kBAAoB,QAAS,EAAA,EACzD,CAAE,GAAI,SAAa,QAAS,gBAAoB,QAAS,EAAA,EACzD,CAAE,GAAI,YAAa,QAAS,mBAAoB,QAAS,EAAA,EACzD,CAAE,GAAI,SAAa,QAAS,gBAAoB,QAAS,EAAA,EACzD,CAAE,GAAI,MAAa,QAAS,aAAoB,QAAS,EAAA,EAEzD,CAAE,GAAI,YAAa,QAAS,mBAAoB,QAAS,EAAA,EACzD,CAAE,GAAI,QAAa,QAAS,eAAoB,QAAS,EAAA,EACzD,CAAE,GAAI,OAAa,QAAS,cAAoB,QAAS,EAAA,EAEzD,CAAE,GAAI,QAAa,QAAS,eAAoB,QAAS,EAAA,CAC3D,EAEA,SAAwBC,GAA2B,CACjD,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAe,OAAO,EACpC,OACEC,EAAAA,KAAC,MAAA,CAAI,UAAU,gCACb,SAAA,CAAAC,EAAAA,IAACC,EAAA,EAAO,EAERD,EAAAA,IAAC,MAAA,CACC,UAAWE,EACT,sCACA,0BACA,oCACA,oBACA,iBAAA,EAEF,aAAYL,EAAE,WAAW,EAExB,SAAAF,EAAS,OAAQQ,GAAQA,EAAI,OAAO,EAAE,IAAKA,GAC1CH,EAAAA,IAACI,EAAA,CAEC,GAAID,EAAI,GACR,UAAW,CAAC,CAAE,SAAAE,CAAA,IACZH,EACE,uDACA,+BACAG,EACI,uCACA,sDAAA,EAIP,SAAAR,EAAEM,EAAI,OAAO,CAAA,EAZTA,EAAI,EAAA,CAcZ,CAAA,CAAA,QAGF,OAAA,CAAK,UAAU,mCACd,SAAAH,EAAAA,IAACM,IAAO,CAAA,CACV,CAAA,EACF,CAEJ"}
@@ -1,2 +1,2 @@
1
- import{u as n,j as t,N as o,c as s,O as l}from"./index-BIBWEKxu.js";import"./react-DlP5eolq.js";const r=[{to:"installed",i18nKey:"agimSkills.tab.installed"},{to:"hot",i18nKey:"agimSkills.tab.hot"},{to:"injection",i18nKey:"agimSkills.tab.injection"}];function c(){const{t:i}=n(["settings"]);return t.jsxs("div",{className:"flex flex-col gap-4",children:[t.jsx("nav",{className:s("flex items-center gap-1","border-b border-border","-mx-3 sm:-mx-4 px-3 sm:px-4 pb-2","overflow-x-auto"),"aria-label":i("agimSkills.title"),children:r.map(e=>t.jsx(o,{to:e.to,className:({isActive:a})=>s("shrink-0 rounded-md px-3 py-1.5 text-sm no-underline","transition-colors tap-target",a?"bg-accent-bg text-accent font-medium":"text-text-dim hover:bg-surface-hover hover:text-text"),children:i(e.i18nKey)},e.to))}),t.jsx(l,{})]})}export{c as default};
2
- //# sourceMappingURL=layout-DOSpVfND.js.map
1
+ import{u as n,j as t,N as o,c as s,O as l}from"./index-B795P_3p.js";import"./react-DlP5eolq.js";const r=[{to:"installed",i18nKey:"agimSkills.tab.installed"},{to:"hot",i18nKey:"agimSkills.tab.hot"},{to:"injection",i18nKey:"agimSkills.tab.injection"}];function c(){const{t:i}=n(["settings"]);return t.jsxs("div",{className:"flex flex-col gap-4",children:[t.jsx("nav",{className:s("flex items-center gap-1","border-b border-border","-mx-3 sm:-mx-4 px-3 sm:px-4 pb-2","overflow-x-auto"),"aria-label":i("agimSkills.title"),children:r.map(e=>t.jsx(o,{to:e.to,className:({isActive:a})=>s("shrink-0 rounded-md px-3 py-1.5 text-sm no-underline","transition-colors tap-target",a?"bg-accent-bg text-accent font-medium":"text-text-dim hover:bg-surface-hover hover:text-text"),children:i(e.i18nKey)},e.to))}),t.jsx(l,{})]})}export{c as default};
2
+ //# sourceMappingURL=layout-BodTIhhE.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"layout-DOSpVfND.js","sources":["../../src/routes/settings/agim-skills/layout.tsx"],"sourcesContent":["/**\n * /settings/agim-skills — combined skill management.\n *\n * 2026-05 consolidation: the v2 SPA briefly had two skill entry points\n * (top-level /skills + this settings route) which duplicated 95% of\n * the data after multi-root scanning landed. We merged both flows here:\n *\n * installed — agim's own loader view; CRUD against the writable\n * workspace dir, read-only for builtins and skills\n * inherited from ~/.claude/skills + opencode + codex.\n * hot — skillhub.cn 热门 (moved from /skills/hot).\n *\n * Old URLs under /skills still resolve via redirects in router.tsx\n * so bookmarks keep working.\n */\n\nimport { NavLink, Outlet } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { cn } from '@/lib/utils'\n\ninterface SubTab {\n to: string\n i18nKey: string\n}\n\nconst SUB_TABS: SubTab[] = [\n { to: 'installed', i18nKey: 'agimSkills.tab.installed' },\n { to: 'hot', i18nKey: 'agimSkills.tab.hot' },\n // v1.2.151 — system-prompt skill block editor (operator override).\n { to: 'injection', i18nKey: 'agimSkills.tab.injection' },\n]\n\nexport default function SettingsAgimSkillsLayout(): JSX.Element {\n const { t } = useTranslation(['settings'])\n return (\n <div className=\"flex flex-col gap-4\">\n <nav\n className={cn(\n 'flex items-center gap-1',\n 'border-b border-border',\n '-mx-3 sm:-mx-4 px-3 sm:px-4 pb-2',\n 'overflow-x-auto',\n )}\n aria-label={t('agimSkills.title')}\n >\n {SUB_TABS.map((tab) => (\n <NavLink\n key={tab.to}\n to={tab.to}\n className={({ isActive }) =>\n cn(\n 'shrink-0 rounded-md px-3 py-1.5 text-sm no-underline',\n 'transition-colors tap-target',\n isActive\n ? 'bg-accent-bg text-accent font-medium'\n : 'text-text-dim hover:bg-surface-hover hover:text-text',\n )\n }\n >\n {t(tab.i18nKey)}\n </NavLink>\n ))}\n </nav>\n <Outlet />\n </div>\n )\n}\n"],"names":["SUB_TABS","SettingsAgimSkillsLayout","t","useTranslation","jsxs","jsx","cn","tab","NavLink","isActive","Outlet"],"mappings":"gGAyBA,MAAMA,EAAqB,CACzB,CAAE,GAAI,YAAa,QAAS,0BAAA,EAC5B,CAAE,GAAI,MAAa,QAAS,oBAAA,EAE5B,CAAE,GAAI,YAAa,QAAS,0BAAA,CAC9B,EAEA,SAAwBC,GAAwC,CAC9D,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAe,CAAC,UAAU,CAAC,EACzC,OACEC,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACb,SAAA,CAAAC,EAAAA,IAAC,MAAA,CACC,UAAWC,EACT,0BACA,yBACA,mCACA,iBAAA,EAEF,aAAYJ,EAAE,kBAAkB,EAE/B,SAAAF,EAAS,IAAKO,GACbF,EAAAA,IAACG,EAAA,CAEC,GAAID,EAAI,GACR,UAAW,CAAC,CAAE,SAAAE,CAAA,IACZH,EACE,uDACA,+BACAG,EACI,uCACA,sDAAA,EAIP,SAAAP,EAAEK,EAAI,OAAO,CAAA,EAZTA,EAAI,EAAA,CAcZ,CAAA,CAAA,QAEFG,EAAA,CAAA,CAAO,CAAA,EACV,CAEJ"}
1
+ {"version":3,"file":"layout-BodTIhhE.js","sources":["../../src/routes/settings/agim-skills/layout.tsx"],"sourcesContent":["/**\n * /settings/agim-skills — combined skill management.\n *\n * 2026-05 consolidation: the v2 SPA briefly had two skill entry points\n * (top-level /skills + this settings route) which duplicated 95% of\n * the data after multi-root scanning landed. We merged both flows here:\n *\n * installed — agim's own loader view; CRUD against the writable\n * workspace dir, read-only for builtins and skills\n * inherited from ~/.claude/skills + opencode + codex.\n * hot — skillhub.cn 热门 (moved from /skills/hot).\n *\n * Old URLs under /skills still resolve via redirects in router.tsx\n * so bookmarks keep working.\n */\n\nimport { NavLink, Outlet } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { cn } from '@/lib/utils'\n\ninterface SubTab {\n to: string\n i18nKey: string\n}\n\nconst SUB_TABS: SubTab[] = [\n { to: 'installed', i18nKey: 'agimSkills.tab.installed' },\n { to: 'hot', i18nKey: 'agimSkills.tab.hot' },\n // v1.2.151 — system-prompt skill block editor (operator override).\n { to: 'injection', i18nKey: 'agimSkills.tab.injection' },\n]\n\nexport default function SettingsAgimSkillsLayout(): JSX.Element {\n const { t } = useTranslation(['settings'])\n return (\n <div className=\"flex flex-col gap-4\">\n <nav\n className={cn(\n 'flex items-center gap-1',\n 'border-b border-border',\n '-mx-3 sm:-mx-4 px-3 sm:px-4 pb-2',\n 'overflow-x-auto',\n )}\n aria-label={t('agimSkills.title')}\n >\n {SUB_TABS.map((tab) => (\n <NavLink\n key={tab.to}\n to={tab.to}\n className={({ isActive }) =>\n cn(\n 'shrink-0 rounded-md px-3 py-1.5 text-sm no-underline',\n 'transition-colors tap-target',\n isActive\n ? 'bg-accent-bg text-accent font-medium'\n : 'text-text-dim hover:bg-surface-hover hover:text-text',\n )\n }\n >\n {t(tab.i18nKey)}\n </NavLink>\n ))}\n </nav>\n <Outlet />\n </div>\n )\n}\n"],"names":["SUB_TABS","SettingsAgimSkillsLayout","t","useTranslation","jsxs","jsx","cn","tab","NavLink","isActive","Outlet"],"mappings":"gGAyBA,MAAMA,EAAqB,CACzB,CAAE,GAAI,YAAa,QAAS,0BAAA,EAC5B,CAAE,GAAI,MAAa,QAAS,oBAAA,EAE5B,CAAE,GAAI,YAAa,QAAS,0BAAA,CAC9B,EAEA,SAAwBC,GAAwC,CAC9D,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAe,CAAC,UAAU,CAAC,EACzC,OACEC,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACb,SAAA,CAAAC,EAAAA,IAAC,MAAA,CACC,UAAWC,EACT,0BACA,yBACA,mCACA,iBAAA,EAEF,aAAYJ,EAAE,kBAAkB,EAE/B,SAAAF,EAAS,IAAKO,GACbF,EAAAA,IAACG,EAAA,CAEC,GAAID,EAAI,GACR,UAAW,CAAC,CAAE,SAAAE,CAAA,IACZH,EACE,uDACA,+BACAG,EACI,uCACA,sDAAA,EAIP,SAAAP,EAAEK,EAAI,OAAO,CAAA,EAZTA,EAAI,EAAA,CAcZ,CAAA,CAAA,QAEFG,EAAA,CAAA,CAAO,CAAA,EACV,CAEJ"}
@@ -1,2 +1,2 @@
1
- import{u as a,j as e,T as r,N as i,c as n,O as m}from"./index-BIBWEKxu.js";import"./react-DlP5eolq.js";const u=[{to:"messengers",i18nKey:"tabs.messengers",mounted:!0},{to:"agents",i18nKey:"tabs.agents",mounted:!0},{to:"llm",i18nKey:"tabs.llm",mounted:!0},{to:"mobile",i18nKey:"tabs.mobile",mounted:!0},{to:"agim-skills",i18nKey:"tabs.agimSkills",mounted:!0},{to:"search",i18nKey:"tabs.search",mounted:!0},{to:"mcp",i18nKey:"tabs.mcp",mounted:!0},{to:"policy",i18nKey:"tabs.policy",mounted:!0},{to:"email",i18nKey:"tabs.email",mounted:!0},{to:"viewer",i18nKey:"tabs.viewer",mounted:!0},{to:"security",i18nKey:"tabs.security",mounted:!0},{to:"workspaces",i18nKey:"tabs.workspaces",mounted:!0},{to:"admins",i18nKey:"tabs.admins",mounted:!0},{to:"service",i18nKey:"tabs.service",mounted:!0}];function d(){const{t:s}=a("settings");return e.jsxs("div",{className:"flex min-h-dvh flex-col bg-bg",children:[e.jsx(r,{}),e.jsx("nav",{className:n("sticky top-0 z-10","flex items-center gap-1","border-b border-border bg-surface","px-3 sm:px-4 py-1","overflow-x-auto"),"aria-label":s("pageTitle"),children:u.filter(t=>t.mounted).map(t=>e.jsx(i,{to:t.to,className:({isActive:o})=>n("shrink-0 rounded-md px-3 py-1.5 text-sm no-underline","transition-colors tap-target",o?"bg-accent-bg text-accent font-medium":"text-text-dim hover:bg-surface-hover hover:text-text"),children:s(t.i18nKey)},t.to))}),e.jsx("main",{className:"flex-1 px-3 sm:px-4 py-4 pb-safe",children:e.jsx(m,{})})]})}export{d as default};
2
- //# sourceMappingURL=layout-CzjqlPxW.js.map
1
+ import{u as a,j as e,T as r,N as i,c as n,O as m}from"./index-B795P_3p.js";import"./react-DlP5eolq.js";const u=[{to:"messengers",i18nKey:"tabs.messengers",mounted:!0},{to:"agents",i18nKey:"tabs.agents",mounted:!0},{to:"llm",i18nKey:"tabs.llm",mounted:!0},{to:"mobile",i18nKey:"tabs.mobile",mounted:!0},{to:"agim-skills",i18nKey:"tabs.agimSkills",mounted:!0},{to:"search",i18nKey:"tabs.search",mounted:!0},{to:"mcp",i18nKey:"tabs.mcp",mounted:!0},{to:"policy",i18nKey:"tabs.policy",mounted:!0},{to:"email",i18nKey:"tabs.email",mounted:!0},{to:"viewer",i18nKey:"tabs.viewer",mounted:!0},{to:"security",i18nKey:"tabs.security",mounted:!0},{to:"workspaces",i18nKey:"tabs.workspaces",mounted:!0},{to:"admins",i18nKey:"tabs.admins",mounted:!0},{to:"service",i18nKey:"tabs.service",mounted:!0}];function d(){const{t:s}=a("settings");return e.jsxs("div",{className:"flex min-h-dvh flex-col bg-bg",children:[e.jsx(r,{}),e.jsx("nav",{className:n("sticky top-0 z-10","flex items-center gap-1","border-b border-border bg-surface","px-3 sm:px-4 py-1","overflow-x-auto"),"aria-label":s("pageTitle"),children:u.filter(t=>t.mounted).map(t=>e.jsx(i,{to:t.to,className:({isActive:o})=>n("shrink-0 rounded-md px-3 py-1.5 text-sm no-underline","transition-colors tap-target",o?"bg-accent-bg text-accent font-medium":"text-text-dim hover:bg-surface-hover hover:text-text"),children:s(t.i18nKey)},t.to))}),e.jsx("main",{className:"flex-1 px-3 sm:px-4 py-4 pb-safe",children:e.jsx(m,{})})]})}export{d as default};
2
+ //# sourceMappingURL=layout-Cltp3ikG.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"layout-CzjqlPxW.js","sources":["../../src/routes/settings/layout.tsx"],"sourcesContent":["/**\n * /settings — layout shell with sub-tab nav (environment / service).\n *\n * Workspaces / WeChat QR / Admin allowlist will land as additional\n * sub-tabs in PR-19b/c. The `mounted` flag gates their nav links.\n */\n\nimport { NavLink, Outlet } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { Topbar } from '@/components/shell/topbar'\nimport { cn } from '@/lib/utils'\n\ninterface SubTab {\n to: string\n i18nKey: string\n mounted: boolean\n}\n\nconst SUB_TABS: SubTab[] = [\n { to: 'messengers', i18nKey: 'tabs.messengers', mounted: true },\n { to: 'agents', i18nKey: 'tabs.agents', mounted: true },\n // Stage 6 — Agim Agent stack (model APIs + runtime knobs).\n { to: 'llm', i18nKey: 'tabs.llm', mounted: true },\n // v1.2.129 — mobile QR generator (open /m/chat from a phone).\n { to: 'mobile', i18nKey: 'tabs.mobile', mounted: true },\n // P1 follow-up — agim SKILL.md editor.\n { to: 'agim-skills', i18nKey: 'tabs.agimSkills', mounted: true },\n // v1.2.126 — web_search provider chain + per-provider keys.\n { to: 'search', i18nKey: 'tabs.search', mounted: true },\n { to: 'mcp', i18nKey: 'tabs.mcp', mounted: true },\n { to: 'policy', i18nKey: 'tabs.policy', mounted: true },\n { to: 'email', i18nKey: 'tabs.email', mounted: true },\n { to: 'viewer', i18nKey: 'tabs.viewer', mounted: true },\n { to: 'security', i18nKey: 'tabs.security', mounted: true },\n { to: 'workspaces', i18nKey: 'tabs.workspaces', mounted: true },\n { to: 'admins', i18nKey: 'tabs.admins', mounted: true },\n // R13 follow-up — /settings/env catch-all editor removed; raw env-var\n // editing belongs in `~/.agim/env` on the host, not in a web form.\n { to: 'service', i18nKey: 'tabs.service', mounted: true },\n]\n\nexport default function SettingsLayout(): JSX.Element {\n const { t } = useTranslation('settings')\n return (\n <div className=\"flex min-h-dvh flex-col bg-bg\">\n <Topbar />\n\n <nav\n className={cn(\n 'sticky top-0 z-10',\n 'flex items-center gap-1',\n 'border-b border-border bg-surface',\n 'px-3 sm:px-4 py-1',\n 'overflow-x-auto',\n )}\n aria-label={t('pageTitle')}\n >\n {SUB_TABS.filter((tab) => tab.mounted).map((tab) => (\n <NavLink\n key={tab.to}\n to={tab.to}\n className={({ isActive }) =>\n cn(\n 'shrink-0 rounded-md px-3 py-1.5 text-sm no-underline',\n 'transition-colors tap-target',\n isActive\n ? 'bg-accent-bg text-accent font-medium'\n : 'text-text-dim hover:bg-surface-hover hover:text-text',\n )\n }\n >\n {t(tab.i18nKey)}\n </NavLink>\n ))}\n </nav>\n\n <main className=\"flex-1 px-3 sm:px-4 py-4 pb-safe\">\n <Outlet />\n </main>\n </div>\n )\n}\n"],"names":["SUB_TABS","SettingsLayout","t","useTranslation","jsxs","jsx","Topbar","cn","tab","NavLink","isActive","Outlet"],"mappings":"uGAkBA,MAAMA,EAAqB,CACzB,CAAE,GAAI,aAAgB,QAAS,kBAAqB,QAAS,EAAA,EAC7D,CAAE,GAAI,SAAgB,QAAS,cAAqB,QAAS,EAAA,EAE7D,CAAE,GAAI,MAAgB,QAAS,WAAqB,QAAS,EAAA,EAE7D,CAAE,GAAI,SAAgB,QAAS,cAAqB,QAAS,EAAA,EAE7D,CAAE,GAAI,cAAgB,QAAS,kBAAqB,QAAS,EAAA,EAE7D,CAAE,GAAI,SAAgB,QAAS,cAAqB,QAAS,EAAA,EAC7D,CAAE,GAAI,MAAgB,QAAS,WAAqB,QAAS,EAAA,EAC7D,CAAE,GAAI,SAAgB,QAAS,cAAqB,QAAS,EAAA,EAC7D,CAAE,GAAI,QAAgB,QAAS,aAAqB,QAAS,EAAA,EAC7D,CAAE,GAAI,SAAgB,QAAS,cAAqB,QAAS,EAAA,EAC7D,CAAE,GAAI,WAAgB,QAAS,gBAAqB,QAAS,EAAA,EAC7D,CAAE,GAAI,aAAgB,QAAS,kBAAqB,QAAS,EAAA,EAC7D,CAAE,GAAI,SAAgB,QAAS,cAAqB,QAAS,EAAA,EAG7D,CAAE,GAAI,UAAgB,QAAS,eAAqB,QAAS,EAAA,CAC/D,EAEA,SAAwBC,GAA8B,CACpD,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAe,UAAU,EACvC,OACEC,EAAAA,KAAC,MAAA,CAAI,UAAU,gCACb,SAAA,CAAAC,EAAAA,IAACC,EAAA,EAAO,EAERD,EAAAA,IAAC,MAAA,CACC,UAAWE,EACT,oBACA,0BACA,oCACA,oBACA,iBAAA,EAEF,aAAYL,EAAE,WAAW,EAExB,SAAAF,EAAS,OAAQQ,GAAQA,EAAI,OAAO,EAAE,IAAKA,GAC1CH,EAAAA,IAACI,EAAA,CAEC,GAAID,EAAI,GACR,UAAW,CAAC,CAAE,SAAAE,CAAA,IACZH,EACE,uDACA,+BACAG,EACI,uCACA,sDAAA,EAIP,SAAAR,EAAEM,EAAI,OAAO,CAAA,EAZTA,EAAI,EAAA,CAcZ,CAAA,CAAA,QAGF,OAAA,CAAK,UAAU,mCACd,SAAAH,EAAAA,IAACM,IAAO,CAAA,CACV,CAAA,EACF,CAEJ"}
1
+ {"version":3,"file":"layout-Cltp3ikG.js","sources":["../../src/routes/settings/layout.tsx"],"sourcesContent":["/**\n * /settings — layout shell with sub-tab nav (environment / service).\n *\n * Workspaces / WeChat QR / Admin allowlist will land as additional\n * sub-tabs in PR-19b/c. The `mounted` flag gates their nav links.\n */\n\nimport { NavLink, Outlet } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { Topbar } from '@/components/shell/topbar'\nimport { cn } from '@/lib/utils'\n\ninterface SubTab {\n to: string\n i18nKey: string\n mounted: boolean\n}\n\nconst SUB_TABS: SubTab[] = [\n { to: 'messengers', i18nKey: 'tabs.messengers', mounted: true },\n { to: 'agents', i18nKey: 'tabs.agents', mounted: true },\n // Stage 6 — Agim Agent stack (model APIs + runtime knobs).\n { to: 'llm', i18nKey: 'tabs.llm', mounted: true },\n // v1.2.129 — mobile QR generator (open /m/chat from a phone).\n { to: 'mobile', i18nKey: 'tabs.mobile', mounted: true },\n // P1 follow-up — agim SKILL.md editor.\n { to: 'agim-skills', i18nKey: 'tabs.agimSkills', mounted: true },\n // v1.2.126 — web_search provider chain + per-provider keys.\n { to: 'search', i18nKey: 'tabs.search', mounted: true },\n { to: 'mcp', i18nKey: 'tabs.mcp', mounted: true },\n { to: 'policy', i18nKey: 'tabs.policy', mounted: true },\n { to: 'email', i18nKey: 'tabs.email', mounted: true },\n { to: 'viewer', i18nKey: 'tabs.viewer', mounted: true },\n { to: 'security', i18nKey: 'tabs.security', mounted: true },\n { to: 'workspaces', i18nKey: 'tabs.workspaces', mounted: true },\n { to: 'admins', i18nKey: 'tabs.admins', mounted: true },\n // R13 follow-up — /settings/env catch-all editor removed; raw env-var\n // editing belongs in `~/.agim/env` on the host, not in a web form.\n { to: 'service', i18nKey: 'tabs.service', mounted: true },\n]\n\nexport default function SettingsLayout(): JSX.Element {\n const { t } = useTranslation('settings')\n return (\n <div className=\"flex min-h-dvh flex-col bg-bg\">\n <Topbar />\n\n <nav\n className={cn(\n 'sticky top-0 z-10',\n 'flex items-center gap-1',\n 'border-b border-border bg-surface',\n 'px-3 sm:px-4 py-1',\n 'overflow-x-auto',\n )}\n aria-label={t('pageTitle')}\n >\n {SUB_TABS.filter((tab) => tab.mounted).map((tab) => (\n <NavLink\n key={tab.to}\n to={tab.to}\n className={({ isActive }) =>\n cn(\n 'shrink-0 rounded-md px-3 py-1.5 text-sm no-underline',\n 'transition-colors tap-target',\n isActive\n ? 'bg-accent-bg text-accent font-medium'\n : 'text-text-dim hover:bg-surface-hover hover:text-text',\n )\n }\n >\n {t(tab.i18nKey)}\n </NavLink>\n ))}\n </nav>\n\n <main className=\"flex-1 px-3 sm:px-4 py-4 pb-safe\">\n <Outlet />\n </main>\n </div>\n )\n}\n"],"names":["SUB_TABS","SettingsLayout","t","useTranslation","jsxs","jsx","Topbar","cn","tab","NavLink","isActive","Outlet"],"mappings":"uGAkBA,MAAMA,EAAqB,CACzB,CAAE,GAAI,aAAgB,QAAS,kBAAqB,QAAS,EAAA,EAC7D,CAAE,GAAI,SAAgB,QAAS,cAAqB,QAAS,EAAA,EAE7D,CAAE,GAAI,MAAgB,QAAS,WAAqB,QAAS,EAAA,EAE7D,CAAE,GAAI,SAAgB,QAAS,cAAqB,QAAS,EAAA,EAE7D,CAAE,GAAI,cAAgB,QAAS,kBAAqB,QAAS,EAAA,EAE7D,CAAE,GAAI,SAAgB,QAAS,cAAqB,QAAS,EAAA,EAC7D,CAAE,GAAI,MAAgB,QAAS,WAAqB,QAAS,EAAA,EAC7D,CAAE,GAAI,SAAgB,QAAS,cAAqB,QAAS,EAAA,EAC7D,CAAE,GAAI,QAAgB,QAAS,aAAqB,QAAS,EAAA,EAC7D,CAAE,GAAI,SAAgB,QAAS,cAAqB,QAAS,EAAA,EAC7D,CAAE,GAAI,WAAgB,QAAS,gBAAqB,QAAS,EAAA,EAC7D,CAAE,GAAI,aAAgB,QAAS,kBAAqB,QAAS,EAAA,EAC7D,CAAE,GAAI,SAAgB,QAAS,cAAqB,QAAS,EAAA,EAG7D,CAAE,GAAI,UAAgB,QAAS,eAAqB,QAAS,EAAA,CAC/D,EAEA,SAAwBC,GAA8B,CACpD,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAe,UAAU,EACvC,OACEC,EAAAA,KAAC,MAAA,CAAI,UAAU,gCACb,SAAA,CAAAC,EAAAA,IAACC,EAAA,EAAO,EAERD,EAAAA,IAAC,MAAA,CACC,UAAWE,EACT,oBACA,0BACA,oCACA,oBACA,iBAAA,EAEF,aAAYL,EAAE,WAAW,EAExB,SAAAF,EAAS,OAAQQ,GAAQA,EAAI,OAAO,EAAE,IAAKA,GAC1CH,EAAAA,IAACI,EAAA,CAEC,GAAID,EAAI,GACR,UAAW,CAAC,CAAE,SAAAE,CAAA,IACZH,EACE,uDACA,+BACAG,EACI,uCACA,sDAAA,EAIP,SAAAR,EAAEM,EAAI,OAAO,CAAA,EAZTA,EAAI,EAAA,CAcZ,CAAA,CAAA,QAGF,OAAA,CAAK,UAAU,mCACd,SAAAH,EAAAA,IAACM,IAAO,CAAA,CACV,CAAA,EACF,CAEJ"}
@@ -1,2 +1,2 @@
1
- import{u as m,j as e,S as d,g as u,h as p,i as h,k as i,f,T as b,N as j,c as x,O as g}from"./index-BIBWEKxu.js";import{u as y}from"./use-memory-w-EY79Zm.js";import"./react-DlP5eolq.js";function _({value:c,onChange:n,className:l}){const{t:r}=m("memory"),{data:o,isLoading:s}=y(),a=o?.users??[];return e.jsxs(d,{value:c||"__placeholder__",onValueChange:t=>n(t==="__placeholder__"?"":t),disabled:s||a.length===0,children:[e.jsx(u,{className:l??"h-9 w-72 max-w-full",children:e.jsx(p,{placeholder:r("userPicker.placeholder")})}),e.jsxs(h,{children:[e.jsx(i,{value:"__placeholder__",disabled:!0,children:r("userPicker.placeholder")}),a.map(t=>e.jsx(i,{value:t.user_key,children:e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-mono text-xs",children:t.user_key}),e.jsx("span",{className:"text-text-dim text-xs",children:r("userPicker.factsLabel",{count:t.fact_count})}),t.has_persona&&e.jsxs("span",{className:"text-accent text-xs",children:["·",r("userPicker.personaTag"),"·"]})]})},t.user_key))]})]})}const v=[{to:"facts",i18nKey:"tabs.facts",mounted:!0},{to:"persona",i18nKey:"tabs.persona",mounted:!0},{to:"vector",i18nKey:"tabs.vector",mounted:!0}];function P(){const{t:c}=m("memory"),[n,l]=f(),r=n.get("user")??"";function o(s){const a=new URLSearchParams(n);s?a.set("user",s):a.delete("user"),l(a,{replace:!0})}return e.jsxs("div",{className:"flex min-h-dvh flex-col bg-bg",children:[e.jsx(b,{}),e.jsx("div",{className:"border-b border-border bg-surface px-3 sm:px-4 py-2",children:e.jsxs("div",{className:"mx-auto flex max-w-7xl items-center gap-3",children:[e.jsx("span",{className:"text-sm text-text-dim shrink-0",children:c("userPicker.label")}),e.jsx(_,{value:r,onChange:o})]})}),e.jsx("nav",{className:x("sticky top-0 z-10","flex items-center gap-1","border-b border-border bg-surface","px-3 sm:px-4 py-1","overflow-x-auto"),"aria-label":c("pageTitle"),children:v.filter(s=>s.mounted).map(s=>e.jsx(j,{to:s.to,className:({isActive:a})=>x("shrink-0 rounded-md px-3 py-1.5 text-sm no-underline","transition-colors tap-target",a?"bg-accent-bg text-accent font-medium":"text-text-dim hover:bg-surface-hover hover:text-text"),children:c(s.i18nKey)},s.to))}),e.jsx("main",{className:"flex-1 px-3 sm:px-4 py-4 pb-safe",children:e.jsx(g,{})})]})}export{P as default};
2
- //# sourceMappingURL=layout-C6q-GbBZ.js.map
1
+ import{u as m,j as e,S as d,g as u,h as p,i as h,k as i,f,T as b,N as j,c as x,O as g}from"./index-B795P_3p.js";import{u as y}from"./use-memory-4xOyJX4L.js";import"./react-DlP5eolq.js";function _({value:c,onChange:n,className:l}){const{t:r}=m("memory"),{data:o,isLoading:s}=y(),a=o?.users??[];return e.jsxs(d,{value:c||"__placeholder__",onValueChange:t=>n(t==="__placeholder__"?"":t),disabled:s||a.length===0,children:[e.jsx(u,{className:l??"h-9 w-72 max-w-full",children:e.jsx(p,{placeholder:r("userPicker.placeholder")})}),e.jsxs(h,{children:[e.jsx(i,{value:"__placeholder__",disabled:!0,children:r("userPicker.placeholder")}),a.map(t=>e.jsx(i,{value:t.user_key,children:e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-mono text-xs",children:t.user_key}),e.jsx("span",{className:"text-text-dim text-xs",children:r("userPicker.factsLabel",{count:t.fact_count})}),t.has_persona&&e.jsxs("span",{className:"text-accent text-xs",children:["·",r("userPicker.personaTag"),"·"]})]})},t.user_key))]})]})}const v=[{to:"facts",i18nKey:"tabs.facts",mounted:!0},{to:"persona",i18nKey:"tabs.persona",mounted:!0},{to:"vector",i18nKey:"tabs.vector",mounted:!0}];function P(){const{t:c}=m("memory"),[n,l]=f(),r=n.get("user")??"";function o(s){const a=new URLSearchParams(n);s?a.set("user",s):a.delete("user"),l(a,{replace:!0})}return e.jsxs("div",{className:"flex min-h-dvh flex-col bg-bg",children:[e.jsx(b,{}),e.jsx("div",{className:"border-b border-border bg-surface px-3 sm:px-4 py-2",children:e.jsxs("div",{className:"mx-auto flex max-w-7xl items-center gap-3",children:[e.jsx("span",{className:"text-sm text-text-dim shrink-0",children:c("userPicker.label")}),e.jsx(_,{value:r,onChange:o})]})}),e.jsx("nav",{className:x("sticky top-0 z-10","flex items-center gap-1","border-b border-border bg-surface","px-3 sm:px-4 py-1","overflow-x-auto"),"aria-label":c("pageTitle"),children:v.filter(s=>s.mounted).map(s=>e.jsx(j,{to:s.to,className:({isActive:a})=>x("shrink-0 rounded-md px-3 py-1.5 text-sm no-underline","transition-colors tap-target",a?"bg-accent-bg text-accent font-medium":"text-text-dim hover:bg-surface-hover hover:text-text"),children:c(s.i18nKey)},s.to))}),e.jsx("main",{className:"flex-1 px-3 sm:px-4 py-4 pb-safe",children:e.jsx(g,{})})]})}export{P as default};
2
+ //# sourceMappingURL=layout-CqgDOB5t.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"layout-C6q-GbBZ.js","sources":["../../src/components/memory/user-picker.tsx","../../src/routes/memory/layout.tsx"],"sourcesContent":["/**\n * MemoryUserPicker — Select for the user_key the /memory route\n * targets. Sources the option list from useMemoryUsers, shows the\n * per-user fact_count + persona-presence as inline metadata so the\n * operator can tell which users are interesting at a glance.\n *\n * Loading: while users fetch, the trigger shows the placeholder so\n * the page doesn't jump.\n *\n * Empty bank: no users → the dropdown is disabled with a tooltip\n * explaining there's nothing to pick. Avoids a confusing \"no items\"\n * dropdown state.\n */\n\nimport { useTranslation } from 'react-i18next'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport { useMemoryUsers } from '@/hooks/use-memory'\n\nexport interface MemoryUserPickerProps {\n value: string\n onChange: (next: string) => void\n className?: string\n}\n\nexport function MemoryUserPicker({ value, onChange, className }: MemoryUserPickerProps): JSX.Element {\n const { t } = useTranslation('memory')\n const { data, isLoading } = useMemoryUsers()\n const users = data?.users ?? []\n\n return (\n <Select\n value={value || '__placeholder__'}\n onValueChange={(v) => onChange(v === '__placeholder__' ? '' : v)}\n disabled={isLoading || users.length === 0}\n >\n <SelectTrigger className={className ?? 'h-9 w-72 max-w-full'}>\n <SelectValue placeholder={t('userPicker.placeholder')} />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__placeholder__\" disabled>\n {t('userPicker.placeholder')}\n </SelectItem>\n {users.map((u) => (\n <SelectItem key={u.user_key} value={u.user_key}>\n <span className=\"flex items-center gap-2\">\n <span className=\"font-mono text-xs\">{u.user_key}</span>\n <span className=\"text-text-dim text-xs\">\n {t('userPicker.factsLabel', { count: u.fact_count })}\n </span>\n {u.has_persona && (\n <span className=\"text-accent text-xs\">·{t('userPicker.personaTag')}·</span>\n )}\n </span>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )\n}\n","/**\n * /memory — layout shell shared by every sub-tab.\n *\n * Memory is partitioned per user_key. The picker lives in the\n * layout so it's the first thing the operator sees and stays put\n * across sub-tabs (facts / persona / vector / skills). The chosen\n * user is held in URL state (?user=) so sub-tabs read it via\n * useSearchParams.\n *\n * Sub-tabs: facts / persona / vector. Skills used to live here too\n * but was promoted to its own top-level /skills tab in 2026-05 — the\n * router keeps a redirect for old /memory/skills bookmarks.\n */\n\nimport { NavLink, Outlet, useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { Topbar } from '@/components/shell/topbar'\nimport { MemoryUserPicker } from '@/components/memory/user-picker'\nimport { cn } from '@/lib/utils'\n\ninterface SubTab {\n to: string\n i18nKey: string\n mounted: boolean\n}\n\nconst SUB_TABS: SubTab[] = [\n { to: 'facts', i18nKey: 'tabs.facts', mounted: true },\n { to: 'persona', i18nKey: 'tabs.persona', mounted: true },\n { to: 'vector', i18nKey: 'tabs.vector', mounted: true },\n // 'skills' was here; promoted to top-level /skills in 2026-05.\n]\n\nexport default function MemoryLayout(): JSX.Element {\n const { t } = useTranslation('memory')\n const [params, setParams] = useSearchParams()\n const userKey = params.get('user') ?? ''\n\n function setUserKey(next: string): void {\n const p = new URLSearchParams(params)\n if (!next) p.delete('user')\n else p.set('user', next)\n setParams(p, { replace: true })\n }\n\n return (\n <div className=\"flex min-h-dvh flex-col bg-bg\">\n <Topbar />\n\n {/* User picker — the primary navigation control for this page */}\n <div className=\"border-b border-border bg-surface px-3 sm:px-4 py-2\">\n <div className=\"mx-auto flex max-w-7xl items-center gap-3\">\n <span className=\"text-sm text-text-dim shrink-0\">{t('userPicker.label')}</span>\n <MemoryUserPicker value={userKey} onChange={setUserKey} />\n </div>\n </div>\n\n {/* Sub-tab nav */}\n <nav\n className={cn(\n 'sticky top-0 z-10',\n 'flex items-center gap-1',\n 'border-b border-border bg-surface',\n 'px-3 sm:px-4 py-1',\n 'overflow-x-auto',\n )}\n aria-label={t('pageTitle')}\n >\n {SUB_TABS.filter((tab) => tab.mounted).map((tab) => (\n <NavLink\n key={tab.to}\n to={tab.to}\n className={({ isActive }) =>\n cn(\n 'shrink-0 rounded-md px-3 py-1.5 text-sm no-underline',\n 'transition-colors tap-target',\n isActive\n ? 'bg-accent-bg text-accent font-medium'\n : 'text-text-dim hover:bg-surface-hover hover:text-text',\n )\n }\n >\n {t(tab.i18nKey)}\n </NavLink>\n ))}\n </nav>\n\n <main className=\"flex-1 px-3 sm:px-4 py-4 pb-safe\">\n <Outlet />\n </main>\n </div>\n )\n}\n"],"names":["MemoryUserPicker","value","onChange","className","t","useTranslation","data","isLoading","useMemoryUsers","users","jsxs","Select","v","jsx","SelectTrigger","SelectValue","SelectContent","SelectItem","u","SUB_TABS","MemoryLayout","params","setParams","useSearchParams","userKey","setUserKey","next","p","Topbar","cn","tab","NavLink","isActive","Outlet"],"mappings":"yLA8BO,SAASA,EAAiB,CAAE,MAAAC,EAAO,SAAAC,EAAU,UAAAC,GAAiD,CACnG,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAe,QAAQ,EAC/B,CAAE,KAAAC,EAAM,UAAAC,CAAA,EAAcC,EAAA,EACtBC,EAAQH,GAAM,OAAS,CAAA,EAE7B,OACEI,EAAAA,KAACC,EAAA,CACC,MAAOV,GAAS,kBAChB,cAAgBW,GAAMV,EAASU,IAAM,kBAAoB,GAAKA,CAAC,EAC/D,SAAUL,GAAaE,EAAM,SAAW,EAExC,SAAA,CAAAI,EAAAA,IAACC,EAAA,CAAc,UAAWX,GAAa,sBACrC,SAAAU,EAAAA,IAACE,GAAY,YAAaX,EAAE,wBAAwB,CAAA,CAAG,CAAA,CACzD,SACCY,EAAA,CACC,SAAA,CAAAH,EAAAA,IAACI,GAAW,MAAM,kBAAkB,SAAQ,GACzC,SAAAb,EAAE,wBAAwB,EAC7B,EACCK,EAAM,IAAKS,GACVL,EAAAA,IAACI,EAAA,CAA4B,MAAOC,EAAE,SACpC,SAAAR,EAAAA,KAAC,OAAA,CAAK,UAAU,0BACd,SAAA,CAAAG,EAAAA,IAAC,OAAA,CAAK,UAAU,oBAAqB,SAAAK,EAAE,SAAS,EAChDL,EAAAA,IAAC,OAAA,CAAK,UAAU,wBACb,SAAAT,EAAE,wBAAyB,CAAE,MAAOc,EAAE,UAAA,CAAY,CAAA,CACrD,EACCA,EAAE,aACDR,OAAC,OAAA,CAAK,UAAU,sBAAsB,SAAA,CAAA,IAAEN,EAAE,uBAAuB,EAAE,GAAA,CAAA,CAAC,CAAA,EAExE,CAAA,EATec,EAAE,QAUnB,CACD,CAAA,CAAA,CACH,CAAA,CAAA,CAAA,CAGN,CCtCA,MAAMC,EAAqB,CACzB,CAAE,GAAI,QAAW,QAAS,aAAgB,QAAS,EAAA,EACnD,CAAE,GAAI,UAAW,QAAS,eAAgB,QAAS,EAAA,EACnD,CAAE,GAAI,SAAW,QAAS,cAAgB,QAAS,EAAA,CAErD,EAEA,SAAwBC,GAA4B,CAClD,KAAM,CAAE,EAAAhB,CAAA,EAAMC,EAAe,QAAQ,EAC/B,CAACgB,EAAQC,CAAS,EAAIC,EAAA,EACtBC,EAAUH,EAAO,IAAI,MAAM,GAAK,GAEtC,SAASI,EAAWC,EAAoB,CACtC,MAAMC,EAAI,IAAI,gBAAgBN,CAAM,EAC/BK,EACAC,EAAE,IAAI,OAAQD,CAAI,EADZC,EAAE,OAAO,MAAM,EAE1BL,EAAUK,EAAG,CAAE,QAAS,EAAA,CAAM,CAChC,CAEA,OACEjB,EAAAA,KAAC,MAAA,CAAI,UAAU,gCACb,SAAA,CAAAG,EAAAA,IAACe,EAAA,EAAO,QAGP,MAAA,CAAI,UAAU,sDACb,SAAAlB,EAAAA,KAAC,MAAA,CAAI,UAAU,4CACb,SAAA,CAAAG,MAAC,OAAA,CAAK,UAAU,iCAAkC,SAAAT,EAAE,kBAAkB,EAAE,EACxES,EAAAA,IAACb,EAAA,CAAiB,MAAOwB,EAAS,SAAUC,CAAA,CAAY,CAAA,CAAA,CAC1D,CAAA,CACF,EAGAZ,EAAAA,IAAC,MAAA,CACC,UAAWgB,EACT,oBACA,0BACA,oCACA,oBACA,iBAAA,EAEF,aAAYzB,EAAE,WAAW,EAExB,SAAAe,EAAS,OAAQW,GAAQA,EAAI,OAAO,EAAE,IAAKA,GAC1CjB,EAAAA,IAACkB,EAAA,CAEC,GAAID,EAAI,GACR,UAAW,CAAC,CAAE,SAAAE,CAAA,IACZH,EACE,uDACA,+BACAG,EACI,uCACA,sDAAA,EAIP,SAAA5B,EAAE0B,EAAI,OAAO,CAAA,EAZTA,EAAI,EAAA,CAcZ,CAAA,CAAA,QAGF,OAAA,CAAK,UAAU,mCACd,SAAAjB,EAAAA,IAACoB,IAAO,CAAA,CACV,CAAA,EACF,CAEJ"}
1
+ {"version":3,"file":"layout-CqgDOB5t.js","sources":["../../src/components/memory/user-picker.tsx","../../src/routes/memory/layout.tsx"],"sourcesContent":["/**\n * MemoryUserPicker — Select for the user_key the /memory route\n * targets. Sources the option list from useMemoryUsers, shows the\n * per-user fact_count + persona-presence as inline metadata so the\n * operator can tell which users are interesting at a glance.\n *\n * Loading: while users fetch, the trigger shows the placeholder so\n * the page doesn't jump.\n *\n * Empty bank: no users → the dropdown is disabled with a tooltip\n * explaining there's nothing to pick. Avoids a confusing \"no items\"\n * dropdown state.\n */\n\nimport { useTranslation } from 'react-i18next'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport { useMemoryUsers } from '@/hooks/use-memory'\n\nexport interface MemoryUserPickerProps {\n value: string\n onChange: (next: string) => void\n className?: string\n}\n\nexport function MemoryUserPicker({ value, onChange, className }: MemoryUserPickerProps): JSX.Element {\n const { t } = useTranslation('memory')\n const { data, isLoading } = useMemoryUsers()\n const users = data?.users ?? []\n\n return (\n <Select\n value={value || '__placeholder__'}\n onValueChange={(v) => onChange(v === '__placeholder__' ? '' : v)}\n disabled={isLoading || users.length === 0}\n >\n <SelectTrigger className={className ?? 'h-9 w-72 max-w-full'}>\n <SelectValue placeholder={t('userPicker.placeholder')} />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__placeholder__\" disabled>\n {t('userPicker.placeholder')}\n </SelectItem>\n {users.map((u) => (\n <SelectItem key={u.user_key} value={u.user_key}>\n <span className=\"flex items-center gap-2\">\n <span className=\"font-mono text-xs\">{u.user_key}</span>\n <span className=\"text-text-dim text-xs\">\n {t('userPicker.factsLabel', { count: u.fact_count })}\n </span>\n {u.has_persona && (\n <span className=\"text-accent text-xs\">·{t('userPicker.personaTag')}·</span>\n )}\n </span>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )\n}\n","/**\n * /memory — layout shell shared by every sub-tab.\n *\n * Memory is partitioned per user_key. The picker lives in the\n * layout so it's the first thing the operator sees and stays put\n * across sub-tabs (facts / persona / vector / skills). The chosen\n * user is held in URL state (?user=) so sub-tabs read it via\n * useSearchParams.\n *\n * Sub-tabs: facts / persona / vector. Skills used to live here too\n * but was promoted to its own top-level /skills tab in 2026-05 — the\n * router keeps a redirect for old /memory/skills bookmarks.\n */\n\nimport { NavLink, Outlet, useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { Topbar } from '@/components/shell/topbar'\nimport { MemoryUserPicker } from '@/components/memory/user-picker'\nimport { cn } from '@/lib/utils'\n\ninterface SubTab {\n to: string\n i18nKey: string\n mounted: boolean\n}\n\nconst SUB_TABS: SubTab[] = [\n { to: 'facts', i18nKey: 'tabs.facts', mounted: true },\n { to: 'persona', i18nKey: 'tabs.persona', mounted: true },\n { to: 'vector', i18nKey: 'tabs.vector', mounted: true },\n // 'skills' was here; promoted to top-level /skills in 2026-05.\n]\n\nexport default function MemoryLayout(): JSX.Element {\n const { t } = useTranslation('memory')\n const [params, setParams] = useSearchParams()\n const userKey = params.get('user') ?? ''\n\n function setUserKey(next: string): void {\n const p = new URLSearchParams(params)\n if (!next) p.delete('user')\n else p.set('user', next)\n setParams(p, { replace: true })\n }\n\n return (\n <div className=\"flex min-h-dvh flex-col bg-bg\">\n <Topbar />\n\n {/* User picker — the primary navigation control for this page */}\n <div className=\"border-b border-border bg-surface px-3 sm:px-4 py-2\">\n <div className=\"mx-auto flex max-w-7xl items-center gap-3\">\n <span className=\"text-sm text-text-dim shrink-0\">{t('userPicker.label')}</span>\n <MemoryUserPicker value={userKey} onChange={setUserKey} />\n </div>\n </div>\n\n {/* Sub-tab nav */}\n <nav\n className={cn(\n 'sticky top-0 z-10',\n 'flex items-center gap-1',\n 'border-b border-border bg-surface',\n 'px-3 sm:px-4 py-1',\n 'overflow-x-auto',\n )}\n aria-label={t('pageTitle')}\n >\n {SUB_TABS.filter((tab) => tab.mounted).map((tab) => (\n <NavLink\n key={tab.to}\n to={tab.to}\n className={({ isActive }) =>\n cn(\n 'shrink-0 rounded-md px-3 py-1.5 text-sm no-underline',\n 'transition-colors tap-target',\n isActive\n ? 'bg-accent-bg text-accent font-medium'\n : 'text-text-dim hover:bg-surface-hover hover:text-text',\n )\n }\n >\n {t(tab.i18nKey)}\n </NavLink>\n ))}\n </nav>\n\n <main className=\"flex-1 px-3 sm:px-4 py-4 pb-safe\">\n <Outlet />\n </main>\n </div>\n )\n}\n"],"names":["MemoryUserPicker","value","onChange","className","t","useTranslation","data","isLoading","useMemoryUsers","users","jsxs","Select","v","jsx","SelectTrigger","SelectValue","SelectContent","SelectItem","u","SUB_TABS","MemoryLayout","params","setParams","useSearchParams","userKey","setUserKey","next","p","Topbar","cn","tab","NavLink","isActive","Outlet"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{u as c,f as x,j as e,T as d,S as m,g as p,h as u,i as h,k as b,N as g,c as n,O as y}from"./index-BIBWEKxu.js";import"./react-DlP5eolq.js";const f=[{to:"health",i18nKey:"tabs.health"},{to:"topn",i18nKey:"tabs.topn"},{to:"audit",i18nKey:"tabs.audit"}],j=[1,7,30,90];function N(){const{t}=c("observability"),[r,i]=x(),l=Math.max(1,Number(r.get("days"))||7);function o(s){const a=new URLSearchParams(r);s===7?a.delete("days"):a.set("days",String(s)),i(a,{replace:!0})}return e.jsxs("div",{className:"flex min-h-dvh flex-col bg-bg",children:[e.jsx(d,{}),e.jsx("div",{className:"border-b border-border bg-surface px-3 sm:px-4 py-2",children:e.jsxs("div",{className:"mx-auto flex max-w-7xl items-center gap-3",children:[e.jsx("span",{className:"text-sm text-text-dim shrink-0",children:t("window.label")}),e.jsxs(m,{value:String(l),onValueChange:s=>o(Number(s)),children:[e.jsx(p,{className:"w-32",children:e.jsx(u,{})}),e.jsx(h,{children:j.map(s=>e.jsx(b,{value:String(s),children:t("window.days",{count:s})},s))})]})]})}),e.jsx("nav",{className:n("sticky top-0 z-10","flex items-center gap-1","border-b border-border bg-surface","px-3 sm:px-4 py-1","overflow-x-auto"),"aria-label":t("pageTitle"),children:f.map(s=>e.jsx(g,{to:s.to,className:({isActive:a})=>n("shrink-0 rounded-md px-3 py-1.5 text-sm no-underline","transition-colors tap-target",a?"bg-accent-bg text-accent font-medium":"text-text-dim hover:bg-surface-hover hover:text-text"),children:t(s.i18nKey)},s.to))}),e.jsx("main",{className:"flex-1 px-3 sm:px-4 py-4 pb-safe",children:e.jsx(y,{})})]})}export{N as default};
2
- //# sourceMappingURL=layout-7wcifbsm.js.map
1
+ import{u as c,f as x,j as e,T as d,S as m,g as p,h as u,i as h,k as b,N as g,c as n,O as y}from"./index-B795P_3p.js";import"./react-DlP5eolq.js";const f=[{to:"health",i18nKey:"tabs.health"},{to:"topn",i18nKey:"tabs.topn"},{to:"audit",i18nKey:"tabs.audit"}],j=[1,7,30,90];function N(){const{t}=c("observability"),[r,i]=x(),l=Math.max(1,Number(r.get("days"))||7);function o(s){const a=new URLSearchParams(r);s===7?a.delete("days"):a.set("days",String(s)),i(a,{replace:!0})}return e.jsxs("div",{className:"flex min-h-dvh flex-col bg-bg",children:[e.jsx(d,{}),e.jsx("div",{className:"border-b border-border bg-surface px-3 sm:px-4 py-2",children:e.jsxs("div",{className:"mx-auto flex max-w-7xl items-center gap-3",children:[e.jsx("span",{className:"text-sm text-text-dim shrink-0",children:t("window.label")}),e.jsxs(m,{value:String(l),onValueChange:s=>o(Number(s)),children:[e.jsx(p,{className:"w-32",children:e.jsx(u,{})}),e.jsx(h,{children:j.map(s=>e.jsx(b,{value:String(s),children:t("window.days",{count:s})},s))})]})]})}),e.jsx("nav",{className:n("sticky top-0 z-10","flex items-center gap-1","border-b border-border bg-surface","px-3 sm:px-4 py-1","overflow-x-auto"),"aria-label":t("pageTitle"),children:f.map(s=>e.jsx(g,{to:s.to,className:({isActive:a})=>n("shrink-0 rounded-md px-3 py-1.5 text-sm no-underline","transition-colors tap-target",a?"bg-accent-bg text-accent font-medium":"text-text-dim hover:bg-surface-hover hover:text-text"),children:t(s.i18nKey)},s.to))}),e.jsx("main",{className:"flex-1 px-3 sm:px-4 py-4 pb-safe",children:e.jsx(y,{})})]})}export{N as default};
2
+ //# sourceMappingURL=layout-DsoDxB0i.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"layout-7wcifbsm.js","sources":["../../src/routes/observability/layout.tsx"],"sourcesContent":["/**\n * /observability — layout shell with sub-tab nav (health / topn /\n * audit) + a global time-window selector that every sub-tab reads\n * via useSearchParams (?days=).\n */\n\nimport { NavLink, Outlet, useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { Topbar } from '@/components/shell/topbar'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport { cn } from '@/lib/utils'\n\nconst SUB_TABS = [\n { to: 'health', i18nKey: 'tabs.health' },\n { to: 'topn', i18nKey: 'tabs.topn' },\n { to: 'audit', i18nKey: 'tabs.audit' },\n]\n\nconst DAY_WINDOWS = [1, 7, 30, 90]\n\nexport default function ObservabilityLayout(): JSX.Element {\n const { t } = useTranslation('observability')\n const [params, setParams] = useSearchParams()\n const days = Math.max(1, Number(params.get('days')) || 7)\n\n function setDays(next: number): void {\n const p = new URLSearchParams(params)\n if (next === 7) p.delete('days')\n else p.set('days', String(next))\n setParams(p, { replace: true })\n }\n\n return (\n <div className=\"flex min-h-dvh flex-col bg-bg\">\n <Topbar />\n\n <div className=\"border-b border-border bg-surface px-3 sm:px-4 py-2\">\n <div className=\"mx-auto flex max-w-7xl items-center gap-3\">\n <span className=\"text-sm text-text-dim shrink-0\">{t('window.label')}</span>\n <Select value={String(days)} onValueChange={(v) => setDays(Number(v))}>\n <SelectTrigger className=\"w-32\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {DAY_WINDOWS.map((n) => (\n <SelectItem key={n} value={String(n)}>\n {t('window.days', { count: n })}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <nav\n className={cn(\n 'sticky top-0 z-10',\n 'flex items-center gap-1',\n 'border-b border-border bg-surface',\n 'px-3 sm:px-4 py-1',\n 'overflow-x-auto',\n )}\n aria-label={t('pageTitle')}\n >\n {SUB_TABS.map((tab) => (\n <NavLink\n key={tab.to}\n to={tab.to}\n className={({ isActive }) =>\n cn(\n 'shrink-0 rounded-md px-3 py-1.5 text-sm no-underline',\n 'transition-colors tap-target',\n isActive\n ? 'bg-accent-bg text-accent font-medium'\n : 'text-text-dim hover:bg-surface-hover hover:text-text',\n )\n }\n >\n {t(tab.i18nKey)}\n </NavLink>\n ))}\n </nav>\n\n <main className=\"flex-1 px-3 sm:px-4 py-4 pb-safe\">\n <Outlet />\n </main>\n </div>\n )\n}\n"],"names":["SUB_TABS","DAY_WINDOWS","ObservabilityLayout","useTranslation","params","setParams","useSearchParams","days","setDays","next","p","jsxs","jsx","Topbar","Select","v","SelectTrigger","SelectValue","SelectContent","n","SelectItem","cn","tab","NavLink","isActive","Outlet"],"mappings":"iJAkBA,MAAMA,EAAW,CACf,CAAE,GAAI,SAAU,QAAS,aAAA,EACzB,CAAE,GAAI,OAAU,QAAS,WAAA,EACzB,CAAE,GAAI,QAAU,QAAS,YAAA,CAC3B,EAEMC,EAAc,CAAC,EAAG,EAAG,GAAI,EAAE,EAEjC,SAAwBC,GAAmC,CACzD,KAAM,CAAE,CAAA,EAAMC,EAAe,eAAe,EACtC,CAACC,EAAQC,CAAS,EAAIC,EAAA,EACtBC,EAAO,KAAK,IAAI,EAAG,OAAOH,EAAO,IAAI,MAAM,CAAC,GAAK,CAAC,EAExD,SAASI,EAAQC,EAAoB,CACnC,MAAMC,EAAI,IAAI,gBAAgBN,CAAM,EAChCK,IAAS,EAAGC,EAAE,OAAO,MAAM,EAC1BA,EAAE,IAAI,OAAQ,OAAOD,CAAI,CAAC,EAC/BJ,EAAUK,EAAG,CAAE,QAAS,EAAA,CAAM,CAChC,CAEA,OACEC,EAAAA,KAAC,MAAA,CAAI,UAAU,gCACb,SAAA,CAAAC,EAAAA,IAACC,EAAA,EAAO,QAEP,MAAA,CAAI,UAAU,sDACb,SAAAF,EAAAA,KAAC,MAAA,CAAI,UAAU,4CACb,SAAA,CAAAC,MAAC,OAAA,CAAK,UAAU,iCAAkC,SAAA,EAAE,cAAc,EAAE,EACpED,EAAAA,KAACG,EAAA,CAAO,MAAO,OAAOP,CAAI,EAAG,cAAgBQ,GAAMP,EAAQ,OAAOO,CAAC,CAAC,EAClE,SAAA,CAAAH,MAACI,EAAA,CAAc,UAAU,OACvB,SAAAJ,MAACK,IAAY,EACf,EACAL,MAACM,GACE,SAAAjB,EAAY,IAAKkB,GAChBP,EAAAA,IAACQ,GAAmB,MAAO,OAAOD,CAAC,EAChC,SAAA,EAAE,cAAe,CAAE,MAAOA,EAAG,CAAA,EADfA,CAEjB,CACD,CAAA,CACH,CAAA,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CACF,EAEAP,EAAAA,IAAC,MAAA,CACC,UAAWS,EACT,oBACA,0BACA,oCACA,oBACA,iBAAA,EAEF,aAAY,EAAE,WAAW,EAExB,SAAArB,EAAS,IAAKsB,GACbV,EAAAA,IAACW,EAAA,CAEC,GAAID,EAAI,GACR,UAAW,CAAC,CAAE,SAAAE,CAAA,IACZH,EACE,uDACA,+BACAG,EACI,uCACA,sDAAA,EAIP,SAAA,EAAEF,EAAI,OAAO,CAAA,EAZTA,EAAI,EAAA,CAcZ,CAAA,CAAA,QAGF,OAAA,CAAK,UAAU,mCACd,SAAAV,EAAAA,IAACa,IAAO,CAAA,CACV,CAAA,EACF,CAEJ"}
1
+ {"version":3,"file":"layout-DsoDxB0i.js","sources":["../../src/routes/observability/layout.tsx"],"sourcesContent":["/**\n * /observability — layout shell with sub-tab nav (health / topn /\n * audit) + a global time-window selector that every sub-tab reads\n * via useSearchParams (?days=).\n */\n\nimport { NavLink, Outlet, useSearchParams } from 'react-router-dom'\nimport { useTranslation } from 'react-i18next'\nimport { Topbar } from '@/components/shell/topbar'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/components/ui/select'\nimport { cn } from '@/lib/utils'\n\nconst SUB_TABS = [\n { to: 'health', i18nKey: 'tabs.health' },\n { to: 'topn', i18nKey: 'tabs.topn' },\n { to: 'audit', i18nKey: 'tabs.audit' },\n]\n\nconst DAY_WINDOWS = [1, 7, 30, 90]\n\nexport default function ObservabilityLayout(): JSX.Element {\n const { t } = useTranslation('observability')\n const [params, setParams] = useSearchParams()\n const days = Math.max(1, Number(params.get('days')) || 7)\n\n function setDays(next: number): void {\n const p = new URLSearchParams(params)\n if (next === 7) p.delete('days')\n else p.set('days', String(next))\n setParams(p, { replace: true })\n }\n\n return (\n <div className=\"flex min-h-dvh flex-col bg-bg\">\n <Topbar />\n\n <div className=\"border-b border-border bg-surface px-3 sm:px-4 py-2\">\n <div className=\"mx-auto flex max-w-7xl items-center gap-3\">\n <span className=\"text-sm text-text-dim shrink-0\">{t('window.label')}</span>\n <Select value={String(days)} onValueChange={(v) => setDays(Number(v))}>\n <SelectTrigger className=\"w-32\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {DAY_WINDOWS.map((n) => (\n <SelectItem key={n} value={String(n)}>\n {t('window.days', { count: n })}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n </div>\n\n <nav\n className={cn(\n 'sticky top-0 z-10',\n 'flex items-center gap-1',\n 'border-b border-border bg-surface',\n 'px-3 sm:px-4 py-1',\n 'overflow-x-auto',\n )}\n aria-label={t('pageTitle')}\n >\n {SUB_TABS.map((tab) => (\n <NavLink\n key={tab.to}\n to={tab.to}\n className={({ isActive }) =>\n cn(\n 'shrink-0 rounded-md px-3 py-1.5 text-sm no-underline',\n 'transition-colors tap-target',\n isActive\n ? 'bg-accent-bg text-accent font-medium'\n : 'text-text-dim hover:bg-surface-hover hover:text-text',\n )\n }\n >\n {t(tab.i18nKey)}\n </NavLink>\n ))}\n </nav>\n\n <main className=\"flex-1 px-3 sm:px-4 py-4 pb-safe\">\n <Outlet />\n </main>\n </div>\n )\n}\n"],"names":["SUB_TABS","DAY_WINDOWS","ObservabilityLayout","useTranslation","params","setParams","useSearchParams","days","setDays","next","p","jsxs","jsx","Topbar","Select","v","SelectTrigger","SelectValue","SelectContent","n","SelectItem","cn","tab","NavLink","isActive","Outlet"],"mappings":"iJAkBA,MAAMA,EAAW,CACf,CAAE,GAAI,SAAU,QAAS,aAAA,EACzB,CAAE,GAAI,OAAU,QAAS,WAAA,EACzB,CAAE,GAAI,QAAU,QAAS,YAAA,CAC3B,EAEMC,EAAc,CAAC,EAAG,EAAG,GAAI,EAAE,EAEjC,SAAwBC,GAAmC,CACzD,KAAM,CAAE,CAAA,EAAMC,EAAe,eAAe,EACtC,CAACC,EAAQC,CAAS,EAAIC,EAAA,EACtBC,EAAO,KAAK,IAAI,EAAG,OAAOH,EAAO,IAAI,MAAM,CAAC,GAAK,CAAC,EAExD,SAASI,EAAQC,EAAoB,CACnC,MAAMC,EAAI,IAAI,gBAAgBN,CAAM,EAChCK,IAAS,EAAGC,EAAE,OAAO,MAAM,EAC1BA,EAAE,IAAI,OAAQ,OAAOD,CAAI,CAAC,EAC/BJ,EAAUK,EAAG,CAAE,QAAS,EAAA,CAAM,CAChC,CAEA,OACEC,EAAAA,KAAC,MAAA,CAAI,UAAU,gCACb,SAAA,CAAAC,EAAAA,IAACC,EAAA,EAAO,QAEP,MAAA,CAAI,UAAU,sDACb,SAAAF,EAAAA,KAAC,MAAA,CAAI,UAAU,4CACb,SAAA,CAAAC,MAAC,OAAA,CAAK,UAAU,iCAAkC,SAAA,EAAE,cAAc,EAAE,EACpED,EAAAA,KAACG,EAAA,CAAO,MAAO,OAAOP,CAAI,EAAG,cAAgBQ,GAAMP,EAAQ,OAAOO,CAAC,CAAC,EAClE,SAAA,CAAAH,MAACI,EAAA,CAAc,UAAU,OACvB,SAAAJ,MAACK,IAAY,EACf,EACAL,MAACM,GACE,SAAAjB,EAAY,IAAKkB,GAChBP,EAAAA,IAACQ,GAAmB,MAAO,OAAOD,CAAC,EAChC,SAAA,EAAE,cAAe,CAAE,MAAOA,EAAG,CAAA,EADfA,CAEjB,CACD,CAAA,CACH,CAAA,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CACF,EAEAP,EAAAA,IAAC,MAAA,CACC,UAAWS,EACT,oBACA,0BACA,oCACA,oBACA,iBAAA,EAEF,aAAY,EAAE,WAAW,EAExB,SAAArB,EAAS,IAAKsB,GACbV,EAAAA,IAACW,EAAA,CAEC,GAAID,EAAI,GACR,UAAW,CAAC,CAAE,SAAAE,CAAA,IACZH,EACE,uDACA,+BACAG,EACI,uCACA,sDAAA,EAIP,SAAA,EAAEF,EAAI,OAAO,CAAA,EAZTA,EAAI,EAAA,CAcZ,CAAA,CAAA,QAGF,OAAA,CAAK,UAAU,mCACd,SAAAV,EAAAA,IAACa,IAAO,CAAA,CACV,CAAA,EACF,CAEJ"}
@@ -1,4 +1,4 @@
1
- import{o as R,u as p,j as e,B as _,l as T,X as F,I as m,S as B,g as O,h as w,i as V,k as f,m as j,L as v,aa as Y,ab as q,ac as W,ad as $,ae as J}from"./index-BIBWEKxu.js";import{r as b}from"./react-DlP5eolq.js";import{T as Z,a as Q,b as K,c as E,d as ee,e as C}from"./table-Dww-k14l.js";import{u as te,a as ae}from"./use-settings-DG1rm9KU.js";import{L as S}from"./loader-circle-BQkLEJZw.js";import{R as X}from"./refresh-ccw-CFPE6zD1.js";import{S as se}from"./save-CNUmUMEf.js";import{N as ne}from"./network-Bbh3j5ew.js";import{S as le}from"./shield-alert-eOBoc2yc.js";import{B as re}from"./bell-CxPf_Xzs.js";import{H as ce}from"./heart-pulse-CrCHhXtC.js";import{T as ie}from"./trash-2-BF98SY8M.js";import{P as oe}from"./plus-6MNGQidu.js";/**
1
+ import{o as R,u as p,j as e,B as _,l as T,X as F,I as m,S as B,g as O,h as w,i as V,k as f,m as j,L as v,aa as Y,ab as q,ac as W,ad as $,ae as J}from"./index-B795P_3p.js";import{r as b}from"./react-DlP5eolq.js";import{T as Z,a as Q,b as K,c as E,d as ee,e as C}from"./table-Dl8Faxz-.js";import{u as te,a as ae}from"./use-settings-GPajsGBB.js";import{L as S}from"./loader-circle-DsLQMvHE.js";import{R as X}from"./refresh-ccw-S3sFYfDb.js";import{S as se}from"./save-DetwgDjo.js";import{N as ne}from"./network-DnBhCncp.js";import{S as le}from"./shield-alert-BM2sbwiD.js";import{B as re}from"./bell-Dm9oEZR5.js";import{H as ce}from"./heart-pulse-BfYs3KFD.js";import{T as ie}from"./trash-2-DUSLukqd.js";import{P as oe}from"./plus-6RZ3XScp.js";/**
2
2
  * @license lucide-react v0.469.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -24,4 +24,4 @@ import{o as R,u as p,j as e,B as _,l as T,X as F,I as m,S as B,g as O,h as w,i a
24
24
  * This source code is licensed under the ISC license.
25
25
  * See the LICENSE file in the root directory of this source tree.
26
26
  */const ue=R("Zap",[["path",{d:"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z",key:"1xq2db"}]]);function pe(t){return{role:t.IMHUB_NATIVE_AGENT_ROLE??"",mode:t.IMHUB_NATIVE_AGENT_MODE||"read-only",autoAllow:t.IMHUB_NATIVE_AGENT_AUTOALLOW??"",denyList:t.IMHUB_NATIVE_AGENT_DENYLIST??"",evalEnabled:y(t.IMHUB_NOTIFICATION_EVALUATOR),evalSources:t.IMHUB_NOTIFICATION_EVALUATOR_SOURCES??"",hbEnabled:y(t.IMHUB_HEARTBEAT_ENABLED),hbTickMs:t.IMHUB_HEARTBEAT_TICK_INTERVAL_MS??"",hbDefaultMin:t.IMHUB_HEARTBEAT_DEFAULT_INTERVAL_MIN??"",toolResultCap:t.IMHUB_NATIVE_TOOL_RESULT_MAX_CHARS??"",toolTimeoutMs:t.IMHUB_NATIVE_TOOL_TIMEOUT_MS??"",blankRetryMax:t.IMHUB_NATIVE_BLANK_RETRY_MAX??"",lengthRecoveryMax:t.IMHUB_NATIVE_LENGTH_RECOVERY_MAX??"",a2aMaxDepth:t.IMHUB_A2A_MAX_DEPTH??"",a2aTimeoutMs:t.IMHUB_A2A_TIMEOUT_DEFAULT_MS??"",callAgentInProcess:!L(t.IMHUB_NATIVE_CALL_AGENT_IN_PROCESS),callAgentMaxPerTurn:t.IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN??"",semanticStuckLoop:!L(t.IMHUB_NATIVE_SEMANTIC_STUCK_LOOP),criticEnabled:y(t.IMHUB_NATIVE_CRITIC),criticRole:t.IMHUB_NATIVE_CRITIC_ROLE??"",planModeDefault:y(t.IMHUB_NATIVE_PLAN_MODE),planIntentAuto:y(t.IMHUB_PLAN_INTENT_AUTO),planIntentPhrases:t.IMHUB_PLAN_INTENT_PHRASES??"",compactTriggerChars:t.IMHUB_NATIVE_COMPACT_TRIGGER_CHARS??"",compactKeepTurns:t.IMHUB_NATIVE_COMPACT_KEEP_TURNS??"",compactKeepFirst:t.IMHUB_NATIVE_COMPACT_KEEP_FIRST??"",compactSummaryChars:t.IMHUB_NATIVE_COMPACT_SUMMARY_CHARS??"",streamPartial:!L(t.IMHUB_NATIVE_STREAM_PARTIAL),maxIter:t.IMHUB_NATIVE_AGENT_MAX_ITER??""}}function L(t){if(!t)return!1;const s=t.toLowerCase().trim();return s==="off"||s==="false"||s==="0"||s==="no"}function y(t){if(!t)return!1;const s=t.toLowerCase();return s==="1"||s==="true"||s==="yes"||s==="on"}function ge(){const{t}=p(["settings","common"]),s=t("nativeAgent.subtitle"),a=t("nativeAgent.llmLink"),l=s.indexOf(a);return l===-1?e.jsx("p",{className:"text-sm text-text-dim",children:s}):e.jsxs("p",{className:"text-sm text-text-dim",children:[s.slice(0,l),e.jsx("a",{className:"underline",href:a,children:a}),s.slice(l+a.length)]})}function Ae({embedded:t=!1}){const{t:s}=p(["settings","common"]),a=te({reveal:!1}),l=ae(),g=a.data?.env??{},r=b.useMemo(()=>pe(g),[g]),[n,h]=b.useState(r),[A,i]=b.useState("");b.useEffect(()=>{const c=JSON.stringify(r);c!==A&&(h(r),i(c))},[r,A]);const d=JSON.stringify(n)!==JSON.stringify(r);function u(c,M){h(U=>({...U,[c]:M}))}async function I(){const c={};if(n.role!==r.role&&(c.IMHUB_NATIVE_AGENT_ROLE=n.role.trim()||null),n.mode!==r.mode&&(c.IMHUB_NATIVE_AGENT_MODE=n.mode),n.autoAllow!==r.autoAllow&&(c.IMHUB_NATIVE_AGENT_AUTOALLOW=n.autoAllow.trim()||null),n.denyList!==r.denyList&&(c.IMHUB_NATIVE_AGENT_DENYLIST=n.denyList.trim()||null),n.evalEnabled!==r.evalEnabled&&(c.IMHUB_NOTIFICATION_EVALUATOR=n.evalEnabled?"on":null),n.evalSources!==r.evalSources&&(c.IMHUB_NOTIFICATION_EVALUATOR_SOURCES=n.evalSources.trim()||null),n.hbEnabled!==r.hbEnabled&&(c.IMHUB_HEARTBEAT_ENABLED=n.hbEnabled?"on":null),n.hbTickMs!==r.hbTickMs&&(c.IMHUB_HEARTBEAT_TICK_INTERVAL_MS=n.hbTickMs.trim()||null),n.hbDefaultMin!==r.hbDefaultMin&&(c.IMHUB_HEARTBEAT_DEFAULT_INTERVAL_MIN=n.hbDefaultMin.trim()||null),n.toolResultCap!==r.toolResultCap&&(c.IMHUB_NATIVE_TOOL_RESULT_MAX_CHARS=n.toolResultCap.trim()||null),n.toolTimeoutMs!==r.toolTimeoutMs&&(c.IMHUB_NATIVE_TOOL_TIMEOUT_MS=n.toolTimeoutMs.trim()||null),n.blankRetryMax!==r.blankRetryMax&&(c.IMHUB_NATIVE_BLANK_RETRY_MAX=n.blankRetryMax.trim()||null),n.lengthRecoveryMax!==r.lengthRecoveryMax&&(c.IMHUB_NATIVE_LENGTH_RECOVERY_MAX=n.lengthRecoveryMax.trim()||null),n.a2aMaxDepth!==r.a2aMaxDepth&&(c.IMHUB_A2A_MAX_DEPTH=n.a2aMaxDepth.trim()||null),n.a2aTimeoutMs!==r.a2aTimeoutMs&&(c.IMHUB_A2A_TIMEOUT_DEFAULT_MS=n.a2aTimeoutMs.trim()||null),n.callAgentInProcess!==r.callAgentInProcess&&(c.IMHUB_NATIVE_CALL_AGENT_IN_PROCESS=n.callAgentInProcess?null:"off"),n.callAgentMaxPerTurn!==r.callAgentMaxPerTurn&&(c.IMHUB_NATIVE_CALL_AGENT_MAX_PER_TURN=n.callAgentMaxPerTurn.trim()||null),n.semanticStuckLoop!==r.semanticStuckLoop&&(c.IMHUB_NATIVE_SEMANTIC_STUCK_LOOP=n.semanticStuckLoop?null:"off"),n.criticEnabled!==r.criticEnabled&&(c.IMHUB_NATIVE_CRITIC=n.criticEnabled?"on":null),n.criticRole!==r.criticRole&&(c.IMHUB_NATIVE_CRITIC_ROLE=n.criticRole.trim()||null),n.planModeDefault!==r.planModeDefault&&(c.IMHUB_NATIVE_PLAN_MODE=n.planModeDefault?"1":null),n.planIntentAuto!==r.planIntentAuto&&(c.IMHUB_PLAN_INTENT_AUTO=n.planIntentAuto?"on":null),n.planIntentPhrases!==r.planIntentPhrases&&(c.IMHUB_PLAN_INTENT_PHRASES=n.planIntentPhrases.trim()||null),n.compactTriggerChars!==r.compactTriggerChars&&(c.IMHUB_NATIVE_COMPACT_TRIGGER_CHARS=n.compactTriggerChars.trim()||null),n.compactKeepTurns!==r.compactKeepTurns&&(c.IMHUB_NATIVE_COMPACT_KEEP_TURNS=n.compactKeepTurns.trim()||null),n.compactKeepFirst!==r.compactKeepFirst&&(c.IMHUB_NATIVE_COMPACT_KEEP_FIRST=n.compactKeepFirst.trim()||null),n.compactSummaryChars!==r.compactSummaryChars&&(c.IMHUB_NATIVE_COMPACT_SUMMARY_CHARS=n.compactSummaryChars.trim()||null),n.streamPartial!==r.streamPartial&&(c.IMHUB_NATIVE_STREAM_PARTIAL=n.streamPartial?null:"off"),n.maxIter!==r.maxIter&&(c.IMHUB_NATIVE_AGENT_MAX_ITER=n.maxIter.trim()||null),Object.keys(c).length!==0)try{await l.mutateAsync({updates:c}),j.success(s("nativeAgent.savedToast"))}catch(M){j.error(M?.message??String(M))}}function k(){h(r)}return e.jsxs("div",{className:t?"flex flex-col gap-6":"mx-auto flex max-w-4xl flex-col gap-6",children:[!t&&e.jsxs(e.Fragment,{children:[e.jsxs("header",{className:"flex items-center gap-3",children:[e.jsx("h1",{className:"text-xl font-semibold",children:s("nativeAgent.title")}),e.jsxs(_,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>void 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(X,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:s("nativeAgent.refresh")})]})]}),e.jsx(ge,{})]}),a.isLoading?e.jsx("div",{className:"h-64 rounded-md bg-surface-2 animate-pulse"}):e.jsxs(e.Fragment,{children:[e.jsx(be,{draft:n,setField:u}),e.jsx(ve,{draft:n,setField:u}),e.jsx(fe,{draft:n,setField:u}),e.jsx(_e,{draft:n,setField:u}),e.jsx(Te,{draft:n,setField:u}),e.jsx(Ie,{draft:n,setField:u}),e.jsx(Ne,{draft:n,setField:u}),e.jsx(je,{draft:n,setField:u})]}),d&&e.jsxs("div",{className:t?"flex items-center gap-2 rounded-md border border-border bg-surface px-4 py-3 shadow":"sticky bottom-2 flex items-center gap-2 rounded-md border border-border bg-surface px-4 py-3 shadow",children:[e.jsx(T,{variant:"info",children:s("nativeAgent.unsaved")}),e.jsxs(_,{variant:"ghost",size:"sm",className:"ml-auto",onClick:k,disabled:l.isPending,children:[e.jsx(F,{className:"h-4 w-4"})," ",s("nativeAgent.discard")]}),e.jsxs(_,{size:"sm",onClick:()=>void I(),disabled:l.isPending,children:[l.isPending?e.jsx(S,{className:"h-4 w-4 animate-spin"}):e.jsx(se,{className:"h-4 w-4"}),s("nativeAgent.save")]})]})]})}function be({draft:t,setField:s}){const{t:a}=p(["settings","common"]);return e.jsxs("section",{className:"rounded-md border border-border bg-surface",children:[e.jsxs("header",{className:"flex items-center gap-2 border-b border-border px-4 py-3",children:[e.jsx(me,{className:"h-4 w-4 text-text-dim"}),e.jsx("h2",{className:"text-sm font-semibold",children:a("nativeAgent.agentCard")})]}),e.jsxs("div",{className:"grid grid-cols-1 gap-3 p-4 sm:grid-cols-2",children:[e.jsx(o,{label:a("nativeAgent.roleOverride"),hint:a("nativeAgent.roleHint"),children:e.jsx(m,{value:t.role,onChange:l=>s("role",l.target.value),placeholder:"native-chat",className:"font-mono text-xs"})}),e.jsx(o,{label:a("nativeAgent.approvalMode"),hint:a("nativeAgent.approvalHint"),children:e.jsxs(B,{value:t.mode,onValueChange:l=>s("mode",l),children:[e.jsx(O,{children:e.jsx(w,{})}),e.jsxs(V,{children:[e.jsx(f,{value:"read-only",children:a("nativeAgent.modeReadOnly")}),e.jsx(f,{value:"allow-list",children:a("nativeAgent.modeAllowList")}),e.jsx(f,{value:"allow-all",children:a("nativeAgent.modeAllowAll")}),e.jsx(f,{value:"deny-all",children:a("nativeAgent.modeDenyAll")})]})]})}),e.jsx(o,{label:a("nativeAgent.autoAllow"),hint:a("nativeAgent.autoAllowHint"),children:e.jsx(m,{value:t.autoAllow,onChange:l=>s("autoAllow",l.target.value),placeholder:"native_,mcp_filesystem_",className:"font-mono text-xs"})}),e.jsx(o,{label:a("nativeAgent.denyList"),hint:a("nativeAgent.denyListHint"),children:e.jsx(m,{value:t.denyList,onChange:l=>s("denyList",l.target.value),placeholder:"mcp_shell_,mcp_dangerous_",className:"font-mono text-xs"})})]})]})}function Ne({draft:t,setField:s}){const{t:a}=p(["settings","common"]);return e.jsxs("section",{className:"rounded-md border border-border bg-surface",children:[e.jsxs("header",{className:"flex items-center gap-2 border-b border-border px-4 py-3",children:[e.jsx(re,{className:"h-4 w-4 text-text-dim"}),e.jsx("h2",{className:"text-sm font-semibold",children:a("nativeAgent.evaluatorCard")}),t.evalEnabled?e.jsx(T,{variant:"success",children:a("nativeAgent.on")}):e.jsx(T,{variant:"outline",children:a("nativeAgent.off")})]}),e.jsx("p",{className:"px-4 pt-2 text-xs text-text-dim",children:a("nativeAgent.evalDesc")}),e.jsxs("div",{className:"grid grid-cols-1 gap-3 p-4 sm:grid-cols-2",children:[e.jsx(o,{label:a("nativeAgent.enableGate"),children:e.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:t.evalEnabled,onChange:l=>s("evalEnabled",l.target.checked),className:"h-4 w-4 accent-accent cursor-pointer"}),e.jsx("span",{children:a("nativeAgent.filterViaLlm")})]})}),e.jsx(o,{label:a("nativeAgent.evalSources"),hint:a("nativeAgent.evalSourcesHint"),children:e.jsx(m,{value:t.evalSources,onChange:l=>s("evalSources",l.target.value),placeholder:"push,heartbeat",className:"font-mono text-xs",disabled:!t.evalEnabled})})]})]})}function je({draft:t,setField:s}){const{t:a}=p(["settings","common"]);return e.jsxs("section",{className:"rounded-md border border-border bg-surface",children:[e.jsxs("header",{className:"flex items-center gap-2 border-b border-border px-4 py-3",children:[e.jsx(ce,{className:"h-4 w-4 text-text-dim"}),e.jsx("h2",{className:"text-sm font-semibold",children:a("nativeAgent.heartbeatCard")}),t.hbEnabled?e.jsx(T,{variant:"success",children:a("nativeAgent.on")}):e.jsx(T,{variant:"outline",children:a("nativeAgent.off")})]}),e.jsx("p",{className:"px-4 pt-2 text-xs text-text-dim",children:a("nativeAgent.hbDesc")}),e.jsxs("div",{className:"grid grid-cols-1 gap-3 p-4 sm:grid-cols-3",children:[e.jsx(o,{label:a("nativeAgent.enableScheduler"),children:e.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:t.hbEnabled,onChange:l=>s("hbEnabled",l.target.checked),className:"h-4 w-4 accent-accent cursor-pointer"}),e.jsx("span",{children:a("nativeAgent.startScanLoop")})]})}),e.jsx(o,{label:a("nativeAgent.tickInterval"),hint:a("nativeAgent.tickHint"),children:e.jsx(m,{type:"number",value:t.hbTickMs,onChange:l=>s("hbTickMs",l.target.value),placeholder:"60000",className:"font-mono text-xs",disabled:!t.hbEnabled})}),e.jsx(o,{label:a("nativeAgent.defaultInterval"),hint:a("nativeAgent.defaultIntervalHint"),children:e.jsx(m,{type:"number",value:t.hbDefaultMin,onChange:l=>s("hbDefaultMin",l.target.value),placeholder:"15",className:"font-mono text-xs",disabled:!t.hbEnabled})})]})]})}function ve({draft:t,setField:s}){const{t:a}=p(["settings","common"]);return e.jsxs("section",{className:"rounded-md border border-border bg-surface",children:[e.jsxs("header",{className:"flex items-center gap-2 border-b border-border px-4 py-3",children:[e.jsx(xe,{className:"h-4 w-4 text-text-dim"}),e.jsx("h2",{className:"text-sm font-semibold",children:a("nativeAgent.runtimeCard")})]}),e.jsx("p",{className:"px-4 pt-2 text-xs text-text-dim",children:a("nativeAgent.runtimeDesc")}),e.jsxs("div",{className:"grid grid-cols-1 gap-3 p-4 sm:grid-cols-2",children:[e.jsx(o,{label:a("nativeAgent.toolResultCap"),hint:a("nativeAgent.toolResultCapHint"),children:e.jsx(m,{type:"number",value:t.toolResultCap,onChange:l=>s("toolResultCap",l.target.value),placeholder:"64000",className:"font-mono text-xs"})}),e.jsx(o,{label:a("nativeAgent.toolTimeoutMs"),hint:a("nativeAgent.toolTimeoutHint"),children:e.jsx(m,{type:"number",value:t.toolTimeoutMs,onChange:l=>s("toolTimeoutMs",l.target.value),placeholder:"60000",className:"font-mono text-xs"})}),e.jsx(o,{label:a("nativeAgent.blankRetryMax"),hint:a("nativeAgent.blankRetryHint"),children:e.jsx(m,{type:"number",value:t.blankRetryMax,onChange:l=>s("blankRetryMax",l.target.value),placeholder:"1",className:"font-mono text-xs"})}),e.jsx(o,{label:a("nativeAgent.lengthRecoveryMax"),hint:a("nativeAgent.lengthRecoveryHint"),children:e.jsx(m,{type:"number",value:t.lengthRecoveryMax,onChange:l=>s("lengthRecoveryMax",l.target.value),placeholder:"1",className:"font-mono text-xs"})})]})]})}function fe({draft:t,setField:s}){const{t:a}=p(["settings","common"]);return e.jsxs("section",{className:"rounded-md border border-border bg-surface",children:[e.jsxs("header",{className:"flex items-center gap-2 border-b border-border px-4 py-3",children:[e.jsx(ne,{className:"h-4 w-4 text-text-dim"}),e.jsx("h2",{className:"text-sm font-semibold",children:a("nativeAgent.a2aCard")})]}),e.jsx("p",{className:"px-4 pt-2 text-xs text-text-dim",children:a("nativeAgent.a2aDesc")}),e.jsxs("div",{className:"grid grid-cols-1 gap-3 p-4 sm:grid-cols-2",children:[e.jsx(o,{label:a("nativeAgent.a2aMaxDepth"),hint:a("nativeAgent.a2aMaxDepthHint"),children:e.jsx(m,{type:"number",value:t.a2aMaxDepth,onChange:l=>s("a2aMaxDepth",l.target.value),placeholder:"1",className:"font-mono text-xs"})}),e.jsx(o,{label:a("nativeAgent.a2aTimeoutMs"),hint:a("nativeAgent.a2aTimeoutMsHint"),children:e.jsx(m,{type:"number",value:t.a2aTimeoutMs,onChange:l=>s("a2aTimeoutMs",l.target.value),placeholder:"1800000",className:"font-mono text-xs"})}),e.jsx(o,{label:a("nativeAgent.callAgentInProcess"),hint:a("nativeAgent.callAgentInProcessHint"),children:e.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:t.callAgentInProcess,onChange:l=>s("callAgentInProcess",l.target.checked),className:"h-4 w-4 accent-accent cursor-pointer"}),e.jsx("span",{children:t.callAgentInProcess?a("nativeAgent.on"):a("nativeAgent.off")})]})}),e.jsx(o,{label:a("nativeAgent.callAgentMaxPerTurn"),hint:a("nativeAgent.callAgentMaxPerTurnHint"),children:e.jsx(m,{type:"number",value:t.callAgentMaxPerTurn,onChange:l=>s("callAgentMaxPerTurn",l.target.value),placeholder:"2",className:"font-mono text-xs"})})]})]})}function _e({draft:t,setField:s}){const{t:a}=p(["settings","common"]);return e.jsxs("section",{className:"rounded-md border border-border bg-surface",children:[e.jsxs("header",{className:"flex items-center gap-2 border-b border-border px-4 py-3",children:[e.jsx(le,{className:"h-4 w-4 text-text-dim"}),e.jsx("h2",{className:"text-sm font-semibold",children:a("nativeAgent.criticCard")})]}),e.jsx("p",{className:"px-4 pt-2 text-xs text-text-dim",children:a("nativeAgent.criticDesc")}),e.jsxs("div",{className:"grid grid-cols-1 gap-3 p-4 sm:grid-cols-2",children:[e.jsx(o,{label:a("nativeAgent.semanticStuckLoop"),hint:a("nativeAgent.semanticStuckLoopHint"),children:e.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:t.semanticStuckLoop,onChange:l=>s("semanticStuckLoop",l.target.checked),className:"h-4 w-4 accent-accent cursor-pointer"}),e.jsx("span",{children:t.semanticStuckLoop?a("nativeAgent.on"):a("nativeAgent.off")})]})}),e.jsx(o,{label:a("nativeAgent.criticEnabled"),hint:a("nativeAgent.criticEnabledHint"),children:e.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:t.criticEnabled,onChange:l=>s("criticEnabled",l.target.checked),className:"h-4 w-4 accent-accent cursor-pointer"}),e.jsx("span",{children:t.criticEnabled?a("nativeAgent.on"):a("nativeAgent.off")})]})}),e.jsx(o,{label:a("nativeAgent.criticRole"),hint:a("nativeAgent.criticRoleHint"),children:e.jsx(m,{value:t.criticRole,onChange:l=>s("criticRole",l.target.value),placeholder:"(use main backend)",className:"font-mono text-xs",disabled:!t.criticEnabled})}),e.jsx(o,{label:a("nativeAgent.planModeDefault"),hint:a("nativeAgent.planModeDefaultHint"),children:e.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:t.planModeDefault,onChange:l=>s("planModeDefault",l.target.checked),className:"h-4 w-4 accent-accent cursor-pointer"}),e.jsx("span",{children:t.planModeDefault?a("nativeAgent.on"):a("nativeAgent.off")})]})}),e.jsx(o,{label:a("nativeAgent.planIntentAuto"),hint:a("nativeAgent.planIntentAutoHint"),children:e.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:t.planIntentAuto,onChange:l=>s("planIntentAuto",l.target.checked),className:"h-4 w-4 accent-accent cursor-pointer"}),e.jsx("span",{children:t.planIntentAuto?a("nativeAgent.on"):a("nativeAgent.off")})]})}),e.jsx(o,{label:a("nativeAgent.planIntentPhrases"),hint:a("nativeAgent.planIntentPhrasesHint"),children:e.jsx(m,{value:t.planIntentPhrases,onChange:l=>s("planIntentPhrases",l.target.value),placeholder:"先想想,plan only,don't act yet",className:"font-mono text-xs",disabled:!t.planIntentAuto})})]})]})}function Te({draft:t,setField:s}){const{t:a}=p(["settings","common"]);return e.jsxs("section",{className:"rounded-md border border-border bg-surface",children:[e.jsxs("header",{className:"flex items-center gap-2 border-b border-border px-4 py-3",children:[e.jsx(de,{className:"h-4 w-4 text-text-dim"}),e.jsx("h2",{className:"text-sm font-semibold",children:a("nativeAgent.compactCard")})]}),e.jsx("p",{className:"px-4 pt-2 text-xs text-text-dim",children:a("nativeAgent.compactDesc")}),e.jsxs("div",{className:"grid grid-cols-1 gap-3 p-4 sm:grid-cols-2",children:[e.jsx(o,{label:a("nativeAgent.compactTriggerChars"),hint:a("nativeAgent.compactTriggerCharsHint"),children:e.jsx(m,{type:"number",value:t.compactTriggerChars,onChange:l=>s("compactTriggerChars",l.target.value),placeholder:"60000",className:"font-mono text-xs"})}),e.jsx(o,{label:a("nativeAgent.compactKeepTurns"),hint:a("nativeAgent.compactKeepTurnsHint"),children:e.jsx(m,{type:"number",value:t.compactKeepTurns,onChange:l=>s("compactKeepTurns",l.target.value),placeholder:"6",className:"font-mono text-xs"})}),e.jsx(o,{label:a("nativeAgent.compactKeepFirst"),hint:a("nativeAgent.compactKeepFirstHint"),children:e.jsx(m,{type:"number",value:t.compactKeepFirst,onChange:l=>s("compactKeepFirst",l.target.value),placeholder:"1",className:"font-mono text-xs"})}),e.jsx(o,{label:a("nativeAgent.compactSummaryChars"),hint:a("nativeAgent.compactSummaryCharsHint"),children:e.jsx(m,{type:"number",value:t.compactSummaryChars,onChange:l=>s("compactSummaryChars",l.target.value),placeholder:"1500",className:"font-mono text-xs"})})]})]})}function Ie({draft:t,setField:s}){const{t:a}=p(["settings","common"]);return e.jsxs("section",{className:"rounded-md border border-border bg-surface",children:[e.jsxs("header",{className:"flex items-center gap-2 border-b border-border px-4 py-3",children:[e.jsx(he,{className:"h-4 w-4 text-text-dim"}),e.jsx("h2",{className:"text-sm font-semibold",children:a("nativeAgent.streamCard")})]}),e.jsx("p",{className:"px-4 pt-2 text-xs text-text-dim",children:a("nativeAgent.streamDesc")}),e.jsxs("div",{className:"grid grid-cols-1 gap-3 p-4 sm:grid-cols-2",children:[e.jsx(o,{label:a("nativeAgent.streamPartial"),hint:a("nativeAgent.streamPartialHint"),children:e.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:t.streamPartial,onChange:l=>s("streamPartial",l.target.checked),className:"h-4 w-4 accent-accent cursor-pointer"}),e.jsx("span",{children:t.streamPartial?a("nativeAgent.on"):a("nativeAgent.off")})]})}),e.jsx(o,{label:a("nativeAgent.maxIter"),hint:a("nativeAgent.maxIterHint"),children:e.jsx(m,{type:"number",value:t.maxIter,onChange:l=>s("maxIter",l.target.value),placeholder:"50",className:"font-mono text-xs"})})]})]})}function o({label:t,hint:s,children:a}){return e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(v,{className:"text-xs font-medium",children:t}),a,s&&e.jsx("p",{className:"text-[11px] text-text-dim",children:s})]})}const Me=["cheap","evaluator","native-chat"],P="__unbind__",G=["deepseek","moonshot","zhipu","openai","anthropic","custom"],H=[{provider:"openai-compat",baseUrl:"https://api.deepseek.com/v1",modelHint:"deepseek-chat"},{provider:"openai-compat",baseUrl:"https://api.moonshot.cn/v1",modelHint:"moonshot-v1-8k"},{provider:"openai-compat",baseUrl:"https://open.bigmodel.cn/api/paas/v4",modelHint:"glm-4-air"},{provider:"openai-compat",baseUrl:"https://api.openai.com/v1",modelHint:"gpt-4o-mini"},{provider:"anthropic",baseUrl:"https://api.anthropic.com",modelHint:"claude-3-5-sonnet-20241022"},{provider:"openai-compat",baseUrl:"",modelHint:""}];function Ge(){const{t}=p(["settings","common"]),s=Y();return e.jsxs("div",{className:"mx-auto flex max-w-5xl flex-col gap-6",children:[e.jsxs("header",{className:"flex items-center gap-3",children:[e.jsx("h1",{className:"text-xl font-semibold",children:t("llm.title")}),e.jsxs(_,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>void s.refetch(),disabled:s.isFetching,"aria-label":t("actions.refresh",{ns:"common"}),children:[s.isFetching?e.jsx(S,{className:"h-4 w-4 animate-spin"}):e.jsx(X,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:t("llm.refresh")})]})]}),e.jsx("p",{className:"text-sm text-text-dim",children:t("llm.subtitle")}),s.isLoading?e.jsx("div",{className:"h-64 rounded-md bg-surface-2 animate-pulse"}):e.jsxs(e.Fragment,{children:[e.jsx(Ee,{data:s.data}),e.jsx(ye,{}),e.jsx(Ce,{data:s.data}),e.jsxs("section",{id:"agim-agent",className:"rounded-md border border-border bg-surface px-4 py-3",children:[e.jsx("h2",{className:"text-sm font-semibold",children:t("llm.agimAgentRuntimeTitle")}),e.jsx("p",{className:"mt-1 text-xs text-text-dim",children:t("llm.agimAgentRuntimeHint")})]}),e.jsx(Ae,{embedded:!0})]})]})}function Ee({data:t}){const{t:s}=p(["settings","common"]),a=q(),l=W(),[g,r]=b.useState({});async function n(i){if(confirm(s("llm.removeConfirm",{name:i})))try{const d=await a.mutateAsync(i);j.success(s("llm.removedToast",{count:d.removedRoles}))}catch(d){j.error(d?.message??String(d))}}async function h(i){r(d=>({...d,[i]:s("llm.pinging")}));try{const d=await l.mutateAsync(i),u=d.ok?`✓ ${d.durationMs}ms · tokens ${d.tokensIn}→${d.tokensOut}`:`✗ ${d.error}`;r(I=>({...I,[i]:u}))}catch(d){r(u=>({...u,[i]:`✗ ${d?.message??String(d)}`}))}}const A=t?.backends??[];return A.length===0?e.jsx("section",{className:"rounded-md border border-border bg-surface p-6 text-center text-sm text-text-dim",children:s("llm.backendsEmpty")}):e.jsxs("section",{className:"rounded-md border border-border bg-surface",children:[e.jsx("header",{className:"border-b border-border px-4 py-3",children:e.jsx("h2",{className:"text-sm font-semibold",children:s("llm.backendsTitle",{count:A.length})})}),e.jsxs(Z,{children:[e.jsx(Q,{children:e.jsxs(K,{children:[e.jsx(E,{children:s("llm.col.name")}),e.jsx(E,{children:s("llm.col.provider")}),e.jsx(E,{children:s("llm.col.model")}),e.jsx(E,{children:s("llm.col.baseUrl")}),e.jsx(E,{children:s("llm.col.apiKey")}),e.jsx(E,{children:s("llm.col.actions")})]})}),e.jsx(ee,{children:A.map(i=>{const d=i.secret.source==="none"?e.jsx(T,{variant:"outline",children:s("llm.secretMissing")}):e.jsx(T,{variant:"success",children:i.secret.source});return e.jsxs(K,{children:[e.jsx(C,{className:"font-mono text-xs",children:i.name}),e.jsx(C,{children:i.provider}),e.jsx(C,{className:"font-mono text-xs",children:i.model}),e.jsx(C,{className:"break-all font-mono text-[11px] text-text-dim",children:i.baseUrl??"—"}),e.jsx(C,{children:d}),e.jsxs(C,{className:"flex flex-col gap-1 sm:flex-row sm:items-center",children:[e.jsxs(_,{variant:"ghost",size:"sm",onClick:()=>void h(i.name),disabled:l.isPending||i.secret.source==="none",title:i.secret.source==="none"?s("llm.setKeyFirst"):s("llm.pingHint"),children:[e.jsx(ue,{className:"h-4 w-4"}),e.jsx("span",{children:s("llm.ping")})]}),e.jsxs(_,{variant:"ghost",size:"sm",onClick:()=>void n(i.name),disabled:a.isPending,className:"text-danger hover:text-danger",children:[e.jsx(ie,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:s("llm.remove")})]}),g[i.name]&&e.jsx("span",{className:"ml-2 text-[11px] text-text-dim",children:g[i.name]})]})]},i.name)})})]})]})}function Ce({data:t}){const{t:s}=p(["settings","common"]),a=J(),l=(t?.backends??[]).map(n=>n.name),g=t?.roles??{};async function r(n,h){const A={[n]:h===P?null:h};try{await a.mutateAsync(A),j.success(s("llm.roleUpdated",{role:n}))}catch(i){j.error(i?.message??String(i))}}return e.jsxs("section",{className:"rounded-md border border-border bg-surface",children:[e.jsxs("header",{className:"border-b border-border px-4 py-3",children:[e.jsx("h2",{className:"text-sm font-semibold",children:s("llm.rolesTitle")}),e.jsx("p",{className:"mt-1 text-xs text-text-dim",children:s("llm.rolesOptionalHint")})]}),e.jsx("div",{className:"grid grid-cols-1 gap-3 p-4 sm:grid-cols-3",children:Me.map(n=>e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(v,{className:"text-xs font-medium",children:n}),e.jsxs(B,{value:g[n]??P,onValueChange:h=>void r(n,h),disabled:l.length===0||a.isPending,children:[e.jsx(O,{className:"font-mono text-xs",children:e.jsx(w,{placeholder:s("llm.unset")})}),e.jsxs(V,{children:[e.jsx(f,{value:P,children:s("llm.unbound")}),l.map(h=>e.jsx(f,{value:h,children:h},h))]})]}),e.jsx("p",{className:"text-[11px] text-text-dim",children:s(`llm.roleHint.${n}`)})]},n))})]})}function ye(){const{t}=p(["settings","common"]),s=$(),[a,l]=b.useState(0),[g,r]=b.useState(""),[n,h]=b.useState(H[0]?.baseUrl??""),[A,i]=b.useState(H[0]?.modelHint??""),[d,u]=b.useState(""),[I,k]=b.useState(null);function c(x){k(x),j.error(x)}function M(x){l(x);const N=H[x];N&&(h(N.baseUrl),i(N.modelHint))}async function U(x){x.preventDefault();const N=H[a];if(!N){c(t("llm.invalidPreset"));return}if(!g.trim()){c(t("llm.nameRequired"));return}if(!n.trim()){c(t("llm.baseUrlRequired"));return}if(!A.trim()){c(t("llm.modelRequired"));return}if(!d.trim()){c(t("llm.apiKeyRequired"));return}try{await s.mutateAsync({name:g.trim(),provider:N.provider,baseUrl:n.trim(),model:A.trim(),apiKey:d.trim()}),k(null),j.success(t("llm.addedWithKey",{name:g.trim()})),r(""),u("")}catch(D){const z=D?.message??String(D);c(z)}}return e.jsxs("section",{className:"rounded-md border border-border bg-surface",children:[e.jsx("header",{className:"border-b border-border px-4 py-3",children:e.jsx("h2",{className:"text-sm font-semibold",children:t("llm.addTitle")})}),e.jsxs("form",{onSubmit:x=>void U(x),className:"grid grid-cols-1 gap-3 p-4 sm:grid-cols-2",children:[e.jsxs("div",{children:[e.jsx(v,{className:"text-xs font-medium",children:t("llm.preset")}),e.jsxs(B,{value:String(a),onValueChange:x=>M(Number(x)),children:[e.jsx(O,{children:e.jsx(w,{})}),e.jsx(V,{children:H.map((x,N)=>e.jsx(f,{value:String(N),children:t(`llm.presets.${G[N]}`)},G[N]))})]})]}),e.jsxs("div",{children:[e.jsx(v,{className:"text-xs font-medium",children:t("llm.name")}),e.jsx(m,{value:g,onChange:x=>r(x.target.value),placeholder:t("llm.namePlaceholder"),className:"font-mono text-xs"})]}),e.jsxs("div",{className:"sm:col-span-2",children:[e.jsx(v,{className:"text-xs font-medium",children:t("llm.baseUrl")}),e.jsx(m,{value:n,onChange:x=>h(x.target.value),placeholder:t("llm.baseUrlPlaceholder"),className:"font-mono text-xs"})]}),e.jsxs("div",{children:[e.jsx(v,{className:"text-xs font-medium",children:t("llm.model")}),e.jsx(m,{value:A,onChange:x=>i(x.target.value),placeholder:t("llm.modelPlaceholder"),className:"font-mono text-xs"})]}),e.jsxs("div",{children:[e.jsx(v,{className:"text-xs font-medium",children:t("llm.apiKey")}),e.jsx(m,{type:"password",value:d,onChange:x=>u(x.target.value),placeholder:t("llm.apiKeyPlaceholder"),className:"font-mono text-xs",autoComplete:"off"})]}),e.jsx("div",{className:"sm:col-span-2 flex",children:e.jsxs("div",{className:"flex w-full flex-col gap-2 sm:items-end",children:[I&&e.jsx("p",{className:"text-xs text-danger",children:I}),e.jsxs(_,{type:"submit",disabled:s.isPending,className:"ml-auto",children:[s.isPending?e.jsx(S,{className:"h-4 w-4 animate-spin"}):e.jsx(oe,{className:"h-4 w-4"}),t("llm.addBackend")]})]})})]})]})}export{Ge as default};
27
- //# sourceMappingURL=llm-DwZX5fwY.js.map
27
+ //# sourceMappingURL=llm-D3Kd9gqa.js.map