agim-cli 1.2.114 → 1.2.116
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.
- package/CHANGELOG.md +68 -0
- package/dist/web/public/assets/{a2a-DjyqPnWh.js → a2a-DoPVhKvM.js} +3 -3
- package/dist/web/public/assets/{a2a-DjyqPnWh.js.map → a2a-DoPVhKvM.js.map} +1 -1
- package/dist/web/public/assets/{activity-Dy3elxiH.js → activity-CegIax_4.js} +2 -2
- package/dist/web/public/assets/{activity-Dy3elxiH.js.map → activity-CegIax_4.js.map} +1 -1
- package/dist/web/public/assets/{admins-p5qJnsCS.js → admins-BCOor7EH.js} +3 -3
- package/dist/web/public/assets/{admins-p5qJnsCS.js.map → admins-BCOor7EH.js.map} +1 -1
- package/dist/web/public/assets/{agents-BK-LNF6u.js → agents-BLw0_jKM.js} +3 -3
- package/dist/web/public/assets/{agents-BK-LNF6u.js.map → agents-BLw0_jKM.js.map} +1 -1
- package/dist/web/public/assets/approvals-CXQok6Cz.js +5 -0
- package/dist/web/public/assets/approvals-CXQok6Cz.js.map +1 -0
- package/dist/web/public/assets/{asks-1MaTIfZO.js → asks-xP2Otb6U.js} +2 -2
- package/dist/web/public/assets/{asks-1MaTIfZO.js.map → asks-xP2Otb6U.js.map} +1 -1
- package/dist/web/public/assets/{audit-jSgqqxdG.js → audit-DNYwnXg8.js} +2 -2
- package/dist/web/public/assets/{audit-jSgqqxdG.js.map → audit-DNYwnXg8.js.map} +1 -1
- package/dist/web/public/assets/{bell-LeCqn72n.js → bell-WsDs6GmV.js} +2 -2
- package/dist/web/public/assets/{bell-LeCqn72n.js.map → bell-WsDs6GmV.js.map} +1 -1
- package/dist/web/public/assets/{bgjobs-BPyKhOuq.js → bgjobs-B2BaMU2j.js} +3 -3
- package/dist/web/public/assets/{bgjobs-BPyKhOuq.js.map → bgjobs-B2BaMU2j.js.map} +1 -1
- package/dist/web/public/assets/{brain-CPuDSbdC.js → brain-B8fJEQyw.js} +2 -2
- package/dist/web/public/assets/{brain-CPuDSbdC.js.map → brain-B8fJEQyw.js.map} +1 -1
- package/dist/web/public/assets/{briefcase-Ck3PTo9z.js → briefcase-Cwk6Nkg7.js} +2 -2
- package/dist/web/public/assets/{briefcase-Ck3PTo9z.js.map → briefcase-Cwk6Nkg7.js.map} +1 -1
- package/dist/web/public/assets/{chevron-right-CNLUFBr6.js → chevron-right-D1NFHRso.js} +2 -2
- package/dist/web/public/assets/{chevron-right-CNLUFBr6.js.map → chevron-right-D1NFHRso.js.map} +1 -1
- package/dist/web/public/assets/{circle-check-CsSqoqeq.js → circle-check-C5jWAGrG.js} +2 -2
- package/dist/web/public/assets/{circle-check-CsSqoqeq.js.map → circle-check-C5jWAGrG.js.map} +1 -1
- package/dist/web/public/assets/{circle-check-big-NZvva0KN.js → circle-check-big-BMc_m83k.js} +2 -2
- package/dist/web/public/assets/{circle-check-big-NZvva0KN.js.map → circle-check-big-BMc_m83k.js.map} +1 -1
- package/dist/web/public/assets/{circle-x-CFWz6gEd.js → circle-x-DK_VnW5O.js} +2 -2
- package/dist/web/public/assets/{circle-x-CFWz6gEd.js.map → circle-x-DK_VnW5O.js.map} +1 -1
- package/dist/web/public/assets/confirm-dialog-CBbIPd8e.js +2 -0
- package/dist/web/public/assets/{confirm-dialog-DgO--07o.js.map → confirm-dialog-CBbIPd8e.js.map} +1 -1
- package/dist/web/public/assets/{data-table-D-Zgmc4f.js → data-table-Dw8WxmGK.js} +5 -5
- package/dist/web/public/assets/{data-table-D-Zgmc4f.js.map → data-table-Dw8WxmGK.js.map} +1 -1
- package/dist/web/public/assets/{dialog-CQgpA4K2.js → dialog-Byj1GNwS.js} +3 -3
- package/dist/web/public/assets/{dialog-CQgpA4K2.js.map → dialog-Byj1GNwS.js.map} +1 -1
- package/dist/web/public/assets/{download-DKzhn49i.js → download-PHySCcQT.js} +2 -2
- package/dist/web/public/assets/{download-DKzhn49i.js.map → download-PHySCcQT.js.map} +1 -1
- package/dist/web/public/assets/{email-j2wp12wu.js → email-BRL-m3Nq.js} +3 -3
- package/dist/web/public/assets/{email-j2wp12wu.js.map → email-BRL-m3Nq.js.map} +1 -1
- package/dist/web/public/assets/{empty-state-C_hR--ro.js → empty-state-C4sK7D2H.js} +2 -2
- package/dist/web/public/assets/{empty-state-C_hR--ro.js.map → empty-state-C4sK7D2H.js.map} +1 -1
- package/dist/web/public/assets/{external-link-CoqEoAcO.js → external-link-CFqp81U8.js} +2 -2
- package/dist/web/public/assets/{external-link-CoqEoAcO.js.map → external-link-CFqp81U8.js.map} +1 -1
- package/dist/web/public/assets/{eye-CXOBz4Cl.js → eye-znt0VqpD.js} +4 -4
- package/dist/web/public/assets/{eye-CXOBz4Cl.js.map → eye-znt0VqpD.js.map} +1 -1
- package/dist/web/public/assets/{facts-CJDnig7y.js → facts-C-z_MHuR.js} +2 -2
- package/dist/web/public/assets/{facts-CJDnig7y.js.map → facts-C-z_MHuR.js.map} +1 -1
- package/dist/web/public/assets/{goals-D89OCyJN.js → goals-DjW7xUUU.js} +4 -4
- package/dist/web/public/assets/{goals-D89OCyJN.js.map → goals-DjW7xUUU.js.map} +1 -1
- package/dist/web/public/assets/{health-BQwZeXAS.js → health-u3wVVbRE.js} +2 -2
- package/dist/web/public/assets/{health-BQwZeXAS.js.map → health-u3wVVbRE.js.map} +1 -1
- package/dist/web/public/assets/{heart-pulse-BzJZEKl7.js → heart-pulse-CuRQDV1Z.js} +2 -2
- package/dist/web/public/assets/{heart-pulse-BzJZEKl7.js.map → heart-pulse-CuRQDV1Z.js.map} +1 -1
- package/dist/web/public/assets/{heartbeat-D4kJCmkw.js → heartbeat-fKsOewwO.js} +3 -3
- package/dist/web/public/assets/{heartbeat-D4kJCmkw.js.map → heartbeat-fKsOewwO.js.map} +1 -1
- package/dist/web/public/assets/{hot-R6aOoPMY.js → hot-ClV4mA4o.js} +4 -4
- package/dist/web/public/assets/{hot-R6aOoPMY.js.map → hot-ClV4mA4o.js.map} +1 -1
- package/dist/web/public/assets/index-7yc9y9We.js +199 -0
- package/dist/web/public/assets/index-7yc9y9We.js.map +1 -0
- package/dist/web/public/assets/index-hiagPF9i.css +1 -0
- package/dist/web/public/assets/{installed-DSJ7AiMe.js → installed-BtgOuIiG.js} +4 -4
- package/dist/web/public/assets/{installed-DSJ7AiMe.js.map → installed-BtgOuIiG.js.map} +1 -1
- package/dist/web/public/assets/{jobs-CdVDgq8m.js → jobs-eiyYlyJG.js} +2 -2
- package/dist/web/public/assets/{jobs-CdVDgq8m.js.map → jobs-eiyYlyJG.js.map} +1 -1
- package/dist/web/public/assets/{layout-BLKq93Z4.js → layout-BpwuHk-s.js} +2 -2
- package/dist/web/public/assets/{layout-BLKq93Z4.js.map → layout-BpwuHk-s.js.map} +1 -1
- package/dist/web/public/assets/{layout-BKjENLxQ.js → layout-CChyylLw.js} +2 -2
- package/dist/web/public/assets/{layout-BKjENLxQ.js.map → layout-CChyylLw.js.map} +1 -1
- package/dist/web/public/assets/{layout-CvmElCgO.js → layout-CQ-wMpff.js} +2 -2
- package/dist/web/public/assets/{layout-CvmElCgO.js.map → layout-CQ-wMpff.js.map} +1 -1
- package/dist/web/public/assets/{layout-BqilVxGS.js → layout-DuYDIza7.js} +2 -2
- package/dist/web/public/assets/{layout-BqilVxGS.js.map → layout-DuYDIza7.js.map} +1 -1
- package/dist/web/public/assets/{layout-Dj03GsQJ.js → layout-Oy_rbq06.js} +2 -2
- package/dist/web/public/assets/{layout-Dj03GsQJ.js.map → layout-Oy_rbq06.js.map} +1 -1
- package/dist/web/public/assets/{llm-C5Uob7Ci.js → llm-Bs-G20DR.js} +3 -3
- package/dist/web/public/assets/{llm-C5Uob7Ci.js.map → llm-Bs-G20DR.js.map} +1 -1
- package/dist/web/public/assets/{loader-circle-DdWIiO8L.js → loader-circle-CwM-6o9f.js} +2 -2
- package/dist/web/public/assets/{loader-circle-DdWIiO8L.js.map → loader-circle-CwM-6o9f.js.map} +1 -1
- package/dist/web/public/assets/{map-pin-kO-wD4fU.js → map-pin-MuWUOLcD.js} +2 -2
- package/dist/web/public/assets/{map-pin-kO-wD4fU.js.map → map-pin-MuWUOLcD.js.map} +1 -1
- package/dist/web/public/assets/{mcp-DL5oUQgm.js → mcp-D9ob2tYX.js} +3 -3
- package/dist/web/public/assets/{mcp-DL5oUQgm.js.map → mcp-D9ob2tYX.js.map} +1 -1
- package/dist/web/public/assets/{memos-Ab9Rp5v_.js → memos-Bd7EttaU.js} +3 -3
- package/dist/web/public/assets/{memos-Ab9Rp5v_.js.map → memos-Bd7EttaU.js.map} +1 -1
- package/dist/web/public/assets/{messengers-D0a8jlLw.js → messengers-CbnTejKi.js} +3 -3
- package/dist/web/public/assets/{messengers-D0a8jlLw.js.map → messengers-CbnTejKi.js.map} +1 -1
- package/dist/web/public/assets/{native-agent-Bnz7Inoh.js → native-agent-BmBH1fBn.js} +3 -3
- package/dist/web/public/assets/{native-agent-Bnz7Inoh.js.map → native-agent-BmBH1fBn.js.map} +1 -1
- package/dist/web/public/assets/{network-BrQvlSjl.js → network-Cdb-7ukZ.js} +2 -2
- package/dist/web/public/assets/{network-BrQvlSjl.js.map → network-Cdb-7ukZ.js.map} +1 -1
- package/dist/web/public/assets/{outbox-BNDPAlVy.js → outbox-BsdSXMUW.js} +3 -3
- package/dist/web/public/assets/{outbox-BNDPAlVy.js.map → outbox-BsdSXMUW.js.map} +1 -1
- package/dist/web/public/assets/pagination-BuNA-fxU.js +17 -0
- package/dist/web/public/assets/{pagination-CyoXKAm9.js.map → pagination-BuNA-fxU.js.map} +1 -1
- package/dist/web/public/assets/{persona-Bxqqj1yV.js → persona-V0lGwDex.js} +2 -2
- package/dist/web/public/assets/{persona-Bxqqj1yV.js.map → persona-V0lGwDex.js.map} +1 -1
- package/dist/web/public/assets/{play-B7ZN5aFX.js → play-BdDkAgqw.js} +2 -2
- package/dist/web/public/assets/{play-B7ZN5aFX.js.map → play-BdDkAgqw.js.map} +1 -1
- package/dist/web/public/assets/{plus-DzvDGrh0.js → plus-FlZ1UWzO.js} +2 -2
- package/dist/web/public/assets/{plus-DzvDGrh0.js.map → plus-FlZ1UWzO.js.map} +1 -1
- package/dist/web/public/assets/policy-CpWgbIqb.js +2 -0
- package/dist/web/public/assets/{policy-CSl5ENVs.js.map → policy-CpWgbIqb.js.map} +1 -1
- package/dist/web/public/assets/{refresh-ccw-B8Fzl2uq.js → refresh-ccw-l9Z6wukO.js} +2 -2
- package/dist/web/public/assets/{refresh-ccw-B8Fzl2uq.js.map → refresh-ccw-l9Z6wukO.js.map} +1 -1
- package/dist/web/public/assets/{reminders-CmLd8DLt.js → reminders-Coh0D3Fv.js} +3 -3
- package/dist/web/public/assets/{reminders-CmLd8DLt.js.map → reminders-Coh0D3Fv.js.map} +1 -1
- package/dist/web/public/assets/{save-JKib3YIn.js → save-CllPj34m.js} +2 -2
- package/dist/web/public/assets/{save-JKib3YIn.js.map → save-CllPj34m.js.map} +1 -1
- package/dist/web/public/assets/{schedules-B-770HIa.js → schedules-0rlWAXrz.js} +3 -3
- package/dist/web/public/assets/{schedules-B-770HIa.js.map → schedules-0rlWAXrz.js.map} +1 -1
- package/dist/web/public/assets/{search-Bc7OS8FB.js → search-DDbspILM.js} +2 -2
- package/dist/web/public/assets/{search-Bc7OS8FB.js.map → search-DDbspILM.js.map} +1 -1
- package/dist/web/public/assets/{security-CD8INSD5.js → security-SlM_YhUr.js} +2 -2
- package/dist/web/public/assets/{security-CD8INSD5.js.map → security-SlM_YhUr.js.map} +1 -1
- package/dist/web/public/assets/{service-CFB2QfK6.js → service-BnbEtpH9.js} +3 -3
- package/dist/web/public/assets/{service-CFB2QfK6.js.map → service-BnbEtpH9.js.map} +1 -1
- package/dist/web/public/assets/{status-badge---MleYSt.js → status-badge-DKc8aeGe.js} +2 -2
- package/dist/web/public/assets/{status-badge---MleYSt.js.map → status-badge-DKc8aeGe.js.map} +1 -1
- package/dist/web/public/assets/{subtasks-CzToK_65.js → subtasks-2PcTOMXV.js} +2 -2
- package/dist/web/public/assets/{subtasks-CzToK_65.js.map → subtasks-2PcTOMXV.js.map} +1 -1
- package/dist/web/public/assets/table-BIc6RbM1.js +2 -0
- package/dist/web/public/assets/{table-Dg3N5NYh.js.map → table-BIc6RbM1.js.map} +1 -1
- package/dist/web/public/assets/{topn-CePuMziu.js → topn-Bn-Y2tpa.js} +2 -2
- package/dist/web/public/assets/{topn-CePuMziu.js.map → topn-Bn-Y2tpa.js.map} +1 -1
- package/dist/web/public/assets/{trash-2-LmyUghia.js → trash-2-UPbZm-9k.js} +3 -3
- package/dist/web/public/assets/{trash-2-LmyUghia.js.map → trash-2-UPbZm-9k.js.map} +1 -1
- package/dist/web/public/assets/{use-background-tasks-CmVigPtZ.js → use-background-tasks-DyaXWxmJ.js} +2 -2
- package/dist/web/public/assets/{use-background-tasks-CmVigPtZ.js.map → use-background-tasks-DyaXWxmJ.js.map} +1 -1
- package/dist/web/public/assets/use-llm-admin-DO9nbZeO.js +2 -0
- package/dist/web/public/assets/{use-llm-admin-D8Go_PKM.js.map → use-llm-admin-DO9nbZeO.js.map} +1 -1
- package/dist/web/public/assets/use-memory-Bf-AR2xS.js +2 -0
- package/dist/web/public/assets/{use-memory-BDuQTDX0.js.map → use-memory-Bf-AR2xS.js.map} +1 -1
- package/dist/web/public/assets/{use-observability-CiO9A5Z9.js → use-observability-Beido9rh.js} +2 -2
- package/dist/web/public/assets/{use-observability-CiO9A5Z9.js.map → use-observability-Beido9rh.js.map} +1 -1
- package/dist/web/public/assets/{use-settings-fG28ShvX.js → use-settings-J28YEhhv.js} +2 -2
- package/dist/web/public/assets/{use-settings-fG28ShvX.js.map → use-settings-J28YEhhv.js.map} +1 -1
- package/dist/web/public/assets/use-workspace-BoRhOeiK.js +2 -0
- package/dist/web/public/assets/{use-workspace-CE3JTeap.js.map → use-workspace-BoRhOeiK.js.map} +1 -1
- package/dist/web/public/assets/useQuery-dWspFqPU.js +2 -0
- package/dist/web/public/assets/{useQuery-BtY7wSLM.js.map → useQuery-dWspFqPU.js.map} +1 -1
- package/dist/web/public/assets/{vector-CakzHMP0.js → vector-DX4RPkXe.js} +2 -2
- package/dist/web/public/assets/{vector-CakzHMP0.js.map → vector-DX4RPkXe.js.map} +1 -1
- package/dist/web/public/assets/{viewer-DWOOXMMI.js → viewer-CRv__j_2.js} +4 -4
- package/dist/web/public/assets/{viewer-DWOOXMMI.js.map → viewer-CRv__j_2.js.map} +1 -1
- package/dist/web/public/assets/{workspace-BnlWyXR1.js → workspace-DU5F-0GM.js} +3 -3
- package/dist/web/public/assets/{workspace-BnlWyXR1.js.map → workspace-DU5F-0GM.js.map} +1 -1
- package/dist/web/public/assets/{workspaces-DTXat9Xq.js → workspaces-DCEYab_X.js} +3 -3
- package/dist/web/public/assets/{workspaces-DTXat9Xq.js.map → workspaces-DCEYab_X.js.map} +1 -1
- package/dist/web/public/assets/{x-BVwIUHdL.js → x-CioZGQfq.js} +2 -2
- package/dist/web/public/assets/{x-BVwIUHdL.js.map → x-CioZGQfq.js.map} +1 -1
- package/dist/web/public/index.html +2 -2
- package/package.json +1 -1
- package/dist/web/public/assets/approvals-BR1f5zmP.js +0 -10
- package/dist/web/public/assets/approvals-BR1f5zmP.js.map +0 -1
- package/dist/web/public/assets/confirm-dialog-DgO--07o.js +0 -2
- package/dist/web/public/assets/index-BS4QrJNL.css +0 -1
- package/dist/web/public/assets/index-DVf2XlVZ.js +0 -166
- package/dist/web/public/assets/index-DVf2XlVZ.js.map +0 -1
- package/dist/web/public/assets/pagination-CyoXKAm9.js +0 -17
- package/dist/web/public/assets/policy-CSl5ENVs.js +0 -2
- package/dist/web/public/assets/table-Dg3N5NYh.js +0 -2
- package/dist/web/public/assets/use-llm-admin-D8Go_PKM.js +0 -2
- package/dist/web/public/assets/use-memory-BDuQTDX0.js +0 -2
- package/dist/web/public/assets/use-workspace-CE3JTeap.js +0 -2
- package/dist/web/public/assets/useQuery-BtY7wSLM.js +0 -2
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
2
|
-
//# sourceMappingURL=layout-
|
|
1
|
+
import{ae as n,V as e,T as r,N as u,t as a,O as i}from"./index-7yc9y9We.js";import"./react-C9F3QeMB.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}];function l(){const{t:s}=n("tasks");return e.jsxs("div",{className:"flex min-h-dvh flex-col bg-bg",children:[e.jsx(r,{}),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(u,{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-DuYDIza7.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout-
|
|
1
|
+
{"version":3,"file":"layout-DuYDIza7.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]\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":"wGAwBA,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,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{
|
|
2
|
-
//# sourceMappingURL=layout-
|
|
1
|
+
import{ae as x,V as e,S as d,l as u,m as p,j as h,k as i,ad as f,T as b,N as j,t as m,O as g}from"./index-7yc9y9We.js";import{f as y}from"./use-memory-Bf-AR2xS.js";import"./react-C9F3QeMB.js";import"./useQuery-dWspFqPU.js";function _({value:n,onChange:c,className:l}){const{t:r}=x("memory"),{data:o,isLoading:s}=y(),a=o?.users??[];return e.jsxs(d,{value:n||"__placeholder__",onValueChange:t=>c(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 T(){const{t:n}=x("memory"),[c,l]=f(),r=c.get("user")??"";function o(s){const a=new URLSearchParams(c);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:n("userPicker.label")}),e.jsx(_,{value:r,onChange:o})]})}),e.jsx("nav",{className:m("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":n("pageTitle"),children:v.filter(s=>s.mounted).map(s=>e.jsx(j,{to:s.to,className:({isActive:a})=>m("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:n(s.i18nKey)},s.to))}),e.jsx("main",{className:"flex-1 px-3 sm:px-4 py-4 pb-safe",children:e.jsx(g,{})})]})}export{T as default};
|
|
2
|
+
//# sourceMappingURL=layout-Oy_rbq06.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout-
|
|
1
|
+
{"version":3,"file":"layout-Oy_rbq06.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,7 +1,7 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{z as I,ae as k,V as e,c as y,B as T,L as f,S as L,l as B,m as H,j as E,k as R,I as N,a4 as m}from"./index-7yc9y9We.js";import{e as b}from"./react-C9F3QeMB.js";import{T as _,d as $,e as U,c as j,a as z,b as g}from"./table-BIc6RbM1.js";import{a as q,d as F,b as M,c as O,u as V}from"./use-llm-admin-DO9nbZeO.js";import{L as K}from"./loader-circle-CwM-6o9f.js";import{R as D}from"./refresh-ccw-l9Z6wukO.js";import{T as W}from"./trash-2-UPbZm-9k.js";import{P as Z}from"./plus-FlZ1UWzO.js";import"./useQuery-dWspFqPU.js";/**
|
|
2
2
|
* @license lucide-react v0.469.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/const Q=I("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"}]]),Y=["cheap","evaluator","native-chat"],P="__unbind__",w=["deepseek","moonshot","zhipu","openai","anthropic","custom"],v=[{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/v1",modelHint:"claude-3-5-sonnet-20241022"},{provider:"openai-compat",baseUrl:"",modelHint:""}];function ce(){const{t:a}=k(["settings","common"]),s=q();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:a("llm.title")}),e.jsxs(y,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>void s.refetch(),disabled:s.isFetching,"aria-label":a("actions.refresh",{ns:"common"}),children:[s.isFetching?e.jsx(K,{className:"h-4 w-4 animate-spin"}):e.jsx(D,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:a("llm.refresh")})]})]}),e.jsx("p",{className:"text-sm text-text-dim",children:a("llm.subtitle")}),s.isLoading?e.jsx("div",{className:"h-64 rounded-md bg-surface-2 animate-pulse"}):e.jsxs(e.Fragment,{children:[e.jsx(G,{data:s.data}),e.jsx(J,{data:s.data}),e.jsx(X,{})]})]})}function G({data:a}){const{t:s}=k(["settings","common"]),x=F(),p=M(),[i,h]=b.useState({});async function r(t){if(confirm(s("llm.removeConfirm",{name:t})))try{const l=await x.mutateAsync(t);m.success(s("llm.removedToast",{count:l.removedRoles}))}catch(l){m.error(l?.message??String(l))}}async function o(t){h(l=>({...l,[t]:s("llm.pinging")}));try{const l=await p.mutateAsync(t),u=l.ok?`✓ ${l.durationMs}ms · tokens ${l.tokensIn}→${l.tokensOut}`:`✗ ${l.error}`;h(S=>({...S,[t]:u}))}catch(l){h(u=>({...u,[t]:`✗ ${l?.message??String(l)}`}))}}const d=a?.backends??[];return d.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:d.length})})}),e.jsxs(_,{children:[e.jsx($,{children:e.jsxs(
|
|
7
|
-
//# sourceMappingURL=llm-
|
|
6
|
+
*/const Q=I("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"}]]),Y=["cheap","evaluator","native-chat"],P="__unbind__",w=["deepseek","moonshot","zhipu","openai","anthropic","custom"],v=[{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/v1",modelHint:"claude-3-5-sonnet-20241022"},{provider:"openai-compat",baseUrl:"",modelHint:""}];function ce(){const{t:a}=k(["settings","common"]),s=q();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:a("llm.title")}),e.jsxs(y,{variant:"ghost",size:"sm",className:"ml-auto",onClick:()=>void s.refetch(),disabled:s.isFetching,"aria-label":a("actions.refresh",{ns:"common"}),children:[s.isFetching?e.jsx(K,{className:"h-4 w-4 animate-spin"}):e.jsx(D,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:a("llm.refresh")})]})]}),e.jsx("p",{className:"text-sm text-text-dim",children:a("llm.subtitle")}),s.isLoading?e.jsx("div",{className:"h-64 rounded-md bg-surface-2 animate-pulse"}):e.jsxs(e.Fragment,{children:[e.jsx(G,{data:s.data}),e.jsx(J,{data:s.data}),e.jsx(X,{})]})]})}function G({data:a}){const{t:s}=k(["settings","common"]),x=F(),p=M(),[i,h]=b.useState({});async function r(t){if(confirm(s("llm.removeConfirm",{name:t})))try{const l=await x.mutateAsync(t);m.success(s("llm.removedToast",{count:l.removedRoles}))}catch(l){m.error(l?.message??String(l))}}async function o(t){h(l=>({...l,[t]:s("llm.pinging")}));try{const l=await p.mutateAsync(t),u=l.ok?`✓ ${l.durationMs}ms · tokens ${l.tokensIn}→${l.tokensOut}`:`✗ ${l.error}`;h(S=>({...S,[t]:u}))}catch(l){h(u=>({...u,[t]:`✗ ${l?.message??String(l)}`}))}}const d=a?.backends??[];return d.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:d.length})})}),e.jsxs(_,{children:[e.jsx($,{children:e.jsxs(U,{children:[e.jsx(j,{children:s("llm.col.name")}),e.jsx(j,{children:s("llm.col.provider")}),e.jsx(j,{children:s("llm.col.model")}),e.jsx(j,{children:s("llm.col.baseUrl")}),e.jsx(j,{children:s("llm.col.apiKey")}),e.jsx(j,{children:s("llm.col.actions")})]})}),e.jsx(z,{children:d.map(t=>{const l=t.secret.source==="none"?e.jsx(T,{variant:"outline",children:s("llm.secretMissing")}):e.jsx(T,{variant:"success",children:t.secret.source});return e.jsxs(U,{children:[e.jsx(g,{className:"font-mono text-xs",children:t.name}),e.jsx(g,{children:t.provider}),e.jsx(g,{className:"font-mono text-xs",children:t.model}),e.jsx(g,{className:"break-all font-mono text-[11px] text-text-dim",children:t.baseUrl??"—"}),e.jsx(g,{children:l}),e.jsxs(g,{className:"flex flex-col gap-1 sm:flex-row sm:items-center",children:[e.jsxs(y,{variant:"ghost",size:"sm",onClick:()=>void o(t.name),disabled:p.isPending||t.secret.source==="none",title:t.secret.source==="none"?s("llm.setKeyFirst"):s("llm.pingHint"),children:[e.jsx(Q,{className:"h-4 w-4"}),e.jsx("span",{children:s("llm.ping")})]}),e.jsxs(y,{variant:"ghost",size:"sm",onClick:()=>void r(t.name),disabled:x.isPending,className:"text-danger hover:text-danger",children:[e.jsx(W,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:s("llm.remove")})]}),i[t.name]&&e.jsx("span",{className:"ml-2 text-[11px] text-text-dim",children:i[t.name]})]})]},t.name)})})]})]})}function J({data:a}){const{t:s}=k(["settings","common"]),x=O(),p=(a?.backends??[]).map(r=>r.name),i=a?.roles??{};async function h(r,o){const d={[r]:o===P?null:o};try{await x.mutateAsync(d),m.success(s("llm.roleUpdated",{role:r}))}catch(t){m.error(t?.message??String(t))}}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:s("llm.rolesTitle")})}),e.jsx("div",{className:"grid grid-cols-1 gap-3 p-4 sm:grid-cols-3",children:Y.map(r=>e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx(f,{className:"text-xs font-medium",children:r}),e.jsxs(L,{value:i[r]??P,onValueChange:o=>void h(r,o),disabled:p.length===0||x.isPending,children:[e.jsx(B,{className:"font-mono text-xs",children:e.jsx(H,{placeholder:s("llm.unset")})}),e.jsxs(E,{children:[e.jsx(R,{value:P,children:s("llm.unbound")}),p.map(o=>e.jsx(R,{value:o,children:o},o))]})]}),e.jsx("p",{className:"text-[11px] text-text-dim",children:s(`llm.roleHint.${r}`)})]},r))})]})}function X(){const{t:a}=k(["settings","common"]),s=V(),[x,p]=b.useState(0),[i,h]=b.useState(""),[r,o]=b.useState(v[0]?.baseUrl??""),[d,t]=b.useState(v[0]?.modelHint??""),[l,u]=b.useState("");function S(n){p(n);const c=v[n];c&&(o(c.baseUrl),t(c.modelHint))}async function A(n){n.preventDefault();const c=v[x];if(!c){m.error(a("llm.invalidPreset"));return}if(!i.trim()){m.error(a("llm.nameRequired"));return}if(!r.trim()){m.error(a("llm.baseUrlRequired"));return}if(!d.trim()){m.error(a("llm.modelRequired"));return}try{await s.mutateAsync({name:i.trim(),provider:c.provider,baseUrl:r.trim(),model:d.trim(),...l.trim()?{apiKey:l.trim()}:{}}),m.success(l.trim()?a("llm.addedWithKey",{name:i.trim()}):a("llm.addedNoKey",{name:i.trim()})),h(""),u("")}catch(C){m.error(C?.message??String(C))}}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:a("llm.addTitle")})}),e.jsxs("form",{onSubmit:n=>void A(n),className:"grid grid-cols-1 gap-3 p-4 sm:grid-cols-2",children:[e.jsxs("div",{children:[e.jsx(f,{className:"text-xs font-medium",children:a("llm.preset")}),e.jsxs(L,{value:String(x),onValueChange:n=>S(Number(n)),children:[e.jsx(B,{children:e.jsx(H,{})}),e.jsx(E,{children:v.map((n,c)=>e.jsx(R,{value:String(c),children:a(`llm.presets.${w[c]}`)},w[c]))})]})]}),e.jsxs("div",{children:[e.jsx(f,{className:"text-xs font-medium",children:a("llm.name")}),e.jsx(N,{value:i,onChange:n=>h(n.target.value),placeholder:a("llm.namePlaceholder"),className:"font-mono text-xs"})]}),e.jsxs("div",{className:"sm:col-span-2",children:[e.jsx(f,{className:"text-xs font-medium",children:a("llm.baseUrl")}),e.jsx(N,{value:r,onChange:n=>o(n.target.value),placeholder:a("llm.baseUrlPlaceholder"),className:"font-mono text-xs"})]}),e.jsxs("div",{children:[e.jsx(f,{className:"text-xs font-medium",children:a("llm.model")}),e.jsx(N,{value:d,onChange:n=>t(n.target.value),placeholder:a("llm.modelPlaceholder"),className:"font-mono text-xs"})]}),e.jsxs("div",{children:[e.jsx(f,{className:"text-xs font-medium",children:a("llm.apiKeyOptional")}),e.jsx(N,{type:"password",value:l,onChange:n=>u(n.target.value),placeholder:a("llm.apiKeyPlaceholder"),className:"font-mono text-xs",autoComplete:"off"})]}),e.jsx("div",{className:"sm:col-span-2 flex",children:e.jsxs(y,{type:"submit",disabled:s.isPending,className:"ml-auto",children:[s.isPending?e.jsx(K,{className:"h-4 w-4 animate-spin"}):e.jsx(Z,{className:"h-4 w-4"}),a("llm.addBackend")]})})]})]})}export{ce as default};
|
|
7
|
+
//# sourceMappingURL=llm-Bs-G20DR.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-C5Uob7Ci.js","sources":["../../node_modules/lucide-react/dist/esm/icons/zap.js","../../src/routes/settings/llm.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Zap = createLucideIcon(\"Zap\", [\n [\n \"path\",\n {\n 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\",\n key: \"1xq2db\"\n }\n ]\n]);\n\nexport { Zap as default };\n//# sourceMappingURL=zap.js.map\n","/**\n * /settings/llm — native LLM backends + role bindings (Stage 6).\n *\n * Front-end for the `/api/llm/*` REST surface that landed in Stage 4.\n * Operators add an OpenAI-compatible or Anthropic backend, paste an\n * API key, bind it to a role (cheap / evaluator / native-chat), and\n * ping-test the connection — all without hand-editing\n * ~/.agim/config.json.\n *\n * Intentionally minimal styling — focused on doing the job; matches\n * the existing settings pages' shadcn look without bespoke chrome.\n */\n\nimport { useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { CheckCircle2, Loader2, Plus, RefreshCcw, Trash2, Zap } from 'lucide-react'\n\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport {\n Select, SelectContent, SelectItem, SelectTrigger, SelectValue,\n} from '@/components/ui/select'\nimport {\n Table, TableBody, TableCell, TableHead, TableHeader, TableRow,\n} from '@/components/ui/table'\nimport {\n useLlmList, useLlmAddBackend, useLlmRemoveBackend, useLlmPutRoles, useLlmPing,\n} from '@/hooks/use-llm-admin'\n\nconst KNOWN_ROLES = ['cheap', 'evaluator', 'native-chat'] as const\nconst UNBIND_SENTINEL = '__unbind__'\n\ninterface ProviderPreset {\n provider: 'openai-compat' | 'anthropic'\n baseUrl: string\n modelHint: string\n}\n\nconst PRESET_KEYS = ['deepseek', 'moonshot', 'zhipu', 'openai', 'anthropic', 'custom'] as const\n\nconst PRESETS: ProviderPreset[] = [\n { provider: 'openai-compat',\n baseUrl: 'https://api.deepseek.com/v1', modelHint: 'deepseek-chat' },\n { provider: 'openai-compat',\n baseUrl: 'https://api.moonshot.cn/v1', modelHint: 'moonshot-v1-8k' },\n { provider: 'openai-compat',\n baseUrl: 'https://open.bigmodel.cn/api/paas/v4', modelHint: 'glm-4-air' },\n { provider: 'openai-compat',\n baseUrl: 'https://api.openai.com/v1', modelHint: 'gpt-4o-mini' },\n { provider: 'anthropic',\n baseUrl: 'https://api.anthropic.com/v1', modelHint: 'claude-3-5-sonnet-20241022' },\n { provider: 'openai-compat',\n baseUrl: '', modelHint: '' },\n]\n\nexport default function SettingsLlmRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const listQuery = useLlmList()\n return (\n <div className=\"mx-auto flex max-w-5xl flex-col gap-6\">\n <header className=\"flex items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('llm.title')}</h1>\n <Button\n variant=\"ghost\" size=\"sm\" className=\"ml-auto\"\n onClick={() => void listQuery.refetch()}\n disabled={listQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {listQuery.isFetching\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('llm.refresh')}</span>\n </Button>\n </header>\n <p className=\"text-sm text-text-dim\">{t('llm.subtitle')}</p>\n\n {listQuery.isLoading ? (\n <div className=\"h-64 rounded-md bg-surface-2 animate-pulse\" />\n ) : (\n <>\n <BackendsCard data={listQuery.data} />\n <RolesCard data={listQuery.data} />\n <AddBackendCard />\n </>\n )}\n </div>\n )\n}\n\n/* ─────────────── Backends list ─────────────── */\n\nfunction BackendsCard({ data }: { data: ReturnType<typeof useLlmList>['data'] }): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const removeBackend = useLlmRemoveBackend()\n const ping = useLlmPing()\n const [pingResults, setPingResults] = useState<Record<string, string>>({})\n\n async function onRemove(name: string): Promise<void> {\n if (!confirm(t('llm.removeConfirm', { name }))) return\n try {\n const r = await removeBackend.mutateAsync(name)\n toast.success(t('llm.removedToast', { count: r.removedRoles }))\n } catch (err) {\n toast.error(((err as Error)?.message ?? String(err)))\n }\n }\n\n async function onPing(name: string): Promise<void> {\n setPingResults((m) => ({ ...m, [name]: t('llm.pinging') }))\n try {\n const r = await ping.mutateAsync(name)\n const msg = r.ok\n ? `✓ ${r.durationMs}ms · tokens ${r.tokensIn}→${r.tokensOut}`\n : `✗ ${r.error}`\n setPingResults((m) => ({ ...m, [name]: msg }))\n } catch (err) {\n setPingResults((m) => ({ ...m, [name]: `✗ ${((err as Error)?.message ?? String(err))}` }))\n }\n }\n\n const rows = data?.backends ?? []\n if (rows.length === 0) {\n return (\n <section className=\"rounded-md border border-border bg-surface p-6 text-center text-sm text-text-dim\">\n {t('llm.backendsEmpty')}\n </section>\n )\n }\n\n return (\n <section className=\"rounded-md border border-border bg-surface\">\n <header className=\"border-b border-border px-4 py-3\">\n <h2 className=\"text-sm font-semibold\">{t('llm.backendsTitle', { count: rows.length })}</h2>\n </header>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{t('llm.col.name')}</TableHead>\n <TableHead>{t('llm.col.provider')}</TableHead>\n <TableHead>{t('llm.col.model')}</TableHead>\n <TableHead>{t('llm.col.baseUrl')}</TableHead>\n <TableHead>{t('llm.col.apiKey')}</TableHead>\n <TableHead>{t('llm.col.actions')}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {rows.map((b) => {\n const keyBadge = b.secret.source === 'none'\n ? <Badge variant=\"outline\">{t('llm.secretMissing')}</Badge>\n : <Badge variant=\"success\">{b.secret.source}</Badge>\n return (\n <TableRow key={b.name}>\n <TableCell className=\"font-mono text-xs\">{b.name}</TableCell>\n <TableCell>{b.provider}</TableCell>\n <TableCell className=\"font-mono text-xs\">{b.model}</TableCell>\n <TableCell className=\"break-all font-mono text-[11px] text-text-dim\">{b.baseUrl ?? '—'}</TableCell>\n <TableCell>{keyBadge}</TableCell>\n <TableCell className=\"flex flex-col gap-1 sm:flex-row sm:items-center\">\n <Button\n variant=\"ghost\" size=\"sm\"\n onClick={() => void onPing(b.name)}\n disabled={ping.isPending || b.secret.source === 'none'}\n title={b.secret.source === 'none' ? t('llm.setKeyFirst') : t('llm.pingHint')}\n >\n <Zap className=\"h-4 w-4\" />\n <span>{t('llm.ping')}</span>\n </Button>\n <Button\n variant=\"ghost\" size=\"sm\"\n onClick={() => void onRemove(b.name)}\n disabled={removeBackend.isPending}\n className=\"text-danger hover:text-danger\"\n >\n <Trash2 className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">{t('llm.remove')}</span>\n </Button>\n {pingResults[b.name] && (\n <span className=\"ml-2 text-[11px] text-text-dim\">{pingResults[b.name]}</span>\n )}\n </TableCell>\n </TableRow>\n )\n })}\n </TableBody>\n </Table>\n </section>\n )\n}\n\n/* ─────────────── Role bindings ─────────────── */\n\nfunction RolesCard({ data }: { data: ReturnType<typeof useLlmList>['data'] }): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const putRoles = useLlmPutRoles()\n const backendNames = (data?.backends ?? []).map((b) => b.name)\n const current = data?.roles ?? {}\n\n async function onChangeRole(role: string, value: string): Promise<void> {\n const next: Record<string, string | null> = {\n [role]: value === UNBIND_SENTINEL ? null : value,\n }\n try {\n await putRoles.mutateAsync(next)\n toast.success(t('llm.roleUpdated', { role }))\n } catch (err) {\n toast.error(((err as Error)?.message ?? String(err)))\n }\n }\n\n return (\n <section className=\"rounded-md border border-border bg-surface\">\n <header className=\"border-b border-border px-4 py-3\">\n <h2 className=\"text-sm font-semibold\">{t('llm.rolesTitle')}</h2>\n </header>\n <div className=\"grid grid-cols-1 gap-3 p-4 sm:grid-cols-3\">\n {KNOWN_ROLES.map((role) => (\n <div key={role} className=\"flex flex-col gap-1\">\n <Label className=\"text-xs font-medium\">{role}</Label>\n <Select\n value={current[role] ?? UNBIND_SENTINEL}\n onValueChange={(v) => void onChangeRole(role, v)}\n disabled={backendNames.length === 0 || putRoles.isPending}\n >\n <SelectTrigger className=\"font-mono text-xs\">\n <SelectValue placeholder={t('llm.unset')} />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={UNBIND_SENTINEL}>{t('llm.unbound')}</SelectItem>\n {backendNames.map((n) => (\n <SelectItem key={n} value={n}>{n}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n <p className=\"text-[11px] text-text-dim\">\n {t(`llm.roleHint.${role}`)}\n </p>\n </div>\n ))}\n </div>\n </section>\n )\n}\n\n/* ─────────────── Add backend form ─────────────── */\n\nfunction AddBackendCard(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const addBackend = useLlmAddBackend()\n const [presetIdx, setPresetIdx] = useState(0)\n const [name, setName] = useState('')\n const [baseUrl, setBaseUrl] = useState(PRESETS[0]?.baseUrl ?? '')\n const [model, setModel] = useState(PRESETS[0]?.modelHint ?? '')\n const [apiKey, setApiKey] = useState('')\n\n function onPickPreset(idx: number): void {\n setPresetIdx(idx)\n const p = PRESETS[idx]\n if (!p) return\n setBaseUrl(p.baseUrl)\n setModel(p.modelHint)\n }\n\n async function onSubmit(e: React.FormEvent): Promise<void> {\n e.preventDefault()\n const p = PRESETS[presetIdx]\n if (!p) { toast.error(t('llm.invalidPreset')); return }\n if (!name.trim()) { toast.error(t('llm.nameRequired')); return }\n if (!baseUrl.trim()) { toast.error(t('llm.baseUrlRequired')); return }\n if (!model.trim()) { toast.error(t('llm.modelRequired')); return }\n try {\n await addBackend.mutateAsync({\n name: name.trim(),\n provider: p.provider,\n baseUrl: baseUrl.trim(),\n model: model.trim(),\n ...(apiKey.trim() ? { apiKey: apiKey.trim() } : {}),\n })\n toast.success(\n apiKey.trim()\n ? t('llm.addedWithKey', { name: name.trim() })\n : t('llm.addedNoKey', { name: name.trim() }),\n )\n setName(''); setApiKey('')\n } catch (err) {\n toast.error(((err as Error)?.message ?? String(err)))\n }\n }\n\n return (\n <section className=\"rounded-md border border-border bg-surface\">\n <header className=\"border-b border-border px-4 py-3\">\n <h2 className=\"text-sm font-semibold\">{t('llm.addTitle')}</h2>\n </header>\n <form onSubmit={(e) => void onSubmit(e)} className=\"grid grid-cols-1 gap-3 p-4 sm:grid-cols-2\">\n <div>\n <Label className=\"text-xs font-medium\">{t('llm.preset')}</Label>\n <Select value={String(presetIdx)} onValueChange={(v) => onPickPreset(Number(v))}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {PRESETS.map((_p, i) => (\n <SelectItem key={PRESET_KEYS[i]} value={String(i)}>\n {t(`llm.presets.${PRESET_KEYS[i]}`)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div>\n <Label className=\"text-xs font-medium\">{t('llm.name')}</Label>\n <Input\n value={name} onChange={(e) => setName(e.target.value)}\n placeholder={t('llm.namePlaceholder')}\n className=\"font-mono text-xs\"\n />\n </div>\n <div className=\"sm:col-span-2\">\n <Label className=\"text-xs font-medium\">{t('llm.baseUrl')}</Label>\n <Input\n value={baseUrl} onChange={(e) => setBaseUrl(e.target.value)}\n placeholder={t('llm.baseUrlPlaceholder')}\n className=\"font-mono text-xs\"\n />\n </div>\n <div>\n <Label className=\"text-xs font-medium\">{t('llm.model')}</Label>\n <Input\n value={model} onChange={(e) => setModel(e.target.value)}\n placeholder={t('llm.modelPlaceholder')}\n className=\"font-mono text-xs\"\n />\n </div>\n <div>\n <Label className=\"text-xs font-medium\">{t('llm.apiKeyOptional')}</Label>\n <Input\n type=\"password\"\n value={apiKey} onChange={(e) => setApiKey(e.target.value)}\n placeholder={t('llm.apiKeyPlaceholder')}\n className=\"font-mono text-xs\"\n autoComplete=\"off\"\n />\n </div>\n <div className=\"sm:col-span-2 flex\">\n <Button\n type=\"submit\"\n disabled={addBackend.isPending}\n className=\"ml-auto\"\n >\n {addBackend.isPending ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <Plus className=\"h-4 w-4\" />}\n {t('llm.addBackend')}\n </Button>\n </div>\n </form>\n </section>\n )\n}\n\n/* helper — toast tag passthrough */\nfunction _unused(): typeof CheckCircle2 { return CheckCircle2 }\nvoid _unused\n"],"names":["Zap","createLucideIcon","KNOWN_ROLES","UNBIND_SENTINEL","PRESET_KEYS","PRESETS","SettingsLlmRoute","t","useTranslation","listQuery","useLlmList","jsxs","jsx","Button","Loader2","RefreshCcw","Fragment","BackendsCard","RolesCard","AddBackendCard","data","removeBackend","useLlmRemoveBackend","ping","useLlmPing","pingResults","setPingResults","useState","onRemove","name","r","toast","err","onPing","m","msg","rows","Table","TableHeader","TableRow","TableHead","TableBody","b","keyBadge","Badge","TableCell","Trash2","putRoles","useLlmPutRoles","backendNames","current","onChangeRole","role","value","next","Label","Select","v","SelectTrigger","SelectValue","SelectContent","SelectItem","n","addBackend","useLlmAddBackend","presetIdx","setPresetIdx","setName","baseUrl","setBaseUrl","model","setModel","apiKey","setApiKey","onPickPreset","idx","p","onSubmit","e","_p","i","Input","Plus"],"mappings":"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","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"llm-Bs-G20DR.js","sources":["../../node_modules/lucide-react/dist/esm/icons/zap.js","../../src/routes/settings/llm.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Zap = createLucideIcon(\"Zap\", [\n [\n \"path\",\n {\n 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\",\n key: \"1xq2db\"\n }\n ]\n]);\n\nexport { Zap as default };\n//# sourceMappingURL=zap.js.map\n","/**\n * /settings/llm — native LLM backends + role bindings (Stage 6).\n *\n * Front-end for the `/api/llm/*` REST surface that landed in Stage 4.\n * Operators add an OpenAI-compatible or Anthropic backend, paste an\n * API key, bind it to a role (cheap / evaluator / native-chat), and\n * ping-test the connection — all without hand-editing\n * ~/.agim/config.json.\n *\n * Intentionally minimal styling — focused on doing the job; matches\n * the existing settings pages' shadcn look without bespoke chrome.\n */\n\nimport { useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { CheckCircle2, Loader2, Plus, RefreshCcw, Trash2, Zap } from 'lucide-react'\n\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport {\n Select, SelectContent, SelectItem, SelectTrigger, SelectValue,\n} from '@/components/ui/select'\nimport {\n Table, TableBody, TableCell, TableHead, TableHeader, TableRow,\n} from '@/components/ui/table'\nimport {\n useLlmList, useLlmAddBackend, useLlmRemoveBackend, useLlmPutRoles, useLlmPing,\n} from '@/hooks/use-llm-admin'\n\nconst KNOWN_ROLES = ['cheap', 'evaluator', 'native-chat'] as const\nconst UNBIND_SENTINEL = '__unbind__'\n\ninterface ProviderPreset {\n provider: 'openai-compat' | 'anthropic'\n baseUrl: string\n modelHint: string\n}\n\nconst PRESET_KEYS = ['deepseek', 'moonshot', 'zhipu', 'openai', 'anthropic', 'custom'] as const\n\nconst PRESETS: ProviderPreset[] = [\n { provider: 'openai-compat',\n baseUrl: 'https://api.deepseek.com/v1', modelHint: 'deepseek-chat' },\n { provider: 'openai-compat',\n baseUrl: 'https://api.moonshot.cn/v1', modelHint: 'moonshot-v1-8k' },\n { provider: 'openai-compat',\n baseUrl: 'https://open.bigmodel.cn/api/paas/v4', modelHint: 'glm-4-air' },\n { provider: 'openai-compat',\n baseUrl: 'https://api.openai.com/v1', modelHint: 'gpt-4o-mini' },\n { provider: 'anthropic',\n baseUrl: 'https://api.anthropic.com/v1', modelHint: 'claude-3-5-sonnet-20241022' },\n { provider: 'openai-compat',\n baseUrl: '', modelHint: '' },\n]\n\nexport default function SettingsLlmRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const listQuery = useLlmList()\n return (\n <div className=\"mx-auto flex max-w-5xl flex-col gap-6\">\n <header className=\"flex items-center gap-3\">\n <h1 className=\"text-xl font-semibold\">{t('llm.title')}</h1>\n <Button\n variant=\"ghost\" size=\"sm\" className=\"ml-auto\"\n onClick={() => void listQuery.refetch()}\n disabled={listQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {listQuery.isFetching\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('llm.refresh')}</span>\n </Button>\n </header>\n <p className=\"text-sm text-text-dim\">{t('llm.subtitle')}</p>\n\n {listQuery.isLoading ? (\n <div className=\"h-64 rounded-md bg-surface-2 animate-pulse\" />\n ) : (\n <>\n <BackendsCard data={listQuery.data} />\n <RolesCard data={listQuery.data} />\n <AddBackendCard />\n </>\n )}\n </div>\n )\n}\n\n/* ─────────────── Backends list ─────────────── */\n\nfunction BackendsCard({ data }: { data: ReturnType<typeof useLlmList>['data'] }): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const removeBackend = useLlmRemoveBackend()\n const ping = useLlmPing()\n const [pingResults, setPingResults] = useState<Record<string, string>>({})\n\n async function onRemove(name: string): Promise<void> {\n if (!confirm(t('llm.removeConfirm', { name }))) return\n try {\n const r = await removeBackend.mutateAsync(name)\n toast.success(t('llm.removedToast', { count: r.removedRoles }))\n } catch (err) {\n toast.error(((err as Error)?.message ?? String(err)))\n }\n }\n\n async function onPing(name: string): Promise<void> {\n setPingResults((m) => ({ ...m, [name]: t('llm.pinging') }))\n try {\n const r = await ping.mutateAsync(name)\n const msg = r.ok\n ? `✓ ${r.durationMs}ms · tokens ${r.tokensIn}→${r.tokensOut}`\n : `✗ ${r.error}`\n setPingResults((m) => ({ ...m, [name]: msg }))\n } catch (err) {\n setPingResults((m) => ({ ...m, [name]: `✗ ${((err as Error)?.message ?? String(err))}` }))\n }\n }\n\n const rows = data?.backends ?? []\n if (rows.length === 0) {\n return (\n <section className=\"rounded-md border border-border bg-surface p-6 text-center text-sm text-text-dim\">\n {t('llm.backendsEmpty')}\n </section>\n )\n }\n\n return (\n <section className=\"rounded-md border border-border bg-surface\">\n <header className=\"border-b border-border px-4 py-3\">\n <h2 className=\"text-sm font-semibold\">{t('llm.backendsTitle', { count: rows.length })}</h2>\n </header>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{t('llm.col.name')}</TableHead>\n <TableHead>{t('llm.col.provider')}</TableHead>\n <TableHead>{t('llm.col.model')}</TableHead>\n <TableHead>{t('llm.col.baseUrl')}</TableHead>\n <TableHead>{t('llm.col.apiKey')}</TableHead>\n <TableHead>{t('llm.col.actions')}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {rows.map((b) => {\n const keyBadge = b.secret.source === 'none'\n ? <Badge variant=\"outline\">{t('llm.secretMissing')}</Badge>\n : <Badge variant=\"success\">{b.secret.source}</Badge>\n return (\n <TableRow key={b.name}>\n <TableCell className=\"font-mono text-xs\">{b.name}</TableCell>\n <TableCell>{b.provider}</TableCell>\n <TableCell className=\"font-mono text-xs\">{b.model}</TableCell>\n <TableCell className=\"break-all font-mono text-[11px] text-text-dim\">{b.baseUrl ?? '—'}</TableCell>\n <TableCell>{keyBadge}</TableCell>\n <TableCell className=\"flex flex-col gap-1 sm:flex-row sm:items-center\">\n <Button\n variant=\"ghost\" size=\"sm\"\n onClick={() => void onPing(b.name)}\n disabled={ping.isPending || b.secret.source === 'none'}\n title={b.secret.source === 'none' ? t('llm.setKeyFirst') : t('llm.pingHint')}\n >\n <Zap className=\"h-4 w-4\" />\n <span>{t('llm.ping')}</span>\n </Button>\n <Button\n variant=\"ghost\" size=\"sm\"\n onClick={() => void onRemove(b.name)}\n disabled={removeBackend.isPending}\n className=\"text-danger hover:text-danger\"\n >\n <Trash2 className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">{t('llm.remove')}</span>\n </Button>\n {pingResults[b.name] && (\n <span className=\"ml-2 text-[11px] text-text-dim\">{pingResults[b.name]}</span>\n )}\n </TableCell>\n </TableRow>\n )\n })}\n </TableBody>\n </Table>\n </section>\n )\n}\n\n/* ─────────────── Role bindings ─────────────── */\n\nfunction RolesCard({ data }: { data: ReturnType<typeof useLlmList>['data'] }): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const putRoles = useLlmPutRoles()\n const backendNames = (data?.backends ?? []).map((b) => b.name)\n const current = data?.roles ?? {}\n\n async function onChangeRole(role: string, value: string): Promise<void> {\n const next: Record<string, string | null> = {\n [role]: value === UNBIND_SENTINEL ? null : value,\n }\n try {\n await putRoles.mutateAsync(next)\n toast.success(t('llm.roleUpdated', { role }))\n } catch (err) {\n toast.error(((err as Error)?.message ?? String(err)))\n }\n }\n\n return (\n <section className=\"rounded-md border border-border bg-surface\">\n <header className=\"border-b border-border px-4 py-3\">\n <h2 className=\"text-sm font-semibold\">{t('llm.rolesTitle')}</h2>\n </header>\n <div className=\"grid grid-cols-1 gap-3 p-4 sm:grid-cols-3\">\n {KNOWN_ROLES.map((role) => (\n <div key={role} className=\"flex flex-col gap-1\">\n <Label className=\"text-xs font-medium\">{role}</Label>\n <Select\n value={current[role] ?? UNBIND_SENTINEL}\n onValueChange={(v) => void onChangeRole(role, v)}\n disabled={backendNames.length === 0 || putRoles.isPending}\n >\n <SelectTrigger className=\"font-mono text-xs\">\n <SelectValue placeholder={t('llm.unset')} />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={UNBIND_SENTINEL}>{t('llm.unbound')}</SelectItem>\n {backendNames.map((n) => (\n <SelectItem key={n} value={n}>{n}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n <p className=\"text-[11px] text-text-dim\">\n {t(`llm.roleHint.${role}`)}\n </p>\n </div>\n ))}\n </div>\n </section>\n )\n}\n\n/* ─────────────── Add backend form ─────────────── */\n\nfunction AddBackendCard(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const addBackend = useLlmAddBackend()\n const [presetIdx, setPresetIdx] = useState(0)\n const [name, setName] = useState('')\n const [baseUrl, setBaseUrl] = useState(PRESETS[0]?.baseUrl ?? '')\n const [model, setModel] = useState(PRESETS[0]?.modelHint ?? '')\n const [apiKey, setApiKey] = useState('')\n\n function onPickPreset(idx: number): void {\n setPresetIdx(idx)\n const p = PRESETS[idx]\n if (!p) return\n setBaseUrl(p.baseUrl)\n setModel(p.modelHint)\n }\n\n async function onSubmit(e: React.FormEvent): Promise<void> {\n e.preventDefault()\n const p = PRESETS[presetIdx]\n if (!p) { toast.error(t('llm.invalidPreset')); return }\n if (!name.trim()) { toast.error(t('llm.nameRequired')); return }\n if (!baseUrl.trim()) { toast.error(t('llm.baseUrlRequired')); return }\n if (!model.trim()) { toast.error(t('llm.modelRequired')); return }\n try {\n await addBackend.mutateAsync({\n name: name.trim(),\n provider: p.provider,\n baseUrl: baseUrl.trim(),\n model: model.trim(),\n ...(apiKey.trim() ? { apiKey: apiKey.trim() } : {}),\n })\n toast.success(\n apiKey.trim()\n ? t('llm.addedWithKey', { name: name.trim() })\n : t('llm.addedNoKey', { name: name.trim() }),\n )\n setName(''); setApiKey('')\n } catch (err) {\n toast.error(((err as Error)?.message ?? String(err)))\n }\n }\n\n return (\n <section className=\"rounded-md border border-border bg-surface\">\n <header className=\"border-b border-border px-4 py-3\">\n <h2 className=\"text-sm font-semibold\">{t('llm.addTitle')}</h2>\n </header>\n <form onSubmit={(e) => void onSubmit(e)} className=\"grid grid-cols-1 gap-3 p-4 sm:grid-cols-2\">\n <div>\n <Label className=\"text-xs font-medium\">{t('llm.preset')}</Label>\n <Select value={String(presetIdx)} onValueChange={(v) => onPickPreset(Number(v))}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n {PRESETS.map((_p, i) => (\n <SelectItem key={PRESET_KEYS[i]} value={String(i)}>\n {t(`llm.presets.${PRESET_KEYS[i]}`)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div>\n <Label className=\"text-xs font-medium\">{t('llm.name')}</Label>\n <Input\n value={name} onChange={(e) => setName(e.target.value)}\n placeholder={t('llm.namePlaceholder')}\n className=\"font-mono text-xs\"\n />\n </div>\n <div className=\"sm:col-span-2\">\n <Label className=\"text-xs font-medium\">{t('llm.baseUrl')}</Label>\n <Input\n value={baseUrl} onChange={(e) => setBaseUrl(e.target.value)}\n placeholder={t('llm.baseUrlPlaceholder')}\n className=\"font-mono text-xs\"\n />\n </div>\n <div>\n <Label className=\"text-xs font-medium\">{t('llm.model')}</Label>\n <Input\n value={model} onChange={(e) => setModel(e.target.value)}\n placeholder={t('llm.modelPlaceholder')}\n className=\"font-mono text-xs\"\n />\n </div>\n <div>\n <Label className=\"text-xs font-medium\">{t('llm.apiKeyOptional')}</Label>\n <Input\n type=\"password\"\n value={apiKey} onChange={(e) => setApiKey(e.target.value)}\n placeholder={t('llm.apiKeyPlaceholder')}\n className=\"font-mono text-xs\"\n autoComplete=\"off\"\n />\n </div>\n <div className=\"sm:col-span-2 flex\">\n <Button\n type=\"submit\"\n disabled={addBackend.isPending}\n className=\"ml-auto\"\n >\n {addBackend.isPending ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <Plus className=\"h-4 w-4\" />}\n {t('llm.addBackend')}\n </Button>\n </div>\n </form>\n </section>\n )\n}\n\n/* helper — toast tag passthrough */\nfunction _unused(): typeof CheckCircle2 { return CheckCircle2 }\nvoid _unused\n"],"names":["Zap","createLucideIcon","KNOWN_ROLES","UNBIND_SENTINEL","PRESET_KEYS","PRESETS","SettingsLlmRoute","t","useTranslation","listQuery","useLlmList","jsxs","jsx","Button","Loader2","RefreshCcw","Fragment","BackendsCard","RolesCard","AddBackendCard","data","removeBackend","useLlmRemoveBackend","ping","useLlmPing","pingResults","setPingResults","useState","onRemove","name","r","toast","err","onPing","m","msg","rows","Table","TableHeader","TableRow","TableHead","TableBody","b","keyBadge","Badge","TableCell","Trash2","putRoles","useLlmPutRoles","backendNames","current","onChangeRole","role","value","next","Label","Select","v","SelectTrigger","SelectValue","SelectContent","SelectItem","n","addBackend","useLlmAddBackend","presetIdx","setPresetIdx","setName","baseUrl","setBaseUrl","model","setModel","apiKey","setApiKey","onPickPreset","idx","p","onSubmit","e","_p","i","Input","Plus"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{z as e}from"./index-7yc9y9We.js";/**
|
|
2
2
|
* @license lucide-react v0.469.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/const r=e("LoaderCircle",[["path",{d:"M21 12a9 9 0 1 1-6.219-8.56",key:"13zald"}]]);export{r as L};
|
|
7
|
-
//# sourceMappingURL=loader-circle-
|
|
7
|
+
//# sourceMappingURL=loader-circle-CwM-6o9f.js.map
|
package/dist/web/public/assets/{loader-circle-DdWIiO8L.js.map → loader-circle-CwM-6o9f.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader-circle-
|
|
1
|
+
{"version":3,"file":"loader-circle-CwM-6o9f.js","sources":["../../node_modules/lucide-react/dist/esm/icons/loader-circle.js"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst LoaderCircle = createLucideIcon(\"LoaderCircle\", [\n [\"path\", { d: \"M21 12a9 9 0 1 1-6.219-8.56\", key: \"13zald\" }]\n]);\n\nexport { LoaderCircle as default };\n//# sourceMappingURL=loader-circle.js.map\n"],"names":["LoaderCircle","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAAeC,EAAiB,eAAgB,CACpD,CAAC,OAAQ,CAAE,EAAG,8BAA+B,IAAK,QAAQ,CAAE,CAC9D,CAAC","x_google_ignoreList":[0]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{z as c}from"./index-7yc9y9We.js";/**
|
|
2
2
|
* @license lucide-react v0.469.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/const r=c("MapPin",[["path",{d:"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0",key:"1r0f0z"}],["circle",{cx:"12",cy:"10",r:"3",key:"ilqhr7"}]]);export{r as M};
|
|
7
|
-
//# sourceMappingURL=map-pin-
|
|
7
|
+
//# sourceMappingURL=map-pin-MuWUOLcD.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map-pin-
|
|
1
|
+
{"version":3,"file":"map-pin-MuWUOLcD.js","sources":["../../node_modules/lucide-react/dist/esm/icons/map-pin.js"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst MapPin = createLucideIcon(\"MapPin\", [\n [\n \"path\",\n {\n d: \"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0\",\n key: \"1r0f0z\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"10\", r: \"3\", key: \"ilqhr7\" }]\n]);\n\nexport { MapPin as default };\n//# sourceMappingURL=map-pin.js.map\n"],"names":["MapPin","createLucideIcon"],"mappings":"wCAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASK,MAACA,EAASC,EAAiB,SAAU,CACxC,CACE,OACA,CACE,EAAG,uGACH,IAAK,QACX,CACA,EACE,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,IAAK,IAAK,QAAQ,CAAE,CAC1D,CAAC","x_google_ignoreList":[0]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{z as A,ae as L,V as e,c as k,B as C,L as x,I as v,S as M,l as z,m as q,j as B,k as R,a4 as o}from"./index-7yc9y9We.js";import{e as l}from"./react-C9F3QeMB.js";import{T as F,d as I,e as H,c as b,a as O,b as N}from"./table-BIc6RbM1.js";import{g as $,h as E,f as V,e as D}from"./use-llm-admin-DO9nbZeO.js";import{L as P}from"./loader-circle-CwM-6o9f.js";import{R as J}from"./refresh-ccw-l9Z6wukO.js";import{A as U}from"./activity-CegIax_4.js";import{T as Q}from"./trash-2-UPbZm-9k.js";import{P as W}from"./plus-FlZ1UWzO.js";import"./useQuery-dWspFqPU.js";/**
|
|
2
2
|
* @license lucide-react v0.469.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/const G=A("ServerCog",[["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}],["path",{d:"M4.5 10H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-.5",key:"tn8das"}],["path",{d:"M4.5 14H4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2h-.5",key:"1g2pve"}],["path",{d:"M6 6h.01",key:"1utrut"}],["path",{d:"M6 18h.01",key:"uhywen"}],["path",{d:"m15.7 13.4-.9-.3",key:"1jwmzr"}],["path",{d:"m9.2 10.9-.9-.3",key:"qapnim"}],["path",{d:"m10.6 15.7.3-.9",key:"quwk0k"}],["path",{d:"m13.6 15.7-.4-1",key:"cb9xp7"}],["path",{d:"m10.8 9.3-.4-1",key:"1uaiz5"}],["path",{d:"m8.3 13.6 1-.4",key:"s6srou"}],["path",{d:"m14.7 10.8 1-.4",key:"4d31cq"}],["path",{d:"m13.4 8.3-.3.9",key:"1bm987"}]]);function me(){const{t}=L(["settings","common"]),s=$();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(G,{className:"h-5 w-5 text-text-dim"}),e.jsx("h1",{className:"text-xl font-semibold",children:t("mcp.title")}),e.jsxs(k,{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(P,{className:"h-4 w-4 animate-spin"}):e.jsx(
|
|
7
|
-
//# sourceMappingURL=mcp-
|
|
6
|
+
*/const G=A("ServerCog",[["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}],["path",{d:"M4.5 10H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-.5",key:"tn8das"}],["path",{d:"M4.5 14H4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2h-.5",key:"1g2pve"}],["path",{d:"M6 6h.01",key:"1utrut"}],["path",{d:"M6 18h.01",key:"uhywen"}],["path",{d:"m15.7 13.4-.9-.3",key:"1jwmzr"}],["path",{d:"m9.2 10.9-.9-.3",key:"qapnim"}],["path",{d:"m10.6 15.7.3-.9",key:"quwk0k"}],["path",{d:"m13.6 15.7-.4-1",key:"cb9xp7"}],["path",{d:"m10.8 9.3-.4-1",key:"1uaiz5"}],["path",{d:"m8.3 13.6 1-.4",key:"s6srou"}],["path",{d:"m14.7 10.8 1-.4",key:"4d31cq"}],["path",{d:"m13.4 8.3-.3.9",key:"1bm987"}]]);function me(){const{t}=L(["settings","common"]),s=$();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(G,{className:"h-5 w-5 text-text-dim"}),e.jsx("h1",{className:"text-xl font-semibold",children:t("mcp.title")}),e.jsxs(k,{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(P,{className:"h-4 w-4 animate-spin"}):e.jsx(J,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:t("mcp.refresh")})]})]}),e.jsx("p",{className:"text-sm text-text-dim",children:t("mcp.subtitle")}),s.isLoading?e.jsx("div",{className:"h-48 rounded-md bg-surface-2 animate-pulse"}):e.jsxs(e.Fragment,{children:[e.jsx(K,{data:s.data}),e.jsx(Y,{})]})]})}function K({data:t}){const{t:s}=L(["settings","common"]),m=E(),p=V(),[i,u]=l.useState({});async function j(r){if(confirm(s("mcp.removeConfirm",{name:r})))try{await m.mutateAsync(r),o.success(s("mcp.removedToast",{name:r}))}catch(a){o.error(a?.message??String(a))}}async function y(r){u(a=>({...a,[r]:s("mcp.probing")}));try{const a=await p.mutateAsync(r),c=a.connected?`✓ ${a.toolCount===1?s("mcp.runtimeConnectedOne",{count:a.toolCount}):s("mcp.runtimeConnected",{count:a.toolCount})}`:`✗ ${a.lastError??s("mcp.runtimeDisconnected")}`;u(h=>({...h,[r]:c}))}catch(a){u(c=>({...c,[r]:`✗ ${a?.message??String(a)}`}))}}const d=t?.servers??[],S=t?.runtime?.servers??[];return d.length===0?e.jsx("section",{className:"rounded-md border border-border bg-surface p-6 text-center text-sm text-text-dim",children:s("mcp.serversEmpty")}):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("h2",{className:"text-sm font-semibold",children:s("mcp.serversTitle",{count:d.length})}),t?.runtime&&e.jsx(C,{variant:"info",children:s("mcp.totalTools",{count:t.runtime.totalTools})})]}),e.jsxs(F,{children:[e.jsx(I,{children:e.jsxs(H,{children:[e.jsx(b,{children:s("mcp.col.name")}),e.jsx(b,{children:s("mcp.col.transport")}),e.jsx(b,{children:s("mcp.col.target")}),e.jsx(b,{children:s("mcp.col.runtime")}),e.jsx(b,{children:s("mcp.col.actions")})]})}),e.jsx(O,{children:d.map(r=>{const a=S.find(n=>n.name===r.name),c=X(r,s),h=r.command?`${r.command} ${(r.args??[]).join(" ")}`.trim():r.url??"—",w=a?a.connected?e.jsx(C,{variant:"success",children:a.toolCount===1?s("mcp.runtimeConnectedOne",{count:a.toolCount}):s("mcp.runtimeConnected",{count:a.toolCount})}):e.jsx(C,{variant:"danger",children:s("mcp.runtimeDisconnected")}):e.jsx(C,{variant:"outline",children:s("mcp.runtimeUnknown")});return e.jsxs(H,{children:[e.jsx(N,{className:"font-mono text-xs",children:r.name}),e.jsx(N,{children:c}),e.jsx(N,{className:"break-all font-mono text-[11px] text-text-dim",children:h}),e.jsx(N,{children:w}),e.jsxs(N,{className:"flex flex-col gap-1 sm:flex-row sm:items-center",children:[e.jsxs(k,{variant:"ghost",size:"sm",onClick:()=>void y(r.name),disabled:p.isPending,children:[e.jsx(U,{className:"h-4 w-4"}),e.jsx("span",{children:s("mcp.health")})]}),e.jsxs(k,{variant:"ghost",size:"sm",onClick:()=>void j(r.name),disabled:m.isPending,className:"text-danger hover:text-danger",children:[e.jsx(Q,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:s("mcp.remove")})]}),i[r.name]&&e.jsx("span",{className:"ml-2 text-[11px] text-text-dim",children:i[r.name]})]})]},r.name)})})]})]})}function X(t,s){return t.command?s("mcp.transportStdio"):t.url?t.url.endsWith("/sse")?s("mcp.transportSse"):s("mcp.transportHttp"):"—"}function Y(){const{t}=L(["settings","common"]),s=D(),[m,p]=l.useState(""),[i,u]=l.useState("stdio"),[j,y]=l.useState(""),[d,S]=l.useState(""),[r,a]=l.useState(""),[c,h]=l.useState("");async function w(n){if(n.preventDefault(),!m.trim()){o.error(t("mcp.nameRequired"));return}let T;if(c.trim())try{T=JSON.parse(c)}catch{o.error(t("mcp.headersInvalid"));return}const g={name:m.trim()};if(i==="stdio"){if(!j.trim()){o.error(t("mcp.commandRequired"));return}g.command=j.trim();const f=d.split(/\s+/).filter(Boolean);f.length>0&&(g.args=f)}else{if(!r.trim()){o.error(t("mcp.urlRequired"));return}g.url=r.trim(),T&&(g.headers=T)}try{await s.mutateAsync(g),o.success(t("mcp.addedToast",{name:m.trim()})),p(""),y(""),S(""),a(""),h("")}catch(f){o.error(f?.message??String(f))}}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("mcp.addTitle")})}),e.jsxs("form",{onSubmit:n=>void w(n),className:"grid grid-cols-1 gap-3 p-4 sm:grid-cols-2",children:[e.jsxs("div",{children:[e.jsx(x,{className:"text-xs font-medium",children:t("mcp.nameLabel")}),e.jsx(v,{value:m,onChange:n=>p(n.target.value),placeholder:t("mcp.namePlaceholder"),className:"font-mono text-xs"})]}),e.jsxs("div",{children:[e.jsx(x,{className:"text-xs font-medium",children:t("mcp.transportLabel")}),e.jsxs(M,{value:i,onValueChange:n=>u(n),children:[e.jsx(z,{children:e.jsx(q,{})}),e.jsxs(B,{children:[e.jsx(R,{value:"stdio",children:t("mcp.transportStdioOption")}),e.jsx(R,{value:"http",children:t("mcp.transportHttpOption")})]})]})]}),i==="stdio"?e.jsxs(e.Fragment,{children:[e.jsxs("div",{children:[e.jsx(x,{className:"text-xs font-medium",children:t("mcp.commandLabel")}),e.jsx(v,{value:j,onChange:n=>y(n.target.value),placeholder:t("mcp.commandPlaceholder"),className:"font-mono text-xs"})]}),e.jsxs("div",{children:[e.jsx(x,{className:"text-xs font-medium",children:t("mcp.argsLabel")}),e.jsx(v,{value:d,onChange:n=>S(n.target.value),placeholder:"-y @modelcontextprotocol/server-filesystem /data",className:"font-mono text-xs"})]})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"sm:col-span-2",children:[e.jsx(x,{className:"text-xs font-medium",children:t("mcp.urlLabel")}),e.jsx(v,{value:r,onChange:n=>a(n.target.value),placeholder:t("mcp.urlPlaceholder"),className:"font-mono text-xs"})]}),e.jsxs("div",{className:"sm:col-span-2",children:[e.jsx(x,{className:"text-xs font-medium",children:t("mcp.headersLabel")}),e.jsx(v,{value:c,onChange:n=>h(n.target.value),placeholder:t("mcp.headersPlaceholder"),className:"font-mono text-xs"})]})]}),e.jsx("div",{className:"sm:col-span-2 flex",children:e.jsxs(k,{type:"submit",disabled:s.isPending,className:"ml-auto",children:[s.isPending?e.jsx(P,{className:"h-4 w-4 animate-spin"}):e.jsx(W,{className:"h-4 w-4"}),t("mcp.addServer")]})})]})]})}export{me as default};
|
|
7
|
+
//# sourceMappingURL=mcp-D9ob2tYX.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-DL5oUQgm.js","sources":["../../node_modules/lucide-react/dist/esm/icons/server-cog.js","../../src/routes/settings/mcp.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ServerCog = createLucideIcon(\"ServerCog\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }],\n [\n \"path\",\n {\n d: \"M4.5 10H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-.5\",\n key: \"tn8das\"\n }\n ],\n [\n \"path\",\n {\n d: \"M4.5 14H4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2h-.5\",\n key: \"1g2pve\"\n }\n ],\n [\"path\", { d: \"M6 6h.01\", key: \"1utrut\" }],\n [\"path\", { d: \"M6 18h.01\", key: \"uhywen\" }],\n [\"path\", { d: \"m15.7 13.4-.9-.3\", key: \"1jwmzr\" }],\n [\"path\", { d: \"m9.2 10.9-.9-.3\", key: \"qapnim\" }],\n [\"path\", { d: \"m10.6 15.7.3-.9\", key: \"quwk0k\" }],\n [\"path\", { d: \"m13.6 15.7-.4-1\", key: \"cb9xp7\" }],\n [\"path\", { d: \"m10.8 9.3-.4-1\", key: \"1uaiz5\" }],\n [\"path\", { d: \"m8.3 13.6 1-.4\", key: \"s6srou\" }],\n [\"path\", { d: \"m14.7 10.8 1-.4\", key: \"4d31cq\" }],\n [\"path\", { d: \"m13.4 8.3-.3.9\", key: \"1bm987\" }]\n]);\n\nexport { ServerCog as default };\n//# sourceMappingURL=server-cog.js.map\n","/**\n * /settings/mcp — external MCP servers admin (Stage 6).\n *\n * Front-end for the `/api/mcp/*` REST surface. List configured servers,\n * see their connection status + tool count, add stdio / HTTP / SSE\n * servers, probe per-server health, remove.\n *\n * The native agent loop consumes any tools advertised here; CLI agents\n * have their own MCP configs and ignore this list. See\n * docs/llm-backends.md § External MCP servers.\n */\n\nimport { useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { Loader2, Plus, RefreshCcw, ServerCog, Trash2, Activity } from 'lucide-react'\n\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport {\n Select, SelectContent, SelectItem, SelectTrigger, SelectValue,\n} from '@/components/ui/select'\nimport {\n Table, TableBody, TableCell, TableHead, TableHeader, TableRow,\n} from '@/components/ui/table'\nimport {\n useMcpList, useMcpAddServer, useMcpRemoveServer, useMcpHealth,\n type McpServerRow,\n} from '@/hooks/use-llm-admin'\n\nexport default function SettingsMcpRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const listQuery = useMcpList()\n return (\n <div className=\"mx-auto flex max-w-5xl flex-col gap-6\">\n <header className=\"flex items-center gap-3\">\n <ServerCog className=\"h-5 w-5 text-text-dim\" />\n <h1 className=\"text-xl font-semibold\">{t('mcp.title')}</h1>\n <Button\n variant=\"ghost\" size=\"sm\" className=\"ml-auto\"\n onClick={() => void listQuery.refetch()}\n disabled={listQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {listQuery.isFetching\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('mcp.refresh')}</span>\n </Button>\n </header>\n <p className=\"text-sm text-text-dim\">{t('mcp.subtitle')}</p>\n\n {listQuery.isLoading ? (\n <div className=\"h-48 rounded-md bg-surface-2 animate-pulse\" />\n ) : (\n <>\n <ServersCard data={listQuery.data} />\n <AddServerCard />\n </>\n )}\n </div>\n )\n}\n\n/* ─────────────── Servers list ─────────────── */\n\nfunction ServersCard({ data }: { data: ReturnType<typeof useMcpList>['data'] }): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const removeServer = useMcpRemoveServer()\n const health = useMcpHealth()\n const [healthResults, setHealthResults] = useState<Record<string, string>>({})\n\n async function onRemove(name: string): Promise<void> {\n if (!confirm(t('mcp.removeConfirm', { name }))) return\n try {\n await removeServer.mutateAsync(name)\n toast.success(t('mcp.removedToast', { name }))\n } catch (err) {\n toast.error(((err as Error)?.message ?? String(err)))\n }\n }\n\n async function onHealth(name: string): Promise<void> {\n setHealthResults((m) => ({ ...m, [name]: t('mcp.probing') }))\n try {\n const r = await health.mutateAsync(name)\n const msg = r.connected\n ? `✓ ${r.toolCount === 1\n ? t('mcp.runtimeConnectedOne', { count: r.toolCount })\n : t('mcp.runtimeConnected', { count: r.toolCount })}`\n : `✗ ${r.lastError ?? t('mcp.runtimeDisconnected')}`\n setHealthResults((m) => ({ ...m, [name]: msg }))\n } catch (err) {\n setHealthResults((m) => ({ ...m, [name]: `✗ ${((err as Error)?.message ?? String(err))}` }))\n }\n }\n\n const rows = data?.servers ?? []\n const runtime = data?.runtime?.servers ?? []\n if (rows.length === 0) {\n return (\n <section className=\"rounded-md border border-border bg-surface p-6 text-center text-sm text-text-dim\">\n {t('mcp.serversEmpty')}\n </section>\n )\n }\n\n return (\n <section className=\"rounded-md border border-border bg-surface\">\n <header className=\"flex items-center gap-2 border-b border-border px-4 py-3\">\n <h2 className=\"text-sm font-semibold\">{t('mcp.serversTitle', { count: rows.length })}</h2>\n {data?.runtime && (\n <Badge variant=\"info\">{t('mcp.totalTools', { count: data.runtime.totalTools })}</Badge>\n )}\n </header>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{t('mcp.col.name')}</TableHead>\n <TableHead>{t('mcp.col.transport')}</TableHead>\n <TableHead>{t('mcp.col.target')}</TableHead>\n <TableHead>{t('mcp.col.runtime')}</TableHead>\n <TableHead>{t('mcp.col.actions')}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {rows.map((s) => {\n const rt = runtime.find((r) => r.name === s.name)\n const transport = transportLabel(s, t)\n const target = s.command\n ? `${s.command} ${(s.args ?? []).join(' ')}`.trim()\n : (s.url ?? '—')\n const runtimeBadge = !rt\n ? <Badge variant=\"outline\">{t('mcp.runtimeUnknown')}</Badge>\n : rt.connected\n ? <Badge variant=\"success\">\n {rt.toolCount === 1\n ? t('mcp.runtimeConnectedOne', { count: rt.toolCount })\n : t('mcp.runtimeConnected', { count: rt.toolCount })}\n </Badge>\n : <Badge variant=\"danger\">{t('mcp.runtimeDisconnected')}</Badge>\n return (\n <TableRow key={s.name}>\n <TableCell className=\"font-mono text-xs\">{s.name}</TableCell>\n <TableCell>{transport}</TableCell>\n <TableCell className=\"break-all font-mono text-[11px] text-text-dim\">{target}</TableCell>\n <TableCell>{runtimeBadge}</TableCell>\n <TableCell className=\"flex flex-col gap-1 sm:flex-row sm:items-center\">\n <Button\n variant=\"ghost\" size=\"sm\"\n onClick={() => void onHealth(s.name)}\n disabled={health.isPending}\n >\n <Activity className=\"h-4 w-4\" />\n <span>{t('mcp.health')}</span>\n </Button>\n <Button\n variant=\"ghost\" size=\"sm\"\n onClick={() => void onRemove(s.name)}\n disabled={removeServer.isPending}\n className=\"text-danger hover:text-danger\"\n >\n <Trash2 className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">{t('mcp.remove')}</span>\n </Button>\n {healthResults[s.name] && (\n <span className=\"ml-2 text-[11px] text-text-dim\">{healthResults[s.name]}</span>\n )}\n </TableCell>\n </TableRow>\n )\n })}\n </TableBody>\n </Table>\n </section>\n )\n}\n\nfunction transportLabel(\n s: McpServerRow,\n t: (key: string) => string,\n): string {\n if (s.command) return t('mcp.transportStdio')\n if (s.url) return s.url.endsWith('/sse') ? t('mcp.transportSse') : t('mcp.transportHttp')\n return '—'\n}\n\n/* ─────────────── Add server form ─────────────── */\n\nfunction AddServerCard(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const addServer = useMcpAddServer()\n const [name, setName] = useState('')\n const [transport, setTransport] = useState<'stdio' | 'http'>('stdio')\n const [command, setCommand] = useState('')\n const [args, setArgs] = useState('')\n const [url, setUrl] = useState('')\n const [headersJson, setHeadersJson] = useState('')\n\n async function onSubmit(e: React.FormEvent): Promise<void> {\n e.preventDefault()\n if (!name.trim()) { toast.error(t('mcp.nameRequired')); return }\n let headers: Record<string, string> | undefined\n if (headersJson.trim()) {\n try { headers = JSON.parse(headersJson) }\n catch { toast.error(t('mcp.headersInvalid')); return }\n }\n const body: Parameters<typeof addServer.mutateAsync>[0] = { name: name.trim() }\n if (transport === 'stdio') {\n if (!command.trim()) { toast.error(t('mcp.commandRequired')); return }\n body.command = command.trim()\n const splitArgs = args.split(/\\s+/).filter(Boolean)\n if (splitArgs.length > 0) body.args = splitArgs\n } else {\n if (!url.trim()) { toast.error(t('mcp.urlRequired')); return }\n body.url = url.trim()\n if (headers) body.headers = headers\n }\n try {\n await addServer.mutateAsync(body)\n toast.success(t('mcp.addedToast', { name: name.trim() }))\n setName(''); setCommand(''); setArgs(''); setUrl(''); setHeadersJson('')\n } catch (err) {\n toast.error(((err as Error)?.message ?? String(err)))\n }\n }\n\n return (\n <section className=\"rounded-md border border-border bg-surface\">\n <header className=\"border-b border-border px-4 py-3\">\n <h2 className=\"text-sm font-semibold\">{t('mcp.addTitle')}</h2>\n </header>\n <form onSubmit={(e) => void onSubmit(e)} className=\"grid grid-cols-1 gap-3 p-4 sm:grid-cols-2\">\n <div>\n <Label className=\"text-xs font-medium\">{t('mcp.nameLabel')}</Label>\n <Input\n value={name} onChange={(e) => setName(e.target.value)}\n placeholder={t('mcp.namePlaceholder')}\n className=\"font-mono text-xs\"\n />\n </div>\n <div>\n <Label className=\"text-xs font-medium\">{t('mcp.transportLabel')}</Label>\n <Select value={transport} onValueChange={(v) => setTransport(v as 'stdio' | 'http')}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"stdio\">{t('mcp.transportStdioOption')}</SelectItem>\n <SelectItem value=\"http\">{t('mcp.transportHttpOption')}</SelectItem>\n </SelectContent>\n </Select>\n </div>\n {transport === 'stdio' ? (\n <>\n <div>\n <Label className=\"text-xs font-medium\">{t('mcp.commandLabel')}</Label>\n <Input\n value={command} onChange={(e) => setCommand(e.target.value)}\n placeholder={t('mcp.commandPlaceholder')}\n className=\"font-mono text-xs\"\n />\n </div>\n <div>\n <Label className=\"text-xs font-medium\">{t('mcp.argsLabel')}</Label>\n <Input\n value={args} onChange={(e) => setArgs(e.target.value)}\n placeholder=\"-y @modelcontextprotocol/server-filesystem /data\"\n className=\"font-mono text-xs\"\n />\n </div>\n </>\n ) : (\n <>\n <div className=\"sm:col-span-2\">\n <Label className=\"text-xs font-medium\">{t('mcp.urlLabel')}</Label>\n <Input\n value={url} onChange={(e) => setUrl(e.target.value)}\n placeholder={t('mcp.urlPlaceholder')}\n className=\"font-mono text-xs\"\n />\n </div>\n <div className=\"sm:col-span-2\">\n <Label className=\"text-xs font-medium\">{t('mcp.headersLabel')}</Label>\n <Input\n value={headersJson} onChange={(e) => setHeadersJson(e.target.value)}\n placeholder={t('mcp.headersPlaceholder')}\n className=\"font-mono text-xs\"\n />\n </div>\n </>\n )}\n <div className=\"sm:col-span-2 flex\">\n <Button type=\"submit\" disabled={addServer.isPending} className=\"ml-auto\">\n {addServer.isPending ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <Plus className=\"h-4 w-4\" />}\n {t('mcp.addServer')}\n </Button>\n </div>\n </form>\n </section>\n )\n}\n"],"names":["ServerCog","createLucideIcon","SettingsMcpRoute","useTranslation","listQuery","useMcpList","jsxs","jsx","Button","Loader2","RefreshCcw","Fragment","ServersCard","AddServerCard","data","t","removeServer","useMcpRemoveServer","health","useMcpHealth","healthResults","setHealthResults","useState","onRemove","name","toast","err","onHealth","m","r","msg","rows","runtime","Badge","Table","TableHeader","TableRow","TableHead","TableBody","s","rt","transport","transportLabel","target","runtimeBadge","TableCell","Activity","Trash2","addServer","useMcpAddServer","setName","setTransport","command","setCommand","args","setArgs","url","setUrl","headersJson","setHeadersJson","onSubmit","e","headers","body","splitArgs","Label","Input","Select","v","SelectTrigger","SelectValue","SelectContent","SelectItem","Plus"],"mappings":"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","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"mcp-D9ob2tYX.js","sources":["../../node_modules/lucide-react/dist/esm/icons/server-cog.js","../../src/routes/settings/mcp.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.469.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ServerCog = createLucideIcon(\"ServerCog\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }],\n [\n \"path\",\n {\n d: \"M4.5 10H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-.5\",\n key: \"tn8das\"\n }\n ],\n [\n \"path\",\n {\n d: \"M4.5 14H4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2h-.5\",\n key: \"1g2pve\"\n }\n ],\n [\"path\", { d: \"M6 6h.01\", key: \"1utrut\" }],\n [\"path\", { d: \"M6 18h.01\", key: \"uhywen\" }],\n [\"path\", { d: \"m15.7 13.4-.9-.3\", key: \"1jwmzr\" }],\n [\"path\", { d: \"m9.2 10.9-.9-.3\", key: \"qapnim\" }],\n [\"path\", { d: \"m10.6 15.7.3-.9\", key: \"quwk0k\" }],\n [\"path\", { d: \"m13.6 15.7-.4-1\", key: \"cb9xp7\" }],\n [\"path\", { d: \"m10.8 9.3-.4-1\", key: \"1uaiz5\" }],\n [\"path\", { d: \"m8.3 13.6 1-.4\", key: \"s6srou\" }],\n [\"path\", { d: \"m14.7 10.8 1-.4\", key: \"4d31cq\" }],\n [\"path\", { d: \"m13.4 8.3-.3.9\", key: \"1bm987\" }]\n]);\n\nexport { ServerCog as default };\n//# sourceMappingURL=server-cog.js.map\n","/**\n * /settings/mcp — external MCP servers admin (Stage 6).\n *\n * Front-end for the `/api/mcp/*` REST surface. List configured servers,\n * see their connection status + tool count, add stdio / HTTP / SSE\n * servers, probe per-server health, remove.\n *\n * The native agent loop consumes any tools advertised here; CLI agents\n * have their own MCP configs and ignore this list. See\n * docs/llm-backends.md § External MCP servers.\n */\n\nimport { useState } from 'react'\nimport { useTranslation } from 'react-i18next'\nimport { toast } from 'sonner'\nimport { Loader2, Plus, RefreshCcw, ServerCog, Trash2, Activity } from 'lucide-react'\n\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport {\n Select, SelectContent, SelectItem, SelectTrigger, SelectValue,\n} from '@/components/ui/select'\nimport {\n Table, TableBody, TableCell, TableHead, TableHeader, TableRow,\n} from '@/components/ui/table'\nimport {\n useMcpList, useMcpAddServer, useMcpRemoveServer, useMcpHealth,\n type McpServerRow,\n} from '@/hooks/use-llm-admin'\n\nexport default function SettingsMcpRoute(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const listQuery = useMcpList()\n return (\n <div className=\"mx-auto flex max-w-5xl flex-col gap-6\">\n <header className=\"flex items-center gap-3\">\n <ServerCog className=\"h-5 w-5 text-text-dim\" />\n <h1 className=\"text-xl font-semibold\">{t('mcp.title')}</h1>\n <Button\n variant=\"ghost\" size=\"sm\" className=\"ml-auto\"\n onClick={() => void listQuery.refetch()}\n disabled={listQuery.isFetching}\n aria-label={t('actions.refresh', { ns: 'common' })}\n >\n {listQuery.isFetching\n ? <Loader2 className=\"h-4 w-4 animate-spin\" />\n : <RefreshCcw className=\"h-4 w-4\" />}\n <span className=\"hidden sm:inline\">{t('mcp.refresh')}</span>\n </Button>\n </header>\n <p className=\"text-sm text-text-dim\">{t('mcp.subtitle')}</p>\n\n {listQuery.isLoading ? (\n <div className=\"h-48 rounded-md bg-surface-2 animate-pulse\" />\n ) : (\n <>\n <ServersCard data={listQuery.data} />\n <AddServerCard />\n </>\n )}\n </div>\n )\n}\n\n/* ─────────────── Servers list ─────────────── */\n\nfunction ServersCard({ data }: { data: ReturnType<typeof useMcpList>['data'] }): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const removeServer = useMcpRemoveServer()\n const health = useMcpHealth()\n const [healthResults, setHealthResults] = useState<Record<string, string>>({})\n\n async function onRemove(name: string): Promise<void> {\n if (!confirm(t('mcp.removeConfirm', { name }))) return\n try {\n await removeServer.mutateAsync(name)\n toast.success(t('mcp.removedToast', { name }))\n } catch (err) {\n toast.error(((err as Error)?.message ?? String(err)))\n }\n }\n\n async function onHealth(name: string): Promise<void> {\n setHealthResults((m) => ({ ...m, [name]: t('mcp.probing') }))\n try {\n const r = await health.mutateAsync(name)\n const msg = r.connected\n ? `✓ ${r.toolCount === 1\n ? t('mcp.runtimeConnectedOne', { count: r.toolCount })\n : t('mcp.runtimeConnected', { count: r.toolCount })}`\n : `✗ ${r.lastError ?? t('mcp.runtimeDisconnected')}`\n setHealthResults((m) => ({ ...m, [name]: msg }))\n } catch (err) {\n setHealthResults((m) => ({ ...m, [name]: `✗ ${((err as Error)?.message ?? String(err))}` }))\n }\n }\n\n const rows = data?.servers ?? []\n const runtime = data?.runtime?.servers ?? []\n if (rows.length === 0) {\n return (\n <section className=\"rounded-md border border-border bg-surface p-6 text-center text-sm text-text-dim\">\n {t('mcp.serversEmpty')}\n </section>\n )\n }\n\n return (\n <section className=\"rounded-md border border-border bg-surface\">\n <header className=\"flex items-center gap-2 border-b border-border px-4 py-3\">\n <h2 className=\"text-sm font-semibold\">{t('mcp.serversTitle', { count: rows.length })}</h2>\n {data?.runtime && (\n <Badge variant=\"info\">{t('mcp.totalTools', { count: data.runtime.totalTools })}</Badge>\n )}\n </header>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{t('mcp.col.name')}</TableHead>\n <TableHead>{t('mcp.col.transport')}</TableHead>\n <TableHead>{t('mcp.col.target')}</TableHead>\n <TableHead>{t('mcp.col.runtime')}</TableHead>\n <TableHead>{t('mcp.col.actions')}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {rows.map((s) => {\n const rt = runtime.find((r) => r.name === s.name)\n const transport = transportLabel(s, t)\n const target = s.command\n ? `${s.command} ${(s.args ?? []).join(' ')}`.trim()\n : (s.url ?? '—')\n const runtimeBadge = !rt\n ? <Badge variant=\"outline\">{t('mcp.runtimeUnknown')}</Badge>\n : rt.connected\n ? <Badge variant=\"success\">\n {rt.toolCount === 1\n ? t('mcp.runtimeConnectedOne', { count: rt.toolCount })\n : t('mcp.runtimeConnected', { count: rt.toolCount })}\n </Badge>\n : <Badge variant=\"danger\">{t('mcp.runtimeDisconnected')}</Badge>\n return (\n <TableRow key={s.name}>\n <TableCell className=\"font-mono text-xs\">{s.name}</TableCell>\n <TableCell>{transport}</TableCell>\n <TableCell className=\"break-all font-mono text-[11px] text-text-dim\">{target}</TableCell>\n <TableCell>{runtimeBadge}</TableCell>\n <TableCell className=\"flex flex-col gap-1 sm:flex-row sm:items-center\">\n <Button\n variant=\"ghost\" size=\"sm\"\n onClick={() => void onHealth(s.name)}\n disabled={health.isPending}\n >\n <Activity className=\"h-4 w-4\" />\n <span>{t('mcp.health')}</span>\n </Button>\n <Button\n variant=\"ghost\" size=\"sm\"\n onClick={() => void onRemove(s.name)}\n disabled={removeServer.isPending}\n className=\"text-danger hover:text-danger\"\n >\n <Trash2 className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">{t('mcp.remove')}</span>\n </Button>\n {healthResults[s.name] && (\n <span className=\"ml-2 text-[11px] text-text-dim\">{healthResults[s.name]}</span>\n )}\n </TableCell>\n </TableRow>\n )\n })}\n </TableBody>\n </Table>\n </section>\n )\n}\n\nfunction transportLabel(\n s: McpServerRow,\n t: (key: string) => string,\n): string {\n if (s.command) return t('mcp.transportStdio')\n if (s.url) return s.url.endsWith('/sse') ? t('mcp.transportSse') : t('mcp.transportHttp')\n return '—'\n}\n\n/* ─────────────── Add server form ─────────────── */\n\nfunction AddServerCard(): JSX.Element {\n const { t } = useTranslation(['settings', 'common'])\n const addServer = useMcpAddServer()\n const [name, setName] = useState('')\n const [transport, setTransport] = useState<'stdio' | 'http'>('stdio')\n const [command, setCommand] = useState('')\n const [args, setArgs] = useState('')\n const [url, setUrl] = useState('')\n const [headersJson, setHeadersJson] = useState('')\n\n async function onSubmit(e: React.FormEvent): Promise<void> {\n e.preventDefault()\n if (!name.trim()) { toast.error(t('mcp.nameRequired')); return }\n let headers: Record<string, string> | undefined\n if (headersJson.trim()) {\n try { headers = JSON.parse(headersJson) }\n catch { toast.error(t('mcp.headersInvalid')); return }\n }\n const body: Parameters<typeof addServer.mutateAsync>[0] = { name: name.trim() }\n if (transport === 'stdio') {\n if (!command.trim()) { toast.error(t('mcp.commandRequired')); return }\n body.command = command.trim()\n const splitArgs = args.split(/\\s+/).filter(Boolean)\n if (splitArgs.length > 0) body.args = splitArgs\n } else {\n if (!url.trim()) { toast.error(t('mcp.urlRequired')); return }\n body.url = url.trim()\n if (headers) body.headers = headers\n }\n try {\n await addServer.mutateAsync(body)\n toast.success(t('mcp.addedToast', { name: name.trim() }))\n setName(''); setCommand(''); setArgs(''); setUrl(''); setHeadersJson('')\n } catch (err) {\n toast.error(((err as Error)?.message ?? String(err)))\n }\n }\n\n return (\n <section className=\"rounded-md border border-border bg-surface\">\n <header className=\"border-b border-border px-4 py-3\">\n <h2 className=\"text-sm font-semibold\">{t('mcp.addTitle')}</h2>\n </header>\n <form onSubmit={(e) => void onSubmit(e)} className=\"grid grid-cols-1 gap-3 p-4 sm:grid-cols-2\">\n <div>\n <Label className=\"text-xs font-medium\">{t('mcp.nameLabel')}</Label>\n <Input\n value={name} onChange={(e) => setName(e.target.value)}\n placeholder={t('mcp.namePlaceholder')}\n className=\"font-mono text-xs\"\n />\n </div>\n <div>\n <Label className=\"text-xs font-medium\">{t('mcp.transportLabel')}</Label>\n <Select value={transport} onValueChange={(v) => setTransport(v as 'stdio' | 'http')}>\n <SelectTrigger><SelectValue /></SelectTrigger>\n <SelectContent>\n <SelectItem value=\"stdio\">{t('mcp.transportStdioOption')}</SelectItem>\n <SelectItem value=\"http\">{t('mcp.transportHttpOption')}</SelectItem>\n </SelectContent>\n </Select>\n </div>\n {transport === 'stdio' ? (\n <>\n <div>\n <Label className=\"text-xs font-medium\">{t('mcp.commandLabel')}</Label>\n <Input\n value={command} onChange={(e) => setCommand(e.target.value)}\n placeholder={t('mcp.commandPlaceholder')}\n className=\"font-mono text-xs\"\n />\n </div>\n <div>\n <Label className=\"text-xs font-medium\">{t('mcp.argsLabel')}</Label>\n <Input\n value={args} onChange={(e) => setArgs(e.target.value)}\n placeholder=\"-y @modelcontextprotocol/server-filesystem /data\"\n className=\"font-mono text-xs\"\n />\n </div>\n </>\n ) : (\n <>\n <div className=\"sm:col-span-2\">\n <Label className=\"text-xs font-medium\">{t('mcp.urlLabel')}</Label>\n <Input\n value={url} onChange={(e) => setUrl(e.target.value)}\n placeholder={t('mcp.urlPlaceholder')}\n className=\"font-mono text-xs\"\n />\n </div>\n <div className=\"sm:col-span-2\">\n <Label className=\"text-xs font-medium\">{t('mcp.headersLabel')}</Label>\n <Input\n value={headersJson} onChange={(e) => setHeadersJson(e.target.value)}\n placeholder={t('mcp.headersPlaceholder')}\n className=\"font-mono text-xs\"\n />\n </div>\n </>\n )}\n <div className=\"sm:col-span-2 flex\">\n <Button type=\"submit\" disabled={addServer.isPending} className=\"ml-auto\">\n {addServer.isPending ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <Plus className=\"h-4 w-4\" />}\n {t('mcp.addServer')}\n </Button>\n </div>\n </form>\n </section>\n )\n}\n"],"names":["ServerCog","createLucideIcon","SettingsMcpRoute","useTranslation","listQuery","useMcpList","jsxs","jsx","Button","Loader2","RefreshCcw","Fragment","ServersCard","AddServerCard","data","t","removeServer","useMcpRemoveServer","health","useMcpHealth","healthResults","setHealthResults","useState","onRemove","name","toast","err","onHealth","m","r","msg","rows","runtime","Badge","Table","TableHeader","TableRow","TableHead","TableBody","s","rt","transport","transportLabel","target","runtimeBadge","TableCell","Activity","Trash2","addServer","useMcpAddServer","setName","setTransport","command","setCommand","args","setArgs","url","setUrl","headersJson","setHeadersJson","onSubmit","e","headers","body","splitArgs","Label","Input","Select","v","SelectTrigger","SelectValue","SelectContent","SelectItem","Plus"],"mappings":"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","x_google_ignoreList":[0]}
|