@samanhappy/mcphub 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/README.md +5 -0
  2. package/dist/constants/oauthServerDefaults.js +2 -0
  3. package/dist/constants/oauthServerDefaults.js.map +1 -1
  4. package/dist/controllers/configController.js +2 -0
  5. package/dist/controllers/configController.js.map +1 -1
  6. package/dist/controllers/credentialBindingController.js +30 -1
  7. package/dist/controllers/credentialBindingController.js.map +1 -1
  8. package/dist/controllers/oauthApprovalController.js +63 -0
  9. package/dist/controllers/oauthApprovalController.js.map +1 -0
  10. package/dist/controllers/oauthServerController.js +55 -20
  11. package/dist/controllers/oauthServerController.js.map +1 -1
  12. package/dist/controllers/serverController.js +83 -27
  13. package/dist/controllers/serverController.js.map +1 -1
  14. package/dist/dao/DaoFactory.js +7 -0
  15. package/dist/dao/DaoFactory.js.map +1 -1
  16. package/dist/dao/DatabaseDaoFactory.js +4 -0
  17. package/dist/dao/DatabaseDaoFactory.js.map +1 -1
  18. package/dist/dao/OAuthApprovalDao.js +52 -0
  19. package/dist/dao/OAuthApprovalDao.js.map +1 -0
  20. package/dist/dao/OAuthApprovalDaoDbImpl.js +26 -0
  21. package/dist/dao/OAuthApprovalDaoDbImpl.js.map +1 -0
  22. package/dist/dao/OAuthTokenDaoDbImpl.js +2 -0
  23. package/dist/dao/OAuthTokenDaoDbImpl.js.map +1 -1
  24. package/dist/dao/index.js +1 -0
  25. package/dist/dao/index.js.map +1 -1
  26. package/dist/db/entities/OAuthApproval.js +58 -0
  27. package/dist/db/entities/OAuthApproval.js.map +1 -0
  28. package/dist/db/entities/OAuthToken.js +4 -0
  29. package/dist/db/entities/OAuthToken.js.map +1 -1
  30. package/dist/db/entities/SystemConfig.js.map +1 -1
  31. package/dist/db/entities/index.js +3 -1
  32. package/dist/db/entities/index.js.map +1 -1
  33. package/dist/middlewares/auth.js +2 -2
  34. package/dist/middlewares/auth.js.map +1 -1
  35. package/dist/middlewares/userContext.js +26 -5
  36. package/dist/middlewares/userContext.js.map +1 -1
  37. package/dist/models/OAuth.js +19 -3
  38. package/dist/models/OAuth.js.map +1 -1
  39. package/dist/routes/index.js +6 -1
  40. package/dist/routes/index.js.map +1 -1
  41. package/dist/services/credentialBindingService.js +39 -3
  42. package/dist/services/credentialBindingService.js.map +1 -1
  43. package/dist/services/forwardAuthService.js +27 -11
  44. package/dist/services/forwardAuthService.js.map +1 -1
  45. package/dist/services/mcpService.js +3 -3
  46. package/dist/services/mcpService.js.map +1 -1
  47. package/dist/services/oauthApprovalService.js +74 -0
  48. package/dist/services/oauthApprovalService.js.map +1 -0
  49. package/dist/services/oauthClientRegistration.js +9 -4
  50. package/dist/services/oauthClientRegistration.js.map +1 -1
  51. package/dist/services/oauthServerService.js +24 -7
  52. package/dist/services/oauthServerService.js.map +1 -1
  53. package/dist/services/openApiGeneratorService.js +10 -3
  54. package/dist/services/openApiGeneratorService.js.map +1 -1
  55. package/dist/services/sseService.js +16 -6
  56. package/dist/services/sseService.js.map +1 -1
  57. package/dist/services/userService.js +2 -0
  58. package/dist/services/userService.js.map +1 -1
  59. package/dist/services/vectorSearchService.js +139 -73
  60. package/dist/services/vectorSearchService.js.map +1 -1
  61. package/dist/types/network.js +2 -0
  62. package/dist/types/network.js.map +1 -0
  63. package/dist/utils/bearerAuth.js +23 -0
  64. package/dist/utils/bearerAuth.js.map +1 -1
  65. package/dist/utils/migration.js +1 -0
  66. package/dist/utils/migration.js.map +1 -1
  67. package/dist/utils/openApiSchema.js +148 -0
  68. package/dist/utils/openApiSchema.js.map +1 -0
  69. package/dist/utils/parameterConversion.js +38 -5
  70. package/dist/utils/parameterConversion.js.map +1 -1
  71. package/dist/utils/passthroughHeaders.js +9 -4
  72. package/dist/utils/passthroughHeaders.js.map +1 -1
  73. package/dist/utils/ssrf.js +46 -12
  74. package/dist/utils/ssrf.js.map +1 -1
  75. package/frontend/dist/assets/{ActivityPage-CSXEpl6y.js → ActivityPage-CB41zWix.js} +2 -2
  76. package/frontend/dist/assets/{ActivityPage-CSXEpl6y.js.map → ActivityPage-CB41zWix.js.map} +1 -1
  77. package/frontend/dist/assets/{ConfirmDialog-BJpzQmMw.js → ConfirmDialog-ByWCtrIw.js} +2 -2
  78. package/frontend/dist/assets/{ConfirmDialog-BJpzQmMw.js.map → ConfirmDialog-ByWCtrIw.js.map} +1 -1
  79. package/frontend/dist/assets/CredentialsPage-BecFRfro.js +2 -0
  80. package/frontend/dist/assets/CredentialsPage-BecFRfro.js.map +1 -0
  81. package/frontend/dist/assets/{Dashboard-Da-YT_l_.js → Dashboard-CwifBwm4.js} +2 -2
  82. package/frontend/dist/assets/{Dashboard-Da-YT_l_.js.map → Dashboard-CwifBwm4.js.map} +1 -1
  83. package/frontend/dist/assets/{DeleteDialog-BoMYLx3J.js → DeleteDialog-BkEKW9LB.js} +2 -2
  84. package/frontend/dist/assets/{DeleteDialog-BoMYLx3J.js.map → DeleteDialog-BkEKW9LB.js.map} +1 -1
  85. package/frontend/dist/assets/{EndpointCopy-CZOjiFAH.js → EndpointCopy-BeLf_ow_.js} +2 -2
  86. package/frontend/dist/assets/{EndpointCopy-CZOjiFAH.js.map → EndpointCopy-BeLf_ow_.js.map} +1 -1
  87. package/frontend/dist/assets/{GroupsPage-CSA5G9_H.js → GroupsPage-DLL1tFj8.js} +2 -2
  88. package/frontend/dist/assets/{GroupsPage-CSA5G9_H.js.map → GroupsPage-DLL1tFj8.js.map} +1 -1
  89. package/frontend/dist/assets/{LoginPage-7RswUPtG.js → LoginPage-DvHL1HNV.js} +2 -2
  90. package/frontend/dist/assets/{LoginPage-7RswUPtG.js.map → LoginPage-DvHL1HNV.js.map} +1 -1
  91. package/frontend/dist/assets/{LogsPage-Dbef_68F.js → LogsPage-Bva6Y11K.js} +2 -2
  92. package/frontend/dist/assets/{LogsPage-Dbef_68F.js.map → LogsPage-Bva6Y11K.js.map} +1 -1
  93. package/frontend/dist/assets/{MarketPage-rSBdHZxo.js → MarketPage-DGxNuifk.js} +2 -2
  94. package/frontend/dist/assets/{MarketPage-rSBdHZxo.js.map → MarketPage-DGxNuifk.js.map} +1 -1
  95. package/frontend/dist/assets/OAuthApprovalsPage-TzVNIJ27.js +2 -0
  96. package/frontend/dist/assets/OAuthApprovalsPage-TzVNIJ27.js.map +1 -0
  97. package/frontend/dist/assets/{OAuthConsentPage-BH9O7bk3.js → OAuthConsentPage-yQSgIbZ8.js} +2 -2
  98. package/frontend/dist/assets/{OAuthConsentPage-BH9O7bk3.js.map → OAuthConsentPage-yQSgIbZ8.js.map} +1 -1
  99. package/frontend/dist/assets/{Pagination-S-7lzy59.js → Pagination-B2WW4qn_.js} +2 -2
  100. package/frontend/dist/assets/{Pagination-S-7lzy59.js.map → Pagination-B2WW4qn_.js.map} +1 -1
  101. package/frontend/dist/assets/{PromptsPage-B558MhVU.js → PromptsPage-CIAVpo9B.js} +2 -2
  102. package/frontend/dist/assets/{PromptsPage-B558MhVU.js.map → PromptsPage-CIAVpo9B.js.map} +1 -1
  103. package/frontend/dist/assets/{ResourcesPage-DQpy8B9L.js → ResourcesPage-C5g-98tB.js} +2 -2
  104. package/frontend/dist/assets/{ResourcesPage-DQpy8B9L.js.map → ResourcesPage-C5g-98tB.js.map} +1 -1
  105. package/frontend/dist/assets/{ServersPage-DBcC8pG2.js → ServersPage-CJEgBQr-.js} +4 -4
  106. package/frontend/dist/assets/{ServersPage-DBcC8pG2.js.map → ServersPage-CJEgBQr-.js.map} +1 -1
  107. package/frontend/dist/assets/SettingsPage-Bub-g0mD.js +14 -0
  108. package/frontend/dist/assets/SettingsPage-Bub-g0mD.js.map +1 -0
  109. package/frontend/dist/assets/{StatusDot-CLxRrJ5l.js → StatusDot-B81gkUBo.js} +2 -2
  110. package/frontend/dist/assets/{StatusDot-CLxRrJ5l.js.map → StatusDot-B81gkUBo.js.map} +1 -1
  111. package/frontend/dist/assets/{ToggleGroup-DuWJZU41.js → ToggleGroup-DZ39486g.js} +2 -2
  112. package/frontend/dist/assets/{ToggleGroup-DuWJZU41.js.map → ToggleGroup-DZ39486g.js.map} +1 -1
  113. package/frontend/dist/assets/{UserGroupSelection-CN0weGXJ.js → UserGroupSelection-DionUENR.js} +2 -2
  114. package/frontend/dist/assets/{UserGroupSelection-CN0weGXJ.js.map → UserGroupSelection-DionUENR.js.map} +1 -1
  115. package/frontend/dist/assets/{UsersPage-B158Bofs.js → UsersPage-pdkVxTsL.js} +2 -2
  116. package/frontend/dist/assets/{UsersPage-B158Bofs.js.map → UsersPage-pdkVxTsL.js.map} +1 -1
  117. package/frontend/dist/assets/{clipboard-BLr_gbf8.js → clipboard-BYlVdxdy.js} +2 -2
  118. package/frontend/dist/assets/{clipboard-BLr_gbf8.js.map → clipboard-BYlVdxdy.js.map} +1 -1
  119. package/frontend/dist/assets/{costRevision-Dzec2k_b.js → costRevision-D-WY0B73.js} +2 -2
  120. package/frontend/dist/assets/{costRevision-Dzec2k_b.js.map → costRevision-D-WY0B73.js.map} +1 -1
  121. package/frontend/dist/assets/{i18n-vendor-COTriSc6.js → i18n-vendor-CPneThYa.js} +3 -3
  122. package/frontend/dist/assets/{i18n-vendor-COTriSc6.js.map → i18n-vendor-CPneThYa.js.map} +1 -1
  123. package/frontend/dist/assets/index-CyD60EHI.css +1 -0
  124. package/frontend/dist/assets/index-DKX_BExz.js +3 -0
  125. package/frontend/dist/assets/index-DKX_BExz.js.map +1 -0
  126. package/frontend/dist/assets/{resourceService-BNH7uNar.js → resourceService-CKAaXBkJ.js} +2 -2
  127. package/frontend/dist/assets/{resourceService-BNH7uNar.js.map → resourceService-CKAaXBkJ.js.map} +1 -1
  128. package/frontend/dist/assets/{useCostData-B2d2eLCD.js → useCostData-DzjFGnw4.js} +2 -2
  129. package/frontend/dist/assets/{useCostData-B2d2eLCD.js.map → useCostData-DzjFGnw4.js.map} +1 -1
  130. package/frontend/dist/assets/{variableDetection-DRdE941j.js → variableDetection-D75LR7nZ.js} +2 -2
  131. package/frontend/dist/assets/{variableDetection-DRdE941j.js.map → variableDetection-D75LR7nZ.js.map} +1 -1
  132. package/frontend/dist/index.html +3 -3
  133. package/mcp_settings.json +2 -0
  134. package/package.json +4 -4
  135. package/frontend/dist/assets/CredentialsPage-CPxOHQUZ.js +0 -2
  136. package/frontend/dist/assets/CredentialsPage-CPxOHQUZ.js.map +0 -1
  137. package/frontend/dist/assets/SettingsPage-BcpeHFR3.js +0 -14
  138. package/frontend/dist/assets/SettingsPage-BcpeHFR3.js.map +0 -1
  139. package/frontend/dist/assets/index-CGRjM_NC.js +0 -3
  140. package/frontend/dist/assets/index-CGRjM_NC.js.map +0 -1
  141. package/frontend/dist/assets/index-DrHctFvx.css +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Dashboard-Da-YT_l_.js","sources":["../../src/pages/Dashboard.tsx"],"sourcesContent":["import { getSmartRoutingPath } from '@/utils/runtime';\nimport React, { useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useNavigate } from 'react-router-dom';\nimport { RefreshCw, Plus, ChevronRight, AlertCircle } from 'lucide-react';\nimport { useServerData } from '@/hooks/useServerData';\nimport { useGroupData } from '@/hooks/useGroupData';\nimport { useSettingsData } from '@/hooks/useSettingsData';\nimport { useCostData } from '@/hooks/useCostData';\nimport { formatTokens } from '@/utils/contextCost';\nimport { Server } from '@/types';\nimport { EndpointCopy } from '@/components/ui/EndpointCopy';\nimport { ServerStatusDot } from '@/components/ui/StatusDot';\n\nconst Stat: React.FC<{ label: string; value: React.ReactNode; tone?: 'ok' | 'warn' | 'err' | 'muted' | 'default' }> = ({\n label,\n value,\n tone = 'default',\n}) => {\n const toneColor =\n tone === 'ok'\n ? 'oklch(0.4 0.13 145)'\n : tone === 'warn'\n ? 'oklch(0.45 0.13 80)'\n : tone === 'err'\n ? 'oklch(0.45 0.18 25)'\n : tone === 'muted'\n ? 'var(--hub-ink-3)'\n : 'var(--hub-ink)';\n return (\n <div className=\"hub-card\" style={{ padding: '14px 16px' }}>\n <div className=\"text-[12px]\" style={{ color: 'var(--hub-ink-3)' }}>\n {label}\n </div>\n <div\n className=\"hub-num\"\n style={{\n fontSize: 26,\n fontWeight: 500,\n letterSpacing: '-0.02em',\n lineHeight: 1.1,\n marginTop: 8,\n color: toneColor,\n }}\n >\n {value}\n </div>\n </div>\n );\n};\n\nconst transportLabel = (t: any, type?: string) => {\n if (!type) return null;\n if (type === 'stdio') return t('server.typeStdio') || 'stdio';\n if (type === 'sse') return t('server.typeSse') || 'sse';\n if (type === 'streamable-http') return t('server.typeStreamableHttp') || 'http';\n if (type === 'openapi') return t('server.typeOpenapi') || 'openapi';\n return type;\n};\n\nconst DashboardPage: React.FC = () => {\n const { t } = useTranslation();\n const navigate = useNavigate();\n const { allServers, error, setError, isLoading, triggerRefresh } = useServerData({\n refreshOnMount: true,\n });\n const { groups } = useGroupData();\n const { installConfig } = useSettingsData();\n const { serverCosts } = useCostData();\n\n const [hasLoaded, setHasLoaded] = React.useState(false);\n const loadingStartedRef = React.useRef(false);\n React.useEffect(() => {\n if (isLoading) {\n loadingStartedRef.current = true;\n return;\n }\n if (loadingStartedRef.current) {\n setHasLoaded(true);\n return;\n }\n if (allServers.length > 0 || error) setHasLoaded(true);\n }, [isLoading, allServers.length, error]);\n\n const stats = useMemo(\n () => ({\n total: allServers.length,\n online: allServers.filter((s: Server) => s.status === 'connected').length,\n disabled: allServers.filter((s: Server) => s.enabled === false).length,\n offline: allServers.filter(\n (s: Server) => s.status === 'disconnected' && s.enabled !== false,\n ).length,\n connecting: allServers.filter(\n (s: Server) =>\n (s.status === 'connecting' || s.status === 'oauth_required') && s.enabled !== false,\n ).length,\n tools: allServers.reduce((acc, s) => acc + (s.tools?.length || 0), 0),\n }),\n [allServers],\n );\n\n const footprint = useMemo(\n () => serverCosts.filter((c) => c.connected).reduce((acc, c) => acc + c.exposed, 0),\n [serverCosts],\n );\n\n const recentServers = useMemo(() => allServers.slice(0, 6), [allServers]);\n const baseUrl = installConfig?.baseUrl?.replace(/\\/+$/, '') || '';\n const recentServerColumns =\n 'minmax(220px,1.9fr) minmax(110px,0.95fr) minmax(120px,0.95fr) 80px 80px 90px 72px';\n\n const showSkeleton = !hasLoaded;\n\n return (\n <div>\n {/* Header */}\n <div className=\"flex items-end justify-between gap-4 mb-6\">\n <div>\n <h1 className=\"hub-h1\">{t('pages.dashboard.title')}</h1>\n <p className=\"hub-sub\">\n {t('pages.dashboard.totalServers')} · <span className=\"hub-num\">{stats.total}</span>\n {' · '}\n {t('pages.dashboard.onlineServers')} · <span className=\"hub-num\">{stats.online}</span>\n </p>\n </div>\n <div className=\"flex gap-2\">\n <button className=\"hub-btn\" onClick={() => triggerRefresh()}>\n <RefreshCw size={13} /> {t('common.refresh')}\n </button>\n <button className=\"hub-btn primary\" onClick={() => navigate('/servers')}>\n <Plus size={13} /> {t('server.add')}\n </button>\n </div>\n </div>\n\n {error && (\n <div\n className=\"hub-card flex items-center justify-between gap-3 mb-5\"\n style={{\n padding: '10px 14px',\n borderColor: 'oklch(0.85 0.1 25)',\n background: 'oklch(0.97 0.03 25)',\n color: 'oklch(0.4 0.18 25)',\n }}\n >\n <div className=\"flex items-center gap-2 min-w-0\">\n <AlertCircle size={14} className=\"flex-shrink-0\" />\n <span className=\"truncate text-[13px]\">{error}</span>\n </div>\n <button\n className=\"hub-icon-btn sm\"\n onClick={() => setError(null)}\n aria-label={t('app.closeButton')}\n >\n ✕\n </button>\n </div>\n )}\n\n {/* Stat row */}\n {showSkeleton ? (\n <div className=\"grid grid-cols-2 md:grid-cols-6 gap-3 mb-6\">\n {Array.from({ length: 6 }).map((_, i) => (\n <div\n key={i}\n className=\"hub-card animate-pulse\"\n style={{ padding: '14px 16px', height: 78 }}\n />\n ))}\n </div>\n ) : (\n <div className=\"grid grid-cols-2 md:grid-cols-6 gap-3 mb-6\">\n <Stat label={t('pages.dashboard.totalServers')} value={stats.total} />\n <Stat label={t('pages.dashboard.onlineServers')} value={stats.online} tone=\"ok\" />\n <Stat label={t('pages.dashboard.connectingServers')} value={stats.connecting} tone=\"warn\" />\n <Stat label={t('pages.dashboard.offlineServers')} value={stats.offline} tone=\"err\" />\n <Stat label={t('pages.dashboard.disabledServers')} value={stats.disabled} tone=\"muted\" />\n <Stat label={t('cost.totalFootprint')} value={formatTokens(footprint)} />\n </div>\n )}\n\n {/* Recent servers */}\n {allServers.length > 0 && !showSkeleton && (\n <div className=\"hub-card overflow-hidden mb-6\">\n <div\n className=\"flex items-center justify-between px-4 py-3\"\n style={{ borderBottom: '1px solid var(--hub-line-2)' }}\n >\n <h3 className=\"hub-card-title\">{t('pages.dashboard.recentServers')}</h3>\n <button\n className=\"hub-btn ghost sm\"\n style={{ color: 'var(--hub-ink-3)' }}\n onClick={() => navigate('/servers')}\n >\n {t('common.viewAll') || 'View all'}\n <ChevronRight size={12} />\n </button>\n </div>\n <div\n className=\"hub-row head hub-mono\"\n style={{ gridTemplateColumns: recentServerColumns }}\n >\n <div>{t('server.name')}</div>\n <div>{t('server.status')}</div>\n <div>{t('common.type') || 'Transport'}</div>\n <div>{t('server.tools')}</div>\n <div>{t('server.prompts')}</div>\n <div>{t('nav.resources')}</div>\n <div>{t('server.enabled')}</div>\n </div>\n {recentServers.map((s) => (\n <div\n key={s.name}\n className=\"hub-row hover cursor-pointer\"\n style={{ gridTemplateColumns: recentServerColumns }}\n onClick={() => navigate('/servers')}\n >\n <div className=\"flex items-center gap-2 min-w-0\">\n <span\n className=\"hub-mono truncate\"\n style={{ fontSize: 13, color: s.enabled === false ? 'var(--hub-ink-3)' : 'var(--hub-ink)' }}\n >\n {s.name}\n </span>\n {s.error && <AlertCircle size={13} className=\"text-[var(--hub-err)] flex-shrink-0\" />}\n </div>\n <div className=\"min-w-0\">\n <ServerStatusDot status={s.status} enabled={s.enabled} />\n </div>\n <div className=\"min-w-0\">\n {s.config?.type ? (\n <span className=\"hub-tag\" title={transportLabel(t, s.config.type) ?? undefined}>\n {transportLabel(t, s.config.type)}\n </span>\n ) : (\n <span style={{ color: 'var(--hub-ink-3)', fontSize: 12 }}>—</span>\n )}\n </div>\n <div className=\"hub-num hub-mono\" style={{ fontSize: 12.5 }}>\n {s.tools?.length || 0}\n </div>\n <div className=\"hub-num hub-mono\" style={{ fontSize: 12.5, color: 'var(--hub-ink-2)' }}>\n {s.prompts?.length || 0}\n </div>\n <div className=\"hub-num hub-mono\" style={{ fontSize: 12.5, color: 'var(--hub-ink-2)' }}>\n {s.resources?.length || 0}\n </div>\n <div className=\"text-[12px]\" style={{ color: s.enabled !== false ? 'var(--hub-ok)' : 'var(--hub-ink-3)' }}>\n {s.enabled !== false ? '✓' : '—'}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* Endpoint quick-access */}\n <div className=\"hub-card mb-5\" style={{ padding: 16 }}>\n <div className=\"flex justify-between items-start gap-3 mb-3\">\n <div>\n <h3 className=\"hub-card-title\">{t('pages.dashboard.endpoints') || 'MCP Endpoints'}</h3>\n <p className=\"hub-sub\" style={{ marginTop: 2 }}>\n {t('pages.dashboard.endpointsHint') ||\n 'Use these URLs in Claude Desktop, Cursor, or any MCP client'}\n </p>\n </div>\n <a\n className=\"hub-btn ghost\"\n href=\"https://docs.mcphub.app\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{ color: 'var(--hub-ink-3)' }}\n >\n {t('common.docs') || 'Docs'} →\n </a>\n </div>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-2.5\">\n <EndpointCopy label=\"ALL\" url={`${baseUrl}/mcp`} />\n <EndpointCopy label=\"SMART\" url={`${baseUrl}/mcp/${getSmartRoutingPath()}`} />\n {groups.slice(0, 2).map((g) => (\n <EndpointCopy key={g.id} label=\"GROUP\" url={`${baseUrl}/mcp/${g.name}`} />\n ))}\n {/* Pad with first server endpoint if there's space */}\n {groups.length < 2 && allServers[0] && (\n <EndpointCopy label=\"SERVER\" url={`${baseUrl}/mcp/${allServers[0].name}`} />\n )}\n </div>\n </div>\n </div>\n );\n};\n\nexport default DashboardPage;\n"],"names":["Stat","label","value","tone","toneColor","jsxs","jsx","transportLabel","t","type","DashboardPage","useTranslation","navigate","useNavigate","allServers","error","setError","isLoading","triggerRefresh","useServerData","groups","useGroupData","installConfig","useSettingsData","serverCosts","useCostData","hasLoaded","setHasLoaded","React","loadingStartedRef","stats","useMemo","acc","s","_a","footprint","c","recentServers","baseUrl","recentServerColumns","showSkeleton","RefreshCw","Plus","AlertCircle","_","i","formatTokens","ChevronRight","ServerStatusDot","_b","_c","_d","EndpointCopy","getSmartRoutingPath","g"],"mappings":"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"}
