@omni-commerce/sdk 0.8.0 → 0.8.1

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/embed.ts","../src/application.ts","../src/widget-chrome.ts","../src/widget.ts","../src/embed-code.ts"],"sourcesContent":["import {\n createApplicationMessageHandler,\n type OmniApplicationOptions,\n} from \"./application\";\nexport type {\n OmniFrontendTool,\n OmniChatApplication,\n OmniApplicationOptions,\n} from \"./application\";\n/** A hosted chat session. Keep its short-lived token in memory, never in iframe URLs. */\nexport { createOmniChatWidget, type OmniChatWidgetOptions } from \"./widget\";\nexport { getOmniChatEmbedCode, getOmniChatReactCode } from \"./embed-code\";\nexport interface OmniChatSession {\n token: string;\n threadId: string;\n expiresIn: number;\n}\nexport interface OmniChatEmbedOptions extends OmniApplicationOptions {\n deploymentId: string;\n baseUrl?: string;\n /** Optional authenticated session mint on the host application's server. */\n getSession?: () => Promise<OmniChatSession>;\n title?: string;\n onError?: (error: Error) => void;\n /** Floating widgets use this to close on Escape from the hosted chat. */\n onRequestClose?: () => void;\n}\nexport interface OmniChatEmbed {\n iframe: HTMLIFrameElement;\n /** Focus the hosted composer, including when reopening a retained chat. */\n focus(): void;\n destroy(): void;\n}\n\nexport function getOmniChatEmbedUrl(\n options: Pick<OmniChatEmbedOptions, \"baseUrl\" | \"deploymentId\">,\n parentOrigin?: string,\n): string {\n if (\n !/^[\\da-f]{8}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{12}$/i.test(\n options.deploymentId,\n )\n )\n throw new Error(\"A valid chat deployment ID is required.\");\n const base = new URL(options.baseUrl ?? \"https://omnicommerce.sg\");\n if (\n (base.protocol !== \"https:\" &&\n !(\n base.protocol === \"http:\" &&\n [\"localhost\", \"127.0.0.1\"].includes(base.hostname)\n )) ||\n base.username ||\n base.password ||\n base.pathname !== \"/\" ||\n base.search ||\n base.hash\n )\n throw new Error(\"Chat baseUrl must be an HTTPS origin, or HTTP localhost.\");\n const url = new URL(`/embed/${options.deploymentId}`, base.origin);\n if (parentOrigin)\n url.searchParams.set(\"parentOrigin\", new URL(parentOrigin).origin);\n return url.toString();\n}\n\n/** Browser-only mounting; importing this entry point is safe during SSR. */\nexport function createOmniChatEmbed(\n container: HTMLElement,\n options: OmniChatEmbedOptions,\n): OmniChatEmbed {\n const document = container.ownerDocument;\n const host = document.defaultView;\n if (!host) throw new Error(\"A browser document is required to mount chat.\");\n const iframe = document.createElement(\"iframe\");\n iframe.src = getOmniChatEmbedUrl(options, host.location.origin);\n iframe.title = options.title ?? \"OmniCommerce assistant\";\n iframe.referrerPolicy = \"strict-origin-when-cross-origin\";\n iframe.setAttribute(\n \"sandbox\",\n \"allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox\",\n );\n Object.assign(iframe.style, {\n width: \"100%\",\n height: \"100%\",\n minHeight: \"320px\",\n border: \"0\",\n display: \"block\",\n });\n const chatOrigin = new URL(iframe.src).origin;\n let destroyed = false;\n let pending: Promise<OmniChatSession> | undefined;\n let previousToken: string | undefined;\n const controller = new AbortController();\n\n const mint = async (): Promise<OmniChatSession> => {\n if (options.getSession) return options.getSession();\n const response = await host.fetch(\n `${chatOrigin}/api/embed/${options.deploymentId}/session`,\n {\n method: \"POST\",\n credentials: \"include\",\n signal: controller.signal,\n headers: {\n \"Content-Type\": \"application/json\",\n ...(previousToken\n ? { Authorization: `Bearer ${previousToken}` }\n : {}),\n },\n body: \"{}\",\n },\n );\n const result = (await response.json()) as OmniChatSession & {\n error?: string;\n };\n if (!response.ok) {\n // A rejected renewal must not keep Retry bound to an obsolete session.\n // The next mint still performs the deployment's full access checks.\n if (response.status === 401 || response.status === 403)\n previousToken = undefined;\n throw new Error(result.error ?? \"Could not open the chat session.\");\n }\n return result;\n };\n const applicationMessage = createApplicationMessageHandler({\n options,\n signal: controller.signal,\n reply: (message) => {\n if (!destroyed)\n iframe.contentWindow?.postMessage(\n { ...message, deploymentId: options.deploymentId },\n chatOrigin,\n );\n },\n });\n const receive = (event: MessageEvent) => {\n if (\n destroyed ||\n event.source !== iframe.contentWindow ||\n event.origin !== chatOrigin ||\n event.data?.deploymentId !== options.deploymentId\n )\n return;\n if (\n event.data.type === \"omni-chat:application-request\" ||\n event.data.type === \"omni-chat:tool-request\"\n ) {\n void applicationMessage(event.data);\n return;\n }\n if (event.data.type === \"omni-chat:close-request\") {\n options.onRequestClose?.();\n return;\n }\n if (event.data.type !== \"omni-chat:session-request\") return;\n pending ??= mint();\n void pending\n .then((session) => {\n if (destroyed) return;\n if (\n typeof session?.token !== \"string\" ||\n !session.token ||\n session.token.length > 4096 ||\n typeof session.threadId !== \"string\" ||\n !session.threadId ||\n !Number.isFinite(session.expiresIn) ||\n session.expiresIn <= 0\n )\n throw new Error(\"Invalid chat session response.\");\n previousToken = session.token;\n iframe.contentWindow?.postMessage(\n {\n type: \"omni-chat:session\",\n deploymentId: options.deploymentId,\n session,\n ...(options.application ? { applicationEnabled: true } : {}),\n },\n chatOrigin,\n );\n })\n .catch((error: unknown) => {\n if (destroyed) return;\n const failure =\n error instanceof Error ? error : new Error(\"Could not open chat.\");\n options.onError?.(failure);\n iframe.contentWindow?.postMessage(\n {\n type: \"omni-chat:session-error\",\n deploymentId: options.deploymentId,\n error: failure.message,\n ...(options.application ? {applicationEnabled: true} : {}),\n },\n chatOrigin,\n );\n })\n .finally(() => {\n pending = undefined;\n });\n };\n host.addEventListener(\"message\", receive);\n container.append(iframe);\n return {\n iframe,\n focus() {\n if (destroyed) return;\n iframe.focus();\n iframe.contentWindow?.postMessage(\n {\n type: \"omni-chat:focus-composer\",\n deploymentId: options.deploymentId,\n },\n chatOrigin,\n );\n },\n destroy() {\n if (destroyed) return;\n destroyed = true;\n controller.abort();\n previousToken = undefined;\n host.removeEventListener(\"message\", receive);\n iframe.remove();\n },\n };\n}\n","/** Host-defined actions execute inside the application, never on the assistant server. */\nexport interface OmniFrontendTool {\n description: string;\n parameters: Record<string, unknown>;\n execute: (\n args: Record<string, unknown>,\n context: { toolCallId: string; abortSignal: AbortSignal },\n ) => unknown | Promise<unknown>;\n}\nexport interface OmniChatApplication {\n name: string;\n description: string;\n /** Return a small, explicitly selected snapshot. Do not include secrets. */\n getContext: () => unknown | Promise<unknown>;\n}\nexport interface OmniApplicationOptions {\n application?: OmniChatApplication;\n /** Names must start with app_; use array arguments for actions with multiple targets. */\n frontendTools?: Record<string, OmniFrontendTool>;\n}\n\nfunction boundedJson(value: unknown, maximum: number): unknown {\n const encoded = JSON.stringify(value);\n if (\n typeof encoded !== \"string\" ||\n new TextEncoder().encode(encoded).length > maximum ||\n /data:[^\"\\s]{0,100};base64,/i.test(encoded)\n )\n throw new Error(\n \"Application data must be bounded JSON without base64 payloads.\",\n );\n return JSON.parse(encoded);\n}\n\nexport function createApplicationMessageHandler(input: {\n options: OmniApplicationOptions;\n signal: AbortSignal;\n reply: (message: Record<string, unknown>) => void;\n}) {\n // A repeated parked call reuses its result instead of applying an action twice.\n const calls = new Map<\n string,\n { signature: string; result: Promise<unknown> }\n >();\n return async (message: Record<string, unknown>) => {\n if (typeof message.requestId !== \"string\" || message.requestId.length > 200)\n return;\n try {\n if (message.type === \"omni-chat:application-request\") {\n const application = input.options.application;\n input.reply({\n type: \"omni-chat:application-response\",\n requestId: message.requestId,\n application: application\n ? boundedJson(\n {\n name: application.name,\n description: application.description,\n context: (await application.getContext()) ?? null,\n tools: Object.entries(input.options.frontendTools ?? {}).map(\n ([name, definition]) => ({\n name,\n description: definition.description,\n parameters: definition.parameters,\n }),\n ),\n },\n 65536,\n )\n : undefined,\n });\n } else if (message.type === \"omni-chat:tool-request\") {\n const name = message.toolName;\n const toolCallId = message.toolCallId;\n if (\n typeof name !== \"string\" ||\n !/^app_[a-z][a-z0-9_]{0,59}$/.test(name) ||\n typeof toolCallId !== \"string\" ||\n !toolCallId ||\n toolCallId.length > 200\n )\n throw new Error(\"Invalid application tool request.\");\n const definition = Object.hasOwn(\n input.options.frontendTools ?? {},\n name,\n )\n ? input.options.frontendTools?.[name]\n : undefined;\n if (!input.options.application || !definition)\n throw new Error(\"This application action is unavailable.\");\n const args = message.args;\n if (!args || typeof args !== \"object\" || Array.isArray(args))\n throw new Error(\"Invalid application action arguments.\");\n const signature = JSON.stringify({ name, args });\n const prior = calls.get(toolCallId);\n if (prior && prior.signature !== signature)\n throw new Error(\"This tool call ID was already used.\");\n const result =\n prior?.result ??\n Promise.resolve().then(() =>\n definition.execute(args as Record<string, unknown>, {\n toolCallId,\n abortSignal: input.signal,\n }),\n );\n if (!prior) {\n if (calls.size >= 200)\n throw new Error(\"Start a new application chat.\");\n calls.set(toolCallId, { signature, result });\n }\n input.reply({\n type: \"omni-chat:tool-response\",\n requestId: message.requestId,\n toolCallId,\n result: boundedJson((await result) ?? null, 12000),\n });\n }\n } catch (error) {\n input.reply({\n type:\n message.type === \"omni-chat:application-request\"\n ? \"omni-chat:application-response\"\n : \"omni-chat:tool-response\",\n requestId: message.requestId,\n toolCallId: message.toolCallId,\n error:\n error instanceof Error\n ? error.message\n : \"The application action failed.\",\n });\n }\n };\n}\n","const iconPaths = {\n chat: \"M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5Z\",\n close: \"m6 6 12 12M6 18 18 6\",\n collapse: \"m6 9 6 6 6-6\",\n};\n\nexport function widgetIcon(document: Document, name: keyof typeof iconPaths) {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 24 24\");\n svg.setAttribute(\"fill\", \"none\");\n svg.setAttribute(\"stroke\", \"currentColor\");\n svg.setAttribute(\"stroke-width\", \"1.8\");\n svg.setAttribute(\"stroke-linecap\", \"round\");\n svg.setAttribute(\"stroke-linejoin\", \"round\");\n svg.setAttribute(\"aria-hidden\", \"true\");\n const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n path.setAttribute(\"d\", iconPaths[name]);\n svg.append(path);\n return svg;\n}\n\n/** Shadow DOM keeps a store's button, font and section CSS out of the widget. */\nexport const widgetStyles = `\n :host { all: initial; font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif; color-scheme: light; }\n *, *::before, *::after { box-sizing: border-box; }\n button { font: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; }\n button:focus-visible { outline: 3px solid var(--omni-launcher-bg); outline-offset: 4px; }\n svg { display: block; width: 22px; height: 22px; flex: none; }\n .launcher {\n display: flex; align-items: center; justify-content: center; gap: 10px;\n height: 52px; padding: 0 20px; border: 1px solid rgba(255,255,255,.14);\n border-radius: 999px; background: var(--omni-launcher-bg); color: var(--omni-launcher-fg);\n font-size: 14px; font-weight: 600; line-height: 1; letter-spacing: -.01em;\n box-shadow: 0 6px 24px rgba(0,0,0,.16), 0 2px 6px rgba(0,0,0,.08);\n transition: transform 160ms ease, box-shadow 160ms ease;\n margin-left: auto;\n }\n .launcher:hover { transform: translateY(-2px); box-shadow: 0 10px 28px rgba(0,0,0,.2); }\n .launcher[hidden] { display: none; }\n .launcher[aria-expanded=\"true\"] { width: 52px; padding: 0; }\n .launcher[aria-expanded=\"true\"] .label { display: none; }\n .panel {\n position: absolute; bottom: 66px; right: 0; width: min(392px, calc(100vw - 40px));\n overflow: hidden; border: 1px solid rgba(0,0,0,.08); border-radius: 20px;\n background: var(--omni-panel-bg); box-shadow: 0 24px 80px rgba(0,0,0,.18), 0 4px 16px rgba(0,0,0,.06);\n animation: omni-chat-enter 180ms ease-out;\n }\n .panel[hidden] { display: none; }\n .frame { height: min(780px, calc(100dvh - 112px)); min-height: 240px; }\n .close {\n position: absolute; z-index: 1; top: 18px; right: 14px;\n display: flex; align-items: center; justify-content: center; width: 34px; height: 34px;\n border: 1px solid color-mix(in srgb, var(--omni-panel-fg) 10%, transparent); border-radius: 50%;\n background: var(--omni-panel-bg); color: var(--omni-panel-fg); transition: background 160ms ease;\n }\n .close svg { width: 17px; height: 17px; }\n .close:hover { background: color-mix(in srgb, var(--omni-panel-fg) 6%, var(--omni-panel-bg)); }\n :host([data-position=\"left\"]) .panel { right: auto; left: 0; }\n :host([data-position=\"left\"]) .launcher { margin-left: 0; }\n :host([data-presentation=\"sidebar\"]) .panel {\n position: fixed; top: 0; bottom: 0; right: 0; left: auto;\n width: min(440px, 100vw); border-radius: 0; border-top: 0; border-bottom: 0;\n animation: omni-sidebar-enter 180ms ease-out;\n }\n :host([data-presentation=\"sidebar\"]) .frame { height: 100dvh; min-height: 0; }\n :host([data-presentation=\"sidebar\"][data-position=\"left\"]) .panel {\n right: auto; left: 0; animation-name: omni-sidebar-enter-left;\n }\n @keyframes omni-sidebar-enter { from { opacity: 0; transform: translateX(100%); } to { opacity: 1; transform: none; } }\n @keyframes omni-sidebar-enter-left { from { opacity: 0; transform: translateX(-100%); } to { opacity: 1; transform: none; } }\n @keyframes omni-chat-enter { from { opacity: 0; transform: translateY(8px) scale(.98); } to { opacity: 1; transform: none; } }\n @media (max-width: 480px) { :host([data-presentation=\"floating\"]) .panel { width: calc(100vw - 40px); border-radius: 18px; } }\n @media (prefers-reduced-motion: reduce) { .panel, :host([data-presentation=\"sidebar\"]) .panel { animation: none; } .launcher { transition: none; } }\n`;\n","import {\n createOmniChatEmbed,\n getOmniChatEmbedUrl,\n type OmniChatEmbedOptions,\n type OmniChatEmbed,\n} from \"./embed\";\nimport { widgetIcon, widgetStyles } from \"./widget-chrome\";\n\nexport type OmniChatWidgetOptions = OmniChatEmbedOptions & {\n /** Floating window by default; sidebar fills the viewport height. */\n presentation?: \"floating\" | \"sidebar\";\n launcherLabel?: string;\n position?: \"left\" | \"right\";\n launcherBackground?: string;\n launcherForeground?: string;\n panelBackground?: string;\n panelForeground?: string;\n};\nlet widgetSequence = 0;\n/** A website launcher using the same hosted assistant as OmniChat. */\nexport function createOmniChatWidget(\n container: HTMLElement,\n options: OmniChatWidgetOptions,\n) {\n getOmniChatEmbedUrl(options);\n const document = container.ownerDocument;\n const root = document.createElement(\"div\");\n root.setAttribute(\"data-omni-chat-widget\", \"\");\n root.setAttribute(\"data-position\", options.position ?? \"right\");\n root.setAttribute(\"data-presentation\", options.presentation ?? \"floating\");\n const shadow = root.attachShadow({ mode: \"open\" });\n const style = document.createElement(\"style\");\n style.textContent = widgetStyles;\n const launcher = document.createElement(\"button\");\n const panel = document.createElement(\"section\");\n const close = document.createElement(\"button\");\n const frame = document.createElement(\"div\");\n let embed: OmniChatEmbed | undefined;\n let destroyed = false;\n Object.assign(root.style, {\n position: \"fixed\",\n bottom: \"20px\",\n [options.position ?? \"right\"]: \"20px\",\n zIndex: \"2147483000\",\n });\n root.style.setProperty(\n \"--omni-launcher-bg\",\n options.launcherBackground ?? \"#2563eb\",\n );\n root.style.setProperty(\n \"--omni-launcher-fg\",\n options.launcherForeground ?? \"#ffffff\",\n );\n root.style.setProperty(\n \"--omni-panel-bg\",\n options.panelBackground ?? \"#ffffff\",\n );\n root.style.setProperty(\n \"--omni-panel-fg\",\n options.panelForeground ?? \"#171717\",\n );\n launcher.type = close.type = \"button\";\n launcher.className = \"launcher\";\n const label = document.createElement(\"span\");\n label.className = \"label\";\n label.textContent = options.launcherLabel ?? \"Chat with us\";\n launcher.append(widgetIcon(document, \"chat\"), label);\n launcher.setAttribute(\"aria-expanded\", \"false\");\n launcher.setAttribute(\"aria-label\", label.textContent);\n panel.hidden = true;\n panel.className = \"panel\";\n panel.setAttribute(\"role\", \"region\");\n panel.setAttribute(\"aria-label\", options.title ?? \"Assistant chat\");\n panel.id = `omni-chat-widget-${++widgetSequence}`;\n launcher.setAttribute(\"aria-controls\", panel.id);\n frame.className = \"frame\";\n close.className = \"close\";\n close.setAttribute(\"aria-label\", \"Close chat\");\n close.title = \"Close chat\";\n close.append(widgetIcon(document, \"close\"));\n const closeChat = () => {\n if (destroyed) return;\n panel.hidden = true;\n launcher.hidden = false;\n launcher.setAttribute(\"aria-expanded\", \"false\");\n launcher.setAttribute(\"aria-label\", label.textContent!);\n launcher.querySelector(\"svg\")?.replaceWith(widgetIcon(document, \"chat\"));\n launcher.focus();\n };\n const openChat = () => {\n if (destroyed) return;\n embed ??= createOmniChatEmbed(frame, {\n ...options,\n onRequestClose: closeChat,\n });\n embed.iframe.style.minHeight = \"0\";\n panel.hidden = false;\n launcher.hidden = options.presentation === \"sidebar\";\n launcher.setAttribute(\"aria-expanded\", \"true\");\n launcher.setAttribute(\"aria-label\", \"Close chat\");\n launcher\n .querySelector(\"svg\")\n ?.replaceWith(widgetIcon(document, \"collapse\"));\n embed.focus();\n };\n launcher.addEventListener(\"click\", () =>\n panel.hidden ? openChat() : closeChat(),\n );\n close.addEventListener(\"click\", closeChat);\n shadow.addEventListener(\"keydown\", (event) => {\n if ((event as KeyboardEvent).key === \"Escape\" && !panel.hidden) closeChat();\n });\n panel.append(close, frame);\n shadow.append(style, panel, launcher);\n container.append(root);\n return {\n open: openChat,\n close: closeChat,\n destroy() {\n destroyed = true;\n embed?.destroy();\n root.remove();\n },\n };\n}\n","import { getOmniChatEmbedUrl, type OmniChatEmbedOptions } from \"./embed\";\nimport type { OmniChatWidgetOptions } from \"./widget\";\n\ntype EmbedCodeOptions = Pick<\n OmniChatEmbedOptions,\n \"baseUrl\" | \"deploymentId\" | \"title\"\n> &\n Pick<\n OmniChatWidgetOptions,\n | \"presentation\"\n | \"launcherLabel\"\n | \"position\"\n | \"launcherBackground\"\n | \"launcherForeground\"\n | \"panelBackground\"\n | \"panelForeground\"\n >;\nconst scriptJson = (value: unknown) =>\n JSON.stringify(value, null, 2).replace(\n /[<>&\\u2028\\u2029]/g,\n (character) =>\n `\\\\u${character.charCodeAt(0).toString(16).padStart(4, \"0\")}`,\n );\n\n/** Copyable integrations contain only public deployment configuration. */\nexport function getOmniChatEmbedCode(\n options: EmbedCodeOptions,\n mode: \"widget\" | \"inline\" = \"widget\",\n) {\n const baseUrl = new URL(getOmniChatEmbedUrl(options)).origin;\n const config = { ...options, baseUrl };\n const id = `omni-chat-${options.deploymentId}`;\n const mount =\n mode === \"widget\"\n ? `OmniCommerceChat.createOmniChatWidget(document.body, ${scriptJson(config)});`\n : `OmniCommerceChat.createOmniChatEmbed(document.getElementById(${scriptJson(id)}), ${scriptJson(config)});`;\n return `${mode === \"inline\" ? `<div id=\"${id}\" style=\"height:600px\"></div>\\n` : \"\"}<script src=\"${baseUrl}/sdk/embed.global.js\"></script>\\n<script>\\n ${mount.replace(/\\n/g, \"\\n \")}\\n</script>`;\n}\nexport function getOmniChatReactCode(options: EmbedCodeOptions) {\n const baseUrl = new URL(getOmniChatEmbedUrl(options)).origin;\n return `import { OmniProvider, OmniChat } from \"@omni-commerce/sdk/react\";\\n\\n<OmniProvider deploymentId={${scriptJson(options.deploymentId)}}\\n baseUrl={${scriptJson(baseUrl)}}${options.title ? `\\n title={${scriptJson(options.title)}}` : \"\"}>\\n <OmniChat style={{ height: 600 }} />\\n</OmniProvider>`;\n}\n"],"mappings":"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","names":["embed_exports","__export","createOmniChatEmbed","createOmniChatWidget","getOmniChatEmbedCode","getOmniChatEmbedUrl","getOmniChatReactCode","boundedJson","value","maximum","encoded","createApplicationMessageHandler","input","calls","message","application","name","definition","toolCallId","args","signature","prior","result","error","iconPaths","widgetIcon","document","name","svg","path","widgetStyles","widgetSequence","createOmniChatWidget","container","options","getOmniChatEmbedUrl","document","root","shadow","style","widgetStyles","launcher","panel","close","frame","embed","destroyed","label","widgetIcon","closeChat","openChat","createOmniChatEmbed","event","scriptJson","value","character","getOmniChatEmbedCode","options","mode","baseUrl","getOmniChatEmbedUrl","config","id","mount","getOmniChatReactCode","getOmniChatEmbedUrl","options","parentOrigin","base","url","createOmniChatEmbed","container","document","host","iframe","chatOrigin","destroyed","pending","previousToken","controller","mint","response","result","applicationMessage","createApplicationMessageHandler","message","receive","event","session","error","failure"]}
1
+ {"version":3,"sources":["../src/embed.ts","../src/application.ts","../src/widget-chrome.ts","../src/widget-config.ts","../src/widget.ts","../src/embed-code.ts"],"sourcesContent":["import {\n createApplicationMessageHandler,\n type OmniApplicationOptions,\n} from \"./application\";\nexport type {\n OmniFrontendTool,\n OmniChatApplication,\n OmniApplicationOptions,\n} from \"./application\";\n/** A hosted chat session. Keep its short-lived token in memory, never in iframe URLs. */\nexport { createOmniChatWidget, type OmniChatWidgetOptions } from \"./widget\";\nexport { getOmniChatEmbedCode, getOmniChatReactCode } from \"./embed-code\";\nexport interface OmniChatSession {\n token: string;\n threadId: string;\n expiresIn: number;\n}\nexport interface OmniChatEmbedOptions extends OmniApplicationOptions {\n deploymentId: string;\n baseUrl?: string;\n /** Optional authenticated session mint on the host application's server. */\n getSession?: () => Promise<OmniChatSession>;\n title?: string;\n onError?: (error: Error) => void;\n /** Floating widgets use this to close on Escape from the hosted chat. */\n onRequestClose?: () => void;\n}\nexport interface OmniChatEmbed {\n iframe: HTMLIFrameElement;\n /** Focus the hosted composer, including when reopening a retained chat. */\n focus(): void;\n destroy(): void;\n}\n\nexport function getOmniChatEmbedUrl(\n options: Pick<OmniChatEmbedOptions, \"baseUrl\" | \"deploymentId\">,\n parentOrigin?: string,\n): string {\n if (\n !/^[\\da-f]{8}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{12}$/i.test(\n options.deploymentId,\n )\n )\n throw new Error(\"A valid chat deployment ID is required.\");\n const base = new URL(options.baseUrl ?? \"https://omnicommerce.sg\");\n if (\n (base.protocol !== \"https:\" &&\n !(\n base.protocol === \"http:\" &&\n [\"localhost\", \"127.0.0.1\"].includes(base.hostname)\n )) ||\n base.username ||\n base.password ||\n base.pathname !== \"/\" ||\n base.search ||\n base.hash\n )\n throw new Error(\"Chat baseUrl must be an HTTPS origin, or HTTP localhost.\");\n const url = new URL(`/embed/${options.deploymentId}`, base.origin);\n if (parentOrigin)\n url.searchParams.set(\"parentOrigin\", new URL(parentOrigin).origin);\n return url.toString();\n}\n\n/** Browser-only mounting; importing this entry point is safe during SSR. */\nexport function createOmniChatEmbed(\n container: HTMLElement,\n options: OmniChatEmbedOptions,\n): OmniChatEmbed {\n const document = container.ownerDocument;\n const host = document.defaultView;\n if (!host) throw new Error(\"A browser document is required to mount chat.\");\n const iframe = document.createElement(\"iframe\");\n iframe.src = getOmniChatEmbedUrl(options, host.location.origin);\n iframe.title = options.title ?? \"OmniCommerce assistant\";\n iframe.referrerPolicy = \"strict-origin-when-cross-origin\";\n iframe.setAttribute(\n \"sandbox\",\n \"allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox\",\n );\n Object.assign(iframe.style, {\n width: \"100%\",\n height: \"100%\",\n minHeight: \"320px\",\n border: \"0\",\n display: \"block\",\n });\n const chatOrigin = new URL(iframe.src).origin;\n let destroyed = false;\n let pending: Promise<OmniChatSession> | undefined;\n let previousToken: string | undefined;\n const controller = new AbortController();\n\n const mint = async (): Promise<OmniChatSession> => {\n if (options.getSession) return options.getSession();\n const response = await host.fetch(\n `${chatOrigin}/api/embed/${options.deploymentId}/session`,\n {\n method: \"POST\",\n credentials: \"include\",\n signal: controller.signal,\n headers: {\n \"Content-Type\": \"application/json\",\n ...(previousToken\n ? { Authorization: `Bearer ${previousToken}` }\n : {}),\n },\n body: \"{}\",\n },\n );\n const result = (await response.json()) as OmniChatSession & {\n error?: string;\n };\n if (!response.ok) {\n // A rejected renewal must not keep Retry bound to an obsolete session.\n // The next mint still performs the deployment's full access checks.\n if (response.status === 401 || response.status === 403)\n previousToken = undefined;\n throw new Error(result.error ?? \"Could not open the chat session.\");\n }\n return result;\n };\n const applicationMessage = createApplicationMessageHandler({\n options,\n signal: controller.signal,\n reply: (message) => {\n if (!destroyed)\n iframe.contentWindow?.postMessage(\n { ...message, deploymentId: options.deploymentId },\n chatOrigin,\n );\n },\n });\n const receive = (event: MessageEvent) => {\n if (\n destroyed ||\n event.source !== iframe.contentWindow ||\n event.origin !== chatOrigin ||\n event.data?.deploymentId !== options.deploymentId\n )\n return;\n if (\n event.data.type === \"omni-chat:application-request\" ||\n event.data.type === \"omni-chat:tool-request\"\n ) {\n void applicationMessage(event.data);\n return;\n }\n if (event.data.type === \"omni-chat:close-request\") {\n options.onRequestClose?.();\n return;\n }\n if (event.data.type !== \"omni-chat:session-request\") return;\n pending ??= mint();\n void pending\n .then((session) => {\n if (destroyed) return;\n if (\n typeof session?.token !== \"string\" ||\n !session.token ||\n session.token.length > 4096 ||\n typeof session.threadId !== \"string\" ||\n !session.threadId ||\n !Number.isFinite(session.expiresIn) ||\n session.expiresIn <= 0\n )\n throw new Error(\"Invalid chat session response.\");\n previousToken = session.token;\n iframe.contentWindow?.postMessage(\n {\n type: \"omni-chat:session\",\n deploymentId: options.deploymentId,\n session,\n ...(options.application ? { applicationEnabled: true } : {}),\n },\n chatOrigin,\n );\n })\n .catch((error: unknown) => {\n if (destroyed) return;\n const failure =\n error instanceof Error ? error : new Error(\"Could not open chat.\");\n options.onError?.(failure);\n iframe.contentWindow?.postMessage(\n {\n type: \"omni-chat:session-error\",\n deploymentId: options.deploymentId,\n error: failure.message,\n ...(options.application ? { applicationEnabled: true } : {}),\n },\n chatOrigin,\n );\n })\n .finally(() => {\n pending = undefined;\n });\n };\n host.addEventListener(\"message\", receive);\n container.append(iframe);\n return {\n iframe,\n focus() {\n if (destroyed) return;\n iframe.focus();\n iframe.contentWindow?.postMessage(\n {\n type: \"omni-chat:focus-composer\",\n deploymentId: options.deploymentId,\n },\n chatOrigin,\n );\n },\n destroy() {\n if (destroyed) return;\n destroyed = true;\n controller.abort();\n previousToken = undefined;\n host.removeEventListener(\"message\", receive);\n iframe.remove();\n },\n };\n}\n","/** Host-defined actions execute inside the application, never on the assistant server. */\nexport interface OmniFrontendTool {\n description: string;\n parameters: Record<string, unknown>;\n execute: (\n args: Record<string, unknown>,\n context: { toolCallId: string; abortSignal: AbortSignal },\n ) => unknown | Promise<unknown>;\n}\nexport interface OmniChatApplication {\n name: string;\n description: string;\n /** Return a small, explicitly selected snapshot. Do not include secrets. */\n getContext: () => unknown | Promise<unknown>;\n}\nexport interface OmniApplicationOptions {\n application?: OmniChatApplication;\n /** Names must start with app_; use array arguments for actions with multiple targets. */\n frontendTools?: Record<string, OmniFrontendTool>;\n}\n\nfunction boundedJson(value: unknown, maximum: number): unknown {\n const encoded = JSON.stringify(value);\n if (\n typeof encoded !== \"string\" ||\n new TextEncoder().encode(encoded).length > maximum ||\n /data:[^\"\\s]{0,100};base64,/i.test(encoded)\n )\n throw new Error(\n \"Application data must be bounded JSON without base64 payloads.\",\n );\n return JSON.parse(encoded);\n}\n\nexport function createApplicationMessageHandler(input: {\n options: OmniApplicationOptions;\n signal: AbortSignal;\n reply: (message: Record<string, unknown>) => void;\n}) {\n // A repeated parked call reuses its result instead of applying an action twice.\n const calls = new Map<\n string,\n { signature: string; result: Promise<unknown> }\n >();\n return async (message: Record<string, unknown>) => {\n if (typeof message.requestId !== \"string\" || message.requestId.length > 200)\n return;\n try {\n if (message.type === \"omni-chat:application-request\") {\n const application = input.options.application;\n input.reply({\n type: \"omni-chat:application-response\",\n requestId: message.requestId,\n application: application\n ? boundedJson(\n {\n name: application.name,\n description: application.description,\n context: (await application.getContext()) ?? null,\n tools: Object.entries(input.options.frontendTools ?? {}).map(\n ([name, definition]) => ({\n name,\n description: definition.description,\n parameters: definition.parameters,\n }),\n ),\n },\n 65536,\n )\n : undefined,\n });\n } else if (message.type === \"omni-chat:tool-request\") {\n const name = message.toolName;\n const toolCallId = message.toolCallId;\n if (\n typeof name !== \"string\" ||\n !/^app_[a-z][a-z0-9_]{0,59}$/.test(name) ||\n typeof toolCallId !== \"string\" ||\n !toolCallId ||\n toolCallId.length > 200\n )\n throw new Error(\"Invalid application tool request.\");\n const definition = Object.hasOwn(\n input.options.frontendTools ?? {},\n name,\n )\n ? input.options.frontendTools?.[name]\n : undefined;\n if (!input.options.application || !definition)\n throw new Error(\"This application action is unavailable.\");\n const args = message.args;\n if (!args || typeof args !== \"object\" || Array.isArray(args))\n throw new Error(\"Invalid application action arguments.\");\n const signature = JSON.stringify({ name, args });\n const prior = calls.get(toolCallId);\n if (prior && prior.signature !== signature)\n throw new Error(\"This tool call ID was already used.\");\n const result =\n prior?.result ??\n Promise.resolve().then(() =>\n definition.execute(args as Record<string, unknown>, {\n toolCallId,\n abortSignal: input.signal,\n }),\n );\n if (!prior) {\n if (calls.size >= 200)\n throw new Error(\"Start a new application chat.\");\n calls.set(toolCallId, { signature, result });\n }\n input.reply({\n type: \"omni-chat:tool-response\",\n requestId: message.requestId,\n toolCallId,\n result: boundedJson((await result) ?? null, 12000),\n });\n }\n } catch (error) {\n input.reply({\n type:\n message.type === \"omni-chat:application-request\"\n ? \"omni-chat:application-response\"\n : \"omni-chat:tool-response\",\n requestId: message.requestId,\n toolCallId: message.toolCallId,\n error:\n error instanceof Error\n ? error.message\n : \"The application action failed.\",\n });\n }\n };\n}\n","const iconPaths = {\n chat: \"M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5Z\",\n close: \"m6 6 12 12M6 18 18 6\",\n collapse: \"m6 9 6 6 6-6\",\n};\n\nexport function widgetIcon(document: Document, name: keyof typeof iconPaths) {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 24 24\");\n svg.setAttribute(\"fill\", \"none\");\n svg.setAttribute(\"stroke\", \"currentColor\");\n svg.setAttribute(\"stroke-width\", \"1.8\");\n svg.setAttribute(\"stroke-linecap\", \"round\");\n svg.setAttribute(\"stroke-linejoin\", \"round\");\n svg.setAttribute(\"aria-hidden\", \"true\");\n const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n path.setAttribute(\"d\", iconPaths[name]);\n svg.append(path);\n return svg;\n}\n\n/** Shadow DOM keeps a store's button, font and section CSS out of the widget. */\nexport const widgetStyles = `\n :host { all: initial; font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif; color-scheme: light; }\n *, *::before, *::after { box-sizing: border-box; }\n button { font: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; }\n button:focus-visible { outline: 3px solid var(--omni-launcher-bg); outline-offset: 4px; }\n svg { display: block; width: 22px; height: 22px; flex: none; }\n .launcher {\n display: flex; align-items: center; justify-content: center; gap: 10px;\n height: 52px; padding: 0 20px; border: 1px solid rgba(255,255,255,.14);\n border-radius: 999px; background: var(--omni-launcher-bg); color: var(--omni-launcher-fg);\n font-size: 14px; font-weight: 600; line-height: 1; letter-spacing: -.01em;\n box-shadow: 0 6px 24px rgba(0,0,0,.16), 0 2px 6px rgba(0,0,0,.08);\n transition: transform 160ms ease, box-shadow 160ms ease;\n margin-left: auto;\n }\n .launcher:hover { transform: translateY(-2px); box-shadow: 0 10px 28px rgba(0,0,0,.2); }\n .launcher[hidden] { display: none; }\n .launcher[aria-expanded=\"true\"] { width: 52px; padding: 0; }\n .launcher[aria-expanded=\"true\"] .label { display: none; }\n .panel {\n position: absolute; bottom: 66px; right: 0; width: min(392px, calc(100vw - 40px));\n overflow: hidden; border: 1px solid rgba(0,0,0,.08); border-radius: 20px;\n background: var(--omni-panel-bg); box-shadow: 0 24px 80px rgba(0,0,0,.18), 0 4px 16px rgba(0,0,0,.06);\n animation: omni-chat-enter 180ms ease-out;\n }\n .panel[hidden] { display: none; }\n .frame { height: min(780px, calc(100dvh - 112px)); min-height: 240px; }\n .close {\n position: absolute; z-index: 1; top: 18px; right: 14px;\n display: flex; align-items: center; justify-content: center; width: 34px; height: 34px;\n border: 1px solid color-mix(in srgb, var(--omni-panel-fg) 10%, transparent); border-radius: 50%;\n background: var(--omni-panel-bg); color: var(--omni-panel-fg); transition: background 160ms ease;\n }\n .close svg { width: 17px; height: 17px; }\n .close:hover { background: color-mix(in srgb, var(--omni-panel-fg) 6%, var(--omni-panel-bg)); }\n :host([data-position=\"left\"]) .panel { right: auto; left: 0; }\n :host([data-position=\"left\"]) .launcher { margin-left: 0; }\n :host([data-presentation=\"sidebar\"]) .panel {\n position: fixed; top: 0; bottom: 0; right: 0; left: auto;\n width: min(440px, 100vw); border-radius: 0; border-top: 0; border-bottom: 0;\n animation: omni-sidebar-enter 180ms ease-out;\n }\n :host([data-presentation=\"sidebar\"]) .frame { height: 100dvh; min-height: 0; }\n :host([data-presentation=\"sidebar\"][data-position=\"left\"]) .panel {\n right: auto; left: 0; animation-name: omni-sidebar-enter-left;\n }\n @keyframes omni-sidebar-enter { from { opacity: 0; transform: translateX(100%); } to { opacity: 1; transform: none; } }\n @keyframes omni-sidebar-enter-left { from { opacity: 0; transform: translateX(-100%); } to { opacity: 1; transform: none; } }\n @keyframes omni-chat-enter { from { opacity: 0; transform: translateY(8px) scale(.98); } to { opacity: 1; transform: none; } }\n @media (max-width: 480px) { :host([data-presentation=\"floating\"]) .panel { width: calc(100vw - 40px); border-radius: 18px; } }\n @media (prefers-reduced-motion: reduce) { .panel, :host([data-presentation=\"sidebar\"]) .panel { animation: none; } .launcher { transition: none; } }\n`;\n","import type { OmniChatWidgetOptions } from \"./widget\";\n\n/** Only public appearance is loaded here; agent settings remain on the server. */\nexport async function loadWidgetConfiguration(\n host: Window,\n origin: string,\n deploymentId: string,\n signal: AbortSignal,\n): Promise<OmniChatWidgetOptions> {\n const response = await host.fetch(`${origin}/api/embed/${deploymentId}`, {\n credentials: \"include\",\n cache: \"no-store\",\n signal,\n });\n const result = await response.json();\n if (!response.ok)\n throw new Error(result.error ?? \"Could not load the chat design.\");\n const design = result.design;\n const color = /^#[0-9a-f]{6}$/i;\n if (\n !design ||\n typeof design.title !== \"string\" ||\n !design.title.trim() ||\n design.title.length > 80 ||\n typeof design.launcherLabel !== \"string\" ||\n !design.launcherLabel.trim() ||\n design.launcherLabel.length > 60 ||\n ![\"left\", \"right\"].includes(design.position) ||\n ![\"floating\", \"sidebar\"].includes(design.presentation) ||\n !design.theme ||\n ![\n design.theme.primary,\n design.theme.primaryForeground,\n design.theme.background,\n design.theme.foreground,\n ].every((value) => typeof value === \"string\" && color.test(value))\n )\n throw new Error(\"Invalid chat design response.\");\n return {\n deploymentId,\n title: design.title,\n launcherLabel: design.launcherLabel,\n position: design.position,\n presentation: design.presentation,\n launcherBackground: design.theme.primary,\n launcherForeground: design.theme.primaryForeground,\n panelBackground: design.theme.background,\n panelForeground: design.theme.foreground,\n };\n}\n","import {\n createOmniChatEmbed,\n getOmniChatEmbedUrl,\n type OmniChatEmbedOptions,\n type OmniChatEmbed,\n} from \"./embed\";\nimport { widgetIcon, widgetStyles } from \"./widget-chrome\";\nimport { loadWidgetConfiguration } from \"./widget-config\";\n\nexport type OmniChatWidgetOptions = OmniChatEmbedOptions & {\n /** Floating window by default; sidebar fills the viewport height. */\n presentation?: \"floating\" | \"sidebar\";\n launcherLabel?: string;\n position?: \"left\" | \"right\";\n launcherBackground?: string;\n launcherForeground?: string;\n panelBackground?: string;\n panelForeground?: string;\n};\nlet widgetSequence = 0;\n/** Loads saved appearance by deployment ID. Explicit options override saved appearance. */\nexport function createOmniChatWidget(\n container: HTMLElement,\n options: OmniChatWidgetOptions,\n) {\n const origin = new URL(getOmniChatEmbedUrl(options)).origin;\n const document = container.ownerDocument;\n const host = document.defaultView;\n if (!host) throw new Error(\"A browser document is required to mount chat.\");\n const controller = new AbortController();\n const root = document.createElement(\"div\");\n root.setAttribute(\"data-omni-chat-widget\", \"\");\n const shadow = root.attachShadow({ mode: \"open\" });\n const style = document.createElement(\"style\");\n style.textContent = widgetStyles;\n const launcher = document.createElement(\"button\");\n const panel = document.createElement(\"section\");\n const close = document.createElement(\"button\");\n const frame = document.createElement(\"div\");\n let embed: OmniChatEmbed | undefined;\n let destroyed = false;\n let loaded = false;\n let openRequested = false;\n let appearance = options;\n Object.assign(root.style, {\n position: \"fixed\",\n bottom: \"20px\",\n zIndex: \"2147483000\",\n });\n launcher.type = close.type = \"button\";\n launcher.className = \"launcher\";\n const label = document.createElement(\"span\");\n label.className = \"label\";\n label.textContent = options.launcherLabel ?? \"Chat with us\";\n launcher.append(widgetIcon(document, \"chat\"), label);\n launcher.setAttribute(\"aria-expanded\", \"false\");\n launcher.setAttribute(\"aria-label\", label.textContent);\n panel.hidden = true;\n panel.className = \"panel\";\n panel.setAttribute(\"role\", \"region\");\n panel.setAttribute(\"aria-label\", options.title ?? \"Assistant chat\");\n panel.id = `omni-chat-widget-${++widgetSequence}`;\n launcher.setAttribute(\"aria-controls\", panel.id);\n frame.className = \"frame\";\n close.className = \"close\";\n close.setAttribute(\"aria-label\", \"Close chat\");\n close.title = \"Close chat\";\n close.append(widgetIcon(document, \"close\"));\n const closeChat = () => {\n if (destroyed) return;\n openRequested = false;\n panel.hidden = true;\n launcher.hidden = false;\n launcher.setAttribute(\"aria-expanded\", \"false\");\n launcher.setAttribute(\"aria-label\", label.textContent!);\n launcher.querySelector(\"svg\")?.replaceWith(widgetIcon(document, \"chat\"));\n launcher.focus();\n };\n const openChat = () => {\n if (destroyed) return;\n if (!loaded) {\n openRequested = true;\n return;\n }\n embed ??= createOmniChatEmbed(frame, {\n ...appearance,\n onRequestClose: closeChat,\n });\n embed.iframe.style.minHeight = \"0\";\n panel.hidden = false;\n launcher.hidden = appearance.presentation === \"sidebar\";\n launcher.setAttribute(\"aria-expanded\", \"true\");\n launcher.setAttribute(\"aria-label\", \"Close chat\");\n launcher\n .querySelector(\"svg\")\n ?.replaceWith(widgetIcon(document, \"collapse\"));\n embed.focus();\n };\n launcher.addEventListener(\"click\", () =>\n panel.hidden ? openChat() : closeChat(),\n );\n close.addEventListener(\"click\", closeChat);\n shadow.addEventListener(\"keydown\", (event) => {\n if ((event as KeyboardEvent).key === \"Escape\" && !panel.hidden) closeChat();\n });\n panel.append(close, frame);\n shadow.append(style, panel, launcher);\n const ready = loadWidgetConfiguration(\n host,\n origin,\n options.deploymentId,\n controller.signal,\n ).then((configuration) => {\n if (destroyed) return;\n appearance = Object.assign(\n configuration,\n Object.fromEntries(\n Object.entries(options).filter(([, value]) => value !== undefined),\n ),\n );\n root.dataset.position = appearance.position ?? \"right\";\n root.dataset.presentation = appearance.presentation ?? \"floating\";\n root.style.removeProperty(\"left\");\n root.style.removeProperty(\"right\");\n root.style.setProperty(appearance.position ?? \"right\", \"20px\");\n root.style.setProperty(\n \"--omni-launcher-bg\",\n appearance.launcherBackground!,\n );\n root.style.setProperty(\n \"--omni-launcher-fg\",\n appearance.launcherForeground!,\n );\n root.style.setProperty(\"--omni-panel-bg\", appearance.panelBackground!);\n root.style.setProperty(\"--omni-panel-fg\", appearance.panelForeground!);\n label.textContent = appearance.launcherLabel!;\n launcher.setAttribute(\"aria-label\", label.textContent);\n panel.setAttribute(\"aria-label\", appearance.title!);\n loaded = true;\n container.append(root);\n if (openRequested) openChat();\n });\n void ready.catch((error: unknown) => {\n if (!destroyed)\n options.onError?.(\n error instanceof Error ? error : new Error(\"Could not load chat.\"),\n );\n });\n return {\n /** Resolves once saved appearance is loaded and the launcher is mounted. */\n ready,\n open: openChat,\n close: closeChat,\n destroy() {\n destroyed = true;\n controller.abort();\n embed?.destroy();\n root.remove();\n },\n };\n}\n","import { getOmniChatEmbedUrl, type OmniChatEmbedOptions } from \"./embed\";\nimport type { OmniChatWidgetOptions } from \"./widget\";\n\ntype EmbedCodeOptions = Pick<\n OmniChatEmbedOptions,\n \"baseUrl\" | \"deploymentId\" | \"title\"\n> &\n Pick<\n OmniChatWidgetOptions,\n | \"presentation\"\n | \"launcherLabel\"\n | \"position\"\n | \"launcherBackground\"\n | \"launcherForeground\"\n | \"panelBackground\"\n | \"panelForeground\"\n >;\nconst scriptJson = (value: unknown) =>\n JSON.stringify(value, null, 2).replace(\n /[<>&\\u2028\\u2029]/g,\n (character) =>\n `\\\\u${character.charCodeAt(0).toString(16).padStart(4, \"0\")}`,\n );\n\n/** Copyable integrations contain only public deployment configuration. */\nexport function getOmniChatEmbedCode(\n options: EmbedCodeOptions,\n mode: \"widget\" | \"inline\" = \"widget\",\n) {\n const baseUrl = new URL(getOmniChatEmbedUrl(options)).origin;\n const config = { ...options, baseUrl };\n const id = `omni-chat-${options.deploymentId}`;\n const mount =\n mode === \"widget\"\n ? `OmniCommerceChat.createOmniChatWidget(document.body, ${scriptJson(config)});`\n : `OmniCommerceChat.createOmniChatEmbed(document.getElementById(${scriptJson(id)}), ${scriptJson(config)});`;\n return `${mode === \"inline\" ? `<div id=\"${id}\" style=\"height:600px\"></div>\\n` : \"\"}<script src=\"${baseUrl}/sdk/embed.global.js\"></script>\\n<script>\\n ${mount.replace(/\\n/g, \"\\n \")}\\n</script>`;\n}\nexport function getOmniChatReactCode(options: EmbedCodeOptions) {\n const baseUrl = new URL(getOmniChatEmbedUrl(options)).origin;\n return `import { OmniProvider, OmniChat } from \"@omni-commerce/sdk/react\";\\n\\n<OmniProvider deploymentId={${scriptJson(options.deploymentId)}}\\n baseUrl={${scriptJson(baseUrl)}}${options.title ? `\\n title={${scriptJson(options.title)}}` : \"\"}>\\n <OmniChat style={{ height: 600 }} />\\n</OmniProvider>`;\n}\n"],"mappings":"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","names":["embed_exports","__export","createOmniChatEmbed","createOmniChatWidget","getOmniChatEmbedCode","getOmniChatEmbedUrl","getOmniChatReactCode","boundedJson","value","maximum","encoded","createApplicationMessageHandler","input","calls","message","application","name","definition","toolCallId","args","signature","prior","result","error","iconPaths","widgetIcon","document","name","svg","path","widgetStyles","loadWidgetConfiguration","host","origin","deploymentId","signal","response","result","design","color","value","widgetSequence","createOmniChatWidget","container","options","origin","getOmniChatEmbedUrl","document","host","controller","root","shadow","style","widgetStyles","launcher","panel","close","frame","embed","destroyed","loaded","openRequested","appearance","label","widgetIcon","closeChat","openChat","createOmniChatEmbed","event","ready","loadWidgetConfiguration","configuration","value","error","scriptJson","value","character","getOmniChatEmbedCode","options","mode","baseUrl","getOmniChatEmbedUrl","config","id","mount","getOmniChatReactCode","getOmniChatEmbedUrl","options","parentOrigin","base","url","createOmniChatEmbed","container","document","host","iframe","chatOrigin","destroyed","pending","previousToken","controller","mint","response","result","applicationMessage","createApplicationMessageHandler","message","receive","event","session","error","failure"]}
package/dist/embed.js CHANGED
@@ -154,15 +154,48 @@ var widgetStyles = `
154
154
  @media (prefers-reduced-motion: reduce) { .panel, :host([data-presentation="sidebar"]) .panel { animation: none; } .launcher { transition: none; } }
155
155
  `;
