@samanhappy/mcphub 1.1.14 → 1.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/README.fr.md +1 -1
  2. package/README.md +1 -1
  3. package/README.zh.md +1 -1
  4. package/dist/betterAuth.js +3 -3
  5. package/dist/betterAuth.js.map +1 -1
  6. package/dist/cli/commands/keys.js +22 -3
  7. package/dist/cli/commands/keys.js.map +1 -1
  8. package/dist/clients/mcpSdkClient.js +2667 -1448
  9. package/dist/clients/mcpSdkClient.js.map +4 -4
  10. package/dist/controllers/bearerKeyController.js +49 -3
  11. package/dist/controllers/bearerKeyController.js.map +1 -1
  12. package/dist/controllers/credentialBindingController.js +1 -1
  13. package/dist/controllers/credentialBindingController.js.map +1 -1
  14. package/dist/controllers/groupController.js +12 -5
  15. package/dist/controllers/groupController.js.map +1 -1
  16. package/dist/controllers/oauthRelayController.js +65 -0
  17. package/dist/controllers/oauthRelayController.js.map +1 -0
  18. package/dist/controllers/personalOAuthController.js +10 -1
  19. package/dist/controllers/personalOAuthController.js.map +1 -1
  20. package/dist/controllers/serverController.js +23 -14
  21. package/dist/controllers/serverController.js.map +1 -1
  22. package/dist/controllers/userController.js +11 -1
  23. package/dist/controllers/userController.js.map +1 -1
  24. package/dist/dao/BearerKeyDao.js +10 -5
  25. package/dist/dao/BearerKeyDao.js.map +1 -1
  26. package/dist/dao/BearerKeyDaoDbImpl.js +16 -5
  27. package/dist/dao/BearerKeyDaoDbImpl.js.map +1 -1
  28. package/dist/dao/GroupDaoDbImpl.js +11 -0
  29. package/dist/dao/GroupDaoDbImpl.js.map +1 -1
  30. package/dist/dao/ServerDao.js +5 -1
  31. package/dist/dao/ServerDao.js.map +1 -1
  32. package/dist/dao/ServerDaoDbImpl.js +3 -0
  33. package/dist/dao/ServerDaoDbImpl.js.map +1 -1
  34. package/dist/dao/UserDaoDbImpl.js +4 -0
  35. package/dist/dao/UserDaoDbImpl.js.map +1 -1
  36. package/dist/db/entities/BearerKey.js +8 -0
  37. package/dist/db/entities/BearerKey.js.map +1 -1
  38. package/dist/db/entities/Group.js +4 -0
  39. package/dist/db/entities/Group.js.map +1 -1
  40. package/dist/db/entities/Server.js +4 -0
  41. package/dist/db/entities/Server.js.map +1 -1
  42. package/dist/db/entities/User.js +4 -0
  43. package/dist/db/entities/User.js.map +1 -1
  44. package/dist/db/repositories/ServerRepository.js +1 -0
  45. package/dist/db/repositories/ServerRepository.js.map +1 -1
  46. package/dist/middlewares/auth.js +7 -1
  47. package/dist/middlewares/auth.js.map +1 -1
  48. package/dist/routes/index.js +2 -0
  49. package/dist/routes/index.js.map +1 -1
  50. package/dist/services/authorizationService.js.map +1 -1
  51. package/dist/services/capabilitySnapshotService.js +2 -1
  52. package/dist/services/capabilitySnapshotService.js.map +1 -1
  53. package/dist/services/credentialBindingService.js +9 -1
  54. package/dist/services/credentialBindingService.js.map +1 -1
  55. package/dist/services/dataService.js +4 -2
  56. package/dist/services/dataService.js.map +1 -1
  57. package/dist/services/groupService.js +15 -7
  58. package/dist/services/groupService.js.map +1 -1
  59. package/dist/services/mcpEventBus.js +6 -0
  60. package/dist/services/mcpEventBus.js.map +1 -0
  61. package/dist/services/mcpService.js +26 -2
  62. package/dist/services/mcpService.js.map +1 -1
  63. package/dist/services/personalOAuthService.js +2 -0
  64. package/dist/services/personalOAuthService.js.map +1 -1
  65. package/dist/services/requestContextService.js +15 -0
  66. package/dist/services/requestContextService.js.map +1 -1
  67. package/dist/services/serverConfigEnvironment.js +2 -1
  68. package/dist/services/serverConfigEnvironment.js.map +1 -1
  69. package/dist/services/sseService.js +58 -6
  70. package/dist/services/sseService.js.map +1 -1
  71. package/dist/services/templateService.js +11 -5
  72. package/dist/services/templateService.js.map +1 -1
  73. package/dist/services/userService.js +5 -1
  74. package/dist/services/userService.js.map +1 -1
  75. package/dist/utils/groupAccess.js +6 -4
  76. package/dist/utils/groupAccess.js.map +1 -1
  77. package/dist/utils/groupKeyScope.js +11 -5
  78. package/dist/utils/groupKeyScope.js.map +1 -1
  79. package/dist/utils/migration.js +5 -0
  80. package/dist/utils/migration.js.map +1 -1
  81. package/dist/utils/oauthBearer.js +1 -0
  82. package/dist/utils/oauthBearer.js.map +1 -1
  83. package/dist/utils/oauthServerMetadata.js +21 -0
  84. package/dist/utils/oauthServerMetadata.js.map +1 -1
  85. package/dist/utils/serverConfigPersistence.js +16 -1
  86. package/dist/utils/serverConfigPersistence.js.map +1 -1
  87. package/dist/utils/serverConfigValidation.js +1 -0
  88. package/dist/utils/serverConfigValidation.js.map +1 -1
  89. package/dist/utils/settingsSync.js +3 -0
  90. package/dist/utils/settingsSync.js.map +1 -1
  91. package/frontend/dist/assets/{ActivityPage-C8Zj4FeE.js → ActivityPage-Bi-TjKez.js} +2 -2
  92. package/frontend/dist/assets/{ActivityPage-C8Zj4FeE.js.map → ActivityPage-Bi-TjKez.js.map} +1 -1
  93. package/frontend/dist/assets/{ConfirmDialog-BYdfb115.js → ConfirmDialog-BJpzQmMw.js} +2 -2
  94. package/frontend/dist/assets/{ConfirmDialog-BYdfb115.js.map → ConfirmDialog-BJpzQmMw.js.map} +1 -1
  95. package/frontend/dist/assets/CredentialsPage-C4Ucer3d.js +2 -0
  96. package/frontend/dist/assets/CredentialsPage-C4Ucer3d.js.map +1 -0
  97. package/frontend/dist/assets/{Dashboard-CCiZcGi4.js → Dashboard-C_2KkuoD.js} +2 -2
  98. package/frontend/dist/assets/{Dashboard-CCiZcGi4.js.map → Dashboard-C_2KkuoD.js.map} +1 -1
  99. package/frontend/dist/assets/{DeleteDialog-BaCsEkJA.js → DeleteDialog-BoMYLx3J.js} +2 -2
  100. package/frontend/dist/assets/{DeleteDialog-BaCsEkJA.js.map → DeleteDialog-BoMYLx3J.js.map} +1 -1
  101. package/frontend/dist/assets/{EndpointCopy-CmKx4RVL.js → EndpointCopy-DITVC2YQ.js} +2 -2
  102. package/frontend/dist/assets/{EndpointCopy-CmKx4RVL.js.map → EndpointCopy-DITVC2YQ.js.map} +1 -1
  103. package/frontend/dist/assets/GroupsPage-sE6YJyuK.js +33 -0
  104. package/frontend/dist/assets/GroupsPage-sE6YJyuK.js.map +1 -0
  105. package/frontend/dist/assets/{LoginPage-Hn1uu0vB.js → LoginPage-CFsd_nY-.js} +2 -2
  106. package/frontend/dist/assets/{LoginPage-Hn1uu0vB.js.map → LoginPage-CFsd_nY-.js.map} +1 -1
  107. package/frontend/dist/assets/{LogsPage-JMCtTjCv.js → LogsPage-BxZuGDuc.js} +2 -2
  108. package/frontend/dist/assets/{LogsPage-JMCtTjCv.js.map → LogsPage-BxZuGDuc.js.map} +1 -1
  109. package/frontend/dist/assets/MarketPage-CDBs4vMb.js +2 -0
  110. package/frontend/dist/assets/{MarketPage-Bvi1KESo.js.map → MarketPage-CDBs4vMb.js.map} +1 -1
  111. package/frontend/dist/assets/{OAuthConsentPage-DofQEZAU.js → OAuthConsentPage-BN_ucViM.js} +2 -2
  112. package/frontend/dist/assets/{OAuthConsentPage-DofQEZAU.js.map → OAuthConsentPage-BN_ucViM.js.map} +1 -1
  113. package/frontend/dist/assets/{Pagination-D99WHhBx.js → Pagination-S-7lzy59.js} +2 -2
  114. package/frontend/dist/assets/{Pagination-D99WHhBx.js.map → Pagination-S-7lzy59.js.map} +1 -1
  115. package/frontend/dist/assets/{PromptsPage-B-8vczAR.js → PromptsPage-Bl3ySXGK.js} +2 -2
  116. package/frontend/dist/assets/{PromptsPage-B-8vczAR.js.map → PromptsPage-Bl3ySXGK.js.map} +1 -1
  117. package/frontend/dist/assets/{ResourcesPage-DLAIatoG.js → ResourcesPage-BOzQkQ92.js} +2 -2
  118. package/frontend/dist/assets/{ResourcesPage-DLAIatoG.js.map → ResourcesPage-BOzQkQ92.js.map} +1 -1
  119. package/frontend/dist/assets/{ServersPage-wVLsTL_f.js → ServersPage-DHYwQ5AM.js} +5 -5
  120. package/frontend/dist/assets/{ServersPage-wVLsTL_f.js.map → ServersPage-DHYwQ5AM.js.map} +1 -1
  121. package/frontend/dist/assets/SettingsPage-CSJ35jlM.js +14 -0
  122. package/frontend/dist/assets/SettingsPage-CSJ35jlM.js.map +1 -0
  123. package/frontend/dist/assets/{StatusDot-00-sTQKv.js → StatusDot-NSjojGCy.js} +2 -2
  124. package/frontend/dist/assets/{StatusDot-00-sTQKv.js.map → StatusDot-NSjojGCy.js.map} +1 -1
  125. package/frontend/dist/assets/{ToggleGroup-CtWBng3r.js → ToggleGroup-BIZWpNzm.js} +2 -2
  126. package/frontend/dist/assets/{ToggleGroup-CtWBng3r.js.map → ToggleGroup-BIZWpNzm.js.map} +1 -1
  127. package/frontend/dist/assets/UserGroupSelection-CN0weGXJ.js +2 -0
  128. package/frontend/dist/assets/UserGroupSelection-CN0weGXJ.js.map +1 -0
  129. package/frontend/dist/assets/UsersPage-DC51v2b8.js +2 -0
  130. package/frontend/dist/assets/UsersPage-DC51v2b8.js.map +1 -0
  131. package/frontend/dist/assets/{clipboard-2RRFM-q8.js → clipboard-ik5YV95M.js} +2 -2
  132. package/frontend/dist/assets/{clipboard-2RRFM-q8.js.map → clipboard-ik5YV95M.js.map} +1 -1
  133. package/frontend/dist/assets/{costRevision-Ntl7VtWo.js → costRevision-Bxov9_vH.js} +2 -2
  134. package/frontend/dist/assets/{costRevision-Ntl7VtWo.js.map → costRevision-Bxov9_vH.js.map} +1 -1
  135. package/frontend/dist/assets/framework-vendor-D0S_ys6r.js +61 -0
  136. package/frontend/dist/assets/framework-vendor-D0S_ys6r.js.map +1 -0
  137. package/frontend/dist/assets/{i18n-vendor-DVmjrzgW.js → i18n-vendor-COTriSc6.js} +2 -2
  138. package/frontend/dist/assets/{i18n-vendor-DVmjrzgW.js.map → i18n-vendor-COTriSc6.js.map} +1 -1
  139. package/frontend/dist/assets/{icons-vendor-CyAS6fj0.js → icons-vendor-DZjjGrOu.js} +2 -2
  140. package/frontend/dist/assets/{icons-vendor-CyAS6fj0.js.map → icons-vendor-DZjjGrOu.js.map} +1 -1
  141. package/frontend/dist/assets/index-6AyPtx0A.js +3 -0
  142. package/frontend/dist/assets/index-6AyPtx0A.js.map +1 -0
  143. package/frontend/dist/assets/{resourceService-BB4UM6IQ.js → resourceService-DMzCAZ0B.js} +2 -2
  144. package/frontend/dist/assets/{resourceService-BB4UM6IQ.js.map → resourceService-DMzCAZ0B.js.map} +1 -1
  145. package/frontend/dist/assets/{useCostData-C3XnQyUj.js → useCostData-CcFSYViI.js} +2 -2
  146. package/frontend/dist/assets/{useCostData-C3XnQyUj.js.map → useCostData-CcFSYViI.js.map} +1 -1
  147. package/frontend/dist/assets/variableDetection-CbYSa1ka.js +80 -0
  148. package/frontend/dist/assets/variableDetection-CbYSa1ka.js.map +1 -0
  149. package/frontend/dist/index.html +4 -4
  150. package/package.json +2 -2
  151. package/frontend/dist/assets/CredentialsPage-BnzqPYjg.js +0 -2
  152. package/frontend/dist/assets/CredentialsPage-BnzqPYjg.js.map +0 -1
  153. package/frontend/dist/assets/GroupsPage-DHgQeVHy.js +0 -33
  154. package/frontend/dist/assets/GroupsPage-DHgQeVHy.js.map +0 -1
  155. package/frontend/dist/assets/MarketPage-Bvi1KESo.js +0 -2
  156. package/frontend/dist/assets/SettingsPage-DkfXDE5_.js +0 -14
  157. package/frontend/dist/assets/SettingsPage-DkfXDE5_.js.map +0 -1
  158. package/frontend/dist/assets/UsersPage-BtdFWcVD.js +0 -2
  159. package/frontend/dist/assets/UsersPage-BtdFWcVD.js.map +0 -1
  160. package/frontend/dist/assets/framework-vendor-CQFm9vKd.js +0 -61
  161. package/frontend/dist/assets/framework-vendor-CQFm9vKd.js.map +0 -1
  162. package/frontend/dist/assets/index-CkSmxNPW.js +0 -3
  163. package/frontend/dist/assets/index-CkSmxNPW.js.map +0 -1
  164. package/frontend/dist/assets/variableDetection-BUXwrSop.js +0 -18
  165. package/frontend/dist/assets/variableDetection-BUXwrSop.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"GroupsPage-DHgQeVHy.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 { 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' | '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 [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[] }>(\n `/groups/${encodeURIComponent(groupId)}/share-candidates`,\n )\n .then((result) => {\n if (cancelled) return;\n if (result.success && Array.isArray(result.data)) setUsers(result.data);\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 <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 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 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 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 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","loading","setLoading","error","setError","isAdvancedExpanded","setIsAdvancedExpanded","useEffect","cancelled","apiGet","result","candidates","username","selectedUsers","allCandidatesSelected","noCandidatesSelected","toggleSharedUser","nextSelected","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,2 +0,0 @@
