@executor-js/plugin-mcp 1.4.33 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/AddMcpSource-4LLERUW5.js +602 -0
  2. package/dist/AddMcpSource-4LLERUW5.js.map +1 -0
  3. package/dist/EditMcpSource-GKJRP75X.js +313 -0
  4. package/dist/EditMcpSource-GKJRP75X.js.map +1 -0
  5. package/dist/McpAccountsPanel-UX7MHEIG.js +132 -0
  6. package/dist/McpAccountsPanel-UX7MHEIG.js.map +1 -0
  7. package/dist/api/group.d.ts +79 -143
  8. package/dist/api/index.d.ts +99 -155
  9. package/dist/chunk-2TXHTMKM.js +1298 -0
  10. package/dist/chunk-2TXHTMKM.js.map +1 -0
  11. package/dist/chunk-6OEQZ72N.js +124 -0
  12. package/dist/chunk-6OEQZ72N.js.map +1 -0
  13. package/dist/chunk-7FJ3PUUL.js +21 -0
  14. package/dist/chunk-7FJ3PUUL.js.map +1 -0
  15. package/dist/chunk-N4EAF5CA.js +146 -0
  16. package/dist/chunk-N4EAF5CA.js.map +1 -0
  17. package/dist/client.js +9 -9
  18. package/dist/client.js.map +1 -1
  19. package/dist/core.js +36 -26
  20. package/dist/index.js +2 -2
  21. package/dist/promise.d.ts +1 -1
  22. package/dist/react/AddMcpSource.d.ts +1 -1
  23. package/dist/react/McpAccountsPanel.d.ts +6 -0
  24. package/dist/react/McpRemoteSourceFields.d.ts +4 -2
  25. package/dist/react/McpSignInButton.d.ts +2 -0
  26. package/dist/react/atoms.d.ts +93 -313
  27. package/dist/react/auth-method-config.d.ts +8 -0
  28. package/dist/react/client.d.ts +78 -142
  29. package/dist/react/index.d.ts +3 -3
  30. package/dist/react/source-plugin.d.ts +5 -5
  31. package/dist/sdk/connection.d.ts +4 -4
  32. package/dist/sdk/errors.d.ts +0 -19
  33. package/dist/sdk/index.d.ts +4 -3
  34. package/dist/sdk/invoke.d.ts +9 -16
  35. package/dist/sdk/plugin.d.ts +101 -236
  36. package/dist/sdk/types.d.ts +25 -130
  37. package/package.json +5 -4
  38. package/dist/AddMcpSource-PADMBVX2.js +0 -688
  39. package/dist/AddMcpSource-PADMBVX2.js.map +0 -1
  40. package/dist/EditMcpSource-L5GC2B4J.js +0 -281
  41. package/dist/EditMcpSource-L5GC2B4J.js.map +0 -1
  42. package/dist/McpSourceSummary-LE3WXFUE.js +0 -170
  43. package/dist/McpSourceSummary-LE3WXFUE.js.map +0 -1
  44. package/dist/chunk-6OYEXHU3.js +0 -156
  45. package/dist/chunk-6OYEXHU3.js.map +0 -1
  46. package/dist/chunk-FMTVLO5L.js +0 -179
  47. package/dist/chunk-FMTVLO5L.js.map +0 -1
  48. package/dist/chunk-LEGVPKYH.js +0 -2391
  49. package/dist/chunk-LEGVPKYH.js.map +0 -1
  50. package/dist/chunk-ZIRGIRGP.js +0 -115
  51. package/dist/chunk-ZIRGIRGP.js.map +0 -1
  52. package/dist/react/McpSourceSummary.d.ts +0 -5
  53. package/dist/sdk/binding-store.d.ts +0 -31
  54. package/dist/sdk/stored-source.d.ts +0 -42
  55. /package/dist/{sdk/connection-pool.test.d.ts → react/auth-method-config.test.d.ts} +0 -0
  56. /package/dist/sdk/{cross-user-isolation.test.d.ts → describe-auth-methods.test.d.ts} +0 -0
  57. /package/dist/sdk/{per-user-auth-isolation.test.d.ts → owner-isolation.test.d.ts} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react/AddMcpSource.tsx","../src/react/McpRemoteSourceFields.tsx"],"sourcesContent":["import { useReducer, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useAtomSet, useAtomValue } from \"@effect/atom-react\";\nimport { Link } from \"@tanstack/react-router\";\nimport * as Exit from \"effect/Exit\";\nimport * as Match from \"effect/Match\";\nimport * as Option from \"effect/Option\";\nimport * as Predicate from \"effect/Predicate\";\nimport * as Schema from \"effect/Schema\";\nimport * as AsyncResult from \"effect/unstable/reactivity/AsyncResult\";\n\nimport { integrationsOptimisticAtom } from \"@executor-js/react/api/atoms\";\nimport { Button } from \"@executor-js/react/components/button\";\nimport {\n AuthTemplateEditor,\n type AuthTemplateEditorKind,\n type AuthTemplateEditorValue,\n} from \"@executor-js/react/components/auth-template-editor\";\nimport {\n CardStack,\n CardStackContent,\n CardStackEntryField,\n} from \"@executor-js/react/components/card-stack\";\nimport { FieldLabel } from \"@executor-js/react/components/field\";\nimport { FloatActions } from \"@executor-js/react/components/float-actions\";\nimport { Input } from \"@executor-js/react/components/input\";\nimport { Spinner } from \"@executor-js/react/components/spinner\";\nimport { Textarea } from \"@executor-js/react/components/textarea\";\nimport {\n integrationDisplayNameFromUrl,\n slugifyNamespace,\n IntegrationIdentityFields,\n useIntegrationIdentity,\n} from \"@executor-js/react/plugins/integration-identity\";\n\nimport { integrationWriteKeys } from \"@executor-js/react/api/reactivity-keys\";\nimport { probeMcpEndpoint, addMcpServer } from \"./atoms\";\nimport { McpRemoteSourceFields } from \"./McpRemoteSourceFields\";\nimport { mcpAuthTemplateFromEditorValue } from \"./auth-method-config\";\nimport { mcpPresets, type McpPreset } from \"../sdk/presets\";\n\n// Post-redesign the remote add flow only REGISTERS the auth template through the\n// shared `AuthTemplateEditor` — accounts (the API key value / OAuth sign-in) are\n// added later from the integration's detail hub (P6: add without auth, connect\n// later). An OAuth-only server (DCR-capable) is constrained to the OAuth tab.\n\nconst ErrorMessage = Schema.Struct({ message: Schema.String });\nconst decodeErrorMessage = Schema.decodeUnknownOption(ErrorMessage);\nconst STDIO_ENV_ESCAPE_REPLACEMENTS: Readonly<Record<string, string>> = {\n \"\\\\\": \"\\\\\",\n n: \"\\n\",\n r: \"\\r\",\n t: \"\\t\",\n '\"': '\"',\n};\n\nconst errorMessageFromExit = (exit: Exit.Exit<unknown, unknown>, fallback: string): string =>\n Option.match(Option.flatMap(Exit.findErrorOption(exit), decodeErrorMessage), {\n onNone: () => fallback,\n onSome: ({ message }) => message,\n });\n\nconst isIntegrationAlreadyExistsExit = (exit: Exit.Exit<unknown, unknown>): boolean =>\n Option.match(Exit.findErrorOption(exit), {\n onNone: () => false,\n onSome: Predicate.isTagged(\"IntegrationAlreadyExistsError\"),\n });\n\nconst integrationExistsMessage = (slug: string): string =>\n `An integration named \"${slug}\" already exists. To add more authentication, update your existing integration.`;\n\n// ---------------------------------------------------------------------------\n// Preset lookup\n// ---------------------------------------------------------------------------\n\nfunction findPreset(id: string | undefined): McpPreset | undefined {\n if (!id) return undefined;\n return mcpPresets.find((p) => p.id === id);\n}\n\n// ---------------------------------------------------------------------------\n// State machine (remote flow)\n// ---------------------------------------------------------------------------\n\ntype ProbeResult = {\n connected: boolean;\n requiresAuthentication: boolean;\n requiresOAuth: boolean;\n supportsDynamicRegistration: boolean;\n name: string;\n slug: string;\n toolCount: number | null;\n serverName: string | null;\n};\n\ntype State =\n | { step: \"url\"; url: string }\n | { step: \"probing\"; url: string; probe: ProbeResult | null }\n | { step: \"probed\"; url: string; probe: ProbeResult }\n | { step: \"adding\"; url: string; probe: ProbeResult }\n | {\n step: \"error\";\n url: string;\n probe: ProbeResult | null;\n error: string;\n };\n\ntype Action =\n | { type: \"set-url\"; url: string }\n | { type: \"probe-start\" }\n | { type: \"probe-ok\"; probe: ProbeResult }\n | { type: \"probe-fail\"; error: string }\n | { type: \"add-start\" }\n | { type: \"add-fail\"; error: string }\n | { type: \"retry\" };\n\nconst init: State = { step: \"url\", url: \"\" };\n\nfunction reducer(state: State, action: Action): State {\n return Match.value(action).pipe(\n Match.discriminator(\"type\")(\"set-url\", (a): State => ({ step: \"url\", url: a.url })),\n Match.discriminator(\"type\")(\n \"probe-start\",\n (): State => ({\n step: \"probing\",\n url: state.url,\n probe: \"probe\" in state ? state.probe : null,\n }),\n ),\n Match.discriminator(\"type\")(\n \"probe-ok\",\n (a): State => ({ step: \"probed\", url: state.url, probe: a.probe }),\n ),\n Match.discriminator(\"type\")(\n \"probe-fail\",\n (a): State => ({\n step: \"error\",\n url: state.url,\n probe: null,\n error: a.error,\n }),\n ),\n Match.discriminator(\"type\")(\"add-start\", (): State => {\n const probe = \"probe\" in state ? state.probe : null;\n if (!probe) return state;\n return { step: \"adding\", url: state.url, probe };\n }),\n Match.discriminator(\"type\")(\"add-fail\", (a): State => {\n if (state.step !== \"adding\") return state;\n return {\n step: \"error\",\n url: state.url,\n probe: state.probe,\n error: a.error,\n };\n }),\n Match.discriminator(\"type\")(\"retry\", (): State => {\n if (state.step !== \"error\") return state;\n return state.probe\n ? { step: \"probed\", url: state.url, probe: state.probe }\n : { step: \"url\", url: state.url };\n }),\n Match.exhaustive,\n );\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport default function AddMcpSource(props: {\n onComplete: (slug?: string) => void;\n onCancel: () => void;\n initialUrl?: string;\n initialPreset?: string;\n /** Whether the stdio transport is enabled on the server. */\n allowStdio?: boolean;\n}) {\n const allowStdio = props.allowStdio ?? false;\n const rawPreset = findPreset(props.initialPreset);\n // Drop stdio presets when stdio is disabled — the caller should have\n // already filtered these out, but defence-in-depth.\n const preset = rawPreset?.transport === \"stdio\" && !allowStdio ? undefined : rawPreset;\n const isStdioPreset = preset?.transport === \"stdio\";\n\n const [transport, setTransport] = useState<\"remote\" | \"stdio\">(\n isStdioPreset && allowStdio ? \"stdio\" : \"remote\",\n );\n\n // --- Stdio state ---\n const [stdioCommand, setStdioCommand] = useState(isStdioPreset ? preset.command : \"\");\n const [stdioArgs, setStdioArgs] = useState(\n isStdioPreset && preset.args ? preset.args.join(\" \") : \"\",\n );\n const [stdioEnv, setStdioEnv] = useState(\"\");\n const stdioIdentity = useIntegrationIdentity({\n fallbackName: isStdioPreset ? preset.name : stdioCommand,\n });\n const [stdioAdding, setStdioAdding] = useState(false);\n const [stdioError, setStdioError] = useState<string | null>(null);\n\n // --- Remote state ---\n const remoteUrl =\n !isStdioPreset && preset?.transport === undefined && preset?.url\n ? preset.url\n : (props.initialUrl ?? \"\");\n\n const [state, dispatch] = useReducer(\n reducer,\n remoteUrl ? { step: \"url\" as const, url: remoteUrl } : init,\n );\n\n const doProbe = useAtomSet(probeMcpEndpoint, { mode: \"promiseExit\" });\n const doAddServer = useAtomSet(addMcpServer, { mode: \"promiseExit\" });\n\n const [authValue, setAuthValue] = useState<AuthTemplateEditorValue>({ kind: \"none\" });\n\n const probe = \"probe\" in state ? state.probe : null;\n\n // OAuth-only servers (DCR-capable) constrain the editor to the OAuth tab; all\n // other servers offer none / API key / OAuth (matching the prior tab set).\n const allowedAuthKinds: readonly AuthTemplateEditorKind[] =\n probe?.requiresOAuth && probe.supportsDynamicRegistration\n ? [\"oauth\"]\n : probe?.requiresAuthentication\n ? [\"apikey\", \"oauth\"]\n : [\"none\", \"apikey\", \"oauth\"];\n\n const remoteIdentity = useIntegrationIdentity({\n fallbackName:\n integrationDisplayNameFromUrl(state.url, \"MCP\") ?? probe?.serverName ?? probe?.name ?? \"\",\n });\n const isProbing = state.step === \"probing\";\n const isAdding = state.step === \"adding\";\n\n // Pre-empt the API's `IntegrationAlreadyExistsError`: adding an integration\n // whose slug already exists clobbers the existing one's connections/policies,\n // so the API blocks it. Surface that here from the tenant-scoped catalog list.\n // A blank derived namespace lets the server assign the slug, so only flag a\n // collision when the user-derived slug is non-empty.\n const integrationsResult = useAtomValue(integrationsOptimisticAtom);\n const existingSlugs = useMemo(\n () =>\n AsyncResult.isSuccess(integrationsResult)\n ? integrationsResult.value.map((integration) => String(integration.slug))\n : [],\n [integrationsResult],\n );\n const remoteSlug = slugifyNamespace(remoteIdentity.namespace);\n const stdioSlug = slugifyNamespace(stdioIdentity.namespace);\n const remoteSlugExists = remoteSlug.length > 0 && existingSlugs.includes(remoteSlug);\n const stdioSlugExists = stdioSlug.length > 0 && existingSlugs.includes(stdioSlug);\n\n const canAdd = Boolean(probe) && !isAdding && !remoteSlugExists;\n // Probe failures are shown inline on the URL field; other failures\n // (add server) render in the bottom error block.\n const probeError = state.step === \"error\" && state.probe === null ? state.error : null;\n const otherError = state.step === \"error\" && state.probe !== null ? state.error : null;\n\n // ---- Remote actions ----\n\n const handleProbe = useCallback(async () => {\n dispatch({ type: \"probe-start\" });\n const exit = await doProbe({\n payload: { endpoint: state.url.trim() },\n });\n if (Exit.isFailure(exit)) {\n dispatch({\n type: \"probe-fail\",\n error: errorMessageFromExit(exit, \"Failed to connect\"),\n });\n return;\n }\n setAuthValue(\n exit.value.requiresOAuth\n ? { kind: \"oauth\", authorizationUrl: \"\", tokenUrl: \"\", scopes: [] }\n : exit.value.requiresAuthentication\n ? {\n kind: \"apikey\",\n placements: [{ carrier: \"header\", name: \"Authorization\", prefix: \"Bearer \" }],\n }\n : { kind: \"none\" },\n );\n dispatch({ type: \"probe-ok\", probe: exit.value });\n }, [state.url, doProbe]);\n\n // Keep the latest handleProbe in a ref so the debounced effect can call it\n // without depending on its identity (which changes every render).\n const handleProbeRef = useRef(handleProbe);\n handleProbeRef.current = handleProbe;\n\n // Auto-probe whenever the URL changes (debounced) while we're on the\n // remote transport and not already probing/probed.\n useEffect(() => {\n if (transport !== \"remote\") return;\n if (state.step !== \"url\") return;\n const trimmed = state.url.trim();\n if (!trimmed) return;\n const handle = setTimeout(() => {\n handleProbeRef.current();\n }, 400);\n return () => clearTimeout(handle);\n }, [transport, state.step, state.url]);\n\n // Register the integration with the chosen auth template, returning the\n // assigned slug (or null on failure — an error is dispatched in that case).\n const registerIntegration = useCallback(\n async (\n auth:\n | { kind: \"none\" }\n | { kind: \"header\"; headerName: string; prefix?: string }\n | { kind: \"oauth2\" },\n ): Promise<string | null> => {\n const displayName = remoteIdentity.name.trim() || probe?.serverName || probe?.name || \"MCP\";\n const slug = slugifyNamespace(remoteIdentity.namespace) || undefined;\n const exit = await doAddServer({\n payload: {\n transport: \"remote\" as const,\n name: displayName,\n endpoint: state.url.trim(),\n ...(slug ? { slug } : {}),\n auth,\n },\n reactivityKeys: integrationWriteKeys,\n });\n if (Exit.isFailure(exit)) {\n dispatch({\n type: \"add-fail\",\n error: isIntegrationAlreadyExistsExit(exit)\n ? integrationExistsMessage(slug ?? displayName)\n : errorMessageFromExit(exit, \"Failed to add server\"),\n });\n return null;\n }\n return exit.value.slug;\n },\n [doAddServer, probe, remoteIdentity, state.url],\n );\n\n const handleAddRemote = useCallback(async () => {\n if (!probe) return;\n dispatch({ type: \"add-start\" });\n const slug = await registerIntegration(mcpAuthTemplateFromEditorValue(authValue));\n if (slug === null) return;\n props.onComplete(slug);\n }, [probe, authValue, registerIntegration, props]);\n\n // ---- Stdio actions ----\n\n const parseStdioArgs = (raw: string): string[] => {\n if (!raw.trim()) return [];\n const args: string[] = [];\n const regex = /[^\\s\"]+|\"([^\"]*)\"/g;\n let match;\n while ((match = regex.exec(raw)) !== null) {\n args.push(match[1] ?? match[0]);\n }\n return args;\n };\n\n const parseStdioEnvValue = (raw: string): string => {\n const value = raw.trim();\n if (value.length < 2) return value;\n\n const quote = value[0];\n if ((quote !== '\"' && quote !== \"'\") || value[value.length - 1] !== quote) {\n return value;\n }\n\n const inner = value.slice(1, -1);\n if (quote === \"'\") return inner;\n\n return inner.replace(\n /\\\\([\\\\nrt\"])/g,\n (_, escaped: string) => STDIO_ENV_ESCAPE_REPLACEMENTS[escaped] ?? escaped,\n );\n };\n\n const parseStdioEnv = (raw: string): Record<string, string> | undefined => {\n if (!raw.trim()) return undefined;\n const env: Record<string, string> = {};\n for (const line of raw.split(\"\\n\")) {\n const eq = line.indexOf(\"=\");\n if (eq > 0) {\n env[line.slice(0, eq).trim()] = parseStdioEnvValue(line.slice(eq + 1));\n }\n }\n return Object.keys(env).length > 0 ? env : undefined;\n };\n\n const handleAddStdio = useCallback(async () => {\n const cmd = stdioCommand.trim();\n if (!cmd) return;\n setStdioAdding(true);\n setStdioError(null);\n const displayName = stdioIdentity.name.trim() || cmd;\n const slug = slugifyNamespace(stdioIdentity.namespace) || undefined;\n const exit = await doAddServer({\n payload: {\n transport: \"stdio\" as const,\n name: displayName,\n ...(slug ? { slug } : {}),\n command: cmd,\n args: parseStdioArgs(stdioArgs),\n env: parseStdioEnv(stdioEnv),\n },\n reactivityKeys: integrationWriteKeys,\n });\n if (Exit.isFailure(exit)) {\n setStdioError(\n isIntegrationAlreadyExistsExit(exit)\n ? integrationExistsMessage(slug ?? displayName)\n : errorMessageFromExit(exit, \"Failed to add server\"),\n );\n setStdioAdding(false);\n return;\n }\n props.onComplete(exit.value.slug);\n }, [stdioCommand, stdioArgs, stdioEnv, stdioIdentity, doAddServer, props]);\n\n // ---- Render ----\n\n return (\n <div className=\"flex flex-1 flex-col gap-6\">\n <div>\n <h1 className=\"text-xl font-semibold text-foreground\">Add MCP Source</h1>\n <p className=\"mt-1 text-[13px] text-muted-foreground\">\n Connect to an MCP server to discover and use its tools.\n </p>\n </div>\n\n {/* Transport toggle — only shown when stdio is enabled server-side */}\n {allowStdio && (\n <div className=\"flex gap-1 rounded-lg border border-border bg-muted/30 p-1\">\n <Button\n variant=\"ghost\"\n type=\"button\"\n onClick={() => setTransport(\"remote\")}\n className={`flex-1 rounded-md px-3 py-1.5 text-sm font-medium transition-colors ${\n transport === \"remote\"\n ? \"bg-background text-foreground shadow-sm\"\n : \"text-muted-foreground hover:text-foreground\"\n }`}\n >\n Remote\n </Button>\n <Button\n variant=\"ghost\"\n type=\"button\"\n onClick={() => setTransport(\"stdio\")}\n className={`flex-1 rounded-md px-3 py-1.5 text-sm font-medium transition-colors ${\n transport === \"stdio\"\n ? \"bg-background text-foreground shadow-sm\"\n : \"text-muted-foreground hover:text-foreground\"\n }`}\n >\n Stdio\n </Button>\n </div>\n )}\n\n {transport === \"remote\" ? (\n <>\n <McpRemoteSourceFields\n url={state.url}\n onUrlChange={(url) => dispatch({ type: \"set-url\", url })}\n identity={remoteIdentity}\n preview={probe}\n probing={isProbing}\n error={probeError}\n onRetry={handleProbe}\n />\n\n {/* Authentication — declares the auth template to register through the\n shared editor. The credential itself (API key value / OAuth sign-in)\n is added from the integration's detail hub after adding. */}\n {probe && (\n <section className=\"space-y-2.5\">\n <FieldLabel>How does this server authenticate?</FieldLabel>\n <AuthTemplateEditor\n value={authValue}\n onChange={setAuthValue}\n allowedKinds={allowedAuthKinds}\n oauthMetadata=\"discovered\"\n />\n </section>\n )}\n\n {/* Error (add server). Probe errors show inline on the field. */}\n {otherError && (\n <div className=\"space-y-2\">\n <div className=\"rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2\">\n <p className=\"text-[12px] text-destructive\">{otherError}</p>\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => dispatch({ type: \"retry\" })}\n className=\"text-xs\"\n >\n Try again\n </Button>\n </div>\n )}\n\n {remoteSlugExists && !isAdding && (\n <div className=\"rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2\">\n <p className=\"text-[12px] text-destructive\">\n An integration named &quot;{remoteSlug}&quot; already exists. To add more\n authentication, update your existing integration.{\" \"}\n <Link\n to=\"/integrations/$namespace\"\n params={{ namespace: remoteSlug }}\n className=\"font-medium underline underline-offset-2\"\n >\n Open it\n </Link>\n </p>\n </div>\n )}\n\n <FloatActions>\n <Button\n type=\"button\"\n variant=\"ghost\"\n onClick={() => props.onCancel()}\n disabled={isAdding}\n >\n Cancel\n </Button>\n {(probe || isProbing) && (\n <Button type=\"button\" onClick={handleAddRemote} disabled={!canAdd}>\n {isAdding ? (\n <>\n <Spinner className=\"size-3.5\" /> Adding…\n </>\n ) : (\n \"Add source\"\n )}\n </Button>\n )}\n </FloatActions>\n </>\n ) : (\n <>\n {/* Stdio form */}\n <CardStack>\n <CardStackContent className=\"border-t-0\">\n <CardStackEntryField\n label=\"Command\"\n description=\"- The executable to run (e.g. npx, uvx, node).\"\n >\n <Input\n value={stdioCommand}\n onChange={(e) => setStdioCommand((e.target as HTMLInputElement).value)}\n placeholder=\"npx\"\n className=\"font-mono text-sm\"\n />\n </CardStackEntryField>\n\n <CardStackEntryField\n label=\"Arguments\"\n description=\"- Space-separated arguments passed to the command.\"\n >\n <Input\n value={stdioArgs}\n onChange={(e) => setStdioArgs((e.target as HTMLInputElement).value)}\n placeholder=\"-y chrome-devtools-mcp@latest\"\n className=\"font-mono text-sm\"\n />\n </CardStackEntryField>\n\n <CardStackEntryField\n label=\"Environment variables\"\n description=\"- One per line, KEY=value format.\"\n >\n <Textarea\n value={stdioEnv}\n onChange={(e) => setStdioEnv((e.target as HTMLTextAreaElement).value)}\n placeholder={\"KEY=value\\nANOTHER=value\"}\n rows={3}\n maxRows={10}\n className=\"font-mono text-sm\"\n />\n </CardStackEntryField>\n </CardStackContent>\n </CardStack>\n\n <IntegrationIdentityFields identity={stdioIdentity} namePlaceholder=\"My MCP Server\" />\n\n {/* Stdio error */}\n {stdioError && (\n <div className=\"rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2\">\n <p className=\"text-[12px] text-destructive\">{stdioError}</p>\n </div>\n )}\n\n {stdioSlugExists && !stdioAdding && (\n <div className=\"rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2\">\n <p className=\"text-[12px] text-destructive\">\n An integration named &quot;{stdioSlug}&quot; already exists. To add more\n authentication, update your existing integration.{\" \"}\n <Link\n to=\"/integrations/$namespace\"\n params={{ namespace: stdioSlug }}\n className=\"font-medium underline underline-offset-2\"\n >\n Open it\n </Link>\n </p>\n </div>\n )}\n\n <FloatActions>\n <Button\n type=\"button\"\n variant=\"ghost\"\n onClick={() => props.onCancel()}\n disabled={stdioAdding}\n >\n Cancel\n </Button>\n <Button\n type=\"button\"\n onClick={handleAddStdio}\n disabled={!stdioCommand.trim() || stdioAdding || stdioSlugExists}\n >\n {stdioAdding ? (\n <>\n <Spinner className=\"size-3.5\" /> Adding…\n </>\n ) : (\n \"Add source\"\n )}\n </Button>\n </FloatActions>\n </>\n )}\n </div>\n );\n}\n","import { Badge } from \"@executor-js/react/components/badge\";\nimport {\n CardStack,\n CardStackContent,\n CardStackEntry,\n CardStackEntryActions,\n CardStackEntryContent,\n CardStackEntryDescription,\n CardStackEntryField,\n CardStackEntryMedia,\n CardStackEntryTitle,\n} from \"@executor-js/react/components/card-stack\";\nimport { FieldError } from \"@executor-js/react/components/field\";\nimport { Input } from \"@executor-js/react/components/input\";\nimport { Skeleton } from \"@executor-js/react/components/skeleton\";\nimport { IntegrationFavicon } from \"@executor-js/react/components/integration-favicon\";\nimport { IOSSpinner } from \"@executor-js/react/components/spinner\";\nimport { Button } from \"@executor-js/react/components/button\";\nimport {\n IntegrationIdentityFieldRows,\n type IntegrationIdentity,\n} from \"@executor-js/react/plugins/integration-identity\";\n\nexport type McpRemoteSourcePreview = {\n readonly name: string;\n readonly serverName: string | null;\n readonly connected: boolean;\n readonly requiresAuthentication: boolean;\n readonly requiresOAuth: boolean;\n readonly toolCount: number | null;\n};\n\nexport function McpRemoteSourceFields(props: {\n readonly url: string;\n readonly onUrlChange: (url: string) => void;\n readonly identity: IntegrationIdentity;\n readonly preview: McpRemoteSourcePreview | null;\n readonly probing?: boolean;\n readonly error?: string | null;\n readonly onRetry?: () => void;\n readonly namespaceReadOnly?: boolean;\n readonly urlDisabled?: boolean;\n}) {\n const previewDescription = props.preview\n ? props.preview.connected\n ? props.preview.toolCount === null\n ? null\n : `${props.preview.toolCount} tool${props.preview.toolCount !== 1 ? \"s\" : \"\"} available`\n : props.preview.requiresOAuth\n ? \"OAuth required to discover tools\"\n : props.preview.requiresAuthentication\n ? \"Authentication required to discover tools\"\n : \"Ready to add\"\n : null;\n\n if (props.preview) {\n return (\n <CardStack>\n <CardStackContent className=\"border-t-0\">\n <CardStackEntry>\n <CardStackEntryMedia>\n <IntegrationFavicon url={props.url} size={32} />\n </CardStackEntryMedia>\n <CardStackEntryContent>\n <CardStackEntryTitle>\n {props.preview.serverName ?? props.preview.name}\n </CardStackEntryTitle>\n {previewDescription ? (\n <CardStackEntryDescription>{previewDescription}</CardStackEntryDescription>\n ) : null}\n </CardStackEntryContent>\n <CardStackEntryActions>\n {props.preview.connected ? (\n <Badge\n variant=\"outline\"\n className=\"border-emerald-500/20 bg-emerald-500/10 text-[10px] text-emerald-600 dark:text-emerald-400\"\n >\n Connected\n </Badge>\n ) : props.preview.requiresOAuth ? (\n <Badge\n variant=\"outline\"\n className=\"border-amber-500/20 bg-amber-500/10 text-[10px] text-amber-600 dark:text-amber-400\"\n >\n OAuth required\n </Badge>\n ) : (\n <Badge\n variant=\"outline\"\n className=\"border-amber-500/20 bg-amber-500/10 text-[10px] text-amber-600 dark:text-amber-400\"\n >\n Auth required\n </Badge>\n )}\n </CardStackEntryActions>\n </CardStackEntry>\n <IntegrationIdentityFieldRows\n identity={props.identity}\n namePlaceholder=\"e.g. Linear\"\n namespaceReadOnly={props.namespaceReadOnly}\n />\n <CardStackEntryField label=\"Server URL\">\n <Input\n value={props.url}\n onChange={(e) => props.onUrlChange((e.target as HTMLInputElement).value)}\n placeholder=\"https://mcp.example.com\"\n className=\"w-full font-mono text-sm\"\n disabled={props.urlDisabled}\n />\n </CardStackEntryField>\n </CardStackContent>\n </CardStack>\n );\n }\n\n if (props.probing) {\n return (\n <CardStack>\n <CardStackContent className=\"border-t-0\">\n <CardStackEntry>\n <CardStackEntryMedia>\n <Skeleton className=\"size-4 rounded\" />\n </CardStackEntryMedia>\n <CardStackEntryContent>\n <Skeleton className=\"h-4 w-40\" />\n <Skeleton className=\"mt-1 h-3 w-32\" />\n </CardStackEntryContent>\n <CardStackEntryActions>\n <Skeleton className=\"h-4 w-20 rounded-full\" />\n </CardStackEntryActions>\n </CardStackEntry>\n </CardStackContent>\n </CardStack>\n );\n }\n\n return (\n <CardStack>\n <CardStackContent className=\"border-t-0\">\n <CardStackEntryField label=\"Server URL\">\n <div className=\"relative\">\n <Input\n value={props.url}\n onChange={(e) => props.onUrlChange((e.target as HTMLInputElement).value)}\n placeholder=\"https://mcp.example.com\"\n className=\"w-full pr-9 font-mono text-sm\"\n aria-invalid={props.error ? true : undefined}\n disabled={props.urlDisabled}\n />\n {props.probing && (\n <div className=\"pointer-events-none absolute right-2 top-1/2 -translate-y-1/2\">\n <IOSSpinner className=\"size-4\" />\n </div>\n )}\n </div>\n {props.error && (\n <div className=\"mt-2 space-y-2\">\n <FieldError>{props.error}</FieldError>\n {props.onRetry && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={props.onRetry}\n className=\"h-7 px-2 text-xs\"\n >\n Try again\n </Button>\n )}\n </div>\n )}\n </CardStackEntryField>\n </CardStackContent>\n </CardStack>\n );\n}\n"],"mappings":"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","names":["Button","CardStack","CardStackContent","CardStackEntryField","Input","jsx","jsxs","match","value","Button","CardStack","CardStackContent","CardStackEntryField","Input"]}