156
156
 
157
+ // src/widget-config.ts
158
+ async function loadWidgetConfiguration(host, origin, deploymentId, signal) {
159
+ const response = await host.fetch(`${origin}/api/embed/${deploymentId}`, {
160
+ credentials: "include",
161
+ cache: "no-store",
162
+ signal
163
+ });
164
+ const result = await response.json();
165
+ if (!response.ok)
166
+ throw new Error(result.error ?? "Could not load the chat design.");
167
+ const design = result.design;
168
+ const color = /^#[0-9a-f]{6}$/i;
169
+ if (!design || typeof design.title !== "string" || !design.title.trim() || design.title.length > 80 || typeof design.launcherLabel !== "string" || !design.launcherLabel.trim() || design.launcherLabel.length > 60 || !["left", "right"].includes(design.position) || !["floating", "sidebar"].includes(design.presentation) || !design.theme || ![
170
+ design.theme.primary,
171
+ design.theme.primaryForeground,
172
+ design.theme.background,
173
+ design.theme.foreground
174
+ ].every((value) => typeof value === "string" && color.test(value)))
175
+ throw new Error("Invalid chat design response.");
176
+ return {
177
+ deploymentId,
178
+ title: design.title,
179
+ launcherLabel: design.launcherLabel,
180
+ position: design.position,
181
+ presentation: design.presentation,
182
+ launcherBackground: design.theme.primary,
183
+ launcherForeground: design.theme.primaryForeground,
184
+ panelBackground: design.theme.background,
185
+ panelForeground: design.theme.foreground
186
+ };
187
+ }
188
+
157
189
  // src/widget.ts
