@samanhappy/mcphub 1.1.14 → 1.1.15
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/README.fr.md +1 -1
- package/README.md +1 -1
- package/README.zh.md +1 -1
- package/dist/betterAuth.js +3 -3
- package/dist/betterAuth.js.map +1 -1
- package/dist/cli/commands/keys.js +22 -3
- package/dist/cli/commands/keys.js.map +1 -1
- package/dist/clients/mcpSdkClient.js +2667 -1448
- package/dist/clients/mcpSdkClient.js.map +4 -4
- package/dist/controllers/bearerKeyController.js +49 -3
- package/dist/controllers/bearerKeyController.js.map +1 -1
- package/dist/controllers/credentialBindingController.js +1 -1
- package/dist/controllers/credentialBindingController.js.map +1 -1
- package/dist/controllers/groupController.js +12 -5
- package/dist/controllers/groupController.js.map +1 -1
- package/dist/controllers/oauthRelayController.js +65 -0
- package/dist/controllers/oauthRelayController.js.map +1 -0
- package/dist/controllers/personalOAuthController.js +10 -1
- package/dist/controllers/personalOAuthController.js.map +1 -1
- package/dist/controllers/serverController.js +23 -14
- package/dist/controllers/serverController.js.map +1 -1
- package/dist/controllers/userController.js +11 -1
- package/dist/controllers/userController.js.map +1 -1
- package/dist/dao/BearerKeyDao.js +10 -5
- package/dist/dao/BearerKeyDao.js.map +1 -1
- package/dist/dao/BearerKeyDaoDbImpl.js +16 -5
- package/dist/dao/BearerKeyDaoDbImpl.js.map +1 -1
- package/dist/dao/GroupDaoDbImpl.js +11 -0
- package/dist/dao/GroupDaoDbImpl.js.map +1 -1
- package/dist/dao/ServerDao.js +5 -1
- package/dist/dao/ServerDao.js.map +1 -1
- package/dist/dao/ServerDaoDbImpl.js +3 -0
- package/dist/dao/ServerDaoDbImpl.js.map +1 -1
- package/dist/dao/UserDaoDbImpl.js +4 -0
- package/dist/dao/UserDaoDbImpl.js.map +1 -1
- package/dist/db/entities/BearerKey.js +8 -0
- package/dist/db/entities/BearerKey.js.map +1 -1
- package/dist/db/entities/Group.js +4 -0
- package/dist/db/entities/Group.js.map +1 -1
- package/dist/db/entities/Server.js +4 -0
- package/dist/db/entities/Server.js.map +1 -1
- package/dist/db/entities/User.js +4 -0
- package/dist/db/entities/User.js.map +1 -1
- package/dist/db/repositories/ServerRepository.js +1 -0
- package/dist/db/repositories/ServerRepository.js.map +1 -1
- package/dist/middlewares/auth.js +7 -1
- package/dist/middlewares/auth.js.map +1 -1
- package/dist/routes/index.js +2 -0
- package/dist/routes/index.js.map +1 -1
- package/dist/services/authorizationService.js.map +1 -1
- package/dist/services/capabilitySnapshotService.js +2 -1
- package/dist/services/capabilitySnapshotService.js.map +1 -1
- package/dist/services/credentialBindingService.js +9 -1
- package/dist/services/credentialBindingService.js.map +1 -1
- package/dist/services/dataService.js +4 -2
- package/dist/services/dataService.js.map +1 -1
- package/dist/services/groupService.js +15 -7
- package/dist/services/groupService.js.map +1 -1
- package/dist/services/mcpEventBus.js +6 -0
- package/dist/services/mcpEventBus.js.map +1 -0
- package/dist/services/mcpService.js +26 -2
- package/dist/services/mcpService.js.map +1 -1
- package/dist/services/personalOAuthService.js +2 -0
- package/dist/services/personalOAuthService.js.map +1 -1
- package/dist/services/requestContextService.js +15 -0
- package/dist/services/requestContextService.js.map +1 -1
- package/dist/services/serverConfigEnvironment.js +2 -1
- package/dist/services/serverConfigEnvironment.js.map +1 -1
- package/dist/services/sseService.js +58 -6
- package/dist/services/sseService.js.map +1 -1
- package/dist/services/templateService.js +11 -5
- package/dist/services/templateService.js.map +1 -1
- package/dist/services/userService.js +5 -1
- package/dist/services/userService.js.map +1 -1
- package/dist/utils/groupAccess.js +6 -4
- package/dist/utils/groupAccess.js.map +1 -1
- package/dist/utils/groupKeyScope.js +11 -5
- package/dist/utils/groupKeyScope.js.map +1 -1
- package/dist/utils/migration.js +5 -0
- package/dist/utils/migration.js.map +1 -1
- package/dist/utils/oauthBearer.js +1 -0
- package/dist/utils/oauthBearer.js.map +1 -1
- package/dist/utils/oauthServerMetadata.js +21 -0
- package/dist/utils/oauthServerMetadata.js.map +1 -1
- package/dist/utils/serverConfigPersistence.js +16 -1
- package/dist/utils/serverConfigPersistence.js.map +1 -1
- package/dist/utils/serverConfigValidation.js +1 -0
- package/dist/utils/serverConfigValidation.js.map +1 -1
- package/dist/utils/settingsSync.js +3 -0
- package/dist/utils/settingsSync.js.map +1 -1
- package/frontend/dist/assets/{ActivityPage-C8Zj4FeE.js → ActivityPage-Bi-TjKez.js} +2 -2
- package/frontend/dist/assets/{ActivityPage-C8Zj4FeE.js.map → ActivityPage-Bi-TjKez.js.map} +1 -1
- package/frontend/dist/assets/{ConfirmDialog-BYdfb115.js → ConfirmDialog-BJpzQmMw.js} +2 -2
- package/frontend/dist/assets/{ConfirmDialog-BYdfb115.js.map → ConfirmDialog-BJpzQmMw.js.map} +1 -1
- package/frontend/dist/assets/CredentialsPage-C4Ucer3d.js +2 -0
- package/frontend/dist/assets/CredentialsPage-C4Ucer3d.js.map +1 -0
- package/frontend/dist/assets/{Dashboard-CCiZcGi4.js → Dashboard-C_2KkuoD.js} +2 -2
- package/frontend/dist/assets/{Dashboard-CCiZcGi4.js.map → Dashboard-C_2KkuoD.js.map} +1 -1
- package/frontend/dist/assets/{DeleteDialog-BaCsEkJA.js → DeleteDialog-BoMYLx3J.js} +2 -2
- package/frontend/dist/assets/{DeleteDialog-BaCsEkJA.js.map → DeleteDialog-BoMYLx3J.js.map} +1 -1
- package/frontend/dist/assets/{EndpointCopy-CmKx4RVL.js → EndpointCopy-DITVC2YQ.js} +2 -2
- package/frontend/dist/assets/{EndpointCopy-CmKx4RVL.js.map → EndpointCopy-DITVC2YQ.js.map} +1 -1
- package/frontend/dist/assets/GroupsPage-sE6YJyuK.js +33 -0
- package/frontend/dist/assets/GroupsPage-sE6YJyuK.js.map +1 -0
- package/frontend/dist/assets/{LoginPage-Hn1uu0vB.js → LoginPage-CFsd_nY-.js} +2 -2
- package/frontend/dist/assets/{LoginPage-Hn1uu0vB.js.map → LoginPage-CFsd_nY-.js.map} +1 -1
- package/frontend/dist/assets/{LogsPage-JMCtTjCv.js → LogsPage-BxZuGDuc.js} +2 -2
- package/frontend/dist/assets/{LogsPage-JMCtTjCv.js.map → LogsPage-BxZuGDuc.js.map} +1 -1
- package/frontend/dist/assets/MarketPage-CDBs4vMb.js +2 -0
- package/frontend/dist/assets/{MarketPage-Bvi1KESo.js.map → MarketPage-CDBs4vMb.js.map} +1 -1
- package/frontend/dist/assets/{OAuthConsentPage-DofQEZAU.js → OAuthConsentPage-BN_ucViM.js} +2 -2
- package/frontend/dist/assets/{OAuthConsentPage-DofQEZAU.js.map → OAuthConsentPage-BN_ucViM.js.map} +1 -1
- package/frontend/dist/assets/{Pagination-D99WHhBx.js → Pagination-S-7lzy59.js} +2 -2
- package/frontend/dist/assets/{Pagination-D99WHhBx.js.map → Pagination-S-7lzy59.js.map} +1 -1
- package/frontend/dist/assets/{PromptsPage-B-8vczAR.js → PromptsPage-Bl3ySXGK.js} +2 -2
- package/frontend/dist/assets/{PromptsPage-B-8vczAR.js.map → PromptsPage-Bl3ySXGK.js.map} +1 -1
- package/frontend/dist/assets/{ResourcesPage-DLAIatoG.js → ResourcesPage-BOzQkQ92.js} +2 -2
- package/frontend/dist/assets/{ResourcesPage-DLAIatoG.js.map → ResourcesPage-BOzQkQ92.js.map} +1 -1
- package/frontend/dist/assets/{ServersPage-wVLsTL_f.js → ServersPage-DHYwQ5AM.js} +5 -5
- package/frontend/dist/assets/{ServersPage-wVLsTL_f.js.map → ServersPage-DHYwQ5AM.js.map} +1 -1
- package/frontend/dist/assets/SettingsPage-CSJ35jlM.js +14 -0
- package/frontend/dist/assets/SettingsPage-CSJ35jlM.js.map +1 -0
- package/frontend/dist/assets/{StatusDot-00-sTQKv.js → StatusDot-NSjojGCy.js} +2 -2
- package/frontend/dist/assets/{StatusDot-00-sTQKv.js.map → StatusDot-NSjojGCy.js.map} +1 -1
- package/frontend/dist/assets/{ToggleGroup-CtWBng3r.js → ToggleGroup-BIZWpNzm.js} +2 -2
- package/frontend/dist/assets/{ToggleGroup-CtWBng3r.js.map → ToggleGroup-BIZWpNzm.js.map} +1 -1
- package/frontend/dist/assets/UserGroupSelection-CN0weGXJ.js +2 -0
- package/frontend/dist/assets/UserGroupSelection-CN0weGXJ.js.map +1 -0
- package/frontend/dist/assets/UsersPage-DC51v2b8.js +2 -0
- package/frontend/dist/assets/UsersPage-DC51v2b8.js.map +1 -0
- package/frontend/dist/assets/{clipboard-2RRFM-q8.js → clipboard-ik5YV95M.js} +2 -2
- package/frontend/dist/assets/{clipboard-2RRFM-q8.js.map → clipboard-ik5YV95M.js.map} +1 -1
- package/frontend/dist/assets/{costRevision-Ntl7VtWo.js → costRevision-Bxov9_vH.js} +2 -2
- package/frontend/dist/assets/{costRevision-Ntl7VtWo.js.map → costRevision-Bxov9_vH.js.map} +1 -1
- package/frontend/dist/assets/framework-vendor-D0S_ys6r.js +61 -0
- package/frontend/dist/assets/framework-vendor-D0S_ys6r.js.map +1 -0
- package/frontend/dist/assets/{i18n-vendor-DVmjrzgW.js → i18n-vendor-COTriSc6.js} +2 -2
- package/frontend/dist/assets/{i18n-vendor-DVmjrzgW.js.map → i18n-vendor-COTriSc6.js.map} +1 -1
- package/frontend/dist/assets/{icons-vendor-CyAS6fj0.js → icons-vendor-DZjjGrOu.js} +2 -2
- package/frontend/dist/assets/{icons-vendor-CyAS6fj0.js.map → icons-vendor-DZjjGrOu.js.map} +1 -1
- package/frontend/dist/assets/index-6AyPtx0A.js +3 -0
- package/frontend/dist/assets/index-6AyPtx0A.js.map +1 -0
- package/frontend/dist/assets/{resourceService-BB4UM6IQ.js → resourceService-DMzCAZ0B.js} +2 -2
- package/frontend/dist/assets/{resourceService-BB4UM6IQ.js.map → resourceService-DMzCAZ0B.js.map} +1 -1
- package/frontend/dist/assets/{useCostData-C3XnQyUj.js → useCostData-CcFSYViI.js} +2 -2
- package/frontend/dist/assets/{useCostData-C3XnQyUj.js.map → useCostData-CcFSYViI.js.map} +1 -1
- package/frontend/dist/assets/variableDetection-CbYSa1ka.js +80 -0
- package/frontend/dist/assets/variableDetection-CbYSa1ka.js.map +1 -0
- package/frontend/dist/index.html +4 -4
- package/package.json +2 -2
- package/frontend/dist/assets/CredentialsPage-BnzqPYjg.js +0 -2
- package/frontend/dist/assets/CredentialsPage-BnzqPYjg.js.map +0 -1
- package/frontend/dist/assets/GroupsPage-DHgQeVHy.js +0 -33
- package/frontend/dist/assets/GroupsPage-DHgQeVHy.js.map +0 -1
- package/frontend/dist/assets/MarketPage-Bvi1KESo.js +0 -2
- package/frontend/dist/assets/SettingsPage-DkfXDE5_.js +0 -14
- package/frontend/dist/assets/SettingsPage-DkfXDE5_.js.map +0 -1
- package/frontend/dist/assets/UsersPage-BtdFWcVD.js +0 -2
- package/frontend/dist/assets/UsersPage-BtdFWcVD.js.map +0 -1
- package/frontend/dist/assets/framework-vendor-CQFm9vKd.js +0 -61
- package/frontend/dist/assets/framework-vendor-CQFm9vKd.js.map +0 -1
- package/frontend/dist/assets/index-CkSmxNPW.js +0 -3
- package/frontend/dist/assets/index-CkSmxNPW.js.map +0 -1
- package/frontend/dist/assets/variableDetection-BUXwrSop.js +0 -18
- package/frontend/dist/assets/variableDetection-BUXwrSop.js.map +0 -1
package/frontend/dist/index.html
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
7
|
<title>MCPHub Dashboard</title>
|
|
8
8
|
<link rel="icon" type="image/x-icon" href="./assets/favicon-DJnZjsC8.ico">
|
|
9
|
-
<script type="module" crossorigin src="./assets/index-
|
|
10
|
-
<link rel="modulepreload" crossorigin href="./assets/framework-vendor-
|
|
11
|
-
<link rel="modulepreload" crossorigin href="./assets/i18n-vendor-
|
|
12
|
-
<link rel="modulepreload" crossorigin href="./assets/icons-vendor-
|
|
9
|
+
<script type="module" crossorigin src="./assets/index-6AyPtx0A.js"></script>
|
|
10
|
+
<link rel="modulepreload" crossorigin href="./assets/framework-vendor-D0S_ys6r.js">
|
|
11
|
+
<link rel="modulepreload" crossorigin href="./assets/i18n-vendor-COTriSc6.js">
|
|
12
|
+
<link rel="modulepreload" crossorigin href="./assets/icons-vendor-DZjjGrOu.js">
|
|
13
13
|
<link rel="stylesheet" crossorigin href="./assets/index-DrHctFvx.css">
|
|
14
14
|
</head>
|
|
15
15
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@samanhappy/mcphub",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.15",
|
|
4
4
|
"description": "Open-source, self-hosted MCP gateway and control plane for connecting, controlling, and operating MCP servers.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
"zod": "^4.4.3"
|
|
136
136
|
},
|
|
137
137
|
"engines": {
|
|
138
|
-
"node": ">=
|
|
138
|
+
"node": ">=22.0.0"
|
|
139
139
|
},
|
|
140
140
|
"scripts": {
|
|
141
141
|
"build": "pnpm backend:build && pnpm frontend:build",
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{i as j,r as i,j as s}from"./framework-vendor-CQFm9vKd.js";import{a as g,h as b,i as N,j as y}from"./index-CkSmxNPW.js";import{u as v}from"./i18n-vendor-DVmjrzgW.js";import"./icons-vendor-CyAS6fj0.js";const w=({binding:t,baseUrl:l,onChange:m})=>{const{t:n}=v(),[o,h]=i.useState({}),[x,f]=i.useState(!1),[c,d]=i.useState(""),u=async a=>{f(!0),d("");try{const e=`${l}/${encodeURIComponent(t.serverName)}`,r=a?await N(e):await y(e,{values:o});if(!r.success)throw new Error(r.message||n("credentials.failed"));h({}),d(n(a?"credentials.deleted":"credentials.saved")),await m()}catch(e){d(e instanceof Error?e.message:n("credentials.failed"))}finally{f(!1)}};return s.jsxs("form",{className:"hub-card p-5 space-y-4",onSubmit:a=>{a.preventDefault(),u(!1)},children:[s.jsxs("div",{className:"flex items-center justify-between gap-3",children:[s.jsx("h2",{className:"font-semibold",children:t.serverName}),s.jsx("span",{className:"hub-tag",children:n(t.configured?"credentials.configured":"credentials.required")})]}),s.jsx("p",{className:"text-sm text-[var(--hub-ink-3)]",children:n("credentials.writeOnly")}),t.updatedAt&&s.jsxs("p",{className:"text-xs text-[var(--hub-ink-3)]",children:[n("credentials.updatedAt"),": ",new Date(t.updatedAt).toLocaleString()]}),t.credentialTemplate.map(a=>{var r;const e=`${a.target}.${a.name}`;return s.jsxs("label",{className:"block space-y-1 text-sm",children:[s.jsxs("span",{className:"font-medium",children:[a.label||a.name," ",s.jsxs("span",{className:"hub-mono text-xs font-normal text-[var(--hub-ink-3)]",children:["(",e,")"]})]}),a.target==="url"?s.jsxs("select",{required:!0,className:"hub-input",value:o[e]||"",onChange:p=>h({...o,[e]:p.target.value}),children:[s.jsx("option",{value:"",children:n("credentials.enterValue")}),(r=a.allowed)==null?void 0:r.map(p=>s.jsx("option",{value:p,children:p},p))]}):s.jsx("input",{type:"password",required:!0,autoComplete:"new-password",maxLength:16384,value:o[e]||"",placeholder:n(t.configuredSlots.includes(e)?"credentials.replaceValue":"credentials.enterValue"),className:"hub-input",onChange:p=>h({...o,[e]:p.target.value})})]},e)}),s.jsxs("div",{className:"flex flex-wrap gap-2",children:[s.jsx("button",{type:"submit",className:"hub-btn primary",disabled:x,children:n("credentials.save")}),s.jsx("button",{type:"button",className:"hub-btn danger",disabled:x||!t.updatedAt,onClick:()=>void u(!0),children:n("credentials.delete")})]}),c&&s.jsx("p",{role:"status",className:"text-sm text-[var(--hub-ink-2)]",children:c})]})};function C({baseUrl:t}){const{t:l}=v(),[m,n]=j(),[o,h]=i.useState([]),[x,f]=i.useState(!0),[c,d]=i.useState(""),u=i.useCallback(async()=>{try{const e=await b(t);if(!e.success)throw new Error(e.message||l("credentials.failed"));h(e.data||[]),d("")}catch(e){d(e instanceof Error?e.message:l("credentials.failed"))}finally{f(!1)}},[t,l]);i.useEffect(()=>{u()},[u]);const a=o.filter(e=>!m.get("server")||e.serverName===m.get("server"));return s.jsxs("div",{className:"max-w-4xl mx-auto space-y-5",children:[s.jsxs("div",{children:[s.jsx("h1",{className:"hub-h1",children:l("credentials.title")}),s.jsx("p",{className:"hub-sub",children:l("credentials.description")})]}),m.has("server")&&s.jsx("button",{className:"hub-btn",onClick:()=>n(e=>(e.delete("server"),e)),children:l("credentials.showAll")}),c&&s.jsx("div",{className:"hub-card px-4 py-3 text-sm",style:{color:"var(--hub-err)"},role:"alert",children:c}),x?s.jsx("div",{className:"hub-card p-10 text-center text-sm",style:{color:"var(--hub-ink-3)"},children:l("credentials.loading")}):!a.length&&!c?s.jsx("div",{className:"hub-card p-10 text-center text-sm",style:{color:"var(--hub-ink-3)"},children:l("credentials.empty")}):null,a.map(e=>s.jsx(w,{binding:e,baseUrl:t,onChange:u},e.serverName))]})}function $(){var a;const{t}=v(),{auth:l}=g(),[m,n]=j(),[o,h]=i.useState([]),[x,f]=i.useState(""),c=!!((a=l.user)!=null&&a.isAdmin),d=c&&m.get("user")||"",u=d?`/users/${encodeURIComponent(d)}/credentials`:"/credentials";return i.useEffect(()=>{if(!c)return;let e=!0;return b("/users").then(r=>{if(e){if(!r.success)throw new Error(r.message||t("credentials.failed"));h(r.data||[])}}).catch(r=>{e&&f(r instanceof Error?r.message:t("credentials.failed"))}),()=>{e=!1}},[c,t]),s.jsxs("div",{className:"space-y-5",children:[c&&s.jsxs("div",{className:"max-w-4xl mx-auto",children:[s.jsxs("label",{className:"block space-y-1 text-sm",children:[s.jsx("span",{children:t("credentials.targetUser")}),s.jsxs("select",{className:"hub-input",value:d,onChange:e=>n(r=>(e.target.value?r.set("user",e.target.value):r.delete("user"),r)),children:[s.jsx("option",{value:"",children:t("credentials.myCredentials")}),o.map(e=>s.jsx("option",{value:e.username,children:e.username},e.username))]})]}),x&&s.jsx("p",{role:"alert",children:x})]}),s.jsx(C,{baseUrl:u},u)]})}export{$ as default};
|
|
2
|
-
//# sourceMappingURL=CredentialsPage-BnzqPYjg.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CredentialsPage-BnzqPYjg.js","sources":["../../src/pages/CredentialsPage.tsx"],"sourcesContent":["import { useCallback, useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useSearchParams } from 'react-router-dom';\nimport { useAuth } from '../contexts/AuthContext';\nimport type { User, MyCredentialBinding } from '../types';\nimport { apiDelete, apiGet, apiPut, type ApiResponse } from '../utils/fetchInterceptor';\n\nconst CredentialForm = ({\n binding,\n baseUrl,\n onChange,\n}: {\n binding: MyCredentialBinding;\n baseUrl: string;\n onChange: () => Promise<void>;\n}) => {\n const { t } = useTranslation();\n const [values, setValues] = useState<Record<string, string>>({});\n const [busy, setBusy] = useState(false);\n const [message, setMessage] = useState('');\n const save = async (remove: boolean) => {\n setBusy(true);\n setMessage('');\n try {\n const url = `${baseUrl}/${encodeURIComponent(binding.serverName)}`;\n const result = remove\n ? await apiDelete<ApiResponse>(url)\n : await apiPut<ApiResponse>(url, { values });\n if (!result.success) throw new Error(result.message || t('credentials.failed'));\n setValues({});\n setMessage(t(remove ? 'credentials.deleted' : 'credentials.saved'));\n await onChange();\n } catch (error) {\n setMessage(error instanceof Error ? error.message : t('credentials.failed'));\n } finally {\n setBusy(false);\n }\n };\n return (\n <form\n className=\"hub-card p-5 space-y-4\"\n onSubmit={(event) => {\n event.preventDefault();\n void save(false);\n }}\n >\n <div className=\"flex items-center justify-between gap-3\">\n <h2 className=\"font-semibold\">{binding.serverName}</h2>\n <span className=\"hub-tag\">\n {t(binding.configured ? 'credentials.configured' : 'credentials.required')}\n </span>\n </div>\n <p className=\"text-sm text-[var(--hub-ink-3)]\">{t('credentials.writeOnly')}</p>\n {binding.updatedAt && (\n <p className=\"text-xs text-[var(--hub-ink-3)]\">\n {t('credentials.updatedAt')}: {new Date(binding.updatedAt).toLocaleString()}\n </p>\n )}\n {binding.credentialTemplate.map((slot) => {\n const id = `${slot.target}.${slot.name}`;\n return (\n <label key={id} className=\"block space-y-1 text-sm\">\n <span className=\"font-medium\">\n {slot.label || slot.name}{' '}\n <span className=\"hub-mono text-xs font-normal text-[var(--hub-ink-3)]\">({id})</span>\n </span>\n {slot.target === 'url' ? (\n <select\n required\n className=\"hub-input\"\n value={values[id] || ''}\n onChange={(event) => setValues({ ...values, [id]: event.target.value })}\n >\n <option value=\"\">{t('credentials.enterValue')}</option>\n {slot.allowed?.map((value) => (\n <option key={value} value={value}>\n {value}\n </option>\n ))}\n </select>\n ) : (\n <input\n type=\"password\"\n required\n autoComplete=\"new-password\"\n maxLength={16384}\n value={values[id] || ''}\n placeholder={t(\n binding.configuredSlots.includes(id)\n ? 'credentials.replaceValue'\n : 'credentials.enterValue',\n )}\n className=\"hub-input\"\n onChange={(event) => setValues({ ...values, [id]: event.target.value })}\n />\n )}\n </label>\n );\n })}\n <div className=\"flex flex-wrap gap-2\">\n <button type=\"submit\" className=\"hub-btn primary\" disabled={busy}>\n {t('credentials.save')}\n </button>\n <button\n type=\"button\"\n className=\"hub-btn danger\"\n disabled={busy || !binding.updatedAt}\n onClick={() => void save(true)}\n >\n {t('credentials.delete')}\n </button>\n </div>\n {message && (\n <p role=\"status\" className=\"text-sm text-[var(--hub-ink-2)]\">\n {message}\n </p>\n )}\n </form>\n );\n};\n\nfunction CredentialList({ baseUrl }: { baseUrl: string }) {\n const { t } = useTranslation();\n const [search, setSearch] = useSearchParams();\n const [bindings, setBindings] = useState<MyCredentialBinding[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState('');\n const reload = useCallback(async () => {\n try {\n const result = await apiGet<ApiResponse<MyCredentialBinding[]>>(baseUrl);\n if (!result.success) throw new Error(result.message || t('credentials.failed'));\n setBindings(result.data || []);\n setError('');\n } catch (error) {\n setError(error instanceof Error ? error.message : t('credentials.failed'));\n } finally {\n setLoading(false);\n }\n }, [baseUrl, t]);\n useEffect(() => {\n void reload();\n }, [reload]);\n const visible = bindings.filter(\n (binding) => !search.get('server') || binding.serverName === search.get('server'),\n );\n return (\n <div className=\"max-w-4xl mx-auto space-y-5\">\n <div>\n <h1 className=\"hub-h1\">{t('credentials.title')}</h1>\n <p className=\"hub-sub\">{t('credentials.description')}</p>\n </div>\n {search.has('server') && (\n <button\n className=\"hub-btn\"\n onClick={() =>\n setSearch((params) => {\n params.delete('server');\n return params;\n })\n }\n >\n {t('credentials.showAll')}\n </button>\n )}\n {error && (\n <div\n className=\"hub-card px-4 py-3 text-sm\"\n style={{ color: 'var(--hub-err)' }}\n role=\"alert\"\n >\n {error}\n </div>\n )}\n {loading ? (\n <div className=\"hub-card p-10 text-center text-sm\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('credentials.loading')}\n </div>\n ) : !visible.length && !error ? (\n <div className=\"hub-card p-10 text-center text-sm\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('credentials.empty')}\n </div>\n ) : null}\n {visible.map((binding) => (\n <CredentialForm\n key={binding.serverName}\n binding={binding}\n baseUrl={baseUrl}\n onChange={reload}\n />\n ))}\n </div>\n );\n}\n\nexport default function CredentialsPage() {\n const { t } = useTranslation();\n const { auth } = useAuth();\n const [search, setSearch] = useSearchParams();\n const [users, setUsers] = useState<User[]>([]);\n const [error, setError] = useState('');\n const admin = Boolean(auth.user?.isAdmin);\n const username = admin ? search.get('user') || '' : '';\n const baseUrl = username ? `/users/${encodeURIComponent(username)}/credentials` : '/credentials';\n useEffect(() => {\n if (!admin) return;\n let active = true;\n void apiGet<ApiResponse<User[]>>('/users')\n .then((result) => {\n if (!active) return;\n if (!result.success) throw new Error(result.message || t('credentials.failed'));\n setUsers(result.data || []);\n })\n .catch((error: unknown) => {\n if (active) setError(error instanceof Error ? error.message : t('credentials.failed'));\n });\n return () => {\n active = false;\n };\n }, [admin, t]);\n return (\n <div className=\"space-y-5\">\n {admin && (\n <div className=\"max-w-4xl mx-auto\">\n <label className=\"block space-y-1 text-sm\">\n <span>{t('credentials.targetUser')}</span>\n <select\n className=\"hub-input\"\n value={username}\n onChange={(event) =>\n setSearch((params) => {\n if (event.target.value) params.set('user', event.target.value);\n else params.delete('user');\n return params;\n })\n }\n >\n <option value=\"\">{t('credentials.myCredentials')}</option>\n {users.map((user) => (\n <option key={user.username} value={user.username}>\n {user.username}\n </option>\n ))}\n </select>\n </label>\n {error && <p role=\"alert\">{error}</p>}\n </div>\n )}\n <CredentialList key={baseUrl} baseUrl={baseUrl} />\n </div>\n );\n}\n"],"names":["CredentialForm","binding","baseUrl","onChange","t","useTranslation","values","setValues","useState","busy","setBusy","message","setMessage","save","remove","url","result","apiDelete","apiPut","error","jsxs","event","jsx","slot","id","_a","value","CredentialList","search","setSearch","useSearchParams","bindings","setBindings","loading","setLoading","setError","reload","useCallback","apiGet","useEffect","visible","params","CredentialsPage","auth","useAuth","users","setUsers","admin","username","active","user"],"mappings":"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"}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import{r as f,j as e,R as M}from"./framework-vendor-CQFm9vKd.js";import{o as Z,h as fe,e as ee,a as ve,k as je,l as se}from"./index-CkSmxNPW.js";import{u as te,a as re}from"./useCostData-C3XnQyUj.js";import{u as G}from"./i18n-vendor-DVmjrzgW.js";import{u as me,c as ye}from"./clipboard-2RRFM-q8.js";import{f as H,p as Ne}from"./contextCost-CilWqGWT.js";import{g as ke,A as Se,C as we,s as Ce}from"./costRevision-Ntl7VtWo.js";import{W as Ae,g as Te,F as Ee,H as De,C as Ie,r as Q,J as oe,z as Fe,w as ze,T as Pe,n as Re,D as ce,N as Le,P as de,l as Ue,X as $e}from"./icons-vendor-CyAS6fj0.js";import{D as Oe}from"./DeleteDialog-BaCsEkJA.js";const Ge=["read","create","update","delete","other"],We=a=>{var s,l,h;if(((s=a.annotations)==null?void 0:s.readOnlyHint)===!0)return"read";const m=a.value.toLowerCase();return/^(delete|remove)[_-]/.test(m)?"delete":((l=a.annotations)==null?void 0:l.destructiveHint)===!0?"other":/^(create|add)[_-]/.test(m)?"create":/^(update|set)[_-]/.test(m)?"update":((h=a.annotations)==null?void 0:h.readOnlyHint)!==!1&&/^(get|list|read|search)[_-]/.test(m)?"read":"other"},Me=(a,m,s)=>{const l=m.trim().toLowerCase();return a.filter(h=>{var i,p;return(h.value.toLowerCase().includes(l)||((i=h.description)==null?void 0:i.toLowerCase().includes(l)))&&(s==="all"||((p=h.annotations)==null?void 0:p[s])===!0)})},He=(a,m,s,l)=>{if(s.length===0||a==="all"&&l==="select")return a;const h=new Set(a==="all"?m:a);for(const i of s)l==="deselect"||l==="invert"&&h.has(i)?h.delete(i):h.add(i);return[...h]},_e=({items:a,selection:m,tools:s,label:l,onChange:h,children:i})=>{const{t:p}=G(),[E,I]=f.useState(""),[N,A]=f.useState("all"),[x,j]=f.useState(!1),S=Me(a,E,N),T=new Set(m==="all"?a.map(t=>t.value):m),u=(t,c)=>h(He(m,a.map(o=>o.value),t.map(o=>o.value),c)),b=s&&x?Ge.map(t=>({risk:t,items:S.filter(c=>We(c)===t)})):[{risk:null,items:S}],v="text-xs text-blue-600 hover:text-blue-800 disabled:opacity-40 disabled:cursor-not-allowed";return e.jsxs("section",{"aria-label":l,children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2 mb-2",children:[e.jsx("input",{type:"search","aria-label":p("groups.bulkSearchLabel",{capability:l}),placeholder:p("groups.bulkSearch"),value:E,onChange:t=>I(t.target.value),className:"min-w-0 flex-1 basis-48 rounded border border-gray-300 bg-white dark:bg-gray-800 px-2 py-1 text-sm"}),s&&e.jsxs(e.Fragment,{children:[e.jsxs("select",{"aria-label":p("groups.annotationFilter"),value:N,onChange:t=>A(t.target.value),className:"max-w-full rounded border border-gray-300 bg-white dark:bg-gray-800 px-2 py-1 text-sm",children:[e.jsx("option",{value:"all",children:p("groups.allAnnotations")}),["readOnlyHint","destructiveHint","idempotentHint"].map(t=>e.jsx("option",{value:t,children:p(`groups.${t}`)},t))]}),e.jsx("button",{type:"button","aria-pressed":x,onClick:()=>j(!x),className:v,children:p(x?"groups.flatList":"groups.riskGroups")})]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-x-3 gap-y-1 mb-2",children:[e.jsx("span",{className:"text-xs text-gray-500",role:"status",children:p("groups.visibleCount",{count:S.length,total:a.length})}),["select","deselect","invert"].map(t=>e.jsx("button",{type:"button",disabled:!S.length,onClick:()=>u(S,t),className:v,children:p(`groups.${t}Visible`)},t))]}),s&&x&&e.jsx("p",{className:"text-xs text-gray-500 mb-2",children:p("groups.riskHint")}),e.jsxs("div",{className:"grid grid-cols-1 gap-2 max-h-96 overflow-y-auto",children:[S.length===0&&e.jsx("p",{className:"text-sm text-gray-500",children:p("groups.noMatchingItems")}),b.filter(t=>t.items.length>0).map(t=>{const c=t.items.filter(o=>T.has(o.value)).length;return e.jsxs(M.Fragment,{children:[t.risk&&e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2 border-b border-gray-200 py-1",children:[e.jsxs("span",{className:"text-xs font-medium",children:[p(`groups.risk_${t.risk}`)," (",c,"/",t.items.length,")"]}),e.jsx("button",{type:"button",className:v,onClick:()=>u(t.items,c===t.items.length?"deselect":"select"),children:p(c===t.items.length?"groups.selectNone":"groups.selectAll")})]}),t.items.map(o=>e.jsx(M.Fragment,{children:i(o)},o.value))]},t.risk??"flat")})]})]})},Be={tools:[],prompts:[],resources:[]},ue={tools:"all",prompts:"all",resources:"all"},pe=({servers:a,value:m,onChange:s,className:l,serverCosts:h=[]})=>{const{t:i}=G(),p=M.useId(),{nameSeparator:E,smartRoutingConfig:I}=me(),[N,A]=f.useState(new Set),x=M.useMemo(()=>m.map(r=>typeof r=="string"?{name:r,...ue}:{...r,tools:r.tools||"all",prompts:r.prompts||"all",resources:r.resources||"all"}),[m]),j=M.useMemo(()=>a.filter(r=>r.enabled!==!1),[a]);M.useEffect(()=>{const r=new Set(x.map(n=>n.name)),d=new Set(j.map(n=>n.name));A(n=>{const w=new Set;return n.forEach(g=>{(r.has(g)||d.has(g))&&w.add(g)}),w})},[x,j]);const S=r=>{if(x.findIndex(n=>n.name===r)>=0){const n=x.filter(w=>w.name!==r);s(n)}else{const n=[...x,{name:r,...ue}];s(n)}},T=r=>{A(d=>{const n=new Set(d);return n.has(r)?n.delete(r):n.add(r),n})},u=r=>["tools","prompts","resources"].some(d=>{const n=r[d];return n==="all"||Array.isArray(n)&&n.length>0}),b=(r,d,n,w=!1)=>{const g=x.find(k=>k.name===r),F={...g?{...g}:{name:r,...Be},[d]:n};if(d==="tools"&&Array.isArray(n)&&F.pinnedTools&&(F.pinnedTools=F.pinnedTools.filter(k=>n.includes(k)),F.pinnedTools.length===0&&delete F.pinnedTools),!u(F)){const k=x.filter(y=>y.name!==r);s(k),w||A(y=>{const $=new Set(y);return $.delete(r),$});return}if(g){s(x.map(k=>k.name===r?F:k));return}s([...x,F])},v=(r,d)=>{const n=x.find(g=>g.name===r);if(!n)return;const w={...n};d?w.alias=d:delete w.alias,s(x.map(g=>g.name===r?w:g))},t=(r,d)=>{const n=x.find(z=>z.name===r);if(!n)return;const w=n.pinnedTools??[],g={...n,pinnedTools:w.includes(d)?w.filter(z=>z!==d):[...w,d]};g.pinnedTools.length===0&&delete g.pinnedTools,s(x.map(z=>z.name===r?g:z))},c=(r,d)=>{const n=`${r}${E}`;return d.startsWith(n)?d.slice(n.length):d},o=(r,d)=>d==="tools"?(r.tools||[]).filter(n=>n.enabled!==!1).map(n=>({key:n.name,value:c(r.name,n.name),description:n.description,annotations:n.annotations,defaultDescription:n.defaultDescription,hasDescriptionOverride:n.hasDescriptionOverride})):d==="prompts"?(r.prompts||[]).filter(n=>n.enabled!==!1).map(n=>({key:n.name,value:c(r.name,n.name),description:n.description})):(r.resources||[]).filter(n=>n.enabled!==!1).map(n=>({key:n.uri,value:n.uri,description:n.description})),C=M.useMemo(()=>{const r=new Map;return h.forEach(d=>{const n=new Map;d.items.forEach(w=>n.set(w.name,w.cost)),r.set(d.name,n)}),r},[h]),L=r=>C.get(r)??new Map,O=(r,d)=>{const n=L(r.name);return o(r,d).filter(w=>J(r.name,d,w.value)).reduce((w,g)=>w+(n.get(g.key)??0),0)},_=r=>["tools","prompts","resources"].reduce((d,n)=>d+O(r,n),0),X=(r,d,n)=>{const w=j.find(k=>k.name===r);if(!w)return;const g=o(w,d).map(k=>k.value),z=x.find(k=>k.name===r);if(!z){b(r,d,[n]);return}const F=z[d];if(F==="all"){const k=g.filter(y=>y!==n);b(r,d,k);return}if(Array.isArray(F)){if(F.includes(n)){b(r,d,F.filter(y=>y!==n));return}const k=[...F,n];b(r,d,k.length===g.length?"all":k);return}b(r,d,[n])},W=r=>{const d=x.find(n=>n.name===r);return!!(d&&u(d))},K=r=>{const d=x.find(n=>n.name===r);return d?["tools","prompts","resources"].some(n=>{const w=d[n];return Array.isArray(w)&&w.length>0}):!1},J=(r,d,n)=>{const w=x.find(z=>z.name===r);if(!w)return!1;const g=w[d];return g==="all"?!0:Array.isArray(g)?g.includes(n):!1},B=(r,d)=>{const n=x.find(z=>z.name===r.name);if(!n)return 0;const w=o(r,d),g=n[d];if(g==="all")return w.length;if(Array.isArray(g)){const z=new Set(w.map(F=>F.value));return g.filter(F=>z.has(F)).length}return 0},D=[{key:"tools",titleKey:"groups.toolSelection",countKey:"groups.toolsSelected",allKey:"groups.allTools"},{key:"prompts",titleKey:"groups.promptSelection",countKey:"groups.promptsSelected",allKey:"groups.allPrompts"},{key:"resources",titleKey:"groups.resourceSelection",countKey:"groups.resourcesSelected",allKey:"groups.allResources"}],P=r=>D.map(({key:d})=>({key:d,count:B(r,d)})).filter(d=>d.count>0);return e.jsxs("div",{className:Z("space-y-4",l),children:[e.jsx("div",{className:"space-y-3",children:j.map(r=>{const d=W(r.name),n=K(r.name),w=N.has(r.name),g=x.find(y=>y.name===r.name),z=P(r),F=D.filter(({key:y})=>o(r,y).length>0),k=L(r.name);return e.jsxs("div",{className:"border border-[var(--hub-line)] rounded-lg bg-[var(--hub-surface)] hover:border-[var(--hub-ink-3)] hover:bg-[var(--hub-surface-hover)] transition-colors",children:[e.jsxs("div",{className:"flex items-center justify-between p-3 cursor-pointer rounded-lg transition-colors",onClick:()=>T(r.name),children:[e.jsxs("div",{className:"flex items-center space-x-3",onClick:y=>{y.stopPropagation(),S(r.name)},children:[e.jsx("input",{type:"checkbox",checked:d||n,onChange:()=>S(r.name),className:"w-4 h-4 text-blue-600 accent-[var(--hub-accent)] rounded focus:ring-blue-500"}),e.jsx("span",{className:"font-medium text-[var(--hub-ink)] cursor-pointer select-none",children:r.name})]}),e.jsxs("div",{className:"flex items-center space-x-3",children:[_(r)>0&&e.jsxs("span",{className:"text-sm text-[var(--hub-ink-3)] hub-mono",title:i("cost.estimate"),children:["Σ ",H(_(r))]}),z.map(({key:y,count:$})=>e.jsxs("span",{className:"text-sm text-green-600 flex items-center gap-1",children:[y==="tools"?e.jsx(Ae,{size:14}):y==="prompts"?e.jsx(Te,{size:14}):e.jsx(Ee,{size:14})," ",$]},y)),F.length>0&&e.jsx("button",{type:"button",className:"p-1 text-[var(--hub-ink-3)] hover:text-[var(--hub-ink-2)] transition-colors",children:e.jsx("svg",{className:Z("w-5 h-5 transition-transform",w&&"rotate-180"),fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})})]})]}),w&&F.length>0&&e.jsx("div",{className:"border-t border-[var(--hub-line)] bg-[var(--hub-bg-2)] p-3",children:e.jsxs("div",{className:"space-y-4",children:[g&&e.jsxs("div",{className:"space-y-1",onClick:y=>y.stopPropagation(),children:[e.jsx("label",{htmlFor:`${p}-${r.name}`,className:"block text-xs font-medium text-[var(--hub-ink-2)]",children:i("groups.alias")}),e.jsx("input",{type:"text",id:`${p}-${r.name}`,value:g.alias||"",placeholder:r.name,onChange:y=>v(r.name,y.target.value),className:"hub-input"}),e.jsxs("label",{className:"flex items-center gap-2 text-xs text-[var(--hub-ink-2)]",children:[e.jsx("input",{type:"checkbox",checked:g.preserveToolNames===!0,onChange:y=>s(x.map($=>$.name===r.name?{...$,preserveToolNames:y.target.checked}:$))}),i("groups.preserveToolNames")]}),e.jsx("p",{className:"text-xs text-[var(--hub-ink-3)]",children:i("groups.preserveToolNamesHint")})]}),F.map(({key:y,titleKey:$,countKey:be,allKey:ge})=>{const V=o(r,y),ae=B(r,y),Y=(g==null?void 0:g[y])==="all"||ae===V.length;return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsx("span",{className:"text-sm font-medium text-[var(--hub-ink-2)]",children:i($)}),e.jsxs("div",{className:"flex items-center gap-3",children:[g&&e.jsx("span",{className:"text-xs text-green-600",children:Y?`(${i(ge)} ${V.length}/${V.length})`:`(${i(be)} ${ae}/${V.length})`}),g&&O(r,y)>0&&e.jsxs("span",{className:"text-xs text-[var(--hub-ink-3)] hub-mono",title:i("cost.estimate"),children:["Σ ",H(O(r,y))]}),e.jsx("button",{type:"button",onClick:()=>{b(r.name,y,Y?[]:"all",!0)},className:"text-sm text-blue-600 hover:text-blue-800 transition-colors",children:i(Y?"groups.selectNone":"groups.selectAll")})]})]}),e.jsx(_e,{items:V,selection:(g==null?void 0:g[y])??[],tools:y==="tools",label:i($),onChange:R=>b(r.name,y,R,!0),children:R=>{var ie;const ne=J(r.name,y,R.value),q=!!((ie=g==null?void 0:g.pinnedTools)!=null&&ie.includes(R.value)),U=y==="tools"?ke({description:R.description,defaultDescription:R.defaultDescription,hasDescriptionOverride:R.hasDescriptionOverride},i("tool.noDescription")):null,le=U!=null&&U.hasDescriptionOverride?i("tool.defaultDescriptionTooltip",{description:U.defaultDescription}):R.description;return e.jsxs("div",{className:"flex min-w-0 items-center gap-2",children:[e.jsxs("label",{className:"flex min-w-0 flex-1 items-center gap-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:ne,onChange:()=>X(r.name,y,R.value),className:"w-3 h-3 text-blue-600 accent-[var(--hub-accent)] rounded focus:ring-blue-500"}),e.jsx("span",{className:"text-[var(--hub-ink-2)] break-all whitespace-nowrap flex-shrink-0",children:R.value}),(R.description||(U==null?void 0:U.hasDescriptionOverride))&&e.jsxs("span",{className:"min-w-0 flex items-center gap-1 text-[var(--hub-ink-3)] text-xs truncate",children:[e.jsx("span",{className:"truncate",title:le||void 0,children:U?U.currentDescription:R.description}),(U==null?void 0:U.hasDescriptionOverride)&&e.jsx("span",{className:"inline-flex flex-shrink-0 items-center rounded-full border border-amber-200 bg-amber-50 px-1.5 py-0.5 text-[10px] font-medium text-amber-700 dark:border-amber-700/60 dark:bg-amber-900/20 dark:text-amber-300",title:le||void 0,children:i("tool.descriptionModifiedBadge")})]}),k.get(R.key)!=null&&e.jsxs("span",{className:"text-xs text-[var(--hub-ink-3)] hub-mono whitespace-nowrap ml-auto flex-shrink-0",title:i("cost.estimate"),children:["Σ ",H(k.get(R.key))]})]}),y==="tools"&&ne&&(I.enabled||q)&&e.jsx("button",{type:"button",onClick:()=>t(r.name,R.value),title:i(q?"groups.unpinTool":"groups.pinTool"),"aria-label":i("groups.pinToolLabel"),"aria-pressed":q,className:Z("flex-shrink-0 transition-colors",q?"text-blue-600":"text-[var(--hub-ink-3)] hover:text-[var(--hub-ink-2)]"),children:e.jsx(De,{size:12,fill:q?"currentColor":"none"})})]},R.key)}})]},y)})]})})]},r.name)})}),j.length===0&&e.jsx("p",{className:"text-[var(--hub-ink-3)] text-sm",children:i("groups.noServerOptions")})]})};function xe({groupId:a,value:m,onChange:s}){const{t:l}=G(),[h,i]=f.useState([]),[p,E]=f.useState(""),[I,N]=f.useState(!1),[A,x]=f.useState(!1),[j,S]=f.useState(!1);f.useEffect(()=>{if(!a||m.visibility!=="group")return;let o=!1;return N(!0),x(!1),fe(`/groups/${encodeURIComponent(a)}/share-candidates`).then(C=>{o||(C.success&&Array.isArray(C.data)?i(C.data):x(!0))}).catch(()=>{o||x(!0)}).finally(()=>{o||N(!1)}),()=>{o=!0}},[a,m.visibility]);const T=m.sharedWithUsers||[],u=[...new Set([...h,...T])].sort().filter(o=>o.toLowerCase().includes(p.toLowerCase())),b=new Set(T),v=u.length>0&&u.every(o=>b.has(o)),t=u.length===0||u.every(o=>!b.has(o)),c=o=>{const C=new Set(T);C.has(o)?C.delete(o):C.add(o),s({sharedWithUsers:Array.from(C)})};return e.jsxs("div",{className:"mb-4",children:[e.jsxs("div",{className:"flex items-center justify-between cursor-pointer bg-[var(--hub-bg-2)] hover:bg-[var(--hub-surface-hover)] p-3 rounded border border-[var(--hub-line)]",onClick:()=>S(!j),children:[e.jsx("h3",{className:"text-sm font-semibold text-[var(--hub-ink)]",children:l("server.sectionAdvanced","Advanced Options")}),e.jsx("span",{className:"text-[var(--hub-ink-3)] text-sm",children:j?"▼":"▶"})]}),j&&e.jsxs("div",{className:"border border-[var(--hub-line)] rounded-b p-4 bg-[var(--hub-surface)] border-t-0",children:[e.jsx("label",{htmlFor:"group-visibility",className:"block text-sm font-medium mb-1.5 text-[var(--hub-ink-2)]",children:l("server.visibility")}),e.jsxs("select",{id:"group-visibility",className:"hub-input",value:m.visibility||"",onChange:o=>s({visibility:o.target.value}),children:[!m.visibility&&e.jsx("option",{value:"",disabled:!0,children:l("groups.legacyVisibility")}),e.jsx("option",{value:"private",children:l("server.visibilityPrivate")}),e.jsx("option",{value:"group",children:l("server.visibilityGroup")}),e.jsx("option",{value:"public",children:l("server.visibilityPublic")})]}),e.jsx("p",{className:"text-xs text-[var(--hub-ink-3)] mt-1",children:l("groups.visibilityDescription")}),!m.visibility&&e.jsx("p",{className:"text-sm text-amber-600",children:l("groups.legacyVisibilityHint")}),m.visibility==="group"&&e.jsxs("div",{className:"mt-4 rounded border border-[var(--hub-line)] p-3",children:[e.jsx("div",{className:"text-sm font-medium text-[var(--hub-ink-2)]",children:l("server.shareWithUsers")}),e.jsx("p",{className:"text-xs text-[var(--hub-ink-3)] mt-1 mb-3",children:l("server.shareWithUsersDescription")}),a?e.jsxs(e.Fragment,{children:[I&&e.jsx("p",{className:"text-sm text-[var(--hub-ink-3)]",children:l("server.shareCandidatesLoading")}),A&&e.jsx("p",{role:"alert",className:"text-sm text-red-600 dark:text-red-400",children:l("server.shareCandidatesError")}),!I&&!A&&u.length===0&&e.jsx("p",{className:"text-sm text-[var(--hub-ink-3)]",children:l(p?"server.noMatchingShareUsers":"server.noShareCandidates")}),u.length>0&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"mb-3 space-y-2",children:[e.jsx("label",{htmlFor:"group-share-search",className:"block text-xs font-medium text-[var(--hub-ink-2)]",children:l("server.shareUserSearchLabel")}),e.jsx("input",{id:"group-share-search",type:"search",value:p,onChange:o=>E(o.target.value),placeholder:l("server.shareUserSearchPlaceholder"),className:"hub-input text-sm"}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx("button",{type:"button",onClick:()=>s({sharedWithUsers:[...new Set([...T,...u])]}),disabled:v,className:"hub-btn text-sm",children:l("server.selectAllShareUsers")}),e.jsx("button",{type:"button",onClick:()=>s({sharedWithUsers:T.filter(o=>!u.includes(o))}),disabled:t,className:"hub-btn text-sm",children:l("server.deselectAllShareUsers")})]})]}),e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-2",children:u.map(o=>e.jsxs("label",{className:"flex items-center gap-2 rounded border border-[var(--hub-line)] px-3 py-2 text-sm text-[var(--hub-ink-2)]",children:[e.jsx("input",{type:"checkbox",checked:b.has(o),onChange:()=>c(o)}),e.jsx("span",{children:o})]},o))})]})]}):e.jsx("p",{className:"text-sm text-[var(--hub-ink-3)]",children:l("groups.shareAfterCreate")})]})]})]})}const Ve=({onAdd:a,onCancel:m})=>{const{t:s}=G(),{createGroup:l}=ee(),{allServers:h}=te(),{serverCosts:i}=re(),[p,E]=f.useState([]),[I,N]=f.useState(null),[A,x]=f.useState(!1),[j,S]=f.useState({visibility:"private",sharedWithUsers:[],name:"",description:"",instructions:"",servers:[]});f.useEffect(()=>{E(h.filter(b=>b.enabled!==!1))},[h]);const T=b=>{const{name:v,value:t}=b.target;S(c=>({...c,[v]:t}))},u=async b=>{b.preventDefault(),x(!0),N(null);try{if(!j.name.trim()){N(s("groups.nameRequired")),x(!1);return}const v=await l(j.name,j.description,j.servers,{visibility:j.visibility,sharedWithUsers:j.sharedWithUsers,instructions:j.instructions});if(!v||!v.success){N((v==null?void 0:v.message)||s("groups.createError")),x(!1);return}a()}catch(v){N(v instanceof Error?v.message:String(v)),x(!1)}};return e.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:e.jsxs("div",{className:"hub-card shadow-lg max-w-3xl w-full max-h-[90vh] flex flex-col",children:[e.jsxs("div",{className:"p-6 flex-shrink-0",children:[e.jsx("h2",{className:"text-xl font-semibold text-[var(--hub-ink)] mb-4",children:s("groups.addNew")}),I&&e.jsx("div",{className:"mb-4 p-3 bg-red-100 text-red-700 rounded-md border border-[var(--hub-line)]",children:I})]}),e.jsxs("form",{onSubmit:u,className:"flex flex-col flex-1 min-h-0",children:[e.jsx("div",{className:"flex-1 overflow-y-auto px-6",children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsxs("label",{className:"block text-[var(--hub-ink-2)] text-sm font-bold mb-2",htmlFor:"name",children:[s("groups.name")," *"]}),e.jsx("input",{type:"text",id:"name",name:"name",value:j.name,onChange:T,className:"w-full border border-[var(--hub-line)] bg-[var(--hub-surface)] rounded-md px-3 py-2 text-[var(--hub-ink)] placeholder:text-[var(--hub-ink-3)] focus:outline-none focus:border-[var(--hub-ink-2)]",placeholder:s("groups.namePlaceholder"),required:!0})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[var(--hub-ink-2)] text-sm font-bold mb-2",htmlFor:"instructions",children:s("groups.instructions")}),e.jsx("textarea",{id:"instructions",name:"instructions",value:j.instructions,onChange:T,rows:3,className:"w-full border border-[var(--hub-line)] bg-[var(--hub-surface)] rounded-md px-3 py-2 text-[var(--hub-ink)] placeholder:text-[var(--hub-ink-3)] focus:outline-none focus:border-[var(--hub-ink-2)]",placeholder:s("groups.instructionsPlaceholder")}),e.jsx("p",{className:"text-xs text-[var(--hub-ink-3)] mt-1",children:s("groups.instructionsHelp")})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[var(--hub-ink-2)] text-sm font-bold mb-2",children:s("groups.configureCapabilities")}),e.jsx(pe,{servers:p,value:j.servers,onChange:b=>S(v=>({...v,servers:b})),className:"border border-[var(--hub-line)] rounded-lg p-4 bg-[var(--hub-bg-2)]",serverCosts:i})]}),e.jsx(xe,{value:j,onChange:b=>S(v=>({...v,...b}))})]})}),e.jsxs("div",{className:"flex justify-end space-x-2 p-5 pt-3 border-t border-[var(--hub-line-2)] flex-shrink-0",children:[e.jsx("button",{type:"button",onClick:m,className:"hub-btn",disabled:A,children:s("common.cancel")}),e.jsx("button",{type:"submit",className:"hub-btn primary",disabled:A,children:s(A?"common.submitting":"common.create")})]})]})]})})},qe=({group:a,onEdit:m,onCancel:s})=>{const{t:l}=G(),{updateGroup:h}=ee(),{allServers:i}=te(),{serverCosts:p}=re(),[E,I]=f.useState([]),[N,A]=f.useState(null),[x,j]=f.useState(!1),[S,T]=f.useState({visibility:a.visibility,sharedWithUsers:a.sharedWithUsers||[],name:a.name,description:a.description||"",instructions:a.instructions||"",servers:a.servers||[]});f.useEffect(()=>{I(i.filter(v=>v.enabled!==!1))},[i]);const u=v=>{const{name:t,value:c}=v.target;T(o=>({...o,[t]:c}))},b=async v=>{v.preventDefault(),j(!0),A(null);try{if(!S.name.trim()){A(l("groups.nameRequired")),j(!1);return}const t=await h(a.id,{visibility:S.visibility,sharedWithUsers:S.sharedWithUsers,name:S.name,description:S.description,instructions:S.instructions,servers:S.servers});if(!t||!t.success){A((t==null?void 0:t.message)||l("groups.updateError")),j(!1);return}m()}catch(t){A(t instanceof Error?t.message:String(t)),j(!1)}};return e.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:e.jsxs("div",{className:"hub-card shadow-lg max-w-3xl w-full max-h-[90vh] flex flex-col",children:[e.jsxs("div",{className:"p-6 flex-shrink-0",children:[e.jsx("h2",{className:"text-xl font-semibold text-[var(--hub-ink)] mb-4",children:l("groups.edit")}),N&&e.jsx("div",{className:"mb-4 p-3 bg-red-100 text-red-700 rounded-md border border-[var(--hub-line)]",children:N})]}),e.jsxs("form",{onSubmit:b,className:"flex flex-col flex-1 min-h-0",children:[e.jsx("div",{className:"flex-1 overflow-y-auto px-6",children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsxs("label",{className:"block text-[var(--hub-ink-2)] text-sm font-bold mb-2",htmlFor:"name",children:[l("groups.name")," *"]}),e.jsx("input",{type:"text",id:"name",name:"name",value:S.name,onChange:u,className:"w-full border border-[var(--hub-line)] bg-[var(--hub-surface)] rounded-md px-3 py-2 text-[var(--hub-ink)] placeholder:text-[var(--hub-ink-3)] focus:outline-none focus:border-[var(--hub-ink-2)]",placeholder:l("groups.namePlaceholder"),required:!0})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[var(--hub-ink-2)] text-sm font-bold mb-2",htmlFor:"instructions",children:l("groups.instructions")}),e.jsx("textarea",{id:"instructions",name:"instructions",value:S.instructions,onChange:u,rows:3,className:"w-full border border-[var(--hub-line)] bg-[var(--hub-surface)] rounded-md px-3 py-2 text-[var(--hub-ink)] placeholder:text-[var(--hub-ink-3)] focus:outline-none focus:border-[var(--hub-ink-2)]",placeholder:l("groups.instructionsPlaceholder")}),e.jsx("p",{className:"text-xs text-[var(--hub-ink-3)] mt-1",children:l("groups.instructionsHelp")})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[var(--hub-ink-2)] text-sm font-bold mb-2",children:l("groups.configureCapabilities")}),e.jsx(pe,{servers:E,value:S.servers,onChange:v=>T(t=>({...t,servers:v})),className:"border border-[var(--hub-line)] rounded-lg p-4 bg-[var(--hub-bg-2)]",serverCosts:p})]}),e.jsx(xe,{groupId:a.id,value:S,onChange:v=>T(t=>({...t,...v}))})]})}),e.jsxs("div",{className:"flex justify-end space-x-2 p-5 pt-3 border-t border-[var(--hub-line-2)] flex-shrink-0",children:[e.jsx("button",{type:"button",onClick:s,className:"hub-btn",disabled:x,children:l("common.cancel")}),e.jsx("button",{type:"submit",className:"hub-btn primary",disabled:x,children:l(x?"common.submitting":"common.save")})]})]})]})})},Ke=a=>a.map(m=>typeof m=="string"?m:m.name),he=(a,m)=>{const s=a.servers.find(l=>typeof l=="string"?l===m:l.name===m);return s?typeof s=="string"?{name:s,tools:"all",prompts:"all",resources:"all"}:s:{name:m,tools:"all",prompts:"all",resources:"all"}},Je=(a,m)=>{var l;return((l=he(a,m).alias)==null?void 0:l.trim())||m},Qe=({group:a,servers:m,onEdit:s,onDelete:l,cost:h})=>{var B;const{t:i}=G(),{auth:p}=ve(),E=!!p.user&&(p.user.isAdmin||p.user.username===a.owner),{showToast:I}=je(),{installConfig:N,nameSeparator:A}=me(),x=((B=N==null?void 0:N.baseUrl)==null?void 0:B.replace(/\/+$/,""))||"",[j,S]=f.useState(!1),[T,u]=f.useState(null),[b,v]=f.useState(!1),[t,c]=f.useState(!1),o=f.useRef(null);f.useEffect(()=>{const D=P=>{o.current&&!o.current.contains(P.target)&&c(!1)};return document.addEventListener("mousedown",D),()=>document.removeEventListener("mousedown",D)},[]);const C=async D=>{await ye(D)?(v(!0),c(!1),I(i("common.copySuccess")||"Copied","success"),setTimeout(()=>v(!1),1500)):I(i("common.copyFailed")||"Copy failed","error")},L=`${x}/mcp/${a.name}`,O=`${x}/mcp/${encodeURIComponent(a.name)}`,_=`${x}/api/${a.name}`,X=Ke(a.servers),W=m.filter(D=>X.includes(D.name)),K=D=>{const P=he(a,D.name),r=`${D.name}${A}`,d=D.tools||[],n=D.prompts||[],w=D.resources||[],g=Array.isArray(P.tools)?d.filter(k=>{if(k.enabled===!1)return!1;const y=k.name.startsWith(r)?k.name.slice(r.length):k.name;return P.tools.includes(y)}).length:d.filter(k=>k.enabled!==!1).length,z=Array.isArray(P.prompts)?n.filter(k=>{if(k.enabled===!1)return!1;const y=k.name.startsWith(r)?k.name.slice(r.length):k.name;return P.prompts.includes(y)}).length:n.filter(k=>k.enabled!==!1).length,F=Array.isArray(P.resources)?w.filter(k=>k.enabled!==!1&&P.resources.includes(k.uri)).length:w.filter(k=>k.enabled!==!1).length;return{visibleTools:g,totalTools:d.length,visiblePrompts:z,totalPrompts:n.length,visibleResources:F,totalResources:w.length}},J=W.reduce((D,P)=>D+K(P).visibleTools,0);return e.jsxs("div",{className:"hub-card flex h-full flex-col overflow-visible",children:[e.jsxs("div",{className:"flex items-start gap-3 px-4 py-3",style:{borderBottom:"1px solid var(--hub-line-2)"},children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{style:{fontSize:15,fontWeight:600,letterSpacing:"-0.015em"},children:a.name}),e.jsx("span",{className:"hub-mono",style:{fontSize:11,color:"var(--hub-ink-3)",padding:"0 6px",border:"1px solid var(--hub-line)",borderRadius:4,height:18,display:"inline-flex",alignItems:"center"},title:a.id,children:a.id})]}),e.jsx("div",{className:"mt-1 text-xs text-[var(--hub-ink-3)]",children:a.visibility?i(`server.visibility${a.visibility==="group"?"Group":a.visibility==="public"?"Public":"Private"}`):i("groups.legacyVisibility")}),a.description&&e.jsx("div",{style:{fontSize:12.5,color:"var(--hub-ink-3)",marginTop:2},children:a.description})]}),e.jsxs("div",{className:"flex items-center gap-1",ref:o,children:[e.jsxs("div",{className:"relative",children:[e.jsx("button",{onClick:()=>c(D=>!D),className:"hub-icon-btn sm",title:i("common.copy"),children:b?e.jsx(Ie,{size:13,className:"text-[var(--hub-ok)]"}):e.jsx(Q,{size:13})}),t&&e.jsxs("div",{className:"absolute top-full right-0 mt-1 z-20 hub-card",style:{minWidth:160,padding:4},children:[e.jsxs("button",{onClick:()=>C(a.id),className:"flex items-center gap-2 w-full px-2.5 py-1.5 text-[13px] rounded-md hover:bg-[var(--hub-surface-hover)] text-left",children:[e.jsx(Q,{size:12})," ",i("common.copyId")]}),e.jsxs("button",{onClick:()=>C(L),className:"flex items-center gap-2 w-full px-2.5 py-1.5 text-[13px] rounded-md hover:bg-[var(--hub-surface-hover)] text-left",children:[e.jsx(oe,{size:12})," ",i("common.copyUrl")]}),e.jsxs("button",{onClick:()=>C(_),className:"flex items-center gap-2 w-full px-2.5 py-1.5 text-[13px] rounded-md hover:bg-[var(--hub-surface-hover)] text-left",children:[e.jsx(oe,{size:12})," ",i("common.copyOpenApiUrl")]}),e.jsxs("button",{onClick:()=>{c(!1),u({name:a.name,url:O,headers:{Authorization:`Bearer ${Se}`}})},className:"flex items-center gap-2 w-full px-2.5 py-1.5 text-[13px] rounded-md hover:bg-[var(--hub-surface-hover)] text-left",children:[e.jsx(Fe,{size:12})," ",i("clientConfig.menuItem")]})]})]}),E&&e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:()=>s(a),className:"hub-icon-btn sm",title:i("groups.edit"),children:e.jsx(ze,{size:13})}),e.jsx("button",{onClick:()=>S(!0),className:"hub-icon-btn sm",title:i("groups.delete"),style:{color:"var(--hub-ink-3)"},children:e.jsx(Pe,{size:13})})]})]})]}),e.jsxs("div",{className:"grid flex-1 items-center gap-3 px-4 py-3",style:{gridTemplateColumns:"1fr 80px 1fr",minHeight:180},children:[e.jsx("div",{className:"flex flex-col gap-1.5",children:W.length===0?e.jsx("div",{style:{fontSize:12,color:"var(--hub-ink-3)"},children:i("groups.noServers")}):W.map(D=>{const P=K(D);return e.jsxs("div",{className:"flex items-center gap-2.5 px-2.5 py-1.5 rounded-md",style:{background:"var(--hub-bg-2)",border:"1px solid var(--hub-line-2)"},children:[e.jsx("span",{className:"inline-block flex-shrink-0",style:{width:6,height:6,borderRadius:50,background:D.status==="connected"?"var(--hub-ok)":D.status==="connecting"?"var(--hub-warn)":"var(--hub-err)"}}),e.jsx("span",{className:"hub-mono truncate flex-1",style:{fontSize:12.5},children:e.jsx("span",{title:D.name,children:Je(a,D.name)})}),e.jsxs("span",{className:"hub-mono hub-num flex-shrink-0",style:{fontSize:11,color:"var(--hub-ink-3)"},children:[P.visibleTools,"/",P.totalTools," tools"]})]},D.name)})}),e.jsxs("svg",{width:"80",height:"80",viewBox:"0 0 80 80",className:"self-center",children:[W.length===0?e.jsx("path",{d:"M0,40 C30,40 50,40 80,40",stroke:"var(--hub-line)",strokeWidth:"1",fill:"none",strokeDasharray:"3 3"}):W.map((D,P)=>{const r=12+60/Math.max(W.length,1)*(P+.5);return e.jsx("path",{d:`M0,${r} C 30,${r} 50,40 80,40`,stroke:"var(--hub-line)",strokeWidth:"1",fill:"none",strokeDasharray:"3 3"},P)}),e.jsx("circle",{cx:"80",cy:"40",r:"4",fill:"var(--hub-ink)"})]}),e.jsxs("div",{className:"px-3 py-2.5 rounded-md",style:{border:"1px solid var(--hub-line)",background:"var(--hub-bg-2)"},children:[e.jsx("div",{className:"hub-sect",style:{marginBottom:4},children:"endpoint"}),e.jsxs("div",{className:"hub-mono break-all",style:{fontSize:12,color:"var(--hub-ink-2)",lineHeight:1.4},children:[e.jsx("span",{style:{color:"var(--hub-ink-3)"},children:"/mcp/"}),e.jsx("b",{style:{color:"var(--hub-ink)",fontWeight:600},children:a.name})]}),e.jsxs("div",{className:"hub-mono break-all",style:{fontSize:12,color:"var(--hub-ink-2)",lineHeight:1.4},children:[e.jsx("span",{style:{color:"var(--hub-ink-3)"},children:"/api/"}),e.jsx("b",{style:{color:"var(--hub-ink)",fontWeight:600},children:a.name})]}),e.jsxs("div",{className:"flex gap-1.5 mt-2",children:[e.jsxs("button",{className:"hub-btn sm flex-1 justify-center",onClick:()=>C(L),title:i("common.copyUrl"),children:[e.jsx(Q,{size:11})," MCP"]}),e.jsxs("button",{className:"hub-btn sm flex-1 justify-center",onClick:()=>C(_),title:i("common.copyOpenApiUrl"),children:[e.jsx(Q,{size:11})," OpenAPI"]})]})]})]}),e.jsxs("div",{className:"flex justify-between items-center px-4 py-2",style:{borderTop:"1px solid var(--hub-line-2)",background:"var(--hub-bg-2)",fontSize:12,color:"var(--hub-ink-3)"},children:[e.jsxs("div",{children:[e.jsxs("div",{className:"hub-mono",children:[e.jsx("span",{style:{color:"var(--hub-ink-2)"},children:W.length})," ",i("nav.servers").toLowerCase()," ·"," ",e.jsx("span",{style:{color:"var(--hub-ink-2)"},children:J})," ",i("server.tools").toLowerCase()]}),h&&e.jsxs("div",{className:"hub-mono mt-1",style:{fontSize:11.5,color:"var(--hub-ink-3)"},children:[e.jsxs("div",{title:i("cost.estimate"),children:[i("cost.totalFootprint"),": ",H(h.direct.exposed),"/",H(h.direct.gross)]}),h.smartRouting&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{children:[i("cost.smartRouting"),": ",H(h.smartRouting.base)," (",i("cost.saved",{percent:Ne(h.direct.exposed,h.smartRouting.base)}),")"]}),e.jsxs("div",{title:i("cost.smartRoutingPdHint"),children:[i("cost.smartRoutingPd"),":"," ",H(h.smartRouting.progressiveDisclosure)]})]}),h.connectedCount<h.totalCount&&e.jsx("div",{children:i("cost.connectedOf",{connected:h.connectedCount,total:h.totalCount})})]})]}),E&&e.jsxs("button",{className:"hub-btn ghost sm",style:{color:"var(--hub-ink-3)"},onClick:()=>s(a),children:[i("groups.configureTools")||i("groups.edit"),e.jsx(Re,{size:11,style:{transform:"rotate(-90deg)"}})]})]}),e.jsx(we,{isOpen:T!==null,target:T,onClose:()=>u(null)}),e.jsx(Oe,{isOpen:j,onClose:()=>S(!1),onConfirm:()=>{l(a.id),S(!1)},serverName:a.name,isGroup:!0})]})},Xe=({onSuccess:a,onCancel:m})=>{const{t:s}=G(),[l,h]=f.useState(""),[i,p]=f.useState(null),[E,I]=f.useState(!1),[N,A]=f.useState(null),x=`{
|
|
2
|
-
"groups": [
|
|
3
|
-
{
|
|
4
|
-
"name": "AI Assistants",
|
|
5
|
-
"servers": ["openai-server", "anthropic-server"]
|
|
6
|
-
},
|
|
7
|
-
{
|
|
8
|
-
"name": "Development Tools",
|
|
9
|
-
"servers": [
|
|
10
|
-
{
|
|
11
|
-
"name": "github-server",
|
|
12
|
-
"tools": ["create_issue", "list_repos"],
|
|
13
|
-
"prompts": ["triage_prompt"],
|
|
14
|
-
"resources": ["resource://docs/repo-guide"]
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
"name": "gitlab-server",
|
|
18
|
-
"tools": "all",
|
|
19
|
-
"prompts": "all",
|
|
20
|
-
"resources": "all"
|
|
21
|
-
}
|
|
22
|
-
]
|
|
23
|
-
}
|
|
24
|
-
]
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
Supports:
|
|
28
|
-
- Simple server list: ["server1", "server2"]
|
|
29
|
-
- Advanced server config: [{"name": "server1", "tools": ["tool1"], "prompts": ["prompt1"], "resources": ["resource://docs/guide"]}]
|
|
30
|
-
- All groups will be imported in a single efficient batch operation.`,j=t=>{try{const c=JSON.parse(t.trim());if(!c.groups||!Array.isArray(c.groups))return p(s("groupImport.invalidFormat")),null;for(const o of c.groups)if(!o.name||typeof o.name!="string")return p(s("groupImport.missingName")),null;return c}catch{return p(s("groupImport.parseError")),null}},S=()=>{p(null);const t=j(l);t&&A(t.groups)},T=async()=>{if(N){I(!0),p(null);try{const t=await se("/groups/batch",{groups:N});if(t.success){const{successCount:c,failureCount:o,results:C}=t;if(o>0){const L=C.filter(O=>!O.success).map(O=>`${O.name}: ${O.message||s("groupImport.addFailed")}`);p(s("groupImport.partialSuccess",{count:c,total:N.length})+`
|
|
31
|
-
`+L.join(`
|
|
32
|
-
`))}c>0&&a()}else p(t.message||s("groupImport.importFailed"))}catch(t){console.error("Import error:",t),p(s("groupImport.importFailed"))}finally{I(!1)}}},u=t=>e.jsx("span",{className:"text-gray-500 ml-2",children:s(`groups.${t}`)}),b=(t,c)=>{if(!c||c==="all")return null;const o=Array.isArray(c)?c.join(", "):c;return e.jsx("span",{className:"text-gray-500 ml-2",children:s(`groups.${t}`,{items:o})})},v=t=>!t||t.length===0?e.jsx("span",{className:"text-gray-500",children:s("groups.noServers")}):e.jsx("div",{className:"space-y-1",children:t.map((c,o)=>typeof c=="string"?e.jsxs("div",{className:"text-sm",children:["• ",c]},o):e.jsxs("div",{className:"text-sm",children:["• ",c.name,c.tools&&c.tools!=="all"&&e.jsxs("span",{className:"text-gray-500 ml-2",children:["(",Array.isArray(c.tools)?c.tools.join(", "):c.tools,")"]}),c.tools==="all"&&u("previewAllTools"),b("previewPrompts",c.prompts),c.prompts==="all"&&u("previewAllPrompts"),b("previewResources",c.resources),c.resources==="all"&&u("previewAllResources")]},o))});return e.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:e.jsxs("div",{className:"bg-white dark:bg-gray-800 shadow rounded-lg p-6 w-full max-w-4xl max-h-[90vh] overflow-y-auto",children:[e.jsxs("div",{className:"flex justify-between items-center mb-6",children:[e.jsx("h2",{className:"text-xl font-semibold text-gray-900",children:s("groupImport.title")}),e.jsx("button",{onClick:m,className:"text-gray-500 hover:text-gray-700",children:"✕"})]}),i&&e.jsx("div",{className:"mb-4 bg-red-50 border-l-4 border-red-500 p-4 rounded",children:e.jsx("p",{className:"text-red-700 whitespace-pre-wrap",children:i})}),N?e.jsxs("div",{children:[e.jsxs("div",{className:"mb-4",children:[e.jsx("h3",{className:"text-lg font-medium text-gray-900 mb-3",children:s("groupImport.previewTitle")}),e.jsx("div",{className:"space-y-3",children:N.map((t,c)=>e.jsx("div",{className:"bg-gray-50 dark:bg-gray-800 p-4 rounded-lg border border-gray-200 dark:border-gray-700",children:e.jsx("div",{className:"flex items-start justify-between",children:e.jsxs("div",{className:"flex-1",children:[e.jsx("h4",{className:"font-medium text-gray-900",children:t.name}),t.description&&e.jsx("p",{className:"text-sm text-gray-600 mt-1",children:t.description}),e.jsxs("div",{className:"mt-2 text-sm text-gray-600",children:[e.jsxs("strong",{children:[s("groups.servers"),":"]}),e.jsx("div",{className:"mt-1",children:v(t.servers)})]})]})})},c))})]}),e.jsxs("div",{className:"flex justify-end space-x-4",children:[e.jsx("button",{onClick:()=>A(null),disabled:E,className:"hub-btn",children:s("common.back")}),e.jsx("button",{onClick:T,disabled:E,className:"hub-btn primary",children:E?e.jsxs(e.Fragment,{children:[e.jsxs("svg",{className:"animate-spin h-4 w-4 mr-2",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[e.jsx("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"4"}),e.jsx("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]}),s("groupImport.importing")]}):s("groupImport.import")})]})]}):e.jsxs("div",{children:[e.jsxs("div",{className:"mb-4",children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-2",children:s("groupImport.inputLabel")}),e.jsx("textarea",{value:l,onChange:t=>h(t.target.value),className:"w-full h-96 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 font-mono text-sm",placeholder:x}),e.jsx("p",{className:"text-xs text-gray-500 mt-2",children:s("groupImport.inputHelp")})]}),e.jsxs("div",{className:"flex justify-end space-x-4",children:[e.jsx("button",{onClick:m,className:"hub-btn",children:s("common.cancel")}),e.jsx("button",{onClick:S,disabled:!l.trim(),className:"hub-btn primary",children:s("groupImport.preview")})]})]})]})})},Ye=({groups:a,onCancel:m})=>{const{t:s}=G(),[l,h]=f.useState(""),[i,p]=f.useState(""),[E,I]=f.useState([]),[N,A]=f.useState(!1),[x,j]=f.useState(!1),[S,T]=f.useState(null),u=t=>{I(c=>c.includes(t)?c.filter(o=>o!==t):[...c,t])},b=()=>{E.length===a.length?I([]):I(a.map(t=>t.id))},v=async()=>{if(!l.trim()){T(s("template.nameRequired"));return}j(!0),T(null);try{const t=await se("/templates/export",{name:l.trim(),description:i.trim()||void 0,groupIds:E.length>0?E:void 0,includeDisabledServers:N});if(t.success&&t.data){const c=t.data,o=new Blob([JSON.stringify(c,null,2)],{type:"application/json"}),C=URL.createObjectURL(o),L=document.createElement("a");L.href=C,L.download=`${c.name.replace(/[^a-zA-Z0-9-_]/g,"_")}.mcphub-template.json`,document.body.appendChild(L),L.click(),document.body.removeChild(L),URL.revokeObjectURL(C),m()}else T(t.message||s("template.exportFailed"))}catch(t){console.error("Export error:",t),T(s("template.exportFailed"))}finally{j(!1)}};return e.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:e.jsxs("div",{className:"bg-white dark:bg-gray-800 shadow rounded-lg p-6 w-full max-w-3xl max-h-[90vh] overflow-y-auto",children:[e.jsxs("div",{className:"flex justify-between items-center mb-6",children:[e.jsx("h2",{className:"text-xl font-semibold text-gray-900",children:s("template.exportTitle")}),e.jsx("button",{onClick:m,className:"text-gray-500 hover:text-gray-700",children:"✕"})]}),S&&e.jsx("div",{className:"mb-4 bg-red-50 dark:bg-red-900/20 border-l-4 border-red-500 p-4 rounded",children:e.jsx("p",{className:"text-red-700 dark:text-red-300",children:S})}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsxs("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:[s("template.name")," *"]}),e.jsx("input",{type:"text",value:l,onChange:t=>h(t.target.value),className:"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:s("template.namePlaceholder")})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:s("template.description")}),e.jsx("input",{type:"text",value:i,onChange:t=>p(t.target.value),className:"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:s("template.descriptionPlaceholder")})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex justify-between items-center mb-2",children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700",children:s("template.selectGroups")}),e.jsx("button",{onClick:b,className:"text-sm text-blue-600 hover:text-blue-800 dark:text-blue-300",children:E.length===a.length?s("template.deselectAll"):s("template.selectAll")})]}),e.jsx("p",{className:"text-xs text-gray-500 mb-2",children:s("template.selectGroupsHelp")}),e.jsx("div",{className:"border border-gray-200 dark:border-gray-700 rounded-md max-h-48 overflow-y-auto",children:a.map(t=>e.jsxs("label",{className:"flex items-center px-3 py-2 hover:bg-gray-50 dark:bg-gray-800 dark:hover:bg-gray-700 cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:E.includes(t.id),onChange:()=>u(t.id),className:"mr-3 h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"}),e.jsxs("div",{children:[e.jsx("span",{className:"text-sm font-medium text-gray-900",children:t.name}),t.description&&e.jsx("span",{className:"text-xs text-gray-500 ml-2",children:t.description})]})]},t.id))})]}),e.jsxs("label",{className:"flex items-center space-x-2 cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:N,onChange:t=>A(t.target.checked),className:"h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"}),e.jsx("span",{className:"text-sm text-gray-700",children:s("template.includeDisabled")})]})]}),e.jsx("div",{className:"mt-4 p-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-700/60 rounded-md",children:e.jsx("p",{className:"text-sm text-blue-700 dark:text-blue-300",children:s("template.exportNote")})}),e.jsxs("div",{className:"flex justify-end space-x-4 mt-6",children:[e.jsx("button",{onClick:m,className:"hub-btn",children:s("common.cancel")}),e.jsx("button",{onClick:v,disabled:x||!l.trim(),className:"hub-btn primary",children:s(x?"template.exporting":"template.export")})]})]})})},Ze=({onSuccess:a,onCancel:m})=>{const{t:s}=G(),[l,h]=f.useState(null),[i,p]=f.useState(null),[E,I]=f.useState(!1),[N,A]=f.useState(null),x=f.useRef(null),j=u=>{var t;p(null),h(null),A(null);const b=(t=u.target.files)==null?void 0:t[0];if(!b)return;const v=new FileReader;v.onload=c=>{var o;try{const C=JSON.parse((o=c.target)==null?void 0:o.result);if(!C.version||!C.name||!C.servers||!C.groups){p(s("template.invalidFormat"));return}h(C)}catch{p(s("template.parseError"))}},v.readAsText(b)},S=u=>{if(p(null),h(null),A(null),!!u.trim())try{const b=JSON.parse(u.trim());if(!b.version||!b.name||!b.servers||!b.groups){p(s("template.invalidFormat"));return}h(b)}catch{p(s("template.parseError"))}},T=async()=>{if(l){I(!0),p(null);try{const u=await se("/templates/import",l);u.data?(A(u.data),u.data.success&&a()):p(u.message||s("template.importFailed"))}catch(u){console.error("Import error:",u),p(s("template.importFailed"))}finally{I(!1)}}};return e.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:e.jsxs("div",{className:"bg-white dark:bg-gray-800 shadow rounded-lg p-6 w-full max-w-4xl max-h-[90vh] overflow-y-auto",children:[e.jsxs("div",{className:"flex justify-between items-center mb-6",children:[e.jsx("h2",{className:"text-xl font-semibold text-gray-900",children:s("template.importTitle")}),e.jsx("button",{onClick:m,className:"text-gray-500 hover:text-gray-700",children:"✕"})]}),i&&e.jsx("div",{className:"mb-4 bg-red-50 dark:bg-red-900/20 border-l-4 border-red-500 p-4 rounded",children:e.jsx("p",{className:"text-red-700 dark:text-red-300",children:i})}),N&&e.jsxs("div",{className:`mb-4 p-4 rounded border-l-4 ${N.success?"bg-green-50 dark:bg-green-900/20 border-green-500":"bg-yellow-50 dark:bg-yellow-900/20 border-yellow-500"}`,children:[e.jsx("p",{className:N.success?"text-green-700 dark:text-green-300":"text-yellow-700 dark:text-yellow-300",children:s("template.importResult",{serversCreated:N.serversCreated,serversSkipped:N.serversSkipped,groupsCreated:N.groupsCreated,groupsSkipped:N.groupsSkipped})}),N.requiredEnvVars.length>0&&e.jsxs("div",{className:"mt-2 p-2 bg-orange-50 dark:bg-orange-900/20 border border-orange-200 dark:border-orange-700/60 rounded",children:[e.jsx("p",{className:"text-sm font-medium text-orange-800 dark:text-orange-300",children:s("template.envVarsNeeded")}),e.jsx("ul",{className:"mt-1 text-sm text-orange-700 dark:text-orange-300",children:N.requiredEnvVars.map(u=>e.jsx("li",{className:"font-mono",children:u},u))})]})]}),l?e.jsxs("div",{children:[e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"p-3 bg-gray-50 dark:bg-gray-800 rounded-md",children:[e.jsx("h3",{className:"font-medium text-gray-900",children:l.name}),l.description&&e.jsx("p",{className:"text-sm text-gray-600 mt-1",children:l.description}),e.jsxs("p",{className:"text-xs text-gray-500 mt-1",children:[s("template.version"),": ",l.version," | ",s("template.createdAt"),":"," ",new Date(l.createdAt).toLocaleDateString()]})]}),e.jsxs("div",{children:[e.jsxs("h4",{className:"text-sm font-medium text-gray-700 mb-2",children:[s("template.servers")," (",Object.keys(l.servers).length,")"]}),e.jsx("div",{className:"border border-gray-200 dark:border-gray-700 rounded-md divide-y divide-gray-200 dark:divide-gray-700 max-h-40 overflow-y-auto",children:Object.entries(l.servers).map(([u,b])=>e.jsxs("div",{className:"px-3 py-2",children:[e.jsx("span",{className:"text-sm font-medium text-gray-900",children:u}),e.jsx("span",{className:"text-xs text-gray-500 ml-2",children:b.type||"stdio"})]},u))})]}),e.jsxs("div",{children:[e.jsxs("h4",{className:"text-sm font-medium text-gray-700 mb-2",children:[s("template.groups")," (",l.groups.length,")"]}),e.jsx("div",{className:"border border-gray-200 dark:border-gray-700 rounded-md divide-y divide-gray-200 dark:divide-gray-700 max-h-40 overflow-y-auto",children:l.groups.map((u,b)=>e.jsxs("div",{className:"px-3 py-2",children:[e.jsx("span",{className:"text-sm font-medium text-gray-900",children:u.name}),u.description&&e.jsx("span",{className:"text-xs text-gray-500 ml-2",children:u.description}),e.jsxs("div",{className:"text-xs text-gray-500 mt-1",children:[u.servers.length," ",s("template.serversInGroup")]})]},b))})]}),l.requiredEnvVars.length>0&&e.jsxs("div",{className:"p-3 bg-orange-50 dark:bg-orange-900/20 border border-orange-200 dark:border-orange-700/60 rounded-md",children:[e.jsx("h4",{className:"text-sm font-medium text-orange-800 dark:text-orange-300",children:s("template.envVarsNeeded")}),e.jsx("ul",{className:"mt-1 text-sm text-orange-700 dark:text-orange-300 font-mono",children:l.requiredEnvVars.map(u=>e.jsx("li",{children:u},u))})]})]}),e.jsxs("div",{className:"flex justify-end space-x-4 mt-6",children:[e.jsx("button",{onClick:()=>{h(null),A(null),x.current&&(x.current.value="")},className:"hub-btn",children:s("common.back")}),e.jsx("button",{onClick:T,disabled:E,className:"hub-btn primary",children:s(E?"template.importing":"template.import")})]})]}):e.jsxs("div",{children:[e.jsxs("div",{className:"mb-4",children:[e.jsx("div",{className:"flex items-center justify-between mb-2",children:e.jsx("label",{className:"block text-sm font-medium text-gray-700",children:s("template.uploadFile")})}),e.jsx("div",{className:"flex items-center space-x-4",children:e.jsx("input",{ref:x,type:"file",accept:".json",onChange:j,className:"block text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100"})})]}),e.jsxs("div",{className:"relative my-4",children:[e.jsx("div",{className:"absolute inset-0 flex items-center",children:e.jsx("div",{className:"w-full border-t border-gray-300"})}),e.jsx("div",{className:"relative flex justify-center text-sm",children:e.jsx("span",{className:"bg-white dark:bg-gray-800 px-2 text-gray-500",children:s("template.or")})})]}),e.jsxs("div",{className:"mb-4",children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-2",children:s("template.pasteJson")}),e.jsx("textarea",{className:"w-full h-64 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 font-mono text-sm",placeholder:s("template.pastePlaceholder"),onChange:u=>S(u.target.value)})]}),e.jsx("div",{className:"flex justify-end space-x-4",children:e.jsx("button",{onClick:m,className:"hub-btn",children:s("common.cancel")})})]})]})})},cs=()=>{const{t:a}=G(),{groups:m,loading:s,error:l,setError:h,deleteGroup:i,triggerRefresh:p}=ee(),{allServers:E}=te({refreshOnMount:!0}),{groupCosts:I}=re(JSON.stringify([m,Ce(E)])),[N,A]=f.useState(null),[x,j]=f.useState(!1),[S,T]=f.useState(!1),[u,b]=f.useState(!1),[v,t]=f.useState(!1),c=async o=>{const C=await i(o);(!C||!C.success)&&h((C==null?void 0:C.message)||a("groups.deleteError"))};return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-end justify-between gap-4 mb-6",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"hub-h1",children:a("pages.groups.title")}),e.jsxs("p",{className:"hub-sub",children:[e.jsx("span",{className:"hub-num",children:m.length})," ",a("nav.groups").toLowerCase()]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs("button",{className:"hub-btn",onClick:()=>T(!0),children:[e.jsx(ce,{size:13})," ",a("groupImport.button")]}),e.jsxs("button",{className:"hub-btn",onClick:()=>b(!0),children:[e.jsx(Le,{size:13})," ",a("template.exportButton")]}),e.jsxs("button",{className:"hub-btn",onClick:()=>t(!0),children:[e.jsx(ce,{size:13})," ",a("template.importButton")]}),e.jsxs("button",{className:"hub-btn primary",onClick:()=>j(!0),children:[e.jsx(de,{size:13})," ",a("groups.add")]})]})]}),l&&e.jsxs("div",{className:"hub-card flex items-center justify-between gap-3 mb-4",style:{padding:"10px 14px",borderColor:"oklch(0.85 0.1 25)",background:"oklch(0.97 0.03 25)",color:"oklch(0.4 0.18 25)"},children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx(Ue,{size:14,className:"flex-shrink-0"}),e.jsx("span",{className:"truncate text-[13px]",children:l})]}),e.jsx("button",{className:"hub-icon-btn sm",onClick:()=>h(null),children:e.jsx($e,{size:13})})]}),s?e.jsx("div",{className:"hub-card p-6 text-center",style:{color:"var(--hub-ink-3)"},children:a("app.loading")}):m.length===0?e.jsx("div",{className:"hub-card p-10 text-center",style:{color:"var(--hub-ink-3)"},children:a("groups.noGroups")}):e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-3.5",children:[m.map(o=>e.jsx(Qe,{group:o,servers:E,onEdit:A,onDelete:c,cost:I.find(C=>C.id===o.id)},o.id)),e.jsx("button",{onClick:()=>j(!0),className:"flex items-center justify-center text-[var(--hub-ink-3)] hover:text-[var(--hub-ink-2)] transition-colors",style:{border:"1px dashed var(--hub-line)",borderRadius:10,minHeight:200,background:"transparent",cursor:"pointer"},children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"grid place-items-center mx-auto mb-2",style:{width:36,height:36,borderRadius:10,border:"1px solid var(--hub-line)"},children:e.jsx(de,{size:16})}),e.jsx("div",{style:{fontSize:13,fontWeight:500,color:"var(--hub-ink-2)"},children:a("groups.add")}),e.jsx("div",{style:{fontSize:12,marginTop:2},children:a("groups.addNew")})]})})]}),x&&e.jsx(Ve,{onAdd:()=>{j(!1),p()},onCancel:()=>j(!1)}),S&&e.jsx(Xe,{onSuccess:()=>{T(!1),p()},onCancel:()=>T(!1)}),N&&e.jsx(qe,{group:N,onEdit:()=>{A(null),p()},onCancel:()=>A(null)}),u&&e.jsx(Ye,{groups:m,onCancel:()=>b(!1)}),v&&e.jsx(Ze,{onSuccess:()=>{t(!1),p()},onCancel:()=>t(!1)})]})};export{cs as default};
|
|
33
|
-
//# sourceMappingURL=GroupsPage-DHgQeVHy.js.map
|