1
+ {"version":3,"file":"Dashboard-CwifBwm4.js","sources":["../../src/pages/Dashboard.tsx"],"sourcesContent":["import { getSmartRoutingPath } from '@/utils/runtime';\nimport React, { useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useNavigate } from 'react-router-dom';\nimport { RefreshCw, Plus, ChevronRight, AlertCircle } from 'lucide-react';\nimport { useServerData } from '@/hooks/useServerData';\nimport { useGroupData } from '@/hooks/useGroupData';\nimport { useSettingsData } from '@/hooks/useSettingsData';\nimport { useCostData } from '@/hooks/useCostData';\nimport { formatTokens } from '@/utils/contextCost';\nimport { Server } from '@/types';\nimport { EndpointCopy } from '@/components/ui/EndpointCopy';\nimport { ServerStatusDot } from '@/components/ui/StatusDot';\n\nconst Stat: React.FC<{ label: string; value: React.ReactNode; tone?: 'ok' | 'warn' | 'err' | 'muted' | 'default' }> = ({\n label,\n value,\n tone = 'default',\n}) => {\n const toneColor =\n tone === 'ok'\n ? 'oklch(0.4 0.13 145)'\n : tone === 'warn'\n ? 'oklch(0.45 0.13 80)'\n : tone === 'err'\n ? 'oklch(0.45 0.18 25)'\n : tone === 'muted'\n ? 'var(--hub-ink-3)'\n : 'var(--hub-ink)';\n return (\n <div className=\"hub-card\" style={{ padding: '14px 16px' }}>\n <div className=\"text-[12px]\" style={{ color: 'var(--hub-ink-3)' }}>\n {label}\n </div>\n <div\n className=\"hub-num\"\n style={{\n fontSize: 26,\n fontWeight: 500,\n letterSpacing: '-0.02em',\n lineHeight: 1.1,\n marginTop: 8,\n color: toneColor,\n }}\n >\n {value}\n </div>\n </div>\n );\n};\n\nconst transportLabel = (t: any, type?: string) => {\n if (!type) return null;\n if (type === 'stdio') return t('server.typeStdio') || 'stdio';\n if (type === 'sse') return t('server.typeSse') || 'sse';\n if (type === 'streamable-http') return t('server.typeStreamableHttp') || 'http';\n if (type === 'openapi') return t('server.typeOpenapi') || 'openapi';\n return type;\n};\n\nconst DashboardPage: React.FC = () => {\n const { t } = useTranslation();\n const navigate = useNavigate();\n const { allServers, error, setError, isLoading, triggerRefresh } = useServerData({\n refreshOnMount: true,\n });\n const { groups } = useGroupData();\n const { installConfig } = useSettingsData();\n const { serverCosts } = useCostData();\n\n const [hasLoaded, setHasLoaded] = React.useState(false);\n const loadingStartedRef = React.useRef(false);\n React.useEffect(() => {\n if (isLoading) {\n loadingStartedRef.current = true;\n return;\n }\n if (loadingStartedRef.current) {\n setHasLoaded(true);\n return;\n }\n if (allServers.length > 0 || error) setHasLoaded(true);\n }, [isLoading, allServers.length, error]);\n\n const stats = useMemo(\n () => ({\n total: allServers.length,\n online: allServers.filter((s: Server) => s.status === 'connected').length,\n disabled: allServers.filter((s: Server) => s.enabled === false).length,\n offline: allServers.filter(\n (s: Server) => s.status === 'disconnected' && s.enabled !== false,\n ).length,\n connecting: allServers.filter(\n (s: Server) =>\n (s.status === 'connecting' || s.status === 'oauth_required') && s.enabled !== false,\n ).length,\n tools: allServers.reduce((acc, s) => acc + (s.tools?.length || 0), 0),\n }),\n [allServers],\n );\n\n const footprint = useMemo(\n () => serverCosts.filter((c) => c.connected).reduce((acc, c) => acc + c.exposed, 0),\n [serverCosts],\n );\n\n const recentServers = useMemo(() => allServers.slice(0, 6), [allServers]);\n const baseUrl = installConfig?.baseUrl?.replace(/\\/+$/, '') || '';\n const recentServerColumns =\n 'minmax(220px,1.9fr) minmax(110px,0.95fr) minmax(120px,0.95fr) 80px 80px 90px 72px';\n\n const showSkeleton = !hasLoaded;\n\n return (\n <div>\n {/* Header */}\n <div className=\"flex items-end justify-between gap-4 mb-6\">\n <div>\n <h1 className=\"hub-h1\">{t('pages.dashboard.title')}</h1>\n <p className=\"hub-sub\">\n {t('pages.dashboard.totalServers')} · <span className=\"hub-num\">{stats.total}</span>\n {' · '}\n {t('pages.dashboard.onlineServers')} · <span className=\"hub-num\">{stats.online}</span>\n </p>\n </div>\n <div className=\"flex gap-2\">\n <button className=\"hub-btn\" onClick={() => triggerRefresh()}>\n <RefreshCw size={13} /> {t('common.refresh')}\n </button>\n <button className=\"hub-btn primary\" onClick={() => navigate('/servers')}>\n <Plus size={13} /> {t('server.add')}\n </button>\n </div>\n </div>\n\n {error && (\n <div\n className=\"hub-card flex items-center justify-between gap-3 mb-5\"\n style={{\n padding: '10px 14px',\n borderColor: 'oklch(0.85 0.1 25)',\n background: 'oklch(0.97 0.03 25)',\n color: 'oklch(0.4 0.18 25)',\n }}\n >\n <div className=\"flex items-center gap-2 min-w-0\">\n <AlertCircle size={14} className=\"flex-shrink-0\" />\n <span className=\"truncate text-[13px]\">{error}</span>\n </div>\n <button\n className=\"hub-icon-btn sm\"\n onClick={() => setError(null)}\n aria-label={t('app.closeButton')}\n >\n ✕\n </button>\n </div>\n )}\n\n {/* Stat row */}\n {showSkeleton ? (\n <div className=\"grid grid-cols-2 md:grid-cols-6 gap-3 mb-6\">\n {Array.from({ length: 6 }).map((_, i) => (\n <div\n key={i}\n className=\"hub-card animate-pulse\"\n style={{ padding: '14px 16px', height: 78 }}\n />\n ))}\n </div>\n ) : (\n <div className=\"grid grid-cols-2 md:grid-cols-6 gap-3 mb-6\">\n <Stat label={t('pages.dashboard.totalServers')} value={stats.total} />\n <Stat label={t('pages.dashboard.onlineServers')} value={stats.online} tone=\"ok\" />\n <Stat label={t('pages.dashboard.connectingServers')} value={stats.connecting} tone=\"warn\" />\n <Stat label={t('pages.dashboard.offlineServers')} value={stats.offline} tone=\"err\" />\n <Stat label={t('pages.dashboard.disabledServers')} value={stats.disabled} tone=\"muted\" />\n <Stat label={t('cost.totalFootprint')} value={formatTokens(footprint)} />\n </div>\n )}\n\n {/* Recent servers */}\n {allServers.length > 0 && !showSkeleton && (\n <div className=\"hub-card overflow-hidden mb-6\">\n <div\n className=\"flex items-center justify-between px-4 py-3\"\n style={{ borderBottom: '1px solid var(--hub-line-2)' }}\n >\n <h3 className=\"hub-card-title\">{t('pages.dashboard.recentServers')}</h3>\n <button\n className=\"hub-btn ghost sm\"\n style={{ color: 'var(--hub-ink-3)' }}\n onClick={() => navigate('/servers')}\n >\n {t('common.viewAll') || 'View all'}\n <ChevronRight size={12} />\n </button>\n </div>\n <div\n className=\"hub-row head hub-mono\"\n style={{ gridTemplateColumns: recentServerColumns }}\n >\n <div>{t('server.name')}</div>\n <div>{t('server.status')}</div>\n <div>{t('common.type') || 'Transport'}</div>\n <div>{t('server.tools')}</div>\n <div>{t('server.prompts')}</div>\n <div>{t('nav.resources')}</div>\n <div>{t('server.enabled')}</div>\n </div>\n {recentServers.map((s) => (\n <div\n key={s.name}\n className=\"hub-row hover cursor-pointer\"\n style={{ gridTemplateColumns: recentServerColumns }}\n onClick={() => navigate('/servers')}\n >\n <div className=\"flex items-center gap-2 min-w-0\">\n <span\n className=\"hub-mono truncate\"\n style={{ fontSize: 13, color: s.enabled === false ? 'var(--hub-ink-3)' : 'var(--hub-ink)' }}\n >\n {s.name}\n </span>\n {s.error && <AlertCircle size={13} className=\"text-[var(--hub-err)] flex-shrink-0\" />}\n </div>\n <div className=\"min-w-0\">\n <ServerStatusDot status={s.status} enabled={s.enabled} />\n </div>\n <div className=\"min-w-0\">\n {s.config?.type ? (\n <span className=\"hub-tag\" title={transportLabel(t, s.config.type) ?? undefined}>\n {transportLabel(t, s.config.type)}\n </span>\n ) : (\n <span style={{ color: 'var(--hub-ink-3)', fontSize: 12 }}>—</span>\n )}\n </div>\n <div className=\"hub-num hub-mono\" style={{ fontSize: 12.5 }}>\n {s.tools?.length || 0}\n </div>\n <div className=\"hub-num hub-mono\" style={{ fontSize: 12.5, color: 'var(--hub-ink-2)' }}>\n {s.prompts?.length || 0}\n </div>\n <div className=\"hub-num hub-mono\" style={{ fontSize: 12.5, color: 'var(--hub-ink-2)' }}>\n {s.resources?.length || 0}\n </div>\n <div className=\"text-[12px]\" style={{ color: s.enabled !== false ? 'var(--hub-ok)' : 'var(--hub-ink-3)' }}>\n {s.enabled !== false ? '✓' : '—'}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* Endpoint quick-access */}\n <div className=\"hub-card mb-5\" style={{ padding: 16 }}>\n <div className=\"flex justify-between items-start gap-3 mb-3\">\n <div>\n <h3 className=\"hub-card-title\">{t('pages.dashboard.endpoints') || 'MCP Endpoints'}</h3>\n <p className=\"hub-sub\" style={{ marginTop: 2 }}>\n {t('pages.dashboard.endpointsHint') ||\n 'Use these URLs in Claude Desktop, Cursor, or any MCP client'}\n </p>\n </div>\n <a\n className=\"hub-btn ghost\"\n href=\"https://docs.mcphub.app\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{ color: 'var(--hub-ink-3)' }}\n >\n {t('common.docs') || 'Docs'} →\n </a>\n </div>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-2.5\">\n <EndpointCopy label=\"ALL\" url={`${baseUrl}/mcp`} />\n <EndpointCopy label=\"SMART\" url={`${baseUrl}/mcp/${getSmartRoutingPath()}`} />\n {groups.slice(0, 2).map((g) => (\n <EndpointCopy key={g.id} label=\"GROUP\" url={`${baseUrl}/mcp/${g.name}`} />\n ))}\n {/* Pad with first server endpoint if there's space */}\n {groups.length < 2 && allServers[0] && (\n <EndpointCopy label=\"SERVER\" url={`${baseUrl}/mcp/${allServers[0].name}`} />\n )}\n </div>\n </div>\n </div>\n );\n};\n\nexport default DashboardPage;\n"],"names":["Stat","label","value","tone","toneColor","jsxs","jsx","transportLabel","t","type","DashboardPage","useTranslation","navigate","useNavigate","allServers","error","setError","isLoading","triggerRefresh","useServerData","groups","useGroupData","installConfig","useSettingsData","serverCosts","useCostData","hasLoaded","setHasLoaded","React","loadingStartedRef","stats","useMemo","acc","s","_a","footprint","c","recentServers","baseUrl","recentServerColumns","showSkeleton","RefreshCw","Plus","AlertCircle","_","i","formatTokens","ChevronRight","ServerStatusDot","_b","_c","_d","EndpointCopy","getSmartRoutingPath","g"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{j as s}from"./framework-vendor-D0S_ys6r.js";import{u as i}from"./i18n-vendor-COTriSc6.js";const d=({isOpen:a,onClose:r,onConfirm:c,serverName:n,isGroup:l=!1,isUser:t=!1})=>{const{t:e}=i();return a?s.jsx("div",{className:"fixed inset-0 bg-black/50 bg-opacity-30 z-50 flex items-center justify-center p-4",children:s.jsx("div",{className:"hub-card max-w-md w-full",children:s.jsxs("div",{className:"p-6",children:[s.jsx("h3",{className:"text-lg font-medium text-gray-900 mb-3",children:e(t?"users.confirmDelete":l?"groups.confirmDelete":"server.confirmDelete")}),s.jsx("p",{className:"text-gray-500 mb-6",children:t?e("users.deleteWarning",{username:n}):l?e("groups.deleteWarning",{name:n}):e("server.deleteWarning",{name:n})}),s.jsxs("div",{className:"flex justify-end space-x-3",children:[s.jsx("button",{onClick:r,className:"hub-btn",children:e("common.cancel")}),s.jsx("button",{onClick:c,className:"hub-btn danger",children:e("common.delete")})]})]})})}):null};export{d as D};
2
- //# sourceMappingURL=DeleteDialog-BoMYLx3J.js.map
1
+ import{j as s}from"./framework-vendor-D0S_ys6r.js";import{u as i}from"./i18n-vendor-CPneThYa.js";const d=({isOpen:a,onClose:r,onConfirm:c,serverName:n,isGroup:l=!1,isUser:t=!1})=>{const{t:e}=i();return a?s.jsx("div",{className:"fixed inset-0 bg-black/50 bg-opacity-30 z-50 flex items-center justify-center p-4",children:s.jsx("div",{className:"hub-card max-w-md w-full",children:s.jsxs("div",{className:"p-6",children:[s.jsx("h3",{className:"text-lg font-medium text-gray-900 mb-3",children:e(t?"users.confirmDelete":l?"groups.confirmDelete":"server.confirmDelete")}),s.jsx("p",{className:"text-gray-500 mb-6",children:t?e("users.deleteWarning",{username:n}):l?e("groups.deleteWarning",{name:n}):e("server.deleteWarning",{name:n})}),s.jsxs("div",{className:"flex justify-end space-x-3",children:[s.jsx("button",{onClick:r,className:"hub-btn",children:e("common.cancel")}),s.jsx("button",{onClick:c,className:"hub-btn danger",children:e("common.delete")})]})]})})}):null};export{d as D};
2
+ //# sourceMappingURL=DeleteDialog-BkEKW9LB.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DeleteDialog-BoMYLx3J.js","sources":["../../src/components/ui/DeleteDialog.tsx"],"sourcesContent":["import { useTranslation } from 'react-i18next'\n\ninterface DeleteDialogProps {\n isOpen: boolean\n onClose: () => void\n onConfirm: () => void\n serverName: string\n isGroup?: boolean\n isUser?: boolean\n}\n\nconst DeleteDialog = ({ isOpen, onClose, onConfirm, serverName, isGroup = false, isUser = false }: DeleteDialogProps) => {\n const { t } = useTranslation()\n\n if (!isOpen) return null\n\n return (\n <div className=\"fixed inset-0 bg-black/50 bg-opacity-30 z-50 flex items-center justify-center p-4\">\n <div className=\"hub-card max-w-md w-full\">\n <div className=\"p-6\">\n <h3 className=\"text-lg font-medium text-gray-900 mb-3\">\n {isUser\n ? t('users.confirmDelete')\n : isGroup\n ? t('groups.confirmDelete')\n : t('server.confirmDelete')}\n </h3>\n <p className=\"text-gray-500 mb-6\">\n {isUser\n ? t('users.deleteWarning', { username: serverName })\n : isGroup\n ? t('groups.deleteWarning', { name: serverName })\n : t('server.deleteWarning', { name: serverName })}\n </p>\n <div className=\"flex justify-end space-x-3\">\n <button\n onClick={onClose}\n className=\"hub-btn\"\n >\n {t('common.cancel')}\n </button>\n <button\n onClick={onConfirm}\n className=\"hub-btn danger\"\n >\n {t('common.delete')}\n </button>\n </div>\n </div>\n </div>\n </div>\n )\n}\n\nexport default DeleteDialog"],"names":["DeleteDialog","isOpen","onClose","onConfirm","serverName","isGroup","isUser","t","useTranslation","jsx","jsxs"],"mappings":"iGAWA,MAAMA,EAAe,CAAC,CAAE,OAAAC,EAAQ,QAAAC,EAAS,UAAAC,EAAW,WAAAC,EAAY,QAAAC,EAAU,GAAO,OAAAC,EAAS,MAA+B,CACvH,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAA,EAEd,OAAKP,EAGHQ,EAAAA,IAAC,MAAA,CAAI,UAAU,oFACb,SAAAA,EAAAA,IAAC,MAAA,CAAI,UAAU,2BACb,SAAAC,EAAAA,KAAC,MAAA,CAAI,UAAU,MACb,SAAA,CAAAD,EAAAA,IAAC,KAAA,CAAG,UAAU,yCACX,SACGF,EADHD,EACK,sBACFD,EACI,uBACA,sBAHmB,EAI7B,EACAI,EAAAA,IAAC,IAAA,CAAE,UAAU,qBACV,SAAAH,EACGC,EAAE,sBAAuB,CAAE,SAAUH,CAAA,CAAY,EACjDC,EACEE,EAAE,uBAAwB,CAAE,KAAMH,CAAA,CAAY,EAC9CG,EAAE,uBAAwB,CAAE,KAAMH,CAAA,CAAY,CAAA,CACtD,EACAM,EAAAA,KAAC,MAAA,CAAI,UAAU,6BACb,SAAA,CAAAD,EAAAA,IAAC,SAAA,CACC,QAASP,EACT,UAAU,UAET,WAAE,eAAe,CAAA,CAAA,EAEpBO,EAAAA,IAAC,SAAA,CACC,QAASN,EACT,UAAU,iBAET,WAAE,eAAe,CAAA,CAAA,CACpB,CAAA,CACF,CAAA,CAAA,CACF,EACF,EACF,EApCkB,IAsCtB"}
1
+ {"version":3,"file":"DeleteDialog-BkEKW9LB.js","sources":["../../src/components/ui/DeleteDialog.tsx"],"sourcesContent":["import { useTranslation } from 'react-i18next'\n\ninterface DeleteDialogProps {\n isOpen: boolean\n onClose: () => void\n onConfirm: () => void\n serverName: string\n isGroup?: boolean\n isUser?: boolean\n}\n\nconst DeleteDialog = ({ isOpen, onClose, onConfirm, serverName, isGroup = false, isUser = false }: DeleteDialogProps) => {\n const { t } = useTranslation()\n\n if (!isOpen) return null\n\n return (\n <div className=\"fixed inset-0 bg-black/50 bg-opacity-30 z-50 flex items-center justify-center p-4\">\n <div className=\"hub-card max-w-md w-full\">\n <div className=\"p-6\">\n <h3 className=\"text-lg font-medium text-gray-900 mb-3\">\n {isUser\n ? t('users.confirmDelete')\n : isGroup\n ? t('groups.confirmDelete')\n : t('server.confirmDelete')}\n </h3>\n <p className=\"text-gray-500 mb-6\">\n {isUser\n ? t('users.deleteWarning', { username: serverName })\n : isGroup\n ? t('groups.deleteWarning', { name: serverName })\n : t('server.deleteWarning', { name: serverName })}\n </p>\n <div className=\"flex justify-end space-x-3\">\n <button\n onClick={onClose}\n className=\"hub-btn\"\n >\n {t('common.cancel')}\n </button>\n <button\n onClick={onConfirm}\n className=\"hub-btn danger\"\n >\n {t('common.delete')}\n </button>\n </div>\n </div>\n </div>\n </div>\n )\n}\n\nexport default DeleteDialog"],"names":["DeleteDialog","isOpen","onClose","onConfirm","serverName","isGroup","isUser","t","useTranslation","jsx","jsxs"],"mappings":"iGAWA,MAAMA,EAAe,CAAC,CAAE,OAAAC,EAAQ,QAAAC,EAAS,UAAAC,EAAW,WAAAC,EAAY,QAAAC,EAAU,GAAO,OAAAC,EAAS,MAA+B,CACvH,KAAM,CAAE,EAAAC,CAAA,EAAMC,EAAA,EAEd,OAAKP,EAGHQ,EAAAA,IAAC,MAAA,CAAI,UAAU,oFACb,SAAAA,EAAAA,IAAC,MAAA,CAAI,UAAU,2BACb,SAAAC,EAAAA,KAAC,MAAA,CAAI,UAAU,MACb,SAAA,CAAAD,EAAAA,IAAC,KAAA,CAAG,UAAU,yCACX,SACGF,EADHD,EACK,sBACFD,EACI,uBACA,sBAHmB,EAI7B,EACAI,EAAAA,IAAC,IAAA,CAAE,UAAU,qBACV,SAAAH,EACGC,EAAE,sBAAuB,CAAE,SAAUH,CAAA,CAAY,EACjDC,EACEE,EAAE,uBAAwB,CAAE,KAAMH,CAAA,CAAY,EAC9CG,EAAE,uBAAwB,CAAE,KAAMH,CAAA,CAAY,CAAA,CACtD,EACAM,EAAAA,KAAC,MAAA,CAAI,UAAU,6BACb,SAAA,CAAAD,EAAAA,IAAC,SAAA,CACC,QAASP,EACT,UAAU,UAET,WAAE,eAAe,CAAA,CAAA,EAEpBO,EAAAA,IAAC,SAAA,CACC,QAASN,EACT,UAAU,iBAET,WAAE,eAAe,CAAA,CAAA,CACpB,CAAA,CACF,CAAA,CAAA,CACF,EACF,EACF,EApCkB,IAsCtB"}
@@ -1,2 +1,2 @@
1
- import{r as y,j as o}from"./framework-vendor-D0S_ys6r.js";import{k as h,o as r}from"./index-CGRjM_NC.js";import{c as x}from"./clipboard-BLr_gbf8.js";import{u as C}from"./i18n-vendor-COTriSc6.js";import{C as b,r as j}from"./icons-vendor-DZjjGrOu.js";const g=({url:s,label:e,prefix:a,className:p,copyValue:m,ariaLabel:l})=>{const{t}=C(),{showToast:c}=h(),[n,i]=y.useState(!1),d=async u=>{if(u.stopPropagation(),!await x(m??s)){c(t("common.copyFailed")||"Copy failed","error");return}i(!0),c(t("common.copySuccess")||"Copied to clipboard","success"),setTimeout(()=>i(!1),1200)};return o.jsxs("div",{className:r("hub-endpoint",p),role:"group","aria-label":l||s,children:[e&&o.jsx("div",{className:"hub-endpoint-label",children:e}),o.jsxs("div",{className:"hub-endpoint-url",title:s,children:[a&&o.jsx("span",{style:{color:"var(--hub-ink-3)"},children:a}),s]}),o.jsx("button",{type:"button",onClick:d,className:r("hub-endpoint-copy",n?"copied":""),title:t("common.copy")||"Copy","aria-label":t("common.copy")||"Copy",children:n?o.jsx(b,{size:13}):o.jsx(j,{size:13})})]})};export{g as E};
2
- //# sourceMappingURL=EndpointCopy-CZOjiFAH.js.map
1
+ import{r as y,j as o}from"./framework-vendor-D0S_ys6r.js";import{l as h,o as r}from"./index-DKX_BExz.js";import{c as x}from"./clipboard-BYlVdxdy.js";import{u as C}from"./i18n-vendor-CPneThYa.js";import{C as b,r as j}from"./icons-vendor-DZjjGrOu.js";const g=({url:s,label:e,prefix:a,className:p,copyValue:l,ariaLabel:m})=>{const{t}=C(),{showToast:c}=h(),[n,i]=y.useState(!1),d=async u=>{if(u.stopPropagation(),!await x(l??s)){c(t("common.copyFailed")||"Copy failed","error");return}i(!0),c(t("common.copySuccess")||"Copied to clipboard","success"),setTimeout(()=>i(!1),1200)};return o.jsxs("div",{className:r("hub-endpoint",p),role:"group","aria-label":m||s,children:[e&&o.jsx("div",{className:"hub-endpoint-label",children:e}),o.jsxs("div",{className:"hub-endpoint-url",title:s,children:[a&&o.jsx("span",{style:{color:"var(--hub-ink-3)"},children:a}),s]}),o.jsx("button",{type:"button",onClick:d,className:r("hub-endpoint-copy",n?"copied":""),title:t("common.copy")||"Copy","aria-label":t("common.copy")||"Copy",children:n?o.jsx(b,{size:13}):o.jsx(j,{size:13})})]})};export{g as E};
2
+ //# sourceMappingURL=EndpointCopy-BeLf_ow_.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"EndpointCopy-CZOjiFAH.js","sources":["../../src/components/ui/EndpointCopy.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { Copy, Check } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { useToast } from '@/contexts/ToastContext';\nimport { copyText } from '@/utils/clipboard';\nimport { cn } from '@/utils/cn';\n\ninterface EndpointCopyProps {\n url: string;\n label?: string;\n prefix?: string;\n className?: string;\n /** Optionally override the value placed on the clipboard. */\n copyValue?: string;\n ariaLabel?: string;\n}\n\nexport const EndpointCopy: React.FC<EndpointCopyProps> = ({\n url,\n label,\n prefix,\n className,\n copyValue,\n ariaLabel,\n}) => {\n const { t } = useTranslation();\n const { showToast } = useToast();\n const [copied, setCopied] = useState(false);\n\n const onCopy = async (e: React.MouseEvent) => {\n e.stopPropagation();\n const ok = await copyText(copyValue ?? url);\n if (!ok) {\n showToast(t('common.copyFailed') || 'Copy failed', 'error');\n return;\n }\n setCopied(true);\n showToast(t('common.copySuccess') || 'Copied to clipboard', 'success');\n setTimeout(() => setCopied(false), 1200);\n };\n\n return (\n <div className={cn('hub-endpoint', className)} role=\"group\" aria-label={ariaLabel || url}>\n {label && <div className=\"hub-endpoint-label\">{label}</div>}\n <div className=\"hub-endpoint-url\" title={url}>\n {prefix && <span style={{ color: 'var(--hub-ink-3)' }}>{prefix}</span>}\n {url}\n </div>\n <button\n type=\"button\"\n onClick={onCopy}\n className={cn('hub-endpoint-copy', copied ? 'copied' : '')}\n title={t('common.copy') || 'Copy'}\n aria-label={t('common.copy') || 'Copy'}\n >\n {copied ? <Check size={13} /> : <Copy size={13} />}\n </button>\n </div>\n );\n};\n\ninterface MonoCopyProps {\n text: string;\n className?: string;\n copyValue?: string;\n title?: string;\n}\n\n/** Inline monospace value with hover-to-copy icon. */\nexport const MonoCopy: React.FC<MonoCopyProps> = ({ text, className, copyValue, title }) => {\n const { t } = useTranslation();\n const { showToast } = useToast();\n const [copied, setCopied] = useState(false);\n\n const onCopy = async (e: React.MouseEvent) => {\n e.stopPropagation();\n const ok = await copyText(copyValue ?? text);\n if (!ok) {\n showToast(t('common.copyFailed') || 'Copy failed', 'error');\n return;\n }\n setCopied(true);\n showToast(t('common.copySuccess') || 'Copied to clipboard', 'success');\n setTimeout(() => setCopied(false), 1200);\n };\n\n return (\n <span\n className={cn(\n 'hub-mono inline-flex items-center gap-1.5 group cursor-pointer text-[12.5px]',\n className,\n )}\n onClick={onCopy}\n title={title || text}\n role=\"button\"\n >\n <span className=\"truncate\">{text}</span>\n {copied ? (\n <Check size={12} className=\"text-[var(--hub-ok)] flex-shrink-0\" />\n ) : (\n <Copy\n size={12}\n className=\"text-[var(--hub-ink-3)] opacity-0 group-hover:opacity-100 transition-opacity flex-shrink-0\"\n />\n )}\n </span>\n );\n};\n"],"names":["EndpointCopy","url","label","prefix","className","copyValue","ariaLabel","useTranslation","showToast","useToast","copied","setCopied","useState","onCopy","e","copyText","jsxs","cn","jsx","Check","Copy"],"mappings":"yPAiBO,MAAMA,EAA4C,CAAC,CACxD,IAAAC,EACA,MAAAC,EACA,OAAAC,EACA,UAAAC,EACA,UAAAC,EACA,UAAAC,CACF,IAAM,CACJ,KAAM,CAAE,CAAA,EAAMC,EAAA,EACR,CAAE,UAAAC,CAAA,EAAcC,EAAA,EAChB,CAACC,EAAQC,CAAS,EAAIC,EAAAA,SAAS,EAAK,EAEpCC,EAAS,MAAOC,GAAwB,CAG5C,GAFAA,EAAE,gBAAA,EAEE,CADO,MAAMC,EAASV,GAAaJ,CAAG,EACjC,CACPO,EAAU,EAAE,mBAAmB,GAAK,cAAe,OAAO,EAC1D,MACF,CACAG,EAAU,EAAI,EACdH,EAAU,EAAE,oBAAoB,GAAK,sBAAuB,SAAS,EACrE,WAAW,IAAMG,EAAU,EAAK,EAAG,IAAI,CACzC,EAEA,OACEK,EAAAA,KAAC,MAAA,CAAI,UAAWC,EAAG,eAAgBb,CAAS,EAAG,KAAK,QAAQ,aAAYE,GAAaL,EAClF,SAAA,CAAAC,GAASgB,EAAAA,IAAC,MAAA,CAAI,UAAU,qBAAsB,SAAAhB,EAAM,EACrDc,EAAAA,KAAC,MAAA,CAAI,UAAU,mBAAmB,MAAOf,EACtC,SAAA,CAAAE,SAAW,OAAA,CAAK,MAAO,CAAE,MAAO,kBAAA,EAAuB,SAAAA,EAAO,EAC9DF,CAAA,EACH,EACAiB,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,QAASL,EACT,UAAWI,EAAG,oBAAqBP,EAAS,SAAW,EAAE,EACzD,MAAO,EAAE,aAAa,GAAK,OAC3B,aAAY,EAAE,aAAa,GAAK,OAE/B,SAAAA,QAAUS,EAAA,CAAM,KAAM,GAAI,EAAKD,EAAAA,IAACE,EAAA,CAAK,KAAM,EAAA,CAAI,CAAA,CAAA,CAClD,EACF,CAEJ"}
1
+ {"version":3,"file":"EndpointCopy-BeLf_ow_.js","sources":["../../src/components/ui/EndpointCopy.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { Copy, Check } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { useToast } from '@/contexts/ToastContext';\nimport { copyText } from '@/utils/clipboard';\nimport { cn } from '@/utils/cn';\n\ninterface EndpointCopyProps {\n url: string;\n label?: string;\n prefix?: string;\n className?: string;\n /** Optionally override the value placed on the clipboard. */\n copyValue?: string;\n ariaLabel?: string;\n}\n\nexport const EndpointCopy: React.FC<EndpointCopyProps> = ({\n url,\n label,\n prefix,\n className,\n copyValue,\n ariaLabel,\n}) => {\n const { t } = useTranslation();\n const { showToast } = useToast();\n const [copied, setCopied] = useState(false);\n\n const onCopy = async (e: React.MouseEvent) => {\n e.stopPropagation();\n const ok = await copyText(copyValue ?? url);\n if (!ok) {\n showToast(t('common.copyFailed') || 'Copy failed', 'error');\n return;\n }\n setCopied(true);\n showToast(t('common.copySuccess') || 'Copied to clipboard', 'success');\n setTimeout(() => setCopied(false), 1200);\n };\n\n return (\n <div className={cn('hub-endpoint', className)} role=\"group\" aria-label={ariaLabel || url}>\n {label && <div className=\"hub-endpoint-label\">{label}</div>}\n <div className=\"hub-endpoint-url\" title={url}>\n {prefix && <span style={{ color: 'var(--hub-ink-3)' }}>{prefix}</span>}\n {url}\n </div>\n <button\n type=\"button\"\n onClick={onCopy}\n className={cn('hub-endpoint-copy', copied ? 'copied' : '')}\n title={t('common.copy') || 'Copy'}\n aria-label={t('common.copy') || 'Copy'}\n >\n {copied ? <Check size={13} /> : <Copy size={13} />}\n </button>\n </div>\n );\n};\n\ninterface MonoCopyProps {\n text: string;\n className?: string;\n copyValue?: string;\n title?: string;\n}\n\n/** Inline monospace value with hover-to-copy icon. */\nexport const MonoCopy: React.FC<MonoCopyProps> = ({ text, className, copyValue, title }) => {\n const { t } = useTranslation();\n const { showToast } = useToast();\n const [copied, setCopied] = useState(false);\n\n const onCopy = async (e: React.MouseEvent) => {\n e.stopPropagation();\n const ok = await copyText(copyValue ?? text);\n if (!ok) {\n showToast(t('common.copyFailed') || 'Copy failed', 'error');\n return;\n }\n setCopied(true);\n showToast(t('common.copySuccess') || 'Copied to clipboard', 'success');\n setTimeout(() => setCopied(false), 1200);\n };\n\n return (\n <span\n className={cn(\n 'hub-mono inline-flex items-center gap-1.5 group cursor-pointer text-[12.5px]',\n className,\n )}\n onClick={onCopy}\n title={title || text}\n role=\"button\"\n >\n <span className=\"truncate\">{text}</span>\n {copied ? (\n <Check size={12} className=\"text-[var(--hub-ok)] flex-shrink-0\" />\n ) : (\n <Copy\n size={12}\n className=\"text-[var(--hub-ink-3)] opacity-0 group-hover:opacity-100 transition-opacity flex-shrink-0\"\n />\n )}\n </span>\n );\n};\n"],"names":["EndpointCopy","url","label","prefix","className","copyValue","ariaLabel","useTranslation","showToast","useToast","copied","setCopied","useState","onCopy","e","copyText","jsxs","cn","jsx","Check","Copy"],"mappings":"yPAiBO,MAAMA,EAA4C,CAAC,CACxD,IAAAC,EACA,MAAAC,EACA,OAAAC,EACA,UAAAC,EACA,UAAAC,EACA,UAAAC,CACF,IAAM,CACJ,KAAM,CAAE,CAAA,EAAMC,EAAA,EACR,CAAE,UAAAC,CAAA,EAAcC,EAAA,EAChB,CAACC,EAAQC,CAAS,EAAIC,EAAAA,SAAS,EAAK,EAEpCC,EAAS,MAAOC,GAAwB,CAG5C,GAFAA,EAAE,gBAAA,EAEE,CADO,MAAMC,EAASV,GAAaJ,CAAG,EACjC,CACPO,EAAU,EAAE,mBAAmB,GAAK,cAAe,OAAO,EAC1D,MACF,CACAG,EAAU,EAAI,EACdH,EAAU,EAAE,oBAAoB,GAAK,sBAAuB,SAAS,EACrE,WAAW,IAAMG,EAAU,EAAK,EAAG,IAAI,CACzC,EAEA,OACEK,EAAAA,KAAC,MAAA,CAAI,UAAWC,EAAG,eAAgBb,CAAS,EAAG,KAAK,QAAQ,aAAYE,GAAaL,EAClF,SAAA,CAAAC,GAASgB,EAAAA,IAAC,MAAA,CAAI,UAAU,qBAAsB,SAAAhB,EAAM,EACrDc,EAAAA,KAAC,MAAA,CAAI,UAAU,mBAAmB,MAAOf,EACtC,SAAA,CAAAE,SAAW,OAAA,CAAK,MAAO,CAAE,MAAO,kBAAA,EAAuB,SAAAA,EAAO,EAC9DF,CAAA,EACH,EACAiB,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,QAASL,EACT,UAAWI,EAAG,oBAAqBP,EAAS,SAAW,EAAE,EACzD,MAAO,EAAE,aAAa,GAAK,OAC3B,aAAY,EAAE,aAAa,GAAK,OAE/B,SAAAA,QAAUS,EAAA,CAAM,KAAM,GAAI,EAAKD,EAAAA,IAACE,EAAA,CAAK,KAAM,EAAA,CAAI,CAAA,CAAA,CAClD,EACF,CAEJ"}
@@ -1,4 +1,4 @@
1
- import{r as g,j as e,R as M}from"./framework-vendor-D0S_ys6r.js";import{o as Z,h as fe,e as ee,a as ve,k as je,l as se}from"./index-CGRjM_NC.js";import{u as te,a as re}from"./useCostData-B2d2eLCD.js";import{u as $}from"./i18n-vendor-COTriSc6.js";import{u as me,c as ye}from"./clipboard-BLr_gbf8.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-Dzec2k_b.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 Ue,n as Ge,D as ce,N as Pe,P as de,l as Re,X as Le}from"./icons-vendor-DZjjGrOu.js";import{U as We}from"./UserGroupSelection-CN0weGXJ.js";import{D as $e}from"./DeleteDialog-BoMYLx3J.js";const Oe=["read","create","update","delete","other"],Me=a=>{var s,l,b;if(((s=a.annotations)==null?void 0:s.readOnlyHint)===!0)return"read";const d=a.value.toLowerCase();return/^(delete|remove)[_-]/.test(d)?"delete":((l=a.annotations)==null?void 0:l.destructiveHint)===!0?"other":/^(create|add)[_-]/.test(d)?"create":/^(update|set)[_-]/.test(d)?"update":((b=a.annotations)==null?void 0:b.readOnlyHint)!==!1&&/^(get|list|read|search)[_-]/.test(d)?"read":"other"},He=(a,d,s)=>{const l=d.trim().toLowerCase();return a.filter(b=>{var i,u;return(b.value.toLowerCase().includes(l)||((i=b.description)==null?void 0:i.toLowerCase().includes(l)))&&(s==="all"||((u=b.annotations)==null?void 0:u[s])===!0)})},_e=(a,d,s,l)=>{if(s.length===0||a==="all"&&l==="select")return a;const b=new Set(a==="all"?d:a);for(const i of s)l==="deselect"||l==="invert"&&b.has(i)?b.delete(i):b.add(i);return[...b]},Be=({items:a,selection:d,tools:s,label:l,onChange:b,children:i})=>{const{t:u}=$(),[E,F]=g.useState(""),[w,A]=g.useState("all"),[m,j]=g.useState(!1),y=He(a,E,w),T=new Set(d==="all"?a.map(t=>t.value):d),h=(t,o)=>b(_e(d,a.map(v=>v.value),t.map(v=>v.value),o)),x=s&&m?Oe.map(t=>({risk:t,items:y.filter(o=>Me(o)===t)})):[{risk:null,items:y}],p="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":u("groups.bulkSearchLabel",{capability:l}),placeholder:u("groups.bulkSearch"),value:E,onChange:t=>F(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":u("groups.annotationFilter"),value:w,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:u("groups.allAnnotations")}),["readOnlyHint","destructiveHint","idempotentHint"].map(t=>e.jsx("option",{value:t,children:u(`groups.${t}`)},t))]}),e.jsx("button",{type:"button","aria-pressed":m,onClick:()=>j(!m),className:p,children:u(m?"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:u("groups.visibleCount",{count:y.length,total:a.length})}),["select","deselect","invert"].map(t=>e.jsx("button",{type:"button",disabled:!y.length,onClick:()=>h(y,t),className:p,children:u(`groups.${t}Visible`)},t))]}),s&&m&&e.jsx("p",{className:"text-xs text-gray-500 mb-2",children:u("groups.riskHint")}),e.jsxs("div",{className:"grid grid-cols-1 gap-2 max-h-96 overflow-y-auto",children:[y.length===0&&e.jsx("p",{className:"text-sm text-gray-500",children:u("groups.noMatchingItems")}),x.filter(t=>t.items.length>0).map(t=>{const o=t.items.filter(v=>T.has(v.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:[u(`groups.risk_${t.risk}`)," (",o,"/",t.items.length,")"]}),e.jsx("button",{type:"button",className:p,onClick:()=>h(t.items,o===t.items.length?"deselect":"select"),children:u(o===t.items.length?"groups.selectNone":"groups.selectAll")})]}),t.items.map(v=>e.jsx(M.Fragment,{children:i(v)},v.value))]},t.risk??"flat")})]})]})},Ve={tools:[],prompts:[],resources:[]},ue={tools:"all",prompts:"all",resources:"all"},pe=({servers:a,value:d,onChange:s,className:l,serverCosts:b=[]})=>{const{t:i}=$(),u=M.useId(),{nameSeparator:E,smartRoutingConfig:F}=me(),[w,A]=g.useState(new Set),m=M.useMemo(()=>d.map(r=>typeof r=="string"?{name:r,...ue}:{...r,tools:r.tools||"all",prompts:r.prompts||"all",resources:r.resources||"all"}),[d]),j=M.useMemo(()=>a.filter(r=>r.enabled!==!1),[a]);M.useEffect(()=>{const r=new Set(m.map(n=>n.name)),c=new Set(j.map(n=>n.name));A(n=>{const C=new Set;return n.forEach(f=>{(r.has(f)||c.has(f))&&C.add(f)}),C})},[m,j]);const y=r=>{if(m.findIndex(n=>n.name===r)>=0){const n=m.filter(C=>C.name!==r);s(n)}else{const n=[...m,{name:r,...ue}];s(n)}},T=r=>{A(c=>{const n=new Set(c);return n.has(r)?n.delete(r):n.add(r),n})},h=r=>["tools","prompts","resources"].some(c=>{const n=r[c];return n==="all"||Array.isArray(n)&&n.length>0}),x=(r,c,n,C=!1)=>{const f=m.find(S=>S.name===r),z={...f?{...f}:{name:r,...Ve},[c]:n};if(c==="tools"&&Array.isArray(n)&&z.pinnedTools&&(z.pinnedTools=z.pinnedTools.filter(S=>n.includes(S)),z.pinnedTools.length===0&&delete z.pinnedTools),!h(z)){const S=m.filter(N=>N.name!==r);s(S),C||A(N=>{const W=new Set(N);return W.delete(r),W});return}if(f){s(m.map(S=>S.name===r?z:S));return}s([...m,z])},p=(r,c)=>{const n=m.find(f=>f.name===r);if(!n)return;const C={...n};c?C.alias=c:delete C.alias,s(m.map(f=>f.name===r?C:f))},t=(r,c)=>{const n=m.find(G=>G.name===r);if(!n)return;const C=n.pinnedTools??[],f={...n,pinnedTools:C.includes(c)?C.filter(G=>G!==c):[...C,c]};f.pinnedTools.length===0&&delete f.pinnedTools,s(m.map(G=>G.name===r?f:G))},o=(r,c)=>{const n=`${r}${E}`;return c.startsWith(n)?c.slice(n.length):c},v=(r,c)=>c==="tools"?(r.tools||[]).filter(n=>n.enabled!==!1).map(n=>({key:n.name,value:o(r.name,n.name),description:n.description,annotations:n.annotations,defaultDescription:n.defaultDescription,hasDescriptionOverride:n.hasDescriptionOverride})):c==="prompts"?(r.prompts||[]).filter(n=>n.enabled!==!1).map(n=>({key:n.name,value:o(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})),D=M.useMemo(()=>{const r=new Map;return b.forEach(c=>{const n=new Map;c.items.forEach(C=>n.set(C.name,C.cost)),r.set(c.name,n)}),r},[b]),k=r=>D.get(r)??new Map,U=(r,c)=>{const n=k(r.name);return v(r,c).filter(C=>J(r.name,c,C.value)).reduce((C,f)=>C+(n.get(f.key)??0),0)},_=r=>["tools","prompts","resources"].reduce((c,n)=>c+U(r,n),0),X=(r,c,n)=>{const C=j.find(S=>S.name===r);if(!C)return;const f=v(C,c).map(S=>S.value),G=m.find(S=>S.name===r);if(!G){x(r,c,[n]);return}const z=G[c];if(z==="all"){const S=f.filter(N=>N!==n);x(r,c,S);return}if(Array.isArray(z)){if(z.includes(n)){x(r,c,z.filter(N=>N!==n));return}const S=[...z,n];x(r,c,S.length===f.length?"all":S);return}x(r,c,[n])},O=r=>{const c=m.find(n=>n.name===r);return!!(c&&h(c))},K=r=>{const c=m.find(n=>n.name===r);return c?["tools","prompts","resources"].some(n=>{const C=c[n];return Array.isArray(C)&&C.length>0}):!1},J=(r,c,n)=>{const C=m.find(G=>G.name===r);if(!C)return!1;const f=C[c];return f==="all"?!0:Array.isArray(f)?f.includes(n):!1},B=(r,c)=>{const n=m.find(G=>G.name===r.name);if(!n)return 0;const C=v(r,c),f=n[c];if(f==="all")return C.length;if(Array.isArray(f)){const G=new Set(C.map(z=>z.value));return f.filter(z=>G.has(z)).length}return 0},I=[{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=>I.map(({key:c})=>({key:c,count:B(r,c)})).filter(c=>c.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 c=O(r.name),n=K(r.name),C=w.has(r.name),f=m.find(N=>N.name===r.name),G=P(r),z=I.filter(({key:N})=>v(r,N).length>0),S=k(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:N=>{N.stopPropagation(),y(r.name)},children:[e.jsx("input",{type:"checkbox",checked:c||n,onChange:()=>y(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))]}),G.map(({key:N,count:W})=>e.jsxs("span",{className:"text-sm text-green-600 flex items-center gap-1",children:[N==="tools"?e.jsx(Ae,{size:14}):N==="prompts"?e.jsx(Te,{size:14}):e.jsx(Ee,{size:14})," ",W]},N)),z.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",C&&"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"})})})]})]}),C&&z.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:[f&&e.jsxs("div",{className:"space-y-1",onClick:N=>N.stopPropagation(),children:[e.jsx("label",{htmlFor:`${u}-${r.name}`,className:"block text-xs font-medium text-[var(--hub-ink-2)]",children:i("groups.alias")}),e.jsx("input",{type:"text",id:`${u}-${r.name}`,value:f.alias||"",placeholder:r.name,onChange:N=>p(r.name,N.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:f.preserveToolNames===!0,onChange:N=>s(m.map(W=>W.name===r.name?{...W,preserveToolNames:N.target.checked}:W))}),i("groups.preserveToolNames")]}),e.jsx("p",{className:"text-xs text-[var(--hub-ink-3)]",children:i("groups.preserveToolNamesHint")})]}),z.map(({key:N,titleKey:W,countKey:be,allKey:ge})=>{const V=v(r,N),ae=B(r,N),Y=(f==null?void 0:f[N])==="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(W)}),e.jsxs("div",{className:"flex items-center gap-3",children:[f&&e.jsx("span",{className:"text-xs text-green-600",children:Y?`(${i(ge)} ${V.length}/${V.length})`:`(${i(be)} ${ae}/${V.length})`}),f&&U(r,N)>0&&e.jsxs("span",{className:"text-xs text-[var(--hub-ink-3)] hub-mono",title:i("cost.estimate"),children:["Σ ",H(U(r,N))]}),e.jsx("button",{type:"button",onClick:()=>{x(r.name,N,Y?[]:"all",!0)},className:"text-sm text-blue-600 hover:text-blue-800 transition-colors",children:i(Y?"groups.selectNone":"groups.selectAll")})]})]}),e.jsx(Be,{items:V,selection:(f==null?void 0:f[N])??[],tools:N==="tools",label:i(W),onChange:R=>x(r.name,N,R,!0),children:R=>{var ie;const ne=J(r.name,N,R.value),q=!!((ie=f==null?void 0:f.pinnedTools)!=null&&ie.includes(R.value)),L=N==="tools"?ke({description:R.description,defaultDescription:R.defaultDescription,hasDescriptionOverride:R.hasDescriptionOverride},i("tool.noDescription")):null,le=L!=null&&L.hasDescriptionOverride?i("tool.defaultDescriptionTooltip",{description:L.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,N,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||(L==null?void 0:L.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:L?L.currentDescription:R.description}),(L==null?void 0:L.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")})]}),S.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(S.get(R.key))]})]}),N==="tools"&&ne&&(F.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)}})]},N)})]})})]},r.name)})}),j.length===0&&e.jsx("p",{className:"text-[var(--hub-ink-3)] text-sm",children:i("groups.noServerOptions")})]})};function he({groupId:a,value:d,onChange:s}){const{t:l}=$(),[b,i]=g.useState([]),[u,E]=g.useState(""),[F,w]=g.useState([]),[A,m]=g.useState(!1),[j,y]=g.useState(!1),[T,h]=g.useState(!1);g.useEffect(()=>{if(!a||d.visibility!=="group")return;let k=!1;return m(!0),y(!1),fe(`/groups/${encodeURIComponent(a)}/share-candidates`).then(U=>{k||(U.success&&Array.isArray(U.data)?(i(U.data),w(U.userGroups||[])):y(!0))}).catch(()=>{k||y(!0)}).finally(()=>{k||m(!1)}),()=>{k=!0}},[a,d.visibility]);const x=d.sharedWithUsers||[],p=[...new Set([...b,...x])].sort().filter(k=>k.toLowerCase().includes(u.toLowerCase())),t=new Set(x),o=p.length>0&&p.every(k=>t.has(k)),v=p.length===0||p.every(k=>!t.has(k)),D=k=>{const U=new Set(x);U.has(k)?U.delete(k):U.add(k),s({sharedWithUsers:Array.from(U)})};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:()=>h(!T),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:T?"▼":"▶"})]}),T&&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:d.visibility||"",onChange:k=>s({visibility:k.target.value}),children:[!d.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")}),!d.visibility&&e.jsx("p",{className:"text-sm text-amber-600",children:l("groups.legacyVisibilityHint")}),d.visibility==="group"&&e.jsxs("div",{className:"mt-4 rounded border border-[var(--hub-line)] p-3",children:[e.jsx(We,{options:F,selected:d.sharedWithUserGroups||[],disabled:A||j||!a,onChange:k=>s({sharedWithUserGroups:k})}),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:[A&&e.jsx("p",{className:"text-sm text-[var(--hub-ink-3)]",children:l("server.shareCandidatesLoading")}),j&&e.jsx("p",{role:"alert",className:"text-sm text-red-600 dark:text-red-400",children:l("server.shareCandidatesError")}),!A&&!j&&p.length===0&&e.jsx("p",{className:"text-sm text-[var(--hub-ink-3)]",children:l(u?"server.noMatchingShareUsers":"server.noShareCandidates")}),p.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:u,onChange:k=>E(k.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([...x,...p])]}),disabled:o,className:"hub-btn text-sm",children:l("server.selectAllShareUsers")}),e.jsx("button",{type:"button",onClick:()=>s({sharedWithUsers:x.filter(k=>!p.includes(k))}),disabled:v,className:"hub-btn text-sm",children:l("server.deselectAllShareUsers")})]})]}),e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-2",children:p.map(k=>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:t.has(k),onChange:()=>D(k)}),e.jsx("span",{children:k})]},k))})]})]}):e.jsx("p",{className:"text-sm text-[var(--hub-ink-3)]",children:l("groups.shareAfterCreate")})]})]})]})}const qe=({onAdd:a,onCancel:d})=>{const{t:s}=$(),{createGroup:l}=ee(),{allServers:b}=te(),{serverCosts:i}=re(),[u,E]=g.useState([]),[F,w]=g.useState(null),[A,m]=g.useState(!1),[j,y]=g.useState({visibility:"private",sharedWithUserGroups:[],sharedWithUsers:[],name:"",description:"",instructions:"",servers:[]});g.useEffect(()=>{E(b.filter(x=>x.enabled!==!1))},[b]);const T=x=>{const{name:p,value:t}=x.target;y(o=>({...o,[p]:t}))},h=async x=>{x.preventDefault(),m(!0),w(null);try{if(!j.name.trim()){w(s("groups.nameRequired")),m(!1);return}const p=await l(j.name,j.description,j.servers,{visibility:j.visibility,sharedWithUserGroups:j.sharedWithUserGroups,sharedWithUsers:j.sharedWithUsers,instructions:j.instructions});if(!p||!p.success){w((p==null?void 0:p.message)||s("groups.createError")),m(!1);return}a()}catch(p){w(p instanceof Error?p.message:String(p)),m(!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")}),F&&e.jsx("div",{className:"mb-4 p-3 bg-red-100 text-red-700 rounded-md border border-[var(--hub-line)]",children:F})]}),e.jsxs("form",{onSubmit:h,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:u,value:j.servers,onChange:x=>y(p=>({...p,servers:x})),className:"border border-[var(--hub-line)] rounded-lg p-4 bg-[var(--hub-bg-2)]",serverCosts:i})]}),e.jsx(he,{value:j,onChange:x=>y(p=>({...p,...x}))})]})}),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:d,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")})]})]})]})})},Ke=({group:a,onEdit:d,onCancel:s})=>{const{t:l}=$(),{updateGroup:b}=ee(),{allServers:i}=te(),{serverCosts:u}=re(),[E,F]=g.useState([]),[w,A]=g.useState(null),[m,j]=g.useState(!1),[y,T]=g.useState({visibility:a.visibility,sharedWithUserGroups:a.sharedWithUserGroups||[],sharedWithUsers:a.sharedWithUsers||[],name:a.name,description:a.description||"",instructions:a.instructions||"",servers:a.servers||[]});g.useEffect(()=>{F(i.filter(p=>p.enabled!==!1))},[i]);const h=p=>{const{name:t,value:o}=p.target;T(v=>({...v,[t]:o}))},x=async p=>{p.preventDefault(),j(!0),A(null);try{if(!y.name.trim()){A(l("groups.nameRequired")),j(!1);return}const t=await b(a.id,{visibility:y.visibility,sharedWithUserGroups:y.sharedWithUserGroups,sharedWithUsers:y.sharedWithUsers,name:y.name,description:y.description,instructions:y.instructions,servers:y.servers});if(!t||!t.success){A((t==null?void 0:t.message)||l("groups.updateError")),j(!1);return}d()}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")}),w&&e.jsx("div",{className:"mb-4 p-3 bg-red-100 text-red-700 rounded-md border border-[var(--hub-line)]",children:w})]}),e.jsxs("form",{onSubmit:x,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:y.name,onChange:h,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:y.instructions,onChange:h,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:y.servers,onChange:p=>T(t=>({...t,servers:p})),className:"border border-[var(--hub-line)] rounded-lg p-4 bg-[var(--hub-bg-2)]",serverCosts:u})]}),e.jsx(he,{groupId:a.id,value:y,onChange:p=>T(t=>({...t,...p}))})]})}),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:m,children:l("common.cancel")}),e.jsx("button",{type:"submit",className:"hub-btn primary",disabled:m,children:l(m?"common.submitting":"common.save")})]})]})]})})},Je=a=>a.map(d=>typeof d=="string"?d:d.name),xe=(a,d)=>{const s=a.servers.find(l=>typeof l=="string"?l===d:l.name===d);return s?typeof s=="string"?{name:s,tools:"all",prompts:"all",resources:"all"}:s:{name:d,tools:"all",prompts:"all",resources:"all"}},Qe=(a,d)=>{var l;return((l=xe(a,d).alias)==null?void 0:l.trim())||d},Xe=({group:a,servers:d,onEdit:s,onDelete:l,cost:b})=>{var B;const{t:i}=$(),{auth:u}=ve(),E=!!u.user&&(u.user.isAdmin||u.user.username===a.owner),{showToast:F}=je(),{installConfig:w,nameSeparator:A}=me(),m=((B=w==null?void 0:w.baseUrl)==null?void 0:B.replace(/\/+$/,""))||"",[j,y]=g.useState(!1),[T,h]=g.useState(null),[x,p]=g.useState(!1),[t,o]=g.useState(!1),v=g.useRef(null);g.useEffect(()=>{const I=P=>{v.current&&!v.current.contains(P.target)&&o(!1)};return document.addEventListener("mousedown",I),()=>document.removeEventListener("mousedown",I)},[]);const D=async I=>{await ye(I)?(p(!0),o(!1),F(i("common.copySuccess")||"Copied","success"),setTimeout(()=>p(!1),1500)):F(i("common.copyFailed")||"Copy failed","error")},k=`${m}/mcp/${a.name}`,U=`${m}/mcp/${encodeURIComponent(a.name)}`,_=`${m}/api/${a.name}`,X=Je(a.servers),O=d.filter(I=>X.includes(I.name)),K=I=>{const P=xe(a,I.name),r=`${I.name}${A}`,c=I.tools||[],n=I.prompts||[],C=I.resources||[],f=Array.isArray(P.tools)?c.filter(S=>{if(S.enabled===!1)return!1;const N=S.name.startsWith(r)?S.name.slice(r.length):S.name;return P.tools.includes(N)}).length:c.filter(S=>S.enabled!==!1).length,G=Array.isArray(P.prompts)?n.filter(S=>{if(S.enabled===!1)return!1;const N=S.name.startsWith(r)?S.name.slice(r.length):S.name;return P.prompts.includes(N)}).length:n.filter(S=>S.enabled!==!1).length,z=Array.isArray(P.resources)?C.filter(S=>S.enabled!==!1&&P.resources.includes(S.uri)).length:C.filter(S=>S.enabled!==!1).length;return{visibleTools:f,totalTools:c.length,visiblePrompts:G,totalPrompts:n.length,visibleResources:z,totalResources:C.length}},J=O.reduce((I,P)=>I+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:v,children:[e.jsxs("div",{className:"relative",children:[e.jsx("button",{onClick:()=>o(I=>!I),className:"hub-icon-btn sm",title:i("common.copy"),children:x?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:()=>D(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:()=>D(k),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:()=>D(_),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:()=>{o(!1),h({name:a.name,url:U,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:()=>y(!0),className:"hub-icon-btn sm",title:i("groups.delete"),style:{color:"var(--hub-ink-3)"},children:e.jsx(Ue,{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:O.length===0?e.jsx("div",{style:{fontSize:12,color:"var(--hub-ink-3)"},children:i("groups.noServers")}):O.map(I=>{const P=K(I);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:I.status==="connected"?"var(--hub-ok)":I.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:I.name,children:Qe(a,I.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"]})]},I.name)})}),e.jsxs("svg",{width:"80",height:"80",viewBox:"0 0 80 80",className:"self-center",children:[O.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"}):O.map((I,P)=>{const r=12+60/Math.max(O.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:()=>D(k),title:i("common.copyUrl"),children:[e.jsx(Q,{size:11})," MCP"]}),e.jsxs("button",{className:"hub-btn sm flex-1 justify-center",onClick:()=>D(_),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:O.length})," ",i("nav.servers").toLowerCase()," ·"," ",e.jsx("span",{style:{color:"var(--hub-ink-2)"},children:J})," ",i("server.tools").toLowerCase()]}),b&&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(b.direct.exposed),"/",H(b.direct.gross)]}),b.smartRouting&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{children:[i("cost.smartRouting"),": ",H(b.smartRouting.base)," (",i("cost.saved",{percent:Ne(b.direct.exposed,b.smartRouting.base)}),")"]}),e.jsxs("div",{title:i("cost.smartRoutingPdHint"),children:[i("cost.smartRoutingPd"),":"," ",H(b.smartRouting.progressiveDisclosure)]})]}),b.connectedCount<b.totalCount&&e.jsx("div",{children:i("cost.connectedOf",{connected:b.connectedCount,total:b.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(Ge,{size:11,style:{transform:"rotate(-90deg)"}})]})]}),e.jsx(we,{isOpen:T!==null,target:T,onClose:()=>h(null)}),e.jsx($e,{isOpen:j,onClose:()=>y(!1),onConfirm:()=>{l(a.id),y(!1)},serverName:a.name,isGroup:!0})]})},Ye=({onSuccess:a,onCancel:d})=>{const{t:s}=$(),[l,b]=g.useState(""),[i,u]=g.useState(null),[E,F]=g.useState(!1),[w,A]=g.useState(null),m=`{
1
+ import{r as g,j as e,R as M}from"./framework-vendor-D0S_ys6r.js";import{o as Z,h as fe,e as ee,a as ve,l as je,j as se}from"./index-DKX_BExz.js";import{u as te,a as re}from"./useCostData-DzjFGnw4.js";import{u as $}from"./i18n-vendor-CPneThYa.js";import{u as me,c as ye}from"./clipboard-BYlVdxdy.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-D-WY0B73.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 Ue,n as Ge,D as ce,N as Pe,P as de,l as Re,X as Le}from"./icons-vendor-DZjjGrOu.js";import{U as We}from"./UserGroupSelection-DionUENR.js";import{D as $e}from"./DeleteDialog-BkEKW9LB.js";const Oe=["read","create","update","delete","other"],Me=a=>{var s,l,b;if(((s=a.annotations)==null?void 0:s.readOnlyHint)===!0)return"read";const d=a.value.toLowerCase();return/^(delete|remove)[_-]/.test(d)?"delete":((l=a.annotations)==null?void 0:l.destructiveHint)===!0?"other":/^(create|add)[_-]/.test(d)?"create":/^(update|set)[_-]/.test(d)?"update":((b=a.annotations)==null?void 0:b.readOnlyHint)!==!1&&/^(get|list|read|search)[_-]/.test(d)?"read":"other"},He=(a,d,s)=>{const l=d.trim().toLowerCase();return a.filter(b=>{var i,u;return(b.value.toLowerCase().includes(l)||((i=b.description)==null?void 0:i.toLowerCase().includes(l)))&&(s==="all"||((u=b.annotations)==null?void 0:u[s])===!0)})},_e=(a,d,s,l)=>{if(s.length===0||a==="all"&&l==="select")return a;const b=new Set(a==="all"?d:a);for(const i of s)l==="deselect"||l==="invert"&&b.has(i)?b.delete(i):b.add(i);return[...b]},Be=({items:a,selection:d,tools:s,label:l,onChange:b,children:i})=>{const{t:u}=$(),[E,F]=g.useState(""),[w,A]=g.useState("all"),[m,j]=g.useState(!1),y=He(a,E,w),T=new Set(d==="all"?a.map(t=>t.value):d),h=(t,o)=>b(_e(d,a.map(v=>v.value),t.map(v=>v.value),o)),x=s&&m?Oe.map(t=>({risk:t,items:y.filter(o=>Me(o)===t)})):[{risk:null,items:y}],p="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":u("groups.bulkSearchLabel",{capability:l}),placeholder:u("groups.bulkSearch"),value:E,onChange:t=>F(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":u("groups.annotationFilter"),value:w,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:u("groups.allAnnotations")}),["readOnlyHint","destructiveHint","idempotentHint"].map(t=>e.jsx("option",{value:t,children:u(`groups.${t}`)},t))]}),e.jsx("button",{type:"button","aria-pressed":m,onClick:()=>j(!m),className:p,children:u(m?"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:u("groups.visibleCount",{count:y.length,total:a.length})}),["select","deselect","invert"].map(t=>e.jsx("button",{type:"button",disabled:!y.length,onClick:()=>h(y,t),className:p,children:u(`groups.${t}Visible`)},t))]}),s&&m&&e.jsx("p",{className:"text-xs text-gray-500 mb-2",children:u("groups.riskHint")}),e.jsxs("div",{className:"grid grid-cols-1 gap-2 max-h-96 overflow-y-auto",children:[y.length===0&&e.jsx("p",{className:"text-sm text-gray-500",children:u("groups.noMatchingItems")}),x.filter(t=>t.items.length>0).map(t=>{const o=t.items.filter(v=>T.has(v.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:[u(`groups.risk_${t.risk}`)," (",o,"/",t.items.length,")"]}),e.jsx("button",{type:"button",className:p,onClick:()=>h(t.items,o===t.items.length?"deselect":"select"),children:u(o===t.items.length?"groups.selectNone":"groups.selectAll")})]}),t.items.map(v=>e.jsx(M.Fragment,{children:i(v)},v.value))]},t.risk??"flat")})]})]})},Ve={tools:[],prompts:[],resources:[]},ue={tools:"all",prompts:"all",resources:"all"},pe=({servers:a,value:d,onChange:s,className:l,serverCosts:b=[]})=>{const{t:i}=$(),u=M.useId(),{nameSeparator:E,smartRoutingConfig:F}=me(),[w,A]=g.useState(new Set),m=M.useMemo(()=>d.map(r=>typeof r=="string"?{name:r,...ue}:{...r,tools:r.tools||"all",prompts:r.prompts||"all",resources:r.resources||"all"}),[d]),j=M.useMemo(()=>a.filter(r=>r.enabled!==!1),[a]);M.useEffect(()=>{const r=new Set(m.map(n=>n.name)),c=new Set(j.map(n=>n.name));A(n=>{const C=new Set;return n.forEach(f=>{(r.has(f)||c.has(f))&&C.add(f)}),C})},[m,j]);const y=r=>{if(m.findIndex(n=>n.name===r)>=0){const n=m.filter(C=>C.name!==r);s(n)}else{const n=[...m,{name:r,...ue}];s(n)}},T=r=>{A(c=>{const n=new Set(c);return n.has(r)?n.delete(r):n.add(r),n})},h=r=>["tools","prompts","resources"].some(c=>{const n=r[c];return n==="all"||Array.isArray(n)&&n.length>0}),x=(r,c,n,C=!1)=>{const f=m.find(S=>S.name===r),z={...f?{...f}:{name:r,...Ve},[c]:n};if(c==="tools"&&Array.isArray(n)&&z.pinnedTools&&(z.pinnedTools=z.pinnedTools.filter(S=>n.includes(S)),z.pinnedTools.length===0&&delete z.pinnedTools),!h(z)){const S=m.filter(N=>N.name!==r);s(S),C||A(N=>{const W=new Set(N);return W.delete(r),W});return}if(f){s(m.map(S=>S.name===r?z:S));return}s([...m,z])},p=(r,c)=>{const n=m.find(f=>f.name===r);if(!n)return;const C={...n};c?C.alias=c:delete C.alias,s(m.map(f=>f.name===r?C:f))},t=(r,c)=>{const n=m.find(G=>G.name===r);if(!n)return;const C=n.pinnedTools??[],f={...n,pinnedTools:C.includes(c)?C.filter(G=>G!==c):[...C,c]};f.pinnedTools.length===0&&delete f.pinnedTools,s(m.map(G=>G.name===r?f:G))},o=(r,c)=>{const n=`${r}${E}`;return c.startsWith(n)?c.slice(n.length):c},v=(r,c)=>c==="tools"?(r.tools||[]).filter(n=>n.enabled!==!1).map(n=>({key:n.name,value:o(r.name,n.name),description:n.description,annotations:n.annotations,defaultDescription:n.defaultDescription,hasDescriptionOverride:n.hasDescriptionOverride})):c==="prompts"?(r.prompts||[]).filter(n=>n.enabled!==!1).map(n=>({key:n.name,value:o(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})),D=M.useMemo(()=>{const r=new Map;return b.forEach(c=>{const n=new Map;c.items.forEach(C=>n.set(C.name,C.cost)),r.set(c.name,n)}),r},[b]),k=r=>D.get(r)??new Map,U=(r,c)=>{const n=k(r.name);return v(r,c).filter(C=>J(r.name,c,C.value)).reduce((C,f)=>C+(n.get(f.key)??0),0)},_=r=>["tools","prompts","resources"].reduce((c,n)=>c+U(r,n),0),X=(r,c,n)=>{const C=j.find(S=>S.name===r);if(!C)return;const f=v(C,c).map(S=>S.value),G=m.find(S=>S.name===r);if(!G){x(r,c,[n]);return}const z=G[c];if(z==="all"){const S=f.filter(N=>N!==n);x(r,c,S);return}if(Array.isArray(z)){if(z.includes(n)){x(r,c,z.filter(N=>N!==n));return}const S=[...z,n];x(r,c,S.length===f.length?"all":S);return}x(r,c,[n])},O=r=>{const c=m.find(n=>n.name===r);return!!(c&&h(c))},K=r=>{const c=m.find(n=>n.name===r);return c?["tools","prompts","resources"].some(n=>{const C=c[n];return Array.isArray(C)&&C.length>0}):!1},J=(r,c,n)=>{const C=m.find(G=>G.name===r);if(!C)return!1;const f=C[c];return f==="all"?!0:Array.isArray(f)?f.includes(n):!1},B=(r,c)=>{const n=m.find(G=>G.name===r.name);if(!n)return 0;const C=v(r,c),f=n[c];if(f==="all")return C.length;if(Array.isArray(f)){const G=new Set(C.map(z=>z.value));return f.filter(z=>G.has(z)).length}return 0},I=[{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=>I.map(({key:c})=>({key:c,count:B(r,c)})).filter(c=>c.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 c=O(r.name),n=K(r.name),C=w.has(r.name),f=m.find(N=>N.name===r.name),G=P(r),z=I.filter(({key:N})=>v(r,N).length>0),S=k(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:N=>{N.stopPropagation(),y(r.name)},children:[e.jsx("input",{type:"checkbox",checked:c||n,onChange:()=>y(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))]}),G.map(({key:N,count:W})=>e.jsxs("span",{className:"text-sm text-green-600 flex items-center gap-1",children:[N==="tools"?e.jsx(Ae,{size:14}):N==="prompts"?e.jsx(Te,{size:14}):e.jsx(Ee,{size:14})," ",W]},N)),z.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",C&&"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"})})})]})]}),C&&z.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:[f&&e.jsxs("div",{className:"space-y-1",onClick:N=>N.stopPropagation(),children:[e.jsx("label",{htmlFor:`${u}-${r.name}`,className:"block text-xs font-medium text-[var(--hub-ink-2)]",children:i("groups.alias")}),e.jsx("input",{type:"text",id:`${u}-${r.name}`,value:f.alias||"",placeholder:r.name,onChange:N=>p(r.name,N.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:f.preserveToolNames===!0,onChange:N=>s(m.map(W=>W.name===r.name?{...W,preserveToolNames:N.target.checked}:W))}),i("groups.preserveToolNames")]}),e.jsx("p",{className:"text-xs text-[var(--hub-ink-3)]",children:i("groups.preserveToolNamesHint")})]}),z.map(({key:N,titleKey:W,countKey:be,allKey:ge})=>{const V=v(r,N),ae=B(r,N),Y=(f==null?void 0:f[N])==="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(W)}),e.jsxs("div",{className:"flex items-center gap-3",children:[f&&e.jsx("span",{className:"text-xs text-green-600",children:Y?`(${i(ge)} ${V.length}/${V.length})`:`(${i(be)} ${ae}/${V.length})`}),f&&U(r,N)>0&&e.jsxs("span",{className:"text-xs text-[var(--hub-ink-3)] hub-mono",title:i("cost.estimate"),children:["Σ ",H(U(r,N))]}),e.jsx("button",{type:"button",onClick:()=>{x(r.name,N,Y?[]:"all",!0)},className:"text-sm text-blue-600 hover:text-blue-800 transition-colors",children:i(Y?"groups.selectNone":"groups.selectAll")})]})]}),e.jsx(Be,{items:V,selection:(f==null?void 0:f[N])??[],tools:N==="tools",label:i(W),onChange:R=>x(r.name,N,R,!0),children:R=>{var ie;const ne=J(r.name,N,R.value),q=!!((ie=f==null?void 0:f.pinnedTools)!=null&&ie.includes(R.value)),L=N==="tools"?ke({description:R.description,defaultDescription:R.defaultDescription,hasDescriptionOverride:R.hasDescriptionOverride},i("tool.noDescription")):null,le=L!=null&&L.hasDescriptionOverride?i("tool.defaultDescriptionTooltip",{description:L.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,N,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||(L==null?void 0:L.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:L?L.currentDescription:R.description}),(L==null?void 0:L.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")})]}),S.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(S.get(R.key))]})]}),N==="tools"&&ne&&(F.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)}})]},N)})]})})]},r.name)})}),j.length===0&&e.jsx("p",{className:"text-[var(--hub-ink-3)] text-sm",children:i("groups.noServerOptions")})]})};function he({groupId:a,value:d,onChange:s}){const{t:l}=$(),[b,i]=g.useState([]),[u,E]=g.useState(""),[F,w]=g.useState([]),[A,m]=g.useState(!1),[j,y]=g.useState(!1),[T,h]=g.useState(!1);g.useEffect(()=>{if(!a||d.visibility!=="group")return;let k=!1;return m(!0),y(!1),fe(`/groups/${encodeURIComponent(a)}/share-candidates`).then(U=>{k||(U.success&&Array.isArray(U.data)?(i(U.data),w(U.userGroups||[])):y(!0))}).catch(()=>{k||y(!0)}).finally(()=>{k||m(!1)}),()=>{k=!0}},[a,d.visibility]);const x=d.sharedWithUsers||[],p=[...new Set([...b,...x])].sort().filter(k=>k.toLowerCase().includes(u.toLowerCase())),t=new Set(x),o=p.length>0&&p.every(k=>t.has(k)),v=p.length===0||p.every(k=>!t.has(k)),D=k=>{const U=new Set(x);U.has(k)?U.delete(k):U.add(k),s({sharedWithUsers:Array.from(U)})};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:()=>h(!T),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:T?"▼":"▶"})]}),T&&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:d.visibility||"",onChange:k=>s({visibility:k.target.value}),children:[!d.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")}),!d.visibility&&e.jsx("p",{className:"text-sm text-amber-600",children:l("groups.legacyVisibilityHint")}),d.visibility==="group"&&e.jsxs("div",{className:"mt-4 rounded border border-[var(--hub-line)] p-3",children:[e.jsx(We,{options:F,selected:d.sharedWithUserGroups||[],disabled:A||j||!a,onChange:k=>s({sharedWithUserGroups:k})}),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:[A&&e.jsx("p",{className:"text-sm text-[var(--hub-ink-3)]",children:l("server.shareCandidatesLoading")}),j&&e.jsx("p",{role:"alert",className:"text-sm text-red-600 dark:text-red-400",children:l("server.shareCandidatesError")}),!A&&!j&&p.length===0&&e.jsx("p",{className:"text-sm text-[var(--hub-ink-3)]",children:l(u?"server.noMatchingShareUsers":"server.noShareCandidates")}),p.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:u,onChange:k=>E(k.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([...x,...p])]}),disabled:o,className:"hub-btn text-sm",children:l("server.selectAllShareUsers")}),e.jsx("button",{type:"button",onClick:()=>s({sharedWithUsers:x.filter(k=>!p.includes(k))}),disabled:v,className:"hub-btn text-sm",children:l("server.deselectAllShareUsers")})]})]}),e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-2",children:p.map(k=>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:t.has(k),onChange:()=>D(k)}),e.jsx("span",{children:k})]},k))})]})]}):e.jsx("p",{className:"text-sm text-[var(--hub-ink-3)]",children:l("groups.shareAfterCreate")})]})]})]})}const qe=({onAdd:a,onCancel:d})=>{const{t:s}=$(),{createGroup:l}=ee(),{allServers:b}=te(),{serverCosts:i}=re(),[u,E]=g.useState([]),[F,w]=g.useState(null),[A,m]=g.useState(!1),[j,y]=g.useState({visibility:"private",sharedWithUserGroups:[],sharedWithUsers:[],name:"",description:"",instructions:"",servers:[]});g.useEffect(()=>{E(b.filter(x=>x.enabled!==!1))},[b]);const T=x=>{const{name:p,value:t}=x.target;y(o=>({...o,[p]:t}))},h=async x=>{x.preventDefault(),m(!0),w(null);try{if(!j.name.trim()){w(s("groups.nameRequired")),m(!1);return}const p=await l(j.name,j.description,j.servers,{visibility:j.visibility,sharedWithUserGroups:j.sharedWithUserGroups,sharedWithUsers:j.sharedWithUsers,instructions:j.instructions});if(!p||!p.success){w((p==null?void 0:p.message)||s("groups.createError")),m(!1);return}a()}catch(p){w(p instanceof Error?p.message:String(p)),m(!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")}),F&&e.jsx("div",{className:"mb-4 p-3 bg-red-100 text-red-700 rounded-md border border-[var(--hub-line)]",children:F})]}),e.jsxs("form",{onSubmit:h,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:u,value:j.servers,onChange:x=>y(p=>({...p,servers:x})),className:"border border-[var(--hub-line)] rounded-lg p-4 bg-[var(--hub-bg-2)]",serverCosts:i})]}),e.jsx(he,{value:j,onChange:x=>y(p=>({...p,...x}))})]})}),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:d,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")})]})]})]})})},Ke=({group:a,onEdit:d,onCancel:s})=>{const{t:l}=$(),{updateGroup:b}=ee(),{allServers:i}=te(),{serverCosts:u}=re(),[E,F]=g.useState([]),[w,A]=g.useState(null),[m,j]=g.useState(!1),[y,T]=g.useState({visibility:a.visibility,sharedWithUserGroups:a.sharedWithUserGroups||[],sharedWithUsers:a.sharedWithUsers||[],name:a.name,description:a.description||"",instructions:a.instructions||"",servers:a.servers||[]});g.useEffect(()=>{F(i.filter(p=>p.enabled!==!1))},[i]);const h=p=>{const{name:t,value:o}=p.target;T(v=>({...v,[t]:o}))},x=async p=>{p.preventDefault(),j(!0),A(null);try{if(!y.name.trim()){A(l("groups.nameRequired")),j(!1);return}const t=await b(a.id,{visibility:y.visibility,sharedWithUserGroups:y.sharedWithUserGroups,sharedWithUsers:y.sharedWithUsers,name:y.name,description:y.description,instructions:y.instructions,servers:y.servers});if(!t||!t.success){A((t==null?void 0:t.message)||l("groups.updateError")),j(!1);return}d()}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")}),w&&e.jsx("div",{className:"mb-4 p-3 bg-red-100 text-red-700 rounded-md border border-[var(--hub-line)]",children:w})]}),e.jsxs("form",{onSubmit:x,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:y.name,onChange:h,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:y.instructions,onChange:h,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:y.servers,onChange:p=>T(t=>({...t,servers:p})),className:"border border-[var(--hub-line)] rounded-lg p-4 bg-[var(--hub-bg-2)]",serverCosts:u})]}),e.jsx(he,{groupId:a.id,value:y,onChange:p=>T(t=>({...t,...p}))})]})}),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:m,children:l("common.cancel")}),e.jsx("button",{type:"submit",className:"hub-btn primary",disabled:m,children:l(m?"common.submitting":"common.save")})]})]})]})})},Je=a=>a.map(d=>typeof d=="string"?d:d.name),xe=(a,d)=>{const s=a.servers.find(l=>typeof l=="string"?l===d:l.name===d);return s?typeof s=="string"?{name:s,tools:"all",prompts:"all",resources:"all"}:s:{name:d,tools:"all",prompts:"all",resources:"all"}},Qe=(a,d)=>{var l;return((l=xe(a,d).alias)==null?void 0:l.trim())||d},Xe=({group:a,servers:d,onEdit:s,onDelete:l,cost:b})=>{var B;const{t:i}=$(),{auth:u}=ve(),E=!!u.user&&(u.user.isAdmin||u.user.username===a.owner),{showToast:F}=je(),{installConfig:w,nameSeparator:A}=me(),m=((B=w==null?void 0:w.baseUrl)==null?void 0:B.replace(/\/+$/,""))||"",[j,y]=g.useState(!1),[T,h]=g.useState(null),[x,p]=g.useState(!1),[t,o]=g.useState(!1),v=g.useRef(null);g.useEffect(()=>{const I=P=>{v.current&&!v.current.contains(P.target)&&o(!1)};return document.addEventListener("mousedown",I),()=>document.removeEventListener("mousedown",I)},[]);const D=async I=>{await ye(I)?(p(!0),o(!1),F(i("common.copySuccess")||"Copied","success"),setTimeout(()=>p(!1),1500)):F(i("common.copyFailed")||"Copy failed","error")},k=`${m}/mcp/${a.name}`,U=`${m}/mcp/${encodeURIComponent(a.name)}`,_=`${m}/api/${a.name}`,X=Je(a.servers),O=d.filter(I=>X.includes(I.name)),K=I=>{const P=xe(a,I.name),r=`${I.name}${A}`,c=I.tools||[],n=I.prompts||[],C=I.resources||[],f=Array.isArray(P.tools)?c.filter(S=>{if(S.enabled===!1)return!1;const N=S.name.startsWith(r)?S.name.slice(r.length):S.name;return P.tools.includes(N)}).length:c.filter(S=>S.enabled!==!1).length,G=Array.isArray(P.prompts)?n.filter(S=>{if(S.enabled===!1)return!1;const N=S.name.startsWith(r)?S.name.slice(r.length):S.name;return P.prompts.includes(N)}).length:n.filter(S=>S.enabled!==!1).length,z=Array.isArray(P.resources)?C.filter(S=>S.enabled!==!1&&P.resources.includes(S.uri)).length:C.filter(S=>S.enabled!==!1).length;return{visibleTools:f,totalTools:c.length,visiblePrompts:G,totalPrompts:n.length,visibleResources:z,totalResources:C.length}},J=O.reduce((I,P)=>I+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:v,children:[e.jsxs("div",{className:"relative",children:[e.jsx("button",{onClick:()=>o(I=>!I),className:"hub-icon-btn sm",title:i("common.copy"),children:x?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:()=>D(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:()=>D(k),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:()=>D(_),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:()=>{o(!1),h({name:a.name,url:U,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:()=>y(!0),className:"hub-icon-btn sm",title:i("groups.delete"),style:{color:"var(--hub-ink-3)"},children:e.jsx(Ue,{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:O.length===0?e.jsx("div",{style:{fontSize:12,color:"var(--hub-ink-3)"},children:i("groups.noServers")}):O.map(I=>{const P=K(I);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:I.status==="connected"?"var(--hub-ok)":I.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:I.name,children:Qe(a,I.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"]})]},I.name)})}),e.jsxs("svg",{width:"80",height:"80",viewBox:"0 0 80 80",className:"self-center",children:[O.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"}):O.map((I,P)=>{const r=12+60/Math.max(O.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:()=>D(k),title:i("common.copyUrl"),children:[e.jsx(Q,{size:11})," MCP"]}),e.jsxs("button",{className:"hub-btn sm flex-1 justify-center",onClick:()=>D(_),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:O.length})," ",i("nav.servers").toLowerCase()," ·"," ",e.jsx("span",{style:{color:"var(--hub-ink-2)"},children:J})," ",i("server.tools").toLowerCase()]}),b&&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(b.direct.exposed),"/",H(b.direct.gross)]}),b.smartRouting&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{children:[i("cost.smartRouting"),": ",H(b.smartRouting.base)," (",i("cost.saved",{percent:Ne(b.direct.exposed,b.smartRouting.base)}),")"]}),e.jsxs("div",{title:i("cost.smartRoutingPdHint"),children:[i("cost.smartRoutingPd"),":"," ",H(b.smartRouting.progressiveDisclosure)]})]}),b.connectedCount<b.totalCount&&e.jsx("div",{children:i("cost.connectedOf",{connected:b.connectedCount,total:b.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(Ge,{size:11,style:{transform:"rotate(-90deg)"}})]})]}),e.jsx(we,{isOpen:T!==null,target:T,onClose:()=>h(null)}),e.jsx($e,{isOpen:j,onClose:()=>y(!1),onConfirm:()=>{l(a.id),y(!1)},serverName:a.name,isGroup:!0})]})},Ye=({onSuccess:a,onCancel:d})=>{const{t:s}=$(),[l,b]=g.useState(""),[i,u]=g.useState(null),[E,F]=g.useState(!1),[w,A]=g.useState(null),m=`{
2
2
  "groups": [
3
3
  {
4
4
  "name": "AI Assistants",
@@ -30,4 +30,4 @@ Supports:
30
30
  - All groups will be imported in a single efficient batch operation.`,j=t=>{try{const o=JSON.parse(t.trim());if(!o.groups||!Array.isArray(o.groups))return u(s("groupImport.invalidFormat")),null;for(const v of o.groups)if(!v.name||typeof v.name!="string")return u(s("groupImport.missingName")),null;return o}catch{return u(s("groupImport.parseError")),null}},y=()=>{u(null);const t=j(l);t&&A(t.groups)},T=async()=>{if(w){F(!0),u(null);try{const t=await se("/groups/batch",{groups:w});if(t.success){const{successCount:o,failureCount:v,results:D}=t;if(v>0){const k=D.filter(U=>!U.success).map(U=>`${U.name}: ${U.message||s("groupImport.addFailed")}`);u(s("groupImport.partialSuccess",{count:o,total:w.length})+`
31
31
  `+k.join(`
32
32
  `))}o>0&&a()}else u(t.message||s("groupImport.importFailed"))}catch(t){console.error("Import error:",t),u(s("groupImport.importFailed"))}finally{F(!1)}}},h=t=>e.jsx("span",{className:"text-gray-500 ml-2",children:s(`groups.${t}`)}),x=(t,o)=>{if(!o||o==="all")return null;const v=Array.isArray(o)?o.join(", "):o;return e.jsx("span",{className:"text-gray-500 ml-2",children:s(`groups.${t}`,{items:v})})},p=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((o,v)=>typeof o=="string"?e.jsxs("div",{className:"text-sm",children:["• ",o]},v):e.jsxs("div",{className:"text-sm",children:["• ",o.name,o.tools&&o.tools!=="all"&&e.jsxs("span",{className:"text-gray-500 ml-2",children:["(",Array.isArray(o.tools)?o.tools.join(", "):o.tools,")"]}),o.tools==="all"&&h("previewAllTools"),x("previewPrompts",o.prompts),o.prompts==="all"&&h("previewAllPrompts"),x("previewResources",o.resources),o.resources==="all"&&h("previewAllResources")]},v))});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:d,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})}),w?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:w.map((t,o)=>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:p(t.servers)})]})]})})},o))})]}),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=>b(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:m}),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:d,className:"hub-btn",children:s("common.cancel")}),e.jsx("button",{onClick:y,disabled:!l.trim(),className:"hub-btn primary",children:s("groupImport.preview")})]})]})]})})},Ze=({groups:a,onCancel:d})=>{const{t:s}=$(),[l,b]=g.useState(""),[i,u]=g.useState(""),[E,F]=g.useState([]),[w,A]=g.useState(!1),[m,j]=g.useState(!1),[y,T]=g.useState(null),h=t=>{F(o=>o.includes(t)?o.filter(v=>v!==t):[...o,t])},x=()=>{E.length===a.length?F([]):F(a.map(t=>t.id))},p=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:w});if(t.success&&t.data){const o=t.data,v=new Blob([JSON.stringify(o,null,2)],{type:"application/json"}),D=URL.createObjectURL(v),k=document.createElement("a");k.href=D,k.download=`${o.name.replace(/[^a-zA-Z0-9-_]/g,"_")}.mcphub-template.json`,document.body.appendChild(k),k.click(),document.body.removeChild(k),URL.revokeObjectURL(D),d()}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:d,className:"text-gray-500 hover:text-gray-700",children:"✕"})]}),y&&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:y})}),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=>b(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=>u(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:x,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:()=>h(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:w,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:d,className:"hub-btn",children:s("common.cancel")}),e.jsx("button",{onClick:p,disabled:m||!l.trim(),className:"hub-btn primary",children:s(m?"template.exporting":"template.export")})]})]})})},es=({onSuccess:a,onCancel:d})=>{const{t:s}=$(),[l,b]=g.useState(null),[i,u]=g.useState(null),[E,F]=g.useState(!1),[w,A]=g.useState(null),m=g.useRef(null),j=h=>{var t;u(null),b(null),A(null);const x=(t=h.target.files)==null?void 0:t[0];if(!x)return;const p=new FileReader;p.onload=o=>{var v;try{const D=JSON.parse((v=o.target)==null?void 0:v.result);if(!D.version||!D.name||!D.servers||!D.groups){u(s("template.invalidFormat"));return}b(D)}catch{u(s("template.parseError"))}},p.readAsText(x)},y=h=>{if(u(null),b(null),A(null),!!h.trim())try{const x=JSON.parse(h.trim());if(!x.version||!x.name||!x.servers||!x.groups){u(s("template.invalidFormat"));return}b(x)}catch{u(s("template.parseError"))}},T=async()=>{if(l){F(!0),u(null);try{const h=await se("/templates/import",l);h.data?(A(h.data),h.data.success&&a()):u(h.message||s("template.importFailed"))}catch(h){console.error("Import error:",h),u(s("template.importFailed"))}finally{F(!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:d,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})}),w&&e.jsxs("div",{className:`mb-4 p-4 rounded border-l-4 ${w.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:w.success?"text-green-700 dark:text-green-300":"text-yellow-700 dark:text-yellow-300",children:s("template.importResult",{serversCreated:w.serversCreated,serversSkipped:w.serversSkipped,groupsCreated:w.groupsCreated,groupsSkipped:w.groupsSkipped})}),w.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:w.requiredEnvVars.map(h=>e.jsx("li",{className:"font-mono",children:h},h))})]})]}),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(([h,x])=>e.jsxs("div",{className:"px-3 py-2",children:[e.jsx("span",{className:"text-sm font-medium text-gray-900",children:h}),e.jsx("span",{className:"text-xs text-gray-500 ml-2",children:x.type||"stdio"})]},h))})]}),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((h,x)=>e.jsxs("div",{className:"px-3 py-2",children:[e.jsx("span",{className:"text-sm font-medium text-gray-900",children:h.name}),h.description&&e.jsx("span",{className:"text-xs text-gray-500 ml-2",children:h.description}),e.jsxs("div",{className:"text-xs text-gray-500 mt-1",children:[h.servers.length," ",s("template.serversInGroup")]})]},x))})]}),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(h=>e.jsx("li",{children:h},h))})]})]}),e.jsxs("div",{className:"flex justify-end space-x-4 mt-6",children:[e.jsx("button",{onClick:()=>{b(null),A(null),m.current&&(m.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:m,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:h=>y(h.target.value)})]}),e.jsx("div",{className:"flex justify-end space-x-4",children:e.jsx("button",{onClick:d,className:"hub-btn",children:s("common.cancel")})})]})]})})},us=()=>{const{t:a}=$(),{groups:d,loading:s,error:l,setError:b,deleteGroup:i,triggerRefresh:u}=ee(),{allServers:E}=te({refreshOnMount:!0}),{groupCosts:F}=re(JSON.stringify([d,Ce(E)])),[w,A]=g.useState(null),[m,j]=g.useState(!1),[y,T]=g.useState(!1),[h,x]=g.useState(!1),[p,t]=g.useState(!1),o=async v=>{const D=await i(v);(!D||!D.success)&&b((D==null?void 0:D.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:d.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:()=>x(!0),children:[e.jsx(Pe,{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(Re,{size:14,className:"flex-shrink-0"}),e.jsx("span",{className:"truncate text-[13px]",children:l})]}),e.jsx("button",{className:"hub-icon-btn sm",onClick:()=>b(null),children:e.jsx(Le,{size:13})})]}),s?e.jsx("div",{className:"hub-card p-6 text-center",style:{color:"var(--hub-ink-3)"},children:a("app.loading")}):d.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:[d.map(v=>e.jsx(Xe,{group:v,servers:E,onEdit:A,onDelete:o,cost:F.find(D=>D.id===v.id)},v.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")})]})})]}),m&&e.jsx(qe,{onAdd:()=>{j(!1),u()},onCancel:()=>j(!1)}),y&&e.jsx(Ye,{onSuccess:()=>{T(!1),u()},onCancel:()=>T(!1)}),w&&e.jsx(Ke,{group:w,onEdit:()=>{A(null),u()},onCancel:()=>A(null)}),h&&e.jsx(Ze,{groups:d,onCancel:()=>x(!1)}),p&&e.jsx(es,{onSuccess:()=>{t(!1),u()},onCancel:()=>t(!1)})]})};export{us as default};
33
- //# sourceMappingURL=GroupsPage-CSA5G9_H.js.map
33
+ //# sourceMappingURL=GroupsPage-DLL1tFj8.js.map