158
190
  var widgetSequence = 0;
159
191
  function createOmniChatWidget(container, options) {
160
- getOmniChatEmbedUrl(options);
192
+ const origin = new URL(getOmniChatEmbedUrl(options)).origin;
161
193
  const document = container.ownerDocument;
194
+ const host = document.defaultView;
195
+ if (!host) throw new Error("A browser document is required to mount chat.");
196
+ const controller = new AbortController();
162
197
  const root = document.createElement("div");
163
198
  root.setAttribute("data-omni-chat-widget", "");
164
- root.setAttribute("data-position", options.position ?? "right");
165
- root.setAttribute("data-presentation", options.presentation ?? "floating");
166
199
  const shadow = root.attachShadow({ mode: "open" });
167
200
  const style = document.createElement("style");
168
201
  style.textContent = widgetStyles;
@@ -172,28 +205,14 @@ function createOmniChatWidget(container, options) {
172
205
  const frame = document.createElement("div");
173
206
  let embed;
174
207
  let destroyed = false;
208
+ let loaded = false;
209
+ let openRequested = false;
210
+ let appearance = options;
175
211
  Object.assign(root.style, {
176
212
  position: "fixed",
177
213
  bottom: "20px",
178
- [options.position ?? "right"]: "20px",
179
214
  zIndex: "2147483000"
180
215
  });
181
- root.style.setProperty(
182
- "--omni-launcher-bg",
183
- options.launcherBackground ?? "#2563eb"
184
- );
185
- root.style.setProperty(
186
- "--omni-launcher-fg",
187
- options.launcherForeground ?? "#ffffff"
188
- );
189
- root.style.setProperty(
190
- "--omni-panel-bg",
191
- options.panelBackground ?? "#ffffff"
192
- );
193
- root.style.setProperty(
194
- "--omni-panel-fg",
195
- options.panelForeground ?? "#171717"
196
- );
197
216
  launcher.type = close.type = "button";
198
217
  launcher.className = "launcher";
199
218
  const label = document.createElement("span");
@@ -215,6 +234,7 @@ function createOmniChatWidget(container, options) {
215
234
  close.append(widgetIcon(document, "close"));
216
235
  const closeChat = () => {
217
236
  if (destroyed) return;
237
+ openRequested = false;
218
238
  panel.hidden = true;
219
239
  launcher.hidden = false;
220
240
  launcher.setAttribute("aria-expanded", "false");
@@ -224,13 +244,17 @@ function createOmniChatWidget(container, options) {
224
244
  };
225
245
  const openChat = () => {
226
246
  if (destroyed) return;
247
+ if (!loaded) {
248
+ openRequested = true;
249
+ return;
250
+ }
227
251
  embed ?? (embed = createOmniChatEmbed(frame, {
228
- ...options,
252
+ ...appearance,
229
253
  onRequestClose: closeChat
230
254
  }));
231
255
  embed.iframe.style.minHeight = "0";
232
256
  panel.hidden = false;
233
- launcher.hidden = options.presentation === "sidebar";
257
+ launcher.hidden = appearance.presentation === "sidebar";
234
258
  launcher.setAttribute("aria-expanded", "true");
235
259
  launcher.setAttribute("aria-label", "Close chat");
236
260
  launcher.querySelector("svg")?.replaceWith(widgetIcon(document, "collapse"));
@@ -246,12 +270,55 @@ function createOmniChatWidget(container, options) {
246
270
  });
247
271
  panel.append(close, frame);
248
272
  shadow.append(style, panel, launcher);
249
- container.append(root);
273
+ const ready = loadWidgetConfiguration(
274
+ host,
275
+ origin,
276
+ options.deploymentId,
277
+ controller.signal
278
+ ).then((configuration) => {
279
+ if (destroyed) return;
280
+ appearance = Object.assign(
281
+ configuration,
282
+ Object.fromEntries(
283
+ Object.entries(options).filter(([, value]) => value !== void 0)
284
+ )
285
+ );
286
+ root.dataset.position = appearance.position ?? "right";
287
+ root.dataset.presentation = appearance.presentation ?? "floating";
288
+ root.style.removeProperty("left");
289
+ root.style.removeProperty("right");
290
+ root.style.setProperty(appearance.position ?? "right", "20px");
291
+ root.style.setProperty(
292
+ "--omni-launcher-bg",
293
+ appearance.launcherBackground
294
+ );
295
+ root.style.setProperty(
296
+ "--omni-launcher-fg",
297
+ appearance.launcherForeground
298
+ );
299
+ root.style.setProperty("--omni-panel-bg", appearance.panelBackground);
300
+ root.style.setProperty("--omni-panel-fg", appearance.panelForeground);
301
+ label.textContent = appearance.launcherLabel;
302
+ launcher.setAttribute("aria-label", label.textContent);
303
+ panel.setAttribute("aria-label", appearance.title);
304
+ loaded = true;
305
+ container.append(root);
306
+ if (openRequested) openChat();
307
+ });
308
+ void ready.catch((error) => {
309
+ if (!destroyed)
310
+ options.onError?.(
311
+ error instanceof Error ? error : new Error("Could not load chat.")
312
+ );
313
+ });
250
314
  return {
315
+ /** Resolves once saved appearance is loaded and the launcher is mounted. */
316
+ ready,
251
317
  open: openChat,
252
318
  close: closeChat,
253
319
  destroy() {
254
320
  destroyed = true;
321
+ controller.abort();
255
322
  embed?.destroy();
256
323
  root.remove();
257
324
  }
package/dist/embed.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/application.ts","../src/widget-chrome.ts","../src/widget.ts","../src/embed-code.ts","../src/embed.ts"],"names":[],"mappings":"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","file":"embed.js","sourcesContent":["/** Host-defined actions execute inside the application, never on the assistant server. */\nexport interface OmniFrontendTool {\n description: string;\n parameters: Record<string, unknown>;\n execute: (\n args: Record<string, unknown>,\n context: { toolCallId: string; abortSignal: AbortSignal },\n ) => unknown | Promise<unknown>;\n}\nexport interface OmniChatApplication {\n name: string;\n description: string;\n /** Return a small, explicitly selected snapshot. Do not include secrets. */\n getContext: () => unknown | Promise<unknown>;\n}\nexport interface OmniApplicationOptions {\n application?: OmniChatApplication;\n /** Names must start with app_; use array arguments for actions with multiple targets. */\n frontendTools?: Record<string, OmniFrontendTool>;\n}\n\nfunction boundedJson(value: unknown, maximum: number): unknown {\n const encoded = JSON.stringify(value);\n if (\n typeof encoded !== \"string\" ||\n new TextEncoder().encode(encoded).length > maximum ||\n /data:[^\"\\s]{0,100};base64,/i.test(encoded)\n )\n throw new Error(\n \"Application data must be bounded JSON without base64 payloads.\",\n );\n return JSON.parse(encoded);\n}\n\nexport function createApplicationMessageHandler(input: {\n options: OmniApplicationOptions;\n signal: AbortSignal;\n reply: (message: Record<string, unknown>) => void;\n}) {\n // A repeated parked call reuses its result instead of applying an action twice.\n const calls = new Map<\n string,\n { signature: string; result: Promise<unknown> }\n >();\n return async (message: Record<string, unknown>) => {\n if (typeof message.requestId !== \"string\" || message.requestId.length > 200)\n return;\n try {\n if (message.type === \"omni-chat:application-request\") {\n const application = input.options.application;\n input.reply({\n type: \"omni-chat:application-response\",\n requestId: message.requestId,\n application: application\n ? boundedJson(\n {\n name: application.name,\n description: application.description,\n context: (await application.getContext()) ?? null,\n tools: Object.entries(input.options.frontendTools ?? {}).map(\n ([name, definition]) => ({\n name,\n description: definition.description,\n parameters: definition.parameters,\n }),\n ),\n },\n 65536,\n )\n : undefined,\n });\n } else if (message.type === \"omni-chat:tool-request\") {\n const name = message.toolName;\n const toolCallId = message.toolCallId;\n if (\n typeof name !== \"string\" ||\n !/^app_[a-z][a-z0-9_]{0,59}$/.test(name) ||\n typeof toolCallId !== \"string\" ||\n !toolCallId ||\n toolCallId.length > 200\n )\n throw new Error(\"Invalid application tool request.\");\n const definition = Object.hasOwn(\n input.options.frontendTools ?? {},\n name,\n )\n ? input.options.frontendTools?.[name]\n : undefined;\n if (!input.options.application || !definition)\n throw new Error(\"This application action is unavailable.\");\n const args = message.args;\n if (!args || typeof args !== \"object\" || Array.isArray(args))\n throw new Error(\"Invalid application action arguments.\");\n const signature = JSON.stringify({ name, args });\n const prior = calls.get(toolCallId);\n if (prior && prior.signature !== signature)\n throw new Error(\"This tool call ID was already used.\");\n const result =\n prior?.result ??\n Promise.resolve().then(() =>\n definition.execute(args as Record<string, unknown>, {\n toolCallId,\n abortSignal: input.signal,\n }),\n );\n if (!prior) {\n if (calls.size >= 200)\n throw new Error(\"Start a new application chat.\");\n calls.set(toolCallId, { signature, result });\n }\n input.reply({\n type: \"omni-chat:tool-response\",\n requestId: message.requestId,\n toolCallId,\n result: boundedJson((await result) ?? null, 12000),\n });\n }\n } catch (error) {\n input.reply({\n type:\n message.type === \"omni-chat:application-request\"\n ? \"omni-chat:application-response\"\n : \"omni-chat:tool-response\",\n requestId: message.requestId,\n toolCallId: message.toolCallId,\n error:\n error instanceof Error\n ? error.message\n : \"The application action failed.\",\n });\n }\n };\n}\n","const iconPaths = {\n chat: \"M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5Z\",\n close: \"m6 6 12 12M6 18 18 6\",\n collapse: \"m6 9 6 6 6-6\",\n};\n\nexport function widgetIcon(document: Document, name: keyof typeof iconPaths) {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 24 24\");\n svg.setAttribute(\"fill\", \"none\");\n svg.setAttribute(\"stroke\", \"currentColor\");\n svg.setAttribute(\"stroke-width\", \"1.8\");\n svg.setAttribute(\"stroke-linecap\", \"round\");\n svg.setAttribute(\"stroke-linejoin\", \"round\");\n svg.setAttribute(\"aria-hidden\", \"true\");\n const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n path.setAttribute(\"d\", iconPaths[name]);\n svg.append(path);\n return svg;\n}\n\n/** Shadow DOM keeps a store's button, font and section CSS out of the widget. */\nexport const widgetStyles = `\n :host { all: initial; font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif; color-scheme: light; }\n *, *::before, *::after { box-sizing: border-box; }\n button { font: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; }\n button:focus-visible { outline: 3px solid var(--omni-launcher-bg); outline-offset: 4px; }\n svg { display: block; width: 22px; height: 22px; flex: none; }\n .launcher {\n display: flex; align-items: center; justify-content: center; gap: 10px;\n height: 52px; padding: 0 20px; border: 1px solid rgba(255,255,255,.14);\n border-radius: 999px; background: var(--omni-launcher-bg); color: var(--omni-launcher-fg);\n font-size: 14px; font-weight: 600; line-height: 1; letter-spacing: -.01em;\n box-shadow: 0 6px 24px rgba(0,0,0,.16), 0 2px 6px rgba(0,0,0,.08);\n transition: transform 160ms ease, box-shadow 160ms ease;\n margin-left: auto;\n }\n .launcher:hover { transform: translateY(-2px); box-shadow: 0 10px 28px rgba(0,0,0,.2); }\n .launcher[hidden] { display: none; }\n .launcher[aria-expanded=\"true\"] { width: 52px; padding: 0; }\n .launcher[aria-expanded=\"true\"] .label { display: none; }\n .panel {\n position: absolute; bottom: 66px; right: 0; width: min(392px, calc(100vw - 40px));\n overflow: hidden; border: 1px solid rgba(0,0,0,.08); border-radius: 20px;\n background: var(--omni-panel-bg); box-shadow: 0 24px 80px rgba(0,0,0,.18), 0 4px 16px rgba(0,0,0,.06);\n animation: omni-chat-enter 180ms ease-out;\n }\n .panel[hidden] { display: none; }\n .frame { height: min(780px, calc(100dvh - 112px)); min-height: 240px; }\n .close {\n position: absolute; z-index: 1; top: 18px; right: 14px;\n display: flex; align-items: center; justify-content: center; width: 34px; height: 34px;\n border: 1px solid color-mix(in srgb, var(--omni-panel-fg) 10%, transparent); border-radius: 50%;\n background: var(--omni-panel-bg); color: var(--omni-panel-fg); transition: background 160ms ease;\n }\n .close svg { width: 17px; height: 17px; }\n .close:hover { background: color-mix(in srgb, var(--omni-panel-fg) 6%, var(--omni-panel-bg)); }\n :host([data-position=\"left\"]) .panel { right: auto; left: 0; }\n :host([data-position=\"left\"]) .launcher { margin-left: 0; }\n :host([data-presentation=\"sidebar\"]) .panel {\n position: fixed; top: 0; bottom: 0; right: 0; left: auto;\n width: min(440px, 100vw); border-radius: 0; border-top: 0; border-bottom: 0;\n animation: omni-sidebar-enter 180ms ease-out;\n }\n :host([data-presentation=\"sidebar\"]) .frame { height: 100dvh; min-height: 0; }\n :host([data-presentation=\"sidebar\"][data-position=\"left\"]) .panel {\n right: auto; left: 0; animation-name: omni-sidebar-enter-left;\n }\n @keyframes omni-sidebar-enter { from { opacity: 0; transform: translateX(100%); } to { opacity: 1; transform: none; } }\n @keyframes omni-sidebar-enter-left { from { opacity: 0; transform: translateX(-100%); } to { opacity: 1; transform: none; } }\n @keyframes omni-chat-enter { from { opacity: 0; transform: translateY(8px) scale(.98); } to { opacity: 1; transform: none; } }\n @media (max-width: 480px) { :host([data-presentation=\"floating\"]) .panel { width: calc(100vw - 40px); border-radius: 18px; } }\n @media (prefers-reduced-motion: reduce) { .panel, :host([data-presentation=\"sidebar\"]) .panel { animation: none; } .launcher { transition: none; } }\n`;\n","import {\n createOmniChatEmbed,\n getOmniChatEmbedUrl,\n type OmniChatEmbedOptions,\n type OmniChatEmbed,\n} from \"./embed\";\nimport { widgetIcon, widgetStyles } from \"./widget-chrome\";\n\nexport type OmniChatWidgetOptions = OmniChatEmbedOptions & {\n /** Floating window by default; sidebar fills the viewport height. */\n presentation?: \"floating\" | \"sidebar\";\n launcherLabel?: string;\n position?: \"left\" | \"right\";\n launcherBackground?: string;\n launcherForeground?: string;\n panelBackground?: string;\n panelForeground?: string;\n};\nlet widgetSequence = 0;\n/** A website launcher using the same hosted assistant as OmniChat. */\nexport function createOmniChatWidget(\n container: HTMLElement,\n options: OmniChatWidgetOptions,\n) {\n getOmniChatEmbedUrl(options);\n const document = container.ownerDocument;\n const root = document.createElement(\"div\");\n root.setAttribute(\"data-omni-chat-widget\", \"\");\n root.setAttribute(\"data-position\", options.position ?? \"right\");\n root.setAttribute(\"data-presentation\", options.presentation ?? \"floating\");\n const shadow = root.attachShadow({ mode: \"open\" });\n const style = document.createElement(\"style\");\n style.textContent = widgetStyles;\n const launcher = document.createElement(\"button\");\n const panel = document.createElement(\"section\");\n const close = document.createElement(\"button\");\n const frame = document.createElement(\"div\");\n let embed: OmniChatEmbed | undefined;\n let destroyed = false;\n Object.assign(root.style, {\n position: \"fixed\",\n bottom: \"20px\",\n [options.position ?? \"right\"]: \"20px\",\n zIndex: \"2147483000\",\n });\n root.style.setProperty(\n \"--omni-launcher-bg\",\n options.launcherBackground ?? \"#2563eb\",\n );\n root.style.setProperty(\n \"--omni-launcher-fg\",\n options.launcherForeground ?? \"#ffffff\",\n );\n root.style.setProperty(\n \"--omni-panel-bg\",\n options.panelBackground ?? \"#ffffff\",\n );\n root.style.setProperty(\n \"--omni-panel-fg\",\n options.panelForeground ?? \"#171717\",\n );\n launcher.type = close.type = \"button\";\n launcher.className = \"launcher\";\n const label = document.createElement(\"span\");\n label.className = \"label\";\n label.textContent = options.launcherLabel ?? \"Chat with us\";\n launcher.append(widgetIcon(document, \"chat\"), label);\n launcher.setAttribute(\"aria-expanded\", \"false\");\n launcher.setAttribute(\"aria-label\", label.textContent);\n panel.hidden = true;\n panel.className = \"panel\";\n panel.setAttribute(\"role\", \"region\");\n panel.setAttribute(\"aria-label\", options.title ?? \"Assistant chat\");\n panel.id = `omni-chat-widget-${++widgetSequence}`;\n launcher.setAttribute(\"aria-controls\", panel.id);\n frame.className = \"frame\";\n close.className = \"close\";\n close.setAttribute(\"aria-label\", \"Close chat\");\n close.title = \"Close chat\";\n close.append(widgetIcon(document, \"close\"));\n const closeChat = () => {\n if (destroyed) return;\n panel.hidden = true;\n launcher.hidden = false;\n launcher.setAttribute(\"aria-expanded\", \"false\");\n launcher.setAttribute(\"aria-label\", label.textContent!);\n launcher.querySelector(\"svg\")?.replaceWith(widgetIcon(document, \"chat\"));\n launcher.focus();\n };\n const openChat = () => {\n if (destroyed) return;\n embed ??= createOmniChatEmbed(frame, {\n ...options,\n onRequestClose: closeChat,\n });\n embed.iframe.style.minHeight = \"0\";\n panel.hidden = false;\n launcher.hidden = options.presentation === \"sidebar\";\n launcher.setAttribute(\"aria-expanded\", \"true\");\n launcher.setAttribute(\"aria-label\", \"Close chat\");\n launcher\n .querySelector(\"svg\")\n ?.replaceWith(widgetIcon(document, \"collapse\"));\n embed.focus();\n };\n launcher.addEventListener(\"click\", () =>\n panel.hidden ? openChat() : closeChat(),\n );\n close.addEventListener(\"click\", closeChat);\n shadow.addEventListener(\"keydown\", (event) => {\n if ((event as KeyboardEvent).key === \"Escape\" && !panel.hidden) closeChat();\n });\n panel.append(close, frame);\n shadow.append(style, panel, launcher);\n container.append(root);\n return {\n open: openChat,\n close: closeChat,\n destroy() {\n destroyed = true;\n embed?.destroy();\n root.remove();\n },\n };\n}\n","import { getOmniChatEmbedUrl, type OmniChatEmbedOptions } from \"./embed\";\nimport type { OmniChatWidgetOptions } from \"./widget\";\n\ntype EmbedCodeOptions = Pick<\n OmniChatEmbedOptions,\n \"baseUrl\" | \"deploymentId\" | \"title\"\n> &\n Pick<\n OmniChatWidgetOptions,\n | \"presentation\"\n | \"launcherLabel\"\n | \"position\"\n | \"launcherBackground\"\n | \"launcherForeground\"\n | \"panelBackground\"\n | \"panelForeground\"\n >;\nconst scriptJson = (value: unknown) =>\n JSON.stringify(value, null, 2).replace(\n /[<>&\\u2028\\u2029]/g,\n (character) =>\n `\\\\u${character.charCodeAt(0).toString(16).padStart(4, \"0\")}`,\n );\n\n/** Copyable integrations contain only public deployment configuration. */\nexport function getOmniChatEmbedCode(\n options: EmbedCodeOptions,\n mode: \"widget\" | \"inline\" = \"widget\",\n) {\n const baseUrl = new URL(getOmniChatEmbedUrl(options)).origin;\n const config = { ...options, baseUrl };\n const id = `omni-chat-${options.deploymentId}`;\n const mount =\n mode === \"widget\"\n ? `OmniCommerceChat.createOmniChatWidget(document.body, ${scriptJson(config)});`\n : `OmniCommerceChat.createOmniChatEmbed(document.getElementById(${scriptJson(id)}), ${scriptJson(config)});`;\n return `${mode === \"inline\" ? `<div id=\"${id}\" style=\"height:600px\"></div>\\n` : \"\"}<script src=\"${baseUrl}/sdk/embed.global.js\"></script>\\n<script>\\n ${mount.replace(/\\n/g, \"\\n \")}\\n</script>`;\n}\nexport function getOmniChatReactCode(options: EmbedCodeOptions) {\n const baseUrl = new URL(getOmniChatEmbedUrl(options)).origin;\n return `import { OmniProvider, OmniChat } from \"@omni-commerce/sdk/react\";\\n\\n<OmniProvider deploymentId={${scriptJson(options.deploymentId)}}\\n baseUrl={${scriptJson(baseUrl)}}${options.title ? `\\n title={${scriptJson(options.title)}}` : \"\"}>\\n <OmniChat style={{ height: 600 }} />\\n</OmniProvider>`;\n}\n","import {\n createApplicationMessageHandler,\n type OmniApplicationOptions,\n} from \"./application\";\nexport type {\n OmniFrontendTool,\n OmniChatApplication,\n OmniApplicationOptions,\n} from \"./application\";\n/** A hosted chat session. Keep its short-lived token in memory, never in iframe URLs. */\nexport { createOmniChatWidget, type OmniChatWidgetOptions } from \"./widget\";\nexport { getOmniChatEmbedCode, getOmniChatReactCode } from \"./embed-code\";\nexport interface OmniChatSession {\n token: string;\n threadId: string;\n expiresIn: number;\n}\nexport interface OmniChatEmbedOptions extends OmniApplicationOptions {\n deploymentId: string;\n baseUrl?: string;\n /** Optional authenticated session mint on the host application's server. */\n getSession?: () => Promise<OmniChatSession>;\n title?: string;\n onError?: (error: Error) => void;\n /** Floating widgets use this to close on Escape from the hosted chat. */\n onRequestClose?: () => void;\n}\nexport interface OmniChatEmbed {\n iframe: HTMLIFrameElement;\n /** Focus the hosted composer, including when reopening a retained chat. */\n focus(): void;\n destroy(): void;\n}\n\nexport function getOmniChatEmbedUrl(\n options: Pick<OmniChatEmbedOptions, \"baseUrl\" | \"deploymentId\">,\n parentOrigin?: string,\n): string {\n if (\n !/^[\\da-f]{8}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{12}$/i.test(\n options.deploymentId,\n )\n )\n throw new Error(\"A valid chat deployment ID is required.\");\n const base = new URL(options.baseUrl ?? \"https://omnicommerce.sg\");\n if (\n (base.protocol !== \"https:\" &&\n !(\n base.protocol === \"http:\" &&\n [\"localhost\", \"127.0.0.1\"].includes(base.hostname)\n )) ||\n base.username ||\n base.password ||\n base.pathname !== \"/\" ||\n base.search ||\n base.hash\n )\n throw new Error(\"Chat baseUrl must be an HTTPS origin, or HTTP localhost.\");\n const url = new URL(`/embed/${options.deploymentId}`, base.origin);\n if (parentOrigin)\n url.searchParams.set(\"parentOrigin\", new URL(parentOrigin).origin);\n return url.toString();\n}\n\n/** Browser-only mounting; importing this entry point is safe during SSR. */\nexport function createOmniChatEmbed(\n container: HTMLElement,\n options: OmniChatEmbedOptions,\n): OmniChatEmbed {\n const document = container.ownerDocument;\n const host = document.defaultView;\n if (!host) throw new Error(\"A browser document is required to mount chat.\");\n const iframe = document.createElement(\"iframe\");\n iframe.src = getOmniChatEmbedUrl(options, host.location.origin);\n iframe.title = options.title ?? \"OmniCommerce assistant\";\n iframe.referrerPolicy = \"strict-origin-when-cross-origin\";\n iframe.setAttribute(\n \"sandbox\",\n \"allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox\",\n );\n Object.assign(iframe.style, {\n width: \"100%\",\n height: \"100%\",\n minHeight: \"320px\",\n border: \"0\",\n display: \"block\",\n });\n const chatOrigin = new URL(iframe.src).origin;\n let destroyed = false;\n let pending: Promise<OmniChatSession> | undefined;\n let previousToken: string | undefined;\n const controller = new AbortController();\n\n const mint = async (): Promise<OmniChatSession> => {\n if (options.getSession) return options.getSession();\n const response = await host.fetch(\n `${chatOrigin}/api/embed/${options.deploymentId}/session`,\n {\n method: \"POST\",\n credentials: \"include\",\n signal: controller.signal,\n headers: {\n \"Content-Type\": \"application/json\",\n ...(previousToken\n ? { Authorization: `Bearer ${previousToken}` }\n : {}),\n },\n body: \"{}\",\n },\n );\n const result = (await response.json()) as OmniChatSession & {\n error?: string;\n };\n if (!response.ok) {\n // A rejected renewal must not keep Retry bound to an obsolete session.\n // The next mint still performs the deployment's full access checks.\n if (response.status === 401 || response.status === 403)\n previousToken = undefined;\n throw new Error(result.error ?? \"Could not open the chat session.\");\n }\n return result;\n };\n const applicationMessage = createApplicationMessageHandler({\n options,\n signal: controller.signal,\n reply: (message) => {\n if (!destroyed)\n iframe.contentWindow?.postMessage(\n { ...message, deploymentId: options.deploymentId },\n chatOrigin,\n );\n },\n });\n const receive = (event: MessageEvent) => {\n if (\n destroyed ||\n event.source !== iframe.contentWindow ||\n event.origin !== chatOrigin ||\n event.data?.deploymentId !== options.deploymentId\n )\n return;\n if (\n event.data.type === \"omni-chat:application-request\" ||\n event.data.type === \"omni-chat:tool-request\"\n ) {\n void applicationMessage(event.data);\n return;\n }\n if (event.data.type === \"omni-chat:close-request\") {\n options.onRequestClose?.();\n return;\n }\n if (event.data.type !== \"omni-chat:session-request\") return;\n pending ??= mint();\n void pending\n .then((session) => {\n if (destroyed) return;\n if (\n typeof session?.token !== \"string\" ||\n !session.token ||\n session.token.length > 4096 ||\n typeof session.threadId !== \"string\" ||\n !session.threadId ||\n !Number.isFinite(session.expiresIn) ||\n session.expiresIn <= 0\n )\n throw new Error(\"Invalid chat session response.\");\n previousToken = session.token;\n iframe.contentWindow?.postMessage(\n {\n type: \"omni-chat:session\",\n deploymentId: options.deploymentId,\n session,\n ...(options.application ? { applicationEnabled: true } : {}),\n },\n chatOrigin,\n );\n })\n .catch((error: unknown) => {\n if (destroyed) return;\n const failure =\n error instanceof Error ? error : new Error(\"Could not open chat.\");\n options.onError?.(failure);\n iframe.contentWindow?.postMessage(\n {\n type: \"omni-chat:session-error\",\n deploymentId: options.deploymentId,\n error: failure.message,\n ...(options.application ? {applicationEnabled: true} : {}),\n },\n chatOrigin,\n );\n })\n .finally(() => {\n pending = undefined;\n });\n };\n host.addEventListener(\"message\", receive);\n container.append(iframe);\n return {\n iframe,\n focus() {\n if (destroyed) return;\n iframe.focus();\n iframe.contentWindow?.postMessage(\n {\n type: \"omni-chat:focus-composer\",\n deploymentId: options.deploymentId,\n },\n chatOrigin,\n );\n },\n destroy() {\n if (destroyed) return;\n destroyed = true;\n controller.abort();\n previousToken = undefined;\n host.removeEventListener(\"message\", receive);\n iframe.remove();\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/application.ts","../src/widget-chrome.ts","../src/widget-config.ts","../src/widget.ts","../src/embed-code.ts","../src/embed.ts"],"names":[],"mappings":"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","file":"embed.js","sourcesContent":["/** Host-defined actions execute inside the application, never on the assistant server. */\nexport interface OmniFrontendTool {\n description: string;\n parameters: Record<string, unknown>;\n execute: (\n args: Record<string, unknown>,\n context: { toolCallId: string; abortSignal: AbortSignal },\n ) => unknown | Promise<unknown>;\n}\nexport interface OmniChatApplication {\n name: string;\n description: string;\n /** Return a small, explicitly selected snapshot. Do not include secrets. */\n getContext: () => unknown | Promise<unknown>;\n}\nexport interface OmniApplicationOptions {\n application?: OmniChatApplication;\n /** Names must start with app_; use array arguments for actions with multiple targets. */\n frontendTools?: Record<string, OmniFrontendTool>;\n}\n\nfunction boundedJson(value: unknown, maximum: number): unknown {\n const encoded = JSON.stringify(value);\n if (\n typeof encoded !== \"string\" ||\n new TextEncoder().encode(encoded).length > maximum ||\n /data:[^\"\\s]{0,100};base64,/i.test(encoded)\n )\n throw new Error(\n \"Application data must be bounded JSON without base64 payloads.\",\n );\n return JSON.parse(encoded);\n}\n\nexport function createApplicationMessageHandler(input: {\n options: OmniApplicationOptions;\n signal: AbortSignal;\n reply: (message: Record<string, unknown>) => void;\n}) {\n // A repeated parked call reuses its result instead of applying an action twice.\n const calls = new Map<\n string,\n { signature: string; result: Promise<unknown> }\n >();\n return async (message: Record<string, unknown>) => {\n if (typeof message.requestId !== \"string\" || message.requestId.length > 200)\n return;\n try {\n if (message.type === \"omni-chat:application-request\") {\n const application = input.options.application;\n input.reply({\n type: \"omni-chat:application-response\",\n requestId: message.requestId,\n application: application\n ? boundedJson(\n {\n name: application.name,\n description: application.description,\n context: (await application.getContext()) ?? null,\n tools: Object.entries(input.options.frontendTools ?? {}).map(\n ([name, definition]) => ({\n name,\n description: definition.description,\n parameters: definition.parameters,\n }),\n ),\n },\n 65536,\n )\n : undefined,\n });\n } else if (message.type === \"omni-chat:tool-request\") {\n const name = message.toolName;\n const toolCallId = message.toolCallId;\n if (\n typeof name !== \"string\" ||\n !/^app_[a-z][a-z0-9_]{0,59}$/.test(name) ||\n typeof toolCallId !== \"string\" ||\n !toolCallId ||\n toolCallId.length > 200\n )\n throw new Error(\"Invalid application tool request.\");\n const definition = Object.hasOwn(\n input.options.frontendTools ?? {},\n name,\n )\n ? input.options.frontendTools?.[name]\n : undefined;\n if (!input.options.application || !definition)\n throw new Error(\"This application action is unavailable.\");\n const args = message.args;\n if (!args || typeof args !== \"object\" || Array.isArray(args))\n throw new Error(\"Invalid application action arguments.\");\n const signature = JSON.stringify({ name, args });\n const prior = calls.get(toolCallId);\n if (prior && prior.signature !== signature)\n throw new Error(\"This tool call ID was already used.\");\n const result =\n prior?.result ??\n Promise.resolve().then(() =>\n definition.execute(args as Record<string, unknown>, {\n toolCallId,\n abortSignal: input.signal,\n }),\n );\n if (!prior) {\n if (calls.size >= 200)\n throw new Error(\"Start a new application chat.\");\n calls.set(toolCallId, { signature, result });\n }\n input.reply({\n type: \"omni-chat:tool-response\",\n requestId: message.requestId,\n toolCallId,\n result: boundedJson((await result) ?? null, 12000),\n });\n }\n } catch (error) {\n input.reply({\n type:\n message.type === \"omni-chat:application-request\"\n ? \"omni-chat:application-response\"\n : \"omni-chat:tool-response\",\n requestId: message.requestId,\n toolCallId: message.toolCallId,\n error:\n error instanceof Error\n ? error.message\n : \"The application action failed.\",\n });\n }\n };\n}\n","const iconPaths = {\n chat: \"M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5Z\",\n close: \"m6 6 12 12M6 18 18 6\",\n collapse: \"m6 9 6 6 6-6\",\n};\n\nexport function widgetIcon(document: Document, name: keyof typeof iconPaths) {\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 24 24\");\n svg.setAttribute(\"fill\", \"none\");\n svg.setAttribute(\"stroke\", \"currentColor\");\n svg.setAttribute(\"stroke-width\", \"1.8\");\n svg.setAttribute(\"stroke-linecap\", \"round\");\n svg.setAttribute(\"stroke-linejoin\", \"round\");\n svg.setAttribute(\"aria-hidden\", \"true\");\n const path = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n path.setAttribute(\"d\", iconPaths[name]);\n svg.append(path);\n return svg;\n}\n\n/** Shadow DOM keeps a store's button, font and section CSS out of the widget. */\nexport const widgetStyles = `\n :host { all: initial; font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif; color-scheme: light; }\n *, *::before, *::after { box-sizing: border-box; }\n button { font: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; }\n button:focus-visible { outline: 3px solid var(--omni-launcher-bg); outline-offset: 4px; }\n svg { display: block; width: 22px; height: 22px; flex: none; }\n .launcher {\n display: flex; align-items: center; justify-content: center; gap: 10px;\n height: 52px; padding: 0 20px; border: 1px solid rgba(255,255,255,.14);\n border-radius: 999px; background: var(--omni-launcher-bg); color: var(--omni-launcher-fg);\n font-size: 14px; font-weight: 600; line-height: 1; letter-spacing: -.01em;\n box-shadow: 0 6px 24px rgba(0,0,0,.16), 0 2px 6px rgba(0,0,0,.08);\n transition: transform 160ms ease, box-shadow 160ms ease;\n margin-left: auto;\n }\n .launcher:hover { transform: translateY(-2px); box-shadow: 0 10px 28px rgba(0,0,0,.2); }\n .launcher[hidden] { display: none; }\n .launcher[aria-expanded=\"true\"] { width: 52px; padding: 0; }\n .launcher[aria-expanded=\"true\"] .label { display: none; }\n .panel {\n position: absolute; bottom: 66px; right: 0; width: min(392px, calc(100vw - 40px));\n overflow: hidden; border: 1px solid rgba(0,0,0,.08); border-radius: 20px;\n background: var(--omni-panel-bg); box-shadow: 0 24px 80px rgba(0,0,0,.18), 0 4px 16px rgba(0,0,0,.06);\n animation: omni-chat-enter 180ms ease-out;\n }\n .panel[hidden] { display: none; }\n .frame { height: min(780px, calc(100dvh - 112px)); min-height: 240px; }\n .close {\n position: absolute; z-index: 1; top: 18px; right: 14px;\n display: flex; align-items: center; justify-content: center; width: 34px; height: 34px;\n border: 1px solid color-mix(in srgb, var(--omni-panel-fg) 10%, transparent); border-radius: 50%;\n background: var(--omni-panel-bg); color: var(--omni-panel-fg); transition: background 160ms ease;\n }\n .close svg { width: 17px; height: 17px; }\n .close:hover { background: color-mix(in srgb, var(--omni-panel-fg) 6%, var(--omni-panel-bg)); }\n :host([data-position=\"left\"]) .panel { right: auto; left: 0; }\n :host([data-position=\"left\"]) .launcher { margin-left: 0; }\n :host([data-presentation=\"sidebar\"]) .panel {\n position: fixed; top: 0; bottom: 0; right: 0; left: auto;\n width: min(440px, 100vw); border-radius: 0; border-top: 0; border-bottom: 0;\n animation: omni-sidebar-enter 180ms ease-out;\n }\n :host([data-presentation=\"sidebar\"]) .frame { height: 100dvh; min-height: 0; }\n :host([data-presentation=\"sidebar\"][data-position=\"left\"]) .panel {\n right: auto; left: 0; animation-name: omni-sidebar-enter-left;\n }\n @keyframes omni-sidebar-enter { from { opacity: 0; transform: translateX(100%); } to { opacity: 1; transform: none; } }\n @keyframes omni-sidebar-enter-left { from { opacity: 0; transform: translateX(-100%); } to { opacity: 1; transform: none; } }\n @keyframes omni-chat-enter { from { opacity: 0; transform: translateY(8px) scale(.98); } to { opacity: 1; transform: none; } }\n @media (max-width: 480px) { :host([data-presentation=\"floating\"]) .panel { width: calc(100vw - 40px); border-radius: 18px; } }\n @media (prefers-reduced-motion: reduce) { .panel, :host([data-presentation=\"sidebar\"]) .panel { animation: none; } .launcher { transition: none; } }\n`;\n","import type { OmniChatWidgetOptions } from \"./widget\";\n\n/** Only public appearance is loaded here; agent settings remain on the server. */\nexport async function loadWidgetConfiguration(\n host: Window,\n origin: string,\n deploymentId: string,\n signal: AbortSignal,\n): Promise<OmniChatWidgetOptions> {\n const response = await host.fetch(`${origin}/api/embed/${deploymentId}`, {\n credentials: \"include\",\n cache: \"no-store\",\n signal,\n });\n const result = await response.json();\n if (!response.ok)\n throw new Error(result.error ?? \"Could not load the chat design.\");\n const design = result.design;\n const color = /^#[0-9a-f]{6}$/i;\n if (\n !design ||\n typeof design.title !== \"string\" ||\n !design.title.trim() ||\n design.title.length > 80 ||\n typeof design.launcherLabel !== \"string\" ||\n !design.launcherLabel.trim() ||\n design.launcherLabel.length > 60 ||\n ![\"left\", \"right\"].includes(design.position) ||\n ![\"floating\", \"sidebar\"].includes(design.presentation) ||\n !design.theme ||\n ![\n design.theme.primary,\n design.theme.primaryForeground,\n design.theme.background,\n design.theme.foreground,\n ].every((value) => typeof value === \"string\" && color.test(value))\n )\n throw new Error(\"Invalid chat design response.\");\n return {\n deploymentId,\n title: design.title,\n launcherLabel: design.launcherLabel,\n position: design.position,\n presentation: design.presentation,\n launcherBackground: design.theme.primary,\n launcherForeground: design.theme.primaryForeground,\n panelBackground: design.theme.background,\n panelForeground: design.theme.foreground,\n };\n}\n","import {\n createOmniChatEmbed,\n getOmniChatEmbedUrl,\n type OmniChatEmbedOptions,\n type OmniChatEmbed,\n} from \"./embed\";\nimport { widgetIcon, widgetStyles } from \"./widget-chrome\";\nimport { loadWidgetConfiguration } from \"./widget-config\";\n\nexport type OmniChatWidgetOptions = OmniChatEmbedOptions & {\n /** Floating window by default; sidebar fills the viewport height. */\n presentation?: \"floating\" | \"sidebar\";\n launcherLabel?: string;\n position?: \"left\" | \"right\";\n launcherBackground?: string;\n launcherForeground?: string;\n panelBackground?: string;\n panelForeground?: string;\n};\nlet widgetSequence = 0;\n/** Loads saved appearance by deployment ID. Explicit options override saved appearance. */\nexport function createOmniChatWidget(\n container: HTMLElement,\n options: OmniChatWidgetOptions,\n) {\n const origin = new URL(getOmniChatEmbedUrl(options)).origin;\n const document = container.ownerDocument;\n const host = document.defaultView;\n if (!host) throw new Error(\"A browser document is required to mount chat.\");\n const controller = new AbortController();\n const root = document.createElement(\"div\");\n root.setAttribute(\"data-omni-chat-widget\", \"\");\n const shadow = root.attachShadow({ mode: \"open\" });\n const style = document.createElement(\"style\");\n style.textContent = widgetStyles;\n const launcher = document.createElement(\"button\");\n const panel = document.createElement(\"section\");\n const close = document.createElement(\"button\");\n const frame = document.createElement(\"div\");\n let embed: OmniChatEmbed | undefined;\n let destroyed = false;\n let loaded = false;\n let openRequested = false;\n let appearance = options;\n Object.assign(root.style, {\n position: \"fixed\",\n bottom: \"20px\",\n zIndex: \"2147483000\",\n });\n launcher.type = close.type = \"button\";\n launcher.className = \"launcher\";\n const label = document.createElement(\"span\");\n label.className = \"label\";\n label.textContent = options.launcherLabel ?? \"Chat with us\";\n launcher.append(widgetIcon(document, \"chat\"), label);\n launcher.setAttribute(\"aria-expanded\", \"false\");\n launcher.setAttribute(\"aria-label\", label.textContent);\n panel.hidden = true;\n panel.className = \"panel\";\n panel.setAttribute(\"role\", \"region\");\n panel.setAttribute(\"aria-label\", options.title ?? \"Assistant chat\");\n panel.id = `omni-chat-widget-${++widgetSequence}`;\n launcher.setAttribute(\"aria-controls\", panel.id);\n frame.className = \"frame\";\n close.className = \"close\";\n close.setAttribute(\"aria-label\", \"Close chat\");\n close.title = \"Close chat\";\n close.append(widgetIcon(document, \"close\"));\n const closeChat = () => {\n if (destroyed) return;\n openRequested = false;\n panel.hidden = true;\n launcher.hidden = false;\n launcher.setAttribute(\"aria-expanded\", \"false\");\n launcher.setAttribute(\"aria-label\", label.textContent!);\n launcher.querySelector(\"svg\")?.replaceWith(widgetIcon(document, \"chat\"));\n launcher.focus();\n };\n const openChat = () => {\n if (destroyed) return;\n if (!loaded) {\n openRequested = true;\n return;\n }\n embed ??= createOmniChatEmbed(frame, {\n ...appearance,\n onRequestClose: closeChat,\n });\n embed.iframe.style.minHeight = \"0\";\n panel.hidden = false;\n launcher.hidden = appearance.presentation === \"sidebar\";\n launcher.setAttribute(\"aria-expanded\", \"true\");\n launcher.setAttribute(\"aria-label\", \"Close chat\");\n launcher\n .querySelector(\"svg\")\n ?.replaceWith(widgetIcon(document, \"collapse\"));\n embed.focus();\n };\n launcher.addEventListener(\"click\", () =>\n panel.hidden ? openChat() : closeChat(),\n );\n close.addEventListener(\"click\", closeChat);\n shadow.addEventListener(\"keydown\", (event) => {\n if ((event as KeyboardEvent).key === \"Escape\" && !panel.hidden) closeChat();\n });\n panel.append(close, frame);\n shadow.append(style, panel, launcher);\n const ready = loadWidgetConfiguration(\n host,\n origin,\n options.deploymentId,\n controller.signal,\n ).then((configuration) => {\n if (destroyed) return;\n appearance = Object.assign(\n configuration,\n Object.fromEntries(\n Object.entries(options).filter(([, value]) => value !== undefined),\n ),\n );\n root.dataset.position = appearance.position ?? \"right\";\n root.dataset.presentation = appearance.presentation ?? \"floating\";\n root.style.removeProperty(\"left\");\n root.style.removeProperty(\"right\");\n root.style.setProperty(appearance.position ?? \"right\", \"20px\");\n root.style.setProperty(\n \"--omni-launcher-bg\",\n appearance.launcherBackground!,\n );\n root.style.setProperty(\n \"--omni-launcher-fg\",\n appearance.launcherForeground!,\n );\n root.style.setProperty(\"--omni-panel-bg\", appearance.panelBackground!);\n root.style.setProperty(\"--omni-panel-fg\", appearance.panelForeground!);\n label.textContent = appearance.launcherLabel!;\n launcher.setAttribute(\"aria-label\", label.textContent);\n panel.setAttribute(\"aria-label\", appearance.title!);\n loaded = true;\n container.append(root);\n if (openRequested) openChat();\n });\n void ready.catch((error: unknown) => {\n if (!destroyed)\n options.onError?.(\n error instanceof Error ? error : new Error(\"Could not load chat.\"),\n );\n });\n return {\n /** Resolves once saved appearance is loaded and the launcher is mounted. */\n ready,\n open: openChat,\n close: closeChat,\n destroy() {\n destroyed = true;\n controller.abort();\n embed?.destroy();\n root.remove();\n },\n };\n}\n","import { getOmniChatEmbedUrl, type OmniChatEmbedOptions } from \"./embed\";\nimport type { OmniChatWidgetOptions } from \"./widget\";\n\ntype EmbedCodeOptions = Pick<\n OmniChatEmbedOptions,\n \"baseUrl\" | \"deploymentId\" | \"title\"\n> &\n Pick<\n OmniChatWidgetOptions,\n | \"presentation\"\n | \"launcherLabel\"\n | \"position\"\n | \"launcherBackground\"\n | \"launcherForeground\"\n | \"panelBackground\"\n | \"panelForeground\"\n >;\nconst scriptJson = (value: unknown) =>\n JSON.stringify(value, null, 2).replace(\n /[<>&\\u2028\\u2029]/g,\n (character) =>\n `\\\\u${character.charCodeAt(0).toString(16).padStart(4, \"0\")}`,\n );\n\n/** Copyable integrations contain only public deployment configuration. */\nexport function getOmniChatEmbedCode(\n options: EmbedCodeOptions,\n mode: \"widget\" | \"inline\" = \"widget\",\n) {\n const baseUrl = new URL(getOmniChatEmbedUrl(options)).origin;\n const config = { ...options, baseUrl };\n const id = `omni-chat-${options.deploymentId}`;\n const mount =\n mode === \"widget\"\n ? `OmniCommerceChat.createOmniChatWidget(document.body, ${scriptJson(config)});`\n : `OmniCommerceChat.createOmniChatEmbed(document.getElementById(${scriptJson(id)}), ${scriptJson(config)});`;\n return `${mode === \"inline\" ? `<div id=\"${id}\" style=\"height:600px\"></div>\\n` : \"\"}<script src=\"${baseUrl}/sdk/embed.global.js\"></script>\\n<script>\\n ${mount.replace(/\\n/g, \"\\n \")}\\n</script>`;\n}\nexport function getOmniChatReactCode(options: EmbedCodeOptions) {\n const baseUrl = new URL(getOmniChatEmbedUrl(options)).origin;\n return `import { OmniProvider, OmniChat } from \"@omni-commerce/sdk/react\";\\n\\n<OmniProvider deploymentId={${scriptJson(options.deploymentId)}}\\n baseUrl={${scriptJson(baseUrl)}}${options.title ? `\\n title={${scriptJson(options.title)}}` : \"\"}>\\n <OmniChat style={{ height: 600 }} />\\n</OmniProvider>`;\n}\n","import {\n createApplicationMessageHandler,\n type OmniApplicationOptions,\n} from \"./application\";\nexport type {\n OmniFrontendTool,\n OmniChatApplication,\n OmniApplicationOptions,\n} from \"./application\";\n/** A hosted chat session. Keep its short-lived token in memory, never in iframe URLs. */\nexport { createOmniChatWidget, type OmniChatWidgetOptions } from \"./widget\";\nexport { getOmniChatEmbedCode, getOmniChatReactCode } from \"./embed-code\";\nexport interface OmniChatSession {\n token: string;\n threadId: string;\n expiresIn: number;\n}\nexport interface OmniChatEmbedOptions extends OmniApplicationOptions {\n deploymentId: string;\n baseUrl?: string;\n /** Optional authenticated session mint on the host application's server. */\n getSession?: () => Promise<OmniChatSession>;\n title?: string;\n onError?: (error: Error) => void;\n /** Floating widgets use this to close on Escape from the hosted chat. */\n onRequestClose?: () => void;\n}\nexport interface OmniChatEmbed {\n iframe: HTMLIFrameElement;\n /** Focus the hosted composer, including when reopening a retained chat. */\n focus(): void;\n destroy(): void;\n}\n\nexport function getOmniChatEmbedUrl(\n options: Pick<OmniChatEmbedOptions, \"baseUrl\" | \"deploymentId\">,\n parentOrigin?: string,\n): string {\n if (\n !/^[\\da-f]{8}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{12}$/i.test(\n options.deploymentId,\n )\n )\n throw new Error(\"A valid chat deployment ID is required.\");\n const base = new URL(options.baseUrl ?? \"https://omnicommerce.sg\");\n if (\n (base.protocol !== \"https:\" &&\n !(\n base.protocol === \"http:\" &&\n [\"localhost\", \"127.0.0.1\"].includes(base.hostname)\n )) ||\n base.username ||\n base.password ||\n base.pathname !== \"/\" ||\n base.search ||\n base.hash\n )\n throw new Error(\"Chat baseUrl must be an HTTPS origin, or HTTP localhost.\");\n const url = new URL(`/embed/${options.deploymentId}`, base.origin);\n if (parentOrigin)\n url.searchParams.set(\"parentOrigin\", new URL(parentOrigin).origin);\n return url.toString();\n}\n\n/** Browser-only mounting; importing this entry point is safe during SSR. */\nexport function createOmniChatEmbed(\n container: HTMLElement,\n options: OmniChatEmbedOptions,\n): OmniChatEmbed {\n const document = container.ownerDocument;\n const host = document.defaultView;\n if (!host) throw new Error(\"A browser document is required to mount chat.\");\n const iframe = document.createElement(\"iframe\");\n iframe.src = getOmniChatEmbedUrl(options, host.location.origin);\n iframe.title = options.title ?? \"OmniCommerce assistant\";\n iframe.referrerPolicy = \"strict-origin-when-cross-origin\";\n iframe.setAttribute(\n \"sandbox\",\n \"allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox\",\n );\n Object.assign(iframe.style, {\n width: \"100%\",\n height: \"100%\",\n minHeight: \"320px\",\n border: \"0\",\n display: \"block\",\n });\n const chatOrigin = new URL(iframe.src).origin;\n let destroyed = false;\n let pending: Promise<OmniChatSession> | undefined;\n let previousToken: string | undefined;\n const controller = new AbortController();\n\n const mint = async (): Promise<OmniChatSession> => {\n if (options.getSession) return options.getSession();\n const response = await host.fetch(\n `${chatOrigin}/api/embed/${options.deploymentId}/session`,\n {\n method: \"POST\",\n credentials: \"include\",\n signal: controller.signal,\n headers: {\n \"Content-Type\": \"application/json\",\n ...(previousToken\n ? { Authorization: `Bearer ${previousToken}` }\n : {}),\n },\n body: \"{}\",\n },\n );\n const result = (await response.json()) as OmniChatSession & {\n error?: string;\n };\n if (!response.ok) {\n // A rejected renewal must not keep Retry bound to an obsolete session.\n // The next mint still performs the deployment's full access checks.\n if (response.status === 401 || response.status === 403)\n previousToken = undefined;\n throw new Error(result.error ?? \"Could not open the chat session.\");\n }\n return result;\n };\n const applicationMessage = createApplicationMessageHandler({\n options,\n signal: controller.signal,\n reply: (message) => {\n if (!destroyed)\n iframe.contentWindow?.postMessage(\n { ...message, deploymentId: options.deploymentId },\n chatOrigin,\n );\n },\n });\n const receive = (event: MessageEvent) => {\n if (\n destroyed ||\n event.source !== iframe.contentWindow ||\n event.origin !== chatOrigin ||\n event.data?.deploymentId !== options.deploymentId\n )\n return;\n if (\n event.data.type === \"omni-chat:application-request\" ||\n event.data.type === \"omni-chat:tool-request\"\n ) {\n void applicationMessage(event.data);\n return;\n }\n if (event.data.type === \"omni-chat:close-request\") {\n options.onRequestClose?.();\n return;\n }\n if (event.data.type !== \"omni-chat:session-request\") return;\n pending ??= mint();\n void pending\n .then((session) => {\n if (destroyed) return;\n if (\n typeof session?.token !== \"string\" ||\n !session.token ||\n session.token.length > 4096 ||\n typeof session.threadId !== \"string\" ||\n !session.threadId ||\n !Number.isFinite(session.expiresIn) ||\n session.expiresIn <= 0\n )\n throw new Error(\"Invalid chat session response.\");\n previousToken = session.token;\n iframe.contentWindow?.postMessage(\n {\n type: \"omni-chat:session\",\n deploymentId: options.deploymentId,\n session,\n ...(options.application ? { applicationEnabled: true } : {}),\n },\n chatOrigin,\n );\n })\n .catch((error: unknown) => {\n if (destroyed) return;\n const failure =\n error instanceof Error ? error : new Error(\"Could not open chat.\");\n options.onError?.(failure);\n iframe.contentWindow?.postMessage(\n {\n type: \"omni-chat:session-error\",\n deploymentId: options.deploymentId,\n error: failure.message,\n ...(options.application ? { applicationEnabled: true } : {}),\n },\n chatOrigin,\n );\n })\n .finally(() => {\n pending = undefined;\n });\n };\n host.addEventListener(\"message\", receive);\n container.append(iframe);\n return {\n iframe,\n focus() {\n if (destroyed) return;\n iframe.focus();\n iframe.contentWindow?.postMessage(\n {\n type: \"omni-chat:focus-composer\",\n deploymentId: options.deploymentId,\n },\n chatOrigin,\n );\n },\n destroy() {\n if (destroyed) return;\n destroyed = true;\n controller.abort();\n previousToken = undefined;\n host.removeEventListener(\"message\", receive);\n iframe.remove();\n },\n };\n}\n"]}
package/dist/index.cjs CHANGED
@@ -35,7 +35,7 @@ function normalizeClientOptions(options = {}) {
35
35
  }
36
36
 
37
37
  // src/version.ts
38
- var SDK_VERSION = "0.8.0";
38
+ var SDK_VERSION = "0.8.1";
39
39
  var SDK_USER_AGENT = `omnicommerce-js/${SDK_VERSION}`;
40
40
 
41
41
  // src/environments.ts