@aikaara/chat-sdk 0.1.4 → 0.2.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 CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./headless-CrgIWcf7.cjs"),a=require("./ui.cjs");function l(t){a.registerComponents();const r=document.createElement("aikaara-chat-widget"),n={baseUrl:"base-url",userToken:"user-token",apiKey:"api-key",title:"title",subtitle:"subtitle",theme:"theme",primaryColor:"primary-color",position:"position",width:"width",height:"height",placeholder:"placeholder",welcomeMessage:"welcome-message",avatarUrl:"avatar-url"};for(const[o,s]of Object.entries(n)){const i=t[o];i!=null&&r.setAttribute(s,String(i))}return r.configure(t),document.body.appendChild(r),r}function u(){const t=document.querySelector("aikaara-chat-widget");t&&t.remove()}exports.ActionCableClient=e.ActionCableClient;exports.AikaaraChatClient=e.AikaaraChatClient;exports.ApiClient=e.ApiClient;exports.ChannelSubscription=e.ChannelSubscription;exports.ConnectionManager=e.ConnectionManager;exports.ConversationManager=e.ConversationManager;exports.EventEmitter=e.EventEmitter;exports.MessageStore=e.MessageStore;exports.AikaaraChatBubble=a.AikaaraChatBubble;exports.AikaaraChatHeader=a.AikaaraChatHeader;exports.AikaaraChatInput=a.AikaaraChatInput;exports.AikaaraChatWidget=a.AikaaraChatWidget;exports.AikaaraErrorBanner=a.AikaaraErrorBanner;exports.AikaaraMessageBubble=a.AikaaraMessageBubble;exports.AikaaraMessageList=a.AikaaraMessageList;exports.AikaaraStreamingMessage=a.AikaaraStreamingMessage;exports.AikaaraTypingIndicator=a.AikaaraTypingIndicator;exports.registerComponents=a.registerComponents;exports.mount=l;exports.unmount=u;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./AikaaraChatClient-ChZ2bL9f.cjs"),n=require("./headless.cjs"),a=require("./ui.cjs");function u(t){a.registerComponents();const r=document.createElement("aikaara-chat-widget"),o={baseUrl:"base-url",userToken:"user-token",apiKey:"api-key",title:"title",subtitle:"subtitle",theme:"theme",primaryColor:"primary-color",position:"position",width:"width",height:"height",placeholder:"placeholder",welcomeMessage:"welcome-message",avatarUrl:"avatar-url"};for(const[s,l]of Object.entries(o)){const i=t[s];i!=null&&r.setAttribute(l,String(i))}return r.configure(t),document.body.appendChild(r),r}function g(){const t=document.querySelector("aikaara-chat-widget");t&&t.remove()}exports.ActionCableClient=e.ActionCableClient;exports.AikaaraChatClient=e.AikaaraChatClient;exports.ApiClient=e.ApiClient;exports.ChannelSubscription=e.ChannelSubscription;exports.ConnectionManager=e.ConnectionManager;exports.ConversationManager=e.ConversationManager;exports.EventEmitter=e.EventEmitter;exports.MessageStore=e.MessageStore;exports.FormBridge=n.FormBridge;exports.TiledeskTransport=n.TiledeskTransport;exports.AikaaraChatBubble=a.AikaaraChatBubble;exports.AikaaraChatHeader=a.AikaaraChatHeader;exports.AikaaraChatInput=a.AikaaraChatInput;exports.AikaaraChatWidget=a.AikaaraChatWidget;exports.AikaaraErrorBanner=a.AikaaraErrorBanner;exports.AikaaraMessageBubble=a.AikaaraMessageBubble;exports.AikaaraMessageList=a.AikaaraMessageList;exports.AikaaraStreamingMessage=a.AikaaraStreamingMessage;exports.AikaaraTypingIndicator=a.AikaaraTypingIndicator;exports.registerComponents=a.registerComponents;exports.mount=u;exports.unmount=g;
package/dist/index.d.ts CHANGED
@@ -22,6 +22,8 @@ export declare interface ActionCableMessage {
22
22
  message?: unknown;
23
23
  }
24
24
 
