@agent-native/dispatch 0.8.20 → 0.8.24

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 (37) hide show
  1. package/dist/components/messaging-setup-panel.d.ts.map +1 -1
  2. package/dist/components/messaging-setup-panel.js +2 -3
  3. package/dist/components/messaging-setup-panel.js.map +1 -1
  4. package/dist/routes/pages/chat.d.ts +21 -2
  5. package/dist/routes/pages/chat.d.ts.map +1 -1
  6. package/dist/routes/pages/chat.js +12 -3
  7. package/dist/routes/pages/chat.js.map +1 -1
  8. package/dist/routes/pages/overview.d.ts +21 -2
  9. package/dist/routes/pages/overview.d.ts.map +1 -1
  10. package/dist/routes/pages/overview.js +13 -4
  11. package/dist/routes/pages/overview.js.map +1 -1
  12. package/dist/server/lib/dispatch-integrations.d.ts.map +1 -1
  13. package/dist/server/lib/dispatch-integrations.js +27 -3
  14. package/dist/server/lib/dispatch-integrations.js.map +1 -1
  15. package/dist/server/lib/mcp-gateway.d.ts.map +1 -1
  16. package/dist/server/lib/mcp-gateway.js +0 -6
  17. package/dist/server/lib/mcp-gateway.js.map +1 -1
  18. package/dist/server/lib/thread-link-preview.d.ts +24 -0
  19. package/dist/server/lib/thread-link-preview.d.ts.map +1 -0
  20. package/dist/server/lib/thread-link-preview.js +176 -0
  21. package/dist/server/lib/thread-link-preview.js.map +1 -0
  22. package/dist/server/lib/vault-store.d.ts +1 -0
  23. package/dist/server/lib/vault-store.d.ts.map +1 -1
  24. package/dist/server/lib/vault-store.js +67 -20
  25. package/dist/server/lib/vault-store.js.map +1 -1
  26. package/package.json +1 -1
  27. package/src/components/messaging-setup-panel.tsx +2 -3
  28. package/src/routes/pages/chat.tsx +20 -3
  29. package/src/routes/pages/overview.tsx +21 -8
  30. package/src/server/lib/dispatch-integrations.spec.ts +69 -0
  31. package/src/server/lib/dispatch-integrations.ts +26 -3
  32. package/src/server/lib/mcp-gateway.ts +0 -6
  33. package/src/server/lib/thread-link-preview.spec.ts +129 -0
  34. package/src/server/lib/thread-link-preview.ts +187 -0
  35. package/src/server/lib/vault-store.spec.ts +25 -0
  36. package/src/server/lib/vault-store.ts +75 -20
  37. package/src/server/lib/workspace-resource-approval-lifecycle.spec.ts +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"overview.js","sourceRoot":"","sources":["../../../src/routes/pages/overview.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport { Link, useNavigate } from \"react-router\";\nimport {\n PromptComposer,\n useActionQuery,\n useChatModels,\n agentNativePath,\n isInBuilderFrame,\n} from \"@agent-native/core/client\";\nimport {\n IconActivity,\n IconAlertTriangle,\n IconApps,\n IconArrowUpRight,\n IconCheck,\n IconClockHour4,\n IconInfoCircle,\n IconKey,\n IconListCheck,\n IconRocket,\n IconPlugConnected,\n IconShieldCheck,\n type IconProps,\n} from \"@tabler/icons-react\";\nimport { CreateAppPopover } from \"@/components/create-app-popover\";\nimport { DispatchShell } from \"@/components/dispatch-shell\";\nimport { WorkspaceAppCard } from \"@/components/workspace-app-card\";\nimport { Alert, AlertDescription, AlertTitle } from \"@/components/ui/alert\";\nimport { Button } from \"@/components/ui/button\";\nimport { Skeleton } from \"@/components/ui/skeleton\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@/components/ui/tooltip\";\nimport { submitOverviewPrompt } from \"@/lib/overview-chat\";\nimport type { WorkspaceAppSummary } from \"@/lib/workspace-apps\";\n\ninterface IntegrationStatus {\n platform: string;\n label: string;\n enabled: boolean;\n configured: boolean;\n}\n\ninterface TaskQueueRecentFailure {\n id: string;\n platform: string;\n error: string;\n attempts: number;\n}\n\ninterface TaskQueueStats {\n pending: number;\n processing: number;\n completed_last_hour: number;\n failed_last_hour: number;\n oldest_pending_age_seconds: number;\n recent_failures: TaskQueueRecentFailure[];\n}\n\nconst ZERO_TASK_QUEUE_STATS: TaskQueueStats = {\n pending: 0,\n processing: 0,\n completed_last_hour: 0,\n failed_last_hour: 0,\n oldest_pending_age_seconds: 0,\n recent_failures: [],\n};\n\nconst HOME_CHAT_SUGGESTIONS = [\n \"Create a lightweight customer onboarding app\",\n \"Ask Slides to draft a board update from our latest metrics\",\n \"Schedule a Monday morning analytics digest\",\n];\n\nfunction HomeChatPanel() {\n const { selectedModel } = useChatModels();\n const navigate = useNavigate();\n\n const send = (message: string) => {\n const trimmed = message.trim();\n if (!trimmed) return;\n\n if (isInBuilderFrame()) {\n submitOverviewPrompt(trimmed, selectedModel);\n return;\n }\n\n navigate(\"/chat\", {\n state: {\n dispatchPrompt: {\n id: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n message: trimmed,\n selectedModel,\n },\n },\n });\n };\n\n return (\n <section className=\"px-2 py-6 sm:py-10\">\n <div className=\"mx-auto w-full max-w-2xl space-y-8\">\n <h1 className=\"text-center text-2xl font-semibold tracking-tight text-foreground sm:text-3xl\">\n What should we do next?\n </h1>\n <div className=\"flex flex-col gap-4\">\n <PromptComposer\n placeholder=\"Message agent…\"\n onSubmit={(text) => {\n send(text);\n }}\n />\n <div className=\"flex flex-wrap justify-center gap-2\">\n {HOME_CHAT_SUGGESTIONS.map((suggestion) => (\n <button\n key={suggestion}\n type=\"button\"\n onClick={() => send(suggestion)}\n className=\"cursor-pointer rounded-full border border-border bg-card px-3 py-1.5 text-xs text-muted-foreground transition hover:border-foreground/30 hover:text-foreground\"\n >\n {suggestion}\n </button>\n ))}\n </div>\n </div>\n </div>\n </section>\n );\n}\n\nfunction AppCardSkeleton() {\n return (\n <div className=\"rounded-lg border bg-card p-4\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0 flex-1 space-y-3\">\n <Skeleton className=\"h-4 w-32\" />\n <Skeleton className=\"h-3 w-24\" />\n <div className=\"space-y-2 pt-1\">\n <Skeleton className=\"h-3 w-full\" />\n <Skeleton className=\"h-3 w-2/3\" />\n </div>\n </div>\n <Skeleton className=\"h-5 w-5 rounded-md\" />\n </div>\n </div>\n );\n}\n\ninterface RecentAuditEvent {\n id: string;\n summary: string;\n actor: string;\n createdAt: string;\n}\n\nfunction RecentActivityList({\n isLoading,\n events,\n}: {\n isLoading: boolean;\n events: RecentAuditEvent[];\n}) {\n if (isLoading && events.length === 0) {\n return (\n <div className=\"mt-4 space-y-3\">\n {Array.from({ length: 3 }).map((_, index) => (\n <div\n key={index}\n className=\"rounded-xl border bg-muted/30 px-4 py-3 space-y-2\"\n >\n <Skeleton className=\"h-4 w-3/5\" />\n <Skeleton className=\"h-3 w-2/5\" />\n </div>\n ))}\n </div>\n );\n }\n if (events.length === 0) {\n return (\n <div className=\"mt-4 space-y-3\">\n <div className=\"rounded-xl border border-dashed px-4 py-6 text-sm text-muted-foreground\">\n No activity yet.\n </div>\n </div>\n );\n }\n return (\n <div className=\"mt-4 space-y-3\">\n {events.map((event) => (\n <div key={event.id} className=\"rounded-xl border bg-muted/30 px-4 py-3\">\n <div className=\"text-sm font-medium text-foreground\">\n {event.summary}\n </div>\n <div className=\"mt-1 text-xs text-muted-foreground\">\n {event.actor} · {new Date(event.createdAt).toLocaleString()}\n </div>\n </div>\n ))}\n </div>\n );\n}\n\nfunction WorkspaceAppsSection({\n apps,\n isLoading,\n}: {\n apps: WorkspaceAppSummary[];\n isLoading: boolean;\n}) {\n const filteredApps = apps.filter((app) => !app.isDispatch);\n const visibleApps = filteredApps.slice(0, 6);\n const showSkeletons = isLoading && visibleApps.length === 0;\n\n return (\n <section className=\"space-y-3\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div className=\"flex items-center gap-2\">\n <IconApps size={16} className=\"text-muted-foreground\" />\n <h2 className=\"text-sm font-semibold text-foreground\">\n Workspace apps\n </h2>\n </div>\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link to=\"/apps\">\n View all\n <IconArrowUpRight size={15} className=\"ml-1.5\" />\n </Link>\n </Button>\n </div>\n\n <div className=\"grid auto-rows-fr gap-3 sm:grid-cols-2 xl:grid-cols-3\">\n {showSkeletons ? (\n Array.from({ length: 6 }).map((_, index) => (\n <AppCardSkeleton key={index} />\n ))\n ) : visibleApps.length > 0 ? (\n visibleApps.map((app) => (\n <WorkspaceAppCard\n key={app.id}\n app={app}\n className=\"h-full min-h-32\"\n />\n ))\n ) : (\n <CreateAppPopover />\n )}\n </div>\n </section>\n );\n}\n\nfunction formatAgeSeconds(seconds: number): string {\n if (!seconds || seconds < 0) return \"0s\";\n if (seconds < 60) return `${seconds}s`;\n if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;\n return `${Math.floor(seconds / 3600)}h ${Math.floor((seconds % 3600) / 60)}m`;\n}\n\nfunction TaskQueueMetric({\n label,\n value,\n tone,\n icon: Icon,\n}: {\n label: string;\n value: string | number;\n tone?: \"default\" | \"warning\" | \"danger\";\n icon?: React.ComponentType<IconProps>;\n}) {\n const toneClass =\n tone === \"danger\"\n ? \"text-red-600 dark:text-red-400\"\n : tone === \"warning\"\n ? \"text-amber-600 dark:text-amber-400\"\n : \"text-foreground\";\n return (\n <div className=\"rounded-xl border bg-card px-4 py-3\">\n <div className=\"flex items-center gap-1.5 text-xs font-medium text-muted-foreground\">\n {Icon ? <Icon size={14} /> : null}\n <span>{label}</span>\n </div>\n <div className={`mt-1 text-2xl font-semibold ${toneClass}`}>{value}</div>\n </div>\n );\n}\n\nfunction TaskQueueSection({ stats }: { stats: TaskQueueStats }) {\n const showAlert = stats.pending > 5 || stats.failed_last_hour > 0;\n return (\n <section className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <IconListCheck size={16} className=\"text-muted-foreground\" />\n <h2 className=\"text-sm font-semibold text-foreground\">Task queue</h2>\n </div>\n {showAlert && (\n <Alert variant={stats.failed_last_hour > 0 ? \"destructive\" : \"default\"}>\n <IconAlertTriangle className=\"h-4 w-4\" />\n <AlertTitle>\n {stats.failed_last_hour > 0\n ? `${stats.failed_last_hour} integration task${stats.failed_last_hour === 1 ? \"\" : \"s\"} failed in the last hour`\n : `${stats.pending} pending integration task${stats.pending === 1 ? \"\" : \"s\"} queued`}\n </AlertTitle>\n <AlertDescription>\n {stats.failed_last_hour > 0\n ? \"Recent failures are listed below. Check platform credentials and retry.\"\n : \"Tasks are waiting to be processed. The queue may be backed up.\"}\n </AlertDescription>\n </Alert>\n )}\n <div className=\"grid gap-3 sm:grid-cols-2 lg:grid-cols-5\">\n <TaskQueueMetric\n label=\"Pending\"\n value={stats.pending}\n tone={stats.pending > 5 ? \"warning\" : \"default\"}\n />\n <TaskQueueMetric label=\"Processing\" value={stats.processing} />\n <TaskQueueMetric\n label=\"Completed (1h)\"\n value={stats.completed_last_hour}\n />\n <TaskQueueMetric\n label=\"Failed (1h)\"\n value={stats.failed_last_hour}\n tone={stats.failed_last_hour > 0 ? \"danger\" : \"default\"}\n />\n <TaskQueueMetric\n label=\"Oldest pending\"\n value={formatAgeSeconds(stats.oldest_pending_age_seconds)}\n icon={IconClockHour4}\n tone={stats.oldest_pending_age_seconds > 300 ? \"warning\" : \"default\"}\n />\n </div>\n {stats.recent_failures.length > 0 && (\n <div className=\"rounded-2xl border bg-card p-4\">\n <div className=\"text-sm font-semibold text-foreground\">\n Recent failures\n </div>\n <div className=\"mt-3 space-y-2\">\n {stats.recent_failures.map((failure) => (\n <div\n key={failure.id}\n className=\"rounded-xl border bg-muted/30 px-3 py-2\"\n >\n <div className=\"flex items-center justify-between gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">\n {failure.platform}\n </span>\n <span>\n {failure.attempts} attempt\n {failure.attempts === 1 ? \"\" : \"s\"}\n </span>\n </div>\n <div className=\"mt-1 truncate text-sm text-foreground\">\n {failure.error || \"(no error message)\"}\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n </section>\n );\n}\n\nfunction HelpTooltip({ content }: { content: string }) {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n className=\"text-muted-foreground/60 hover:text-foreground cursor-pointer\"\n >\n <IconInfoCircle className=\"h-3.5 w-3.5\" />\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"top\" className=\"max-w-64 text-xs leading-relaxed\">\n {content}\n </TooltipContent>\n </Tooltip>\n );\n}\n\nfunction StatCard({\n label,\n help,\n value,\n icon: Icon,\n cta,\n}: {\n label: string;\n help: string;\n value: number;\n icon: React.ComponentType<IconProps>;\n cta?: React.ReactNode;\n}) {\n return (\n <div className=\"rounded-2xl border bg-card p-5\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-1.5 text-sm font-medium text-foreground\">\n <span>{label}</span>\n <HelpTooltip content={help} />\n </div>\n <div className=\"mt-3 text-3xl font-semibold text-foreground\">\n {value}\n </div>\n </div>\n <div className=\"rounded-xl border bg-muted/30 p-3 text-muted-foreground\">\n <Icon size={18} />\n </div>\n </div>\n {cta ? <div className=\"mt-4\">{cta}</div> : null}\n </div>\n );\n}\n\ninterface ChecklistStep {\n number: number;\n title: string;\n description: string;\n complete: boolean;\n /** If set, renders a link button to this path */\n to?: string;\n actionLabel?: string;\n /** If true, this step is always shown as informational (never \"complete\") */\n informational?: boolean;\n}\n\nfunction StepRow({ step }: { step: ChecklistStep }) {\n const done = step.complete && !step.informational;\n\n return (\n <div\n className={`flex items-start gap-4 rounded-xl border px-5 py-4 ${done ? \"border-border/50 bg-muted/20\" : \"bg-card\"}`}\n >\n {/* Status marker */}\n <div className=\"flex-none pt-0.5\">\n {done ? (\n <div className=\"flex h-7 w-7 items-center justify-center rounded-full bg-emerald-500/15 text-emerald-600 dark:text-emerald-400\">\n <IconCheck size={16} strokeWidth={2.5} />\n </div>\n ) : (\n <div className=\"flex h-7 w-7 items-center justify-center rounded-full border border-muted-foreground/30 text-muted-foreground\">\n <IconListCheck size={15} />\n </div>\n )}\n </div>\n\n {/* Text */}\n <div className={`min-w-0 flex-1 ${done ? \"opacity-50\" : \"\"}`}>\n <div\n className={`text-sm font-semibold ${done ? \"line-through decoration-muted-foreground/40\" : \"text-foreground\"}`}\n >\n {step.title}\n </div>\n <p className=\"mt-0.5 text-sm leading-relaxed text-muted-foreground\">\n {step.description}\n </p>\n </div>\n\n {/* Action */}\n {step.to && !done && (\n <div className=\"flex-none pt-0.5\">\n <Button variant=\"outline\" size=\"sm\" asChild>\n <Link to={step.to}>{step.actionLabel || \"Set up\"}</Link>\n </Button>\n </div>\n )}\n </div>\n );\n}\n\nexport function meta() {\n return [{ title: \"Overview — Dispatch\" }];\n}\n\nexport default function OverviewRoute() {\n const { data, isLoading } = useActionQuery(\"list-dispatch-overview\", {});\n const { data: connectedAgents } = useActionQuery(\"list-connected-agents\", {});\n const { data: workspaceApps = [], isLoading: appsLoading } = useActionQuery(\n \"list-workspace-apps\",\n { includeAgentCards: false },\n {\n refetchInterval: 2_000,\n },\n );\n const [integrationStatuses, setIntegrationStatuses] = useState<\n IntegrationStatus[]\n >([]);\n const [taskQueueStats, setTaskQueueStats] = useState<TaskQueueStats>(\n ZERO_TASK_QUEUE_STATS,\n );\n\n useEffect(() => {\n let active = true;\n fetch(agentNativePath(\"/_agent-native/integrations/status\"))\n .then((res) => (res.ok ? res.json() : []))\n .then((rows) => {\n if (active) {\n setIntegrationStatuses(Array.isArray(rows) ? rows : []);\n }\n })\n .catch(() => {\n if (active) setIntegrationStatuses([]);\n });\n return () => {\n active = false;\n };\n }, []);\n\n useEffect(() => {\n let active = true;\n const load = () => {\n fetch(agentNativePath(\"/_agent-native/integrations/task-queue/status\"))\n .then((res) => (res.ok ? res.json() : null))\n .then((stats) => {\n if (!active || !stats || typeof stats !== \"object\") return;\n setTaskQueueStats({\n pending: Number(stats.pending ?? 0),\n processing: Number(stats.processing ?? 0),\n completed_last_hour: Number(stats.completed_last_hour ?? 0),\n failed_last_hour: Number(stats.failed_last_hour ?? 0),\n oldest_pending_age_seconds: Number(\n stats.oldest_pending_age_seconds ?? 0,\n ),\n recent_failures: Array.isArray(stats.recent_failures)\n ? stats.recent_failures\n : [],\n });\n })\n .catch(() => {\n // Endpoint may not exist on older deploys — ignore.\n });\n };\n load();\n const id = window.setInterval(load, 15000);\n return () => {\n active = false;\n window.clearInterval(id);\n };\n }, []);\n\n const counts = data?.counts || {\n destinations: 0,\n pendingApprovals: 0,\n linkedIdentities: 0,\n activeTokens: 0,\n };\n\n const messagingStatuses = useMemo(\n () =>\n integrationStatuses.filter(\n (row) => row.platform === \"slack\" || row.platform === \"telegram\",\n ),\n [integrationStatuses],\n );\n\n const connectedMessagingCount = messagingStatuses.filter(\n (row) => row.enabled || row.configured,\n ).length;\n const connectedAgentCount = connectedAgents?.length || 0;\n const vaultSecretCount = data?.vault?.secretCount || 0;\n const typedWorkspaceApps = workspaceApps as WorkspaceAppSummary[];\n\n const messagingDone = connectedMessagingCount > 0;\n const agentsDone = connectedAgentCount > 0;\n const vaultDone = vaultSecretCount > 0;\n\n const steps: ChecklistStep[] = [\n {\n number: 1,\n title: \"Connect Slack\",\n description:\n \"Add @agent-native to your Slack workspace so your team can ask questions, create decks, pull analytics, and more — right from Slack.\",\n complete: messagingDone,\n to: \"/messaging\",\n actionLabel: \"Connect\",\n },\n {\n number: 2,\n title: \"Review connected agents\",\n description:\n \"Dispatch delegates work to specialized apps. The built-in suite (Slides, Analytics, Content, Video, and more) is available automatically.\",\n complete: agentsDone,\n to: \"/agents\",\n actionLabel: \"Review\",\n },\n {\n number: 3,\n title: \"Set up your vault\",\n description:\n \"Store API keys centrally and sync them to apps that need them.\",\n complete: vaultDone,\n to: \"/vault\",\n actionLabel: \"Open vault\",\n },\n {\n number: 4,\n title: \"Try it out\",\n description: \"Mention @agent-native in any Slack channel to get started.\",\n complete: false,\n informational: true,\n },\n ];\n\n const hasIncompleteSteps = steps.some((s) => !s.complete && !s.informational);\n\n return (\n <DispatchShell\n title=\"Overview\"\n description=\"Create apps, manage shared keys, and route work across your workspace.\"\n >\n <HomeChatPanel />\n\n <WorkspaceAppsSection apps={typedWorkspaceApps} isLoading={appsLoading} />\n\n {hasIncompleteSteps && (\n <section className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <IconRocket size={16} className=\"text-muted-foreground\" />\n <h2 className=\"text-sm font-semibold text-foreground\">\n Getting started\n </h2>\n </div>\n <div className=\"space-y-2\">\n {steps.map((step) => (\n <StepRow key={step.number} step={step} />\n ))}\n </div>\n </section>\n )}\n\n <section className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <IconActivity size={16} className=\"text-muted-foreground\" />\n <h2 className=\"text-sm font-semibold text-foreground\">At a glance</h2>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2 xl:grid-cols-4\">\n <StatCard\n label=\"Vault secrets\"\n help=\"Credentials stored in the workspace vault.\"\n value={data?.vault?.secretCount || 0}\n icon={IconKey}\n cta={\n (data?.vault?.secretCount || 0) === 0 ? (\n <Button variant=\"outline\" size=\"sm\" asChild>\n <Link to=\"/vault\">Set up vault</Link>\n </Button>\n ) : undefined\n }\n />\n <StatCard\n label={\n data?.vault?.accessMode === \"manual\"\n ? \"Active grants\"\n : \"Accessible keys\"\n }\n help={\n data?.vault?.accessMode === \"manual\"\n ? \"Secrets currently granted to apps. Sync them to push credentials.\"\n : \"Vault keys available to every workspace app.\"\n }\n value={data?.vault?.activeGrantCount || 0}\n icon={IconShieldCheck}\n />\n <StatCard\n label=\"Destinations\"\n help=\"Saved outbound targets used for proactive sends and scheduled jobs.\"\n value={counts.destinations}\n icon={IconArrowUpRight}\n cta={\n counts.destinations === 0 ? (\n <Button variant=\"outline\" size=\"sm\" asChild>\n <Link to=\"/destinations\">Set up destinations</Link>\n </Button>\n ) : undefined\n }\n />\n <StatCard\n label=\"Agents\"\n help=\"Agents available to dispatch for delegation over A2A. This includes the built-in app suite plus any additional agents you add.\"\n value={connectedAgentCount}\n icon={IconPlugConnected}\n cta={\n connectedAgentCount === 0 ? (\n <Button variant=\"outline\" size=\"sm\" asChild>\n <Link to=\"/agents\">Open agents</Link>\n </Button>\n ) : undefined\n }\n />\n </div>\n </section>\n\n <details className=\"rounded-xl border\">\n <summary className=\"flex cursor-pointer list-none items-center justify-between gap-3 px-5 py-4 text-sm font-semibold text-foreground hover:bg-muted/30 [&::-webkit-details-marker]:hidden\">\n <span>Operations detail</span>\n <span className=\"text-xs font-normal text-muted-foreground\">\n Queue, audit, and approvals\n </span>\n </summary>\n <div className=\"space-y-5 border-t px-5 py-5\">\n <TaskQueueSection stats={taskQueueStats} />\n\n <div className=\"grid gap-4 xl:grid-cols-3\">\n <section className=\"rounded-2xl border bg-card p-5 xl:col-span-2\">\n <div className=\"flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-foreground\">\n Recent activity\n </h2>\n </div>\n <RecentActivityList\n isLoading={isLoading}\n events={data?.recentAudit ?? []}\n />\n </section>\n\n <section className=\"rounded-2xl border bg-card p-5\">\n <h2 className=\"text-lg font-semibold text-foreground\">\n Approval mode\n </h2>\n <div className=\"mt-4 rounded-xl border bg-muted/30 p-4\">\n <div className=\"text-sm font-medium text-muted-foreground\">\n Current policy\n </div>\n <div className=\"mt-2 text-2xl font-semibold text-foreground\">\n {data?.settings?.enabled ? \"Reviewed\" : \"Immediate\"}\n </div>\n <p className=\"mt-2 text-sm text-muted-foreground\">\n {data?.settings?.enabled\n ? \"Changes wait for approval before they apply.\"\n : \"Changes apply immediately and are recorded in audit.\"}\n </p>\n </div>\n <div className=\"mt-4 space-y-2\">\n {(data?.recentApprovals || []).map((approval) => (\n <div\n key={approval.id}\n className=\"rounded-xl border px-4 py-3\"\n >\n <div className=\"text-sm font-medium text-foreground\">\n {approval.summary}\n </div>\n <div className=\"mt-1 text-xs text-muted-foreground\">\n {approval.status} · requested by {approval.requestedBy}\n </div>\n </div>\n ))}\n {(data?.recentApprovals?.length || 0) === 0 && (\n <div className=\"rounded-xl border border-dashed px-4 py-6 text-sm text-muted-foreground\">\n No approval requests.\n </div>\n )}\n </div>\n </section>\n </div>\n </div>\n </details>\n </DispatchShell>\n );\n}\n"]}