1
- import{r as t,j as e,d as He,b as We,i as _e}from"./framework-vendor-CQFm9vKd.js";import{h as J,l as ve,a as je,k as Fe}from"./index-CkSmxNPW.js";import{u as ne}from"./i18n-vendor-DVmjrzgW.js";import{g as Ne,a as ke,d as Oe,s as he}from"./variableDetection-BUXwrSop.js";import{C as Se,a0 as Qe,a5 as qe,a7 as Ge,l as Je,X as Xe,G as Ye,n as Ze}from"./icons-vendor-CyAS6fj0.js";import{P as Ke}from"./Pagination-D99WHhBx.js";import"./contextCost-CilWqGWT.js";const es=()=>{const{t:s}=ne(),[f,v]=t.useState([]),[d,m]=t.useState([]),[o,a]=t.useState([]),[A,p]=t.useState([]),[i,D]=t.useState(""),[P,U]=t.useState(""),[M,H]=t.useState(""),[I,C]=t.useState(!0),[F,S]=t.useState(null),[z,O]=t.useState(null),[V,T]=t.useState([]),[Q,$]=t.useState(1),[w,q]=t.useState(9),[k,K]=t.useState(1),B=t.useCallback(async()=>{try{C(!0);const r=await J("/market/servers");r&&r.success&&Array.isArray(r.data)?(m(r.data),E(r.data,Q)):(console.error("Invalid market servers data format",{data:r}),S(s("market.fetchError")))}catch(r){console.error("Error fetching market servers",{err:r}),S(r instanceof Error?r.message:String(r))}finally{C(!1)}},[s]),E=t.useCallback((r,l,G=w)=>{const se=r.length,_=Math.ceil(se/G);K(_);const Y=Math.max(1,Math.min(l,_));Y!==l&&$(Y);const ee=(Y-1)*G,re=r.slice(ee,ee+G);v(re)},[w]),y=t.useCallback(r=>{$(r),E(d,r,w)},[d,E,w]),n=t.useCallback(async()=>{try{const r=await J("/market/categories");r&&r.success&&Array.isArray(r.data)?a(r.data):console.error("Invalid categories data format",{data:r})}catch(r){console.error("Error fetching categories",{err:r})}},[]),x=t.useCallback(async()=>{try{const r=await J("/market/tags");r&&r.success&&Array.isArray(r.data)?p(r.data):console.error("Invalid tags data format",{data:r})}catch(r){console.error("Error fetching tags",{err:r})}},[]),g=t.useCallback(async r=>{try{C(!0);const l=await J(`/market/servers/${r}`);return l&&l.success&&l.data?(O(l.data),l.data):(console.error("Invalid market server data format",{name:r,data:l}),S(s("market.serverNotFound")),null)}catch(l){return console.error("Error fetching market server",{name:r,err:l}),S(l instanceof Error?l.message:String(l)),null}finally{C(!1)}},[s]),N=t.useCallback(async r=>{try{if(C(!0),H(r),!r.trim()){B();return}const l=await J(`/market/servers/search?query=${encodeURIComponent(r)}`);l&&l.success&&Array.isArray(l.data)?(m(l.data),$(1),E(l.data,1)):(console.error("Invalid market search results format",{query:r,data:l}),S(s("market.searchError")))}catch(l){console.error("Error searching market servers",{query:r,err:l}),S(l instanceof Error?l.message:String(l))}finally{C(!1)}},[s,d,E,B]),W=t.useCallback(async r=>{try{if(C(!0),D(r),U(""),!r){B();return}const l=await J(`/market/categories/${encodeURIComponent(r)}`);l&&l.success&&Array.isArray(l.data)?(m(l.data),$(1),E(l.data,1)):(console.error("Invalid market category filter results format",{category:r,data:l}),S(s("market.filterError")))}catch(l){console.error("Error filtering market servers by category",{category:r,err:l}),S(l instanceof Error?l.message:String(l))}finally{C(!1)}},[s,B,E]),R=t.useCallback(async r=>{try{if(C(!0),U(r),D(""),!r){B();return}const l=await J(`/market/tags/${encodeURIComponent(r)}`);l&&l.success&&Array.isArray(l.data)?(m(l.data),$(1),E(l.data,1)):(console.error("Invalid market tag filter results format",{tag:r,data:l}),S(s("market.tagFilterError")))}catch(l){console.error("Error filtering market servers by tag",{tag:r,err:l}),S(l instanceof Error?l.message:String(l))}finally{C(!1)}},[s,B,E]),X=t.useCallback(async()=>{try{const r=await J("/servers");if(r&&r.success&&Array.isArray(r.data)){const l=r.data.map(G=>G.name);T(l)}}catch(r){console.error("Error fetching installed servers",{err:r})}},[]),c=t.useCallback(r=>V.includes(r),[V]),b=t.useCallback(async(r,l)=>{var G,se;try{const _=(G=r.installations)!=null&&G.npm?"npm":Object.keys(r.installations||{}).length>0?Object.keys(r.installations)[0]:null;if(!_||!((se=r.installations)!=null&&se[_]))return S(s("market.noInstallationMethod")),!1;const Y=r.installations[_],ee={name:r.name,config:l.type==="stdio"?{command:l.command||Y.command||"",args:l.args||Y.args||[],env:{...Y.env,...l.env}}:l},re=await ve("/servers",ee);if(!re.success)throw new Error(re.message||"Failed to install server");return await X(),!0}catch(_){return console.error("Error installing market server",{serverName:r.name,err:_}),S(_ instanceof Error?_.message:String(_)),!1}},[s,X]),u=t.useCallback(r=>{q(r),$(1),E(d,1,r)},[d,E]);return t.useEffect(()=>{B(),n(),x(),X()},[B,n,x,X]),{servers:f,allServers:d,categories:o,tags:A,selectedCategory:i,selectedTag:P,searchQuery:M,loading:I,error:F,setError:S,currentServer:z,fetchMarketServers:B,fetchServerByName:g,searchServers:N,filterByCategory:W,filterByTag:R,installServer:b,currentPage:Q,totalPages:k,serversPerPage:w,changePage:y,changeServersPerPage:u,isServerInstalled:c}},ss=()=>{const{t:s}=ne(),[f,v]=t.useState([]),[d,m]=t.useState([]),[o,a]=t.useState(!0),[A,p]=t.useState(null),[i,D]=t.useState(""),[P,U]=t.useState(1),[M,H]=t.useState(9),[I,C]=t.useState(null),[F,S]=t.useState(!1),[z,O]=t.useState([]),[V]=t.useState(1),T=t.useCallback(async(n,x)=>{try{a(!0),p(null);const g=new URLSearchParams;g.append("limit",M.toString()),n&&g.append("cursor",n);const N=x!==void 0?x:i;N.trim()&&g.append("search",N.trim());const W=await J(`/registry/servers?${g.toString()}`);if(W&&W.success&&W.data){const R=W.data;if(R.servers&&Array.isArray(R.servers)){v(R.servers);const X=R.metadata.count===M&&!!R.metadata.nextCursor;S(X),C(R.metadata.nextCursor||null),m(n?c=>[...c,...R.servers]:R.servers)}else console.error("Invalid registry servers data format",{data:R}),p(s("registry.fetchError"))}else p(s("registry.fetchError"))}catch(g){console.error("Error fetching registry servers",{cursor:n,search:x,err:g});const N=g instanceof Error?g.message:String(g);p(N)}finally{a(!1)}},[s,M]),Q=t.useCallback(async()=>{if(!F||!I)return;const n=z[z.length-1]||"";O(x=>[...x,n]),U(x=>x+1),await T(I,i)},[F,I,z,i,T]),$=t.useCallback(async()=>{if(P<=1)return;const n=[...z];n.pop();const x=n[n.length-1];O(n),U(g=>g-1),await T(x||void 0,i)},[P,z,i,T]),w=t.useCallback(async n=>{n!==P&&(n>P&&F?await Q():n<P&&P>1&&await $())},[P,F,Q,$]),q=t.useCallback(async n=>{H(n),U(1),O([]),m([]),await T(void 0,i)},[i,T]),k=t.useCallback(async n=>{try{a(!0),p(null);const x=encodeURIComponent(n),g=await J(`/registry/servers/versions?serverName=${x}`);if(g&&g.success&&g.data){const N=g.data;return N.servers&&Array.isArray(N.servers)&&N.servers.length>0?N.servers[0]:(console.error("Invalid registry server data format",{serverName:n,data:N}),p(s("registry.serverNotFound")),null)}else return p(s("registry.serverNotFound")),null}catch(x){console.error("Error fetching registry server",{serverName:n,err:x});const g=x instanceof Error?x.message:String(x);return p(g),null}finally{a(!1)}},[s]),K=t.useCallback(async n=>{try{p(null);const x=encodeURIComponent(n),g=await J(`/registry/servers/versions?serverName=${x}`);if(g&&g.success&&g.data){const N=g.data;return N.servers&&Array.isArray(N.servers)?N.servers:(console.error("Invalid registry server versions data format",{serverName:n,data:N}),[])}else return[]}catch(x){console.error("Error fetching versions for registry server",{serverName:n,err:x});const g=x instanceof Error?x.message:String(x);return p(g),[]}},[]),B=t.useCallback(async(n,x)=>{try{p(null);const g=encodeURIComponent(n),N=encodeURIComponent(x),W=await J(`/registry/servers/version?serverName=${g}&version=${N}`);if(W&&W.success&&W.data){const R=W.data;return R&&R.server?R:(console.error("Invalid registry server version data format",{serverName:n,version:x,data:R}),null)}else return null}catch(g){console.error("Error fetching specific registry server version",{serverName:n,version:x,err:g});const N=g instanceof Error?g.message:String(g);return p(N),null}},[]),E=t.useCallback(async n=>{console.log("Searching registry servers",{query:n}),D(n),U(1),O([]),m([]),await T(void 0,n)},[T]),y=t.useCallback(async()=>{D(""),U(1),O([]),m([]),await T(void 0,"")},[T]);return t.useEffect(()=>{T(void 0,i)},[]),{servers:f,allServers:d,loading:o,error:A,setError:p,searchQuery:i,searchServers:E,clearSearch:y,fetchServerByName:k,fetchServerVersions:K,fetchServerVersion:B,currentPage:P,totalPages:V,hasNextPage:F,hasPreviousPage:P>1,changePage:w,goToNextPage:Q,goToPreviousPage:$,serversPerPage:M,changeServersPerPage:q}},rs=s=>s.split(" ").map(f=>f.charAt(0)).join("").toUpperCase().slice(0,2),ts=({server:s,onClick:f})=>{var o,a,A;const{t:v}=ne(),d=(s.tags||[]).slice(0,3),m=(o=s.categories)==null?void 0:o[0];return e.jsxs("div",{className:"hub-card flex flex-col cursor-pointer transition-colors h-full overflow-hidden",onClick:()=>f(s),onMouseEnter:p=>p.currentTarget.style.borderColor="var(--hub-ink-2)",onMouseLeave:p=>p.currentTarget.style.borderColor="var(--hub-line)",children:[e.jsxs("div",{className:"p-3.5 flex-1 flex flex-col gap-2.5",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"hub-mono",style:{width:28,height:28,borderRadius:7,background:"var(--hub-ink)",color:"var(--hub-bg)",display:"grid",placeItems:"center",fontWeight:600,fontSize:13,flexShrink:0},children:rs(s.display_name||s.name)[0]||"?"}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"truncate",style:{fontSize:14,fontWeight:500,letterSpacing:"-0.01em"},children:s.display_name}),s.is_official&&e.jsxs("span",{className:"inline-flex items-center gap-0.5",style:{fontSize:10,color:"var(--hub-accent)",background:"var(--hub-accent-soft)",padding:"0 5px",height:16,borderRadius:3,fontWeight:500},children:[e.jsx(Se,{size:9,strokeWidth:2.5}),v("market.official")]})]}),e.jsxs("div",{className:"hub-mono truncate",style:{fontSize:11,color:"var(--hub-ink-3)"},children:["@",((a=s.author)==null?void 0:a.name)||v("market.unknown")]})]})]}),e.jsx("div",{className:"flex-1 line-clamp-2",style:{fontSize:12.5,color:"var(--hub-ink-2)",lineHeight:1.5},children:s.description}),d.length>0&&e.jsx("div",{className:"flex gap-1 flex-wrap",children:d.map(p=>e.jsxs("span",{className:"hub-tag",style:{background:"oklch(0.96 0.04 145)",color:"oklch(0.4 0.1 145)",border:0},children:["#",p]},p))})]}),e.jsx("div",{className:"flex items-center justify-between px-3.5 py-2",style:{borderTop:"1px solid var(--hub-line-2)",background:"var(--hub-bg-2)"},children:e.jsxs("div",{className:"hub-mono flex items-center gap-3",style:{fontSize:11.5,color:"var(--hub-ink-3)"},children:[e.jsxs("span",{className:"inline-flex items-center gap-1",children:[e.jsx(Qe,{size:11}),((A=s.tools)==null?void 0:A.length)??0," ",v("server.tools").toLowerCase()]}),m&&e.jsx("span",{className:"truncate",children:m})]})})]})},as=({server:s,onBack:f,onInstall:v,installing:d=!1,isInstalled:m=!1})=>{var k,K,B,E;const{t:o}=ne(),{auth:a}=je(),A=Ne({type:"stdio"},(k=a.user)==null?void 0:k.isAdmin),[p,i]=t.useState(!1),[D,P]=t.useState(null),[U,M]=t.useState(!1),[H,I]=t.useState(null),[C,F]=t.useState([]),S=()=>m?{className:"bg-green-600 cursor-default px-4 py-2 rounded text-sm font-medium text-white",disabled:!0,text:o("market.installed")}:d?{className:"bg-gray-400 cursor-not-allowed px-4 py-2 rounded text-sm font-medium text-white",disabled:!0,text:o("market.installing")}:{className:`hub-btn primary ${A?"opacity-50 cursor-not-allowed":""}`,disabled:!!A,text:o("market.install")},z=()=>{i(!p),P(null),M(!1),I(null)},O=async()=>{H&&(await V(H),M(!1),I(null))},V=async y=>{try{P(null),v(s,y.config),i(!1)}catch(n){console.error("Error installing server:",n),P(o("errors.serverInstall"))}},T=()=>{!m&&!A&&z()},Q=()=>{if(!s.installations)return;if(s.installations.npm)return s.installations.npm;if(s.installations.uvx)return s.installations.uvx;if(s.installations.default)return s.installations.default;const y=Object.keys(s.installations);if(y.length>0)return s.installations[y[0]]},$=async y=>{try{const n=Oe(y);n.length>0?(F(n),I(y),M(!0)):await V(y)}catch(n){console.error("Error processing server installation:",n),P(o("errors.serverInstall"))}},w=S(),q=Q();return e.jsxs("div",{className:"bg-white dark:bg-gray-800 rounded-lg shadow-md p-6",children:[e.jsx("div",{className:"mb-4",children:e.jsxs("button",{onClick:f,className:"text-gray-600 hover:text-gray-900 flex items-center",children:[e.jsx("svg",{className:"h-5 w-5 mr-1",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M9.707 16.707a1 1 0 01-1.414 0l-6-6a1 1 0 010-1.414l6-6a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l4.293 4.293a1 1 0 010 1.414z",clipRule:"evenodd"})}),o("market.backToList")]})}),e.jsxs("div",{className:"flex justify-between items-start mb-4",children:[e.jsx("div",{children:e.jsxs("h2",{className:"text-2xl font-bold text-gray-900 flex items-center flex-wrap",children:[s.display_name,e.jsxs("span",{className:"text-sm font-normal text-gray-500 ml-2",children:["(",s.name,")"]}),e.jsxs("span",{className:"text-sm font-normal text-gray-600 ml-4",children:[o("market.author"),": ",((K=s.author)==null?void 0:K.name)||o("market.unknown")," •"," ",o("market.license"),": ",s.license," •",e.jsx("a",{href:s.repository.url,target:"_blank",rel:"noopener noreferrer",className:"text-blue-500 hover:underline ml-1",children:o("market.repository")})]})]})}),e.jsxs("div",{className:"flex items-center",children:[s.is_official&&e.jsx("span",{className:"bg-blue-100 text-blue-800 dark:text-blue-300 dark:bg-blue-900/40 dark:text-blue-300 text-sm font-normal px-4 py-2 rounded mr-2 flex items-center label-primary",children:o("market.official")}),e.jsx("button",{onClick:T,disabled:w.disabled,className:w.className,children:w.text})]})]}),A&&e.jsx("p",{role:"status",className:"text-sm text-amber-700 dark:text-amber-300 mb-4",children:o(A)}),e.jsx("p",{className:"text-gray-700 mb-6",children:s.description}),e.jsxs("div",{className:"mb-6",children:[e.jsxs("h3",{className:"text-lg font-semibold mb-3",children:[o("market.categories")," & ",o("market.tags")]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[(B=s.categories)==null?void 0:B.map((y,n)=>e.jsx("span",{className:"bg-gray-100 dark:bg-gray-800 text-gray-800 px-3 py-1 rounded",children:y},`cat-${n}`)),s.tags&&s.tags.map((y,n)=>e.jsxs("span",{className:"bg-gray-100 dark:bg-gray-800 text-green-700 dark:text-green-300 px-2 py-1 rounded text-sm",children:["#",y]},`tag-${n}`))]})]}),s.arguments&&Object.keys(s.arguments).length>0&&e.jsxs("div",{className:"mb-6",children:[e.jsx("h3",{className:"text-lg font-semibold mb-3",children:o("market.arguments")}),e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"min-w-full divide-y divide-gray-200 dark:divide-gray-700",children:[e.jsx("thead",{className:"bg-gray-50 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider whitespace-nowrap",children:o("market.argumentName")}),e.jsx("th",{className:"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider whitespace-nowrap",children:o("market.description")}),e.jsx("th",{className:"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider whitespace-nowrap",children:o("market.required")}),e.jsx("th",{className:"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider whitespace-nowrap",children:o("market.example")})]})}),e.jsx("tbody",{className:"bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700",children:Object.entries(s.arguments).map(([y,n],x)=>e.jsxs("tr",{children:[e.jsx("td",{className:"px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900",children:y}),e.jsx("td",{className:"px-6 py-4 text-sm text-gray-500",children:n.description}),e.jsx("td",{className:"px-6 py-4 whitespace-nowrap text-sm text-gray-500",children:n.required?e.jsx("span",{className:"text-green-600",children:"✓"}):e.jsx("span",{className:"text-gray-600",children:"✗"})}),e.jsx("td",{className:"px-6 py-4 whitespace-nowrap text-sm text-gray-500",children:e.jsx("code",{className:"bg-gray-100 dark:bg-gray-800 px-2 py-1 rounded",children:n.example})})]},x))})]})})]}),e.jsxs("div",{className:"mb-6",children:[e.jsx("h3",{className:"text-lg font-semibold mb-3",children:o("market.tools")}),e.jsx("div",{className:"space-y-4",children:(E=s.tools)==null?void 0:E.map((y,n)=>e.jsxs("div",{className:"border border-gray-200 dark:border-gray-700 rounded p-4",children:[e.jsxs("h4",{className:"font-medium mb-2",children:[y.name,e.jsx("button",{type:"button",onClick:()=>{const x=document.getElementById(`schema-${n}`);x&&x.classList.toggle("hidden")},className:"text-sm text-blue-500 font-normal hover:underline focus:outline-none ml-2",children:o("market.viewSchema")})]}),e.jsx("p",{className:"text-gray-600 mb-2",children:y.description}),e.jsx("div",{className:"mt-2",children:e.jsx("pre",{id:`schema-${n}`,className:"hidden bg-gray-50 dark:bg-gray-800 p-3 rounded text-sm overflow-auto mt-2",children:JSON.stringify(y.inputSchema,null,2)})})]},n))})]}),s.examples&&s.examples.length>0&&e.jsxs("div",{className:"mb-6",children:[e.jsx("h3",{className:"text-lg font-semibold mb-3",children:o("market.examples")}),e.jsx("div",{className:"space-y-4",children:s.examples.map((y,n)=>e.jsxs("div",{className:"border border-gray-200 dark:border-gray-700 rounded p-4",children:[e.jsx("h4",{className:"font-medium mb-2",children:y.title}),e.jsx("p",{className:"text-gray-600 mb-2",children:y.description}),e.jsx("pre",{className:"bg-gray-50 dark:bg-gray-800 p-3 rounded text-sm overflow-auto",children:y.prompt})]},n))})]}),e.jsx("div",{className:"mt-6 flex justify-end",children:e.jsx("button",{onClick:T,disabled:w.disabled,className:w.className,children:w.text})}),p&&e.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:e.jsx(ke,{onSubmit:$,onCancel:z,modalTitle:o("market.installServer",{name:s.display_name}),formError:D,initialData:{name:s.name,status:"disconnected",config:q?{command:q.command||"",args:q.args||[],env:q.env||{}}:void 0}})}),U&&e.jsx("div",{className:"fixed inset-0 bg-black/50 z-[60] flex items-center justify-center p-4",children:e.jsxs("div",{className:"hub-card p-6 w-full max-w-md",children:[e.jsx("h3",{className:"text-lg font-semibold text-gray-900 mb-4",children:o("server.confirmVariables")}),e.jsx("p",{className:"text-gray-600 mb-4",children:o("server.variablesDetected")}),e.jsx("div",{className:"bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-700/60 rounded p-3 mb-4",children:e.jsxs("div",{className:"flex items-start",children:[e.jsx("div",{className:"flex-shrink-0",children:e.jsx("svg",{className:"h-5 w-5 text-yellow-400",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z",clipRule:"evenodd"})})}),e.jsxs("div",{className:"ml-3",children:[e.jsxs("h4",{className:"text-sm font-medium text-yellow-800 dark:text-yellow-300",children:[o("server.detectedVariables"),":"]}),e.jsx("ul",{className:"mt-1 text-sm text-yellow-700 dark:text-yellow-300",children:C.map((y,n)=>e.jsxs("li",{className:"font-mono",children:["$",`{${y}}`]},n))})]})]})}),e.jsx("p",{className:"text-gray-600 text-sm mb-6",children:o("market.confirmVariablesMessage")}),e.jsxs("div",{className:"flex justify-end space-x-3",children:[e.jsx("button",{onClick:()=>{M(!1),I(null)},className:"hub-btn",children:o("common.cancel")}),e.jsx("button",{onClick:O,className:"hub-btn primary",children:o("market.confirmAndInstall")})]})]})})]})},ns=s=>{if(!s)return"";try{const f=new Date(s),v=f.getFullYear(),d=(f.getMonth()+1).toString().padStart(2,"0"),m=f.getDate().toString().padStart(2,"0");return`${v}/${d}/${m}`}catch{return""}},ls=({serverEntry:s,onClick:f})=>{var M,H;const{t:v}=ne(),{server:d,_meta:m}=s,o=m==null?void 0:m["io.modelcontextprotocol.registry/official"],a=o==null?void 0:o.isLatest,A=o==null?void 0:o.publishedAt,p=o==null?void 0:o.updatedAt,i=((M=d.packages)==null?void 0:M.length)||0,D=((H=d.remotes)==null?void 0:H.length)||0,P=d.description?d.description.length<=150?d.description:d.description.slice(0,150)+"...":v("registry.noDescription"),U=d.icons&&d.icons.length>0?d.icons.find(C=>!C.theme||C.theme==="light")||d.icons[0]:null;return e.jsxs("div",{className:"hub-card flex flex-col cursor-pointer transition-colors h-full overflow-hidden",onClick:()=>f(s),onMouseEnter:I=>I.currentTarget.style.borderColor="var(--hub-ink-2)",onMouseLeave:I=>I.currentTarget.style.borderColor="var(--hub-line)",children:[e.jsxs("div",{className:"p-3.5 flex-1 flex flex-col gap-2.5",children:[e.jsxs("div",{className:"flex items-start gap-2",children:[U?e.jsx("img",{src:U.src,alt:d.title||d.name,className:"rounded-md object-cover flex-shrink-0",style:{width:28,height:28},onError:I=>{I.currentTarget.style.display="none"}}):e.jsx("div",{className:"hub-mono flex-shrink-0",style:{width:28,height:28,borderRadius:7,background:"var(--hub-ink)",color:"var(--hub-bg)",display:"grid",placeItems:"center",fontWeight:600,fontSize:13},children:d.name.charAt(0).toUpperCase()}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"truncate",style:{fontSize:14,fontWeight:500,letterSpacing:"-0.01em"},children:d.title||d.name}),a&&e.jsxs("span",{className:"inline-flex items-center gap-0.5 flex-shrink-0",style:{fontSize:10,color:"oklch(0.4 0.13 145)",background:"oklch(0.95 0.05 145)",padding:"0 5px",height:16,borderRadius:3,fontWeight:500},children:[e.jsx(Se,{size:9,strokeWidth:2.5}),v("registry.latest")]})]}),e.jsxs("div",{className:"hub-mono truncate",style:{fontSize:11,color:"var(--hub-ink-3)"},children:[d.name," · v",d.version]})]})]}),e.jsx("div",{className:"flex-1 line-clamp-2",style:{fontSize:12.5,color:"var(--hub-ink-2)",lineHeight:1.5},children:P})]}),e.jsxs("div",{className:"flex items-center justify-between px-3.5 py-2",style:{borderTop:"1px solid var(--hub-line-2)",background:"var(--hub-bg-2)"},children:[e.jsxs("div",{className:"hub-mono flex items-center gap-3",style:{fontSize:11.5,color:"var(--hub-ink-3)"},children:[i>0&&e.jsxs("span",{className:"inline-flex items-center gap-1",children:[e.jsx(qe,{size:11}),i]}),D>0&&e.jsxs("span",{className:"inline-flex items-center gap-1",children:[e.jsx(Ge,{size:11}),D]}),(A||p)&&e.jsx("span",{children:ns(p||A)})]}),e.jsxs("span",{className:"hub-mono",style:{fontSize:11,color:"var(--hub-accent)"},children:[v("registry.viewDetails")," →"]})]})]})},is=({serverEntry:s,onBack:f,onInstall:v,installing:d=!1,isInstalled:m=!1,fetchVersions:o})=>{var X;const{t:a}=ne(),{auth:A}=je(),p=Ne({type:"stdio"},(X=A.user)==null?void 0:X.isAdmin),{server:i,_meta:D}=s,[P,U]=t.useState(i.version),[M,H]=t.useState([]),[I,C]=t.useState(!1),[F,S]=t.useState(!1),[z,O]=t.useState(null),[V,T]=t.useState(null),[Q,$]=t.useState(null),[w,q]=t.useState({packages:!0,remotes:!0,repository:!0}),k=D==null?void 0:D["io.modelcontextprotocol.registry/official"];t.useEffect(()=>{(async()=>{if(o){C(!0);try{const b=await o(i.name);H(b)}catch(b){console.error("Failed to load versions:",b)}finally{C(!1)}}})()},[i.name,o]);const B=i.icons&&i.icons.length>0?i.icons.find(b=>!b.theme||b.theme==="light")||i.icons[0]:null,E=c=>{if(!c)return"";try{return new Date(c).toLocaleDateString()}catch{return""}},y=c=>{q(b=>({...b,[c]:!b[c]}))},n=(c,b)=>{c==="package"&&p||(O(c),T(b),$(null),S(!0))},x=()=>{S(!1),$(null)},g=async c=>{try{if(!v||!V||!z)return;$(null);const b=c.config;v(i,b),S(!1)}catch(b){console.error("Error installing server:",b),$(a("errors.serverInstall"))}},N=()=>{if(!V||!z)return null;if(console.log("Building initial form data for:",V),z==="package"&&"identifier"in V){const c=V,b={};c.environmentVariables&&c.environmentVariables.forEach(r=>{b[r.name]=r.default||""});const u=os(c.registryType);return{name:he(i.name),status:"disconnected",config:{type:"stdio",command:u,args:cs(u,c),env:Object.keys(b).length>0?b:void 0}}}else if(z==="remote"&&"url"in V){const c=V,b={};c.headers&&c.headers.forEach(r=>{b[r.name]=r.default||r.value||""});const u=c.type==="sse"?"sse":"streamable-http";return{name:he(i.name),status:"disconnected",config:{type:u,url:c.url,headers:Object.keys(b).length>0?b:void 0}}}return null},W=(c,b)=>e.jsxs("div",{className:"border border-gray-200 dark:border-gray-700 rounded-lg p-4 mb-3 hover:border-blue-400 transition-colors",children:[e.jsxs("div",{className:"flex items-start justify-between mb-3",children:[e.jsxs("div",{className:"flex-1",children:[e.jsx("h4",{className:"font-medium text-gray-900",children:c.identifier}),c.version&&e.jsxs("p",{className:"text-sm text-gray-500",children:["Version: ",c.version]}),c.runtimeHint&&e.jsx("p",{className:"text-sm text-gray-600 mt-1",children:c.runtimeHint})]}),e.jsx("button",{onClick:()=>n("package",c),disabled:m||d||!!p,className:`px-4 py-2 rounded text-sm font-medium transition-colors ${m?"hub-btn cursor-default":d||p?"hub-btn cursor-not-allowed opacity-50":"hub-btn primary"}`,children:a(m?"registry.installed":d?"registry.installing":"registry.install")})]}),p&&e.jsx("p",{role:"status",className:"text-sm text-amber-700 dark:text-amber-300 mb-3",children:a(p)}),c.registryType&&e.jsxs("div",{className:"text-sm text-gray-600 mb-2",children:[e.jsx("span",{className:"font-medium",children:"Registry:"})," ",c.registryType]}),c.transport&&e.jsxs("div",{className:"text-sm text-gray-600 mb-2",children:[e.jsx("span",{className:"font-medium",children:"Transport:"})," ",c.transport.type,c.transport.url&&e.jsxs("span",{className:"ml-2 text-gray-500",children:["(",c.transport.url,")"]})]}),c.environmentVariables&&c.environmentVariables.length>0&&e.jsxs("div",{className:"mt-3 border-t border-gray-200 dark:border-gray-700 pt-3",children:[e.jsxs("h5",{className:"text-sm font-medium text-gray-700 mb-2",children:[a("registry.environmentVariables"),":"]}),e.jsx("div",{className:"space-y-2",children:c.environmentVariables.map((u,r)=>e.jsxs("div",{className:"text-sm",children:[e.jsxs("div",{className:"flex items-start",children:[e.jsx("span",{className:"font-mono text-gray-900 font-medium",children:u.name}),u.isRequired&&e.jsx("span",{className:"ml-2 inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-red-100 text-red-800",children:a("common.required")}),u.isSecret&&e.jsx("span",{className:"ml-2 inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-yellow-100 text-yellow-800",children:a("common.secret")})]}),u.description&&e.jsx("p",{className:"text-gray-600 mt-1",children:u.description}),u.default&&e.jsxs("p",{className:"text-gray-500 mt-1",children:[e.jsxs("span",{className:"font-medium",children:[a("common.default"),":"]})," ",e.jsx("span",{className:"font-mono",children:u.default})]})]},r))})]}),c.packageArguments&&c.packageArguments.length>0&&e.jsxs("div",{className:"mt-3 border-t border-gray-200 dark:border-gray-700 pt-3",children:[e.jsxs("h5",{className:"text-sm font-medium text-gray-700 mb-2",children:[a("registry.packageArguments"),":"]}),e.jsx("div",{className:"space-y-2",children:c.packageArguments.map((u,r)=>e.jsxs("div",{className:"text-sm",children:[e.jsxs("div",{className:"flex items-start",children:[e.jsx("span",{className:"font-mono text-gray-900 font-medium",children:u.name}),u.isRequired&&e.jsx("span",{className:"ml-2 inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-red-100 text-red-800",children:a("common.required")}),u.isSecret&&e.jsx("span",{className:"ml-2 inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-yellow-100 text-yellow-800",children:a("common.secret")}),u.isRepeated&&e.jsx("span",{className:"ml-2 inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-purple-100 text-purple-800 dark:bg-purple-900/40 dark:text-purple-300",children:a("common.repeated")})]}),u.description&&e.jsx("p",{className:"text-gray-600 mt-1",children:u.description}),u.type&&e.jsxs("p",{className:"text-gray-500 mt-1",children:[e.jsxs("span",{className:"font-medium",children:[a("common.type"),":"]})," ",e.jsx("span",{className:"font-mono",children:u.type})]}),u.default&&e.jsxs("p",{className:"text-gray-500 mt-1",children:[e.jsxs("span",{className:"font-medium",children:[a("common.default"),":"]})," ",e.jsx("span",{className:"font-mono",children:u.default})]}),u.value&&e.jsxs("p",{className:"text-gray-500 mt-1",children:[e.jsxs("span",{className:"font-medium",children:[a("common.value"),":"]})," ",e.jsx("span",{className:"font-mono",children:u.value})]}),u.valueHint&&e.jsxs("p",{className:"text-gray-500 mt-1",children:[e.jsxs("span",{className:"font-medium",children:[a("common.valueHint"),":"]})," ",e.jsx("span",{className:"font-mono",children:u.valueHint})]}),u.choices&&u.choices.length>0&&e.jsxs("p",{className:"text-gray-500 mt-1",children:[e.jsxs("span",{className:"font-medium",children:[a("common.choices"),":"]})," ",e.jsx("span",{className:"font-mono",children:u.choices.join(", ")})]})]},r))})]})]},b),R=(c,b)=>e.jsxs("div",{className:"border border-gray-200 dark:border-gray-700 rounded-lg p-4 mb-3 hover:border-blue-400 transition-colors",children:[e.jsxs("div",{className:"flex items-start justify-between mb-3",children:[e.jsxs("div",{className:"flex-1",children:[e.jsx("h4",{className:"font-medium text-gray-900",children:c.type}),e.jsx("p",{className:"text-sm text-gray-600 mt-1 break-all",children:c.url})]}),e.jsx("button",{onClick:()=>n("remote",c),disabled:m||d,className:`px-4 py-2 rounded text-sm font-medium transition-colors ${m?"hub-btn cursor-default":d?"hub-btn cursor-not-allowed opacity-50":"hub-btn primary"}`,children:a(m?"registry.installed":d?"registry.installing":"registry.install")})]}),c.headers&&c.headers.length>0&&e.jsxs("div",{className:"mt-3 border-t border-gray-200 dark:border-gray-700 pt-3",children:[e.jsxs("h5",{className:"text-sm font-medium text-gray-700 mb-2",children:[a("registry.headers"),":"]}),e.jsx("div",{className:"space-y-2",children:c.headers.map((u,r)=>e.jsxs("div",{className:"text-sm",children:[e.jsxs("div",{className:"flex items-start",children:[e.jsx("span",{className:"font-mono text-gray-900 font-medium",children:u.name}),u.isRequired&&e.jsx("span",{className:"ml-2 inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-red-100 text-red-800",children:a("common.required")}),u.isSecret&&e.jsx("span",{className:"ml-2 inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-yellow-100 text-yellow-800",children:a("common.secret")})]}),u.description&&e.jsx("p",{className:"text-gray-600 mt-1",children:u.description}),u.value&&e.jsxs("p",{className:"text-gray-500 mt-1",children:[e.jsxs("span",{className:"font-medium",children:[a("common.value"),":"]})," ",e.jsx("span",{className:"font-mono",children:u.value})]}),u.default&&e.jsxs("p",{className:"text-gray-500 mt-1",children:[e.jsxs("span",{className:"font-medium",children:[a("common.default"),":"]})," ",e.jsx("span",{className:"font-mono",children:u.default})]})]},r))})]})]},b);return e.jsxs("div",{className:"bg-white dark:bg-gray-800 shadow rounded-lg p-6",children:[e.jsxs("div",{className:"mb-6",children:[e.jsxs("button",{onClick:f,className:"flex items-center text-blue-600 hover:text-blue-800 mb-4 transition-colors",children:[e.jsx("svg",{className:"w-5 h-5 mr-2",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M15 19l-7-7 7-7"})}),a("registry.backToList")]}),e.jsxs("div",{className:"flex items-start space-x-4",children:[B?e.jsx("img",{src:B.src,alt:i.title,className:"w-20 h-20 rounded-lg object-cover flex-shrink-0",onError:c=>{c.currentTarget.style.display="none"}}):e.jsx("div",{className:"w-20 h-20 bg-gradient-to-br from-blue-500 to-purple-600 rounded-lg flex items-center justify-center text-white text-3xl font-semibold flex-shrink-0",children:"M"}),e.jsxs("div",{className:"flex-1",children:[e.jsx("h1",{className:"text-3xl font-bold text-gray-900 mb-2",children:i.name}),e.jsxs("div",{className:"flex flex-wrap gap-2 mb-3",children:[(k==null?void 0:k.isLatest)&&e.jsx("span",{className:"inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-green-100 text-green-800",children:a("registry.latest")}),e.jsxs("span",{className:"inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300",children:["v",i.version]}),(k==null?void 0:k.status)&&e.jsx("span",{className:"inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-gray-100 dark:bg-gray-800 text-gray-800",children:k.status}),e.jsxs("span",{className:"flex flex-wrap items-center gap-4 text-sm text-gray-600",children:[(k==null?void 0:k.publishedAt)&&e.jsxs("div",{children:[e.jsxs("span",{className:"font-medium",children:[a("registry.published"),":"]})," ",E(k.publishedAt)]}),(k==null?void 0:k.updatedAt)&&e.jsxs("div",{children:[e.jsxs("span",{className:"font-medium",children:[a("registry.updated"),":"]})," ",E(k.updatedAt)]})]})]})]})]})]}),e.jsxs("div",{className:"mb-6",children:[e.jsx("h2",{className:"text-xl font-semibold text-gray-900 mb-3",children:a("registry.description")}),e.jsx("p",{className:"text-gray-700 leading-relaxed whitespace-pre-wrap",children:i.description})]}),i.websiteUrl&&e.jsxs("div",{className:"mb-6",children:[e.jsx("h2",{className:"text-xl font-semibold text-gray-900 mb-3",children:a("registry.website")}),e.jsx("a",{href:i.websiteUrl,target:"_blank",rel:"noopener noreferrer",className:"text-blue-600 hover:text-blue-800 hover:underline",children:i.websiteUrl})]}),i.packages&&i.packages.length>0&&e.jsxs("div",{className:"mb-6",children:[e.jsxs("button",{onClick:()=>y("packages"),className:"flex items-center justify-between w-full text-xl font-semibold text-gray-900 mb-3 hover:text-blue-600 transition-colors",children:[e.jsxs("span",{children:[a("registry.packages")," (",i.packages.length,")"]}),e.jsx("svg",{className:`w-5 h-5 transform transition-transform ${w.packages?"rotate-180":""}`,fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})]}),w.packages&&e.jsx("div",{className:"space-y-3",children:i.packages.map(W)})]}),i.remotes&&i.remotes.length>0&&e.jsxs("div",{className:"mb-6",children:[e.jsxs("button",{onClick:()=>y("remotes"),className:"flex items-center justify-between w-full text-xl font-semibold text-gray-900 mb-3 hover:text-blue-600 transition-colors",children:[e.jsxs("span",{children:[a("registry.remotes")," (",i.remotes.length,")"]}),e.jsx("svg",{className:`w-5 h-5 transform transition-transform ${w.remotes?"rotate-180":""}`,fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})]}),w.remotes&&e.jsx("div",{className:"space-y-3",children:i.remotes.map(R)})]}),i.repository&&e.jsxs("div",{className:"mb-6",children:[e.jsxs("button",{onClick:()=>y("repository"),className:"flex items-center justify-between w-full text-xl font-semibold text-gray-900 mb-3 hover:text-blue-600 transition-colors",children:[e.jsx("span",{children:a("registry.repository")}),e.jsx("svg",{className:`w-5 h-5 transform transition-transform ${w.repository?"rotate-180":""}`,fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})]}),w.repository&&e.jsxs("div",{className:"border border-gray-200 dark:border-gray-700 rounded-lg p-4",children:[i.repository.url&&e.jsxs("div",{className:"mb-2",children:[e.jsx("span",{className:"font-medium text-gray-700",children:"URL:"})," ",e.jsx("a",{href:i.repository.url,target:"_blank",rel:"noopener noreferrer",className:"text-blue-600 hover:text-blue-800 hover:underline break-all",children:i.repository.url})]}),i.repository.source&&e.jsxs("div",{className:"mb-2",children:[e.jsx("span",{className:"font-medium text-gray-700",children:"Source:"})," ",i.repository.source]}),i.repository.subfolder&&e.jsxs("div",{className:"mb-2",children:[e.jsx("span",{className:"font-medium text-gray-700",children:"Subfolder:"})," ",i.repository.subfolder]}),i.repository.id&&e.jsxs("div",{children:[e.jsx("span",{className:"font-medium text-gray-700",children:"ID:"})," ",i.repository.id]})]})]}),F&&V&&z&&e.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:e.jsx(ke,{onSubmit:g,onCancel:x,modalTitle:a("registry.installServer",{name:i.title||i.name}),formError:Q,initialData:N()})})]})};function os(s){switch(s.toLowerCase()){case"pypi":case"python":return"uvx";case"npm":case"node":return"npx";case"oci":case"docker":return"docker";default:return""}}function cs(s,f){const v=[f.identifier+(f.version?`@${f.version}`:"")],d=[];switch(f.packageArguments&&f.packageArguments.length>0&&f.packageArguments.forEach(m=>{if(m.isRequired||m.default||m.value){const o=`--${m.name}`,a=m.value||m.default||`\${${m.name.toUpperCase()}}`;d.push(o,a)}}),s.toLowerCase()){case"uvx":return[...v,...d];case"npx":return[...v,...d];case"docker":{const m=[];return f.environmentVariables&&f.environmentVariables.forEach(o=>{m.push("-e",`${o.name}`)}),["run","-i","--rm",...m,...v,...d]}default:return[...v,...d]}}const ds=({currentPage:s,hasNextPage:f,hasPreviousPage:v,onNextPage:d,onPreviousPage:m})=>e.jsxs("div",{className:"flex items-center justify-center space-x-2 my-6",children:[e.jsxs("button",{onClick:m,disabled:!v,className:"hub-btn",children:[e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-5 w-5 inline-block mr-1",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z",clipRule:"evenodd"})}),"Prev"]}),e.jsxs("span",{className:"hub-btn primary",children:["Page ",s]}),e.jsxs("button",{onClick:d,disabled:!f,className:"hub-btn",children:["Next",e.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-5 w-5 inline-block ml-1",viewBox:"0 0 20 20",fill:"currentColor",children:e.jsx("path",{fillRule:"evenodd",d:"M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z",clipRule:"evenodd"})})]})]}),ys=()=>{const{t:s}=ne(),f=He(),{serverName:v}=We(),{showToast:d}=Fe(),[m,o]=_e(),a=m.get("tab")==="registry"?"registry":"local",{servers:A,allServers:p,categories:i,loading:D,error:P,setError:U,searchServers:M,filterByCategory:H,filterByTag:I,selectedCategory:C,selectedTag:F,installServer:S,fetchServerByName:z,isServerInstalled:O,currentPage:V,totalPages:T,changePage:Q,serversPerPage:$,changeServersPerPage:w}=es(),{servers:q,allServers:k,loading:K,error:B,setError:E,searchServers:y,clearSearch:n,fetchServerByName:x,fetchServerVersions:g,currentPage:N,totalPages:W,hasNextPage:R,hasPreviousPage:X,changePage:c,goToNextPage:b,goToPreviousPage:u,serversPerPage:r,changeServersPerPage:l}=ss(),[G,se]=t.useState(null),[_,Y]=t.useState(null),[ee,re]=t.useState(""),[de,xe]=t.useState(""),[ge,ce]=t.useState(!1),[we,Ce]=t.useState(new Set);t.useEffect(()=>{(async()=>{if(v)if(a==="registry"){const j=await x(v);j?Y(j):f("/market?tab=registry")}else{const j=await z(v);j?se(j):f("/market?tab=local")}else se(null),Y(null)})()},[v,a,z,x,f]);const Pe=h=>{const j=new URLSearchParams(m);j.set("tab",h),o(j),v&&f("/market?"+j.toString())},Ee=h=>{h.preventDefault(),a==="local"?M(ee):a==="registry"&&y(de)},Re=h=>{a==="local"&&H(h)},Ie=()=>{a==="local"?(re(""),H(""),I("")):a==="registry"&&(xe(""),n())},pe=h=>{var j;if(a==="registry"){const ae=(j=h.server)==null?void 0:j.name;ae&&f(`/market/${encodeURIComponent(ae)}?tab=registry`)}else f(`/market/${h.name}?tab=local`)},fe=()=>f(`/market?tab=${a}`),Te=async(h,j)=>{try{ce(!0),await S(h,j)&&d(s("market.installSuccess",{serverName:h.display_name}),"success")}finally{ce(!1)}},Le=async(h,j)=>{try{ce(!0);const Z={name:he(h.name),config:j},ae=await ve("/servers",Z);if(!ae.success){d((ae==null?void 0:ae.message)||s("server.addError"),"error");return}Ce(Ue=>new Set(Ue).add(h.name)),d(s("registry.installSuccess",{name:h.title||h.name}),"success")}catch(Z){d(s("registry.installError",{error:Z instanceof Error?Z.message:String(Z)}),"error")}finally{ce(!1)}},Ae=h=>{a==="local"?Q(h):c(h),window.scrollTo({top:0,behavior:"smooth"})},ze=h=>{const j=parseInt(h.target.value,10);a==="local"?w(j):l(j)};if(G)return e.jsx(as,{server:G,onBack:fe,onInstall:Te,installing:ge,isInstalled:O(G.name)});if(_)return e.jsx(is,{serverEntry:_,onBack:fe,onInstall:Le,installing:ge,isInstalled:we.has(_.server.name),fetchVersions:g});const L=a==="local",le=a==="registry",me=L?A:q,ue=L?p:k,$e=L?i:[],Be=L?D:K,ye=L?P:B,Ve=L?U:E,te=L?C:"",Me=L?F:"",ie=L?V:N,De=L?T:W,oe=L?$:r,be=[{id:"local",label:s("market.title"),sourceLabel:"MCPM",sourceUrl:"https://mcpm.sh"},{id:"registry",label:s("registry.title"),sourceLabel:s("registry.official"),sourceUrl:"https://registry.modelcontextprotocol.io"}];return e.jsxs("div",{children:[e.jsx("div",{className:"flex items-end justify-between gap-4 mb-6",children:e.jsxs("div",{children:[e.jsx("h1",{className:"hub-h1",children:s("nav.market")}),e.jsx("p",{className:"hub-sub",children:be.map(h=>h.label).join(" · ")})]})}),e.jsx("div",{className:"mb-5",children:e.jsx("div",{style:{borderBottom:"1px solid var(--hub-line)"},children:e.jsx("nav",{className:"flex -mb-px gap-1.5",children:be.map(h=>{const j=a===h.id;return e.jsxs("button",{onClick:()=>Pe(h.id),className:"py-2 px-3 transition-colors text-[14px]",style:{borderBottom:"2px solid "+(j?"var(--hub-ink)":"transparent"),color:j?"var(--hub-ink)":"var(--hub-ink-3)",fontWeight:j?500:400},children:[h.label,e.jsxs("a",{href:h.sourceUrl,target:"_blank",rel:"noopener noreferrer",className:"hub-mono ml-1.5",style:{fontSize:11,color:"var(--hub-ink-3)"},onClick:Z=>Z.stopPropagation(),children:["(",h.sourceLabel,")"]})]},h.id)})})})}),ye&&e.jsxs("div",{className:"hub-card flex items-center justify-between gap-3 mb-4",style:{padding:"10px 14px",borderColor:"oklch(0.85 0.1 25)",background:"oklch(0.97 0.03 25)",color:"oklch(0.4 0.18 25)"},children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx(Je,{size:14,className:"flex-shrink-0"}),e.jsx("span",{className:"truncate text-[13px]",children:ye})]}),e.jsx("button",{className:"hub-icon-btn sm",onClick:()=>Ve(null),children:e.jsx(Xe,{size:13})})]}),(L||le)&&e.jsxs("form",{onSubmit:Ee,className:"hub-card flex items-center gap-2 px-3 mb-5",style:{padding:6},children:[e.jsx(Ye,{size:16,style:{color:"var(--hub-ink-3)",margin:"0 6px 0 6px"}}),e.jsx("input",{type:"text",value:le?de:ee,onChange:h=>{le?xe(h.target.value):re(h.target.value)},placeholder:s(le?"registry.searchPlaceholder":"market.searchPlaceholder"),className:"flex-1 bg-transparent outline-none",style:{height:32,fontSize:14,color:"var(--hub-ink)"}}),e.jsx("button",{type:"submit",className:"hub-btn",children:s("common.search")}),(L&&(ee||te||Me)||le&&de)&&e.jsx("button",{type:"button",onClick:Ie,className:"hub-btn ghost",children:s("common.clear")})]}),e.jsxs("div",{className:L?"grid gap-5":"",style:L?{gridTemplateColumns:"180px 1fr"}:void 0,children:[L&&e.jsxs("div",{children:[e.jsx("h3",{className:"hub-sect mb-2",children:s("market.categories")}),e.jsxs("div",{className:"flex flex-col gap-0.5",children:[e.jsxs("button",{onClick:()=>H(""),className:"flex items-center justify-between transition-colors text-[13px]",style:{padding:"6px 10px",borderRadius:6,background:te?"transparent":"var(--hub-surface)",color:te?"var(--hub-ink-2)":"var(--hub-ink)",border:"1px solid "+(te?"transparent":"var(--hub-line)")},children:[e.jsx("span",{children:s("common.all")}),e.jsx("span",{className:"hub-mono",style:{fontSize:11,color:"var(--hub-ink-3)"},children:p.length})]}),$e.map(h=>e.jsx("button",{onClick:()=>Re(h),className:"flex items-center justify-between transition-colors text-[13px]",style:{padding:"6px 10px",borderRadius:6,background:te===h?"var(--hub-surface)":"transparent",color:te===h?"var(--hub-ink)":"var(--hub-ink-2)",border:"1px solid "+(te===h?"var(--hub-line)":"transparent")},children:e.jsx("span",{className:"truncate",children:h})},h))]})]}),e.jsx("div",{children:Be?e.jsx("div",{className:"hub-card p-6 text-center",style:{color:"var(--hub-ink-3)"},children:s("app.loading")}):me.length===0?e.jsx("div",{className:"hub-card p-10 text-center",style:{color:"var(--hub-ink-3)"},children:s(L?"market.noServers":"registry.noServers")}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-3",children:me.map((h,j)=>L?e.jsx(ts,{server:h,onClick:pe},j):e.jsx(ls,{serverEntry:h,onClick:pe},j))}),e.jsxs("div",{className:"flex items-center mt-4 text-[12px]",style:{color:"var(--hub-ink-3)"},children:[e.jsx("div",{className:"flex-[2]",children:L?s("market.showing",{from:(ie-1)*oe+1,to:Math.min(ie*oe,ue.length),total:ue.length}):s("registry.showing",{from:(ie-1)*oe+1,to:(ie-1)*oe+me.length,total:ue.length+(R?"+":"")})}),e.jsx("div",{className:"flex-[4] flex justify-center",children:le?e.jsx(ds,{currentPage:ie,hasNextPage:R,hasPreviousPage:X,onNextPage:b,onPreviousPage:u}):e.jsx(Ke,{currentPage:ie,totalPages:De,onPageChange:Ae})}),e.jsxs("div",{className:"flex-[2] flex items-center justify-end gap-2",children:[e.jsxs("label",{htmlFor:"perPage",children:[s(L?"market.perPage":"registry.perPage"),":"]}),e.jsxs("div",{className:"relative",children:[e.jsxs("select",{id:"perPage",value:oe,onChange:ze,className:"hub-input pr-7",style:{height:26,width:70,padding:"0 6px",fontSize:12},children:[e.jsx("option",{value:"6",children:"6"}),e.jsx("option",{value:"9",children:"9"}),e.jsx("option",{value:"12",children:"12"}),e.jsx("option",{value:"24",children:"24"})]}),e.jsx(Ze,{size:11,className:"absolute right-1.5 top-1/2 -translate-y-1/2 pointer-events-none",style:{color:"var(--hub-ink-3)"}})]})]})]})]})})]})]})};export{ys as default};
2
- //# sourceMappingURL=MarketPage-Bvi1KESo.js.map