@samanhappy/mcphub 1.1.15 → 1.2.1

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 (150) hide show
  1. package/README.fr.md +1 -0
  2. package/README.md +6 -0
  3. package/README.zh.md +1 -0
  4. package/dist/clients/openapi.js +3 -2
  5. package/dist/clients/openapi.js.map +1 -1
  6. package/dist/controllers/configController.js +2 -0
  7. package/dist/controllers/configController.js.map +1 -1
  8. package/dist/controllers/credentialBindingController.js +1 -1
  9. package/dist/controllers/credentialBindingController.js.map +1 -1
  10. package/dist/controllers/healthController.js +23 -1
  11. package/dist/controllers/healthController.js.map +1 -1
  12. package/dist/controllers/metricsController.js +9 -1
  13. package/dist/controllers/metricsController.js.map +1 -1
  14. package/dist/controllers/oauthDynamicRegistrationController.js +5 -5
  15. package/dist/controllers/oauthDynamicRegistrationController.js.map +1 -1
  16. package/dist/controllers/serverController.js +64 -26
  17. package/dist/controllers/serverController.js.map +1 -1
  18. package/dist/db/connection.js +6 -2
  19. package/dist/db/connection.js.map +1 -1
  20. package/dist/db/entities/OAuthState.js +43 -0
  21. package/dist/db/entities/OAuthState.js.map +1 -0
  22. package/dist/db/entities/SystemConfig.js.map +1 -1
  23. package/dist/db/entities/index.js +3 -1
  24. package/dist/db/entities/index.js.map +1 -1
  25. package/dist/db/replicaSchema.js +40 -0
  26. package/dist/db/replicaSchema.js.map +1 -0
  27. package/dist/db/setup.js +25 -0
  28. package/dist/db/setup.js.map +1 -0
  29. package/dist/db/transactionContext.js +21 -0
  30. package/dist/db/transactionContext.js.map +1 -0
  31. package/dist/index.js +2 -0
  32. package/dist/index.js.map +1 -1
  33. package/dist/middlewares/replicaConfig.js +134 -0
  34. package/dist/middlewares/replicaConfig.js.map +1 -0
  35. package/dist/middlewares/userContext.js +1 -1
  36. package/dist/middlewares/userContext.js.map +1 -1
  37. package/dist/models/OAuth.js +57 -7
  38. package/dist/models/OAuth.js.map +1 -1
  39. package/dist/routes/index.js +14 -1
  40. package/dist/routes/index.js.map +1 -1
  41. package/dist/server.js +13 -4
  42. package/dist/server.js.map +1 -1
  43. package/dist/services/credentialBindingService.js +5 -1
  44. package/dist/services/credentialBindingService.js.map +1 -1
  45. package/dist/services/mcpOAuthProvider.js +91 -5
  46. package/dist/services/mcpOAuthProvider.js.map +1 -1
  47. package/dist/services/mcpService.js +113 -10
  48. package/dist/services/mcpService.js.map +1 -1
  49. package/dist/services/metricsService.js +4 -0
  50. package/dist/services/metricsService.js.map +1 -1
  51. package/dist/services/oauthClientRegistration.js +21 -1
  52. package/dist/services/oauthClientRegistration.js.map +1 -1
  53. package/dist/services/oauthServerService.js +5 -6
  54. package/dist/services/oauthServerService.js.map +1 -1
  55. package/dist/services/oauthSettingsStore.js +21 -0
  56. package/dist/services/oauthSettingsStore.js.map +1 -1
  57. package/dist/services/openApiGeneratorService.js +10 -3
  58. package/dist/services/openApiGeneratorService.js.map +1 -1
  59. package/dist/services/personalOAuthService.js +40 -2
  60. package/dist/services/personalOAuthService.js.map +1 -1
  61. package/dist/services/replicaLock.js +30 -0
  62. package/dist/services/replicaLock.js.map +1 -0
  63. package/dist/services/replicaService.js +111 -0
  64. package/dist/services/replicaService.js.map +1 -0
  65. package/dist/services/sseService.js +3 -2
  66. package/dist/services/sseService.js.map +1 -1
  67. package/dist/types/network.js +2 -0
  68. package/dist/types/network.js.map +1 -0
  69. package/dist/utils/logger.js +7 -0
  70. package/dist/utils/logger.js.map +1 -1
  71. package/dist/utils/migration.js +3 -0
  72. package/dist/utils/migration.js.map +1 -1
  73. package/dist/utils/openApiSchema.js +148 -0
  74. package/dist/utils/openApiSchema.js.map +1 -0
  75. package/dist/utils/parameterConversion.js +38 -5
  76. package/dist/utils/parameterConversion.js.map +1 -1
  77. package/dist/utils/passthroughHeaders.js +7 -3
  78. package/dist/utils/passthroughHeaders.js.map +1 -1
  79. package/dist/utils/replicaLogContext.js +3 -0
  80. package/dist/utils/replicaLogContext.js.map +1 -0
  81. package/dist/utils/replicaMode.js +17 -0
  82. package/dist/utils/replicaMode.js.map +1 -0
  83. package/dist/utils/serverConfigPersistence.js +4 -0
  84. package/dist/utils/serverConfigPersistence.js.map +1 -1
  85. package/dist/utils/settingsSync.js +1 -0
  86. package/dist/utils/settingsSync.js.map +1 -1
  87. package/dist/utils/ssrf.js +46 -12
  88. package/dist/utils/ssrf.js.map +1 -1
  89. package/frontend/dist/assets/{ActivityPage-Bi-TjKez.js → ActivityPage-DZFLY-Um.js} +2 -2
  90. package/frontend/dist/assets/{ActivityPage-Bi-TjKez.js.map → ActivityPage-DZFLY-Um.js.map} +1 -1
  91. package/frontend/dist/assets/{ConfirmDialog-BJpzQmMw.js → ConfirmDialog-ByWCtrIw.js} +2 -2
  92. package/frontend/dist/assets/{ConfirmDialog-BJpzQmMw.js.map → ConfirmDialog-ByWCtrIw.js.map} +1 -1
  93. package/frontend/dist/assets/{CredentialsPage-C4Ucer3d.js → CredentialsPage-BqEsnkMx.js} +2 -2
  94. package/frontend/dist/assets/{CredentialsPage-C4Ucer3d.js.map → CredentialsPage-BqEsnkMx.js.map} +1 -1
  95. package/frontend/dist/assets/{Dashboard-C_2KkuoD.js → Dashboard-BRU2Gk9z.js} +2 -2
  96. package/frontend/dist/assets/{Dashboard-C_2KkuoD.js.map → Dashboard-BRU2Gk9z.js.map} +1 -1
  97. package/frontend/dist/assets/{DeleteDialog-BoMYLx3J.js → DeleteDialog-BkEKW9LB.js} +2 -2
  98. package/frontend/dist/assets/{DeleteDialog-BoMYLx3J.js.map → DeleteDialog-BkEKW9LB.js.map} +1 -1
  99. package/frontend/dist/assets/{EndpointCopy-DITVC2YQ.js → EndpointCopy-3f1Uw-gu.js} +2 -2
  100. package/frontend/dist/assets/{EndpointCopy-DITVC2YQ.js.map → EndpointCopy-3f1Uw-gu.js.map} +1 -1
  101. package/frontend/dist/assets/{GroupsPage-sE6YJyuK.js → GroupsPage-D_E7QL_o.js} +2 -2
  102. package/frontend/dist/assets/{GroupsPage-sE6YJyuK.js.map → GroupsPage-D_E7QL_o.js.map} +1 -1
  103. package/frontend/dist/assets/{LoginPage-CFsd_nY-.js → LoginPage-Bsfdp4yD.js} +2 -2
  104. package/frontend/dist/assets/{LoginPage-CFsd_nY-.js.map → LoginPage-Bsfdp4yD.js.map} +1 -1
  105. package/frontend/dist/assets/{LogsPage-BxZuGDuc.js → LogsPage-CCHmA5cZ.js} +2 -2
  106. package/frontend/dist/assets/{LogsPage-BxZuGDuc.js.map → LogsPage-CCHmA5cZ.js.map} +1 -1
  107. package/frontend/dist/assets/{MarketPage-CDBs4vMb.js → MarketPage-DrQQT14y.js} +2 -2
  108. package/frontend/dist/assets/{MarketPage-CDBs4vMb.js.map → MarketPage-DrQQT14y.js.map} +1 -1
  109. package/frontend/dist/assets/{OAuthConsentPage-BN_ucViM.js → OAuthConsentPage-934ieVvL.js} +2 -2
  110. package/frontend/dist/assets/{OAuthConsentPage-BN_ucViM.js.map → OAuthConsentPage-934ieVvL.js.map} +1 -1
  111. package/frontend/dist/assets/{Pagination-S-7lzy59.js → Pagination-B2WW4qn_.js} +2 -2
  112. package/frontend/dist/assets/{Pagination-S-7lzy59.js.map → Pagination-B2WW4qn_.js.map} +1 -1
  113. package/frontend/dist/assets/{PromptsPage-Bl3ySXGK.js → PromptsPage-QAI8kF63.js} +2 -2
  114. package/frontend/dist/assets/{PromptsPage-Bl3ySXGK.js.map → PromptsPage-QAI8kF63.js.map} +1 -1
  115. package/frontend/dist/assets/{ResourcesPage-BOzQkQ92.js → ResourcesPage-TclV1l2q.js} +2 -2
  116. package/frontend/dist/assets/{ResourcesPage-BOzQkQ92.js.map → ResourcesPage-TclV1l2q.js.map} +1 -1
  117. package/frontend/dist/assets/{ServersPage-DHYwQ5AM.js → ServersPage-Bc0tS2uo.js} +4 -4
  118. package/frontend/dist/assets/ServersPage-Bc0tS2uo.js.map +1 -0
  119. package/frontend/dist/assets/SettingsPage-Dfhl51E1.js +14 -0
  120. package/frontend/dist/assets/SettingsPage-Dfhl51E1.js.map +1 -0
  121. package/frontend/dist/assets/{StatusDot-NSjojGCy.js → StatusDot-C_UTW6B7.js} +2 -2
  122. package/frontend/dist/assets/{StatusDot-NSjojGCy.js.map → StatusDot-C_UTW6B7.js.map} +1 -1
  123. package/frontend/dist/assets/{ToggleGroup-BIZWpNzm.js → ToggleGroup-CUUsTJDm.js} +2 -2
  124. package/frontend/dist/assets/{ToggleGroup-BIZWpNzm.js.map → ToggleGroup-CUUsTJDm.js.map} +1 -1
  125. package/frontend/dist/assets/{UserGroupSelection-CN0weGXJ.js → UserGroupSelection-DionUENR.js} +2 -2
  126. package/frontend/dist/assets/{UserGroupSelection-CN0weGXJ.js.map → UserGroupSelection-DionUENR.js.map} +1 -1
  127. package/frontend/dist/assets/{UsersPage-DC51v2b8.js → UsersPage-MpTb3xJ-.js} +2 -2
  128. package/frontend/dist/assets/{UsersPage-DC51v2b8.js.map → UsersPage-MpTb3xJ-.js.map} +1 -1
  129. package/frontend/dist/assets/{clipboard-ik5YV95M.js → clipboard-DVbqnePj.js} +2 -2
  130. package/frontend/dist/assets/{clipboard-ik5YV95M.js.map → clipboard-DVbqnePj.js.map} +1 -1
  131. package/frontend/dist/assets/{costRevision-Bxov9_vH.js → costRevision-DXEYAFUy.js} +2 -2
  132. package/frontend/dist/assets/{costRevision-Bxov9_vH.js.map → costRevision-DXEYAFUy.js.map} +1 -1
  133. package/frontend/dist/assets/{i18n-vendor-COTriSc6.js → i18n-vendor-CPneThYa.js} +3 -3
  134. package/frontend/dist/assets/{i18n-vendor-COTriSc6.js.map → i18n-vendor-CPneThYa.js.map} +1 -1
  135. package/frontend/dist/assets/index-BNm-68Gn.js +3 -0
  136. package/frontend/dist/assets/index-BNm-68Gn.js.map +1 -0
  137. package/frontend/dist/assets/{index-DrHctFvx.css → index-C33aH9Y7.css} +1 -1
  138. package/frontend/dist/assets/{resourceService-DMzCAZ0B.js → resourceService-DPjgql8Z.js} +2 -2
  139. package/frontend/dist/assets/{resourceService-DMzCAZ0B.js.map → resourceService-DPjgql8Z.js.map} +1 -1
  140. package/frontend/dist/assets/{useCostData-CcFSYViI.js → useCostData-CDNXYHZf.js} +2 -2
  141. package/frontend/dist/assets/{useCostData-CcFSYViI.js.map → useCostData-CDNXYHZf.js.map} +1 -1
  142. package/frontend/dist/assets/{variableDetection-CbYSa1ka.js → variableDetection-DGr_LErx.js} +14 -14
  143. package/frontend/dist/assets/{variableDetection-CbYSa1ka.js.map → variableDetection-DGr_LErx.js.map} +1 -1
  144. package/frontend/dist/index.html +3 -3
  145. package/package.json +6 -4
  146. package/frontend/dist/assets/ServersPage-DHYwQ5AM.js.map +0 -1
  147. package/frontend/dist/assets/SettingsPage-CSJ35jlM.js +0 -14
  148. package/frontend/dist/assets/SettingsPage-CSJ35jlM.js.map +0 -1
  149. package/frontend/dist/assets/index-6AyPtx0A.js +0 -3
  150. package/frontend/dist/assets/index-6AyPtx0A.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"GroupsPage-sE6YJyuK.js","sources":["../../src/utils/capabilitySelection.ts","../../src/components/CapabilitySelection.tsx","../../src/components/ServerToolConfig.tsx","../../src/components/GroupVisibilityFields.tsx","../../src/components/AddGroupForm.tsx","../../src/components/EditGroupForm.tsx","../../src/components/GroupCard.tsx","../../src/components/GroupImportForm.tsx","../../src/components/TemplateExportForm.tsx","../../src/components/TemplateImportForm.tsx","../../src/pages/GroupsPage.tsx"],"sourcesContent":["export interface SelectableCapability {\n value: string;\n description?: string;\n annotations?: Record<string, unknown>;\n}\nexport type SelectionAction = 'select' | 'deselect' | 'invert';\nexport type AnnotationFilter = 'all' | 'readOnlyHint' | 'destructiveHint' | 'idempotentHint';\nexport type RiskGroup = 'read' | 'create' | 'update' | 'delete' | 'other';\nexport const RISK_GROUPS: RiskGroup[] = ['read', 'create', 'update', 'delete', 'other'];\nexport const classifyTool = (item: SelectableCapability): RiskGroup => {\n if (item.annotations?.readOnlyHint === true) return 'read';\n const name = item.value.toLowerCase();\n if (/^(delete|remove)[_-]/.test(name)) return 'delete';\n // A destructive hint does not distinguish create/update/delete.\n if (item.annotations?.destructiveHint === true) return 'other';\n if (/^(create|add)[_-]/.test(name)) return 'create';\n if (/^(update|set)[_-]/.test(name)) return 'update';\n if (item.annotations?.readOnlyHint !== false && /^(get|list|read|search)[_-]/.test(name))\n return 'read';\n return 'other';\n};\n\nexport const filterCapabilities = <T extends SelectableCapability>(\n items: T[],\n query: string,\n annotation: AnnotationFilter,\n): T[] => {\n const search = query.trim().toLowerCase();\n return items.filter(\n (item) =>\n (item.value.toLowerCase().includes(search) ||\n item.description?.toLowerCase().includes(search)) &&\n (annotation === 'all' || item.annotations?.[annotation] === true),\n );\n};\n\nexport const applyVisibleSelection = (\n selection: string[] | 'all',\n all: string[],\n visible: string[],\n action: SelectionAction,\n): string[] | 'all' => {\n if (visible.length === 0 || (selection === 'all' && action === 'select')) return selection;\n const selected = new Set(selection === 'all' ? all : selection);\n for (const name of visible) {\n if (action === 'deselect' || (action === 'invert' && selected.has(name))) selected.delete(name);\n else selected.add(name);\n }\n // An explicit snapshot stays explicit, including when every current item is selected.\n return [...selected];\n};\n","import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n AnnotationFilter,\n applyVisibleSelection,\n classifyTool,\n filterCapabilities,\n RISK_GROUPS,\n SelectableCapability,\n SelectionAction,\n} from '@/utils/capabilitySelection';\n\ninterface Props<T extends SelectableCapability> {\n items: T[];\n selection: string[] | 'all';\n tools: boolean;\n label: string;\n onChange: (selection: string[] | 'all') => void;\n children: (item: T) => React.ReactNode;\n}\n\nexport const CapabilitySelection = <T extends SelectableCapability>({\n items,\n selection,\n tools,\n label,\n onChange,\n children,\n}: Props<T>) => {\n const { t } = useTranslation();\n const [query, setQuery] = useState('');\n const [annotation, setAnnotation] = useState<AnnotationFilter>('all');\n const [grouped, setGrouped] = useState(false);\n const visible = filterCapabilities(items, query, annotation);\n const selected = new Set(selection === 'all' ? items.map((item) => item.value) : selection);\n const apply = (target: T[], action: SelectionAction) =>\n onChange(\n applyVisibleSelection(\n selection,\n items.map((item) => item.value),\n target.map((item) => item.value),\n action,\n ),\n );\n const sections =\n tools && grouped\n ? RISK_GROUPS.map((risk) => ({\n risk,\n items: visible.filter((item) => classifyTool(item) === risk),\n }))\n : [{ risk: null, items: visible }];\n const buttonClass =\n 'text-xs text-blue-600 hover:text-blue-800 disabled:opacity-40 disabled:cursor-not-allowed';\n\n return (\n <section aria-label={label}>\n <div className=\"flex flex-wrap items-center gap-2 mb-2\">\n <input\n type=\"search\"\n aria-label={t('groups.bulkSearchLabel', { capability: label })}\n placeholder={t('groups.bulkSearch')}\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n 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\"\n />\n {tools && (\n <>\n <select\n aria-label={t('groups.annotationFilter')}\n value={annotation}\n onChange={(event) => setAnnotation(event.target.value as AnnotationFilter)}\n className=\"max-w-full rounded border border-gray-300 bg-white dark:bg-gray-800 px-2 py-1 text-sm\"\n >\n <option value=\"all\">{t('groups.allAnnotations')}</option>\n {(['readOnlyHint', 'destructiveHint', 'idempotentHint'] as const).map((hint) => (\n <option key={hint} value={hint}>\n {t(`groups.${hint}`)}\n </option>\n ))}\n </select>\n <button\n type=\"button\"\n aria-pressed={grouped}\n onClick={() => setGrouped(!grouped)}\n className={buttonClass}\n >\n {t(grouped ? 'groups.flatList' : 'groups.riskGroups')}\n </button>\n </>\n )}\n </div>\n <div className=\"flex flex-wrap items-center gap-x-3 gap-y-1 mb-2\">\n <span className=\"text-xs text-gray-500\" role=\"status\">\n {t('groups.visibleCount', { count: visible.length, total: items.length })}\n </span>\n {(['select', 'deselect', 'invert'] as const).map((action) => (\n <button\n key={action}\n type=\"button\"\n disabled={!visible.length}\n onClick={() => apply(visible, action)}\n className={buttonClass}\n >\n {t(`groups.${action}Visible`)}\n </button>\n ))}\n </div>\n {tools && grouped && <p className=\"text-xs text-gray-500 mb-2\">{t('groups.riskHint')}</p>}\n <div className=\"grid grid-cols-1 gap-2 max-h-96 overflow-y-auto\">\n {visible.length === 0 && (\n <p className=\"text-sm text-gray-500\">{t('groups.noMatchingItems')}</p>\n )}\n {sections\n .filter((section) => section.items.length > 0)\n .map((section) => {\n const count = section.items.filter((item) => selected.has(item.value)).length;\n return (\n <React.Fragment key={section.risk ?? 'flat'}>\n {section.risk && (\n <div className=\"flex flex-wrap items-center justify-between gap-2 border-b border-gray-200 py-1\">\n <span className=\"text-xs font-medium\">\n {t(`groups.risk_${section.risk}`)} ({count}/{section.items.length})\n </span>\n <button\n type=\"button\"\n className={buttonClass}\n onClick={() =>\n apply(section.items, count === section.items.length ? 'deselect' : 'select')\n }\n >\n {t(count === section.items.length ? 'groups.selectNone' : 'groups.selectAll')}\n </button>\n </div>\n )}\n {section.items.map((item) => (\n <React.Fragment key={item.value}>{children(item)}</React.Fragment>\n ))}\n </React.Fragment>\n );\n })}\n </div>\n </section>\n );\n};\n","import { CapabilitySelection } from './CapabilitySelection.js';\nimport React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { IGroupServerConfig, Prompt, Resource, Server, ServerCost, Tool } from '@/types';\nimport { Wrench, MessageSquare, FileText, Pin } from 'lucide-react';\nimport { cn } from '@/utils/cn';\nimport { useSettingsData } from '@/hooks/useSettingsData';\nimport { formatTokens } from '@/utils/contextCost';\nimport { getToolDescriptionInfo } from '@/utils/toolDescription';\n\ntype CapabilityKey = 'tools' | 'prompts' | 'resources';\n\nconst EMPTY_SELECTIONS: Pick<IGroupServerConfig, CapabilityKey> = {\n tools: [],\n prompts: [],\n resources: [],\n};\n\nconst FULL_SELECTIONS: Pick<IGroupServerConfig, CapabilityKey> = {\n tools: 'all',\n prompts: 'all',\n resources: 'all',\n};\n\ninterface ServerToolConfigProps {\n servers: Server[];\n value: string[] | IGroupServerConfig[];\n onChange: (value: IGroupServerConfig[]) => void;\n className?: string;\n serverCosts?: ServerCost[];\n}\n\ninterface CapabilityItem {\n annotations?: Record<string, unknown>;\n key: string;\n value: string;\n description?: string;\n defaultDescription?: string;\n hasDescriptionOverride?: boolean;\n}\n\nexport const ServerToolConfig: React.FC<ServerToolConfigProps> = ({\n servers,\n value,\n onChange,\n className,\n serverCosts = [],\n}) => {\n const { t } = useTranslation();\n const aliasInputId = React.useId();\n const { nameSeparator, smartRoutingConfig } = useSettingsData();\n const [expandedServers, setExpandedServers] = useState<Set<string>>(new Set());\n\n // Normalize current value to IGroupServerConfig[] format\n const normalizedValue: IGroupServerConfig[] = React.useMemo(() => {\n return value.map((item) => {\n if (typeof item === 'string') {\n return { name: item, ...FULL_SELECTIONS };\n }\n return {\n ...item,\n tools: item.tools || 'all',\n prompts: item.prompts || 'all',\n resources: item.resources || 'all',\n };\n });\n }, [value]);\n\n // Get available servers (enabled only)\n const availableServers = React.useMemo(\n () => servers.filter((server) => server.enabled !== false),\n [servers],\n );\n\n // Clean up expanded servers when servers are removed from configuration\n // But keep servers that were explicitly expanded even if they have no configuration\n React.useEffect(() => {\n const configuredServerNames = new Set(normalizedValue.map((config) => config.name));\n const availableServerNames = new Set(availableServers.map((server) => server.name));\n\n setExpandedServers((prev) => {\n const newSet = new Set<string>();\n prev.forEach((serverName) => {\n // Keep expanded if server is configured OR if server exists and user manually expanded it\n if (configuredServerNames.has(serverName) || availableServerNames.has(serverName)) {\n newSet.add(serverName);\n }\n });\n return newSet;\n });\n }, [normalizedValue, availableServers]);\n\n const toggleServer = (serverName: string) => {\n const existingIndex = normalizedValue.findIndex((config) => config.name === serverName);\n\n if (existingIndex >= 0) {\n // Remove server - this also removes all capability selections\n const newValue = normalizedValue.filter((config) => config.name !== serverName);\n onChange(newValue);\n } else {\n // Add server with all capabilities by default\n const newValue = [...normalizedValue, { name: serverName, ...FULL_SELECTIONS }];\n onChange(newValue);\n }\n };\n\n const toggleServerExpanded = (serverName: string) => {\n setExpandedServers((prev) => {\n const newSet = new Set(prev);\n if (newSet.has(serverName)) {\n newSet.delete(serverName);\n } else {\n newSet.add(serverName);\n }\n return newSet;\n });\n };\n\n const hasAnyCapabilitySelection = (config: IGroupServerConfig) => {\n return (['tools', 'prompts', 'resources'] as CapabilityKey[]).some((capability) => {\n const selection = config[capability];\n return selection === 'all' || (Array.isArray(selection) && selection.length > 0);\n });\n };\n\n const updateServerCapability = (\n serverName: string,\n capability: CapabilityKey,\n selection: string[] | 'all',\n keepExpanded = false,\n ) => {\n const existingServer = normalizedValue.find((config) => config.name === serverName);\n const baseConfig: IGroupServerConfig = existingServer\n ? { ...existingServer }\n : { name: serverName, ...EMPTY_SELECTIONS };\n const nextConfig: IGroupServerConfig = {\n ...baseConfig,\n [capability]: selection,\n };\n // A deselected tool drops its pin, so selecting it again does not silently re-pin it\n if (capability === 'tools' && Array.isArray(selection) && nextConfig.pinnedTools) {\n nextConfig.pinnedTools = nextConfig.pinnedTools.filter((name) => selection.includes(name));\n if (nextConfig.pinnedTools.length === 0) delete nextConfig.pinnedTools;\n }\n\n if (!hasAnyCapabilitySelection(nextConfig)) {\n const newValue = normalizedValue.filter((config) => config.name !== serverName);\n onChange(newValue);\n if (!keepExpanded) {\n setExpandedServers((prev) => {\n const newSet = new Set(prev);\n newSet.delete(serverName);\n return newSet;\n });\n }\n return;\n }\n\n if (existingServer) {\n onChange(normalizedValue.map((config) => (config.name === serverName ? nextConfig : config)));\n return;\n }\n\n onChange([...normalizedValue, nextConfig]);\n };\n\n const updateServerAlias = (serverName: string, alias: string) => {\n const existingServer = normalizedValue.find((config) => config.name === serverName);\n if (!existingServer) return;\n\n const nextConfig: IGroupServerConfig = { ...existingServer };\n if (alias) {\n nextConfig.alias = alias;\n } else {\n delete nextConfig.alias;\n }\n\n onChange(normalizedValue.map((config) => (config.name === serverName ? nextConfig : config)));\n };\n\n const togglePinnedTool = (serverName: string, toolName: string) => {\n const existingServer = normalizedValue.find((config) => config.name === serverName);\n if (!existingServer) return;\n\n const pinnedTools = existingServer.pinnedTools ?? [];\n const nextConfig: IGroupServerConfig = {\n ...existingServer,\n pinnedTools: pinnedTools.includes(toolName)\n ? pinnedTools.filter((name) => name !== toolName)\n : [...pinnedTools, toolName],\n };\n if (nextConfig.pinnedTools!.length === 0) delete nextConfig.pinnedTools;\n\n onChange(normalizedValue.map((config) => (config.name === serverName ? nextConfig : config)));\n };\n\n const normalizeNamedCapability = (serverName: string, name: string) => {\n const prefix = `${serverName}${nameSeparator}`;\n return name.startsWith(prefix) ? name.slice(prefix.length) : name;\n };\n\n const getCapabilityItems = (server: Server, capability: CapabilityKey): CapabilityItem[] => {\n if (capability === 'tools') {\n return (server.tools || [])\n .filter((tool) => tool.enabled !== false)\n .map((tool: Tool) => ({\n key: tool.name,\n value: normalizeNamedCapability(server.name, tool.name),\n description: tool.description,\n annotations: tool.annotations,\n defaultDescription: tool.defaultDescription,\n hasDescriptionOverride: tool.hasDescriptionOverride,\n }));\n }\n\n if (capability === 'prompts') {\n return (server.prompts || [])\n .filter((prompt) => prompt.enabled !== false)\n .map((prompt: Prompt) => ({\n key: prompt.name,\n value: normalizeNamedCapability(server.name, prompt.name),\n description: prompt.description,\n }));\n }\n\n return (server.resources || [])\n .filter((resource) => resource.enabled !== false)\n .map((resource: Resource) => ({\n key: resource.uri,\n value: resource.uri,\n description: resource.description,\n }));\n };\n\n // Build one nested map (server -> item name -> cost) once per serverCosts change,\n // so per-render lookups don't rebuild a Map on every call (avoids O(N^2) churn).\n const serverCostsMap = React.useMemo(() => {\n const outerMap = new Map<string, Map<string, number>>();\n serverCosts.forEach((sc) => {\n const innerMap = new Map<string, number>();\n sc.items.forEach((i) => innerMap.set(i.name, i.cost));\n outerMap.set(sc.name, innerMap);\n });\n return outerMap;\n }, [serverCosts]);\n\n const costMapForServer = (serverName: string): Map<string, number> =>\n serverCostsMap.get(serverName) ?? new Map<string, number>();\n\n const getSelectedCapabilityCost = (server: Server, capability: CapabilityKey): number => {\n const costMap = costMapForServer(server.name);\n return getCapabilityItems(server, capability)\n .filter((item) => isCapabilityItemSelected(server.name, capability, item.value))\n .reduce((sum, item) => sum + (costMap.get(item.key) ?? 0), 0);\n };\n\n const getServerSelectedCost = (server: Server): number =>\n (['tools', 'prompts', 'resources'] as CapabilityKey[]).reduce(\n (sum, cap) => sum + getSelectedCapabilityCost(server, cap),\n 0,\n );\n\n const toggleCapabilityItem = (\n serverName: string,\n capability: CapabilityKey,\n itemValue: string,\n ) => {\n const server = availableServers.find((s) => s.name === serverName);\n if (!server) return;\n\n const allItems = getCapabilityItems(server, capability).map((item) => item.value);\n const serverConfig = normalizedValue.find((config) => config.name === serverName);\n\n if (!serverConfig) {\n updateServerCapability(serverName, capability, [itemValue]);\n return;\n }\n\n const currentSelection = serverConfig[capability];\n if (currentSelection === 'all') {\n const nextSelection = allItems.filter((value) => value !== itemValue);\n updateServerCapability(serverName, capability, nextSelection);\n return;\n }\n\n if (Array.isArray(currentSelection)) {\n if (currentSelection.includes(itemValue)) {\n updateServerCapability(\n serverName,\n capability,\n currentSelection.filter((value) => value !== itemValue),\n );\n return;\n }\n\n const nextSelection = [...currentSelection, itemValue];\n updateServerCapability(\n serverName,\n capability,\n nextSelection.length === allItems.length ? 'all' : nextSelection,\n );\n return;\n }\n\n updateServerCapability(serverName, capability, [itemValue]);\n };\n\n const isServerSelected = (serverName: string) => {\n const serverConfig = normalizedValue.find((config) => config.name === serverName);\n return Boolean(serverConfig && hasAnyCapabilitySelection(serverConfig));\n };\n\n const isServerPartiallySelected = (serverName: string) => {\n const serverConfig = normalizedValue.find((config) => config.name === serverName);\n if (!serverConfig) return false;\n\n return (['tools', 'prompts', 'resources'] as CapabilityKey[]).some((capability) => {\n const selection = serverConfig[capability];\n return Array.isArray(selection) && selection.length > 0;\n });\n };\n\n const isCapabilityItemSelected = (\n serverName: string,\n capability: CapabilityKey,\n itemValue: string,\n ) => {\n const serverConfig = normalizedValue.find((config) => config.name === serverName);\n if (!serverConfig) return false;\n\n const selection = serverConfig[capability];\n if (selection === 'all') return true;\n return Array.isArray(selection) ? selection.includes(itemValue) : false;\n };\n\n const getSelectedCapabilityCount = (server: Server, capability: CapabilityKey) => {\n const serverConfig = normalizedValue.find((config) => config.name === server.name);\n if (!serverConfig) return 0;\n\n const items = getCapabilityItems(server, capability);\n const selection = serverConfig[capability];\n if (selection === 'all') return items.length;\n if (Array.isArray(selection)) {\n const itemSet = new Set(items.map((item) => item.value));\n return selection.filter((item) => itemSet.has(item)).length;\n }\n return 0;\n };\n\n const capabilityConfigs: Array<{\n key: CapabilityKey;\n titleKey: string;\n countKey: string;\n allKey: string;\n }> = [\n {\n key: 'tools',\n titleKey: 'groups.toolSelection',\n countKey: 'groups.toolsSelected',\n allKey: 'groups.allTools',\n },\n {\n key: 'prompts',\n titleKey: 'groups.promptSelection',\n countKey: 'groups.promptsSelected',\n allKey: 'groups.allPrompts',\n },\n {\n key: 'resources',\n titleKey: 'groups.resourceSelection',\n countKey: 'groups.resourcesSelected',\n allKey: 'groups.allResources',\n },\n ];\n\n const getServerSummaryBadges = (server: Server) => {\n return capabilityConfigs\n .map(({ key }) => ({ key, count: getSelectedCapabilityCount(server, key) }))\n .filter((entry) => entry.count > 0);\n };\n\n return (\n <div className={cn('space-y-4', className)}>\n <div className=\"space-y-3\">\n {availableServers.map((server) => {\n const isSelected = isServerSelected(server.name);\n const isPartiallySelected = isServerPartiallySelected(server.name);\n const isExpanded = expandedServers.has(server.name);\n const serverConfig = normalizedValue.find((config) => config.name === server.name);\n const summaryBadges = getServerSummaryBadges(server);\n const serverCapabilities = capabilityConfigs.filter(\n ({ key }) => getCapabilityItems(server, key).length > 0,\n );\n const costMap = costMapForServer(server.name);\n\n return (\n <div\n key={server.name}\n 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\"\n >\n <div\n className=\"flex items-center justify-between p-3 cursor-pointer rounded-lg transition-colors\"\n onClick={() => toggleServerExpanded(server.name)}\n >\n <div\n className=\"flex items-center space-x-3\"\n onClick={(e) => {\n e.stopPropagation();\n toggleServer(server.name);\n }}\n >\n <input\n type=\"checkbox\"\n checked={isSelected || isPartiallySelected}\n onChange={() => toggleServer(server.name)}\n className=\"w-4 h-4 text-blue-600 accent-[var(--hub-accent)] rounded focus:ring-blue-500\"\n />\n <span className=\"font-medium text-[var(--hub-ink)] cursor-pointer select-none\">\n {server.name}\n </span>\n </div>\n\n <div className=\"flex items-center space-x-3\">\n {getServerSelectedCost(server) > 0 && (\n <span className=\"text-sm text-[var(--hub-ink-3)] hub-mono\" title={t('cost.estimate')}>\n Σ {formatTokens(getServerSelectedCost(server))}\n </span>\n )}\n {summaryBadges.map(({ key, count }) => (\n <span key={key} className=\"text-sm text-green-600 flex items-center gap-1\">\n {key === 'tools' ? (\n <Wrench size={14} />\n ) : key === 'prompts' ? (\n <MessageSquare size={14} />\n ) : (\n <FileText size={14} />\n )}{' '}\n {count}\n </span>\n ))}\n\n {serverCapabilities.length > 0 && (\n <button\n type=\"button\"\n className=\"p-1 text-[var(--hub-ink-3)] hover:text-[var(--hub-ink-2)] transition-colors\"\n >\n <svg\n className={cn('w-5 h-5 transition-transform', isExpanded && 'rotate-180')}\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 9l-7 7-7-7\"\n />\n </svg>\n </button>\n )}\n </div>\n </div>\n\n {isExpanded && serverCapabilities.length > 0 && (\n <div className=\"border-t border-[var(--hub-line)] bg-[var(--hub-bg-2)] p-3\">\n <div className=\"space-y-4\">\n {serverConfig && (\n <div className=\"space-y-1\" onClick={(e) => e.stopPropagation()}>\n <label\n htmlFor={`${aliasInputId}-${server.name}`}\n className=\"block text-xs font-medium text-[var(--hub-ink-2)]\"\n >\n {t('groups.alias')}\n </label>\n <input\n type=\"text\"\n id={`${aliasInputId}-${server.name}`}\n value={serverConfig.alias || ''}\n placeholder={server.name}\n onChange={(event) => updateServerAlias(server.name, event.target.value)}\n className=\"hub-input\"\n />\n <label className=\"flex items-center gap-2 text-xs text-[var(--hub-ink-2)]\">\n <input\n type=\"checkbox\"\n checked={serverConfig.preserveToolNames === true}\n onChange={(event) =>\n onChange(\n normalizedValue.map((config) =>\n config.name === server.name\n ? { ...config, preserveToolNames: event.target.checked }\n : config,\n ),\n )\n }\n />\n {t('groups.preserveToolNames')}\n </label>\n <p className=\"text-xs text-[var(--hub-ink-3)]\">\n {t('groups.preserveToolNamesHint')}\n </p>\n </div>\n )}\n {serverCapabilities.map(({ key, titleKey, countKey, allKey }) => {\n const items = getCapabilityItems(server, key);\n const selectedCount = getSelectedCapabilityCount(server, key);\n const allSelected =\n serverConfig?.[key] === 'all' || selectedCount === items.length;\n\n return (\n <div key={key}>\n <div className=\"flex items-center justify-between mb-3\">\n <span className=\"text-sm font-medium text-[var(--hub-ink-2)]\">{t(titleKey)}</span>\n <div className=\"flex items-center gap-3\">\n {serverConfig && (\n <span className=\"text-xs text-green-600\">\n {allSelected\n ? `(${t(allKey)} ${items.length}/${items.length})`\n : `(${t(countKey)} ${selectedCount}/${items.length})`}\n </span>\n )}\n {serverConfig && getSelectedCapabilityCost(server, key) > 0 && (\n <span\n className=\"text-xs text-[var(--hub-ink-3)] hub-mono\"\n title={t('cost.estimate')}\n >\n Σ {formatTokens(getSelectedCapabilityCost(server, key))}\n </span>\n )}\n <button\n type=\"button\"\n onClick={() => {\n updateServerCapability(\n server.name,\n key,\n allSelected ? [] : 'all',\n true,\n );\n }}\n className=\"text-sm text-blue-600 hover:text-blue-800 transition-colors\"\n >\n {allSelected ? t('groups.selectNone') : t('groups.selectAll')}\n </button>\n </div>\n </div>\n\n <CapabilitySelection\n items={items}\n selection={serverConfig?.[key] ?? []}\n tools={key === 'tools'}\n label={t(titleKey)}\n onChange={(selection) =>\n updateServerCapability(server.name, key, selection, true)\n }\n >\n {(item) => {\n const isChecked = isCapabilityItemSelected(\n server.name,\n key,\n item.value,\n );\n const isPinned = Boolean(\n serverConfig?.pinnedTools?.includes(item.value),\n );\n const descriptionInfo =\n key === 'tools'\n ? getToolDescriptionInfo(\n {\n description: item.description,\n defaultDescription: item.defaultDescription,\n hasDescriptionOverride: item.hasDescriptionOverride,\n },\n t('tool.noDescription'),\n )\n : null;\n const descriptionTitle = descriptionInfo?.hasDescriptionOverride\n ? t('tool.defaultDescriptionTooltip', {\n description: descriptionInfo.defaultDescription,\n })\n : item.description;\n\n return (\n <div key={item.key} className=\"flex min-w-0 items-center gap-2\">\n <label className=\"flex min-w-0 flex-1 items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={isChecked}\n onChange={() =>\n toggleCapabilityItem(server.name, key, item.value)\n }\n className=\"w-3 h-3 text-blue-600 accent-[var(--hub-accent)] rounded focus:ring-blue-500\"\n />\n <span className=\"text-[var(--hub-ink-2)] break-all whitespace-nowrap flex-shrink-0\">\n {item.value}\n </span>\n {(item.description ||\n descriptionInfo?.hasDescriptionOverride) && (\n <span className=\"min-w-0 flex items-center gap-1 text-[var(--hub-ink-3)] text-xs truncate\">\n <span\n className=\"truncate\"\n title={descriptionTitle || undefined}\n >\n {descriptionInfo\n ? descriptionInfo.currentDescription\n : item.description}\n </span>\n {descriptionInfo?.hasDescriptionOverride && (\n <span\n 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\"\n title={descriptionTitle || undefined}\n >\n {t('tool.descriptionModifiedBadge')}\n </span>\n )}\n </span>\n )}\n {costMap.get(item.key) != null && (\n <span\n className=\"text-xs text-[var(--hub-ink-3)] hub-mono whitespace-nowrap ml-auto flex-shrink-0\"\n title={t('cost.estimate')}\n >\n Σ {formatTokens(costMap.get(item.key)!)}\n </span>\n )}\n </label>\n {/* Shown while Smart Routing is on, and for an existing pin even\n when it is off, so a pin is never left invisible */}\n {key === 'tools' &&\n isChecked &&\n (smartRoutingConfig.enabled || isPinned) && (\n <button\n type=\"button\"\n onClick={() => togglePinnedTool(server.name, item.value)}\n title={t(isPinned ? 'groups.unpinTool' : 'groups.pinTool')}\n aria-label={t('groups.pinToolLabel')}\n aria-pressed={isPinned}\n className={cn(\n 'flex-shrink-0 transition-colors',\n isPinned\n ? 'text-blue-600'\n : 'text-[var(--hub-ink-3)] hover:text-[var(--hub-ink-2)]',\n )}\n >\n <Pin size={12} fill={isPinned ? 'currentColor' : 'none'} />\n </button>\n )}\n </div>\n );\n }}\n </CapabilitySelection>\n </div>\n );\n })}\n </div>\n </div>\n )}\n </div>\n );\n })}\n </div>\n\n {availableServers.length === 0 && (\n <p className=\"text-[var(--hub-ink-3)] text-sm\">{t('groups.noServerOptions')}</p>\n )}\n </div>\n );\n};\n","import UserGroupSelection from './UserGroupSelection';\nimport { useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport type { Group } from '@/types';\nimport { apiGet } from '@/utils/fetchInterceptor';\n\ntype Access = Pick<Group, 'visibility' | 'sharedWithUserGroups' | 'sharedWithUsers'>;\n\nexport default function GroupVisibilityFields({\n groupId,\n value,\n onChange,\n}: {\n groupId?: string;\n value: Access;\n onChange: (access: Access) => void;\n}) {\n const { t } = useTranslation();\n const [users, setUsers] = useState<string[]>([]);\n const [search, setSearch] = useState('');\n const [userGroups, setUserGroups] = useState<string[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState(false);\n const [isAdvancedExpanded, setIsAdvancedExpanded] = useState(false);\n useEffect(() => {\n if (!groupId || value.visibility !== 'group') return;\n let cancelled = false;\n setLoading(true);\n setError(false);\n apiGet<{ success: boolean; data?: string[]; userGroups?: string[] }>(\n `/groups/${encodeURIComponent(groupId)}/share-candidates`,\n )\n .then((result) => {\n if (cancelled) return;\n if (result.success && Array.isArray(result.data)) {\n setUsers(result.data);\n setUserGroups(result.userGroups || []);\n } else setError(true);\n })\n .catch(() => {\n if (!cancelled) setError(true);\n })\n .finally(() => {\n if (!cancelled) setLoading(false);\n });\n return () => {\n cancelled = true;\n };\n }, [groupId, value.visibility]);\n const selected = value.sharedWithUsers || [];\n const candidates = [...new Set([...users, ...selected])]\n .sort()\n .filter((username) => username.toLowerCase().includes(search.toLowerCase()));\n const selectedUsers = new Set(selected);\n const allCandidatesSelected =\n candidates.length > 0 && candidates.every((username) => selectedUsers.has(username));\n const noCandidatesSelected =\n candidates.length === 0 || candidates.every((username) => !selectedUsers.has(username));\n\n const toggleSharedUser = (username: string) => {\n const nextSelected = new Set(selected);\n if (nextSelected.has(username)) {\n nextSelected.delete(username);\n } else {\n nextSelected.add(username);\n }\n onChange({ sharedWithUsers: Array.from(nextSelected) });\n };\n\n return (\n <div className=\"mb-4\">\n <div\n 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)]\"\n onClick={() => setIsAdvancedExpanded(!isAdvancedExpanded)}\n >\n <h3 className=\"text-sm font-semibold text-[var(--hub-ink)]\">\n {t('server.sectionAdvanced', 'Advanced Options')}\n </h3>\n <span className=\"text-[var(--hub-ink-3)] text-sm\">{isAdvancedExpanded ? '▼' : '▶'}</span>\n </div>\n\n {isAdvancedExpanded && (\n <div className=\"border border-[var(--hub-line)] rounded-b p-4 bg-[var(--hub-surface)] border-t-0\">\n <label\n htmlFor=\"group-visibility\"\n className=\"block text-sm font-medium mb-1.5 text-[var(--hub-ink-2)]\"\n >\n {t('server.visibility')}\n </label>\n <select\n id=\"group-visibility\"\n className=\"hub-input\"\n value={value.visibility || ''}\n onChange={(event) =>\n onChange({ visibility: event.target.value as Group['visibility'] })\n }\n >\n {!value.visibility && (\n <option value=\"\" disabled>\n {t('groups.legacyVisibility')}\n </option>\n )}\n <option value=\"private\">{t('server.visibilityPrivate')}</option>\n <option value=\"group\">{t('server.visibilityGroup')}</option>\n <option value=\"public\">{t('server.visibilityPublic')}</option>\n </select>\n <p className=\"text-xs text-[var(--hub-ink-3)] mt-1\">{t('groups.visibilityDescription')}</p>\n {!value.visibility && (\n <p className=\"text-sm text-amber-600\">{t('groups.legacyVisibilityHint')}</p>\n )}\n {value.visibility === 'group' && (\n <div className=\"mt-4 rounded border border-[var(--hub-line)] p-3\">\n <UserGroupSelection\n options={userGroups}\n selected={value.sharedWithUserGroups || []}\n disabled={loading || error || !groupId}\n onChange={(sharedWithUserGroups) => onChange({ sharedWithUserGroups })}\n />\n <div className=\"text-sm font-medium text-[var(--hub-ink-2)]\">\n {t('server.shareWithUsers')}\n </div>\n <p className=\"text-xs text-[var(--hub-ink-3)] mt-1 mb-3\">\n {t('server.shareWithUsersDescription')}\n </p>\n {!groupId ? (\n <p className=\"text-sm text-[var(--hub-ink-3)]\">{t('groups.shareAfterCreate')}</p>\n ) : (\n <>\n {loading && (\n <p className=\"text-sm text-[var(--hub-ink-3)]\">{t('server.shareCandidatesLoading')}</p>\n )}\n {error && (\n <p role=\"alert\" className=\"text-sm text-red-600 dark:text-red-400\">\n {t('server.shareCandidatesError')}\n </p>\n )}\n {!loading && !error && candidates.length === 0 && (\n <p className=\"text-sm text-[var(--hub-ink-3)]\">\n {search ? t('server.noMatchingShareUsers') : t('server.noShareCandidates')}\n </p>\n )}\n {candidates.length > 0 && (\n <>\n <div className=\"mb-3 space-y-2\">\n <label\n htmlFor=\"group-share-search\"\n className=\"block text-xs font-medium text-[var(--hub-ink-2)]\"\n >\n {t('server.shareUserSearchLabel')}\n </label>\n <input\n id=\"group-share-search\"\n type=\"search\"\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n placeholder={t('server.shareUserSearchPlaceholder')}\n className=\"hub-input text-sm\"\n />\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n onClick={() =>\n onChange({\n sharedWithUsers: [...new Set([...selected, ...candidates])],\n })\n }\n disabled={allCandidatesSelected}\n className=\"hub-btn text-sm\"\n >\n {t('server.selectAllShareUsers')}\n </button>\n <button\n type=\"button\"\n onClick={() =>\n onChange({\n sharedWithUsers: selected.filter(\n (name) => !candidates.includes(name),\n ),\n })\n }\n disabled={noCandidatesSelected}\n className=\"hub-btn text-sm\"\n >\n {t('server.deselectAllShareUsers')}\n </button>\n </div>\n </div>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-2\">\n {candidates.map((username) => (\n <label\n key={username}\n className=\"flex items-center gap-2 rounded border border-[var(--hub-line)] px-3 py-2 text-sm text-[var(--hub-ink-2)]\"\n >\n <input\n type=\"checkbox\"\n checked={selectedUsers.has(username)}\n onChange={() => toggleSharedUser(username)}\n />\n <span>{username}</span>\n </label>\n ))}\n </div>\n </>\n )}\n </>\n )}\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n","import { useState, useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useGroupData } from '@/hooks/useGroupData';\nimport { useServerData } from '@/hooks/useServerData';\nimport { useCostData } from '@/hooks/useCostData';\nimport { GroupFormData, Server, IGroupServerConfig } from '@/types';\nimport { ServerToolConfig } from './ServerToolConfig';\nimport GroupVisibilityFields from './GroupVisibilityFields';\n\ninterface AddGroupFormProps {\n onAdd: () => void;\n onCancel: () => void;\n}\n\nconst AddGroupForm = ({ onAdd, onCancel }: AddGroupFormProps) => {\n const { t } = useTranslation();\n const { createGroup } = useGroupData();\n const { allServers } = useServerData();\n const { serverCosts } = useCostData();\n const [availableServers, setAvailableServers] = useState<Server[]>([]);\n const [error, setError] = useState<string | null>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n\n const [formData, setFormData] = useState<GroupFormData>({\n visibility: 'private',\n sharedWithUserGroups: [],\n sharedWithUsers: [],\n name: '',\n description: '',\n instructions: '',\n servers: [] as IGroupServerConfig[],\n });\n\n useEffect(() => {\n // Filter available servers (enabled only)\n setAvailableServers(allServers.filter((server) => server.enabled !== false));\n }, [allServers]);\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {\n const { name, value } = e.target;\n setFormData((prev) => ({\n ...prev,\n [name]: value,\n }));\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setIsSubmitting(true);\n setError(null);\n\n try {\n if (!formData.name.trim()) {\n setError(t('groups.nameRequired'));\n setIsSubmitting(false);\n return;\n }\n\n const result = await createGroup(formData.name, formData.description, formData.servers, {\n visibility: formData.visibility,\n sharedWithUserGroups: formData.sharedWithUserGroups,\n sharedWithUsers: formData.sharedWithUsers,\n instructions: formData.instructions,\n });\n if (!result || !result.success) {\n setError(result?.message || t('groups.createError'));\n setIsSubmitting(false);\n return;\n }\n\n onAdd();\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n setIsSubmitting(false);\n }\n };\n\n return (\n <div className=\"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4\">\n <div className=\"hub-card shadow-lg max-w-3xl w-full max-h-[90vh] flex flex-col\">\n <div className=\"p-6 flex-shrink-0\">\n <h2 className=\"text-xl font-semibold text-[var(--hub-ink)] mb-4\">{t('groups.addNew')}</h2>\n\n {error && (\n <div className=\"mb-4 p-3 bg-red-100 text-red-700 rounded-md border border-[var(--hub-line)]\">\n {error}\n </div>\n )}\n </div>\n\n <form onSubmit={handleSubmit} className=\"flex flex-col flex-1 min-h-0\">\n <div className=\"flex-1 overflow-y-auto px-6\">\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-[var(--hub-ink-2)] text-sm font-bold mb-2\" htmlFor=\"name\">\n {t('groups.name')} *\n </label>\n <input\n type=\"text\"\n id=\"name\"\n name=\"name\"\n value={formData.name}\n onChange={handleChange}\n 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)]\"\n placeholder={t('groups.namePlaceholder')}\n required\n />\n </div>\n\n <div>\n <label\n className=\"block text-[var(--hub-ink-2)] text-sm font-bold mb-2\"\n htmlFor=\"instructions\"\n >\n {t('groups.instructions')}\n </label>\n <textarea\n id=\"instructions\"\n name=\"instructions\"\n value={formData.instructions}\n onChange={handleChange}\n rows={3}\n 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)]\"\n placeholder={t('groups.instructionsPlaceholder')}\n />\n <p className=\"text-xs text-[var(--hub-ink-3)] mt-1\">{t('groups.instructionsHelp')}</p>\n </div>\n\n <div>\n <label className=\"block text-[var(--hub-ink-2)] text-sm font-bold mb-2\">\n {t('groups.configureCapabilities')}\n </label>\n <ServerToolConfig\n servers={availableServers}\n value={formData.servers as IGroupServerConfig[]}\n onChange={(servers) => setFormData((prev) => ({ ...prev, servers }))}\n className=\"border border-[var(--hub-line)] rounded-lg p-4 bg-[var(--hub-bg-2)]\"\n serverCosts={serverCosts}\n />\n </div>\n\n <GroupVisibilityFields\n value={formData}\n onChange={(access) => setFormData((previous) => ({ ...previous, ...access }))}\n />\n </div>\n </div>\n\n <div className=\"flex justify-end space-x-2 p-5 pt-3 border-t border-[var(--hub-line-2)] flex-shrink-0\">\n <button type=\"button\" onClick={onCancel} className=\"hub-btn\" disabled={isSubmitting}>\n {t('common.cancel')}\n </button>\n <button type=\"submit\" className=\"hub-btn primary\" disabled={isSubmitting}>\n {isSubmitting ? t('common.submitting') : t('common.create')}\n </button>\n </div>\n </form>\n </div>\n </div>\n );\n};\n\nexport default AddGroupForm;\n","import { useState, useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Group, GroupFormData, Server, IGroupServerConfig } from '@/types';\nimport { useGroupData } from '@/hooks/useGroupData';\nimport { useServerData } from '@/hooks/useServerData';\nimport { useCostData } from '@/hooks/useCostData';\nimport { ServerToolConfig } from './ServerToolConfig';\nimport GroupVisibilityFields from './GroupVisibilityFields';\n\ninterface EditGroupFormProps {\n group: Group;\n onEdit: () => void;\n onCancel: () => void;\n}\n\nconst EditGroupForm = ({ group, onEdit, onCancel }: EditGroupFormProps) => {\n const { t } = useTranslation();\n const { updateGroup } = useGroupData();\n const { allServers } = useServerData();\n const { serverCosts } = useCostData();\n const [availableServers, setAvailableServers] = useState<Server[]>([]);\n const [error, setError] = useState<string | null>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n\n const [formData, setFormData] = useState<GroupFormData>({\n visibility: group.visibility,\n sharedWithUserGroups: group.sharedWithUserGroups || [],\n sharedWithUsers: group.sharedWithUsers || [],\n name: group.name,\n description: group.description || '',\n instructions: group.instructions || '',\n servers: group.servers || [],\n });\n\n useEffect(() => {\n // Filter available servers (enabled only)\n setAvailableServers(allServers.filter((server) => server.enabled !== false));\n }, [allServers]);\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {\n const { name, value } = e.target;\n setFormData((prev) => ({\n ...prev,\n [name]: value,\n }));\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setIsSubmitting(true);\n setError(null);\n\n try {\n if (!formData.name.trim()) {\n setError(t('groups.nameRequired'));\n setIsSubmitting(false);\n return;\n }\n\n const result = await updateGroup(group.id, {\n visibility: formData.visibility,\n sharedWithUserGroups: formData.sharedWithUserGroups,\n sharedWithUsers: formData.sharedWithUsers,\n name: formData.name,\n description: formData.description,\n instructions: formData.instructions,\n servers: formData.servers,\n });\n\n if (!result || !result.success) {\n setError(result?.message || t('groups.updateError'));\n setIsSubmitting(false);\n return;\n }\n\n onEdit();\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n setIsSubmitting(false);\n }\n };\n\n return (\n <div className=\"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4\">\n <div className=\"hub-card shadow-lg max-w-3xl w-full max-h-[90vh] flex flex-col\">\n <div className=\"p-6 flex-shrink-0\">\n <h2 className=\"text-xl font-semibold text-[var(--hub-ink)] mb-4\">{t('groups.edit')}</h2>\n\n {error && (\n <div className=\"mb-4 p-3 bg-red-100 text-red-700 rounded-md border border-[var(--hub-line)]\">\n {error}\n </div>\n )}\n </div>\n\n <form onSubmit={handleSubmit} className=\"flex flex-col flex-1 min-h-0\">\n <div className=\"flex-1 overflow-y-auto px-6\">\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-[var(--hub-ink-2)] text-sm font-bold mb-2\" htmlFor=\"name\">\n {t('groups.name')} *\n </label>\n <input\n type=\"text\"\n id=\"name\"\n name=\"name\"\n value={formData.name}\n onChange={handleChange}\n 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)]\"\n placeholder={t('groups.namePlaceholder')}\n required\n />\n </div>\n\n <div>\n <label\n className=\"block text-[var(--hub-ink-2)] text-sm font-bold mb-2\"\n htmlFor=\"instructions\"\n >\n {t('groups.instructions')}\n </label>\n <textarea\n id=\"instructions\"\n name=\"instructions\"\n value={formData.instructions}\n onChange={handleChange}\n rows={3}\n 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)]\"\n placeholder={t('groups.instructionsPlaceholder')}\n />\n <p className=\"text-xs text-[var(--hub-ink-3)] mt-1\">{t('groups.instructionsHelp')}</p>\n </div>\n\n <div>\n <label className=\"block text-[var(--hub-ink-2)] text-sm font-bold mb-2\">\n {t('groups.configureCapabilities')}\n </label>\n <ServerToolConfig\n servers={availableServers}\n value={formData.servers as IGroupServerConfig[]}\n onChange={(servers) => setFormData((prev) => ({ ...prev, servers }))}\n className=\"border border-[var(--hub-line)] rounded-lg p-4 bg-[var(--hub-bg-2)]\"\n serverCosts={serverCosts}\n />\n </div>\n\n <GroupVisibilityFields\n groupId={group.id}\n value={formData}\n onChange={(access) => setFormData((previous) => ({ ...previous, ...access }))}\n />\n </div>\n </div>\n\n <div className=\"flex justify-end space-x-2 p-5 pt-3 border-t border-[var(--hub-line-2)] flex-shrink-0\">\n <button type=\"button\" onClick={onCancel} className=\"hub-btn\" disabled={isSubmitting}>\n {t('common.cancel')}\n </button>\n <button type=\"submit\" className=\"hub-btn primary\" disabled={isSubmitting}>\n {isSubmitting ? t('common.submitting') : t('common.save')}\n </button>\n </div>\n </form>\n </div>\n </div>\n );\n};\n\nexport default EditGroupForm;\n","import { useAuth } from '@/contexts/AuthContext';\nimport { useState, useRef, useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Edit3, Trash2, Copy, Check, Link as LinkIcon, FileCode, ChevronDown } from 'lucide-react';\nimport { Group, Server, IGroupServerConfig, GroupCost } from '@/types';\nimport DeleteDialog from '@/components/ui/DeleteDialog';\nimport CopyClientConfigDialog from '@/components/ui/CopyClientConfigDialog';\nimport {\n ACCESS_TOKEN_PLACEHOLDER,\n type ClientSnippetTarget,\n} from '@/utils/mcpClientSnippets';\nimport { copyText } from '@/utils/clipboard';\nimport { useToast } from '@/contexts/ToastContext';\nimport { useSettingsData } from '@/hooks/useSettingsData';\nimport { formatTokens, percentSaved } from '@/utils/contextCost';\n\ninterface GroupCardProps {\n group: Group;\n servers: Server[];\n onEdit: (group: Group) => void;\n onDelete: (groupId: string) => void;\n cost?: GroupCost;\n}\n\nconst getServerNames = (servers: string[] | IGroupServerConfig[]): string[] =>\n servers.map((server) => (typeof server === 'string' ? server : server.name));\n\nconst getServerConfig = (group: Group, serverName: string): IGroupServerConfig => {\n const server = group.servers.find((s) =>\n typeof s === 'string' ? s === serverName : s.name === serverName,\n );\n if (!server) return { name: serverName, tools: 'all', prompts: 'all', resources: 'all' };\n if (typeof server === 'string') {\n return { name: server, tools: 'all', prompts: 'all', resources: 'all' };\n }\n return server;\n};\n\nconst getServerDisplayName = (group: Group, serverName: string): string => {\n const config = getServerConfig(group, serverName);\n return config.alias?.trim() || serverName;\n};\n\nconst GroupCard = ({ group, servers, onEdit, onDelete, cost }: GroupCardProps) => {\n const { t } = useTranslation();\n const { auth } = useAuth();\n const canManage = !!auth.user && (auth.user.isAdmin || auth.user.username === group.owner);\n const { showToast } = useToast();\n const { installConfig, nameSeparator } = useSettingsData();\n const baseUrl = installConfig?.baseUrl?.replace(/\\/+$/, '') || '';\n\n const [showDeleteDialog, setShowDeleteDialog] = useState(false);\n const [clientConfigTarget, setClientConfigTarget] = useState<ClientSnippetTarget | null>(null);\n const [copied, setCopied] = useState(false);\n const [showCopyDropdown, setShowCopyDropdown] = useState(false);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handle = (e: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {\n setShowCopyDropdown(false);\n }\n };\n document.addEventListener('mousedown', handle);\n return () => document.removeEventListener('mousedown', handle);\n }, []);\n\n const doCopy = async (text: string) => {\n const ok = await copyText(text);\n if (ok) {\n setCopied(true);\n setShowCopyDropdown(false);\n showToast(t('common.copySuccess') || 'Copied', 'success');\n setTimeout(() => setCopied(false), 1500);\n } else {\n showToast(t('common.copyFailed') || 'Copy failed', 'error');\n }\n };\n\n const groupEndpoint = `${baseUrl}/mcp/${group.name}`;\n // Only the client-config dialog needs a URL-encoded path segment: group names\n // may contain spaces/CJK, and the generated client snippets must be valid URLs.\n // The raw groupEndpoint above is intentionally left as-is for the legacy\n // \"Copy URL\" actions.\n const clientConfigEndpoint = `${baseUrl}/mcp/${encodeURIComponent(group.name)}`;\n const groupOpenApiEndpoint = `${baseUrl}/api/${group.name}`;\n\n const serverNames = getServerNames(group.servers);\n const groupServers = servers.filter((s) => serverNames.includes(s.name));\n\n const tally = (server: Server) => {\n const cfg = getServerConfig(group, server.name);\n const prefix = `${server.name}${nameSeparator}`;\n const allTools = server.tools || [];\n const allPrompts = server.prompts || [];\n const allResources = server.resources || [];\n\n const visibleTools = Array.isArray(cfg.tools)\n ? allTools.filter((t) => {\n if (t.enabled === false) return false;\n const short = t.name.startsWith(prefix) ? t.name.slice(prefix.length) : t.name;\n return cfg.tools!.includes(short);\n }).length\n : allTools.filter((t) => t.enabled !== false).length;\n const visiblePrompts = Array.isArray(cfg.prompts)\n ? allPrompts.filter((p) => {\n if (p.enabled === false) return false;\n const short = p.name.startsWith(prefix) ? p.name.slice(prefix.length) : p.name;\n return cfg.prompts!.includes(short);\n }).length\n : allPrompts.filter((p) => p.enabled !== false).length;\n const visibleResources = Array.isArray(cfg.resources)\n ? allResources.filter((r) => r.enabled !== false && cfg.resources!.includes(r.uri)).length\n : allResources.filter((r) => r.enabled !== false).length;\n\n return {\n visibleTools,\n totalTools: allTools.length,\n visiblePrompts,\n totalPrompts: allPrompts.length,\n visibleResources,\n totalResources: allResources.length,\n };\n };\n\n const totalVisibleTools = groupServers.reduce((acc, s) => acc + tally(s).visibleTools, 0);\n\n return (\n <div className=\"hub-card flex h-full flex-col overflow-visible\">\n {/* Header */}\n <div\n className=\"flex items-start gap-3 px-4 py-3\"\n style={{ borderBottom: '1px solid var(--hub-line-2)' }}\n >\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span style={{ fontSize: 15, fontWeight: 600, letterSpacing: '-0.015em' }}>\n {group.name}\n </span>\n <span\n className=\"hub-mono\"\n style={{\n fontSize: 11,\n color: 'var(--hub-ink-3)',\n padding: '0 6px',\n border: '1px solid var(--hub-line)',\n borderRadius: 4,\n height: 18,\n display: 'inline-flex',\n alignItems: 'center',\n }}\n title={group.id}\n >\n {group.id}\n </span>\n </div>\n <div className=\"mt-1 text-xs text-[var(--hub-ink-3)]\">\n {group.visibility\n ? t(\n `server.visibility${group.visibility === 'group' ? 'Group' : group.visibility === 'public' ? 'Public' : 'Private'}`,\n )\n : t('groups.legacyVisibility')}\n </div>\n {group.description && (\n <div style={{ fontSize: 12.5, color: 'var(--hub-ink-3)', marginTop: 2 }}>\n {group.description}\n </div>\n )}\n </div>\n <div className=\"flex items-center gap-1\" ref={dropdownRef}>\n <div className=\"relative\">\n <button\n onClick={() => setShowCopyDropdown((v) => !v)}\n className=\"hub-icon-btn sm\"\n title={t('common.copy')}\n >\n {copied ? <Check size={13} className=\"text-[var(--hub-ok)]\" /> : <Copy size={13} />}\n </button>\n {showCopyDropdown && (\n <div\n className=\"absolute top-full right-0 mt-1 z-20 hub-card\"\n style={{ minWidth: 160, padding: 4 }}\n >\n <button\n onClick={() => doCopy(group.id)}\n 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\"\n >\n <Copy size={12} /> {t('common.copyId')}\n </button>\n <button\n onClick={() => doCopy(groupEndpoint)}\n 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\"\n >\n <LinkIcon size={12} /> {t('common.copyUrl')}\n </button>\n <button\n onClick={() => doCopy(groupOpenApiEndpoint)}\n 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\"\n >\n <LinkIcon size={12} /> {t('common.copyOpenApiUrl')}\n </button>\n <button\n onClick={() => {\n setShowCopyDropdown(false);\n setClientConfigTarget({\n name: group.name,\n url: clientConfigEndpoint,\n headers: { Authorization: `Bearer ${ACCESS_TOKEN_PLACEHOLDER}` },\n });\n }}\n 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\"\n >\n <FileCode size={12} /> {t('clientConfig.menuItem')}\n </button>\n </div>\n )}\n </div>\n {canManage && (\n <>\n <button\n onClick={() => onEdit(group)}\n className=\"hub-icon-btn sm\"\n title={t('groups.edit')}\n >\n <Edit3 size={13} />\n </button>\n <button\n onClick={() => setShowDeleteDialog(true)}\n className=\"hub-icon-btn sm\"\n title={t('groups.delete')}\n style={{ color: 'var(--hub-ink-3)' }}\n >\n <Trash2 size={13} />\n </button>\n </>\n )}\n </div>\n </div>\n\n {/* Routing diagram */}\n <div\n className=\"grid flex-1 items-center gap-3 px-4 py-3\"\n style={{ gridTemplateColumns: '1fr 80px 1fr', minHeight: 180 }}\n >\n {/* Servers */}\n <div className=\"flex flex-col gap-1.5\">\n {groupServers.length === 0 ? (\n <div style={{ fontSize: 12, color: 'var(--hub-ink-3)' }}>{t('groups.noServers')}</div>\n ) : (\n groupServers.map((s) => {\n const tn = tally(s);\n return (\n <div\n key={s.name}\n className=\"flex items-center gap-2.5 px-2.5 py-1.5 rounded-md\"\n style={{\n background: 'var(--hub-bg-2)',\n border: '1px solid var(--hub-line-2)',\n }}\n >\n <span\n className=\"inline-block flex-shrink-0\"\n style={{\n width: 6,\n height: 6,\n borderRadius: 50,\n background:\n s.status === 'connected'\n ? 'var(--hub-ok)'\n : s.status === 'connecting'\n ? 'var(--hub-warn)'\n : 'var(--hub-err)',\n }}\n />\n <span className=\"hub-mono truncate flex-1\" style={{ fontSize: 12.5 }}>\n <span title={s.name}>{getServerDisplayName(group, s.name)}</span>\n </span>\n <span\n className=\"hub-mono hub-num flex-shrink-0\"\n style={{ fontSize: 11, color: 'var(--hub-ink-3)' }}\n >\n {tn.visibleTools}/{tn.totalTools} tools\n </span>\n </div>\n );\n })\n )}\n </div>\n\n {/* Flow */}\n <svg width=\"80\" height=\"80\" viewBox=\"0 0 80 80\" className=\"self-center\">\n {groupServers.length === 0 ? (\n <path\n d=\"M0,40 C30,40 50,40 80,40\"\n stroke=\"var(--hub-line)\"\n strokeWidth=\"1\"\n fill=\"none\"\n strokeDasharray=\"3 3\"\n />\n ) : (\n groupServers.map((_, i) => {\n const y1 = 12 + (60 / Math.max(groupServers.length, 1)) * (i + 0.5);\n return (\n <path\n key={i}\n d={`M0,${y1} C 30,${y1} 50,40 80,40`}\n stroke=\"var(--hub-line)\"\n strokeWidth=\"1\"\n fill=\"none\"\n strokeDasharray=\"3 3\"\n />\n );\n })\n )}\n <circle cx=\"80\" cy=\"40\" r=\"4\" fill=\"var(--hub-ink)\" />\n </svg>\n\n {/* Endpoint */}\n <div\n className=\"px-3 py-2.5 rounded-md\"\n style={{\n border: '1px solid var(--hub-line)',\n background: 'var(--hub-bg-2)',\n }}\n >\n <div className=\"hub-sect\" style={{ marginBottom: 4 }}>\n endpoint\n </div>\n <div\n className=\"hub-mono break-all\"\n style={{ fontSize: 12, color: 'var(--hub-ink-2)', lineHeight: 1.4 }}\n >\n <span style={{ color: 'var(--hub-ink-3)' }}>/mcp/</span>\n <b style={{ color: 'var(--hub-ink)', fontWeight: 600 }}>{group.name}</b>\n </div>\n <div\n className=\"hub-mono break-all\"\n style={{ fontSize: 12, color: 'var(--hub-ink-2)', lineHeight: 1.4 }}\n >\n <span style={{ color: 'var(--hub-ink-3)' }}>/api/</span>\n <b style={{ color: 'var(--hub-ink)', fontWeight: 600 }}>{group.name}</b>\n </div>\n <div className=\"flex gap-1.5 mt-2\">\n <button\n className=\"hub-btn sm flex-1 justify-center\"\n onClick={() => doCopy(groupEndpoint)}\n title={t('common.copyUrl')}\n >\n <Copy size={11} /> MCP\n </button>\n <button\n className=\"hub-btn sm flex-1 justify-center\"\n onClick={() => doCopy(groupOpenApiEndpoint)}\n title={t('common.copyOpenApiUrl')}\n >\n <Copy size={11} /> OpenAPI\n </button>\n </div>\n </div>\n </div>\n\n {/* Footer */}\n <div\n className=\"flex justify-between items-center px-4 py-2\"\n style={{\n borderTop: '1px solid var(--hub-line-2)',\n background: 'var(--hub-bg-2)',\n fontSize: 12,\n color: 'var(--hub-ink-3)',\n }}\n >\n <div>\n <div className=\"hub-mono\">\n <span style={{ color: 'var(--hub-ink-2)' }}>{groupServers.length}</span>{' '}\n {t('nav.servers').toLowerCase()} ·{' '}\n <span style={{ color: 'var(--hub-ink-2)' }}>{totalVisibleTools}</span>{' '}\n {t('server.tools').toLowerCase()}\n </div>\n {cost && (\n <div className=\"hub-mono mt-1\" style={{ fontSize: 11.5, color: 'var(--hub-ink-3)' }}>\n <div title={t('cost.estimate')}>\n {t('cost.totalFootprint')}: {formatTokens(cost.direct.exposed)}/\n {formatTokens(cost.direct.gross)}\n </div>\n {cost.smartRouting && (\n <>\n <div>\n {t('cost.smartRouting')}: {formatTokens(cost.smartRouting.base)} (\n {t('cost.saved', {\n percent: percentSaved(cost.direct.exposed, cost.smartRouting.base),\n })}\n )\n </div>\n <div title={t('cost.smartRoutingPdHint')}>\n {t('cost.smartRoutingPd')}:{' '}\n {formatTokens(cost.smartRouting.progressiveDisclosure)}\n </div>\n </>\n )}\n {cost.connectedCount < cost.totalCount && (\n <div>\n {t('cost.connectedOf', {\n connected: cost.connectedCount,\n total: cost.totalCount,\n })}\n </div>\n )}\n </div>\n )}\n </div>\n {canManage && (\n <button\n className=\"hub-btn ghost sm\"\n style={{ color: 'var(--hub-ink-3)' }}\n onClick={() => onEdit(group)}\n >\n {t('groups.configureTools') || t('groups.edit')}\n <ChevronDown size={11} style={{ transform: 'rotate(-90deg)' }} />\n </button>\n )}\n </div>\n\n <CopyClientConfigDialog\n isOpen={clientConfigTarget !== null}\n target={clientConfigTarget}\n onClose={() => setClientConfigTarget(null)}\n />\n\n <DeleteDialog\n isOpen={showDeleteDialog}\n onClose={() => setShowDeleteDialog(false)}\n onConfirm={() => {\n onDelete(group.id);\n setShowDeleteDialog(false);\n }}\n serverName={group.name}\n isGroup={true}\n />\n </div>\n );\n};\n\nexport default GroupCard;\n","import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { apiPost } from '@/utils/fetchInterceptor';\n\ninterface GroupImportFormProps {\n onSuccess: () => void;\n onCancel: () => void;\n}\n\ninterface ImportGroupConfig {\n name: string;\n description?: string;\n servers?: string[] | Array<{\n name: string;\n tools?: string[] | 'all';\n prompts?: string[] | 'all';\n resources?: string[] | 'all';\n }>;\n}\n\ninterface ImportJsonFormat {\n groups: ImportGroupConfig[];\n}\n\nconst GroupImportForm: React.FC<GroupImportFormProps> = ({ onSuccess, onCancel }) => {\n const { t } = useTranslation();\n const [jsonInput, setJsonInput] = useState('');\n const [error, setError] = useState<string | null>(null);\n const [isImporting, setIsImporting] = useState(false);\n const [previewGroups, setPreviewGroups] = useState<ImportGroupConfig[] | null>(null);\n\n const examplePlaceholder = `{\n \"groups\": [\n {\n \"name\": \"AI Assistants\",\n \"servers\": [\"openai-server\", \"anthropic-server\"]\n },\n {\n \"name\": \"Development Tools\",\n \"servers\": [\n {\n \"name\": \"github-server\",\n \"tools\": [\"create_issue\", \"list_repos\"],\n \"prompts\": [\"triage_prompt\"],\n \"resources\": [\"resource://docs/repo-guide\"]\n },\n {\n \"name\": \"gitlab-server\",\n \"tools\": \"all\",\n \"prompts\": \"all\",\n \"resources\": \"all\"\n }\n ]\n }\n ]\n}\n\nSupports:\n- Simple server list: [\"server1\", \"server2\"]\n- Advanced server config: [{\"name\": \"server1\", \"tools\": [\"tool1\"], \"prompts\": [\"prompt1\"], \"resources\": [\"resource://docs/guide\"]}]\n- All groups will be imported in a single efficient batch operation.`;\n\n const parseAndValidateJson = (input: string): ImportJsonFormat | null => {\n try {\n const parsed = JSON.parse(input.trim());\n\n // Validate structure\n if (!parsed.groups || !Array.isArray(parsed.groups)) {\n setError(t('groupImport.invalidFormat'));\n return null;\n }\n\n // Validate each group\n for (const group of parsed.groups) {\n if (!group.name || typeof group.name !== 'string') {\n setError(t('groupImport.missingName'));\n return null;\n }\n }\n\n return parsed as ImportJsonFormat;\n } catch (e) {\n setError(t('groupImport.parseError'));\n return null;\n }\n };\n\n const handlePreview = () => {\n setError(null);\n const parsed = parseAndValidateJson(jsonInput);\n if (!parsed) return;\n\n setPreviewGroups(parsed.groups);\n };\n\n const handleImport = async () => {\n if (!previewGroups) return;\n\n setIsImporting(true);\n setError(null);\n\n try {\n // Use batch import API for better performance\n const result = await apiPost('/groups/batch', {\n groups: previewGroups,\n });\n\n if (result.success) {\n const { successCount, failureCount, results } = result;\n\n if (failureCount > 0) {\n const errors = results\n .filter((r: any) => !r.success)\n .map((r: any) => `${r.name}: ${r.message || t('groupImport.addFailed')}`);\n\n setError(\n t('groupImport.partialSuccess', { count: successCount, total: previewGroups.length }) +\n '\\n' +\n errors.join('\\n'),\n );\n }\n\n if (successCount > 0) {\n onSuccess();\n }\n } else {\n setError(result.message || t('groupImport.importFailed'));\n }\n } catch (err) {\n console.error('Import error:', err);\n setError(t('groupImport.importFailed'));\n } finally {\n setIsImporting(false);\n }\n };\n\n const renderAllCapabilitiesLabel = (\n key: 'previewAllTools' | 'previewAllPrompts' | 'previewAllResources',\n ) => <span className=\"text-gray-500 ml-2\">{t(`groups.${key}`)}</span>;\n\n const renderCapabilityPreview = (\n key: 'previewPrompts' | 'previewResources',\n value: string[] | 'all' | undefined,\n ) => {\n if (!value || value === 'all') {\n return null;\n }\n\n const items = Array.isArray(value) ? value.join(', ') : value;\n return <span className=\"text-gray-500 ml-2\">{t(`groups.${key}`, { items })}</span>;\n };\n\n const renderServerList = (\n servers?: string[] | Array<{\n name: string;\n tools?: string[] | 'all';\n prompts?: string[] | 'all';\n resources?: string[] | 'all';\n }>,\n ) => {\n if (!servers || servers.length === 0) {\n return <span className=\"text-gray-500\">{t('groups.noServers')}</span>;\n }\n\n return (\n <div className=\"space-y-1\">\n {servers.map((server, idx) => {\n if (typeof server === 'string') {\n return (\n <div key={idx} className=\"text-sm\">\n • {server}\n </div>\n );\n } else {\n return (\n <div key={idx} className=\"text-sm\">\n • {server.name}\n {server.tools && server.tools !== 'all' && (\n <span className=\"text-gray-500 ml-2\">\n ({Array.isArray(server.tools) ? server.tools.join(', ') : server.tools})\n </span>\n )}\n {server.tools === 'all' && renderAllCapabilitiesLabel('previewAllTools')}\n {renderCapabilityPreview('previewPrompts', server.prompts)}\n {server.prompts === 'all' && renderAllCapabilitiesLabel('previewAllPrompts')}\n {renderCapabilityPreview('previewResources', server.resources)}\n {server.resources === 'all' && renderAllCapabilitiesLabel('previewAllResources')}\n </div>\n );\n }\n })}\n </div>\n );\n };\n\n return (\n <div className=\"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4\">\n <div className=\"bg-white dark:bg-gray-800 shadow rounded-lg p-6 w-full max-w-4xl max-h-[90vh] overflow-y-auto\">\n <div className=\"flex justify-between items-center mb-6\">\n <h2 className=\"text-xl font-semibold text-gray-900\">{t('groupImport.title')}</h2>\n <button onClick={onCancel} className=\"text-gray-500 hover:text-gray-700\">\n ✕\n </button>\n </div>\n\n {error && (\n <div className=\"mb-4 bg-red-50 border-l-4 border-red-500 p-4 rounded\">\n <p className=\"text-red-700 whitespace-pre-wrap\">{error}</p>\n </div>\n )}\n\n {!previewGroups ? (\n <div>\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">\n {t('groupImport.inputLabel')}\n </label>\n <textarea\n value={jsonInput}\n onChange={(e) => setJsonInput(e.target.value)}\n 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\"\n placeholder={examplePlaceholder}\n />\n <p className=\"text-xs text-gray-500 mt-2\">{t('groupImport.inputHelp')}</p>\n </div>\n\n <div className=\"flex justify-end space-x-4\">\n <button\n onClick={onCancel}\n className=\"hub-btn\"\n >\n {t('common.cancel')}\n </button>\n <button\n onClick={handlePreview}\n disabled={!jsonInput.trim()}\n className=\"hub-btn primary\"\n >\n {t('groupImport.preview')}\n </button>\n </div>\n </div>\n ) : (\n <div>\n <div className=\"mb-4\">\n <h3 className=\"text-lg font-medium text-gray-900 mb-3\">\n {t('groupImport.previewTitle')}\n </h3>\n <div className=\"space-y-3\">\n {previewGroups.map((group, index) => (\n <div key={index} className=\"bg-gray-50 dark:bg-gray-800 p-4 rounded-lg border border-gray-200 dark:border-gray-700\">\n <div className=\"flex items-start justify-between\">\n <div className=\"flex-1\">\n <h4 className=\"font-medium text-gray-900\">{group.name}</h4>\n {group.description && (\n <p className=\"text-sm text-gray-600 mt-1\">{group.description}</p>\n )}\n <div className=\"mt-2 text-sm text-gray-600\">\n <strong>{t('groups.servers')}:</strong>\n <div className=\"mt-1\">{renderServerList(group.servers)}</div>\n </div>\n </div>\n </div>\n </div>\n ))}\n </div>\n </div>\n\n <div className=\"flex justify-end space-x-4\">\n <button\n onClick={() => setPreviewGroups(null)}\n disabled={isImporting}\n className=\"hub-btn\"\n >\n {t('common.back')}\n </button>\n <button\n onClick={handleImport}\n disabled={isImporting}\n className=\"hub-btn primary\"\n >\n {isImporting ? (\n <>\n <svg\n className=\"animate-spin h-4 w-4 mr-2\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n ></circle>\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n 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\"\n ></path>\n </svg>\n {t('groupImport.importing')}\n </>\n ) : (\n t('groupImport.import')\n )}\n </button>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default GroupImportForm;\n","import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { apiPost } from '@/utils/fetchInterceptor';\nimport { Group, ConfigTemplate } from '@/types';\n\ninterface TemplateExportFormProps {\n groups: Group[];\n onCancel: () => void;\n}\n\nconst TemplateExportForm: React.FC<TemplateExportFormProps> = ({ groups, onCancel }) => {\n const { t } = useTranslation();\n const [name, setName] = useState('');\n const [description, setDescription] = useState('');\n const [selectedGroupIds, setSelectedGroupIds] = useState<string[]>([]);\n const [includeDisabled, setIncludeDisabled] = useState(false);\n const [isExporting, setIsExporting] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const handleToggleGroup = (groupId: string) => {\n setSelectedGroupIds((prev) =>\n prev.includes(groupId) ? prev.filter((id) => id !== groupId) : [...prev, groupId],\n );\n };\n\n const handleSelectAll = () => {\n if (selectedGroupIds.length === groups.length) {\n setSelectedGroupIds([]);\n } else {\n setSelectedGroupIds(groups.map((g) => g.id));\n }\n };\n\n const handleExport = async () => {\n if (!name.trim()) {\n setError(t('template.nameRequired'));\n return;\n }\n\n setIsExporting(true);\n setError(null);\n\n try {\n const result = await apiPost('/templates/export', {\n name: name.trim(),\n description: description.trim() || undefined,\n groupIds: selectedGroupIds.length > 0 ? selectedGroupIds : undefined,\n includeDisabledServers: includeDisabled,\n });\n\n if (result.success && result.data) {\n const template: ConfigTemplate = result.data;\n const blob = new Blob([JSON.stringify(template, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `${template.name.replace(/[^a-zA-Z0-9-_]/g, '_')}.mcphub-template.json`;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n onCancel();\n } else {\n setError(result.message || t('template.exportFailed'));\n }\n } catch (err) {\n console.error('Export error:', err);\n setError(t('template.exportFailed'));\n } finally {\n setIsExporting(false);\n }\n };\n\n return (\n <div className=\"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4\">\n <div className=\"bg-white dark:bg-gray-800 shadow rounded-lg p-6 w-full max-w-3xl max-h-[90vh] overflow-y-auto\">\n <div className=\"flex justify-between items-center mb-6\">\n <h2 className=\"text-xl font-semibold text-gray-900\">{t('template.exportTitle')}</h2>\n <button onClick={onCancel} className=\"text-gray-500 hover:text-gray-700\">\n ✕\n </button>\n </div>\n\n {error && (\n <div className=\"mb-4 bg-red-50 dark:bg-red-900/20 border-l-4 border-red-500 p-4 rounded\">\n <p className=\"text-red-700 dark:text-red-300\">{error}</p>\n </div>\n )}\n\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n {t('template.name')} *\n </label>\n <input\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder={t('template.namePlaceholder')}\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n {t('template.description')}\n </label>\n <input\n type=\"text\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder={t('template.descriptionPlaceholder')}\n />\n </div>\n\n <div>\n <div className=\"flex justify-between items-center mb-2\">\n <label className=\"block text-sm font-medium text-gray-700\">\n {t('template.selectGroups')}\n </label>\n <button\n onClick={handleSelectAll}\n className=\"text-sm text-blue-600 hover:text-blue-800 dark:text-blue-300\"\n >\n {selectedGroupIds.length === groups.length\n ? t('template.deselectAll')\n : t('template.selectAll')}\n </button>\n </div>\n <p className=\"text-xs text-gray-500 mb-2\">{t('template.selectGroupsHelp')}</p>\n <div className=\"border border-gray-200 dark:border-gray-700 rounded-md max-h-48 overflow-y-auto\">\n {groups.map((group) => (\n <label\n key={group.id}\n className=\"flex items-center px-3 py-2 hover:bg-gray-50 dark:bg-gray-800 dark:hover:bg-gray-700 cursor-pointer\"\n >\n <input\n type=\"checkbox\"\n checked={selectedGroupIds.includes(group.id)}\n onChange={() => handleToggleGroup(group.id)}\n className=\"mr-3 h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500\"\n />\n <div>\n <span className=\"text-sm font-medium text-gray-900\">{group.name}</span>\n {group.description && (\n <span className=\"text-xs text-gray-500 ml-2\">{group.description}</span>\n )}\n </div>\n </label>\n ))}\n </div>\n </div>\n\n <label className=\"flex items-center space-x-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={includeDisabled}\n onChange={(e) => setIncludeDisabled(e.target.checked)}\n className=\"h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500\"\n />\n <span className=\"text-sm text-gray-700\">{t('template.includeDisabled')}</span>\n </label>\n </div>\n\n <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\">\n <p className=\"text-sm text-blue-700 dark:text-blue-300\">{t('template.exportNote')}</p>\n </div>\n\n <div className=\"flex justify-end space-x-4 mt-6\">\n <button\n onClick={onCancel}\n className=\"hub-btn\"\n >\n {t('common.cancel')}\n </button>\n <button\n onClick={handleExport}\n disabled={isExporting || !name.trim()}\n className=\"hub-btn primary\"\n >\n {isExporting ? t('template.exporting') : t('template.export')}\n </button>\n </div>\n </div>\n </div>\n );\n};\n\nexport default TemplateExportForm;\n","import React, { useState, useRef } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { apiPost } from '@/utils/fetchInterceptor';\nimport { ConfigTemplate, TemplateImportResult } from '@/types';\n\ninterface TemplateImportFormProps {\n onSuccess: () => void;\n onCancel: () => void;\n}\n\nconst TemplateImportForm: React.FC<TemplateImportFormProps> = ({ onSuccess, onCancel }) => {\n const { t } = useTranslation();\n const [template, setTemplate] = useState<ConfigTemplate | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [isImporting, setIsImporting] = useState(false);\n const [result, setResult] = useState<TemplateImportResult | null>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {\n setError(null);\n setTemplate(null);\n setResult(null);\n\n const file = e.target.files?.[0];\n if (!file) return;\n\n const reader = new FileReader();\n reader.onload = (event) => {\n try {\n const parsed = JSON.parse(event.target?.result as string);\n if (!parsed.version || !parsed.name || !parsed.servers || !parsed.groups) {\n setError(t('template.invalidFormat'));\n return;\n }\n setTemplate(parsed as ConfigTemplate);\n } catch {\n setError(t('template.parseError'));\n }\n };\n reader.readAsText(file);\n };\n\n const handlePaste = (input: string) => {\n setError(null);\n setTemplate(null);\n setResult(null);\n\n if (!input.trim()) return;\n\n try {\n const parsed = JSON.parse(input.trim());\n if (!parsed.version || !parsed.name || !parsed.servers || !parsed.groups) {\n setError(t('template.invalidFormat'));\n return;\n }\n setTemplate(parsed as ConfigTemplate);\n } catch {\n setError(t('template.parseError'));\n }\n };\n\n const handleImport = async () => {\n if (!template) return;\n\n setIsImporting(true);\n setError(null);\n\n try {\n const response = await apiPost('/templates/import', template);\n\n if (response.data) {\n setResult(response.data as TemplateImportResult);\n if (response.data.success) {\n onSuccess();\n }\n } else {\n setError(response.message || t('template.importFailed'));\n }\n } catch (err) {\n console.error('Import error:', err);\n setError(t('template.importFailed'));\n } finally {\n setIsImporting(false);\n }\n };\n\n return (\n <div className=\"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4\">\n <div className=\"bg-white dark:bg-gray-800 shadow rounded-lg p-6 w-full max-w-4xl max-h-[90vh] overflow-y-auto\">\n <div className=\"flex justify-between items-center mb-6\">\n <h2 className=\"text-xl font-semibold text-gray-900\">{t('template.importTitle')}</h2>\n <button onClick={onCancel} className=\"text-gray-500 hover:text-gray-700\">\n ✕\n </button>\n </div>\n\n {error && (\n <div className=\"mb-4 bg-red-50 dark:bg-red-900/20 border-l-4 border-red-500 p-4 rounded\">\n <p className=\"text-red-700 dark:text-red-300\">{error}</p>\n </div>\n )}\n\n {result && (\n <div\n className={`mb-4 p-4 rounded border-l-4 ${result.success ? 'bg-green-50 dark:bg-green-900/20 border-green-500' : 'bg-yellow-50 dark:bg-yellow-900/20 border-yellow-500'}`}\n >\n <p className={result.success ? 'text-green-700 dark:text-green-300' : 'text-yellow-700 dark:text-yellow-300'}>\n {t('template.importResult', {\n serversCreated: result.serversCreated,\n serversSkipped: result.serversSkipped,\n groupsCreated: result.groupsCreated,\n groupsSkipped: result.groupsSkipped,\n })}\n </p>\n {result.requiredEnvVars.length > 0 && (\n <div className=\"mt-2 p-2 bg-orange-50 dark:bg-orange-900/20 border border-orange-200 dark:border-orange-700/60 rounded\">\n <p className=\"text-sm font-medium text-orange-800 dark:text-orange-300\">\n {t('template.envVarsNeeded')}\n </p>\n <ul className=\"mt-1 text-sm text-orange-700 dark:text-orange-300\">\n {result.requiredEnvVars.map((v) => (\n <li key={v} className=\"font-mono\">\n {v}\n </li>\n ))}\n </ul>\n </div>\n )}\n </div>\n )}\n\n {!template ? (\n <div>\n <div className=\"mb-4\">\n <div className=\"flex items-center justify-between mb-2\">\n <label className=\"block text-sm font-medium text-gray-700\">\n {t('template.uploadFile')}\n </label>\n </div>\n <div className=\"flex items-center space-x-4\">\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\".json\"\n onChange={handleFileSelect}\n 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\"\n />\n </div>\n </div>\n\n <div className=\"relative my-4\">\n <div className=\"absolute inset-0 flex items-center\">\n <div className=\"w-full border-t border-gray-300\" />\n </div>\n <div className=\"relative flex justify-center text-sm\">\n <span className=\"bg-white dark:bg-gray-800 px-2 text-gray-500\">{t('template.or')}</span>\n </div>\n </div>\n\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">\n {t('template.pasteJson')}\n </label>\n <textarea\n 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\"\n placeholder={t('template.pastePlaceholder')}\n onChange={(e) => handlePaste(e.target.value)}\n />\n </div>\n\n <div className=\"flex justify-end space-x-4\">\n <button\n onClick={onCancel}\n className=\"hub-btn\"\n >\n {t('common.cancel')}\n </button>\n </div>\n </div>\n ) : (\n <div>\n {/* Template preview */}\n <div className=\"space-y-4\">\n <div className=\"p-3 bg-gray-50 dark:bg-gray-800 rounded-md\">\n <h3 className=\"font-medium text-gray-900\">{template.name}</h3>\n {template.description && (\n <p className=\"text-sm text-gray-600 mt-1\">{template.description}</p>\n )}\n <p className=\"text-xs text-gray-500 mt-1\">\n {t('template.version')}: {template.version} | {t('template.createdAt')}:{' '}\n {new Date(template.createdAt).toLocaleDateString()}\n </p>\n </div>\n\n <div>\n <h4 className=\"text-sm font-medium text-gray-700 mb-2\">\n {t('template.servers')} ({Object.keys(template.servers).length})\n </h4>\n <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\">\n {Object.entries(template.servers).map(([name, config]) => (\n <div key={name} className=\"px-3 py-2\">\n <span className=\"text-sm font-medium text-gray-900\">{name}</span>\n <span className=\"text-xs text-gray-500 ml-2\">\n {config.type || 'stdio'}\n </span>\n </div>\n ))}\n </div>\n </div>\n\n <div>\n <h4 className=\"text-sm font-medium text-gray-700 mb-2\">\n {t('template.groups')} ({template.groups.length})\n </h4>\n <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\">\n {template.groups.map((group, idx) => (\n <div key={idx} className=\"px-3 py-2\">\n <span className=\"text-sm font-medium text-gray-900\">{group.name}</span>\n {group.description && (\n <span className=\"text-xs text-gray-500 ml-2\">{group.description}</span>\n )}\n <div className=\"text-xs text-gray-500 mt-1\">\n {group.servers.length} {t('template.serversInGroup')}\n </div>\n </div>\n ))}\n </div>\n </div>\n\n {template.requiredEnvVars.length > 0 && (\n <div className=\"p-3 bg-orange-50 dark:bg-orange-900/20 border border-orange-200 dark:border-orange-700/60 rounded-md\">\n <h4 className=\"text-sm font-medium text-orange-800 dark:text-orange-300\">\n {t('template.envVarsNeeded')}\n </h4>\n <ul className=\"mt-1 text-sm text-orange-700 dark:text-orange-300 font-mono\">\n {template.requiredEnvVars.map((v) => (\n <li key={v}>{v}</li>\n ))}\n </ul>\n </div>\n )}\n </div>\n\n <div className=\"flex justify-end space-x-4 mt-6\">\n <button\n onClick={() => {\n setTemplate(null);\n setResult(null);\n if (fileInputRef.current) fileInputRef.current.value = '';\n }}\n className=\"hub-btn\"\n >\n {t('common.back')}\n </button>\n <button\n onClick={handleImport}\n disabled={isImporting}\n className=\"hub-btn primary\"\n >\n {isImporting ? t('template.importing') : t('template.import')}\n </button>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default TemplateImportForm;\n","import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Plus, Download, Upload, AlertCircle, X } from 'lucide-react';\nimport { Group } from '@/types';\nimport { useGroupData } from '@/hooks/useGroupData';\nimport { useServerData } from '@/hooks/useServerData';\nimport AddGroupForm from '@/components/AddGroupForm';\nimport EditGroupForm from '@/components/EditGroupForm';\nimport GroupCard from '@/components/GroupCard';\nimport GroupImportForm from '@/components/GroupImportForm';\nimport TemplateExportForm from '@/components/TemplateExportForm';\nimport TemplateImportForm from '@/components/TemplateImportForm';\nimport { serverCostRevision } from '@/utils/costRevision';\nimport { useCostData } from '@/hooks/useCostData';\n\nconst GroupsPage: React.FC = () => {\n const { t } = useTranslation();\n const {\n groups,\n loading: groupsLoading,\n error: groupError,\n setError: setGroupError,\n deleteGroup,\n triggerRefresh,\n } = useGroupData();\n const { allServers } = useServerData({ refreshOnMount: true });\n const { groupCosts } = useCostData(JSON.stringify([groups, serverCostRevision(allServers)]));\n\n const [editingGroup, setEditingGroup] = useState<Group | null>(null);\n const [showAddForm, setShowAddForm] = useState(false);\n const [showImportForm, setShowImportForm] = useState(false);\n const [showTemplateExport, setShowTemplateExport] = useState(false);\n const [showTemplateImport, setShowTemplateImport] = useState(false);\n\n const handleDeleteGroup = async (groupId: string) => {\n const result = await deleteGroup(groupId);\n if (!result || !result.success) {\n setGroupError(result?.message || t('groups.deleteError'));\n }\n };\n\n return (\n <div>\n <div className=\"flex items-end justify-between gap-4 mb-6\">\n <div>\n <h1 className=\"hub-h1\">{t('pages.groups.title')}</h1>\n <p className=\"hub-sub\">\n <span className=\"hub-num\">{groups.length}</span> {t('nav.groups').toLowerCase()}\n </p>\n </div>\n <div className=\"flex gap-2\">\n <button className=\"hub-btn\" onClick={() => setShowImportForm(true)}>\n <Upload size={13} /> {t('groupImport.button')}\n </button>\n <button className=\"hub-btn\" onClick={() => setShowTemplateExport(true)}>\n <Download size={13} /> {t('template.exportButton')}\n </button>\n <button className=\"hub-btn\" onClick={() => setShowTemplateImport(true)}>\n <Upload size={13} /> {t('template.importButton')}\n </button>\n <button className=\"hub-btn primary\" onClick={() => setShowAddForm(true)}>\n <Plus size={13} /> {t('groups.add')}\n </button>\n </div>\n </div>\n\n {groupError && (\n <div\n className=\"hub-card flex items-center justify-between gap-3 mb-4\"\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]\">{groupError}</span>\n </div>\n <button className=\"hub-icon-btn sm\" onClick={() => setGroupError(null)}>\n <X size={13} />\n </button>\n </div>\n )}\n\n {groupsLoading ? (\n <div className=\"hub-card p-6 text-center\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('app.loading')}\n </div>\n ) : groups.length === 0 ? (\n <div className=\"hub-card p-10 text-center\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('groups.noGroups')}\n </div>\n ) : (\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-3.5\">\n {groups.map((group) => (\n <GroupCard\n key={group.id}\n group={group}\n servers={allServers}\n onEdit={setEditingGroup}\n onDelete={handleDeleteGroup}\n cost={groupCosts.find((c) => c.id === group.id)}\n />\n ))}\n <button\n onClick={() => setShowAddForm(true)}\n className=\"flex items-center justify-center text-[var(--hub-ink-3)] hover:text-[var(--hub-ink-2)] transition-colors\"\n style={{\n border: '1px dashed var(--hub-line)',\n borderRadius: 10,\n minHeight: 200,\n background: 'transparent',\n cursor: 'pointer',\n }}\n >\n <div className=\"text-center\">\n <div\n className=\"grid place-items-center mx-auto mb-2\"\n style={{\n width: 36,\n height: 36,\n borderRadius: 10,\n border: '1px solid var(--hub-line)',\n }}\n >\n <Plus size={16} />\n </div>\n <div style={{ fontSize: 13, fontWeight: 500, color: 'var(--hub-ink-2)' }}>\n {t('groups.add')}\n </div>\n <div style={{ fontSize: 12, marginTop: 2 }}>{t('groups.addNew')}</div>\n </div>\n </button>\n </div>\n )}\n\n {showAddForm && (\n <AddGroupForm\n onAdd={() => {\n setShowAddForm(false);\n triggerRefresh();\n }}\n onCancel={() => setShowAddForm(false)}\n />\n )}\n\n {showImportForm && (\n <GroupImportForm\n onSuccess={() => {\n setShowImportForm(false);\n triggerRefresh();\n }}\n onCancel={() => setShowImportForm(false)}\n />\n )}\n\n {editingGroup && (\n <EditGroupForm\n group={editingGroup}\n onEdit={() => {\n setEditingGroup(null);\n triggerRefresh();\n }}\n onCancel={() => setEditingGroup(null)}\n />\n )}\n\n {showTemplateExport && (\n <TemplateExportForm groups={groups} onCancel={() => setShowTemplateExport(false)} />\n )}\n\n {showTemplateImport && (\n <TemplateImportForm\n onSuccess={() => {\n setShowTemplateImport(false);\n triggerRefresh();\n }}\n onCancel={() => setShowTemplateImport(false)}\n />\n )}\n </div>\n );\n};\n\nexport default GroupsPage;\n"],"names":["RISK_GROUPS","classifyTool","item","_a","name","_b","_c","filterCapabilities","items","query","annotation","search","applyVisibleSelection","selection","all","visible","action","selected","CapabilitySelection","tools","label","onChange","children","t","useTranslation","setQuery","useState","setAnnotation","grouped","setGrouped","apply","target","sections","risk","buttonClass","jsxs","jsx","event","Fragment","hint","section","count","React","EMPTY_SELECTIONS","FULL_SELECTIONS","ServerToolConfig","servers","value","className","serverCosts","aliasInputId","nameSeparator","smartRoutingConfig","useSettingsData","expandedServers","setExpandedServers","normalizedValue","availableServers","server","configuredServerNames","config","availableServerNames","prev","newSet","serverName","toggleServer","newValue","toggleServerExpanded","hasAnyCapabilitySelection","capability","updateServerCapability","keepExpanded","existingServer","nextConfig","updateServerAlias","alias","togglePinnedTool","toolName","pinnedTools","normalizeNamedCapability","prefix","getCapabilityItems","tool","prompt","resource","serverCostsMap","outerMap","sc","innerMap","i","costMapForServer","getSelectedCapabilityCost","costMap","isCapabilityItemSelected","sum","getServerSelectedCost","cap","toggleCapabilityItem","itemValue","s","allItems","serverConfig","currentSelection","nextSelection","isServerSelected","isServerPartiallySelected","getSelectedCapabilityCount","itemSet","capabilityConfigs","getServerSummaryBadges","key","entry","cn","isSelected","isPartiallySelected","isExpanded","summaryBadges","serverCapabilities","e","formatTokens","Wrench","MessageSquare","FileText","titleKey","countKey","allKey","selectedCount","allSelected","isChecked","isPinned","descriptionInfo","getToolDescriptionInfo","descriptionTitle","Pin","GroupVisibilityFields","groupId","users","setUsers","setSearch","userGroups","setUserGroups","loading","setLoading","error","setError","isAdvancedExpanded","setIsAdvancedExpanded","useEffect","cancelled","apiGet","result","candidates","username","selectedUsers","allCandidatesSelected","noCandidatesSelected","toggleSharedUser","nextSelected","UserGroupSelection","sharedWithUserGroups","AddGroupForm","onAdd","onCancel","createGroup","useGroupData","allServers","useServerData","useCostData","setAvailableServers","isSubmitting","setIsSubmitting","formData","setFormData","handleChange","handleSubmit","err","access","previous","EditGroupForm","group","onEdit","updateGroup","getServerNames","getServerConfig","getServerDisplayName","GroupCard","onDelete","cost","auth","useAuth","canManage","showToast","useToast","installConfig","baseUrl","showDeleteDialog","setShowDeleteDialog","clientConfigTarget","setClientConfigTarget","copied","setCopied","showCopyDropdown","setShowCopyDropdown","dropdownRef","useRef","handle","doCopy","text","copyText","groupEndpoint","clientConfigEndpoint","groupOpenApiEndpoint","serverNames","groupServers","tally","cfg","allTools","allPrompts","allResources","visibleTools","short","visiblePrompts","p","visibleResources","r","totalVisibleTools","acc","v","Check","Copy","LinkIcon","ACCESS_TOKEN_PLACEHOLDER","FileCode","Edit3","Trash2","tn","_","y1","percentSaved","ChevronDown","CopyClientConfigDialog","DeleteDialog","GroupImportForm","onSuccess","jsonInput","setJsonInput","isImporting","setIsImporting","previewGroups","setPreviewGroups","examplePlaceholder","parseAndValidateJson","input","parsed","handlePreview","handleImport","apiPost","successCount","failureCount","results","errors","renderAllCapabilitiesLabel","renderCapabilityPreview","renderServerList","idx","index","TemplateExportForm","groups","setName","description","setDescription","selectedGroupIds","setSelectedGroupIds","includeDisabled","setIncludeDisabled","isExporting","setIsExporting","handleToggleGroup","id","handleSelectAll","g","handleExport","template","blob","url","a","TemplateImportForm","setTemplate","setResult","fileInputRef","handleFileSelect","file","reader","handlePaste","response","GroupsPage","groupsLoading","groupError","setGroupError","deleteGroup","triggerRefresh","groupCosts","serverCostRevision","editingGroup","setEditingGroup","showAddForm","setShowAddForm","showImportForm","setShowImportForm","showTemplateExport","setShowTemplateExport","showTemplateImport","setShowTemplateImport","handleDeleteGroup","Upload","Download","Plus","AlertCircle","X","c"],"mappings":"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"}