25
+ export declare type AgentAction = EditEntityAction | SaveEntityAction | TestToolAction | NavigateAction;
26
+
25
27
  export declare interface AgentEvent {
26
28
  type: AgentEventType;
27
29
  [key: string]: unknown;
@@ -52,7 +54,32 @@ export declare class AikaaraChatClient extends EventEmitter<ChatEvents> {
52
54
  get messages(): Message[];
53
55
  get conversationId(): string | null;
54
56
  get isConnected(): boolean;
57
+ /**
58
+ * Update the agent's context with information about the host app's current state.
59
+ * Call this on route changes so the agent knows what page/entity the user is viewing.
60
+ *
61
+ * The context is stored in conversation metadata and interpolated into the system prompt.
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * // On route change
66
+ * client.setContext({
67
+ * currentPage: '/products/42',
68
+ * entityType: 'product',
69
+ * entityId: '42',
70
+ * availableRoutes: { products: '/products', orders: '/orders' },
71
+ * });
72
+ * ```
73
+ */
74
+ setContext(context: AppContext): Promise<void>;
55
75
  disconnect(): Promise<void>;
76
+ /**
77
+ * Parse structured action results from tool execution output.
78
+ * When the agent calls tools like `edit_current_entity`, `save_current_entity`,
79
+ * `navigate_to`, or `test_tool_by_id`, the result contains an action payload
80
+ * that the SDK emits as a typed event for the host app to handle.
81
+ */
82
+ private parseActionResult;
56
83
  private handleBroadcast;
57
84
  }
58
85
 
@@ -95,6 +122,8 @@ export declare class AikaaraChatWidget extends HTMLElement {
95
122
  private getConfig;
96
123
  private render;
97
124
  private initController;
125
+ sendUserEvent(eventKey: string, value?: Record<string, unknown>, source?: string): void;
126
+ getClient(): AikaaraChatClient | null;
98
127
  private darkenColor;
99
128
  }
100
129
 
@@ -157,19 +186,36 @@ export declare class AikaaraTypingIndicator extends HTMLElement {
157
186
  export declare class ApiClient {
158
187
  private baseUrl;
159
188
  private apiKey?;
189
+ private authToken?;
160
190
  private userToken;
161
- constructor(baseUrl: string, userToken: string, apiKey?: string);
191
+ constructor(baseUrl: string, userToken: string, apiKey?: string, authToken?: string);
162
192
  createConversation(params: {
163
193
  systemPromptId?: number;
164
194
  channel?: string;
165
195
  title?: string;
166
196
  extUid?: string;
167
197
  }): Promise<CreateConversationResponse>;
198
+ updateContext(conversationId: string, context: Record<string, unknown>): Promise<void>;
168
199
  getMessages(conversationId: string): Promise<Message[]>;
169
200
  private mapMessage;
170
201
  private request;
171
202
  }
172
203
 
204
+ export declare interface AppContext {
205
+ /** Current page/route path in the host app (e.g., '/products/42') */
206
+ currentPage: string;
207
+ /** Entity type on the current page (e.g., 'product', 'agent') */
208
+ entityType?: string;
209
+ /** Entity ID on the current page */
210
+ entityId?: string | number;
211
+ /** Project/workspace ID if applicable */
212
+ projectId?: string | number;
213
+ /** Routes the agent can navigate to — map of label → path */
214
+ availableRoutes?: Record<string, string>;
215
+ /** Additional context for the agent (e.g., form field names, entity schema) */
216
+ custom?: Record<string, unknown>;
217
+ }
218
+
173
219
  export declare class ChannelSubscription {
174
220
  readonly identifier: string;
175
221
  private callbacks;
@@ -188,10 +234,11 @@ export declare class ChannelSubscription {
188
234
 
189
235
  export declare interface ChatClientConfig extends ConnectionConfig {
190
236
  apiKey?: string;
237
+ authToken?: string;
191
238
  extUid?: string;
192
239
  conversationId?: string;
193
240
  systemPromptId?: number;
194
- channel?: 'widget' | 'api';
241
+ channel?: 'widget' | 'api' | 'sidekick';
195
242
  onMessage?: (message: Message) => void;
196
243
  onStatusChange?: (status: string) => void;
197
244
  onError?: (error: Error) => void;
@@ -222,12 +269,26 @@ export declare interface ChatEvents {
222
269
  'typing:stop': void;
223
270
  'error': Error;
224
271
  'status': string;
272
+ 'action:edit_entity': EditEntityAction;
273
+ 'action:save_entity': SaveEntityAction;
274
+ 'action:test_tool': TestToolAction;
275
+ 'action:navigate': NavigateAction;
276
+ 'tool:start': {
277
+ toolName: string;
278
+ args: Record<string, unknown>;
279
+ };
280
+ 'tool:end': {
281
+ toolName: string;
282
+ result: unknown;
283
+ isError: boolean;
284
+ };
225
285
  }
226
286
 
227
287
  export declare interface ConnectionConfig {
228
288
  baseUrl: string;
229
289
  wsUrl?: string;
230
290
  userToken: string;
291
+ tiledesk?: TiledeskTransportConfig;
231
292
  reconnect?: boolean;
232
293
  maxReconnectAttempts?: number;
233
294
  reconnectInterval?: number;
@@ -270,6 +331,13 @@ declare interface CreateConversationResponse {
270
331
  status: string;
271
332
  }
272
333
 
334
+ export declare interface EditEntityAction {
335
+ action: 'edit_entity';
336
+ entity_type: string;
337
+ entity_id: string | number;
338
+ fields: FieldUpdate[];
339
+ }
340
+
273
341
  export declare class EventEmitter<Events extends Record<string, any>> {
274
342
  private handlers;
275
343
  on<K extends keyof Events & string>(event: K, handler: (data: Events[K]) => void): () => void;
@@ -278,6 +346,128 @@ export declare class EventEmitter<Events extends Record<string, any>> {
278
346
  removeAllListeners(): void;
279
347
  }
280
348
 
349
+ export declare interface FieldUpdate {
350
+ field: string;
351
+ value: unknown;
352
+ previousValue?: unknown;
353
+ }
354
+
355
+ export declare class FormBridge extends EventEmitter<FormBridgeEvents> {
356
+ private registration;
357
+ private pendingEdits;
358
+ constructor(client: AikaaraChatClient);
359
+ /**
360
+ * Register a form to receive AI-driven edits.
361
+ * Only one form can be registered at a time (the active page).
362
+ */
363
+ registerForm(reg: FormRegistration): void;
364
+ /**
365
+ * Unregister the form (call on unmount).
366
+ */
367
+ unregisterForm(entityType: string, entityId: string | number): void;
368
+ /**
369
+ * Get the current form registration (if any).
370
+ */
371
+ get currentForm(): FormRegistration | null;
372
+ /**
373
+ * Manually push field updates (for custom tool handling).
374
+ */
375
+ pushFieldUpdates(entityType: string, entityId: string | number, fields: FieldUpdate[]): void;
376
+ /**
377
+ * Request the current form to save.
378
+ */
379
+ requestSave(): Promise<{
380
+ success: boolean;
381
+ error?: string;
382
+ }>;
383
+ /**
384
+ * Request the current form to run a test.
385
+ */
386
+ requestTest(params?: Record<string, unknown>): Promise<{
387
+ success: boolean;
388
+ error?: string;
389
+ }>;
390
+ private setupListeners;
391
+ }
392
+
393
+ /**
394
+ * FormBridge — Enables AI agents to visually edit forms in the host application.
395
+ *
396
+ * This bridges the gap between AI tool results and UI form state. When the agent
397
+ * calls tools like `edit_current_entity`, the FormBridge receives the action and
398
+ * pushes field updates to the registered form.
399
+ *
400
+ * ## Usage (any framework)
401
+ *
402
+ * ```typescript
403
+ * import { AikaaraChatClient, FormBridge } from '@aikaara/chat-sdk/headless';
404
+ *
405
+ * const client = new AikaaraChatClient({ baseUrl, userToken, authToken });
406
+ * const bridge = new FormBridge(client);
407
+ *
408
+ * // Register a form (call when your form mounts)
409
+ * bridge.registerForm({
410
+ * entityType: 'product',
411
+ * entityId: 42,
412
+ * onFieldUpdate: (fields) => {
413
+ * for (const { field, value } of fields) {
414
+ * formState[field] = value; // update your form framework
415
+ * }
416
+ * },
417
+ * onSave: async () => await api.saveProduct(42, formState),
418
+ * getCurrentValues: () => ({ ...formState }),
419
+ * });
420
+ *
421
+ * // Unregister when form unmounts
422
+ * bridge.unregisterForm('product', 42);
423
+ * ```
424
+ *
425
+ * ## React hook (provided by dashboard, but easy to replicate)
426
+ *
427
+ * ```tsx
428
+ * function useFormBridge(bridge, { entityType, entityId, onFieldUpdate, onSave }) {
429
+ * useEffect(() => {
430
+ * bridge.registerForm({ entityType, entityId, onFieldUpdate, onSave, getCurrentValues });
431
+ * return () => bridge.unregisterForm(entityType, entityId);
432
+ * }, [entityType, entityId]);
433
+ * }
434
+ * ```
435
+ */
436
+ export declare interface FormBridgeEvents {
437
+ 'edit:applied': {
438
+ entityType: string;
439
+ entityId: string | number;
440
+ fields: FieldUpdate[];
441
+ };
442
+ 'edit:pending': {
443
+ entityType: string;
444
+ entityId: string | number;
445
+ fields: FieldUpdate[];
446
+ };
447
+ 'save:success': {
448
+ entityType: string;
449
+ entityId: string | number;
450
+ };
451
+ 'save:error': {
452
+ entityType: string;
453
+ entityId: string | number;
454
+ error: string;
455
+ };
456
+ 'test:triggered': {
457
+ toolId: number;
458
+ parameters: Record<string, unknown>;
459
+ };
460
+ }
461
+
462
+ export declare interface FormRegistration {
463
+ entityType: string;
464
+ entityId: string | number;
465
+ onFieldUpdate: (fields: FieldUpdate[]) => void;
466
+ onSave: () => Promise<void>;
467
+ onTest?: (params?: Record<string, unknown>) => Promise<void>;
468
+ getCurrentValues: () => Record<string, unknown>;
469
+ }
470
+
281
471
  export declare interface Message {
282
472
  id: string;
283
473
  conversationId: string;
@@ -313,10 +503,66 @@ export declare class MessageStore {
313
503
 
314
504
  export declare function mount(config: WidgetConfig): AikaaraChatWidget;
315
505
 
506
+ export declare interface NavigateAction {
507
+ navigate_to: string;
508
+ }
509
+
316
510
  export declare function registerComponents(): void;
317
511
 
512
+ export declare interface SaveEntityAction {
513
+ action: 'save_entity';
514
+ }
515
+
318
516
  declare type SubscriptionCallback = (data: unknown) => void;
319
517
 
518
+ export declare interface TestToolAction {
519
+ action: 'test_tool';
520
+ tool_id: number;
521
+ parameters: Record<string, unknown>;
522
+ }
523
+
524
+ export declare interface TiledeskMessage {
525
+ text?: string;
526
+ type?: string;
527
+ sender?: string;
528
+ senderFullname?: string;
529
+ recipient?: string;
530
+ timestamp?: number;
531
+ attributes?: Record<string, unknown>;
532
+ metadata?: Record<string, unknown>;
533
+ [key: string]: unknown;
534
+ }
535
+
536
+ export declare class TiledeskTransport {
537
+ private client;
538
+ private config;
539
+ private messageHandlers;
540
+ private stateHandlers;
541
+ private subscribedTopics;
542
+ private reconnectAttempt;
543
+ private maxReconnectAttempts;
544
+ private disposed;
545
+ constructor(config: TiledeskTransportConfig);
546
+ connect(): Promise<void>;
547
+ subscribeToConversation(conversationId: string): void;
548
+ unsubscribeFromConversation(conversationId: string): void;
549
+ publishMessage(conversationId: string, text: string): void;
550
+ onMessage(handler: TransportMessageHandler): () => void;
551
+ onStateChange(handler: TransportStateHandler): () => void;
552
+ disconnect(): void;
553
+ get isConnected(): boolean;
554
+ private scheduleReconnect;
555
+ private notifyStateChange;
556
+ }
557
+
558
+ export declare interface TiledeskTransportConfig {
559
+ mqttEndpoint: string;
560
+ jwtToken: string;
561
+ userId: string;
562
+ userName?: string;
563
+ projectId: string;
564
+ }
565
+
320
566
  export declare interface ToolCall {
321
567
  id: string;
322
568
  type: 'function';
@@ -331,6 +577,10 @@ export declare interface ToolCallResult {
331
577
  content: string;
332
578
  }
333
579
 
580
+ export declare type TransportMessageHandler = (message: TiledeskMessage) => void;
581
+
582
+ export declare type TransportStateHandler = (connected: boolean) => void;
583
+
334
584
  export declare function unmount(): void;
335
585
 
336
586
  export declare interface WidgetConfig extends ChatClientConfig {
package/dist/index.mjs CHANGED
@@ -1,9 +1,10 @@
1
- import { A as p, a as d, b as g, C as h, c as k, d as C, E as b, M as A } from "./headless-BhsiNVQj.mjs";
1
+ import { A as p, a as d, b as g, C as h, c as k, d as C, E as b, M as A } from "./AikaaraChatClient-C4lWcRsS.mjs";
2
+ import { FormBridge as M, TiledeskTransport as w } from "./headless.mjs";
2
3
  import { registerComponents as n } from "./ui.mjs";
3
- import { AikaaraChatBubble as M, AikaaraChatHeader as w, AikaaraChatInput as y, AikaaraChatWidget as v, AikaaraErrorBanner as E, AikaaraMessageBubble as S, AikaaraMessageList as x, AikaaraStreamingMessage as B, AikaaraTypingIndicator as I } from "./ui.mjs";
4
- function l(a) {
4
+ import { AikaaraChatBubble as v, AikaaraChatHeader as E, AikaaraChatInput as S, AikaaraChatWidget as x, AikaaraErrorBanner as B, AikaaraMessageBubble as T, AikaaraMessageList as I, AikaaraStreamingMessage as U, AikaaraTypingIndicator as j } from "./ui.mjs";
5
+ function l(e) {
5
6
  n();
6
- const e = document.createElement("aikaara-chat-widget"), r = {
7
+ const a = document.createElement("aikaara-chat-widget"), r = {
7
8
  baseUrl: "base-url",
8
9
  userToken: "user-token",
9
10
  apiKey: "api-key",
@@ -19,33 +20,35 @@ function l(a) {
19
20
  avatarUrl: "avatar-url"
20
21
  };
21
22
  for (const [i, o] of Object.entries(r)) {
22
- const t = a[i];
23
- t != null && e.setAttribute(o, String(t));
23
+ const t = e[i];
24
+ t != null && a.setAttribute(o, String(t));
24
25
  }
25
- return e.configure(a), document.body.appendChild(e), e;
26
+ return a.configure(e), document.body.appendChild(a), a;
26
27
  }
27
28
  function c() {
28
- const a = document.querySelector("aikaara-chat-widget");
29
- a && a.remove();
29
+ const e = document.querySelector("aikaara-chat-widget");
30
+ e && e.remove();
30
31
  }
31
32
  export {
32
33
  p as ActionCableClient,
33
- M as AikaaraChatBubble,
34
+ v as AikaaraChatBubble,
34
35
  d as AikaaraChatClient,
35
- w as AikaaraChatHeader,
36
- y as AikaaraChatInput,
37
- v as AikaaraChatWidget,
38
- E as AikaaraErrorBanner,
39
- S as AikaaraMessageBubble,
40
- x as AikaaraMessageList,
41
- B as AikaaraStreamingMessage,
42
- I as AikaaraTypingIndicator,
36
+ E as AikaaraChatHeader,
37
+ S as AikaaraChatInput,
38
+ x as AikaaraChatWidget,
39
+ B as AikaaraErrorBanner,
40
+ T as AikaaraMessageBubble,
41
+ I as AikaaraMessageList,
42
+ U as AikaaraStreamingMessage,
43
+ j as AikaaraTypingIndicator,
43
44
  g as ApiClient,
44
45
  h as ChannelSubscription,
45
46
  k as ConnectionManager,
46
47
  C as ConversationManager,
47
48
  b as EventEmitter,
49
+ M as FormBridge,
48
50
  A as MessageStore,
51
+ w as TiledeskTransport,
49
52
  l as mount,
50
53
  n as registerComponents,
51
54
  c as unmount
package/dist/ui.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("./headless-CrgIWcf7.cjs");class w{client;panel;bubble;header;messageList;input;errorBanner;isOpen=!1;constructor(e,t){this.client=new r.AikaaraChatClient(e),this.bubble=t.querySelector("aikaara-chat-bubble"),this.panel=t.querySelector(".aikaara-panel"),this.header=t.querySelector("aikaara-chat-header"),this.messageList=t.querySelector("aikaara-message-list"),this.input=t.querySelector("aikaara-chat-input"),this.errorBanner=t.querySelector("aikaara-error-banner"),e.welcomeMessage&&this.messageList.setWelcomeMessage(e.welcomeMessage),e.showTimestamps!==void 0&&this.messageList.setShowTimestamps(e.showTimestamps),this.wireEvents()}async connect(){try{await this.client.connect(),this.messageList.renderMessages(this.client.messages)}catch{this.errorBanner.show("Failed to connect. Retrying...",5e3)}}async disconnect(){await this.client.disconnect()}wireEvents(){this.bubble.addEventListener("toggle",()=>{this.togglePanel()}),this.header.addEventListener("header-close",()=>{this.togglePanel(!1)}),this.input.addEventListener("send",(e=>{this.handleSend(e.detail.content)})),this.client.on("message:sent",e=>{this.messageList.addMessage(e)}),this.client.on("stream:start",()=>{this.messageList.removeTypingIndicator();const e=this.client.messages[this.client.messages.length-1];e&&this.messageList.addMessage(e)}),this.client.on("stream:update",({content:e})=>{this.messageList.updateStreamingContent(e)}),this.client.on("stream:end",()=>{this.messageList.finalizeStreaming()}),this.client.on("typing:start",()=>{const e=this.client.messages,t=e[e.length-1];(!t||t.status!=="streaming")&&this.messageList.showTypingIndicator()}),this.client.on("typing:stop",()=>{this.messageList.removeTypingIndicator()}),this.client.on("connection:state",e=>{this.header.setStatus(e),e==="connected"?(this.errorBanner.hide(),this.input.disabled=!1):e==="reconnecting"?(this.errorBanner.show("Connection lost. Reconnecting..."),this.input.disabled=!0):e==="disconnected"&&(this.input.disabled=!0)}),this.client.on("error",e=>{this.errorBanner.show(e.message,5e3)})}async handleSend(e){try{await this.client.sendMessage(e)}catch{this.errorBanner.show("Failed to send message",3e3)}}togglePanel(e){this.isOpen=e!==void 0?e:!this.isOpen,this.isOpen?(this.panel.removeAttribute("hidden"),requestAnimationFrame(()=>{this.panel.classList.remove("entering"),this.panel.classList.add("visible"),this.input.focus()})):(this.panel.classList.remove("visible"),this.panel.classList.add("entering"),setTimeout(()=>{this.panel.setAttribute("hidden","")},200))}}class c extends HTMLElement{shadow;controller=null;_config={};static get observedAttributes(){return["base-url","ws-url","user-token","api-key","title","subtitle","theme","primary-color","position","width","height","placeholder","welcome-message","avatar-url"]}constructor(){super(),this.shadow=this.attachShadow({mode:"open"})}connectedCallback(){this.render(),this.initController()}disconnectedCallback(){this.controller?.disconnect()}attributeChangedCallback(e,t,a){t!==a&&this.controller&&(this.render(),this.initController())}configure(e){this._config={...this._config,...e}}getConfig(){return{baseUrl:this.getAttribute("base-url")||this._config.baseUrl||"",wsUrl:this.getAttribute("ws-url")||this._config.wsUrl,userToken:this.getAttribute("user-token")||this._config.userToken||"",apiKey:this.getAttribute("api-key")||this._config.apiKey,title:this.getAttribute("title")||this._config.title||"Chat",subtitle:this.getAttribute("subtitle")||this._config.subtitle,theme:this.getAttribute("theme")||this._config.theme||r.DEFAULT_THEME,primaryColor:this.getAttribute("primary-color")||this._config.primaryColor||r.DEFAULT_PRIMARY_COLOR,position:this.getAttribute("position")||this._config.position||r.DEFAULT_POSITION,width:Number(this.getAttribute("width"))||this._config.width||r.DEFAULT_WIDGET_WIDTH,height:Number(this.getAttribute("height"))||this._config.height||r.DEFAULT_WIDGET_HEIGHT,fontFamily:this._config.fontFamily||r.DEFAULT_FONT_FAMILY,borderRadius:this._config.borderRadius??r.DEFAULT_BORDER_RADIUS,placeholder:this.getAttribute("placeholder")||this._config.placeholder||r.DEFAULT_PLACEHOLDER,welcomeMessage:this.getAttribute("welcome-message")||this._config.welcomeMessage,avatarUrl:this.getAttribute("avatar-url")||this._config.avatarUrl,showTimestamps:this._config.showTimestamps??!0,persistConversation:this._config.persistConversation??!0,showBubble:this._config.showBubble??!0,offset:this._config.offset||r.DEFAULT_OFFSET,conversationId:this._config.conversationId,systemPromptId:this._config.systemPromptId,channel:this._config.channel,extUid:this._config.extUid,onMessage:this._config.onMessage,onStatusChange:this._config.onStatusChange,onError:this._config.onError,onStreamUpdate:this._config.onStreamUpdate,onConnectionStateChange:this._config.onConnectionStateChange}}render(){const e=this.getConfig();this.shadow.innerHTML=`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("./AikaaraChatClient-ChZ2bL9f.cjs");class w{client;panel;bubble;header;messageList;input;errorBanner;isOpen=!1;constructor(e,t){this.client=new r.AikaaraChatClient(e),this.bubble=t.querySelector("aikaara-chat-bubble"),this.panel=t.querySelector(".aikaara-panel"),this.header=t.querySelector("aikaara-chat-header"),this.messageList=t.querySelector("aikaara-message-list"),this.input=t.querySelector("aikaara-chat-input"),this.errorBanner=t.querySelector("aikaara-error-banner"),e.welcomeMessage&&this.messageList.setWelcomeMessage(e.welcomeMessage),e.showTimestamps!==void 0&&this.messageList.setShowTimestamps(e.showTimestamps),this.wireEvents()}async connect(){try{await this.client.connect(),this.messageList.renderMessages(this.client.messages)}catch{this.errorBanner.show("Failed to connect. Retrying...",5e3)}}async disconnect(){await this.client.disconnect()}wireEvents(){this.bubble.addEventListener("toggle",()=>{this.togglePanel()}),this.header.addEventListener("header-close",()=>{this.togglePanel(!1)}),this.input.addEventListener("send",(e=>{this.handleSend(e.detail.content)})),this.client.on("message:sent",e=>{this.messageList.addMessage(e)}),this.client.on("stream:start",()=>{this.messageList.removeTypingIndicator();const e=this.client.messages[this.client.messages.length-1];e&&this.messageList.addMessage(e)}),this.client.on("stream:update",({content:e})=>{this.messageList.updateStreamingContent(e)}),this.client.on("stream:end",()=>{this.messageList.finalizeStreaming()}),this.client.on("typing:start",()=>{const e=this.client.messages,t=e[e.length-1];(!t||t.status!=="streaming")&&this.messageList.showTypingIndicator()}),this.client.on("typing:stop",()=>{this.messageList.removeTypingIndicator()}),this.client.on("connection:state",e=>{this.header.setStatus(e),e==="connected"?(this.errorBanner.hide(),this.input.disabled=!1):e==="reconnecting"?(this.errorBanner.show("Connection lost. Reconnecting..."),this.input.disabled=!0):e==="disconnected"&&(this.input.disabled=!0)}),this.client.on("error",e=>{this.errorBanner.show(e.message,5e3)})}async handleSend(e){try{await this.client.sendMessage(e)}catch{this.errorBanner.show("Failed to send message",3e3)}}sendUserEvent(e,t,a){this.client.sendUserEvent(e,t,a)}getClient(){return this.client}togglePanel(e){this.isOpen=e!==void 0?e:!this.isOpen,this.isOpen?(this.panel.removeAttribute("hidden"),requestAnimationFrame(()=>{this.panel.classList.remove("entering"),this.panel.classList.add("visible"),this.input.focus()})):(this.panel.classList.remove("visible"),this.panel.classList.add("entering"),setTimeout(()=>{this.panel.setAttribute("hidden","")},200))}}class c extends HTMLElement{shadow;controller=null;_config={};static get observedAttributes(){return["base-url","ws-url","user-token","api-key","title","subtitle","theme","primary-color","position","width","height","placeholder","welcome-message","avatar-url"]}constructor(){super(),this.shadow=this.attachShadow({mode:"open"})}connectedCallback(){this.render(),this.initController()}disconnectedCallback(){this.controller?.disconnect()}attributeChangedCallback(e,t,a){t!==a&&this.controller&&(this.render(),this.initController())}configure(e){this._config={...this._config,...e}}getConfig(){return{baseUrl:this.getAttribute("base-url")||this._config.baseUrl||"",wsUrl:this.getAttribute("ws-url")||this._config.wsUrl,userToken:this.getAttribute("user-token")||this._config.userToken||"",apiKey:this.getAttribute("api-key")||this._config.apiKey,title:this.getAttribute("title")||this._config.title||"Chat",subtitle:this.getAttribute("subtitle")||this._config.subtitle,theme:this.getAttribute("theme")||this._config.theme||r.DEFAULT_THEME,primaryColor:this.getAttribute("primary-color")||this._config.primaryColor||r.DEFAULT_PRIMARY_COLOR,position:this.getAttribute("position")||this._config.position||r.DEFAULT_POSITION,width:Number(this.getAttribute("width"))||this._config.width||r.DEFAULT_WIDGET_WIDTH,height:Number(this.getAttribute("height"))||this._config.height||r.DEFAULT_WIDGET_HEIGHT,fontFamily:this._config.fontFamily||r.DEFAULT_FONT_FAMILY,borderRadius:this._config.borderRadius??r.DEFAULT_BORDER_RADIUS,placeholder:this.getAttribute("placeholder")||this._config.placeholder||r.DEFAULT_PLACEHOLDER,welcomeMessage:this.getAttribute("welcome-message")||this._config.welcomeMessage,avatarUrl:this.getAttribute("avatar-url")||this._config.avatarUrl,showTimestamps:this._config.showTimestamps??!0,persistConversation:this._config.persistConversation??!0,showBubble:this._config.showBubble??!0,offset:this._config.offset||r.DEFAULT_OFFSET,conversationId:this._config.conversationId,systemPromptId:this._config.systemPromptId,channel:this._config.channel,extUid:this._config.extUid,onMessage:this._config.onMessage,onStatusChange:this._config.onStatusChange,onError:this._config.onError,onStreamUpdate:this._config.onStreamUpdate,onConnectionStateChange:this._config.onConnectionStateChange}}render(){const e=this.getConfig();this.shadow.innerHTML=`
2
2
  <style>
3
3
  :host {
4
4
  --aikaara-primary: ${e.primaryColor};
@@ -87,7 +87,7 @@
87
87
  <aikaara-chat-input placeholder="${e.placeholder||r.DEFAULT_PLACEHOLDER}"></aikaara-chat-input>
88
88
  <aikaara-error-banner></aikaara-error-banner>
89
89
  </div>
90
- `}async initController(){const e=this.getConfig();!e.baseUrl||!e.userToken||(this.controller?.disconnect(),this.controller=new w(e,this.shadow),await this.controller.connect())}darkenColor(e){try{const t=parseInt(e.replace("#",""),16),a=Math.max(0,(t>>16)-20),s=Math.max(0,(t>>8&255)-20),o=Math.max(0,(t&255)-20);return`#${(a<<16|s<<8|o).toString(16).padStart(6,"0")}`}catch{return e}}}class h extends HTMLElement{shadow;constructor(){super(),this.shadow=this.attachShadow({mode:"open"})}connectedCallback(){this.render(),this.shadow.querySelector(".bubble")?.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("toggle",{bubbles:!0,composed:!0}))})}render(){this.shadow.innerHTML=`
90
+ `}async initController(){const e=this.getConfig();!e.baseUrl||!e.userToken||(this.controller?.disconnect(),this.controller=new w(e,this.shadow),await this.controller.connect())}sendUserEvent(e,t,a){this.controller?.sendUserEvent(e,t,a)}getClient(){return this.controller?.getClient()??null}darkenColor(e){try{const t=parseInt(e.replace("#",""),16),a=Math.max(0,(t>>16)-20),s=Math.max(0,(t>>8&255)-20),o=Math.max(0,(t&255)-20);return`#${(a<<16|s<<8|o).toString(16).padStart(6,"0")}`}catch{return e}}}class h extends HTMLElement{shadow;constructor(){super(),this.shadow=this.attachShadow({mode:"open"})}connectedCallback(){this.render(),this.shadow.querySelector(".bubble")?.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("toggle",{bubbles:!0,composed:!0}))})}render(){this.shadow.innerHTML=`
91
91
  <style>
92
92
  .bubble {
93
93
  width: var(--aikaara-bubble-size, 60px);
@@ -216,7 +216,7 @@
216
216
  </svg>
217
217
  </button>
218
218
  </div>
219
- `}setStatus(e){this.setAttribute("status",e)}}function l(i){let e=T(i);return e=e.replace(/```(\w*)\n([\s\S]*?)```/g,(t,a,s)=>`<pre><code>${s.trim()}</code></pre>`),e=e.replace(/`([^`]+)`/g,"<code>$1</code>"),e=e.replace(/\*\*(.+?)\*\*/g,"<strong>$1</strong>"),e=e.replace(/\*(.+?)\*/g,"<em>$1</em>"),e=e.replace(/\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)/g,'<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'),e=e.replace(/\n/g,"<br>"),e}function T(i){const e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#039;"};return i.replace(/[&<>"']/g,t=>e[t])}const C=new Set(["p","br","strong","em","code","pre","a","ul","ol","li","blockquote","h1","h2","h3","h4","h5","h6","span","div"]),L={a:new Set(["href","target","rel"]),code:new Set(["class"]),pre:new Set(["class"]),span:new Set(["class"]),div:new Set(["class"])};function d(i){const e=document.createElement("template");return e.innerHTML=i,p(e.content),e.innerHTML}function p(i){const e=Array.from(i.childNodes);for(const t of e)if(t.nodeType===Node.ELEMENT_NODE){const a=t,s=a.tagName.toLowerCase();if(!C.has(s)){const n=document.createTextNode(a.textContent||"");i.replaceChild(n,t);continue}const o=L[s]||new Set,v=Array.from(a.attributes);for(const n of v)o.has(n.name)||a.removeAttribute(n.name);if(a.hasAttribute("href")){const n=a.getAttribute("href")||"";!n.startsWith("http://")&&!n.startsWith("https://")&&!n.startsWith("/")&&a.removeAttribute("href")}p(t)}}class u extends HTMLElement{shadow;container;welcomeMessage="";showTimestamps=!0;constructor(){super(),this.shadow=this.attachShadow({mode:"open"})}connectedCallback(){this.shadow.innerHTML=`
219
+ `}setStatus(e){this.setAttribute("status",e)}}function l(i){let e=C(i);return e=e.replace(/```(\w*)\n([\s\S]*?)```/g,(t,a,s)=>`<pre><code>${s.trim()}</code></pre>`),e=e.replace(/`([^`]+)`/g,"<code>$1</code>"),e=e.replace(/\*\*(.+?)\*\*/g,"<strong>$1</strong>"),e=e.replace(/\*(.+?)\*/g,"<em>$1</em>"),e=e.replace(/\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)/g,'<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'),e=e.replace(/\n/g,"<br>"),e}function C(i){const e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#039;"};return i.replace(/[&<>"']/g,t=>e[t])}const T=new Set(["p","br","strong","em","code","pre","a","ul","ol","li","blockquote","h1","h2","h3","h4","h5","h6","span","div"]),L={a:new Set(["href","target","rel"]),code:new Set(["class"]),pre:new Set(["class"]),span:new Set(["class"]),div:new Set(["class"])};function d(i){const e=document.createElement("template");return e.innerHTML=i,p(e.content),e.innerHTML}function p(i){const e=Array.from(i.childNodes);for(const t of e)if(t.nodeType===Node.ELEMENT_NODE){const a=t,s=a.tagName.toLowerCase();if(!T.has(s)){const n=document.createTextNode(a.textContent||"");i.replaceChild(n,t);continue}const o=L[s]||new Set,v=Array.from(a.attributes);for(const n of v)o.has(n.name)||a.removeAttribute(n.name);if(a.hasAttribute("href")){const n=a.getAttribute("href")||"";!n.startsWith("http://")&&!n.startsWith("https://")&&!n.startsWith("/")&&a.removeAttribute("href")}p(t)}}class u extends HTMLElement{shadow;container;welcomeMessage="";showTimestamps=!0;constructor(){super(),this.shadow=this.attachShadow({mode:"open"})}connectedCallback(){this.shadow.innerHTML=`
220
220
  <style>
221
221
  :host {
222
222
  display: flex;