diff --git a/web/app/dashboard/channels/_components/edit.tsx b/web/app/dashboard/channels/_components/edit.tsx index 91cae2f..399db77 100644 --- a/web/app/dashboard/channels/_components/edit.tsx +++ b/web/app/dashboard/channels/_components/edit.tsx @@ -740,7 +740,7 @@ function WebAccessGuide({ channelId }: { channelId: string }) { return "" } return ` diff --git a/web/components/support-chat/widget-demo.tsx b/web/components/support-chat/widget-demo.tsx index 7007d6c..5ce3096 100644 --- a/web/components/support-chat/widget-demo.tsx +++ b/web/components/support-chat/widget-demo.tsx @@ -4,12 +4,12 @@ import { SignJWT } from "jose" import { CheckIcon, CopyIcon } from "lucide-react" import { useEffect, useMemo, useState } from "react" -import type { CSAgentConfig } from "@/lib/sdk/config-types" +import type { AgentDeskConfig } from "@/lib/sdk/config-types" import { useI18n } from "@/i18n/provider" const STORAGE_KEY = "agent-desk-web-widget-test-config" const DEFAULT_JWT_TTL_MINUTES = "30" -const INITIAL_CONFIG: CSAgentConfig = { +const INITIAL_CONFIG: AgentDeskConfig = { channelId: "", baseUrl: "", apiBaseUrl: "", @@ -17,7 +17,7 @@ const INITIAL_CONFIG: CSAgentConfig = { type AuthMode = "guest" | "jwt" -type WidgetDemoConfig = CSAgentConfig & { +type WidgetDemoConfig = AgentDeskConfig & { authMode?: AuthMode jwtSecret?: string jwtUserId?: string @@ -53,32 +53,32 @@ function removeMountedWidget() { return } - window.CSAgentWidget?.destroy() + window.AgentDeskWidget?.destroy() document .querySelectorAll( '[data-agent-desk-widget="launcher"], [data-agent-desk-widget="frame"], [data-agent-desk-widget="script"]' ) .forEach((node) => node.remove()) - delete window.CSAgentConfig + delete window.AgentDeskConfig delete window.__CS_AI_AGENT_WIDGET_CONFIG__ delete window.__CS_AI_AGENT_WIDGET_STATE__ - delete window.CSAgentWidget + delete window.AgentDeskWidget } -function injectWidget(config: CSAgentConfig) { +function injectWidget(config: AgentDeskConfig) { removeMountedWidget() - window.CSAgentConfig = config + window.AgentDeskConfig = config const script = document.createElement("script") script.async = true script.src = `${window.location.origin}/sdk/agent-desk-sdk.min.js` - script.dataset.csAgentWidget = "script" + script.dataset.agentDeskWidget = "script" document.body.appendChild(script) } -function buildWidgetConfig(config: WidgetDemoConfig): CSAgentConfig { - const nextConfig: CSAgentConfig = { +function buildWidgetConfig(config: WidgetDemoConfig): AgentDeskConfig { + const nextConfig: AgentDeskConfig = { channelId: config.channelId.trim(), baseUrl: "", apiBaseUrl: "", @@ -200,7 +200,7 @@ export function SupportWidgetDemo() { } return ` @@ -225,11 +225,11 @@ ${configLines.join(",\n")} } async function handleCopyDirectUrl() { - if (!window.CSAgentWidget || typeof navigator === "undefined") { + if (!window.AgentDeskWidget || typeof navigator === "undefined") { return } try { - const url = await window.CSAgentWidget.getChatUrl() + const url = await window.AgentDeskWidget.getChatUrl() setLatestDirectChatUrl(url) if (config.authMode === "jwt") { setGeneratedToken(new URL(url).searchParams.get("userToken") || "") @@ -243,11 +243,11 @@ ${configLines.join(",\n")} } async function handleOpenDirectChat() { - if (!window.CSAgentWidget) { + if (!window.AgentDeskWidget) { return } try { - const url = await window.CSAgentWidget.getChatUrl() + const url = await window.AgentDeskWidget.getChatUrl() setLatestDirectChatUrl(url) if (config.authMode === "jwt") { setGeneratedToken(new URL(url).searchParams.get("userToken") || "") diff --git a/web/lib/sdk/agent-desk-sdk.test.mjs b/web/lib/sdk/agent-desk-sdk.test.mjs index 9b86368..ddc7854 100644 --- a/web/lib/sdk/agent-desk-sdk.test.mjs +++ b/web/lib/sdk/agent-desk-sdk.test.mjs @@ -68,7 +68,7 @@ async function loadSdk(config) { createElementNS: (_namespace, tagName) => createElement(tagName), }, window: { - CSAgentConfig: config, + AgentDeskConfig: config, location: { origin: "https://host.example", }, @@ -109,10 +109,10 @@ test("getChatUrl resolves a fresh userToken for each call", async () => { getUserToken: async () => `token_${++calls}`, }) - assert.equal(typeof sandbox.window.CSAgentWidget.getChatUrl, "function") + assert.equal(typeof sandbox.window.AgentDeskWidget.getChatUrl, "function") - const first = await sandbox.window.CSAgentWidget.getChatUrl() - const second = await sandbox.window.CSAgentWidget.getChatUrl() + const first = await sandbox.window.AgentDeskWidget.getChatUrl() + const second = await sandbox.window.AgentDeskWidget.getChatUrl() assert.equal(new URL(first).pathname, "/support/chat/") assert.equal(new URL(second).pathname, "/support/chat/") @@ -129,7 +129,7 @@ test("launcher click creates chat iframe with a freshly resolved userToken", asy }) await flushPromises() const launcher = sandbox.document.body.children.find( - (child) => child.dataset.csAgentWidget === "launcher" + (child) => child.dataset.agentDeskWidget === "launcher" ) assert.ok(launcher) @@ -138,7 +138,7 @@ test("launcher click creates chat iframe with a freshly resolved userToken", asy await flushPromises() const frame = sandbox.document.body.children.find( - (child) => child.dataset.csAgentWidget === "frame" + (child) => child.dataset.agentDeskWidget === "frame" ) assert.ok(frame) @@ -153,14 +153,14 @@ test("chat iframe layout uses dynamic viewport height for iOS browser chrome", a }) await flushPromises() const launcher = sandbox.document.body.children.find( - (child) => child.dataset.csAgentWidget === "launcher" + (child) => child.dataset.agentDeskWidget === "launcher" ) launcher.click() await flushPromises() const frame = sandbox.document.body.children.find( - (child) => child.dataset.csAgentWidget === "frame" + (child) => child.dataset.agentDeskWidget === "frame" ) assert.ok(frame) diff --git a/web/lib/sdk/agent-desk-sdk.ts b/web/lib/sdk/agent-desk-sdk.ts index 1280f4c..afc5b33 100644 --- a/web/lib/sdk/agent-desk-sdk.ts +++ b/web/lib/sdk/agent-desk-sdk.ts @@ -1,10 +1,10 @@ import type { - CSAgentConfig, - CSAgentWidget, + AgentDeskConfig, + AgentDeskWidget, SupportChatRuntimeConfig, } from "./config-types" -type NormalizedCSAgentConfig = CSAgentConfig & { +type NormalizedAgentDeskConfig = AgentDeskConfig & { baseUrl: string channelId: string position: "left" | "right" @@ -23,7 +23,7 @@ type WidgetState = { configLoading: boolean frameHideTimer: number | null frameDestroyTimer: number | null - config: NormalizedCSAgentConfig | null + config: NormalizedAgentDeskConfig | null frameConfig: SupportChatRuntimeConfig | null frameUrl: URL | null animationDuration: number @@ -33,7 +33,7 @@ type WidgetState = { type WidgetConfigResponse = { success?: boolean data?: Partial> } @@ -64,7 +64,7 @@ type FrameMessage = (function () { const DEFAULT_CONFIG: Pick< - NormalizedCSAgentConfig, + NormalizedAgentDeskConfig, "position" | "themeColor" | "width" > = { position: "right", @@ -94,7 +94,7 @@ type FrameMessage = window.__CS_AI_AGENT_WIDGET_STATE__ = state } - function normalizeConfig(config?: CSAgentConfig): NormalizedCSAgentConfig { + function normalizeConfig(config?: AgentDeskConfig): NormalizedAgentDeskConfig { const merged: Record = { ...DEFAULT_CONFIG, ...(config || {}) } merged.baseUrl = String(merged.baseUrl || window.location.origin).replace(/\/$/, "") if (merged.apiBaseUrl) { @@ -109,10 +109,10 @@ type FrameMessage = if (typeof merged.getUserToken !== "function") { delete merged.getUserToken } - return merged as NormalizedCSAgentConfig + return merged as NormalizedAgentDeskConfig } - function resolveWidgetBaseUrl(config: NormalizedCSAgentConfig) { + function resolveWidgetBaseUrl(config: NormalizedAgentDeskConfig) { const currentScript = document.currentScript as HTMLScriptElement | null if (currentScript?.src) { return currentScript.src.replace(/\/sdk\/agent-desk-sdk\.min\.js(?:\?.*)?$/, "") @@ -120,7 +120,7 @@ type FrameMessage = return String(config.widgetBaseUrl || config.baseUrl || window.location.origin).replace(/\/$/, "") } - function createFrameUrl(config: NormalizedCSAgentConfig, userToken: string) { + function createFrameUrl(config: NormalizedAgentDeskConfig, userToken: string) { const widgetBaseUrl = resolveWidgetBaseUrl(config) const frameUrl = new URL(`${widgetBaseUrl}/support/chat/`) frameUrl.searchParams.set("channelId", config.channelId) @@ -133,7 +133,7 @@ type FrameMessage = } function createFrameConfig( - config: NormalizedCSAgentConfig, + config: NormalizedAgentDeskConfig, userToken: string ): SupportChatRuntimeConfig { const { getUserToken: _getUserToken, ...payload } = config @@ -169,13 +169,13 @@ type FrameMessage = } function mergeWidgetConfig( - config: NormalizedCSAgentConfig, + config: NormalizedAgentDeskConfig, remoteConfig?: WidgetConfigResponse["data"] ) { if (!remoteConfig) { return config } - const merged: NormalizedCSAgentConfig = { ...config } + const merged: NormalizedAgentDeskConfig = { ...config } const remoteKeys = ["title", "subtitle", "themeColor", "position", "width"] as const remoteKeys.forEach((key) => { const value = remoteConfig[key] @@ -186,7 +186,7 @@ type FrameMessage = return merged } - function fetchWidgetConfig(config: NormalizedCSAgentConfig) { + function fetchWidgetConfig(config: NormalizedAgentDeskConfig) { const baseUrl = String(config.apiBaseUrl || config.baseUrl || "").replace(/\/$/, "") if (!baseUrl || !config.channelId || typeof fetch !== "function") { return Promise.resolve(config) @@ -368,7 +368,7 @@ type FrameMessage = } state.frame = document.createElement("iframe") - state.frame.dataset.csAgentWidget = "frame" + state.frame.dataset.agentDeskWidget = "frame" state.frame.title = state.config.title || getDefaultWidgetTitle() state.frame.src = state.frameUrl.toString() applyFrameLayout() @@ -434,7 +434,7 @@ type FrameMessage = ] const text = document.createElement("span") button.type = "button" - button.dataset.csAgentWidget = "launcher" + button.dataset.agentDeskWidget = "launcher" button.setAttribute("aria-label", config.title || getDefaultWidgetTitle()) icon.setAttribute("viewBox", "0 0 24 24") icon.setAttribute("fill", "none") @@ -491,8 +491,8 @@ type FrameMessage = return button } - function mount(config?: CSAgentConfig) { - const rawConfig = config || window.CSAgentConfig || { channelId: "" } + function mount(config?: AgentDeskConfig) { + const rawConfig = config || window.AgentDeskConfig || { channelId: "" } state.config = normalizeConfig(rawConfig) const widgetBaseUrl = resolveWidgetBaseUrl(state.config) if (!rawConfig.baseUrl) { @@ -552,7 +552,7 @@ type FrameMessage = }) } - window.CSAgentWidget = { + window.AgentDeskWidget = { mount, destroy, open: () => openWidget(), @@ -562,21 +562,21 @@ type FrameMessage = }, getChatUrl: () => { if (!state.config) { - mount(window.CSAgentConfig || { channelId: "" }) + mount(window.AgentDeskConfig || { channelId: "" }) } if (!state.config?.channelId) { return Promise.reject(new Error("channelId is required")) } return prepareFrameUrl().then((frameUrl) => frameUrl.toString()) }, - } satisfies CSAgentWidget + } satisfies AgentDeskWidget if (!state.listenerBound) { window.addEventListener("message", handleWindowMessage) state.listenerBound = true } - if (window.CSAgentConfig) { - mount(window.CSAgentConfig) + if (window.AgentDeskConfig) { + mount(window.AgentDeskConfig) } })() diff --git a/web/lib/sdk/config-types.ts b/web/lib/sdk/config-types.ts index 83e4c44..caf6a55 100644 --- a/web/lib/sdk/config-types.ts +++ b/web/lib/sdk/config-types.ts @@ -1,4 +1,4 @@ -export type CSAgentConfig = { +export type AgentDeskConfig = { channelId: string baseUrl?: string apiBaseUrl?: string @@ -16,13 +16,13 @@ export type CSAgentConfig = { width?: string } -export type SupportChatRuntimeConfig = Omit & { - /** Used only by /support/chat to exchange for a chat token; not part of CSAgentConfig. */ +export type SupportChatRuntimeConfig = Omit & { + /** Used only by /support/chat to exchange for a chat token; not part of AgentDeskConfig. */ userToken?: string } -export type CSAgentWidget = { - mount: (config?: CSAgentConfig) => void +export type AgentDeskWidget = { + mount: (config?: AgentDeskConfig) => void destroy: () => void open: () => Promise close: () => void @@ -31,8 +31,8 @@ export type CSAgentWidget = { declare global { interface Window { - CSAgentConfig?: CSAgentConfig - CSAgentWidget?: CSAgentWidget + AgentDeskConfig?: AgentDeskConfig + AgentDeskWidget?: AgentDeskWidget __CS_AI_AGENT_WIDGET_CONFIG__?: SupportChatRuntimeConfig __CS_AI_AGENT_WIDGET_STATE__?: unknown } diff --git a/web/lib/sdk/runtime-config.ts b/web/lib/sdk/runtime-config.ts index a89aa81..04035db 100644 --- a/web/lib/sdk/runtime-config.ts +++ b/web/lib/sdk/runtime-config.ts @@ -36,8 +36,8 @@ export function readSupportChatRuntimeConfig(): SupportChatRuntimeConfig { if (window.__CS_AI_AGENT_WIDGET_CONFIG__) { return window.__CS_AI_AGENT_WIDGET_CONFIG__ } - if (window.CSAgentConfig) { - const { getUserToken: _getUserToken, ...hostConfig } = window.CSAgentConfig + if (window.AgentDeskConfig) { + const { getUserToken: _getUserToken, ...hostConfig } = window.AgentDeskConfig return { ...fallback, ...hostConfig, diff --git a/web/public/sdk/agent-desk-sdk.min.js b/web/public/sdk/agent-desk-sdk.min.js index 9643c19..5ae2165 100644 --- a/web/public/sdk/agent-desk-sdk.min.js +++ b/web/public/sdk/agent-desk-sdk.min.js @@ -1 +1 @@ -var __rest=this&&this.__rest||function(e,t){var n={};for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&t.indexOf(i)<0&&(n[i]=e[i]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var r=0;for(i=Object.getOwnPropertySymbols(e);rString(e||"").trim())}catch(e){return Promise.reject(e)}}().then(e=>{if(!n.config)throw new Error("channelId is required");return n.frameUrl=function(e,t){const n=r(e),i=new URL(`${n}/support/chat/`);return i.searchParams.set("channelId",e.channelId),i.searchParams.set("baseUrl",e.baseUrl),e.apiBaseUrl&&i.searchParams.set("apiBaseUrl",e.apiBaseUrl),e.externalId&&i.searchParams.set("externalId",e.externalId),e.externalName&&i.searchParams.set("externalName",e.externalName),t&&i.searchParams.set("userToken",t),i}(n.config,e),n.frameConfig=a(n.config,e),n.frameUrl})}function s(){n.frameHideTimer&&(window.clearTimeout(n.frameHideTimer),n.frameHideTimer=null),n.frameDestroyTimer&&(window.clearTimeout(n.frameDestroyTimer),n.frameDestroyTimer=null)}function l(){const e=n.frame,t=n.config;if(e&&t){if(e.style.position="fixed",e.style.border="0",e.style.overflow="hidden",e.style.background="#fff",e.style.zIndex="2147483000",e.style.boxShadow="0 28px 80px rgba(15, 35, 65, 0.28)",e.style.willChange="top,right,bottom,left,width,height,opacity,transform,border-radius",e.style.transition="top 260ms cubic-bezier(0.22, 1, 0.36, 1), right 260ms cubic-bezier(0.22, 1, 0.36, 1), bottom 260ms cubic-bezier(0.22, 1, 0.36, 1), left 260ms cubic-bezier(0.22, 1, 0.36, 1), width 260ms cubic-bezier(0.22, 1, 0.36, 1), height 260ms cubic-bezier(0.22, 1, 0.36, 1), opacity 220ms ease, transform 260ms cubic-bezier(0.22, 1, 0.36, 1), border-radius 260ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 260ms ease",e.style.transformOrigin="left"===t.position?"left bottom":"right bottom",n.isMaximized)return e.style.top="max(12px, env(safe-area-inset-top))",e.style.right="max(12px, env(safe-area-inset-right))",e.style.bottom="max(12px, env(safe-area-inset-bottom))",e.style.left="max(12px, env(safe-area-inset-left))",e.style.width="calc(100vw - max(12px, env(safe-area-inset-left)) - max(12px, env(safe-area-inset-right)))",e.style.maxWidth="none",e.style.height="calc(100dvh - max(12px, env(safe-area-inset-top)) - max(12px, env(safe-area-inset-bottom)))",void(e.style.borderRadius="20px");e.style.top="",e.style.bottom="max(88px, calc(72px + env(safe-area-inset-bottom)))",e.style.right="left"===t.position?"":"max(12px, env(safe-area-inset-right))",e.style.left="left"===t.position?"max(12px, env(safe-area-inset-left))":"",e.style.width=t.width||"380px",e.style.maxWidth="calc(100vw - max(12px, env(safe-area-inset-left)) - max(12px, env(safe-area-inset-right)))",e.style.height="min(760px, calc(100dvh - max(104px, calc(88px + env(safe-area-inset-bottom))) - max(12px, env(safe-area-inset-top))))",e.style.borderRadius="24px"}}function d(e){var t;if((null===(t=n.frame)||void 0===t?void 0:t.contentWindow)&&n.frameUrl)try{n.frame.contentWindow.postMessage(e,n.frameUrl.origin)}catch(e){console.error("[agent-desk-widget] postMessage failed",e)}}function c(){n.frame&&n.frameLoaded&&n.frameReady&&n.config&&(n.initSent||(n.initSent=!0,d({type:"agent-desk:init",payload:n.frameConfig||a(n.config,"")})),d({type:n.isOpen?"agent-desk:open":"agent-desk:minimize"}),d({type:"agent-desk:maximized",payload:{isMaximized:n.isMaximized}}))}function f(){const e=n.frame;if(e){if(s(),l(),e.style.display="block",n.isOpen)return e.style.visibility="visible",e.style.pointerEvents="auto",n.frameHideTimer=window.setTimeout(()=>{n.frame&&(n.frame.style.opacity="1",n.frame.style.transform="translate3d(0, 0, 0) scale(1)")},16),void c();e.style.pointerEvents="none",e.style.opacity="0",e.style.transform=n.isMaximized?"translate3d(0, 10px, 0) scale(0.985)":"translate3d(0, 16px, 0) scale(0.96)",n.frameHideTimer=window.setTimeout(()=>{n.frame&&!n.isOpen&&(n.frame.style.visibility="hidden")},n.animationDuration),c()}}function m(e){const t=e||window.CSAgentConfig||{channelId:""};n.config=i(t);const a=r(n.config);t.baseUrl||(n.config.baseUrl=a),n.config.channelId?(n.configLoading=!0,function(e){const t=String(e.apiBaseUrl||e.baseUrl||"").replace(/\/$/,"");if(!t||!e.channelId||"function"!=typeof fetch)return Promise.resolve(e);const n=`${t}/api/channel/config?channelId=${encodeURIComponent(e.channelId)}`;return fetch(n,{method:"GET",cache:"no-store",headers:{"X-Channel-Id":e.channelId}}).then(e=>e.json()).then(t=>t&&!1!==t.success?function(e,t){if(!t)return e;const n=Object.assign({},e);return["title","subtitle","themeColor","position","width"].forEach(e=>{const i=t[e];null!=i&&(n[e]=i)}),n}(e,t.data||{}):e).catch(()=>e)}(n.config).then(e=>{var t;n.configLoading=!1,n.config=i(e),(null===(t=n.button)||void 0===t?void 0:t.parentNode)&&(n.button.parentNode.removeChild(n.button),n.button=null),function(){if(n.button)return n.button;const e=n.config;if(!e)return null;const t=document.createElement("button"),i=document.createElementNS("http://www.w3.org/2000/svg","svg"),r=document.createElement("span");t.type="button",t.dataset.csAgentWidget="launcher",t.setAttribute("aria-label",e.title||getDefaultWidgetTitle()),i.setAttribute("viewBox","0 0 24 24"),i.setAttribute("fill","none"),i.setAttribute("stroke","currentColor"),i.setAttribute("stroke-width","2"),i.setAttribute("stroke-linecap","round"),i.setAttribute("stroke-linejoin","round"),i.setAttribute("aria-hidden","true"),i.style.width="24px",i.style.height="24px",i.style.flex="0 0 auto",["M3 11a9 9 0 1 1 18 0","M3 11h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z","M21 11h-3a2 2 0 0 0-2 2v3a2 2 0 0 0 2 2h1a2 2 0 0 0 2-2z","M21 16v2a4 4 0 0 1-4 4h-5"].forEach(e=>{const t=document.createElementNS("http://www.w3.org/2000/svg","path");t.setAttribute("d",e),i.appendChild(t)}),r.textContent=getLauncherText(),r.style.display="block",t.style.position="fixed",t.style.bottom="24px",t.style.right="left"===e.position?"":"24px",t.style.left="left"===e.position?"24px":"",t.style.zIndex="2147483000",t.style.display="inline-flex",t.style.flexDirection="column",t.style.alignItems="center",t.style.justifyContent="center",t.style.gap="4px",t.style.width="64px",t.style.height="64px",t.style.border="0",t.style.borderRadius="999px",t.style.padding="0",t.style.background=e.themeColor||"#0f6cbd",t.style.color="#fff",t.style.font="600 13px/1 sans-serif",t.style.boxShadow="0 18px 40px rgba(15, 35, 65, 0.24)",t.style.cursor="pointer",t.appendChild(i),t.appendChild(r),t.addEventListener("click",()=>{if(n.isOpen)return n.isOpen=!1,void f();u()}),document.body.appendChild(t),n.button=t}()})):console.error("[agent-desk-widget] channelId is required")}function u(){return o().then(()=>{n.frame||(n.frame?n.frame:n.frameUrl&&n.config&&(n.frame=document.createElement("iframe"),n.frame.dataset.csAgentWidget="frame",n.frame.title=n.config.title||getDefaultWidgetTitle(),n.frame.src=n.frameUrl.toString(),l(),n.frame.style.display="block",n.frame.style.visibility="hidden",n.frame.style.pointerEvents="none",n.frame.style.opacity="0",n.frame.style.transform="translate3d(0, 18px, 0) scale(0.96)",n.frame.addEventListener("load",()=>{n.frameLoaded=!0,f()}),document.body.appendChild(n.frame),n.frame)),n.frame&&(n.isOpen=!0,f())}).catch(e=>{console.error("[agent-desk-widget] open failed",e)})}t||(window.__CS_AI_AGENT_WIDGET_STATE__=n),window.CSAgentWidget={mount:m,destroy:function(){var e,t;s(),(null===(e=n.frame)||void 0===e?void 0:e.parentNode)&&n.frame.parentNode.removeChild(n.frame),(null===(t=n.button)||void 0===t?void 0:t.parentNode)&&n.button.parentNode.removeChild(n.button),n.button=null,n.frame=null,n.frameLoaded=!1,n.frameReady=!1,n.initSent=!1,n.isOpen=!1,n.isMaximized=!1,n.configLoading=!1,n.frameConfig=null,n.frameUrl=null},open:()=>u(),close:()=>{n.isOpen=!1,f()},getChatUrl:()=>{var e;return n.config||m(window.CSAgentConfig||{channelId:""}),(null===(e=n.config)||void 0===e?void 0:e.channelId)?o().then(e=>e.toString()):Promise.reject(new Error("channelId is required"))}},n.listenerBound||(window.addEventListener("message",function(e){if(!n.frame||e.source!==n.frame.contentWindow)return;const t=e.data||{};return"agent-desk:ready"===t.type?(n.frameReady=!0,void c()):"agent-desk:request-minimize"===t.type?(n.isOpen=!1,void f()):void("agent-desk:request-close"!==t.type?"agent-desk:request-toggle-maximize"===t.type&&(n.isMaximized=!n.isMaximized,f()):n.frame&&(s(),n.frame.style.pointerEvents="none",n.frame.style.opacity="0",n.frame.style.transform="translate3d(0, 18px, 0) scale(0.94)",n.frame.style.visibility="hidden",n.frameDestroyTimer=window.setTimeout(()=>{n.frame&&(n.frame.parentNode&&n.frame.parentNode.removeChild(n.frame),n.frame=null,n.frameLoaded=!1,n.frameReady=!1,n.initSent=!1,n.isOpen=!1,n.isMaximized=!1,s())},n.animationDuration)))}),n.listenerBound=!0),window.CSAgentConfig&&m(window.CSAgentConfig)}(); +var __rest=this&&this.__rest||function(e,t){var n={};for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&t.indexOf(i)<0&&(n[i]=e[i]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var r=0;for(i=Object.getOwnPropertySymbols(e);rString(e||"").trim())}catch(e){return Promise.reject(e)}}().then(e=>{if(!n.config)throw new Error("channelId is required");return n.frameUrl=function(e,t){const n=r(e),i=new URL(`${n}/support/chat/`);return i.searchParams.set("channelId",e.channelId),i.searchParams.set("baseUrl",e.baseUrl),e.apiBaseUrl&&i.searchParams.set("apiBaseUrl",e.apiBaseUrl),e.externalId&&i.searchParams.set("externalId",e.externalId),e.externalName&&i.searchParams.set("externalName",e.externalName),t&&i.searchParams.set("userToken",t),i}(n.config,e),n.frameConfig=a(n.config,e),n.frameUrl})}function s(){n.frameHideTimer&&(window.clearTimeout(n.frameHideTimer),n.frameHideTimer=null),n.frameDestroyTimer&&(window.clearTimeout(n.frameDestroyTimer),n.frameDestroyTimer=null)}function l(){const e=n.frame,t=n.config;if(e&&t){if(e.style.position="fixed",e.style.border="0",e.style.overflow="hidden",e.style.background="#fff",e.style.zIndex="2147483000",e.style.boxShadow="0 28px 80px rgba(15, 35, 65, 0.28)",e.style.willChange="top,right,bottom,left,width,height,opacity,transform,border-radius",e.style.transition="top 260ms cubic-bezier(0.22, 1, 0.36, 1), right 260ms cubic-bezier(0.22, 1, 0.36, 1), bottom 260ms cubic-bezier(0.22, 1, 0.36, 1), left 260ms cubic-bezier(0.22, 1, 0.36, 1), width 260ms cubic-bezier(0.22, 1, 0.36, 1), height 260ms cubic-bezier(0.22, 1, 0.36, 1), opacity 220ms ease, transform 260ms cubic-bezier(0.22, 1, 0.36, 1), border-radius 260ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 260ms ease",e.style.transformOrigin="left"===t.position?"left bottom":"right bottom",n.isMaximized)return e.style.top="max(12px, env(safe-area-inset-top))",e.style.right="max(12px, env(safe-area-inset-right))",e.style.bottom="max(12px, env(safe-area-inset-bottom))",e.style.left="max(12px, env(safe-area-inset-left))",e.style.width="calc(100vw - max(12px, env(safe-area-inset-left)) - max(12px, env(safe-area-inset-right)))",e.style.maxWidth="none",e.style.height="calc(100dvh - max(12px, env(safe-area-inset-top)) - max(12px, env(safe-area-inset-bottom)))",void(e.style.borderRadius="20px");e.style.top="",e.style.bottom="max(88px, calc(72px + env(safe-area-inset-bottom)))",e.style.right="left"===t.position?"":"max(12px, env(safe-area-inset-right))",e.style.left="left"===t.position?"max(12px, env(safe-area-inset-left))":"",e.style.width=t.width||"380px",e.style.maxWidth="calc(100vw - max(12px, env(safe-area-inset-left)) - max(12px, env(safe-area-inset-right)))",e.style.height="min(760px, calc(100dvh - max(104px, calc(88px + env(safe-area-inset-bottom))) - max(12px, env(safe-area-inset-top))))",e.style.borderRadius="24px"}}function d(e){var t;if((null===(t=n.frame)||void 0===t?void 0:t.contentWindow)&&n.frameUrl)try{n.frame.contentWindow.postMessage(e,n.frameUrl.origin)}catch(e){console.error("[agent-desk-widget] postMessage failed",e)}}function c(){n.frame&&n.frameLoaded&&n.frameReady&&n.config&&(n.initSent||(n.initSent=!0,d({type:"agent-desk:init",payload:n.frameConfig||a(n.config,"")})),d({type:n.isOpen?"agent-desk:open":"agent-desk:minimize"}),d({type:"agent-desk:maximized",payload:{isMaximized:n.isMaximized}}))}function f(){const e=n.frame;if(e){if(s(),l(),e.style.display="block",n.isOpen)return e.style.visibility="visible",e.style.pointerEvents="auto",n.frameHideTimer=window.setTimeout(()=>{n.frame&&(n.frame.style.opacity="1",n.frame.style.transform="translate3d(0, 0, 0) scale(1)")},16),void c();e.style.pointerEvents="none",e.style.opacity="0",e.style.transform=n.isMaximized?"translate3d(0, 10px, 0) scale(0.985)":"translate3d(0, 16px, 0) scale(0.96)",n.frameHideTimer=window.setTimeout(()=>{n.frame&&!n.isOpen&&(n.frame.style.visibility="hidden")},n.animationDuration),c()}}function m(e){const t=e||window.AgentDeskConfig||{channelId:""};n.config=i(t);const a=r(n.config);t.baseUrl||(n.config.baseUrl=a),n.config.channelId?(n.configLoading=!0,function(e){const t=String(e.apiBaseUrl||e.baseUrl||"").replace(/\/$/,"");if(!t||!e.channelId||"function"!=typeof fetch)return Promise.resolve(e);const n=`${t}/api/channel/config?channelId=${encodeURIComponent(e.channelId)}`;return fetch(n,{method:"GET",cache:"no-store",headers:{"X-Channel-Id":e.channelId}}).then(e=>e.json()).then(t=>t&&!1!==t.success?function(e,t){if(!t)return e;const n=Object.assign({},e);return["title","subtitle","themeColor","position","width"].forEach(e=>{const i=t[e];null!=i&&(n[e]=i)}),n}(e,t.data||{}):e).catch(()=>e)}(n.config).then(e=>{var t;n.configLoading=!1,n.config=i(e),(null===(t=n.button)||void 0===t?void 0:t.parentNode)&&(n.button.parentNode.removeChild(n.button),n.button=null),function(){if(n.button)return n.button;const e=n.config;if(!e)return null;const t=document.createElement("button"),i=document.createElementNS("http://www.w3.org/2000/svg","svg"),r=document.createElement("span");t.type="button",t.dataset.agentDeskWidget="launcher",t.setAttribute("aria-label",e.title||getDefaultWidgetTitle()),i.setAttribute("viewBox","0 0 24 24"),i.setAttribute("fill","none"),i.setAttribute("stroke","currentColor"),i.setAttribute("stroke-width","2"),i.setAttribute("stroke-linecap","round"),i.setAttribute("stroke-linejoin","round"),i.setAttribute("aria-hidden","true"),i.style.width="24px",i.style.height="24px",i.style.flex="0 0 auto",["M3 11a9 9 0 1 1 18 0","M3 11h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z","M21 11h-3a2 2 0 0 0-2 2v3a2 2 0 0 0 2 2h1a2 2 0 0 0 2-2z","M21 16v2a4 4 0 0 1-4 4h-5"].forEach(e=>{const t=document.createElementNS("http://www.w3.org/2000/svg","path");t.setAttribute("d",e),i.appendChild(t)}),r.textContent=getLauncherText(),r.style.display="block",t.style.position="fixed",t.style.bottom="24px",t.style.right="left"===e.position?"":"24px",t.style.left="left"===e.position?"24px":"",t.style.zIndex="2147483000",t.style.display="inline-flex",t.style.flexDirection="column",t.style.alignItems="center",t.style.justifyContent="center",t.style.gap="4px",t.style.width="64px",t.style.height="64px",t.style.border="0",t.style.borderRadius="999px",t.style.padding="0",t.style.background=e.themeColor||"#0f6cbd",t.style.color="#fff",t.style.font="600 13px/1 sans-serif",t.style.boxShadow="0 18px 40px rgba(15, 35, 65, 0.24)",t.style.cursor="pointer",t.appendChild(i),t.appendChild(r),t.addEventListener("click",()=>{if(n.isOpen)return n.isOpen=!1,void f();u()}),document.body.appendChild(t),n.button=t}()})):console.error("[agent-desk-widget] channelId is required")}function u(){return o().then(()=>{n.frame||(n.frame?n.frame:n.frameUrl&&n.config&&(n.frame=document.createElement("iframe"),n.frame.dataset.agentDeskWidget="frame",n.frame.title=n.config.title||getDefaultWidgetTitle(),n.frame.src=n.frameUrl.toString(),l(),n.frame.style.display="block",n.frame.style.visibility="hidden",n.frame.style.pointerEvents="none",n.frame.style.opacity="0",n.frame.style.transform="translate3d(0, 18px, 0) scale(0.96)",n.frame.addEventListener("load",()=>{n.frameLoaded=!0,f()}),document.body.appendChild(n.frame),n.frame)),n.frame&&(n.isOpen=!0,f())}).catch(e=>{console.error("[agent-desk-widget] open failed",e)})}t||(window.__CS_AI_AGENT_WIDGET_STATE__=n),window.AgentDeskWidget={mount:m,destroy:function(){var e,t;s(),(null===(e=n.frame)||void 0===e?void 0:e.parentNode)&&n.frame.parentNode.removeChild(n.frame),(null===(t=n.button)||void 0===t?void 0:t.parentNode)&&n.button.parentNode.removeChild(n.button),n.button=null,n.frame=null,n.frameLoaded=!1,n.frameReady=!1,n.initSent=!1,n.isOpen=!1,n.isMaximized=!1,n.configLoading=!1,n.frameConfig=null,n.frameUrl=null},open:()=>u(),close:()=>{n.isOpen=!1,f()},getChatUrl:()=>{var e;return n.config||m(window.AgentDeskConfig||{channelId:""}),(null===(e=n.config)||void 0===e?void 0:e.channelId)?o().then(e=>e.toString()):Promise.reject(new Error("channelId is required"))}},n.listenerBound||(window.addEventListener("message",function(e){if(!n.frame||e.source!==n.frame.contentWindow)return;const t=e.data||{};return"agent-desk:ready"===t.type?(n.frameReady=!0,void c()):"agent-desk:request-minimize"===t.type?(n.isOpen=!1,void f()):void("agent-desk:request-close"!==t.type?"agent-desk:request-toggle-maximize"===t.type&&(n.isMaximized=!n.isMaximized,f()):n.frame&&(s(),n.frame.style.pointerEvents="none",n.frame.style.opacity="0",n.frame.style.transform="translate3d(0, 18px, 0) scale(0.94)",n.frame.style.visibility="hidden",n.frameDestroyTimer=window.setTimeout(()=>{n.frame&&(n.frame.parentNode&&n.frame.parentNode.removeChild(n.frame),n.frame=null,n.frameLoaded=!1,n.frameReady=!1,n.initSent=!1,n.isOpen=!1,n.isMaximized=!1,s())},n.animationDuration)))}),n.listenerBound=!0),window.AgentDeskConfig&&m(window.AgentDeskConfig)}();