@aikaara/chat-sdk 0.8.1 → 0.8.2

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-BrBxPpjb.cjs");class r extends i.EventEmitter{registration=null;pendingEdits=[];constructor(e){super(),this.setupListeners(e)}registerForm(e){this.registration=e;const t=this.pendingEdits.filter(s=>s.entity_type===e.entityType&&String(s.entity_id)===String(e.entityId));if(t.length>0){for(const s of t)e.onFieldUpdate(s.fields),this.emit("edit:applied",{entityType:s.entity_type,entityId:s.entity_id,fields:s.fields});this.pendingEdits=this.pendingEdits.filter(s=>!(s.entity_type===e.entityType&&String(s.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,s){this.registration&&this.registration.entityType===e&&String(this.registration.entityId)===String(t)?(this.registration.onFieldUpdate(s),this.emit("edit:applied",{entityType:e,entityId:t,fields:s})):(this.pendingEdits.push({action:"edit_entity",entity_type:e,entity_id:t,fields:s}),this.emit("edit:pending",{entityType:e,entityId:t,fields:s}))}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.SsoExchangeAdapter=i.SsoExchangeAdapter;exports.TiledeskTransport=i.TiledeskTransport;exports.clearPersistedConversationId=i.clearPersistedConversationId;exports.collectSsoCredentials=i.collectSsoCredentials;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=r;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./MountTenant-DvmiAoZ_.cjs");class r extends i.EventEmitter{registration=null;pendingEdits=[];constructor(e){super(),this.setupListeners(e)}registerForm(e){this.registration=e;const t=this.pendingEdits.filter(s=>s.entity_type===e.entityType&&String(s.entity_id)===String(e.entityId));if(t.length>0){for(const s of t)e.onFieldUpdate(s.fields),this.emit("edit:applied",{entityType:s.entity_type,entityId:s.entity_id,fields:s.fields});this.pendingEdits=this.pendingEdits.filter(s=>!(s.entity_type===e.entityType&&String(s.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,s){this.registration&&this.registration.entityType===e&&String(this.registration.entityId)===String(t)?(this.registration.onFieldUpdate(s),this.emit("edit:applied",{entityType:e,entityId:t,fields:s})):(this.pendingEdits.push({action:"edit_entity",entity_type:e,entity_id:t,fields:s}),this.emit("edit:pending",{entityType:e,entityId:t,fields:s}))}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.SsoExchangeAdapter=i.SsoExchangeAdapter;exports.TiledeskTransport=i.TiledeskTransport;exports.clearPersistedConversationId=i.clearPersistedConversationId;exports.collectSsoCredentials=i.collectSsoCredentials;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=r;
@@ -222,7 +222,7 @@ export declare class ApiClient {
222
222
  private baseUrl;
223
223
  private apiKey?;
224
224
  private authToken?;
225
- private userToken;
225
+ protected userToken: string;
226
226
  constructor(baseUrl: string, userToken: string, apiKey?: string, authToken?: string);
227
227
  createConversation(params: {
228
228
  systemPromptId?: number;
@@ -948,6 +948,61 @@ export declare interface Presigned3StepAdapterConfig {
948
948
  extraHeaders?: Record<string, string>;
949
949
  }
950
950
 
951
+ /**
952
+ * One slot's component pointer. The `kind` discriminator picks which
953
+ * loader runs. Both kinds resolve to a `Promise<HTMLElement>` after load,
954
+ * which the runtime appends into the slot anchor.
955
+ */
956
+ declare type RemoteComponent = {
957
+ kind: 'iife-element';
958
+ /** URL of an IIFE bundle that calls `customElements.define(tag, …)`. */
959
+ scriptUrl: string;
960
+ /** Custom-element tag the bundle registers. */
961
+ tag: string;
962
+ /** Optional method-call map: `{ setLayout: "stacked" }` becomes
963
+ * `el.setLayout("stacked")` after mount. */
964
+ props?: Record<string, unknown>;
965
+ } | {
966
+ kind: 'remote-dom';
967
+ /** URL of an IIFE bundle that, when executed, leaves a global at
968
+ * `globalName` exposing `mount({ target, ctx, complete, props })`.
969
+ * Authored via `@aikaara/chat-sdk/remote-author`. */
970
+ scriptUrl: string;
971
+ /** Optional global name; defaults to the slot id with non-alphanumeric
972
+ * chars replaced by underscores (e.g. "screen:login" → "screen_login"). */
973
+ globalName?: string;
974
+ /** Sandbox kind. Today only `iframe`; `worker` reserved for later. */
975
+ sandbox?: 'iframe' | 'worker';
976
+ /** Forwarded to the bundle's `mount({ props })` call. */
977
+ props?: Record<string, unknown>;
978
+ };
979
+
980
+ /**
981
+ * One route in `descriptor.app.routes`.
982
+ *
983
+ * `path` is matched against the URL pathname AFTER the tenant's slug
984
+ * prefix is stripped (in subpath mode). Supports trailing wildcards (`/*`)
985
+ * and named params (`/:id`) — the parser is intentionally tiny.
986
+ *
987
+ * `component` references a slot in `descriptor.components`.
988
+ *
989
+ * `guards` are simple predicate names the shell evaluates against runtime
990
+ * session state. Today: `'sso'` (SSO exchange done), `'authed'` (user
991
+ * has any session), `'panVerified'` (PAN flow finished). Tenants can
992
+ * extend by exposing flags via `complete(payload)` from preceding screens.
993
+ *
994
+ * `redirectIfFails` lets a guard send the user to another route id
995
+ * instead of erroring. Useful for `'authed'` failing → redirect to login.
996
+ */
997
+ declare interface RouteDef {
998
+ path: string;
999
+ component: string;
1000
+ guards?: string[];
1001
+ redirectIfFails?: string;
1002
+ /** Optional layout slot wrapping this route's component. */
1003
+ layout?: string;
1004
+ }
1005
+
951
1006
  export declare interface SaveEntityAction {
952
1007
  action: 'save_entity';
953
1008
  }
@@ -1892,6 +1947,43 @@ export declare interface WidgetConfigDescriptor {
1892
1947
  scriptUrl?: string;
1893
1948
  props?: Record<string, unknown>;
1894
1949
  }>;
1950
+ /**
1951
+ * Multi-screen app definition. When present, the hosted-shell renders a
1952
+ * History-API router rooted at the tenant's mount path. Each route
1953
+ * names a slot key that resolves to a `components[slot]` entry.
1954
+ *
1955
+ * When absent, behaviour is the today's single-screen mount (chat
1956
+ * widget at root). No breaking change for existing tenants.
1957
+ */
1958
+ app?: {
1959
+ /** Route id rendered when path matches `/` (or `/<slug>/` in subpath). */
1960
+ defaultRoute: string;
1961
+ /** Map of route id → definition. */
1962
+ routes: Record<string, RouteDef>;
1963
+ };
1964
+ /**
1965
+ * Unified slot map. Supersedes `templates` and the bespoke
1966
+ * `linkHandlers[].render` mechanism. Each key is a slot id that some
1967
+ * piece of the runtime knows to look up:
1968
+ *
1969
+ * "template:<contentTypeOrTemplateId>" — Tiledesk contentType=300 templates
1970
+ * "screen:login" | "screen:prechat" | "screen:chat" | … — full screens
1971
+ * "panel:header" | "panel:left-rail" | … — chat-shell side panels
1972
+ * "viewer:file" | "viewer:compare-plans" | … — link-modal renderers
1973
+ *
1974
+ * Two component kinds today:
1975
+ * - `iife-element` : tenant ships an IIFE that calls customElements.define;
1976
+ * SDK loads the script + creates `<tag>` and dispatches.
1977
+ * - `remote-dom` : tenant ships a remote-dom bundle (React/Preact/Svelte
1978
+ * JSX); SDK lazy-loads `@aikaara/chat-sdk/remote-host`,
1979
+ * creates a hidden iframe with DOMRemoteReceiver, and
1980
+ * mirrors the tenant's tree into the host slot.
1981
+ *
1982
+ * Backwards compat: at mount time, every entry in `templates` is mirrored
1983
+ * into `components['template:'+id]` as kind:'iife-element' if a matching
1984
+ * key isn't already present. Tenants on the old shape see no change.
1985
+ */
1986
+ components?: Record<string, RemoteComponent>;
1895
1987
  }
1896
1988
 
1897
1989
  /**
package/dist/headless.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { E as s } from "./MountTenant-BVimPLfY.mjs";
2
- import { A as p, b as l, k as g, C as h, l as c, m as y, M as u, S as m, n as f, T as S, o as T, p as _, q as E, s as v, t as C, u as F, v as A, w as k, x as I, y as x, z as U } from "./MountTenant-BVimPLfY.mjs";
1
+ import { E as s } from "./MountTenant-DzNgBTiU.mjs";
2
+ import { A as p, b as l, k as g, C as h, l as c, m as y, M as u, S as m, n as f, T as S, o as T, p as _, q as E, s as v, t as C, u as F, v as A, w as k, x as I, y as x, z as U } from "./MountTenant-DzNgBTiU.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-BrBxPpjb.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.SsoExchangeAdapter=e.SsoExchangeAdapter;exports.TiledeskTransport=e.TiledeskTransport;exports.clearPersistedConversationId=e.clearPersistedConversationId;exports.collectSsoCredentials=e.collectSsoCredentials;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-DvmiAoZ_.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.SsoExchangeAdapter=e.SsoExchangeAdapter;exports.TiledeskTransport=e.TiledeskTransport;exports.clearPersistedConversationId=e.clearPersistedConversationId;exports.collectSsoCredentials=e.collectSsoCredentials;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
@@ -292,7 +292,7 @@ export declare class ApiClient {
292
292
  private baseUrl;
293
293
  private apiKey?;
294
294
  private authToken?;
295
- private userToken;
295
+ protected userToken: string;
296
296
  constructor(baseUrl: string, userToken: string, apiKey?: string, authToken?: string);
297
297
  createConversation(params: {
298
298
  systemPromptId?: number;
@@ -853,6 +853,61 @@ export declare interface Presigned3StepAdapterConfig {
853
853
 
854
854
  export declare function registerComponents(): void;
855
855
 
856
+ /**
857
+ * One slot's component pointer. The `kind` discriminator picks which
858
+ * loader runs. Both kinds resolve to a `Promise<HTMLElement>` after load,
859
+ * which the runtime appends into the slot anchor.
860
+ */
861
+ declare type RemoteComponent = {
862
+ kind: 'iife-element';
863
+ /** URL of an IIFE bundle that calls `customElements.define(tag, …)`. */
864
+ scriptUrl: string;
865
+ /** Custom-element tag the bundle registers. */
866
+ tag: string;
867
+ /** Optional method-call map: `{ setLayout: "stacked" }` becomes
868
+ * `el.setLayout("stacked")` after mount. */
869
+ props?: Record<string, unknown>;
870
+ } | {
871
+ kind: 'remote-dom';
872
+ /** URL of an IIFE bundle that, when executed, leaves a global at
873
+ * `globalName` exposing `mount({ target, ctx, complete, props })`.
874
+ * Authored via `@aikaara/chat-sdk/remote-author`. */
875
+ scriptUrl: string;
876
+ /** Optional global name; defaults to the slot id with non-alphanumeric
877
+ * chars replaced by underscores (e.g. "screen:login" → "screen_login"). */
878
+ globalName?: string;
879
+ /** Sandbox kind. Today only `iframe`; `worker` reserved for later. */
880
+ sandbox?: 'iframe' | 'worker';
881
+ /** Forwarded to the bundle's `mount({ props })` call. */
882
+ props?: Record<string, unknown>;
883
+ };
884
+
885
+ /**
886
+ * One route in `descriptor.app.routes`.
887
+ *
888
+ * `path` is matched against the URL pathname AFTER the tenant's slug
889
+ * prefix is stripped (in subpath mode). Supports trailing wildcards (`/*`)
890
+ * and named params (`/:id`) — the parser is intentionally tiny.
891
+ *
892
+ * `component` references a slot in `descriptor.components`.
893
+ *
894
+ * `guards` are simple predicate names the shell evaluates against runtime
895
+ * session state. Today: `'sso'` (SSO exchange done), `'authed'` (user
896
+ * has any session), `'panVerified'` (PAN flow finished). Tenants can
897
+ * extend by exposing flags via `complete(payload)` from preceding screens.
898
+ *
899
+ * `redirectIfFails` lets a guard send the user to another route id
900
+ * instead of erroring. Useful for `'authed'` failing → redirect to login.
901
+ */
902
+ declare interface RouteDef {
903
+ path: string;
904
+ component: string;
905
+ guards?: string[];
906
+ redirectIfFails?: string;
907
+ /** Optional layout slot wrapping this route's component. */
908
+ layout?: string;
909
+ }
910
+
856
911
  export declare interface SaveEntityAction {
857
912
  action: 'save_entity';
858
913
  }
@@ -1654,6 +1709,43 @@ export declare interface WidgetConfigDescriptor {
1654
1709
  scriptUrl?: string;
1655
1710
  props?: Record<string, unknown>;
1656
1711
  }>;
1712
+ /**
1713
+ * Multi-screen app definition. When present, the hosted-shell renders a
1714
+ * History-API router rooted at the tenant's mount path. Each route
1715
+ * names a slot key that resolves to a `components[slot]` entry.
1716
+ *
1717
+ * When absent, behaviour is the today's single-screen mount (chat
1718
+ * widget at root). No breaking change for existing tenants.
1719
+ */
1720
+ app?: {
1721
+ /** Route id rendered when path matches `/` (or `/<slug>/` in subpath). */
1722
+ defaultRoute: string;
1723
+ /** Map of route id → definition. */
1724
+ routes: Record<string, RouteDef>;
1725
+ };
1726
+ /**
1727
+ * Unified slot map. Supersedes `templates` and the bespoke
1728
+ * `linkHandlers[].render` mechanism. Each key is a slot id that some
1729
+ * piece of the runtime knows to look up:
1730
+ *
1731
+ * "template:<contentTypeOrTemplateId>" — Tiledesk contentType=300 templates
1732
+ * "screen:login" | "screen:prechat" | "screen:chat" | … — full screens
1733
+ * "panel:header" | "panel:left-rail" | … — chat-shell side panels
1734
+ * "viewer:file" | "viewer:compare-plans" | … — link-modal renderers
1735
+ *
1736
+ * Two component kinds today:
1737
+ * - `iife-element` : tenant ships an IIFE that calls customElements.define;
1738
+ * SDK loads the script + creates `<tag>` and dispatches.
1739
+ * - `remote-dom` : tenant ships a remote-dom bundle (React/Preact/Svelte
1740
+ * JSX); SDK lazy-loads `@aikaara/chat-sdk/remote-host`,
1741
+ * creates a hidden iframe with DOMRemoteReceiver, and
1742
+ * mirrors the tenant's tree into the host slot.
1743
+ *
1744
+ * Backwards compat: at mount time, every entry in `templates` is mirrored
1745
+ * into `components['template:'+id]` as kind:'iife-element' if a matching
1746
+ * key isn't already present. Tenants on the old shape see no change.
1747
+ */
1748
+ components?: Record<string, RemoteComponent>;
1657
1749
  }
1658
1750
 
1659
1751
  /**
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { r as o } from "./MountTenant-BVimPLfY.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 S, j as T, k as v, C as y, l as w, m as M, E, M as x, S as B, n as F, T as U, o as I, p as j, q, s as H, t as P, u as W, v as z, w as K, x as L, y as O, z as R } from "./MountTenant-BVimPLfY.mjs";
1
+ import { r as o } from "./MountTenant-DzNgBTiU.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 S, j as T, k as v, C as y, l as w, m as M, E, M as x, S as B, n as F, T as U, o as I, p as j, q, s as H, t as P, u as W, v as z, w as K, x as L, y as O, z as R } from "./MountTenant-DzNgBTiU.mjs";
3
3
  import { FormBridge as G } from "./headless.mjs";
4
4
  function l(e) {
5
5
  o();
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=1;function p(s){let n=!1,t=null;const c=o=>{window.parent?.postMessage({aikaara:r,type:"complete",payload:o},"*")},i=o=>{window.parent?.postMessage({aikaara:r,type:"error",message:o},"*")};window.addEventListener("message",o=>{const e=o.data;!e||e.aikaara!==r||(e.type==="bootstrap"&&!n?(n=!0,t={target:document.body,ctx:e.ctx,props:e.props??{},complete:c,fail:i},Promise.resolve(s(t)).catch(a=>i(a?.message??String(a)))):e.type==="update"&&t&&(t={...t,props:{...t.props,...e.props}},Promise.resolve(s(t)).catch(a=>i(a?.message??String(a)))))}),window.parent?.postMessage({aikaara:r,type:"ready"},"*")}function d(s){p(s)}exports.initRemoteAuthor=p;exports.mount=d;
@@ -0,0 +1,62 @@
1
+ export declare interface AuthorMountArgs {
2
+ /** DOM node to render into — the iframe's `document.body`. */
3
+ target: HTMLElement;
4
+ /** Snapshot of host state at bootstrap time. */
5
+ ctx: RemoteAuthorContext | undefined;
6
+ /** Tenant-supplied props from `descriptor.components[slot].props`. */
7
+ props: Record<string, unknown>;
8
+ /** Signal flow completion. Host receives via its `onComplete` callback. */
9
+ complete: (payload: unknown) => void;
10
+ /** Surface a tenant error to the host. */
11
+ fail: (message: string) => void;
12
+ }
13
+
14
+ /**
15
+ * Wire up the host protocol and call `render` once bootstrap arrives.
16
+ * Subsequent host `update` messages re-invoke `render` so the bundle can
17
+ * re-render with new props (or just accept the changes if React-managed).
18
+ */
19
+ export declare function initRemoteAuthor(render: Renderer): void;
20
+
21
+ /** Convenience wrapper for the common "render once, ignore updates" case. */
22
+ export declare function mount(render: Renderer): void;
23
+
24
+ /**
25
+ * `@aikaara/chat-sdk/remote-author` — tiny tenant-side helper.
26
+ *
27
+ * Pull this into a tenant component bundle. The bundle, when loaded by the
28
+ * shell's RemoteComponentLoader (kind: 'remote-dom'), runs inside a
29
+ * sandboxed iframe. It needs to:
30
+ *
31
+ * 1. Tell the host it's ready.
32
+ * 2. Receive a `bootstrap` message carrying `ctx` + `props`.
33
+ * 3. Render whatever it wants into `document.body`.
34
+ * 4. Optionally call `complete(payload)` to signal the flow finished.
35
+ *
36
+ * This module wraps that protocol so tenants don't have to write
37
+ * postMessage boilerplate. They write a `mount(target, ctx, complete, props)`
38
+ * function (or just call `init(...)` with a render callback).
39
+ *
40
+ * Framework-agnostic: works with React, Preact, Svelte, Vue, vanilla JS.
41
+ *
42
+ * @example React
43
+ * import { initRemoteAuthor } from '@aikaara/chat-sdk/remote-author';
44
+ * import { createRoot } from 'react-dom/client';
45
+ * import LoginScreen from './LoginScreen';
46
+ *
47
+ * initRemoteAuthor(({ target, ctx, complete, props }) => {
48
+ * createRoot(target).render(
49
+ * <LoginScreen ctx={ctx} complete={complete} {...props} />
50
+ * );
51
+ * });
52
+ */
53
+ export declare interface RemoteAuthorContext {
54
+ slug: string;
55
+ theme?: Record<string, unknown>;
56
+ identity?: Record<string, unknown>;
57
+ extras?: Record<string, unknown>;
58
+ }
59
+
60
+ declare type Renderer = (args: AuthorMountArgs) => void | Promise<void>;
61
+
62
+ export { }
@@ -0,0 +1,31 @@
1
+ function n(s) {
2
+ let r = !1, t = null;
3
+ const i = (a) => {
4
+ window.parent?.postMessage(
5
+ { aikaara: 1, type: "complete", payload: a },
6
+ "*"
7
+ );
8
+ }, p = (a) => {
9
+ window.parent?.postMessage(
10
+ { aikaara: 1, type: "error", message: a },
11
+ "*"
12
+ );
13
+ };
14
+ window.addEventListener("message", (a) => {
15
+ const e = a.data;
16
+ !e || e.aikaara !== 1 || (e.type === "bootstrap" && !r ? (r = !0, t = {
17
+ target: document.body,
18
+ ctx: e.ctx,
19
+ props: e.props ?? {},
20
+ complete: i,
21
+ fail: p
22
+ }, Promise.resolve(s(t)).catch((o) => p(o?.message ?? String(o)))) : e.type === "update" && t && (t = { ...t, props: { ...t.props, ...e.props } }, Promise.resolve(s(t)).catch((o) => p(o?.message ?? String(o)))));
23
+ }), window.parent?.postMessage({ aikaara: 1, type: "ready" }, "*");
24
+ }
25
+ function O(s) {
26
+ n(s);
27
+ }
28
+ export {
29
+ n as initRemoteAuthor,
30
+ O as mount
31
+ };
@@ -0,0 +1,3 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=new Map;async function d(e,r){switch(e.kind){case"iife-element":return p(e,r);case"remote-dom":return w(e,r);default:{const t=e;throw new Error(`loadRemoteComponent: unknown kind ${JSON.stringify(t)}`)}}}async function p(e,r){customElements.get(e.tag)||(await f(e.scriptUrl),await h(e.tag));const t=document.createElement(e.tag);return c(t,e.props),c(t,r.props),r.ctx&&c(t,{setCtx:r.ctx}),r.onComplete&&t.addEventListener("complete",n=>r.onComplete?.(n.detail)),r.onError&&t.addEventListener("error",n=>r.onError?.(n.error??new Error("component error"))),r.target.appendChild(t),{el:t,unmount(){t.remove()},update(n){c(t,n)}}}function c(e,r){if(r)for(const[t,n]of Object.entries(r)){const s=e[t];if(typeof s=="function")try{s.call(e,n)}catch(o){console.warn(`[RemoteComponentLoader] ${t}() threw`,o)}}}function f(e){const r=u.get(e);if(r)return r;const t=new Promise((n,s)=>{const o=document.createElement("script");o.src=e,o.async=!0,o.onload=()=>n(),o.onerror=()=>s(new Error(`Failed to load script ${e}`)),document.head.appendChild(o)});return u.set(e,t),t}function h(e,r=5e3){return customElements.get(e)?Promise.resolve():Promise.race([customElements.whenDefined(e).then(()=>{}),new Promise((t,n)=>{setTimeout(()=>n(new Error(`Custom element <${e}> never registered`)),r)})])}const l=1;function w(e,r){const t=document.createElement("iframe");t.setAttribute("sandbox","allow-scripts allow-same-origin allow-forms allow-popups"),t.style.cssText="width:100%;height:100%;border:0;display:block;background:transparent;",t.setAttribute("title",`aikaara-remote:${e.globalName??e.scriptUrl}`);const n=[],s=a=>t.contentWindow?.postMessage(a,"*");let o=!1;const m=a=>{if(a.source!==t.contentWindow)return;const i=a.data;!i||i.aikaara!==l||(i.type==="ready"?s({aikaara:l,type:"bootstrap",ctx:r.ctx,props:{...e.props??{},...r.props??{}}}):i.type==="complete"?r.onComplete?.(i.payload):i.type==="error"&&r.onError?.(new Error(i.message)))};return window.addEventListener("message",m),n.push(()=>window.removeEventListener("message",m)),t.srcdoc=`<!doctype html><html><head><meta charset="utf-8">
2
+ <style>html,body{margin:0;padding:0;height:100%;background:transparent;}</style>
3
+ </head><body><script src="${g(e.scriptUrl)}" defer><\/script></body></html>`,r.target.appendChild(t),{el:t,unmount(){if(!o){o=!0;for(const a of n)try{a()}catch{}t.remove()}},update(a){s({aikaara:l,type:"update",props:a})}}}function g(e){return e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;")}exports.loadRemoteComponent=d;
@@ -0,0 +1,68 @@
1
+ export declare interface LoadOptions {
2
+ /** Where the rendered element should be inserted. */
3
+ target: HTMLElement;
4
+ /** Forwarded to the tenant component. */
5
+ props?: Record<string, unknown>;
6
+ /** Forwarded as the `ctx` payload (read-only state from host). */
7
+ ctx?: RemoteHostContext;
8
+ /** Tenant components call this to signal a flow step finished
9
+ * (e.g. screen:login → onComplete({ext_uid, token})). */
10
+ onComplete?: (payload: unknown) => void;
11
+ /** Tenant component error → host can show a banner / fall back. */
12
+ onError?: (err: Error) => void;
13
+ }
14
+
15
+ /** Load + mount one slot's component. Returns a handle for tear-down. */
16
+ export declare function loadRemoteComponent(def: RemoteComponent, opts: LoadOptions): Promise<MountedComponent>;
17
+
18
+ export declare interface MountedComponent {
19
+ /** The DOM node added to `target` (custom element or iframe). */
20
+ el: HTMLElement;
21
+ /** Tear down + remove from DOM. Idempotent. */
22
+ unmount(): void;
23
+ /** Push a new `props` payload to the mounted component. */
24
+ update(props: Record<string, unknown>): void;
25
+ }
26
+
27
+ /**
28
+ * One slot's component pointer. The `kind` discriminator picks which
29
+ * loader runs. Both kinds resolve to a `Promise<HTMLElement>` after load,
30
+ * which the runtime appends into the slot anchor.
31
+ */
32
+ export declare type RemoteComponent = {
33
+ kind: 'iife-element';
34
+ /** URL of an IIFE bundle that calls `customElements.define(tag, …)`. */
35
+ scriptUrl: string;
36
+ /** Custom-element tag the bundle registers. */
37
+ tag: string;
38
+ /** Optional method-call map: `{ setLayout: "stacked" }` becomes
39
+ * `el.setLayout("stacked")` after mount. */
40
+ props?: Record<string, unknown>;
41
+ } | {
42
+ kind: 'remote-dom';
43
+ /** URL of an IIFE bundle that, when executed, leaves a global at
44
+ * `globalName` exposing `mount({ target, ctx, complete, props })`.
45
+ * Authored via `@aikaara/chat-sdk/remote-author`. */
46
+ scriptUrl: string;
47
+ /** Optional global name; defaults to the slot id with non-alphanumeric
48
+ * chars replaced by underscores (e.g. "screen:login" → "screen_login"). */
49
+ globalName?: string;
50
+ /** Sandbox kind. Today only `iframe`; `worker` reserved for later. */
51
+ sandbox?: 'iframe' | 'worker';
52
+ /** Forwarded to the bundle's `mount({ props })` call. */
53
+ props?: Record<string, unknown>;
54
+ };
55
+
56
+ export declare interface RemoteHostContext {
57
+ /** Project slug currently mounted. */
58
+ slug: string;
59
+ /** Theme tokens from descriptor.theme — passed for tenant components
60
+ * to render in-brand without re-fetching the descriptor. */
61
+ theme?: Record<string, unknown>;
62
+ /** Identity bag (already-resolved user info). */
63
+ identity?: Record<string, unknown>;
64
+ /** Free-form: descriptor block(s) the tenant component might need. */
65
+ extras?: Record<string, unknown>;
66
+ }
67
+
68
+ export { }
@@ -0,0 +1,104 @@
1
+ const u = /* @__PURE__ */ new Map();
2
+ async function g(e, r) {
3
+ switch (e.kind) {
4
+ case "iife-element":
5
+ return p(e, r);
6
+ case "remote-dom":
7
+ return h(e, r);
8
+ default: {
9
+ const t = e;
10
+ throw new Error(`loadRemoteComponent: unknown kind ${JSON.stringify(t)}`);
11
+ }
12
+ }
13
+ }
14
+ async function p(e, r) {
15
+ customElements.get(e.tag) || (await d(e.scriptUrl), await f(e.tag));
16
+ const t = document.createElement(e.tag);
17
+ return i(t, e.props), i(t, r.props), r.ctx && i(t, { setCtx: r.ctx }), r.onComplete && t.addEventListener("complete", (n) => r.onComplete?.(n.detail)), r.onError && t.addEventListener("error", (n) => r.onError?.(n.error ?? new Error("component error"))), r.target.appendChild(t), {
18
+ el: t,
19
+ unmount() {
20
+ t.remove();
21
+ },
22
+ update(n) {
23
+ i(t, n);
24
+ }
25
+ };
26
+ }
27
+ function i(e, r) {
28
+ if (r)
29
+ for (const [t, n] of Object.entries(r)) {
30
+ const s = e[t];
31
+ if (typeof s == "function")
32
+ try {
33
+ s.call(e, n);
34
+ } catch (o) {
35
+ console.warn(`[RemoteComponentLoader] ${t}() threw`, o);
36
+ }
37
+ }
38
+ }
39
+ function d(e) {
40
+ const r = u.get(e);
41
+ if (r) return r;
42
+ const t = new Promise((n, s) => {
43
+ const o = document.createElement("script");
44
+ o.src = e, o.async = !0, o.onload = () => n(), o.onerror = () => s(new Error(`Failed to load script ${e}`)), document.head.appendChild(o);
45
+ });
46
+ return u.set(e, t), t;
47
+ }
48
+ function f(e, r = 5e3) {
49
+ return customElements.get(e) ? Promise.resolve() : Promise.race([
50
+ customElements.whenDefined(e).then(() => {
51
+ }),
52
+ new Promise((t, n) => {
53
+ setTimeout(() => n(new Error(`Custom element <${e}> never registered`)), r);
54
+ })
55
+ ]);
56
+ }
57
+ const l = 1;
58
+ function h(e, r) {
59
+ const t = document.createElement("iframe");
60
+ t.setAttribute(
61
+ "sandbox",
62
+ // Restrictive set: scripts (run the bundle), same-origin (so the
63
+ // bundle can use localStorage/cookies on its own srcdoc origin),
64
+ // forms (login submits), popups (when tenant code opens external
65
+ // links). NOT allow-top-navigation — the bundle can't break out.
66
+ "allow-scripts allow-same-origin allow-forms allow-popups"
67
+ ), t.style.cssText = "width:100%;height:100%;border:0;display:block;background:transparent;", t.setAttribute("title", `aikaara-remote:${e.globalName ?? e.scriptUrl}`);
68
+ const n = [], s = (a) => t.contentWindow?.postMessage(a, "*");
69
+ let o = !1;
70
+ const m = (a) => {
71
+ if (a.source !== t.contentWindow) return;
72
+ const c = a.data;
73
+ !c || c.aikaara !== l || (c.type === "ready" ? s({
74
+ aikaara: l,
75
+ type: "bootstrap",
76
+ ctx: r.ctx,
77
+ props: { ...e.props ?? {}, ...r.props ?? {} }
78
+ }) : c.type === "complete" ? r.onComplete?.(c.payload) : c.type === "error" && r.onError?.(new Error(c.message)));
79
+ };
80
+ return window.addEventListener("message", m), n.push(() => window.removeEventListener("message", m)), t.srcdoc = `<!doctype html><html><head><meta charset="utf-8">
81
+ <style>html,body{margin:0;padding:0;height:100%;background:transparent;}</style>
82
+ </head><body><script src="${w(e.scriptUrl)}" defer><\/script></body></html>`, r.target.appendChild(t), {
83
+ el: t,
84
+ unmount() {
85
+ if (!o) {
86
+ o = !0;
87
+ for (const a of n) try {
88
+ a();
89
+ } catch {
90
+ }
91
+ t.remove();
92
+ }
93
+ },
94
+ update(a) {
95
+ s({ aikaara: l, type: "update", props: a });
96
+ }
97
+ };
98
+ }
99
+ function w(e) {
100
+ return e.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;");
101
+ }
102
+ export {
103
+ g as loadRemoteComponent
104
+ };
package/dist/ui.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("./MountTenant-BrBxPpjb.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;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("./MountTenant-DvmiAoZ_.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.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { B as i, a as s, c as e, d as t, e as A, D as k, f as n, F as o, g, h as l, G as d, H as m, i as p, I as C, J as h, K as b, j as M, r as c } from "./MountTenant-BVimPLfY.mjs";
1
+ import { B as i, a as s, c as e, d as t, e as A, D as k, f as n, F as o, g, h as l, G as d, H as m, i as p, I as C, J as h, K as b, j as M, r as c } from "./MountTenant-DzNgBTiU.mjs";
2
2
  export {
3
3
  i as AikaaraChat,
4
4
  s as AikaaraChatBubble,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aikaara/chat-sdk",
3
- "version": "0.8.1",
3
+ "version": "0.8.2",
4
4
  "type": "module",
5
5
  "description": "Aikaara Chat SDK — embeddable chat widget and headless client",
6
6
  "license": "MIT",
@@ -19,6 +19,16 @@
19
19
  "types": "./dist/ui.d.ts",
20
20
  "import": "./dist/ui.mjs",
21
21
  "require": "./dist/ui.cjs"
22
+ },
23
+ "./remote-host": {
24
+ "types": "./dist/remote-host.d.ts",
25
+ "import": "./dist/remote-host.mjs",
26
+ "require": "./dist/remote-host.cjs"
27
+ },
28
+ "./remote-author": {
29
+ "types": "./dist/remote-author.d.ts",
30
+ "import": "./dist/remote-author.mjs",
31
+ "require": "./dist/remote-author.cjs"
22
32
  }
23
33
  },
24
34
  "main": "./dist/index.cjs",