@runtypelabs/persona 3.11.0 → 3.12.0

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,2 +1,2 @@
1
- "use strict";var SiteAgentInstaller=(()=>{var w=Object.defineProperty;var P=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var W=Object.prototype.hasOwnProperty;var T=(s,i,d,t)=>{if(i&&typeof i=="object"||typeof i=="function")for(let a of j(i))!W.call(s,a)&&a!==d&&w(s,a,{get:()=>i[a],enumerable:!(t=P(i,a))||t.enumerable});return s};var _=s=>T(w({},"__esModule",{value:!0}),s);var F={};(function(){"use strict";if(window.__siteAgentInstallerLoaded)return;window.__siteAgentInstallerLoaded=!0;let i=(()=>{let n=document.currentScript;if(!n)return{};let e={},o=n.getAttribute("data-config");if(o)try{let c=JSON.parse(o);if(c.config){let{__proto__:E,constructor:M,prototype:$,...v}=c;Object.assign(e,v)}else e.config=c}catch(c){console.error("Failed to parse data-config JSON:",c)}let r=n.getAttribute("data-runtype-token");r&&(e.clientToken=r);let l=n.getAttribute("data-flow-id");l&&(e.flowId=l);let f=n.getAttribute("data-api-url");f&&(e.apiUrl=f);let p=n.getAttribute("data-preview-param");return p&&(e.previewQueryParam=p),e})(),t={...window.siteAgentConfig||{},...i};if(!(()=>{if(!t.previewQueryParam)return!0;let e=new URLSearchParams(window.location.search).get(t.previewQueryParam);return e!==null&&e!==""&&e.toLowerCase()!=="false"&&e!=="0"})())return;let m=t.version||"latest",A=t.cdn||"jsdelivr",C=t.autoInit!==!1,h=()=>{if(t.cssUrl&&t.jsUrl)return{cssUrl:t.cssUrl,jsUrl:t.jsUrl};let e=`/npm/@runtypelabs/persona@${m}/dist`;return A==="unpkg"?{cssUrl:`https://unpkg.com${e}/widget.css`,jsUrl:`https://unpkg.com${e}/index.global.js`}:{cssUrl:`https://cdn.jsdelivr.net${e}/widget.css`,jsUrl:`https://cdn.jsdelivr.net${e}/index.global.js`}},{cssUrl:g,jsUrl:u}=h(),y=()=>!!document.head.querySelector("link[data-persona]")||!!document.head.querySelector('link[href*="widget.css"]'),k=()=>!!window.AgentWidget,S=n=>{let e=!1,o=()=>{e||(e=!0,n())},r=()=>{typeof requestIdleCallback!="undefined"?requestIdleCallback(()=>{requestAnimationFrame(()=>{requestAnimationFrame(o)})},{timeout:3e3}):setTimeout(o,300)};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",r):r()},U=()=>new Promise((n,e)=>{if(y()){n();return}let o=document.createElement("link");o.rel="stylesheet",o.href=g,o.setAttribute("data-persona","true"),o.onload=()=>n(),o.onerror=()=>e(new Error(`Failed to load CSS from ${g}`)),document.head.appendChild(o)}),b=()=>new Promise((n,e)=>{if(k()){n();return}let o=document.createElement("script");o.src=u,o.async=!0,o.onload=()=>n(),o.onerror=()=>e(new Error(`Failed to load JS from ${u}`)),document.head.appendChild(o)}),I=()=>{var r;if(!window.AgentWidget||!window.AgentWidget.initAgentWidget){console.warn("AgentWidget not available. Make sure the script loaded successfully.");return}let n=t.target||"body",e={...t.config};if(t.apiUrl&&!e.apiUrl&&(e.apiUrl=t.apiUrl),t.clientToken&&!e.clientToken&&(e.clientToken=t.clientToken),t.flowId&&!e.flowId&&(e.flowId=t.flowId),!(!(e.apiUrl||e.clientToken)&&Object.keys(e).length===0)){!e.postprocessMessage&&window.AgentWidget.markdownPostprocessor&&(e.postprocessMessage=({text:l})=>window.AgentWidget.markdownPostprocessor(l));try{window.AgentWidget.initAgentWidget({target:n,config:e,useShadowDom:(r=t.useShadowDom)!=null?r:!1})}catch(l){console.error("Failed to initialize AgentWidget:",l)}}};S(async()=>{try{await U(),await b(),C&&(t.config||t.apiUrl||t.clientToken)&&setTimeout(I,0)}catch(n){console.error("Failed to install AgentWidget:",n)}})})();return _(F);})();
1
+ "use strict";var SiteAgentInstaller=(()=>{var m=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var W=Object.getOwnPropertyNames;var T=Object.prototype.hasOwnProperty;var _=(s,i,g,t)=>{if(i&&typeof i=="object"||typeof i=="function")for(let a of W(i))!T.call(s,a)&&a!==g&&m(s,a,{get:()=>i[a],enumerable:!(t=j(i,a))||t.enumerable});return s};var F=s=>_(m({},"__esModule",{value:!0}),s);var L={};(function(){"use strict";if(window.__siteAgentInstallerLoaded)return;window.__siteAgentInstallerLoaded=!0;let i=(()=>{let n=document.currentScript;if(!n)return{};let e={},o=n.getAttribute("data-config");if(o)try{let c=o.replace(/[\r\n]+\s*/g,""),d=JSON.parse(c);if(d.config){let{__proto__:M,constructor:$,prototype:J,...P}=d;Object.assign(e,P)}else e.config=d}catch(c){console.error("Failed to parse data-config JSON:",c)}let r=n.getAttribute("data-runtype-token");r&&(e.clientToken=r);let l=n.getAttribute("data-flow-id");l&&(e.flowId=l);let p=n.getAttribute("data-api-url");p&&(e.apiUrl=p);let w=n.getAttribute("data-preview-param");return w&&(e.previewQueryParam=w),e})(),t={...window.siteAgentConfig||{},...i};if(!(()=>{if(!t.previewQueryParam)return!0;let e=new URLSearchParams(window.location.search).get(t.previewQueryParam);return e!==null&&e!==""&&e.toLowerCase()!=="false"&&e!=="0"})())return;let A=t.version||"latest",C=t.cdn||"jsdelivr",h=t.autoInit!==!1,y=()=>{if(t.cssUrl&&t.jsUrl)return{cssUrl:t.cssUrl,jsUrl:t.jsUrl};let e=`/npm/@runtypelabs/persona@${A}/dist`;return C==="unpkg"?{cssUrl:`https://unpkg.com${e}/widget.css`,jsUrl:`https://unpkg.com${e}/index.global.js`}:{cssUrl:`https://cdn.jsdelivr.net${e}/widget.css`,jsUrl:`https://cdn.jsdelivr.net${e}/index.global.js`}},{cssUrl:u,jsUrl:f}=y(),k=()=>!!document.head.querySelector("link[data-persona]")||!!document.head.querySelector('link[href*="widget.css"]'),S=()=>!!window.AgentWidget,U=n=>{let e=!1,o=()=>{e||(e=!0,n())},r=()=>{typeof requestIdleCallback!="undefined"?requestIdleCallback(()=>{requestAnimationFrame(()=>{requestAnimationFrame(o)})},{timeout:3e3}):setTimeout(o,300)};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",r):r()},b=()=>new Promise((n,e)=>{if(k()){n();return}let o=document.createElement("link");o.rel="stylesheet",o.href=u,o.setAttribute("data-persona","true"),o.onload=()=>n(),o.onerror=()=>e(new Error(`Failed to load CSS from ${u}`)),document.head.appendChild(o)}),I=()=>new Promise((n,e)=>{if(S()){n();return}let o=document.createElement("script");o.src=f,o.async=!0,o.onload=()=>n(),o.onerror=()=>e(new Error(`Failed to load JS from ${f}`)),document.head.appendChild(o)}),v=()=>{var r;if(!window.AgentWidget||!window.AgentWidget.initAgentWidget){console.warn("AgentWidget not available. Make sure the script loaded successfully.");return}let n=t.target||"body",e={...t.config};if(t.apiUrl&&!e.apiUrl&&(e.apiUrl=t.apiUrl),t.clientToken&&!e.clientToken&&(e.clientToken=t.clientToken),t.flowId&&!e.flowId&&(e.flowId=t.flowId),!(!(e.apiUrl||e.clientToken)&&Object.keys(e).length===0)){!e.postprocessMessage&&window.AgentWidget.markdownPostprocessor&&(e.postprocessMessage=({text:l})=>window.AgentWidget.markdownPostprocessor(l));try{window.AgentWidget.initAgentWidget({target:n,config:e,useShadowDom:(r=t.useShadowDom)!=null?r:!1})}catch(l){console.error("Failed to initialize AgentWidget:",l)}}};U(async()=>{try{await b(),await I(),h&&(t.config||t.apiUrl||t.clientToken)&&setTimeout(v,0)}catch(n){console.error("Failed to install AgentWidget:",n)}})})();return F(L);})();
2
2
  //# sourceMappingURL=install.global.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/install.ts"],"sourcesContent":["/**\n * Standalone installer script for easy script tag installation\n * This script automatically loads CSS and JS, then initializes the widget\n * if configuration is provided via window.siteAgentConfig\n */\n\nexport {};\n\ninterface SiteAgentInstallConfig {\n version?: string;\n cdn?: \"unpkg\" | \"jsdelivr\";\n cssUrl?: string;\n jsUrl?: string;\n target?: string | HTMLElement;\n config?: any;\n autoInit?: boolean;\n // Client token mode options (can also be set via data attributes)\n clientToken?: string;\n flowId?: string;\n apiUrl?: string;\n // Optional query param key that gates widget installation in preview mode\n previewQueryParam?: string;\n // Shadow DOM option (defaults to false for better CSS compatibility)\n useShadowDom?: boolean;\n}\n\ndeclare global {\n interface Window {\n siteAgentConfig?: SiteAgentInstallConfig;\n AgentWidget?: any;\n }\n}\n\n(function() {\n \"use strict\";\n\n // Prevent double installation\n if ((window as any).__siteAgentInstallerLoaded) {\n return;\n }\n (window as any).__siteAgentInstallerLoaded = true;\n\n /**\n * Read configuration from data attributes on the current script tag.\n * Supports: data-config (JSON), data-runtype-token, data-flow-id, data-api-url\n */\n const getConfigFromScript = (): Partial<SiteAgentInstallConfig> => {\n // Try to get the current script element\n const script = document.currentScript as HTMLScriptElement | null;\n if (!script) return {};\n\n const scriptConfig: Partial<SiteAgentInstallConfig> = {};\n\n // Full config from data-config attribute (JSON string)\n const configJson = script.getAttribute('data-config');\n if (configJson) {\n try {\n const parsedConfig = JSON.parse(configJson);\n // If it has nested 'config' property, use it; otherwise treat as widget config\n if (parsedConfig.config) {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { __proto__: _a, constructor: _b, prototype: _c, ...safeConfig } = parsedConfig;\n Object.assign(scriptConfig, safeConfig);\n } else {\n // Treat the entire object as widget config\n scriptConfig.config = parsedConfig;\n }\n } catch (e) {\n console.error(\"Failed to parse data-config JSON:\", e);\n }\n }\n\n // Client token from data attribute (primary method for client token mode)\n const token = script.getAttribute('data-runtype-token');\n if (token) {\n scriptConfig.clientToken = token;\n }\n\n // Optional flow ID\n const flowId = script.getAttribute('data-flow-id');\n if (flowId) {\n scriptConfig.flowId = flowId;\n }\n\n // Optional API URL override\n const apiUrl = script.getAttribute('data-api-url');\n if (apiUrl) {\n scriptConfig.apiUrl = apiUrl;\n }\n\n // Optional preview query param gate\n const previewQueryParam = script.getAttribute('data-preview-param');\n if (previewQueryParam) {\n scriptConfig.previewQueryParam = previewQueryParam;\n }\n\n return scriptConfig;\n };\n\n // Get config from script attributes (must be called synchronously during script execution)\n const scriptConfig = getConfigFromScript();\n\n // Merge script attributes with window config (script attributes take precedence)\n const windowConfig: SiteAgentInstallConfig = window.siteAgentConfig || {};\n const config: SiteAgentInstallConfig = { ...windowConfig, ...scriptConfig };\n\n const isPreviewModeEnabled = (): boolean => {\n if (!config.previewQueryParam) {\n return true;\n }\n\n const params = new URLSearchParams(window.location.search);\n const value = params.get(config.previewQueryParam);\n return value !== null && value !== \"\" && value.toLowerCase() !== \"false\" && value !== \"0\";\n };\n\n if (!isPreviewModeEnabled()) {\n return;\n }\n \n const version = config.version || \"latest\";\n const cdn = config.cdn || \"jsdelivr\";\n const autoInit = config.autoInit !== false; // Default to true\n\n // Determine CDN base URL\n const getCdnBase = () => {\n if (config.cssUrl && config.jsUrl) {\n return { cssUrl: config.cssUrl, jsUrl: config.jsUrl };\n }\n \n const packageName = \"@runtypelabs/persona\";\n const basePath = `/npm/${packageName}@${version}/dist`;\n \n if (cdn === \"unpkg\") {\n return {\n cssUrl: `https://unpkg.com${basePath}/widget.css`,\n jsUrl: `https://unpkg.com${basePath}/index.global.js`\n };\n } else {\n return {\n cssUrl: `https://cdn.jsdelivr.net${basePath}/widget.css`,\n jsUrl: `https://cdn.jsdelivr.net${basePath}/index.global.js`\n };\n }\n };\n\n const { cssUrl, jsUrl } = getCdnBase();\n\n // Check if CSS is already loaded\n const isCssLoaded = () => {\n return !!document.head.querySelector('link[data-persona]') ||\n !!document.head.querySelector(`link[href*=\"widget.css\"]`);\n };\n\n // Check if JS is already loaded\n const isJsLoaded = () => {\n return !!(window as any).AgentWidget;\n };\n\n /**\n * Wait for framework hydration to complete (Next.js, Nuxt, etc.)\n * This prevents the framework from removing dynamically added CSS during reconciliation.\n * Uses requestIdleCallback + double requestAnimationFrame for reliable detection.\n */\n const waitForHydration = (callback: () => void): void => {\n let executed = false;\n \n const execute = () => {\n if (executed) return;\n executed = true;\n callback();\n };\n\n const afterDom = () => {\n // Strategy 1: Use requestIdleCallback if available (best for detecting idle after hydration)\n if (typeof requestIdleCallback !== 'undefined') {\n requestIdleCallback(() => {\n // Double requestAnimationFrame ensures at least one full paint cycle completed\n requestAnimationFrame(() => {\n requestAnimationFrame(execute);\n });\n }, { timeout: 3000 }); // Max wait 3 seconds, then proceed anyway\n } else {\n // Strategy 2: Fallback for Safari (no requestIdleCallback)\n // 300ms is typically enough for hydration on most pages\n setTimeout(execute, 300);\n }\n };\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', afterDom);\n } else {\n // DOM already ready, but still wait for potential hydration\n afterDom();\n }\n };\n\n // Load CSS\n const loadCSS = (): Promise<void> => {\n return new Promise((resolve, reject) => {\n if (isCssLoaded()) {\n resolve();\n return;\n }\n\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = cssUrl;\n link.setAttribute(\"data-persona\", \"true\");\n \n link.onload = () => resolve();\n link.onerror = () => reject(new Error(`Failed to load CSS from ${cssUrl}`));\n document.head.appendChild(link);\n });\n };\n\n // Load JS\n const loadJS = (): Promise<void> => {\n return new Promise((resolve, reject) => {\n if (isJsLoaded()) {\n resolve();\n return;\n }\n\n const script = document.createElement(\"script\");\n script.src = jsUrl;\n script.async = true;\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(`Failed to load JS from ${jsUrl}`));\n document.head.appendChild(script);\n });\n };\n\n // Initialize widget\n const initWidget = () => {\n if (!window.AgentWidget || !window.AgentWidget.initAgentWidget) {\n console.warn(\"AgentWidget not available. Make sure the script loaded successfully.\");\n return;\n }\n\n const target = config.target || \"body\";\n // Merge top-level config options into widget config\n const widgetConfig = { ...config.config };\n \n // Merge apiUrl from top-level config into widget config if present\n if (config.apiUrl && !widgetConfig.apiUrl) {\n widgetConfig.apiUrl = config.apiUrl;\n }\n \n // Merge clientToken from top-level config into widget config if present\n if (config.clientToken && !widgetConfig.clientToken) {\n widgetConfig.clientToken = config.clientToken;\n }\n \n // Merge flowId from top-level config into widget config if present\n if (config.flowId && !widgetConfig.flowId) {\n widgetConfig.flowId = config.flowId;\n }\n\n // Only initialize if we have either apiUrl OR clientToken (or other config)\n const hasApiConfig = widgetConfig.apiUrl || widgetConfig.clientToken;\n if (!hasApiConfig && Object.keys(widgetConfig).length === 0) {\n return;\n }\n\n // Auto-apply markdown postprocessor if not explicitly set and available\n if (!widgetConfig.postprocessMessage && window.AgentWidget.markdownPostprocessor) {\n widgetConfig.postprocessMessage = ({ text }: { text: string }) => \n window.AgentWidget.markdownPostprocessor(text);\n }\n\n try {\n window.AgentWidget.initAgentWidget({\n target,\n config: widgetConfig,\n // Explicitly disable shadow DOM for better CSS compatibility with host page\n useShadowDom: config.useShadowDom ?? false\n });\n } catch (error) {\n console.error(\"Failed to initialize AgentWidget:\", error);\n }\n };\n\n // Main installation flow (called after hydration completes)\n const install = async () => {\n try {\n await loadCSS();\n await loadJS();\n \n // Auto-init if we have config OR apiUrl OR clientToken\n const shouldAutoInit = autoInit && (\n config.config || \n config.apiUrl || \n config.clientToken\n );\n \n if (shouldAutoInit) {\n // Wait a tick to ensure AgentWidget is fully initialized\n setTimeout(initWidget, 0);\n }\n } catch (error) {\n console.error(\"Failed to install AgentWidget:\", error);\n }\n };\n\n // Start installation after hydration completes\n // This prevents Next.js/Nuxt/etc. from removing dynamically added CSS\n waitForHydration(install);\n})();\n\n"],"mappings":"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","names":["install_exports","scriptConfig","script","configJson","parsedConfig","_a","_b","_c","safeConfig","e","token","flowId","apiUrl","previewQueryParam","config","value","version","cdn","autoInit","getCdnBase","basePath","cssUrl","jsUrl","isCssLoaded","isJsLoaded","waitForHydration","callback","executed","execute","afterDom","loadCSS","resolve","reject","link","loadJS","initWidget","target","widgetConfig","text","error"]}
1
+ {"version":3,"sources":["../src/install.ts"],"sourcesContent":["/**\n * Standalone installer script for easy script tag installation\n * This script automatically loads CSS and JS, then initializes the widget\n * if configuration is provided via window.siteAgentConfig\n */\n\nexport {};\n\ninterface SiteAgentInstallConfig {\n version?: string;\n cdn?: \"unpkg\" | \"jsdelivr\";\n cssUrl?: string;\n jsUrl?: string;\n target?: string | HTMLElement;\n config?: any;\n autoInit?: boolean;\n // Client token mode options (can also be set via data attributes)\n clientToken?: string;\n flowId?: string;\n apiUrl?: string;\n // Optional query param key that gates widget installation in preview mode\n previewQueryParam?: string;\n // Shadow DOM option (defaults to false for better CSS compatibility)\n useShadowDom?: boolean;\n}\n\ndeclare global {\n interface Window {\n siteAgentConfig?: SiteAgentInstallConfig;\n AgentWidget?: any;\n }\n}\n\n(function() {\n \"use strict\";\n\n // Prevent double installation\n if ((window as any).__siteAgentInstallerLoaded) {\n return;\n }\n (window as any).__siteAgentInstallerLoaded = true;\n\n /**\n * Read configuration from data attributes on the current script tag.\n * Supports: data-config (JSON), data-runtype-token, data-flow-id, data-api-url\n */\n const getConfigFromScript = (): Partial<SiteAgentInstallConfig> => {\n // Try to get the current script element\n const script = document.currentScript as HTMLScriptElement | null;\n if (!script) return {};\n\n const scriptConfig: Partial<SiteAgentInstallConfig> = {};\n\n // Full config from data-config attribute (JSON string)\n const configJson = script.getAttribute('data-config');\n if (configJson) {\n try {\n // HTML attributes preserve literal newlines/tabs which are invalid\n // control characters inside JSON string literals — strip them.\n const normalizedJson = configJson.replace(/[\\r\\n]+\\s*/g, '');\n const parsedConfig = JSON.parse(normalizedJson);\n // If it has nested 'config' property, use it; otherwise treat as widget config\n if (parsedConfig.config) {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { __proto__: _a, constructor: _b, prototype: _c, ...safeConfig } = parsedConfig;\n Object.assign(scriptConfig, safeConfig);\n } else {\n // Treat the entire object as widget config\n scriptConfig.config = parsedConfig;\n }\n } catch (e) {\n console.error(\"Failed to parse data-config JSON:\", e);\n }\n }\n\n // Client token from data attribute (primary method for client token mode)\n const token = script.getAttribute('data-runtype-token');\n if (token) {\n scriptConfig.clientToken = token;\n }\n\n // Optional flow ID\n const flowId = script.getAttribute('data-flow-id');\n if (flowId) {\n scriptConfig.flowId = flowId;\n }\n\n // Optional API URL override\n const apiUrl = script.getAttribute('data-api-url');\n if (apiUrl) {\n scriptConfig.apiUrl = apiUrl;\n }\n\n // Optional preview query param gate\n const previewQueryParam = script.getAttribute('data-preview-param');\n if (previewQueryParam) {\n scriptConfig.previewQueryParam = previewQueryParam;\n }\n\n return scriptConfig;\n };\n\n // Get config from script attributes (must be called synchronously during script execution)\n const scriptConfig = getConfigFromScript();\n\n // Merge script attributes with window config (script attributes take precedence)\n const windowConfig: SiteAgentInstallConfig = window.siteAgentConfig || {};\n const config: SiteAgentInstallConfig = { ...windowConfig, ...scriptConfig };\n\n const isPreviewModeEnabled = (): boolean => {\n if (!config.previewQueryParam) {\n return true;\n }\n\n const params = new URLSearchParams(window.location.search);\n const value = params.get(config.previewQueryParam);\n return value !== null && value !== \"\" && value.toLowerCase() !== \"false\" && value !== \"0\";\n };\n\n if (!isPreviewModeEnabled()) {\n return;\n }\n \n const version = config.version || \"latest\";\n const cdn = config.cdn || \"jsdelivr\";\n const autoInit = config.autoInit !== false; // Default to true\n\n // Determine CDN base URL\n const getCdnBase = () => {\n if (config.cssUrl && config.jsUrl) {\n return { cssUrl: config.cssUrl, jsUrl: config.jsUrl };\n }\n \n const packageName = \"@runtypelabs/persona\";\n const basePath = `/npm/${packageName}@${version}/dist`;\n \n if (cdn === \"unpkg\") {\n return {\n cssUrl: `https://unpkg.com${basePath}/widget.css`,\n jsUrl: `https://unpkg.com${basePath}/index.global.js`\n };\n } else {\n return {\n cssUrl: `https://cdn.jsdelivr.net${basePath}/widget.css`,\n jsUrl: `https://cdn.jsdelivr.net${basePath}/index.global.js`\n };\n }\n };\n\n const { cssUrl, jsUrl } = getCdnBase();\n\n // Check if CSS is already loaded\n const isCssLoaded = () => {\n return !!document.head.querySelector('link[data-persona]') ||\n !!document.head.querySelector(`link[href*=\"widget.css\"]`);\n };\n\n // Check if JS is already loaded\n const isJsLoaded = () => {\n return !!(window as any).AgentWidget;\n };\n\n /**\n * Wait for framework hydration to complete (Next.js, Nuxt, etc.)\n * This prevents the framework from removing dynamically added CSS during reconciliation.\n * Uses requestIdleCallback + double requestAnimationFrame for reliable detection.\n */\n const waitForHydration = (callback: () => void): void => {\n let executed = false;\n \n const execute = () => {\n if (executed) return;\n executed = true;\n callback();\n };\n\n const afterDom = () => {\n // Strategy 1: Use requestIdleCallback if available (best for detecting idle after hydration)\n if (typeof requestIdleCallback !== 'undefined') {\n requestIdleCallback(() => {\n // Double requestAnimationFrame ensures at least one full paint cycle completed\n requestAnimationFrame(() => {\n requestAnimationFrame(execute);\n });\n }, { timeout: 3000 }); // Max wait 3 seconds, then proceed anyway\n } else {\n // Strategy 2: Fallback for Safari (no requestIdleCallback)\n // 300ms is typically enough for hydration on most pages\n setTimeout(execute, 300);\n }\n };\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', afterDom);\n } else {\n // DOM already ready, but still wait for potential hydration\n afterDom();\n }\n };\n\n // Load CSS\n const loadCSS = (): Promise<void> => {\n return new Promise((resolve, reject) => {\n if (isCssLoaded()) {\n resolve();\n return;\n }\n\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = cssUrl;\n link.setAttribute(\"data-persona\", \"true\");\n \n link.onload = () => resolve();\n link.onerror = () => reject(new Error(`Failed to load CSS from ${cssUrl}`));\n document.head.appendChild(link);\n });\n };\n\n // Load JS\n const loadJS = (): Promise<void> => {\n return new Promise((resolve, reject) => {\n if (isJsLoaded()) {\n resolve();\n return;\n }\n\n const script = document.createElement(\"script\");\n script.src = jsUrl;\n script.async = true;\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(`Failed to load JS from ${jsUrl}`));\n document.head.appendChild(script);\n });\n };\n\n // Initialize widget\n const initWidget = () => {\n if (!window.AgentWidget || !window.AgentWidget.initAgentWidget) {\n console.warn(\"AgentWidget not available. Make sure the script loaded successfully.\");\n return;\n }\n\n const target = config.target || \"body\";\n // Merge top-level config options into widget config\n const widgetConfig = { ...config.config };\n \n // Merge apiUrl from top-level config into widget config if present\n if (config.apiUrl && !widgetConfig.apiUrl) {\n widgetConfig.apiUrl = config.apiUrl;\n }\n \n // Merge clientToken from top-level config into widget config if present\n if (config.clientToken && !widgetConfig.clientToken) {\n widgetConfig.clientToken = config.clientToken;\n }\n \n // Merge flowId from top-level config into widget config if present\n if (config.flowId && !widgetConfig.flowId) {\n widgetConfig.flowId = config.flowId;\n }\n\n // Only initialize if we have either apiUrl OR clientToken (or other config)\n const hasApiConfig = widgetConfig.apiUrl || widgetConfig.clientToken;\n if (!hasApiConfig && Object.keys(widgetConfig).length === 0) {\n return;\n }\n\n // Auto-apply markdown postprocessor if not explicitly set and available\n if (!widgetConfig.postprocessMessage && window.AgentWidget.markdownPostprocessor) {\n widgetConfig.postprocessMessage = ({ text }: { text: string }) => \n window.AgentWidget.markdownPostprocessor(text);\n }\n\n try {\n window.AgentWidget.initAgentWidget({\n target,\n config: widgetConfig,\n // Explicitly disable shadow DOM for better CSS compatibility with host page\n useShadowDom: config.useShadowDom ?? false\n });\n } catch (error) {\n console.error(\"Failed to initialize AgentWidget:\", error);\n }\n };\n\n // Main installation flow (called after hydration completes)\n const install = async () => {\n try {\n await loadCSS();\n await loadJS();\n \n // Auto-init if we have config OR apiUrl OR clientToken\n const shouldAutoInit = autoInit && (\n config.config || \n config.apiUrl || \n config.clientToken\n );\n \n if (shouldAutoInit) {\n // Wait a tick to ensure AgentWidget is fully initialized\n setTimeout(initWidget, 0);\n }\n } catch (error) {\n console.error(\"Failed to install AgentWidget:\", error);\n }\n };\n\n // Start installation after hydration completes\n // This prevents Next.js/Nuxt/etc. from removing dynamically added CSS\n waitForHydration(install);\n})();\n\n"],"mappings":"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","names":["install_exports","scriptConfig","script","configJson","normalizedJson","parsedConfig","_a","_b","_c","safeConfig","e","token","flowId","apiUrl","previewQueryParam","config","value","version","cdn","autoInit","getCdnBase","basePath","cssUrl","jsUrl","isCssLoaded","isJsLoaded","waitForHydration","callback","executed","execute","afterDom","loadCSS","resolve","reject","link","loadJS","initWidget","target","widgetConfig","text","error"]}
@@ -239,7 +239,8 @@ var DEFAULT_WIDGET_CONFIG = {
239
239
  reasoningDisplay: {
240
240
  activePreview: false,
241
241
  previewMaxLines: 3,
242
- expandable: true
242
+ expandable: true,
243
+ loadingAnimation: "none"
243
244
  }
244
245
  },
245
246
  suggestionChips: [
@@ -3360,6 +3361,14 @@ var computeToolElapsed = (tool) => {
3360
3361
  );
3361
3362
  return formatElapsedMs(durationMs);
3362
3363
  };
3364
+ var computeReasoningElapsed = (reasoning) => {
3365
+ var _a, _b, _c;
3366
+ const durationMs = reasoning.durationMs !== void 0 ? reasoning.durationMs : Math.max(
3367
+ 0,
3368
+ ((_a = reasoning.completedAt) != null ? _a : Date.now()) - ((_c = (_b = reasoning.startedAt) != null ? _b : reasoning.completedAt) != null ? _c : Date.now())
3369
+ );
3370
+ return formatElapsedMs(durationMs);
3371
+ };
3363
3372
  var resolveToolHeaderText = (tool, template, fallback) => {
3364
3373
  var _a;
3365
3374
  if (!template) return fallback;
@@ -8020,6 +8029,7 @@ var morphMessages = (container, newContent, options = {}) => {
8020
8029
  morphStyle: "innerHTML",
8021
8030
  callbacks: {
8022
8031
  beforeNodeMorphed(oldNode, newNode) {
8032
+ var _a, _b;
8023
8033
  if (!(oldNode instanceof HTMLElement)) return;
8024
8034
  if (preserveTypingAnimation) {
8025
8035
  if (oldNode.classList.contains("persona-animate-typing")) {
@@ -8029,6 +8039,13 @@ var morphMessages = (container, newContent, options = {}) => {
8029
8039
  if (newNode instanceof HTMLElement && !newNode.hasAttribute("data-preserve-animation")) {
8030
8040
  return;
8031
8041
  }
8042
+ if (newNode instanceof HTMLElement && newNode.hasAttribute("data-preserve-animation")) {
8043
+ const oldText = (_a = oldNode.textContent) != null ? _a : "";
8044
+ const newText = (_b = newNode.textContent) != null ? _b : "";
8045
+ if (oldText !== newText) {
8046
+ return;
8047
+ }
8048
+ }
8032
8049
  return false;
8033
8050
  }
8034
8051
  }
@@ -8039,7 +8056,7 @@ var morphMessages = (container, newContent, options = {}) => {
8039
8056
 
8040
8057
  // src/utils/message-fingerprint.ts
8041
8058
  function computeMessageFingerprint(message, configVersion) {
8042
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A;
8059
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C;
8043
8060
  return [
8044
8061
  message.id,
8045
8062
  message.role,
@@ -8051,11 +8068,12 @@ function computeMessageFingerprint(message, configVersion) {
8051
8068
  (_i = (_h = message.llmContent) == null ? void 0 : _h.length) != null ? _i : 0,
8052
8069
  (_k = (_j = message.approval) == null ? void 0 : _j.status) != null ? _k : "",
8053
8070
  (_m = (_l = message.toolCall) == null ? void 0 : _l.status) != null ? _m : "",
8054
- (_p = (_o = (_n = message.toolCall) == null ? void 0 : _n.chunks) == null ? void 0 : _o.length) != null ? _p : 0,
8055
- (_t = (_s = (_r = (_q = message.toolCall) == null ? void 0 : _q.chunks) == null ? void 0 : _r[message.toolCall.chunks.length - 1]) == null ? void 0 : _s.slice(-32)) != null ? _t : "",
8056
- typeof ((_u = message.toolCall) == null ? void 0 : _u.args) === "string" ? message.toolCall.args.length : ((_v = message.toolCall) == null ? void 0 : _v.args) ? JSON.stringify(message.toolCall.args).length : 0,
8057
- (_y = (_x = (_w = message.reasoning) == null ? void 0 : _w.chunks) == null ? void 0 : _x.length) != null ? _y : 0,
8058
- (_A = (_z = message.contentParts) == null ? void 0 : _z.length) != null ? _A : 0,
8071
+ (_o = (_n = message.toolCall) == null ? void 0 : _n.name) != null ? _o : "",
8072
+ (_r = (_q = (_p = message.toolCall) == null ? void 0 : _p.chunks) == null ? void 0 : _q.length) != null ? _r : 0,
8073
+ (_v = (_u = (_t = (_s = message.toolCall) == null ? void 0 : _s.chunks) == null ? void 0 : _t[message.toolCall.chunks.length - 1]) == null ? void 0 : _u.slice(-32)) != null ? _v : "",
8074
+ typeof ((_w = message.toolCall) == null ? void 0 : _w.args) === "string" ? message.toolCall.args.length : ((_x = message.toolCall) == null ? void 0 : _x.args) ? JSON.stringify(message.toolCall.args).length : 0,
8075
+ (_A = (_z = (_y = message.reasoning) == null ? void 0 : _y.chunks) == null ? void 0 : _z.length) != null ? _A : 0,
8076
+ (_C = (_B = message.contentParts) == null ? void 0 : _B.length) != null ? _C : 0,
8059
8077
  configVersion
8060
8078
  ].join("\0");
8061
8079
  }
@@ -10177,7 +10195,7 @@ var updateReasoningBubbleUI = (messageId, bubble) => {
10177
10195
  }
10178
10196
  };
10179
10197
  var createReasoningBubble = (message, config) => {
10180
- var _a, _b, _c, _d, _e, _f, _g;
10198
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
10181
10199
  const reasoning = message.reasoning;
10182
10200
  const bubble = createElement(
10183
10201
  "div",
@@ -10220,13 +10238,23 @@ var createReasoningBubble = (message, config) => {
10220
10238
  const headerContent = createElement("div", "persona-flex persona-flex-col persona-text-left");
10221
10239
  const title = createElement("span", "persona-text-xs persona-text-persona-primary");
10222
10240
  const defaultSummary = "Thinking...";
10223
- const customSummary = (_e = (_d = config == null ? void 0 : config.reasoning) == null ? void 0 : _d.renderCollapsedSummary) == null ? void 0 : _e.call(_d, {
10241
+ const reasoningConfig = (_d = config == null ? void 0 : config.reasoning) != null ? _d : {};
10242
+ const startedAt = String((_e = reasoning.startedAt) != null ? _e : Date.now());
10243
+ const createElapsedSpan = () => {
10244
+ const span = createElement("span", "");
10245
+ span.setAttribute("data-tool-elapsed", startedAt);
10246
+ span.textContent = computeReasoningElapsed(reasoning);
10247
+ return span;
10248
+ };
10249
+ const customSummary = (_f = reasoningConfig.renderCollapsedSummary) == null ? void 0 : _f.call(reasoningConfig, {
10224
10250
  message,
10225
10251
  reasoning,
10226
10252
  defaultSummary,
10227
10253
  previewText,
10228
10254
  isActive,
10229
- config: config != null ? config : {}
10255
+ config: config != null ? config : {},
10256
+ elapsed: computeReasoningElapsed(reasoning),
10257
+ createElapsedElement: createElapsedSpan
10230
10258
  });
10231
10259
  if (typeof customSummary === "string" && customSummary.trim()) {
10232
10260
  title.textContent = customSummary;
@@ -10240,10 +10268,101 @@ var createReasoningBubble = (message, config) => {
10240
10268
  const status = createElement("span", "persona-text-xs persona-text-persona-primary");
10241
10269
  status.textContent = describeReasonStatus(reasoning);
10242
10270
  headerContent.appendChild(status);
10243
- if (reasoning.status === "complete") {
10244
- title.style.display = "none";
10245
- } else {
10271
+ const loadingAnimation = (_g = reasoningDisplayConfig.loadingAnimation) != null ? _g : "none";
10272
+ const activeTemplate = reasoningConfig.activeTextTemplate;
10273
+ const completeTemplate = reasoningConfig.completeTextTemplate;
10274
+ const currentTemplate = isActive ? activeTemplate : completeTemplate;
10275
+ const skipCustomElement = customSummary instanceof HTMLElement;
10276
+ const appendCharSpans = (container, text2, startIndex) => {
10277
+ let idx = startIndex;
10278
+ for (const char of text2) {
10279
+ const span = createElement("span", "persona-tool-char");
10280
+ span.style.setProperty("--char-index", String(idx));
10281
+ span.textContent = char === " " ? "\xA0" : char;
10282
+ container.appendChild(span);
10283
+ idx++;
10284
+ }
10285
+ return idx;
10286
+ };
10287
+ const renderFormattedTitle = (template, animated) => {
10288
+ title.textContent = "";
10289
+ const segments = parseFormattedTemplate(template, "");
10290
+ let charIndex = 0;
10291
+ for (const seg of segments) {
10292
+ const parent = seg.styles.length > 0 ? (() => {
10293
+ const w = createElement("span", seg.styles.map((s) => `persona-tool-text-${s}`).join(" "));
10294
+ title.appendChild(w);
10295
+ return w;
10296
+ })() : title;
10297
+ if (seg.isDuration && isActive) {
10298
+ parent.appendChild(createElapsedSpan());
10299
+ } else {
10300
+ const text2 = seg.isDuration ? computeReasoningElapsed(reasoning) : seg.text;
10301
+ if (animated) {
10302
+ charIndex = appendCharSpans(parent, text2, charIndex);
10303
+ } else {
10304
+ parent.appendChild(document.createTextNode(text2));
10305
+ }
10306
+ }
10307
+ }
10308
+ };
10309
+ if (!skipCustomElement && currentTemplate) {
10310
+ status.style.display = "none";
10246
10311
  title.style.display = "";
10312
+ if (isActive && loadingAnimation !== "none") {
10313
+ const animDuration = (_h = reasoningConfig.loadingAnimationDuration) != null ? _h : 2e3;
10314
+ title.setAttribute("data-preserve-animation", "true");
10315
+ if (loadingAnimation === "pulse") {
10316
+ title.classList.add("persona-tool-loading-pulse");
10317
+ title.style.setProperty("--persona-tool-anim-duration", `${animDuration}ms`);
10318
+ renderFormattedTitle(currentTemplate, false);
10319
+ } else {
10320
+ title.classList.add(`persona-tool-loading-${loadingAnimation}`);
10321
+ title.style.setProperty("--persona-tool-anim-duration", `${animDuration}ms`);
10322
+ if (loadingAnimation === "shimmer-color") {
10323
+ if (reasoningConfig.loadingAnimationColor) {
10324
+ title.style.setProperty("--persona-tool-anim-color", reasoningConfig.loadingAnimationColor);
10325
+ }
10326
+ if (reasoningConfig.loadingAnimationSecondaryColor) {
10327
+ title.style.setProperty("--persona-tool-anim-secondary-color", reasoningConfig.loadingAnimationSecondaryColor);
10328
+ }
10329
+ }
10330
+ renderFormattedTitle(currentTemplate, true);
10331
+ }
10332
+ } else {
10333
+ renderFormattedTitle(currentTemplate, false);
10334
+ }
10335
+ } else if (!skipCustomElement && isActive && loadingAnimation !== "none") {
10336
+ title.style.display = "";
10337
+ const animDuration = (_i = reasoningConfig.loadingAnimationDuration) != null ? _i : 2e3;
10338
+ title.setAttribute("data-preserve-animation", "true");
10339
+ if (loadingAnimation === "pulse") {
10340
+ title.classList.add("persona-tool-loading-pulse");
10341
+ title.style.setProperty("--persona-tool-anim-duration", `${animDuration}ms`);
10342
+ } else {
10343
+ title.classList.add(`persona-tool-loading-${loadingAnimation}`);
10344
+ title.style.setProperty("--persona-tool-anim-duration", `${animDuration}ms`);
10345
+ if (loadingAnimation === "shimmer-color") {
10346
+ if (reasoningConfig.loadingAnimationColor) {
10347
+ title.style.setProperty("--persona-tool-anim-color", reasoningConfig.loadingAnimationColor);
10348
+ }
10349
+ if (reasoningConfig.loadingAnimationSecondaryColor) {
10350
+ title.style.setProperty("--persona-tool-anim-secondary-color", reasoningConfig.loadingAnimationSecondaryColor);
10351
+ }
10352
+ }
10353
+ const text2 = title.textContent || defaultSummary;
10354
+ title.textContent = "";
10355
+ appendCharSpans(title, text2, 0);
10356
+ }
10357
+ if (reasoning.status === "complete") {
10358
+ title.style.display = "none";
10359
+ }
10360
+ } else if (!skipCustomElement) {
10361
+ if (reasoning.status === "complete") {
10362
+ title.style.display = "none";
10363
+ } else {
10364
+ title.style.display = "";
10365
+ }
10247
10366
  }
10248
10367
  let toggleIcon = null;
10249
10368
  if (expandable) {
@@ -10269,7 +10388,7 @@ var createReasoningBubble = (message, config) => {
10269
10388
  collapsedPreview.style.display = "none";
10270
10389
  collapsedPreview.style.whiteSpace = "pre-wrap";
10271
10390
  if (!expanded && isActive && reasoningDisplayConfig.activePreview && previewText) {
10272
- const renderedPreview = (_g = (_f = config == null ? void 0 : config.reasoning) == null ? void 0 : _f.renderCollapsedPreview) == null ? void 0 : _g.call(_f, {
10391
+ const renderedPreview = (_k = (_j = config == null ? void 0 : config.reasoning) == null ? void 0 : _j.renderCollapsedPreview) == null ? void 0 : _k.call(_j, {
10273
10392
  message,
10274
10393
  reasoning,
10275
10394
  defaultPreview: previewText,
@@ -1198,6 +1198,17 @@ type AgentWidgetReasoningDisplayFeature = {
1198
1198
  * @default true
1199
1199
  */
1200
1200
  expandable?: boolean;
1201
+ /**
1202
+ * Animation mode applied to the reasoning header text while reasoning is active.
1203
+ * Reuses the same modes as tool call animations.
1204
+ * - "none" — static text, no animation
1205
+ * - "pulse" — opacity pulse on the entire header text
1206
+ * - "shimmer" — monochrome opacity sweep per character
1207
+ * - "shimmer-color" — color gradient sweep per character
1208
+ * - "rainbow" — rainbow color cycle per character
1209
+ * @default "none"
1210
+ */
1211
+ loadingAnimation?: AgentWidgetToolCallLoadingAnimation;
1201
1212
  };
1202
1213
  type AgentWidgetFeatureFlags = {
1203
1214
  showReasoning?: boolean;
@@ -1821,6 +1832,14 @@ type AgentWidgetReasoningConfig = {
1821
1832
  previewText: string;
1822
1833
  isActive: boolean;
1823
1834
  config: AgentWidgetConfig;
1835
+ /** Static elapsed time snapshot, e.g. "2.6s". */
1836
+ elapsed: string;
1837
+ /**
1838
+ * Returns a `<span>` whose text content is automatically updated every
1839
+ * 100ms by the widget's global timer. Place it anywhere in your returned
1840
+ * HTMLElement to get a live-ticking duration display.
1841
+ */
1842
+ createElapsedElement: () => HTMLElement;
1824
1843
  }) => HTMLElement | string | null;
1825
1844
  /**
1826
1845
  * Override the lightweight collapsed preview content shown for active reasoning rows.
@@ -1833,6 +1852,45 @@ type AgentWidgetReasoningConfig = {
1833
1852
  isActive: boolean;
1834
1853
  config: AgentWidgetConfig;
1835
1854
  }) => HTMLElement | string | null;
1855
+ /**
1856
+ * Template string for the header text while reasoning is active (streaming).
1857
+ *
1858
+ * **Placeholders:** `{duration}` (live-updating elapsed time).
1859
+ *
1860
+ * **Inline formatting:** `~dim~`, `*italic*`, `**bold**` — parsed at render time.
1861
+ *
1862
+ * When not set, falls back to the default "Thinking..." text.
1863
+ * @example "Thinking... ~{duration}~"
1864
+ */
1865
+ activeTextTemplate?: string;
1866
+ /**
1867
+ * Template string for the header text when reasoning is complete.
1868
+ *
1869
+ * **Placeholders:** `{duration}` (final elapsed time).
1870
+ *
1871
+ * **Inline formatting:** `~dim~`, `*italic*`, `**bold**` — same syntax as `activeTextTemplate`.
1872
+ *
1873
+ * When not set, falls back to the default "Thought for X seconds" text.
1874
+ * @example "Thought for ~{duration}~"
1875
+ */
1876
+ completeTextTemplate?: string;
1877
+ /**
1878
+ * Primary color for shimmer-color animation mode.
1879
+ * Defaults to the current text color.
1880
+ */
1881
+ loadingAnimationColor?: string;
1882
+ /**
1883
+ * Secondary/end color for shimmer-color animation mode.
1884
+ * Creates a gradient sweep between `loadingAnimationColor` and this color.
1885
+ * @default "#3b82f6"
1886
+ */
1887
+ loadingAnimationSecondaryColor?: string;
1888
+ /**
1889
+ * Duration of one full animation cycle in milliseconds.
1890
+ * Applies to pulse, shimmer, shimmer-color, and rainbow modes.
1891
+ * @default 2000
1892
+ */
1893
+ loadingAnimationDuration?: number;
1836
1894
  };
1837
1895
  type AgentWidgetSuggestionChipsConfig = {
1838
1896
  fontFamily?: "sans-serif" | "serif" | "mono";
@@ -1198,6 +1198,17 @@ type AgentWidgetReasoningDisplayFeature = {
1198
1198
  * @default true
1199
1199
  */
1200
1200
  expandable?: boolean;
1201
+ /**
1202
+ * Animation mode applied to the reasoning header text while reasoning is active.
1203
+ * Reuses the same modes as tool call animations.
1204
+ * - "none" — static text, no animation
1205
+ * - "pulse" — opacity pulse on the entire header text
1206
+ * - "shimmer" — monochrome opacity sweep per character
1207
+ * - "shimmer-color" — color gradient sweep per character
1208
+ * - "rainbow" — rainbow color cycle per character
1209
+ * @default "none"
1210
+ */
1211
+ loadingAnimation?: AgentWidgetToolCallLoadingAnimation;
1201
1212
  };
1202
1213
  type AgentWidgetFeatureFlags = {
1203
1214
  showReasoning?: boolean;
@@ -1821,6 +1832,14 @@ type AgentWidgetReasoningConfig = {
1821
1832
  previewText: string;
1822
1833
  isActive: boolean;
1823
1834
  config: AgentWidgetConfig;
1835
+ /** Static elapsed time snapshot, e.g. "2.6s". */
1836
+ elapsed: string;
1837
+ /**
1838
+ * Returns a `<span>` whose text content is automatically updated every
1839
+ * 100ms by the widget's global timer. Place it anywhere in your returned
1840
+ * HTMLElement to get a live-ticking duration display.
1841
+ */
1842
+ createElapsedElement: () => HTMLElement;
1824
1843
  }) => HTMLElement | string | null;
1825
1844
  /**
1826
1845
  * Override the lightweight collapsed preview content shown for active reasoning rows.
@@ -1833,6 +1852,45 @@ type AgentWidgetReasoningConfig = {
1833
1852
  isActive: boolean;
1834
1853
  config: AgentWidgetConfig;
1835
1854
  }) => HTMLElement | string | null;
1855
+ /**
1856
+ * Template string for the header text while reasoning is active (streaming).
1857
+ *
1858
+ * **Placeholders:** `{duration}` (live-updating elapsed time).
1859
+ *
1860
+ * **Inline formatting:** `~dim~`, `*italic*`, `**bold**` — parsed at render time.
1861
+ *
1862
+ * When not set, falls back to the default "Thinking..." text.
1863
+ * @example "Thinking... ~{duration}~"
1864
+ */
1865
+ activeTextTemplate?: string;
1866
+ /**
1867
+ * Template string for the header text when reasoning is complete.
1868
+ *
1869
+ * **Placeholders:** `{duration}` (final elapsed time).
1870
+ *
1871
+ * **Inline formatting:** `~dim~`, `*italic*`, `**bold**` — same syntax as `activeTextTemplate`.
1872
+ *
1873
+ * When not set, falls back to the default "Thought for X seconds" text.
1874
+ * @example "Thought for ~{duration}~"
1875
+ */
1876
+ completeTextTemplate?: string;
1877
+ /**
1878
+ * Primary color for shimmer-color animation mode.
1879
+ * Defaults to the current text color.
1880
+ */
1881
+ loadingAnimationColor?: string;
1882
+ /**
1883
+ * Secondary/end color for shimmer-color animation mode.
1884
+ * Creates a gradient sweep between `loadingAnimationColor` and this color.
1885
+ * @default "#3b82f6"
1886
+ */
1887
+ loadingAnimationSecondaryColor?: string;
1888
+ /**
1889
+ * Duration of one full animation cycle in milliseconds.
1890
+ * Applies to pulse, shimmer, shimmer-color, and rainbow modes.
1891
+ * @default 2000
1892
+ */
1893
+ loadingAnimationDuration?: number;
1836
1894
  };
1837
1895
  type AgentWidgetSuggestionChipsConfig = {
1838
1896
  fontFamily?: "sans-serif" | "serif" | "mono";