1
+ {"version":3,"file":"GroupsPage-D_E7QL_o.js","sources":["../../src/utils/capabilitySelection.ts","../../src/components/CapabilitySelection.tsx","../../src/components/ServerToolConfig.tsx","../../src/components/GroupVisibilityFields.tsx","../../src/components/AddGroupForm.tsx","../../src/components/EditGroupForm.tsx","../../src/components/GroupCard.tsx","../../src/components/GroupImportForm.tsx","../../src/components/TemplateExportForm.tsx","../../src/components/TemplateImportForm.tsx","../../src/pages/GroupsPage.tsx"],"sourcesContent":["export interface SelectableCapability {\n value: string;\n description?: string;\n annotations?: Record<string, unknown>;\n}\nexport type SelectionAction = 'select' | 'deselect' | 'invert';\nexport type AnnotationFilter = 'all' | 'readOnlyHint' | 'destructiveHint' | 'idempotentHint';\nexport type RiskGroup = 'read' | 'create' | 'update' | 'delete' | 'other';\nexport const RISK_GROUPS: RiskGroup[] = ['read', 'create', 'update', 'delete', 'other'];\nexport const classifyTool = (item: SelectableCapability): RiskGroup => {\n if (item.annotations?.readOnlyHint === true) return 'read';\n const name = item.value.toLowerCase();\n if (/^(delete|remove)[_-]/.test(name)) return 'delete';\n // A destructive hint does not distinguish create/update/delete.\n if (item.annotations?.destructiveHint === true) return 'other';\n if (/^(create|add)[_-]/.test(name)) return 'create';\n if (/^(update|set)[_-]/.test(name)) return 'update';\n if (item.annotations?.readOnlyHint !== false && /^(get|list|read|search)[_-]/.test(name))\n return 'read';\n return 'other';\n};\n\nexport const filterCapabilities = <T extends SelectableCapability>(\n items: T[],\n query: string,\n annotation: AnnotationFilter,\n): T[] => {\n const search = query.trim().toLowerCase();\n return items.filter(\n (item) =>\n (item.value.toLowerCase().includes(search) ||\n item.description?.toLowerCase().includes(search)) &&\n (annotation === 'all' || item.annotations?.[annotation] === true),\n );\n};\n\nexport const applyVisibleSelection = (\n selection: string[] | 'all',\n all: string[],\n visible: string[],\n action: SelectionAction,\n): string[] | 'all' => {\n if (visible.length === 0 || (selection === 'all' && action === 'select')) return selection;\n const selected = new Set(selection === 'all' ? all : selection);\n for (const name of visible) {\n if (action === 'deselect' || (action === 'invert' && selected.has(name))) selected.delete(name);\n else selected.add(name);\n }\n // An explicit snapshot stays explicit, including when every current item is selected.\n return [...selected];\n};\n","import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n AnnotationFilter,\n applyVisibleSelection,\n classifyTool,\n filterCapabilities,\n RISK_GROUPS,\n SelectableCapability,\n SelectionAction,\n} from '@/utils/capabilitySelection';\n\ninterface Props<T extends SelectableCapability> {\n items: T[];\n selection: string[] | 'all';\n tools: boolean;\n label: string;\n onChange: (selection: string[] | 'all') => void;\n children: (item: T) => React.ReactNode;\n}\n\nexport const CapabilitySelection = <T extends SelectableCapability>({\n items,\n selection,\n tools,\n label,\n onChange,\n children,\n}: Props<T>) => {\n const { t } = useTranslation();\n const [query, setQuery] = useState('');\n const [annotation, setAnnotation] = useState<AnnotationFilter>('all');\n const [grouped, setGrouped] = useState(false);\n const visible = filterCapabilities(items, query, annotation);\n const selected = new Set(selection === 'all' ? items.map((item) => item.value) : selection);\n const apply = (target: T[], action: SelectionAction) =>\n onChange(\n applyVisibleSelection(\n selection,\n items.map((item) => item.value),\n target.map((item) => item.value),\n action,\n ),\n );\n const sections =\n tools && grouped\n ? RISK_GROUPS.map((risk) => ({\n risk,\n items: visible.filter((item) => classifyTool(item) === risk),\n }))\n : [{ risk: null, items: visible }];\n const buttonClass =\n 'text-xs text-blue-600 hover:text-blue-800 disabled:opacity-40 disabled:cursor-not-allowed';\n\n return (\n <section aria-label={label}>\n <div className=\"flex flex-wrap items-center gap-2 mb-2\">\n <input\n type=\"search\"\n aria-label={t('groups.bulkSearchLabel', { capability: label })}\n placeholder={t('groups.bulkSearch')}\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n 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\"\n />\n {tools && (\n <>\n <select\n aria-label={t('groups.annotationFilter')}\n value={annotation}\n onChange={(event) => setAnnotation(event.target.value as AnnotationFilter)}\n className=\"max-w-full rounded border border-gray-300 bg-white dark:bg-gray-800 px-2 py-1 text-sm\"\n >\n <option value=\"all\">{t('groups.allAnnotations')}</option>\n {(['readOnlyHint', 'destructiveHint', 'idempotentHint'] as const).map((hint) => (\n <option key={hint} value={hint}>\n {t(`groups.${hint}`)}\n </option>\n ))}\n </select>\n <button\n type=\"button\"\n aria-pressed={grouped}\n onClick={() => setGrouped(!grouped)}\n className={buttonClass}\n >\n {t(grouped ? 'groups.flatList' : 'groups.riskGroups')}\n </button>\n </>\n )}\n </div>\n <div className=\"flex flex-wrap items-center gap-x-3 gap-y-1 mb-2\">\n <span className=\"text-xs text-gray-500\" role=\"status\">\n {t('groups.visibleCount', { count: visible.length, total: items.length })}\n </span>\n {(['select', 'deselect', 'invert'] as const).map((action) => (\n <button\n key={action}\n type=\"button\"\n disabled={!visible.length}\n onClick={() => apply(visible, action)}\n className={buttonClass}\n >\n {t(`groups.${action}Visible`)}\n </button>\n ))}\n </div>\n {tools && grouped && <p className=\"text-xs text-gray-500 mb-2\">{t('groups.riskHint')}</p>}\n <div className=\"grid grid-cols-1 gap-2 max-h-96 overflow-y-auto\">\n {visible.length === 0 && (\n <p className=\"text-sm text-gray-500\">{t('groups.noMatchingItems')}</p>\n )}\n {sections\n .filter((section) => section.items.length > 0)\n .map((section) => {\n const count = section.items.filter((item) => selected.has(item.value)).length;\n return (\n <React.Fragment key={section.risk ?? 'flat'}>\n {section.risk && (\n <div className=\"flex flex-wrap items-center justify-between gap-2 border-b border-gray-200 py-1\">\n <span className=\"text-xs font-medium\">\n {t(`groups.risk_${section.risk}`)} ({count}/{section.items.length})\n </span>\n <button\n type=\"button\"\n className={buttonClass}\n onClick={() =>\n apply(section.items, count === section.items.length ? 'deselect' : 'select')\n }\n >\n {t(count === section.items.length ? 'groups.selectNone' : 'groups.selectAll')}\n </button>\n </div>\n )}\n {section.items.map((item) => (\n <React.Fragment key={item.value}>{children(item)}</React.Fragment>\n ))}\n </React.Fragment>\n );\n })}\n </div>\n </section>\n );\n};\n","import { CapabilitySelection } from './CapabilitySelection.js';\nimport React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { IGroupServerConfig, Prompt, Resource, Server, ServerCost, Tool } from '@/types';\nimport { Wrench, MessageSquare, FileText, Pin } from 'lucide-react';\nimport { cn } from '@/utils/cn';\nimport { useSettingsData } from '@/hooks/useSettingsData';\nimport { formatTokens } from '@/utils/contextCost';\nimport { getToolDescriptionInfo } from '@/utils/toolDescription';\n\ntype CapabilityKey = 'tools' | 'prompts' | 'resources';\n\nconst EMPTY_SELECTIONS: Pick<IGroupServerConfig, CapabilityKey> = {\n tools: [],\n prompts: [],\n resources: [],\n};\n\nconst FULL_SELECTIONS: Pick<IGroupServerConfig, CapabilityKey> = {\n tools: 'all',\n prompts: 'all',\n resources: 'all',\n};\n\ninterface ServerToolConfigProps {\n servers: Server[];\n value: string[] | IGroupServerConfig[];\n onChange: (value: IGroupServerConfig[]) => void;\n className?: string;\n serverCosts?: ServerCost[];\n}\n\ninterface CapabilityItem {\n annotations?: Record<string, unknown>;\n key: string;\n value: string;\n description?: string;\n defaultDescription?: string;\n hasDescriptionOverride?: boolean;\n}\n\nexport const ServerToolConfig: React.FC<ServerToolConfigProps> = ({\n servers,\n value,\n onChange,\n className,\n serverCosts = [],\n}) => {\n const { t } = useTranslation();\n const aliasInputId = React.useId();\n const { nameSeparator, smartRoutingConfig } = useSettingsData();\n const [expandedServers, setExpandedServers] = useState<Set<string>>(new Set());\n\n // Normalize current value to IGroupServerConfig[] format\n const normalizedValue: IGroupServerConfig[] = React.useMemo(() => {\n return value.map((item) => {\n if (typeof item === 'string') {\n return { name: item, ...FULL_SELECTIONS };\n }\n return {\n ...item,\n tools: item.tools || 'all',\n prompts: item.prompts || 'all',\n resources: item.resources || 'all',\n };\n });\n }, [value]);\n\n // Get available servers (enabled only)\n const availableServers = React.useMemo(\n () => servers.filter((server) => server.enabled !== false),\n [servers],\n );\n\n // Clean up expanded servers when servers are removed from configuration\n // But keep servers that were explicitly expanded even if they have no configuration\n React.useEffect(() => {\n const configuredServerNames = new Set(normalizedValue.map((config) => config.name));\n const availableServerNames = new Set(availableServers.map((server) => server.name));\n\n setExpandedServers((prev) => {\n const newSet = new Set<string>();\n prev.forEach((serverName) => {\n // Keep expanded if server is configured OR if server exists and user manually expanded it\n if (configuredServerNames.has(serverName) || availableServerNames.has(serverName)) {\n newSet.add(serverName);\n }\n });\n return newSet;\n });\n }, [normalizedValue, availableServers]);\n\n const toggleServer = (serverName: string) => {\n const existingIndex = normalizedValue.findIndex((config) => config.name === serverName);\n\n if (existingIndex >= 0) {\n // Remove server - this also removes all capability selections\n const newValue = normalizedValue.filter((config) => config.name !== serverName);\n onChange(newValue);\n } else {\n // Add server with all capabilities by default\n const newValue = [...normalizedValue, { name: serverName, ...FULL_SELECTIONS }];\n onChange(newValue);\n }\n };\n\n const toggleServerExpanded = (serverName: string) => {\n setExpandedServers((prev) => {\n const newSet = new Set(prev);\n if (newSet.has(serverName)) {\n newSet.delete(serverName);\n } else {\n newSet.add(serverName);\n }\n return newSet;\n });\n };\n\n const hasAnyCapabilitySelection = (config: IGroupServerConfig) => {\n return (['tools', 'prompts', 'resources'] as CapabilityKey[]).some((capability) => {\n const selection = config[capability];\n return selection === 'all' || (Array.isArray(selection) && selection.length > 0);\n });\n };\n\n const updateServerCapability = (\n serverName: string,\n capability: CapabilityKey,\n selection: string[] | 'all',\n keepExpanded = false,\n ) => {\n const existingServer = normalizedValue.find((config) => config.name === serverName);\n const baseConfig: IGroupServerConfig = existingServer\n ? { ...existingServer }\n : { name: serverName, ...EMPTY_SELECTIONS };\n const nextConfig: IGroupServerConfig = {\n ...baseConfig,\n [capability]: selection,\n };\n // A deselected tool drops its pin, so selecting it again does not silently re-pin it\n if (capability === 'tools' && Array.isArray(selection) && nextConfig.pinnedTools) {\n nextConfig.pinnedTools = nextConfig.pinnedTools.filter((name) => selection.includes(name));\n if (nextConfig.pinnedTools.length === 0) delete nextConfig.pinnedTools;\n }\n\n if (!hasAnyCapabilitySelection(nextConfig)) {\n const newValue = normalizedValue.filter((config) => config.name !== serverName);\n onChange(newValue);\n if (!keepExpanded) {\n setExpandedServers((prev) => {\n const newSet = new Set(prev);\n newSet.delete(serverName);\n return newSet;\n });\n }\n return;\n }\n\n if (existingServer) {\n onChange(normalizedValue.map((config) => (config.name === serverName ? nextConfig : config)));\n return;\n }\n\n onChange([...normalizedValue, nextConfig]);\n };\n\n const updateServerAlias = (serverName: string, alias: string) => {\n const existingServer = normalizedValue.find((config) => config.name === serverName);\n if (!existingServer) return;\n\n const nextConfig: IGroupServerConfig = { ...existingServer };\n if (alias) {\n nextConfig.alias = alias;\n } else {\n delete nextConfig.alias;\n }\n\n onChange(normalizedValue.map((config) => (config.name === serverName ? nextConfig : config)));\n };\n\n const togglePinnedTool = (serverName: string, toolName: string) => {\n const existingServer = normalizedValue.find((config) => config.name === serverName);\n if (!existingServer) return;\n\n const pinnedTools = existingServer.pinnedTools ?? [];\n const nextConfig: IGroupServerConfig = {\n ...existingServer,\n pinnedTools: pinnedTools.includes(toolName)\n ? pinnedTools.filter((name) => name !== toolName)\n : [...pinnedTools, toolName],\n };\n if (nextConfig.pinnedTools!.length === 0) delete nextConfig.pinnedTools;\n\n onChange(normalizedValue.map((config) => (config.name === serverName ? nextConfig : config)));\n };\n\n const normalizeNamedCapability = (serverName: string, name: string) => {\n const prefix = `${serverName}${nameSeparator}`;\n return name.startsWith(prefix) ? name.slice(prefix.length) : name;\n };\n\n const getCapabilityItems = (server: Server, capability: CapabilityKey): CapabilityItem[] => {\n if (capability === 'tools') {\n return (server.tools || [])\n .filter((tool) => tool.enabled !== false)\n .map((tool: Tool) => ({\n key: tool.name,\n value: normalizeNamedCapability(server.name, tool.name),\n description: tool.description,\n annotations: tool.annotations,\n defaultDescription: tool.defaultDescription,\n hasDescriptionOverride: tool.hasDescriptionOverride,\n }));\n }\n\n if (capability === 'prompts') {\n return (server.prompts || [])\n .filter((prompt) => prompt.enabled !== false)\n .map((prompt: Prompt) => ({\n key: prompt.name,\n value: normalizeNamedCapability(server.name, prompt.name),\n description: prompt.description,\n }));\n }\n\n return (server.resources || [])\n .filter((resource) => resource.enabled !== false)\n .map((resource: Resource) => ({\n key: resource.uri,\n value: resource.uri,\n description: resource.description,\n }));\n };\n\n // Build one nested map (server -> item name -> cost) once per serverCosts change,\n // so per-render lookups don't rebuild a Map on every call (avoids O(N^2) churn).\n const serverCostsMap = React.useMemo(() => {\n const outerMap = new Map<string, Map<string, number>>();\n serverCosts.forEach((sc) => {\n const innerMap = new Map<string, number>();\n sc.items.forEach((i) => innerMap.set(i.name, i.cost));\n outerMap.set(sc.name, innerMap);\n });\n return outerMap;\n }, [serverCosts]);\n\n const costMapForServer = (serverName: string): Map<string, number> =>\n serverCostsMap.get(serverName) ?? new Map<string, number>();\n\n const getSelectedCapabilityCost = (server: Server, capability: CapabilityKey): number => {\n const costMap = costMapForServer(server.name);\n return getCapabilityItems(server, capability)\n .filter((item) => isCapabilityItemSelected(server.name, capability, item.value))\n .reduce((sum, item) => sum + (costMap.get(item.key) ?? 0), 0);\n };\n\n const getServerSelectedCost = (server: Server): number =>\n (['tools', 'prompts', 'resources'] as CapabilityKey[]).reduce(\n (sum, cap) => sum + getSelectedCapabilityCost(server, cap),\n 0,\n );\n\n const toggleCapabilityItem = (\n serverName: string,\n capability: CapabilityKey,\n itemValue: string,\n ) => {\n const server = availableServers.find((s) => s.name === serverName);\n if (!server) return;\n\n const allItems = getCapabilityItems(server, capability).map((item) => item.value);\n const serverConfig = normalizedValue.find((config) => config.name === serverName);\n\n if (!serverConfig) {\n updateServerCapability(serverName, capability, [itemValue]);\n return;\n }\n\n const currentSelection = serverConfig[capability];\n if (currentSelection === 'all') {\n const nextSelection = allItems.filter((value) => value !== itemValue);\n updateServerCapability(serverName, capability, nextSelection);\n return;\n }\n\n if (Array.isArray(currentSelection)) {\n if (currentSelection.includes(itemValue)) {\n updateServerCapability(\n serverName,\n capability,\n currentSelection.filter((value) => value !== itemValue),\n );\n return;\n }\n\n const nextSelection = [...currentSelection, itemValue];\n updateServerCapability(\n serverName,\n capability,\n nextSelection.length === allItems.length ? 'all' : nextSelection,\n );\n return;\n }\n\n updateServerCapability(serverName, capability, [itemValue]);\n };\n\n const isServerSelected = (serverName: string) => {\n const serverConfig = normalizedValue.find((config) => config.name === serverName);\n return Boolean(serverConfig && hasAnyCapabilitySelection(serverConfig));\n };\n\n const isServerPartiallySelected = (serverName: string) => {\n const serverConfig = normalizedValue.find((config) => config.name === serverName);\n if (!serverConfig) return false;\n\n return (['tools', 'prompts', 'resources'] as CapabilityKey[]).some((capability) => {\n const selection = serverConfig[capability];\n return Array.isArray(selection) && selection.length > 0;\n });\n };\n\n const isCapabilityItemSelected = (\n serverName: string,\n capability: CapabilityKey,\n itemValue: string,\n ) => {\n const serverConfig = normalizedValue.find((config) => config.name === serverName);\n if (!serverConfig) return false;\n\n const selection = serverConfig[capability];\n if (selection === 'all') return true;\n return Array.isArray(selection) ? selection.includes(itemValue) : false;\n };\n\n const getSelectedCapabilityCount = (server: Server, capability: CapabilityKey) => {\n const serverConfig = normalizedValue.find((config) => config.name === server.name);\n if (!serverConfig) return 0;\n\n const items = getCapabilityItems(server, capability);\n const selection = serverConfig[capability];\n if (selection === 'all') return items.length;\n if (Array.isArray(selection)) {\n const itemSet = new Set(items.map((item) => item.value));\n return selection.filter((item) => itemSet.has(item)).length;\n }\n return 0;\n };\n\n const capabilityConfigs: Array<{\n key: CapabilityKey;\n titleKey: string;\n countKey: string;\n allKey: string;\n }> = [\n {\n key: 'tools',\n titleKey: 'groups.toolSelection',\n countKey: 'groups.toolsSelected',\n allKey: 'groups.allTools',\n },\n {\n key: 'prompts',\n titleKey: 'groups.promptSelection',\n countKey: 'groups.promptsSelected',\n allKey: 'groups.allPrompts',\n },\n {\n key: 'resources',\n titleKey: 'groups.resourceSelection',\n countKey: 'groups.resourcesSelected',\n allKey: 'groups.allResources',\n },\n ];\n\n const getServerSummaryBadges = (server: Server) => {\n return capabilityConfigs\n .map(({ key }) => ({ key, count: getSelectedCapabilityCount(server, key) }))\n .filter((entry) => entry.count > 0);\n };\n\n return (\n <div className={cn('space-y-4', className)}>\n <div className=\"space-y-3\">\n {availableServers.map((server) => {\n const isSelected = isServerSelected(server.name);\n const isPartiallySelected = isServerPartiallySelected(server.name);\n const isExpanded = expandedServers.has(server.name);\n const serverConfig = normalizedValue.find((config) => config.name === server.name);\n const summaryBadges = getServerSummaryBadges(server);\n const serverCapabilities = capabilityConfigs.filter(\n ({ key }) => getCapabilityItems(server, key).length > 0,\n );\n const costMap = costMapForServer(server.name);\n\n return (\n <div\n key={server.name}\n 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\"\n >\n <div\n className=\"flex items-center justify-between p-3 cursor-pointer rounded-lg transition-colors\"\n onClick={() => toggleServerExpanded(server.name)}\n >\n <div\n className=\"flex items-center space-x-3\"\n onClick={(e) => {\n e.stopPropagation();\n toggleServer(server.name);\n }}\n >\n <input\n type=\"checkbox\"\n checked={isSelected || isPartiallySelected}\n onChange={() => toggleServer(server.name)}\n className=\"w-4 h-4 text-blue-600 accent-[var(--hub-accent)] rounded focus:ring-blue-500\"\n />\n <span className=\"font-medium text-[var(--hub-ink)] cursor-pointer select-none\">\n {server.name}\n </span>\n </div>\n\n <div className=\"flex items-center space-x-3\">\n {getServerSelectedCost(server) > 0 && (\n <span className=\"text-sm text-[var(--hub-ink-3)] hub-mono\" title={t('cost.estimate')}>\n Σ {formatTokens(getServerSelectedCost(server))}\n </span>\n )}\n {summaryBadges.map(({ key, count }) => (\n <span key={key} className=\"text-sm text-green-600 flex items-center gap-1\">\n {key === 'tools' ? (\n <Wrench size={14} />\n ) : key === 'prompts' ? (\n <MessageSquare size={14} />\n ) : (\n <FileText size={14} />\n )}{' '}\n {count}\n </span>\n ))}\n\n {serverCapabilities.length > 0 && (\n <button\n type=\"button\"\n className=\"p-1 text-[var(--hub-ink-3)] hover:text-[var(--hub-ink-2)] transition-colors\"\n >\n <svg\n className={cn('w-5 h-5 transition-transform', isExpanded && 'rotate-180')}\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 9l-7 7-7-7\"\n />\n </svg>\n </button>\n )}\n </div>\n </div>\n\n {isExpanded && serverCapabilities.length > 0 && (\n <div className=\"border-t border-[var(--hub-line)] bg-[var(--hub-bg-2)] p-3\">\n <div className=\"space-y-4\">\n {serverConfig && (\n <div className=\"space-y-1\" onClick={(e) => e.stopPropagation()}>\n <label\n htmlFor={`${aliasInputId}-${server.name}`}\n className=\"block text-xs font-medium text-[var(--hub-ink-2)]\"\n >\n {t('groups.alias')}\n </label>\n <input\n type=\"text\"\n id={`${aliasInputId}-${server.name}`}\n value={serverConfig.alias || ''}\n placeholder={server.name}\n onChange={(event) => updateServerAlias(server.name, event.target.value)}\n className=\"hub-input\"\n />\n <label className=\"flex items-center gap-2 text-xs text-[var(--hub-ink-2)]\">\n <input\n type=\"checkbox\"\n checked={serverConfig.preserveToolNames === true}\n onChange={(event) =>\n onChange(\n normalizedValue.map((config) =>\n config.name === server.name\n ? { ...config, preserveToolNames: event.target.checked }\n : config,\n ),\n )\n }\n />\n {t('groups.preserveToolNames')}\n </label>\n <p className=\"text-xs text-[var(--hub-ink-3)]\">\n {t('groups.preserveToolNamesHint')}\n </p>\n </div>\n )}\n {serverCapabilities.map(({ key, titleKey, countKey, allKey }) => {\n const items = getCapabilityItems(server, key);\n const selectedCount = getSelectedCapabilityCount(server, key);\n const allSelected =\n serverConfig?.[key] === 'all' || selectedCount === items.length;\n\n return (\n <div key={key}>\n <div className=\"flex items-center justify-between mb-3\">\n <span className=\"text-sm font-medium text-[var(--hub-ink-2)]\">{t(titleKey)}</span>\n <div className=\"flex items-center gap-3\">\n {serverConfig && (\n <span className=\"text-xs text-green-600\">\n {allSelected\n ? `(${t(allKey)} ${items.length}/${items.length})`\n : `(${t(countKey)} ${selectedCount}/${items.length})`}\n </span>\n )}\n {serverConfig && getSelectedCapabilityCost(server, key) > 0 && (\n <span\n className=\"text-xs text-[var(--hub-ink-3)] hub-mono\"\n title={t('cost.estimate')}\n >\n Σ {formatTokens(getSelectedCapabilityCost(server, key))}\n </span>\n )}\n <button\n type=\"button\"\n onClick={() => {\n updateServerCapability(\n server.name,\n key,\n allSelected ? [] : 'all',\n true,\n );\n }}\n className=\"text-sm text-blue-600 hover:text-blue-800 transition-colors\"\n >\n {allSelected ? t('groups.selectNone') : t('groups.selectAll')}\n </button>\n </div>\n </div>\n\n <CapabilitySelection\n items={items}\n selection={serverConfig?.[key] ?? []}\n tools={key === 'tools'}\n label={t(titleKey)}\n onChange={(selection) =>\n updateServerCapability(server.name, key, selection, true)\n }\n >\n {(item) => {\n const isChecked = isCapabilityItemSelected(\n server.name,\n key,\n item.value,\n );\n const isPinned = Boolean(\n serverConfig?.pinnedTools?.includes(item.value),\n );\n const descriptionInfo =\n key === 'tools'\n ? getToolDescriptionInfo(\n {\n description: item.description,\n defaultDescription: item.defaultDescription,\n hasDescriptionOverride: item.hasDescriptionOverride,\n },\n t('tool.noDescription'),\n )\n : null;\n const descriptionTitle = descriptionInfo?.hasDescriptionOverride\n ? t('tool.defaultDescriptionTooltip', {\n description: descriptionInfo.defaultDescription,\n })\n : item.description;\n\n return (\n <div key={item.key} className=\"flex min-w-0 items-center gap-2\">\n <label className=\"flex min-w-0 flex-1 items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={isChecked}\n onChange={() =>\n toggleCapabilityItem(server.name, key, item.value)\n }\n className=\"w-3 h-3 text-blue-600 accent-[var(--hub-accent)] rounded focus:ring-blue-500\"\n />\n <span className=\"text-[var(--hub-ink-2)] break-all whitespace-nowrap flex-shrink-0\">\n {item.value}\n </span>\n {(item.description ||\n descriptionInfo?.hasDescriptionOverride) && (\n <span className=\"min-w-0 flex items-center gap-1 text-[var(--hub-ink-3)] text-xs truncate\">\n <span\n className=\"truncate\"\n title={descriptionTitle || undefined}\n >\n {descriptionInfo\n ? descriptionInfo.currentDescription\n : item.description}\n </span>\n {descriptionInfo?.hasDescriptionOverride && (\n <span\n 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\"\n title={descriptionTitle || undefined}\n >\n {t('tool.descriptionModifiedBadge')}\n </span>\n )}\n </span>\n )}\n {costMap.get(item.key) != null && (\n <span\n className=\"text-xs text-[var(--hub-ink-3)] hub-mono whitespace-nowrap ml-auto flex-shrink-0\"\n title={t('cost.estimate')}\n >\n Σ {formatTokens(costMap.get(item.key)!)}\n </span>\n )}\n </label>\n {/* Shown while Smart Routing is on, and for an existing pin even\n when it is off, so a pin is never left invisible */}\n {key === 'tools' &&\n isChecked &&\n (smartRoutingConfig.enabled || isPinned) && (\n <button\n type=\"button\"\n onClick={() => togglePinnedTool(server.name, item.value)}\n title={t(isPinned ? 'groups.unpinTool' : 'groups.pinTool')}\n aria-label={t('groups.pinToolLabel')}\n aria-pressed={isPinned}\n className={cn(\n 'flex-shrink-0 transition-colors',\n isPinned\n ? 'text-blue-600'\n : 'text-[var(--hub-ink-3)] hover:text-[var(--hub-ink-2)]',\n )}\n >\n <Pin size={12} fill={isPinned ? 'currentColor' : 'none'} />\n </button>\n )}\n </div>\n );\n }}\n </CapabilitySelection>\n </div>\n );\n })}\n </div>\n </div>\n )}\n </div>\n );\n })}\n </div>\n\n {availableServers.length === 0 && (\n <p className=\"text-[var(--hub-ink-3)] text-sm\">{t('groups.noServerOptions')}</p>\n )}\n </div>\n );\n};\n","import UserGroupSelection from './UserGroupSelection';\nimport { useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport type { Group } from '@/types';\nimport { apiGet } from '@/utils/fetchInterceptor';\n\ntype Access = Pick<Group, 'visibility' | 'sharedWithUserGroups' | 'sharedWithUsers'>;\n\nexport default function GroupVisibilityFields({\n groupId,\n value,\n onChange,\n}: {\n groupId?: string;\n value: Access;\n onChange: (access: Access) => void;\n}) {\n const { t } = useTranslation();\n const [users, setUsers] = useState<string[]>([]);\n const [search, setSearch] = useState('');\n const [userGroups, setUserGroups] = useState<string[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState(false);\n const [isAdvancedExpanded, setIsAdvancedExpanded] = useState(false);\n useEffect(() => {\n if (!groupId || value.visibility !== 'group') return;\n let cancelled = false;\n setLoading(true);\n setError(false);\n apiGet<{ success: boolean; data?: string[]; userGroups?: string[] }>(\n `/groups/${encodeURIComponent(groupId)}/share-candidates`,\n )\n .then((result) => {\n if (cancelled) return;\n if (result.success && Array.isArray(result.data)) {\n setUsers(result.data);\n setUserGroups(result.userGroups || []);\n } else setError(true);\n })\n .catch(() => {\n if (!cancelled) setError(true);\n })\n .finally(() => {\n if (!cancelled) setLoading(false);\n });\n return () => {\n cancelled = true;\n };\n }, [groupId, value.visibility]);\n const selected = value.sharedWithUsers || [];\n const candidates = [...new Set([...users, ...selected])]\n .sort()\n .filter((username) => username.toLowerCase().includes(search.toLowerCase()));\n const selectedUsers = new Set(selected);\n const allCandidatesSelected =\n candidates.length > 0 && candidates.every((username) => selectedUsers.has(username));\n const noCandidatesSelected =\n candidates.length === 0 || candidates.every((username) => !selectedUsers.has(username));\n\n const toggleSharedUser = (username: string) => {\n const nextSelected = new Set(selected);\n if (nextSelected.has(username)) {\n nextSelected.delete(username);\n } else {\n nextSelected.add(username);\n }\n onChange({ sharedWithUsers: Array.from(nextSelected) });\n };\n\n return (\n <div className=\"mb-4\">\n <div\n 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)]\"\n onClick={() => setIsAdvancedExpanded(!isAdvancedExpanded)}\n >\n <h3 className=\"text-sm font-semibold text-[var(--hub-ink)]\">\n {t('server.sectionAdvanced', 'Advanced Options')}\n </h3>\n <span className=\"text-[var(--hub-ink-3)] text-sm\">{isAdvancedExpanded ? '▼' : '▶'}</span>\n </div>\n\n {isAdvancedExpanded && (\n <div className=\"border border-[var(--hub-line)] rounded-b p-4 bg-[var(--hub-surface)] border-t-0\">\n <label\n htmlFor=\"group-visibility\"\n className=\"block text-sm font-medium mb-1.5 text-[var(--hub-ink-2)]\"\n >\n {t('server.visibility')}\n </label>\n <select\n id=\"group-visibility\"\n className=\"hub-input\"\n value={value.visibility || ''}\n onChange={(event) =>\n onChange({ visibility: event.target.value as Group['visibility'] })\n }\n >\n {!value.visibility && (\n <option value=\"\" disabled>\n {t('groups.legacyVisibility')}\n </option>\n )}\n <option value=\"private\">{t('server.visibilityPrivate')}</option>\n <option value=\"group\">{t('server.visibilityGroup')}</option>\n <option value=\"public\">{t('server.visibilityPublic')}</option>\n </select>\n <p className=\"text-xs text-[var(--hub-ink-3)] mt-1\">{t('groups.visibilityDescription')}</p>\n {!value.visibility && (\n <p className=\"text-sm text-amber-600\">{t('groups.legacyVisibilityHint')}</p>\n )}\n {value.visibility === 'group' && (\n <div className=\"mt-4 rounded border border-[var(--hub-line)] p-3\">\n <UserGroupSelection\n options={userGroups}\n selected={value.sharedWithUserGroups || []}\n disabled={loading || error || !groupId}\n onChange={(sharedWithUserGroups) => onChange({ sharedWithUserGroups })}\n />\n <div className=\"text-sm font-medium text-[var(--hub-ink-2)]\">\n {t('server.shareWithUsers')}\n </div>\n <p className=\"text-xs text-[var(--hub-ink-3)] mt-1 mb-3\">\n {t('server.shareWithUsersDescription')}\n </p>\n {!groupId ? (\n <p className=\"text-sm text-[var(--hub-ink-3)]\">{t('groups.shareAfterCreate')}</p>\n ) : (\n <>\n {loading && (\n <p className=\"text-sm text-[var(--hub-ink-3)]\">{t('server.shareCandidatesLoading')}</p>\n )}\n {error && (\n <p role=\"alert\" className=\"text-sm text-red-600 dark:text-red-400\">\n {t('server.shareCandidatesError')}\n </p>\n )}\n {!loading && !error && candidates.length === 0 && (\n <p className=\"text-sm text-[var(--hub-ink-3)]\">\n {search ? t('server.noMatchingShareUsers') : t('server.noShareCandidates')}\n </p>\n )}\n {candidates.length > 0 && (\n <>\n <div className=\"mb-3 space-y-2\">\n <label\n htmlFor=\"group-share-search\"\n className=\"block text-xs font-medium text-[var(--hub-ink-2)]\"\n >\n {t('server.shareUserSearchLabel')}\n </label>\n <input\n id=\"group-share-search\"\n type=\"search\"\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n placeholder={t('server.shareUserSearchPlaceholder')}\n className=\"hub-input text-sm\"\n />\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n onClick={() =>\n onChange({\n sharedWithUsers: [...new Set([...selected, ...candidates])],\n })\n }\n disabled={allCandidatesSelected}\n className=\"hub-btn text-sm\"\n >\n {t('server.selectAllShareUsers')}\n </button>\n <button\n type=\"button\"\n onClick={() =>\n onChange({\n sharedWithUsers: selected.filter(\n (name) => !candidates.includes(name),\n ),\n })\n }\n disabled={noCandidatesSelected}\n className=\"hub-btn text-sm\"\n >\n {t('server.deselectAllShareUsers')}\n </button>\n </div>\n </div>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-2\">\n {candidates.map((username) => (\n <label\n key={username}\n className=\"flex items-center gap-2 rounded border border-[var(--hub-line)] px-3 py-2 text-sm text-[var(--hub-ink-2)]\"\n >\n <input\n type=\"checkbox\"\n checked={selectedUsers.has(username)}\n onChange={() => toggleSharedUser(username)}\n />\n <span>{username}</span>\n </label>\n ))}\n </div>\n </>\n )}\n </>\n )}\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n","import { useState, useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useGroupData } from '@/hooks/useGroupData';\nimport { useServerData } from '@/hooks/useServerData';\nimport { useCostData } from '@/hooks/useCostData';\nimport { GroupFormData, Server, IGroupServerConfig } from '@/types';\nimport { ServerToolConfig } from './ServerToolConfig';\nimport GroupVisibilityFields from './GroupVisibilityFields';\n\ninterface AddGroupFormProps {\n onAdd: () => void;\n onCancel: () => void;\n}\n\nconst AddGroupForm = ({ onAdd, onCancel }: AddGroupFormProps) => {\n const { t } = useTranslation();\n const { createGroup } = useGroupData();\n const { allServers } = useServerData();\n const { serverCosts } = useCostData();\n const [availableServers, setAvailableServers] = useState<Server[]>([]);\n const [error, setError] = useState<string | null>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n\n const [formData, setFormData] = useState<GroupFormData>({\n visibility: 'private',\n sharedWithUserGroups: [],\n sharedWithUsers: [],\n name: '',\n description: '',\n instructions: '',\n servers: [] as IGroupServerConfig[],\n });\n\n useEffect(() => {\n // Filter available servers (enabled only)\n setAvailableServers(allServers.filter((server) => server.enabled !== false));\n }, [allServers]);\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {\n const { name, value } = e.target;\n setFormData((prev) => ({\n ...prev,\n [name]: value,\n }));\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setIsSubmitting(true);\n setError(null);\n\n try {\n if (!formData.name.trim()) {\n setError(t('groups.nameRequired'));\n setIsSubmitting(false);\n return;\n }\n\n const result = await createGroup(formData.name, formData.description, formData.servers, {\n visibility: formData.visibility,\n sharedWithUserGroups: formData.sharedWithUserGroups,\n sharedWithUsers: formData.sharedWithUsers,\n instructions: formData.instructions,\n });\n if (!result || !result.success) {\n setError(result?.message || t('groups.createError'));\n setIsSubmitting(false);\n return;\n }\n\n onAdd();\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n setIsSubmitting(false);\n }\n };\n\n return (\n <div className=\"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4\">\n <div className=\"hub-card shadow-lg max-w-3xl w-full max-h-[90vh] flex flex-col\">\n <div className=\"p-6 flex-shrink-0\">\n <h2 className=\"text-xl font-semibold text-[var(--hub-ink)] mb-4\">{t('groups.addNew')}</h2>\n\n {error && (\n <div className=\"mb-4 p-3 bg-red-100 text-red-700 rounded-md border border-[var(--hub-line)]\">\n {error}\n </div>\n )}\n </div>\n\n <form onSubmit={handleSubmit} className=\"flex flex-col flex-1 min-h-0\">\n <div className=\"flex-1 overflow-y-auto px-6\">\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-[var(--hub-ink-2)] text-sm font-bold mb-2\" htmlFor=\"name\">\n {t('groups.name')} *\n </label>\n <input\n type=\"text\"\n id=\"name\"\n name=\"name\"\n value={formData.name}\n onChange={handleChange}\n 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)]\"\n placeholder={t('groups.namePlaceholder')}\n required\n />\n </div>\n\n <div>\n <label\n className=\"block text-[var(--hub-ink-2)] text-sm font-bold mb-2\"\n htmlFor=\"instructions\"\n >\n {t('groups.instructions')}\n </label>\n <textarea\n id=\"instructions\"\n name=\"instructions\"\n value={formData.instructions}\n onChange={handleChange}\n rows={3}\n 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)]\"\n placeholder={t('groups.instructionsPlaceholder')}\n />\n <p className=\"text-xs text-[var(--hub-ink-3)] mt-1\">{t('groups.instructionsHelp')}</p>\n </div>\n\n <div>\n <label className=\"block text-[var(--hub-ink-2)] text-sm font-bold mb-2\">\n {t('groups.configureCapabilities')}\n </label>\n <ServerToolConfig\n servers={availableServers}\n value={formData.servers as IGroupServerConfig[]}\n onChange={(servers) => setFormData((prev) => ({ ...prev, servers }))}\n className=\"border border-[var(--hub-line)] rounded-lg p-4 bg-[var(--hub-bg-2)]\"\n serverCosts={serverCosts}\n />\n </div>\n\n <GroupVisibilityFields\n value={formData}\n onChange={(access) => setFormData((previous) => ({ ...previous, ...access }))}\n />\n </div>\n </div>\n\n <div className=\"flex justify-end space-x-2 p-5 pt-3 border-t border-[var(--hub-line-2)] flex-shrink-0\">\n <button type=\"button\" onClick={onCancel} className=\"hub-btn\" disabled={isSubmitting}>\n {t('common.cancel')}\n </button>\n <button type=\"submit\" className=\"hub-btn primary\" disabled={isSubmitting}>\n {isSubmitting ? t('common.submitting') : t('common.create')}\n </button>\n </div>\n </form>\n </div>\n </div>\n );\n};\n\nexport default AddGroupForm;\n","import { useState, useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Group, GroupFormData, Server, IGroupServerConfig } from '@/types';\nimport { useGroupData } from '@/hooks/useGroupData';\nimport { useServerData } from '@/hooks/useServerData';\nimport { useCostData } from '@/hooks/useCostData';\nimport { ServerToolConfig } from './ServerToolConfig';\nimport GroupVisibilityFields from './GroupVisibilityFields';\n\ninterface EditGroupFormProps {\n group: Group;\n onEdit: () => void;\n onCancel: () => void;\n}\n\nconst EditGroupForm = ({ group, onEdit, onCancel }: EditGroupFormProps) => {\n const { t } = useTranslation();\n const { updateGroup } = useGroupData();\n const { allServers } = useServerData();\n const { serverCosts } = useCostData();\n const [availableServers, setAvailableServers] = useState<Server[]>([]);\n const [error, setError] = useState<string | null>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n\n const [formData, setFormData] = useState<GroupFormData>({\n visibility: group.visibility,\n sharedWithUserGroups: group.sharedWithUserGroups || [],\n sharedWithUsers: group.sharedWithUsers || [],\n name: group.name,\n description: group.description || '',\n instructions: group.instructions || '',\n servers: group.servers || [],\n });\n\n useEffect(() => {\n // Filter available servers (enabled only)\n setAvailableServers(allServers.filter((server) => server.enabled !== false));\n }, [allServers]);\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {\n const { name, value } = e.target;\n setFormData((prev) => ({\n ...prev,\n [name]: value,\n }));\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setIsSubmitting(true);\n setError(null);\n\n try {\n if (!formData.name.trim()) {\n setError(t('groups.nameRequired'));\n setIsSubmitting(false);\n return;\n }\n\n const result = await updateGroup(group.id, {\n visibility: formData.visibility,\n sharedWithUserGroups: formData.sharedWithUserGroups,\n sharedWithUsers: formData.sharedWithUsers,\n name: formData.name,\n description: formData.description,\n instructions: formData.instructions,\n servers: formData.servers,\n });\n\n if (!result || !result.success) {\n setError(result?.message || t('groups.updateError'));\n setIsSubmitting(false);\n return;\n }\n\n onEdit();\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n setIsSubmitting(false);\n }\n };\n\n return (\n <div className=\"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4\">\n <div className=\"hub-card shadow-lg max-w-3xl w-full max-h-[90vh] flex flex-col\">\n <div className=\"p-6 flex-shrink-0\">\n <h2 className=\"text-xl font-semibold text-[var(--hub-ink)] mb-4\">{t('groups.edit')}</h2>\n\n {error && (\n <div className=\"mb-4 p-3 bg-red-100 text-red-700 rounded-md border border-[var(--hub-line)]\">\n {error}\n </div>\n )}\n </div>\n\n <form onSubmit={handleSubmit} className=\"flex flex-col flex-1 min-h-0\">\n <div className=\"flex-1 overflow-y-auto px-6\">\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-[var(--hub-ink-2)] text-sm font-bold mb-2\" htmlFor=\"name\">\n {t('groups.name')} *\n </label>\n <input\n type=\"text\"\n id=\"name\"\n name=\"name\"\n value={formData.name}\n onChange={handleChange}\n 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)]\"\n placeholder={t('groups.namePlaceholder')}\n required\n />\n </div>\n\n <div>\n <label\n className=\"block text-[var(--hub-ink-2)] text-sm font-bold mb-2\"\n htmlFor=\"instructions\"\n >\n {t('groups.instructions')}\n </label>\n <textarea\n id=\"instructions\"\n name=\"instructions\"\n value={formData.instructions}\n onChange={handleChange}\n rows={3}\n 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)]\"\n placeholder={t('groups.instructionsPlaceholder')}\n />\n <p className=\"text-xs text-[var(--hub-ink-3)] mt-1\">{t('groups.instructionsHelp')}</p>\n </div>\n\n <div>\n <label className=\"block text-[var(--hub-ink-2)] text-sm font-bold mb-2\">\n {t('groups.configureCapabilities')}\n </label>\n <ServerToolConfig\n servers={availableServers}\n value={formData.servers as IGroupServerConfig[]}\n onChange={(servers) => setFormData((prev) => ({ ...prev, servers }))}\n className=\"border border-[var(--hub-line)] rounded-lg p-4 bg-[var(--hub-bg-2)]\"\n serverCosts={serverCosts}\n />\n </div>\n\n <GroupVisibilityFields\n groupId={group.id}\n value={formData}\n onChange={(access) => setFormData((previous) => ({ ...previous, ...access }))}\n />\n </div>\n </div>\n\n <div className=\"flex justify-end space-x-2 p-5 pt-3 border-t border-[var(--hub-line-2)] flex-shrink-0\">\n <button type=\"button\" onClick={onCancel} className=\"hub-btn\" disabled={isSubmitting}>\n {t('common.cancel')}\n </button>\n <button type=\"submit\" className=\"hub-btn primary\" disabled={isSubmitting}>\n {isSubmitting ? t('common.submitting') : t('common.save')}\n </button>\n </div>\n </form>\n </div>\n </div>\n );\n};\n\nexport default EditGroupForm;\n","import { useAuth } from '@/contexts/AuthContext';\nimport { useState, useRef, useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Edit3, Trash2, Copy, Check, Link as LinkIcon, FileCode, ChevronDown } from 'lucide-react';\nimport { Group, Server, IGroupServerConfig, GroupCost } from '@/types';\nimport DeleteDialog from '@/components/ui/DeleteDialog';\nimport CopyClientConfigDialog from '@/components/ui/CopyClientConfigDialog';\nimport {\n ACCESS_TOKEN_PLACEHOLDER,\n type ClientSnippetTarget,\n} from '@/utils/mcpClientSnippets';\nimport { copyText } from '@/utils/clipboard';\nimport { useToast } from '@/contexts/ToastContext';\nimport { useSettingsData } from '@/hooks/useSettingsData';\nimport { formatTokens, percentSaved } from '@/utils/contextCost';\n\ninterface GroupCardProps {\n group: Group;\n servers: Server[];\n onEdit: (group: Group) => void;\n onDelete: (groupId: string) => void;\n cost?: GroupCost;\n}\n\nconst getServerNames = (servers: string[] | IGroupServerConfig[]): string[] =>\n servers.map((server) => (typeof server === 'string' ? server : server.name));\n\nconst getServerConfig = (group: Group, serverName: string): IGroupServerConfig => {\n const server = group.servers.find((s) =>\n typeof s === 'string' ? s === serverName : s.name === serverName,\n );\n if (!server) return { name: serverName, tools: 'all', prompts: 'all', resources: 'all' };\n if (typeof server === 'string') {\n return { name: server, tools: 'all', prompts: 'all', resources: 'all' };\n }\n return server;\n};\n\nconst getServerDisplayName = (group: Group, serverName: string): string => {\n const config = getServerConfig(group, serverName);\n return config.alias?.trim() || serverName;\n};\n\nconst GroupCard = ({ group, servers, onEdit, onDelete, cost }: GroupCardProps) => {\n const { t } = useTranslation();\n const { auth } = useAuth();\n const canManage = !!auth.user && (auth.user.isAdmin || auth.user.username === group.owner);\n const { showToast } = useToast();\n const { installConfig, nameSeparator } = useSettingsData();\n const baseUrl = installConfig?.baseUrl?.replace(/\\/+$/, '') || '';\n\n const [showDeleteDialog, setShowDeleteDialog] = useState(false);\n const [clientConfigTarget, setClientConfigTarget] = useState<ClientSnippetTarget | null>(null);\n const [copied, setCopied] = useState(false);\n const [showCopyDropdown, setShowCopyDropdown] = useState(false);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handle = (e: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {\n setShowCopyDropdown(false);\n }\n };\n document.addEventListener('mousedown', handle);\n return () => document.removeEventListener('mousedown', handle);\n }, []);\n\n const doCopy = async (text: string) => {\n const ok = await copyText(text);\n if (ok) {\n setCopied(true);\n setShowCopyDropdown(false);\n showToast(t('common.copySuccess') || 'Copied', 'success');\n setTimeout(() => setCopied(false), 1500);\n } else {\n showToast(t('common.copyFailed') || 'Copy failed', 'error');\n }\n };\n\n const groupEndpoint = `${baseUrl}/mcp/${group.name}`;\n // Only the client-config dialog needs a URL-encoded path segment: group names\n // may contain spaces/CJK, and the generated client snippets must be valid URLs.\n // The raw groupEndpoint above is intentionally left as-is for the legacy\n // \"Copy URL\" actions.\n const clientConfigEndpoint = `${baseUrl}/mcp/${encodeURIComponent(group.name)}`;\n const groupOpenApiEndpoint = `${baseUrl}/api/${group.name}`;\n\n const serverNames = getServerNames(group.servers);\n const groupServers = servers.filter((s) => serverNames.includes(s.name));\n\n const tally = (server: Server) => {\n const cfg = getServerConfig(group, server.name);\n const prefix = `${server.name}${nameSeparator}`;\n const allTools = server.tools || [];\n const allPrompts = server.prompts || [];\n const allResources = server.resources || [];\n\n const visibleTools = Array.isArray(cfg.tools)\n ? allTools.filter((t) => {\n if (t.enabled === false) return false;\n const short = t.name.startsWith(prefix) ? t.name.slice(prefix.length) : t.name;\n return cfg.tools!.includes(short);\n }).length\n : allTools.filter((t) => t.enabled !== false).length;\n const visiblePrompts = Array.isArray(cfg.prompts)\n ? allPrompts.filter((p) => {\n if (p.enabled === false) return false;\n const short = p.name.startsWith(prefix) ? p.name.slice(prefix.length) : p.name;\n return cfg.prompts!.includes(short);\n }).length\n : allPrompts.filter((p) => p.enabled !== false).length;\n const visibleResources = Array.isArray(cfg.resources)\n ? allResources.filter((r) => r.enabled !== false && cfg.resources!.includes(r.uri)).length\n : allResources.filter((r) => r.enabled !== false).length;\n\n return {\n visibleTools,\n totalTools: allTools.length,\n visiblePrompts,\n totalPrompts: allPrompts.length,\n visibleResources,\n totalResources: allResources.length,\n };\n };\n\n const totalVisibleTools = groupServers.reduce((acc, s) => acc + tally(s).visibleTools, 0);\n\n return (\n <div className=\"hub-card flex h-full flex-col overflow-visible\">\n {/* Header */}\n <div\n className=\"flex items-start gap-3 px-4 py-3\"\n style={{ borderBottom: '1px solid var(--hub-line-2)' }}\n >\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span style={{ fontSize: 15, fontWeight: 600, letterSpacing: '-0.015em' }}>\n {group.name}\n </span>\n <span\n className=\"hub-mono\"\n style={{\n fontSize: 11,\n color: 'var(--hub-ink-3)',\n padding: '0 6px',\n border: '1px solid var(--hub-line)',\n borderRadius: 4,\n height: 18,\n display: 'inline-flex',\n alignItems: 'center',\n }}\n title={group.id}\n >\n {group.id}\n </span>\n </div>\n <div className=\"mt-1 text-xs text-[var(--hub-ink-3)]\">\n {group.visibility\n ? t(\n `server.visibility${group.visibility === 'group' ? 'Group' : group.visibility === 'public' ? 'Public' : 'Private'}`,\n )\n : t('groups.legacyVisibility')}\n </div>\n {group.description && (\n <div style={{ fontSize: 12.5, color: 'var(--hub-ink-3)', marginTop: 2 }}>\n {group.description}\n </div>\n )}\n </div>\n <div className=\"flex items-center gap-1\" ref={dropdownRef}>\n <div className=\"relative\">\n <button\n onClick={() => setShowCopyDropdown((v) => !v)}\n className=\"hub-icon-btn sm\"\n title={t('common.copy')}\n >\n {copied ? <Check size={13} className=\"text-[var(--hub-ok)]\" /> : <Copy size={13} />}\n </button>\n {showCopyDropdown && (\n <div\n className=\"absolute top-full right-0 mt-1 z-20 hub-card\"\n style={{ minWidth: 160, padding: 4 }}\n >\n <button\n onClick={() => doCopy(group.id)}\n 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\"\n >\n <Copy size={12} /> {t('common.copyId')}\n </button>\n <button\n onClick={() => doCopy(groupEndpoint)}\n 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\"\n >\n <LinkIcon size={12} /> {t('common.copyUrl')}\n </button>\n <button\n onClick={() => doCopy(groupOpenApiEndpoint)}\n 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\"\n >\n <LinkIcon size={12} /> {t('common.copyOpenApiUrl')}\n </button>\n <button\n onClick={() => {\n setShowCopyDropdown(false);\n setClientConfigTarget({\n name: group.name,\n url: clientConfigEndpoint,\n headers: { Authorization: `Bearer ${ACCESS_TOKEN_PLACEHOLDER}` },\n });\n }}\n 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\"\n >\n <FileCode size={12} /> {t('clientConfig.menuItem')}\n </button>\n </div>\n )}\n </div>\n {canManage && (\n <>\n <button\n onClick={() => onEdit(group)}\n className=\"hub-icon-btn sm\"\n title={t('groups.edit')}\n >\n <Edit3 size={13} />\n </button>\n <button\n onClick={() => setShowDeleteDialog(true)}\n className=\"hub-icon-btn sm\"\n title={t('groups.delete')}\n style={{ color: 'var(--hub-ink-3)' }}\n >\n <Trash2 size={13} />\n </button>\n </>\n )}\n </div>\n </div>\n\n {/* Routing diagram */}\n <div\n className=\"grid flex-1 items-center gap-3 px-4 py-3\"\n style={{ gridTemplateColumns: '1fr 80px 1fr', minHeight: 180 }}\n >\n {/* Servers */}\n <div className=\"flex flex-col gap-1.5\">\n {groupServers.length === 0 ? (\n <div style={{ fontSize: 12, color: 'var(--hub-ink-3)' }}>{t('groups.noServers')}</div>\n ) : (\n groupServers.map((s) => {\n const tn = tally(s);\n return (\n <div\n key={s.name}\n className=\"flex items-center gap-2.5 px-2.5 py-1.5 rounded-md\"\n style={{\n background: 'var(--hub-bg-2)',\n border: '1px solid var(--hub-line-2)',\n }}\n >\n <span\n className=\"inline-block flex-shrink-0\"\n style={{\n width: 6,\n height: 6,\n borderRadius: 50,\n background:\n s.status === 'connected'\n ? 'var(--hub-ok)'\n : s.status === 'connecting'\n ? 'var(--hub-warn)'\n : 'var(--hub-err)',\n }}\n />\n <span className=\"hub-mono truncate flex-1\" style={{ fontSize: 12.5 }}>\n <span title={s.name}>{getServerDisplayName(group, s.name)}</span>\n </span>\n <span\n className=\"hub-mono hub-num flex-shrink-0\"\n style={{ fontSize: 11, color: 'var(--hub-ink-3)' }}\n >\n {tn.visibleTools}/{tn.totalTools} tools\n </span>\n </div>\n );\n })\n )}\n </div>\n\n {/* Flow */}\n <svg width=\"80\" height=\"80\" viewBox=\"0 0 80 80\" className=\"self-center\">\n {groupServers.length === 0 ? (\n <path\n d=\"M0,40 C30,40 50,40 80,40\"\n stroke=\"var(--hub-line)\"\n strokeWidth=\"1\"\n fill=\"none\"\n strokeDasharray=\"3 3\"\n />\n ) : (\n groupServers.map((_, i) => {\n const y1 = 12 + (60 / Math.max(groupServers.length, 1)) * (i + 0.5);\n return (\n <path\n key={i}\n d={`M0,${y1} C 30,${y1} 50,40 80,40`}\n stroke=\"var(--hub-line)\"\n strokeWidth=\"1\"\n fill=\"none\"\n strokeDasharray=\"3 3\"\n />\n );\n })\n )}\n <circle cx=\"80\" cy=\"40\" r=\"4\" fill=\"var(--hub-ink)\" />\n </svg>\n\n {/* Endpoint */}\n <div\n className=\"px-3 py-2.5 rounded-md\"\n style={{\n border: '1px solid var(--hub-line)',\n background: 'var(--hub-bg-2)',\n }}\n >\n <div className=\"hub-sect\" style={{ marginBottom: 4 }}>\n endpoint\n </div>\n <div\n className=\"hub-mono break-all\"\n style={{ fontSize: 12, color: 'var(--hub-ink-2)', lineHeight: 1.4 }}\n >\n <span style={{ color: 'var(--hub-ink-3)' }}>/mcp/</span>\n <b style={{ color: 'var(--hub-ink)', fontWeight: 600 }}>{group.name}</b>\n </div>\n <div\n className=\"hub-mono break-all\"\n style={{ fontSize: 12, color: 'var(--hub-ink-2)', lineHeight: 1.4 }}\n >\n <span style={{ color: 'var(--hub-ink-3)' }}>/api/</span>\n <b style={{ color: 'var(--hub-ink)', fontWeight: 600 }}>{group.name}</b>\n </div>\n <div className=\"flex gap-1.5 mt-2\">\n <button\n className=\"hub-btn sm flex-1 justify-center\"\n onClick={() => doCopy(groupEndpoint)}\n title={t('common.copyUrl')}\n >\n <Copy size={11} /> MCP\n </button>\n <button\n className=\"hub-btn sm flex-1 justify-center\"\n onClick={() => doCopy(groupOpenApiEndpoint)}\n title={t('common.copyOpenApiUrl')}\n >\n <Copy size={11} /> OpenAPI\n </button>\n </div>\n </div>\n </div>\n\n {/* Footer */}\n <div\n className=\"flex justify-between items-center px-4 py-2\"\n style={{\n borderTop: '1px solid var(--hub-line-2)',\n background: 'var(--hub-bg-2)',\n fontSize: 12,\n color: 'var(--hub-ink-3)',\n }}\n >\n <div>\n <div className=\"hub-mono\">\n <span style={{ color: 'var(--hub-ink-2)' }}>{groupServers.length}</span>{' '}\n {t('nav.servers').toLowerCase()} ·{' '}\n <span style={{ color: 'var(--hub-ink-2)' }}>{totalVisibleTools}</span>{' '}\n {t('server.tools').toLowerCase()}\n </div>\n {cost && (\n <div className=\"hub-mono mt-1\" style={{ fontSize: 11.5, color: 'var(--hub-ink-3)' }}>\n <div title={t('cost.estimate')}>\n {t('cost.totalFootprint')}: {formatTokens(cost.direct.exposed)}/\n {formatTokens(cost.direct.gross)}\n </div>\n {cost.smartRouting && (\n <>\n <div>\n {t('cost.smartRouting')}: {formatTokens(cost.smartRouting.base)} (\n {t('cost.saved', {\n percent: percentSaved(cost.direct.exposed, cost.smartRouting.base),\n })}\n )\n </div>\n <div title={t('cost.smartRoutingPdHint')}>\n {t('cost.smartRoutingPd')}:{' '}\n {formatTokens(cost.smartRouting.progressiveDisclosure)}\n </div>\n </>\n )}\n {cost.connectedCount < cost.totalCount && (\n <div>\n {t('cost.connectedOf', {\n connected: cost.connectedCount,\n total: cost.totalCount,\n })}\n </div>\n )}\n </div>\n )}\n </div>\n {canManage && (\n <button\n className=\"hub-btn ghost sm\"\n style={{ color: 'var(--hub-ink-3)' }}\n onClick={() => onEdit(group)}\n >\n {t('groups.configureTools') || t('groups.edit')}\n <ChevronDown size={11} style={{ transform: 'rotate(-90deg)' }} />\n </button>\n )}\n </div>\n\n <CopyClientConfigDialog\n isOpen={clientConfigTarget !== null}\n target={clientConfigTarget}\n onClose={() => setClientConfigTarget(null)}\n />\n\n <DeleteDialog\n isOpen={showDeleteDialog}\n onClose={() => setShowDeleteDialog(false)}\n onConfirm={() => {\n onDelete(group.id);\n setShowDeleteDialog(false);\n }}\n serverName={group.name}\n isGroup={true}\n />\n </div>\n );\n};\n\nexport default GroupCard;\n","import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { apiPost } from '@/utils/fetchInterceptor';\n\ninterface GroupImportFormProps {\n onSuccess: () => void;\n onCancel: () => void;\n}\n\ninterface ImportGroupConfig {\n name: string;\n description?: string;\n servers?: string[] | Array<{\n name: string;\n tools?: string[] | 'all';\n prompts?: string[] | 'all';\n resources?: string[] | 'all';\n }>;\n}\n\ninterface ImportJsonFormat {\n groups: ImportGroupConfig[];\n}\n\nconst GroupImportForm: React.FC<GroupImportFormProps> = ({ onSuccess, onCancel }) => {\n const { t } = useTranslation();\n const [jsonInput, setJsonInput] = useState('');\n const [error, setError] = useState<string | null>(null);\n const [isImporting, setIsImporting] = useState(false);\n const [previewGroups, setPreviewGroups] = useState<ImportGroupConfig[] | null>(null);\n\n const examplePlaceholder = `{\n \"groups\": [\n {\n \"name\": \"AI Assistants\",\n \"servers\": [\"openai-server\", \"anthropic-server\"]\n },\n {\n \"name\": \"Development Tools\",\n \"servers\": [\n {\n \"name\": \"github-server\",\n \"tools\": [\"create_issue\", \"list_repos\"],\n \"prompts\": [\"triage_prompt\"],\n \"resources\": [\"resource://docs/repo-guide\"]\n },\n {\n \"name\": \"gitlab-server\",\n \"tools\": \"all\",\n \"prompts\": \"all\",\n \"resources\": \"all\"\n }\n ]\n }\n ]\n}\n\nSupports:\n- Simple server list: [\"server1\", \"server2\"]\n- Advanced server config: [{\"name\": \"server1\", \"tools\": [\"tool1\"], \"prompts\": [\"prompt1\"], \"resources\": [\"resource://docs/guide\"]}]\n- All groups will be imported in a single efficient batch operation.`;\n\n const parseAndValidateJson = (input: string): ImportJsonFormat | null => {\n try {\n const parsed = JSON.parse(input.trim());\n\n // Validate structure\n if (!parsed.groups || !Array.isArray(parsed.groups)) {\n setError(t('groupImport.invalidFormat'));\n return null;\n }\n\n // Validate each group\n for (const group of parsed.groups) {\n if (!group.name || typeof group.name !== 'string') {\n setError(t('groupImport.missingName'));\n return null;\n }\n }\n\n return parsed as ImportJsonFormat;\n } catch (e) {\n setError(t('groupImport.parseError'));\n return null;\n }\n };\n\n const handlePreview = () => {\n setError(null);\n const parsed = parseAndValidateJson(jsonInput);\n if (!parsed) return;\n\n setPreviewGroups(parsed.groups);\n };\n\n const handleImport = async () => {\n if (!previewGroups) return;\n\n setIsImporting(true);\n setError(null);\n\n try {\n // Use batch import API for better performance\n const result = await apiPost('/groups/batch', {\n groups: previewGroups,\n });\n\n if (result.success) {\n const { successCount, failureCount, results } = result;\n\n if (failureCount > 0) {\n const errors = results\n .filter((r: any) => !r.success)\n .map((r: any) => `${r.name}: ${r.message || t('groupImport.addFailed')}`);\n\n setError(\n t('groupImport.partialSuccess', { count: successCount, total: previewGroups.length }) +\n '\\n' +\n errors.join('\\n'),\n );\n }\n\n if (successCount > 0) {\n onSuccess();\n }\n } else {\n setError(result.message || t('groupImport.importFailed'));\n }\n } catch (err) {\n console.error('Import error:', err);\n setError(t('groupImport.importFailed'));\n } finally {\n setIsImporting(false);\n }\n };\n\n const renderAllCapabilitiesLabel = (\n key: 'previewAllTools' | 'previewAllPrompts' | 'previewAllResources',\n ) => <span className=\"text-gray-500 ml-2\">{t(`groups.${key}`)}</span>;\n\n const renderCapabilityPreview = (\n key: 'previewPrompts' | 'previewResources',\n value: string[] | 'all' | undefined,\n ) => {\n if (!value || value === 'all') {\n return null;\n }\n\n const items = Array.isArray(value) ? value.join(', ') : value;\n return <span className=\"text-gray-500 ml-2\">{t(`groups.${key}`, { items })}</span>;\n };\n\n const renderServerList = (\n servers?: string[] | Array<{\n name: string;\n tools?: string[] | 'all';\n prompts?: string[] | 'all';\n resources?: string[] | 'all';\n }>,\n ) => {\n if (!servers || servers.length === 0) {\n return <span className=\"text-gray-500\">{t('groups.noServers')}</span>;\n }\n\n return (\n <div className=\"space-y-1\">\n {servers.map((server, idx) => {\n if (typeof server === 'string') {\n return (\n <div key={idx} className=\"text-sm\">\n • {server}\n </div>\n );\n } else {\n return (\n <div key={idx} className=\"text-sm\">\n • {server.name}\n {server.tools && server.tools !== 'all' && (\n <span className=\"text-gray-500 ml-2\">\n ({Array.isArray(server.tools) ? server.tools.join(', ') : server.tools})\n </span>\n )}\n {server.tools === 'all' && renderAllCapabilitiesLabel('previewAllTools')}\n {renderCapabilityPreview('previewPrompts', server.prompts)}\n {server.prompts === 'all' && renderAllCapabilitiesLabel('previewAllPrompts')}\n {renderCapabilityPreview('previewResources', server.resources)}\n {server.resources === 'all' && renderAllCapabilitiesLabel('previewAllResources')}\n </div>\n );\n }\n })}\n </div>\n );\n };\n\n return (\n <div className=\"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4\">\n <div className=\"bg-white dark:bg-gray-800 shadow rounded-lg p-6 w-full max-w-4xl max-h-[90vh] overflow-y-auto\">\n <div className=\"flex justify-between items-center mb-6\">\n <h2 className=\"text-xl font-semibold text-gray-900\">{t('groupImport.title')}</h2>\n <button onClick={onCancel} className=\"text-gray-500 hover:text-gray-700\">\n ✕\n </button>\n </div>\n\n {error && (\n <div className=\"mb-4 bg-red-50 border-l-4 border-red-500 p-4 rounded\">\n <p className=\"text-red-700 whitespace-pre-wrap\">{error}</p>\n </div>\n )}\n\n {!previewGroups ? (\n <div>\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">\n {t('groupImport.inputLabel')}\n </label>\n <textarea\n value={jsonInput}\n onChange={(e) => setJsonInput(e.target.value)}\n 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\"\n placeholder={examplePlaceholder}\n />\n <p className=\"text-xs text-gray-500 mt-2\">{t('groupImport.inputHelp')}</p>\n </div>\n\n <div className=\"flex justify-end space-x-4\">\n <button\n onClick={onCancel}\n className=\"hub-btn\"\n >\n {t('common.cancel')}\n </button>\n <button\n onClick={handlePreview}\n disabled={!jsonInput.trim()}\n className=\"hub-btn primary\"\n >\n {t('groupImport.preview')}\n </button>\n </div>\n </div>\n ) : (\n <div>\n <div className=\"mb-4\">\n <h3 className=\"text-lg font-medium text-gray-900 mb-3\">\n {t('groupImport.previewTitle')}\n </h3>\n <div className=\"space-y-3\">\n {previewGroups.map((group, index) => (\n <div key={index} className=\"bg-gray-50 dark:bg-gray-800 p-4 rounded-lg border border-gray-200 dark:border-gray-700\">\n <div className=\"flex items-start justify-between\">\n <div className=\"flex-1\">\n <h4 className=\"font-medium text-gray-900\">{group.name}</h4>\n {group.description && (\n <p className=\"text-sm text-gray-600 mt-1\">{group.description}</p>\n )}\n <div className=\"mt-2 text-sm text-gray-600\">\n <strong>{t('groups.servers')}:</strong>\n <div className=\"mt-1\">{renderServerList(group.servers)}</div>\n </div>\n </div>\n </div>\n </div>\n ))}\n </div>\n </div>\n\n <div className=\"flex justify-end space-x-4\">\n <button\n onClick={() => setPreviewGroups(null)}\n disabled={isImporting}\n className=\"hub-btn\"\n >\n {t('common.back')}\n </button>\n <button\n onClick={handleImport}\n disabled={isImporting}\n className=\"hub-btn primary\"\n >\n {isImporting ? (\n <>\n <svg\n className=\"animate-spin h-4 w-4 mr-2\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n ></circle>\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n 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\"\n ></path>\n </svg>\n {t('groupImport.importing')}\n </>\n ) : (\n t('groupImport.import')\n )}\n </button>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default GroupImportForm;\n","import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { apiPost } from '@/utils/fetchInterceptor';\nimport { Group, ConfigTemplate } from '@/types';\n\ninterface TemplateExportFormProps {\n groups: Group[];\n onCancel: () => void;\n}\n\nconst TemplateExportForm: React.FC<TemplateExportFormProps> = ({ groups, onCancel }) => {\n const { t } = useTranslation();\n const [name, setName] = useState('');\n const [description, setDescription] = useState('');\n const [selectedGroupIds, setSelectedGroupIds] = useState<string[]>([]);\n const [includeDisabled, setIncludeDisabled] = useState(false);\n const [isExporting, setIsExporting] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const handleToggleGroup = (groupId: string) => {\n setSelectedGroupIds((prev) =>\n prev.includes(groupId) ? prev.filter((id) => id !== groupId) : [...prev, groupId],\n );\n };\n\n const handleSelectAll = () => {\n if (selectedGroupIds.length === groups.length) {\n setSelectedGroupIds([]);\n } else {\n setSelectedGroupIds(groups.map((g) => g.id));\n }\n };\n\n const handleExport = async () => {\n if (!name.trim()) {\n setError(t('template.nameRequired'));\n return;\n }\n\n setIsExporting(true);\n setError(null);\n\n try {\n const result = await apiPost('/templates/export', {\n name: name.trim(),\n description: description.trim() || undefined,\n groupIds: selectedGroupIds.length > 0 ? selectedGroupIds : undefined,\n includeDisabledServers: includeDisabled,\n });\n\n if (result.success && result.data) {\n const template: ConfigTemplate = result.data;\n const blob = new Blob([JSON.stringify(template, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `${template.name.replace(/[^a-zA-Z0-9-_]/g, '_')}.mcphub-template.json`;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n onCancel();\n } else {\n setError(result.message || t('template.exportFailed'));\n }\n } catch (err) {\n console.error('Export error:', err);\n setError(t('template.exportFailed'));\n } finally {\n setIsExporting(false);\n }\n };\n\n return (\n <div className=\"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4\">\n <div className=\"bg-white dark:bg-gray-800 shadow rounded-lg p-6 w-full max-w-3xl max-h-[90vh] overflow-y-auto\">\n <div className=\"flex justify-between items-center mb-6\">\n <h2 className=\"text-xl font-semibold text-gray-900\">{t('template.exportTitle')}</h2>\n <button onClick={onCancel} className=\"text-gray-500 hover:text-gray-700\">\n ✕\n </button>\n </div>\n\n {error && (\n <div className=\"mb-4 bg-red-50 dark:bg-red-900/20 border-l-4 border-red-500 p-4 rounded\">\n <p className=\"text-red-700 dark:text-red-300\">{error}</p>\n </div>\n )}\n\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n {t('template.name')} *\n </label>\n <input\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder={t('template.namePlaceholder')}\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n {t('template.description')}\n </label>\n <input\n type=\"text\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n placeholder={t('template.descriptionPlaceholder')}\n />\n </div>\n\n <div>\n <div className=\"flex justify-between items-center mb-2\">\n <label className=\"block text-sm font-medium text-gray-700\">\n {t('template.selectGroups')}\n </label>\n <button\n onClick={handleSelectAll}\n className=\"text-sm text-blue-600 hover:text-blue-800 dark:text-blue-300\"\n >\n {selectedGroupIds.length === groups.length\n ? t('template.deselectAll')\n : t('template.selectAll')}\n </button>\n </div>\n <p className=\"text-xs text-gray-500 mb-2\">{t('template.selectGroupsHelp')}</p>\n <div className=\"border border-gray-200 dark:border-gray-700 rounded-md max-h-48 overflow-y-auto\">\n {groups.map((group) => (\n <label\n key={group.id}\n className=\"flex items-center px-3 py-2 hover:bg-gray-50 dark:bg-gray-800 dark:hover:bg-gray-700 cursor-pointer\"\n >\n <input\n type=\"checkbox\"\n checked={selectedGroupIds.includes(group.id)}\n onChange={() => handleToggleGroup(group.id)}\n className=\"mr-3 h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500\"\n />\n <div>\n <span className=\"text-sm font-medium text-gray-900\">{group.name}</span>\n {group.description && (\n <span className=\"text-xs text-gray-500 ml-2\">{group.description}</span>\n )}\n </div>\n </label>\n ))}\n </div>\n </div>\n\n <label className=\"flex items-center space-x-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={includeDisabled}\n onChange={(e) => setIncludeDisabled(e.target.checked)}\n className=\"h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500\"\n />\n <span className=\"text-sm text-gray-700\">{t('template.includeDisabled')}</span>\n </label>\n </div>\n\n <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\">\n <p className=\"text-sm text-blue-700 dark:text-blue-300\">{t('template.exportNote')}</p>\n </div>\n\n <div className=\"flex justify-end space-x-4 mt-6\">\n <button\n onClick={onCancel}\n className=\"hub-btn\"\n >\n {t('common.cancel')}\n </button>\n <button\n onClick={handleExport}\n disabled={isExporting || !name.trim()}\n className=\"hub-btn primary\"\n >\n {isExporting ? t('template.exporting') : t('template.export')}\n </button>\n </div>\n </div>\n </div>\n );\n};\n\nexport default TemplateExportForm;\n","import React, { useState, useRef } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { apiPost } from '@/utils/fetchInterceptor';\nimport { ConfigTemplate, TemplateImportResult } from '@/types';\n\ninterface TemplateImportFormProps {\n onSuccess: () => void;\n onCancel: () => void;\n}\n\nconst TemplateImportForm: React.FC<TemplateImportFormProps> = ({ onSuccess, onCancel }) => {\n const { t } = useTranslation();\n const [template, setTemplate] = useState<ConfigTemplate | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [isImporting, setIsImporting] = useState(false);\n const [result, setResult] = useState<TemplateImportResult | null>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {\n setError(null);\n setTemplate(null);\n setResult(null);\n\n const file = e.target.files?.[0];\n if (!file) return;\n\n const reader = new FileReader();\n reader.onload = (event) => {\n try {\n const parsed = JSON.parse(event.target?.result as string);\n if (!parsed.version || !parsed.name || !parsed.servers || !parsed.groups) {\n setError(t('template.invalidFormat'));\n return;\n }\n setTemplate(parsed as ConfigTemplate);\n } catch {\n setError(t('template.parseError'));\n }\n };\n reader.readAsText(file);\n };\n\n const handlePaste = (input: string) => {\n setError(null);\n setTemplate(null);\n setResult(null);\n\n if (!input.trim()) return;\n\n try {\n const parsed = JSON.parse(input.trim());\n if (!parsed.version || !parsed.name || !parsed.servers || !parsed.groups) {\n setError(t('template.invalidFormat'));\n return;\n }\n setTemplate(parsed as ConfigTemplate);\n } catch {\n setError(t('template.parseError'));\n }\n };\n\n const handleImport = async () => {\n if (!template) return;\n\n setIsImporting(true);\n setError(null);\n\n try {\n const response = await apiPost('/templates/import', template);\n\n if (response.data) {\n setResult(response.data as TemplateImportResult);\n if (response.data.success) {\n onSuccess();\n }\n } else {\n setError(response.message || t('template.importFailed'));\n }\n } catch (err) {\n console.error('Import error:', err);\n setError(t('template.importFailed'));\n } finally {\n setIsImporting(false);\n }\n };\n\n return (\n <div className=\"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4\">\n <div className=\"bg-white dark:bg-gray-800 shadow rounded-lg p-6 w-full max-w-4xl max-h-[90vh] overflow-y-auto\">\n <div className=\"flex justify-between items-center mb-6\">\n <h2 className=\"text-xl font-semibold text-gray-900\">{t('template.importTitle')}</h2>\n <button onClick={onCancel} className=\"text-gray-500 hover:text-gray-700\">\n ✕\n </button>\n </div>\n\n {error && (\n <div className=\"mb-4 bg-red-50 dark:bg-red-900/20 border-l-4 border-red-500 p-4 rounded\">\n <p className=\"text-red-700 dark:text-red-300\">{error}</p>\n </div>\n )}\n\n {result && (\n <div\n className={`mb-4 p-4 rounded border-l-4 ${result.success ? 'bg-green-50 dark:bg-green-900/20 border-green-500' : 'bg-yellow-50 dark:bg-yellow-900/20 border-yellow-500'}`}\n >\n <p className={result.success ? 'text-green-700 dark:text-green-300' : 'text-yellow-700 dark:text-yellow-300'}>\n {t('template.importResult', {\n serversCreated: result.serversCreated,\n serversSkipped: result.serversSkipped,\n groupsCreated: result.groupsCreated,\n groupsSkipped: result.groupsSkipped,\n })}\n </p>\n {result.requiredEnvVars.length > 0 && (\n <div className=\"mt-2 p-2 bg-orange-50 dark:bg-orange-900/20 border border-orange-200 dark:border-orange-700/60 rounded\">\n <p className=\"text-sm font-medium text-orange-800 dark:text-orange-300\">\n {t('template.envVarsNeeded')}\n </p>\n <ul className=\"mt-1 text-sm text-orange-700 dark:text-orange-300\">\n {result.requiredEnvVars.map((v) => (\n <li key={v} className=\"font-mono\">\n {v}\n </li>\n ))}\n </ul>\n </div>\n )}\n </div>\n )}\n\n {!template ? (\n <div>\n <div className=\"mb-4\">\n <div className=\"flex items-center justify-between mb-2\">\n <label className=\"block text-sm font-medium text-gray-700\">\n {t('template.uploadFile')}\n </label>\n </div>\n <div className=\"flex items-center space-x-4\">\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\".json\"\n onChange={handleFileSelect}\n 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\"\n />\n </div>\n </div>\n\n <div className=\"relative my-4\">\n <div className=\"absolute inset-0 flex items-center\">\n <div className=\"w-full border-t border-gray-300\" />\n </div>\n <div className=\"relative flex justify-center text-sm\">\n <span className=\"bg-white dark:bg-gray-800 px-2 text-gray-500\">{t('template.or')}</span>\n </div>\n </div>\n\n <div className=\"mb-4\">\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">\n {t('template.pasteJson')}\n </label>\n <textarea\n 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\"\n placeholder={t('template.pastePlaceholder')}\n onChange={(e) => handlePaste(e.target.value)}\n />\n </div>\n\n <div className=\"flex justify-end space-x-4\">\n <button\n onClick={onCancel}\n className=\"hub-btn\"\n >\n {t('common.cancel')}\n </button>\n </div>\n </div>\n ) : (\n <div>\n {/* Template preview */}\n <div className=\"space-y-4\">\n <div className=\"p-3 bg-gray-50 dark:bg-gray-800 rounded-md\">\n <h3 className=\"font-medium text-gray-900\">{template.name}</h3>\n {template.description && (\n <p className=\"text-sm text-gray-600 mt-1\">{template.description}</p>\n )}\n <p className=\"text-xs text-gray-500 mt-1\">\n {t('template.version')}: {template.version} | {t('template.createdAt')}:{' '}\n {new Date(template.createdAt).toLocaleDateString()}\n </p>\n </div>\n\n <div>\n <h4 className=\"text-sm font-medium text-gray-700 mb-2\">\n {t('template.servers')} ({Object.keys(template.servers).length})\n </h4>\n <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\">\n {Object.entries(template.servers).map(([name, config]) => (\n <div key={name} className=\"px-3 py-2\">\n <span className=\"text-sm font-medium text-gray-900\">{name}</span>\n <span className=\"text-xs text-gray-500 ml-2\">\n {config.type || 'stdio'}\n </span>\n </div>\n ))}\n </div>\n </div>\n\n <div>\n <h4 className=\"text-sm font-medium text-gray-700 mb-2\">\n {t('template.groups')} ({template.groups.length})\n </h4>\n <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\">\n {template.groups.map((group, idx) => (\n <div key={idx} className=\"px-3 py-2\">\n <span className=\"text-sm font-medium text-gray-900\">{group.name}</span>\n {group.description && (\n <span className=\"text-xs text-gray-500 ml-2\">{group.description}</span>\n )}\n <div className=\"text-xs text-gray-500 mt-1\">\n {group.servers.length} {t('template.serversInGroup')}\n </div>\n </div>\n ))}\n </div>\n </div>\n\n {template.requiredEnvVars.length > 0 && (\n <div className=\"p-3 bg-orange-50 dark:bg-orange-900/20 border border-orange-200 dark:border-orange-700/60 rounded-md\">\n <h4 className=\"text-sm font-medium text-orange-800 dark:text-orange-300\">\n {t('template.envVarsNeeded')}\n </h4>\n <ul className=\"mt-1 text-sm text-orange-700 dark:text-orange-300 font-mono\">\n {template.requiredEnvVars.map((v) => (\n <li key={v}>{v}</li>\n ))}\n </ul>\n </div>\n )}\n </div>\n\n <div className=\"flex justify-end space-x-4 mt-6\">\n <button\n onClick={() => {\n setTemplate(null);\n setResult(null);\n if (fileInputRef.current) fileInputRef.current.value = '';\n }}\n className=\"hub-btn\"\n >\n {t('common.back')}\n </button>\n <button\n onClick={handleImport}\n disabled={isImporting}\n className=\"hub-btn primary\"\n >\n {isImporting ? t('template.importing') : t('template.import')}\n </button>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default TemplateImportForm;\n","import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Plus, Download, Upload, AlertCircle, X } from 'lucide-react';\nimport { Group } from '@/types';\nimport { useGroupData } from '@/hooks/useGroupData';\nimport { useServerData } from '@/hooks/useServerData';\nimport AddGroupForm from '@/components/AddGroupForm';\nimport EditGroupForm from '@/components/EditGroupForm';\nimport GroupCard from '@/components/GroupCard';\nimport GroupImportForm from '@/components/GroupImportForm';\nimport TemplateExportForm from '@/components/TemplateExportForm';\nimport TemplateImportForm from '@/components/TemplateImportForm';\nimport { serverCostRevision } from '@/utils/costRevision';\nimport { useCostData } from '@/hooks/useCostData';\n\nconst GroupsPage: React.FC = () => {\n const { t } = useTranslation();\n const {\n groups,\n loading: groupsLoading,\n error: groupError,\n setError: setGroupError,\n deleteGroup,\n triggerRefresh,\n } = useGroupData();\n const { allServers } = useServerData({ refreshOnMount: true });\n const { groupCosts } = useCostData(JSON.stringify([groups, serverCostRevision(allServers)]));\n\n const [editingGroup, setEditingGroup] = useState<Group | null>(null);\n const [showAddForm, setShowAddForm] = useState(false);\n const [showImportForm, setShowImportForm] = useState(false);\n const [showTemplateExport, setShowTemplateExport] = useState(false);\n const [showTemplateImport, setShowTemplateImport] = useState(false);\n\n const handleDeleteGroup = async (groupId: string) => {\n const result = await deleteGroup(groupId);\n if (!result || !result.success) {\n setGroupError(result?.message || t('groups.deleteError'));\n }\n };\n\n return (\n <div>\n <div className=\"flex items-end justify-between gap-4 mb-6\">\n <div>\n <h1 className=\"hub-h1\">{t('pages.groups.title')}</h1>\n <p className=\"hub-sub\">\n <span className=\"hub-num\">{groups.length}</span> {t('nav.groups').toLowerCase()}\n </p>\n </div>\n <div className=\"flex gap-2\">\n <button className=\"hub-btn\" onClick={() => setShowImportForm(true)}>\n <Upload size={13} /> {t('groupImport.button')}\n </button>\n <button className=\"hub-btn\" onClick={() => setShowTemplateExport(true)}>\n <Download size={13} /> {t('template.exportButton')}\n </button>\n <button className=\"hub-btn\" onClick={() => setShowTemplateImport(true)}>\n <Upload size={13} /> {t('template.importButton')}\n </button>\n <button className=\"hub-btn primary\" onClick={() => setShowAddForm(true)}>\n <Plus size={13} /> {t('groups.add')}\n </button>\n </div>\n </div>\n\n {groupError && (\n <div\n className=\"hub-card flex items-center justify-between gap-3 mb-4\"\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]\">{groupError}</span>\n </div>\n <button className=\"hub-icon-btn sm\" onClick={() => setGroupError(null)}>\n <X size={13} />\n </button>\n </div>\n )}\n\n {groupsLoading ? (\n <div className=\"hub-card p-6 text-center\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('app.loading')}\n </div>\n ) : groups.length === 0 ? (\n <div className=\"hub-card p-10 text-center\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('groups.noGroups')}\n </div>\n ) : (\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-3.5\">\n {groups.map((group) => (\n <GroupCard\n key={group.id}\n group={group}\n servers={allServers}\n onEdit={setEditingGroup}\n onDelete={handleDeleteGroup}\n cost={groupCosts.find((c) => c.id === group.id)}\n />\n ))}\n <button\n onClick={() => setShowAddForm(true)}\n className=\"flex items-center justify-center text-[var(--hub-ink-3)] hover:text-[var(--hub-ink-2)] transition-colors\"\n style={{\n border: '1px dashed var(--hub-line)',\n borderRadius: 10,\n minHeight: 200,\n background: 'transparent',\n cursor: 'pointer',\n }}\n >\n <div className=\"text-center\">\n <div\n className=\"grid place-items-center mx-auto mb-2\"\n style={{\n width: 36,\n height: 36,\n borderRadius: 10,\n border: '1px solid var(--hub-line)',\n }}\n >\n <Plus size={16} />\n </div>\n <div style={{ fontSize: 13, fontWeight: 500, color: 'var(--hub-ink-2)' }}>\n {t('groups.add')}\n </div>\n <div style={{ fontSize: 12, marginTop: 2 }}>{t('groups.addNew')}</div>\n </div>\n </button>\n </div>\n )}\n\n {showAddForm && (\n <AddGroupForm\n onAdd={() => {\n setShowAddForm(false);\n triggerRefresh();\n }}\n onCancel={() => setShowAddForm(false)}\n />\n )}\n\n {showImportForm && (\n <GroupImportForm\n onSuccess={() => {\n setShowImportForm(false);\n triggerRefresh();\n }}\n onCancel={() => setShowImportForm(false)}\n />\n )}\n\n {editingGroup && (\n <EditGroupForm\n group={editingGroup}\n onEdit={() => {\n setEditingGroup(null);\n triggerRefresh();\n }}\n onCancel={() => setEditingGroup(null)}\n />\n )}\n\n {showTemplateExport && (\n <TemplateExportForm groups={groups} onCancel={() => setShowTemplateExport(false)} />\n )}\n\n {showTemplateImport && (\n <TemplateImportForm\n onSuccess={() => {\n setShowTemplateImport(false);\n triggerRefresh();\n }}\n onCancel={() => setShowTemplateImport(false)}\n />\n )}\n </div>\n );\n};\n\nexport default GroupsPage;\n"],"names":["RISK_GROUPS","classifyTool","item","_a","name","_b","_c","filterCapabilities","items","query","annotation","search","applyVisibleSelection","selection","all","visible","action","selected","CapabilitySelection","tools","label","onChange","children","t","useTranslation","setQuery","useState","setAnnotation","grouped","setGrouped","apply","target","sections","risk","buttonClass","jsxs","jsx","event","Fragment","hint","section","count","React","EMPTY_SELECTIONS","FULL_SELECTIONS","ServerToolConfig","servers","value","className","serverCosts","aliasInputId","nameSeparator","smartRoutingConfig","useSettingsData","expandedServers","setExpandedServers","normalizedValue","availableServers","server","configuredServerNames","config","availableServerNames","prev","newSet","serverName","toggleServer","newValue","toggleServerExpanded","hasAnyCapabilitySelection","capability","updateServerCapability","keepExpanded","existingServer","nextConfig","updateServerAlias","alias","togglePinnedTool","toolName","pinnedTools","normalizeNamedCapability","prefix","getCapabilityItems","tool","prompt","resource","serverCostsMap","outerMap","sc","innerMap","i","costMapForServer","getSelectedCapabilityCost","costMap","isCapabilityItemSelected","sum","getServerSelectedCost","cap","toggleCapabilityItem","itemValue","s","allItems","serverConfig","currentSelection","nextSelection","isServerSelected","isServerPartiallySelected","getSelectedCapabilityCount","itemSet","capabilityConfigs","getServerSummaryBadges","key","entry","cn","isSelected","isPartiallySelected","isExpanded","summaryBadges","serverCapabilities","e","formatTokens","Wrench","MessageSquare","FileText","titleKey","countKey","allKey","selectedCount","allSelected","isChecked","isPinned","descriptionInfo","getToolDescriptionInfo","descriptionTitle","Pin","GroupVisibilityFields","groupId","users","setUsers","setSearch","userGroups","setUserGroups","loading","setLoading","error","setError","isAdvancedExpanded","setIsAdvancedExpanded","useEffect","cancelled","apiGet","result","candidates","username","selectedUsers","allCandidatesSelected","noCandidatesSelected","toggleSharedUser","nextSelected","UserGroupSelection","sharedWithUserGroups","AddGroupForm","onAdd","onCancel","createGroup","useGroupData","allServers","useServerData","useCostData","setAvailableServers","isSubmitting","setIsSubmitting","formData","setFormData","handleChange","handleSubmit","err","access","previous","EditGroupForm","group","onEdit","updateGroup","getServerNames","getServerConfig","getServerDisplayName","GroupCard","onDelete","cost","auth","useAuth","canManage","showToast","useToast","installConfig","baseUrl","showDeleteDialog","setShowDeleteDialog","clientConfigTarget","setClientConfigTarget","copied","setCopied","showCopyDropdown","setShowCopyDropdown","dropdownRef","useRef","handle","doCopy","text","copyText","groupEndpoint","clientConfigEndpoint","groupOpenApiEndpoint","serverNames","groupServers","tally","cfg","allTools","allPrompts","allResources","visibleTools","short","visiblePrompts","p","visibleResources","r","totalVisibleTools","acc","v","Check","Copy","LinkIcon","ACCESS_TOKEN_PLACEHOLDER","FileCode","Edit3","Trash2","tn","_","y1","percentSaved","ChevronDown","CopyClientConfigDialog","DeleteDialog","GroupImportForm","onSuccess","jsonInput","setJsonInput","isImporting","setIsImporting","previewGroups","setPreviewGroups","examplePlaceholder","parseAndValidateJson","input","parsed","handlePreview","handleImport","apiPost","successCount","failureCount","results","errors","renderAllCapabilitiesLabel","renderCapabilityPreview","renderServerList","idx","index","TemplateExportForm","groups","setName","description","setDescription","selectedGroupIds","setSelectedGroupIds","includeDisabled","setIncludeDisabled","isExporting","setIsExporting","handleToggleGroup","id","handleSelectAll","g","handleExport","template","blob","url","a","TemplateImportForm","setTemplate","setResult","fileInputRef","handleFileSelect","file","reader","handlePaste","response","GroupsPage","groupsLoading","groupError","setGroupError","deleteGroup","triggerRefresh","groupCosts","serverCostRevision","editingGroup","setEditingGroup","showAddForm","setShowAddForm","showImportForm","setShowImportForm","showTemplateExport","setShowTemplateExport","showTemplateImport","setShowTemplateImport","handleDeleteGroup","Upload","Download","Plus","AlertCircle","X","c"],"mappings":"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"}