@@ -0,0 +1,313 @@
1
+ import {
2
+ mcpAuthTemplateFromEditorValue
3
+ } from "./chunk-7FJ3PUUL.js";
4
+ import {
5
+ configureMcpServer,
6
+ mcpServerAtom
7
+ } from "./chunk-N4EAF5CA.js";
8
+ import "./chunk-6OEQZ72N.js";
9
+
10
+ // src/react/EditMcpSource.tsx
11
+ import { useCallback, useEffect, useMemo, useState } from "react";
12
+ import { useAtomValue, useAtomSet } from "@effect/atom-react";
13
+ import * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
14
+ import * as Exit from "effect/Exit";
15
+ import { AuthTemplateSlug, IntegrationSlug } from "@executor-js/sdk/shared";
16
+ import { createConnection } from "@executor-js/react/api/atoms";
17
+ import { connectionWriteKeys, integrationWriteKeys } from "@executor-js/react/api/reactivity-keys";
18
+ import { connectionIdentifier } from "@executor-js/react/lib/connection-name";
19
+ import {
20
+ AuthTemplateEditor
21
+ } from "@executor-js/react/components/auth-template-editor";
22
+ import {
23
+ CredentialControlField,
24
+ ConnectionOwnerUsageRow,
25
+ useConnectionOwner
26
+ } from "@executor-js/react/plugins/connection-owner";
27
+ import { OAuthSignInButton } from "@executor-js/react/plugins/oauth-sign-in";
28
+ import { Button } from "@executor-js/react/components/button";
29
+ import { AddAccountModal } from "@executor-js/react/components/add-account-modal";
30
+ import {
31
+ CardStack,
32
+ CardStackContent,
33
+ CardStackEntry,
34
+ CardStackEntryContent,
35
+ CardStackEntryDescription,
36
+ CardStackEntryTitle
37
+ } from "@executor-js/react/components/card-stack";
38
+ import { Input } from "@executor-js/react/components/input";
39
+ import { Badge } from "@executor-js/react/components/badge";
40
+ import { jsx, jsxs } from "react/jsx-runtime";
41
+ var HEADER_TEMPLATE = AuthTemplateSlug.make("header");
42
+ var OAUTH_TEMPLATE = AuthTemplateSlug.make("oauth2");
43
+ var authTemplateToEditorValue = (auth) => {
44
+ if (auth.kind === "none") return { kind: "none" };
45
+ if (auth.kind === "oauth2")
46
+ return { kind: "oauth", authorizationUrl: "", tokenUrl: "", scopes: [] };
47
+ return {
48
+ kind: "apikey",
49
+ placements: [
50
+ {
51
+ carrier: "header",
52
+ name: auth.headerName,
53
+ prefix: auth.prefix ?? ""
54
+ }
55
+ ]
56
+ };
57
+ };
58
+ var authTemplatesEqual = (left, right) => {
59
+ if (left.kind !== right.kind) return false;
60
+ if (left.kind === "header" && right.kind === "header") {
61
+ return left.headerName === right.headerName && (left.prefix ?? "") === (right.prefix ?? "");
62
+ }
63
+ return true;
64
+ };
65
+ function RemoteEdit(props) {
66
+ const { server } = props;
67
+ const auth = server.config.auth;
68
+ const { connectionOwner, setConnectionOwner, connectionOwnerOptions } = useConnectionOwner();
69
+ const doCreate = useAtomSet(createConnection, { mode: "promiseExit" });
70
+ const doConfigure = useAtomSet(configureMcpServer, { mode: "promiseExit" });
71
+ const [authValue, setAuthValue] = useState(
72
+ () => authTemplateToEditorValue(auth)
73
+ );
74
+ const [apiKey, setApiKey] = useState("");
75
+ const [saving, setSaving] = useState(false);
76
+ const [authSaving, setAuthSaving] = useState(false);
77
+ const [error, setError] = useState(null);
78
+ const [connected, setConnected] = useState(false);
79
+ const [oauthModalOpen, setOauthModalOpen] = useState(false);
80
+ const editedAuth = mcpAuthTemplateFromEditorValue(authValue);
81
+ const authChanged = !authTemplatesEqual(editedAuth, auth);
82
+ useEffect(() => {
83
+ setAuthValue(authTemplateToEditorValue(auth));
84
+ }, [auth]);
85
+ const handleSaveAuth = useCallback(async () => {
86
+ setAuthSaving(true);
87
+ setError(null);
88
+ const nextConfig = {
89
+ ...server.config,
90
+ auth: mcpAuthTemplateFromEditorValue(authValue)
91
+ };
92
+ const exit = await doConfigure({
93
+ params: { slug: server.slug },
94
+ payload: { config: nextConfig },
95
+ reactivityKeys: integrationWriteKeys
96
+ });
97
+ if (Exit.isFailure(exit)) {
98
+ setError("Failed to update authentication method");
99
+ setAuthSaving(false);
100
+ return;
101
+ }
102
+ setAuthSaving(false);
103
+ }, [authValue, doConfigure, server.config, server.slug]);
104
+ const handleSaveKey = useCallback(async () => {
105
+ if (apiKey.trim() === "") return;
106
+ setSaving(true);
107
+ setError(null);
108
+ const exit = await doCreate({
109
+ payload: {
110
+ owner: connectionOwner,
111
+ name: connectionIdentifier(`${server.slug} key`),
112
+ integration: server.slug,
113
+ template: HEADER_TEMPLATE,
114
+ identityLabel: server.description || String(server.slug),
115
+ value: apiKey.trim()
116
+ },
117
+ reactivityKeys: connectionWriteKeys
118
+ });
119
+ if (Exit.isFailure(exit)) {
120
+ setError("Failed to save credential");
121
+ setSaving(false);
122
+ return;
123
+ }
124
+ setSaving(false);
125
+ setConnected(true);
126
+ props.onSave();
127
+ }, [apiKey, connectionOwner, doCreate, server, props]);
128
+ const handleOAuth = useCallback(() => {
129
+ setError(null);
130
+ setOauthModalOpen(true);
131
+ }, []);
132
+ const oauthMethods = useMemo(
133
+ () => auth.kind === "oauth2" ? [
134
+ {
135
+ id: "oauth2",
136
+ label: "OAuth",
137
+ kind: "oauth",
138
+ source: "spec",
139
+ template: OAUTH_TEMPLATE,
140
+ placements: [],
141
+ oauth: { discoveryUrl: server.config.endpoint, supportsDynamicRegistration: true }
142
+ }
143
+ ] : [],
144
+ [auth.kind, server.config.endpoint]
145
+ );
146
+ const oauthInitialState = useMemo(
147
+ () => oauthModalOpen && auth.kind === "oauth2" ? {
148
+ key: `${String(server.slug)}:${connectionOwner}:oauth`,
149
+ owner: connectionOwner,
150
+ template: String(OAUTH_TEMPLATE),
151
+ label: `${server.description || String(server.slug)} OAuth`
152
+ } : null,
153
+ [auth.kind, connectionOwner, oauthModalOpen, server]
154
+ );
155
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
156
+ /* @__PURE__ */ jsxs("div", { children: [
157
+ /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-foreground", children: "Edit MCP Source" }),
158
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: "Manage the connection for this MCP server. The endpoint is part of the server's identity \u2014 remove and re-add to change it." })
159
+ ] }),
160
+ /* @__PURE__ */ jsx(CardStack, { children: /* @__PURE__ */ jsx(CardStackContent, { className: "border-t-0", children: /* @__PURE__ */ jsxs(CardStackEntry, { children: [
161
+ /* @__PURE__ */ jsxs(CardStackEntryContent, { children: [
162
+ /* @__PURE__ */ jsx(CardStackEntryTitle, { children: server.description || String(server.slug) }),
163
+ /* @__PURE__ */ jsx(CardStackEntryDescription, { className: "font-mono text-xs", children: server.config.endpoint })
164
+ ] }),
165
+ /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "text-xs", children: "remote" })
166
+ ] }) }) }),
167
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3 rounded-lg border border-border bg-card p-4", children: [
168
+ /* @__PURE__ */ jsxs("div", { children: [
169
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-card-foreground", children: "Authentication method" }),
170
+ /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-xs text-muted-foreground", children: "Choose how a connection credential is sent to this MCP server." })
171
+ ] }),
172
+ /* @__PURE__ */ jsx(
173
+ AuthTemplateEditor,
174
+ {
175
+ value: authValue,
176
+ onChange: setAuthValue,
177
+ allowedKinds: ["none", "apikey", "oauth"],
178
+ oauthMetadata: "discovered"
179
+ }
180
+ ),
181
+ authChanged ? /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(
182
+ Button,
183
+ {
184
+ type: "button",
185
+ size: "sm",
186
+ onClick: () => void handleSaveAuth(),
187
+ disabled: authSaving,
188
+ children: authSaving ? "Saving\u2026" : "Save authentication method"
189
+ }
190
+ ) }) : null
191
+ ] }),
192
+ authChanged ? /* @__PURE__ */ jsx("div", { className: "rounded-md border border-border bg-muted/30 px-3 py-2 text-xs text-muted-foreground", children: "Save the authentication method before adding a connection." }) : null,
193
+ !authChanged && auth.kind === "header" && /* @__PURE__ */ jsx(
194
+ ConnectionOwnerUsageRow,
195
+ {
196
+ value: connectionOwner,
197
+ options: connectionOwnerOptions,
198
+ onChange: setConnectionOwner,
199
+ label: "Connection saved to",
200
+ help: "Choose who can use this credential.",
201
+ children: /* @__PURE__ */ jsxs(CredentialControlField, { label: `${auth.headerName} value`, help: "Saved as a connection.", children: [
202
+ /* @__PURE__ */ jsx(
203
+ Input,
204
+ {
205
+ type: "password",
206
+ value: apiKey,
207
+ onChange: (e) => setApiKey(e.target.value),
208
+ placeholder: "sk-\u2026",
209
+ className: "font-mono text-sm",
210
+ autoComplete: "new-password"
211
+ }
212
+ ),
213
+ /* @__PURE__ */ jsx("div", { className: "mt-2 flex justify-end", children: /* @__PURE__ */ jsx(
214
+ Button,
215
+ {
216
+ type: "button",
217
+ size: "sm",
218
+ onClick: () => void handleSaveKey(),
219
+ disabled: apiKey.trim() === "" || saving,
220
+ children: saving ? "Saving\u2026" : connected ? "Saved" : "Save connection"
221
+ }
222
+ ) })
223
+ ] })
224
+ }
225
+ ),
226
+ !authChanged && auth.kind === "oauth2" && /* @__PURE__ */ jsx(
227
+ ConnectionOwnerUsageRow,
228
+ {
229
+ value: connectionOwner,
230
+ options: connectionOwnerOptions,
231
+ onChange: setConnectionOwner,
232
+ label: "Connection saved to",
233
+ help: "Choose who can use the OAuth connection.",
234
+ children: /* @__PURE__ */ jsxs(CredentialControlField, { label: "Connect via OAuth", help: "Start the provider OAuth flow.", children: [
235
+ /* @__PURE__ */ jsx(
236
+ OAuthSignInButton,
237
+ {
238
+ busy: false,
239
+ error,
240
+ isConnected: connected,
241
+ onSignIn: handleOAuth,
242
+ signingInLabel: "Signing in\u2026",
243
+ reconnectingLabel: "Reconnecting\u2026"
244
+ }
245
+ ),
246
+ /* @__PURE__ */ jsx(
247
+ AddAccountModal,
248
+ {
249
+ integration: server.slug,
250
+ integrationName: server.description || String(server.slug),
251
+ methods: oauthMethods,
252
+ open: oauthModalOpen,
253
+ onOpenChange: setOauthModalOpen,
254
+ initialState: oauthInitialState
255
+ }
256
+ )
257
+ ] })
258
+ }
259
+ ),
260
+ !authChanged && auth.kind === "none" && /* @__PURE__ */ jsx("div", { className: "rounded-md border border-border bg-muted/30 px-3 py-2 text-xs text-muted-foreground", children: "This server does not require a credential." }),
261
+ error && /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: error }) }),
262
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end border-t border-border pt-4", children: /* @__PURE__ */ jsx(Button, { onClick: props.onSave, children: "Done" }) })
263
+ ] });
264
+ }
265
+ function StdioReadOnly(props) {
266
+ const { command, args } = props.server.config;
267
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
268
+ /* @__PURE__ */ jsxs("div", { children: [
269
+ /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-foreground", children: "Edit MCP Source" }),
270
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: "Stdio MCP sources cannot be edited in the UI. Remove and recreate the source with the updated command." })
271
+ ] }),
272
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 rounded-lg border border-border bg-card px-4 py-3", children: [
273
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
274
+ /* @__PURE__ */ jsx("p", { className: "truncate text-sm font-semibold text-card-foreground", children: String(props.server.slug) }),
275
+ /* @__PURE__ */ jsxs("p", { className: "mt-0.5 text-xs text-muted-foreground font-mono", children: [
276
+ command,
277
+ " ",
278
+ (args ?? []).join(" ")
279
+ ] })
280
+ ] }),
281
+ /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "text-xs", children: "stdio" })
282
+ ] }),
283
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end border-t border-border pt-4", children: /* @__PURE__ */ jsx(Button, { onClick: props.onSave, children: "Done" }) })
284
+ ] });
285
+ }
286
+ function EditMcpSource({
287
+ sourceId,
288
+ onSave
289
+ }) {
290
+ const slug = IntegrationSlug.make(sourceId);
291
+ const serverResult = useAtomValue(mcpServerAtom(slug));
292
+ const server = AsyncResult.isSuccess(serverResult) ? serverResult.value : null;
293
+ if (!AsyncResult.isSuccess(serverResult) || server === null) {
294
+ return /* @__PURE__ */ jsx("div", { className: "space-y-6", children: /* @__PURE__ */ jsxs("div", { children: [
295
+ /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-foreground", children: "Edit MCP Source" }),
296
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: "Loading configuration\u2026" })
297
+ ] }) });
298
+ }
299
+ if (server.config.transport === "stdio") {
300
+ return /* @__PURE__ */ jsx(
301
+ StdioReadOnly,
302
+ {
303
+ server,
304
+ onSave
305
+ }
306
+ );
307
+ }
308
+ return /* @__PURE__ */ jsx(RemoteEdit, { server, onSave });
309
+ }
310
+ export {
311
+ EditMcpSource as default
312
+ };
313
+ //# sourceMappingURL=EditMcpSource-GKJRP75X.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react/EditMcpSource.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useAtomValue, useAtomSet } from \"@effect/atom-react\";\nimport * as AsyncResult from \"effect/unstable/reactivity/AsyncResult\";\nimport * as Exit from \"effect/Exit\";\n\nimport { AuthTemplateSlug, IntegrationSlug } from \"@executor-js/sdk/shared\";\nimport { createConnection } from \"@executor-js/react/api/atoms\";\nimport { connectionWriteKeys, integrationWriteKeys } from \"@executor-js/react/api/reactivity-keys\";\nimport { connectionIdentifier } from \"@executor-js/react/lib/connection-name\";\nimport {\n AuthTemplateEditor,\n type AuthTemplateEditorValue,\n} from \"@executor-js/react/components/auth-template-editor\";\nimport {\n CredentialControlField,\n ConnectionOwnerUsageRow,\n useConnectionOwner,\n} from \"@executor-js/react/plugins/connection-owner\";\nimport { OAuthSignInButton } from \"@executor-js/react/plugins/oauth-sign-in\";\nimport { Button } from \"@executor-js/react/components/button\";\nimport { AddAccountModal } from \"@executor-js/react/components/add-account-modal\";\nimport {\n CardStack,\n CardStackContent,\n CardStackEntry,\n CardStackEntryContent,\n CardStackEntryDescription,\n CardStackEntryTitle,\n} from \"@executor-js/react/components/card-stack\";\nimport { Input } from \"@executor-js/react/components/input\";\nimport { Badge } from \"@executor-js/react/components/badge\";\nimport type { AuthMethod } from \"@executor-js/react/lib/auth-placements\";\n\nimport { configureMcpServer, mcpServerAtom } from \"./atoms\";\nimport type { McpAuthTemplate, McpIntegrationConfig } from \"../sdk/types\";\nimport { mcpAuthTemplateFromEditorValue } from \"./auth-method-config\";\n\nconst HEADER_TEMPLATE = AuthTemplateSlug.make(\"header\");\nconst OAUTH_TEMPLATE = AuthTemplateSlug.make(\"oauth2\");\n\ntype McpServer = {\n readonly slug: IntegrationSlug;\n readonly description: string;\n readonly kind: string;\n readonly canRemove: boolean;\n readonly canRefresh: boolean;\n readonly config: McpIntegrationConfig;\n};\n\nconst authTemplateToEditorValue = (auth: McpRemoteConfig[\"auth\"]): AuthTemplateEditorValue => {\n if (auth.kind === \"none\") return { kind: \"none\" };\n if (auth.kind === \"oauth2\")\n return { kind: \"oauth\", authorizationUrl: \"\", tokenUrl: \"\", scopes: [] };\n return {\n kind: \"apikey\",\n placements: [\n {\n carrier: \"header\",\n name: auth.headerName,\n prefix: auth.prefix ?? \"\",\n },\n ],\n };\n};\n\nconst authTemplatesEqual = (left: McpAuthTemplate, right: McpAuthTemplate): boolean => {\n if (left.kind !== right.kind) return false;\n if (left.kind === \"header\" && right.kind === \"header\") {\n return left.headerName === right.headerName && (left.prefix ?? \"\") === (right.prefix ?? \"\");\n }\n return true;\n};\n\n// ---------------------------------------------------------------------------\n// Remote edit — v2: the integration's endpoint + auth template are part of its\n// identity (opaque-to-core config). The editable surface is the connection: an\n// API-key header value, or an OAuth sign-in, both owner-scoped.\n// ---------------------------------------------------------------------------\n\nfunction RemoteEdit(props: {\n server: McpServer & { config: McpRemoteConfig };\n onSave: () => void;\n}) {\n const { server } = props;\n const auth = server.config.auth;\n const { connectionOwner, setConnectionOwner, connectionOwnerOptions } = useConnectionOwner();\n const doCreate = useAtomSet(createConnection, { mode: \"promiseExit\" });\n const doConfigure = useAtomSet(configureMcpServer, { mode: \"promiseExit\" });\n\n const [authValue, setAuthValue] = useState<AuthTemplateEditorValue>(() =>\n authTemplateToEditorValue(auth),\n );\n const [apiKey, setApiKey] = useState(\"\");\n const [saving, setSaving] = useState(false);\n const [authSaving, setAuthSaving] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [connected, setConnected] = useState(false);\n const [oauthModalOpen, setOauthModalOpen] = useState(false);\n\n const editedAuth = mcpAuthTemplateFromEditorValue(authValue);\n const authChanged = !authTemplatesEqual(editedAuth, auth);\n\n useEffect(() => {\n setAuthValue(authTemplateToEditorValue(auth));\n }, [auth]);\n\n const handleSaveAuth = useCallback(async () => {\n setAuthSaving(true);\n setError(null);\n const nextConfig: McpRemoteConfig = {\n ...server.config,\n auth: mcpAuthTemplateFromEditorValue(authValue),\n };\n const exit = await doConfigure({\n params: { slug: server.slug },\n payload: { config: nextConfig },\n reactivityKeys: integrationWriteKeys,\n });\n if (Exit.isFailure(exit)) {\n setError(\"Failed to update authentication method\");\n setAuthSaving(false);\n return;\n }\n setAuthSaving(false);\n }, [authValue, doConfigure, server.config, server.slug]);\n\n const handleSaveKey = useCallback(async () => {\n if (apiKey.trim() === \"\") return;\n setSaving(true);\n setError(null);\n const exit = await doCreate({\n payload: {\n owner: connectionOwner,\n name: connectionIdentifier(`${server.slug} key`),\n integration: server.slug,\n template: HEADER_TEMPLATE,\n identityLabel: server.description || String(server.slug),\n value: apiKey.trim(),\n },\n reactivityKeys: connectionWriteKeys,\n });\n if (Exit.isFailure(exit)) {\n setError(\"Failed to save credential\");\n setSaving(false);\n return;\n }\n setSaving(false);\n setConnected(true);\n props.onSave();\n }, [apiKey, connectionOwner, doCreate, server, props]);\n\n const handleOAuth = useCallback(() => {\n setError(null);\n setOauthModalOpen(true);\n }, []);\n\n const oauthMethods = useMemo<readonly AuthMethod[]>(\n () =>\n auth.kind === \"oauth2\"\n ? [\n {\n id: \"oauth2\",\n label: \"OAuth\",\n kind: \"oauth\",\n source: \"spec\",\n template: OAUTH_TEMPLATE,\n placements: [],\n oauth: { discoveryUrl: server.config.endpoint, supportsDynamicRegistration: true },\n },\n ]\n : [],\n [auth.kind, server.config.endpoint],\n );\n const oauthInitialState = useMemo(\n () =>\n oauthModalOpen && auth.kind === \"oauth2\"\n ? {\n key: `${String(server.slug)}:${connectionOwner}:oauth`,\n owner: connectionOwner,\n template: String(OAUTH_TEMPLATE),\n label: `${server.description || String(server.slug)} OAuth`,\n }\n : null,\n [auth.kind, connectionOwner, oauthModalOpen, server],\n );\n\n return (\n <div className=\"space-y-6\">\n <div>\n <h1 className=\"text-xl font-semibold text-foreground\">Edit MCP Source</h1>\n <p className=\"mt-1 text-sm text-muted-foreground\">\n Manage the connection for this MCP server. The endpoint is part of the server's identity —\n remove and re-add to change it.\n </p>\n </div>\n\n <CardStack>\n <CardStackContent className=\"border-t-0\">\n <CardStackEntry>\n <CardStackEntryContent>\n <CardStackEntryTitle>{server.description || String(server.slug)}</CardStackEntryTitle>\n <CardStackEntryDescription className=\"font-mono text-xs\">\n {server.config.endpoint}\n </CardStackEntryDescription>\n </CardStackEntryContent>\n <Badge variant=\"secondary\" className=\"text-xs\">\n remote\n </Badge>\n </CardStackEntry>\n </CardStackContent>\n </CardStack>\n\n <div className=\"space-y-3 rounded-lg border border-border bg-card p-4\">\n <div>\n <p className=\"text-sm font-medium text-card-foreground\">Authentication method</p>\n <p className=\"mt-0.5 text-xs text-muted-foreground\">\n Choose how a connection credential is sent to this MCP server.\n </p>\n </div>\n <AuthTemplateEditor\n value={authValue}\n onChange={setAuthValue}\n allowedKinds={[\"none\", \"apikey\", \"oauth\"]}\n oauthMetadata=\"discovered\"\n />\n {authChanged ? (\n <div className=\"flex justify-end\">\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => void handleSaveAuth()}\n disabled={authSaving}\n >\n {authSaving ? \"Saving…\" : \"Save authentication method\"}\n </Button>\n </div>\n ) : null}\n </div>\n\n {authChanged ? (\n <div className=\"rounded-md border border-border bg-muted/30 px-3 py-2 text-xs text-muted-foreground\">\n Save the authentication method before adding a connection.\n </div>\n ) : null}\n\n {!authChanged && auth.kind === \"header\" && (\n <ConnectionOwnerUsageRow\n value={connectionOwner}\n options={connectionOwnerOptions}\n onChange={setConnectionOwner}\n label=\"Connection saved to\"\n help=\"Choose who can use this credential.\"\n >\n <CredentialControlField label={`${auth.headerName} value`} help=\"Saved as a connection.\">\n <Input\n type=\"password\"\n value={apiKey}\n onChange={(e) => setApiKey((e.target as HTMLInputElement).value)}\n placeholder=\"sk-…\"\n className=\"font-mono text-sm\"\n autoComplete=\"new-password\"\n />\n <div className=\"mt-2 flex justify-end\">\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => void handleSaveKey()}\n disabled={apiKey.trim() === \"\" || saving}\n >\n {saving ? \"Saving…\" : connected ? \"Saved\" : \"Save connection\"}\n </Button>\n </div>\n </CredentialControlField>\n </ConnectionOwnerUsageRow>\n )}\n\n {!authChanged && auth.kind === \"oauth2\" && (\n <ConnectionOwnerUsageRow\n value={connectionOwner}\n options={connectionOwnerOptions}\n onChange={setConnectionOwner}\n label=\"Connection saved to\"\n help=\"Choose who can use the OAuth connection.\"\n >\n <CredentialControlField label=\"Connect via OAuth\" help=\"Start the provider OAuth flow.\">\n <OAuthSignInButton\n busy={false}\n error={error}\n isConnected={connected}\n onSignIn={handleOAuth}\n signingInLabel=\"Signing in…\"\n reconnectingLabel=\"Reconnecting…\"\n />\n <AddAccountModal\n integration={server.slug}\n integrationName={server.description || String(server.slug)}\n methods={oauthMethods}\n open={oauthModalOpen}\n onOpenChange={setOauthModalOpen}\n initialState={oauthInitialState}\n />\n </CredentialControlField>\n </ConnectionOwnerUsageRow>\n )}\n\n {!authChanged && auth.kind === \"none\" && (\n <div className=\"rounded-md border border-border bg-muted/30 px-3 py-2 text-xs text-muted-foreground\">\n This server does not require a credential.\n </div>\n )}\n\n {error && (\n <div className=\"rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2\">\n <p className=\"text-sm text-destructive\">{error}</p>\n </div>\n )}\n\n <div className=\"flex items-center justify-end border-t border-border pt-4\">\n <Button onClick={props.onSave}>Done</Button>\n </div>\n </div>\n );\n}\n\ntype McpRemoteConfig = Extract<McpIntegrationConfig, { transport: \"remote\" }>;\n\n// ---------------------------------------------------------------------------\n// Stdio read-only view\n// ---------------------------------------------------------------------------\n\nfunction StdioReadOnly(props: {\n server: McpServer & { config: Extract<McpIntegrationConfig, { transport: \"stdio\" }> };\n onSave: () => void;\n}) {\n const { command, args } = props.server.config;\n return (\n <div className=\"space-y-6\">\n <div>\n <h1 className=\"text-xl font-semibold text-foreground\">Edit MCP Source</h1>\n <p className=\"mt-1 text-sm text-muted-foreground\">\n Stdio MCP sources cannot be edited in the UI. Remove and recreate the source with the\n updated command.\n </p>\n </div>\n\n <div className=\"flex items-center gap-3 rounded-lg border border-border bg-card px-4 py-3\">\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-semibold text-card-foreground\">\n {String(props.server.slug)}\n </p>\n <p className=\"mt-0.5 text-xs text-muted-foreground font-mono\">\n {command} {(args ?? []).join(\" \")}\n </p>\n </div>\n <Badge variant=\"secondary\" className=\"text-xs\">\n stdio\n </Badge>\n </div>\n\n <div className=\"flex items-center justify-end border-t border-border pt-4\">\n <Button onClick={props.onSave}>Done</Button>\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Main component — `sourceId` is the integration slug (v2).\n// ---------------------------------------------------------------------------\n\nexport default function EditMcpSource({\n sourceId,\n onSave,\n}: {\n readonly sourceId: string;\n readonly onSave: () => void;\n}) {\n const slug = IntegrationSlug.make(sourceId);\n const serverResult = useAtomValue(mcpServerAtom(slug));\n const server = AsyncResult.isSuccess(serverResult) ? serverResult.value : null;\n\n if (!AsyncResult.isSuccess(serverResult) || server === null) {\n return (\n <div className=\"space-y-6\">\n <div>\n <h1 className=\"text-xl font-semibold text-foreground\">Edit MCP Source</h1>\n <p className=\"mt-1 text-sm text-muted-foreground\">Loading configuration…</p>\n </div>\n </div>\n );\n }\n\n if (server.config.transport === \"stdio\") {\n return (\n <StdioReadOnly\n server={\n server as McpServer & { config: Extract<McpIntegrationConfig, { transport: \"stdio\" }> }\n }\n onSave={onSave}\n />\n );\n }\n\n return <RemoteEdit server={server as McpServer & { config: McpRemoteConfig }} onSave={onSave} />;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,132 @@
1
+ import {
2
+ configureMcpServer,
3
+ mcpServerAtom
4
+ } from "./chunk-N4EAF5CA.js";
5
+ import "./chunk-6OEQZ72N.js";
6
+
7
+ // src/react/McpAccountsPanel.tsx
8
+ import { useCallback, useMemo } from "react";
9
+ import { useAtomSet, useAtomValue } from "@effect/atom-react";
10
+ import * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
11
+ import * as Exit from "effect/Exit";
12
+ import { AuthTemplateSlug, IntegrationSlug } from "@executor-js/sdk/shared";
13
+ import { AccountsSection } from "@executor-js/react/components/accounts-section";
14
+ import { integrationWriteKeys } from "@executor-js/react/api/reactivity-keys";
15
+ import { jsx } from "react/jsx-runtime";
16
+ var NONE_TEMPLATE = AuthTemplateSlug.make("none");
17
+ var HEADER_TEMPLATE = AuthTemplateSlug.make("header");
18
+ var OAUTH_TEMPLATE = AuthTemplateSlug.make("oauth2");
19
+ var NO_AUTH_METHOD = {
20
+ id: "none",
21
+ label: "No authentication",
22
+ kind: "none",
23
+ source: "spec",
24
+ template: NONE_TEMPLATE,
25
+ placements: []
26
+ };
27
+ var authMethodFromConfig = (config) => {
28
+ if (config.transport === "stdio") return null;
29
+ const auth = config.auth;
30
+ if (auth.kind === "none") return NO_AUTH_METHOD;
31
+ if (auth.kind === "oauth2") {
32
+ return {
33
+ id: "oauth2",
34
+ label: "OAuth2",
35
+ kind: "oauth",
36
+ source: "spec",
37
+ template: OAUTH_TEMPLATE,
38
+ placements: [],
39
+ oauth: { discoveryUrl: config.endpoint, supportsDynamicRegistration: true }
40
+ };
41
+ }
42
+ return {
43
+ id: "header",
44
+ label: `API key (${auth.headerName})`,
45
+ kind: "apikey",
46
+ source: "custom",
47
+ template: HEADER_TEMPLATE,
48
+ placements: [
49
+ {
50
+ carrier: "header",
51
+ name: auth.headerName,
52
+ prefix: auth.prefix ?? ""
53
+ }
54
+ ]
55
+ };
56
+ };
57
+ var headerAuthFromPlacements = (placements) => {
58
+ const header = placements.find(
59
+ (placement) => placement.carrier === "header" && placement.name.trim().length > 0
60
+ );
61
+ if (!header) return null;
62
+ return {
63
+ headerName: header.name.trim(),
64
+ ...header.prefix ? { prefix: header.prefix } : {}
65
+ };
66
+ };
67
+ function McpAccountsPanel(props) {
68
+ const { sourceId, integrationName, accountHandoff } = props;
69
+ const slug = IntegrationSlug.make(sourceId);
70
+ const serverResult = useAtomValue(mcpServerAtom(slug));
71
+ const doConfigure = useAtomSet(configureMcpServer, { mode: "promiseExit" });
72
+ const server = AsyncResult.isSuccess(serverResult) ? serverResult.value : null;
73
+ const config = server?.config ?? null;
74
+ const method = config ? authMethodFromConfig(config) : null;
75
+ const methods = method ? [method] : [];
76
+ const createCustomMethod = useCallback(
77
+ async (input) => {
78
+ if (config === null || config.transport !== "remote") return null;
79
+ const header = headerAuthFromPlacements(input.placements);
80
+ if (header === null) return null;
81
+ const nextConfig = {
82
+ ...config,
83
+ auth: { kind: "header", ...header }
84
+ };
85
+ const exit = await doConfigure({
86
+ params: { slug },
87
+ payload: { config: nextConfig },
88
+ reactivityKeys: integrationWriteKeys
89
+ });
90
+ if (Exit.isFailure(exit)) return null;
91
+ return authMethodFromConfig(exit.value.config);
92
+ },
93
+ [config, doConfigure, slug]
94
+ );
95
+ const removeCustomMethod = useCallback(
96
+ async (methodToRemove) => {
97
+ if (config === null || config.transport !== "remote" || methodToRemove.template !== HEADER_TEMPLATE) {
98
+ return false;
99
+ }
100
+ const nextConfig = {
101
+ ...config,
102
+ auth: { kind: "none" }
103
+ };
104
+ const exit = await doConfigure({
105
+ params: { slug },
106
+ payload: { config: nextConfig },
107
+ reactivityKeys: integrationWriteKeys
108
+ });
109
+ return Exit.isSuccess(exit);
110
+ },
111
+ [config, doConfigure, slug]
112
+ );
113
+ const canConfigureAuth = useMemo(
114
+ () => config !== null && config.transport === "remote",
115
+ [config]
116
+ );
117
+ return /* @__PURE__ */ jsx("div", { className: "mx-auto max-w-3xl space-y-8 px-6 py-8", children: /* @__PURE__ */ jsx(
118
+ AccountsSection,
119
+ {
120
+ integration: slug,
121
+ integrationName,
122
+ methods,
123
+ accountHandoff,
124
+ createCustomMethod: canConfigureAuth ? createCustomMethod : void 0,
125
+ removeCustomMethod: canConfigureAuth ? removeCustomMethod : void 0
126
+ }
127
+ ) });
128
+ }
129
+ export {
130
+ McpAccountsPanel as default
131
+ };
132
+ //# sourceMappingURL=McpAccountsPanel-UX7MHEIG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react/McpAccountsPanel.tsx"],"sourcesContent":["import { useCallback, useMemo } from \"react\";\nimport { useAtomSet, useAtomValue } from \"@effect/atom-react\";\nimport * as AsyncResult from \"effect/unstable/reactivity/AsyncResult\";\nimport * as Exit from \"effect/Exit\";\n\nimport { AuthTemplateSlug, IntegrationSlug } from \"@executor-js/sdk/shared\";\nimport type { IntegrationAccountHandoff } from \"@executor-js/sdk/client\";\nimport { AccountsSection } from \"@executor-js/react/components/accounts-section\";\nimport type { CreateCustomMethod } from \"@executor-js/react/components/add-custom-method-modal\";\nimport type { AuthMethod, Placement } from \"@executor-js/react/lib/auth-placements\";\nimport { integrationWriteKeys } from \"@executor-js/react/api/reactivity-keys\";\n\nimport { configureMcpServer, mcpServerAtom } from \"./atoms\";\nimport type { McpIntegrationConfig } from \"../sdk/types\";\n\nconst NONE_TEMPLATE = AuthTemplateSlug.make(\"none\");\nconst HEADER_TEMPLATE = AuthTemplateSlug.make(\"header\");\nconst OAUTH_TEMPLATE = AuthTemplateSlug.make(\"oauth2\");\n\nconst NO_AUTH_METHOD: AuthMethod = {\n id: \"none\",\n label: \"No authentication\",\n kind: \"none\",\n source: \"spec\",\n template: NONE_TEMPLATE,\n placements: [],\n};\n\nconst authMethodFromConfig = (config: McpIntegrationConfig): AuthMethod | null => {\n if (config.transport === \"stdio\") return null;\n const auth = config.auth;\n if (auth.kind === \"none\") return NO_AUTH_METHOD;\n if (auth.kind === \"oauth2\") {\n return {\n id: \"oauth2\",\n label: \"OAuth2\",\n kind: \"oauth\",\n source: \"spec\",\n template: OAUTH_TEMPLATE,\n placements: [],\n oauth: { discoveryUrl: config.endpoint, supportsDynamicRegistration: true },\n };\n }\n return {\n id: \"header\",\n label: `API key (${auth.headerName})`,\n kind: \"apikey\",\n source: \"custom\",\n template: HEADER_TEMPLATE,\n placements: [\n {\n carrier: \"header\",\n name: auth.headerName,\n prefix: auth.prefix ?? \"\",\n },\n ],\n };\n};\n\nconst headerAuthFromPlacements = (\n placements: readonly Placement[],\n): { readonly headerName: string; readonly prefix?: string } | null => {\n const header = placements.find(\n (placement: Placement) => placement.carrier === \"header\" && placement.name.trim().length > 0,\n );\n if (!header) return null;\n return {\n headerName: header.name.trim(),\n ...(header.prefix ? { prefix: header.prefix } : {}),\n };\n};\n\nexport default function McpAccountsPanel(props: {\n readonly sourceId: string;\n readonly integrationName: string;\n readonly accountHandoff?: IntegrationAccountHandoff | null;\n}) {\n const { sourceId, integrationName, accountHandoff } = props;\n const slug = IntegrationSlug.make(sourceId);\n const serverResult = useAtomValue(mcpServerAtom(slug));\n const doConfigure = useAtomSet(configureMcpServer, { mode: \"promiseExit\" });\n\n const server = AsyncResult.isSuccess(serverResult) ? serverResult.value : null;\n const config = server?.config ?? null;\n const method = config ? authMethodFromConfig(config) : null;\n const methods = method ? [method] : [];\n\n const createCustomMethod = useCallback<CreateCustomMethod>(\n async (input: { readonly label: string; readonly placements: readonly Placement[] }) => {\n if (config === null || config.transport !== \"remote\") return null;\n const header = headerAuthFromPlacements(input.placements);\n if (header === null) return null;\n const nextConfig: McpIntegrationConfig = {\n ...config,\n auth: { kind: \"header\", ...header },\n };\n const exit = await doConfigure({\n params: { slug },\n payload: { config: nextConfig },\n reactivityKeys: integrationWriteKeys,\n });\n if (Exit.isFailure(exit)) return null;\n return authMethodFromConfig(exit.value.config);\n },\n [config, doConfigure, slug],\n );\n\n const removeCustomMethod = useCallback(\n async (methodToRemove: AuthMethod): Promise<boolean> => {\n if (\n config === null ||\n config.transport !== \"remote\" ||\n methodToRemove.template !== HEADER_TEMPLATE\n ) {\n return false;\n }\n const nextConfig: McpIntegrationConfig = {\n ...config,\n auth: { kind: \"none\" },\n };\n const exit = await doConfigure({\n params: { slug },\n payload: { config: nextConfig },\n reactivityKeys: integrationWriteKeys,\n });\n return Exit.isSuccess(exit);\n },\n [config, doConfigure, slug],\n );\n\n const canConfigureAuth = useMemo(\n () => config !== null && config.transport === \"remote\",\n [config],\n );\n\n return (\n <div className=\"mx-auto max-w-3xl space-y-8 px-6 py-8\">\n <AccountsSection\n integration={slug}\n integrationName={integrationName}\n methods={methods}\n accountHandoff={accountHandoff}\n createCustomMethod={canConfigureAuth ? createCustomMethod : undefined}\n removeCustomMethod={canConfigureAuth ? removeCustomMethod : undefined}\n />\n </div>\n );\n}\n"],"mappings":";;;;;;;AAAA,SAAS,aAAa,eAAe;AACrC,SAAS,YAAY,oBAAoB;AACzC,YAAY,iBAAiB;AAC7B,YAAY,UAAU;AAEtB,SAAS,kBAAkB,uBAAuB;AAElD,SAAS,uBAAuB;AAGhC,SAAS,4BAA4B;AA+H/B;AA1HN,IAAM,gBAAgB,iBAAiB,KAAK,MAAM;AAClD,IAAM,kBAAkB,iBAAiB,KAAK,QAAQ;AACtD,IAAM,iBAAiB,iBAAiB,KAAK,QAAQ;AAErD,IAAM,iBAA6B;AAAA,EACjC,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,YAAY,CAAC;AACf;AAEA,IAAM,uBAAuB,CAAC,WAAoD;AAChF,MAAI,OAAO,cAAc,QAAS,QAAO;AACzC,QAAM,OAAO,OAAO;AACpB,MAAI,KAAK,SAAS,OAAQ,QAAO;AACjC,MAAI,KAAK,SAAS,UAAU;AAC1B,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAY,CAAC;AAAA,MACb,OAAO,EAAE,cAAc,OAAO,UAAU,6BAA6B,KAAK;AAAA,IAC5E;AAAA,EACF;AACA,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,OAAO,YAAY,KAAK,UAAU;AAAA,IAClC,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,YAAY;AAAA,MACV;AAAA,QACE,SAAS;AAAA,QACT,MAAM,KAAK;AAAA,QACX,QAAQ,KAAK,UAAU;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAM,2BAA2B,CAC/B,eACqE;AACrE,QAAM,SAAS,WAAW;AAAA,IACxB,CAAC,cAAyB,UAAU,YAAY,YAAY,UAAU,KAAK,KAAK,EAAE,SAAS;AAAA,EAC7F;AACA,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO;AAAA,IACL,YAAY,OAAO,KAAK,KAAK;AAAA,IAC7B,GAAI,OAAO,SAAS,EAAE,QAAQ,OAAO,OAAO,IAAI,CAAC;AAAA,EACnD;AACF;AAEe,SAAR,iBAAkC,OAItC;AACD,QAAM,EAAE,UAAU,iBAAiB,eAAe,IAAI;AACtD,QAAM,OAAO,gBAAgB,KAAK,QAAQ;AAC1C,QAAM,eAAe,aAAa,cAAc,IAAI,CAAC;AACrD,QAAM,cAAc,WAAW,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAE1E,QAAM,SAAqB,sBAAU,YAAY,IAAI,aAAa,QAAQ;AAC1E,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,SAAS,SAAS,qBAAqB,MAAM,IAAI;AACvD,QAAM,UAAU,SAAS,CAAC,MAAM,IAAI,CAAC;AAErC,QAAM,qBAAqB;AAAA,IACzB,OAAO,UAAiF;AACtF,UAAI,WAAW,QAAQ,OAAO,cAAc,SAAU,QAAO;AAC7D,YAAM,SAAS,yBAAyB,MAAM,UAAU;AACxD,UAAI,WAAW,KAAM,QAAO;AAC5B,YAAM,aAAmC;AAAA,QACvC,GAAG;AAAA,QACH,MAAM,EAAE,MAAM,UAAU,GAAG,OAAO;AAAA,MACpC;AACA,YAAM,OAAO,MAAM,YAAY;AAAA,QAC7B,QAAQ,EAAE,KAAK;AAAA,QACf,SAAS,EAAE,QAAQ,WAAW;AAAA,QAC9B,gBAAgB;AAAA,MAClB,CAAC;AACD,UAAS,eAAU,IAAI,EAAG,QAAO;AACjC,aAAO,qBAAqB,KAAK,MAAM,MAAM;AAAA,IAC/C;AAAA,IACA,CAAC,QAAQ,aAAa,IAAI;AAAA,EAC5B;AAEA,QAAM,qBAAqB;AAAA,IACzB,OAAO,mBAAiD;AACtD,UACE,WAAW,QACX,OAAO,cAAc,YACrB,eAAe,aAAa,iBAC5B;AACA,eAAO;AAAA,MACT;AACA,YAAM,aAAmC;AAAA,QACvC,GAAG;AAAA,QACH,MAAM,EAAE,MAAM,OAAO;AAAA,MACvB;AACA,YAAM,OAAO,MAAM,YAAY;AAAA,QAC7B,QAAQ,EAAE,KAAK;AAAA,QACf,SAAS,EAAE,QAAQ,WAAW;AAAA,QAC9B,gBAAgB;AAAA,MAClB,CAAC;AACD,aAAY,eAAU,IAAI;AAAA,IAC5B;AAAA,IACA,CAAC,QAAQ,aAAa,IAAI;AAAA,EAC5B;AAEA,QAAM,mBAAmB;AAAA,IACvB,MAAM,WAAW,QAAQ,OAAO,cAAc;AAAA,IAC9C,CAAC,MAAM;AAAA,EACT;AAEA,SACE,oBAAC,SAAI,WAAU,yCACb;AAAA,IAAC;AAAA;AAAA,MACC,aAAa;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA,oBAAoB,mBAAmB,qBAAqB;AAAA,MAC5D,oBAAoB,mBAAmB,qBAAqB;AAAA;AAAA,EAC9D,GACF;AAEJ;","names":[]}