@opengeni/react 7.4.0 → 7.5.0-canary.36919050519001
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/README.md +124 -27
- package/dist/artifacts-document.js +3 -2
- package/dist/artifacts-presentation.js +3 -2
- package/dist/artifacts-spreadsheet.js +2 -2
- package/dist/artifacts.d.ts +1 -0
- package/dist/artifacts.js +516 -1413
- package/dist/artifacts.js.map +1 -1
- package/dist/{browser-viewer-2E6R2Y4W.js → browser-viewer-Z7S7QEJL.js} +6 -5
- package/dist/chat-interactive-block-UGBTNB3L.js +11 -0
- package/dist/{chunk-Y3QTZN2F.js → chunk-2VFNCX4E.js} +6 -6
- package/dist/{chunk-UDD6DLLT.js → chunk-3IJJEYW4.js} +15 -3
- package/dist/chunk-3IJJEYW4.js.map +1 -0
- package/dist/chunk-4RVYOY4O.js +379 -0
- package/dist/chunk-4RVYOY4O.js.map +1 -0
- package/dist/chunk-5CVXZA3Y.js +292 -0
- package/dist/chunk-5CVXZA3Y.js.map +1 -0
- package/dist/{chunk-5YK2ZDIG.js → chunk-5J4FOW6Q.js} +2 -10
- package/dist/chunk-5J4FOW6Q.js.map +1 -0
- package/dist/{chunk-KVERXCFY.js → chunk-5KYZIQFY.js} +40 -3
- package/dist/chunk-5KYZIQFY.js.map +1 -0
- package/dist/{chunk-KNDIXZN6.js → chunk-7UAMYXJY.js} +25 -18
- package/dist/{chunk-KNDIXZN6.js.map → chunk-7UAMYXJY.js.map} +1 -1
- package/dist/{chunk-SEEVCT36.js → chunk-A4UJB2MM.js} +2 -2
- package/dist/{chunk-X4HIN6TV.js → chunk-AFLPWUQ7.js} +71 -162
- package/dist/chunk-AFLPWUQ7.js.map +1 -0
- package/dist/chunk-B3V6TG77.js +41 -0
- package/dist/chunk-B3V6TG77.js.map +1 -0
- package/dist/{chunk-XEJEOAOV.js → chunk-B7WMS3CS.js} +51 -40
- package/dist/chunk-B7WMS3CS.js.map +1 -0
- package/dist/{chunk-S5JQ4R22.js → chunk-BDKR6BAR.js} +54 -24
- package/dist/chunk-BDKR6BAR.js.map +1 -0
- package/dist/{chunk-4MDLEHXL.js → chunk-DYWBUX5Q.js} +24 -12
- package/dist/chunk-DYWBUX5Q.js.map +1 -0
- package/dist/{chunk-YZ3YYMOM.js → chunk-E3G7SAYZ.js} +252 -624
- package/dist/chunk-E3G7SAYZ.js.map +1 -0
- package/dist/chunk-JT4JW7BC.js +54 -0
- package/dist/chunk-JT4JW7BC.js.map +1 -0
- package/dist/{chunk-5AZSK6MV.js → chunk-LWNLETQT.js} +5 -5
- package/dist/{chunk-USXVQACU.js → chunk-M7LBYP63.js} +5 -4
- package/dist/{chunk-USXVQACU.js.map → chunk-M7LBYP63.js.map} +1 -1
- package/dist/{chunk-L4OSXQ6H.js → chunk-NBOHNRLJ.js} +1289 -1060
- package/dist/chunk-NBOHNRLJ.js.map +1 -0
- package/dist/chunk-RHREZ7BO.js +11 -0
- package/dist/chunk-RHREZ7BO.js.map +1 -0
- package/dist/chunk-SCOTPE2I.js +589 -0
- package/dist/chunk-SCOTPE2I.js.map +1 -0
- package/dist/chunk-WEHMPOXK.js +39 -0
- package/dist/chunk-WEHMPOXK.js.map +1 -0
- package/dist/chunk-WRHIZYZF.js +988 -0
- package/dist/chunk-WRHIZYZF.js.map +1 -0
- package/dist/{chunk-3E2AITTZ.js → chunk-WUISZ3WU.js} +32 -28
- package/dist/{chunk-3E2AITTZ.js.map → chunk-WUISZ3WU.js.map} +1 -1
- package/dist/chunk-XCHWDJ22.js +107 -0
- package/dist/chunk-XCHWDJ22.js.map +1 -0
- package/dist/{chunk-DUEBTL3N.js → chunk-Y2PRMYLC.js} +4 -3
- package/dist/{chunk-DUEBTL3N.js.map → chunk-Y2PRMYLC.js.map} +1 -1
- package/dist/chunk-YBXQDQFX.js +1772 -0
- package/dist/chunk-YBXQDQFX.js.map +1 -0
- package/dist/chunk-YV4L3ILF.js +9 -0
- package/dist/chunk-YV4L3ILF.js.map +1 -0
- package/dist/{chunk-V2ABIVYJ.js → chunk-ZXSEDZP7.js} +70 -6
- package/dist/chunk-ZXSEDZP7.js.map +1 -0
- package/dist/components/artifacts/artifact-chrome.d.ts +120 -0
- package/dist/components/artifacts/artifact-sandbox.d.ts +27 -0
- package/dist/components/artifacts/chat-interactive-block.d.ts +29 -0
- package/dist/components/artifacts/deferred-chat-media.d.ts +15 -0
- package/dist/components/artifacts/editable-artifact-ui.d.ts +2 -1
- package/dist/components/artifacts/editable-artifact-view.d.ts +46 -0
- package/dist/components/artifacts/index.d.ts +7 -0
- package/dist/components/artifacts/latest-task-runner.d.ts +15 -0
- package/dist/components/artifacts/session-artifact-viewer.d.ts +39 -0
- package/dist/components/artifacts/site-view.d.ts +23 -0
- package/dist/components/browser-select-control.d.ts +3 -1
- package/dist/components/code-editor.d.ts +1 -4
- package/dist/components/desktop-viewer.d.ts +1 -1
- package/dist/components/message-timeline.d.ts +20 -3
- package/dist/components/open-geni-links.d.ts +16 -0
- package/dist/components/session-conversation.d.ts +20 -1
- package/dist/components/timeline-pill-geometry.d.ts +8 -0
- package/dist/components/timeline-pill-placement.d.ts +24 -0
- package/dist/components/usage-limit-notice.d.ts +49 -0
- package/dist/components/usage-member-list.d.ts +91 -0
- package/dist/components/usage-meter.d.ts +73 -0
- package/dist/composer.js +5 -5
- package/dist/{computer-viewer-WMJE6OA3.js → computer-viewer-KJWLH3GI.js} +7 -5
- package/dist/connect.js +7 -6
- package/dist/connect.js.map +1 -1
- package/dist/conversation-timeline.d.ts +1 -1
- package/dist/desktop.d.ts +7 -0
- package/dist/desktop.js +26 -0
- package/dist/desktop.js.map +1 -0
- package/dist/editor.d.ts +7 -0
- package/dist/editor.js +21 -0
- package/dist/editor.js.map +1 -0
- package/dist/hooks/latest-question.d.ts +1 -1
- package/dist/hooks/use-composer.d.ts +4 -0
- package/dist/hooks/use-desktop-stream.d.ts +1 -1
- package/dist/hooks/use-usage.d.ts +40 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.js +460 -1386
- package/dist/index.js.map +1 -1
- package/dist/interaction.js +8 -6
- package/dist/interaction.js.map +1 -1
- package/dist/{latest-question-QB4EUCW5.js → latest-question-IS445HOW.js} +3 -3
- package/dist/lib/format.d.ts +6 -1
- package/dist/lib/workbench-peers.d.ts +36 -0
- package/dist/machines.js +2 -2
- package/dist/{markdown-table-layout-PFUEZ2U4.js → markdown-table-layout-QXSLK4BY.js} +37 -5
- package/dist/markdown-table-layout-QXSLK4BY.js.map +1 -0
- package/dist/{queue-surface-implementation-IM2HD3SK.js → queue-surface-implementation-2CAQAIHM.js} +2 -2
- package/dist/realtime.js +3 -3
- package/dist/{sandbox-files-PXPIZAFG.js → sandbox-files-AEJTWGT4.js} +8 -5
- package/dist/sandbox-files-AEJTWGT4.js.map +1 -0
- package/dist/session-ui.d.ts +9 -2
- package/dist/session-ui.js +39 -20
- package/dist/session-ui.js.map +1 -1
- package/dist/session.js +4 -4
- package/dist/sites.js +4 -289
- package/dist/sites.js.map +1 -1
- package/dist/terminal.d.ts +8 -0
- package/dist/terminal.js +31 -0
- package/dist/terminal.js.map +1 -0
- package/dist/timeline/allowance-exhausted-row.d.ts +24 -0
- package/dist/timeline/genie-loading.d.ts +3 -1
- package/dist/timeline/types.d.ts +8 -1
- package/dist/{timeline-annotation-selection-ODLVF4OI.js → timeline-annotation-selection-DMLMM2TX.js} +6 -1
- package/dist/timeline-annotation-selection-DMLMM2TX.js.map +1 -0
- package/dist/timeline-pill-geometry-Z23V243M.js +110 -0
- package/dist/timeline-pill-geometry-Z23V243M.js.map +1 -0
- package/dist/usage/allowance-copy.d.ts +25 -0
- package/dist/usage/summary.d.ts +35 -0
- package/dist/usage.d.ts +13 -0
- package/dist/usage.js +1073 -0
- package/dist/usage.js.map +1 -0
- package/package.json +19 -3
- package/src/artifacts.ts +37 -0
- package/src/components/artifacts/artifact-chrome.tsx +413 -0
- package/src/components/artifacts/artifact-sandbox.tsx +185 -0
- package/src/components/artifacts/chat-interactive-block.tsx +260 -0
- package/src/components/artifacts/deferred-chat-media.tsx +67 -0
- package/src/components/artifacts/editable-artifact-ui.tsx +3 -1
- package/src/components/artifacts/editable-artifact-view.tsx +187 -0
- package/src/components/artifacts/editable-artifact-workbench.tsx +5 -2
- package/src/components/artifacts/editable-document.tsx +34 -36
- package/src/components/artifacts/editable-presentation.tsx +21 -16
- package/src/components/artifacts/index.ts +41 -0
- package/src/components/artifacts/latest-task-runner.ts +49 -0
- package/src/components/artifacts/session-artifact-viewer.tsx +376 -0
- package/src/components/artifacts/site-view.tsx +116 -0
- package/src/components/browser-select-control.tsx +4 -1
- package/src/components/browser-viewer.tsx +81 -22
- package/src/components/code-editor.tsx +13 -16
- package/src/components/computer-viewer.tsx +51 -23
- package/src/components/desktop-viewer.tsx +1 -1
- package/src/components/markdown-table-layout.ts +49 -5
- package/src/components/markdown.tsx +5 -2
- package/src/components/message-timeline.tsx +557 -516
- package/src/components/open-geni-links.tsx +24 -0
- package/src/components/sandbox-terminal.tsx +48 -11
- package/src/components/session-chrome.tsx +22 -3
- package/src/components/session-conversation.tsx +195 -102
- package/src/components/timeline-annotation-selection.tsx +7 -0
- package/src/components/timeline-pill-geometry.ts +169 -0
- package/src/components/timeline-pill-placement.ts +99 -0
- package/src/components/usage-limit-notice.tsx +179 -0
- package/src/components/usage-member-list.tsx +792 -0
- package/src/components/usage-meter.tsx +382 -0
- package/src/conversation-timeline.ts +10 -2
- package/src/desktop.ts +24 -0
- package/src/editor.ts +13 -0
- package/src/hooks/use-available-models.ts +1 -1
- package/src/hooks/use-composer.ts +57 -2
- package/src/hooks/use-desktop-stream.ts +19 -28
- package/src/hooks/use-usage.ts +100 -0
- package/src/index.ts +22 -0
- package/src/lib/format.ts +32 -6
- package/src/lib/workbench-peers.ts +62 -0
- package/src/session-ui.ts +22 -0
- package/src/terminal.ts +26 -0
- package/src/timeline/activity-rail.tsx +5 -3
- package/src/timeline/allowance-exhausted-row.tsx +86 -0
- package/src/timeline/genie-loading.tsx +16 -6
- package/src/timeline/projection.ts +78 -4
- package/src/timeline/types.ts +8 -0
- package/src/usage/allowance-copy.ts +64 -0
- package/src/usage/summary.ts +93 -0
- package/src/usage.ts +50 -0
- package/styles/compiled.css +325 -0
- package/dist/chunk-4MDLEHXL.js.map +0 -1
- package/dist/chunk-5YK2ZDIG.js.map +0 -1
- package/dist/chunk-KVERXCFY.js.map +0 -1
- package/dist/chunk-L4OSXQ6H.js.map +0 -1
- package/dist/chunk-S5JQ4R22.js.map +0 -1
- package/dist/chunk-UDD6DLLT.js.map +0 -1
- package/dist/chunk-UGMKPUEM.js +0 -299
- package/dist/chunk-UGMKPUEM.js.map +0 -1
- package/dist/chunk-V2ABIVYJ.js.map +0 -1
- package/dist/chunk-X4HIN6TV.js.map +0 -1
- package/dist/chunk-XEJEOAOV.js.map +0 -1
- package/dist/chunk-YZ3YYMOM.js.map +0 -1
- package/dist/markdown-table-layout-PFUEZ2U4.js.map +0 -1
- package/dist/timeline-annotation-selection-ODLVF4OI.js.map +0 -1
- /package/dist/{browser-viewer-2E6R2Y4W.js.map → browser-viewer-Z7S7QEJL.js.map} +0 -0
- /package/dist/{computer-viewer-WMJE6OA3.js.map → chat-interactive-block-UGBTNB3L.js.map} +0 -0
- /package/dist/{chunk-Y3QTZN2F.js.map → chunk-2VFNCX4E.js.map} +0 -0
- /package/dist/{chunk-SEEVCT36.js.map → chunk-A4UJB2MM.js.map} +0 -0
- /package/dist/{chunk-5AZSK6MV.js.map → chunk-LWNLETQT.js.map} +0 -0
- /package/dist/{sandbox-files-PXPIZAFG.js.map → computer-viewer-KJWLH3GI.js.map} +0 -0
- /package/dist/{latest-question-QB4EUCW5.js.map → latest-question-IS445HOW.js.map} +0 -0
- /package/dist/{queue-surface-implementation-IM2HD3SK.js.map → queue-surface-implementation-2CAQAIHM.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/artifacts/chat-interactive-block.tsx","../src/components/artifacts/artifact-sandbox.tsx","../src/components/artifacts/deferred-chat-media.tsx","../src/components/artifacts/visualization-assets.gen.ts","../src/components/artifacts/inline-html-document.ts"],"sourcesContent":["import type { OpenGeniClient, ToolGatewayIdentity } from \"@opengeni/sdk\";\nimport { useEffect, useMemo, useState } from \"react\";\n\nimport { loadSiteSnapshot } from \"../../sites-ui\";\nimport { useOpenGeniLinkResolver } from \"../open-geni-links\";\nimport {\n ArtifactButton,\n ArtifactLabelsProvider,\n ArtifactSelect,\n useArtifactLabels,\n type ArtifactLabels,\n} from \"./artifact-chrome\";\nimport { ArtifactSandbox } from \"./artifact-sandbox\";\nimport { DeferredChatMedia } from \"./deferred-chat-media\";\nimport { inlineHtmlDocument } from \"./inline-html-document\";\nimport type { PublishedHtmlArtifactToolBridge } from \"./published-html-artifact-frame\";\n\n// Fixed chat viewports keep async Site loads and fragment resize messages from\n// moving the conversation. Full-screen remains available for larger content.\nconst INLINE_PREVIEW_HEIGHT = 360;\nconst SITE_PREVIEW_HEIGHT = 400;\nconst PREVIEW_CHROME_HEIGHT = 50;\n\n/** Reads a Site needs to render; the console client, the SDK client, or a proxy. */\nexport type SiteSnapshotClient = Pick<\n OpenGeniClient,\n \"getWorkspaceArtifact\" | \"getWorkspaceArtifactHtml\"\n> &\n Partial<Pick<OpenGeniClient, \"getWorkspaceArtifactContent\">>;\n\n/** The exact saved Site a tool bridge is pinned to (absent for inline HTML). */\nexport type SiteToolScope = {\n artifactId: string;\n siteVersionId: string;\n requestedTools: readonly ToolGatewayIdentity[];\n};\n\n/** Host-owned Site API access. Omit it and Sites render without workspace tools. */\nexport type SiteToolBridgeFactory = (\n site?: SiteToolScope,\n) => PublishedHtmlArtifactToolBridge | undefined;\n\nexport type ChatInteractiveBlockProps = {\n workspaceId: string;\n kind: \"html\" | \"site\";\n content: string;\n client: SiteSnapshotClient;\n toolBridge?: SiteToolBridgeFactory | undefined;\n theme?: \"light\" | \"dark\" | undefined;\n /** Translations for the preview's copy; defaults to English. */\n labels?: Partial<ArtifactLabels> | undefined;\n};\n\n/**\n * Inline preview for an assistant `opengeni-html` or `opengeni-site` fence, as\n * the OpenGeni console renders it. \"Open Site\" goes through the nearest\n * `resolveLink`, so a host decides where a Site opens.\n */\nexport function ChatInteractiveBlock({ labels, ...props }: ChatInteractiveBlockProps) {\n return (\n <ArtifactLabelsProvider labels={labels}>\n <InteractiveBlock {...props} />\n </ArtifactLabelsProvider>\n );\n}\n\nfunction InteractiveBlock(props: ChatInteractiveBlockProps) {\n const labels = useArtifactLabels();\n const height =\n (props.kind === \"html\" ? INLINE_PREVIEW_HEIGHT : SITE_PREVIEW_HEIGHT) + PREVIEW_CHROME_HEIGHT;\n return (\n <DeferredChatMedia\n key={`${props.workspaceId}:${props.kind}:${props.kind === \"site\" ? props.content : \"inline\"}`}\n height={height}\n actionLabel={props.kind === \"html\" ? labels.loadPreview : labels.loadSitePreview}\n >\n <div style={{ height }}>\n <LoadedChatInteractiveBlock {...props} />\n </div>\n </DeferredChatMedia>\n );\n}\n\nfunction LoadedChatInteractiveBlock(props: ChatInteractiveBlockProps) {\n const labels = useArtifactLabels();\n if (props.kind === \"html\") return <InlineHtml {...props} />;\n try {\n const value = JSON.parse(props.content);\n if (\n !value ||\n typeof value.siteId !== \"string\" ||\n !/^[0-9a-f-]{36}$/i.test(value.siteId) ||\n (value.versionId !== undefined &&\n (typeof value.versionId !== \"string\" || !/^[0-9a-f-]{36}$/i.test(value.versionId)))\n )\n throw new Error(\"Invalid Site reference\");\n return (\n <SiteEmbed\n key={`${props.workspaceId}:${value.siteId}:${value.versionId ?? \"current\"}`}\n {...props}\n siteId={value.siteId}\n initialVersionId={value.versionId}\n />\n );\n } catch {\n return <p role=\"alert\">{labels.siteReferenceInvalid}</p>;\n }\n}\n\nfunction InlineHtml({ content, toolBridge, theme }: ChatInteractiveBlockProps) {\n const labels = useArtifactLabels();\n const html = useMemo(() => inlineHtmlDocument(content), [content]);\n const bridge = useMemo(() => toolBridge?.(), [toolBridge]);\n return (\n <ArtifactSandbox\n title={labels.preview}\n showTitle={false}\n showLiveStatus={false}\n html={html}\n toolBridge={bridge}\n height={INLINE_PREVIEW_HEIGHT}\n className=\"h-full\"\n fill\n theme={theme}\n />\n );\n}\n\nfunction SiteEmbed(\n props: ChatInteractiveBlockProps & { siteId: string; initialVersionId?: string },\n) {\n const [versionId, setVersionId] = useState(props.initialVersionId);\n return (\n <SiteEmbedContent\n key={versionId ?? \"current\"}\n {...props}\n versionId={versionId}\n onVersionChange={setVersionId}\n />\n );\n}\n\nfunction SiteEmbedContent({\n workspaceId,\n client,\n toolBridge,\n theme,\n siteId,\n versionId,\n onVersionChange,\n}: ChatInteractiveBlockProps & {\n siteId: string;\n versionId?: string | undefined;\n onVersionChange: (id: string) => void;\n}) {\n const [loaded, setLoaded] = useState<{\n client: SiteSnapshotClient;\n snapshot: Awaited<ReturnType<typeof loadSiteSnapshot>>;\n } | null>(null);\n const snapshot = loaded?.client === client ? loaded.snapshot : null;\n const [error, setError] = useState(false);\n const [retry, setRetry] = useState(0);\n useEffect(() => {\n const abort = new AbortController();\n setError(false);\n setLoaded(null);\n void loadSiteSnapshot(client, workspaceId, siteId, {\n signal: abort.signal,\n ...(versionId ? { versionId } : {}),\n })\n .then((value) => {\n if (!abort.signal.aborted) setLoaded({ client, snapshot: value });\n })\n .catch(() => {\n if (!abort.signal.aborted) setError(true);\n });\n return () => abort.abort();\n }, [client, workspaceId, siteId, versionId, retry]);\n const content = snapshot?.content;\n const bridge = useMemo(\n () =>\n content\n ? toolBridge?.({\n artifactId: siteId,\n siteVersionId: content.versionId,\n requestedTools: content.requestedTools,\n })\n : undefined,\n [toolBridge, siteId, content],\n );\n const open = useOpenGeniLinkResolver()?.({ kind: \"site\", artifactId: siteId, workspaceId });\n const labels = useArtifactLabels();\n if (error)\n return (\n <p role=\"alert\">\n {labels.siteLoadFailed}{\" \"}\n <ArtifactButton size=\"sm\" onClick={() => setRetry((v) => v + 1)}>\n {labels.retry}\n </ArtifactButton>\n </p>\n );\n if (!snapshot) return <p role=\"status\">{labels.loadingSite}</p>;\n if (!content) return <p>{labels.siteUnpublished}</p>;\n return (\n <ArtifactSandbox\n title={snapshot.detail.artifact.title}\n html={content.html}\n toolBridge={bridge}\n height={SITE_PREVIEW_HEIGHT}\n className=\"h-full\"\n fill\n theme={theme}\n headerControls={\n <>\n {/* One published version has nothing to choose; keep the bar for the title. */}\n {snapshot.detail.versions.length > 1 ||\n !snapshot.detail.versions.some((v) => v.id === content.versionId) ? (\n <ArtifactSelect\n aria-label={labels.siteVersion}\n className=\"bg-transparent text-xs\"\n value={content.versionId}\n onChange={(e) => onVersionChange(e.target.value)}\n >\n {!snapshot.detail.versions.some((v) => v.id === content.versionId) && (\n <option value={content.versionId}>{labels.savedVersion}</option>\n )}\n {snapshot.detail.versions.map((v) => (\n <option key={v.id} value={v.id}>\n {labels.version(v.revision)}\n </option>\n ))}\n </ArtifactSelect>\n ) : null}\n {open?.href ? (\n <a\n className=\"shrink-0 whitespace-nowrap text-xs underline\"\n href={open.href}\n data-og-open-site=\"\"\n >\n {labels.openSite}\n </a>\n ) : open?.open ? (\n <button\n type=\"button\"\n className=\"shrink-0 cursor-pointer whitespace-nowrap text-xs underline\"\n data-og-open-site=\"\"\n onClick={() =>\n void Promise.resolve()\n .then(open.open)\n .catch(() => undefined)\n }\n >\n {labels.openSite}\n </button>\n ) : null}\n </>\n }\n />\n );\n}\n","import {\n ArrowLeftIcon,\n Globe2Icon,\n Maximize2Icon,\n PlugZapIcon,\n RefreshCwIcon,\n SparklesIcon,\n} from \"lucide-react\";\nimport { useLayoutEffect, useRef, useState, type ReactNode } from \"react\";\n\nimport { cn } from \"../../lib/cn\";\nimport { ArtifactBadge, ArtifactButton, useArtifactLabels } from \"./artifact-chrome\";\nimport {\n PublishedHtmlArtifactFrame,\n type PublishedHtmlArtifactToolBridge,\n} from \"./published-html-artifact-frame\";\n\nexport type ArtifactSandboxProps = {\n html: string;\n height?: number | undefined;\n autoHeight?: boolean | undefined;\n theme?: \"light\" | \"dark\" | undefined;\n headerControls?: ReactNode | undefined;\n title: string;\n /** Hide the visible title/icon while retaining the accessible iframe title. */\n showTitle?: boolean | undefined;\n showLiveStatus?: boolean | undefined;\n versionLabel?: string | undefined;\n className?: string | undefined;\n editDisabled?: boolean | undefined;\n onEdit?: (() => void) | undefined;\n toolBridge?: PublishedHtmlArtifactToolBridge | undefined;\n connectedToolCount?: number | undefined;\n sourceFileCount?: number | undefined;\n fill?: boolean | undefined;\n};\n\n/**\n * The Site/preview frame chrome shared by the console and embedding hosts:\n * title, version and tool badges, live status, reload, and a full-screen mode\n * that escapes the host's scroll containers through the modal top layer.\n */\nexport function ArtifactSandbox(props: ArtifactSandboxProps) {\n const labels = useArtifactLabels();\n const [reloadKey, setReloadKey] = useState(0);\n const [focused, setFocused] = useState(false);\n const frameRef = useRef<HTMLDialogElement>(null);\n const modalRef = useRef(false);\n useLayoutEffect(() => {\n const frame = frameRef.current;\n if (!frame) return;\n if (focused) {\n // A fixed child of the chat timeline is still clipped and layered by its\n // scroll pane and the sibling workspace dock. The modal top layer escapes\n // both while keeping the live Site iframe mounted in the same DOM node.\n frame.close();\n frame.showModal();\n modalRef.current = true;\n } else if (modalRef.current) {\n frame.close();\n frame.show();\n modalRef.current = false;\n }\n }, [focused]);\n const reload = () => {\n setReloadKey((value) => value + 1);\n };\n return (\n <dialog\n ref={frameRef}\n open\n aria-label={props.title}\n onCancel={(event) => {\n event.preventDefault();\n setFocused(false);\n }}\n className={cn(\n \"og-root static m-0 w-full max-h-none max-w-none overflow-hidden rounded-2xl border border-border/80 bg-white p-0 text-left shadow-sm\",\n props.className,\n props.fill && \"flex min-h-0 flex-col\",\n focused &&\n \"fixed inset-0 z-50 flex h-dvh w-dvw flex-col rounded-none border-0 bg-surface shadow-none\",\n )}\n >\n <div className=\"flex min-h-12 shrink-0 items-center justify-between gap-3 border-b border-border/80 bg-surface/95 px-3 sm:px-4\">\n <div className=\"flex min-w-0 items-center gap-2.5\">\n {focused ? (\n <ArtifactButton\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 shrink-0 px-2\"\n onClick={() => setFocused(false)}\n >\n <ArrowLeftIcon className=\"mr-2 size-3.5\" />\n {labels.back}\n </ArtifactButton>\n ) : null}\n {!focused && props.showTitle !== false ? (\n <span className=\"grid size-6 shrink-0 place-items-center rounded-md bg-surface-2 text-fg-muted\">\n <Globe2Icon className=\"size-3.5\" />\n </span>\n ) : null}\n {props.showTitle !== false && (\n <span className=\"truncate text-xs font-semibold text-fg\">{props.title}</span>\n )}\n {props.headerControls}\n {props.versionLabel ? (\n <ArtifactBadge className=\"hidden h-5 rounded-md border-border/80 px-1.5 text-2xs font-normal text-fg-muted sm:inline-flex\">\n {props.versionLabel}\n </ArtifactBadge>\n ) : null}\n {props.connectedToolCount ? (\n <ArtifactBadge\n className=\"hidden h-5 max-w-40 gap-1 rounded-md border-border/80 px-1.5 text-2xs font-normal text-fg-muted sm:inline-flex\"\n title={labels.toolsAvailable(props.connectedToolCount)}\n >\n <PlugZapIcon className=\"size-3\" />\n {labels.toolCount(props.connectedToolCount)}\n </ArtifactBadge>\n ) : null}\n {props.sourceFileCount ? (\n <span className=\"hidden text-2xs text-fg-subtle xl:inline\">\n {labels.sourceFileCount(props.sourceFileCount)}\n </span>\n ) : null}\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n {focused && props.onEdit ? (\n <ArtifactButton\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 px-2\"\n disabled={props.editDisabled}\n onClick={props.onEdit}\n >\n <SparklesIcon className=\"mr-2 size-3.5\" />\n <span className=\"hidden sm:inline\">{labels.editWithAgent}</span>\n <span className=\"sm:hidden\">{labels.editShort}</span>\n </ArtifactButton>\n ) : null}\n {props.showLiveStatus !== false && (\n <span className=\"mr-1 hidden items-center gap-1.5 text-2xs font-medium text-fg-muted sm:inline-flex\">\n <span className=\"size-1.5 rounded-full bg-status-success ring-4 ring-status-success/10\" />\n {labels.live}\n </span>\n )}\n <ArtifactButton\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-8 rounded-md text-fg-muted hover:text-fg\"\n aria-label={labels.reloadSite}\n onClick={reload}\n >\n <RefreshCwIcon className=\"size-3.5\" />\n </ArtifactButton>\n {!focused ? (\n <ArtifactButton\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-8 rounded-md text-fg-muted hover:text-fg\"\n aria-label={labels.openFullScreen}\n onClick={() => setFocused(true)}\n >\n <Maximize2Icon className=\"size-3.5\" />\n </ArtifactButton>\n ) : null}\n </div>\n </div>\n <PublishedHtmlArtifactFrame\n key={reloadKey}\n title={props.title}\n html={props.html}\n autoHeight={Boolean(props.autoHeight && !focused)}\n {...(props.theme ? { theme: props.theme } : {})}\n {...(!focused && props.height ? { style: { height: props.height } } : {})}\n {...(props.toolBridge ? { toolBridge: props.toolBridge } : {})}\n className={cn(\n \"block h-[clamp(30rem,62vh,48rem)] w-full border-0 bg-white\",\n props.fill && \"h-0 min-h-0 flex-1\",\n focused && \"min-h-0 flex-1\",\n )}\n />\n </dialog>\n );\n}\n","import { useEffect, useRef, useState, type ReactNode } from \"react\";\n\n/**\n * Reserve the chat slot before starting expensive media work. Activation is\n * one-way: scrolling away must not discard an interactive preview's state.\n * The timeline parks at its initial tip in layout effects before this observer\n * is attached, so historical previews above the entry viewport stay dormant.\n */\nexport function DeferredChatMedia({\n children,\n height,\n label,\n actionLabel,\n}: {\n children: ReactNode;\n height: number;\n /** What is loading, as in \"Load {label}\". */\n label?: string | undefined;\n /** The complete (translated) activation label; overrides `label`. */\n actionLabel?: string | undefined;\n}) {\n const host = useRef<HTMLDivElement>(null);\n const [active, setActive] = useState(false);\n useEffect(() => {\n const node = host.current;\n if (active || !node) return;\n if (typeof IntersectionObserver === \"undefined\") {\n setActive(true);\n return;\n }\n let disposed = false;\n const observer = new IntersectionObserver(\n (entries) => {\n if (disposed || !entries.some((entry) => entry.isIntersecting)) return;\n setActive(true);\n observer.disconnect();\n },\n {\n root: node.closest(\"[data-og-timeline-scroller]\"),\n rootMargin: \"200px 0px\",\n },\n );\n observer.observe(node);\n return () => {\n disposed = true;\n observer.disconnect();\n };\n }, [active]);\n\n return (\n <div ref={host} data-chat-media={active ? \"active\" : \"deferred\"}>\n {active ? (\n children\n ) : (\n <div className=\"flex w-full items-center justify-center\" style={{ height }}>\n <button\n type=\"button\"\n className=\"rounded-md px-3 py-2 text-sm text-fg-muted hover:text-fg focus-visible:outline-2 focus-visible:outline-ring\"\n onClick={() => setActive(true)}\n >\n {actionLabel ?? `Load ${label ?? \"media\"}`}\n </button>\n </div>\n )}\n </div>\n );\n}\n","// Generated by scripts/generate-visualization-assets.ts.\nexport const VISUALIZATION_CSS = \"/* Adapted from Codex visualize 1.0.32; shared with the OpenGeni visualization skill. */\\n:root {\\n color-scheme: light dark;\\n background-color: var(\\n --background,\\n var(--color-background-primary, light-dark(rgb(255 255 255), rgb(24 24 24)))\\n ) !important;\\n\\n /* Agent-facing contract; keep in sync with SKILL.md. */\\n --background: var(\\n --color-background-primary,\\n light-dark(rgb(255 255 255), rgb(24 24 24))\\n );\\n --foreground: var(\\n --color-text-primary,\\n light-dark(rgb(26 28 31), rgb(255 255 255))\\n );\\n --card: color-mix(in oklab, var(--foreground) 5%, var(--background));\\n --card-foreground: var(\\n --color-text-primary,\\n light-dark(rgb(26 28 31), rgb(255 255 255))\\n );\\n --popover: var(\\n --color-background-secondary,\\n light-dark(rgb(255 255 255), rgb(45 45 45))\\n );\\n --popover-foreground: var(\\n --color-text-primary,\\n light-dark(rgb(26 28 31), rgb(255 255 255))\\n );\\n --primary: var(\\n --color-text-info,\\n light-dark(rgb(51 156 255), rgb(131 195 255))\\n );\\n --primary-foreground: var(\\n --color-text-inverse,\\n light-dark(rgb(255 255 255), rgb(13 13 13))\\n );\\n --secondary: var(\\n --color-background-secondary,\\n light-dark(rgb(255 255 255 / 96%), rgb(54 54 54 / 96%))\\n );\\n --secondary-foreground: var(\\n --color-text-primary,\\n light-dark(rgb(26 28 31), rgb(255 255 255))\\n );\\n --muted: color-mix(in srgb, var(--foreground) 10%, transparent);\\n --muted-foreground: var(\\n --color-text-secondary,\\n light-dark(rgb(26 28 31 / 49.4%), rgb(255 255 255 / 49.8%))\\n );\\n --accent: var(\\n --color-background-info,\\n light-dark(rgb(229 242 255), rgb(13 39 63))\\n );\\n --accent-foreground: var(\\n --color-text-info,\\n light-dark(rgb(51 156 255), rgb(131 195 255))\\n );\\n --destructive: var(\\n --color-text-warning,\\n light-dark(rgb(226 85 7), rgb(255 133 73))\\n );\\n --border: var(\\n --color-border-secondary,\\n light-dark(rgb(26 28 31 / 8%), rgb(255 255 255 / 8.2%))\\n );\\n --input: var(\\n --color-border-primary,\\n light-dark(\\n rgb(26 28 31 / 11.8%),\\n color-mix(in oklab, rgb(0 0 0) 10%, transparent)\\n )\\n );\\n --ring: var(\\n --color-ring-primary,\\n light-dark(rgb(51 156 255), rgb(131 195 255 / 76%))\\n );\\n --font-size-base: var(--font-text-md-size, 14px);\\n --blue: light-dark(rgb(51 156 255), rgb(51 156 255));\\n --orange: light-dark(rgb(226 85 7), rgb(251 106 34));\\n --green: light-dark(rgb(0 162 64), rgb(64 201 119));\\n --red: light-dark(rgb(224 46 42), rgb(255 103 100));\\n --purple: light-dark(rgb(146 79 247), rgb(173 123 249));\\n --yellow: light-dark(rgb(255 195 0), rgb(255 210 64));\\n --viz-series-1: var(--primary);\\n --viz-series-2: light-dark(rgb(243 136 59), rgb(245 154 86));\\n --viz-series-3: light-dark(rgb(93 201 119), rgb(116 213 139));\\n --viz-series-4: light-dark(rgb(235 119 177), rgb(240 143 192));\\n --viz-series-5: light-dark(rgb(155 121 236), rgb(170 145 239));\\n --viz-series-6: light-dark(rgb(58 185 177), rgb(90 203 194));\\n\\n /* Internal implementation variables; not part of the agent contract. */\\n --font-sans: -apple-system, system-ui, \\\"Segoe UI\\\", sans-serif;\\n --font-mono:\\n ui-monospace, SFMono-Regular, \\\"SF Mono\\\", Menlo, Consolas, \\\"Liberation Mono\\\",\\n monospace;\\n --font-size-normal: max(11px, var(--font-size-base));\\n --font-size-tooltip: calc(var(--font-size-base) - 1px);\\n --font-size-small: max(11px, calc(var(--font-size-base) - 2px));\\n --font-size-h1: calc(var(--font-size-normal) * 1.7142857143);\\n --font-size-h2: calc(var(--font-size-normal) * 1.4285714286);\\n --font-size-h3: calc(var(--font-size-normal) * 1.2857142857);\\n --font-weight-normal: 430;\\n --font-weight-medium: 500;\\n --icon-size: 16px;\\n --line-height-normal: calc(var(--font-size-normal) * 1.5);\\n --line-height-tooltip: calc(var(--font-size-tooltip) * 1.4285714286);\\n --line-height-small: calc(var(--font-size-small) + 4px);\\n --corner-shape: round;\\n --radius: var(--border-radius-lg, 10px);\\n --radius-sm: calc(var(--radius) * 0.6);\\n --radius-md: calc(var(--radius) * 0.8);\\n --radius-lg: var(--radius);\\n --radius-2xl: calc(var(--radius) * 1.6);\\n --radius-full: 9999px;\\n --shadow-sm: 0 1px 2px -1px rgb(0 0 0 / 8%);\\n --checkmark-image: url(\\\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 17 17'%3E%3Cpath d='M 12.8961 3.64101C13.1297 3.41418 13.4984 3.37523 13.7779 3.56581C14.0571 3.75635 14.1554 4.11331 14.0299 4.41347L13.9615 4.53847L7.71151 13.7045C7.59411 13.8767 7.4063 13.9877 7.19881 14.0072C6.99136 14.0267 6.78564 13.9533 6.63826 13.806L2.88826 10.056L2.79842 9.9457C2.6192 9.67407 2.64927 9.30496 2.88826 9.06581C3.12738 8.82669 3.49647 8.79676 3.76815 8.97597L3.8785 9.06581L7.03084 12.2182L12.8053 3.74941L12.8961 3.64101Z'/%3E%3C/svg%3E\\\");\\n\\n /* Legacy aliases; not part of the current agent contract. */\\n --viz-bg: transparent;\\n --viz-panel: var(--card);\\n --viz-border: var(--border);\\n --viz-text: var(--foreground);\\n --viz-muted: var(--muted-foreground);\\n --viz-accent: var(--primary);\\n --viz-accent-text: var(--primary-foreground);\\n --viz-accent-bg: var(--accent);\\n --viz-font-size: var(--font-size-base);\\n --viz-warning: var(--destructive);\\n}\\n\\n:root[data-theme=\\\"light\\\"] {\\n color-scheme: light;\\n}\\n\\n:root[data-theme=\\\"dark\\\"] {\\n color-scheme: dark;\\n}\\n\\n* {\\n box-sizing: border-box;\\n}\\n\\nhtml > body {\\n /* Preserve MCP aliases for older inline renderers without creating :root cycles. */\\n --color-background-primary: var(\\n --background,\\n light-dark(rgb(255 255 255), rgb(24 24 24))\\n );\\n --color-text-primary: var(\\n --foreground,\\n light-dark(rgb(26 28 31), rgb(255 255 255))\\n );\\n --color-border-secondary: var(\\n --border,\\n light-dark(rgb(26 28 31 / 8%), rgb(255 255 255 / 8.2%))\\n );\\n\\n margin: 0;\\n padding: var(--visualize-paint-gutter, 16px);\\n color: var(--foreground);\\n background: transparent !important;\\n font-family: var(--font-sans) !important;\\n font-size: var(--font-size-normal);\\n font-weight: var(--font-weight-normal);\\n line-height: var(--line-height-normal);\\n}\\n\\na {\\n color: color-mix(in srgb, var(--viz-accent) 80%, var(--viz-text) 20%);\\n cursor: pointer;\\n font-weight: var(--font-weight-medium, 500);\\n text-decoration: none;\\n text-underline-offset: 2px;\\n}\\n\\na:is(:hover, :focus-visible) {\\n text-decoration-line: underline;\\n text-decoration-style: dashed;\\n text-decoration-thickness: 0.5px;\\n}\\n\\nh1,\\nh2,\\nh3,\\nh4,\\nh5,\\nh6,\\np {\\n margin-block: 0;\\n}\\n\\nh1 {\\n font-size: var(--font-size-h1);\\n font-weight: var(--font-weight-medium);\\n line-height: 1.25;\\n}\\n\\nh2 {\\n font-size: var(--font-size-h2);\\n font-weight: var(--font-weight-medium);\\n line-height: 1.25;\\n}\\n\\nh3,\\nh4,\\nh5,\\nh6 {\\n font-size: var(--font-size-h3);\\n font-weight: var(--font-weight-medium);\\n line-height: 1.3;\\n}\\n\\nb,\\nstrong,\\nth {\\n font-weight: var(--font-weight-medium);\\n}\\n\\ncode:not(pre code) {\\n display: inline;\\n padding: 1px 6px;\\n border-radius: var(--radius-sm);\\n corner-shape: var(--corner-shape);\\n background: var(--muted);\\n font-family: var(--font-mono);\\n font-size: 0.92em;\\n overflow-wrap: anywhere;\\n -webkit-box-decoration-break: clone;\\n box-decoration-break: clone;\\n word-break: break-word;\\n}\\n\\n.table-responsive {\\n width: 100%;\\n overflow-x: auto;\\n scrollbar-width: thin;\\n}\\n\\n.table {\\n width: 100%;\\n border-collapse: collapse;\\n color: var(--foreground);\\n font: inherit;\\n text-align: start;\\n}\\n\\n.table :is(th, td) {\\n padding-block: 10px;\\n padding-inline: 0 24px;\\n overflow-wrap: anywhere;\\n border-bottom: 1px solid var(--border);\\n text-align: start;\\n vertical-align: top;\\n}\\n\\n.table-responsive > .table :is(th, td) {\\n overflow-wrap: break-word;\\n}\\n\\n.table :is(th, td):last-child {\\n padding-inline-end: 0;\\n}\\n\\n.table :is(caption, thead th) {\\n font-weight: 600;\\n}\\n\\n.table thead th {\\n padding-block: 8px;\\n border-bottom-color: color-mix(in srgb, var(--foreground) 16%, transparent);\\n}\\n\\n.table tbody tr:last-child :is(th, td) {\\n border-bottom: 0;\\n}\\n\\n.table.table-sm :is(th, td) {\\n padding-block: 6px;\\n}\\n\\n.table.table-sm :is(th, td):not(:last-child) {\\n padding-inline-end: 16px;\\n}\\n\\n.table :is(.text-end, [align=\\\"right\\\"]) {\\n text-align: end;\\n font-variant-numeric: tabular-nums;\\n}\\n\\n.table :is(.text-center, [align=\\\"center\\\"]) {\\n text-align: center;\\n}\\n\\n.table .text-nowrap {\\n white-space: nowrap;\\n}\\n\\n#widget {\\n display: flex;\\n flex-direction: column;\\n gap: 12px;\\n width: 100%;\\n padding: 0;\\n background: transparent !important;\\n}\\n\\n.card {\\n min-width: 0;\\n padding: 12px;\\n overflow: hidden;\\n overflow-wrap: break-word;\\n border-radius: var(--radius-2xl);\\n corner-shape: var(--corner-shape);\\n color: var(--card-foreground);\\n background: var(--card);\\n}\\n\\n#widget > :not(.card, .progress) {\\n width: 100% !important;\\n max-width: none !important;\\n margin: 0 !important;\\n padding: 0 !important;\\n border: 0 !important;\\n border-radius: 0 !important;\\n background: transparent !important;\\n box-shadow: none !important;\\n}\\n\\n.tooltip {\\n position: fixed;\\n z-index: 50;\\n top: 0;\\n left: 0;\\n width: max-content;\\n max-width: min(\\n 20rem,\\n var(--tooltip-available-width, calc(100vw - 10px)),\\n calc(100vw - 10px)\\n );\\n max-height: min(\\n var(--tooltip-available-height, calc(100vh - 10px)),\\n calc(100vh - 10px)\\n );\\n padding: 4px 8px;\\n border: 1px solid var(--border);\\n border-radius: var(--radius-lg);\\n corner-shape: var(--corner-shape);\\n color: var(--popover-foreground);\\n background: var(--popover);\\n box-shadow: none;\\n font-size: var(--font-size-tooltip);\\n line-height: var(--line-height-tooltip);\\n overflow-wrap: break-word;\\n white-space: normal;\\n pointer-events: none;\\n user-select: none;\\n}\\n\\n.viz-grid {\\n display: grid;\\n grid-template-columns: repeat(auto-fit, minmax(max(180px, 24%), 1fr));\\n gap: 10px;\\n}\\n\\n.viz-stat {\\n display: flex;\\n flex-direction: column;\\n gap: 2px;\\n}\\n\\n.viz-stat-value {\\n font-size: var(--font-size-h2);\\n font-weight: var(--font-weight-medium);\\n line-height: 1.25;\\n}\\n\\n.viz-row {\\n display: flex;\\n flex-wrap: wrap;\\n align-items: center;\\n gap: 10px;\\n}\\n\\nhr {\\n width: 100%;\\n height: 1px;\\n margin-block: 6px;\\n border: 0;\\n background: var(--border);\\n}\\n\\n.nav {\\n display: flex;\\n min-width: 0;\\n align-items: center;\\n gap: 4px;\\n}\\n\\n.progress {\\n display: flex;\\n height: 8px;\\n margin-block: calc((var(--line-height-normal, 1.5em) - 8px) / 2);\\n overflow: hidden;\\n border: 0;\\n border-radius: var(--radius-full);\\n background: var(--muted);\\n}\\n\\n.progress-bar:only-child {\\n border-radius: var(--radius-full);\\n}\\n\\n.progress-bar {\\n height: 100%;\\n flex-shrink: 0;\\n border: 0;\\n background: var(--viz-series-1);\\n}\\n\\n.viz-badge {\\n padding: 3px 8px;\\n border-radius: var(--radius-full);\\n color: var(--accent-foreground);\\n background: var(--accent);\\n font-weight: var(--font-weight-medium);\\n}\\n\\nsmall,\\n.text-small,\\n.viz-badge {\\n font-size: var(--font-size-small);\\n line-height: var(--line-height-small);\\n}\\n\\n.text-muted {\\n color: var(--muted-foreground);\\n}\\n\\n.tabular-nums {\\n font-variant-numeric: tabular-nums;\\n}\\n\\n.sr-only {\\n position: absolute;\\n width: 1px;\\n height: 1px;\\n padding: 0;\\n overflow: hidden;\\n clip: rect(0, 0, 0, 0);\\n white-space: nowrap;\\n border: 0;\\n}\\n\\n.viz-controls {\\n display: flex;\\n flex-wrap: wrap;\\n align-items: center;\\n gap: 8px;\\n}\\n\\n.viz-controls > .form-label {\\n display: grid;\\n min-width: min(100%, 260px);\\n flex: 1 1 280px;\\n grid-template-columns: minmax(0, 1fr) auto;\\n align-items: baseline;\\n gap: 2px 12px;\\n margin-bottom: 0;\\n}\\n\\n.viz-controls > .form-label > :is(.form-control, .form-range, .form-select) {\\n grid-column: 1 / -1;\\n}\\n\\n.btn,\\n.nav-link,\\n.form-check-input,\\n.form-control,\\n.form-range,\\n.form-select {\\n font: inherit;\\n}\\n\\n.btn,\\n.nav-link {\\n appearance: button;\\n display: inline-flex;\\n inline-size: fit-content;\\n max-inline-size: 100%;\\n min-height: 28px;\\n align-items: center;\\n justify-content: center;\\n gap: 4px;\\n margin: 0;\\n padding: 0 8px;\\n -webkit-app-region: no-drag;\\n border: 1px solid var(--input);\\n border-radius: var(--radius-lg);\\n corner-shape: var(--corner-shape);\\n color: var(--secondary-foreground);\\n background: var(--secondary);\\n cursor: var(--cursor-interaction, pointer);\\n text-align: center;\\n text-decoration: none;\\n white-space: nowrap;\\n user-select: none;\\n -webkit-font-smoothing: antialiased;\\n}\\n\\n.btn:is(.btn-block, .viz-tile) {\\n inline-size: 100%;\\n}\\n\\n.btn.viz-tile {\\n min-width: 0;\\n overflow-wrap: anywhere;\\n white-space: normal;\\n}\\n\\na.btn {\\n cursor: pointer;\\n text-decoration: none;\\n}\\n\\n.btn:not(:disabled):hover,\\n.nav-link:not(:disabled):not([aria-disabled=\\\"true\\\"]):hover {\\n background: color-mix(in srgb, var(--foreground) 6%, var(--secondary));\\n}\\n\\n.btn-primary {\\n border-color: transparent;\\n color: var(--primary-foreground);\\n background: var(--foreground);\\n background-clip: padding-box;\\n}\\n\\n.btn-primary .text-muted {\\n color: color-mix(in srgb, var(--primary-foreground) 50%, transparent);\\n}\\n\\n.btn-primary:not(:disabled):hover {\\n background: color-mix(in srgb, var(--foreground) 80%, transparent);\\n background-clip: padding-box;\\n}\\n\\n.btn-ghost {\\n border-color: transparent;\\n color: var(--muted-foreground);\\n background: transparent;\\n}\\n\\n.btn-ghost:not(:disabled):hover {\\n color: var(--foreground);\\n background: color-mix(in srgb, var(--foreground) 6%, var(--secondary));\\n}\\n\\n.nav-pills .nav-link {\\n min-width: 0;\\n border-color: transparent;\\n color: var(--muted-foreground);\\n background: transparent;\\n}\\n\\n.nav-justified .nav-link {\\n flex: 1 1 0;\\n overflow-wrap: anywhere;\\n white-space: normal;\\n}\\n\\n.nav-pills .nav-link.active {\\n color: var(--foreground);\\n background: var(--muted);\\n}\\n\\n.btn:disabled,\\n.nav-link:disabled,\\n.nav-link[aria-disabled=\\\"true\\\"] {\\n cursor: not-allowed;\\n opacity: 0.4;\\n}\\n\\n[data-lucide] {\\n stroke-width: 1.6;\\n}\\n\\n.form-label {\\n display: block;\\n margin-bottom: 6px;\\n color: var(--foreground);\\n}\\n\\n.form-control {\\n display: block;\\n width: 100%;\\n min-height: 28px;\\n padding: 0 8px;\\n outline: none;\\n border: 1px solid var(--input);\\n border-radius: var(--radius-lg);\\n corner-shape: var(--corner-shape);\\n color: var(--foreground);\\n background: var(--secondary);\\n}\\n\\n.form-control::placeholder {\\n color: var(--muted-foreground);\\n}\\n\\n.form-control[type=\\\"file\\\"] {\\n padding: 0;\\n overflow: hidden;\\n cursor: var(--cursor-interaction, pointer);\\n}\\n\\n.form-control[type=\\\"file\\\"]::file-selector-button {\\n min-height: 26px;\\n margin-right: 8px;\\n padding: 0 8px;\\n border: 0;\\n border-right: 1px solid var(--input);\\n color: var(--secondary-foreground);\\n background: var(--secondary);\\n cursor: inherit;\\n font: inherit;\\n}\\n\\n.form-control[type=\\\"file\\\"]:not(:disabled):hover::file-selector-button {\\n background: color-mix(in srgb, var(--foreground) 6%, var(--secondary));\\n}\\n\\n.form-control-color[type=\\\"color\\\"] {\\n width: 40px;\\n height: 28px;\\n padding: 3px;\\n cursor: var(--cursor-interaction, pointer);\\n}\\n\\n.form-control-color[type=\\\"color\\\"]::-webkit-color-swatch-wrapper {\\n padding: 0;\\n}\\n\\n.form-control-color[type=\\\"color\\\"]::-webkit-color-swatch {\\n border: 0;\\n border-radius: calc(var(--radius-lg) - 4px);\\n corner-shape: var(--corner-shape);\\n}\\n\\ntextarea.form-control {\\n height: auto;\\n min-height: 72px;\\n padding: 8px 10px;\\n resize: vertical;\\n}\\n\\n.form-control:focus-visible {\\n border-color: var(--ring);\\n box-shadow: inset 0 0 0 1px var(--ring);\\n}\\n\\n.form-control:disabled,\\n.form-select:disabled {\\n cursor: not-allowed;\\n opacity: 0.4;\\n}\\n\\n.form-select {\\n appearance: none;\\n display: block;\\n width: 100%;\\n min-height: 28px;\\n margin: 0;\\n padding: 0 32px 0 8px;\\n outline: none;\\n border: 1px solid var(--input);\\n border-radius: var(--radius-lg);\\n corner-shape: var(--corner-shape);\\n color: var(--foreground);\\n background-color: var(--secondary);\\n background-image:\\n linear-gradient(45deg, transparent 50%, var(--muted-foreground) 50%),\\n linear-gradient(135deg, var(--muted-foreground) 50%, transparent 50%);\\n background-position:\\n calc(100% - 14px) 50%,\\n calc(100% - 10px) 50%;\\n background-repeat: no-repeat;\\n background-size: 4px 4px;\\n cursor: var(--cursor-interaction, default);\\n}\\n\\n.form-select:not(:disabled):hover {\\n background-color: color-mix(in srgb, var(--foreground) 6%, var(--secondary));\\n}\\n\\n.form-select:focus-visible {\\n border-color: var(--ring);\\n box-shadow: inset 0 0 0 1px var(--ring);\\n}\\n\\n.form-check {\\n display: flex;\\n min-height: 20px;\\n align-items: center;\\n gap: 6px;\\n}\\n\\n.form-check-input {\\n appearance: none;\\n width: 14px;\\n height: 14px;\\n flex: 0 0 auto;\\n margin: 0;\\n border: 1px solid var(--input);\\n color: var(--primary-foreground);\\n background-color: transparent;\\n cursor: var(--cursor-interaction, default);\\n transition:\\n background-color 150ms,\\n border-color 150ms,\\n box-shadow 150ms;\\n}\\n\\n.form-check:not(.form-switch) .form-check-input[type=\\\"checkbox\\\"] {\\n border-color: var(--input);\\n border-radius: var(--radius-sm);\\n corner-shape: var(--corner-shape);\\n background-color: var(--secondary);\\n box-shadow: var(--shadow-sm);\\n}\\n\\n.form-check:not(.form-switch)\\n .form-check-input:not(:disabled):not(:checked):hover {\\n background-color: var(--card);\\n}\\n\\n.form-check:not(.form-switch) .form-check-input[type=\\\"checkbox\\\"]:checked {\\n border-color: var(--primary);\\n background-color: var(--primary);\\n}\\n\\n.form-check:not(.form-switch)\\n .form-check-input[type=\\\"checkbox\\\"]:checked::before {\\n display: block;\\n width: 100%;\\n height: 100%;\\n background: var(--primary-foreground);\\n content: \\\"\\\";\\n mask: var(--checkmark-image) center / 12px 12px no-repeat;\\n}\\n\\n.form-check-input[type=\\\"radio\\\"] {\\n width: 14px;\\n height: 14px;\\n border-radius: var(--radius-full);\\n}\\n\\n.form-check-input[type=\\\"radio\\\"]:checked {\\n border: 2px solid var(--primary);\\n background:\\n radial-gradient(circle, var(--primary-foreground) 0 2.5px, transparent 3px),\\n var(--primary);\\n}\\n\\n.form-check:not(.form-switch) .form-check-input:focus-visible {\\n outline: 2px solid var(--ring);\\n outline-offset: 2px;\\n}\\n\\n.form-check:not(.form-switch) .form-check-input:disabled {\\n cursor: not-allowed;\\n pointer-events: none;\\n}\\n\\n.form-check:not(.form-switch) .form-check-input:disabled + .form-check-label {\\n cursor: not-allowed;\\n}\\n\\n.form-switch .form-check-input:disabled,\\n.form-switch .form-check-input:disabled + .form-check-label {\\n cursor: not-allowed;\\n opacity: 0.6;\\n}\\n\\n.form-check-label {\\n color: var(--foreground);\\n cursor: var(--cursor-interaction, default);\\n}\\n\\n.form-switch .form-check-input {\\n position: relative;\\n width: 32px;\\n height: 20px;\\n border: 0;\\n border-radius: var(--radius-full);\\n background: var(--muted);\\n box-shadow: none;\\n transition: background-color 200ms cubic-bezier(0, 0, 0.2, 1);\\n}\\n\\n.form-switch .form-check-input::before {\\n position: absolute;\\n top: 50%;\\n left: 0;\\n width: 16px;\\n height: 16px;\\n box-sizing: border-box;\\n border: 1px solid light-dark(var(--primary-foreground), var(--foreground));\\n border-radius: var(--radius-full);\\n background: light-dark(var(--primary-foreground), var(--foreground));\\n box-shadow: var(--shadow-sm);\\n content: \\\"\\\";\\n transform: translate(2px, -50%);\\n transition: transform 200ms cubic-bezier(0, 0, 0.2, 1);\\n}\\n\\n.form-switch .form-check-input:checked {\\n background: var(--primary);\\n}\\n\\n.form-switch .form-check-input:checked::before {\\n transform: translate(14px, -50%);\\n}\\n\\n.form-switch .form-check-input:focus-visible {\\n box-shadow: 0 0 0 2px var(--ring);\\n}\\n\\n.form-range {\\n appearance: none;\\n display: block;\\n width: 100%;\\n height: 28px;\\n flex: 1;\\n margin: 0;\\n padding: 0;\\n outline: none;\\n border: 0;\\n accent-color: var(--primary);\\n background: linear-gradient(\\n color-mix(in srgb, var(--foreground) 7%, transparent),\\n color-mix(in srgb, var(--foreground) 7%, transparent)\\n )\\n center / 100% 2px no-repeat;\\n}\\n\\n.form-range::-webkit-slider-runnable-track {\\n height: 28px;\\n background: transparent;\\n}\\n\\n.form-range::-webkit-slider-thumb {\\n appearance: none;\\n width: 20px;\\n height: 20px;\\n margin-top: 4px;\\n border: 1px solid var(--border);\\n border-radius: var(--radius-full);\\n background: light-dark(var(--primary-foreground), var(--foreground));\\n}\\n\\n.form-range:focus-visible::-webkit-slider-thumb {\\n border-color: var(--ring);\\n box-shadow: inset 0 0 0 1px var(--ring);\\n}\\n\\n.form-range::-moz-range-track {\\n height: 28px;\\n background: transparent;\\n}\\n\\n.form-range::-moz-range-thumb {\\n width: 20px;\\n height: 20px;\\n border: 1px solid var(--border);\\n border-radius: var(--radius-full);\\n background: light-dark(var(--primary-foreground), var(--foreground));\\n}\\n\\n.form-range:focus-visible::-moz-range-thumb {\\n border-color: var(--ring);\\n box-shadow: inset 0 0 0 1px var(--ring);\\n}\\n\\n.form-range:disabled {\\n cursor: not-allowed;\\n opacity: 0.4;\\n}\\n\\n.btn:not(.btn-primary, .viz-tile):is(\\n [aria-pressed=\\\"true\\\"],\\n [aria-selected=\\\"true\\\"],\\n .is-selected\\n) {\\n border-color: var(--primary);\\n color: var(--primary-foreground);\\n background: var(--primary);\\n}\\n\\n.btn.viz-tile:is([aria-pressed=\\\"true\\\"], [aria-selected=\\\"true\\\"], .is-selected) {\\n border-color: var(--primary);\\n box-shadow: inset 0 0 0 1px var(--primary);\\n}\\n\\n.btn:focus-visible,\\n.nav-link:focus-visible {\\n outline: 2px solid var(--ring);\\n outline-offset: 2px;\\n}\\n\\n@media (pointer: coarse) {\\n .btn,\\n .nav-link,\\n .form-control,\\n .form-select {\\n min-width: 44px;\\n min-height: 44px;\\n }\\n\\n /* Keep small-screen WebKit from zooming when a text field receives focus. */\\n .form-control,\\n .form-select {\\n font-size: max(16px, var(--font-size-normal));\\n }\\n\\n .form-control[type=\\\"file\\\"]::file-selector-button {\\n min-width: 44px;\\n min-height: 44px;\\n }\\n\\n .form-control-color[type=\\\"color\\\"] {\\n width: 44px;\\n height: 44px;\\n }\\n\\n .form-control:is(\\n [type=\\\"date\\\"],\\n [type=\\\"datetime-local\\\"],\\n [type=\\\"month\\\"],\\n [type=\\\"time\\\"],\\n [type=\\\"week\\\"]\\n ) {\\n min-width: 0;\\n max-width: 100%;\\n padding-block: 8px;\\n }\\n\\n .form-check {\\n min-height: 44px;\\n padding-inline: 15px;\\n }\\n\\n .form-check-input {\\n position: relative;\\n }\\n\\n .form-check-input::after {\\n position: absolute;\\n top: 50%;\\n left: 50%;\\n width: 44px;\\n height: 44px;\\n content: \\\"\\\";\\n transform: translate(-50%, -50%);\\n }\\n\\n .form-check-label {\\n display: inline-flex;\\n min-width: 44px;\\n min-height: 44px;\\n align-items: center;\\n }\\n\\n .form-range {\\n height: 44px;\\n touch-action: pan-y;\\n }\\n\\n .form-range::-webkit-slider-runnable-track {\\n height: 44px;\\n }\\n\\n .form-range::-moz-range-track {\\n height: 44px;\\n }\\n\\n .form-range::-webkit-slider-thumb {\\n margin-top: 12px;\\n }\\n}\\n\\nsvg {\\n display: block;\\n max-width: 100%;\\n height: auto;\\n}\\n\\n#widget > svg {\\n width: 100%;\\n}\\n\\n/* Model-authored chart rules can otherwise stretch icons after these styles load. */\\nsvg.lucide {\\n display: block;\\n width: var(--icon-size) !important;\\n height: var(--icon-size) !important;\\n flex: none;\\n margin: 0 !important;\\n stroke-width: 1.6;\\n}\\n\\n.text-warning,\\n.text-destructive {\\n color: var(--destructive);\\n}\\n\";\nexport const VISUALIZATION_HELPERS = \"\\n<script src=\\\"https://unpkg.com/@floating-ui/core@1.7.3/dist/floating-ui.core.umd.min.js\\\"></script>\\n<script src=\\\"https://unpkg.com/@floating-ui/dom@1.7.4/dist/floating-ui.dom.umd.min.js\\\"></script>\\n<script>\\n (() => {\\n if (window.FloatingUIDOM == null) {\\n return;\\n }\\n const { autoUpdate, computePosition, flip, offset, shift, size } = window.FloatingUIDOM;\\n const tooltipPlacements = new Set([\\\"top\\\", \\\"right\\\", \\\"bottom\\\", \\\"left\\\"]);\\n const tooltipId = `codex-visualization-tooltip-${\\n window.crypto?.randomUUID?.() ?? Date.now().toString(36)\\n }`;\\n const tooltipGap = 5;\\n const hoverDelay = 700;\\n const skipDelay = 300;\\n let activeTrigger = null;\\n let pendingTrigger = null;\\n let tooltip = null;\\n let openTimeout = null;\\n let autoUpdateCleanup = null;\\n let positionRequest = 0;\\n let skipDelayUntil = 0;\\n let lastPointerWasTouch = false;\\n let pinnedByTouch = false;\\n\\n const getTrigger = (target) =>\\n target?.nodeType === Node.ELEMENT_NODE ? target.closest(\\\"[data-tooltip]\\\") : null;\\n const containsTarget = (trigger, target) =>\\n target?.nodeType != null && trigger.contains(target);\\n const getContent = (trigger) => trigger.getAttribute(\\\"data-tooltip\\\")?.trim() ?? \\\"\\\";\\n const getPlacement = (trigger) => {\\n const placement = trigger.getAttribute(\\\"data-tooltip-placement\\\");\\n return tooltipPlacements.has(placement) ? placement : \\\"top\\\";\\n };\\n const getTooltip = () => {\\n if (tooltip == null) {\\n tooltip = document.createElement(\\\"div\\\");\\n tooltip.id = tooltipId;\\n tooltip.className = \\\"tooltip\\\";\\n tooltip.setAttribute(\\\"role\\\", \\\"tooltip\\\");\\n }\\n return tooltip;\\n };\\n const setDescribedBy = (trigger, described) => {\\n const ids = new Set(\\n (trigger.getAttribute(\\\"aria-describedby\\\") ?? \\\"\\\").split(/\\\\s+/).filter(Boolean),\\n );\\n if (described) {\\n ids.add(tooltipId);\\n } else {\\n ids.delete(tooltipId);\\n }\\n if (ids.size === 0) {\\n trigger.removeAttribute(\\\"aria-describedby\\\");\\n } else {\\n trigger.setAttribute(\\\"aria-describedby\\\", [...ids].join(\\\" \\\"));\\n }\\n };\\n const clearOpenTimeout = () => {\\n if (openTimeout != null) {\\n window.clearTimeout(openTimeout);\\n openTimeout = null;\\n }\\n pendingTrigger = null;\\n };\\n const closeTooltip = (activateSkipDelay = true) => {\\n clearOpenTimeout();\\n pinnedByTouch = false;\\n positionRequest += 1;\\n autoUpdateCleanup?.();\\n autoUpdateCleanup = null;\\n if (activeTrigger == null) {\\n return;\\n }\\n setDescribedBy(activeTrigger, false);\\n activeTrigger = null;\\n tooltip?.remove();\\n if (activateSkipDelay) {\\n skipDelayUntil = Date.now() + skipDelay;\\n }\\n };\\n const updatePosition = (trigger, floating) => {\\n const request = ++positionRequest;\\n void computePosition(trigger, floating, {\\n middleware: [\\n offset(tooltipGap),\\n flip({ padding: tooltipGap }),\\n shift({ padding: tooltipGap }),\\n size({\\n padding: tooltipGap,\\n apply({ availableHeight, availableWidth, elements }) {\\n elements.floating.style.setProperty(\\n \\\"--tooltip-available-width\\\",\\n `${Math.max(0, availableWidth)}px`,\\n );\\n elements.floating.style.setProperty(\\n \\\"--tooltip-available-height\\\",\\n `${Math.max(0, availableHeight)}px`,\\n );\\n },\\n }),\\n ],\\n placement: getPlacement(trigger),\\n strategy: \\\"fixed\\\",\\n })\\n .then(({ x, y }) => {\\n if (activeTrigger !== trigger || request !== positionRequest) {\\n return;\\n }\\n const scale = window.devicePixelRatio || 1;\\n floating.style.transform = `translate(${Math.round(x * scale) / scale}px, ${Math.round(y * scale) / scale}px)`;\\n floating.style.visibility = \\\"visible\\\";\\n })\\n .catch(() => {\\n if (activeTrigger === trigger && request === positionRequest) {\\n closeTooltip(false);\\n }\\n });\\n };\\n const openTooltip = (trigger) => {\\n const content = getContent(trigger);\\n if (!trigger.isConnected || content.length === 0) {\\n return;\\n }\\n clearOpenTimeout();\\n if (activeTrigger === trigger) {\\n return;\\n }\\n closeTooltip();\\n const floating = getTooltip();\\n floating.textContent = content;\\n floating.style.visibility = \\\"hidden\\\";\\n floating.style.transform = \\\"translate(0, 0)\\\";\\n document.body.appendChild(floating);\\n activeTrigger = trigger;\\n setDescribedBy(trigger, true);\\n autoUpdateCleanup = autoUpdate(trigger, floating, () => {\\n updatePosition(trigger, floating);\\n });\\n };\\n const requestOpen = (trigger, immediate = false) => {\\n if (\\n getContent(trigger).length === 0 ||\\n activeTrigger === trigger ||\\n pendingTrigger === trigger\\n ) {\\n return;\\n }\\n clearOpenTimeout();\\n pendingTrigger = trigger;\\n const delay =\\n immediate || activeTrigger != null || Date.now() < skipDelayUntil ? 0 : hoverDelay;\\n if (delay === 0) {\\n openTooltip(trigger);\\n return;\\n }\\n openTimeout = window.setTimeout(() => {\\n openTimeout = null;\\n pendingTrigger = null;\\n openTooltip(trigger);\\n }, delay);\\n };\\n const handlePointerOpen = (event) => {\\n if (event.pointerType === \\\"touch\\\") {\\n return;\\n }\\n const trigger = getTrigger(event.target);\\n if (trigger == null || containsTarget(trigger, event.relatedTarget)) {\\n return;\\n }\\n requestOpen(trigger);\\n };\\n const handlePointer = (event) => {\\n lastPointerWasTouch = event.type === \\\"pointerdown\\\" && event.pointerType === \\\"touch\\\";\\n };\\n const handleTouchClick = (event) => {\\n const isTouch = event.pointerType === \\\"touch\\\" || lastPointerWasTouch;\\n lastPointerWasTouch = false;\\n if (!isTouch || event.detail === 0) {\\n return;\\n }\\n const trigger = getTrigger(event.target);\\n if (\\n trigger == null ||\\n !trigger.isConnected ||\\n getContent(trigger).length === 0 ||\\n (pinnedByTouch && activeTrigger === trigger)\\n ) {\\n if (pinnedByTouch) {\\n closeTooltip();\\n }\\n return;\\n }\\n openTooltip(trigger);\\n pinnedByTouch = activeTrigger === trigger;\\n window.setTimeout(() => {\\n if (activeTrigger === trigger && !trigger.isConnected) {\\n closeTooltip(false);\\n }\\n }, 0);\\n };\\n const handleLeave = (event) => {\\n if (pinnedByTouch) {\\n return;\\n }\\n const trigger = getTrigger(event.target);\\n if (trigger == null || containsTarget(trigger, event.relatedTarget)) {\\n return;\\n }\\n if (activeTrigger === trigger || pendingTrigger === trigger) {\\n closeTooltip();\\n }\\n };\\n const handleFocusIn = (event) => {\\n const trigger = getTrigger(event.target);\\n if (trigger?.matches(\\\":focus-visible\\\")) {\\n requestOpen(trigger, true);\\n }\\n };\\n const handleKeyDown = (event) => {\\n if (event.key === \\\"Escape\\\") {\\n closeTooltip();\\n }\\n };\\n const handleContextMenu = (event) => {\\n lastPointerWasTouch = false;\\n const trigger = getTrigger(event.target);\\n if (activeTrigger === trigger || pendingTrigger === trigger) {\\n closeTooltip();\\n }\\n };\\n const destroy = () => {\\n closeTooltip(false);\\n lastPointerWasTouch = false;\\n document.removeEventListener(\\\"pointerover\\\", handlePointerOpen);\\n document.removeEventListener(\\\"pointerdown\\\", handlePointer);\\n document.removeEventListener(\\\"pointercancel\\\", handlePointer);\\n document.removeEventListener(\\\"click\\\", handleTouchClick);\\n document.removeEventListener(\\\"pointerout\\\", handleLeave);\\n document.removeEventListener(\\\"focusin\\\", handleFocusIn);\\n document.removeEventListener(\\\"focusout\\\", handleLeave);\\n document.removeEventListener(\\\"keydown\\\", handleKeyDown);\\n document.removeEventListener(\\\"contextmenu\\\", handleContextMenu);\\n tooltip = null;\\n };\\n\\n document.addEventListener(\\\"pointerover\\\", handlePointerOpen);\\n document.addEventListener(\\\"pointerdown\\\", handlePointer);\\n document.addEventListener(\\\"pointercancel\\\", handlePointer);\\n document.addEventListener(\\\"click\\\", handleTouchClick);\\n document.addEventListener(\\\"pointerout\\\", handleLeave);\\n document.addEventListener(\\\"focusin\\\", handleFocusIn);\\n document.addEventListener(\\\"focusout\\\", handleLeave);\\n document.addEventListener(\\\"keydown\\\", handleKeyDown);\\n document.addEventListener(\\\"contextmenu\\\", handleContextMenu);\\n window.addEventListener(\\\"pagehide\\\", destroy, { once: true });\\n })();\\n</script>\\n<script id=\\\"codex-visualization-tabs\\\">\\n (() => {\\n const selector = '.nav[role=\\\"tablist\\\"] [role=\\\"tab\\\"]';\\n const disabled = ':disabled,[aria-disabled=\\\"true\\\"]';\\n const selectTab = (selected) => {\\n const panelId = selected.getAttribute(\\\"aria-controls\\\");\\n for (const tab of selected.closest('[role=\\\"tablist\\\"]').querySelectorAll('[role=\\\"tab\\\"]')) {\\n const active = tab === selected;\\n tab.classList.toggle(\\\"active\\\", active);\\n tab.setAttribute(\\\"aria-selected\\\", String(active));\\n const id = tab.getAttribute(\\\"aria-controls\\\");\\n const panel = id && document.getElementById(id);\\n if (panel != null) {\\n panel.hidden = id !== panelId;\\n if (!panel.hidden && selected.id) {\\n panel.setAttribute(\\\"aria-labelledby\\\", selected.id);\\n }\\n }\\n }\\n };\\n const interact = (event) => {\\n const tab = event.target?.closest?.(selector);\\n if (event.defaultPrevented || tab == null || tab.matches(disabled)) {\\n return;\\n }\\n if (event.type === \\\"click\\\") {\\n selectTab(tab);\\n return;\\n }\\n const tabs = Array.from(\\n tab.closest('[role=\\\"tablist\\\"]').querySelectorAll('[role=\\\"tab\\\"]'),\\n ).filter((candidate) => !candidate.matches(disabled));\\n const current = tabs.indexOf(tab);\\n let next;\\n if (event.key === \\\"ArrowRight\\\" || event.key === \\\"ArrowDown\\\") {\\n next = (current + 1) % tabs.length;\\n } else if (event.key === \\\"ArrowLeft\\\" || event.key === \\\"ArrowUp\\\") {\\n next = (current + tabs.length - 1) % tabs.length;\\n } else if (event.key === \\\"Home\\\") {\\n next = 0;\\n } else if (event.key === \\\"End\\\") {\\n next = tabs.length - 1;\\n } else {\\n return;\\n }\\n event.preventDefault();\\n tabs[next].focus();\\n selectTab(tabs[next]);\\n };\\n\\n for (const list of document.querySelectorAll('.nav[role=\\\"tablist\\\"]')) {\\n const selected =\\n list.querySelector('[role=\\\"tab\\\"][aria-selected=\\\"true\\\"]') ??\\n list.querySelector('[role=\\\"tab\\\"].active') ??\\n list.querySelector('[role=\\\"tab\\\"]');\\n if (selected != null) {\\n selectTab(selected);\\n }\\n }\\n document.addEventListener(\\\"click\\\", interact);\\n document.addEventListener(\\\"keydown\\\", interact);\\n window.addEventListener(\\n \\\"pagehide\\\",\\n () => {\\n document.removeEventListener(\\\"click\\\", interact);\\n document.removeEventListener(\\\"keydown\\\", interact);\\n },\\n { once: true },\\n );\\n })();\\n</script>\\n<script\\n id=\\\"codex-visualization-lucide\\\"\\n async\\n src=\\\"https://unpkg.com/lucide@1.17.0/dist/umd/lucide.js\\\"\\n></script>\\n<script>\\n (() => {\\n const initialize = () => {\\n globalThis.lucide?.createIcons({ attrs: { width: 16, height: 16 } });\\n };\\n if (globalThis.lucide != null) {\\n initialize();\\n return;\\n }\\n document\\n .getElementById(\\\"codex-visualization-lucide\\\")\\n ?.addEventListener(\\\"load\\\", initialize, { once: true });\\n })();\\n</script>\\n\";\n","import { VISUALIZATION_CSS, VISUALIZATION_HELPERS } from \"./visualization-assets.gen\";\n\n/** Conversation styling/helpers only. Rendering and tool transport remain in the Site frame. */\nexport function inlineHtmlDocument(fragment: string): string {\n return (\n '<!doctype html><html><head><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><style>' +\n VISUALIZATION_CSS +\n \"</style><style>html,body{margin:0;min-height:0}body{padding:16px;box-sizing:border-box}</style></head><body>\" +\n fragment +\n VISUALIZATION_HELPERS +\n `<script>\n(()=>{\n window.addEventListener('message',event=>{\n if(event.source!==parent||event.data?.type!=='opengeni.preview.theme')return;\n if(event.data.theme==='light'||event.data.theme==='dark')document.documentElement.style.colorScheme=event.data.theme;\n previous=0;resize();\n });\n let previous=0;\n const resize=()=>{const height=Math.ceil(document.body.getBoundingClientRect().height);if(height!==previous){previous=height;parent.postMessage({type:'opengeni.preview.height',height},'*')}};\n new ResizeObserver(resize).observe(document.body);resize();\n})();\n</script></body></html>`\n );\n}\n"],"mappings":"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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAC1B,IAAM,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACC9B,SAAS,mBAAmB,UAA0B;AAC3D,SACE,0GACA,oBACA,iHACA,WACA,wBACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAaJ;;;AJsCM,SAwJE,UAxJF,OAAAC,MAqIA,QAAAC,aArIA;AA1CN,IAAM,wBAAwB;AAC9B,IAAM,sBAAsB;AAC5B,IAAM,wBAAwB;AAqCvB,SAAS,qBAAqB,EAAE,QAAQ,GAAG,MAAM,GAA8B;AACpF,SACE,gBAAAD,KAAC,0BAAuB,QACtB,0BAAAA,KAAC,oBAAkB,GAAG,OAAO,GAC/B;AAEJ;AAEA,SAAS,iBAAiB,OAAkC;AAC1D,QAAM,SAAS,kBAAkB;AACjC,QAAM,UACH,MAAM,SAAS,SAAS,wBAAwB,uBAAuB;AAC1E,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MAEC;AAAA,MACA,aAAa,MAAM,SAAS,SAAS,OAAO,cAAc,OAAO;AAAA,MAEjE,0BAAAA,KAAC,SAAI,OAAO,EAAE,OAAO,GACnB,0BAAAA,KAAC,8BAA4B,GAAG,OAAO,GACzC;AAAA;AAAA,IANK,GAAG,MAAM,WAAW,IAAI,MAAM,IAAI,IAAI,MAAM,SAAS,SAAS,MAAM,UAAU,QAAQ;AAAA,EAO7F;AAEJ;AAEA,SAAS,2BAA2B,OAAkC;AACpE,QAAM,SAAS,kBAAkB;AACjC,MAAI,MAAM,SAAS,OAAQ,QAAO,gBAAAA,KAAC,cAAY,GAAG,OAAO;AACzD,MAAI;AACF,UAAM,QAAQ,KAAK,MAAM,MAAM,OAAO;AACtC,QACE,CAAC,SACD,OAAO,MAAM,WAAW,YACxB,CAAC,mBAAmB,KAAK,MAAM,MAAM,KACpC,MAAM,cAAc,WAClB,OAAO,MAAM,cAAc,YAAY,CAAC,mBAAmB,KAAK,MAAM,SAAS;AAElF,YAAM,IAAI,MAAM,wBAAwB;AAC1C,WACE,gBAAAA;AAAA,MAAC;AAAA;AAAA,QAEE,GAAG;AAAA,QACJ,QAAQ,MAAM;AAAA,QACd,kBAAkB,MAAM;AAAA;AAAA,MAHnB,GAAG,MAAM,WAAW,IAAI,MAAM,MAAM,IAAI,MAAM,aAAa,SAAS;AAAA,IAI3E;AAAA,EAEJ,QAAQ;AACN,WAAO,gBAAAA,KAAC,OAAE,MAAK,SAAS,iBAAO,sBAAqB;AAAA,EACtD;AACF;AAEA,SAAS,WAAW,EAAE,SAAS,YAAY,MAAM,GAA8B;AAC7E,QAAM,SAAS,kBAAkB;AACjC,QAAM,OAAO,QAAQ,MAAM,mBAAmB,OAAO,GAAG,CAAC,OAAO,CAAC;AACjE,QAAM,SAAS,QAAQ,MAAM,aAAa,GAAG,CAAC,UAAU,CAAC;AACzD,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,OAAO;AAAA,MACd,WAAW;AAAA,MACX,gBAAgB;AAAA,MAChB;AAAA,MACA,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,WAAU;AAAA,MACV,MAAI;AAAA,MACJ;AAAA;AAAA,EACF;AAEJ;AAEA,SAAS,UACP,OACA;AACA,QAAM,CAAC,WAAW,YAAY,IAAIE,UAAS,MAAM,gBAAgB;AACjE,SACE,gBAAAF;AAAA,IAAC;AAAA;AAAA,MAEE,GAAG;AAAA,MACJ;AAAA,MACA,iBAAiB;AAAA;AAAA,IAHZ,aAAa;AAAA,EAIpB;AAEJ;AAEA,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,CAAC,QAAQ,SAAS,IAAIE,UAGlB,IAAI;AACd,QAAM,WAAW,QAAQ,WAAW,SAAS,OAAO,WAAW;AAC/D,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAS,KAAK;AACxC,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAS,CAAC;AACpC,EAAAC,WAAU,MAAM;AACd,UAAM,QAAQ,IAAI,gBAAgB;AAClC,aAAS,KAAK;AACd,cAAU,IAAI;AACd,SAAK,iBAAiB,QAAQ,aAAa,QAAQ;AAAA,MACjD,QAAQ,MAAM;AAAA,MACd,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,IACnC,CAAC,EACE,KAAK,CAAC,UAAU;AACf,UAAI,CAAC,MAAM,OAAO,QAAS,WAAU,EAAE,QAAQ,UAAU,MAAM,CAAC;AAAA,IAClE,CAAC,EACA,MAAM,MAAM;AACX,UAAI,CAAC,MAAM,OAAO,QAAS,UAAS,IAAI;AAAA,IAC1C,CAAC;AACH,WAAO,MAAM,MAAM,MAAM;AAAA,EAC3B,GAAG,CAAC,QAAQ,aAAa,QAAQ,WAAW,KAAK,CAAC;AAClD,QAAM,UAAU,UAAU;AAC1B,QAAM,SAAS;AAAA,IACb,MACE,UACI,aAAa;AAAA,MACX,YAAY;AAAA,MACZ,eAAe,QAAQ;AAAA,MACvB,gBAAgB,QAAQ;AAAA,IAC1B,CAAC,IACD;AAAA,IACN,CAAC,YAAY,QAAQ,OAAO;AAAA,EAC9B;AACA,QAAM,OAAO,wBAAwB,IAAI,EAAE,MAAM,QAAQ,YAAY,QAAQ,YAAY,CAAC;AAC1F,QAAM,SAAS,kBAAkB;AACjC,MAAI;AACF,WACE,gBAAAF,MAAC,OAAE,MAAK,SACL;AAAA,aAAO;AAAA,MAAgB;AAAA,MACxB,gBAAAD,KAAC,kBAAe,MAAK,MAAK,SAAS,MAAM,SAAS,CAAC,MAAM,IAAI,CAAC,GAC3D,iBAAO,OACV;AAAA,OACF;AAEJ,MAAI,CAAC,SAAU,QAAO,gBAAAA,KAAC,OAAE,MAAK,UAAU,iBAAO,aAAY;AAC3D,MAAI,CAAC,QAAS,QAAO,gBAAAA,KAAC,OAAG,iBAAO,iBAAgB;AAChD,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,SAAS,OAAO,SAAS;AAAA,MAChC,MAAM,QAAQ;AAAA,MACd,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,WAAU;AAAA,MACV,MAAI;AAAA,MACJ;AAAA,MACA,gBACE,gBAAAC,MAAA,YAEG;AAAA,iBAAS,OAAO,SAAS,SAAS,KACnC,CAAC,SAAS,OAAO,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ,SAAS,IAC9D,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,cAAY,OAAO;AAAA,YACnB,WAAU;AAAA,YACV,OAAO,QAAQ;AAAA,YACf,UAAU,CAAC,MAAM,gBAAgB,EAAE,OAAO,KAAK;AAAA,YAE9C;AAAA,eAAC,SAAS,OAAO,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ,SAAS,KAC/D,gBAAAD,KAAC,YAAO,OAAO,QAAQ,WAAY,iBAAO,cAAa;AAAA,cAExD,SAAS,OAAO,SAAS,IAAI,CAAC,MAC7B,gBAAAA,KAAC,YAAkB,OAAO,EAAE,IACzB,iBAAO,QAAQ,EAAE,QAAQ,KADf,EAAE,EAEf,CACD;AAAA;AAAA;AAAA,QACH,IACE;AAAA,QACH,MAAM,OACL,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,MAAM,KAAK;AAAA,YACX,qBAAkB;AAAA,YAEjB,iBAAO;AAAA;AAAA,QACV,IACE,MAAM,OACR,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,qBAAkB;AAAA,YAClB,SAAS,MACP,KAAK,QAAQ,QAAQ,EAClB,KAAK,KAAK,IAAI,EACd,MAAM,MAAM,MAAS;AAAA,YAGzB,iBAAO;AAAA;AAAA,QACV,IACE;AAAA,SACN;AAAA;AAAA,EAEJ;AAEJ;","names":["useEffect","useState","useRef","useState","jsx","jsx","jsxs","useState","useEffect"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/sandbox-liveness.ts"],"sourcesContent":["/**\n * A sandbox is available for new I/O only after a holder has observed `warm`.\n *\n * `draining` means the holder count is zero and teardown owns the provider\n * instance. The provider may disappear before the durable lease reaches `cold`,\n * so treating `draining` as live races capture/termination. Explicit user intent\n * reacquires a holder; only its subsequent `warm` state re-enables live I/O.\n */\nexport function sandboxAcceptsLiveIo(liveness: string | null | undefined): boolean {\n return liveness === \"warm\";\n}\n"],"mappings":";AAQO,SAAS,qBAAqB,UAA8C;AACjF,SAAO,aAAa;AACtB;","names":[]}
|
|
@@ -7,12 +7,14 @@ import {
|
|
|
7
7
|
isCreditExhaustion,
|
|
8
8
|
presentFailure,
|
|
9
9
|
tryParseJson
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-3IJJEYW4.js";
|
|
11
11
|
|
|
12
12
|
// src/timeline/projection.ts
|
|
13
13
|
import {
|
|
14
14
|
parseMediaGenerationResult,
|
|
15
|
-
parseToolDisplayMetadata
|
|
15
|
+
parseToolDisplayMetadata,
|
|
16
|
+
EMPTY_FINAL_REPLY_NOTICE,
|
|
17
|
+
turnCompletedWithEmptyFinalReply
|
|
16
18
|
} from "@opengeni/sdk";
|
|
17
19
|
|
|
18
20
|
// src/timeline/fleet-decision-projection.ts
|
|
@@ -255,6 +257,10 @@ function asRecord(value) {
|
|
|
255
257
|
}
|
|
256
258
|
|
|
257
259
|
// src/timeline/projection.ts
|
|
260
|
+
import {
|
|
261
|
+
allowanceExhaustedMessage,
|
|
262
|
+
parseAllowanceExhaustedRefusal
|
|
263
|
+
} from "@opengeni/sdk/allowance-refusal";
|
|
258
264
|
function isTimelineUserQuestion(event) {
|
|
259
265
|
return event.type === "user.message" && workerCompletionPayload(asRecord2(event.payload).childCompletion) === null;
|
|
260
266
|
}
|
|
@@ -301,6 +307,34 @@ function timelineAnnotationToolOutputText(output) {
|
|
|
301
307
|
}
|
|
302
308
|
function buildTimeline(events, options = {}) {
|
|
303
309
|
const items = [];
|
|
310
|
+
const allowanceNotices = /* @__PURE__ */ new Set();
|
|
311
|
+
const allowanceNotice = (event, turnId) => {
|
|
312
|
+
const refusal = parseAllowanceExhaustedRefusal(event.payload);
|
|
313
|
+
if (!refusal) return null;
|
|
314
|
+
const text = allowanceExhaustedMessage(refusal);
|
|
315
|
+
const key = JSON.stringify([
|
|
316
|
+
turnId,
|
|
317
|
+
event.turnAttemptId,
|
|
318
|
+
startupRecoveryRevisionByTurn.get(turnId ?? "") ?? 0,
|
|
319
|
+
refusal.scope,
|
|
320
|
+
refusal.subjectId,
|
|
321
|
+
refusal.resetsAt
|
|
322
|
+
]);
|
|
323
|
+
if (!allowanceNotices.has(key)) {
|
|
324
|
+
allowanceNotices.add(key);
|
|
325
|
+
items.push({
|
|
326
|
+
kind: "notice",
|
|
327
|
+
id: `${event.id}-allowance`,
|
|
328
|
+
tone: "failed",
|
|
329
|
+
text,
|
|
330
|
+
// The canonical sentence replaces upstream prose, so a host renderer
|
|
331
|
+
// reading `message` never shows a wrapper's private wording.
|
|
332
|
+
allowance: { ...refusal, message: text },
|
|
333
|
+
occurredAt: event.occurredAt
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
return text;
|
|
337
|
+
};
|
|
304
338
|
const prescan = prescanTurnAnchors(events);
|
|
305
339
|
const ordered = orderTimelineEvents(events, prescan);
|
|
306
340
|
let completeHistoryPrefix = options.partialStart !== true;
|
|
@@ -1049,6 +1083,10 @@ ${message}` : message;
|
|
|
1049
1083
|
});
|
|
1050
1084
|
break;
|
|
1051
1085
|
}
|
|
1086
|
+
case "usage.exhausted": {
|
|
1087
|
+
allowanceNotice(event, turnId);
|
|
1088
|
+
break;
|
|
1089
|
+
}
|
|
1052
1090
|
case "turn.completed": {
|
|
1053
1091
|
if (payload.maintenance === "context_compaction") {
|
|
1054
1092
|
finalizeOpen(turnId, "complete", event.occurredAt);
|
|
@@ -1056,6 +1094,15 @@ ${message}` : message;
|
|
|
1056
1094
|
takePendingWaitOutcome(turnId);
|
|
1057
1095
|
break;
|
|
1058
1096
|
}
|
|
1097
|
+
const allowance = parseAllowanceExhaustedRefusal(payload);
|
|
1098
|
+
if (allowance) {
|
|
1099
|
+
finalizeOpen(turnId, "complete", event.occurredAt);
|
|
1100
|
+
takeAgentResponse(turnId);
|
|
1101
|
+
takePendingWaitOutcome(turnId);
|
|
1102
|
+
items.push(turnEndItem(event, "failed", ALLOWANCE_TURN_END_TEXT));
|
|
1103
|
+
allowanceNotice(event, turnId);
|
|
1104
|
+
break;
|
|
1105
|
+
}
|
|
1059
1106
|
if (isCreditExhaustionPayload(payload)) {
|
|
1060
1107
|
finalizeOpen(turnId, "complete", event.occurredAt);
|
|
1061
1108
|
takeAgentResponse(turnId);
|
|
@@ -1106,6 +1153,16 @@ ${message}` : message;
|
|
|
1106
1153
|
finalizeOpen(turnId, "complete", event.occurredAt);
|
|
1107
1154
|
const completedTurn = turnEndItem(event, "complete", null);
|
|
1108
1155
|
items.push(completedTurn);
|
|
1156
|
+
if (turnCompletedWithEmptyFinalReply(payload)) {
|
|
1157
|
+
items.push({
|
|
1158
|
+
kind: "notice",
|
|
1159
|
+
id: `${event.id}-empty-final-reply`,
|
|
1160
|
+
tone: "input",
|
|
1161
|
+
text: EMPTY_FINAL_REPLY_NOTICE,
|
|
1162
|
+
recordedOutcome: true,
|
|
1163
|
+
occurredAt: event.occurredAt
|
|
1164
|
+
});
|
|
1165
|
+
}
|
|
1109
1166
|
const hasCompletedFinalResponse = latestAgentResponse?.completed === true && latestAgentResponse.item.phase !== "commentary" && Boolean(visibleTrackedResponse);
|
|
1110
1167
|
if (!hasAuthoritativeFinalOutput && pendingWaitOutcome) {
|
|
1111
1168
|
completedTurn.preserveWaitResponse = true;
|
|
@@ -1129,10 +1186,13 @@ ${message}` : message;
|
|
|
1129
1186
|
takeAgentResponse(turnId);
|
|
1130
1187
|
takePendingWaitOutcome(turnId);
|
|
1131
1188
|
const hadActivity = hasTurnActivity(items, turnId);
|
|
1132
|
-
const
|
|
1189
|
+
const allowance = parseAllowanceExhaustedRefusal(payload);
|
|
1190
|
+
const failureText = allowance ? ALLOWANCE_TURN_END_TEXT : isCreditExhaustionPayload(payload) ? CREDIT_EXHAUSTION_MESSAGE : failureMessage(payload);
|
|
1133
1191
|
finalizeOpen(turnId, "cancelled", event.occurredAt);
|
|
1134
1192
|
items.push(turnEndItem(event, "failed", failureText));
|
|
1135
|
-
if (
|
|
1193
|
+
if (allowance) {
|
|
1194
|
+
allowanceNotice(event, turnId);
|
|
1195
|
+
} else if (!hadActivity) {
|
|
1136
1196
|
items.push({
|
|
1137
1197
|
kind: "notice",
|
|
1138
1198
|
id: event.id,
|
|
@@ -1399,7 +1459,9 @@ function mergeToolCallRaw(existingValue, nextValue) {
|
|
|
1399
1459
|
function stripOpaqueCitationTokens(text) {
|
|
1400
1460
|
return text.replace(/\s*cite(?:[^]+)+/gu, "");
|
|
1401
1461
|
}
|
|
1462
|
+
var ALLOWANCE_TURN_END_TEXT = "Usage limit reached";
|
|
1402
1463
|
function isCreditExhaustionPayload(payload) {
|
|
1464
|
+
if (payload.code === "allowance_exhausted") return false;
|
|
1403
1465
|
return isCreditExhaustion({
|
|
1404
1466
|
error: typeof payload.error === "string" ? payload.error : null,
|
|
1405
1467
|
detail: typeof payload.detail === "string" ? payload.detail : null,
|
|
@@ -1858,7 +1920,9 @@ function isAgentActivityEvent(type) {
|
|
|
1858
1920
|
return type.startsWith("agent.") || type.startsWith("sandbox.");
|
|
1859
1921
|
}
|
|
1860
1922
|
function isTurnExecutionEvidence(type) {
|
|
1861
|
-
return isAgentActivityEvent(type) || type === "turn.completed" || type === "turn.failed" ||
|
|
1923
|
+
return isAgentActivityEvent(type) || type === "turn.completed" || type === "turn.failed" || // An admission refusal can settle a queued turn before it ever starts:
|
|
1924
|
+
// its prompt still belongs above the "usage limit reached" row.
|
|
1925
|
+
type === "usage.exhausted" || type === "turn.superseded" || type === "turn.recovery.requested" || type === "turn.capacity_waiting" || type === "session.requiresAction" || type === "tool.auth_needed" || type === "credential.auth_needed" || type.startsWith("turn.startup.phase.") || type.startsWith("rig.setup.") || type === "codex.capacity.waiting" || type === "codex.capacity.resumed" || type === "codex.fleet.decision";
|
|
1862
1926
|
}
|
|
1863
1927
|
function turnEndItem(event, outcome, failureText) {
|
|
1864
1928
|
return {
|
|
@@ -2508,4 +2572,4 @@ export {
|
|
|
2508
2572
|
isTurnExecutionEvidence,
|
|
2509
2573
|
extractSessionRef
|
|
2510
2574
|
};
|
|
2511
|
-
//# sourceMappingURL=chunk-
|
|
2575
|
+
//# sourceMappingURL=chunk-ZXSEDZP7.js.map
|