@agent-native/core 0.22.33 → 0.22.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionViewer.js +26 -1
- package/dist/client/extensions/ExtensionViewer.js.map +1 -1
- package/dist/client/extensions/ExtensionViewer.spec.d.ts +2 -0
- package/dist/client/extensions/ExtensionViewer.spec.d.ts.map +1 -0
- package/dist/client/extensions/ExtensionViewer.spec.js +94 -0
- package/dist/client/extensions/ExtensionViewer.spec.js.map +1 -0
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +5 -50
- package/dist/deploy/build.js.map +1 -1
- package/dist/mcp/build-server.d.ts +8 -0
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js +43 -6
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/mcp/embed-app.d.ts.map +1 -1
- package/dist/mcp/embed-app.js +19 -0
- package/dist/mcp/embed-app.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +13 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/stdio.d.ts.map +1 -1
- package/dist/mcp/stdio.js +9 -2
- package/dist/mcp/stdio.js.map +1 -1
- package/dist/server/auth-marketing.d.ts +14 -0
- package/dist/server/auth-marketing.d.ts.map +1 -0
- package/dist/server/auth-marketing.js +268 -0
- package/dist/server/auth-marketing.js.map +1 -0
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +34 -25
- package/dist/server/auth.js.map +1 -1
- package/dist/server/embed-route.d.ts.map +1 -1
- package/dist/server/embed-route.js +39 -1
- package/dist/server/embed-route.js.map +1 -1
- package/dist/server/onboarding-html.d.ts +6 -0
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +6 -1
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/ssr-handler.d.ts +0 -1
- package/dist/server/ssr-handler.d.ts.map +1 -1
- package/dist/server/ssr-handler.js +6 -7
- package/dist/server/ssr-handler.js.map +1 -1
- package/docs/content/actions.md +1 -1
- package/docs/content/external-agents.md +30 -13
- package/docs/content/mcp-protocol.md +18 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExtensionViewer.d.ts","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionViewer.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ExtensionViewer.d.ts","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionViewer.tsx"],"names":[],"mappings":"AAiGA,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;CACrB;AA4JD,wBAAgB,eAAe,CAAC,EAAE,WAAW,EAAE,EAAE,oBAAoB,2CAkhBpE"}
|
|
@@ -14,6 +14,9 @@ import { isAllowedExtensionPath, sanitizeExtensionRequestOptions, checkBridgePol
|
|
|
14
14
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "../components/ui/tooltip.js";
|
|
15
15
|
import { deleteOrHideExtension, invalidateExtensionRemoval, } from "./delete-extension.js";
|
|
16
16
|
import { extensionPath, isExtensionPathname } from "../../extensions/path.js";
|
|
17
|
+
import { buildExtensionHtml } from "../../extensions/html-shell.js";
|
|
18
|
+
import { getThemeVars } from "../../extensions/theme.js";
|
|
19
|
+
import { isEmbedMcpChatBridgeActive } from "../embed-auth.js";
|
|
17
20
|
const THEME_CSS_VARS = [
|
|
18
21
|
"--background",
|
|
19
22
|
"--foreground",
|
|
@@ -62,6 +65,23 @@ function readExtensionTitleSuffix() {
|
|
|
62
65
|
function extensionDocumentTitle(name, suffix) {
|
|
63
66
|
return suffix ? `${name} \u2014 ${suffix}` : `${name} \u2014 Extensions`;
|
|
64
67
|
}
|
|
68
|
+
function extensionRole(value) {
|
|
69
|
+
return value === "owner" ||
|
|
70
|
+
value === "admin" ||
|
|
71
|
+
value === "editor" ||
|
|
72
|
+
value === "viewer"
|
|
73
|
+
? value
|
|
74
|
+
: "viewer";
|
|
75
|
+
}
|
|
76
|
+
function buildExtensionViewerSrcDoc(extension, isDark) {
|
|
77
|
+
const role = extensionRole(extension.role);
|
|
78
|
+
return buildExtensionHtml(extension.content ?? "", getThemeVars(isDark), isDark, extension.id, {
|
|
79
|
+
authorEmail: extension.ownerEmail ?? "",
|
|
80
|
+
viewerEmail: "",
|
|
81
|
+
isAuthor: role === "owner",
|
|
82
|
+
role,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
65
85
|
function applyCanonicalLink(path) {
|
|
66
86
|
if (typeof document === "undefined" || typeof window === "undefined") {
|
|
67
87
|
return () => { };
|
|
@@ -409,6 +429,11 @@ export function ExtensionViewer({ extensionId }) {
|
|
|
409
429
|
return applyCanonicalLink(canonicalPath);
|
|
410
430
|
}, [extension, location.hash, location.pathname, location.search, navigate]);
|
|
411
431
|
const iframeSrc = useMemo(() => agentNativePath(`/_agent-native/extensions/${extensionId}/render?dark=${document.documentElement.classList.contains("dark")}&v=${encodeURIComponent(extension?.updatedAt ?? "")}&r=${refreshKey}`), [extensionId, extension?.updatedAt, refreshKey]);
|
|
432
|
+
const iframeSrcDoc = useMemo(() => {
|
|
433
|
+
if (!extension?.content || !isEmbedMcpChatBridgeActive())
|
|
434
|
+
return undefined;
|
|
435
|
+
return buildExtensionViewerSrcDoc(extension, isDark);
|
|
436
|
+
}, [extension, isDark]);
|
|
412
437
|
useEffect(() => {
|
|
413
438
|
setIframeReady(false);
|
|
414
439
|
// Reset role to deny-by-default on every reload — the new render's
|
|
@@ -456,7 +481,7 @@ export function ExtensionViewer({ extensionId }) {
|
|
|
456
481
|
submitRename();
|
|
457
482
|
if (e.key === "Escape")
|
|
458
483
|
setIsRenaming(false);
|
|
459
|
-
}, className: "min-w-0 bg-transparent px-0 py-0 text-sm font-medium outline-none border-b border-primary" })) : (_jsxs(_Fragment, { children: [_jsx("span", { className: "truncate text-sm font-medium", children: extension.name }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: startRename, className: "shrink-0 cursor-pointer rounded p-0.5 text-muted-foreground/40 opacity-0 group-hover/name:opacity-100 hover:text-foreground", children: _jsx(IconPencil, { className: "h-3 w-3" }) }) }), _jsx(TooltipContent, { children: "Rename" })] })] }))] })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => setRefreshKey((k) => k + 1), className: "inline-flex items-center justify-center rounded-md h-8 w-8 text-muted-foreground hover:bg-accent hover:text-accent-foreground cursor-pointer", children: _jsx(IconRefresh, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { children: "Refresh" })] }), _jsx(EditToolPopover, { extension: extension, onOpenChange: onPopoverOpenChange }), _jsx(ShareButton, { resourceType: "extension", resourceId: extensionId, resourceTitle: extension.name, onOpenChange: onPopoverOpenChange, accessNote: _jsx(_Fragment, { children: "Extensions can be shared inside your organization only \u2014 they run with the viewer's credentials, so cross-org access isn't supported." }) }), _jsx(ToolMoreMenu, { extensionId: extensionId, toolName: extension.name, canDelete: extension.canDelete, onOpenChange: onPopoverOpenChange }), _jsx(NotificationsBell, {}), _jsx(AgentToggleButton, {})] })] }), _jsxs("div", { className: "relative flex-1 min-h-0", children: [!iframeReady && (_jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-background z-10", children: _jsx(IconLoader2, { className: "size-5 animate-spin text-muted-foreground", role: "status", "aria-label": "Loading" }) })), _jsx("iframe", { ref: iframeRef, src: iframeSrc, className: "h-full w-full border-0", sandbox: "allow-scripts allow-forms", title: extension.name, style: {
|
|
484
|
+
}, className: "min-w-0 bg-transparent px-0 py-0 text-sm font-medium outline-none border-b border-primary" })) : (_jsxs(_Fragment, { children: [_jsx("span", { className: "truncate text-sm font-medium", children: extension.name }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: startRename, className: "shrink-0 cursor-pointer rounded p-0.5 text-muted-foreground/40 opacity-0 group-hover/name:opacity-100 hover:text-foreground", children: _jsx(IconPencil, { className: "h-3 w-3" }) }) }), _jsx(TooltipContent, { children: "Rename" })] })] }))] })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => setRefreshKey((k) => k + 1), className: "inline-flex items-center justify-center rounded-md h-8 w-8 text-muted-foreground hover:bg-accent hover:text-accent-foreground cursor-pointer", children: _jsx(IconRefresh, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { children: "Refresh" })] }), _jsx(EditToolPopover, { extension: extension, onOpenChange: onPopoverOpenChange }), _jsx(ShareButton, { resourceType: "extension", resourceId: extensionId, resourceTitle: extension.name, onOpenChange: onPopoverOpenChange, accessNote: _jsx(_Fragment, { children: "Extensions can be shared inside your organization only \u2014 they run with the viewer's credentials, so cross-org access isn't supported." }) }), _jsx(ToolMoreMenu, { extensionId: extensionId, toolName: extension.name, canDelete: extension.canDelete, onOpenChange: onPopoverOpenChange }), _jsx(NotificationsBell, {}), _jsx(AgentToggleButton, {})] })] }), _jsxs("div", { className: "relative flex-1 min-h-0", children: [!iframeReady && (_jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-background z-10", children: _jsx(IconLoader2, { className: "size-5 animate-spin text-muted-foreground", role: "status", "aria-label": "Loading" }) })), _jsx("iframe", { ref: iframeRef, src: iframeSrcDoc ? undefined : iframeSrc, srcDoc: iframeSrcDoc, className: "h-full w-full border-0", sandbox: "allow-scripts allow-forms", title: extension.name, style: {
|
|
460
485
|
pointerEvents: openPopoverCount > 0 ? "none" : "auto",
|
|
461
486
|
}, onLoad: () => {
|
|
462
487
|
sendThemeToIframe();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExtensionViewer.js","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionViewer.tsx"],"names":[],"mappings":"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","sourcesContent":["import { agentNativePath, appPath } from \"../api-path.js\";\nimport { useState, useEffect, useRef, useCallback, useMemo } from \"react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { Link, useLocation, useNavigate } from \"react-router\";\nimport {\n IconArrowLeft,\n IconChevronRight,\n IconDots,\n IconLoader2,\n IconPencil,\n IconRefresh,\n IconTrash,\n IconX,\n} from \"@tabler/icons-react\";\nimport { ShareButton } from \"../sharing/ShareButton.js\";\nimport { AgentToggleButton } from \"../AgentPanel.js\";\nimport { NotificationsBell } from \"../notifications/NotificationsBell.js\";\nimport { sendToAgentChat } from \"../agent-chat.js\";\nimport { PromptComposer } from \"../composer/PromptComposer.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport {\n isAllowedExtensionPath,\n sanitizeExtensionRequestOptions,\n checkBridgePolicy,\n type ExtensionBridgeRole,\n} from \"./iframe-bridge.js\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"../components/ui/tooltip.js\";\nimport {\n deleteOrHideExtension,\n invalidateExtensionRemoval,\n} from \"./delete-extension.js\";\nimport { extensionPath, isExtensionPathname } from \"../../extensions/path.js\";\n\nconst THEME_CSS_VARS = [\n \"--background\",\n \"--foreground\",\n \"--card\",\n \"--card-foreground\",\n \"--popover\",\n \"--popover-foreground\",\n \"--primary\",\n \"--primary-foreground\",\n \"--secondary\",\n \"--secondary-foreground\",\n \"--muted\",\n \"--muted-foreground\",\n \"--accent\",\n \"--accent-foreground\",\n \"--destructive\",\n \"--destructive-foreground\",\n \"--border\",\n \"--input\",\n \"--ring\",\n \"--radius\",\n \"--sidebar-background\",\n \"--sidebar-foreground\",\n \"--sidebar-primary\",\n \"--sidebar-primary-foreground\",\n \"--sidebar-accent\",\n \"--sidebar-accent-foreground\",\n \"--sidebar-border\",\n \"--sidebar-ring\",\n];\n\nfunction getParentThemeVars(): Record<string, string> {\n const computed = getComputedStyle(document.documentElement);\n const vars: Record<string, string> = {};\n for (const name of THEME_CSS_VARS) {\n const val = computed.getPropertyValue(name).trim();\n if (val) vars[name] = val;\n }\n return vars;\n}\n\ninterface Extension {\n id: string;\n name: string;\n description?: string;\n content?: string;\n updatedAt?: string;\n canDelete?: boolean;\n}\n\nexport interface ExtensionViewerProps {\n extensionId: string;\n}\n\nfunction readExtensionTitleSuffix(): string | null {\n const current = typeof document !== \"undefined\" ? document.title.trim() : \"\";\n const match = current.match(/^(?:Extension|Tool)s?\\s+(?:\\u2014|-)\\s+(.+)$/);\n return match?.[1]?.trim() || null;\n}\n\nfunction extensionDocumentTitle(name: string, suffix: string | null): string {\n return suffix ? `${name} \\u2014 ${suffix}` : `${name} \\u2014 Extensions`;\n}\n\nfunction applyCanonicalLink(path: string): () => void {\n if (typeof document === \"undefined\" || typeof window === \"undefined\") {\n return () => {};\n }\n\n let link = document.querySelector<HTMLLinkElement>('link[rel=\"canonical\"]');\n const created = !link;\n const previousHref = link?.getAttribute(\"href\") ?? null;\n const previousMarker = link?.dataset.agentNativeExtensionCanonical;\n\n if (!link) {\n link = document.createElement(\"link\");\n link.rel = \"canonical\";\n document.head.appendChild(link);\n }\n\n link.dataset.agentNativeExtensionCanonical = \"true\";\n link.href = new URL(appPath(path), window.location.origin).toString();\n\n return () => {\n if (!link) return;\n if (created) {\n link.remove();\n return;\n }\n if (previousHref === null) {\n link.removeAttribute(\"href\");\n } else {\n link.href = previousHref;\n }\n if (previousMarker === undefined) {\n delete link.dataset.agentNativeExtensionCanonical;\n } else {\n link.dataset.agentNativeExtensionCanonical = previousMarker;\n }\n };\n}\n\nfunction EditToolPopover({\n extension,\n onOpenChange,\n}: {\n extension: Extension;\n onOpenChange?: (open: boolean) => void;\n}) {\n const [open, setOpen] = useState(false);\n const setOpenAndNotify = (v: boolean) => {\n setOpen(v);\n onOpenChange?.(v);\n };\n\n // Radix's outside-click detection runs in the parent document, so a click\n // inside the extension iframe (or any other iframe) never fires it. The browser\n // does shift focus to the iframe though, which blurs the parent window — we\n // hook that to close the popover so it behaves like a normal click-outside.\n useEffect(() => {\n if (!open) return;\n const handleBlur = () => {\n // Defer until after the focus actually lands so document.activeElement\n // reflects the iframe (or whatever the user clicked on).\n setTimeout(() => {\n if (document.activeElement?.tagName === \"IFRAME\")\n setOpenAndNotify(false);\n }, 0);\n };\n window.addEventListener(\"blur\", handleBlur);\n return () => window.removeEventListener(\"blur\", handleBlur);\n }, [open]);\n\n const handleSubmit = (text: string) => {\n const trimmed = text.trim();\n if (!trimmed) return;\n sendToAgentChat({\n message: `Update extension \"${extension.name}\" (${extension.id}): ${trimmed}`,\n context: [\n `The user is viewing extension \"${extension.name}\" (id: ${extension.id}) and wants to edit it.`,\n \"This is an existing sandboxed Alpine.js extension stored in SQL. Use list-extensions/update-extension for this extension id.\",\n \"Do not call connect-builder and do not route this to a source-code change flow.\",\n ].join(\"\\n\"),\n submit: true,\n openSidebar: true,\n newTab: true,\n });\n setOpenAndNotify(false);\n };\n\n return (\n <Popover open={open} onOpenChange={setOpenAndNotify}>\n <Tooltip>\n <TooltipTrigger asChild>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex items-center justify-center rounded-md h-8 w-8 text-muted-foreground hover:bg-accent hover:text-accent-foreground cursor-pointer\"\n >\n <IconPencil className=\"h-4 w-4\" />\n </button>\n </PopoverTrigger>\n </TooltipTrigger>\n <TooltipContent>Edit</TooltipContent>\n </Tooltip>\n <PopoverContent align=\"end\" sideOffset={6} className=\"w-[420px] p-3\">\n <p className=\"px-1 pb-2 text-sm font-semibold text-foreground\">\n Edit extension\n </p>\n <PromptComposer\n autoFocus\n placeholder=\"What would you like to change?\"\n draftScope={`extensions:edit:${extension.id}`}\n onSubmit={handleSubmit}\n />\n </PopoverContent>\n </Popover>\n );\n}\n\nexport function ExtensionViewer({ extensionId }: ExtensionViewerProps) {\n const location = useLocation();\n const navigate = useNavigate();\n const [isDark, setIsDark] = useState(false);\n const [iframeReady, setIframeReady] = useState(false);\n const iframeRef = useRef<HTMLIFrameElement | null>(null);\n const toolRef = useRef<Extension | null>(null);\n const [isRenaming, setIsRenaming] = useState(false);\n const [renameValue, setRenameValue] = useState(\"\");\n const [refreshKey, setRefreshKey] = useState(0);\n const renameInputRef = useRef<HTMLInputElement | null>(null);\n const titleSuffixRef = useRef<string | null | undefined>(undefined);\n // Tracks how many toolbar popovers are open. Iframes capture pointer events\n // from areas they visually overlap, so when a popover opens above the iframe,\n // hover and click on the popover items get swallowed by the iframe. Disabling\n // pointer-events on the iframe while any popover is open lets the popover\n // receive its own events. Each popover increments on open / decrements on\n // close, so concurrent popovers (rare) compose correctly.\n const [openPopoverCount, setOpenPopoverCount] = useState(0);\n const onPopoverOpenChange = useCallback((open: boolean) => {\n setOpenPopoverCount((c) => Math.max(0, c + (open ? 1 : -1)));\n }, []);\n const queryClient = useQueryClient();\n // (audit H4) Role plumbed through from the iframe's render binding. Until\n // the iframe announces its role we deny non-trivial helper calls — that\n // way a malicious extension body that races the announcement can't briefly\n // operate at higher privilege than the viewer's actual role.\n const bridgeContextRef = useRef<{\n role: ExtensionBridgeRole;\n isAuthor: boolean;\n }>({\n role: \"viewer\",\n isAuthor: false,\n });\n\n useEffect(() => {\n setIsDark(document.documentElement.classList.contains(\"dark\"));\n\n const observer = new MutationObserver(() => {\n setIsDark(document.documentElement.classList.contains(\"dark\"));\n });\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\"],\n });\n return () => observer.disconnect();\n }, []);\n\n const sendThemeToIframe = () => {\n const win = iframeRef.current?.contentWindow;\n if (!win) return;\n win.postMessage(\n {\n type: \"agent-native-theme-update\",\n isDark: document.documentElement.classList.contains(\"dark\"),\n vars: getParentThemeVars(),\n },\n \"*\",\n );\n };\n\n useEffect(() => {\n if (!iframeReady) return;\n sendThemeToIframe();\n }, [isDark, iframeReady]);\n\n useEffect(() => {\n const handleMessage = async (event: MessageEvent) => {\n if (event.source !== iframeRef.current?.contentWindow) return;\n const message = event.data;\n if (!message) return;\n\n if (message.type === \"agent-native-extension-binding\") {\n // (audit H4) The iframe announced its render binding. Trust the role\n // value because the iframe's binding is generated server-side in\n // extensions/routes.ts (resolveAccess), not by user-authored content.\n const binding = message.binding ?? {};\n const role: ExtensionBridgeRole =\n binding.role === \"owner\" ||\n binding.role === \"admin\" ||\n binding.role === \"editor\" ||\n binding.role === \"viewer\"\n ? binding.role\n : \"viewer\";\n bridgeContextRef.current = {\n role,\n isAuthor: !!binding.isAuthor,\n };\n return;\n }\n\n if (\n message.type === \"agent-native-extension-consent-granted\" ||\n message.type === \"agent-native-extension-consent-cancelled\"\n ) {\n // (audit C1) The consent stub fired; force a reload of the iframe so\n // the next render returns the extension body (granted) or stays on the\n // stub (cancelled — viewer can also navigate away).\n if (message.type === \"agent-native-extension-consent-granted\") {\n // Invalidate the cached extension record — author may have edited\n // since the cache was warmed.\n queryClient.invalidateQueries({\n queryKey: [\"extension\", extensionId],\n });\n setRefreshKey((k) => k + 1);\n }\n return;\n }\n\n if (message.type === \"agent-native-extension-keydown\") {\n document.dispatchEvent(\n new KeyboardEvent(\"keydown\", {\n key: message.key,\n code: message.code,\n metaKey: !!message.metaKey,\n ctrlKey: !!message.ctrlKey,\n shiftKey: !!message.shiftKey,\n altKey: !!message.altKey,\n bubbles: true,\n cancelable: true,\n }),\n );\n return;\n }\n\n if (message.type === \"agent-native-extension-error-fix\") {\n const t = toolRef.current;\n if (!t) return;\n const errors: string[] = message.errors || [];\n const errorDetails: Array<{ message: string; stack: string }> =\n message.errorDetails || [];\n const consoleLogs: Array<{ level: string; message: string }> =\n message.consoleLogs || [];\n const networkLogs: Array<{\n path: string;\n method: string;\n ok?: boolean;\n status?: number;\n error?: string;\n }> = message.networkLogs || [];\n\n const detailedTrace = errorDetails\n .map((e) => (e.stack ? `${e.message}\\n${e.stack}` : e.message))\n .join(\"\\n\\n\");\n\n // Force a fresh read from the server. toolRef.current is bound to the\n // React Query cache, which is the same state the agent's previous\n // (broken) turn just wrote — without this, Fix-in-same-chat ends up\n // patching the agent's prior attempt from chat history instead of the\n // current DB row, which is why users had to open a new chat to\n // recover. Cache-bust so we never read a stale fetch.\n let freshContent: string | undefined;\n try {\n const res = await fetch(\n agentNativePath(`/_agent-native/extensions/${t.id}`),\n { cache: \"no-store\" },\n );\n if (res.ok) {\n const fresh = (await res.json()) as Extension;\n freshContent =\n typeof fresh?.content === \"string\" ? fresh.content : undefined;\n }\n } catch {\n // Fall through with the cached value — agent can still re-read via\n // its get-extension tool.\n }\n\n const contextParts = [\n `The user is viewing extension \"${t.name}\" (id: ${t.id}) and there are runtime errors that need fixing.`,\n `\\nFull error details:\\n${detailedTrace}`,\n ];\n\n if (consoleLogs.length > 0) {\n const consoleStr = consoleLogs\n .map((l) => `[${l.level}] ${l.message}`)\n .join(\"\\n\");\n contextParts.push(`\\nRecent console output:\\n${consoleStr}`);\n }\n\n if (networkLogs.length > 0) {\n const netStr = networkLogs\n .map(\n (l) =>\n `${l.method} ${l.path} → ${l.ok ? l.status : \"FAILED: \" + (l.error || l.status)}`,\n )\n .join(\"\\n\");\n contextParts.push(`\\nRecent network requests:\\n${netStr}`);\n }\n\n if (freshContent) {\n contextParts.push(\n `\\nCurrent extension content (just re-read from the database — this is the authoritative source, not anything you may have written in a previous turn):\\n\\`\\`\\`html\\n${freshContent}\\n\\`\\`\\``,\n );\n }\n\n sendToAgentChat({\n message: `Fix runtime errors in this extension. The content snapshot below was just re-read from the database — treat it as authoritative and ignore any prior version you may have generated in this chat. If in doubt, call get-extension first.\\n\\nErrors:\\n${errors.join(\"\\n\")}`,\n context: contextParts.join(\"\\n\"),\n submit: true,\n openSidebar: true,\n });\n return;\n }\n\n if (message.type !== \"agent-native-extension-request\") return;\n\n const requestId = String(message.requestId ?? \"\");\n const path = String(message.path ?? \"\");\n const respond = (payload: Record<string, unknown>) => {\n iframeRef.current?.contentWindow?.postMessage(\n {\n type: \"agent-native-extension-response\",\n requestId,\n ...payload,\n },\n \"*\",\n );\n };\n\n if (!requestId || !isAllowedExtensionPath(path, extensionId)) {\n respond({ error: \"Extension request path is not allowed\" });\n return;\n }\n\n try {\n const options = sanitizeExtensionRequestOptions(message.options);\n // (audit H4) Role-aware policy gate: viewer-shared extensions can read\n // but not write. Decided here in the parent before the request\n // leaves; the server enforces a second layer.\n const policy = checkBridgePolicy(\n path,\n options.method ?? \"GET\",\n bridgeContextRef.current,\n );\n if (!policy.ok) {\n respond({\n response: {\n ok: false,\n status: 403,\n statusText: \"Forbidden\",\n body: { error: policy.error },\n },\n });\n return;\n }\n // (audit H5) Tag every outbound bridge request with the\n // X-Agent-Native-Extension-Bridge sentinel so the action-routes layer can\n // enforce per-action `toolCallable` opt-in. The header is added by\n // the parent — it is NOT taken from the iframe-supplied options\n // (which were filtered by sanitizeExtensionRequestOptions).\n const finalHeaders = new Headers(options.headers ?? undefined);\n finalHeaders.set(\"X-Agent-Native-Extension-Bridge\", \"1\");\n finalHeaders.set(\"X-Agent-Native-Extension-Id\", extensionId);\n finalHeaders.set(\"X-Agent-Native-Tool-Bridge\", \"1\");\n finalHeaders.set(\"X-Agent-Native-Tool-Id\", extensionId);\n const res = await fetch(agentNativePath(path), {\n ...options,\n headers: finalHeaders,\n credentials: \"same-origin\",\n });\n const text = await res.text();\n let body: unknown = text;\n if (text) {\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n }\n respond({\n response: {\n ok: res.ok,\n status: res.status,\n statusText: res.statusText,\n body,\n },\n });\n } catch (err: any) {\n respond({ error: err?.message ?? \"Extension host request failed\" });\n }\n };\n\n window.addEventListener(\"message\", handleMessage);\n return () => window.removeEventListener(\"message\", handleMessage);\n }, [extensionId, queryClient]);\n\n const { data: extension, isLoading } = useQuery<Extension | null>({\n queryKey: [\"extension\", extensionId],\n queryFn: async () => {\n const res = await fetch(\n agentNativePath(`/_agent-native/extensions/${extensionId}`),\n );\n if (res.status === 403 || res.status === 404) return null;\n if (!res.ok) throw new Error(\"Failed to fetch extension\");\n return res.json();\n },\n });\n\n toolRef.current = extension ?? null;\n\n useEffect(() => {\n if (!extension) return;\n const canonicalPath = extensionPath(extension.id, extension.name);\n if (titleSuffixRef.current === undefined) {\n titleSuffixRef.current = readExtensionTitleSuffix();\n }\n document.title = extensionDocumentTitle(\n extension.name,\n titleSuffixRef.current,\n );\n\n if (\n isExtensionPathname(location.pathname, extension.id) &&\n location.pathname !== canonicalPath\n ) {\n navigate(`${canonicalPath}${location.search}${location.hash}`, {\n replace: true,\n });\n }\n\n return applyCanonicalLink(canonicalPath);\n }, [extension, location.hash, location.pathname, location.search, navigate]);\n\n const iframeSrc = useMemo(\n () =>\n agentNativePath(\n `/_agent-native/extensions/${extensionId}/render?dark=${document.documentElement.classList.contains(\"dark\")}&v=${encodeURIComponent(extension?.updatedAt ?? \"\")}&r=${refreshKey}`,\n ),\n [extensionId, extension?.updatedAt, refreshKey],\n );\n\n useEffect(() => {\n setIframeReady(false);\n // Reset role to deny-by-default on every reload — the new render's\n // binding announcement re-establishes the role before any helper call.\n bridgeContextRef.current = { role: \"viewer\", isAuthor: false };\n }, [extensionId, extension?.updatedAt, refreshKey]);\n\n const startRename = useCallback(() => {\n if (!extension) return;\n setRenameValue(extension.name);\n setIsRenaming(true);\n requestAnimationFrame(() => renameInputRef.current?.select());\n }, [extension]);\n\n const submitRename = useCallback(async () => {\n const trimmed = renameValue.trim();\n if (!trimmed || !extension || trimmed === extension.name) {\n setIsRenaming(false);\n return;\n }\n queryClient.setQueryData<Extension>([\"extension\", extensionId], (old) =>\n old ? { ...old, name: trimmed } : old,\n );\n queryClient.setQueryData<Extension[]>([\"extensions\"], (old) =>\n (old ?? []).map((t) =>\n t.id === extensionId ? { ...t, name: trimmed } : t,\n ),\n );\n setIsRenaming(false);\n try {\n await fetch(agentNativePath(`/_agent-native/extensions/${extensionId}`), {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ name: trimmed }),\n });\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n queryClient.invalidateQueries({ queryKey: [\"extensions\"] });\n } catch {\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n queryClient.invalidateQueries({ queryKey: [\"extensions\"] });\n }\n }, [renameValue, extension, extensionId, queryClient]);\n\n if (isLoading) {\n return (\n <div className=\"flex h-full flex-col\">\n <div className=\"flex h-12 items-center gap-2 px-3 border-b shrink-0\">\n <div className=\"h-3.5 w-3.5 rounded bg-muted animate-pulse\" />\n <div className=\"h-3.5 w-24 rounded bg-muted animate-pulse\" />\n </div>\n <div className=\"flex-1 bg-muted/20 animate-pulse\" />\n </div>\n );\n }\n\n if (!extension) {\n return (\n <div className=\"flex h-full items-center justify-center text-sm text-muted-foreground\">\n Extension not found\n </div>\n );\n }\n\n return (\n <TooltipProvider delayDuration={200}>\n <div className=\"flex h-full w-full flex-col\">\n <div className=\"flex h-12 shrink-0 items-center justify-between gap-3 border-b px-3\">\n <div className=\"flex min-w-0 items-center gap-3\">\n <Tooltip>\n <TooltipTrigger asChild>\n <Link\n to=\"/\"\n className=\"inline-flex h-8 shrink-0 items-center justify-center gap-1.5 rounded-md px-2 text-xs font-medium text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n aria-label=\"Back to app\"\n >\n <IconArrowLeft className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">Back to app</span>\n </Link>\n </TooltipTrigger>\n <TooltipContent>Back to app</TooltipContent>\n </Tooltip>\n <nav\n aria-label=\"Extension breadcrumb\"\n className=\"group/name flex min-w-0 items-center gap-1 text-sm\"\n >\n <Link\n to=\"/extensions\"\n className=\"shrink-0 text-muted-foreground hover:text-foreground\"\n >\n Extensions\n </Link>\n <IconChevronRight className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground/60\" />\n {isRenaming ? (\n <input\n ref={renameInputRef}\n value={renameValue}\n onChange={(e) => setRenameValue(e.target.value)}\n onBlur={submitRename}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") submitRename();\n if (e.key === \"Escape\") setIsRenaming(false);\n }}\n className=\"min-w-0 bg-transparent px-0 py-0 text-sm font-medium outline-none border-b border-primary\"\n />\n ) : (\n <>\n <span className=\"truncate text-sm font-medium\">\n {extension.name}\n </span>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={startRename}\n className=\"shrink-0 cursor-pointer rounded p-0.5 text-muted-foreground/40 opacity-0 group-hover/name:opacity-100 hover:text-foreground\"\n >\n <IconPencil className=\"h-3 w-3\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>Rename</TooltipContent>\n </Tooltip>\n </>\n )}\n </nav>\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={() => setRefreshKey((k) => k + 1)}\n className=\"inline-flex items-center justify-center rounded-md h-8 w-8 text-muted-foreground hover:bg-accent hover:text-accent-foreground cursor-pointer\"\n >\n <IconRefresh className=\"h-4 w-4\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>Refresh</TooltipContent>\n </Tooltip>\n <EditToolPopover\n extension={extension}\n onOpenChange={onPopoverOpenChange}\n />\n <ShareButton\n resourceType=\"extension\"\n resourceId={extensionId}\n resourceTitle={extension.name}\n onOpenChange={onPopoverOpenChange}\n accessNote={\n <>\n Extensions can be shared inside your organization only — they\n run with the viewer's credentials, so cross-org access isn't\n supported.\n </>\n }\n />\n <ToolMoreMenu\n extensionId={extensionId}\n toolName={extension.name}\n canDelete={extension.canDelete}\n onOpenChange={onPopoverOpenChange}\n />\n <NotificationsBell />\n <AgentToggleButton />\n </div>\n </div>\n <div className=\"relative flex-1 min-h-0\">\n {!iframeReady && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-background z-10\">\n <IconLoader2\n className=\"size-5 animate-spin text-muted-foreground\"\n role=\"status\"\n aria-label=\"Loading\"\n />\n </div>\n )}\n <iframe\n ref={iframeRef}\n key={`${extension.updatedAt}-${refreshKey}`}\n src={iframeSrc}\n className=\"h-full w-full border-0\"\n sandbox=\"allow-scripts allow-forms\"\n title={extension.name}\n style={{\n pointerEvents: openPopoverCount > 0 ? \"none\" : \"auto\",\n }}\n onLoad={() => {\n sendThemeToIframe();\n setTimeout(() => setIframeReady(true), 150);\n }}\n />\n </div>\n </div>\n </TooltipProvider>\n );\n}\n\ninterface SlotDeclaration {\n id: string;\n extensionId: string;\n slotId: string;\n}\n\nfunction ToolMoreMenu({\n extensionId,\n toolName,\n canDelete,\n onOpenChange,\n}: {\n extensionId: string;\n toolName: string;\n canDelete?: boolean;\n onOpenChange?: (open: boolean) => void;\n}) {\n const [open, setOpen] = useState(false);\n const [confirmingDelete, setConfirmingDelete] = useState(false);\n const queryClient = useQueryClient();\n const navigate = useNavigate();\n const setOpenAndNotify = (v: boolean) => {\n setOpen(v);\n onOpenChange?.(v);\n };\n\n const { data: slots = [] } = useQuery<SlotDeclaration[]>({\n queryKey: [\"extension-slots\", extensionId],\n queryFn: async () => {\n const res = await fetch(\n agentNativePath(`/_agent-native/slots/extension/${extensionId}`),\n );\n if (!res.ok) return [];\n return res.json();\n },\n enabled: open,\n });\n\n const closeMenu = () => {\n setOpenAndNotify(false);\n setConfirmingDelete(false);\n };\n\n const removeFromSlot = async (slotId: string) => {\n try {\n await fetch(\n agentNativePath(\n `/_agent-native/slots/${encodeURIComponent(slotId)}/install/${encodeURIComponent(extensionId)}`,\n ),\n { method: \"DELETE\" },\n );\n } finally {\n queryClient.invalidateQueries({ queryKey: [\"slot-installs\", slotId] });\n }\n };\n\n const deleteExtension = async () => {\n closeMenu();\n try {\n await deleteOrHideExtension({ id: extensionId, canDelete });\n invalidateExtensionRemoval(queryClient, extensionId);\n slots.forEach((s) =>\n queryClient.invalidateQueries({\n queryKey: [\"slot-installs\", s.slotId],\n }),\n );\n navigate(\"/extensions\");\n } catch {\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n }\n };\n\n return (\n <Popover\n open={open}\n onOpenChange={(o) => {\n setOpenAndNotify(o);\n if (!o) setConfirmingDelete(false);\n }}\n >\n <Tooltip>\n <TooltipTrigger asChild>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex items-center justify-center rounded-md h-8 w-8 text-muted-foreground hover:bg-accent hover:text-accent-foreground cursor-pointer\"\n aria-label=\"More options\"\n >\n <IconDots className=\"h-4 w-4\" />\n </button>\n </PopoverTrigger>\n </TooltipTrigger>\n <TooltipContent>More options</TooltipContent>\n </Tooltip>\n <PopoverContent align=\"end\" sideOffset={4} className=\"w-72 p-0\">\n {!confirmingDelete ? (\n <>\n <div className=\"px-3 py-2 border-b border-border/40\">\n <p className=\"text-[12px] font-medium\">Appears in</p>\n {slots.length === 0 ? (\n <p className=\"text-[11px] text-muted-foreground/70 mt-0.5\">\n Not installed in any widget areas. Ask the agent to add it\n somewhere.\n </p>\n ) : (\n <p className=\"text-[11px] text-muted-foreground/70 mt-0.5\">\n This extension can render in {slots.length} widget area\n {slots.length === 1 ? \"\" : \"s\"}.\n </p>\n )}\n </div>\n {slots.length > 0 && (\n <div className=\"max-h-48 overflow-y-auto py-1\">\n {slots.map((s) => (\n <div\n key={s.id}\n className=\"flex items-center gap-2 px-3 py-1.5 text-[12px]\"\n >\n <span className=\"flex-1 truncate font-mono text-[11px] text-muted-foreground\">\n {s.slotId}\n </span>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={() => removeFromSlot(s.slotId)}\n className=\"rounded p-1 text-muted-foreground/60 hover:bg-accent hover:text-foreground cursor-pointer\"\n aria-label=\"Remove from this widget area\"\n >\n <IconX className=\"h-3.5 w-3.5\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>\n Remove from this widget area (for me)\n </TooltipContent>\n </Tooltip>\n </div>\n ))}\n </div>\n )}\n <div className=\"border-t border-border/40 p-1\">\n <button\n type=\"button\"\n onClick={() => setConfirmingDelete(true)}\n className=\"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-[12px] text-destructive hover:bg-destructive/10 cursor-pointer text-left\"\n >\n <IconTrash className=\"h-3.5 w-3.5\" />\n <span>\n {canDelete === false\n ? \"Remove from my list...\"\n : \"Delete extension...\"}\n </span>\n </button>\n </div>\n </>\n ) : (\n <div className=\"flex flex-col gap-2 p-3\">\n <p className=\"text-[12px]\">\n {canDelete === false ? \"Remove \" : \"Delete \"}\n <span className=\"font-medium\">{toolName}</span>?\n {canDelete === false\n ? \" This hides it from your Extensions list without deleting it for anyone else.\"\n : \" This removes the extension everywhere, for everyone it's shared with.\"}\n </p>\n <div className=\"flex justify-end gap-1\">\n <button\n type=\"button\"\n onClick={() => setConfirmingDelete(false)}\n className=\"rounded-md px-2 py-1 text-[12px] hover:bg-accent cursor-pointer\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={deleteExtension}\n className=\"rounded-md bg-destructive px-2 py-1 text-[12px] text-destructive-foreground hover:bg-destructive/90 cursor-pointer\"\n >\n {canDelete === false ? \"Remove\" : \"Delete\"}\n </button>\n </div>\n </div>\n )}\n </PopoverContent>\n </Popover>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ExtensionViewer.js","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionViewer.tsx"],"names":[],"mappings":"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","sourcesContent":["import { agentNativePath, appPath } from \"../api-path.js\";\nimport { useState, useEffect, useRef, useCallback, useMemo } from \"react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { Link, useLocation, useNavigate } from \"react-router\";\nimport {\n IconArrowLeft,\n IconChevronRight,\n IconDots,\n IconLoader2,\n IconPencil,\n IconRefresh,\n IconTrash,\n IconX,\n} from \"@tabler/icons-react\";\nimport { ShareButton } from \"../sharing/ShareButton.js\";\nimport { AgentToggleButton } from \"../AgentPanel.js\";\nimport { NotificationsBell } from \"../notifications/NotificationsBell.js\";\nimport { sendToAgentChat } from \"../agent-chat.js\";\nimport { PromptComposer } from \"../composer/PromptComposer.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport {\n isAllowedExtensionPath,\n sanitizeExtensionRequestOptions,\n checkBridgePolicy,\n type ExtensionBridgeRole,\n} from \"./iframe-bridge.js\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"../components/ui/tooltip.js\";\nimport {\n deleteOrHideExtension,\n invalidateExtensionRemoval,\n} from \"./delete-extension.js\";\nimport { extensionPath, isExtensionPathname } from \"../../extensions/path.js\";\nimport { buildExtensionHtml } from \"../../extensions/html-shell.js\";\nimport { getThemeVars } from \"../../extensions/theme.js\";\nimport { isEmbedMcpChatBridgeActive } from \"../embed-auth.js\";\n\nconst THEME_CSS_VARS = [\n \"--background\",\n \"--foreground\",\n \"--card\",\n \"--card-foreground\",\n \"--popover\",\n \"--popover-foreground\",\n \"--primary\",\n \"--primary-foreground\",\n \"--secondary\",\n \"--secondary-foreground\",\n \"--muted\",\n \"--muted-foreground\",\n \"--accent\",\n \"--accent-foreground\",\n \"--destructive\",\n \"--destructive-foreground\",\n \"--border\",\n \"--input\",\n \"--ring\",\n \"--radius\",\n \"--sidebar-background\",\n \"--sidebar-foreground\",\n \"--sidebar-primary\",\n \"--sidebar-primary-foreground\",\n \"--sidebar-accent\",\n \"--sidebar-accent-foreground\",\n \"--sidebar-border\",\n \"--sidebar-ring\",\n];\n\nfunction getParentThemeVars(): Record<string, string> {\n const computed = getComputedStyle(document.documentElement);\n const vars: Record<string, string> = {};\n for (const name of THEME_CSS_VARS) {\n const val = computed.getPropertyValue(name).trim();\n if (val) vars[name] = val;\n }\n return vars;\n}\n\ninterface Extension {\n id: string;\n name: string;\n description?: string;\n content?: string;\n updatedAt?: string;\n ownerEmail?: string;\n role?: ExtensionBridgeRole | null;\n canDelete?: boolean;\n}\n\nexport interface ExtensionViewerProps {\n extensionId: string;\n}\n\nfunction readExtensionTitleSuffix(): string | null {\n const current = typeof document !== \"undefined\" ? document.title.trim() : \"\";\n const match = current.match(/^(?:Extension|Tool)s?\\s+(?:\\u2014|-)\\s+(.+)$/);\n return match?.[1]?.trim() || null;\n}\n\nfunction extensionDocumentTitle(name: string, suffix: string | null): string {\n return suffix ? `${name} \\u2014 ${suffix}` : `${name} \\u2014 Extensions`;\n}\n\nfunction extensionRole(value: unknown): ExtensionBridgeRole {\n return value === \"owner\" ||\n value === \"admin\" ||\n value === \"editor\" ||\n value === \"viewer\"\n ? value\n : \"viewer\";\n}\n\nfunction buildExtensionViewerSrcDoc(\n extension: Extension,\n isDark: boolean,\n): string {\n const role = extensionRole(extension.role);\n return buildExtensionHtml(\n extension.content ?? \"\",\n getThemeVars(isDark),\n isDark,\n extension.id,\n {\n authorEmail: extension.ownerEmail ?? \"\",\n viewerEmail: \"\",\n isAuthor: role === \"owner\",\n role,\n },\n );\n}\n\nfunction applyCanonicalLink(path: string): () => void {\n if (typeof document === \"undefined\" || typeof window === \"undefined\") {\n return () => {};\n }\n\n let link = document.querySelector<HTMLLinkElement>('link[rel=\"canonical\"]');\n const created = !link;\n const previousHref = link?.getAttribute(\"href\") ?? null;\n const previousMarker = link?.dataset.agentNativeExtensionCanonical;\n\n if (!link) {\n link = document.createElement(\"link\");\n link.rel = \"canonical\";\n document.head.appendChild(link);\n }\n\n link.dataset.agentNativeExtensionCanonical = \"true\";\n link.href = new URL(appPath(path), window.location.origin).toString();\n\n return () => {\n if (!link) return;\n if (created) {\n link.remove();\n return;\n }\n if (previousHref === null) {\n link.removeAttribute(\"href\");\n } else {\n link.href = previousHref;\n }\n if (previousMarker === undefined) {\n delete link.dataset.agentNativeExtensionCanonical;\n } else {\n link.dataset.agentNativeExtensionCanonical = previousMarker;\n }\n };\n}\n\nfunction EditToolPopover({\n extension,\n onOpenChange,\n}: {\n extension: Extension;\n onOpenChange?: (open: boolean) => void;\n}) {\n const [open, setOpen] = useState(false);\n const setOpenAndNotify = (v: boolean) => {\n setOpen(v);\n onOpenChange?.(v);\n };\n\n // Radix's outside-click detection runs in the parent document, so a click\n // inside the extension iframe (or any other iframe) never fires it. The browser\n // does shift focus to the iframe though, which blurs the parent window — we\n // hook that to close the popover so it behaves like a normal click-outside.\n useEffect(() => {\n if (!open) return;\n const handleBlur = () => {\n // Defer until after the focus actually lands so document.activeElement\n // reflects the iframe (or whatever the user clicked on).\n setTimeout(() => {\n if (document.activeElement?.tagName === \"IFRAME\")\n setOpenAndNotify(false);\n }, 0);\n };\n window.addEventListener(\"blur\", handleBlur);\n return () => window.removeEventListener(\"blur\", handleBlur);\n }, [open]);\n\n const handleSubmit = (text: string) => {\n const trimmed = text.trim();\n if (!trimmed) return;\n sendToAgentChat({\n message: `Update extension \"${extension.name}\" (${extension.id}): ${trimmed}`,\n context: [\n `The user is viewing extension \"${extension.name}\" (id: ${extension.id}) and wants to edit it.`,\n \"This is an existing sandboxed Alpine.js extension stored in SQL. Use list-extensions/update-extension for this extension id.\",\n \"Do not call connect-builder and do not route this to a source-code change flow.\",\n ].join(\"\\n\"),\n submit: true,\n openSidebar: true,\n newTab: true,\n });\n setOpenAndNotify(false);\n };\n\n return (\n <Popover open={open} onOpenChange={setOpenAndNotify}>\n <Tooltip>\n <TooltipTrigger asChild>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex items-center justify-center rounded-md h-8 w-8 text-muted-foreground hover:bg-accent hover:text-accent-foreground cursor-pointer\"\n >\n <IconPencil className=\"h-4 w-4\" />\n </button>\n </PopoverTrigger>\n </TooltipTrigger>\n <TooltipContent>Edit</TooltipContent>\n </Tooltip>\n <PopoverContent align=\"end\" sideOffset={6} className=\"w-[420px] p-3\">\n <p className=\"px-1 pb-2 text-sm font-semibold text-foreground\">\n Edit extension\n </p>\n <PromptComposer\n autoFocus\n placeholder=\"What would you like to change?\"\n draftScope={`extensions:edit:${extension.id}`}\n onSubmit={handleSubmit}\n />\n </PopoverContent>\n </Popover>\n );\n}\n\nexport function ExtensionViewer({ extensionId }: ExtensionViewerProps) {\n const location = useLocation();\n const navigate = useNavigate();\n const [isDark, setIsDark] = useState(false);\n const [iframeReady, setIframeReady] = useState(false);\n const iframeRef = useRef<HTMLIFrameElement | null>(null);\n const toolRef = useRef<Extension | null>(null);\n const [isRenaming, setIsRenaming] = useState(false);\n const [renameValue, setRenameValue] = useState(\"\");\n const [refreshKey, setRefreshKey] = useState(0);\n const renameInputRef = useRef<HTMLInputElement | null>(null);\n const titleSuffixRef = useRef<string | null | undefined>(undefined);\n // Tracks how many toolbar popovers are open. Iframes capture pointer events\n // from areas they visually overlap, so when a popover opens above the iframe,\n // hover and click on the popover items get swallowed by the iframe. Disabling\n // pointer-events on the iframe while any popover is open lets the popover\n // receive its own events. Each popover increments on open / decrements on\n // close, so concurrent popovers (rare) compose correctly.\n const [openPopoverCount, setOpenPopoverCount] = useState(0);\n const onPopoverOpenChange = useCallback((open: boolean) => {\n setOpenPopoverCount((c) => Math.max(0, c + (open ? 1 : -1)));\n }, []);\n const queryClient = useQueryClient();\n // (audit H4) Role plumbed through from the iframe's render binding. Until\n // the iframe announces its role we deny non-trivial helper calls — that\n // way a malicious extension body that races the announcement can't briefly\n // operate at higher privilege than the viewer's actual role.\n const bridgeContextRef = useRef<{\n role: ExtensionBridgeRole;\n isAuthor: boolean;\n }>({\n role: \"viewer\",\n isAuthor: false,\n });\n\n useEffect(() => {\n setIsDark(document.documentElement.classList.contains(\"dark\"));\n\n const observer = new MutationObserver(() => {\n setIsDark(document.documentElement.classList.contains(\"dark\"));\n });\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\"],\n });\n return () => observer.disconnect();\n }, []);\n\n const sendThemeToIframe = () => {\n const win = iframeRef.current?.contentWindow;\n if (!win) return;\n win.postMessage(\n {\n type: \"agent-native-theme-update\",\n isDark: document.documentElement.classList.contains(\"dark\"),\n vars: getParentThemeVars(),\n },\n \"*\",\n );\n };\n\n useEffect(() => {\n if (!iframeReady) return;\n sendThemeToIframe();\n }, [isDark, iframeReady]);\n\n useEffect(() => {\n const handleMessage = async (event: MessageEvent) => {\n if (event.source !== iframeRef.current?.contentWindow) return;\n const message = event.data;\n if (!message) return;\n\n if (message.type === \"agent-native-extension-binding\") {\n // (audit H4) The iframe announced its render binding. Trust the role\n // value because the iframe's binding is generated server-side in\n // extensions/routes.ts (resolveAccess), not by user-authored content.\n const binding = message.binding ?? {};\n const role: ExtensionBridgeRole =\n binding.role === \"owner\" ||\n binding.role === \"admin\" ||\n binding.role === \"editor\" ||\n binding.role === \"viewer\"\n ? binding.role\n : \"viewer\";\n bridgeContextRef.current = {\n role,\n isAuthor: !!binding.isAuthor,\n };\n return;\n }\n\n if (\n message.type === \"agent-native-extension-consent-granted\" ||\n message.type === \"agent-native-extension-consent-cancelled\"\n ) {\n // (audit C1) The consent stub fired; force a reload of the iframe so\n // the next render returns the extension body (granted) or stays on the\n // stub (cancelled — viewer can also navigate away).\n if (message.type === \"agent-native-extension-consent-granted\") {\n // Invalidate the cached extension record — author may have edited\n // since the cache was warmed.\n queryClient.invalidateQueries({\n queryKey: [\"extension\", extensionId],\n });\n setRefreshKey((k) => k + 1);\n }\n return;\n }\n\n if (message.type === \"agent-native-extension-keydown\") {\n document.dispatchEvent(\n new KeyboardEvent(\"keydown\", {\n key: message.key,\n code: message.code,\n metaKey: !!message.metaKey,\n ctrlKey: !!message.ctrlKey,\n shiftKey: !!message.shiftKey,\n altKey: !!message.altKey,\n bubbles: true,\n cancelable: true,\n }),\n );\n return;\n }\n\n if (message.type === \"agent-native-extension-error-fix\") {\n const t = toolRef.current;\n if (!t) return;\n const errors: string[] = message.errors || [];\n const errorDetails: Array<{ message: string; stack: string }> =\n message.errorDetails || [];\n const consoleLogs: Array<{ level: string; message: string }> =\n message.consoleLogs || [];\n const networkLogs: Array<{\n path: string;\n method: string;\n ok?: boolean;\n status?: number;\n error?: string;\n }> = message.networkLogs || [];\n\n const detailedTrace = errorDetails\n .map((e) => (e.stack ? `${e.message}\\n${e.stack}` : e.message))\n .join(\"\\n\\n\");\n\n // Force a fresh read from the server. toolRef.current is bound to the\n // React Query cache, which is the same state the agent's previous\n // (broken) turn just wrote — without this, Fix-in-same-chat ends up\n // patching the agent's prior attempt from chat history instead of the\n // current DB row, which is why users had to open a new chat to\n // recover. Cache-bust so we never read a stale fetch.\n let freshContent: string | undefined;\n try {\n const res = await fetch(\n agentNativePath(`/_agent-native/extensions/${t.id}`),\n { cache: \"no-store\" },\n );\n if (res.ok) {\n const fresh = (await res.json()) as Extension;\n freshContent =\n typeof fresh?.content === \"string\" ? fresh.content : undefined;\n }\n } catch {\n // Fall through with the cached value — agent can still re-read via\n // its get-extension tool.\n }\n\n const contextParts = [\n `The user is viewing extension \"${t.name}\" (id: ${t.id}) and there are runtime errors that need fixing.`,\n `\\nFull error details:\\n${detailedTrace}`,\n ];\n\n if (consoleLogs.length > 0) {\n const consoleStr = consoleLogs\n .map((l) => `[${l.level}] ${l.message}`)\n .join(\"\\n\");\n contextParts.push(`\\nRecent console output:\\n${consoleStr}`);\n }\n\n if (networkLogs.length > 0) {\n const netStr = networkLogs\n .map(\n (l) =>\n `${l.method} ${l.path} → ${l.ok ? l.status : \"FAILED: \" + (l.error || l.status)}`,\n )\n .join(\"\\n\");\n contextParts.push(`\\nRecent network requests:\\n${netStr}`);\n }\n\n if (freshContent) {\n contextParts.push(\n `\\nCurrent extension content (just re-read from the database — this is the authoritative source, not anything you may have written in a previous turn):\\n\\`\\`\\`html\\n${freshContent}\\n\\`\\`\\``,\n );\n }\n\n sendToAgentChat({\n message: `Fix runtime errors in this extension. The content snapshot below was just re-read from the database — treat it as authoritative and ignore any prior version you may have generated in this chat. If in doubt, call get-extension first.\\n\\nErrors:\\n${errors.join(\"\\n\")}`,\n context: contextParts.join(\"\\n\"),\n submit: true,\n openSidebar: true,\n });\n return;\n }\n\n if (message.type !== \"agent-native-extension-request\") return;\n\n const requestId = String(message.requestId ?? \"\");\n const path = String(message.path ?? \"\");\n const respond = (payload: Record<string, unknown>) => {\n iframeRef.current?.contentWindow?.postMessage(\n {\n type: \"agent-native-extension-response\",\n requestId,\n ...payload,\n },\n \"*\",\n );\n };\n\n if (!requestId || !isAllowedExtensionPath(path, extensionId)) {\n respond({ error: \"Extension request path is not allowed\" });\n return;\n }\n\n try {\n const options = sanitizeExtensionRequestOptions(message.options);\n // (audit H4) Role-aware policy gate: viewer-shared extensions can read\n // but not write. Decided here in the parent before the request\n // leaves; the server enforces a second layer.\n const policy = checkBridgePolicy(\n path,\n options.method ?? \"GET\",\n bridgeContextRef.current,\n );\n if (!policy.ok) {\n respond({\n response: {\n ok: false,\n status: 403,\n statusText: \"Forbidden\",\n body: { error: policy.error },\n },\n });\n return;\n }\n // (audit H5) Tag every outbound bridge request with the\n // X-Agent-Native-Extension-Bridge sentinel so the action-routes layer can\n // enforce per-action `toolCallable` opt-in. The header is added by\n // the parent — it is NOT taken from the iframe-supplied options\n // (which were filtered by sanitizeExtensionRequestOptions).\n const finalHeaders = new Headers(options.headers ?? undefined);\n finalHeaders.set(\"X-Agent-Native-Extension-Bridge\", \"1\");\n finalHeaders.set(\"X-Agent-Native-Extension-Id\", extensionId);\n finalHeaders.set(\"X-Agent-Native-Tool-Bridge\", \"1\");\n finalHeaders.set(\"X-Agent-Native-Tool-Id\", extensionId);\n const res = await fetch(agentNativePath(path), {\n ...options,\n headers: finalHeaders,\n credentials: \"same-origin\",\n });\n const text = await res.text();\n let body: unknown = text;\n if (text) {\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n }\n respond({\n response: {\n ok: res.ok,\n status: res.status,\n statusText: res.statusText,\n body,\n },\n });\n } catch (err: any) {\n respond({ error: err?.message ?? \"Extension host request failed\" });\n }\n };\n\n window.addEventListener(\"message\", handleMessage);\n return () => window.removeEventListener(\"message\", handleMessage);\n }, [extensionId, queryClient]);\n\n const { data: extension, isLoading } = useQuery<Extension | null>({\n queryKey: [\"extension\", extensionId],\n queryFn: async () => {\n const res = await fetch(\n agentNativePath(`/_agent-native/extensions/${extensionId}`),\n );\n if (res.status === 403 || res.status === 404) return null;\n if (!res.ok) throw new Error(\"Failed to fetch extension\");\n return res.json();\n },\n });\n\n toolRef.current = extension ?? null;\n\n useEffect(() => {\n if (!extension) return;\n const canonicalPath = extensionPath(extension.id, extension.name);\n if (titleSuffixRef.current === undefined) {\n titleSuffixRef.current = readExtensionTitleSuffix();\n }\n document.title = extensionDocumentTitle(\n extension.name,\n titleSuffixRef.current,\n );\n\n if (\n isExtensionPathname(location.pathname, extension.id) &&\n location.pathname !== canonicalPath\n ) {\n navigate(`${canonicalPath}${location.search}${location.hash}`, {\n replace: true,\n });\n }\n\n return applyCanonicalLink(canonicalPath);\n }, [extension, location.hash, location.pathname, location.search, navigate]);\n\n const iframeSrc = useMemo(\n () =>\n agentNativePath(\n `/_agent-native/extensions/${extensionId}/render?dark=${document.documentElement.classList.contains(\"dark\")}&v=${encodeURIComponent(extension?.updatedAt ?? \"\")}&r=${refreshKey}`,\n ),\n [extensionId, extension?.updatedAt, refreshKey],\n );\n const iframeSrcDoc = useMemo(() => {\n if (!extension?.content || !isEmbedMcpChatBridgeActive()) return undefined;\n return buildExtensionViewerSrcDoc(extension, isDark);\n }, [extension, isDark]);\n\n useEffect(() => {\n setIframeReady(false);\n // Reset role to deny-by-default on every reload — the new render's\n // binding announcement re-establishes the role before any helper call.\n bridgeContextRef.current = { role: \"viewer\", isAuthor: false };\n }, [extensionId, extension?.updatedAt, refreshKey]);\n\n const startRename = useCallback(() => {\n if (!extension) return;\n setRenameValue(extension.name);\n setIsRenaming(true);\n requestAnimationFrame(() => renameInputRef.current?.select());\n }, [extension]);\n\n const submitRename = useCallback(async () => {\n const trimmed = renameValue.trim();\n if (!trimmed || !extension || trimmed === extension.name) {\n setIsRenaming(false);\n return;\n }\n queryClient.setQueryData<Extension>([\"extension\", extensionId], (old) =>\n old ? { ...old, name: trimmed } : old,\n );\n queryClient.setQueryData<Extension[]>([\"extensions\"], (old) =>\n (old ?? []).map((t) =>\n t.id === extensionId ? { ...t, name: trimmed } : t,\n ),\n );\n setIsRenaming(false);\n try {\n await fetch(agentNativePath(`/_agent-native/extensions/${extensionId}`), {\n method: \"PUT\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ name: trimmed }),\n });\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n queryClient.invalidateQueries({ queryKey: [\"extensions\"] });\n } catch {\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n queryClient.invalidateQueries({ queryKey: [\"extensions\"] });\n }\n }, [renameValue, extension, extensionId, queryClient]);\n\n if (isLoading) {\n return (\n <div className=\"flex h-full flex-col\">\n <div className=\"flex h-12 items-center gap-2 px-3 border-b shrink-0\">\n <div className=\"h-3.5 w-3.5 rounded bg-muted animate-pulse\" />\n <div className=\"h-3.5 w-24 rounded bg-muted animate-pulse\" />\n </div>\n <div className=\"flex-1 bg-muted/20 animate-pulse\" />\n </div>\n );\n }\n\n if (!extension) {\n return (\n <div className=\"flex h-full items-center justify-center text-sm text-muted-foreground\">\n Extension not found\n </div>\n );\n }\n\n return (\n <TooltipProvider delayDuration={200}>\n <div className=\"flex h-full w-full flex-col\">\n <div className=\"flex h-12 shrink-0 items-center justify-between gap-3 border-b px-3\">\n <div className=\"flex min-w-0 items-center gap-3\">\n <Tooltip>\n <TooltipTrigger asChild>\n <Link\n to=\"/\"\n className=\"inline-flex h-8 shrink-0 items-center justify-center gap-1.5 rounded-md px-2 text-xs font-medium text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n aria-label=\"Back to app\"\n >\n <IconArrowLeft className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">Back to app</span>\n </Link>\n </TooltipTrigger>\n <TooltipContent>Back to app</TooltipContent>\n </Tooltip>\n <nav\n aria-label=\"Extension breadcrumb\"\n className=\"group/name flex min-w-0 items-center gap-1 text-sm\"\n >\n <Link\n to=\"/extensions\"\n className=\"shrink-0 text-muted-foreground hover:text-foreground\"\n >\n Extensions\n </Link>\n <IconChevronRight className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground/60\" />\n {isRenaming ? (\n <input\n ref={renameInputRef}\n value={renameValue}\n onChange={(e) => setRenameValue(e.target.value)}\n onBlur={submitRename}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") submitRename();\n if (e.key === \"Escape\") setIsRenaming(false);\n }}\n className=\"min-w-0 bg-transparent px-0 py-0 text-sm font-medium outline-none border-b border-primary\"\n />\n ) : (\n <>\n <span className=\"truncate text-sm font-medium\">\n {extension.name}\n </span>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={startRename}\n className=\"shrink-0 cursor-pointer rounded p-0.5 text-muted-foreground/40 opacity-0 group-hover/name:opacity-100 hover:text-foreground\"\n >\n <IconPencil className=\"h-3 w-3\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>Rename</TooltipContent>\n </Tooltip>\n </>\n )}\n </nav>\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={() => setRefreshKey((k) => k + 1)}\n className=\"inline-flex items-center justify-center rounded-md h-8 w-8 text-muted-foreground hover:bg-accent hover:text-accent-foreground cursor-pointer\"\n >\n <IconRefresh className=\"h-4 w-4\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>Refresh</TooltipContent>\n </Tooltip>\n <EditToolPopover\n extension={extension}\n onOpenChange={onPopoverOpenChange}\n />\n <ShareButton\n resourceType=\"extension\"\n resourceId={extensionId}\n resourceTitle={extension.name}\n onOpenChange={onPopoverOpenChange}\n accessNote={\n <>\n Extensions can be shared inside your organization only — they\n run with the viewer's credentials, so cross-org access isn't\n supported.\n </>\n }\n />\n <ToolMoreMenu\n extensionId={extensionId}\n toolName={extension.name}\n canDelete={extension.canDelete}\n onOpenChange={onPopoverOpenChange}\n />\n <NotificationsBell />\n <AgentToggleButton />\n </div>\n </div>\n <div className=\"relative flex-1 min-h-0\">\n {!iframeReady && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-background z-10\">\n <IconLoader2\n className=\"size-5 animate-spin text-muted-foreground\"\n role=\"status\"\n aria-label=\"Loading\"\n />\n </div>\n )}\n <iframe\n ref={iframeRef}\n key={`${extension.updatedAt}-${refreshKey}`}\n src={iframeSrcDoc ? undefined : iframeSrc}\n srcDoc={iframeSrcDoc}\n className=\"h-full w-full border-0\"\n sandbox=\"allow-scripts allow-forms\"\n title={extension.name}\n style={{\n pointerEvents: openPopoverCount > 0 ? \"none\" : \"auto\",\n }}\n onLoad={() => {\n sendThemeToIframe();\n setTimeout(() => setIframeReady(true), 150);\n }}\n />\n </div>\n </div>\n </TooltipProvider>\n );\n}\n\ninterface SlotDeclaration {\n id: string;\n extensionId: string;\n slotId: string;\n}\n\nfunction ToolMoreMenu({\n extensionId,\n toolName,\n canDelete,\n onOpenChange,\n}: {\n extensionId: string;\n toolName: string;\n canDelete?: boolean;\n onOpenChange?: (open: boolean) => void;\n}) {\n const [open, setOpen] = useState(false);\n const [confirmingDelete, setConfirmingDelete] = useState(false);\n const queryClient = useQueryClient();\n const navigate = useNavigate();\n const setOpenAndNotify = (v: boolean) => {\n setOpen(v);\n onOpenChange?.(v);\n };\n\n const { data: slots = [] } = useQuery<SlotDeclaration[]>({\n queryKey: [\"extension-slots\", extensionId],\n queryFn: async () => {\n const res = await fetch(\n agentNativePath(`/_agent-native/slots/extension/${extensionId}`),\n );\n if (!res.ok) return [];\n return res.json();\n },\n enabled: open,\n });\n\n const closeMenu = () => {\n setOpenAndNotify(false);\n setConfirmingDelete(false);\n };\n\n const removeFromSlot = async (slotId: string) => {\n try {\n await fetch(\n agentNativePath(\n `/_agent-native/slots/${encodeURIComponent(slotId)}/install/${encodeURIComponent(extensionId)}`,\n ),\n { method: \"DELETE\" },\n );\n } finally {\n queryClient.invalidateQueries({ queryKey: [\"slot-installs\", slotId] });\n }\n };\n\n const deleteExtension = async () => {\n closeMenu();\n try {\n await deleteOrHideExtension({ id: extensionId, canDelete });\n invalidateExtensionRemoval(queryClient, extensionId);\n slots.forEach((s) =>\n queryClient.invalidateQueries({\n queryKey: [\"slot-installs\", s.slotId],\n }),\n );\n navigate(\"/extensions\");\n } catch {\n queryClient.invalidateQueries({ queryKey: [\"extension\", extensionId] });\n }\n };\n\n return (\n <Popover\n open={open}\n onOpenChange={(o) => {\n setOpenAndNotify(o);\n if (!o) setConfirmingDelete(false);\n }}\n >\n <Tooltip>\n <TooltipTrigger asChild>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex items-center justify-center rounded-md h-8 w-8 text-muted-foreground hover:bg-accent hover:text-accent-foreground cursor-pointer\"\n aria-label=\"More options\"\n >\n <IconDots className=\"h-4 w-4\" />\n </button>\n </PopoverTrigger>\n </TooltipTrigger>\n <TooltipContent>More options</TooltipContent>\n </Tooltip>\n <PopoverContent align=\"end\" sideOffset={4} className=\"w-72 p-0\">\n {!confirmingDelete ? (\n <>\n <div className=\"px-3 py-2 border-b border-border/40\">\n <p className=\"text-[12px] font-medium\">Appears in</p>\n {slots.length === 0 ? (\n <p className=\"text-[11px] text-muted-foreground/70 mt-0.5\">\n Not installed in any widget areas. Ask the agent to add it\n somewhere.\n </p>\n ) : (\n <p className=\"text-[11px] text-muted-foreground/70 mt-0.5\">\n This extension can render in {slots.length} widget area\n {slots.length === 1 ? \"\" : \"s\"}.\n </p>\n )}\n </div>\n {slots.length > 0 && (\n <div className=\"max-h-48 overflow-y-auto py-1\">\n {slots.map((s) => (\n <div\n key={s.id}\n className=\"flex items-center gap-2 px-3 py-1.5 text-[12px]\"\n >\n <span className=\"flex-1 truncate font-mono text-[11px] text-muted-foreground\">\n {s.slotId}\n </span>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={() => removeFromSlot(s.slotId)}\n className=\"rounded p-1 text-muted-foreground/60 hover:bg-accent hover:text-foreground cursor-pointer\"\n aria-label=\"Remove from this widget area\"\n >\n <IconX className=\"h-3.5 w-3.5\" />\n </button>\n </TooltipTrigger>\n <TooltipContent>\n Remove from this widget area (for me)\n </TooltipContent>\n </Tooltip>\n </div>\n ))}\n </div>\n )}\n <div className=\"border-t border-border/40 p-1\">\n <button\n type=\"button\"\n onClick={() => setConfirmingDelete(true)}\n className=\"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-[12px] text-destructive hover:bg-destructive/10 cursor-pointer text-left\"\n >\n <IconTrash className=\"h-3.5 w-3.5\" />\n <span>\n {canDelete === false\n ? \"Remove from my list...\"\n : \"Delete extension...\"}\n </span>\n </button>\n </div>\n </>\n ) : (\n <div className=\"flex flex-col gap-2 p-3\">\n <p className=\"text-[12px]\">\n {canDelete === false ? \"Remove \" : \"Delete \"}\n <span className=\"font-medium\">{toolName}</span>?\n {canDelete === false\n ? \" This hides it from your Extensions list without deleting it for anyone else.\"\n : \" This removes the extension everywhere, for everyone it's shared with.\"}\n </p>\n <div className=\"flex justify-end gap-1\">\n <button\n type=\"button\"\n onClick={() => setConfirmingDelete(false)}\n className=\"rounded-md px-2 py-1 text-[12px] hover:bg-accent cursor-pointer\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={deleteExtension}\n className=\"rounded-md bg-destructive px-2 py-1 text-[12px] text-destructive-foreground hover:bg-destructive/90 cursor-pointer\"\n >\n {canDelete === false ? \"Remove\" : \"Delete\"}\n </button>\n </div>\n </div>\n )}\n </PopoverContent>\n </Popover>\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExtensionViewer.spec.d.ts","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionViewer.spec.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
// @vitest-environment happy-dom
|
|
3
|
+
import { act } from "react";
|
|
4
|
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
5
|
+
import { createRoot } from "react-dom/client";
|
|
6
|
+
import { MemoryRouter } from "react-router";
|
|
7
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
8
|
+
import { ExtensionViewer } from "./ExtensionViewer.js";
|
|
9
|
+
const embedState = vi.hoisted(() => ({ active: false }));
|
|
10
|
+
vi.mock("../embed-auth.js", () => ({
|
|
11
|
+
ensureEmbedAuthFetchInterceptor: vi.fn(),
|
|
12
|
+
isEmbedMcpChatBridgeActive: () => embedState.active,
|
|
13
|
+
}));
|
|
14
|
+
vi.mock("../sharing/ShareButton.js", () => ({
|
|
15
|
+
ShareButton: () => _jsx("button", { type: "button", children: "Share" }),
|
|
16
|
+
}));
|
|
17
|
+
vi.mock("../AgentPanel.js", () => ({
|
|
18
|
+
AgentToggleButton: () => _jsx("button", { type: "button", children: "Agent" }),
|
|
19
|
+
}));
|
|
20
|
+
vi.mock("../notifications/NotificationsBell.js", () => ({
|
|
21
|
+
NotificationsBell: () => _jsx("button", { type: "button", children: "Notifications" }),
|
|
22
|
+
}));
|
|
23
|
+
vi.mock("../composer/PromptComposer.js", () => ({
|
|
24
|
+
PromptComposer: () => _jsx("div", {}),
|
|
25
|
+
}));
|
|
26
|
+
vi.mock("../components/ui/popover.js", () => ({
|
|
27
|
+
Popover: ({ children }) => (_jsx("div", { children: children })),
|
|
28
|
+
PopoverContent: ({ children }) => (_jsx("div", { children: children })),
|
|
29
|
+
PopoverTrigger: ({ children }) => (_jsx(_Fragment, { children: children })),
|
|
30
|
+
}));
|
|
31
|
+
vi.mock("../components/ui/tooltip.js", () => ({
|
|
32
|
+
Tooltip: ({ children }) => _jsx(_Fragment, { children: children }),
|
|
33
|
+
TooltipContent: ({ children }) => (_jsx("div", { children: children })),
|
|
34
|
+
TooltipProvider: ({ children }) => (_jsx(_Fragment, { children: children })),
|
|
35
|
+
TooltipTrigger: ({ children }) => (_jsx(_Fragment, { children: children })),
|
|
36
|
+
}));
|
|
37
|
+
const extensionResponse = {
|
|
38
|
+
id: "ext-1",
|
|
39
|
+
name: "GitHub Stars Over Time",
|
|
40
|
+
description: "Tracks stars",
|
|
41
|
+
content: "<section>Star history chart</section>",
|
|
42
|
+
updatedAt: "2026-05-22T00:00:00.000Z",
|
|
43
|
+
ownerEmail: "owner@example.test",
|
|
44
|
+
role: "owner",
|
|
45
|
+
canDelete: true,
|
|
46
|
+
};
|
|
47
|
+
describe("ExtensionViewer MCP embeds", () => {
|
|
48
|
+
let container;
|
|
49
|
+
let root;
|
|
50
|
+
let queryClient;
|
|
51
|
+
beforeEach(() => {
|
|
52
|
+
vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
|
|
53
|
+
vi.stubGlobal("fetch", vi.fn(async () => Response.json(extensionResponse)));
|
|
54
|
+
embedState.active = false;
|
|
55
|
+
queryClient = new QueryClient({
|
|
56
|
+
defaultOptions: {
|
|
57
|
+
queries: { retry: false },
|
|
58
|
+
mutations: { retry: false },
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
container = document.createElement("div");
|
|
62
|
+
root = createRoot(container);
|
|
63
|
+
});
|
|
64
|
+
afterEach(() => {
|
|
65
|
+
act(() => root.unmount());
|
|
66
|
+
queryClient.clear();
|
|
67
|
+
container.remove();
|
|
68
|
+
vi.unstubAllGlobals();
|
|
69
|
+
});
|
|
70
|
+
async function renderViewer() {
|
|
71
|
+
await act(async () => {
|
|
72
|
+
root.render(_jsx(QueryClientProvider, { client: queryClient, children: _jsx(MemoryRouter, { initialEntries: ["/extensions/ext-1/github-stars"], children: _jsx(ExtensionViewer, { extensionId: "ext-1" }) }) }));
|
|
73
|
+
});
|
|
74
|
+
await vi.waitFor(() => {
|
|
75
|
+
expect(container.querySelector("iframe")).toBeTruthy();
|
|
76
|
+
});
|
|
77
|
+
return container.querySelector("iframe");
|
|
78
|
+
}
|
|
79
|
+
it("uses the extension render route in the normal app", async () => {
|
|
80
|
+
const iframe = await renderViewer();
|
|
81
|
+
expect(iframe.getAttribute("src")).toContain("/_agent-native/extensions/ext-1/render");
|
|
82
|
+
expect(iframe.getAttribute("srcdoc")).toBeNull();
|
|
83
|
+
expect(iframe.getAttribute("sandbox")).toBe("allow-scripts allow-forms");
|
|
84
|
+
});
|
|
85
|
+
it("uses sandboxed srcdoc inside MCP chat embeds to avoid a blocked nested route frame", async () => {
|
|
86
|
+
embedState.active = true;
|
|
87
|
+
const iframe = await renderViewer();
|
|
88
|
+
expect(iframe.getAttribute("src")).toBeNull();
|
|
89
|
+
expect(iframe.getAttribute("srcdoc")).toContain("Star history chart");
|
|
90
|
+
expect(iframe.getAttribute("srcdoc")).toContain("agent-native-extension-binding");
|
|
91
|
+
expect(iframe.getAttribute("sandbox")).toBe("allow-scripts allow-forms");
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
//# sourceMappingURL=ExtensionViewer.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExtensionViewer.spec.js","sourceRoot":"","sources":["../../../src/client/extensions/ExtensionViewer.spec.tsx"],"names":[],"mappings":";AAAA,gCAAgC;AAChC,OAAc,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAE,UAAU,EAAa,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;AAEzD,EAAE,CAAC,IAAI,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,CAAC;IACjC,+BAA+B,EAAE,EAAE,CAAC,EAAE,EAAE;IACxC,0BAA0B,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,MAAM;CACpD,CAAC,CAAC,CAAC;AAEJ,EAAE,CAAC,IAAI,CAAC,2BAA2B,EAAE,GAAG,EAAE,CAAC,CAAC;IAC1C,WAAW,EAAE,GAAG,EAAE,CAAC,iBAAQ,IAAI,EAAC,QAAQ,sBAAe;CACxD,CAAC,CAAC,CAAC;AAEJ,EAAE,CAAC,IAAI,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,CAAC;IACjC,iBAAiB,EAAE,GAAG,EAAE,CAAC,iBAAQ,IAAI,EAAC,QAAQ,sBAAe;CAC9D,CAAC,CAAC,CAAC;AAEJ,EAAE,CAAC,IAAI,CAAC,uCAAuC,EAAE,GAAG,EAAE,CAAC,CAAC;IACtD,iBAAiB,EAAE,GAAG,EAAE,CAAC,iBAAQ,IAAI,EAAC,QAAQ,8BAAuB;CACtE,CAAC,CAAC,CAAC;AAEJ,EAAE,CAAC,IAAI,CAAC,+BAA+B,EAAE,GAAG,EAAE,CAAC,CAAC;IAC9C,cAAc,EAAE,GAAG,EAAE,CAAC,eAAO;CAC9B,CAAC,CAAC,CAAC;AAEJ,EAAE,CAAC,IAAI,CAAC,6BAA6B,EAAE,GAAG,EAAE,CAAC,CAAC;IAC5C,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAiC,EAAE,EAAE,CAAC,CACxD,wBAAM,QAAQ,GAAO,CACtB;IACD,cAAc,EAAE,CAAC,EAAE,QAAQ,EAAiC,EAAE,EAAE,CAAC,CAC/D,wBAAM,QAAQ,GAAO,CACtB;IACD,cAAc,EAAE,CAAC,EAAE,QAAQ,EAAiC,EAAE,EAAE,CAAC,CAC/D,4BAAG,QAAQ,GAAI,CAChB;CACF,CAAC,CAAC,CAAC;AAEJ,EAAE,CAAC,IAAI,CAAC,6BAA6B,EAAE,GAAG,EAAE,CAAC,CAAC;IAC5C,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAiC,EAAE,EAAE,CAAC,4BAAG,QAAQ,GAAI;IACzE,cAAc,EAAE,CAAC,EAAE,QAAQ,EAAiC,EAAE,EAAE,CAAC,CAC/D,wBAAM,QAAQ,GAAO,CACtB;IACD,eAAe,EAAE,CAAC,EAAE,QAAQ,EAAiC,EAAE,EAAE,CAAC,CAChE,4BAAG,QAAQ,GAAI,CAChB;IACD,cAAc,EAAE,CAAC,EAAE,QAAQ,EAAiC,EAAE,EAAE,CAAC,CAC/D,4BAAG,QAAQ,GAAI,CAChB;CACF,CAAC,CAAC,CAAC;AAEJ,MAAM,iBAAiB,GAAG;IACxB,EAAE,EAAE,OAAO;IACX,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EAAE,cAAc;IAC3B,OAAO,EAAE,uCAAuC;IAChD,SAAS,EAAE,0BAA0B;IACrC,UAAU,EAAE,oBAAoB;IAChC,IAAI,EAAE,OAAO;IACb,SAAS,EAAE,IAAI;CAChB,CAAC;AAEF,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,IAAI,SAAyB,CAAC;IAC9B,IAAI,IAAU,CAAC;IACf,IAAI,WAAwB,CAAC;IAE7B,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,UAAU,CAAC,0BAA0B,EAAE,IAAI,CAAC,CAAC;QAChD,EAAE,CAAC,UAAU,CACX,OAAO,EACP,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CACpD,CAAC;QACF,UAAU,CAAC,MAAM,GAAG,KAAK,CAAC;QAC1B,WAAW,GAAG,IAAI,WAAW,CAAC;YAC5B,cAAc,EAAE;gBACd,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE;gBACzB,SAAS,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE;aAC5B;SACF,CAAC,CAAC;QACH,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1B,WAAW,CAAC,KAAK,EAAE,CAAC;QACpB,SAAS,CAAC,MAAM,EAAE,CAAC;QACnB,EAAE,CAAC,gBAAgB,EAAE,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,KAAK,UAAU,YAAY;QACzB,MAAM,GAAG,CAAC,KAAK,IAAI,EAAE;YACnB,IAAI,CAAC,MAAM,CACT,KAAC,mBAAmB,IAAC,MAAM,EAAE,WAAW,YACtC,KAAC,YAAY,IAAC,cAAc,EAAE,CAAC,gCAAgC,CAAC,YAC9D,KAAC,eAAe,IAAC,WAAW,EAAC,OAAO,GAAG,GAC1B,GACK,CACvB,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE;YACpB,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;QACzD,CAAC,CAAC,CAAC;QACH,OAAO,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAsB,CAAC;IAChE,CAAC;IAED,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;QAEpC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAC1C,wCAAwC,CACzC,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QACjD,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oFAAoF,EAAE,KAAK,IAAI,EAAE;QAClG,UAAU,CAAC,MAAM,GAAG,IAAI,CAAC;QACzB,MAAM,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;QAEpC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC9C,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;QACtE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAC7C,gCAAgC,CACjC,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// @vitest-environment happy-dom\nimport React, { act } from \"react\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { createRoot, type Root } from \"react-dom/client\";\nimport { MemoryRouter } from \"react-router\";\nimport { afterEach, beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { ExtensionViewer } from \"./ExtensionViewer.js\";\n\nconst embedState = vi.hoisted(() => ({ active: false }));\n\nvi.mock(\"../embed-auth.js\", () => ({\n ensureEmbedAuthFetchInterceptor: vi.fn(),\n isEmbedMcpChatBridgeActive: () => embedState.active,\n}));\n\nvi.mock(\"../sharing/ShareButton.js\", () => ({\n ShareButton: () => <button type=\"button\">Share</button>,\n}));\n\nvi.mock(\"../AgentPanel.js\", () => ({\n AgentToggleButton: () => <button type=\"button\">Agent</button>,\n}));\n\nvi.mock(\"../notifications/NotificationsBell.js\", () => ({\n NotificationsBell: () => <button type=\"button\">Notifications</button>,\n}));\n\nvi.mock(\"../composer/PromptComposer.js\", () => ({\n PromptComposer: () => <div />,\n}));\n\nvi.mock(\"../components/ui/popover.js\", () => ({\n Popover: ({ children }: { children: React.ReactNode }) => (\n <div>{children}</div>\n ),\n PopoverContent: ({ children }: { children: React.ReactNode }) => (\n <div>{children}</div>\n ),\n PopoverTrigger: ({ children }: { children: React.ReactNode }) => (\n <>{children}</>\n ),\n}));\n\nvi.mock(\"../components/ui/tooltip.js\", () => ({\n Tooltip: ({ children }: { children: React.ReactNode }) => <>{children}</>,\n TooltipContent: ({ children }: { children: React.ReactNode }) => (\n <div>{children}</div>\n ),\n TooltipProvider: ({ children }: { children: React.ReactNode }) => (\n <>{children}</>\n ),\n TooltipTrigger: ({ children }: { children: React.ReactNode }) => (\n <>{children}</>\n ),\n}));\n\nconst extensionResponse = {\n id: \"ext-1\",\n name: \"GitHub Stars Over Time\",\n description: \"Tracks stars\",\n content: \"<section>Star history chart</section>\",\n updatedAt: \"2026-05-22T00:00:00.000Z\",\n ownerEmail: \"owner@example.test\",\n role: \"owner\",\n canDelete: true,\n};\n\ndescribe(\"ExtensionViewer MCP embeds\", () => {\n let container: HTMLDivElement;\n let root: Root;\n let queryClient: QueryClient;\n\n beforeEach(() => {\n vi.stubGlobal(\"IS_REACT_ACT_ENVIRONMENT\", true);\n vi.stubGlobal(\n \"fetch\",\n vi.fn(async () => Response.json(extensionResponse)),\n );\n embedState.active = false;\n queryClient = new QueryClient({\n defaultOptions: {\n queries: { retry: false },\n mutations: { retry: false },\n },\n });\n container = document.createElement(\"div\");\n root = createRoot(container);\n });\n\n afterEach(() => {\n act(() => root.unmount());\n queryClient.clear();\n container.remove();\n vi.unstubAllGlobals();\n });\n\n async function renderViewer() {\n await act(async () => {\n root.render(\n <QueryClientProvider client={queryClient}>\n <MemoryRouter initialEntries={[\"/extensions/ext-1/github-stars\"]}>\n <ExtensionViewer extensionId=\"ext-1\" />\n </MemoryRouter>\n </QueryClientProvider>,\n );\n });\n await vi.waitFor(() => {\n expect(container.querySelector(\"iframe\")).toBeTruthy();\n });\n return container.querySelector(\"iframe\") as HTMLIFrameElement;\n }\n\n it(\"uses the extension render route in the normal app\", async () => {\n const iframe = await renderViewer();\n\n expect(iframe.getAttribute(\"src\")).toContain(\n \"/_agent-native/extensions/ext-1/render\",\n );\n expect(iframe.getAttribute(\"srcdoc\")).toBeNull();\n expect(iframe.getAttribute(\"sandbox\")).toBe(\"allow-scripts allow-forms\");\n });\n\n it(\"uses sandboxed srcdoc inside MCP chat embeds to avoid a blocked nested route frame\", async () => {\n embedState.active = true;\n const iframe = await renderViewer();\n\n expect(iframe.getAttribute(\"src\")).toBeNull();\n expect(iframe.getAttribute(\"srcdoc\")).toContain(\"Star history chart\");\n expect(iframe.getAttribute(\"srcdoc\")).toContain(\n \"agent-native-extension-binding\",\n );\n expect(iframe.getAttribute(\"sandbox\")).toBe(\"allow-scripts allow-forms\");\n });\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/deploy/build.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;GAYG;AAOH,OAAO,EAML,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/deploy/build.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;GAYG;AAOH,OAAO,EAML,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AAiC7B;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,eAAe,EAAE,EACzB,WAAW,EAAE,MAAM,EAAE,EACrB,kBAAkB,GAAE,MAAM,EAAO,EACjC,OAAO,GAAE,gBAAgB,EAAO,EAChC,aAAa,GAAE,oBAAoB,GAAG,IAAW,GAChD,MAAM,CA6ZR;AA0VD,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAE9C;AAmVD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,gBAAgB,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,UAAU,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,GAAG,CAAC;IACX,KAAK,EAAE,eAAe,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAiBf"}
|
package/dist/deploy/build.js
CHANGED
|
@@ -21,11 +21,9 @@ import { discoverApiRoutes, discoverPlugins, discoverActionFiles, getMissingDefa
|
|
|
21
21
|
import { getWorkspaceCoreExports, } from "./workspace-core.js";
|
|
22
22
|
import { generateActionRegistryForProject } from "../vite/action-types-plugin.js";
|
|
23
23
|
import { mcpEmbedStaticAssetRouteRules } from "../shared/mcp-embed-headers.js";
|
|
24
|
-
import { EMBED_SESSION_COOKIE, EMBED_TOKEN_QUERY_PARAM, } from "../shared/embed-auth.js";
|
|
25
24
|
const cwd = process.cwd();
|
|
26
25
|
const preset = process.env.NITRO_PRESET || "node";
|
|
27
26
|
const DEFAULT_SSR_CACHE_CONTROL = "public, max-age=5, stale-while-revalidate=604800, stale-if-error=3600";
|
|
28
|
-
const AUTHENTICATED_SSR_CACHE_CONTROL = "private, max-age=5, stale-while-revalidate=604800, stale-if-error=3600";
|
|
29
27
|
function normalizeConfiguredAppBasePath() {
|
|
30
28
|
const raw = process.env.VITE_APP_BASE_PATH || process.env.APP_BASE_PATH;
|
|
31
29
|
if (!raw || raw === "/")
|
|
@@ -264,62 +262,21 @@ function injectHeadScript(html, script) {
|
|
|
264
262
|
}
|
|
265
263
|
|
|
266
264
|
const DEFAULT_SSR_CACHE_CONTROL = ${JSON.stringify(DEFAULT_SSR_CACHE_CONTROL)};
|
|
267
|
-
const AUTHENTICATED_SSR_CACHE_CONTROL = ${JSON.stringify(AUTHENTICATED_SSR_CACHE_CONTROL)};
|
|
268
|
-
const EMBED_SESSION_COOKIE = ${JSON.stringify(EMBED_SESSION_COOKIE)};
|
|
269
|
-
const EMBED_TOKEN_QUERY_PARAM = ${JSON.stringify(EMBED_TOKEN_QUERY_PARAM)};
|
|
270
|
-
const ANONYMOUS_SESSION_COOKIE_NAMES = new Set(["an_docs_session"]);
|
|
271
|
-
const BETTER_AUTH_SESSION_COOKIE_RE = /\\.session_(?:token|data)$/;
|
|
272
265
|
|
|
273
|
-
function
|
|
274
|
-
if (ANONYMOUS_SESSION_COOKIE_NAMES.has(name)) return false;
|
|
275
|
-
const bareName = String(name || "").replace(/^__(?:Secure|Host)-/, "");
|
|
276
|
-
return (
|
|
277
|
-
bareName === EMBED_SESSION_COOKIE ||
|
|
278
|
-
bareName === "an_session" ||
|
|
279
|
-
bareName === "an_session_workspace" ||
|
|
280
|
-
bareName.startsWith("an_session_") ||
|
|
281
|
-
bareName === "an.session_token" ||
|
|
282
|
-
bareName === "an.session_data" ||
|
|
283
|
-
BETTER_AUTH_SESSION_COOKIE_RE.test(bareName)
|
|
284
|
-
);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
function requestHasAuthenticatedCookie(cookieHeader) {
|
|
288
|
-
if (!cookieHeader) return false;
|
|
289
|
-
return String(cookieHeader)
|
|
290
|
-
.split(";")
|
|
291
|
-
.map((cookie) => cookie.trim().split("=", 1)[0]?.trim())
|
|
292
|
-
.filter(Boolean)
|
|
293
|
-
.some(isAuthenticatedCookieName);
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
function requestHasAuthSignal(request) {
|
|
297
|
-
const url = new URL(request.url);
|
|
298
|
-
return Boolean(
|
|
299
|
-
request.headers.get("authorization") ||
|
|
300
|
-
requestHasAuthenticatedCookie(request.headers.get("cookie")) ||
|
|
301
|
-
url.searchParams.has(EMBED_TOKEN_QUERY_PARAM) ||
|
|
302
|
-
url.searchParams.has("_session")
|
|
303
|
-
);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
function applyDefaultSsrCacheHeader(headers, status, hasAuthSignal) {
|
|
266
|
+
function applyDefaultSsrCacheHeader(headers, status) {
|
|
307
267
|
if (headers.has("cache-control")) return;
|
|
308
268
|
if (status < 200 || status >= 400) return;
|
|
309
269
|
|
|
310
270
|
const contentType = (headers.get("content-type") || "").toLowerCase();
|
|
311
271
|
if (!contentType.includes("text/html")) return;
|
|
312
272
|
|
|
313
|
-
headers.set(
|
|
314
|
-
"cache-control",
|
|
315
|
-
hasAuthSignal ? AUTHENTICATED_SSR_CACHE_CONTROL : DEFAULT_SSR_CACHE_CONTROL,
|
|
316
|
-
);
|
|
273
|
+
headers.set("cache-control", DEFAULT_SSR_CACHE_CONTROL);
|
|
317
274
|
}
|
|
318
275
|
|
|
319
|
-
async function rewriteMountedResponse(response, basePath
|
|
276
|
+
async function rewriteMountedResponse(response, basePath) {
|
|
320
277
|
const sentryClientConfigScript = getSentryClientConfigScript();
|
|
321
278
|
const headers = new Headers(response.headers);
|
|
322
|
-
applyDefaultSsrCacheHeader(headers, response.status
|
|
279
|
+
applyDefaultSsrCacheHeader(headers, response.status);
|
|
323
280
|
|
|
324
281
|
const location = headers.get("location");
|
|
325
282
|
if (location?.startsWith("/") && !location.startsWith("//")) {
|
|
@@ -435,7 +392,6 @@ ${actionRegistrations.join("\n")}
|
|
|
435
392
|
return new Response(null, { status: 404 });
|
|
436
393
|
}
|
|
437
394
|
const request = requestWithPathname(event.req, p);
|
|
438
|
-
const hasAuthSignal = requestHasAuthSignal(event.req);
|
|
439
395
|
if (event.req.method === "HEAD") {
|
|
440
396
|
const getRequest = requestWithMethod(request, "GET");
|
|
441
397
|
const response = await rrHandler(getRequest);
|
|
@@ -446,10 +402,9 @@ ${actionRegistrations.join("\n")}
|
|
|
446
402
|
headers: response.headers,
|
|
447
403
|
}),
|
|
448
404
|
basePath,
|
|
449
|
-
hasAuthSignal,
|
|
450
405
|
);
|
|
451
406
|
}
|
|
452
|
-
return rewriteMountedResponse(await rrHandler(request), basePath
|
|
407
|
+
return rewriteMountedResponse(await rrHandler(request), basePath);
|
|
453
408
|
}));
|
|
454
409
|
|
|
455
410
|
_handler = app.fetch.bind(app);
|