@aikaara/chat-sdk 0.1.3 → 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-DDmLD-ag.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,11 +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;
289
+ wsUrl?: string;
229
290
  userToken: string;
291
+ tiledesk?: TiledeskTransportConfig;
230
292
  reconnect?: boolean;
231
293
  maxReconnectAttempts?: number;
232
294
  reconnectInterval?: number;
@@ -269,6 +331,13 @@ declare interface CreateConversationResponse {
269
331
  status: string;
270
332
  }
271
333
 
334
+ export declare interface EditEntityAction {
335
+ action: 'edit_entity';
336
+ entity_type: string;
337
+ entity_id: string | number;
338
+ fields: FieldUpdate[];
339
+ }
340
+
272
341
  export declare class EventEmitter<Events extends Record<string, any>> {
273
342
  private handlers;
274
343
  on<K extends keyof Events & string>(event: K, handler: (data: Events[K]) => void): () => void;
@@ -277,6 +346,128 @@ export declare class EventEmitter<Events extends Record<string, any>> {
277
346
  removeAllListeners(): void;
278
347
  }
279
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
+
280
471
  export declare interface Message {
281
472
  id: string;
282
473
  conversationId: string;
@@ -299,6 +490,8 @@ export declare class MessageStore {
299
490
  confirmOptimistic(tempId: string): void;
300
491
  addStreamingMessage(conversationId: string): Message;
301
492
  updateStreaming(content: string): void;
493
+ appendToStreaming(delta: string): void;
494
+ get streamingContent(): string;
302
495
  finalizeStreaming(usage?: {
303
496
  tokensInput: number;
304
497
  tokensOutput: number;
@@ -310,10 +503,66 @@ export declare class MessageStore {
310
503
 
311
504
  export declare function mount(config: WidgetConfig): AikaaraChatWidget;
312
505
 
506
+ export declare interface NavigateAction {
507
+ navigate_to: string;
508
+ }
509
+
313
510
  export declare function registerComponents(): void;
314
511
 
512
+ export declare interface SaveEntityAction {
513
+ action: 'save_entity';
514
+ }
515
+
315
516
  declare type SubscriptionCallback = (data: unknown) => void;
316
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
+
317
566
  export declare interface ToolCall {
318
567
  id: string;
319
568
  type: 'function';
@@ -328,6 +577,10 @@ export declare interface ToolCallResult {
328
577
  content: string;
329
578
  }
330
579
 
580
+ export declare type TransportMessageHandler = (message: TiledeskMessage) => void;
581
+
582
+ export declare type TransportStateHandler = (connected: boolean) => void;
583
+
331
584
  export declare function unmount(): void;
332
585
 
333
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-CXRux2Q-.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,8 +1,8 @@
1
- "use strict";var T=Object.defineProperty;var C=(s,t,e)=>t in s?T(s,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[t]=e;var i=(s,t,e)=>C(s,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./headless-DDmLD-ag.cjs");class L{constructor(t,e){i(this,"client");i(this,"panel");i(this,"bubble");i(this,"header");i(this,"messageList");i(this,"input");i(this,"errorBanner");i(this,"isOpen",!1);this.client=new o.AikaaraChatClient(t),this.bubble=e.querySelector("aikaara-chat-bubble"),this.panel=e.querySelector(".aikaara-panel"),this.header=e.querySelector("aikaara-chat-header"),this.messageList=e.querySelector("aikaara-message-list"),this.input=e.querySelector("aikaara-chat-input"),this.errorBanner=e.querySelector("aikaara-error-banner"),t.welcomeMessage&&this.messageList.setWelcomeMessage(t.welcomeMessage),t.showTimestamps!==void 0&&this.messageList.setShowTimestamps(t.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",(t=>{this.handleSend(t.detail.content)})),this.client.on("message:sent",t=>{this.messageList.addMessage(t)}),this.client.on("stream:start",()=>{this.messageList.removeTypingIndicator();const t=this.client.messages[this.client.messages.length-1];t&&this.messageList.addMessage(t)}),this.client.on("stream:update",({content:t})=>{this.messageList.updateStreamingContent(t)}),this.client.on("stream:end",()=>{this.messageList.finalizeStreaming()}),this.client.on("typing:start",()=>{const t=this.client.messages,e=t[t.length-1];(!e||e.status!=="streaming")&&this.messageList.showTypingIndicator()}),this.client.on("typing:stop",()=>{this.messageList.removeTypingIndicator()}),this.client.on("connection:state",t=>{this.header.setStatus(t),t==="connected"?(this.errorBanner.hide(),this.input.disabled=!1):t==="reconnecting"?(this.errorBanner.show("Connection lost. Reconnecting..."),this.input.disabled=!0):t==="disconnected"&&(this.input.disabled=!0)}),this.client.on("error",t=>{this.errorBanner.show(t.message,5e3)})}async handleSend(t){try{await this.client.sendMessage(t)}catch{this.errorBanner.show("Failed to send message",3e3)}}togglePanel(t){this.isOpen=t!==void 0?t:!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 b extends HTMLElement{constructor(){super();i(this,"shadow");i(this,"controller",null);i(this,"_config",{});this.shadow=this.attachShadow({mode:"open"})}static get observedAttributes(){return["base-url","user-token","api-key","title","subtitle","theme","primary-color","position","width","height","placeholder","welcome-message","avatar-url"]}connectedCallback(){this.render(),this.initController()}disconnectedCallback(){var e;(e=this.controller)==null||e.disconnect()}attributeChangedCallback(e,a,r){a!==r&&this.controller&&(this.render(),this.initController())}configure(e){this._config={...this._config,...e}}getConfig(){return{baseUrl:this.getAttribute("base-url")||this._config.baseUrl||"",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||o.DEFAULT_THEME,primaryColor:this.getAttribute("primary-color")||this._config.primaryColor||o.DEFAULT_PRIMARY_COLOR,position:this.getAttribute("position")||this._config.position||o.DEFAULT_POSITION,width:Number(this.getAttribute("width"))||this._config.width||o.DEFAULT_WIDGET_WIDTH,height:Number(this.getAttribute("height"))||this._config.height||o.DEFAULT_WIDGET_HEIGHT,fontFamily:this._config.fontFamily||o.DEFAULT_FONT_FAMILY,borderRadius:this._config.borderRadius??o.DEFAULT_BORDER_RADIUS,placeholder:this.getAttribute("placeholder")||this._config.placeholder||o.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||o.DEFAULT_OFFSET,conversationId:this._config.conversationId,systemPromptId:this._config.systemPromptId,channel:this._config.channel,onMessage:this._config.onMessage,onStatusChange:this._config.onStatusChange,onError:this._config.onError,onStreamUpdate:this._config.onStreamUpdate,onConnectionStateChange:this._config.onConnectionStateChange}}render(){var a,r;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};
5
- --aikaara-primary-hover: ${this.darkenColor(e.primaryColor||o.DEFAULT_PRIMARY_COLOR)};
5
+ --aikaara-primary-hover: ${this.darkenColor(e.primaryColor||r.DEFAULT_PRIMARY_COLOR)};
6
6
  --aikaara-bg: #ffffff;
7
7
  --aikaara-bg-secondary: #f9fafb;
8
8
  --aikaara-text: #1f2937;
@@ -13,8 +13,8 @@
13
13
  --aikaara-panel-width: ${e.width}px;
14
14
  --aikaara-panel-height: ${e.height}px;
15
15
  --aikaara-bubble-size: 60px;
16
- --aikaara-offset-x: ${((a=e.offset)==null?void 0:a.x)??20}px;
17
- --aikaara-offset-y: ${((r=e.offset)==null?void 0:r.y)??20}px;
16
+ --aikaara-offset-x: ${e.offset?.x??20}px;
17
+ --aikaara-offset-y: ${e.offset?.y??20}px;
18
18
  font-family: var(--aikaara-font);
19
19
  position: fixed;
20
20
  z-index: 9999;
@@ -52,6 +52,27 @@
52
52
  opacity: 1;
53
53
  transform: translateY(0) scale(1);
54
54
  }
55
+
56
+ aikaara-chat-header,
57
+ aikaara-message-list,
58
+ aikaara-chat-input,
59
+ aikaara-error-banner {
60
+ display: block;
61
+ }
62
+
63
+ aikaara-message-list {
64
+ flex: 1;
65
+ overflow: scroll;
66
+ min-height: 0;
67
+ }
68
+
69
+ aikaara-chat-input {
70
+ flex-shrink: 0;
71
+ }
72
+
73
+ aikaara-chat-header {
74
+ flex-shrink: 0;
75
+ }
55
76
  </style>
56
77
 
57
78
  <aikaara-chat-bubble></aikaara-chat-bubble>
@@ -63,10 +84,10 @@
63
84
  ${e.avatarUrl?`avatar-url="${e.avatarUrl}"`:""}
64
85
  ></aikaara-chat-header>
65
86
  <aikaara-message-list></aikaara-message-list>
66
- <aikaara-chat-input placeholder="${e.placeholder||o.DEFAULT_PLACEHOLDER}"></aikaara-chat-input>
87
+ <aikaara-chat-input placeholder="${e.placeholder||r.DEFAULT_PLACEHOLDER}"></aikaara-chat-input>
67
88
  <aikaara-error-banner></aikaara-error-banner>
68
89
  </div>
69
- `}async initController(){var a;const e=this.getConfig();!e.baseUrl||!e.userToken||((a=this.controller)==null||a.disconnect(),this.controller=new L(e,this.shadow),await this.controller.connect())}darkenColor(e){try{const a=parseInt(e.replace("#",""),16),r=Math.max(0,(a>>16)-20),n=Math.max(0,(a>>8&255)-20),d=Math.max(0,(a&255)-20);return`#${(r<<16|n<<8|d).toString(16).padStart(6,"0")}`}catch{return e}}}class p extends HTMLElement{constructor(){super();i(this,"shadow");this.shadow=this.attachShadow({mode:"open"})}connectedCallback(){var e;this.render(),(e=this.shadow.querySelector(".bubble"))==null||e.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=`
70
91
  <style>
71
92
  .bubble {
72
93
  width: var(--aikaara-bubble-size, 60px);
@@ -101,7 +122,7 @@
101
122
  <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>
102
123
  </svg>
103
124
  </button>
104
- `}setIcon(e){const a=this.shadow.querySelector(".bubble");a&&(a.innerHTML=e)}}class u extends HTMLElement{constructor(){super();i(this,"shadow");this.shadow=this.attachShadow({mode:"open"})}static get observedAttributes(){return["title","subtitle","avatar-url","status"]}connectedCallback(){this.render(),this.bindClose()}attributeChangedCallback(){this.render(),this.bindClose()}bindClose(){var e;(e=this.shadow.querySelector(".close-btn"))==null||e.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("header-close",{bubbles:!0,composed:!0}))})}render(){const e=this.getAttribute("title")||"Chat",a=this.getAttribute("subtitle")||"",r=this.getAttribute("avatar-url"),n=this.getAttribute("status")||"connected",d=n==="connected"?"#10b981":n==="connecting"||n==="reconnecting"?"#f59e0b":"#ef4444";this.shadow.innerHTML=`
125
+ `}setIcon(e){const t=this.shadow.querySelector(".bubble");t&&(t.innerHTML=e)}}class b extends HTMLElement{shadow;static get observedAttributes(){return["title","subtitle","avatar-url","status"]}constructor(){super(),this.shadow=this.attachShadow({mode:"open"})}connectedCallback(){this.render(),this.bindClose()}attributeChangedCallback(){this.render(),this.bindClose()}bindClose(){this.shadow.querySelector(".close-btn")?.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("header-close",{bubbles:!0,composed:!0}))})}render(){const e=this.getAttribute("title")||"Chat",t=this.getAttribute("subtitle")||"",a=this.getAttribute("avatar-url"),s=this.getAttribute("status")||"connected",o=s==="connected"?"#10b981":s==="connecting"||s==="reconnecting"?"#f59e0b":"#ef4444";this.shadow.innerHTML=`
105
126
  <style>
106
127
  .header {
107
128
  display: flex;
@@ -180,14 +201,14 @@
180
201
  </style>
181
202
  <div class="header">
182
203
  <div class="avatar">
183
- ${r?`<img src="${r}" alt="Avatar" />`:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>'}
204
+ ${a?`<img src="${a}" alt="Avatar" />`:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>'}
184
205
  </div>
185
206
  <div class="info">
186
207
  <div class="title">
187
208
  ${e}
188
- <span class="status-dot" style="background:${d}"></span>
209
+ <span class="status-dot" style="background:${o}"></span>
189
210
  </div>
190
- ${a?`<div class="subtitle">${a}</div>`:""}
211
+ ${t?`<div class="subtitle">${t}</div>`:""}
191
212
  </div>
192
213
  <button class="close-btn" aria-label="Close chat">
193
214
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
@@ -195,8 +216,13 @@
195
216
  </svg>
196
217
  </button>
197
218
  </div>
198
- `}setStatus(e){this.setAttribute("status",e)}}function c(s){let t=A(s);return t=t.replace(/```(\w*)\n([\s\S]*?)```/g,(e,a,r)=>`<pre><code>${r.trim()}</code></pre>`),t=t.replace(/`([^`]+)`/g,"<code>$1</code>"),t=t.replace(/\*\*(.+?)\*\*/g,"<strong>$1</strong>"),t=t.replace(/\*(.+?)\*/g,"<em>$1</em>"),t=t.replace(/\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)/g,'<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'),t=t.replace(/\n/g,"<br>"),t}function A(s){const t={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#039;"};return s.replace(/[&<>"']/g,e=>t[e])}const E=new Set(["p","br","strong","em","code","pre","a","ul","ol","li","blockquote","h1","h2","h3","h4","h5","h6","span","div"]),S={a:new Set(["href","target","rel"]),code:new Set(["class"]),pre:new Set(["class"]),span:new Set(["class"]),div:new Set(["class"])};function h(s){const t=document.createElement("template");return t.innerHTML=s,g(t.content),t.innerHTML}function g(s){const t=Array.from(s.childNodes);for(const e of t)if(e.nodeType===Node.ELEMENT_NODE){const a=e,r=a.tagName.toLowerCase();if(!E.has(r)){const l=document.createTextNode(a.textContent||"");s.replaceChild(l,e);continue}const n=S[r]||new Set,d=Array.from(a.attributes);for(const l of d)n.has(l.name)||a.removeAttribute(l.name);if(a.hasAttribute("href")){const l=a.getAttribute("href")||"";!l.startsWith("http://")&&!l.startsWith("https://")&&!l.startsWith("/")&&a.removeAttribute("href")}g(e)}}class m extends HTMLElement{constructor(){super();i(this,"shadow");i(this,"container");i(this,"welcomeMessage","");i(this,"showTimestamps",!0);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=`
199
220
  <style>
221
+ :host {
222
+ display: flex;
223
+ flex-direction: column;
224
+ min-height: 0;
225
+ }
200
226
  .message-list {
201
227
  flex: 1;
202
228
  overflow-y: auto;
@@ -298,7 +324,7 @@
298
324
  }
299
325
  </style>
300
326
  <div class="message-list"></div>
301
- `,this.container=this.shadow.querySelector(".message-list")}setWelcomeMessage(e){this.welcomeMessage=e}setShowTimestamps(e){this.showTimestamps=e}renderMessages(e){if(this.container){if(this.container.innerHTML="",e.length===0&&this.welcomeMessage){this.container.innerHTML=`<div class="welcome">${h(c(this.welcomeMessage))}</div>`;return}for(const a of e)this.appendMessageElement(a);this.scrollToBottom()}}addMessage(e){const a=this.container.querySelector(".welcome");a&&a.remove(),this.appendMessageElement(e),this.scrollToBottom()}updateStreamingContent(e){const a=this.container.querySelector('[data-streaming="true"] .bubble');a&&(a.innerHTML=h(c(e)),a.classList.add("streaming-cursor"),this.scrollToBottom())}finalizeStreaming(){const e=this.container.querySelector('[data-streaming="true"]');if(e){e.removeAttribute("data-streaming");const a=e.querySelector(".bubble");a==null||a.classList.remove("streaming-cursor")}}showTypingIndicator(){this.removeTypingIndicator();const e=document.createElement("div");e.classList.add("typing-indicator"),e.setAttribute("data-typing","true"),e.innerHTML='<span class="dot"></span><span class="dot"></span><span class="dot"></span>',this.container.appendChild(e),this.scrollToBottom()}removeTypingIndicator(){var e;(e=this.container.querySelector('[data-typing="true"]'))==null||e.remove()}appendMessageElement(e){const a=document.createElement("div");a.classList.add("message-wrap",e.role),e.status==="streaming"&&a.setAttribute("data-streaming","true");const r=document.createElement("div");if(r.classList.add("bubble",e.role),e.role==="user"?r.textContent=e.content:(r.innerHTML=h(c(e.content||"")),e.status==="streaming"&&r.classList.add("streaming-cursor")),a.appendChild(r),this.showTimestamps&&e.createdAt){const n=document.createElement("div");n.classList.add("timestamp"),n.textContent=this.formatTime(e.createdAt),a.appendChild(n)}this.container.appendChild(a)}scrollToBottom(){requestAnimationFrame(()=>{this.container.scrollTop=this.container.scrollHeight})}formatTime(e){try{return new Date(e).toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit"})}catch{return""}}}class f extends HTMLElement{constructor(){super();i(this,"shadow");this.shadow=this.attachShadow({mode:"open"})}static get observedAttributes(){return["role","content","timestamp"]}connectedCallback(){this.render()}attributeChangedCallback(){this.render()}render(){const e=this.getAttribute("role")||"user",a=this.getAttribute("content")||"",r=this.getAttribute("timestamp")||"",n=e==="user"?document.createTextNode(a).textContent||"":h(c(a));this.shadow.innerHTML=`
327
+ `,this.container=this.shadow.querySelector(".message-list"),this.welcomeMessage&&this.renderMessages([])}setWelcomeMessage(e){this.welcomeMessage=e}setShowTimestamps(e){this.showTimestamps=e}renderMessages(e){if(this.container){if(this.container.innerHTML="",e.length===0&&this.welcomeMessage){this.container.innerHTML=`<div class="welcome">${d(l(this.welcomeMessage))}</div>`;return}for(const t of e)this.appendMessageElement(t);this.scrollToBottom()}}addMessage(e){const t=this.container.querySelector(".welcome");t&&t.remove(),this.appendMessageElement(e),this.scrollToBottom()}updateStreamingContent(e){const t=this.container.querySelector('[data-streaming="true"] .bubble');t&&(t.innerHTML=d(l(e)),t.classList.add("streaming-cursor"),this.scrollToBottom())}finalizeStreaming(){const e=this.container.querySelector('[data-streaming="true"]');e&&(e.removeAttribute("data-streaming"),e.querySelector(".bubble")?.classList.remove("streaming-cursor"))}showTypingIndicator(){this.removeTypingIndicator();const e=document.createElement("div");e.classList.add("typing-indicator"),e.setAttribute("data-typing","true"),e.innerHTML='<span class="dot"></span><span class="dot"></span><span class="dot"></span>',this.container.appendChild(e),this.scrollToBottom()}removeTypingIndicator(){this.container.querySelector('[data-typing="true"]')?.remove()}appendMessageElement(e){const t=document.createElement("div");t.classList.add("message-wrap",e.role),e.status==="streaming"&&t.setAttribute("data-streaming","true");const a=document.createElement("div");if(a.classList.add("bubble",e.role),e.role==="user"?a.textContent=e.content:(a.innerHTML=d(l(e.content||"")),e.status==="streaming"&&a.classList.add("streaming-cursor")),t.appendChild(a),this.showTimestamps&&e.createdAt){const s=document.createElement("div");s.classList.add("timestamp"),s.textContent=this.formatTime(e.createdAt),t.appendChild(s)}this.container.appendChild(t)}scrollToBottom(){requestAnimationFrame(()=>{this.container.scrollTop=this.container.scrollHeight})}formatTime(e){try{return new Date(e).toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit"})}catch{return""}}}class g extends HTMLElement{shadow;static get observedAttributes(){return["role","content","timestamp"]}constructor(){super(),this.shadow=this.attachShadow({mode:"open"})}connectedCallback(){this.render()}attributeChangedCallback(){this.render()}render(){const e=this.getAttribute("role")||"user",t=this.getAttribute("content")||"",a=this.getAttribute("timestamp")||"",s=e==="user"?document.createTextNode(t).textContent||"":d(l(t));this.shadow.innerHTML=`
302
328
  <style>
303
329
  :host { display: flex; flex-direction: column; }
304
330
  :host([role="user"]) { align-items: flex-end; }
@@ -328,9 +354,9 @@
328
354
  padding: 0 4px;
329
355
  }
330
356
  </style>
331
- <div class="bubble ${e}">${n}</div>
332
- ${r?`<div class="timestamp">${r}</div>`:""}
333
- `}}class x extends HTMLElement{constructor(){super();i(this,"shadow");i(this,"textarea");i(this,"sendBtn");i(this,"_disabled",!1);this.shadow=this.attachShadow({mode:"open"})}connectedCallback(){const e=this.getAttribute("placeholder")||"Type a message...";this.shadow.innerHTML=`
357
+ <div class="bubble ${e}">${s}</div>
358
+ ${a?`<div class="timestamp">${a}</div>`:""}
359
+ `}}class m extends HTMLElement{shadow;textarea;sendBtn;_disabled=!1;constructor(){super(),this.shadow=this.attachShadow({mode:"open"})}connectedCallback(){const e=this.getAttribute("placeholder")||"Type a message...";this.shadow.innerHTML=`
334
360
  <style>
335
361
  .input-container {
336
362
  display: flex;
@@ -388,7 +414,7 @@
388
414
  </svg>
389
415
  </button>
390
416
  </div>
391
- `,this.textarea=this.shadow.querySelector("textarea"),this.sendBtn=this.shadow.querySelector(".send-btn"),this.textarea.addEventListener("input",()=>{this.autoGrow(),this.sendBtn.disabled=this._disabled||!this.textarea.value.trim()}),this.textarea.addEventListener("keydown",a=>{a.key==="Enter"&&!a.shiftKey&&(a.preventDefault(),this.handleSend())}),this.sendBtn.addEventListener("click",()=>this.handleSend())}set disabled(e){var a;this._disabled=e,this.textarea&&(this.textarea.disabled=e),this.sendBtn&&(this.sendBtn.disabled=e||!((a=this.textarea)!=null&&a.value.trim()))}get disabled(){return this._disabled}focus(){var e;(e=this.textarea)==null||e.focus()}clear(){this.textarea&&(this.textarea.value="",this.textarea.style.height="auto",this.sendBtn.disabled=!0)}handleSend(){const e=this.textarea.value.trim();!e||this._disabled||(this.dispatchEvent(new CustomEvent("send",{detail:{content:e},bubbles:!0,composed:!0})),this.clear(),this.textarea.focus())}autoGrow(){this.textarea.style.height="auto",this.textarea.style.height=Math.min(this.textarea.scrollHeight,120)+"px"}}class k extends HTMLElement{constructor(){super();i(this,"shadow");this.shadow=this.attachShadow({mode:"open"})}connectedCallback(){this.shadow.innerHTML=`
417
+ `,this.textarea=this.shadow.querySelector("textarea"),this.sendBtn=this.shadow.querySelector(".send-btn"),this.textarea.addEventListener("input",()=>{this.autoGrow(),this.sendBtn.disabled=this._disabled||!this.textarea.value.trim()}),this.textarea.addEventListener("keydown",t=>{t.key==="Enter"&&!t.shiftKey&&(t.preventDefault(),this.handleSend())}),this.sendBtn.addEventListener("click",()=>this.handleSend())}set disabled(e){this._disabled=e,this.textarea&&(this.textarea.disabled=e),this.sendBtn&&(this.sendBtn.disabled=e||!this.textarea?.value.trim())}get disabled(){return this._disabled}focus(){this.textarea?.focus()}clear(){this.textarea&&(this.textarea.value="",this.textarea.style.height="auto",this.sendBtn.disabled=!0)}handleSend(){const e=this.textarea.value.trim();!e||this._disabled||(this.dispatchEvent(new CustomEvent("send",{detail:{content:e},bubbles:!0,composed:!0})),this.clear(),this.textarea.focus())}autoGrow(){this.textarea.style.height="auto",this.textarea.style.height=Math.min(this.textarea.scrollHeight,120)+"px"}}class f extends HTMLElement{shadow;constructor(){super(),this.shadow=this.attachShadow({mode:"open"})}connectedCallback(){this.shadow.innerHTML=`
392
418
  <style>
393
419
  :host { display: none; }
394
420
  :host([visible]) { display: block; }
@@ -422,7 +448,7 @@
422
448
  <span class="dot"></span>
423
449
  <span class="dot"></span>
424
450
  </div>
425
- `}show(){this.setAttribute("visible","")}hide(){this.removeAttribute("visible")}}class y extends HTMLElement{constructor(){super();i(this,"shadow");i(this,"bubble");this.shadow=this.attachShadow({mode:"open"})}connectedCallback(){this.shadow.innerHTML=`
451
+ `}show(){this.setAttribute("visible","")}hide(){this.removeAttribute("visible")}}class x extends HTMLElement{shadow;bubble;constructor(){super(),this.shadow=this.attachShadow({mode:"open"})}connectedCallback(){this.shadow.innerHTML=`
426
452
  <style>
427
453
  :host {
428
454
  display: flex;
@@ -471,7 +497,7 @@
471
497
  }
472
498
  </style>
473
499
  <div class="bubble cursor"></div>
474
- `,this.bubble=this.shadow.querySelector(".bubble")}updateContent(e){this.bubble&&(this.bubble.innerHTML=h(c(e)),this.bubble.classList.add("cursor"))}finalize(){var e;(e=this.bubble)==null||e.classList.remove("cursor")}}class v extends HTMLElement{constructor(){super();i(this,"shadow");i(this,"container");i(this,"dismissTimer",null);this.shadow=this.attachShadow({mode:"open"})}connectedCallback(){var e;this.shadow.innerHTML=`
500
+ `,this.bubble=this.shadow.querySelector(".bubble")}updateContent(e){this.bubble&&(this.bubble.innerHTML=d(l(e)),this.bubble.classList.add("cursor"))}finalize(){this.bubble?.classList.remove("cursor")}}class k extends HTMLElement{shadow;container;dismissTimer=null;constructor(){super(),this.shadow=this.attachShadow({mode:"open"})}connectedCallback(){this.shadow.innerHTML=`
475
501
  <style>
476
502
  .banner {
477
503
  display: none;
@@ -499,4 +525,4 @@
499
525
  <span class="message"></span>
500
526
  <button class="dismiss">Dismiss</button>
501
527
  </div>
502
- `,this.container=this.shadow.querySelector(".banner"),(e=this.shadow.querySelector(".dismiss"))==null||e.addEventListener("click",()=>this.hide())}show(e,a){const r=this.container.querySelector(".message");r&&(r.textContent=e),this.container.classList.add("visible"),this.dismissTimer&&clearTimeout(this.dismissTimer),a&&(this.dismissTimer=setTimeout(()=>this.hide(),a))}hide(){this.container.classList.remove("visible"),this.dismissTimer&&(clearTimeout(this.dismissTimer),this.dismissTimer=null)}}function w(){const s=[["aikaara-chat-widget",b],["aikaara-chat-bubble",p],["aikaara-chat-header",u],["aikaara-message-list",m],["aikaara-message-bubble",f],["aikaara-chat-input",x],["aikaara-typing-indicator",k],["aikaara-streaming-message",y],["aikaara-error-banner",v]];for(const[t,e]of s)customElements.get(t)||customElements.define(t,e)}w();exports.AikaaraChatBubble=p;exports.AikaaraChatHeader=u;exports.AikaaraChatInput=x;exports.AikaaraChatWidget=b;exports.AikaaraErrorBanner=v;exports.AikaaraMessageBubble=f;exports.AikaaraMessageList=m;exports.AikaaraStreamingMessage=y;exports.AikaaraTypingIndicator=k;exports.registerComponents=w;
528
+ `,this.container=this.shadow.querySelector(".banner"),this.shadow.querySelector(".dismiss")?.addEventListener("click",()=>this.hide())}show(e,t){const a=this.container.querySelector(".message");a&&(a.textContent=e),this.container.classList.add("visible"),this.dismissTimer&&clearTimeout(this.dismissTimer),t&&(this.dismissTimer=setTimeout(()=>this.hide(),t))}hide(){this.container.classList.remove("visible"),this.dismissTimer&&(clearTimeout(this.dismissTimer),this.dismissTimer=null)}}function y(){const i=[["aikaara-chat-widget",c],["aikaara-chat-bubble",h],["aikaara-chat-header",b],["aikaara-message-list",u],["aikaara-message-bubble",g],["aikaara-chat-input",m],["aikaara-typing-indicator",f],["aikaara-streaming-message",x],["aikaara-error-banner",k]];for(const[e,t]of i)customElements.get(e)||customElements.define(e,t)}y();exports.AikaaraChatBubble=h;exports.AikaaraChatHeader=b;exports.AikaaraChatInput=m;exports.AikaaraChatWidget=c;exports.AikaaraErrorBanner=k;exports.AikaaraMessageBubble=g;exports.AikaaraMessageList=u;exports.AikaaraStreamingMessage=x;exports.AikaaraTypingIndicator=f;exports.registerComponents=y;