@ash-cloud/ash-ai 0.1.8

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.
Files changed (64) hide show
  1. package/dist/ash-widget.js +2 -0
  2. package/dist/ash-widget.js.map +1 -0
  3. package/dist/embed.cjs +19 -0
  4. package/dist/embed.cjs.map +1 -0
  5. package/dist/embed.d.cts +278 -0
  6. package/dist/embed.d.ts +278 -0
  7. package/dist/embed.js +16 -0
  8. package/dist/embed.js.map +1 -0
  9. package/dist/icons.cjs +156 -0
  10. package/dist/icons.cjs.map +1 -0
  11. package/dist/icons.d.cts +1 -0
  12. package/dist/icons.d.ts +1 -0
  13. package/dist/icons.js +3 -0
  14. package/dist/icons.js.map +1 -0
  15. package/dist/index-DJwpy-R5.js +6797 -0
  16. package/dist/index.cjs +17502 -0
  17. package/dist/index.cjs.map +1 -0
  18. package/dist/index.d.cts +9590 -0
  19. package/dist/index.d.ts +9590 -0
  20. package/dist/index.js +17328 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/playground/App.d.ts +2 -0
  23. package/dist/playground/App.d.ts.map +1 -0
  24. package/dist/playground/Playground.d.ts +62 -0
  25. package/dist/playground/Playground.d.ts.map +1 -0
  26. package/dist/playground/components/ChatInput.d.ts +60 -0
  27. package/dist/playground/components/ChatInput.d.ts.map +1 -0
  28. package/dist/playground/components/MessageList.d.ts +28 -0
  29. package/dist/playground/components/MessageList.d.ts.map +1 -0
  30. package/dist/playground/components/NormalizedMessageList.d.ts +26 -0
  31. package/dist/playground/components/NormalizedMessageList.d.ts.map +1 -0
  32. package/dist/playground/components/SandboxLogsPanel.d.ts +16 -0
  33. package/dist/playground/components/SandboxLogsPanel.d.ts.map +1 -0
  34. package/dist/playground/components/Sidebar.d.ts +7 -0
  35. package/dist/playground/components/Sidebar.d.ts.map +1 -0
  36. package/dist/playground/components/ToolCallCard.d.ts +9 -0
  37. package/dist/playground/components/ToolCallCard.d.ts.map +1 -0
  38. package/dist/playground/components/icons.d.ts +9 -0
  39. package/dist/playground/components/icons.d.ts.map +1 -0
  40. package/dist/playground/contexts/ThemeContext.d.ts +9 -0
  41. package/dist/playground/contexts/ThemeContext.d.ts.map +1 -0
  42. package/dist/playground/index.d.ts +30 -0
  43. package/dist/playground/index.d.ts.map +1 -0
  44. package/dist/playground/main.d.ts +1 -0
  45. package/dist/playground/main.d.ts.map +1 -0
  46. package/dist/playground/pages/AgentsPage.d.ts +2 -0
  47. package/dist/playground/pages/AgentsPage.d.ts.map +1 -0
  48. package/dist/playground/pages/ChatPage.d.ts +2 -0
  49. package/dist/playground/pages/ChatPage.d.ts.map +1 -0
  50. package/dist/playground/pages/SessionsPage.d.ts +2 -0
  51. package/dist/playground/pages/SessionsPage.d.ts.map +1 -0
  52. package/dist/playground.css +1 -0
  53. package/dist/playground.d.ts +18 -0
  54. package/dist/playground.d.ts.map +1 -0
  55. package/dist/playground.js +3753 -0
  56. package/dist/schema-B_CVsJm5.d.cts +1585 -0
  57. package/dist/schema-B_CVsJm5.d.ts +1585 -0
  58. package/dist/schema.cjs +254 -0
  59. package/dist/schema.cjs.map +1 -0
  60. package/dist/schema.d.cts +3 -0
  61. package/dist/schema.d.ts +3 -0
  62. package/dist/schema.js +235 -0
  63. package/dist/schema.js.map +1 -0
  64. package/package.json +108 -0