1
+ {"version":3,"file":"overview.js","sourceRoot":"","sources":["../../../src/routes/pages/overview.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport { Link, useNavigate, type LoaderFunctionArgs } from \"react-router\";\nimport {\n PromptComposer,\n useActionQuery,\n useChatModels,\n agentNativePath,\n isInBuilderFrame,\n} from \"@agent-native/core/client\";\nimport {\n IconActivity,\n IconAlertTriangle,\n IconApps,\n IconArrowUpRight,\n IconCheck,\n IconClockHour4,\n IconInfoCircle,\n IconKey,\n IconListCheck,\n IconRocket,\n IconPlugConnected,\n IconShieldCheck,\n type IconProps,\n} from \"@tabler/icons-react\";\nimport { CreateAppPopover } from \"@/components/create-app-popover\";\nimport { DispatchShell } from \"@/components/dispatch-shell\";\nimport { WorkspaceAppCard } from \"@/components/workspace-app-card\";\nimport { Alert, AlertDescription, AlertTitle } from \"@/components/ui/alert\";\nimport { Button } from \"@/components/ui/button\";\nimport { Skeleton } from \"@/components/ui/skeleton\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@/components/ui/tooltip\";\nimport { submitOverviewPrompt } from \"@/lib/overview-chat\";\nimport {\n buildThreadLinkPreviewMeta,\n loadThreadLinkPreview,\n} from \"@/server/lib/thread-link-preview\";\nimport type { WorkspaceAppSummary } from \"@/lib/workspace-apps\";\n\ninterface IntegrationStatus {\n platform: string;\n label: string;\n enabled: boolean;\n configured: boolean;\n}\n\ninterface TaskQueueRecentFailure {\n id: string;\n platform: string;\n error: string;\n attempts: number;\n}\n\ninterface TaskQueueStats {\n pending: number;\n processing: number;\n completed_last_hour: number;\n failed_last_hour: number;\n oldest_pending_age_seconds: number;\n recent_failures: TaskQueueRecentFailure[];\n}\n\nconst ZERO_TASK_QUEUE_STATS: TaskQueueStats = {\n pending: 0,\n processing: 0,\n completed_last_hour: 0,\n failed_last_hour: 0,\n oldest_pending_age_seconds: 0,\n recent_failures: [],\n};\n\nconst HOME_CHAT_SUGGESTIONS = [\n \"Create a lightweight customer onboarding app\",\n \"Ask Slides to draft a board update from our latest metrics\",\n \"Schedule a Monday morning analytics digest\",\n];\n\nfunction HomeChatPanel() {\n const { selectedModel } = useChatModels();\n const navigate = useNavigate();\n\n const send = (message: string) => {\n const trimmed = message.trim();\n if (!trimmed) return;\n\n if (isInBuilderFrame()) {\n submitOverviewPrompt(trimmed, selectedModel);\n return;\n }\n\n navigate(\"/chat\", {\n state: {\n dispatchPrompt: {\n id: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n message: trimmed,\n selectedModel,\n },\n },\n });\n };\n\n return (\n <section className=\"px-2 py-6 sm:py-10\">\n <div className=\"mx-auto w-full max-w-2xl space-y-8\">\n <h1 className=\"text-center text-2xl font-semibold tracking-tight text-foreground sm:text-3xl\">\n What should we do next?\n </h1>\n <div className=\"flex flex-col gap-4\">\n <PromptComposer\n placeholder=\"Message agent…\"\n onSubmit={(text) => {\n send(text);\n }}\n />\n <div className=\"flex flex-wrap justify-center gap-2\">\n {HOME_CHAT_SUGGESTIONS.map((suggestion) => (\n <button\n key={suggestion}\n type=\"button\"\n onClick={() => send(suggestion)}\n className=\"cursor-pointer rounded-full border border-border bg-card px-3 py-1.5 text-xs text-muted-foreground transition hover:border-foreground/30 hover:text-foreground\"\n >\n {suggestion}\n </button>\n ))}\n </div>\n </div>\n </div>\n </section>\n );\n}\n\nfunction AppCardSkeleton() {\n return (\n <div className=\"rounded-lg border bg-card p-4\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0 flex-1 space-y-3\">\n <Skeleton className=\"h-4 w-32\" />\n <Skeleton className=\"h-3 w-24\" />\n <div className=\"space-y-2 pt-1\">\n <Skeleton className=\"h-3 w-full\" />\n <Skeleton className=\"h-3 w-2/3\" />\n </div>\n </div>\n <Skeleton className=\"h-5 w-5 rounded-md\" />\n </div>\n </div>\n );\n}\n\ninterface RecentAuditEvent {\n id: string;\n summary: string;\n actor: string;\n createdAt: string;\n}\n\nfunction RecentActivityList({\n isLoading,\n events,\n}: {\n isLoading: boolean;\n events: RecentAuditEvent[];\n}) {\n if (isLoading && events.length === 0) {\n return (\n <div className=\"mt-4 space-y-3\">\n {Array.from({ length: 3 }).map((_, index) => (\n <div\n key={index}\n className=\"rounded-xl border bg-muted/30 px-4 py-3 space-y-2\"\n >\n <Skeleton className=\"h-4 w-3/5\" />\n <Skeleton className=\"h-3 w-2/5\" />\n </div>\n ))}\n </div>\n );\n }\n if (events.length === 0) {\n return (\n <div className=\"mt-4 space-y-3\">\n <div className=\"rounded-xl border border-dashed px-4 py-6 text-sm text-muted-foreground\">\n No activity yet.\n </div>\n </div>\n );\n }\n return (\n <div className=\"mt-4 space-y-3\">\n {events.map((event) => (\n <div key={event.id} className=\"rounded-xl border bg-muted/30 px-4 py-3\">\n <div className=\"text-sm font-medium text-foreground\">\n {event.summary}\n </div>\n <div className=\"mt-1 text-xs text-muted-foreground\">\n {event.actor} · {new Date(event.createdAt).toLocaleString()}\n </div>\n </div>\n ))}\n </div>\n );\n}\n\nfunction WorkspaceAppsSection({\n apps,\n isLoading,\n}: {\n apps: WorkspaceAppSummary[];\n isLoading: boolean;\n}) {\n const filteredApps = apps.filter((app) => !app.isDispatch);\n const visibleApps = filteredApps.slice(0, 6);\n const showSkeletons = isLoading && visibleApps.length === 0;\n\n return (\n <section className=\"space-y-3\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div className=\"flex items-center gap-2\">\n <IconApps size={16} className=\"text-muted-foreground\" />\n <h2 className=\"text-sm font-semibold text-foreground\">\n Workspace apps\n </h2>\n </div>\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link to=\"/apps\">\n View all\n <IconArrowUpRight size={15} className=\"ml-1.5\" />\n </Link>\n </Button>\n </div>\n\n <div className=\"grid auto-rows-fr gap-3 sm:grid-cols-2 xl:grid-cols-3\">\n {showSkeletons ? (\n Array.from({ length: 6 }).map((_, index) => (\n <AppCardSkeleton key={index} />\n ))\n ) : visibleApps.length > 0 ? (\n visibleApps.map((app) => (\n <WorkspaceAppCard\n key={app.id}\n app={app}\n className=\"h-full min-h-32\"\n />\n ))\n ) : (\n <CreateAppPopover />\n )}\n </div>\n </section>\n );\n}\n\nfunction formatAgeSeconds(seconds: number): string {\n if (!seconds || seconds < 0) return \"0s\";\n if (seconds < 60) return `${seconds}s`;\n if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;\n return `${Math.floor(seconds / 3600)}h ${Math.floor((seconds % 3600) / 60)}m`;\n}\n\nfunction TaskQueueMetric({\n label,\n value,\n tone,\n icon: Icon,\n}: {\n label: string;\n value: string | number;\n tone?: \"default\" | \"warning\" | \"danger\";\n icon?: React.ComponentType<IconProps>;\n}) {\n const toneClass =\n tone === \"danger\"\n ? \"text-red-600 dark:text-red-400\"\n : tone === \"warning\"\n ? \"text-amber-600 dark:text-amber-400\"\n : \"text-foreground\";\n return (\n <div className=\"rounded-xl border bg-card px-4 py-3\">\n <div className=\"flex items-center gap-1.5 text-xs font-medium text-muted-foreground\">\n {Icon ? <Icon size={14} /> : null}\n <span>{label}</span>\n </div>\n <div className={`mt-1 text-2xl font-semibold ${toneClass}`}>{value}</div>\n </div>\n );\n}\n\nfunction TaskQueueSection({ stats }: { stats: TaskQueueStats }) {\n const showAlert = stats.pending > 5 || stats.failed_last_hour > 0;\n return (\n <section className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <IconListCheck size={16} className=\"text-muted-foreground\" />\n <h2 className=\"text-sm font-semibold text-foreground\">Task queue</h2>\n </div>\n {showAlert && (\n <Alert variant={stats.failed_last_hour > 0 ? \"destructive\" : \"default\"}>\n <IconAlertTriangle className=\"h-4 w-4\" />\n <AlertTitle>\n {stats.failed_last_hour > 0\n ? `${stats.failed_last_hour} integration task${stats.failed_last_hour === 1 ? \"\" : \"s\"} failed in the last hour`\n : `${stats.pending} pending integration task${stats.pending === 1 ? \"\" : \"s\"} queued`}\n </AlertTitle>\n <AlertDescription>\n {stats.failed_last_hour > 0\n ? \"Recent failures are listed below. Check platform credentials and retry.\"\n : \"Tasks are waiting to be processed. The queue may be backed up.\"}\n </AlertDescription>\n </Alert>\n )}\n <div className=\"grid gap-3 sm:grid-cols-2 lg:grid-cols-5\">\n <TaskQueueMetric\n label=\"Pending\"\n value={stats.pending}\n tone={stats.pending > 5 ? \"warning\" : \"default\"}\n />\n <TaskQueueMetric label=\"Processing\" value={stats.processing} />\n <TaskQueueMetric\n label=\"Completed (1h)\"\n value={stats.completed_last_hour}\n />\n <TaskQueueMetric\n label=\"Failed (1h)\"\n value={stats.failed_last_hour}\n tone={stats.failed_last_hour > 0 ? \"danger\" : \"default\"}\n />\n <TaskQueueMetric\n label=\"Oldest pending\"\n value={formatAgeSeconds(stats.oldest_pending_age_seconds)}\n icon={IconClockHour4}\n tone={stats.oldest_pending_age_seconds > 300 ? \"warning\" : \"default\"}\n />\n </div>\n {stats.recent_failures.length > 0 && (\n <div className=\"rounded-2xl border bg-card p-4\">\n <div className=\"text-sm font-semibold text-foreground\">\n Recent failures\n </div>\n <div className=\"mt-3 space-y-2\">\n {stats.recent_failures.map((failure) => (\n <div\n key={failure.id}\n className=\"rounded-xl border bg-muted/30 px-3 py-2\"\n >\n <div className=\"flex items-center justify-between gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">\n {failure.platform}\n </span>\n <span>\n {failure.attempts} attempt\n {failure.attempts === 1 ? \"\" : \"s\"}\n </span>\n </div>\n <div className=\"mt-1 truncate text-sm text-foreground\">\n {failure.error || \"(no error message)\"}\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n </section>\n );\n}\n\nfunction HelpTooltip({ content }: { content: string }) {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n className=\"text-muted-foreground/60 hover:text-foreground cursor-pointer\"\n >\n <IconInfoCircle className=\"h-3.5 w-3.5\" />\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"top\" className=\"max-w-64 text-xs leading-relaxed\">\n {content}\n </TooltipContent>\n </Tooltip>\n );\n}\n\nfunction StatCard({\n label,\n help,\n value,\n icon: Icon,\n cta,\n}: {\n label: string;\n help: string;\n value: number;\n icon: React.ComponentType<IconProps>;\n cta?: React.ReactNode;\n}) {\n return (\n <div className=\"min-w-0 rounded-2xl border bg-card p-5\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-1.5 text-sm font-medium leading-snug text-foreground\">\n <span className=\"min-w-0\">{label}</span>\n <HelpTooltip content={help} />\n </div>\n <div className=\"mt-3 text-3xl font-semibold text-foreground\">\n {value}\n </div>\n </div>\n <div className=\"shrink-0 rounded-xl border bg-muted/30 p-3 text-muted-foreground\">\n <Icon size={18} />\n </div>\n </div>\n {cta ? <div className=\"mt-4\">{cta}</div> : null}\n </div>\n );\n}\n\ninterface ChecklistStep {\n number: number;\n title: string;\n description: string;\n complete: boolean;\n /** If set, renders a link button to this path */\n to?: string;\n actionLabel?: string;\n /** If true, this step is always shown as informational (never \"complete\") */\n informational?: boolean;\n}\n\nfunction StepRow({ step }: { step: ChecklistStep }) {\n const done = step.complete && !step.informational;\n\n return (\n <div\n className={`flex items-start gap-4 rounded-xl border px-5 py-4 ${done ? \"border-border/50 bg-muted/20\" : \"bg-card\"}`}\n >\n {/* Status marker */}\n <div className=\"flex-none pt-0.5\">\n {done ? (\n <div className=\"flex h-7 w-7 items-center justify-center rounded-full bg-emerald-500/15 text-emerald-600 dark:text-emerald-400\">\n <IconCheck size={16} strokeWidth={2.5} />\n </div>\n ) : (\n <div className=\"flex h-7 w-7 items-center justify-center rounded-full border border-muted-foreground/30 text-muted-foreground\">\n <IconListCheck size={15} />\n </div>\n )}\n </div>\n\n {/* Text */}\n <div className={`min-w-0 flex-1 ${done ? \"opacity-50\" : \"\"}`}>\n <div\n className={`text-sm font-semibold ${done ? \"line-through decoration-muted-foreground/40\" : \"text-foreground\"}`}\n >\n {step.title}\n </div>\n <p className=\"mt-0.5 text-sm leading-relaxed text-muted-foreground\">\n {step.description}\n </p>\n </div>\n\n {/* Action */}\n {step.to && !done && (\n <div className=\"flex-none pt-0.5\">\n <Button variant=\"outline\" size=\"sm\" asChild>\n <Link to={step.to}>{step.actionLabel || \"Set up\"}</Link>\n </Button>\n </div>\n )}\n </div>\n );\n}\n\nexport async function loader({ request }: LoaderFunctionArgs) {\n const threadId = new URL(request.url).searchParams.get(\"thread\");\n return {\n threadPreview: await loadThreadLinkPreview(threadId),\n };\n}\n\nexport function meta({ data }: { data?: Awaited<ReturnType<typeof loader>> }) {\n return data?.threadPreview\n ? buildThreadLinkPreviewMeta(data.threadPreview)\n : [{ title: \"Overview — Dispatch\" }];\n}\n\nexport default function OverviewRoute() {\n const { data, isLoading } = useActionQuery(\"list-dispatch-overview\", {});\n const { data: connectedAgents } = useActionQuery(\"list-connected-agents\", {});\n const { data: workspaceApps = [], isLoading: appsLoading } = useActionQuery(\n \"list-workspace-apps\",\n { includeAgentCards: false },\n {\n refetchInterval: 2_000,\n },\n );\n const [integrationStatuses, setIntegrationStatuses] = useState<\n IntegrationStatus[]\n >([]);\n const [taskQueueStats, setTaskQueueStats] = useState<TaskQueueStats>(\n ZERO_TASK_QUEUE_STATS,\n );\n\n useEffect(() => {\n let active = true;\n fetch(agentNativePath(\"/_agent-native/integrations/status\"))\n .then((res) => (res.ok ? res.json() : []))\n .then((rows) => {\n if (active) {\n setIntegrationStatuses(Array.isArray(rows) ? rows : []);\n }\n })\n .catch(() => {\n if (active) setIntegrationStatuses([]);\n });\n return () => {\n active = false;\n };\n }, []);\n\n useEffect(() => {\n let active = true;\n const load = () => {\n fetch(agentNativePath(\"/_agent-native/integrations/task-queue/status\"))\n .then((res) => (res.ok ? res.json() : null))\n .then((stats) => {\n if (!active || !stats || typeof stats !== \"object\") return;\n setTaskQueueStats({\n pending: Number(stats.pending ?? 0),\n processing: Number(stats.processing ?? 0),\n completed_last_hour: Number(stats.completed_last_hour ?? 0),\n failed_last_hour: Number(stats.failed_last_hour ?? 0),\n oldest_pending_age_seconds: Number(\n stats.oldest_pending_age_seconds ?? 0,\n ),\n recent_failures: Array.isArray(stats.recent_failures)\n ? stats.recent_failures\n : [],\n });\n })\n .catch(() => {\n // Endpoint may not exist on older deploys — ignore.\n });\n };\n load();\n const id = window.setInterval(load, 15000);\n return () => {\n active = false;\n window.clearInterval(id);\n };\n }, []);\n\n const counts = data?.counts || {\n destinations: 0,\n pendingApprovals: 0,\n linkedIdentities: 0,\n activeTokens: 0,\n };\n\n const messagingStatuses = useMemo(\n () =>\n integrationStatuses.filter(\n (row) => row.platform === \"slack\" || row.platform === \"telegram\",\n ),\n [integrationStatuses],\n );\n\n const connectedMessagingCount = messagingStatuses.filter(\n (row) => row.enabled || row.configured,\n ).length;\n const connectedAgentCount = connectedAgents?.length || 0;\n const vaultSecretCount = data?.vault?.secretCount || 0;\n const typedWorkspaceApps = workspaceApps as WorkspaceAppSummary[];\n\n const messagingDone = connectedMessagingCount > 0;\n const agentsDone = connectedAgentCount > 0;\n const vaultDone = vaultSecretCount > 0;\n\n const steps: ChecklistStep[] = [\n {\n number: 1,\n title: \"Connect Slack\",\n description:\n \"Add @agent-native to your Slack workspace so your team can ask questions, create decks, pull analytics, and more — right from Slack.\",\n complete: messagingDone,\n to: \"/messaging\",\n actionLabel: \"Connect\",\n },\n {\n number: 2,\n title: \"Review connected agents\",\n description:\n \"Dispatch delegates work to specialized apps. The built-in suite (Slides, Analytics, Content, Video, and more) is available automatically.\",\n complete: agentsDone,\n to: \"/agents\",\n actionLabel: \"Review\",\n },\n {\n number: 3,\n title: \"Set up your vault\",\n description:\n \"Store API keys centrally and sync them to apps that need them.\",\n complete: vaultDone,\n to: \"/vault\",\n actionLabel: \"Open vault\",\n },\n {\n number: 4,\n title: \"Try it out\",\n description: \"Mention @agent-native in any Slack channel to get started.\",\n complete: false,\n informational: true,\n },\n ];\n\n const hasIncompleteSteps = steps.some((s) => !s.complete && !s.informational);\n\n return (\n <DispatchShell\n title=\"Overview\"\n description=\"Create apps, manage shared keys, and route work across your workspace.\"\n >\n <HomeChatPanel />\n\n <WorkspaceAppsSection apps={typedWorkspaceApps} isLoading={appsLoading} />\n\n {hasIncompleteSteps && (\n <section className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <IconRocket size={16} className=\"text-muted-foreground\" />\n <h2 className=\"text-sm font-semibold text-foreground\">\n Getting started\n </h2>\n </div>\n <div className=\"space-y-2\">\n {steps.map((step) => (\n <StepRow key={step.number} step={step} />\n ))}\n </div>\n </section>\n )}\n\n <section className=\"space-y-3\">\n <div className=\"flex items-center gap-2\">\n <IconActivity size={16} className=\"text-muted-foreground\" />\n <h2 className=\"text-sm font-semibold text-foreground\">At a glance</h2>\n </div>\n <div className=\"grid grid-cols-[repeat(auto-fit,minmax(min(100%,13rem),1fr))] gap-4\">\n <StatCard\n label=\"Vault secrets\"\n help=\"Credentials stored in the workspace vault.\"\n value={data?.vault?.secretCount || 0}\n icon={IconKey}\n cta={\n (data?.vault?.secretCount || 0) === 0 ? (\n <Button variant=\"outline\" size=\"sm\" asChild>\n <Link to=\"/vault\">Set up vault</Link>\n </Button>\n ) : undefined\n }\n />\n <StatCard\n label={\n data?.vault?.accessMode === \"manual\"\n ? \"Active grants\"\n : \"Accessible keys\"\n }\n help={\n data?.vault?.accessMode === \"manual\"\n ? \"Secrets currently granted to apps. Sync them to push credentials.\"\n : \"Vault keys available to every workspace app.\"\n }\n value={data?.vault?.activeGrantCount || 0}\n icon={IconShieldCheck}\n />\n <StatCard\n label=\"Destinations\"\n help=\"Saved outbound targets used for proactive sends and scheduled jobs.\"\n value={counts.destinations}\n icon={IconArrowUpRight}\n cta={\n counts.destinations === 0 ? (\n <Button variant=\"outline\" size=\"sm\" asChild>\n <Link to=\"/destinations\">Set up destinations</Link>\n </Button>\n ) : undefined\n }\n />\n <StatCard\n label=\"Agents\"\n help=\"Agents available to dispatch for delegation over A2A. This includes the built-in app suite plus any additional agents you add.\"\n value={connectedAgentCount}\n icon={IconPlugConnected}\n cta={\n connectedAgentCount === 0 ? (\n <Button variant=\"outline\" size=\"sm\" asChild>\n <Link to=\"/agents\">Open agents</Link>\n </Button>\n ) : undefined\n }\n />\n </div>\n </section>\n\n <details className=\"rounded-xl border\">\n <summary className=\"flex cursor-pointer list-none items-center justify-between gap-3 px-5 py-4 text-sm font-semibold text-foreground hover:bg-muted/30 [&::-webkit-details-marker]:hidden\">\n <span>Operations detail</span>\n <span className=\"text-xs font-normal text-muted-foreground\">\n Queue, audit, and approvals\n </span>\n </summary>\n <div className=\"space-y-5 border-t px-5 py-5\">\n <TaskQueueSection stats={taskQueueStats} />\n\n <div className=\"grid gap-4 xl:grid-cols-3\">\n <section className=\"rounded-2xl border bg-card p-5 xl:col-span-2\">\n <div className=\"flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-foreground\">\n Recent activity\n </h2>\n </div>\n <RecentActivityList\n isLoading={isLoading}\n events={data?.recentAudit ?? []}\n />\n </section>\n\n <section className=\"rounded-2xl border bg-card p-5\">\n <h2 className=\"text-lg font-semibold text-foreground\">\n Approval mode\n </h2>\n <div className=\"mt-4 rounded-xl border bg-muted/30 p-4\">\n <div className=\"text-sm font-medium text-muted-foreground\">\n Current policy\n </div>\n <div className=\"mt-2 text-2xl font-semibold text-foreground\">\n {data?.settings?.enabled ? \"Reviewed\" : \"Immediate\"}\n </div>\n <p className=\"mt-2 text-sm text-muted-foreground\">\n {data?.settings?.enabled\n ? \"Changes wait for approval before they apply.\"\n : \"Changes apply immediately and are recorded in audit.\"}\n </p>\n </div>\n <div className=\"mt-4 space-y-2\">\n {(data?.recentApprovals || []).map((approval) => (\n <div\n key={approval.id}\n className=\"rounded-xl border px-4 py-3\"\n >\n <div className=\"text-sm font-medium text-foreground\">\n {approval.summary}\n </div>\n <div className=\"mt-1 text-xs text-muted-foreground\">\n {approval.status} · requested by {approval.requestedBy}\n </div>\n </div>\n ))}\n {(data?.recentApprovals?.length || 0) === 0 && (\n <div className=\"rounded-xl border border-dashed px-4 py-6 text-sm text-muted-foreground\">\n No approval requests.\n </div>\n )}\n </div>\n </section>\n </div>\n </div>\n </details>\n </DispatchShell>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"dispatch-integrations.d.ts","sourceRoot":"","sources":["../../../src/server/lib/dispatch-integrations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EAChB,MAAM,2BAA2B,CAAC;AAuBnC,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,eAAe,GACxB,MAAM,GAAG,IAAI,CAmBf;AA0GD,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,eAAe,GACxB,OAAO,CAAC,MAAM,CAAC,CAuCjB;AAED,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC,CA6BxE"}
1
+ {"version":3,"file":"dispatch-integrations.d.ts","sourceRoot":"","sources":["../../../src/server/lib/dispatch-integrations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EAChB,MAAM,2BAA2B,CAAC;AAuBnC,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,eAAe,GACxB,MAAM,GAAG,IAAI,CAmBf;AA0GD,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,eAAe,GACxB,OAAO,CAAC,MAAM,CAAC,CA8DjB;AAED,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAA;CAAE,CAAC,CA6BxE"}
@@ -122,12 +122,36 @@ export async function resolveDispatchOwner(incoming) {
122
122
  });
123
123
  if (owner)
124
124
  return owner;
125
- // For email, the sender's email address is already a natural identity.
126
- // If the senderId looks like an email address, use it directly as the owner.
125
+ // For email, the sender's `From:` address is attacker-settable: SMTP lets
126
+ // anyone claim any From, and our inbound webhook secret only authenticates
127
+ // the provider→app hop, not the original sender. So we must NOT grant a
128
+ // real user's identity (their API keys, org secrets, personal
129
+ // instructions, ownable data) off the bare From. Mirror the Slack gate:
130
+ // only return the sender email as the acting owner when BOTH
131
+ // (a) the message is DKIM/SPF-verified for the From domain, AND
132
+ // (b) that email maps to a real org member.
133
+ // Otherwise fall through to the synthetic, credential-less fallback owner.
134
+ // (A linked identity, handled by resolveLinkedOwner above, remains an
135
+ // always-allowed way to bind an address regardless of verification.)
136
+ //
137
+ // Escape hatch: set DISPATCH_TRUST_UNVERIFIED_EMAIL_SENDER=1 to restore
138
+ // the legacy "trust the From header" behavior. OFF by default; only use
139
+ // this if you fully control the inbound mail path and accept that a
140
+ // spoofed From can act as any org member. See FINDING 3 (inbound-email
141
+ // impersonation) in the webhook security audit.
127
142
  if (incoming.platform === "email" &&
128
143
  incoming.senderId &&
129
144
  incoming.senderId.includes("@")) {
130
- return incoming.senderId;
145
+ if (process.env.DISPATCH_TRUST_UNVERIFIED_EMAIL_SENDER === "1") {
146
+ return incoming.senderId;
147
+ }
148
+ if (incoming.senderVerified) {
149
+ const orgId = await resolveOrgIdForEmail(incoming.senderId);
150
+ if (orgId)
151
+ return incoming.senderId;
152
+ }
153
+ // Unverified or not an org member — do not impersonate. Fall through to
154
+ // the synthetic fallback owner below.
131
155
  }
132
156
  // Slack gives us a user id in the event payload. Resolve it to a verified
133
157
  // workspace email and use that user's own org context when they are an
@@ -1 +1 @@
1
- {"version":3,"file":"dispatch-integrations.js","sourceRoot":"","sources":["../../../src/server/lib/dispatch-integrations.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n IncomingMessage,\n PlatformAdapter,\n} from \"@agent-native/core/server\";\nimport { resolveOrgIdForEmail } from \"@agent-native/core/org\";\nimport crypto from \"node:crypto\";\nimport { consumeLinkToken, resolveLinkedOwner } from \"./dispatch-store.js\";\nimport { handleRemoteCodeCommand } from \"./dispatch-remote-commands.js\";\n\ntype SlackSenderProfile = {\n email: string | null;\n name: string | null;\n};\n\nconst slackProfileCache = new Map<\n string,\n { profile: SlackSenderProfile; expiresAt: number }\n>();\nconst SLACK_PROFILE_CACHE_TTL = 10 * 60 * 1000;\n\nfunction contextString(value: unknown): string | null {\n if (typeof value === \"string\" && value.trim()) return value.trim();\n if (typeof value === \"number\" && Number.isFinite(value)) return String(value);\n return null;\n}\n\nexport function identityKeyForIncoming(\n incoming: IncomingMessage,\n): string | null {\n const senderId = contextString(incoming.senderId);\n if (!senderId) return null;\n\n if (incoming.platform === \"slack\") {\n const teamId = contextString(incoming.platformContext.teamId);\n return teamId ? `${teamId}:${senderId}` : senderId;\n }\n\n if (incoming.platform === \"whatsapp\") {\n const phoneNumberId = contextString(incoming.platformContext.phoneNumberId);\n return phoneNumberId ? `${phoneNumberId}:${senderId}` : senderId;\n }\n\n if (incoming.platform === \"email\") {\n return senderId.toLowerCase();\n }\n\n return senderId;\n}\n\nfunction fallbackOwnerForIncoming(incoming: IncomingMessage): string {\n const tenant =\n contextString(incoming.platformContext.teamId) ||\n contextString(incoming.platformContext.phoneNumberId) ||\n contextString(incoming.platformContext.chatId) ||\n contextString(incoming.platformContext.from) ||\n incoming.externalThreadId;\n const raw = `${incoming.platform}:${tenant}:${incoming.senderId || \"\"}`;\n const hash = crypto\n .createHash(\"sha256\")\n .update(raw)\n .digest(\"hex\")\n .slice(0, 16);\n return `dispatch+${hash}@integration.local`;\n}\n\nfunction configuredDefaultOwnerForIncoming(\n incoming: IncomingMessage,\n): string | null {\n // This is intentionally Slack-only: a deployment-wide default owner grants\n // that Slack workspace access to the owner's connected agents and org\n // credentials, so other platforms should opt in with explicit identity links.\n if (incoming.platform !== \"slack\") return null;\n const email = process.env.DISPATCH_DEFAULT_OWNER_EMAIL?.trim();\n if (!email) return null;\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email) ? email : null;\n}\n\nasync function resolveSlackSenderProfile(\n incoming: IncomingMessage,\n): Promise<SlackSenderProfile> {\n if (incoming.platform !== \"slack\") return { email: null, name: null };\n const token = process.env.SLACK_BOT_TOKEN;\n const userId = contextString(incoming.senderId);\n const teamId = contextString(incoming.platformContext.teamId);\n if (!token || !userId) return { email: null, name: null };\n\n // Slack user IDs are scoped per workspace, so without a teamId we can't\n // safely cache: two installs of the bot in different workspaces could\n // share user-id strings and collide on a single \"default\" key. Skip the\n // cache (and lookup on every request) when teamId is missing.\n const cacheKey = teamId ? `${teamId}:${userId}` : null;\n if (cacheKey) {\n const cached = slackProfileCache.get(cacheKey);\n if (cached && cached.expiresAt > Date.now()) return cached.profile;\n }\n\n try {\n const params = new URLSearchParams({ user: userId });\n const res = await fetch(`https://slack.com/api/users.info?${params}`, {\n headers: { Authorization: `Bearer ${token}` },\n });\n const data = (await res.json()) as {\n ok?: boolean;\n user?: {\n real_name?: string;\n name?: string;\n profile?: {\n email?: string;\n real_name?: string;\n display_name?: string;\n };\n };\n };\n const profile = data.ok\n ? {\n email: data.user?.profile?.email?.trim().toLowerCase() || null,\n name:\n data.user?.profile?.real_name?.trim() ||\n data.user?.profile?.display_name?.trim() ||\n data.user?.real_name?.trim() ||\n data.user?.name?.trim() ||\n null,\n }\n : { email: null, name: null };\n if (cacheKey) {\n slackProfileCache.set(cacheKey, {\n profile,\n expiresAt: Date.now() + SLACK_PROFILE_CACHE_TTL,\n });\n }\n return profile;\n } catch {\n return { email: null, name: null };\n }\n}\n\nasync function resolveSlackOwnerFromVerifiedEmail(\n incoming: IncomingMessage,\n): Promise<string | null> {\n const profile = await resolveSlackSenderProfile(incoming);\n if (!profile.email) return null;\n\n incoming.senderEmail = profile.email;\n incoming.platformContext.senderEmail = profile.email;\n if (profile.name) {\n incoming.senderName = profile.name;\n incoming.platformContext.senderName = profile.name;\n }\n\n const orgId = await resolveOrgIdForEmail(profile.email);\n return orgId ? profile.email : null;\n}\n\nexport async function resolveDispatchOwner(\n incoming: IncomingMessage,\n): Promise<string> {\n try {\n const externalUserId = identityKeyForIncoming(incoming);\n\n // Webhooks do not have the browser request's org context, so allow a safe\n // cross-org fallback when the linked platform identity maps to one owner.\n const owner = await resolveLinkedOwner(incoming.platform, externalUserId, {\n allowAnyOrgFallback: true,\n });\n if (owner) return owner;\n\n // For email, the sender's email address is already a natural identity.\n // If the senderId looks like an email address, use it directly as the owner.\n if (\n incoming.platform === \"email\" &&\n incoming.senderId &&\n incoming.senderId.includes(\"@\")\n ) {\n return incoming.senderId;\n }\n\n // Slack gives us a user id in the event payload. Resolve it to a verified\n // workspace email and use that user's own org context when they are an\n // Agent-Native member, so artifacts created via @agent-native are visible\n // when they open the target app.\n if (incoming.platform === \"slack\") {\n const slackOwner = await resolveSlackOwnerFromVerifiedEmail(incoming);\n if (slackOwner) return slackOwner;\n }\n\n const defaultOwner = configuredDefaultOwnerForIncoming(incoming);\n if (defaultOwner) return defaultOwner;\n\n return fallbackOwnerForIncoming(incoming);\n } catch {\n const defaultOwner = configuredDefaultOwnerForIncoming(incoming);\n if (defaultOwner) return defaultOwner;\n return fallbackOwnerForIncoming(incoming);\n }\n}\n\nexport async function beforeDispatchProcess(\n incoming: IncomingMessage,\n adapter: PlatformAdapter,\n): Promise<{ handled: true; responseText?: string } | { handled: false }> {\n const trimmed = incoming.text.trim();\n const commandText =\n contextString(incoming.platformContext.rawText) || trimmed;\n const match = commandText.match(/^\\/link(?:@\\w+)?\\s+([a-zA-Z0-9_-]+)$/);\n if (!match) {\n return handleRemoteCodeCommand(incoming, adapter, {\n resolveOwner: () => resolveDispatchOwner(incoming),\n });\n }\n\n try {\n const owner = await consumeLinkToken({\n platform: incoming.platform,\n token: match[1],\n externalUserId: identityKeyForIncoming(incoming),\n externalUserName: incoming.senderName || null,\n });\n return {\n handled: true,\n responseText: `Linked successfully. Future ${incoming.platform} messages will use ${owner}'s personal dispatch context.`,\n };\n } catch (error) {\n return {\n handled: true,\n responseText:\n error instanceof Error ? error.message : \"Failed to link this account.\",\n };\n }\n}\n"]}
1
+ {"version":3,"file":"dispatch-integrations.js","sourceRoot":"","sources":["../../../src/server/lib/dispatch-integrations.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n IncomingMessage,\n PlatformAdapter,\n} from \"@agent-native/core/server\";\nimport { resolveOrgIdForEmail } from \"@agent-native/core/org\";\nimport crypto from \"node:crypto\";\nimport { consumeLinkToken, resolveLinkedOwner } from \"./dispatch-store.js\";\nimport { handleRemoteCodeCommand } from \"./dispatch-remote-commands.js\";\n\ntype SlackSenderProfile = {\n email: string | null;\n name: string | null;\n};\n\nconst slackProfileCache = new Map<\n string,\n { profile: SlackSenderProfile; expiresAt: number }\n>();\nconst SLACK_PROFILE_CACHE_TTL = 10 * 60 * 1000;\n\nfunction contextString(value: unknown): string | null {\n if (typeof value === \"string\" && value.trim()) return value.trim();\n if (typeof value === \"number\" && Number.isFinite(value)) return String(value);\n return null;\n}\n\nexport function identityKeyForIncoming(\n incoming: IncomingMessage,\n): string | null {\n const senderId = contextString(incoming.senderId);\n if (!senderId) return null;\n\n if (incoming.platform === \"slack\") {\n const teamId = contextString(incoming.platformContext.teamId);\n return teamId ? `${teamId}:${senderId}` : senderId;\n }\n\n if (incoming.platform === \"whatsapp\") {\n const phoneNumberId = contextString(incoming.platformContext.phoneNumberId);\n return phoneNumberId ? `${phoneNumberId}:${senderId}` : senderId;\n }\n\n if (incoming.platform === \"email\") {\n return senderId.toLowerCase();\n }\n\n return senderId;\n}\n\nfunction fallbackOwnerForIncoming(incoming: IncomingMessage): string {\n const tenant =\n contextString(incoming.platformContext.teamId) ||\n contextString(incoming.platformContext.phoneNumberId) ||\n contextString(incoming.platformContext.chatId) ||\n contextString(incoming.platformContext.from) ||\n incoming.externalThreadId;\n const raw = `${incoming.platform}:${tenant}:${incoming.senderId || \"\"}`;\n const hash = crypto\n .createHash(\"sha256\")\n .update(raw)\n .digest(\"hex\")\n .slice(0, 16);\n return `dispatch+${hash}@integration.local`;\n}\n\nfunction configuredDefaultOwnerForIncoming(\n incoming: IncomingMessage,\n): string | null {\n // This is intentionally Slack-only: a deployment-wide default owner grants\n // that Slack workspace access to the owner's connected agents and org\n // credentials, so other platforms should opt in with explicit identity links.\n if (incoming.platform !== \"slack\") return null;\n const email = process.env.DISPATCH_DEFAULT_OWNER_EMAIL?.trim();\n if (!email) return null;\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email) ? email : null;\n}\n\nasync function resolveSlackSenderProfile(\n incoming: IncomingMessage,\n): Promise<SlackSenderProfile> {\n if (incoming.platform !== \"slack\") return { email: null, name: null };\n const token = process.env.SLACK_BOT_TOKEN;\n const userId = contextString(incoming.senderId);\n const teamId = contextString(incoming.platformContext.teamId);\n if (!token || !userId) return { email: null, name: null };\n\n // Slack user IDs are scoped per workspace, so without a teamId we can't\n // safely cache: two installs of the bot in different workspaces could\n // share user-id strings and collide on a single \"default\" key. Skip the\n // cache (and lookup on every request) when teamId is missing.\n const cacheKey = teamId ? `${teamId}:${userId}` : null;\n if (cacheKey) {\n const cached = slackProfileCache.get(cacheKey);\n if (cached && cached.expiresAt > Date.now()) return cached.profile;\n }\n\n try {\n const params = new URLSearchParams({ user: userId });\n const res = await fetch(`https://slack.com/api/users.info?${params}`, {\n headers: { Authorization: `Bearer ${token}` },\n });\n const data = (await res.json()) as {\n ok?: boolean;\n user?: {\n real_name?: string;\n name?: string;\n profile?: {\n email?: string;\n real_name?: string;\n display_name?: string;\n };\n };\n };\n const profile = data.ok\n ? {\n email: data.user?.profile?.email?.trim().toLowerCase() || null,\n name:\n data.user?.profile?.real_name?.trim() ||\n data.user?.profile?.display_name?.trim() ||\n data.user?.real_name?.trim() ||\n data.user?.name?.trim() ||\n null,\n }\n : { email: null, name: null };\n if (cacheKey) {\n slackProfileCache.set(cacheKey, {\n profile,\n expiresAt: Date.now() + SLACK_PROFILE_CACHE_TTL,\n });\n }\n return profile;\n } catch {\n return { email: null, name: null };\n }\n}\n\nasync function resolveSlackOwnerFromVerifiedEmail(\n incoming: IncomingMessage,\n): Promise<string | null> {\n const profile = await resolveSlackSenderProfile(incoming);\n if (!profile.email) return null;\n\n incoming.senderEmail = profile.email;\n incoming.platformContext.senderEmail = profile.email;\n if (profile.name) {\n incoming.senderName = profile.name;\n incoming.platformContext.senderName = profile.name;\n }\n\n const orgId = await resolveOrgIdForEmail(profile.email);\n return orgId ? profile.email : null;\n}\n\nexport async function resolveDispatchOwner(\n incoming: IncomingMessage,\n): Promise<string> {\n try {\n const externalUserId = identityKeyForIncoming(incoming);\n\n // Webhooks do not have the browser request's org context, so allow a safe\n // cross-org fallback when the linked platform identity maps to one owner.\n const owner = await resolveLinkedOwner(incoming.platform, externalUserId, {\n allowAnyOrgFallback: true,\n });\n if (owner) return owner;\n\n // For email, the sender's `From:` address is attacker-settable: SMTP lets\n // anyone claim any From, and our inbound webhook secret only authenticates\n // the provider→app hop, not the original sender. So we must NOT grant a\n // real user's identity (their API keys, org secrets, personal\n // instructions, ownable data) off the bare From. Mirror the Slack gate:\n // only return the sender email as the acting owner when BOTH\n // (a) the message is DKIM/SPF-verified for the From domain, AND\n // (b) that email maps to a real org member.\n // Otherwise fall through to the synthetic, credential-less fallback owner.\n // (A linked identity, handled by resolveLinkedOwner above, remains an\n // always-allowed way to bind an address regardless of verification.)\n //\n // Escape hatch: set DISPATCH_TRUST_UNVERIFIED_EMAIL_SENDER=1 to restore\n // the legacy \"trust the From header\" behavior. OFF by default; only use\n // this if you fully control the inbound mail path and accept that a\n // spoofed From can act as any org member. See FINDING 3 (inbound-email\n // impersonation) in the webhook security audit.\n if (\n incoming.platform === \"email\" &&\n incoming.senderId &&\n incoming.senderId.includes(\"@\")\n ) {\n if (process.env.DISPATCH_TRUST_UNVERIFIED_EMAIL_SENDER === \"1\") {\n return incoming.senderId;\n }\n if (incoming.senderVerified) {\n const orgId = await resolveOrgIdForEmail(incoming.senderId);\n if (orgId) return incoming.senderId;\n }\n // Unverified or not an org member — do not impersonate. Fall through to\n // the synthetic fallback owner below.\n }\n\n // Slack gives us a user id in the event payload. Resolve it to a verified\n // workspace email and use that user's own org context when they are an\n // Agent-Native member, so artifacts created via @agent-native are visible\n // when they open the target app.\n if (incoming.platform === \"slack\") {\n const slackOwner = await resolveSlackOwnerFromVerifiedEmail(incoming);\n if (slackOwner) return slackOwner;\n }\n\n const defaultOwner = configuredDefaultOwnerForIncoming(incoming);\n if (defaultOwner) return defaultOwner;\n\n return fallbackOwnerForIncoming(incoming);\n } catch {\n const defaultOwner = configuredDefaultOwnerForIncoming(incoming);\n if (defaultOwner) return defaultOwner;\n return fallbackOwnerForIncoming(incoming);\n }\n}\n\nexport async function beforeDispatchProcess(\n incoming: IncomingMessage,\n adapter: PlatformAdapter,\n): Promise<{ handled: true; responseText?: string } | { handled: false }> {\n const trimmed = incoming.text.trim();\n const commandText =\n contextString(incoming.platformContext.rawText) || trimmed;\n const match = commandText.match(/^\\/link(?:@\\w+)?\\s+([a-zA-Z0-9_-]+)$/);\n if (!match) {\n return handleRemoteCodeCommand(incoming, adapter, {\n resolveOwner: () => resolveDispatchOwner(incoming),\n });\n }\n\n try {\n const owner = await consumeLinkToken({\n platform: incoming.platform,\n token: match[1],\n externalUserId: identityKeyForIncoming(incoming),\n externalUserName: incoming.senderName || null,\n });\n return {\n handled: true,\n responseText: `Linked successfully. Future ${incoming.platform} messages will use ${owner}'s personal dispatch context.`,\n };\n } catch (error) {\n return {\n handled: true,\n responseText:\n error instanceof Error ? error.message : \"Failed to link this account.\",\n };\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-gateway.d.ts","sourceRoot":"","sources":["../../../src/server/lib/mcp-gateway.ts"],"names":[],"mappings":"AAoBA,OAAO,EAGL,KAAK,4BAA4B,EAClC,MAAM,uBAAuB,CAAC;AAU/B,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB;AA2LD,wBAAsB,mBAAmB,IAAI,OAAO,CAAC;IACnD,QAAQ,EAAE,4BAA4B,CAAC;IACvC,IAAI,EAAE,wBAAwB,EAAE,CAAC;CAClC,CAAC,CAcD;AAED,wBAAsB,0BAA0B,IAAI,OAAO,CACzD,wBAAwB,EAAE,CAC3B,CAGA;AAED,wBAAsB,gCAAgC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAG1E;AAED,wBAAsB,4BAA4B,CAChD,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,wBAAwB,CAAC,CAwBnC;AAED,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAsB9D;AAED,wBAAsB,yBAAyB,CAAC,KAAK,EAAE;IACrD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IACnD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B,GAAG,OAAO,CAAC;IACV,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC,CAkDD;AA+KD,wBAAsB,oCAAoC,CAAC,KAAK,EAAE;IAChE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B,GAAG,OAAO,CAAC;IACV,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC,CAmED"}
1
+ {"version":3,"file":"mcp-gateway.d.ts","sourceRoot":"","sources":["../../../src/server/lib/mcp-gateway.ts"],"names":[],"mappings":"AAoBA,OAAO,EAGL,KAAK,4BAA4B,EAClC,MAAM,uBAAuB,CAAC;AAU/B,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB;AAqLD,wBAAsB,mBAAmB,IAAI,OAAO,CAAC;IACnD,QAAQ,EAAE,4BAA4B,CAAC;IACvC,IAAI,EAAE,wBAAwB,EAAE,CAAC;CAClC,CAAC,CAcD;AAED,wBAAsB,0BAA0B,IAAI,OAAO,CACzD,wBAAwB,EAAE,CAC3B,CAGA;AAED,wBAAsB,gCAAgC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAG1E;AAED,wBAAsB,4BAA4B,CAChD,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,wBAAwB,CAAC,CAwBnC;AAED,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAsB9D;AAED,wBAAsB,yBAAyB,CAAC,KAAK,EAAE;IACrD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IACnD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B,GAAG,OAAO,CAAC;IACV,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC,CAkDD;AA+KD,wBAAsB,oCAAoC,CAAC,KAAK,EAAE;IAChE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B,GAAG,OAAO,CAAC;IACV,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC,CAmED"}
@@ -124,12 +124,6 @@ function safeAppOrigin(app) {
124
124
  return null;
125
125
  }
126
126
  }
127
- function appOrigin(app) {
128
- const origin = safeAppOrigin(app);
129
- if (!origin)
130
- throw new Error(`Invalid app URL for "${app.id}": ${app.url}`);
131
- return origin;
132
- }
133
127
  function appBaseUrl(app) {
134
128
  return app.url.replace(/\/+$/, "");
135
129
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-gateway.js","sourceRoot":"","sources":["../../../src/server/lib/mcp-gateway.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EACL,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,wBAAwB,EACxB,iBAAiB,GAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,cAAc,GAEf,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,eAAe,EACf,mBAAmB,GACpB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,EACL,+BAA+B,EAC/B,uBAAuB,GAExB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,eAAe,GAAG,UAAU,CAAC;AACnC,MAAM,aAAa,GAAG,uBAAuB,CAAC;AAC9C,MAAM,oBAAoB,GACxB,kGAAkG,CAAC;AACrG,MAAM,cAAc,GAAG,SAAS,CAAC;AACjC,MAAM,6BAA6B,GAAG,CAAC,CAAC;AACxC,MAAM,kCAAkC,GAAG,GAAG,CAAC;AAW/C,SAAS,cAAc,CAAC,KAAa;IACnC,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AACpC,CAAC;AAED,SAAS,gBAAgB,CAAC,GAA8B;IACtD,MAAM,KAAK,GAAG,GAAG,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3B,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QACvE,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAyB;IAClD,MAAM,OAAO,GAAG,KAAK,EAAE,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,GAAG;QAAE,OAAO,EAAE,CAAC;IAC3C,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACnE,OAAO,UAAU,CAAC,CAAC,CAAC,IAAI,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5C,CAAC;AAED,SAAS,sBAAsB,CAAC,OAAe;IAC7C,MAAM,QAAQ,GAAG,iBAAiB,CAChC,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,CAC5D,CAAC;IACF,IAAI,CAAC,QAAQ;QAAE,OAAO,OAAO,CAAC;IAC9B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;QAC7B,MAAM,IAAI,GAAG,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7C,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC;YACzD,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,GAAG,CAAC,QAAQ,GAAG,IAAI,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,QAAQ,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,GAAG,CAAC;QAC5E,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB;IAC1B,MAAM,aAAa,GAAG,gBAAgB,CAAC,iBAAiB,EAAE,EAAE,aAAa,CAAC,CAAC;IAC3E,IAAI,aAAa;QAAE,OAAO,sBAAsB,CAAC,aAAa,CAAC,CAAC;IAEhE,MAAM,UAAU,GACd,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;QACnD,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;QACrC,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;QACjC,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;QACxC,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAChD,IAAI,UAAU;QAAE,OAAO,sBAAsB,CAAC,UAAU,CAAC,CAAC;IAE1D,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY;QAC1C,CAAC,CAAC,mCAAmC;QACrC,CAAC,CAAC,uBAAuB,CAAC;AAC9B,CAAC;AAED,SAAS,eAAe,CACtB,QAAsC;IAEtC,OAAO;QACL,EAAE,EAAE,eAAe;QACnB,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,oBAAoB;QACjC,GAAG,EAAE,mBAAmB,EAAE;QAC1B,KAAK,EAAE,cAAc;QACrB,OAAO,EAAE,uBAAuB,CAAC,eAAe,EAAE,QAAQ,CAAC;KAC5D,CAAC;AACJ,CAAC;AAED,MAAM,aAAa,GAAG,IAAI,MAAM,CAAC,0BAA0B,CAAC,CAAC;AAE7D,SAAS,WAAW,CAAC,GAAY;IAC/B,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE;QAAE,OAAO,IAAI,CAAC;IACxD,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACzB,IAAI,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3C,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACxC,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACnE,IAAI,wBAAwB,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACtD,IAAI,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3C,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC;IACnD,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,EAAE,6BAA6B,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IAC7C,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,kBAAkB,CACzB,IAAY,EACZ,MAA6D;IAE7D,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,6BAA6B,CAAC,CAAC;IACzD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;AACnD,CAAC;AAED,SAAS,aAAa,CAAC,GAA6B;IAClD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,OAAO,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ;YAC1D,CAAC,CAAC,GAAG,CAAC,MAAM;YACZ,CAAC,CAAC,IAAI,CAAC;IACX,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,GAA6B;IAC9C,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;IAC5E,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,UAAU,CAAC,GAA6B;IAC/C,OAAO,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,WAAW,CAAC,GAA6B;IAChD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACvE,OAAO,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC1C,CAAC;AAED,SAAS,iBAAiB,CAAC,GAA6B,EAAE,GAAQ;IAChE,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IACnD,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,QAAQ,GAAG,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,kBAAkB,CAAC,GAA6B;IACvD,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;AACjC,CAAC;AAED,SAAS,eAAe,CAAC,GAA6B,EAAE,GAAQ;IAC9D,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,QAAQ;QACnB,CAAC,CAAC,GAAG,CAAC,QAAQ,KAAK,QAAQ;YACzB,CAAC,CAAC,GAAG;YACL,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;QACvC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC;IACjB,OAAO,GAAG,IAAI,IAAI,GAAG,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;AAClD,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAmB;IAChD,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IACxB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IAC/C,OAAO,CACL,KAAK,KAAK,aAAa;QACvB,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC;QAChC,KAAK,KAAK,QAAQ;QAClB,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAC5B,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,GAA6B,EAAE,IAAY;IACvE,IAAI,GAAG,CAAC,EAAE,KAAK,eAAe,IAAI,qBAAqB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,KAAK,CACb,SAAS,IAAI,oFAAoF,CAClG,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CACtB,KAAsB,EACtB,QAAsC;IAEtC,OAAO;QACL,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,OAAO,EAAE,uBAAuB,CAAC,KAAK,CAAC,EAAE,EAAE,QAAQ,CAAC;KACrD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB;IAIvC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC3C,+BAA+B,EAAE;QACjC,cAAc,CAAC,UAAU,CAAC;KAC3B,CAAC,CAAC;IACH,OAAO;QACL,QAAQ;QACR,IAAI,EAAE;YACJ,eAAe,CAAC,QAAQ,CAAC;YACzB,GAAG,MAAM;iBACN,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,eAAe,CAAC;iBAC/D,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;SACpD;KACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,0BAA0B;IAG9C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,mBAAmB,EAAE,CAAC;IAC7C,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,IAAI,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gCAAgC;IACpD,MAAM,IAAI,GAAG,MAAM,0BAA0B,EAAE,CAAC;IAChD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,GAAW;IAEX,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAChD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,mBAAmB,EAAE,CAAC;IAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CACrB,CAAC,SAAS,EAAE,EAAE,CACZ,SAAS,CAAC,EAAE,KAAK,MAAM,IAAI,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,MAAM,CACrE,CAAC;IACF,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,gBAAgB,GAAG,+DAA+D,CACnF,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CACb,2BAA2B,KAAK,CAAC,EAAE,oEAAoE,CACxG,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,qBAAqB,KAAK,CAAC,EAAE,wDAAwD,CACtF,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,GAAW,EACX,OAAe;IAEf,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IACtC,IAAI,CAAC,cAAc;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,MAAM,4BAA4B,CAAC,GAAG,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,mBAAmB,EAAE,CAAC;IACxC,IAAI,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAEzD,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,GAAG,KAAK;QAClC,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC;YAChB,YAAY,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;YACrC,eAAe,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;SACzC,CAAC;QACJ,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAEjB,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,GAAG,EAAE,cAAc,EAAE;QAC3D,SAAS;QACT,SAAS,EAAE,SAAS,IAAI,SAAS;QACjC,SAAS,EAAE,SAAS,IAAI,SAAS;QACjC,SAAS,EAAE,CAAC,GAAG,MAAM;KACtB,CAAC,CAAC;IACH,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AACxD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,KAO/C;IAWC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACtC,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC;IACxC,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,YAAY,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACtE,MAAM,MAAM,GAAG,MAAM,4BAA4B,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7D,IAAI,IAAI;QAAE,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,IAAI;QACjB,CAAC,CAAC,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC;QACxC,CAAC,CAAC,aAAa,CAAC;YACZ,GAAG,EAAE,MAAM,CAAC,EAAE;YACd,IAAI;YACJ,MAAM,EAAE,KAAK,CAAC,MAAM;SACrB,CAAC,CAAC;IACP,MAAM,GAAG,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC;IAC7C,IAAI,YAAY,GAEL,IAAI,CAAC;IAChB,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,IAAI,CAAC;YACH,YAAY,GAAG,MAAM,oCAAoC,CAAC;gBACxD,GAAG,EAAE,MAAM,CAAC,EAAE;gBACd,GAAG;gBACH,MAAM,EAAE,KAAK,CAAC,MAAM;aACrB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CACV,uDAAuD,MAAM,CAAC,EAAE,GAAG,EACnE,KAAK,CACN,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO;QACL,GAAG,EAAE,MAAM,CAAC,EAAE;QACd,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzB,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzB,GAAG;QACH,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChD,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,GAAG,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,YAAY,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3E,GAAG,CAAC,YAAY,EAAE,UAAU;YAC1B,CAAC,CAAC,EAAE,eAAe,EAAE,YAAY,CAAC,UAAU,EAAE;YAC9C,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,OAAO,YAAY,EAAE,SAAS,KAAK,QAAQ;YAC7C,CAAC,CAAC,EAAE,cAAc,EAAE,YAAY,CAAC,SAAS,EAAE;YAC5C,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAAC,MAAe;IAC7C,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QACzC,MAAM,UAAU,GAAI,MAAc,CAAC,iBAAiB,CAAC;QACrD,IAAI,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ;YAAE,OAAO,UAAU,CAAC;QACpE,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAE,MAAc,CAAC,OAAO,CAAC;YAClD,CAAC,CAAG,MAAc,CAAC,OAA0C;YAC7D,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CACrB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CACjE,EAAE,IAAI,CAAC;QACR,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YAC5C,IAAK,MAAc,CAAC,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;gBAAE,OAAO,MAAM,CAAC;QAC1D,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,yBAAyB,CAAC,KAAc;IAC/C,MAAM,OAAO,GACX,KAAK,YAAY,KAAK;QACpB,CAAC,CAAC,KAAK,CAAC,OAAO;QACf,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ;YACzB,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IAC5B,IACE,mEAAmE,CAAC,IAAI,CACtE,OAAO,CACR,EACD,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,2HAA2H,CAAC,IAAI,CACrI,OAAO,CACR,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAe;IAC1C,MAAM,IAAI,GACR,kCAAkC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7E,OAAO,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC;AAChD,CAAC;AAED,KAAK,UAAU,4BAA4B,CAAC,KAK3C;IACC,MAAM,QAAQ,GAAG,QAAQ,CAAC;IAC1B,KAAK,IAAI,OAAO,GAAG,CAAC,GAAI,OAAO,IAAI,CAAC,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC;YACnC,OAAO,EAAE;gBACP,CAAC,QAAQ,CAAC,EAAE;oBACV,IAAI,EAAE,MAAM;oBACZ,GAAG,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,oBAAoB;oBACjD,OAAO,EAAE;wBACP,aAAa,EAAE,UAAU,KAAK,CAAC,KAAK,EAAE;qBACvC;iBACF;aACF;SACF,CAAC,CAAC;QACH,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;YACtB,OAAO,MAAM,OAAO,CAAC,QAAQ,CAC3B,gBAAgB,CAAC,QAAQ,EAAE,sBAAsB,CAAC,EAClD;gBACE,GAAG,EAAE,KAAK,CAAC,GAAG;gBACd,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,MAAM;aAC/B,CACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IACE,OAAO,IAAI,6BAA6B;gBACxC,CAAC,yBAAyB,CAAC,KAAK,CAAC,EACjC,CAAC;gBACD,MAAM,KAAK,CAAC;YACd,CAAC;YACD,MAAM,KAAK,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC;QAC5C,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,SAAS,EAAE,EAAE;gBACvC,OAAO,CAAC,IAAI,CAAC,8CAA8C,EAAE,SAAS,CAAC,CAAC;YAC1E,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,0BAA0B,CAAC,KAIzC;IACC,MAAM,WAAW,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE;QACnC,CAAC,CAAC,MAAM,4BAA4B,CAAC,KAAK,CAAC,GAAG,CAAC;QAC/C,CAAC,CAAC,IAAI,CAAC;IACT,IAAI,WAAW,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QACrE,oBAAoB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACxC,OAAO;YACL,GAAG,EAAE,WAAW;YAChB,IAAI;YACJ,GAAG,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,IAAI,EAAE;SACzC,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IAED,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;QAC7D,CAAC;QACD,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAC5D,OAAO;YACL,GAAG,EAAE,WAAW;YAChB,IAAI;YACJ,GAAG,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,IAAI,EAAE;SACzC,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,0BAA0B,EAAE,CAAC;IAC9E,MAAM,MAAM,GAAG,IAAI;SAChB,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;SAC/C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACpE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,2DAA2D,CAC5D,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,WAAW,CAAC,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1D,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAC1D,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACnC,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC;AACpE,CAAC;AAED,KAAK,UAAU,8BAA8B,CAAC,KAM7C;IAMC,MAAM,MAAM,GAAG,MAAM,wBAAwB,CAAC;QAC5C,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,UAAU,EAAE,KAAK,CAAC,IAAI;QACtB,KAAK,EAAE,KAAK,CAAC,MAAM,IAAI,IAAI;KAC5B,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACrD,OAAO;QACL,QAAQ,EAAE,IAAI,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE;QACtD,UAAU,EAAE,KAAK,CAAC,IAAI;QACtB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,GAAG,EAAE,eAAe;KACrB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oCAAoC,CAAC,KAK1D;IAMC,MAAM,SAAS,GAAG,mBAAmB,EAAE,CAAC;IACxC,IAAI,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,MAAM,0BAA0B,CAAC,KAAK,CAAC,CAAC;IAEvD,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,eAAe,EAAE,CAAC;QACtC,OAAO,8BAA8B,CAAC;YACpC,UAAU,EAAE,SAAS;YACrB,KAAK;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC;YAC/B,MAAM,EAAE,KAAK,CAAC,MAAM;SACrB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,GAAG,KAAK;QAClC,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC;YAChB,YAAY,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;YACrC,eAAe,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;SACzC,CAAC;QACJ,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACjB,MAAM,eAAe,GACnB,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/D,MAAM,eAAe,GACnB,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/D,MAAM,aAAa,GAAG,eAAe,IAAI,eAAe,CAAC;IACzD,MAAM,eAAe,GAAG,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACvE,MAAM,KAAK,GAAG,MAAM,YAAY,CAC9B,SAAS,EACT,eAAe,EACf,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,EAC5C;QACE,SAAS,EAAE,IAAI;QACf,oEAAoE;QACpE,uEAAuE;QACvE,wEAAwE;QACxE,kBAAkB,EAAE,CAAC,aAAa;KACnC,CACF,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,4BAA4B,CAAC;QAChD,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,KAAK;QACL,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,sBAAsB,CAAC,MAAM,CAI3C,CAAC;IACF,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IACD,MAAM,MAAM,GAKR;QACF,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE;KACnB,CAAC;IACF,IAAI,MAAM,CAAC,UAAU;QAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IAC7D,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ;QAAE,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;IAC9E,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import { callAgent, signA2AToken } from \"@agent-native/core/a2a\";\nimport {\n buildMcpToolName,\n McpClientManager,\n} from \"@agent-native/core/mcp-client\";\nimport {\n buildDeepLink,\n buildEmbedStartPath,\n createEmbedSessionTicket,\n getRequestContext,\n} from \"@agent-native/core/server\";\nimport {\n discoverAgents,\n type DiscoveredAgent,\n} from \"@agent-native/core/server/agent-discovery\";\nimport {\n getRequestOrgId,\n getRequestUserEmail,\n} from \"@agent-native/core/server\";\nimport { getOrgA2ASecret, getOrgDomain } from \"@agent-native/core/org\";\nimport {\n getDispatchMcpAppAccessSettings,\n isAppAllowedByMcpAccess,\n type DispatchMcpAppAccessSettings,\n} from \"./mcp-access-store.js\";\n\nconst DISPATCH_APP_ID = \"dispatch\";\nconst DISPATCH_NAME = \"Agent-Native Dispatch\";\nconst DISPATCH_DESCRIPTION =\n \"Workspace control plane for extensions, agents, vault, integrations, approvals, and app routing.\";\nconst DISPATCH_COLOR = \"#14B8A6\";\nconst TARGET_EMBED_SESSION_ATTEMPTS = 3;\nconst TARGET_EMBED_SESSION_RETRY_BASE_MS = 250;\n\nexport interface DispatchMcpAccessibleApp {\n id: string;\n name: string;\n description: string;\n url: string;\n color: string;\n granted: boolean;\n}\n\nfunction normalizeAppId(value: string): string {\n return value.trim().toLowerCase();\n}\n\nfunction normalizeBaseUrl(raw: string | undefined | null): string | null {\n const value = raw?.trim();\n if (!value) return null;\n try {\n const url = new URL(value);\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") return null;\n return url.toString().replace(/\\/+$/, \"\");\n } catch {\n return null;\n }\n}\n\nfunction normalizeBasePath(value: string | undefined): string {\n const trimmed = value?.trim();\n if (!trimmed || trimmed === \"/\") return \"\";\n const normalized = trimmed.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n return normalized ? `/${normalized}` : \"\";\n}\n\nfunction withConfiguredBasePath(baseUrl: string): string {\n const basePath = normalizeBasePath(\n process.env.VITE_APP_BASE_PATH || process.env.APP_BASE_PATH,\n );\n if (!basePath) return baseUrl;\n try {\n const url = new URL(baseUrl);\n const path = normalizeBasePath(url.pathname);\n if (path === basePath || path.startsWith(`${basePath}/`)) {\n return baseUrl;\n }\n url.pathname = path && path !== \"/\" ? `${basePath}${path}` : `${basePath}/`;\n return url.toString().replace(/\\/+$/, \"\");\n } catch {\n return baseUrl;\n }\n}\n\nfunction dispatchSelfBaseUrl(): string {\n const requestOrigin = normalizeBaseUrl(getRequestContext()?.requestOrigin);\n if (requestOrigin) return withConfiguredBasePath(requestOrigin);\n\n const configured =\n normalizeBaseUrl(process.env.WORKSPACE_GATEWAY_URL) ??\n normalizeBaseUrl(process.env.APP_URL) ??\n normalizeBaseUrl(process.env.URL) ??\n normalizeBaseUrl(process.env.DEPLOY_URL) ??\n normalizeBaseUrl(process.env.BETTER_AUTH_URL);\n if (configured) return withConfiguredBasePath(configured);\n\n return process.env.NODE_ENV === \"production\"\n ? \"https://dispatch.agent-native.com\"\n : \"http://localhost:8092\";\n}\n\nfunction dispatchSelfApp(\n settings: DispatchMcpAppAccessSettings,\n): DispatchMcpAccessibleApp {\n return {\n id: DISPATCH_APP_ID,\n name: DISPATCH_NAME,\n description: DISPATCH_DESCRIPTION,\n url: dispatchSelfBaseUrl(),\n color: DISPATCH_COLOR,\n granted: isAppAllowedByMcpAccess(DISPATCH_APP_ID, settings),\n };\n}\n\nconst CONTROL_CHARS = new RegExp(\"[\\\\u0000-\\\\u001f\\\\u007f]\");\n\nfunction safeAppPath(raw: unknown): string | null {\n if (typeof raw !== \"string\" || !raw.trim()) return null;\n const value = raw.trim();\n if (CONTROL_CHARS.test(value)) return null;\n if (!value.startsWith(\"/\")) return null;\n if (value.startsWith(\"//\") || value.startsWith(\"/\\\\\")) return null;\n if (/^\\/[a-z][a-z0-9+.-]*:/i.test(value)) return null;\n if (/%(?:2f|5c)/i.test(value)) return null;\n const rawPath = value.split(/[?#]/, 1)[0] ?? value;\n let parsed: URL;\n try {\n parsed = new URL(value, \"http://agent-native.invalid\");\n } catch {\n return null;\n }\n if (parsed.pathname !== rawPath) return null;\n return value;\n}\n\nfunction appendParamsToPath(\n path: string,\n params: Record<string, string | number | boolean> | undefined,\n): string {\n if (!params || Object.keys(params).length === 0) return path;\n const url = new URL(path, \"http://agent-native.invalid\");\n for (const [key, value] of Object.entries(params)) {\n url.searchParams.set(key, String(value));\n }\n return `${url.pathname}${url.search}${url.hash}`;\n}\n\nfunction safeAppOrigin(app: DispatchMcpAccessibleApp): string | null {\n try {\n const url = new URL(app.url);\n return url.protocol === \"http:\" || url.protocol === \"https:\"\n ? url.origin\n : null;\n } catch {\n return null;\n }\n}\n\nfunction appOrigin(app: DispatchMcpAccessibleApp): string {\n const origin = safeAppOrigin(app);\n if (!origin) throw new Error(`Invalid app URL for \"${app.id}\": ${app.url}`);\n return origin;\n}\n\nfunction appBaseUrl(app: DispatchMcpAccessibleApp): string {\n return app.url.replace(/\\/+$/, \"\");\n}\n\nfunction appBasePath(app: DispatchMcpAccessibleApp): string {\n const pathname = new URL(appBaseUrl(app)).pathname.replace(/\\/+$/, \"\");\n return pathname === \"/\" ? \"\" : pathname;\n}\n\nfunction appMatchesUrlPath(app: DispatchMcpAccessibleApp, url: URL): boolean {\n const origin = safeAppOrigin(app);\n if (!origin || url.origin !== origin) return false;\n const basePath = appBasePath(app);\n if (!basePath) return true;\n return url.pathname === basePath || url.pathname.startsWith(`${basePath}/`);\n}\n\nfunction appPathSpecificity(app: DispatchMcpAccessibleApp): number {\n return appBasePath(app).length;\n}\n\nfunction appRelativePath(app: DispatchMcpAccessibleApp, url: URL): string {\n const basePath = appBasePath(app);\n const path = basePath\n ? url.pathname === basePath\n ? \"/\"\n : url.pathname.slice(basePath.length)\n : url.pathname;\n return `${path || \"/\"}${url.search}${url.hash}`;\n}\n\nfunction isDispatchControlPath(path: string | null): boolean {\n if (!path) return false;\n const route = path.split(/[?#]/, 1)[0] ?? path;\n return (\n route === \"/extensions\" ||\n route.startsWith(\"/extensions/\") ||\n route === \"/tools\" ||\n route.startsWith(\"/tools/\")\n );\n}\n\nfunction assertAppCanOpenPath(app: DispatchMcpAccessibleApp, path: string) {\n if (app.id !== DISPATCH_APP_ID && isDispatchControlPath(path)) {\n throw new Error(\n `Path \"${path}\" belongs to Dispatch. Use app: \"dispatch\" for Dispatch extension and tool routes.`,\n );\n }\n}\n\nfunction toAccessibleApp(\n agent: DiscoveredAgent,\n settings: DispatchMcpAppAccessSettings,\n): DispatchMcpAccessibleApp {\n return {\n id: agent.id,\n name: agent.name,\n description: agent.description,\n url: agent.url,\n color: agent.color,\n granted: isAppAllowedByMcpAccess(agent.id, settings),\n };\n}\n\nexport async function listDispatchMcpApps(): Promise<{\n settings: DispatchMcpAppAccessSettings;\n apps: DispatchMcpAccessibleApp[];\n}> {\n const [settings, agents] = await Promise.all([\n getDispatchMcpAppAccessSettings(),\n discoverAgents(\"dispatch\"),\n ]);\n return {\n settings,\n apps: [\n dispatchSelfApp(settings),\n ...agents\n .filter((agent) => normalizeAppId(agent.id) !== DISPATCH_APP_ID)\n .map((agent) => toAccessibleApp(agent, settings)),\n ],\n };\n}\n\nexport async function listGrantedDispatchMcpApps(): Promise<\n DispatchMcpAccessibleApp[]\n> {\n const { apps } = await listDispatchMcpApps();\n return apps.filter((app) => app.granted && safeAppOrigin(app));\n}\n\nexport async function listGrantedDispatchMcpAppOrigins(): Promise<string[]> {\n const apps = await listGrantedDispatchMcpApps();\n return Array.from(new Set(apps.flatMap((app) => safeAppOrigin(app) ?? [])));\n}\n\nexport async function resolveGrantedDispatchMcpApp(\n app: string,\n): Promise<DispatchMcpAccessibleApp> {\n const target = normalizeAppId(app);\n if (!target) throw new Error(\"app is required\");\n const { apps } = await listDispatchMcpApps();\n const match = apps.find(\n (candidate) =>\n candidate.id === target || candidate.name.toLowerCase() === target,\n );\n if (!match) {\n throw new Error(\n `Unknown app \"${app}\". Call list_apps to see apps available through Dispatch MCP.`,\n );\n }\n if (!match.granted) {\n throw new Error(\n `Dispatch MCP access to \"${match.id}\" is not granted. Open Dispatch > Agents to change MCP app access.`,\n );\n }\n if (!safeAppOrigin(match)) {\n throw new Error(\n `Dispatch MCP app \"${match.id}\" has an invalid URL and cannot be opened through MCP.`,\n );\n }\n return match;\n}\n\nexport async function askGrantedDispatchMcpApp(\n app: string,\n message: string,\n): Promise<{ app: string; routedVia: \"a2a\"; response: string }> {\n const trimmedMessage = message.trim();\n if (!trimmedMessage) throw new Error(\"message is required\");\n const target = await resolveGrantedDispatchMcpApp(app);\n const userEmail = getRequestUserEmail();\n if (!userEmail) throw new Error(\"no authenticated user\");\n\n const orgId = getRequestOrgId();\n const [orgDomain, orgSecret] = orgId\n ? await Promise.all([\n getOrgDomain(orgId).catch(() => null),\n getOrgA2ASecret(orgId).catch(() => null),\n ])\n : [null, null];\n\n const response = await callAgent(target.url, trimmedMessage, {\n userEmail,\n orgDomain: orgDomain ?? undefined,\n orgSecret: orgSecret ?? undefined,\n timeoutMs: 5 * 60_000,\n });\n return { app: target.id, routedVia: \"a2a\", response };\n}\n\nexport async function openGrantedDispatchMcpApp(input: {\n app: string;\n view?: string;\n path?: string;\n params?: Record<string, string | number | boolean>;\n embed?: boolean;\n chrome?: \"full\" | \"minimal\";\n}): Promise<{\n app: string;\n view?: string;\n path?: string;\n url: string;\n embed?: boolean;\n chrome?: \"full\" | \"minimal\";\n embedStartUrl?: string;\n embedTargetPath?: string;\n embedExpiresAt?: number;\n}> {\n const view = input.view?.trim() ?? \"\";\n const hasPathInput = input.path != null;\n const path = safeAppPath(input.path);\n if (hasPathInput && !path) {\n throw new Error(\"path must be a safe app-relative route\");\n }\n if (!view && !path) throw new Error(\"open_app requires view or path\");\n const target = await resolveGrantedDispatchMcpApp(input.app);\n if (path) assertAppCanOpenPath(target, path);\n const relUrl = path\n ? appendParamsToPath(path, input.params)\n : buildDeepLink({\n app: target.id,\n view,\n params: input.params,\n });\n const url = `${appBaseUrl(target)}${relUrl}`;\n let embedSession: Awaited<\n ReturnType<typeof createGrantedDispatchMcpEmbedSession>\n > | null = null;\n if (input.embed) {\n try {\n embedSession = await createGrantedDispatchMcpEmbedSession({\n app: target.id,\n url,\n chrome: input.chrome,\n });\n } catch (error) {\n console.warn(\n `[dispatch] Could not pre-mint MCP embed session for ${target.id}:`,\n error,\n );\n }\n }\n return {\n app: target.id,\n ...(view ? { view } : {}),\n ...(path ? { path } : {}),\n url,\n ...(input.embed === true ? { embed: true } : {}),\n ...(input.chrome ? { chrome: input.chrome } : {}),\n ...(embedSession?.startUrl ? { embedStartUrl: embedSession.startUrl } : {}),\n ...(embedSession?.targetPath\n ? { embedTargetPath: embedSession.targetPath }\n : {}),\n ...(typeof embedSession?.expiresAt === \"number\"\n ? { embedExpiresAt: embedSession.expiresAt }\n : {}),\n };\n}\n\nfunction parseMcpToolTextResult(result: unknown): Record<string, unknown> {\n if (result && typeof result === \"object\") {\n const structured = (result as any).structuredContent;\n if (structured && typeof structured === \"object\") return structured;\n const parts = Array.isArray((result as any).content)\n ? ((result as any).content as Array<Record<string, unknown>>)\n : [];\n const text = parts.find(\n (part) => part?.type === \"text\" && typeof part.text === \"string\",\n )?.text;\n if (typeof text === \"string\" && text.trim()) {\n if ((result as any).isError) throw new Error(text.trim());\n const parsed = JSON.parse(text);\n if (parsed && typeof parsed === \"object\") return parsed;\n }\n }\n throw new Error(\"Target app did not return an embed session.\");\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction isRetryableTargetMcpError(error: unknown): boolean {\n const message =\n error instanceof Error\n ? error.message\n : typeof error === \"string\"\n ? error\n : String(error ?? \"\");\n if (\n /rejected the request|unauthorized|forbidden|401|403|404|405|html/i.test(\n message,\n )\n ) {\n return false;\n }\n return /streamable http|handshake|failed to fetch|fetch failed|networkerror|econnrefused|enotfound|timed out|timeout|502|503|504/i.test(\n message,\n );\n}\n\nfunction targetMcpRetryDelay(attempt: number): number {\n const base =\n TARGET_EMBED_SESSION_RETRY_BASE_MS * Math.pow(2, Math.max(0, attempt - 1));\n return base + Math.floor(Math.random() * 100);\n}\n\nasync function callTargetCreateEmbedSession(input: {\n app: DispatchMcpAccessibleApp;\n token: string;\n url: string;\n chrome?: \"full\" | \"minimal\";\n}): Promise<unknown> {\n const serverId = \"target\";\n for (let attempt = 1; ; attempt += 1) {\n const manager = new McpClientManager({\n servers: {\n [serverId]: {\n type: \"http\",\n url: `${appBaseUrl(input.app)}/_agent-native/mcp`,\n headers: {\n Authorization: `Bearer ${input.token}`,\n },\n },\n },\n });\n try {\n await manager.start();\n return await manager.callTool(\n buildMcpToolName(serverId, \"create_embed_session\"),\n {\n url: input.url,\n chrome: input.chrome ?? \"full\",\n },\n );\n } catch (error) {\n if (\n attempt >= TARGET_EMBED_SESSION_ATTEMPTS ||\n !isRetryableTargetMcpError(error)\n ) {\n throw error;\n }\n await sleep(targetMcpRetryDelay(attempt));\n } finally {\n await manager.stop().catch((stopError) => {\n console.warn(\"[dispatch] Failed to stop target MCP client:\", stopError);\n });\n }\n }\n}\n\nasync function resolveDispatchEmbedTarget(input: {\n app?: string;\n url?: string;\n path?: string;\n}): Promise<{ app: DispatchMcpAccessibleApp; path: string; url: string }> {\n const explicitApp = input.app?.trim()\n ? await resolveGrantedDispatchMcpApp(input.app)\n : null;\n if (explicitApp && input.path) {\n const path = safeAppPath(input.path);\n if (!path) throw new Error(\"path must be a safe app-relative route\");\n assertAppCanOpenPath(explicitApp, path);\n return {\n app: explicitApp,\n path,\n url: `${appBaseUrl(explicitApp)}${path}`,\n };\n }\n\n if (!input.url) {\n throw new Error(\"create_embed_session requires a url or app + path.\");\n }\n\n let parsed: URL;\n try {\n parsed = new URL(input.url);\n } catch {\n if (!explicitApp) {\n throw new Error(\"Relative embed paths require an app id.\");\n }\n const path = safeAppPath(input.url);\n if (!path) throw new Error(\"url must be a safe app route.\");\n return {\n app: explicitApp,\n path,\n url: `${appBaseUrl(explicitApp)}${path}`,\n };\n }\n\n const apps = explicitApp ? [explicitApp] : await listGrantedDispatchMcpApps();\n const target = apps\n .filter((app) => appMatchesUrlPath(app, parsed))\n .sort((a, b) => appPathSpecificity(b) - appPathSpecificity(a))[0];\n if (!target) {\n throw new Error(\n \"Embed URL must belong to an app granted through Dispatch.\",\n );\n }\n const path = safeAppPath(appRelativePath(target, parsed));\n if (!path) throw new Error(\"Embed URL path is not safe.\");\n assertAppCanOpenPath(target, path);\n return { app: target, path, url: `${appBaseUrl(target)}${path}` };\n}\n\nasync function createDispatchSelfEmbedSession(input: {\n ownerEmail: string;\n orgId?: string;\n path: string;\n baseUrl: string;\n chrome?: \"full\" | \"minimal\";\n}): Promise<{\n startUrl: string;\n targetPath?: string;\n expiresAt?: number;\n app: string;\n}> {\n const ticket = await createEmbedSessionTicket({\n ownerEmail: input.ownerEmail,\n orgId: input.orgId,\n targetPath: input.path,\n scope: input.chrome ?? null,\n });\n const startPath = buildEmbedStartPath(ticket.ticket);\n return {\n startUrl: new URL(startPath, input.baseUrl).toString(),\n targetPath: input.path,\n expiresAt: ticket.expiresAt,\n app: DISPATCH_APP_ID,\n };\n}\n\nexport async function createGrantedDispatchMcpEmbedSession(input: {\n app?: string;\n url?: string;\n path?: string;\n chrome?: \"full\" | \"minimal\";\n}): Promise<{\n startUrl: string;\n targetPath?: string;\n expiresAt?: number;\n app: string;\n}> {\n const userEmail = getRequestUserEmail();\n if (!userEmail) throw new Error(\"no authenticated user\");\n const target = await resolveDispatchEmbedTarget(input);\n\n const orgId = getRequestOrgId();\n if (target.app.id === DISPATCH_APP_ID) {\n return createDispatchSelfEmbedSession({\n ownerEmail: userEmail,\n orgId,\n path: target.path,\n baseUrl: appBaseUrl(target.app),\n chrome: input.chrome,\n });\n }\n\n const [orgDomain, orgSecret] = orgId\n ? await Promise.all([\n getOrgDomain(orgId).catch(() => null),\n getOrgA2ASecret(orgId).catch(() => null),\n ])\n : [null, null];\n const usableOrgSecret =\n typeof orgSecret === \"string\" && orgSecret.trim().length > 0;\n const usableOrgDomain =\n typeof orgDomain === \"string\" && orgDomain.trim().length > 0;\n const useOrgSigning = usableOrgDomain && usableOrgSecret;\n const signedOrgDomain = usableOrgDomain ? orgDomain.trim() : undefined;\n const token = await signA2AToken(\n userEmail,\n signedOrgDomain,\n useOrgSigning ? orgSecret.trim() : undefined,\n {\n expiresIn: \"5m\",\n // Prefer the synced org A2A secret when present because first-party\n // production apps do not have to share the same deployment env secret.\n // Fall back to the global A2A_SECRET for orgs that have not synced yet.\n preferGlobalSecret: !useOrgSigning,\n },\n );\n\n const result = await callTargetCreateEmbedSession({\n app: target.app,\n token,\n url: target.url,\n chrome: input.chrome,\n });\n const parsed = parseMcpToolTextResult(result) as {\n startUrl?: string;\n targetPath?: string;\n expiresAt?: number;\n };\n if (!parsed.startUrl) {\n throw new Error(\"Target app did not return an embed start URL.\");\n }\n const output: {\n startUrl: string;\n targetPath?: string;\n expiresAt?: number;\n app: string;\n } = {\n startUrl: parsed.startUrl,\n app: target.app.id,\n };\n if (parsed.targetPath) output.targetPath = parsed.targetPath;\n if (typeof parsed.expiresAt === \"number\") output.expiresAt = parsed.expiresAt;\n return output;\n}\n"]}
1
+ {"version":3,"file":"mcp-gateway.js","sourceRoot":"","sources":["../../../src/server/lib/mcp-gateway.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EACL,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,wBAAwB,EACxB,iBAAiB,GAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,cAAc,GAEf,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,eAAe,EACf,mBAAmB,GACpB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,EACL,+BAA+B,EAC/B,uBAAuB,GAExB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,eAAe,GAAG,UAAU,CAAC;AACnC,MAAM,aAAa,GAAG,uBAAuB,CAAC;AAC9C,MAAM,oBAAoB,GACxB,kGAAkG,CAAC;AACrG,MAAM,cAAc,GAAG,SAAS,CAAC;AACjC,MAAM,6BAA6B,GAAG,CAAC,CAAC;AACxC,MAAM,kCAAkC,GAAG,GAAG,CAAC;AAW/C,SAAS,cAAc,CAAC,KAAa;IACnC,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AACpC,CAAC;AAED,SAAS,gBAAgB,CAAC,GAA8B;IACtD,MAAM,KAAK,GAAG,GAAG,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3B,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QACvE,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAyB;IAClD,MAAM,OAAO,GAAG,KAAK,EAAE,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,GAAG;QAAE,OAAO,EAAE,CAAC;IAC3C,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACnE,OAAO,UAAU,CAAC,CAAC,CAAC,IAAI,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5C,CAAC;AAED,SAAS,sBAAsB,CAAC,OAAe;IAC7C,MAAM,QAAQ,GAAG,iBAAiB,CAChC,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,CAC5D,CAAC;IACF,IAAI,CAAC,QAAQ;QAAE,OAAO,OAAO,CAAC;IAC9B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;QAC7B,MAAM,IAAI,GAAG,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7C,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC;YACzD,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,GAAG,CAAC,QAAQ,GAAG,IAAI,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,QAAQ,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,GAAG,CAAC;QAC5E,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB;IAC1B,MAAM,aAAa,GAAG,gBAAgB,CAAC,iBAAiB,EAAE,EAAE,aAAa,CAAC,CAAC;IAC3E,IAAI,aAAa;QAAE,OAAO,sBAAsB,CAAC,aAAa,CAAC,CAAC;IAEhE,MAAM,UAAU,GACd,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;QACnD,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;QACrC,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;QACjC,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;QACxC,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAChD,IAAI,UAAU;QAAE,OAAO,sBAAsB,CAAC,UAAU,CAAC,CAAC;IAE1D,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY;QAC1C,CAAC,CAAC,mCAAmC;QACrC,CAAC,CAAC,uBAAuB,CAAC;AAC9B,CAAC;AAED,SAAS,eAAe,CACtB,QAAsC;IAEtC,OAAO;QACL,EAAE,EAAE,eAAe;QACnB,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,oBAAoB;QACjC,GAAG,EAAE,mBAAmB,EAAE;QAC1B,KAAK,EAAE,cAAc;QACrB,OAAO,EAAE,uBAAuB,CAAC,eAAe,EAAE,QAAQ,CAAC;KAC5D,CAAC;AACJ,CAAC;AAED,MAAM,aAAa,GAAG,IAAI,MAAM,CAAC,0BAA0B,CAAC,CAAC;AAE7D,SAAS,WAAW,CAAC,GAAY;IAC/B,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE;QAAE,OAAO,IAAI,CAAC;IACxD,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACzB,IAAI,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3C,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACxC,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACnE,IAAI,wBAAwB,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACtD,IAAI,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3C,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC;IACnD,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,EAAE,6BAA6B,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IAC7C,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,kBAAkB,CACzB,IAAY,EACZ,MAA6D;IAE7D,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,6BAA6B,CAAC,CAAC;IACzD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;AACnD,CAAC;AAED,SAAS,aAAa,CAAC,GAA6B;IAClD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,OAAO,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ;YAC1D,CAAC,CAAC,GAAG,CAAC,MAAM;YACZ,CAAC,CAAC,IAAI,CAAC;IACX,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,GAA6B;IAC/C,OAAO,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,WAAW,CAAC,GAA6B;IAChD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACvE,OAAO,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC1C,CAAC;AAED,SAAS,iBAAiB,CAAC,GAA6B,EAAE,GAAQ;IAChE,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IACnD,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,QAAQ,GAAG,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,kBAAkB,CAAC,GAA6B;IACvD,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;AACjC,CAAC;AAED,SAAS,eAAe,CAAC,GAA6B,EAAE,GAAQ;IAC9D,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,QAAQ;QACnB,CAAC,CAAC,GAAG,CAAC,QAAQ,KAAK,QAAQ;YACzB,CAAC,CAAC,GAAG;YACL,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;QACvC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC;IACjB,OAAO,GAAG,IAAI,IAAI,GAAG,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;AAClD,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAmB;IAChD,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IACxB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IAC/C,OAAO,CACL,KAAK,KAAK,aAAa;QACvB,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC;QAChC,KAAK,KAAK,QAAQ;QAClB,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAC5B,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,GAA6B,EAAE,IAAY;IACvE,IAAI,GAAG,CAAC,EAAE,KAAK,eAAe,IAAI,qBAAqB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,KAAK,CACb,SAAS,IAAI,oFAAoF,CAClG,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CACtB,KAAsB,EACtB,QAAsC;IAEtC,OAAO;QACL,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,OAAO,EAAE,uBAAuB,CAAC,KAAK,CAAC,EAAE,EAAE,QAAQ,CAAC;KACrD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB;IAIvC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC3C,+BAA+B,EAAE;QACjC,cAAc,CAAC,UAAU,CAAC;KAC3B,CAAC,CAAC;IACH,OAAO;QACL,QAAQ;QACR,IAAI,EAAE;YACJ,eAAe,CAAC,QAAQ,CAAC;YACzB,GAAG,MAAM;iBACN,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,eAAe,CAAC;iBAC/D,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;SACpD;KACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,0BAA0B;IAG9C,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,mBAAmB,EAAE,CAAC;IAC7C,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,IAAI,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gCAAgC;IACpD,MAAM,IAAI,GAAG,MAAM,0BAA0B,EAAE,CAAC;IAChD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,GAAW;IAEX,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAChD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,mBAAmB,EAAE,CAAC;IAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CACrB,CAAC,SAAS,EAAE,EAAE,CACZ,SAAS,CAAC,EAAE,KAAK,MAAM,IAAI,SAAS,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,MAAM,CACrE,CAAC;IACF,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,gBAAgB,GAAG,+DAA+D,CACnF,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CACb,2BAA2B,KAAK,CAAC,EAAE,oEAAoE,CACxG,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,qBAAqB,KAAK,CAAC,EAAE,wDAAwD,CACtF,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,GAAW,EACX,OAAe;IAEf,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IACtC,IAAI,CAAC,cAAc;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,MAAM,4BAA4B,CAAC,GAAG,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,mBAAmB,EAAE,CAAC;IACxC,IAAI,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAEzD,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,GAAG,KAAK;QAClC,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC;YAChB,YAAY,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;YACrC,eAAe,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;SACzC,CAAC;QACJ,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAEjB,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,GAAG,EAAE,cAAc,EAAE;QAC3D,SAAS;QACT,SAAS,EAAE,SAAS,IAAI,SAAS;QACjC,SAAS,EAAE,SAAS,IAAI,SAAS;QACjC,SAAS,EAAE,CAAC,GAAG,MAAM;KACtB,CAAC,CAAC;IACH,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AACxD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,KAO/C;IAWC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACtC,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC;IACxC,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,YAAY,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACtE,MAAM,MAAM,GAAG,MAAM,4BAA4B,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7D,IAAI,IAAI;QAAE,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,IAAI;QACjB,CAAC,CAAC,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC;QACxC,CAAC,CAAC,aAAa,CAAC;YACZ,GAAG,EAAE,MAAM,CAAC,EAAE;YACd,IAAI;YACJ,MAAM,EAAE,KAAK,CAAC,MAAM;SACrB,CAAC,CAAC;IACP,MAAM,GAAG,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC;IAC7C,IAAI,YAAY,GAEL,IAAI,CAAC;IAChB,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,IAAI,CAAC;YACH,YAAY,GAAG,MAAM,oCAAoC,CAAC;gBACxD,GAAG,EAAE,MAAM,CAAC,EAAE;gBACd,GAAG;gBACH,MAAM,EAAE,KAAK,CAAC,MAAM;aACrB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CACV,uDAAuD,MAAM,CAAC,EAAE,GAAG,EACnE,KAAK,CACN,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO;QACL,GAAG,EAAE,MAAM,CAAC,EAAE;QACd,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzB,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzB,GAAG;QACH,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChD,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,GAAG,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,YAAY,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3E,GAAG,CAAC,YAAY,EAAE,UAAU;YAC1B,CAAC,CAAC,EAAE,eAAe,EAAE,YAAY,CAAC,UAAU,EAAE;YAC9C,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,OAAO,YAAY,EAAE,SAAS,KAAK,QAAQ;YAC7C,CAAC,CAAC,EAAE,cAAc,EAAE,YAAY,CAAC,SAAS,EAAE;YAC5C,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAAC,MAAe;IAC7C,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QACzC,MAAM,UAAU,GAAI,MAAc,CAAC,iBAAiB,CAAC;QACrD,IAAI,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ;YAAE,OAAO,UAAU,CAAC;QACpE,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAE,MAAc,CAAC,OAAO,CAAC;YAClD,CAAC,CAAG,MAAc,CAAC,OAA0C;YAC7D,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CACrB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CACjE,EAAE,IAAI,CAAC;QACR,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YAC5C,IAAK,MAAc,CAAC,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;gBAAE,OAAO,MAAM,CAAC;QAC1D,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,yBAAyB,CAAC,KAAc;IAC/C,MAAM,OAAO,GACX,KAAK,YAAY,KAAK;QACpB,CAAC,CAAC,KAAK,CAAC,OAAO;QACf,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ;YACzB,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IAC5B,IACE,mEAAmE,CAAC,IAAI,CACtE,OAAO,CACR,EACD,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,2HAA2H,CAAC,IAAI,CACrI,OAAO,CACR,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAe;IAC1C,MAAM,IAAI,GACR,kCAAkC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7E,OAAO,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC;AAChD,CAAC;AAED,KAAK,UAAU,4BAA4B,CAAC,KAK3C;IACC,MAAM,QAAQ,GAAG,QAAQ,CAAC;IAC1B,KAAK,IAAI,OAAO,GAAG,CAAC,GAAI,OAAO,IAAI,CAAC,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC;YACnC,OAAO,EAAE;gBACP,CAAC,QAAQ,CAAC,EAAE;oBACV,IAAI,EAAE,MAAM;oBACZ,GAAG,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,oBAAoB;oBACjD,OAAO,EAAE;wBACP,aAAa,EAAE,UAAU,KAAK,CAAC,KAAK,EAAE;qBACvC;iBACF;aACF;SACF,CAAC,CAAC;QACH,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;YACtB,OAAO,MAAM,OAAO,CAAC,QAAQ,CAC3B,gBAAgB,CAAC,QAAQ,EAAE,sBAAsB,CAAC,EAClD;gBACE,GAAG,EAAE,KAAK,CAAC,GAAG;gBACd,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,MAAM;aAC/B,CACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IACE,OAAO,IAAI,6BAA6B;gBACxC,CAAC,yBAAyB,CAAC,KAAK,CAAC,EACjC,CAAC;gBACD,MAAM,KAAK,CAAC;YACd,CAAC;YACD,MAAM,KAAK,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC;QAC5C,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,SAAS,EAAE,EAAE;gBACvC,OAAO,CAAC,IAAI,CAAC,8CAA8C,EAAE,SAAS,CAAC,CAAC;YAC1E,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,0BAA0B,CAAC,KAIzC;IACC,MAAM,WAAW,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE;QACnC,CAAC,CAAC,MAAM,4BAA4B,CAAC,KAAK,CAAC,GAAG,CAAC;QAC/C,CAAC,CAAC,IAAI,CAAC;IACT,IAAI,WAAW,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QACrE,oBAAoB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACxC,OAAO;YACL,GAAG,EAAE,WAAW;YAChB,IAAI;YACJ,GAAG,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,IAAI,EAAE;SACzC,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IAED,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;QAC7D,CAAC;QACD,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAC5D,OAAO;YACL,GAAG,EAAE,WAAW;YAChB,IAAI;YACJ,GAAG,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,IAAI,EAAE;SACzC,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,0BAA0B,EAAE,CAAC;IAC9E,MAAM,MAAM,GAAG,IAAI;SAChB,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;SAC/C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACpE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,2DAA2D,CAC5D,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,WAAW,CAAC,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1D,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAC1D,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACnC,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC;AACpE,CAAC;AAED,KAAK,UAAU,8BAA8B,CAAC,KAM7C;IAMC,MAAM,MAAM,GAAG,MAAM,wBAAwB,CAAC;QAC5C,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,UAAU,EAAE,KAAK,CAAC,IAAI;QACtB,KAAK,EAAE,KAAK,CAAC,MAAM,IAAI,IAAI;KAC5B,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACrD,OAAO;QACL,QAAQ,EAAE,IAAI,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE;QACtD,UAAU,EAAE,KAAK,CAAC,IAAI;QACtB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,GAAG,EAAE,eAAe;KACrB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oCAAoC,CAAC,KAK1D;IAMC,MAAM,SAAS,GAAG,mBAAmB,EAAE,CAAC;IACxC,IAAI,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,MAAM,0BAA0B,CAAC,KAAK,CAAC,CAAC;IAEvD,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,eAAe,EAAE,CAAC;QACtC,OAAO,8BAA8B,CAAC;YACpC,UAAU,EAAE,SAAS;YACrB,KAAK;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC;YAC/B,MAAM,EAAE,KAAK,CAAC,MAAM;SACrB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,GAAG,KAAK;QAClC,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC;YAChB,YAAY,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;YACrC,eAAe,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;SACzC,CAAC;QACJ,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACjB,MAAM,eAAe,GACnB,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/D,MAAM,eAAe,GACnB,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/D,MAAM,aAAa,GAAG,eAAe,IAAI,eAAe,CAAC;IACzD,MAAM,eAAe,GAAG,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACvE,MAAM,KAAK,GAAG,MAAM,YAAY,CAC9B,SAAS,EACT,eAAe,EACf,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,EAC5C;QACE,SAAS,EAAE,IAAI;QACf,oEAAoE;QACpE,uEAAuE;QACvE,wEAAwE;QACxE,kBAAkB,EAAE,CAAC,aAAa;KACnC,CACF,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,4BAA4B,CAAC;QAChD,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,KAAK;QACL,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,sBAAsB,CAAC,MAAM,CAI3C,CAAC;IACF,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IACD,MAAM,MAAM,GAKR;QACF,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE;KACnB,CAAC;IACF,IAAI,MAAM,CAAC,UAAU;QAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IAC7D,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ;QAAE,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;IAC9E,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import { callAgent, signA2AToken } from \"@agent-native/core/a2a\";\nimport {\n buildMcpToolName,\n McpClientManager,\n} from \"@agent-native/core/mcp-client\";\nimport {\n buildDeepLink,\n buildEmbedStartPath,\n createEmbedSessionTicket,\n getRequestContext,\n} from \"@agent-native/core/server\";\nimport {\n discoverAgents,\n type DiscoveredAgent,\n} from \"@agent-native/core/server/agent-discovery\";\nimport {\n getRequestOrgId,\n getRequestUserEmail,\n} from \"@agent-native/core/server\";\nimport { getOrgA2ASecret, getOrgDomain } from \"@agent-native/core/org\";\nimport {\n getDispatchMcpAppAccessSettings,\n isAppAllowedByMcpAccess,\n type DispatchMcpAppAccessSettings,\n} from \"./mcp-access-store.js\";\n\nconst DISPATCH_APP_ID = \"dispatch\";\nconst DISPATCH_NAME = \"Agent-Native Dispatch\";\nconst DISPATCH_DESCRIPTION =\n \"Workspace control plane for extensions, agents, vault, integrations, approvals, and app routing.\";\nconst DISPATCH_COLOR = \"#14B8A6\";\nconst TARGET_EMBED_SESSION_ATTEMPTS = 3;\nconst TARGET_EMBED_SESSION_RETRY_BASE_MS = 250;\n\nexport interface DispatchMcpAccessibleApp {\n id: string;\n name: string;\n description: string;\n url: string;\n color: string;\n granted: boolean;\n}\n\nfunction normalizeAppId(value: string): string {\n return value.trim().toLowerCase();\n}\n\nfunction normalizeBaseUrl(raw: string | undefined | null): string | null {\n const value = raw?.trim();\n if (!value) return null;\n try {\n const url = new URL(value);\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") return null;\n return url.toString().replace(/\\/+$/, \"\");\n } catch {\n return null;\n }\n}\n\nfunction normalizeBasePath(value: string | undefined): string {\n const trimmed = value?.trim();\n if (!trimmed || trimmed === \"/\") return \"\";\n const normalized = trimmed.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n return normalized ? `/${normalized}` : \"\";\n}\n\nfunction withConfiguredBasePath(baseUrl: string): string {\n const basePath = normalizeBasePath(\n process.env.VITE_APP_BASE_PATH || process.env.APP_BASE_PATH,\n );\n if (!basePath) return baseUrl;\n try {\n const url = new URL(baseUrl);\n const path = normalizeBasePath(url.pathname);\n if (path === basePath || path.startsWith(`${basePath}/`)) {\n return baseUrl;\n }\n url.pathname = path && path !== \"/\" ? `${basePath}${path}` : `${basePath}/`;\n return url.toString().replace(/\\/+$/, \"\");\n } catch {\n return baseUrl;\n }\n}\n\nfunction dispatchSelfBaseUrl(): string {\n const requestOrigin = normalizeBaseUrl(getRequestContext()?.requestOrigin);\n if (requestOrigin) return withConfiguredBasePath(requestOrigin);\n\n const configured =\n normalizeBaseUrl(process.env.WORKSPACE_GATEWAY_URL) ??\n normalizeBaseUrl(process.env.APP_URL) ??\n normalizeBaseUrl(process.env.URL) ??\n normalizeBaseUrl(process.env.DEPLOY_URL) ??\n normalizeBaseUrl(process.env.BETTER_AUTH_URL);\n if (configured) return withConfiguredBasePath(configured);\n\n return process.env.NODE_ENV === \"production\"\n ? \"https://dispatch.agent-native.com\"\n : \"http://localhost:8092\";\n}\n\nfunction dispatchSelfApp(\n settings: DispatchMcpAppAccessSettings,\n): DispatchMcpAccessibleApp {\n return {\n id: DISPATCH_APP_ID,\n name: DISPATCH_NAME,\n description: DISPATCH_DESCRIPTION,\n url: dispatchSelfBaseUrl(),\n color: DISPATCH_COLOR,\n granted: isAppAllowedByMcpAccess(DISPATCH_APP_ID, settings),\n };\n}\n\nconst CONTROL_CHARS = new RegExp(\"[\\\\u0000-\\\\u001f\\\\u007f]\");\n\nfunction safeAppPath(raw: unknown): string | null {\n if (typeof raw !== \"string\" || !raw.trim()) return null;\n const value = raw.trim();\n if (CONTROL_CHARS.test(value)) return null;\n if (!value.startsWith(\"/\")) return null;\n if (value.startsWith(\"//\") || value.startsWith(\"/\\\\\")) return null;\n if (/^\\/[a-z][a-z0-9+.-]*:/i.test(value)) return null;\n if (/%(?:2f|5c)/i.test(value)) return null;\n const rawPath = value.split(/[?#]/, 1)[0] ?? value;\n let parsed: URL;\n try {\n parsed = new URL(value, \"http://agent-native.invalid\");\n } catch {\n return null;\n }\n if (parsed.pathname !== rawPath) return null;\n return value;\n}\n\nfunction appendParamsToPath(\n path: string,\n params: Record<string, string | number | boolean> | undefined,\n): string {\n if (!params || Object.keys(params).length === 0) return path;\n const url = new URL(path, \"http://agent-native.invalid\");\n for (const [key, value] of Object.entries(params)) {\n url.searchParams.set(key, String(value));\n }\n return `${url.pathname}${url.search}${url.hash}`;\n}\n\nfunction safeAppOrigin(app: DispatchMcpAccessibleApp): string | null {\n try {\n const url = new URL(app.url);\n return url.protocol === \"http:\" || url.protocol === \"https:\"\n ? url.origin\n : null;\n } catch {\n return null;\n }\n}\n\nfunction appBaseUrl(app: DispatchMcpAccessibleApp): string {\n return app.url.replace(/\\/+$/, \"\");\n}\n\nfunction appBasePath(app: DispatchMcpAccessibleApp): string {\n const pathname = new URL(appBaseUrl(app)).pathname.replace(/\\/+$/, \"\");\n return pathname === \"/\" ? \"\" : pathname;\n}\n\nfunction appMatchesUrlPath(app: DispatchMcpAccessibleApp, url: URL): boolean {\n const origin = safeAppOrigin(app);\n if (!origin || url.origin !== origin) return false;\n const basePath = appBasePath(app);\n if (!basePath) return true;\n return url.pathname === basePath || url.pathname.startsWith(`${basePath}/`);\n}\n\nfunction appPathSpecificity(app: DispatchMcpAccessibleApp): number {\n return appBasePath(app).length;\n}\n\nfunction appRelativePath(app: DispatchMcpAccessibleApp, url: URL): string {\n const basePath = appBasePath(app);\n const path = basePath\n ? url.pathname === basePath\n ? \"/\"\n : url.pathname.slice(basePath.length)\n : url.pathname;\n return `${path || \"/\"}${url.search}${url.hash}`;\n}\n\nfunction isDispatchControlPath(path: string | null): boolean {\n if (!path) return false;\n const route = path.split(/[?#]/, 1)[0] ?? path;\n return (\n route === \"/extensions\" ||\n route.startsWith(\"/extensions/\") ||\n route === \"/tools\" ||\n route.startsWith(\"/tools/\")\n );\n}\n\nfunction assertAppCanOpenPath(app: DispatchMcpAccessibleApp, path: string) {\n if (app.id !== DISPATCH_APP_ID && isDispatchControlPath(path)) {\n throw new Error(\n `Path \"${path}\" belongs to Dispatch. Use app: \"dispatch\" for Dispatch extension and tool routes.`,\n );\n }\n}\n\nfunction toAccessibleApp(\n agent: DiscoveredAgent,\n settings: DispatchMcpAppAccessSettings,\n): DispatchMcpAccessibleApp {\n return {\n id: agent.id,\n name: agent.name,\n description: agent.description,\n url: agent.url,\n color: agent.color,\n granted: isAppAllowedByMcpAccess(agent.id, settings),\n };\n}\n\nexport async function listDispatchMcpApps(): Promise<{\n settings: DispatchMcpAppAccessSettings;\n apps: DispatchMcpAccessibleApp[];\n}> {\n const [settings, agents] = await Promise.all([\n getDispatchMcpAppAccessSettings(),\n discoverAgents(\"dispatch\"),\n ]);\n return {\n settings,\n apps: [\n dispatchSelfApp(settings),\n ...agents\n .filter((agent) => normalizeAppId(agent.id) !== DISPATCH_APP_ID)\n .map((agent) => toAccessibleApp(agent, settings)),\n ],\n };\n}\n\nexport async function listGrantedDispatchMcpApps(): Promise<\n DispatchMcpAccessibleApp[]\n> {\n const { apps } = await listDispatchMcpApps();\n return apps.filter((app) => app.granted && safeAppOrigin(app));\n}\n\nexport async function listGrantedDispatchMcpAppOrigins(): Promise<string[]> {\n const apps = await listGrantedDispatchMcpApps();\n return Array.from(new Set(apps.flatMap((app) => safeAppOrigin(app) ?? [])));\n}\n\nexport async function resolveGrantedDispatchMcpApp(\n app: string,\n): Promise<DispatchMcpAccessibleApp> {\n const target = normalizeAppId(app);\n if (!target) throw new Error(\"app is required\");\n const { apps } = await listDispatchMcpApps();\n const match = apps.find(\n (candidate) =>\n candidate.id === target || candidate.name.toLowerCase() === target,\n );\n if (!match) {\n throw new Error(\n `Unknown app \"${app}\". Call list_apps to see apps available through Dispatch MCP.`,\n );\n }\n if (!match.granted) {\n throw new Error(\n `Dispatch MCP access to \"${match.id}\" is not granted. Open Dispatch > Agents to change MCP app access.`,\n );\n }\n if (!safeAppOrigin(match)) {\n throw new Error(\n `Dispatch MCP app \"${match.id}\" has an invalid URL and cannot be opened through MCP.`,\n );\n }\n return match;\n}\n\nexport async function askGrantedDispatchMcpApp(\n app: string,\n message: string,\n): Promise<{ app: string; routedVia: \"a2a\"; response: string }> {\n const trimmedMessage = message.trim();\n if (!trimmedMessage) throw new Error(\"message is required\");\n const target = await resolveGrantedDispatchMcpApp(app);\n const userEmail = getRequestUserEmail();\n if (!userEmail) throw new Error(\"no authenticated user\");\n\n const orgId = getRequestOrgId();\n const [orgDomain, orgSecret] = orgId\n ? await Promise.all([\n getOrgDomain(orgId).catch(() => null),\n getOrgA2ASecret(orgId).catch(() => null),\n ])\n : [null, null];\n\n const response = await callAgent(target.url, trimmedMessage, {\n userEmail,\n orgDomain: orgDomain ?? undefined,\n orgSecret: orgSecret ?? undefined,\n timeoutMs: 5 * 60_000,\n });\n return { app: target.id, routedVia: \"a2a\", response };\n}\n\nexport async function openGrantedDispatchMcpApp(input: {\n app: string;\n view?: string;\n path?: string;\n params?: Record<string, string | number | boolean>;\n embed?: boolean;\n chrome?: \"full\" | \"minimal\";\n}): Promise<{\n app: string;\n view?: string;\n path?: string;\n url: string;\n embed?: boolean;\n chrome?: \"full\" | \"minimal\";\n embedStartUrl?: string;\n embedTargetPath?: string;\n embedExpiresAt?: number;\n}> {\n const view = input.view?.trim() ?? \"\";\n const hasPathInput = input.path != null;\n const path = safeAppPath(input.path);\n if (hasPathInput && !path) {\n throw new Error(\"path must be a safe app-relative route\");\n }\n if (!view && !path) throw new Error(\"open_app requires view or path\");\n const target = await resolveGrantedDispatchMcpApp(input.app);\n if (path) assertAppCanOpenPath(target, path);\n const relUrl = path\n ? appendParamsToPath(path, input.params)\n : buildDeepLink({\n app: target.id,\n view,\n params: input.params,\n });\n const url = `${appBaseUrl(target)}${relUrl}`;\n let embedSession: Awaited<\n ReturnType<typeof createGrantedDispatchMcpEmbedSession>\n > | null = null;\n if (input.embed) {\n try {\n embedSession = await createGrantedDispatchMcpEmbedSession({\n app: target.id,\n url,\n chrome: input.chrome,\n });\n } catch (error) {\n console.warn(\n `[dispatch] Could not pre-mint MCP embed session for ${target.id}:`,\n error,\n );\n }\n }\n return {\n app: target.id,\n ...(view ? { view } : {}),\n ...(path ? { path } : {}),\n url,\n ...(input.embed === true ? { embed: true } : {}),\n ...(input.chrome ? { chrome: input.chrome } : {}),\n ...(embedSession?.startUrl ? { embedStartUrl: embedSession.startUrl } : {}),\n ...(embedSession?.targetPath\n ? { embedTargetPath: embedSession.targetPath }\n : {}),\n ...(typeof embedSession?.expiresAt === \"number\"\n ? { embedExpiresAt: embedSession.expiresAt }\n : {}),\n };\n}\n\nfunction parseMcpToolTextResult(result: unknown): Record<string, unknown> {\n if (result && typeof result === \"object\") {\n const structured = (result as any).structuredContent;\n if (structured && typeof structured === \"object\") return structured;\n const parts = Array.isArray((result as any).content)\n ? ((result as any).content as Array<Record<string, unknown>>)\n : [];\n const text = parts.find(\n (part) => part?.type === \"text\" && typeof part.text === \"string\",\n )?.text;\n if (typeof text === \"string\" && text.trim()) {\n if ((result as any).isError) throw new Error(text.trim());\n const parsed = JSON.parse(text);\n if (parsed && typeof parsed === \"object\") return parsed;\n }\n }\n throw new Error(\"Target app did not return an embed session.\");\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction isRetryableTargetMcpError(error: unknown): boolean {\n const message =\n error instanceof Error\n ? error.message\n : typeof error === \"string\"\n ? error\n : String(error ?? \"\");\n if (\n /rejected the request|unauthorized|forbidden|401|403|404|405|html/i.test(\n message,\n )\n ) {\n return false;\n }\n return /streamable http|handshake|failed to fetch|fetch failed|networkerror|econnrefused|enotfound|timed out|timeout|502|503|504/i.test(\n message,\n );\n}\n\nfunction targetMcpRetryDelay(attempt: number): number {\n const base =\n TARGET_EMBED_SESSION_RETRY_BASE_MS * Math.pow(2, Math.max(0, attempt - 1));\n return base + Math.floor(Math.random() * 100);\n}\n\nasync function callTargetCreateEmbedSession(input: {\n app: DispatchMcpAccessibleApp;\n token: string;\n url: string;\n chrome?: \"full\" | \"minimal\";\n}): Promise<unknown> {\n const serverId = \"target\";\n for (let attempt = 1; ; attempt += 1) {\n const manager = new McpClientManager({\n servers: {\n [serverId]: {\n type: \"http\",\n url: `${appBaseUrl(input.app)}/_agent-native/mcp`,\n headers: {\n Authorization: `Bearer ${input.token}`,\n },\n },\n },\n });\n try {\n await manager.start();\n return await manager.callTool(\n buildMcpToolName(serverId, \"create_embed_session\"),\n {\n url: input.url,\n chrome: input.chrome ?? \"full\",\n },\n );\n } catch (error) {\n if (\n attempt >= TARGET_EMBED_SESSION_ATTEMPTS ||\n !isRetryableTargetMcpError(error)\n ) {\n throw error;\n }\n await sleep(targetMcpRetryDelay(attempt));\n } finally {\n await manager.stop().catch((stopError) => {\n console.warn(\"[dispatch] Failed to stop target MCP client:\", stopError);\n });\n }\n }\n}\n\nasync function resolveDispatchEmbedTarget(input: {\n app?: string;\n url?: string;\n path?: string;\n}): Promise<{ app: DispatchMcpAccessibleApp; path: string; url: string }> {\n const explicitApp = input.app?.trim()\n ? await resolveGrantedDispatchMcpApp(input.app)\n : null;\n if (explicitApp && input.path) {\n const path = safeAppPath(input.path);\n if (!path) throw new Error(\"path must be a safe app-relative route\");\n assertAppCanOpenPath(explicitApp, path);\n return {\n app: explicitApp,\n path,\n url: `${appBaseUrl(explicitApp)}${path}`,\n };\n }\n\n if (!input.url) {\n throw new Error(\"create_embed_session requires a url or app + path.\");\n }\n\n let parsed: URL;\n try {\n parsed = new URL(input.url);\n } catch {\n if (!explicitApp) {\n throw new Error(\"Relative embed paths require an app id.\");\n }\n const path = safeAppPath(input.url);\n if (!path) throw new Error(\"url must be a safe app route.\");\n return {\n app: explicitApp,\n path,\n url: `${appBaseUrl(explicitApp)}${path}`,\n };\n }\n\n const apps = explicitApp ? [explicitApp] : await listGrantedDispatchMcpApps();\n const target = apps\n .filter((app) => appMatchesUrlPath(app, parsed))\n .sort((a, b) => appPathSpecificity(b) - appPathSpecificity(a))[0];\n if (!target) {\n throw new Error(\n \"Embed URL must belong to an app granted through Dispatch.\",\n );\n }\n const path = safeAppPath(appRelativePath(target, parsed));\n if (!path) throw new Error(\"Embed URL path is not safe.\");\n assertAppCanOpenPath(target, path);\n return { app: target, path, url: `${appBaseUrl(target)}${path}` };\n}\n\nasync function createDispatchSelfEmbedSession(input: {\n ownerEmail: string;\n orgId?: string;\n path: string;\n baseUrl: string;\n chrome?: \"full\" | \"minimal\";\n}): Promise<{\n startUrl: string;\n targetPath?: string;\n expiresAt?: number;\n app: string;\n}> {\n const ticket = await createEmbedSessionTicket({\n ownerEmail: input.ownerEmail,\n orgId: input.orgId,\n targetPath: input.path,\n scope: input.chrome ?? null,\n });\n const startPath = buildEmbedStartPath(ticket.ticket);\n return {\n startUrl: new URL(startPath, input.baseUrl).toString(),\n targetPath: input.path,\n expiresAt: ticket.expiresAt,\n app: DISPATCH_APP_ID,\n };\n}\n\nexport async function createGrantedDispatchMcpEmbedSession(input: {\n app?: string;\n url?: string;\n path?: string;\n chrome?: \"full\" | \"minimal\";\n}): Promise<{\n startUrl: string;\n targetPath?: string;\n expiresAt?: number;\n app: string;\n}> {\n const userEmail = getRequestUserEmail();\n if (!userEmail) throw new Error(\"no authenticated user\");\n const target = await resolveDispatchEmbedTarget(input);\n\n const orgId = getRequestOrgId();\n if (target.app.id === DISPATCH_APP_ID) {\n return createDispatchSelfEmbedSession({\n ownerEmail: userEmail,\n orgId,\n path: target.path,\n baseUrl: appBaseUrl(target.app),\n chrome: input.chrome,\n });\n }\n\n const [orgDomain, orgSecret] = orgId\n ? await Promise.all([\n getOrgDomain(orgId).catch(() => null),\n getOrgA2ASecret(orgId).catch(() => null),\n ])\n : [null, null];\n const usableOrgSecret =\n typeof orgSecret === \"string\" && orgSecret.trim().length > 0;\n const usableOrgDomain =\n typeof orgDomain === \"string\" && orgDomain.trim().length > 0;\n const useOrgSigning = usableOrgDomain && usableOrgSecret;\n const signedOrgDomain = usableOrgDomain ? orgDomain.trim() : undefined;\n const token = await signA2AToken(\n userEmail,\n signedOrgDomain,\n useOrgSigning ? orgSecret.trim() : undefined,\n {\n expiresIn: \"5m\",\n // Prefer the synced org A2A secret when present because first-party\n // production apps do not have to share the same deployment env secret.\n // Fall back to the global A2A_SECRET for orgs that have not synced yet.\n preferGlobalSecret: !useOrgSigning,\n },\n );\n\n const result = await callTargetCreateEmbedSession({\n app: target.app,\n token,\n url: target.url,\n chrome: input.chrome,\n });\n const parsed = parseMcpToolTextResult(result) as {\n startUrl?: string;\n targetPath?: string;\n expiresAt?: number;\n };\n if (!parsed.startUrl) {\n throw new Error(\"Target app did not return an embed start URL.\");\n }\n const output: {\n startUrl: string;\n targetPath?: string;\n expiresAt?: number;\n app: string;\n } = {\n startUrl: parsed.startUrl,\n app: target.app.id,\n };\n if (parsed.targetPath) output.targetPath = parsed.targetPath;\n if (typeof parsed.expiresAt === \"number\") output.expiresAt = parsed.expiresAt;\n return output;\n}\n"]}
@@ -0,0 +1,24 @@
1
+ export interface ThreadLinkPreview {
2
+ title: string;
3
+ description: string;
4
+ imageUrl: string | null;
5
+ }
6
+ export declare function extractThreadPreviewImageUrl(threadData: string): string | null;
7
+ export declare function loadThreadLinkPreview(threadId: string | null | undefined): Promise<ThreadLinkPreview | null>;
8
+ export declare function buildThreadLinkPreviewMeta(preview: ThreadLinkPreview | null): ({
9
+ title: string;
10
+ name?: undefined;
11
+ content?: undefined;
12
+ property?: undefined;
13
+ } | {
14
+ name: string;
15
+ content: string;
16
+ title?: undefined;
17
+ property?: undefined;
18
+ } | {
19
+ property: string;
20
+ content: string;
21
+ title?: undefined;
22
+ name?: undefined;
23
+ })[];
24
+ //# sourceMappingURL=thread-link-preview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thread-link-preview.d.ts","sourceRoot":"","sources":["../../../src/server/lib/thread-link-preview.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAiGD,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,MAAM,GACjB,MAAM,GAAG,IAAI,CAiCf;AAQD,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAClC,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAcnC;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI;;;;;;;;;;;;;;;KAqB3E"}