@aikaara/chat-sdk 0.6.0 → 0.7.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/headless.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./MountTenant-HkluWr4X.cjs");class s extends i.EventEmitter{registration=null;pendingEdits=[];constructor(e){super(),this.setupListeners(e)}registerForm(e){this.registration=e;const t=this.pendingEdits.filter(r=>r.entity_type===e.entityType&&String(r.entity_id)===String(e.entityId));if(t.length>0){for(const r of t)e.onFieldUpdate(r.fields),this.emit("edit:applied",{entityType:r.entity_type,entityId:r.entity_id,fields:r.fields});this.pendingEdits=this.pendingEdits.filter(r=>!(r.entity_type===e.entityType&&String(r.entity_id)===String(e.entityId)))}}unregisterForm(e,t){this.registration?.entityType===e&&String(this.registration?.entityId)===String(t)&&(this.registration=null)}get currentForm(){return this.registration}pushFieldUpdates(e,t,r){this.registration&&this.registration.entityType===e&&String(this.registration.entityId)===String(t)?(this.registration.onFieldUpdate(r),this.emit("edit:applied",{entityType:e,entityId:t,fields:r})):(this.pendingEdits.push({action:"edit_entity",entity_type:e,entity_id:t,fields:r}),this.emit("edit:pending",{entityType:e,entityId:t,fields:r}))}async requestSave(){if(!this.registration)return{success:!1,error:"No form registered"};try{return await this.registration.onSave(),this.emit("save:success",{entityType:this.registration.entityType,entityId:this.registration.entityId}),{success:!0}}catch(e){const t=e instanceof Error?e.message:"Save failed";return this.emit("save:error",{entityType:this.registration.entityType,entityId:this.registration.entityId,error:t}),{success:!1,error:t}}}async requestTest(e){if(!this.registration?.onTest)return{success:!1,error:"Current form does not support testing"};try{return await this.registration.onTest(e),{success:!0}}catch(t){return{success:!1,error:t instanceof Error?t.message:"Test failed"}}}setupListeners(e){e.on("action:edit_entity",t=>{this.pushFieldUpdates(t.entity_type,t.entity_id,t.fields)}),e.on("action:save_entity",t=>{this.requestSave()}),e.on("action:test_tool",t=>{this.emit("test:triggered",{toolId:t.tool_id,parameters:t.parameters}),this.requestTest(t.parameters)})}}exports.ActionCableClient=i.ActionCableClient;exports.AikaaraChatClient=i.AikaaraChatClient;exports.ApiClient=i.ApiClient;exports.ChannelSubscription=i.ChannelSubscription;exports.ConnectionManager=i.ConnectionManager;exports.ConversationManager=i.ConversationManager;exports.EventEmitter=i.EventEmitter;exports.MessageStore=i.MessageStore;exports.SessionAuthAdapter=i.SessionAuthAdapter;exports.TiledeskTransport=i.TiledeskTransport;exports.clearPersistedConversationId=i.clearPersistedConversationId;exports.createFetchUploadAdapter=i.createFetchUploadAdapter;exports.createPresigned3StepUploadAdapter=i.createPresigned3StepUploadAdapter;exports.createTiledeskHistoryAdapter=i.createTiledeskHistoryAdapter;exports.extractTiledeskFileEnvelope=i.extractTiledeskFileEnvelope;exports.inferTiledeskRole=i.inferTiledeskRole;exports.isTiledeskSelfEcho=i.isTiledeskSelfEcho;exports.mountFromSlug=i.mountFromSlug;exports.mountTenantWidget=i.mount;exports.parseTiledeskTemplate=i.parseTiledeskTemplate;exports.FormBridge=s;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./MountTenant-B9HM04oO.cjs");class s extends i.EventEmitter{registration=null;pendingEdits=[];constructor(e){super(),this.setupListeners(e)}registerForm(e){this.registration=e;const t=this.pendingEdits.filter(r=>r.entity_type===e.entityType&&String(r.entity_id)===String(e.entityId));if(t.length>0){for(const r of t)e.onFieldUpdate(r.fields),this.emit("edit:applied",{entityType:r.entity_type,entityId:r.entity_id,fields:r.fields});this.pendingEdits=this.pendingEdits.filter(r=>!(r.entity_type===e.entityType&&String(r.entity_id)===String(e.entityId)))}}unregisterForm(e,t){this.registration?.entityType===e&&String(this.registration?.entityId)===String(t)&&(this.registration=null)}get currentForm(){return this.registration}pushFieldUpdates(e,t,r){this.registration&&this.registration.entityType===e&&String(this.registration.entityId)===String(t)?(this.registration.onFieldUpdate(r),this.emit("edit:applied",{entityType:e,entityId:t,fields:r})):(this.pendingEdits.push({action:"edit_entity",entity_type:e,entity_id:t,fields:r}),this.emit("edit:pending",{entityType:e,entityId:t,fields:r}))}async requestSave(){if(!this.registration)return{success:!1,error:"No form registered"};try{return await this.registration.onSave(),this.emit("save:success",{entityType:this.registration.entityType,entityId:this.registration.entityId}),{success:!0}}catch(e){const t=e instanceof Error?e.message:"Save failed";return this.emit("save:error",{entityType:this.registration.entityType,entityId:this.registration.entityId,error:t}),{success:!1,error:t}}}async requestTest(e){if(!this.registration?.onTest)return{success:!1,error:"Current form does not support testing"};try{return await this.registration.onTest(e),{success:!0}}catch(t){return{success:!1,error:t instanceof Error?t.message:"Test failed"}}}setupListeners(e){e.on("action:edit_entity",t=>{this.pushFieldUpdates(t.entity_type,t.entity_id,t.fields)}),e.on("action:save_entity",t=>{this.requestSave()}),e.on("action:test_tool",t=>{this.emit("test:triggered",{toolId:t.tool_id,parameters:t.parameters}),this.requestTest(t.parameters)})}}exports.ActionCableClient=i.ActionCableClient;exports.AikaaraChatClient=i.AikaaraChatClient;exports.ApiClient=i.ApiClient;exports.ChannelSubscription=i.ChannelSubscription;exports.ConnectionManager=i.ConnectionManager;exports.ConversationManager=i.ConversationManager;exports.EventEmitter=i.EventEmitter;exports.MessageStore=i.MessageStore;exports.SessionAuthAdapter=i.SessionAuthAdapter;exports.TiledeskTransport=i.TiledeskTransport;exports.clearPersistedConversationId=i.clearPersistedConversationId;exports.createFetchUploadAdapter=i.createFetchUploadAdapter;exports.createPresigned3StepUploadAdapter=i.createPresigned3StepUploadAdapter;exports.createTiledeskHistoryAdapter=i.createTiledeskHistoryAdapter;exports.extractTiledeskFileEnvelope=i.extractTiledeskFileEnvelope;exports.inferTiledeskRole=i.inferTiledeskRole;exports.isTiledeskSelfEcho=i.isTiledeskSelfEcho;exports.mountFromSlug=i.mountFromSlug;exports.mountTenantWidget=i.mount;exports.parseTiledeskTemplate=i.parseTiledeskTemplate;exports.FormBridge=s;
@@ -196,6 +196,13 @@ declare class AikaaraChatWidget extends HTMLElement {
196
196
  attributeChangedCallback(_name: string, oldVal: string, newVal: string): void;
197
197
  configure(config: Partial<WidgetConfig>): void;
198
198
  private getConfig;
199
+ /**
200
+ * Mirror the theme tokens onto `document.documentElement` so elements
201
+ * that live OUTSIDE the chat shadow (e.g. the body-level link modal) can
202
+ * read them via `--aikaara-*`. The widget shadow already gets a copy via
203
+ * `themeVars()` for in-widget styling.
204
+ */
205
+ private propagateThemeToDocument;
199
206
  /**
200
207
  * Render `--aikaara-*` CSS variables from a theme-token bag.
201
208
  * Tokens are kebab-cased, with `radius` / `bubbleRadius` / `buttonRadius`
@@ -703,6 +710,35 @@ export declare function inferTiledeskRole(message: TiledeskMessage, cfg: Tiledes
703
710
  */
704
711
  export declare function isTiledeskSelfEcho(message: TiledeskMessage, userId: string): boolean;
705
712
 
713
+ /**
714
+ * Descriptor entry for intercepting link clicks. `match` is a glob pattern
715
+ * (`*` = any, `?` = single char) tested against the full clicked URL.
716
+ */
717
+ declare interface LinkHandler {
718
+ /** Glob pattern matched against the clicked URL. */
719
+ match: string;
720
+ /** What to do on match. `tab` opens in new tab, `iframe` uses default modal,
721
+ * `fetch-render` fetches data and mounts `render` inside the modal. */
722
+ target?: 'tab' | 'iframe' | 'fetch-render';
723
+ /** Modal title when `target` involves the modal. Default: link text. */
724
+ title?: string;
725
+ /** Fetch config (only used with `target: "fetch-render"`). */
726
+ fetch?: {
727
+ url: string;
728
+ method?: 'GET' | 'POST';
729
+ headers?: Record<string, string>;
730
+ body?: Record<string, unknown>;
731
+ /** Bearer source. `session` (default) | `chat` | `none`. */
732
+ authHeader?: 'session' | 'chat' | 'none';
733
+ };
734
+ /** Custom element name to mount in the modal body (e.g. `aikaara-compare-plans`). */
735
+ render?: string;
736
+ /** Properties to call on the rendered element. Each key is a method name
737
+ * invoked with one argument: the listed value (parsed/static). Default
738
+ * passes the API response via `.setData(<response>)`. */
739
+ props?: Record<string, unknown>;
740
+ }
741
+
706
742
  export declare interface Message {
707
743
  id: string;
708
744
  conversationId: string;
@@ -830,6 +866,22 @@ declare interface NavigateAction_2 {
830
866
 
831
867
  export declare function parseTiledeskTemplate(message: TiledeskMessage): TiledeskParsedTemplate;
832
868
 
869
+ /**
870
+ * One HTTP call run by the SDK before auth. Failure of `soft: true` steps
871
+ * is logged and ignored; failure of strict steps aborts the mount.
872
+ */
873
+ declare interface PreflightStep {
874
+ url: string;
875
+ method?: 'GET' | 'POST' | 'PUT';
876
+ body?: Record<string, unknown>;
877
+ headers?: Record<string, string>;
878
+ /** Bearer source. Default `session`. `none` skips Authorization. */
879
+ authHeader?: 'session' | 'none';
880
+ authHeaderTemplate?: string;
881
+ /** Continue on non-2xx. Default `false` (mount abort). */
882
+ soft?: boolean;
883
+ }
884
+
833
885
  /**
834
886
  * Three-step presigned-S3 upload (sign → PUT → register). Driven entirely
835
887
  * by descriptor — no tenant-specific code in host apps.
@@ -1032,6 +1084,8 @@ export declare interface TenantMountOptions {
1032
1084
  overrides?: Partial<WidgetConfigDescriptor>;
1033
1085
  /** Surfaced from the SDK. */
1034
1086
  onError?: (err: Error) => void;
1087
+ /** Bearer source for descriptor.linkHandlers fetches. */
1088
+ getLinkBearer?: (source: 'session' | 'chat' | 'none') => Promise<string | null>;
1035
1089
  }
1036
1090
 
1037
1091
  export declare interface TestToolAction {
@@ -1441,6 +1495,10 @@ export declare interface WidgetConfig extends ChatClientConfig {
1441
1495
  theme?: 'light' | 'dark' | 'auto';
1442
1496
  /** Token set rendered as `--aikaara-*` CSS variables on the widget host. */
1443
1497
  themeTokens?: WidgetTheme;
1498
+ /** Per-URL-pattern link interceptors (modal renderers, fetch-and-render, etc). */
1499
+ linkHandlers?: LinkHandler[];
1500
+ /** Returns a bearer value for a `linkHandlers[].fetch.authHeader` source. */
1501
+ getLinkBearer?: (source: 'session' | 'chat' | 'none') => Promise<string | null>;
1444
1502
  primaryColor?: string;
1445
1503
  fontFamily?: string;
1446
1504
  borderRadius?: number;
@@ -1537,6 +1595,28 @@ export declare interface WidgetConfigDescriptor {
1537
1595
  * itself — the host app no longer needs a `tokenProvider` callback.
1538
1596
  */
1539
1597
  auth?: SessionAuthDescriptor;
1598
+ /**
1599
+ * HTTP calls fired in order before `auth`. Use for backend warmups whose
1600
+ * side effects the auth call depends on (e.g. bandhan's bootstrap
1601
+ * `/chatbuddy/auth` with no serviceType, which seeds the `customerNew`
1602
+ * Mongo doc that the real auth call later reads). Each entry uses the
1603
+ * caller-supplied session token as bearer by default. URLs support
1604
+ * `{userId}`, `{projectId}`, `{slug}` placeholders.
1605
+ */
1606
+ preflight?: PreflightStep[];
1607
+ /**
1608
+ * Per-URL-pattern interceptors for in-message links. When a `<a href>`
1609
+ * matches one of these, the SDK swaps the default iframe modal for a
1610
+ * fetch-and-render flow:
1611
+ * 1. Extract query/path placeholders from the clicked URL.
1612
+ * 2. Fetch `fetch.url` with bearer auth, populate placeholders.
1613
+ * 3. Mount `render` (a custom element name) inside the link modal,
1614
+ * passing the parsed JSON via `.setData(data)`.
1615
+ *
1616
+ * No match → default iframe modal. `target: "tab"` on the entry → open
1617
+ * in a new tab without the modal.
1618
+ */
1619
+ linkHandlers?: LinkHandler[];
1540
1620
  /**
1541
1621
  * Built-in upload strategy. `mode: "presigned-3step"` runs sign → PUT →
1542
1622
  * register entirely from descriptor config; `mode: "direct"` POSTs as
@@ -1555,6 +1635,28 @@ export declare interface WidgetConfigDescriptor {
1555
1635
  mode: 'presigned-3step';
1556
1636
  tokenSource?: 'session' | 'chat';
1557
1637
  } & Presigned3StepAdapterConfig);
1638
+ /**
1639
+ * Per-templateId override map. Tells the chat SDK which custom element
1640
+ * tag to mount when a Tiledesk template message arrives carrying the
1641
+ * matching `metadata.templateId`. Optionally lazy-loads the bundle from
1642
+ * `scriptUrl` (typically a `/widget-assets`-uploaded S3 URL); once the
1643
+ * script registers the tag via `customElements.define`, subsequent
1644
+ * renders for that templateId resolve synchronously.
1645
+ *
1646
+ * `props` is a method-call map: each key is a method name on the mounted
1647
+ * element, called with the listed value before the standard
1648
+ * `.setPayload(payload, message)` call.
1649
+ *
1650
+ * templates: {
1651
+ * "12": { render: "aikaara-template-form", props: { setLayout: "stacked" } },
1652
+ * "99": { render: "bandhan-loan-quote", scriptUrl: "https://s3.../loan-quote-v3.iife.js" }
1653
+ * }
1654
+ */
1655
+ templates?: Record<string, {
1656
+ render: string;
1657
+ scriptUrl?: string;
1658
+ props?: Record<string, unknown>;
1659
+ }>;
1558
1660
  }
1559
1661
 
1560
1662
  /**
@@ -1579,6 +1681,14 @@ declare interface WidgetTheme {
1579
1681
  userBubbleText?: string;
1580
1682
  botBubbleBg?: string;
1581
1683
  botBubbleText?: string;
1684
+ /** Link-modal sizing. `modalWidth`/`modalHeight` are CSS strings (e.g.
1685
+ * "min(900px, 100%)"); `modalMaxWidth`/`modalMaxHeight` clamp them. */
1686
+ modalWidth?: string;
1687
+ modalHeight?: string;
1688
+ modalMaxWidth?: string;
1689
+ modalMaxHeight?: string;
1690
+ /** Padding around the backdrop (string with units, e.g. "24px"). */
1691
+ modalPadding?: string;
1582
1692
  }
1583
1693
 
1584
1694
  export { }
package/dist/headless.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { E as s } from "./MountTenant-CLlH4Zh6.mjs";
2
- import { A as p, b as g, k as l, C as h, l as y, m as c, M as u, S as m, T as f, n as T, o as S, p as _, q as v, s as E, t as C, u as F, v as A, w as k, x as I } from "./MountTenant-CLlH4Zh6.mjs";
1
+ import { E as s } from "./MountTenant-CFY0Ou0M.mjs";
2
+ import { A as p, b as g, k as l, C as h, l as y, m as c, M as u, S as m, T as f, n as T, o as S, p as _, q as v, s as E, t as C, u as F, v as A, w as k, x as I } from "./MountTenant-CFY0Ou0M.mjs";
3
3
  class a extends s {
4
4
  registration = null;
5
5
  pendingEdits = [];
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./MountTenant-HkluWr4X.cjs"),s=require("./headless.cjs");function l(a){e.registerComponents();const t=document.createElement("aikaara-chat-widget"),i={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[n,o]of Object.entries(i)){const r=a[n];r!=null&&t.setAttribute(o,String(r))}return t.configure(a),document.body.appendChild(t),t}function d(){const a=document.querySelector("aikaara-chat-widget");a&&a.remove()}exports.ActionCableClient=e.ActionCableClient;exports.AikaaraChatBubble=e.AikaaraChatBubble;exports.AikaaraChatClient=e.AikaaraChatClient;exports.AikaaraChatHeader=e.AikaaraChatHeader;exports.AikaaraChatInput=e.AikaaraChatInput;exports.AikaaraChatWidget=e.AikaaraChatWidget;exports.AikaaraErrorBanner=e.AikaaraErrorBanner;exports.AikaaraMessageBubble=e.AikaaraMessageBubble;exports.AikaaraMessageList=e.AikaaraMessageList;exports.AikaaraStreamingMessage=e.AikaaraStreamingMessage;exports.AikaaraTypingIndicator=e.AikaaraTypingIndicator;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.SessionAuthAdapter=e.SessionAuthAdapter;exports.TiledeskTransport=e.TiledeskTransport;exports.clearPersistedConversationId=e.clearPersistedConversationId;exports.createFetchUploadAdapter=e.createFetchUploadAdapter;exports.createPresigned3StepUploadAdapter=e.createPresigned3StepUploadAdapter;exports.createTiledeskHistoryAdapter=e.createTiledeskHistoryAdapter;exports.extractTiledeskFileEnvelope=e.extractTiledeskFileEnvelope;exports.inferTiledeskRole=e.inferTiledeskRole;exports.isTiledeskSelfEcho=e.isTiledeskSelfEcho;exports.mountFromSlug=e.mountFromSlug;exports.mountTenantWidget=e.mount;exports.parseTiledeskTemplate=e.parseTiledeskTemplate;exports.registerComponents=e.registerComponents;exports.FormBridge=s.FormBridge;exports.mount=l;exports.unmount=d;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./MountTenant-B9HM04oO.cjs"),s=require("./headless.cjs");function l(a){e.registerComponents();const t=document.createElement("aikaara-chat-widget"),i={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[n,o]of Object.entries(i)){const r=a[n];r!=null&&t.setAttribute(o,String(r))}return t.configure(a),document.body.appendChild(t),t}function d(){const a=document.querySelector("aikaara-chat-widget");a&&a.remove()}exports.ActionCableClient=e.ActionCableClient;exports.AikaaraChatBubble=e.AikaaraChatBubble;exports.AikaaraChatClient=e.AikaaraChatClient;exports.AikaaraChatHeader=e.AikaaraChatHeader;exports.AikaaraChatInput=e.AikaaraChatInput;exports.AikaaraChatWidget=e.AikaaraChatWidget;exports.AikaaraErrorBanner=e.AikaaraErrorBanner;exports.AikaaraMessageBubble=e.AikaaraMessageBubble;exports.AikaaraMessageList=e.AikaaraMessageList;exports.AikaaraStreamingMessage=e.AikaaraStreamingMessage;exports.AikaaraTypingIndicator=e.AikaaraTypingIndicator;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.SessionAuthAdapter=e.SessionAuthAdapter;exports.TiledeskTransport=e.TiledeskTransport;exports.clearPersistedConversationId=e.clearPersistedConversationId;exports.createFetchUploadAdapter=e.createFetchUploadAdapter;exports.createPresigned3StepUploadAdapter=e.createPresigned3StepUploadAdapter;exports.createTiledeskHistoryAdapter=e.createTiledeskHistoryAdapter;exports.extractTiledeskFileEnvelope=e.extractTiledeskFileEnvelope;exports.inferTiledeskRole=e.inferTiledeskRole;exports.isTiledeskSelfEcho=e.isTiledeskSelfEcho;exports.mountFromSlug=e.mountFromSlug;exports.mountTenantWidget=e.mount;exports.parseTiledeskTemplate=e.parseTiledeskTemplate;exports.registerComponents=e.registerComponents;exports.FormBridge=s.FormBridge;exports.mount=l;exports.unmount=d;
package/dist/index.d.ts CHANGED
@@ -174,6 +174,13 @@ export declare class AikaaraChatWidget extends HTMLElement {
174
174
  attributeChangedCallback(_name: string, oldVal: string, newVal: string): void;
175
175
  configure(config: Partial<WidgetConfig>): void;
176
176
  private getConfig;
177
+ /**
178
+ * Mirror the theme tokens onto `document.documentElement` so elements
179
+ * that live OUTSIDE the chat shadow (e.g. the body-level link modal) can
180
+ * read them via `--aikaara-*`. The widget shadow already gets a copy via
181
+ * `themeVars()` for in-widget styling.
182
+ */
183
+ private propagateThemeToDocument;
177
184
  /**
178
185
  * Render `--aikaara-*` CSS variables from a theme-token bag.
179
186
  * Tokens are kebab-cased, with `radius` / `bubbleRadius` / `buttonRadius`
@@ -221,6 +228,9 @@ export declare class AikaaraMessageList extends HTMLElement {
221
228
  private container;
222
229
  private welcomeMessage;
223
230
  private showTimestamps;
231
+ private linkHandlers;
232
+ private getLinkBearer;
233
+ setLinkConfig(handlers: LinkHandler[], bearer?: (source: 'session' | 'chat' | 'none') => Promise<string | null>): void;
224
234
  constructor();
225
235
  connectedCallback(): void;
226
236
  setWelcomeMessage(message: string): void;
@@ -241,6 +251,13 @@ export declare class AikaaraMessageList extends HTMLElement {
241
251
  private findRenderedMessage;
242
252
  private scrollToBottom;
243
253
  private formatTime;
254
+ /**
255
+ * Resolve a clicked URL against the descriptor's `linkHandlers`. Mounts
256
+ * the link modal and either iframes the URL, fetches+renders structured
257
+ * data, or opens in a new tab depending on the matched handler.
258
+ */
259
+ private handleLinkClick;
260
+ private getOrCreateModal;
244
261
  }
245
262
 
246
263
  export declare class AikaaraStreamingMessage extends HTMLElement {
@@ -613,6 +630,35 @@ export declare function inferTiledeskRole(message: TiledeskMessage, cfg: Tiledes
613
630
  */
614
631
  export declare function isTiledeskSelfEcho(message: TiledeskMessage, userId: string): boolean;
615
632
 
633
+ /**
634
+ * Descriptor entry for intercepting link clicks. `match` is a glob pattern
635
+ * (`*` = any, `?` = single char) tested against the full clicked URL.
636
+ */
637
+ declare interface LinkHandler {
638
+ /** Glob pattern matched against the clicked URL. */
639
+ match: string;
640
+ /** What to do on match. `tab` opens in new tab, `iframe` uses default modal,
641
+ * `fetch-render` fetches data and mounts `render` inside the modal. */
642
+ target?: 'tab' | 'iframe' | 'fetch-render';
643
+ /** Modal title when `target` involves the modal. Default: link text. */
644
+ title?: string;
645
+ /** Fetch config (only used with `target: "fetch-render"`). */
646
+ fetch?: {
647
+ url: string;
648
+ method?: 'GET' | 'POST';
649
+ headers?: Record<string, string>;
650
+ body?: Record<string, unknown>;
651
+ /** Bearer source. `session` (default) | `chat` | `none`. */
652
+ authHeader?: 'session' | 'chat' | 'none';
653
+ };
654
+ /** Custom element name to mount in the modal body (e.g. `aikaara-compare-plans`). */
655
+ render?: string;
656
+ /** Properties to call on the rendered element. Each key is a method name
657
+ * invoked with one argument: the listed value (parsed/static). Default
658
+ * passes the API response via `.setData(<response>)`. */
659
+ props?: Record<string, unknown>;
660
+ }
661
+
616
662
  export declare interface Message {
617
663
  id: string;
618
664
  conversationId: string;
@@ -712,6 +758,22 @@ export declare interface NavigateAction {
712
758
 
713
759
  export declare function parseTiledeskTemplate(message: TiledeskMessage): TiledeskParsedTemplate;
714
760
 
761
+ /**
762
+ * One HTTP call run by the SDK before auth. Failure of `soft: true` steps
763
+ * is logged and ignored; failure of strict steps aborts the mount.
764
+ */
765
+ declare interface PreflightStep {
766
+ url: string;
767
+ method?: 'GET' | 'POST' | 'PUT';
768
+ body?: Record<string, unknown>;
769
+ headers?: Record<string, string>;
770
+ /** Bearer source. Default `session`. `none` skips Authorization. */
771
+ authHeader?: 'session' | 'none';
772
+ authHeaderTemplate?: string;
773
+ /** Continue on non-2xx. Default `false` (mount abort). */
774
+ soft?: boolean;
775
+ }
776
+
715
777
  /**
716
778
  * Three-step presigned-S3 upload (sign → PUT → register). Driven entirely
717
779
  * by descriptor — no tenant-specific code in host apps.
@@ -901,6 +963,8 @@ export declare interface TenantMountOptions {
901
963
  overrides?: Partial<WidgetConfigDescriptor>;
902
964
  /** Surfaced from the SDK. */
903
965
  onError?: (err: Error) => void;
966
+ /** Bearer source for descriptor.linkHandlers fetches. */
967
+ getLinkBearer?: (source: 'session' | 'chat' | 'none') => Promise<string | null>;
904
968
  }
905
969
 
906
970
  export declare interface TestToolAction {
@@ -1182,6 +1246,10 @@ export declare interface WidgetConfig extends ChatClientConfig {
1182
1246
  theme?: 'light' | 'dark' | 'auto';
1183
1247
  /** Token set rendered as `--aikaara-*` CSS variables on the widget host. */
1184
1248
  themeTokens?: WidgetTheme;
1249
+ /** Per-URL-pattern link interceptors (modal renderers, fetch-and-render, etc). */
1250
+ linkHandlers?: LinkHandler[];
1251
+ /** Returns a bearer value for a `linkHandlers[].fetch.authHeader` source. */
1252
+ getLinkBearer?: (source: 'session' | 'chat' | 'none') => Promise<string | null>;
1185
1253
  primaryColor?: string;
1186
1254
  fontFamily?: string;
1187
1255
  borderRadius?: number;
@@ -1278,6 +1346,28 @@ export declare interface WidgetConfigDescriptor {
1278
1346
  * itself — the host app no longer needs a `tokenProvider` callback.
1279
1347
  */
1280
1348
  auth?: SessionAuthDescriptor;
1349
+ /**
1350
+ * HTTP calls fired in order before `auth`. Use for backend warmups whose
1351
+ * side effects the auth call depends on (e.g. bandhan's bootstrap
1352
+ * `/chatbuddy/auth` with no serviceType, which seeds the `customerNew`
1353
+ * Mongo doc that the real auth call later reads). Each entry uses the
1354
+ * caller-supplied session token as bearer by default. URLs support
1355
+ * `{userId}`, `{projectId}`, `{slug}` placeholders.
1356
+ */
1357
+ preflight?: PreflightStep[];
1358
+ /**
1359
+ * Per-URL-pattern interceptors for in-message links. When a `<a href>`
1360
+ * matches one of these, the SDK swaps the default iframe modal for a
1361
+ * fetch-and-render flow:
1362
+ * 1. Extract query/path placeholders from the clicked URL.
1363
+ * 2. Fetch `fetch.url` with bearer auth, populate placeholders.
1364
+ * 3. Mount `render` (a custom element name) inside the link modal,
1365
+ * passing the parsed JSON via `.setData(data)`.
1366
+ *
1367
+ * No match → default iframe modal. `target: "tab"` on the entry → open
1368
+ * in a new tab without the modal.
1369
+ */
1370
+ linkHandlers?: LinkHandler[];
1281
1371
  /**
1282
1372
  * Built-in upload strategy. `mode: "presigned-3step"` runs sign → PUT →
1283
1373
  * register entirely from descriptor config; `mode: "direct"` POSTs as
@@ -1296,6 +1386,28 @@ export declare interface WidgetConfigDescriptor {
1296
1386
  mode: 'presigned-3step';
1297
1387
  tokenSource?: 'session' | 'chat';
1298
1388
  } & Presigned3StepAdapterConfig);
1389
+ /**
1390
+ * Per-templateId override map. Tells the chat SDK which custom element
1391
+ * tag to mount when a Tiledesk template message arrives carrying the
1392
+ * matching `metadata.templateId`. Optionally lazy-loads the bundle from
1393
+ * `scriptUrl` (typically a `/widget-assets`-uploaded S3 URL); once the
1394
+ * script registers the tag via `customElements.define`, subsequent
1395
+ * renders for that templateId resolve synchronously.
1396
+ *
1397
+ * `props` is a method-call map: each key is a method name on the mounted
1398
+ * element, called with the listed value before the standard
1399
+ * `.setPayload(payload, message)` call.
1400
+ *
1401
+ * templates: {
1402
+ * "12": { render: "aikaara-template-form", props: { setLayout: "stacked" } },
1403
+ * "99": { render: "bandhan-loan-quote", scriptUrl: "https://s3.../loan-quote-v3.iife.js" }
1404
+ * }
1405
+ */
1406
+ templates?: Record<string, {
1407
+ render: string;
1408
+ scriptUrl?: string;
1409
+ props?: Record<string, unknown>;
1410
+ }>;
1299
1411
  }
1300
1412
 
1301
1413
  /**
@@ -1320,6 +1432,14 @@ declare interface WidgetTheme {
1320
1432
  userBubbleText?: string;
1321
1433
  botBubbleBg?: string;
1322
1434
  botBubbleText?: string;
1435
+ /** Link-modal sizing. `modalWidth`/`modalHeight` are CSS strings (e.g.
1436
+ * "min(900px, 100%)"); `modalMaxWidth`/`modalMaxHeight` clamp them. */
1437
+ modalWidth?: string;
1438
+ modalHeight?: string;
1439
+ modalMaxWidth?: string;
1440
+ modalMaxHeight?: string;
1441
+ /** Padding around the backdrop (string with units, e.g. "24px"). */
1442
+ modalPadding?: string;
1323
1443
  }
1324
1444
 
1325
1445
  export { }
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { r as o } from "./MountTenant-CLlH4Zh6.mjs";
2
- import { A as u, a as m, b as g, c as h, d as k, e as A, f as C, g as b, h as f, i as T, j as v, k as S, C as w, l as y, m as M, E, M as x, S as B, T as F, n as U, o as I, p as j, q, s as H, t as P, u as W, v as K, w as L, x as O } from "./MountTenant-CLlH4Zh6.mjs";
1
+ import { r as o } from "./MountTenant-CFY0Ou0M.mjs";
2
+ import { A as u, a as m, b as g, c as h, d as k, e as A, f as C, g as b, h as f, i as T, j as v, k as S, C as w, l as y, m as M, E, M as x, S as B, T as F, n as U, o as I, p as j, q, s as H, t as P, u as W, v as K, w as L, x as O } from "./MountTenant-CFY0Ou0M.mjs";
3
3
  import { FormBridge as z } from "./headless.mjs";
4
4
  function l(e) {
5
5
  o();
package/dist/ui.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("./MountTenant-HkluWr4X.cjs");exports.AikaaraChat=a.AikaaraChat;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.AikaaraModalAction=a.AikaaraModalAction;exports.AikaaraOptionList=a.AikaaraOptionList;exports.AikaaraStreamingMessage=a.AikaaraStreamingMessage;exports.AikaaraSubmitAction=a.AikaaraSubmitAction;exports.AikaaraSystemPill=a.AikaaraSystemPill;exports.AikaaraTemplateRenderer=a.AikaaraTemplateRenderer;exports.AikaaraTypingIndicator=a.AikaaraTypingIndicator;exports.registerComponents=a.registerComponents;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("./MountTenant-B9HM04oO.cjs");exports.AikaaraChat=a.AikaaraChat;exports.AikaaraChatBubble=a.AikaaraChatBubble;exports.AikaaraChatHeader=a.AikaaraChatHeader;exports.AikaaraChatInput=a.AikaaraChatInput;exports.AikaaraChatWidget=a.AikaaraChatWidget;exports.AikaaraComparePlans=a.AikaaraComparePlans;exports.AikaaraErrorBanner=a.AikaaraErrorBanner;exports.AikaaraLinkModal=a.AikaaraLinkModal;exports.AikaaraMessageBubble=a.AikaaraMessageBubble;exports.AikaaraMessageList=a.AikaaraMessageList;exports.AikaaraModalAction=a.AikaaraModalAction;exports.AikaaraOptionList=a.AikaaraOptionList;exports.AikaaraStreamingMessage=a.AikaaraStreamingMessage;exports.AikaaraSubmitAction=a.AikaaraSubmitAction;exports.AikaaraSystemPill=a.AikaaraSystemPill;exports.AikaaraTemplateRenderer=a.AikaaraTemplateRenderer;exports.AikaaraTypingIndicator=a.AikaaraTypingIndicator;exports.registerComponents=a.registerComponents;
package/dist/ui.d.ts CHANGED
@@ -175,6 +175,13 @@ export declare class AikaaraChatWidget extends HTMLElement {
175
175
  attributeChangedCallback(_name: string, oldVal: string, newVal: string): void;
176
176
  configure(config: Partial<WidgetConfig>): void;
177
177
  private getConfig;
178
+ /**
179
+ * Mirror the theme tokens onto `document.documentElement` so elements
180
+ * that live OUTSIDE the chat shadow (e.g. the body-level link modal) can
181
+ * read them via `--aikaara-*`. The widget shadow already gets a copy via
182
+ * `themeVars()` for in-widget styling.
183
+ */
184
+ private propagateThemeToDocument;
178
185
  /**
179
186
  * Render `--aikaara-*` CSS variables from a theme-token bag.
180
187
  * Tokens are kebab-cased, with `radius` / `bubbleRadius` / `buttonRadius`
@@ -190,6 +197,21 @@ export declare class AikaaraChatWidget extends HTMLElement {
190
197
  private darkenColor;
191
198
  }
192
199
 
200
+ export declare class AikaaraComparePlans extends HTMLElement {
201
+ private shadow;
202
+ private data;
203
+ private columns;
204
+ private features;
205
+ constructor();
206
+ connectedCallback(): void;
207
+ /** Set the `/itr/plans` API response. Triggers re-render. */
208
+ setData(data: PlansResponse): void;
209
+ setColumns(columns: Column[]): void;
210
+ setFeatures(features: FeatureRow[]): void;
211
+ private priceFor;
212
+ private render;
213
+ }
214
+
193
215
  export declare class AikaaraErrorBanner extends HTMLElement {
194
216
  private shadow;
195
217
  private container;
@@ -200,6 +222,35 @@ export declare class AikaaraErrorBanner extends HTMLElement {
200
222
  hide(): void;
201
223
  }
202
224
 
225
+ /**
226
+ * `<aikaara-link-modal>` — overlay dialog that loads an external URL in an
227
+ * iframe inside the chat widget instead of navigating away.
228
+ *
229
+ * Triggered by clicks on `<a href>` inside bot/assistant bubbles when the
230
+ * widget is configured to intercept them (default behaviour). Listens for
231
+ * `aikaara-open-link` on document; emits `aikaara-link-modal-open` /
232
+ * `aikaara-link-modal-close` for instrumentation.
233
+ *
234
+ * Falls back to opening the URL in a new tab if the iframe fails to load
235
+ * (e.g. upstream sets `X-Frame-Options: DENY`).
236
+ */
237
+ export declare class AikaaraLinkModal extends HTMLElement {
238
+ private shadow;
239
+ private root;
240
+ private iframe;
241
+ private fallbackTimer;
242
+ constructor();
243
+ connectedCallback(): void;
244
+ /** Open the modal pointed at `url`. */
245
+ show(url: string, title?: string): void;
246
+ /** Open modal with a custom element mounted in the body. */
247
+ showElement(tagName: string, title?: string, configure?: (el: HTMLElement) => void): void;
248
+ /** Toggle which body slot is visible (iframe vs custom element host). */
249
+ private swapBody;
250
+ close(): void;
251
+ private render;
252
+ }
253
+
203
254
  export declare class AikaaraMessageBubble extends HTMLElement {
204
255
  private shadow;
205
256
  private templatePayload;
@@ -222,6 +273,9 @@ export declare class AikaaraMessageList extends HTMLElement {
222
273
  private container;
223
274
  private welcomeMessage;
224
275
  private showTimestamps;
276
+ private linkHandlers;
277
+ private getLinkBearer;
278
+ setLinkConfig(handlers: LinkHandler[], bearer?: (source: 'session' | 'chat' | 'none') => Promise<string | null>): void;
225
279
  constructor();
226
280
  connectedCallback(): void;
227
281
  setWelcomeMessage(message: string): void;
@@ -242,6 +296,13 @@ export declare class AikaaraMessageList extends HTMLElement {
242
296
  private findRenderedMessage;
243
297
  private scrollToBottom;
244
298
  private formatTime;
299
+ /**
300
+ * Resolve a clicked URL against the descriptor's `linkHandlers`. Mounts
301
+ * the link modal and either iframes the URL, fetches+renders structured
302
+ * data, or opens in a new tab depending on the matched handler.
303
+ */
304
+ private handleLinkClick;
305
+ private getOrCreateModal;
245
306
  }
246
307
 
247
308
  export declare class AikaaraModalAction extends HTMLElement {
@@ -481,6 +542,19 @@ declare interface ChatEvents {
481
542
  };
482
543
  }
483
544
 
545
+ declare interface Column {
546
+ /** Column header text. */
547
+ label: string;
548
+ /** API `planType` value(s) this column corresponds to. First match wins. */
549
+ match: string[];
550
+ /** Submit-button label template. `{price}` is replaced with the basePrice. */
551
+ selectLabel: string;
552
+ /** Postback `message` value sent to the chat when this column is selected. */
553
+ postback: string;
554
+ /** Which features (by row index in `featureRows`) are enabled in this column. */
555
+ features: boolean[];
556
+ }
557
+
484
558
  declare interface ConnectionConfig {
485
559
  baseUrl: string;
486
560
  wsUrl?: string;
@@ -546,12 +620,45 @@ declare class EventEmitter<Events extends Record<string, any>> {
546
620
  removeAllListeners(): void;
547
621
  }
548
622
 
623
+ declare interface FeatureRow {
624
+ label: string;
625
+ }
626
+
549
627
  declare interface FieldUpdate {
550
628
  field: string;
551
629
  value: unknown;
552
630
  previousValue?: unknown;
553
631
  }
554
632
 
633
+ /**
634
+ * Descriptor entry for intercepting link clicks. `match` is a glob pattern
635
+ * (`*` = any, `?` = single char) tested against the full clicked URL.
636
+ */
637
+ declare interface LinkHandler {
638
+ /** Glob pattern matched against the clicked URL. */
639
+ match: string;
640
+ /** What to do on match. `tab` opens in new tab, `iframe` uses default modal,
641
+ * `fetch-render` fetches data and mounts `render` inside the modal. */
642
+ target?: 'tab' | 'iframe' | 'fetch-render';
643
+ /** Modal title when `target` involves the modal. Default: link text. */
644
+ title?: string;
645
+ /** Fetch config (only used with `target: "fetch-render"`). */
646
+ fetch?: {
647
+ url: string;
648
+ method?: 'GET' | 'POST';
649
+ headers?: Record<string, string>;
650
+ body?: Record<string, unknown>;
651
+ /** Bearer source. `session` (default) | `chat` | `none`. */
652
+ authHeader?: 'session' | 'chat' | 'none';
653
+ };
654
+ /** Custom element name to mount in the modal body (e.g. `aikaara-compare-plans`). */
655
+ render?: string;
656
+ /** Properties to call on the rendered element. Each key is a method name
657
+ * invoked with one argument: the listed value (parsed/static). Default
658
+ * passes the API response via `.setData(<response>)`. */
659
+ props?: Record<string, unknown>;
660
+ }
661
+
555
662
  declare interface Message {
556
663
  id: string;
557
664
  conversationId: string;
@@ -666,6 +773,31 @@ declare interface OptionListPayload {
666
773
  type: 'checkbox' | 'radio' | 'button';
667
774
  }
668
775
 
776
+ /**
777
+ * `<aikaara-compare-plans>` — built-in renderer for bandhan-style plan
778
+ * comparison popups. Configured by `descriptor.linkHandlers` to fire when
779
+ * the user taps a "Compare DIY with Assisted Plan" link inside a chat
780
+ * message. Receives the raw `/itr/plans` API response via `.setData()` and
781
+ * an optional `.setColumns([...])` override (defaults to DIY/DIY+Notice/
782
+ * Assisted matching the bandhan UI).
783
+ *
784
+ * Pure presentation. Selecting a plan emits an `aikaara-plan-select`
785
+ * CustomEvent (composed) so the host app or template renderer can route the
786
+ * postback through the chat (`message`-style action).
787
+ */
788
+ declare interface PlanRow {
789
+ planType: string;
790
+ planMaster?: {
791
+ basePrice?: number;
792
+ totalAmount?: number;
793
+ };
794
+ }
795
+
796
+ declare interface PlansResponse {
797
+ success?: boolean;
798
+ data?: PlanRow[];
799
+ }
800
+
669
801
  export declare function registerComponents(): void;
670
802
 
671
803
  declare interface SaveEntityAction {
@@ -988,6 +1120,10 @@ declare interface WidgetConfig extends ChatClientConfig {
988
1120
  theme?: 'light' | 'dark' | 'auto';
989
1121
  /** Token set rendered as `--aikaara-*` CSS variables on the widget host. */
990
1122
  themeTokens?: WidgetTheme;
1123
+ /** Per-URL-pattern link interceptors (modal renderers, fetch-and-render, etc). */
1124
+ linkHandlers?: LinkHandler[];
1125
+ /** Returns a bearer value for a `linkHandlers[].fetch.authHeader` source. */
1126
+ getLinkBearer?: (source: 'session' | 'chat' | 'none') => Promise<string | null>;
991
1127
  primaryColor?: string;
992
1128
  fontFamily?: string;
993
1129
  borderRadius?: number;
@@ -1034,6 +1170,14 @@ declare interface WidgetTheme {
1034
1170
  userBubbleText?: string;
1035
1171
  botBubbleBg?: string;
1036
1172
  botBubbleText?: string;
1173
+ /** Link-modal sizing. `modalWidth`/`modalHeight` are CSS strings (e.g.
1174
+ * "min(900px, 100%)"); `modalMaxWidth`/`modalMaxHeight` clamp them. */
1175
+ modalWidth?: string;
1176
+ modalHeight?: string;
1177
+ modalMaxWidth?: string;
1178
+ modalMaxHeight?: string;
1179
+ /** Padding around the backdrop (string with units, e.g. "24px"). */
1180
+ modalPadding?: string;
1037
1181
  }
1038
1182
 
1039
1183
  export { }
package/dist/ui.mjs CHANGED
@@ -1,19 +1,21 @@
1
- import { y as i, a as s, c as e, d as t, e as A, f as k, g as n, h as o, z as g, B as d, i as h, D as l, F as m, G as p, j as C, r as b } from "./MountTenant-CLlH4Zh6.mjs";
1
+ import { y as i, a as s, c as e, d as t, e as A, z as k, f as n, B as o, g, h as l, D as d, F as m, i as p, G as C, H as h, I as b, j as M, r as c } from "./MountTenant-CFY0Ou0M.mjs";
2
2
  export {
3
3
  i as AikaaraChat,
4
4
  s as AikaaraChatBubble,
5
5
  e as AikaaraChatHeader,
6
6
  t as AikaaraChatInput,
7
7
  A as AikaaraChatWidget,
8
- k as AikaaraErrorBanner,
9
- n as AikaaraMessageBubble,
10
- o as AikaaraMessageList,
11
- g as AikaaraModalAction,
12
- d as AikaaraOptionList,
13
- h as AikaaraStreamingMessage,
14
- l as AikaaraSubmitAction,
15
- m as AikaaraSystemPill,
16
- p as AikaaraTemplateRenderer,
17
- C as AikaaraTypingIndicator,
18
- b as registerComponents
8
+ k as AikaaraComparePlans,
9
+ n as AikaaraErrorBanner,
10
+ o as AikaaraLinkModal,
11
+ g as AikaaraMessageBubble,
12
+ l as AikaaraMessageList,
13
+ d as AikaaraModalAction,
14
+ m as AikaaraOptionList,
15
+ p as AikaaraStreamingMessage,
16
+ C as AikaaraSubmitAction,
17
+ h as AikaaraSystemPill,
18
+ b as AikaaraTemplateRenderer,
19
+ M as AikaaraTypingIndicator,
20
+ c as registerComponents
19
21
  };