package/dist/embed.cjs ADDED
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ // src/embed/loader.ts
4
+ function generateEmbedSnippet(widgetUrl, settings) {
5
+ const settingsJson = JSON.stringify(settings, null, 2);
6
+ return `<!-- Ash AI Widget -->
7
+ <script>
8
+ window.AshSettings = ${settingsJson};
9
+ (function(){var w=window;var a=w.Ash;if(typeof a==="function"){a('boot',w.AshSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Ash=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='${widgetUrl}';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();
10
+ </script>`;
11
+ }
12
+ function generateMinifiedLoader(widgetUrl) {
13
+ return `(function(){var w=window;var a=w.Ash;if(typeof a==="function"){a('boot',w.AshSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Ash=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='${widgetUrl}';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();`;
14
+ }
15
+
16
+ exports.generateEmbedSnippet = generateEmbedSnippet;
17
+ exports.generateMinifiedLoader = generateMinifiedLoader;
18
+ //# sourceMappingURL=embed.cjs.map
19
+ //# sourceMappingURL=embed.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/embed/loader.ts"],"names":[],"mappings":";;;AA2WO,SAAS,oBAAA,CACd,WACA,QAAA,EACQ;AACR,EAAA,MAAM,YAAA,GAAe,IAAA,CAAK,SAAA,CAAU,QAAA,EAAU,MAAM,CAAC,CAAA;AAErD,EAAA,OAAO,CAAA;AAAA;AAAA,uBAAA,EAEgB,YAAY,CAAA;AAAA,iSAAA,EAC8P,SAAS,CAAA;AAAA,SAAA,CAAA;AAE5S;AAKO,SAAS,uBAAuB,SAAA,EAA2B;AAChE,EAAA,OAAO,kSAAkS,SAAS,CAAA,wNAAA,CAAA;AACpT","file":"embed.cjs","sourcesContent":["/**\n * Ash AI Embeddable Widget Loader\n *\n * This is the lightweight loader script that users embed on their sites.\n * It creates a command queue and asynchronously loads the full widget bundle.\n *\n * Usage:\n * ```html\n * <script>\n * window.AshSettings = {\n * apiBasePath: 'https://your-api.com/api',\n * agent: 'your-agent-slug'\n * };\n * (function(){var w=window;var a=w.Ash;if(typeof a===\"function\"){a('boot',w.AshSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Ash=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://cdn.your-domain.com/ash-widget.js';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();\n * </script>\n * ```\n */\n\n// =============================================================================\n// Event Types\n// =============================================================================\n\n/**\n * Tool use event - fired when the agent invokes a tool\n */\nexport interface AshToolUseEvent {\n type: 'tool_use';\n toolName: string;\n toolId: string;\n input: unknown;\n}\n\n/**\n * Tool result event - fired when a tool returns a result\n */\nexport interface AshToolResultEvent {\n type: 'tool_result';\n toolId: string;\n result: unknown;\n isError?: boolean;\n}\n\n/**\n * Streaming event - fired during message streaming\n */\nexport interface AshStreamEvent {\n type: 'stream_start' | 'stream_delta' | 'stream_end';\n content?: string;\n fullContent?: string;\n}\n\n/**\n * Error event - fired when an error occurs\n */\nexport interface AshErrorEvent {\n type: 'error';\n error: string;\n code?: string;\n}\n\n/**\n * Message event - fired for complete messages\n */\nexport interface AshMessageEvent {\n type: 'message';\n role: 'user' | 'assistant';\n content: string;\n messageId?: string;\n}\n\n/**\n * Todo item in a todo update\n */\nexport interface AshTodoItem {\n content: string;\n status: 'pending' | 'in_progress' | 'completed';\n activeForm: string;\n}\n\n/**\n * Todo update event - fired when todos are updated\n */\nexport interface AshTodoUpdateEvent {\n type: 'todo_update';\n todos: AshTodoItem[];\n stats: {\n total: number;\n completed: number;\n inProgress: number;\n pending: number;\n };\n}\n\n/**\n * Union of all widget events\n */\nexport type AshEvent =\n | AshToolUseEvent\n | AshToolResultEvent\n | AshStreamEvent\n | AshErrorEvent\n | AshMessageEvent\n | AshTodoUpdateEvent;\n\n/**\n * Context data that can be pushed to the widget\n */\nexport interface AshContextData {\n /**\n * Key-value pairs to include in the system context\n */\n [key: string]: unknown;\n}\n\n// =============================================================================\n// Settings Interface\n// =============================================================================\n\nexport interface AshWidgetSettings {\n /**\n * Base path for API calls (e.g., \"https://your-api.com/api\")\n */\n apiBasePath: string;\n\n /**\n * Agent slug to use (optional - auto-selects first agent if not specified)\n */\n agent?: string;\n\n /**\n * Widget position on the page\n * - 'bottom-right', 'bottom-left', 'top-right', 'top-left': Floating widget in corner\n * - 'inline' or 'embedded': Widget fills its parent container (use with containerId)\n * @default 'bottom-right'\n */\n position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left' | 'inline' | 'embedded';\n\n /**\n * Container element ID for inline/embedded mode.\n * The widget will render inside this element and fill it completely.\n * Make sure to set a height on the container element.\n */\n containerId?: string;\n\n /**\n * Initial session ID to resume\n */\n sessionId?: string;\n\n /**\n * Whether to show the widget on load\n * @default false (shows launcher button)\n */\n open?: boolean;\n\n /**\n * Custom launcher button text\n * @default undefined (shows icon only)\n */\n launcherText?: string;\n\n /**\n * Theme customization\n */\n theme?: {\n /**\n * Primary accent color (hex)\n * @default '#ccff00'\n */\n accentColor?: string;\n\n /**\n * Background color for widget (hex)\n * @default '#0a0a0a'\n */\n backgroundColor?: string;\n\n /**\n * Text color (hex)\n * @default '#f3f4f6'\n */\n textColor?: string;\n\n /**\n * Border radius for the widget container\n * @default '16px'\n */\n borderRadius?: string;\n };\n\n /**\n * Widget dimensions\n */\n size?: {\n /**\n * Width of the widget panel\n * @default '400px'\n */\n width?: string;\n\n /**\n * Height of the widget panel\n * @default '600px'\n */\n height?: string;\n\n /**\n * Maximum height (for inline mode)\n */\n maxHeight?: string;\n };\n\n /**\n * Z-index for the widget\n * @default 2147483647 (max z-index)\n */\n zIndex?: number;\n\n /**\n * Custom greeting message shown before first interaction\n */\n greeting?: string;\n\n /**\n * Placeholder text for the input field\n * @default 'Type a message...'\n */\n placeholder?: string;\n\n /**\n * Callback when widget is opened\n */\n onOpen?: () => void;\n\n /**\n * Callback when widget is closed\n */\n onClose?: () => void;\n\n /**\n * Callback when a session starts\n */\n onSessionStart?: (sessionId: string) => void;\n\n /**\n * Callback when a message is sent\n */\n onMessageSent?: (message: string) => void;\n\n /**\n * Callback when a message is received\n */\n onMessageReceived?: (message: string) => void;\n\n // =========================================================================\n // Advanced Event Hooks\n // =========================================================================\n\n /**\n * Callback for all events (use for logging or custom handling)\n * This is called for every event type\n */\n onEvent?: (event: AshEvent) => void;\n\n /**\n * Callback when the agent uses a tool\n */\n onToolUse?: (event: AshToolUseEvent) => void;\n\n /**\n * Callback when a tool returns a result\n */\n onToolResult?: (event: AshToolResultEvent) => void;\n\n /**\n * Callback when streaming starts\n */\n onStreamStart?: () => void;\n\n /**\n * Callback during streaming with delta content\n */\n onStreamDelta?: (content: string, fullContent: string) => void;\n\n /**\n * Callback when streaming ends\n */\n onStreamEnd?: (fullContent: string) => void;\n\n /**\n * Callback when an error occurs\n */\n onError?: (error: string, code?: string) => void;\n\n /**\n * Callback when todos are updated (TodoWrite tool is called)\n */\n onTodoUpdate?: (event: AshTodoUpdateEvent) => void;\n\n // =========================================================================\n // Context & Data\n // =========================================================================\n\n /**\n * Initial context data to include with messages\n * This data will be sent as part of the system context\n */\n context?: AshContextData;\n\n /**\n * Hide the default launcher button (for custom triggers)\n * @default false\n */\n hideLauncher?: boolean;\n}\n\nexport type AshCommand =\n // Lifecycle commands\n | ['boot', AshWidgetSettings]\n | ['shutdown']\n // Visibility commands\n | ['open']\n | ['close']\n | ['toggle']\n | ['show']\n | ['hide']\n | ['showLauncher']\n | ['hideLauncher']\n // Configuration commands\n | ['update', Partial<AshWidgetSettings>]\n // Event listener commands\n | ['onOpen', () => void]\n | ['onClose', () => void]\n | ['onEvent', (event: AshEvent) => void]\n // Data/Context commands\n | ['setContext', AshContextData]\n | ['updateContext', Partial<AshContextData>]\n | ['clearContext']\n // Message commands\n | ['sendMessage', string]\n | ['sendMessageWithContext', string, AshContextData]\n // Query commands (returns via callback)\n | ['getSessionId', (sessionId: string | null) => void]\n | ['getContext', (context: AshContextData) => void]\n | ['getMessages', (messages: Array<{ role: string; content: string }>) => void];\n\nexport interface AshWidget {\n (command: AshCommand[0], ...args: unknown[]): void;\n q?: AshCommand[];\n c?: (args: AshCommand) => void;\n booted?: boolean;\n}\n\ndeclare global {\n interface Window {\n Ash: AshWidget;\n AshSettings?: AshWidgetSettings;\n }\n}\n\n/**\n * Generate the embed snippet for a given configuration\n */\nexport function generateEmbedSnippet(\n widgetUrl: string,\n settings: Partial<AshWidgetSettings>\n): string {\n const settingsJson = JSON.stringify(settings, null, 2);\n\n return `<!-- Ash AI Widget -->\n<script>\n window.AshSettings = ${settingsJson};\n (function(){var w=window;var a=w.Ash;if(typeof a===\"function\"){a('boot',w.AshSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Ash=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='${widgetUrl}';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();\n</script>`;\n}\n\n/**\n * Generate a minified version of the loader\n */\nexport function generateMinifiedLoader(widgetUrl: string): string {\n return `(function(){var w=window;var a=w.Ash;if(typeof a===\"function\"){a('boot',w.AshSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Ash=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='${widgetUrl}';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();`;\n}\n"]}
@@ -0,0 +1,278 @@
1
+ /**
2
+ * Ash AI Embeddable Widget Loader
3
+ *
4
+ * This is the lightweight loader script that users embed on their sites.
5
+ * It creates a command queue and asynchronously loads the full widget bundle.
6
+ *
7
+ * Usage:
8
+ * ```html
9
+ * <script>
10
+ * window.AshSettings = {
11
+ * apiBasePath: 'https://your-api.com/api',
12
+ * agent: 'your-agent-slug'
13
+ * };
14
+ * (function(){var w=window;var a=w.Ash;if(typeof a==="function"){a('boot',w.AshSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Ash=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://cdn.your-domain.com/ash-widget.js';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();
15
+ * </script>
16
+ * ```
17
+ */
18
+ /**
19
+ * Tool use event - fired when the agent invokes a tool
20
+ */
21
+ interface AshToolUseEvent {
22
+ type: 'tool_use';
23
+ toolName: string;
24
+ toolId: string;
25
+ input: unknown;
26
+ }
27
+ /**
28
+ * Tool result event - fired when a tool returns a result
29
+ */
30
+ interface AshToolResultEvent {
31
+ type: 'tool_result';
32
+ toolId: string;
33
+ result: unknown;
34
+ isError?: boolean;
35
+ }
36
+ /**
37
+ * Streaming event - fired during message streaming
38
+ */
39
+ interface AshStreamEvent {
40
+ type: 'stream_start' | 'stream_delta' | 'stream_end';
41
+ content?: string;
42
+ fullContent?: string;
43
+ }
44
+ /**
45
+ * Error event - fired when an error occurs
46
+ */
47
+ interface AshErrorEvent {
48
+ type: 'error';
49
+ error: string;
50
+ code?: string;
51
+ }
52
+ /**
53
+ * Message event - fired for complete messages
54
+ */
55
+ interface AshMessageEvent {
56
+ type: 'message';
57
+ role: 'user' | 'assistant';
58
+ content: string;
59
+ messageId?: string;
60
+ }
61
+ /**
62
+ * Todo item in a todo update
63
+ */
64
+ interface AshTodoItem {
65
+ content: string;
66
+ status: 'pending' | 'in_progress' | 'completed';
67
+ activeForm: string;
68
+ }
69
+ /**
70
+ * Todo update event - fired when todos are updated
71
+ */
72
+ interface AshTodoUpdateEvent {
73
+ type: 'todo_update';
74
+ todos: AshTodoItem[];
75
+ stats: {
76
+ total: number;
77
+ completed: number;
78
+ inProgress: number;
79
+ pending: number;
80
+ };
81
+ }
82
+ /**
83
+ * Union of all widget events
84
+ */
85
+ type AshEvent = AshToolUseEvent | AshToolResultEvent | AshStreamEvent | AshErrorEvent | AshMessageEvent | AshTodoUpdateEvent;
86
+ /**
87
+ * Context data that can be pushed to the widget
88
+ */
89
+ interface AshContextData {
90
+ /**
91
+ * Key-value pairs to include in the system context
92
+ */
93
+ [key: string]: unknown;
94
+ }
95
+ interface AshWidgetSettings {
96
+ /**
97
+ * Base path for API calls (e.g., "https://your-api.com/api")
98
+ */
99
+ apiBasePath: string;
100
+ /**
101
+ * Agent slug to use (optional - auto-selects first agent if not specified)
102
+ */
103
+ agent?: string;
104
+ /**
105
+ * Widget position on the page
106
+ * - 'bottom-right', 'bottom-left', 'top-right', 'top-left': Floating widget in corner
107
+ * - 'inline' or 'embedded': Widget fills its parent container (use with containerId)
108
+ * @default 'bottom-right'
109
+ */
110
+ position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left' | 'inline' | 'embedded';
111
+ /**
112
+ * Container element ID for inline/embedded mode.
113
+ * The widget will render inside this element and fill it completely.
114
+ * Make sure to set a height on the container element.
115
+ */
116
+ containerId?: string;
117
+ /**
118
+ * Initial session ID to resume
119
+ */
120
+ sessionId?: string;
121
+ /**
122
+ * Whether to show the widget on load
123
+ * @default false (shows launcher button)
124
+ */
125
+ open?: boolean;
126
+ /**
127
+ * Custom launcher button text
128
+ * @default undefined (shows icon only)
129
+ */
130
+ launcherText?: string;
131
+ /**
132
+ * Theme customization
133
+ */
134
+ theme?: {
135
+ /**
136
+ * Primary accent color (hex)
137
+ * @default '#ccff00'
138
+ */
139
+ accentColor?: string;
140
+ /**
141
+ * Background color for widget (hex)
142
+ * @default '#0a0a0a'
143
+ */
144
+ backgroundColor?: string;
145
+ /**
146
+ * Text color (hex)
147
+ * @default '#f3f4f6'
148
+ */
149
+ textColor?: string;
150
+ /**
151
+ * Border radius for the widget container
152
+ * @default '16px'
153
+ */
154
+ borderRadius?: string;
155
+ };
156
+ /**
157
+ * Widget dimensions
158
+ */
159
+ size?: {
160
+ /**
161
+ * Width of the widget panel
162
+ * @default '400px'
163
+ */
164
+ width?: string;
165
+ /**
166
+ * Height of the widget panel
167
+ * @default '600px'
168
+ */
169
+ height?: string;
170
+ /**
171
+ * Maximum height (for inline mode)
172
+ */
173
+ maxHeight?: string;
174
+ };
175
+ /**
176
+ * Z-index for the widget
177
+ * @default 2147483647 (max z-index)
178
+ */
179
+ zIndex?: number;
180
+ /**
181
+ * Custom greeting message shown before first interaction
182
+ */
183
+ greeting?: string;
184
+ /**
185
+ * Placeholder text for the input field
186
+ * @default 'Type a message...'
187
+ */
188
+ placeholder?: string;
189
+ /**
190
+ * Callback when widget is opened
191
+ */
192
+ onOpen?: () => void;
193
+ /**
194
+ * Callback when widget is closed
195
+ */
196
+ onClose?: () => void;
197
+ /**
198
+ * Callback when a session starts
199
+ */
200
+ onSessionStart?: (sessionId: string) => void;
201
+ /**
202
+ * Callback when a message is sent
203
+ */
204
+ onMessageSent?: (message: string) => void;
205
+ /**
206
+ * Callback when a message is received
207
+ */
208
+ onMessageReceived?: (message: string) => void;
209
+ /**
210
+ * Callback for all events (use for logging or custom handling)
211
+ * This is called for every event type
212
+ */
213
+ onEvent?: (event: AshEvent) => void;
214
+ /**
215
+ * Callback when the agent uses a tool
216
+ */
217
+ onToolUse?: (event: AshToolUseEvent) => void;
218
+ /**
219
+ * Callback when a tool returns a result
220
+ */
221
+ onToolResult?: (event: AshToolResultEvent) => void;
222
+ /**
223
+ * Callback when streaming starts
224
+ */
225
+ onStreamStart?: () => void;
226
+ /**
227
+ * Callback during streaming with delta content
228
+ */
229
+ onStreamDelta?: (content: string, fullContent: string) => void;
230
+ /**
231
+ * Callback when streaming ends
232
+ */
233
+ onStreamEnd?: (fullContent: string) => void;
234
+ /**
235
+ * Callback when an error occurs
236
+ */
237
+ onError?: (error: string, code?: string) => void;
238
+ /**
239
+ * Callback when todos are updated (TodoWrite tool is called)
240
+ */
241
+ onTodoUpdate?: (event: AshTodoUpdateEvent) => void;
242
+ /**
243
+ * Initial context data to include with messages
244
+ * This data will be sent as part of the system context
245
+ */
246
+ context?: AshContextData;
247
+ /**
248
+ * Hide the default launcher button (for custom triggers)
249
+ * @default false
250
+ */
251
+ hideLauncher?: boolean;
252
+ }
253
+ type AshCommand = ['boot', AshWidgetSettings] | ['shutdown'] | ['open'] | ['close'] | ['toggle'] | ['show'] | ['hide'] | ['showLauncher'] | ['hideLauncher'] | ['update', Partial<AshWidgetSettings>] | ['onOpen', () => void] | ['onClose', () => void] | ['onEvent', (event: AshEvent) => void] | ['setContext', AshContextData] | ['updateContext', Partial<AshContextData>] | ['clearContext'] | ['sendMessage', string] | ['sendMessageWithContext', string, AshContextData] | ['getSessionId', (sessionId: string | null) => void] | ['getContext', (context: AshContextData) => void] | ['getMessages', (messages: Array<{
254
+ role: string;
255
+ content: string;
256
+ }>) => void];
257
+ interface AshWidget {
258
+ (command: AshCommand[0], ...args: unknown[]): void;
259
+ q?: AshCommand[];
260
+ c?: (args: AshCommand) => void;
261
+ booted?: boolean;
262
+ }
263
+ declare global {
264
+ interface Window {
265
+ Ash: AshWidget;
266
+ AshSettings?: AshWidgetSettings;
267
+ }
268
+ }
269
+ /**
270
+ * Generate the embed snippet for a given configuration
271
+ */
272
+ declare function generateEmbedSnippet(widgetUrl: string, settings: Partial<AshWidgetSettings>): string;
273
+ /**
274
+ * Generate a minified version of the loader
275
+ */
276
+ declare function generateMinifiedLoader(widgetUrl: string): string;
277
+
278
+ export { type AshCommand, type AshContextData, type AshErrorEvent, type AshEvent, type AshMessageEvent, type AshStreamEvent, type AshTodoItem, type AshTodoUpdateEvent, type AshToolResultEvent, type AshToolUseEvent, type AshWidget, type AshWidgetSettings, generateEmbedSnippet, generateMinifiedLoader };
@@ -0,0 +1,278 @@
1
+ /**
2
+ * Ash AI Embeddable Widget Loader
3
+ *
4
+ * This is the lightweight loader script that users embed on their sites.
5
+ * It creates a command queue and asynchronously loads the full widget bundle.
6
+ *
7
+ * Usage:
8
+ * ```html
9
+ * <script>
10
+ * window.AshSettings = {
11
+ * apiBasePath: 'https://your-api.com/api',
12
+ * agent: 'your-agent-slug'
13
+ * };
14
+ * (function(){var w=window;var a=w.Ash;if(typeof a==="function"){a('boot',w.AshSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Ash=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://cdn.your-domain.com/ash-widget.js';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();
15
+ * </script>
16
+ * ```
17
+ */
18
+ /**
19
+ * Tool use event - fired when the agent invokes a tool
20
+ */
21
+ interface AshToolUseEvent {
22
+ type: 'tool_use';
23
+ toolName: string;
24
+ toolId: string;
25
+ input: unknown;
26
+ }
27
+ /**
28
+ * Tool result event - fired when a tool returns a result
29
+ */
30
+ interface AshToolResultEvent {
31
+ type: 'tool_result';
32
+ toolId: string;
33
+ result: unknown;
34
+ isError?: boolean;
35
+ }
36
+ /**
37
+ * Streaming event - fired during message streaming
38
+ */
39
+ interface AshStreamEvent {
40
+ type: 'stream_start' | 'stream_delta' | 'stream_end';
41
+ content?: string;
42
+ fullContent?: string;
43
+ }
44
+ /**
45
+ * Error event - fired when an error occurs
46
+ */
47
+ interface AshErrorEvent {
48
+ type: 'error';
49
+ error: string;
50
+ code?: string;
51
+ }
52
+ /**
53
+ * Message event - fired for complete messages
54
+ */
55
+ interface AshMessageEvent {
56
+ type: 'message';
57
+ role: 'user' | 'assistant';
58
+ content: string;
59
+ messageId?: string;
60
+ }
61
+ /**
62
+ * Todo item in a todo update
63
+ */
64
+ interface AshTodoItem {
65
+ content: string;
66
+ status: 'pending' | 'in_progress' | 'completed';
67
+ activeForm: string;
68
+ }
69
+ /**
70
+ * Todo update event - fired when todos are updated
71
+ */
72
+ interface AshTodoUpdateEvent {
73
+ type: 'todo_update';
74
+ todos: AshTodoItem[];
75
+ stats: {
76
+ total: number;
77
+ completed: number;
78
+ inProgress: number;
79
+ pending: number;
80
+ };
81
+ }
82
+ /**
83
+ * Union of all widget events
84
+ */
85
+ type AshEvent = AshToolUseEvent | AshToolResultEvent | AshStreamEvent | AshErrorEvent | AshMessageEvent | AshTodoUpdateEvent;
86
+ /**
87
+ * Context data that can be pushed to the widget
88
+ */
89
+ interface AshContextData {
90
+ /**
91
+ * Key-value pairs to include in the system context
92
+ */
93
+ [key: string]: unknown;
94
+ }
95
+ interface AshWidgetSettings {
96
+ /**
97
+ * Base path for API calls (e.g., "https://your-api.com/api")
98
+ */
99
+ apiBasePath: string;
100
+ /**
101
+ * Agent slug to use (optional - auto-selects first agent if not specified)
102
+ */
103
+ agent?: string;
104
+ /**
105
+ * Widget position on the page
106
+ * - 'bottom-right', 'bottom-left', 'top-right', 'top-left': Floating widget in corner
107
+ * - 'inline' or 'embedded': Widget fills its parent container (use with containerId)
108
+ * @default 'bottom-right'
109
+ */
110
+ position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left' | 'inline' | 'embedded';
111
+ /**
112
+ * Container element ID for inline/embedded mode.
113
+ * The widget will render inside this element and fill it completely.
114
+ * Make sure to set a height on the container element.
115
+ */
116
+ containerId?: string;
117
+ /**
118
+ * Initial session ID to resume
119
+ */
120
+ sessionId?: string;
121
+ /**
122
+ * Whether to show the widget on load
123
+ * @default false (shows launcher button)
124
+ */
125
+ open?: boolean;
126
+ /**
127
+ * Custom launcher button text
128
+ * @default undefined (shows icon only)
129
+ */
130
+ launcherText?: string;
131
+ /**
132
+ * Theme customization
133
+ */
134
+ theme?: {
135
+ /**
136
+ * Primary accent color (hex)
137
+ * @default '#ccff00'
138
+ */
139
+ accentColor?: string;
140
+ /**
141
+ * Background color for widget (hex)
142
+ * @default '#0a0a0a'
143
+ */
144
+ backgroundColor?: string;
145
+ /**
146
+ * Text color (hex)
147
+ * @default '#f3f4f6'
148
+ */
149
+ textColor?: string;
150
+ /**
151
+ * Border radius for the widget container
152
+ * @default '16px'
153
+ */
154
+ borderRadius?: string;
155
+ };
156
+ /**
157
+ * Widget dimensions
158
+ */
159
+ size?: {
160
+ /**
161
+ * Width of the widget panel
162
+ * @default '400px'
163
+ */
164
+ width?: string;
165
+ /**
166
+ * Height of the widget panel
167
+ * @default '600px'
168
+ */
169
+ height?: string;
170
+ /**
171
+ * Maximum height (for inline mode)
172
+ */
173
+ maxHeight?: string;
174
+ };
175
+ /**
176
+ * Z-index for the widget
177
+ * @default 2147483647 (max z-index)
178
+ */
179
+ zIndex?: number;
180
+ /**
181
+ * Custom greeting message shown before first interaction
182
+ */
183
+ greeting?: string;
184
+ /**
185
+ * Placeholder text for the input field
186
+ * @default 'Type a message...'
187
+ */
188
+ placeholder?: string;
189
+ /**
190
+ * Callback when widget is opened
191
+ */
192
+ onOpen?: () => void;
193
+ /**
194
+ * Callback when widget is closed
195
+ */
196
+ onClose?: () => void;
197
+ /**
198
+ * Callback when a session starts
199
+ */
200
+ onSessionStart?: (sessionId: string) => void;
201
+ /**
202
+ * Callback when a message is sent
203
+ */
204
+ onMessageSent?: (message: string) => void;
205
+ /**
206
+ * Callback when a message is received
207
+ */
208
+ onMessageReceived?: (message: string) => void;
209
+ /**
210
+ * Callback for all events (use for logging or custom handling)
211
+ * This is called for every event type
212
+ */
213
+ onEvent?: (event: AshEvent) => void;
214
+ /**
215
+ * Callback when the agent uses a tool
216
+ */
217
+ onToolUse?: (event: AshToolUseEvent) => void;
218
+ /**
219
+ * Callback when a tool returns a result
220
+ */
221
+ onToolResult?: (event: AshToolResultEvent) => void;
222
+ /**
223
+ * Callback when streaming starts
224
+ */
225
+ onStreamStart?: () => void;
226
+ /**
227
+ * Callback during streaming with delta content
228
+ */
229
+ onStreamDelta?: (content: string, fullContent: string) => void;
230
+ /**
231
+ * Callback when streaming ends
232
+ */
233
+ onStreamEnd?: (fullContent: string) => void;
234
+ /**
235
+ * Callback when an error occurs
236
+ */
237
+ onError?: (error: string, code?: string) => void;
238
+ /**
239
+ * Callback when todos are updated (TodoWrite tool is called)
240
+ */
241
+ onTodoUpdate?: (event: AshTodoUpdateEvent) => void;
242
+ /**
243
+ * Initial context data to include with messages
244
+ * This data will be sent as part of the system context
245
+ */
246
+ context?: AshContextData;
247
+ /**
248
+ * Hide the default launcher button (for custom triggers)
249
+ * @default false
250
+ */
251
+ hideLauncher?: boolean;
252
+ }
253
+ type AshCommand = ['boot', AshWidgetSettings] | ['shutdown'] | ['open'] | ['close'] | ['toggle'] | ['show'] | ['hide'] | ['showLauncher'] | ['hideLauncher'] | ['update', Partial<AshWidgetSettings>] | ['onOpen', () => void] | ['onClose', () => void] | ['onEvent', (event: AshEvent) => void] | ['setContext', AshContextData] | ['updateContext', Partial<AshContextData>] | ['clearContext'] | ['sendMessage', string] | ['sendMessageWithContext', string, AshContextData] | ['getSessionId', (sessionId: string | null) => void] | ['getContext', (context: AshContextData) => void] | ['getMessages', (messages: Array<{
254
+ role: string;
255
+ content: string;
256
+ }>) => void];
257
+ interface AshWidget {
258
+ (command: AshCommand[0], ...args: unknown[]): void;
259
+ q?: AshCommand[];
260
+ c?: (args: AshCommand) => void;
261
+ booted?: boolean;
262
+ }
263
+ declare global {
264
+ interface Window {
265
+ Ash: AshWidget;
266
+ AshSettings?: AshWidgetSettings;
267
+ }
268
+ }
269
+ /**
270
+ * Generate the embed snippet for a given configuration
271
+ */
272
+ declare function generateEmbedSnippet(widgetUrl: string, settings: Partial<AshWidgetSettings>): string;
273
+ /**
274
+ * Generate a minified version of the loader
275
+ */
276
+ declare function generateMinifiedLoader(widgetUrl: string): string;
277
+
278
+ export { type AshCommand, type AshContextData, type AshErrorEvent, type AshEvent, type AshMessageEvent, type AshStreamEvent, type AshTodoItem, type AshTodoUpdateEvent, type AshToolResultEvent, type AshToolUseEvent, type AshWidget, type AshWidgetSettings, generateEmbedSnippet, generateMinifiedLoader };
package/dist/embed.js ADDED
@@ -0,0 +1,16 @@
1
+ // src/embed/loader.ts
2
+ function generateEmbedSnippet(widgetUrl, settings) {
3
+ const settingsJson = JSON.stringify(settings, null, 2);
4
+ return `<!-- Ash AI Widget -->
5
+ <script>
6
+ window.AshSettings = ${settingsJson};
7
+ (function(){var w=window;var a=w.Ash;if(typeof a==="function"){a('boot',w.AshSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Ash=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='${widgetUrl}';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();
8
+ </script>`;
9
+ }
10
+ function generateMinifiedLoader(widgetUrl) {
11
+ return `(function(){var w=window;var a=w.Ash;if(typeof a==="function"){a('boot',w.AshSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Ash=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='${widgetUrl}';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();`;
12
+ }
13
+
14
+ export { generateEmbedSnippet, generateMinifiedLoader };
15
+ //# sourceMappingURL=embed.js.map
16
+ //# sourceMappingURL=embed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/embed/loader.ts"],"names":[],"mappings":";AA2WO,SAAS,oBAAA,CACd,WACA,QAAA,EACQ;AACR,EAAA,MAAM,YAAA,GAAe,IAAA,CAAK,SAAA,CAAU,QAAA,EAAU,MAAM,CAAC,CAAA;AAErD,EAAA,OAAO,CAAA;AAAA;AAAA,uBAAA,EAEgB,YAAY,CAAA;AAAA,iSAAA,EAC8P,SAAS,CAAA;AAAA,SAAA,CAAA;AAE5S;AAKO,SAAS,uBAAuB,SAAA,EAA2B;AAChE,EAAA,OAAO,kSAAkS,SAAS,CAAA,wNAAA,CAAA;AACpT","file":"embed.js","sourcesContent":["/**\n * Ash AI Embeddable Widget Loader\n *\n * This is the lightweight loader script that users embed on their sites.\n * It creates a command queue and asynchronously loads the full widget bundle.\n *\n * Usage:\n * ```html\n * <script>\n * window.AshSettings = {\n * apiBasePath: 'https://your-api.com/api',\n * agent: 'your-agent-slug'\n * };\n * (function(){var w=window;var a=w.Ash;if(typeof a===\"function\"){a('boot',w.AshSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Ash=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://cdn.your-domain.com/ash-widget.js';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();\n * </script>\n * ```\n */\n\n// =============================================================================\n// Event Types\n// =============================================================================\n\n/**\n * Tool use event - fired when the agent invokes a tool\n */\nexport interface AshToolUseEvent {\n type: 'tool_use';\n toolName: string;\n toolId: string;\n input: unknown;\n}\n\n/**\n * Tool result event - fired when a tool returns a result\n */\nexport interface AshToolResultEvent {\n type: 'tool_result';\n toolId: string;\n result: unknown;\n isError?: boolean;\n}\n\n/**\n * Streaming event - fired during message streaming\n */\nexport interface AshStreamEvent {\n type: 'stream_start' | 'stream_delta' | 'stream_end';\n content?: string;\n fullContent?: string;\n}\n\n/**\n * Error event - fired when an error occurs\n */\nexport interface AshErrorEvent {\n type: 'error';\n error: string;\n code?: string;\n}\n\n/**\n * Message event - fired for complete messages\n */\nexport interface AshMessageEvent {\n type: 'message';\n role: 'user' | 'assistant';\n content: string;\n messageId?: string;\n}\n\n/**\n * Todo item in a todo update\n */\nexport interface AshTodoItem {\n content: string;\n status: 'pending' | 'in_progress' | 'completed';\n activeForm: string;\n}\n\n/**\n * Todo update event - fired when todos are updated\n */\nexport interface AshTodoUpdateEvent {\n type: 'todo_update';\n todos: AshTodoItem[];\n stats: {\n total: number;\n completed: number;\n inProgress: number;\n pending: number;\n };\n}\n\n/**\n * Union of all widget events\n */\nexport type AshEvent =\n | AshToolUseEvent\n | AshToolResultEvent\n | AshStreamEvent\n | AshErrorEvent\n | AshMessageEvent\n | AshTodoUpdateEvent;\n\n/**\n * Context data that can be pushed to the widget\n */\nexport interface AshContextData {\n /**\n * Key-value pairs to include in the system context\n */\n [key: string]: unknown;\n}\n\n// =============================================================================\n// Settings Interface\n// =============================================================================\n\nexport interface AshWidgetSettings {\n /**\n * Base path for API calls (e.g., \"https://your-api.com/api\")\n */\n apiBasePath: string;\n\n /**\n * Agent slug to use (optional - auto-selects first agent if not specified)\n */\n agent?: string;\n\n /**\n * Widget position on the page\n * - 'bottom-right', 'bottom-left', 'top-right', 'top-left': Floating widget in corner\n * - 'inline' or 'embedded': Widget fills its parent container (use with containerId)\n * @default 'bottom-right'\n */\n position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left' | 'inline' | 'embedded';\n\n /**\n * Container element ID for inline/embedded mode.\n * The widget will render inside this element and fill it completely.\n * Make sure to set a height on the container element.\n */\n containerId?: string;\n\n /**\n * Initial session ID to resume\n */\n sessionId?: string;\n\n /**\n * Whether to show the widget on load\n * @default false (shows launcher button)\n */\n open?: boolean;\n\n /**\n * Custom launcher button text\n * @default undefined (shows icon only)\n */\n launcherText?: string;\n\n /**\n * Theme customization\n */\n theme?: {\n /**\n * Primary accent color (hex)\n * @default '#ccff00'\n */\n accentColor?: string;\n\n /**\n * Background color for widget (hex)\n * @default '#0a0a0a'\n */\n backgroundColor?: string;\n\n /**\n * Text color (hex)\n * @default '#f3f4f6'\n */\n textColor?: string;\n\n /**\n * Border radius for the widget container\n * @default '16px'\n */\n borderRadius?: string;\n };\n\n /**\n * Widget dimensions\n */\n size?: {\n /**\n * Width of the widget panel\n * @default '400px'\n */\n width?: string;\n\n /**\n * Height of the widget panel\n * @default '600px'\n */\n height?: string;\n\n /**\n * Maximum height (for inline mode)\n */\n maxHeight?: string;\n };\n\n /**\n * Z-index for the widget\n * @default 2147483647 (max z-index)\n */\n zIndex?: number;\n\n /**\n * Custom greeting message shown before first interaction\n */\n greeting?: string;\n\n /**\n * Placeholder text for the input field\n * @default 'Type a message...'\n */\n placeholder?: string;\n\n /**\n * Callback when widget is opened\n */\n onOpen?: () => void;\n\n /**\n * Callback when widget is closed\n */\n onClose?: () => void;\n\n /**\n * Callback when a session starts\n */\n onSessionStart?: (sessionId: string) => void;\n\n /**\n * Callback when a message is sent\n */\n onMessageSent?: (message: string) => void;\n\n /**\n * Callback when a message is received\n */\n onMessageReceived?: (message: string) => void;\n\n // =========================================================================\n // Advanced Event Hooks\n // =========================================================================\n\n /**\n * Callback for all events (use for logging or custom handling)\n * This is called for every event type\n */\n onEvent?: (event: AshEvent) => void;\n\n /**\n * Callback when the agent uses a tool\n */\n onToolUse?: (event: AshToolUseEvent) => void;\n\n /**\n * Callback when a tool returns a result\n */\n onToolResult?: (event: AshToolResultEvent) => void;\n\n /**\n * Callback when streaming starts\n */\n onStreamStart?: () => void;\n\n /**\n * Callback during streaming with delta content\n */\n onStreamDelta?: (content: string, fullContent: string) => void;\n\n /**\n * Callback when streaming ends\n */\n onStreamEnd?: (fullContent: string) => void;\n\n /**\n * Callback when an error occurs\n */\n onError?: (error: string, code?: string) => void;\n\n /**\n * Callback when todos are updated (TodoWrite tool is called)\n */\n onTodoUpdate?: (event: AshTodoUpdateEvent) => void;\n\n // =========================================================================\n // Context & Data\n // =========================================================================\n\n /**\n * Initial context data to include with messages\n * This data will be sent as part of the system context\n */\n context?: AshContextData;\n\n /**\n * Hide the default launcher button (for custom triggers)\n * @default false\n */\n hideLauncher?: boolean;\n}\n\nexport type AshCommand =\n // Lifecycle commands\n | ['boot', AshWidgetSettings]\n | ['shutdown']\n // Visibility commands\n | ['open']\n | ['close']\n | ['toggle']\n | ['show']\n | ['hide']\n | ['showLauncher']\n | ['hideLauncher']\n // Configuration commands\n | ['update', Partial<AshWidgetSettings>]\n // Event listener commands\n | ['onOpen', () => void]\n | ['onClose', () => void]\n | ['onEvent', (event: AshEvent) => void]\n // Data/Context commands\n | ['setContext', AshContextData]\n | ['updateContext', Partial<AshContextData>]\n | ['clearContext']\n // Message commands\n | ['sendMessage', string]\n | ['sendMessageWithContext', string, AshContextData]\n // Query commands (returns via callback)\n | ['getSessionId', (sessionId: string | null) => void]\n | ['getContext', (context: AshContextData) => void]\n | ['getMessages', (messages: Array<{ role: string; content: string }>) => void];\n\nexport interface AshWidget {\n (command: AshCommand[0], ...args: unknown[]): void;\n q?: AshCommand[];\n c?: (args: AshCommand) => void;\n booted?: boolean;\n}\n\ndeclare global {\n interface Window {\n Ash: AshWidget;\n AshSettings?: AshWidgetSettings;\n }\n}\n\n/**\n * Generate the embed snippet for a given configuration\n */\nexport function generateEmbedSnippet(\n widgetUrl: string,\n settings: Partial<AshWidgetSettings>\n): string {\n const settingsJson = JSON.stringify(settings, null, 2);\n\n return `<!-- Ash AI Widget -->\n<script>\n window.AshSettings = ${settingsJson};\n (function(){var w=window;var a=w.Ash;if(typeof a===\"function\"){a('boot',w.AshSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Ash=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='${widgetUrl}';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();\n</script>`;\n}\n\n/**\n * Generate a minified version of the loader\n */\nexport function generateMinifiedLoader(widgetUrl: string): string {\n return `(function(){var w=window;var a=w.Ash;if(typeof a===\"function\"){a('boot',w.AshSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Ash=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='${widgetUrl}';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();`;\n}\n"]}