@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.
- package/dist/index.cjs +43 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +58 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.global.js +61 -61
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +43 -43
- package/dist/index.js.map +1 -1
- package/dist/install.global.js +1 -1
- package/dist/install.global.js.map +1 -1
- package/dist/theme-editor.cjs +133 -14
- package/dist/theme-editor.d.cts +58 -0
- package/dist/theme-editor.d.ts +58 -0
- package/dist/theme-editor.js +133 -14
- package/dist/theme-reference.cjs +1 -1
- package/dist/theme-reference.js +1 -1
- package/package.json +1 -1
- package/src/components/reasoning-bubble.ts +139 -5
- package/src/defaults.ts +1 -0
- package/src/install.ts +4 -1
- package/src/theme-reference.ts +6 -3
- package/src/tool-call-display-defaults.test.ts +1 -0
- package/src/types.ts +58 -0
- package/src/utils/formatting.test.ts +25 -1
- package/src/utils/formatting.ts +15 -0
- package/src/utils/message-fingerprint.test.ts +12 -0
- package/src/utils/message-fingerprint.ts +1 -0
- package/src/utils/morph.test.ts +86 -0
- package/src/utils/morph.ts +8 -0
package/dist/install.global.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var SiteAgentInstaller=(()=>{var
|
|
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"]}
|
package/dist/theme-editor.cjs
CHANGED
|
@@ -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
|
-
(
|
|
8055
|
-
(
|
|
8056
|
-
|
|
8057
|
-
|
|
8058
|
-
(_A = (_z = message.
|
|
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
|
|
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
|
-
|
|
10244
|
-
|
|
10245
|
-
|
|
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 = (
|
|
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,
|
package/dist/theme-editor.d.cts
CHANGED
|
@@ -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";
|
package/dist/theme-editor.d.ts
CHANGED
|
@@ -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";
|