@samanhappy/mcphub 1.1.12 → 1.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/index.js +1 -1
- package/dist/config/index.js.map +1 -1
- package/dist/controllers/bearerKeyController.js +33 -1
- package/dist/controllers/bearerKeyController.js.map +1 -1
- package/dist/controllers/configController.js +1 -0
- package/dist/controllers/configController.js.map +1 -1
- package/dist/controllers/credentialBindingController.js +35 -11
- package/dist/controllers/credentialBindingController.js.map +1 -1
- package/dist/controllers/serverController.js +29 -4
- package/dist/controllers/serverController.js.map +1 -1
- package/dist/dao/ActivityDao.js +2 -0
- package/dist/dao/ActivityDao.js.map +1 -1
- package/dist/dao/BearerKeyDaoDbImpl.js +3 -0
- package/dist/dao/BearerKeyDaoDbImpl.js.map +1 -1
- package/dist/dao/GroupDao.js +24 -0
- package/dist/dao/GroupDao.js.map +1 -1
- package/dist/dao/GroupDaoDbImpl.js +23 -0
- package/dist/dao/GroupDaoDbImpl.js.map +1 -1
- package/dist/dao/ServerDao.js +5 -0
- package/dist/dao/ServerDao.js.map +1 -1
- package/dist/dao/ServerDaoDbImpl.js +1 -0
- package/dist/dao/ServerDaoDbImpl.js.map +1 -1
- package/dist/dao/SystemConfigDao.js +5 -2
- package/dist/dao/SystemConfigDao.js.map +1 -1
- package/dist/dao/SystemConfigDaoDbImpl.js +11 -0
- package/dist/dao/SystemConfigDaoDbImpl.js.map +1 -1
- package/dist/dao/base/JsonFileBaseDao.js +17 -2
- package/dist/dao/base/JsonFileBaseDao.js.map +1 -1
- package/dist/db/entities/Activity.js +4 -0
- package/dist/db/entities/Activity.js.map +1 -1
- package/dist/db/entities/CredentialBindingImport.js +26 -0
- package/dist/db/entities/CredentialBindingImport.js.map +1 -0
- package/dist/db/entities/SystemConfig.js +8 -0
- package/dist/db/entities/SystemConfig.js.map +1 -1
- package/dist/db/entities/index.js +3 -1
- package/dist/db/entities/index.js.map +1 -1
- package/dist/db/repositories/GroupRepository.js +36 -0
- package/dist/db/repositories/GroupRepository.js.map +1 -1
- package/dist/db/repositories/ServerRepository.js.map +1 -1
- package/dist/db/repositories/VectorEmbeddingRepository.js +11 -1
- package/dist/db/repositories/VectorEmbeddingRepository.js.map +1 -1
- package/dist/routes/index.js +6 -2
- package/dist/routes/index.js.map +1 -1
- package/dist/server.js +2 -0
- package/dist/server.js.map +1 -1
- package/dist/services/activityLoggingService.js +1 -0
- package/dist/services/activityLoggingService.js.map +1 -1
- package/dist/services/contextCostService.js +2 -2
- package/dist/services/contextCostService.js.map +1 -1
- package/dist/services/groupService.js +6 -1
- package/dist/services/groupService.js.map +1 -1
- package/dist/services/mcpService.js +127 -4
- package/dist/services/mcpService.js.map +1 -1
- package/dist/services/principalRuntimeService.js +19 -0
- package/dist/services/principalRuntimeService.js.map +1 -1
- package/dist/services/smartRoutingService.js +20 -2
- package/dist/services/smartRoutingService.js.map +1 -1
- package/dist/services/toolPolicyDiagnostics.js +27 -0
- package/dist/services/toolPolicyDiagnostics.js.map +1 -0
- package/dist/services/toolPolicyService.js +41 -0
- package/dist/services/toolPolicyService.js.map +1 -0
- package/dist/services/vectorSearchService.js +117 -66
- package/dist/services/vectorSearchService.js.map +1 -1
- package/dist/types/toolPolicy.js +2 -0
- package/dist/types/toolPolicy.js.map +1 -0
- package/dist/utils/credentialBindingMigration.js +65 -0
- package/dist/utils/credentialBindingMigration.js.map +1 -0
- package/dist/utils/groupKeyScope.js +28 -0
- package/dist/utils/groupKeyScope.js.map +1 -0
- package/dist/utils/migration.js +10 -10
- package/dist/utils/migration.js.map +1 -1
- package/dist/utils/serverIdentity.js +7 -0
- package/dist/utils/serverIdentity.js.map +1 -0
- package/dist/utils/settingsSync.js +11 -1
- package/dist/utils/settingsSync.js.map +1 -1
- package/dist/utils/systemConfigCache.js +1 -1
- package/dist/utils/systemConfigCache.js.map +1 -1
- package/dist/utils/tokenCost.js +35 -3
- package/dist/utils/tokenCost.js.map +1 -1
- package/dist/utils/toolPolicy.js +42 -0
- package/dist/utils/toolPolicy.js.map +1 -0
- package/frontend/dist/assets/{ActivityPage-DWA-okla.js → ActivityPage-C8Zj4FeE.js} +2 -2
- package/frontend/dist/assets/{ActivityPage-DWA-okla.js.map → ActivityPage-C8Zj4FeE.js.map} +1 -1
- package/frontend/dist/assets/CredentialsPage-BnzqPYjg.js +2 -0
- package/frontend/dist/assets/CredentialsPage-BnzqPYjg.js.map +1 -0
- package/frontend/dist/assets/{Dashboard-Diql_Btr.js → Dashboard-CCiZcGi4.js} +2 -2
- package/frontend/dist/assets/{Dashboard-Diql_Btr.js.map → Dashboard-CCiZcGi4.js.map} +1 -1
- package/frontend/dist/assets/{EndpointCopy-0d-dK6uJ.js → EndpointCopy-CmKx4RVL.js} +2 -2
- package/frontend/dist/assets/{EndpointCopy-0d-dK6uJ.js.map → EndpointCopy-CmKx4RVL.js.map} +1 -1
- package/frontend/dist/assets/GroupsPage-DHgQeVHy.js +33 -0
- package/frontend/dist/assets/{GroupsPage-gZ0nnzCn.js.map → GroupsPage-DHgQeVHy.js.map} +1 -1
- package/frontend/dist/assets/LoginPage-Hn1uu0vB.js +2 -0
- package/frontend/dist/assets/LoginPage-Hn1uu0vB.js.map +1 -0
- package/frontend/dist/assets/{LogsPage-C7erxObE.js → LogsPage-JMCtTjCv.js} +2 -2
- package/frontend/dist/assets/LogsPage-JMCtTjCv.js.map +1 -0
- package/frontend/dist/assets/MarketPage-Bvi1KESo.js +2 -0
- package/frontend/dist/assets/{MarketPage-BZHQQB57.js.map → MarketPage-Bvi1KESo.js.map} +1 -1
- package/frontend/dist/assets/{OAuthConsentPage-Czhwhcx8.js → OAuthConsentPage-DofQEZAU.js} +2 -2
- package/frontend/dist/assets/{OAuthConsentPage-Czhwhcx8.js.map → OAuthConsentPage-DofQEZAU.js.map} +1 -1
- package/frontend/dist/assets/Pagination-D99WHhBx.js +2 -0
- package/frontend/dist/assets/Pagination-D99WHhBx.js.map +1 -0
- package/frontend/dist/assets/{PromptsPage-D0yHQbns.js → PromptsPage-B-8vczAR.js} +2 -2
- package/frontend/dist/assets/{PromptsPage-D0yHQbns.js.map → PromptsPage-B-8vczAR.js.map} +1 -1
- package/frontend/dist/assets/{ResourcesPage-BFoqAAq0.js → ResourcesPage-DLAIatoG.js} +2 -2
- package/frontend/dist/assets/{ResourcesPage-BFoqAAq0.js.map → ResourcesPage-DLAIatoG.js.map} +1 -1
- package/frontend/dist/assets/ServersPage-wVLsTL_f.js +39 -0
- package/frontend/dist/assets/ServersPage-wVLsTL_f.js.map +1 -0
- package/frontend/dist/assets/SettingsPage-DkfXDE5_.js +14 -0
- package/frontend/dist/assets/SettingsPage-DkfXDE5_.js.map +1 -0
- package/frontend/dist/assets/{StatusDot-BniiEZ-W.js → StatusDot-00-sTQKv.js} +2 -2
- package/frontend/dist/assets/{StatusDot-BniiEZ-W.js.map → StatusDot-00-sTQKv.js.map} +1 -1
- package/frontend/dist/assets/{ToggleGroup-Df-pFUN3.js → ToggleGroup-CtWBng3r.js} +2 -2
- package/frontend/dist/assets/{ToggleGroup-Df-pFUN3.js.map → ToggleGroup-CtWBng3r.js.map} +1 -1
- package/frontend/dist/assets/UsersPage-BtdFWcVD.js +2 -0
- package/frontend/dist/assets/UsersPage-BtdFWcVD.js.map +1 -0
- package/frontend/dist/assets/clipboard-2RRFM-q8.js +2 -0
- package/frontend/dist/assets/{clipboard-BrGjez3U.js.map → clipboard-2RRFM-q8.js.map} +1 -1
- package/frontend/dist/assets/{CopyClientConfigDialog-xeHg7JJj.js → costRevision-Ntl7VtWo.js} +4 -4
- package/frontend/dist/assets/costRevision-Ntl7VtWo.js.map +1 -0
- package/frontend/dist/assets/{icons-vendor-CkcU1LMA.js → icons-vendor-CyAS6fj0.js} +2 -2
- package/frontend/dist/assets/{icons-vendor-CkcU1LMA.js.map → icons-vendor-CyAS6fj0.js.map} +1 -1
- package/frontend/dist/assets/index-CkSmxNPW.js +3 -0
- package/frontend/dist/assets/index-CkSmxNPW.js.map +1 -0
- package/frontend/dist/assets/index-DrHctFvx.css +1 -0
- package/frontend/dist/assets/{resourceService-8K1eUH8N.js → resourceService-BB4UM6IQ.js} +2 -2
- package/frontend/dist/assets/{resourceService-8K1eUH8N.js.map → resourceService-BB4UM6IQ.js.map} +1 -1
- package/frontend/dist/assets/useCostData-C3XnQyUj.js +2 -0
- package/frontend/dist/assets/useCostData-C3XnQyUj.js.map +1 -0
- package/frontend/dist/assets/{variableDetection-Djnw5--_.js → variableDetection-BUXwrSop.js} +2 -2
- package/frontend/dist/assets/{variableDetection-Djnw5--_.js.map → variableDetection-BUXwrSop.js.map} +1 -1
- package/frontend/dist/index.html +3 -3
- package/mcp_settings.json +2 -0
- package/package.json +1 -1
- package/frontend/dist/assets/CopyClientConfigDialog-xeHg7JJj.js.map +0 -1
- package/frontend/dist/assets/CredentialsPage-D8mMIH5f.js +0 -2
- package/frontend/dist/assets/CredentialsPage-D8mMIH5f.js.map +0 -1
- package/frontend/dist/assets/GroupsPage-gZ0nnzCn.js +0 -33
- package/frontend/dist/assets/LoginPage-BRyFcGQ5.js +0 -2
- package/frontend/dist/assets/LoginPage-BRyFcGQ5.js.map +0 -1
- package/frontend/dist/assets/LogsPage-C7erxObE.js.map +0 -1
- package/frontend/dist/assets/MarketPage-BZHQQB57.js +0 -2
- package/frontend/dist/assets/Pagination-BRqqU5Ct.js +0 -2
- package/frontend/dist/assets/Pagination-BRqqU5Ct.js.map +0 -1
- package/frontend/dist/assets/ServersPage-CMG1tNig.js +0 -39
- package/frontend/dist/assets/ServersPage-CMG1tNig.js.map +0 -1
- package/frontend/dist/assets/SettingsPage-C6GAVHlw.js +0 -14
- package/frontend/dist/assets/SettingsPage-C6GAVHlw.js.map +0 -1
- package/frontend/dist/assets/UsersPage-je7LsHJG.js +0 -2
- package/frontend/dist/assets/UsersPage-je7LsHJG.js.map +0 -1
- package/frontend/dist/assets/clipboard-BrGjez3U.js +0 -2
- package/frontend/dist/assets/index-DL9uGzQF.js +0 -3
- package/frontend/dist/assets/index-DL9uGzQF.js.map +0 -1
- package/frontend/dist/assets/index-JDk4RjZI.css +0 -1
- package/frontend/dist/assets/useCostData-BuDleGRv.js +0 -2
- package/frontend/dist/assets/useCostData-BuDleGRv.js.map +0 -1
package/frontend/dist/index.html
CHANGED
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
7
|
<title>MCPHub Dashboard</title>
|
|
8
8
|
<link rel="icon" type="image/x-icon" href="./assets/favicon-DJnZjsC8.ico">
|
|
9
|
-
<script type="module" crossorigin src="./assets/index-
|
|
9
|
+
<script type="module" crossorigin src="./assets/index-CkSmxNPW.js"></script>
|
|
10
10
|
<link rel="modulepreload" crossorigin href="./assets/framework-vendor-CQFm9vKd.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="./assets/i18n-vendor-DVmjrzgW.js">
|
|
12
|
-
<link rel="modulepreload" crossorigin href="./assets/icons-vendor-
|
|
13
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
12
|
+
<link rel="modulepreload" crossorigin href="./assets/icons-vendor-CyAS6fj0.js">
|
|
13
|
+
<link rel="stylesheet" crossorigin href="./assets/index-DrHctFvx.css">
|
|
14
14
|
</head>
|
|
15
15
|
|
|
16
16
|
<body class="bg-gray-100">
|
package/mcp_settings.json
CHANGED
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CopyClientConfigDialog-xeHg7JJj.js","sources":["../../src/utils/toolDescription.ts","../../src/utils/mcpClientSnippets.ts","../../src/components/ui/CopyClientConfigDialog.tsx"],"sourcesContent":["type ToolDescriptionSource = {\n description?: string;\n defaultDescription?: string;\n hasDescriptionOverride?: boolean;\n};\n\nexport interface ToolDescriptionInfo {\n currentDescription: string;\n defaultDescription?: string;\n hasDescriptionOverride: boolean;\n}\n\nconst normalizeDescription = (description: string | undefined, fallback: string): string => {\n return description && description.trim() ? description : fallback;\n};\n\nexport const getToolDescriptionInfo = (\n tool: ToolDescriptionSource,\n noDescriptionText: string,\n): ToolDescriptionInfo => {\n const currentDescription = normalizeDescription(tool.description, noDescriptionText);\n\n if (!tool.hasDescriptionOverride) {\n return {\n currentDescription,\n hasDescriptionOverride: false,\n };\n }\n\n return {\n currentDescription,\n defaultDescription: normalizeDescription(tool.defaultDescription, noDescriptionText),\n hasDescriptionOverride: true,\n };\n};\n","/**\n * Per-client MCP configuration presets for the copy actions (#1165).\n *\n * MCPHub hands out HTTP endpoints, so every preset describes the same target -\n * a name, an optional URL/headers pair (HTTP) or command/args/env triple\n * (stdio) - in the shape the selected client expects. Eleven of the fourteen\n * presets were verified against the upstream sources below (URLs re-checked\n * 2026-09, the month this file landed); the remaining three reuse the generic\n * `mcpServers` shape (or, for the generic-http escape hatch, the bare entry)\n * these copy actions always produced.\n *\n * Which clients document an explicit transport field, and which do not:\n * - Documents a transport field (the `type` key is written into the entry):\n * claude-code (`type: \"http\" | \"sse\" | \"stdio\"`; a remote entry with `url`\n * but no `type` is a configuration error per\n * https://code.claude.com/docs/en/mcp), vscode (`\"http\" | \"sse\" | \"stdio\"`,\n * final URL after the 2026-09 migration:\n * https://code.visualstudio.com/docs/agent-customization/mcp-servers),\n * codebuddy (`type` marked Required; fixed `\"http\"` for HTTP, `\"sse\"` for\n * SSE and `\"stdio\"` for stdio, per\n * https://www.codebuddy.ai/docs/cli/mcp), qoder (every remote\n * example carries `type`; for Streamable HTTP the doc says to configure the\n * URL the same way as SSE and the IDE auto-detects it, so the http target\n * deliberately keeps the bare `url` + `headers` shape rather than tagging\n * it `sse`; https://docs.qoder.com/zh/user-guide/chat/model-context-protocol),\n * cherry-studio (`baseUrl` + `'sse' | 'streamableHttp'`, strict schema),\n * opencode (`type: 'remote' | 'local'`).\n * - Field table does not list a transport key: cursor\n * (https://cursor.com/docs/mcp), trae (https://docs.trae.ai/ide/add-mcp-servers),\n * zcode (https://zcode.z.ai/en/docs/mcp-services), windsurf\n * (https://docs.windsurf.com/windsurf/cascade/mcp). The `type: \"sse\"` marker\n * the generic shape injects for SSE targets on these presets is added on\n * the assumption that unknown keys are ignored, not required by their\n * documented shape; it is kept because SSE upstreams must not be dialed as\n * streamable HTTP.\n * - Verified but the format carries no `type` key at all: codex (TOML;\n * `codex-rs/config/src/mcp_types.rs`,\n * https://github.com/openai/codex/blob/main/codex-rs/config/src/mcp_types.rs).\n * (The generic-http escape hatch, one of the three unverified presets, is not\n * a \"no `type`\" format: for a remote target it always writes an explicit\n * `type` - `\"http\"`, or `\"sse\"` for an SSE upstream.)\n *\n * Upstream sources used:\n * - Claude Code MCP configuration: https://code.claude.com/docs/en/mcp\n * - Cursor MCP docs: https://cursor.com/docs/mcp\n * - VS Code MCP configuration reference:\n * https://code.visualstudio.com/docs/agent-customization/mcp-servers\n * - Codex `codex-rs/config/src/mcp_types.rs`:\n * https://github.com/openai/codex/blob/main/codex-rs/config/src/mcp_types.rs\n * - OpenCode mcp-servers docs: https://opencode.ai/docs/mcp-servers/\n * - Cherry Studio `mcpProtocolInstall.ts`:\n * https://github.com/CherryHQ/cherry-studio/blob/main/src/shared/data/types/mcpProtocolInstall.ts\n * - CodeBuddy MCP CLI docs: https://www.codebuddy.ai/docs/cli/mcp\n * - Qoder MCP user guide:\n * https://docs.qoder.com/zh/user-guide/chat/model-context-protocol\n * - Trae MCP docs: https://docs.trae.ai/ide/add-mcp-servers\n * - Windsurf MCP docs: https://docs.windsurf.com/windsurf/cascade/mcp\n * - ZCode MCP docs: https://zcode.z.ai/en/docs/mcp-services\n */\n\nexport type ClientSnippetId =\n | 'generic-mcp-servers'\n | 'generic-http'\n | 'claude-code'\n | 'cursor'\n | 'vscode'\n | 'codex'\n | 'opencode'\n | 'windsurf'\n | 'cherry-studio'\n | 'codebuddy'\n | 'qoder'\n | 'trae'\n | 'zcode'\n | 'workbuddy';\n\nexport interface ClientSnippetPreset {\n id: ClientSnippetId;\n}\n\n/** Tab the dialog opens on; the shape the copy actions produced before. */\nexport const DEFAULT_CLIENT_SNIPPET_ID: ClientSnippetId = 'generic-mcp-servers';\n\n/**\n * Tabs shown in the copy dialog, most common clients first. The first entry is\n * the shape the copy actions produced before the presets existed, so the\n * default tab stays familiar; the bare HTTP entry is the escape hatch for\n * clients that wrap the entry in their own container.\n */\nexport const CLIENT_SNIPPET_PRESETS: readonly ClientSnippetPreset[] = [\n { id: 'generic-mcp-servers' },\n { id: 'claude-code' },\n { id: 'cursor' },\n { id: 'vscode' },\n { id: 'codex' },\n { id: 'opencode' },\n { id: 'windsurf' },\n { id: 'cherry-studio' },\n { id: 'codebuddy' },\n { id: 'qoder' },\n { id: 'trae' },\n { id: 'zcode' },\n { id: 'workbuddy' },\n { id: 'generic-http' },\n];\n\nexport interface ClientSnippetTarget {\n name: string;\n /** Stored transport type; `sse` is called out so clients do not misdial it as http. */\n type?: 'stdio' | 'sse' | 'streamable-http' | 'openapi';\n /** HTTP targets carry a URL (and usually an Authorization header). */\n url?: string;\n headers?: Record<string, string>;\n /** stdio targets carry a command instead. */\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n description?: string;\n}\n\nexport interface ClientSnippetBlock {\n kind: 'config' | 'command';\n text: string;\n}\n\nexport interface ClientSnippetOptions {\n /** Description used by the VS Code token input prompt. */\n tokenPromptDescription?: string;\n}\n\n/** Placeholder MCPHub uses for snippets that need a token pasted in by hand. */\nexport const ACCESS_TOKEN_PLACEHOLDER = '<your-access-token>';\nconst TOKEN_INPUT_ID = 'mcphub-token';\n\nconst isHttpTarget = (target: ClientSnippetTarget): boolean => Boolean(target.url);\n\nconst definedHeaders = (target: ClientSnippetTarget): Record<string, string> | undefined => {\n const entries = Object.entries(target.headers ?? {}).filter(([, value]) => value !== undefined);\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n};\n\nconst definedEnv = (target: ClientSnippetTarget): Record<string, string> | undefined => {\n const entries = Object.entries(target.env ?? {}).filter(([, value]) => value !== undefined);\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n};\n\nconst stdioEntry = (target: ClientSnippetTarget): Record<string, unknown> => {\n const args = target.args?.filter((arg) => arg !== undefined) ?? [];\n const env = definedEnv(target);\n return {\n command: target.command ?? '',\n ...(args.length > 0 ? { args } : {}),\n ...(env ? { env } : {}),\n };\n};\n\n/**\n * HTTP/stdio entry for clients whose docs make the transport a required field.\n * Claude Code skips an entry that has a `url` but no `type` (it reads the\n * entry as stdio and reports a configuration error), and CodeBuddy's field\n * table marks `type` as Required, fixed to `\"http\"` for the HTTP form and\n * `\"sse\"` for the SSE form.\n *\n * Stdio targets differ between the two clients. Claude Code reads a type-less\n * entry as stdio (https://code.claude.com/docs/en/mcp), so its stdio shape\n * keeps the plain command/args/env form with no `type` key. CodeBuddy's docs\n * mark `type` as Required with the fixed value `\"stdio\"`\n * (https://www.codebuddy.ai/docs/cli/mcp), so its stdio shape writes\n * `\"type\": \"stdio\"`; pass `stdioType` only for CodeBuddy.\n */\nconst typedTransportEntry = (\n target: ClientSnippetTarget,\n stdioType: boolean = false,\n): Record<string, unknown> => {\n if (!isHttpTarget(target)) {\n return stdioType ? { type: 'stdio', ...stdioEntry(target) } : stdioEntry(target);\n }\n\n const headers = definedHeaders(target);\n return {\n type: target.type === 'sse' ? 'sse' : 'http',\n url: target.url ?? '',\n ...(headers ? { headers } : {}),\n };\n};\n\n// This helper feeds the generic `mcpServers` shape for the generic-mcp-servers,\n// qoder, cursor, windsurf, trae, zcode and workbuddy presets. Only qoder's\n// upstream docs carry a transport field for this shape; for the rest\n// (generic-mcp-servers, cursor, windsurf, trae, zcode, workbuddy) the\n// `type: \"sse\"` marker is added on the assumption that unknown keys are\n// ignored, so it is unverified against a field table. It is kept because an\n// SSE upstream must not be dialed as streamable HTTP.\nconst httpEntry = (target: ClientSnippetTarget): Record<string, unknown> => {\n const headers = definedHeaders(target);\n return {\n // Only `sse` is spelled out: it is the one HTTP transport a client might\n // otherwise misdial as streamable HTTP. Every other target keeps the bare\n // `url` + `headers` shape these presets always produced.\n ...(target.type === 'sse' ? { type: 'sse' } : {}),\n url: target.url ?? '',\n ...(headers ? { headers } : {}),\n };\n};\n\nconst withWrappedName = (\n wrapper: string,\n name: string,\n entry: Record<string, unknown>,\n): string => JSON.stringify({ [wrapper]: { [name]: entry } }, null, 2);\n\nconst jsonSnippet = (target: ClientSnippetTarget): string =>\n withWrappedName(\n 'mcpServers',\n target.name,\n isHttpTarget(target) ? httpEntry(target) : stdioEntry(target),\n );\n\n// VS Code wants the transport spelled out and can prompt for the token itself,\n// so the shared placeholder becomes an input reference plus an `inputs` entry.\nconst vscodeSnippet = (target: ClientSnippetTarget, options: ClientSnippetOptions): string => {\n const headers = definedHeaders(target);\n const placeholder = `Bearer ${ACCESS_TOKEN_PLACEHOLDER}`;\n const needsTokenInput = headers?.Authorization === placeholder;\n\n const body = needsTokenInput\n ? { ...headers, Authorization: `Bearer \\${input:${TOKEN_INPUT_ID}}` }\n : headers;\n\n const entry = isHttpTarget(target)\n ? {\n // VS Code distinguishes the SSE transport from streamable HTTP.\n type: target.type === 'sse' ? 'sse' : 'http',\n url: target.url,\n ...(body ? { headers: body } : {}),\n }\n : { type: 'stdio', ...stdioEntry(target) };\n\n return JSON.stringify(\n {\n servers: { [target.name]: entry },\n ...(needsTokenInput\n ? {\n inputs: [\n {\n id: TOKEN_INPUT_ID,\n type: 'promptString',\n description: options.tokenPromptDescription ?? 'MCPHub access token',\n password: true,\n },\n ],\n }\n : {}),\n },\n null,\n 2,\n );\n};\n\nconst TOML_BARE_KEY = /^[A-Za-z0-9_-]+$/;\n\nconst tomlKey = (key: string): string => (TOML_BARE_KEY.test(key) ? key : JSON.stringify(key));\nconst tomlValue = (value: string): string => JSON.stringify(value);\nconst tomlInlineTable = (entries: Record<string, string>): string =>\n `{ ${Object.entries(entries)\n .map(([key, value]) => `${tomlKey(key)} = ${tomlValue(value)}`)\n .join(', ')} }`;\n\n// Codex calls the header map `http_headers` (there is no `headers` key), and\n// needs quoted table keys for names that are not bare TOML keys - group names\n// may contain spaces or CJK. Note `#[schemars(deny_unknown_fields)]` in\n// `mcp_types.rs` only constrains the generated JSON Schema; the Rust struct\n// itself has no `#[serde(deny_unknown_fields)]`, so TOML parsing may silently\n// ignore unknown fields instead of rejecting them.\nconst codexSnippet = (target: ClientSnippetTarget): string => {\n const key = tomlKey(target.name);\n const lines = [`[mcp_servers.${key}]`];\n\n if (isHttpTarget(target)) {\n lines.push(`url = ${tomlValue(target.url ?? '')}`);\n const headers = definedHeaders(target);\n if (headers) {\n lines.push(`http_headers = ${tomlInlineTable(headers)}`);\n }\n return lines.join('\\n');\n }\n\n lines.push(`command = ${tomlValue(target.command ?? '')}`);\n const args = target.args?.filter((arg) => arg !== undefined) ?? [];\n if (args.length > 0) {\n lines.push(`args = [${args.map(tomlValue).join(', ')}]`);\n }\n const env = definedEnv(target);\n if (env) {\n lines.push('', `[mcp_servers.${key}.env]`);\n for (const [name, value] of Object.entries(env)) {\n lines.push(`${tomlKey(name)} = ${tomlValue(value)}`);\n }\n }\n return lines.join('\\n');\n};\n\nconst openCodeSnippet = (target: ClientSnippetTarget): string => {\n if (!isHttpTarget(target)) {\n const env = definedEnv(target);\n const args = target.args?.filter((arg) => arg !== undefined) ?? [];\n return JSON.stringify(\n {\n mcp: {\n [target.name]: {\n type: 'local',\n command: [target.command ?? '', ...args],\n ...(env ? { environment: env } : {}),\n },\n },\n },\n null,\n 2,\n );\n }\n\n const headers = definedHeaders(target);\n return JSON.stringify(\n {\n mcp: {\n [target.name]: {\n type: 'remote',\n url: target.url,\n ...(headers ? { headers } : {}),\n },\n },\n },\n null,\n 2,\n );\n};\n\n// Cherry Studio's `ProtocolMcpServerConfigSchema` is a strict object: remote\n// servers use `baseUrl` + `type: 'sse' | 'streamableHttp'` (no `url` key) and\n// stdio servers use command/args/env. The install-time metadata\n// (`installSource`, `isTrusted`, `installedAt`, `isActive: false`) belongs to\n// `ProtocolMcpServerInstallSchema`, the install *request* schema, not to this\n// hand-pasted config; an entry carrying `isActive` would not satisfy\n// `ProtocolMcpServerConfigSchema` (which has no such key).\nconst cherryStudioSnippet = (target: ClientSnippetTarget): string => {\n const base = {\n name: target.name,\n description: target.description ?? '',\n };\n\n const headers = definedHeaders(target);\n const entry = isHttpTarget(target)\n ? {\n ...base,\n // The schema accepts exactly two remote transports; keep SSE upstreams\n // spelled out so Cherry Studio does not dial them as streamable HTTP.\n type: target.type === 'sse' ? 'sse' : 'streamableHttp',\n baseUrl: target.url,\n ...(headers ? { headers } : {}),\n }\n : { ...base, type: 'stdio', ...stdioEntry(target) };\n\n return withWrappedName('mcpServers', target.name, entry);\n};\n\nconst CLI_SAFE = /^[A-Za-z0-9._:@/=-]+$/;\n\n// Single quotes are the only reliable POSIX quoting for a pasted command:\n// double quotes still let the shell expand `$(...)`, backticks and `${...}`\n// inside them. Within single quotes nothing is expanded, so the only character\n// needing special handling is `'` itself, escaped as `'\\''` (close quote,\n// escaped quote, reopen).\nconst shellQuote = (value: string): string => `'${value.replace(/'/g, \"'\\\\''\")}'`;\n\nconst cliArg = (value: string): string =>\n CLI_SAFE.test(value) ? value : shellQuote(value);\n\n// Claude Code's one-liner equivalent of the JSON block, in the documented\n// HTTP shape: `claude mcp add --transport <t> <name> <url> [--header ...]`.\n//\n// A positional that starts with `-` cannot be spelled safely in that shape:\n// shell quoting is gone by the time the CLI's tokenizer sees the value, and\n// the documented `--` separator belongs to the stdio form, so relying on it\n// for the HTTP form would be an unverified parsing assumption. Since\n// SERVER_NAME_PATTERN admits names like `-foo`, a name or URL starting with\n// a dash omits the command block outright - the JSON config block still\n// carries the full entry - rather than emitting a command the CLI would\n// misparse as one of its own options.\nconst claudeCodeCommand = (target: ClientSnippetTarget): string | undefined => {\n if (!isHttpTarget(target)) {\n return undefined;\n }\n\n if (target.name.startsWith('-') || (target.url ?? '').startsWith('-')) {\n return undefined;\n }\n\n const parts = [\n 'claude',\n 'mcp',\n 'add',\n '--transport',\n // SSE endpoints must not be dialed as streamable HTTP.\n target.type === 'sse' ? 'sse' : 'http',\n cliArg(target.name),\n cliArg(target.url ?? ''),\n ];\n for (const [name, value] of Object.entries(definedHeaders(target) ?? {})) {\n parts.push('--header', cliArg(`${name}: ${value}`));\n }\n return parts.join(' ');\n};\n\nconst asString = (value: unknown): string | undefined =>\n typeof value === 'string' && value.length > 0 ? value : undefined;\n\n/** Narrow a stored `type` to the four legal server types; anything else is dropped. */\nconst asServerType = (value: unknown): ClientSnippetTarget['type'] => {\n switch (value) {\n case 'stdio':\n case 'sse':\n case 'streamable-http':\n case 'openapi':\n return value;\n default:\n return undefined;\n }\n};\n\nconst asStringRecord = (value: unknown): Record<string, string> | undefined => {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return undefined;\n }\n\n const entries = Object.entries(value as Record<string, unknown>).filter(\n (entry): entry is [string, string] => typeof entry[1] === 'string',\n );\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n};\n\nconst asStringArray = (value: unknown): string[] | undefined => {\n if (!Array.isArray(value)) {\n return undefined;\n }\n\n const items = value.filter((item): item is string => typeof item === 'string');\n return items.length > 0 ? items : undefined;\n};\n\n/**\n * Narrow a stored server configuration (the `mcp-settings/export` payload\n * carries MCPHub's internal fields too) down to what a client snippet needs.\n */\nexport const toClientSnippetTarget = (\n name: string,\n config: Record<string, unknown> | undefined,\n): ClientSnippetTarget => {\n const source = config ?? {};\n\n return {\n name,\n ...(asServerType(source.type) ? { type: asServerType(source.type) } : {}),\n ...(asString(source.url) ? { url: asString(source.url) } : {}),\n ...(asStringRecord(source.headers) ? { headers: asStringRecord(source.headers) } : {}),\n ...(asString(source.command) ? { command: asString(source.command) } : {}),\n ...(asStringArray(source.args) ? { args: asStringArray(source.args) } : {}),\n ...(asStringRecord(source.env) ? { env: asStringRecord(source.env) } : {}),\n ...(asString(source.description) ? { description: asString(source.description) } : {}),\n };\n};\n\nconst configSnippet = (\n id: ClientSnippetId,\n target: ClientSnippetTarget,\n options: ClientSnippetOptions,\n): string => {\n switch (id) {\n case 'generic-mcp-servers':\n return jsonSnippet(target);\n case 'generic-http':\n return JSON.stringify(\n isHttpTarget(target)\n ? { type: 'http', ...httpEntry(target) }\n : stdioEntry(target),\n null,\n 2,\n );\n case 'vscode':\n return vscodeSnippet(target, options);\n case 'codex':\n return codexSnippet(target);\n case 'opencode':\n return openCodeSnippet(target);\n case 'cherry-studio':\n return cherryStudioSnippet(target);\n case 'claude-code':\n return withWrappedName('mcpServers', target.name, typedTransportEntry(target));\n case 'codebuddy':\n // CodeBuddy's field table marks `type` as Required, fixed to `\"stdio\"`\n // for stdio entries, so unlike Claude Code it always carries the type.\n return withWrappedName('mcpServers', target.name, typedTransportEntry(target, true));\n default:\n return jsonSnippet(target);\n }\n};\n\nexport const buildClientSnippetBlocks = (\n id: ClientSnippetId,\n target: ClientSnippetTarget,\n options: ClientSnippetOptions = {},\n): ClientSnippetBlock[] => {\n // OpenAPI-backed servers carry neither a URL nor a command, so every preset\n // would degrade to filler like `command: \"\"`. Return no blocks and let the\n // dialog explain that there is no client-side transport to copy.\n if (!target.url && !target.command) {\n return [];\n }\n\n const blocks: ClientSnippetBlock[] = [{ kind: 'config', text: configSnippet(id, target, options) }];\n\n if (id === 'claude-code') {\n const command = claudeCodeCommand(target);\n if (command) {\n blocks.push({ kind: 'command', text: command });\n }\n }\n\n return blocks;\n};\n","import { useEffect, useMemo, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Check, Copy, X } from 'lucide-react';\nimport {\n buildClientSnippetBlocks,\n CLIENT_SNIPPET_PRESETS,\n DEFAULT_CLIENT_SNIPPET_ID,\n type ClientSnippetId,\n type ClientSnippetTarget,\n} from '@/utils/mcpClientSnippets';\nimport { copyText } from '@/utils/clipboard';\nimport { useToast } from '@/contexts/ToastContext';\n\ninterface CopyClientConfigDialogProps {\n isOpen: boolean;\n onClose: () => void;\n /** Target to render; `null` keeps the dialog closed. */\n target: ClientSnippetTarget | null;\n}\n\n/**\n * Per-client MCP configuration presets for the copy actions (#1165): one tab\n * per client, each with the path it belongs in and a ready-to-paste snippet.\n */\nconst CopyClientConfigDialog = ({ isOpen, onClose, target }: CopyClientConfigDialogProps) => {\n const { t } = useTranslation();\n const { showToast } = useToast();\n const [activeId, setActiveId] = useState<ClientSnippetId>(DEFAULT_CLIENT_SNIPPET_ID);\n const [copiedBlock, setCopiedBlock] = useState<string | null>(null);\n const dialogRef = useRef<HTMLDivElement>(null);\n const returnFocusRef = useRef<HTMLElement | null>(null);\n\n useEffect(() => {\n if (!isOpen) {\n setCopiedBlock(null);\n setActiveId(DEFAULT_CLIENT_SNIPPET_ID);\n }\n }, [isOpen]);\n\n // Like the other hand-rolled modals in this codebase the dialog does not trap\n // focus; it does move focus inside on open and hand it back to the trigger on\n // close, so keyboard users are not left behind on the page underneath.\n useEffect(() => {\n if (!isOpen) return;\n returnFocusRef.current =\n document.activeElement instanceof HTMLElement ? document.activeElement : null;\n dialogRef.current?.focus();\n\n return () => {\n returnFocusRef.current?.focus();\n };\n }, [isOpen]);\n\n useEffect(() => {\n if (!isOpen) return;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') onClose();\n };\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, [isOpen, onClose]);\n\n const blocks = useMemo(\n () =>\n target\n ? buildClientSnippetBlocks(activeId, target, {\n tokenPromptDescription: t('clientConfig.tokenPrompt'),\n })\n : [],\n [activeId, target, t],\n );\n\n if (!isOpen || !target) {\n return null;\n }\n\n const handleCopy = async (key: string, value: string) => {\n const ok = await copyText(value);\n if (!ok) {\n showToast(t('common.copyFailed'), 'error');\n return;\n }\n setCopiedBlock(key);\n showToast(t('common.copySuccess'), 'success');\n setTimeout(() => setCopiedBlock((current) => (current === key ? null : current)), 1500);\n };\n\n return (\n <div\n className=\"fixed inset-0 bg-black/50 z-[100] flex items-center justify-center p-4\"\n onClick={(event) => {\n if (event.target === event.currentTarget) onClose();\n }}\n >\n <div\n ref={dialogRef}\n tabIndex={-1}\n className=\"hub-card w-full max-w-2xl\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={t('clientConfig.title')}\n >\n <div\n className=\"flex items-start justify-between gap-3 px-4 py-3\"\n style={{ borderBottom: '1px solid var(--hub-line-2)' }}\n >\n <div className=\"min-w-0\">\n <div className=\"text-[14px] font-medium\" style={{ color: 'var(--hub-ink)' }}>\n {t('clientConfig.title')}\n </div>\n <div className=\"text-[12px] mt-0.5\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('clientConfig.description', { name: target.name })}\n </div>\n </div>\n <button className=\"hub-icon-btn sm\" onClick={onClose} aria-label={t('app.closeButton')}>\n <X size={13} />\n </button>\n </div>\n\n {/* A target with neither URL nor command (OpenAPI-backed servers) has no\n transport, so every preset returns the same empty result: offering 14\n clickable tabs would only suggest the dialog is broken. The tab strip\n and its per-client hint are therefore hidden and only the explanation\n below is shown. */}\n {blocks.length > 0 && (\n <div className=\"px-4 pt-3\">\n <div\n className=\"flex flex-wrap gap-1\"\n role=\"tablist\"\n aria-label={t('clientConfig.title')}\n >\n {CLIENT_SNIPPET_PRESETS.map((preset) => {\n const active = preset.id === activeId;\n return (\n <button\n key={preset.id}\n role=\"tab\"\n aria-selected={active}\n onClick={() => setActiveId(preset.id)}\n className=\"px-2.5 py-1 rounded-md text-[12px] transition-colors hover:bg-[var(--hub-surface-hover)]\"\n style={{\n background: active ? 'var(--hub-surface)' : 'transparent',\n border: '1px solid ' + (active ? 'var(--hub-line)' : 'transparent'),\n color: active ? 'var(--hub-ink)' : 'var(--hub-ink-2)',\n }}\n >\n {t(`clientConfig.clients.${preset.id}.label`)}\n </button>\n );\n })}\n </div>\n\n <p className=\"text-[12px] mt-3\" style={{ color: 'var(--hub-ink-3)' }}>\n {t(`clientConfig.clients.${activeId}.hint`)}\n </p>\n </div>\n )}\n\n <div className=\"px-4 pb-4 pt-2 space-y-3 max-h-[60vh] overflow-auto\">\n {blocks.length === 0 ? (\n // OpenAPI-backed servers have no client-side transport to copy.\n <p className=\"text-[12px]\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('clientConfig.noTransport')}\n </p>\n ) : (\n blocks.map((block) => {\n const key = `${activeId}:${block.kind}`;\n const copied = copiedBlock === key;\n return (\n <div key={key}>\n <div className=\"flex items-center justify-between mb-1\">\n <span className=\"text-[12px]\" style={{ color: 'var(--hub-ink-2)' }}>\n {t(\n block.kind === 'command'\n ? 'clientConfig.commandBlock'\n : 'clientConfig.configBlock',\n )}\n </span>\n <button\n className=\"hub-btn sm\"\n onClick={() => void handleCopy(key, block.text)}\n >\n {copied ? <Check size={12} className=\"text-[var(--hub-ok)]\" /> : <Copy size={12} />}\n {copied ? t('clientConfig.copied') : t('common.copy')}\n </button>\n </div>\n <pre\n className=\"hub-mono m-0 p-3 rounded-md overflow-auto\"\n style={{\n background: 'var(--hub-bg-2)',\n border: '1px solid var(--hub-line-2)',\n fontSize: 12,\n lineHeight: 1.5,\n color: 'var(--hub-ink-2)',\n maxHeight: 320,\n }}\n >\n <code>{block.text}</code>\n </pre>\n </div>\n );\n })\n )}\n </div>\n\n <div\n className=\"flex justify-end px-4 py-3\"\n style={{ borderTop: '1px solid var(--hub-line-2)' }}\n >\n <button className=\"hub-btn\" onClick={onClose}>\n {t('common.cancel')}\n </button>\n </div>\n </div>\n </div>\n );\n};\n\nexport default CopyClientConfigDialog;\n"],"names":["normalizeDescription","description","fallback","getToolDescriptionInfo","tool","noDescriptionText","currentDescription","DEFAULT_CLIENT_SNIPPET_ID","CLIENT_SNIPPET_PRESETS","ACCESS_TOKEN_PLACEHOLDER","TOKEN_INPUT_ID","isHttpTarget","target","definedHeaders","entries","value","definedEnv","stdioEntry","args","_a","arg","env","typedTransportEntry","stdioType","headers","httpEntry","withWrappedName","wrapper","name","entry","jsonSnippet","vscodeSnippet","options","placeholder","needsTokenInput","body","TOML_BARE_KEY","tomlKey","key","tomlValue","tomlInlineTable","codexSnippet","lines","openCodeSnippet","cherryStudioSnippet","base","CLI_SAFE","shellQuote","cliArg","claudeCodeCommand","parts","asString","asServerType","asStringRecord","asStringArray","items","item","toClientSnippetTarget","config","source","configSnippet","id","buildClientSnippetBlocks","blocks","command","CopyClientConfigDialog","isOpen","onClose","useTranslation","showToast","useToast","activeId","setActiveId","useState","copiedBlock","setCopiedBlock","dialogRef","useRef","returnFocusRef","useEffect","onKeyDown","event","useMemo","handleCopy","copyText","current","jsx","jsxs","X","preset","active","block","copied","Check","Copy"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{i as b,r as l,j as s}from"./framework-vendor-CQFm9vKd.js";import{f as v,h as j,i as N}from"./index-DL9uGzQF.js";import{u as f}from"./i18n-vendor-DVmjrzgW.js";import"./icons-vendor-CkcU1LMA.js";const g=({binding:a,onChange:u})=>{const{t:r}=f(),[n,m]=l.useState({}),[p,x]=l.useState(!1),[i,d]=l.useState(""),o=async t=>{x(!0),d("");try{const e=`/credentials/${encodeURIComponent(a.serverName)}`,h=t?await j(e):await N(e,{values:n});if(!h.success)throw new Error(h.message||r("credentials.failed"));m({}),d(r(t?"credentials.deleted":"credentials.saved")),await u()}catch(e){d(e instanceof Error?e.message:r("credentials.failed"))}finally{x(!1)}};return s.jsxs("form",{className:"hub-card p-5 space-y-4",onSubmit:t=>{t.preventDefault(),o(!1)},children:[s.jsxs("div",{className:"flex items-center justify-between gap-3",children:[s.jsx("h2",{className:"font-semibold",children:a.serverName}),s.jsx("span",{className:"hub-tag",children:r(a.configured?"credentials.configured":"credentials.required")})]}),s.jsx("p",{className:"text-sm text-[var(--hub-ink-3)]",children:r("credentials.writeOnly")}),a.credentialTemplate.map(t=>{var h;const e=`${t.target}.${t.name}`;return s.jsxs("label",{className:"block space-y-1 text-sm",children:[s.jsxs("span",{className:"font-medium",children:[t.label||t.name," ",s.jsxs("span",{className:"hub-mono text-xs font-normal text-[var(--hub-ink-3)]",children:["(",e,")"]})]}),t.target==="url"?s.jsxs("select",{required:!0,className:"hub-input",value:n[e]||"",onChange:c=>m({...n,[e]:c.target.value}),children:[s.jsx("option",{value:"",children:r("credentials.enterValue")}),(h=t.allowed)==null?void 0:h.map(c=>s.jsx("option",{value:c,children:c},c))]}):s.jsx("input",{type:"password",required:!0,autoComplete:"new-password",maxLength:16384,value:n[e]||"",placeholder:r(a.configuredSlots.includes(e)?"credentials.replaceValue":"credentials.enterValue"),className:"hub-input",onChange:c=>m({...n,[e]:c.target.value})})]},e)}),s.jsxs("div",{className:"flex flex-wrap gap-2",children:[s.jsx("button",{type:"submit",className:"hub-btn primary",disabled:p,children:r("credentials.save")}),s.jsx("button",{type:"button",className:"hub-btn danger",disabled:p||!a.updatedAt,onClick:()=>void o(!0),children:r("credentials.delete")})]}),i&&s.jsx("p",{role:"status",className:"text-sm text-[var(--hub-ink-2)]",children:i})]})};function k(){const{t:a}=f(),[u,r]=b(),[n,m]=l.useState([]),[p,x]=l.useState(!0),[i,d]=l.useState(""),o=l.useCallback(async()=>{try{const e=await v("/credentials");if(!e.success)throw new Error(e.message||a("credentials.failed"));m(e.data||[]),d("")}catch(e){d(e instanceof Error?e.message:a("credentials.failed"))}finally{x(!1)}},[a]);l.useEffect(()=>{o()},[o]);const t=n.filter(e=>!u.get("server")||e.serverName===u.get("server"));return s.jsxs("div",{className:"max-w-4xl mx-auto space-y-5",children:[s.jsxs("div",{children:[s.jsx("h1",{className:"hub-h1",children:a("credentials.title")}),s.jsx("p",{className:"hub-sub",children:a("credentials.description")})]}),u.has("server")&&s.jsx("button",{className:"hub-btn",onClick:()=>r({}),children:a("credentials.showAll")}),i&&s.jsx("div",{className:"hub-card px-4 py-3 text-sm",style:{color:"var(--hub-err)"},role:"alert",children:i}),p?s.jsx("div",{className:"hub-card p-10 text-center text-sm",style:{color:"var(--hub-ink-3)"},children:a("credentials.loading")}):!t.length&&!i?s.jsx("div",{className:"hub-card p-10 text-center text-sm",style:{color:"var(--hub-ink-3)"},children:a("credentials.empty")}):null,t.map(e=>s.jsx(g,{binding:e,onChange:o},e.serverName))]})}export{k as default};
|
|
2
|
-
//# sourceMappingURL=CredentialsPage-D8mMIH5f.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CredentialsPage-D8mMIH5f.js","sources":["../../src/pages/CredentialsPage.tsx"],"sourcesContent":["import { useCallback, useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useSearchParams } from 'react-router-dom';\nimport type { MyCredentialBinding } from '../types';\nimport { apiDelete, apiGet, apiPut, type ApiResponse } from '../utils/fetchInterceptor';\n\nconst CredentialForm = ({\n binding,\n onChange,\n}: {\n binding: MyCredentialBinding;\n onChange: () => Promise<void>;\n}) => {\n const { t } = useTranslation();\n const [values, setValues] = useState<Record<string, string>>({});\n const [busy, setBusy] = useState(false);\n const [message, setMessage] = useState('');\n const save = async (remove: boolean) => {\n setBusy(true);\n setMessage('');\n try {\n const url = `/credentials/${encodeURIComponent(binding.serverName)}`;\n const result = remove\n ? await apiDelete<ApiResponse>(url)\n : await apiPut<ApiResponse>(url, { values });\n if (!result.success) throw new Error(result.message || t('credentials.failed'));\n setValues({});\n setMessage(t(remove ? 'credentials.deleted' : 'credentials.saved'));\n await onChange();\n } catch (error) {\n setMessage(error instanceof Error ? error.message : t('credentials.failed'));\n } finally {\n setBusy(false);\n }\n };\n return (\n <form\n className=\"hub-card p-5 space-y-4\"\n onSubmit={(event) => {\n event.preventDefault();\n void save(false);\n }}\n >\n <div className=\"flex items-center justify-between gap-3\">\n <h2 className=\"font-semibold\">{binding.serverName}</h2>\n <span className=\"hub-tag\">\n {t(binding.configured ? 'credentials.configured' : 'credentials.required')}\n </span>\n </div>\n <p className=\"text-sm text-[var(--hub-ink-3)]\">{t('credentials.writeOnly')}</p>\n {binding.credentialTemplate.map((slot) => {\n const id = `${slot.target}.${slot.name}`;\n return (\n <label key={id} className=\"block space-y-1 text-sm\">\n <span className=\"font-medium\">\n {slot.label || slot.name}{' '}\n <span className=\"hub-mono text-xs font-normal text-[var(--hub-ink-3)]\">({id})</span>\n </span>\n {slot.target === 'url' ? (\n <select\n required\n className=\"hub-input\"\n value={values[id] || ''}\n onChange={(event) => setValues({ ...values, [id]: event.target.value })}\n >\n <option value=\"\">{t('credentials.enterValue')}</option>\n {slot.allowed?.map((value) => (\n <option key={value} value={value}>\n {value}\n </option>\n ))}\n </select>\n ) : (\n <input\n type=\"password\"\n required\n autoComplete=\"new-password\"\n maxLength={16384}\n value={values[id] || ''}\n placeholder={t(\n binding.configuredSlots.includes(id)\n ? 'credentials.replaceValue'\n : 'credentials.enterValue',\n )}\n className=\"hub-input\"\n onChange={(event) => setValues({ ...values, [id]: event.target.value })}\n />\n )}\n </label>\n );\n })}\n <div className=\"flex flex-wrap gap-2\">\n <button type=\"submit\" className=\"hub-btn primary\" disabled={busy}>\n {t('credentials.save')}\n </button>\n <button\n type=\"button\"\n className=\"hub-btn danger\"\n disabled={busy || !binding.updatedAt}\n onClick={() => void save(true)}\n >\n {t('credentials.delete')}\n </button>\n </div>\n {message && (\n <p role=\"status\" className=\"text-sm text-[var(--hub-ink-2)]\">\n {message}\n </p>\n )}\n </form>\n );\n};\n\nexport default function CredentialsPage() {\n const { t } = useTranslation();\n const [search, setSearch] = useSearchParams();\n const [bindings, setBindings] = useState<MyCredentialBinding[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState('');\n const reload = useCallback(async () => {\n try {\n const result = await apiGet<ApiResponse<MyCredentialBinding[]>>('/credentials');\n if (!result.success) throw new Error(result.message || t('credentials.failed'));\n setBindings(result.data || []);\n setError('');\n } catch (error) {\n setError(error instanceof Error ? error.message : t('credentials.failed'));\n } finally {\n setLoading(false);\n }\n }, [t]);\n useEffect(() => {\n void reload();\n }, [reload]);\n const visible = bindings.filter(\n (binding) => !search.get('server') || binding.serverName === search.get('server'),\n );\n return (\n <div className=\"max-w-4xl mx-auto space-y-5\">\n <div>\n <h1 className=\"hub-h1\">{t('credentials.title')}</h1>\n <p className=\"hub-sub\">{t('credentials.description')}</p>\n </div>\n {search.has('server') && (\n <button className=\"hub-btn\" onClick={() => setSearch({})}>\n {t('credentials.showAll')}\n </button>\n )}\n {error && (\n <div\n className=\"hub-card px-4 py-3 text-sm\"\n style={{ color: 'var(--hub-err)' }}\n role=\"alert\"\n >\n {error}\n </div>\n )}\n {loading ? (\n <div className=\"hub-card p-10 text-center text-sm\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('credentials.loading')}\n </div>\n ) : !visible.length && !error ? (\n <div className=\"hub-card p-10 text-center text-sm\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('credentials.empty')}\n </div>\n ) : null}\n {visible.map((binding) => (\n <CredentialForm key={binding.serverName} binding={binding} onChange={reload} />\n ))}\n </div>\n );\n}\n"],"names":["CredentialForm","binding","onChange","t","useTranslation","values","setValues","useState","busy","setBusy","message","setMessage","save","remove","url","result","apiDelete","apiPut","error","jsxs","event","jsx","slot","id","_a","value","CredentialsPage","search","setSearch","useSearchParams","bindings","setBindings","loading","setLoading","setError","reload","useCallback","apiGet","useEffect","visible"],"mappings":"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"}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import{r as g,j as e,R as M}from"./framework-vendor-CQFm9vKd.js";import{n as Z,f as fe,d as ee,u as ve,j as je,k as se}from"./index-DL9uGzQF.js";import{u as te,a as re}from"./useCostData-BuDleGRv.js";import{u as G}from"./i18n-vendor-DVmjrzgW.js";import{u as me,c as ye}from"./clipboard-BrGjez3U.js";import{f as H,p as Ne}from"./contextCost-CilWqGWT.js";import{g as ke,A as Se,C as we}from"./CopyClientConfigDialog-xeHg7JJj.js";import{W as Ce,g as Ae,F as Te,H as Ee,C as De,r as Q,J as oe,z as Ie,w as Fe,T as ze,n as Pe,D as ce,N as Re,P as de,l as Le,X as Ue}from"./icons-vendor-CkcU1LMA.js";import{D as $e}from"./DeleteDialog-BaCsEkJA.js";const Oe=["read","create","update","delete","other"],Ge=a=>{var s,l,h;if(((s=a.annotations)==null?void 0:s.readOnlyHint)===!0)return"read";const m=a.value.toLowerCase();return/^(delete|remove)[_-]/.test(m)?"delete":((l=a.annotations)==null?void 0:l.destructiveHint)===!0?"other":/^(create|add)[_-]/.test(m)?"create":/^(update|set)[_-]/.test(m)?"update":((h=a.annotations)==null?void 0:h.readOnlyHint)!==!1&&/^(get|list|read|search)[_-]/.test(m)?"read":"other"},We=(a,m,s)=>{const l=m.trim().toLowerCase();return a.filter(h=>{var i,p;return(h.value.toLowerCase().includes(l)||((i=h.description)==null?void 0:i.toLowerCase().includes(l)))&&(s==="all"||((p=h.annotations)==null?void 0:p[s])===!0)})},Me=(a,m,s,l)=>{if(s.length===0||a==="all"&&l==="select")return a;const h=new Set(a==="all"?m:a);for(const i of s)l==="deselect"||l==="invert"&&h.has(i)?h.delete(i):h.add(i);return[...h]},He=({items:a,selection:m,tools:s,label:l,onChange:h,children:i})=>{const{t:p}=G(),[E,I]=g.useState(""),[N,A]=g.useState("all"),[x,w]=g.useState(!1),j=We(a,E,N),T=new Set(m==="all"?a.map(t=>t.value):m),d=(t,o)=>h(Me(m,a.map(c=>c.value),t.map(c=>c.value),o)),b=s&&x?Oe.map(t=>({risk:t,items:j.filter(o=>Ge(o)===t)})):[{risk:null,items:j}],f="text-xs text-blue-600 hover:text-blue-800 disabled:opacity-40 disabled:cursor-not-allowed";return e.jsxs("section",{"aria-label":l,children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2 mb-2",children:[e.jsx("input",{type:"search","aria-label":p("groups.bulkSearchLabel",{capability:l}),placeholder:p("groups.bulkSearch"),value:E,onChange:t=>I(t.target.value),className:"min-w-0 flex-1 basis-48 rounded border border-gray-300 bg-white dark:bg-gray-800 px-2 py-1 text-sm"}),s&&e.jsxs(e.Fragment,{children:[e.jsxs("select",{"aria-label":p("groups.annotationFilter"),value:N,onChange:t=>A(t.target.value),className:"max-w-full rounded border border-gray-300 bg-white dark:bg-gray-800 px-2 py-1 text-sm",children:[e.jsx("option",{value:"all",children:p("groups.allAnnotations")}),["readOnlyHint","destructiveHint","idempotentHint"].map(t=>e.jsx("option",{value:t,children:p(`groups.${t}`)},t))]}),e.jsx("button",{type:"button","aria-pressed":x,onClick:()=>w(!x),className:f,children:p(x?"groups.flatList":"groups.riskGroups")})]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-x-3 gap-y-1 mb-2",children:[e.jsx("span",{className:"text-xs text-gray-500",role:"status",children:p("groups.visibleCount",{count:j.length,total:a.length})}),["select","deselect","invert"].map(t=>e.jsx("button",{type:"button",disabled:!j.length,onClick:()=>d(j,t),className:f,children:p(`groups.${t}Visible`)},t))]}),s&&x&&e.jsx("p",{className:"text-xs text-gray-500 mb-2",children:p("groups.riskHint")}),e.jsxs("div",{className:"grid grid-cols-1 gap-2 max-h-96 overflow-y-auto",children:[j.length===0&&e.jsx("p",{className:"text-sm text-gray-500",children:p("groups.noMatchingItems")}),b.filter(t=>t.items.length>0).map(t=>{const o=t.items.filter(c=>T.has(c.value)).length;return e.jsxs(M.Fragment,{children:[t.risk&&e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2 border-b border-gray-200 py-1",children:[e.jsxs("span",{className:"text-xs font-medium",children:[p(`groups.risk_${t.risk}`)," (",o,"/",t.items.length,")"]}),e.jsx("button",{type:"button",className:f,onClick:()=>d(t.items,o===t.items.length?"deselect":"select"),children:p(o===t.items.length?"groups.selectNone":"groups.selectAll")})]}),t.items.map(c=>e.jsx(M.Fragment,{children:i(c)},c.value))]},t.risk??"flat")})]})]})},_e={tools:[],prompts:[],resources:[]},ue={tools:"all",prompts:"all",resources:"all"},pe=({servers:a,value:m,onChange:s,className:l,serverCosts:h=[]})=>{const{t:i}=G(),p=M.useId(),{nameSeparator:E,smartRoutingConfig:I}=me(),[N,A]=g.useState(new Set),x=M.useMemo(()=>m.map(r=>typeof r=="string"?{name:r,...ue}:{...r,tools:r.tools||"all",prompts:r.prompts||"all",resources:r.resources||"all"}),[m]),w=M.useMemo(()=>a.filter(r=>r.enabled!==!1),[a]);M.useEffect(()=>{const r=new Set(x.map(n=>n.name)),u=new Set(w.map(n=>n.name));A(n=>{const S=new Set;return n.forEach(v=>{(r.has(v)||u.has(v))&&S.add(v)}),S})},[x,w]);const j=r=>{if(x.findIndex(n=>n.name===r)>=0){const n=x.filter(S=>S.name!==r);s(n)}else{const n=[...x,{name:r,...ue}];s(n)}},T=r=>{A(u=>{const n=new Set(u);return n.has(r)?n.delete(r):n.add(r),n})},d=r=>["tools","prompts","resources"].some(u=>{const n=r[u];return n==="all"||Array.isArray(n)&&n.length>0}),b=(r,u,n,S=!1)=>{const v=x.find(k=>k.name===r),F={...v?{...v}:{name:r,..._e},[u]:n};if(u==="tools"&&Array.isArray(n)&&F.pinnedTools&&(F.pinnedTools=F.pinnedTools.filter(k=>n.includes(k)),F.pinnedTools.length===0&&delete F.pinnedTools),!d(F)){const k=x.filter(y=>y.name!==r);s(k),S||A(y=>{const $=new Set(y);return $.delete(r),$});return}if(v){s(x.map(k=>k.name===r?F:k));return}s([...x,F])},f=(r,u)=>{const n=x.find(v=>v.name===r);if(!n)return;const S={...n};u?S.alias=u:delete S.alias,s(x.map(v=>v.name===r?S:v))},t=(r,u)=>{const n=x.find(P=>P.name===r);if(!n)return;const S=n.pinnedTools??[],v={...n,pinnedTools:S.includes(u)?S.filter(P=>P!==u):[...S,u]};v.pinnedTools.length===0&&delete v.pinnedTools,s(x.map(P=>P.name===r?v:P))},o=(r,u)=>{const n=`${r}${E}`;return u.startsWith(n)?u.slice(n.length):u},c=(r,u)=>u==="tools"?(r.tools||[]).filter(n=>n.enabled!==!1).map(n=>({key:n.name,value:o(r.name,n.name),description:n.description,annotations:n.annotations,defaultDescription:n.defaultDescription,hasDescriptionOverride:n.hasDescriptionOverride})):u==="prompts"?(r.prompts||[]).filter(n=>n.enabled!==!1).map(n=>({key:n.name,value:o(r.name,n.name),description:n.description})):(r.resources||[]).filter(n=>n.enabled!==!1).map(n=>({key:n.uri,value:n.uri,description:n.description})),C=M.useMemo(()=>{const r=new Map;return h.forEach(u=>{const n=new Map;u.items.forEach(S=>n.set(S.name,S.cost)),r.set(u.name,n)}),r},[h]),z=r=>C.get(r)??new Map,O=(r,u)=>{const n=z(r.name);return c(r,u).filter(S=>J(r.name,u,S.value)).reduce((S,v)=>S+(n.get(v.key)??0),0)},_=r=>["tools","prompts","resources"].reduce((u,n)=>u+O(r,n),0),X=(r,u,n)=>{const S=w.find(k=>k.name===r);if(!S)return;const v=c(S,u).map(k=>k.value),P=x.find(k=>k.name===r);if(!P){b(r,u,[n]);return}const F=P[u];if(F==="all"){const k=v.filter(y=>y!==n);b(r,u,k);return}if(Array.isArray(F)){if(F.includes(n)){b(r,u,F.filter(y=>y!==n));return}const k=[...F,n];b(r,u,k.length===v.length?"all":k);return}b(r,u,[n])},W=r=>{const u=x.find(n=>n.name===r);return!!(u&&d(u))},K=r=>{const u=x.find(n=>n.name===r);return u?["tools","prompts","resources"].some(n=>{const S=u[n];return Array.isArray(S)&&S.length>0}):!1},J=(r,u,n)=>{const S=x.find(P=>P.name===r);if(!S)return!1;const v=S[u];return v==="all"?!0:Array.isArray(v)?v.includes(n):!1},B=(r,u)=>{const n=x.find(P=>P.name===r.name);if(!n)return 0;const S=c(r,u),v=n[u];if(v==="all")return S.length;if(Array.isArray(v)){const P=new Set(S.map(F=>F.value));return v.filter(F=>P.has(F)).length}return 0},D=[{key:"tools",titleKey:"groups.toolSelection",countKey:"groups.toolsSelected",allKey:"groups.allTools"},{key:"prompts",titleKey:"groups.promptSelection",countKey:"groups.promptsSelected",allKey:"groups.allPrompts"},{key:"resources",titleKey:"groups.resourceSelection",countKey:"groups.resourcesSelected",allKey:"groups.allResources"}],R=r=>D.map(({key:u})=>({key:u,count:B(r,u)})).filter(u=>u.count>0);return e.jsxs("div",{className:Z("space-y-4",l),children:[e.jsx("div",{className:"space-y-3",children:w.map(r=>{const u=W(r.name),n=K(r.name),S=N.has(r.name),v=x.find(y=>y.name===r.name),P=R(r),F=D.filter(({key:y})=>c(r,y).length>0),k=z(r.name);return e.jsxs("div",{className:"border border-[var(--hub-line)] rounded-lg bg-[var(--hub-surface)] hover:border-[var(--hub-ink-3)] hover:bg-[var(--hub-surface-hover)] transition-colors",children:[e.jsxs("div",{className:"flex items-center justify-between p-3 cursor-pointer rounded-lg transition-colors",onClick:()=>T(r.name),children:[e.jsxs("div",{className:"flex items-center space-x-3",onClick:y=>{y.stopPropagation(),j(r.name)},children:[e.jsx("input",{type:"checkbox",checked:u||n,onChange:()=>j(r.name),className:"w-4 h-4 text-blue-600 accent-[var(--hub-accent)] rounded focus:ring-blue-500"}),e.jsx("span",{className:"font-medium text-[var(--hub-ink)] cursor-pointer select-none",children:r.name})]}),e.jsxs("div",{className:"flex items-center space-x-3",children:[_(r)>0&&e.jsxs("span",{className:"text-sm text-[var(--hub-ink-3)] hub-mono",title:i("cost.estimate"),children:["Σ ",H(_(r))]}),P.map(({key:y,count:$})=>e.jsxs("span",{className:"text-sm text-green-600 flex items-center gap-1",children:[y==="tools"?e.jsx(Ce,{size:14}):y==="prompts"?e.jsx(Ae,{size:14}):e.jsx(Te,{size:14})," ",$]},y)),F.length>0&&e.jsx("button",{type:"button",className:"p-1 text-[var(--hub-ink-3)] hover:text-[var(--hub-ink-2)] transition-colors",children:e.jsx("svg",{className:Z("w-5 h-5 transition-transform",S&&"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"})})})]})]}),S&&F.length>0&&e.jsx("div",{className:"border-t border-[var(--hub-line)] bg-[var(--hub-bg-2)] p-3",children:e.jsxs("div",{className:"space-y-4",children:[v&&e.jsxs("div",{className:"space-y-1",onClick:y=>y.stopPropagation(),children:[e.jsx("label",{htmlFor:`${p}-${r.name}`,className:"block text-xs font-medium text-[var(--hub-ink-2)]",children:i("groups.alias")}),e.jsx("input",{type:"text",id:`${p}-${r.name}`,value:v.alias||"",placeholder:r.name,onChange:y=>f(r.name,y.target.value),className:"hub-input"}),e.jsxs("label",{className:"flex items-center gap-2 text-xs text-[var(--hub-ink-2)]",children:[e.jsx("input",{type:"checkbox",checked:v.preserveToolNames===!0,onChange:y=>s(x.map($=>$.name===r.name?{...$,preserveToolNames:y.target.checked}:$))}),i("groups.preserveToolNames")]}),e.jsx("p",{className:"text-xs text-[var(--hub-ink-3)]",children:i("groups.preserveToolNamesHint")})]}),F.map(({key:y,titleKey:$,countKey:be,allKey:ge})=>{const V=c(r,y),ae=B(r,y),Y=(v==null?void 0:v[y])==="all"||ae===V.length;return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsx("span",{className:"text-sm font-medium text-[var(--hub-ink-2)]",children:i($)}),e.jsxs("div",{className:"flex items-center gap-3",children:[v&&e.jsx("span",{className:"text-xs text-green-600",children:Y?`(${i(ge)} ${V.length}/${V.length})`:`(${i(be)} ${ae}/${V.length})`}),v&&O(r,y)>0&&e.jsxs("span",{className:"text-xs text-[var(--hub-ink-3)] hub-mono",title:i("cost.estimate"),children:["Σ ",H(O(r,y))]}),e.jsx("button",{type:"button",onClick:()=>{b(r.name,y,Y?[]:"all",!0)},className:"text-sm text-blue-600 hover:text-blue-800 transition-colors",children:i(Y?"groups.selectNone":"groups.selectAll")})]})]}),e.jsx(He,{items:V,selection:(v==null?void 0:v[y])??[],tools:y==="tools",label:i($),onChange:L=>b(r.name,y,L,!0),children:L=>{var ie;const ne=J(r.name,y,L.value),q=!!((ie=v==null?void 0:v.pinnedTools)!=null&&ie.includes(L.value)),U=y==="tools"?ke({description:L.description,defaultDescription:L.defaultDescription,hasDescriptionOverride:L.hasDescriptionOverride},i("tool.noDescription")):null,le=U!=null&&U.hasDescriptionOverride?i("tool.defaultDescriptionTooltip",{description:U.defaultDescription}):L.description;return e.jsxs("div",{className:"flex min-w-0 items-center gap-2",children:[e.jsxs("label",{className:"flex min-w-0 flex-1 items-center gap-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:ne,onChange:()=>X(r.name,y,L.value),className:"w-3 h-3 text-blue-600 accent-[var(--hub-accent)] rounded focus:ring-blue-500"}),e.jsx("span",{className:"text-[var(--hub-ink-2)] break-all whitespace-nowrap flex-shrink-0",children:L.value}),(L.description||(U==null?void 0:U.hasDescriptionOverride))&&e.jsxs("span",{className:"min-w-0 flex items-center gap-1 text-[var(--hub-ink-3)] text-xs truncate",children:[e.jsx("span",{className:"truncate",title:le||void 0,children:U?U.currentDescription:L.description}),(U==null?void 0:U.hasDescriptionOverride)&&e.jsx("span",{className:"inline-flex flex-shrink-0 items-center rounded-full border border-amber-200 bg-amber-50 px-1.5 py-0.5 text-[10px] font-medium text-amber-700 dark:border-amber-700/60 dark:bg-amber-900/20 dark:text-amber-300",title:le||void 0,children:i("tool.descriptionModifiedBadge")})]}),k.get(L.key)!=null&&e.jsxs("span",{className:"text-xs text-[var(--hub-ink-3)] hub-mono whitespace-nowrap ml-auto flex-shrink-0",title:i("cost.estimate"),children:["Σ ",H(k.get(L.key))]})]}),y==="tools"&&ne&&(I.enabled||q)&&e.jsx("button",{type:"button",onClick:()=>t(r.name,L.value),title:i(q?"groups.unpinTool":"groups.pinTool"),"aria-label":i("groups.pinToolLabel"),"aria-pressed":q,className:Z("flex-shrink-0 transition-colors",q?"text-blue-600":"text-[var(--hub-ink-3)] hover:text-[var(--hub-ink-2)]"),children:e.jsx(Ee,{size:12,fill:q?"currentColor":"none"})})]},L.key)}})]},y)})]})})]},r.name)})}),w.length===0&&e.jsx("p",{className:"text-[var(--hub-ink-3)] text-sm",children:i("groups.noServerOptions")})]})};function xe({groupId:a,value:m,onChange:s}){const{t:l}=G(),[h,i]=g.useState([]),[p,E]=g.useState(""),[I,N]=g.useState(!1),[A,x]=g.useState(!1),[w,j]=g.useState(!1);g.useEffect(()=>{if(!a||m.visibility!=="group")return;let c=!1;return N(!0),x(!1),fe(`/groups/${encodeURIComponent(a)}/share-candidates`).then(C=>{c||(C.success&&Array.isArray(C.data)?i(C.data):x(!0))}).catch(()=>{c||x(!0)}).finally(()=>{c||N(!1)}),()=>{c=!0}},[a,m.visibility]);const T=m.sharedWithUsers||[],d=[...new Set([...h,...T])].sort().filter(c=>c.toLowerCase().includes(p.toLowerCase())),b=new Set(T),f=d.length>0&&d.every(c=>b.has(c)),t=d.length===0||d.every(c=>!b.has(c)),o=c=>{const C=new Set(T);C.has(c)?C.delete(c):C.add(c),s({sharedWithUsers:Array.from(C)})};return e.jsxs("div",{className:"mb-4",children:[e.jsxs("div",{className:"flex items-center justify-between cursor-pointer bg-[var(--hub-bg-2)] hover:bg-[var(--hub-surface-hover)] p-3 rounded border border-[var(--hub-line)]",onClick:()=>j(!w),children:[e.jsx("h3",{className:"text-sm font-semibold text-[var(--hub-ink)]",children:l("server.sectionAdvanced","Advanced Options")}),e.jsx("span",{className:"text-[var(--hub-ink-3)] text-sm",children:w?"▼":"▶"})]}),w&&e.jsxs("div",{className:"border border-[var(--hub-line)] rounded-b p-4 bg-[var(--hub-surface)] border-t-0",children:[e.jsx("label",{htmlFor:"group-visibility",className:"block text-sm font-medium mb-1.5 text-[var(--hub-ink-2)]",children:l("server.visibility")}),e.jsxs("select",{id:"group-visibility",className:"hub-input",value:m.visibility||"",onChange:c=>s({visibility:c.target.value}),children:[!m.visibility&&e.jsx("option",{value:"",disabled:!0,children:l("groups.legacyVisibility")}),e.jsx("option",{value:"private",children:l("server.visibilityPrivate")}),e.jsx("option",{value:"group",children:l("server.visibilityGroup")}),e.jsx("option",{value:"public",children:l("server.visibilityPublic")})]}),e.jsx("p",{className:"text-xs text-[var(--hub-ink-3)] mt-1",children:l("groups.visibilityDescription")}),!m.visibility&&e.jsx("p",{className:"text-sm text-amber-600",children:l("groups.legacyVisibilityHint")}),m.visibility==="group"&&e.jsxs("div",{className:"mt-4 rounded border border-[var(--hub-line)] p-3",children:[e.jsx("div",{className:"text-sm font-medium text-[var(--hub-ink-2)]",children:l("server.shareWithUsers")}),e.jsx("p",{className:"text-xs text-[var(--hub-ink-3)] mt-1 mb-3",children:l("server.shareWithUsersDescription")}),a?e.jsxs(e.Fragment,{children:[I&&e.jsx("p",{className:"text-sm text-[var(--hub-ink-3)]",children:l("server.shareCandidatesLoading")}),A&&e.jsx("p",{role:"alert",className:"text-sm text-red-600 dark:text-red-400",children:l("server.shareCandidatesError")}),!I&&!A&&d.length===0&&e.jsx("p",{className:"text-sm text-[var(--hub-ink-3)]",children:l(p?"server.noMatchingShareUsers":"server.noShareCandidates")}),d.length>0&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"mb-3 space-y-2",children:[e.jsx("label",{htmlFor:"group-share-search",className:"block text-xs font-medium text-[var(--hub-ink-2)]",children:l("server.shareUserSearchLabel")}),e.jsx("input",{id:"group-share-search",type:"search",value:p,onChange:c=>E(c.target.value),placeholder:l("server.shareUserSearchPlaceholder"),className:"hub-input text-sm"}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx("button",{type:"button",onClick:()=>s({sharedWithUsers:[...new Set([...T,...d])]}),disabled:f,className:"hub-btn text-sm",children:l("server.selectAllShareUsers")}),e.jsx("button",{type:"button",onClick:()=>s({sharedWithUsers:T.filter(c=>!d.includes(c))}),disabled:t,className:"hub-btn text-sm",children:l("server.deselectAllShareUsers")})]})]}),e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-2",children:d.map(c=>e.jsxs("label",{className:"flex items-center gap-2 rounded border border-[var(--hub-line)] px-3 py-2 text-sm text-[var(--hub-ink-2)]",children:[e.jsx("input",{type:"checkbox",checked:b.has(c),onChange:()=>o(c)}),e.jsx("span",{children:c})]},c))})]})]}):e.jsx("p",{className:"text-sm text-[var(--hub-ink-3)]",children:l("groups.shareAfterCreate")})]})]})]})}const Be=({onAdd:a,onCancel:m})=>{const{t:s}=G(),{createGroup:l}=ee(),{allServers:h}=te(),{serverCosts:i}=re(),[p,E]=g.useState([]),[I,N]=g.useState(null),[A,x]=g.useState(!1),[w,j]=g.useState({visibility:"private",sharedWithUsers:[],name:"",description:"",instructions:"",servers:[]});g.useEffect(()=>{E(h.filter(b=>b.enabled!==!1))},[h]);const T=b=>{const{name:f,value:t}=b.target;j(o=>({...o,[f]:t}))},d=async b=>{b.preventDefault(),x(!0),N(null);try{if(!w.name.trim()){N(s("groups.nameRequired")),x(!1);return}const f=await l(w.name,w.description,w.servers,{visibility:w.visibility,sharedWithUsers:w.sharedWithUsers,instructions:w.instructions});if(!f||!f.success){N((f==null?void 0:f.message)||s("groups.createError")),x(!1);return}a()}catch(f){N(f instanceof Error?f.message:String(f)),x(!1)}};return e.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:e.jsxs("div",{className:"hub-card shadow-lg max-w-3xl w-full max-h-[90vh] flex flex-col",children:[e.jsxs("div",{className:"p-6 flex-shrink-0",children:[e.jsx("h2",{className:"text-xl font-semibold text-[var(--hub-ink)] mb-4",children:s("groups.addNew")}),I&&e.jsx("div",{className:"mb-4 p-3 bg-red-100 text-red-700 rounded-md border border-[var(--hub-line)]",children:I})]}),e.jsxs("form",{onSubmit:d,className:"flex flex-col flex-1 min-h-0",children:[e.jsx("div",{className:"flex-1 overflow-y-auto px-6",children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsxs("label",{className:"block text-[var(--hub-ink-2)] text-sm font-bold mb-2",htmlFor:"name",children:[s("groups.name")," *"]}),e.jsx("input",{type:"text",id:"name",name:"name",value:w.name,onChange:T,className:"w-full border border-[var(--hub-line)] bg-[var(--hub-surface)] rounded-md px-3 py-2 text-[var(--hub-ink)] placeholder:text-[var(--hub-ink-3)] focus:outline-none focus:border-[var(--hub-ink-2)]",placeholder:s("groups.namePlaceholder"),required:!0})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[var(--hub-ink-2)] text-sm font-bold mb-2",htmlFor:"instructions",children:s("groups.instructions")}),e.jsx("textarea",{id:"instructions",name:"instructions",value:w.instructions,onChange:T,rows:3,className:"w-full border border-[var(--hub-line)] bg-[var(--hub-surface)] rounded-md px-3 py-2 text-[var(--hub-ink)] placeholder:text-[var(--hub-ink-3)] focus:outline-none focus:border-[var(--hub-ink-2)]",placeholder:s("groups.instructionsPlaceholder")}),e.jsx("p",{className:"text-xs text-[var(--hub-ink-3)] mt-1",children:s("groups.instructionsHelp")})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[var(--hub-ink-2)] text-sm font-bold mb-2",children:s("groups.configureCapabilities")}),e.jsx(pe,{servers:p,value:w.servers,onChange:b=>j(f=>({...f,servers:b})),className:"border border-[var(--hub-line)] rounded-lg p-4 bg-[var(--hub-bg-2)]",serverCosts:i})]}),e.jsx(xe,{value:w,onChange:b=>j(f=>({...f,...b}))})]})}),e.jsxs("div",{className:"flex justify-end space-x-2 p-5 pt-3 border-t border-[var(--hub-line-2)] flex-shrink-0",children:[e.jsx("button",{type:"button",onClick:m,className:"hub-btn",disabled:A,children:s("common.cancel")}),e.jsx("button",{type:"submit",className:"hub-btn primary",disabled:A,children:s(A?"common.submitting":"common.create")})]})]})]})})},Ve=({group:a,onEdit:m,onCancel:s})=>{const{t:l}=G(),{updateGroup:h}=ee(),{allServers:i}=te(),{serverCosts:p}=re(),[E,I]=g.useState([]),[N,A]=g.useState(null),[x,w]=g.useState(!1),[j,T]=g.useState({visibility:a.visibility,sharedWithUsers:a.sharedWithUsers||[],name:a.name,description:a.description||"",instructions:a.instructions||"",servers:a.servers||[]});g.useEffect(()=>{I(i.filter(f=>f.enabled!==!1))},[i]);const d=f=>{const{name:t,value:o}=f.target;T(c=>({...c,[t]:o}))},b=async f=>{f.preventDefault(),w(!0),A(null);try{if(!j.name.trim()){A(l("groups.nameRequired")),w(!1);return}const t=await h(a.id,{visibility:j.visibility,sharedWithUsers:j.sharedWithUsers,name:j.name,description:j.description,instructions:j.instructions,servers:j.servers});if(!t||!t.success){A((t==null?void 0:t.message)||l("groups.updateError")),w(!1);return}m()}catch(t){A(t instanceof Error?t.message:String(t)),w(!1)}};return e.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:e.jsxs("div",{className:"hub-card shadow-lg max-w-3xl w-full max-h-[90vh] flex flex-col",children:[e.jsxs("div",{className:"p-6 flex-shrink-0",children:[e.jsx("h2",{className:"text-xl font-semibold text-[var(--hub-ink)] mb-4",children:l("groups.edit")}),N&&e.jsx("div",{className:"mb-4 p-3 bg-red-100 text-red-700 rounded-md border border-[var(--hub-line)]",children:N})]}),e.jsxs("form",{onSubmit:b,className:"flex flex-col flex-1 min-h-0",children:[e.jsx("div",{className:"flex-1 overflow-y-auto px-6",children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsxs("label",{className:"block text-[var(--hub-ink-2)] text-sm font-bold mb-2",htmlFor:"name",children:[l("groups.name")," *"]}),e.jsx("input",{type:"text",id:"name",name:"name",value:j.name,onChange:d,className:"w-full border border-[var(--hub-line)] bg-[var(--hub-surface)] rounded-md px-3 py-2 text-[var(--hub-ink)] placeholder:text-[var(--hub-ink-3)] focus:outline-none focus:border-[var(--hub-ink-2)]",placeholder:l("groups.namePlaceholder"),required:!0})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[var(--hub-ink-2)] text-sm font-bold mb-2",htmlFor:"instructions",children:l("groups.instructions")}),e.jsx("textarea",{id:"instructions",name:"instructions",value:j.instructions,onChange:d,rows:3,className:"w-full border border-[var(--hub-line)] bg-[var(--hub-surface)] rounded-md px-3 py-2 text-[var(--hub-ink)] placeholder:text-[var(--hub-ink-3)] focus:outline-none focus:border-[var(--hub-ink-2)]",placeholder:l("groups.instructionsPlaceholder")}),e.jsx("p",{className:"text-xs text-[var(--hub-ink-3)] mt-1",children:l("groups.instructionsHelp")})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-[var(--hub-ink-2)] text-sm font-bold mb-2",children:l("groups.configureCapabilities")}),e.jsx(pe,{servers:E,value:j.servers,onChange:f=>T(t=>({...t,servers:f})),className:"border border-[var(--hub-line)] rounded-lg p-4 bg-[var(--hub-bg-2)]",serverCosts:p})]}),e.jsx(xe,{groupId:a.id,value:j,onChange:f=>T(t=>({...t,...f}))})]})}),e.jsxs("div",{className:"flex justify-end space-x-2 p-5 pt-3 border-t border-[var(--hub-line-2)] flex-shrink-0",children:[e.jsx("button",{type:"button",onClick:s,className:"hub-btn",disabled:x,children:l("common.cancel")}),e.jsx("button",{type:"submit",className:"hub-btn primary",disabled:x,children:l(x?"common.submitting":"common.save")})]})]})]})})},qe=a=>a.map(m=>typeof m=="string"?m:m.name),he=(a,m)=>{const s=a.servers.find(l=>typeof l=="string"?l===m:l.name===m);return s?typeof s=="string"?{name:s,tools:"all",prompts:"all",resources:"all"}:s:{name:m,tools:"all",prompts:"all",resources:"all"}},Ke=(a,m)=>{var l;return((l=he(a,m).alias)==null?void 0:l.trim())||m},Je=({group:a,servers:m,onEdit:s,onDelete:l,cost:h})=>{var B;const{t:i}=G(),{auth:p}=ve(),E=!!p.user&&(p.user.isAdmin||p.user.username===a.owner),{showToast:I}=je(),{installConfig:N,nameSeparator:A}=me(),x=((B=N==null?void 0:N.baseUrl)==null?void 0:B.replace(/\/+$/,""))||"",[w,j]=g.useState(!1),[T,d]=g.useState(null),[b,f]=g.useState(!1),[t,o]=g.useState(!1),c=g.useRef(null);g.useEffect(()=>{const D=R=>{c.current&&!c.current.contains(R.target)&&o(!1)};return document.addEventListener("mousedown",D),()=>document.removeEventListener("mousedown",D)},[]);const C=async D=>{await ye(D)?(f(!0),o(!1),I(i("common.copySuccess")||"Copied","success"),setTimeout(()=>f(!1),1500)):I(i("common.copyFailed")||"Copy failed","error")},z=`${x}/mcp/${a.name}`,O=`${x}/mcp/${encodeURIComponent(a.name)}`,_=`${x}/api/${a.name}`,X=qe(a.servers),W=m.filter(D=>X.includes(D.name)),K=D=>{const R=he(a,D.name),r=`${D.name}${A}`,u=D.tools||[],n=D.prompts||[],S=D.resources||[],v=Array.isArray(R.tools)?u.filter(k=>{if(k.enabled===!1)return!1;const y=k.name.startsWith(r)?k.name.slice(r.length):k.name;return R.tools.includes(y)}).length:u.filter(k=>k.enabled!==!1).length,P=Array.isArray(R.prompts)?n.filter(k=>{if(k.enabled===!1)return!1;const y=k.name.startsWith(r)?k.name.slice(r.length):k.name;return R.prompts.includes(y)}).length:n.filter(k=>k.enabled!==!1).length,F=Array.isArray(R.resources)?S.filter(k=>k.enabled!==!1&&R.resources.includes(k.uri)).length:S.filter(k=>k.enabled!==!1).length;return{visibleTools:v,totalTools:u.length,visiblePrompts:P,totalPrompts:n.length,visibleResources:F,totalResources:S.length}},J=W.reduce((D,R)=>D+K(R).visibleTools,0);return e.jsxs("div",{className:"hub-card flex h-full flex-col overflow-visible",children:[e.jsxs("div",{className:"flex items-start gap-3 px-4 py-3",style:{borderBottom:"1px solid var(--hub-line-2)"},children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{style:{fontSize:15,fontWeight:600,letterSpacing:"-0.015em"},children:a.name}),e.jsx("span",{className:"hub-mono",style:{fontSize:11,color:"var(--hub-ink-3)",padding:"0 6px",border:"1px solid var(--hub-line)",borderRadius:4,height:18,display:"inline-flex",alignItems:"center"},title:a.id,children:a.id})]}),e.jsx("div",{className:"mt-1 text-xs text-[var(--hub-ink-3)]",children:a.visibility?i(`server.visibility${a.visibility==="group"?"Group":a.visibility==="public"?"Public":"Private"}`):i("groups.legacyVisibility")}),a.description&&e.jsx("div",{style:{fontSize:12.5,color:"var(--hub-ink-3)",marginTop:2},children:a.description})]}),e.jsxs("div",{className:"flex items-center gap-1",ref:c,children:[e.jsxs("div",{className:"relative",children:[e.jsx("button",{onClick:()=>o(D=>!D),className:"hub-icon-btn sm",title:i("common.copy"),children:b?e.jsx(De,{size:13,className:"text-[var(--hub-ok)]"}):e.jsx(Q,{size:13})}),t&&e.jsxs("div",{className:"absolute top-full right-0 mt-1 z-20 hub-card",style:{minWidth:160,padding:4},children:[e.jsxs("button",{onClick:()=>C(a.id),className:"flex items-center gap-2 w-full px-2.5 py-1.5 text-[13px] rounded-md hover:bg-[var(--hub-surface-hover)] text-left",children:[e.jsx(Q,{size:12})," ",i("common.copyId")]}),e.jsxs("button",{onClick:()=>C(z),className:"flex items-center gap-2 w-full px-2.5 py-1.5 text-[13px] rounded-md hover:bg-[var(--hub-surface-hover)] text-left",children:[e.jsx(oe,{size:12})," ",i("common.copyUrl")]}),e.jsxs("button",{onClick:()=>C(_),className:"flex items-center gap-2 w-full px-2.5 py-1.5 text-[13px] rounded-md hover:bg-[var(--hub-surface-hover)] text-left",children:[e.jsx(oe,{size:12})," ",i("common.copyOpenApiUrl")]}),e.jsxs("button",{onClick:()=>{o(!1),d({name:a.name,url:O,headers:{Authorization:`Bearer ${Se}`}})},className:"flex items-center gap-2 w-full px-2.5 py-1.5 text-[13px] rounded-md hover:bg-[var(--hub-surface-hover)] text-left",children:[e.jsx(Ie,{size:12})," ",i("clientConfig.menuItem")]})]})]}),E&&e.jsxs(e.Fragment,{children:[e.jsx("button",{onClick:()=>s(a),className:"hub-icon-btn sm",title:i("groups.edit"),children:e.jsx(Fe,{size:13})}),e.jsx("button",{onClick:()=>j(!0),className:"hub-icon-btn sm",title:i("groups.delete"),style:{color:"var(--hub-ink-3)"},children:e.jsx(ze,{size:13})})]})]})]}),e.jsxs("div",{className:"grid flex-1 items-center gap-3 px-4 py-3",style:{gridTemplateColumns:"1fr 80px 1fr",minHeight:180},children:[e.jsx("div",{className:"flex flex-col gap-1.5",children:W.length===0?e.jsx("div",{style:{fontSize:12,color:"var(--hub-ink-3)"},children:i("groups.noServers")}):W.map(D=>{const R=K(D);return e.jsxs("div",{className:"flex items-center gap-2.5 px-2.5 py-1.5 rounded-md",style:{background:"var(--hub-bg-2)",border:"1px solid var(--hub-line-2)"},children:[e.jsx("span",{className:"inline-block flex-shrink-0",style:{width:6,height:6,borderRadius:50,background:D.status==="connected"?"var(--hub-ok)":D.status==="connecting"?"var(--hub-warn)":"var(--hub-err)"}}),e.jsx("span",{className:"hub-mono truncate flex-1",style:{fontSize:12.5},children:e.jsx("span",{title:D.name,children:Ke(a,D.name)})}),e.jsxs("span",{className:"hub-mono hub-num flex-shrink-0",style:{fontSize:11,color:"var(--hub-ink-3)"},children:[R.visibleTools,"/",R.totalTools," tools"]})]},D.name)})}),e.jsxs("svg",{width:"80",height:"80",viewBox:"0 0 80 80",className:"self-center",children:[W.length===0?e.jsx("path",{d:"M0,40 C30,40 50,40 80,40",stroke:"var(--hub-line)",strokeWidth:"1",fill:"none",strokeDasharray:"3 3"}):W.map((D,R)=>{const r=12+60/Math.max(W.length,1)*(R+.5);return e.jsx("path",{d:`M0,${r} C 30,${r} 50,40 80,40`,stroke:"var(--hub-line)",strokeWidth:"1",fill:"none",strokeDasharray:"3 3"},R)}),e.jsx("circle",{cx:"80",cy:"40",r:"4",fill:"var(--hub-ink)"})]}),e.jsxs("div",{className:"px-3 py-2.5 rounded-md",style:{border:"1px solid var(--hub-line)",background:"var(--hub-bg-2)"},children:[e.jsx("div",{className:"hub-sect",style:{marginBottom:4},children:"endpoint"}),e.jsxs("div",{className:"hub-mono break-all",style:{fontSize:12,color:"var(--hub-ink-2)",lineHeight:1.4},children:[e.jsx("span",{style:{color:"var(--hub-ink-3)"},children:"/mcp/"}),e.jsx("b",{style:{color:"var(--hub-ink)",fontWeight:600},children:a.name})]}),e.jsxs("div",{className:"hub-mono break-all",style:{fontSize:12,color:"var(--hub-ink-2)",lineHeight:1.4},children:[e.jsx("span",{style:{color:"var(--hub-ink-3)"},children:"/api/"}),e.jsx("b",{style:{color:"var(--hub-ink)",fontWeight:600},children:a.name})]}),e.jsxs("div",{className:"flex gap-1.5 mt-2",children:[e.jsxs("button",{className:"hub-btn sm flex-1 justify-center",onClick:()=>C(z),title:i("common.copyUrl"),children:[e.jsx(Q,{size:11})," MCP"]}),e.jsxs("button",{className:"hub-btn sm flex-1 justify-center",onClick:()=>C(_),title:i("common.copyOpenApiUrl"),children:[e.jsx(Q,{size:11})," OpenAPI"]})]})]})]}),e.jsxs("div",{className:"flex justify-between items-center px-4 py-2",style:{borderTop:"1px solid var(--hub-line-2)",background:"var(--hub-bg-2)",fontSize:12,color:"var(--hub-ink-3)"},children:[e.jsxs("div",{children:[e.jsxs("div",{className:"hub-mono",children:[e.jsx("span",{style:{color:"var(--hub-ink-2)"},children:W.length})," ",i("nav.servers").toLowerCase()," ·"," ",e.jsx("span",{style:{color:"var(--hub-ink-2)"},children:J})," ",i("server.tools").toLowerCase()]}),h&&e.jsxs("div",{className:"hub-mono mt-1",style:{fontSize:11.5,color:"var(--hub-ink-3)"},children:[e.jsxs("div",{title:i("cost.estimate"),children:[i("cost.totalFootprint"),": ",H(h.direct.exposed),"/",H(h.direct.gross)]}),h.smartRouting&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{children:[i("cost.smartRouting"),": ",H(h.smartRouting.base)," (",i("cost.saved",{percent:Ne(h.direct.exposed,h.smartRouting.base)}),")"]}),e.jsxs("div",{title:i("cost.smartRoutingPdHint"),children:[i("cost.smartRoutingPd"),":"," ",H(h.smartRouting.progressiveDisclosure)]})]}),h.connectedCount<h.totalCount&&e.jsx("div",{children:i("cost.connectedOf",{connected:h.connectedCount,total:h.totalCount})})]})]}),E&&e.jsxs("button",{className:"hub-btn ghost sm",style:{color:"var(--hub-ink-3)"},onClick:()=>s(a),children:[i("groups.configureTools")||i("groups.edit"),e.jsx(Pe,{size:11,style:{transform:"rotate(-90deg)"}})]})]}),e.jsx(we,{isOpen:T!==null,target:T,onClose:()=>d(null)}),e.jsx($e,{isOpen:w,onClose:()=>j(!1),onConfirm:()=>{l(a.id),j(!1)},serverName:a.name,isGroup:!0})]})},Qe=({onSuccess:a,onCancel:m})=>{const{t:s}=G(),[l,h]=g.useState(""),[i,p]=g.useState(null),[E,I]=g.useState(!1),[N,A]=g.useState(null),x=`{
|
|
2
|
-
"groups": [
|
|
3
|
-
{
|
|
4
|
-
"name": "AI Assistants",
|
|
5
|
-
"servers": ["openai-server", "anthropic-server"]
|
|
6
|
-
},
|
|
7
|
-
{
|
|
8
|
-
"name": "Development Tools",
|
|
9
|
-
"servers": [
|
|
10
|
-
{
|
|
11
|
-
"name": "github-server",
|
|
12
|
-
"tools": ["create_issue", "list_repos"],
|
|
13
|
-
"prompts": ["triage_prompt"],
|
|
14
|
-
"resources": ["resource://docs/repo-guide"]
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
"name": "gitlab-server",
|
|
18
|
-
"tools": "all",
|
|
19
|
-
"prompts": "all",
|
|
20
|
-
"resources": "all"
|
|
21
|
-
}
|
|
22
|
-
]
|
|
23
|
-
}
|
|
24
|
-
]
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
Supports:
|
|
28
|
-
- Simple server list: ["server1", "server2"]
|
|
29
|
-
- Advanced server config: [{"name": "server1", "tools": ["tool1"], "prompts": ["prompt1"], "resources": ["resource://docs/guide"]}]
|
|
30
|
-
- All groups will be imported in a single efficient batch operation.`,w=t=>{try{const o=JSON.parse(t.trim());if(!o.groups||!Array.isArray(o.groups))return p(s("groupImport.invalidFormat")),null;for(const c of o.groups)if(!c.name||typeof c.name!="string")return p(s("groupImport.missingName")),null;return o}catch{return p(s("groupImport.parseError")),null}},j=()=>{p(null);const t=w(l);t&&A(t.groups)},T=async()=>{if(N){I(!0),p(null);try{const t=await se("/groups/batch",{groups:N});if(t.success){const{successCount:o,failureCount:c,results:C}=t;if(c>0){const z=C.filter(O=>!O.success).map(O=>`${O.name}: ${O.message||s("groupImport.addFailed")}`);p(s("groupImport.partialSuccess",{count:o,total:N.length})+`
|
|
31
|
-
`+z.join(`
|
|
32
|
-
`))}o>0&&a()}else p(t.message||s("groupImport.importFailed"))}catch(t){console.error("Import error:",t),p(s("groupImport.importFailed"))}finally{I(!1)}}},d=t=>e.jsx("span",{className:"text-gray-500 ml-2",children:s(`groups.${t}`)}),b=(t,o)=>{if(!o||o==="all")return null;const c=Array.isArray(o)?o.join(", "):o;return e.jsx("span",{className:"text-gray-500 ml-2",children:s(`groups.${t}`,{items:c})})},f=t=>!t||t.length===0?e.jsx("span",{className:"text-gray-500",children:s("groups.noServers")}):e.jsx("div",{className:"space-y-1",children:t.map((o,c)=>typeof o=="string"?e.jsxs("div",{className:"text-sm",children:["• ",o]},c):e.jsxs("div",{className:"text-sm",children:["• ",o.name,o.tools&&o.tools!=="all"&&e.jsxs("span",{className:"text-gray-500 ml-2",children:["(",Array.isArray(o.tools)?o.tools.join(", "):o.tools,")"]}),o.tools==="all"&&d("previewAllTools"),b("previewPrompts",o.prompts),o.prompts==="all"&&d("previewAllPrompts"),b("previewResources",o.resources),o.resources==="all"&&d("previewAllResources")]},c))});return e.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:e.jsxs("div",{className:"bg-white dark:bg-gray-800 shadow rounded-lg p-6 w-full max-w-4xl max-h-[90vh] overflow-y-auto",children:[e.jsxs("div",{className:"flex justify-between items-center mb-6",children:[e.jsx("h2",{className:"text-xl font-semibold text-gray-900",children:s("groupImport.title")}),e.jsx("button",{onClick:m,className:"text-gray-500 hover:text-gray-700",children:"✕"})]}),i&&e.jsx("div",{className:"mb-4 bg-red-50 border-l-4 border-red-500 p-4 rounded",children:e.jsx("p",{className:"text-red-700 whitespace-pre-wrap",children:i})}),N?e.jsxs("div",{children:[e.jsxs("div",{className:"mb-4",children:[e.jsx("h3",{className:"text-lg font-medium text-gray-900 mb-3",children:s("groupImport.previewTitle")}),e.jsx("div",{className:"space-y-3",children:N.map((t,o)=>e.jsx("div",{className:"bg-gray-50 dark:bg-gray-800 p-4 rounded-lg border border-gray-200 dark:border-gray-700",children:e.jsx("div",{className:"flex items-start justify-between",children:e.jsxs("div",{className:"flex-1",children:[e.jsx("h4",{className:"font-medium text-gray-900",children:t.name}),t.description&&e.jsx("p",{className:"text-sm text-gray-600 mt-1",children:t.description}),e.jsxs("div",{className:"mt-2 text-sm text-gray-600",children:[e.jsxs("strong",{children:[s("groups.servers"),":"]}),e.jsx("div",{className:"mt-1",children:f(t.servers)})]})]})})},o))})]}),e.jsxs("div",{className:"flex justify-end space-x-4",children:[e.jsx("button",{onClick:()=>A(null),disabled:E,className:"hub-btn",children:s("common.back")}),e.jsx("button",{onClick:T,disabled:E,className:"hub-btn primary",children:E?e.jsxs(e.Fragment,{children:[e.jsxs("svg",{className:"animate-spin h-4 w-4 mr-2",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[e.jsx("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"4"}),e.jsx("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]}),s("groupImport.importing")]}):s("groupImport.import")})]})]}):e.jsxs("div",{children:[e.jsxs("div",{className:"mb-4",children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-2",children:s("groupImport.inputLabel")}),e.jsx("textarea",{value:l,onChange:t=>h(t.target.value),className:"w-full h-96 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 font-mono text-sm",placeholder:x}),e.jsx("p",{className:"text-xs text-gray-500 mt-2",children:s("groupImport.inputHelp")})]}),e.jsxs("div",{className:"flex justify-end space-x-4",children:[e.jsx("button",{onClick:m,className:"hub-btn",children:s("common.cancel")}),e.jsx("button",{onClick:j,disabled:!l.trim(),className:"hub-btn primary",children:s("groupImport.preview")})]})]})]})})},Xe=({groups:a,onCancel:m})=>{const{t:s}=G(),[l,h]=g.useState(""),[i,p]=g.useState(""),[E,I]=g.useState([]),[N,A]=g.useState(!1),[x,w]=g.useState(!1),[j,T]=g.useState(null),d=t=>{I(o=>o.includes(t)?o.filter(c=>c!==t):[...o,t])},b=()=>{E.length===a.length?I([]):I(a.map(t=>t.id))},f=async()=>{if(!l.trim()){T(s("template.nameRequired"));return}w(!0),T(null);try{const t=await se("/templates/export",{name:l.trim(),description:i.trim()||void 0,groupIds:E.length>0?E:void 0,includeDisabledServers:N});if(t.success&&t.data){const o=t.data,c=new Blob([JSON.stringify(o,null,2)],{type:"application/json"}),C=URL.createObjectURL(c),z=document.createElement("a");z.href=C,z.download=`${o.name.replace(/[^a-zA-Z0-9-_]/g,"_")}.mcphub-template.json`,document.body.appendChild(z),z.click(),document.body.removeChild(z),URL.revokeObjectURL(C),m()}else T(t.message||s("template.exportFailed"))}catch(t){console.error("Export error:",t),T(s("template.exportFailed"))}finally{w(!1)}};return e.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:e.jsxs("div",{className:"bg-white dark:bg-gray-800 shadow rounded-lg p-6 w-full max-w-3xl max-h-[90vh] overflow-y-auto",children:[e.jsxs("div",{className:"flex justify-between items-center mb-6",children:[e.jsx("h2",{className:"text-xl font-semibold text-gray-900",children:s("template.exportTitle")}),e.jsx("button",{onClick:m,className:"text-gray-500 hover:text-gray-700",children:"✕"})]}),j&&e.jsx("div",{className:"mb-4 bg-red-50 dark:bg-red-900/20 border-l-4 border-red-500 p-4 rounded",children:e.jsx("p",{className:"text-red-700 dark:text-red-300",children:j})}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsxs("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:[s("template.name")," *"]}),e.jsx("input",{type:"text",value:l,onChange:t=>h(t.target.value),className:"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:s("template.namePlaceholder")})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-1",children:s("template.description")}),e.jsx("input",{type:"text",value:i,onChange:t=>p(t.target.value),className:"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500",placeholder:s("template.descriptionPlaceholder")})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex justify-between items-center mb-2",children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700",children:s("template.selectGroups")}),e.jsx("button",{onClick:b,className:"text-sm text-blue-600 hover:text-blue-800 dark:text-blue-300",children:E.length===a.length?s("template.deselectAll"):s("template.selectAll")})]}),e.jsx("p",{className:"text-xs text-gray-500 mb-2",children:s("template.selectGroupsHelp")}),e.jsx("div",{className:"border border-gray-200 dark:border-gray-700 rounded-md max-h-48 overflow-y-auto",children:a.map(t=>e.jsxs("label",{className:"flex items-center px-3 py-2 hover:bg-gray-50 dark:bg-gray-800 dark:hover:bg-gray-700 cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:E.includes(t.id),onChange:()=>d(t.id),className:"mr-3 h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"}),e.jsxs("div",{children:[e.jsx("span",{className:"text-sm font-medium text-gray-900",children:t.name}),t.description&&e.jsx("span",{className:"text-xs text-gray-500 ml-2",children:t.description})]})]},t.id))})]}),e.jsxs("label",{className:"flex items-center space-x-2 cursor-pointer",children:[e.jsx("input",{type:"checkbox",checked:N,onChange:t=>A(t.target.checked),className:"h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"}),e.jsx("span",{className:"text-sm text-gray-700",children:s("template.includeDisabled")})]})]}),e.jsx("div",{className:"mt-4 p-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-700/60 rounded-md",children:e.jsx("p",{className:"text-sm text-blue-700 dark:text-blue-300",children:s("template.exportNote")})}),e.jsxs("div",{className:"flex justify-end space-x-4 mt-6",children:[e.jsx("button",{onClick:m,className:"hub-btn",children:s("common.cancel")}),e.jsx("button",{onClick:f,disabled:x||!l.trim(),className:"hub-btn primary",children:s(x?"template.exporting":"template.export")})]})]})})},Ye=({onSuccess:a,onCancel:m})=>{const{t:s}=G(),[l,h]=g.useState(null),[i,p]=g.useState(null),[E,I]=g.useState(!1),[N,A]=g.useState(null),x=g.useRef(null),w=d=>{var t;p(null),h(null),A(null);const b=(t=d.target.files)==null?void 0:t[0];if(!b)return;const f=new FileReader;f.onload=o=>{var c;try{const C=JSON.parse((c=o.target)==null?void 0:c.result);if(!C.version||!C.name||!C.servers||!C.groups){p(s("template.invalidFormat"));return}h(C)}catch{p(s("template.parseError"))}},f.readAsText(b)},j=d=>{if(p(null),h(null),A(null),!!d.trim())try{const b=JSON.parse(d.trim());if(!b.version||!b.name||!b.servers||!b.groups){p(s("template.invalidFormat"));return}h(b)}catch{p(s("template.parseError"))}},T=async()=>{if(l){I(!0),p(null);try{const d=await se("/templates/import",l);d.data?(A(d.data),d.data.success&&a()):p(d.message||s("template.importFailed"))}catch(d){console.error("Import error:",d),p(s("template.importFailed"))}finally{I(!1)}}};return e.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4",children:e.jsxs("div",{className:"bg-white dark:bg-gray-800 shadow rounded-lg p-6 w-full max-w-4xl max-h-[90vh] overflow-y-auto",children:[e.jsxs("div",{className:"flex justify-between items-center mb-6",children:[e.jsx("h2",{className:"text-xl font-semibold text-gray-900",children:s("template.importTitle")}),e.jsx("button",{onClick:m,className:"text-gray-500 hover:text-gray-700",children:"✕"})]}),i&&e.jsx("div",{className:"mb-4 bg-red-50 dark:bg-red-900/20 border-l-4 border-red-500 p-4 rounded",children:e.jsx("p",{className:"text-red-700 dark:text-red-300",children:i})}),N&&e.jsxs("div",{className:`mb-4 p-4 rounded border-l-4 ${N.success?"bg-green-50 dark:bg-green-900/20 border-green-500":"bg-yellow-50 dark:bg-yellow-900/20 border-yellow-500"}`,children:[e.jsx("p",{className:N.success?"text-green-700 dark:text-green-300":"text-yellow-700 dark:text-yellow-300",children:s("template.importResult",{serversCreated:N.serversCreated,serversSkipped:N.serversSkipped,groupsCreated:N.groupsCreated,groupsSkipped:N.groupsSkipped})}),N.requiredEnvVars.length>0&&e.jsxs("div",{className:"mt-2 p-2 bg-orange-50 dark:bg-orange-900/20 border border-orange-200 dark:border-orange-700/60 rounded",children:[e.jsx("p",{className:"text-sm font-medium text-orange-800 dark:text-orange-300",children:s("template.envVarsNeeded")}),e.jsx("ul",{className:"mt-1 text-sm text-orange-700 dark:text-orange-300",children:N.requiredEnvVars.map(d=>e.jsx("li",{className:"font-mono",children:d},d))})]})]}),l?e.jsxs("div",{children:[e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"p-3 bg-gray-50 dark:bg-gray-800 rounded-md",children:[e.jsx("h3",{className:"font-medium text-gray-900",children:l.name}),l.description&&e.jsx("p",{className:"text-sm text-gray-600 mt-1",children:l.description}),e.jsxs("p",{className:"text-xs text-gray-500 mt-1",children:[s("template.version"),": ",l.version," | ",s("template.createdAt"),":"," ",new Date(l.createdAt).toLocaleDateString()]})]}),e.jsxs("div",{children:[e.jsxs("h4",{className:"text-sm font-medium text-gray-700 mb-2",children:[s("template.servers")," (",Object.keys(l.servers).length,")"]}),e.jsx("div",{className:"border border-gray-200 dark:border-gray-700 rounded-md divide-y divide-gray-200 dark:divide-gray-700 max-h-40 overflow-y-auto",children:Object.entries(l.servers).map(([d,b])=>e.jsxs("div",{className:"px-3 py-2",children:[e.jsx("span",{className:"text-sm font-medium text-gray-900",children:d}),e.jsx("span",{className:"text-xs text-gray-500 ml-2",children:b.type||"stdio"})]},d))})]}),e.jsxs("div",{children:[e.jsxs("h4",{className:"text-sm font-medium text-gray-700 mb-2",children:[s("template.groups")," (",l.groups.length,")"]}),e.jsx("div",{className:"border border-gray-200 dark:border-gray-700 rounded-md divide-y divide-gray-200 dark:divide-gray-700 max-h-40 overflow-y-auto",children:l.groups.map((d,b)=>e.jsxs("div",{className:"px-3 py-2",children:[e.jsx("span",{className:"text-sm font-medium text-gray-900",children:d.name}),d.description&&e.jsx("span",{className:"text-xs text-gray-500 ml-2",children:d.description}),e.jsxs("div",{className:"text-xs text-gray-500 mt-1",children:[d.servers.length," ",s("template.serversInGroup")]})]},b))})]}),l.requiredEnvVars.length>0&&e.jsxs("div",{className:"p-3 bg-orange-50 dark:bg-orange-900/20 border border-orange-200 dark:border-orange-700/60 rounded-md",children:[e.jsx("h4",{className:"text-sm font-medium text-orange-800 dark:text-orange-300",children:s("template.envVarsNeeded")}),e.jsx("ul",{className:"mt-1 text-sm text-orange-700 dark:text-orange-300 font-mono",children:l.requiredEnvVars.map(d=>e.jsx("li",{children:d},d))})]})]}),e.jsxs("div",{className:"flex justify-end space-x-4 mt-6",children:[e.jsx("button",{onClick:()=>{h(null),A(null),x.current&&(x.current.value="")},className:"hub-btn",children:s("common.back")}),e.jsx("button",{onClick:T,disabled:E,className:"hub-btn primary",children:s(E?"template.importing":"template.import")})]})]}):e.jsxs("div",{children:[e.jsxs("div",{className:"mb-4",children:[e.jsx("div",{className:"flex items-center justify-between mb-2",children:e.jsx("label",{className:"block text-sm font-medium text-gray-700",children:s("template.uploadFile")})}),e.jsx("div",{className:"flex items-center space-x-4",children:e.jsx("input",{ref:x,type:"file",accept:".json",onChange:w,className:"block text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100"})})]}),e.jsxs("div",{className:"relative my-4",children:[e.jsx("div",{className:"absolute inset-0 flex items-center",children:e.jsx("div",{className:"w-full border-t border-gray-300"})}),e.jsx("div",{className:"relative flex justify-center text-sm",children:e.jsx("span",{className:"bg-white dark:bg-gray-800 px-2 text-gray-500",children:s("template.or")})})]}),e.jsxs("div",{className:"mb-4",children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-2",children:s("template.pasteJson")}),e.jsx("textarea",{className:"w-full h-64 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 font-mono text-sm",placeholder:s("template.pastePlaceholder"),onChange:d=>j(d.target.value)})]}),e.jsx("div",{className:"flex justify-end space-x-4",children:e.jsx("button",{onClick:m,className:"hub-btn",children:s("common.cancel")})})]})]})})},os=()=>{const{t:a}=G(),{groups:m,loading:s,error:l,setError:h,deleteGroup:i,triggerRefresh:p}=ee(),{allServers:E}=te({refreshOnMount:!0}),{groupCosts:I,refetch:N}=re();g.useEffect(()=>{N()},[m,E,N]);const[A,x]=g.useState(null),[w,j]=g.useState(!1),[T,d]=g.useState(!1),[b,f]=g.useState(!1),[t,o]=g.useState(!1),c=async C=>{const z=await i(C);(!z||!z.success)&&h((z==null?void 0:z.message)||a("groups.deleteError"))};return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-end justify-between gap-4 mb-6",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"hub-h1",children:a("pages.groups.title")}),e.jsxs("p",{className:"hub-sub",children:[e.jsx("span",{className:"hub-num",children:m.length})," ",a("nav.groups").toLowerCase()]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs("button",{className:"hub-btn",onClick:()=>d(!0),children:[e.jsx(ce,{size:13})," ",a("groupImport.button")]}),e.jsxs("button",{className:"hub-btn",onClick:()=>f(!0),children:[e.jsx(Re,{size:13})," ",a("template.exportButton")]}),e.jsxs("button",{className:"hub-btn",onClick:()=>o(!0),children:[e.jsx(ce,{size:13})," ",a("template.importButton")]}),e.jsxs("button",{className:"hub-btn primary",onClick:()=>j(!0),children:[e.jsx(de,{size:13})," ",a("groups.add")]})]})]}),l&&e.jsxs("div",{className:"hub-card flex items-center justify-between gap-3 mb-4",style:{padding:"10px 14px",borderColor:"oklch(0.85 0.1 25)",background:"oklch(0.97 0.03 25)",color:"oklch(0.4 0.18 25)"},children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx(Le,{size:14,className:"flex-shrink-0"}),e.jsx("span",{className:"truncate text-[13px]",children:l})]}),e.jsx("button",{className:"hub-icon-btn sm",onClick:()=>h(null),children:e.jsx(Ue,{size:13})})]}),s?e.jsx("div",{className:"hub-card p-6 text-center",style:{color:"var(--hub-ink-3)"},children:a("app.loading")}):m.length===0?e.jsx("div",{className:"hub-card p-10 text-center",style:{color:"var(--hub-ink-3)"},children:a("groups.noGroups")}):e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-3.5",children:[m.map(C=>e.jsx(Je,{group:C,servers:E,onEdit:x,onDelete:c,cost:I.find(z=>z.id===C.id)},C.id)),e.jsx("button",{onClick:()=>j(!0),className:"flex items-center justify-center text-[var(--hub-ink-3)] hover:text-[var(--hub-ink-2)] transition-colors",style:{border:"1px dashed var(--hub-line)",borderRadius:10,minHeight:200,background:"transparent",cursor:"pointer"},children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"grid place-items-center mx-auto mb-2",style:{width:36,height:36,borderRadius:10,border:"1px solid var(--hub-line)"},children:e.jsx(de,{size:16})}),e.jsx("div",{style:{fontSize:13,fontWeight:500,color:"var(--hub-ink-2)"},children:a("groups.add")}),e.jsx("div",{style:{fontSize:12,marginTop:2},children:a("groups.addNew")})]})})]}),w&&e.jsx(Be,{onAdd:()=>{j(!1),p()},onCancel:()=>j(!1)}),T&&e.jsx(Qe,{onSuccess:()=>{d(!1),p()},onCancel:()=>d(!1)}),A&&e.jsx(Ve,{group:A,onEdit:()=>{x(null),p()},onCancel:()=>x(null)}),b&&e.jsx(Xe,{groups:m,onCancel:()=>f(!1)}),t&&e.jsx(Ye,{onSuccess:()=>{o(!1),p()},onCancel:()=>o(!1)})]})};export{os as default};
|
|
33
|
-
//# sourceMappingURL=GroupsPage-gZ0nnzCn.js.map
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{d as V,j as e,r as n,u as oe}from"./framework-vendor-CQFm9vKd.js";import{u as le,g as ie,G as H,T as ce,L as de,a as ue,s as he,b as K,c as ge}from"./index-DL9uGzQF.js";import{u as J}from"./i18n-vendor-DVmjrzgW.js";import{B as me,l as _}from"./icons-vendor-CkcU1LMA.js";const be=({isOpen:s,onClose:d})=>{const{t:i}=J(),c=V();if(!s)return null;const k=()=>{d(),c("/settings"),setTimeout(()=>{const o=document.querySelector('[data-section="password"]');if(o){o.scrollIntoView({behavior:"smooth",block:"start"});const v=o.querySelector('[role="button"]');v&&!o.querySelector(".mt-4")&&v.click()}},100)},x=o=>{o.target===o.currentTarget&&d()},w=o=>{o.key==="Escape"&&d()};return e.jsx("div",{className:"fixed inset-0 bg-black/50 z-[100] flex items-center justify-center p-4",onClick:x,onKeyDown:w,tabIndex:-1,children:e.jsx("div",{className:"bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full transform transition-all duration-200 ease-out",role:"dialog","aria-modal":"true","aria-labelledby":"password-warning-title","aria-describedby":"password-warning-message",children:e.jsxs("div",{className:"p-6",children:[e.jsxs("div",{className:"flex items-start space-x-3",children:[e.jsx("div",{className:"flex-shrink-0",children:e.jsx("svg",{className:"w-6 h-6 text-yellow-600 dark:text-yellow-400",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"})})}),e.jsxs("div",{className:"flex-1",children:[e.jsx("h3",{id:"password-warning-title",className:"text-lg font-medium text-gray-900 dark:text-white mb-2",children:i("auth.defaultPasswordWarning")}),e.jsx("p",{id:"password-warning-message",className:"text-gray-600 dark:text-gray-300 leading-relaxed",children:i("auth.defaultPasswordMessage")})]})]}),e.jsxs("div",{className:"flex justify-end space-x-3 mt-6",children:[e.jsx("button",{onClick:d,className:"hub-btn",children:i("common.cancel")}),e.jsx("button",{onClick:k,className:"hub-btn primary",autoFocus:!0,children:i("auth.goToSettings")})]})]})})})},pe=s=>{if(!s)return null;try{const d=typeof window<"u"?window.location.origin:"http://localhost",i=new URL(s,d);return i.origin!==d?null:`${i.pathname}${i.search}${i.hash}`||"/"}catch{return s.startsWith("/")&&!s.startsWith("//")?s:null}},je=()=>{const{t:s}=J(),[d,i]=n.useState(!1),[c,k]=n.useState(!1),[x,w]=n.useState(""),[o,v]=n.useState(""),[m,C]=n.useState(""),[Q,u]=n.useState(null),[N,S]=n.useState(!1),[h,R]=n.useState(null),[U,j]=n.useState(null),[z,X]=n.useState(void 0),[P,Y]=n.useState(!1),[g,W]=n.useState({google:!1,github:!1,oidc:!1}),[Z,ee]=n.useState("oidc"),[se,A]=n.useState(!1),{login:te,register:ae,auth:b}=le(),y=oe(),E=V(),l=n.useMemo(()=>{const a=new URLSearchParams(y.search);return pe(a.get("returnUrl"))},[y.search]),I=n.useCallback(a=>{if(!a)return!1;const t=a.toLowerCase();return t.includes("failed to fetch")||t.includes("networkerror")||t.includes("network error")||t.includes("connection refused")||t.includes("unable to connect")||t.includes("fetch error")||t.includes("econnrefused")||t.includes("http 500")||t.includes("internal server error")||t.includes("proxy error")},[]),T=n.useCallback(()=>{if(!l)return"/";if(!l.startsWith("/oauth/authorize"))return l;const a=ie();if(!a)return l;try{const t=window.location.origin,r=new URL(l,t);return r.searchParams.set("token",a),`${r.pathname}${r.search}${r.hash}`}catch{const t=l.includes("?")?"&":"?";return`${l}${t}token=${encodeURIComponent(a)}`}},[l]),p=n.useCallback(()=>{l?window.location.assign(T()):E("/")},[T,E,l]);n.useEffect(()=>{!b.loading&&b.isAuthenticated&&p()},[b.isAuthenticated,b.loading,p]),n.useEffect(()=>{const t=new URLSearchParams(y.search).get("error");if(t){const r=`auth.error.${t}`,f=s(r);j(f!==r?f:s("auth.socialLoginFailed"))}},[y.search,s]),n.useEffect(()=>{(async()=>{var f,B,D,F,M,O,q,G;const t=await ue();i(t.allowRegistration===!0);const r=t.betterAuth;if(!(r!=null&&r.enabled)){W({google:!1,github:!1,oidc:!1});return}X(r.basePath),Y(r.disablePasswordLogin===!0),ee(((B=(f=r.providers)==null?void 0:f.oidc)==null?void 0:B.providerId)||"oidc"),W({google:((F=(D=r.providers)==null?void 0:D.google)==null?void 0:F.enabled)===!0,github:((O=(M=r.providers)==null?void 0:M.github)==null?void 0:O.enabled)===!0,oidc:((G=(q=r.providers)==null?void 0:q.oidc)==null?void 0:G.enabled)===!0})})()},[]);const re=async a=>{a.preventDefault(),u(null),j(null),S(!0);try{if(!o||!m){u(s("auth.emptyFields")),S(!1);return}if(c){if(m!==x){u(s("auth.passwordsNotMatch"));return}await ae(o,m)&&p();return}const t=await te(o,m);if(t.success)t.isUsingDefaultPassword?A(!0):p();else{const r=t.message;u(I(r)?s("auth.serverUnavailable"):s("auth.loginFailed"))}}catch(t){const r=t instanceof Error?t.message:void 0;u(I(r)?s("auth.serverUnavailable"):s("auth.loginError"))}finally{S(!1)}},L=async a=>{j(null),R(a);try{if(a==="oidc"){await he({providerId:Z,callbackURL:l||"/",errorCallbackURL:`${K()}/login`,basePathOverride:z});return}await ge(z).signIn.social({provider:a,callbackURL:l||"/",errorCallbackURL:`${K()}/login`})}catch(t){console.error("Social login error:",t),j(s("auth.socialLoginFailed")),R(null)}},$=Q||(c?b.error:null),ne=()=>{A(!1),p()};return e.jsxs("div",{className:"relative min-h-screen w-full overflow-hidden",style:{background:"var(--hub-bg)",color:"var(--hub-ink)"},children:[e.jsxs("div",{className:"absolute top-3 right-4 z-20 flex items-center gap-1",children:[e.jsx("a",{href:"https://github.com/samanhappy/mcphub",target:"_blank",rel:"noopener noreferrer",className:"hub-icon-btn","aria-label":"GitHub Repository",children:e.jsx(H,{className:"h-4 w-4"})}),e.jsx("a",{href:"https://docs.mcphub.app",target:"_blank",rel:"noopener noreferrer",className:"hub-icon-btn","aria-label":"Documentation",children:e.jsx(me,{className:"h-4 w-4"})}),e.jsx(ce,{}),e.jsx(de,{})]}),e.jsx("div",{className:"pointer-events-none absolute inset-0 -z-10",children:e.jsxs("svg",{className:"h-full w-full",style:{opacity:.5},xmlns:"http://www.w3.org/2000/svg",children:[e.jsx("defs",{children:e.jsx("pattern",{id:"grid",width:"32",height:"32",patternUnits:"userSpaceOnUse",children:e.jsx("path",{d:"M 32 0 L 0 0 0 32",fill:"none",stroke:"var(--hub-line-2)",strokeWidth:"0.5"})})}),e.jsx("rect",{width:"100%",height:"100%",fill:"url(#grid)"})]})}),e.jsx("div",{className:"relative mx-auto flex min-h-screen w-full max-w-md items-center justify-center px-6",children:e.jsxs("div",{className:"w-full space-y-8",children:[e.jsxs("div",{className:"flex flex-col items-center gap-3",children:[e.jsxs("div",{className:"relative grid place-items-center",style:{width:44,height:44,borderRadius:10,background:"var(--hub-ink)",color:"var(--hub-bg)"},children:[e.jsx("span",{className:"hub-mono font-semibold",style:{fontSize:18},children:"M"}),e.jsx("span",{className:"absolute",style:{right:-2,bottom:-2,width:8,height:8,borderRadius:50,background:"var(--hub-ok)",boxShadow:"0 0 0 3px var(--hub-bg)"}})]}),e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{style:{fontSize:20,fontWeight:600,letterSpacing:"-0.02em",color:"var(--hub-ink)"},children:s("app.title")}),e.jsx("p",{className:"hub-sub",style:{marginTop:4},children:s("auth.slogan")})]})]}),e.jsxs("div",{className:"hub-card",style:{padding:"22px 22px 20px",boxShadow:"0 1px 2px rgba(0,0,0,0.02)"},children:[!P&&e.jsxs("form",{className:"space-y-3",onSubmit:re,children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:"username",className:"hub-sect block",style:{marginBottom:6},children:s("auth.username")}),e.jsx("input",{id:"username",name:"username",type:"text",autoComplete:"username",required:!0,className:"hub-input",placeholder:s("auth.username"),value:o,onChange:a=>v(a.target.value)})]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"password",className:"hub-sect block",style:{marginBottom:6},children:s("auth.password")}),e.jsx("input",{id:"password",name:"password",type:"password",autoComplete:c?"new-password":"current-password",minLength:c?8:void 0,required:!0,className:"hub-input",placeholder:s("auth.password"),value:m,onChange:a=>C(a.target.value)})]}),c&&e.jsxs("div",{children:[e.jsx("p",{className:"hub-sub mb-3",children:s("auth.passwordStrengthHint")}),e.jsx("label",{htmlFor:"confirmPassword",className:"hub-sect block mb-1.5",children:s("auth.confirmPassword")}),e.jsx("input",{id:"confirmPassword",name:"confirmPassword",type:"password",autoComplete:"new-password",required:!0,className:"hub-input",value:x,onChange:a=>w(a.target.value)})]}),$&&e.jsxs("div",{role:"alert",className:"flex items-center gap-2",style:{padding:"8px 10px",borderRadius:7,border:"1px solid oklch(0.85 0.1 25)",background:"oklch(0.97 0.03 25)",color:"oklch(0.4 0.18 25)",fontSize:12.5},children:[e.jsx(_,{size:13,className:"flex-shrink-0"}),e.jsx("span",{children:$})]}),e.jsx("button",{type:"submit",disabled:N,className:"hub-btn primary w-full justify-center",style:{height:34},children:s(N?"common.loading":c?"auth.createAccount":"auth.login")}),d&&e.jsx("button",{type:"button",disabled:N,className:"hub-btn w-full justify-center",onClick:()=>{k(!c),u(null),C(""),w("")},children:s(c?"auth.backToLogin":"auth.createAccount")})]}),(g.google||g.github||g.oidc)&&e.jsxs("div",{className:P?"space-y-3":"mt-5 space-y-3",children:[!P&&e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"h-px flex-1",style:{background:"var(--hub-line)"}}),e.jsx("span",{className:"hub-sect",style:{textTransform:"uppercase",letterSpacing:"0.08em"},children:s("auth.orContinue")}),e.jsx("div",{className:"h-px flex-1",style:{background:"var(--hub-line)"}})]}),U&&e.jsxs("div",{className:"flex items-center gap-2",style:{padding:"8px 10px",borderRadius:7,border:"1px solid oklch(0.85 0.1 25)",background:"oklch(0.97 0.03 25)",color:"oklch(0.4 0.18 25)",fontSize:12.5},children:[e.jsx(_,{size:13,className:"flex-shrink-0"}),e.jsx("span",{children:U})]}),e.jsxs("div",{className:"space-y-2",children:[g.google&&e.jsx("button",{type:"button",onClick:()=>L("google"),disabled:h!==null,className:"hub-btn w-full justify-center",style:{height:34},children:s(h==="google"?"auth.loggingIn":"auth.loginWithGoogle")}),g.github&&e.jsxs("button",{type:"button",onClick:()=>L("github"),disabled:h!==null,className:"hub-btn w-full justify-center",style:{height:34,background:"var(--hub-ink)",color:"var(--hub-bg)",borderColor:"var(--hub-ink)"},children:[e.jsx(H,{className:"h-3.5 w-3.5"}),s(h==="github"?"auth.loggingIn":"auth.loginWithGithub")]}),g.oidc&&e.jsx("button",{type:"button",onClick:()=>L("oidc"),disabled:h!==null,className:"hub-btn w-full justify-center",style:{height:34},children:s(h==="oidc"?"auth.loggingIn":"auth.loginWithOIDC")})]})]})]}),e.jsxs("p",{className:"text-center hub-mono",style:{fontSize:11,color:"var(--hub-ink-3)"},children:["v","1.1.12"]})]})}),e.jsx(be,{isOpen:se,onClose:ne})]})};export{je as default};
|
|
2
|
-
//# sourceMappingURL=LoginPage-BRyFcGQ5.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"LoginPage-BRyFcGQ5.js","sources":["../../src/components/ui/DefaultPasswordWarningModal.tsx","../../src/pages/LoginPage.tsx"],"sourcesContent":["import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useNavigate } from 'react-router-dom';\n\ninterface DefaultPasswordWarningModalProps {\n isOpen: boolean;\n onClose: () => void;\n}\n\nconst DefaultPasswordWarningModal: React.FC<DefaultPasswordWarningModalProps> = ({\n isOpen,\n onClose,\n}) => {\n const { t } = useTranslation();\n const navigate = useNavigate();\n\n if (!isOpen) return null;\n\n const handleGoToSettings = () => {\n onClose();\n navigate('/settings');\n // Auto-scroll to password section after a small delay to ensure page is loaded\n setTimeout(() => {\n const passwordSection = document.querySelector('[data-section=\"password\"]');\n if (passwordSection) {\n passwordSection.scrollIntoView({ behavior: 'smooth', block: 'start' });\n // If the section is collapsed, expand it\n const clickTarget = passwordSection.querySelector('[role=\"button\"]');\n if (clickTarget && !passwordSection.querySelector('.mt-4')) {\n (clickTarget as HTMLElement).click();\n }\n }\n }, 100);\n };\n\n const handleBackdropClick = (e: React.MouseEvent) => {\n if (e.target === e.currentTarget) {\n onClose();\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n onClose();\n }\n };\n\n return (\n <div\n className=\"fixed inset-0 bg-black/50 z-[100] flex items-center justify-center p-4\"\n onClick={handleBackdropClick}\n onKeyDown={handleKeyDown}\n tabIndex={-1}\n >\n <div\n className=\"bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full transform transition-all duration-200 ease-out\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"password-warning-title\"\n aria-describedby=\"password-warning-message\"\n >\n <div className=\"p-6\">\n <div className=\"flex items-start space-x-3\">\n <div className=\"flex-shrink-0\">\n <svg\n className=\"w-6 h-6 text-yellow-600 dark:text-yellow-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z\"\n />\n </svg>\n </div>\n <div className=\"flex-1\">\n <h3\n id=\"password-warning-title\"\n className=\"text-lg font-medium text-gray-900 dark:text-white mb-2\"\n >\n {t('auth.defaultPasswordWarning')}\n </h3>\n <p\n id=\"password-warning-message\"\n className=\"text-gray-600 dark:text-gray-300 leading-relaxed\"\n >\n {t('auth.defaultPasswordMessage')}\n </p>\n </div>\n </div>\n\n <div className=\"flex justify-end space-x-3 mt-6\">\n <button\n onClick={onClose}\n className=\"hub-btn\"\n >\n {t('common.cancel')}\n </button>\n <button\n onClick={handleGoToSettings}\n className=\"hub-btn primary\"\n autoFocus\n >\n {t('auth.goToSettings')}\n </button>\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport default DefaultPasswordWarningModal;\n","import React, { useState, useMemo, useCallback, useEffect } from 'react';\nimport { useLocation, useNavigate } from 'react-router-dom';\nimport { useTranslation } from 'react-i18next';\nimport { BookOpen, AlertCircle } from 'lucide-react';\nimport { useAuth } from '../contexts/AuthContext';\nimport { getToken } from '../services/authService';\nimport { getPublicConfig } from '../services/configService';\nimport { createBetterAuthClient, startOidcLogin } from '../services/betterAuthClient';\nimport { getBasePath } from '../utils/runtime';\nimport ThemeSwitch from '@/components/ui/ThemeSwitch';\nimport LanguageSwitch from '@/components/ui/LanguageSwitch';\nimport GitHubIcon from '@/components/icons/GitHubIcon';\nimport DefaultPasswordWarningModal from '@/components/ui/DefaultPasswordWarningModal';\n\ntype SocialProvider = 'google' | 'github' | 'oidc';\n\nconst sanitizeReturnUrl = (value: string | null): string | null => {\n if (!value) return null;\n try {\n const origin = typeof window !== 'undefined' ? window.location.origin : 'http://localhost';\n const url = new URL(value, origin);\n if (url.origin !== origin) return null;\n const relativePath = `${url.pathname}${url.search}${url.hash}`;\n return relativePath || '/';\n } catch {\n if (value.startsWith('/') && !value.startsWith('//')) return value;\n return null;\n }\n};\n\nconst LoginPage: React.FC = () => {\n const { t } = useTranslation();\n const [allowRegistration, setAllowRegistration] = useState(false);\n const [registering, setRegistering] = useState(false);\n const [confirmPassword, setConfirmPassword] = useState('');\n const [username, setUsername] = useState('');\n const [password, setPassword] = useState('');\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(false);\n const [socialLoading, setSocialLoading] = useState<SocialProvider | null>(null);\n const [socialError, setSocialError] = useState<string | null>(null);\n const [betterAuthBasePath, setBetterAuthBasePath] = useState<string | undefined>(undefined);\n // Set from the public config: only SSO sign-in is offered\n const [passwordLoginDisabled, setPasswordLoginDisabled] = useState(false);\n const [socialProviders, setSocialProviders] = useState({\n google: false,\n github: false,\n oidc: false,\n });\n const [oidcProviderId, setOidcProviderId] = useState<string>('oidc');\n const [showDefaultPasswordWarning, setShowDefaultPasswordWarning] = useState(false);\n const { login, register, auth } = useAuth();\n const location = useLocation();\n const navigate = useNavigate();\n const returnUrl = useMemo(() => {\n const params = new URLSearchParams(location.search);\n return sanitizeReturnUrl(params.get('returnUrl'));\n }, [location.search]);\n\n const isServerUnavailableError = useCallback((message?: string) => {\n if (!message) return false;\n const normalized = message.toLowerCase();\n return (\n normalized.includes('failed to fetch') ||\n normalized.includes('networkerror') ||\n normalized.includes('network error') ||\n normalized.includes('connection refused') ||\n normalized.includes('unable to connect') ||\n normalized.includes('fetch error') ||\n normalized.includes('econnrefused') ||\n normalized.includes('http 500') ||\n normalized.includes('internal server error') ||\n normalized.includes('proxy error')\n );\n }, []);\n\n const buildRedirectTarget = useCallback(() => {\n if (!returnUrl) return '/';\n if (!returnUrl.startsWith('/oauth/authorize')) return returnUrl;\n const token = getToken();\n if (!token) return returnUrl;\n try {\n const origin = window.location.origin;\n const url = new URL(returnUrl, origin);\n url.searchParams.set('token', token);\n return `${url.pathname}${url.search}${url.hash}`;\n } catch {\n const separator = returnUrl.includes('?') ? '&' : '?';\n return `${returnUrl}${separator}token=${encodeURIComponent(token)}`;\n }\n }, [returnUrl]);\n\n const redirectAfterLogin = useCallback(() => {\n if (returnUrl) {\n window.location.assign(buildRedirectTarget());\n } else {\n navigate('/');\n }\n }, [buildRedirectTarget, navigate, returnUrl]);\n\n useEffect(() => {\n if (!auth.loading && auth.isAuthenticated) redirectAfterLogin();\n }, [auth.isAuthenticated, auth.loading, redirectAfterLogin]);\n\n useEffect(() => {\n const params = new URLSearchParams(location.search);\n const errorCode = params.get('error');\n if (errorCode) {\n const i18nKey = `auth.error.${errorCode}`;\n const translated = t(i18nKey);\n setSocialError(translated !== i18nKey ? translated : t('auth.socialLoginFailed'));\n }\n }, [location.search, t]);\n\n useEffect(() => {\n const loadAuthProviders = async () => {\n const publicConfig = await getPublicConfig();\n setAllowRegistration(publicConfig.allowRegistration === true);\n const betterAuth = publicConfig.betterAuth;\n if (!betterAuth?.enabled) {\n setSocialProviders({ google: false, github: false, oidc: false });\n return;\n }\n setBetterAuthBasePath(betterAuth.basePath);\n setPasswordLoginDisabled(betterAuth.disablePasswordLogin === true);\n setOidcProviderId(betterAuth.providers?.oidc?.providerId || 'oidc');\n setSocialProviders({\n google: betterAuth.providers?.google?.enabled === true,\n github: betterAuth.providers?.github?.enabled === true,\n oidc: betterAuth.providers?.oidc?.enabled === true,\n });\n };\n loadAuthProviders();\n }, []);\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError(null);\n setSocialError(null);\n setLoading(true);\n try {\n if (!username || !password) {\n setError(t('auth.emptyFields'));\n setLoading(false);\n return;\n }\n if (registering) {\n if (password !== confirmPassword) {\n setError(t('auth.passwordsNotMatch'));\n return;\n }\n if (await register(username, password)) redirectAfterLogin();\n return;\n }\n const result = await login(username, password);\n if (result.success) {\n if (result.isUsingDefaultPassword) setShowDefaultPasswordWarning(true);\n else redirectAfterLogin();\n } else {\n const message = result.message;\n setError(\n isServerUnavailableError(message) ? t('auth.serverUnavailable') : t('auth.loginFailed'),\n );\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : undefined;\n setError(\n isServerUnavailableError(message) ? t('auth.serverUnavailable') : t('auth.loginError'),\n );\n } finally {\n setLoading(false);\n }\n };\n\n const handleSocialLogin = async (provider: SocialProvider) => {\n setSocialError(null);\n setSocialLoading(provider);\n try {\n if (provider === 'oidc') {\n await startOidcLogin({\n providerId: oidcProviderId,\n callbackURL: returnUrl || '/',\n errorCallbackURL: `${getBasePath()}/login`,\n basePathOverride: betterAuthBasePath,\n });\n return;\n }\n\n const client = createBetterAuthClient(betterAuthBasePath);\n await client.signIn.social({\n provider,\n callbackURL: returnUrl || '/',\n errorCallbackURL: `${getBasePath()}/login`,\n });\n } catch (err) {\n console.error('Social login error:', err);\n setSocialError(t('auth.socialLoginFailed'));\n setSocialLoading(null);\n }\n };\n\n const formError = error || (registering ? auth.error : null);\n\n const handleCloseWarning = () => {\n setShowDefaultPasswordWarning(false);\n redirectAfterLogin();\n };\n\n return (\n <div\n className=\"relative min-h-screen w-full overflow-hidden\"\n style={{ background: 'var(--hub-bg)', color: 'var(--hub-ink)' }}\n >\n {/* Top-right controls */}\n <div className=\"absolute top-3 right-4 z-20 flex items-center gap-1\">\n <a\n href=\"https://github.com/samanhappy/mcphub\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"hub-icon-btn\"\n aria-label=\"GitHub Repository\"\n >\n <GitHubIcon className=\"h-4 w-4\" />\n </a>\n <a\n href=\"https://docs.mcphub.app\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"hub-icon-btn\"\n aria-label=\"Documentation\"\n >\n <BookOpen className=\"h-4 w-4\" />\n </a>\n <ThemeSwitch />\n <LanguageSwitch />\n </div>\n\n {/* Subtle grid pattern (kept low-key, hair-line) */}\n <div className=\"pointer-events-none absolute inset-0 -z-10\">\n <svg\n className=\"h-full w-full\"\n style={{ opacity: 0.5 }}\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <defs>\n <pattern id=\"grid\" width=\"32\" height=\"32\" patternUnits=\"userSpaceOnUse\">\n <path\n d=\"M 32 0 L 0 0 0 32\"\n fill=\"none\"\n stroke=\"var(--hub-line-2)\"\n strokeWidth=\"0.5\"\n />\n </pattern>\n </defs>\n <rect width=\"100%\" height=\"100%\" fill=\"url(#grid)\" />\n </svg>\n </div>\n\n <div className=\"relative mx-auto flex min-h-screen w-full max-w-md items-center justify-center px-6\">\n <div className=\"w-full space-y-8\">\n {/* Brand */}\n <div className=\"flex flex-col items-center gap-3\">\n <div\n className=\"relative grid place-items-center\"\n style={{\n width: 44,\n height: 44,\n borderRadius: 10,\n background: 'var(--hub-ink)',\n color: 'var(--hub-bg)',\n }}\n >\n <span className=\"hub-mono font-semibold\" style={{ fontSize: 18 }}>\n M\n </span>\n <span\n className=\"absolute\"\n style={{\n right: -2,\n bottom: -2,\n width: 8,\n height: 8,\n borderRadius: 50,\n background: 'var(--hub-ok)',\n boxShadow: '0 0 0 3px var(--hub-bg)',\n }}\n />\n </div>\n <div className=\"text-center\">\n <h1\n style={{\n fontSize: 20,\n fontWeight: 600,\n letterSpacing: '-0.02em',\n color: 'var(--hub-ink)',\n }}\n >\n {t('app.title')}\n </h1>\n <p className=\"hub-sub\" style={{ marginTop: 4 }}>\n {t('auth.slogan')}\n </p>\n </div>\n </div>\n\n {/* Login card */}\n <div\n className=\"hub-card\"\n style={{\n padding: '22px 22px 20px',\n boxShadow: '0 1px 2px rgba(0,0,0,0.02)',\n }}\n >\n {!passwordLoginDisabled && (\n <form className=\"space-y-3\" onSubmit={handleSubmit}>\n <div>\n <label\n htmlFor=\"username\"\n className=\"hub-sect block\"\n style={{ marginBottom: 6 }}\n >\n {t('auth.username')}\n </label>\n <input\n id=\"username\"\n name=\"username\"\n type=\"text\"\n autoComplete=\"username\"\n required\n className=\"hub-input\"\n placeholder={t('auth.username')}\n value={username}\n onChange={(e) => setUsername(e.target.value)}\n />\n </div>\n <div>\n <label\n htmlFor=\"password\"\n className=\"hub-sect block\"\n style={{ marginBottom: 6 }}\n >\n {t('auth.password')}\n </label>\n <input\n id=\"password\"\n name=\"password\"\n type=\"password\"\n autoComplete={registering ? 'new-password' : 'current-password'}\n minLength={registering ? 8 : undefined}\n required\n className=\"hub-input\"\n placeholder={t('auth.password')}\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n />\n </div>\n\n {registering && (\n <div>\n <p className=\"hub-sub mb-3\">{t('auth.passwordStrengthHint')}</p>\n <label htmlFor=\"confirmPassword\" className=\"hub-sect block mb-1.5\">\n {t('auth.confirmPassword')}\n </label>\n <input\n id=\"confirmPassword\"\n name=\"confirmPassword\"\n type=\"password\"\n autoComplete=\"new-password\"\n required\n className=\"hub-input\"\n value={confirmPassword}\n onChange={(e) => setConfirmPassword(e.target.value)}\n />\n </div>\n )}\n\n {formError && (\n <div role=\"alert\"\n className=\"flex items-center gap-2\"\n style={{\n padding: '8px 10px',\n borderRadius: 7,\n border: '1px solid oklch(0.85 0.1 25)',\n background: 'oklch(0.97 0.03 25)',\n color: 'oklch(0.4 0.18 25)',\n fontSize: 12.5,\n }}\n >\n <AlertCircle size={13} className=\"flex-shrink-0\" />\n <span>{formError}</span>\n </div>\n )}\n\n <button\n type=\"submit\"\n disabled={loading}\n className=\"hub-btn primary w-full justify-center\"\n style={{ height: 34 }}\n >\n {loading\n ? t('common.loading')\n : t(registering ? 'auth.createAccount' : 'auth.login')}\n </button>\n {allowRegistration && (\n <button\n type=\"button\"\n disabled={loading}\n className=\"hub-btn w-full justify-center\"\n onClick={() => {\n setRegistering(!registering);\n setError(null);\n setPassword('');\n setConfirmPassword('');\n }}\n >\n {t(registering ? 'auth.backToLogin' : 'auth.createAccount')}\n </button>\n )}\n </form>\n )}\n\n {(socialProviders.google || socialProviders.github || socialProviders.oidc) && (\n <div className={passwordLoginDisabled ? 'space-y-3' : 'mt-5 space-y-3'}>\n {!passwordLoginDisabled && (\n <div className=\"flex items-center gap-3\">\n <div className=\"h-px flex-1\" style={{ background: 'var(--hub-line)' }} />\n <span\n className=\"hub-sect\"\n style={{ textTransform: 'uppercase', letterSpacing: '0.08em' }}\n >\n {t('auth.orContinue')}\n </span>\n <div className=\"h-px flex-1\" style={{ background: 'var(--hub-line)' }} />\n </div>\n )}\n\n {socialError && (\n <div\n className=\"flex items-center gap-2\"\n style={{\n padding: '8px 10px',\n borderRadius: 7,\n border: '1px solid oklch(0.85 0.1 25)',\n background: 'oklch(0.97 0.03 25)',\n color: 'oklch(0.4 0.18 25)',\n fontSize: 12.5,\n }}\n >\n <AlertCircle size={13} className=\"flex-shrink-0\" />\n <span>{socialError}</span>\n </div>\n )}\n\n <div className=\"space-y-2\">\n {socialProviders.google && (\n <button\n type=\"button\"\n onClick={() => handleSocialLogin('google')}\n disabled={socialLoading !== null}\n className=\"hub-btn w-full justify-center\"\n style={{ height: 34 }}\n >\n {socialLoading === 'google'\n ? t('auth.loggingIn')\n : t('auth.loginWithGoogle')}\n </button>\n )}\n {socialProviders.github && (\n <button\n type=\"button\"\n onClick={() => handleSocialLogin('github')}\n disabled={socialLoading !== null}\n className=\"hub-btn w-full justify-center\"\n style={{\n height: 34,\n background: 'var(--hub-ink)',\n color: 'var(--hub-bg)',\n borderColor: 'var(--hub-ink)',\n }}\n >\n <GitHubIcon className=\"h-3.5 w-3.5\" />\n {socialLoading === 'github'\n ? t('auth.loggingIn')\n : t('auth.loginWithGithub')}\n </button>\n )}\n {socialProviders.oidc && (\n <button\n type=\"button\"\n onClick={() => handleSocialLogin('oidc')}\n disabled={socialLoading !== null}\n className=\"hub-btn w-full justify-center\"\n style={{ height: 34 }}\n >\n {socialLoading === 'oidc'\n ? t('auth.loggingIn')\n : t('auth.loginWithOIDC')}\n </button>\n )}\n </div>\n </div>\n )}\n </div>\n\n <p\n className=\"text-center hub-mono\"\n style={{ fontSize: 11, color: 'var(--hub-ink-3)' }}\n >\n v{import.meta.env.PACKAGE_VERSION}\n </p>\n </div>\n </div>\n\n <DefaultPasswordWarningModal\n isOpen={showDefaultPasswordWarning}\n onClose={handleCloseWarning}\n />\n </div>\n );\n};\n\nexport default LoginPage;\n"],"names":["DefaultPasswordWarningModal","isOpen","onClose","t","useTranslation","navigate","useNavigate","handleGoToSettings","passwordSection","clickTarget","handleBackdropClick","e","handleKeyDown","jsx","jsxs","sanitizeReturnUrl","value","origin","url","LoginPage","allowRegistration","setAllowRegistration","useState","registering","setRegistering","confirmPassword","setConfirmPassword","username","setUsername","password","setPassword","error","setError","loading","setLoading","socialLoading","setSocialLoading","socialError","setSocialError","betterAuthBasePath","setBetterAuthBasePath","passwordLoginDisabled","setPasswordLoginDisabled","socialProviders","setSocialProviders","oidcProviderId","setOidcProviderId","showDefaultPasswordWarning","setShowDefaultPasswordWarning","login","register","auth","useAuth","location","useLocation","returnUrl","useMemo","params","isServerUnavailableError","useCallback","message","normalized","buildRedirectTarget","token","getToken","separator","redirectAfterLogin","useEffect","errorCode","i18nKey","translated","publicConfig","getPublicConfig","betterAuth","_b","_a","_d","_c","_f","_e","_h","_g","handleSubmit","result","err","handleSocialLogin","provider","startOidcLogin","getBasePath","createBetterAuthClient","formError","handleCloseWarning","GitHubIcon","BookOpen","ThemeSwitch","LanguageSwitch","AlertCircle"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"LogsPage-C7erxObE.js","sources":["../../../node_modules/.pnpm/@radix-ui+react-compose-refs@1.1.5_@types+react@19.2.16_react@19.2.7/node_modules/@radix-ui/react-compose-refs/dist/index.mjs","../../../node_modules/.pnpm/@radix-ui+react-slot@1.3.3_@types+react@19.2.16_react@19.2.7/node_modules/@radix-ui/react-slot/dist/index.mjs","../../src/components/ui/Button.tsx","../../src/components/ui/Badge.tsx","../../src/components/LogViewer.tsx","../../src/pages/LogsPage.tsx"],"sourcesContent":["var __defProp = Object.defineProperty;\nvar __name = (target, value) => __defProp(target, \"name\", { value, configurable: true });\n\n// src/compose-refs.tsx\nimport * as React from \"react\";\nfunction setRef(ref, value) {\n if (typeof ref === \"function\") {\n return ref(value);\n } else if (ref !== null && ref !== void 0) {\n ref.current = value;\n }\n}\n__name(setRef, \"setRef\");\nfunction composeRefs(...refs) {\n return (node) => {\n let hasCleanup = false;\n const cleanups = refs.map((ref) => {\n const cleanup = setRef(ref, node);\n if (!hasCleanup && typeof cleanup == \"function\") {\n hasCleanup = true;\n }\n return cleanup;\n });\n if (hasCleanup) {\n return () => {\n for (let i = 0; i < cleanups.length; i++) {\n const cleanup = cleanups[i];\n if (typeof cleanup == \"function\") {\n cleanup();\n } else {\n setRef(refs[i], null);\n }\n }\n };\n }\n };\n}\n__name(composeRefs, \"composeRefs\");\nfunction useComposedRefs(...refs) {\n return React.useCallback(composeRefs(...refs), refs);\n}\n__name(useComposedRefs, \"useComposedRefs\");\nexport {\n composeRefs,\n useComposedRefs\n};\n//# sourceMappingURL=index.mjs.map\n","var __defProp = Object.defineProperty;\nvar __name = (target, value) => __defProp(target, \"name\", { value, configurable: true });\n\n// src/slot.tsx\nimport * as React from \"react\";\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\n// @__NO_SIDE_EFFECTS__\nfunction createSlot(ownerName) {\n const Slot2 = React.forwardRef((props, forwardedRef) => {\n let { children, ...slotProps } = props;\n let slottableElement = null;\n let hasSlottable = false;\n const newChildren = [];\n if (isLazyComponent(children) && typeof use === \"function\") {\n children = use(children._payload);\n }\n React.Children.forEach(children, (maybeSlottable) => {\n if (isSlottable(maybeSlottable)) {\n hasSlottable = true;\n const slottable = maybeSlottable;\n let child = \"child\" in slottable.props ? slottable.props.child : slottable.props.children;\n if (isLazyComponent(child) && typeof use === \"function\") {\n child = use(child._payload);\n }\n slottableElement = getSlottableElementFromSlottable(slottable, child);\n newChildren.push(slottableElement?.props?.children);\n } else {\n newChildren.push(maybeSlottable);\n }\n });\n if (slottableElement) {\n slottableElement = React.cloneElement(slottableElement, void 0, newChildren);\n } else if (\n // A `Slottable` was found but it didn't resolve to a single element (e.g.\n // it wrapped multiple elements, text, or a render-prop `child` that\n // wasn't an element). Don't fall back to treating the `Slottable` wrapper\n // itself as the slot target — throw a descriptive error below instead.\n !hasSlottable && React.Children.count(children) === 1 && React.isValidElement(children)\n ) {\n slottableElement = children;\n }\n const slottableElementRef = slottableElement ? getElementRef(slottableElement) : void 0;\n const composedRef = useComposedRefs(forwardedRef, slottableElementRef);\n if (!slottableElement) {\n if (children || children === 0) {\n throw new Error(\n hasSlottable ? createSlottableError(ownerName) : createSlotError(ownerName)\n );\n }\n return children;\n }\n const mergedProps = mergeProps(slotProps, slottableElement.props ?? {});\n if (slottableElement.type !== React.Fragment) {\n mergedProps.ref = forwardedRef ? composedRef : slottableElementRef;\n }\n return React.cloneElement(slottableElement, mergedProps);\n });\n Slot2.displayName = `${ownerName}.Slot`;\n return Slot2;\n}\n__name(createSlot, \"createSlot\");\nvar Slot = /* @__PURE__ */ createSlot(\"Slot\");\nvar SLOTTABLE_IDENTIFIER = Symbol.for(\"radix.slottable\");\n// @__NO_SIDE_EFFECTS__\nfunction createSlottable(ownerName) {\n const Slottable2 = /* @__PURE__ */ __name((props) => \"child\" in props ? props.children(props.child) : props.children, \"Slottable\");\n Slottable2.displayName = `${ownerName}.Slottable`;\n Slottable2.__radixId = SLOTTABLE_IDENTIFIER;\n return Slottable2;\n}\n__name(createSlottable, \"createSlottable\");\nvar Slottable = /* @__PURE__ */ createSlottable(\"Slottable\");\nvar getSlottableElementFromSlottable = /* @__PURE__ */ __name((slottable, child) => {\n if (\"child\" in slottable.props) {\n const child2 = slottable.props.child;\n if (!React.isValidElement(child2)) return null;\n return React.cloneElement(child2, void 0, slottable.props.children(child2.props.children));\n }\n return React.isValidElement(child) ? child : null;\n}, \"getSlottableElementFromSlottable\");\nfunction mergeProps(slotProps, childProps) {\n const overrideProps = { ...childProps };\n for (const propName in childProps) {\n const slotPropValue = slotProps[propName];\n const childPropValue = childProps[propName];\n const isHandler = /^on[A-Z]/.test(propName);\n if (isHandler) {\n if (slotPropValue && childPropValue) {\n overrideProps[propName] = (...args) => {\n const result = childPropValue(...args);\n slotPropValue(...args);\n return result;\n };\n } else if (slotPropValue) {\n overrideProps[propName] = slotPropValue;\n }\n } else if (propName === \"style\") {\n overrideProps[propName] = { ...slotPropValue, ...childPropValue };\n } else if (propName === \"className\") {\n overrideProps[propName] = [slotPropValue, childPropValue].filter(Boolean).join(\" \");\n }\n }\n return { ...slotProps, ...overrideProps };\n}\n__name(mergeProps, \"mergeProps\");\nfunction getElementRef(element) {\n let getter = Object.getOwnPropertyDescriptor(element.props, \"ref\")?.get;\n let mayWarn = getter && \"isReactWarning\" in getter && getter.isReactWarning;\n if (mayWarn) {\n return element.ref;\n }\n getter = Object.getOwnPropertyDescriptor(element, \"ref\")?.get;\n mayWarn = getter && \"isReactWarning\" in getter && getter.isReactWarning;\n if (mayWarn) {\n return element.props.ref;\n }\n return element.props.ref || element.ref;\n}\n__name(getElementRef, \"getElementRef\");\nfunction isSlottable(child) {\n return React.isValidElement(child) && typeof child.type === \"function\" && \"__radixId\" in child.type && child.type.__radixId === SLOTTABLE_IDENTIFIER;\n}\n__name(isSlottable, \"isSlottable\");\nvar REACT_LAZY_TYPE = Symbol.for(\"react.lazy\");\nfunction isLazyComponent(element) {\n return element != null && typeof element === \"object\" && \"$$typeof\" in element && element.$$typeof === REACT_LAZY_TYPE && \"_payload\" in element && isPromiseLike(element._payload);\n}\n__name(isLazyComponent, \"isLazyComponent\");\nfunction isPromiseLike(value) {\n return typeof value === \"object\" && value !== null && \"then\" in value;\n}\n__name(isPromiseLike, \"isPromiseLike\");\nvar createSlotError = /* @__PURE__ */ __name((ownerName) => {\n return `${ownerName} failed to slot onto its children. Expected a single React element child or \\`Slottable\\`.`;\n}, \"createSlotError\");\nvar createSlottableError = /* @__PURE__ */ __name((ownerName) => {\n return `${ownerName} failed to slot onto its \\`Slottable\\`. Expected \\`Slottable\\` to receive a single React element child.`;\n}, \"createSlottableError\");\nvar use = React[\" use \".trim().toString()];\nexport {\n Slot as Root,\n Slot,\n Slottable,\n createSlot,\n createSlottable\n};\n//# sourceMappingURL=index.mjs.map\n","import React, { useState } from 'react';\nimport { Slot } from '@radix-ui/react-slot';\nimport { cn } from '../../utils/cn';\n\ntype ButtonVariant = 'default' | 'outline' | 'ghost' | 'link' | 'destructive';\ntype ButtonSize = 'default' | 'sm' | 'lg' | 'icon';\n\ninterface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n asChild?: boolean;\n loading?: boolean;\n children: React.ReactNode;\n // Allow async handlers: Button detects a returned promise and shows the\n // loading state for the duration of the call.\n onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void | Promise<void>;\n}\n\nconst variantStyles: Record<ButtonVariant, string> = {\n default: 'bg-blue-500 text-white hover:bg-blue-600 focus:ring-blue-500',\n outline: 'border border-gray-300 dark:border-gray-700 bg-transparent hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-300',\n ghost: 'bg-transparent hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-300',\n link: 'bg-transparent underline-offset-4 hover:underline text-blue-500 hover:text-blue-600',\n destructive: 'bg-red-500 text-white hover:bg-red-600 focus:ring-red-500',\n};\n\nconst sizeStyles: Record<ButtonSize, string> = {\n default: 'h-10 py-2 px-4',\n sm: 'h-8 px-3 text-sm',\n lg: 'h-12 px-6',\n icon: 'h-10 w-10 p-0 text-center',\n};\n\nexport function Button({\n variant = 'default',\n size = 'default',\n className,\n disabled,\n loading: externalLoading = false,\n asChild = false,\n children,\n onClick,\n ...props\n}: ButtonProps) {\n const [internalLoading, setInternalLoading] = useState(false);\n const isLoading = externalLoading || internalLoading;\n\n const handleClick = async (e: React.MouseEvent<HTMLButtonElement>) => {\n if (!onClick) return;\n \n try {\n const result = onClick(e);\n if (result && typeof (result as any).then === 'function') {\n setInternalLoading(true);\n await result;\n }\n } finally {\n if (internalLoading) {\n // Need to check if component unmounted?\n // It's a standard pattern, state update on unmounted is no longer an error in React 18+\n }\n setInternalLoading(false);\n }\n };\n\n const Comp = asChild ? Slot : 'button';\n\n return (\n <Comp\n className={cn(\n 'rounded-md inline-flex items-center justify-center font-medium transition-all duration-200 active:scale-95 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none relative',\n variantStyles[variant],\n sizeStyles[size],\n className\n )}\n disabled={disabled || isLoading}\n onClick={handleClick}\n {...props}\n >\n {asChild ? (\n children\n ) : (\n <>\n <span className={cn('flex items-center justify-center', isLoading && 'invisible')}>\n {children}\n </span>\n {isLoading && (\n <span className=\"absolute inset-0 flex items-center justify-center\">\n <svg className=\"animate-spin h-5 w-5\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\"></circle>\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n </span>\n )}\n </>\n )}\n </Comp>\n );\n}","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { cn } from '../../utils/cn';\n\ntype BadgeVariant = 'default' | 'secondary' | 'outline' | 'destructive';\n\ntype BadgeProps = {\n children: React.ReactNode;\n variant?: BadgeVariant;\n className?: string;\n onClick?: () => void;\n};\n\nconst badgeVariants = {\n default: 'bg-blue-500 text-white hover:bg-blue-600',\n secondary:\n 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600',\n outline:\n 'bg-transparent border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800',\n destructive: 'bg-red-500 text-white hover:bg-red-600',\n};\n\nexport function Badge({ children, variant = 'default', className, onClick }: BadgeProps) {\n return (\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold transition-colors',\n badgeVariants[variant],\n onClick ? 'cursor-pointer' : '',\n className,\n )}\n onClick={onClick}\n >\n {children}\n </span>\n );\n}\n\n// For backward compatibility with existing code\nexport const StatusBadge = ({\n status,\n onAuthClick,\n}: {\n status: 'connected' | 'disconnected' | 'connecting' | 'oauth_required';\n onAuthClick?: (e: React.MouseEvent) => void;\n}) => {\n const { t } = useTranslation();\n\n const colors = {\n connecting: 'status-badge-connecting',\n connected: 'status-badge-online',\n disconnected: 'status-badge-offline',\n oauth_required: 'status-badge-oauth-required',\n };\n\n // Map status to translation keys\n const statusTranslations = {\n connected: 'status.online',\n disconnected: 'status.offline',\n connecting: 'status.connecting',\n oauth_required: 'status.oauthRequired',\n };\n\n const isOAuthRequired = status === 'oauth_required';\n\n return (\n <span\n className={`px-2 inline-flex text-xs leading-5 font-semibold rounded-full ${colors[status]} ${isOAuthRequired && onAuthClick ? 'cursor-pointer hover:opacity-80' : ''}`}\n onClick={isOAuthRequired && onAuthClick ? (e) => onAuthClick(e) : undefined}\n title={isOAuthRequired ? t('status.clickToAuthorize') : undefined}\n >\n {isOAuthRequired && '🔐 '}\n {t(statusTranslations[status] || status)}\n </span>\n );\n};\n","import React, { useEffect, useRef, useState } from 'react';\nimport { LogEntry } from '../services/logService';\nimport { Button } from './ui/Button';\nimport { Badge } from './ui/Badge';\nimport { useTranslation } from 'react-i18next';\n\ninterface LogViewerProps {\n logs: LogEntry[];\n isLoading?: boolean;\n error?: Error | null;\n onClear?: () => void;\n}\n\nconst LogViewer: React.FC<LogViewerProps> = ({ logs, isLoading = false, error = null, onClear }) => {\n const { t } = useTranslation();\n const logContainerRef = useRef<HTMLDivElement>(null);\n const [autoScroll, setAutoScroll] = useState(true);\n const [filter, setFilter] = useState<string>('');\n const [typeFilter, setTypeFilter] = useState<Array<'info' | 'error' | 'warn' | 'debug'>>(['info', 'error', 'warn', 'debug']);\n const [sourceFilter, setSourceFilter] = useState<Array<'main' | 'child'>>(['main', 'child']);\n\n // Auto scroll to bottom when new logs come in if autoScroll is enabled\n useEffect(() => {\n if (autoScroll && logContainerRef.current) {\n logContainerRef.current.scrollTop = logContainerRef.current.scrollHeight;\n }\n }, [logs, autoScroll]);\n\n // Filter logs based on current filter settings\n const filteredLogs = logs.filter(log => {\n const matchesText = filter ? log.message.toLowerCase().includes(filter.toLowerCase()) : true;\n const matchesType = typeFilter.includes(log.type);\n const matchesSource = sourceFilter.includes(log.source as 'main' | 'child');\n return matchesText && matchesType && matchesSource;\n });\n\n // Format timestamp to readable format\n const formatTimestamp = (timestamp: number) => {\n const date = new Date(timestamp);\n return date.toLocaleTimeString([], {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n hour12: false\n });\n };\n\n // Get badge color based on log type\n const getLogTypeColor = (type: string) => {\n switch (type) {\n case 'error': return 'bg-red-400/80 text-white';\n case 'warn': return 'bg-yellow-400/80 text-gray-900';\n case 'debug': return 'bg-purple-400/80 text-white';\n case 'info': return 'bg-blue-400/80 text-white';\n default: return 'bg-blue-400/80 text-white';\n }\n };\n\n // Get badge color based on log source\n const getSourceColor = (source: string) => {\n switch (source) {\n case 'main': return 'bg-green-400/80 text-white';\n case 'child': return 'bg-orange-400/80 text-white';\n default: return 'bg-gray-400/80 text-white';\n }\n };\n\n return (\n <div className=\"flex flex-col h-full\">\n <div className=\"bg-card p-3 rounded-t-md flex flex-wrap items-center justify-between gap-2\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-semibold text-sm\">{t('logs.filters')}:</span>\n\n {/* Text search filter */}\n <input\n type=\"text\"\n placeholder={t('logs.search')}\n className=\"shadow appearance-none border border-gray-200 dark:border-gray-700 rounded py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline form-input\"\n value={filter}\n onChange={(e) => setFilter(e.target.value)}\n />\n\n {/* Log type filters */}\n <div className=\"flex gap-1 items-center\">\n {(['debug', 'info', 'error', 'warn'] as const).map(type => (\n <Badge\n key={type}\n variant={typeFilter.includes(type) ? 'default' : 'outline'}\n className={`cursor-pointer ${typeFilter.includes(type) ? getLogTypeColor(type) : ''}`}\n onClick={() => {\n if (typeFilter.includes(type)) {\n setTypeFilter(prev => prev.filter(t => t !== type));\n } else {\n setTypeFilter(prev => [...prev, type]);\n }\n }}\n >\n {type}\n </Badge>\n ))}\n </div>\n\n {/* Log source filters */}\n <div className=\"flex gap-1 items-center ml-2\">\n {(['main', 'child'] as const).map(source => (\n <Badge\n key={source}\n variant={sourceFilter.includes(source) ? 'default' : 'outline'}\n className={`cursor-pointer ${sourceFilter.includes(source) ? getSourceColor(source) : ''}`}\n onClick={() => {\n if (sourceFilter.includes(source)) {\n setSourceFilter(prev => prev.filter(s => s !== source));\n } else {\n setSourceFilter(prev => [...prev, source]);\n }\n }}\n >\n {source === 'main' ? t('logs.mainProcess') : t('logs.childProcess')}\n </Badge>\n ))}\n </div>\n </div>\n\n <div className=\"flex items-center gap-2\">\n <label className=\"flex items-center gap-1 text-sm\">\n <input\n type=\"checkbox\"\n checked={autoScroll}\n onChange={() => setAutoScroll(!autoScroll)}\n className=\"form-checkbox h-4 w-4\"\n />\n {t('logs.autoScroll')}\n </label>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={onClear}\n className='btn-secondary'\n disabled={isLoading || logs.length === 0}\n >\n {t('logs.clearLogs')}\n </Button>\n </div>\n </div>\n\n <div\n ref={logContainerRef}\n className=\"flex-grow p-2 overflow-auto bg-card rounded-b-md font-mono text-sm\"\n style={{ maxHeight: 'calc(100vh - 300px)' }}\n >\n {isLoading ? (\n <div className=\"flex justify-center items-center h-full\">\n <span>{t('logs.loading')}</span>\n </div>\n ) : error ? (\n <div className=\"text-red-500 p-2\">\n {error.message}\n </div>\n ) : filteredLogs.length === 0 ? (\n <div className=\"text-center text-muted-foreground p-8\">\n {filter || typeFilter.length < 4 || sourceFilter.length < 2\n ? t('logs.noMatch')\n : t('logs.noLogs')}\n </div>\n ) : (\n filteredLogs.map((log, index) => (\n <div\n key={`${log.timestamp}-${index}`}\n className={`py-1 ${log.type === 'error' ? 'text-red-500' :\n log.type === 'warn' ? 'text-yellow-500' : ''\n }`}\n >\n <span className=\"text-gray-400\">[{formatTimestamp(log.timestamp)}]</span>\n <Badge className={`ml-2 mr-1 ${getLogTypeColor(log.type)}`}>\n {log.type}\n </Badge>\n <Badge\n variant=\"default\"\n className={`mr-2 ${getSourceColor(log.source)}`}\n >\n {log.source === 'main' ? t('logs.main') : t('logs.child')}\n {log.processId ? ` (${log.processId})` : ''}\n </Badge>\n <span className=\"whitespace-pre-wrap\">{log.message}</span>\n </div>\n ))\n )}\n </div>\n </div>\n );\n};\n\nexport default LogViewer;","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport LogViewer from '../components/LogViewer';\nimport { useLogs } from '../services/logService';\n\nconst LogsPage: React.FC = () => {\n const { t } = useTranslation();\n const { logs, loading, error, clearLogs } = useLogs();\n\n return (\n <div>\n <div className=\"mb-6\">\n <h1 className=\"hub-h1\">{t('pages.logs.title')}</h1>\n <p className=\"hub-sub\">\n <span className=\"hub-num\">{logs.length}</span> entries\n </p>\n </div>\n <div className=\"hub-card overflow-hidden\">\n <LogViewer logs={logs} isLoading={loading} error={error} onClear={clearLogs} />\n </div>\n </div>\n );\n};\n\nexport default LogsPage;\n"],"names":["__defProp","__name","target","value","setRef","ref","composeRefs","refs","node","hasCleanup","cleanups","cleanup","i","useComposedRefs","React.useCallback","createSlot","ownerName","Slot2","React.forwardRef","props","forwardedRef","children","slotProps","slottableElement","hasSlottable","newChildren","isLazyComponent","use","React.Children","maybeSlottable","isSlottable","slottable","child","getSlottableElementFromSlottable","_a","React.cloneElement","React.isValidElement","slottableElementRef","getElementRef","composedRef","createSlottableError","createSlotError","mergedProps","mergeProps","React.Fragment","Slot","SLOTTABLE_IDENTIFIER","createSlottable","Slottable2","child2","childProps","overrideProps","propName","slotPropValue","childPropValue","args","result","element","getter","mayWarn","_b","REACT_LAZY_TYPE","isPromiseLike","React","variantStyles","sizeStyles","Button","variant","size","className","disabled","externalLoading","asChild","onClick","internalLoading","setInternalLoading","useState","isLoading","handleClick","e","Comp","jsx","cn","jsxs","Fragment","badgeVariants","Badge","LogViewer","logs","error","onClear","useTranslation","logContainerRef","useRef","autoScroll","setAutoScroll","filter","setFilter","typeFilter","setTypeFilter","sourceFilter","setSourceFilter","useEffect","filteredLogs","log","matchesText","matchesType","matchesSource","formatTimestamp","timestamp","getLogTypeColor","type","getSourceColor","source","prev","t","s","index","LogsPage","loading","clearLogs","useLogs"],"mappings":"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","x_google_ignoreList":[0,1]}
|