@aikaara/chat-sdk 0.3.3 → 0.4.1

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 s=require("./ui-B0-Np9Dn.cjs");class x extends s.EventEmitter{registration=null;pendingEdits=[];constructor(e){super(),this.setupListeners(e)}registerForm(e){this.registration=e;const r=this.pendingEdits.filter(i=>i.entity_type===e.entityType&&String(i.entity_id)===String(e.entityId));if(r.length>0){for(const i of r)e.onFieldUpdate(i.fields),this.emit("edit:applied",{entityType:i.entity_type,entityId:i.entity_id,fields:i.fields});this.pendingEdits=this.pendingEdits.filter(i=>!(i.entity_type===e.entityType&&String(i.entity_id)===String(e.entityId)))}}unregisterForm(e,r){this.registration?.entityType===e&&String(this.registration?.entityId)===String(r)&&(this.registration=null)}get currentForm(){return this.registration}pushFieldUpdates(e,r,i){this.registration&&this.registration.entityType===e&&String(this.registration.entityId)===String(r)?(this.registration.onFieldUpdate(i),this.emit("edit:applied",{entityType:e,entityId:r,fields:i})):(this.pendingEdits.push({action:"edit_entity",entity_type:e,entity_id:r,fields:i}),this.emit("edit:pending",{entityType:e,entityId:r,fields:i}))}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 r=e instanceof Error?e.message:"Save failed";return this.emit("save:error",{entityType:this.registration.entityType,entityId:this.registration.entityId,error:r}),{success:!1,error:r}}}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(r){return{success:!1,error:r instanceof Error?r.message:"Test failed"}}}setupListeners(e){e.on("action:edit_entity",r=>{this.pushFieldUpdates(r.entity_type,r.entity_id,r.fields)}),e.on("action:save_entity",r=>{this.requestSave()}),e.on("action:test_tool",r=>{this.emit("test:triggered",{toolId:r.tool_id,parameters:r.parameters}),this.requestTest(r.parameters)})}}function I(t){return{async upload(e,r){const i=new FormData,o=t.fieldName??"file";i.append(o,e,e.name);const a=typeof t.extraFields=="function"?t.extraFields(r):t.extraFields;if(a)for(const[h,f]of Object.entries(a))i.append(h,f);i.append("conversationId",r.conversationId),i.append("userId",r.userId),r.projectId&&i.append("projectId",r.projectId);const d=typeof t.headers=="function"?await t.headers():t.headers??{},u=await fetch(t.endpoint,{method:t.method??"POST",body:i,headers:d,credentials:t.credentials});if(!u.ok)throw new Error(`Upload failed: ${u.status} ${u.statusText}`);const l=await u.json().catch(()=>({}));if(t.parseResponse)return t.parseResponse(l,r);const n=l,c=n.url??n.fileUrl??n.publicUrl,y=n.fileName??n.name??e.name;if(!c)throw new Error('Upload response missing "url" / "fileUrl" / "publicUrl"');return{url:c,fileName:y,cloudFileId:typeof n.cloudFileId=="string"?n.cloudFileId:void 0,relativePath:typeof n.path=="string"?n.path:void 0,contentType:typeof n.contentType=="string"?n.contentType:void 0,byteSize:typeof n.byteSize=="number"?n.byteSize:void 0,meta:n}}}}const S="/tilechat/{userId}/conversations/{conversationId}/messages?pageSize={pageSize}";function T(t){const e=t.apiBase.replace(/\/$/,""),r=t.pageSize??200,i=t.pathTemplate??S;return{async fetchMessages(o,a){const d=i.replace("{userId}",encodeURIComponent(a.userId)).replace("{conversationId}",encodeURIComponent(o)).replace("{appId}",encodeURIComponent(a.appId??"tilechat")).replace("{projectId}",encodeURIComponent(a.projectId??"")).replace("{pageSize}",String(r)),u=d.startsWith("http")?d:`${e}${d.startsWith("/")?d:`/${d}`}`,l={accept:"application/json","content-type":"application/json",...t.extraHeaders??{}};if(t.getToken){const h=await t.getToken();h&&(l.authorization=h)}const n=await fetch(u,{method:"GET",headers:l,credentials:"include"}),c=await n.json().catch(()=>null);if(t.parseResponse&&c)return t.parseResponse(c);const y=c;if(y&&Array.isArray(y.result))return y.result;if(!n.ok)throw new Error(`History fetch failed: ${n.status} ${n.statusText}`);return[]}}}function w(){const t=typeof crypto<"u"?crypto:null;if(t?.randomUUID)return t.randomUUID();if(t?.getRandomValues){const e=new Uint8Array(16);t.getRandomValues(e),e[6]=e[6]&15|64,e[8]=e[8]&63|128;const r=[...e].map(i=>i.toString(16).padStart(2,"0")).join("");return`${r.slice(0,8)}-${r.slice(8,12)}-${r.slice(12,16)}-${r.slice(16,20)}-${r.slice(20)}`}return"xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx".replace(/[xy]/g,e=>{const r=Math.random()*16|0;return(e==="x"?r:r&3|8).toString(16)})}const k="aikaara_chat:requestId";function g(t,e){return`${k}:${t}:${e}`}function b(t,e){try{return localStorage.getItem(g(t,e))}catch{return null}}function E(t,e,r){try{localStorage.setItem(g(t,e),r)}catch{}}function A(t,e){try{localStorage.removeItem(g(t,e))}catch{}}async function C(t,e){const r=await fetch(t,{method:"GET",headers:{accept:"application/json",...e??{}}});if(!r.ok){const o=await r.text().catch(()=>"");throw new Error(`Widget config fetch failed: ${r.status} ${r.statusText} ${o.slice(0,200)}`)}const i=await r.json();if(i&&typeof i=="object"){if("config"in i)return i.config;if("data"in i)return i.data}return i}function F(t,e){return t.replace("{projectId}",e).replace("{uuid}",w().replace(/-/g,""))}async function U(t){const e={...t.config??(t.configUrl?await C(t.configUrl,t.configHeaders):{}),...t.overrides??{}},r=e.transport??"tiledesk",i=e.tiledesk;if((r==="tiledesk"||r==="dual")&&!i)throw new Error("mount: descriptor.tiledesk is required for tiledesk/dual transport");const o=i?.projectId??"",a=t.identity.userId,d=t.forceNewConversation?null:b(a,o),u=i?.requestIdTemplate??"support-group-{projectId}-{uuid}",l=t.conversationId??d??F(u,o);(!d||t.forceNewConversation)&&o&&E(a,o,l);const n=await t.tokenProvider(),c=t.tokenProvider,y=t.historyTokenProvider??c,h=i?{mqttEndpoint:i.mqttEndpoint,jwtToken:n,userId:a,userName:t.identity.userName,projectId:i.projectId,appId:i.appId,mqttUsername:i.mqttUsername,protocolId:i.protocolId,protocolVersion:i.protocolVersion,keepAliveSec:i.keepAliveSec,connectTimeoutMs:i.connectTimeoutMs,maxReconnectAttempts:i.maxReconnectAttempts,reconnectMaxDelayMs:i.reconnectMaxDelayMs,wildcardSubscribe:i.wildcardSubscribe,enablePresence:i.enablePresence,autoInitiateOnEmpty:i.autoInitiateOnEmpty,chatInitiatedAttributes:i.chatInitiatedAttributes,messageDefaults:{...i.messageDefaults,...t.identity.departmentId?{departmentId:t.identity.departmentId}:i.messageDefaults?.departmentId?{departmentId:i.messageDefaults.departmentId}:{}},fileTemplate:i.fileTemplate,topicTemplates:i.topicTemplates,debug:i.debug,senderFullname:t.identity.senderFullname??t.identity.userName,tokenProvider:c}:void 0,f=t.uploadAdapter??(e.uploadEndpoint?I({endpoint:e.uploadEndpoint,fieldName:e.uploadFieldName,extraFields:e.uploadExtraFields}):void 0),v=t.historyAdapter??(e.historyApiBase?T({apiBase:e.historyApiBase,pageSize:e.historyPageSize??200,pathTemplate:e.historyPathTemplate,getToken:y}):void 0),p={transport:r,baseUrl:"",userToken:a,conversationId:l,display:e.display??"embed",position:e.position,primaryColor:e.primaryColor,title:e.title,subtitle:e.subtitle,avatarUrl:e.avatarUrl,width:e.width,height:e.height,borderRadius:e.borderRadius,fontFamily:e.fontFamily,welcomeMessage:e.welcomeMessage,placeholder:e.placeholder,showTimestamps:e.showTimestamps,persistConversation:e.persistConversation,tiledesk:h,tiledeskIdentity:{userId:a,userName:t.identity.userName,departmentId:t.identity.departmentId,senderFullname:t.identity.senderFullname??t.identity.userName},templateActionAttributes:e.templateActionAttributes,uploadAdapter:f,historyAdapter:v,onError:t.onError},m=document.createElement("aikaara-chat-widget");return m.configure(p),p.title&&m.setAttribute("title",p.title),p.primaryColor&&m.setAttribute("primary-color",p.primaryColor),p.display&&m.setAttribute("display",p.display),p.display==="embed"&&(m.style.cssText="display:flex;flex-direction:column;width:100%;height:100%;min-height:0;"),t.container.appendChild(m),{widget:m,requestId:l,config:p,destroy(){m.remove()}}}exports.ActionCableClient=s.ActionCableClient;exports.AikaaraChatClient=s.AikaaraChatClient;exports.ApiClient=s.ApiClient;exports.ChannelSubscription=s.ChannelSubscription;exports.ConnectionManager=s.ConnectionManager;exports.ConversationManager=s.ConversationManager;exports.EventEmitter=s.EventEmitter;exports.MessageStore=s.MessageStore;exports.TiledeskTransport=s.TiledeskTransport;exports.extractTiledeskFileEnvelope=s.extractTiledeskFileEnvelope;exports.inferTiledeskRole=s.inferTiledeskRole;exports.isTiledeskSelfEcho=s.isTiledeskSelfEcho;exports.parseTiledeskTemplate=s.parseTiledeskTemplate;exports.FormBridge=x;exports.clearPersistedConversationId=A;exports.createFetchUploadAdapter=I;exports.createTiledeskHistoryAdapter=T;exports.mountTenantWidget=U;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./MountTenant-B4Py61gI.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;
@@ -514,6 +514,8 @@ declare interface CreateConversationResponse {
514
514
 
515
515
  export declare function createFetchUploadAdapter(config: FetchUploadAdapterConfig): UploadAdapter;
516
516
 
517
+ export declare function createPresigned3StepUploadAdapter(config: Presigned3StepAdapterConfig): UploadAdapter;
518
+
517
519
  export declare function createTiledeskHistoryAdapter(config: TiledeskHistoryAdapterConfig): ConversationHistoryAdapter;
518
520
 
519
521
  export declare interface EditEntityAction {
@@ -789,6 +791,22 @@ export declare interface MountedTenantWidget {
789
791
  destroy: () => void;
790
792
  }
791
793
 
794
+ /**
795
+ * Single-call mount. Pulls the descriptor from `widget_configs/:slug`, runs
796
+ * descriptor.auth to mint chat JWT + requestId, builds upload + history
797
+ * adapters from descriptor.upload, and mounts the web component. Host app
798
+ * supplies only the user id + their session JWT.
799
+ *
800
+ * import { mountFromSlug } from '@aikaara/chat-sdk';
801
+ *
802
+ * await mountFromSlug({
803
+ * container: '#chat',
804
+ * slug: 'bandhan-itr',
805
+ * user: { id: '33568', token: () => getCognitoJwt() },
806
+ * });
807
+ */
808
+ export declare function mountFromSlug(opts: SlugMountOptions): Promise<SlugMountedWidget>;
809
+
792
810
  /**
793
811
  * Standard tenant mount. Fetches the descriptor (when `configUrl` is set),
794
812
  * merges per-mount overrides, builds default adapters from the descriptor's
@@ -806,6 +824,39 @@ declare interface NavigateAction_2 {
806
824
 
807
825
  export declare function parseTiledeskTemplate(message: TiledeskMessage): TiledeskParsedTemplate;
808
826
 
827
+ /**
828
+ * Three-step presigned-S3 upload (sign → PUT → register). Driven entirely
829
+ * by descriptor — no tenant-specific code in host apps.
830
+ */
831
+ export declare interface Presigned3StepAdapterConfig {
832
+ /** GET endpoint that returns a presigned URL. `{fileName}` placeholder. */
833
+ signEndpoint: string;
834
+ signMethod?: 'GET' | 'POST';
835
+ /** Dot path into the response JSON for the presigned URL. Default `data.s3SignedUrl`. */
836
+ signedUrlPath?: string;
837
+ /** Optional POST registering the upload (e.g. `/chatbuddy/file-upload`). */
838
+ registerEndpoint?: string;
839
+ /**
840
+ * Body JSON for the register POST. Tokens: `{fileName}`, `{userId}`,
841
+ * `{requestId}` (alias `{conversationId}`).
842
+ */
843
+ registerBody?: Record<string, unknown>;
844
+ /**
845
+ * Final URL the chat message will carry. Tokens: `{fileName}`, `{userId}`,
846
+ * `{requestId}`. When omitted the presigned URL itself is used.
847
+ */
848
+ viewerTemplate?: string;
849
+ /**
850
+ * Rewrite the host portion of the presigned URL before PUTting (used for
851
+ * dev proxies). E.g. `/s3-upload`. Leave empty for direct.
852
+ */
853
+ s3HostRewrite?: string;
854
+ /** Bearer token getter for sign + register calls. */
855
+ authHeader?: () => string | Promise<string>;
856
+ /** Static extra headers for sign + register. */
857
+ extraHeaders?: Record<string, string>;
858
+ }
859
+
809
860
  export declare interface SaveEntityAction {
810
861
  action: 'save_entity';
811
862
  }
@@ -814,6 +865,108 @@ declare interface SaveEntityAction_2 {
814
865
  action: 'save_entity';
815
866
  }
816
867
 
868
+ export declare class SessionAuthAdapter {
869
+ private readonly descriptor;
870
+ private readonly sessionToken;
871
+ private cache;
872
+ private inflight;
873
+ constructor(descriptor: SessionAuthDescriptor, sessionToken: SessionTokenProvider);
874
+ /** Force-refresh by clearing cache. Next `get()` call refetches. */
875
+ reset(): void;
876
+ get(): Promise<SessionAuthData>;
877
+ private fetchOnce;
878
+ }
879
+
880
+ export declare interface SessionAuthData {
881
+ token: string;
882
+ requestId: string;
883
+ fullName: string;
884
+ expiresAt: number;
885
+ }
886
+
887
+ /**
888
+ * Descriptor-driven session auth.
889
+ *
890
+ * The host app supplies a "session token" — typically a JWT issued by their
891
+ * own auth (Cognito/Auth0/firebase/etc) — and the descriptor declares how to
892
+ * exchange it for a chat-platform JWT + conversation requestId. The SDK runs
893
+ * the exchange itself, caches the result, and refreshes when the chat JWT
894
+ * approaches expiry. The original requestId is preserved across refreshes so
895
+ * the conversation thread is stable.
896
+ */
897
+ export declare interface SessionAuthDescriptor {
898
+ /** Absolute or same-origin URL — POSTed with the session token as bearer. */
899
+ endpoint: string;
900
+ method?: 'POST' | 'GET';
901
+ /** JSON body for the request. POST only. */
902
+ body?: Record<string, unknown>;
903
+ /** Extra static headers (e.g. partnerid). */
904
+ headers?: Record<string, string>;
905
+ /** Header carrying the session token. Default `Authorization`. */
906
+ authHeader?: string;
907
+ /**
908
+ * Template for the session-token header value. `{token}` is replaced.
909
+ * Default: `Bearer {token}`. Use `JWT {token}` etc. when required.
910
+ */
911
+ authHeaderTemplate?: string;
912
+ /** Dot path into the response JSON for the chat JWT. Default `data.token`. */
913
+ tokenPath?: string;
914
+ /** Stripped from the extracted token before use (e.g. `JWT `). */
915
+ tokenStripPrefix?: string;
916
+ /** Dot path for the conversation requestId. Default `data.requestId`. */
917
+ requestIdPath?: string;
918
+ /** Dot path for the user display name. Default `data.fullName`. */
919
+ fullNamePath?: string;
920
+ /** Refetch when the JWT is within this many ms of expiry. Default 60_000. */
921
+ expiryBufferMs?: number;
922
+ }
923
+
924
+ export declare type SessionTokenProvider = string | (() => string | Promise<string>);
925
+
926
+ export declare interface SlugMountedWidget extends MountedTenantWidget {
927
+ fullName: string;
928
+ /** Force a fresh /chatbuddy/auth-style refetch (clears cached requestId). */
929
+ refreshAuth(): Promise<void>;
930
+ }
931
+
932
+ export declare interface SlugMountOptions {
933
+ /** Container element or CSS selector (e.g. `#chat`). */
934
+ container: HTMLElement | string;
935
+ /** Tenant identifier — the SDK fetches `${configBase}/widget_configs/${slug}`. */
936
+ slug: string;
937
+ /** Defaults to `https://api.aikaara.com`. Override for self-hosted aikaara. */
938
+ configBase?: string;
939
+ /** Additional headers for the descriptor fetch. */
940
+ configHeaders?: Record<string, string>;
941
+ user: {
942
+ id: string;
943
+ /** Display name fallback when descriptor.auth doesn't return one. */
944
+ name?: string;
945
+ departmentId?: string;
946
+ /**
947
+ * Session JWT (Cognito/Auth0/firebase/etc) — passed as bearer to
948
+ * `descriptor.auth.endpoint`. Can be a string (static for the session)
949
+ * or a getter that re-resolves on each refresh.
950
+ */
951
+ token: SessionTokenProvider;
952
+ };
953
+ /** Optional escape hatches; merge over descriptor-driven defaults. */
954
+ hooks?: {
955
+ upload?: UploadAdapter;
956
+ history?: ConversationHistoryAdapter;
957
+ onError?: (err: Error) => void;
958
+ };
959
+ /** Per-mount visual overrides. */
960
+ overrides?: Partial<WidgetConfigDescriptor>;
961
+ /**
962
+ * Inline descriptor used when the slug fetch fails (e.g. 404, network
963
+ * error). Lets host apps ship without requiring the aikaara backend to be
964
+ * seeded — useful for demos / first-run / offline dev. When the fetch
965
+ * succeeds the response wins; this is purely a safety net.
966
+ */
967
+ fallbackConfig?: WidgetConfigDescriptor;
968
+ }
969
+
817
970
  declare type SubscriptionCallback = (data: unknown) => void;
818
971
 
819
972
  declare interface TemplateMessageEvent {
@@ -1358,6 +1511,28 @@ export declare interface WidgetConfigDescriptor {
1358
1511
  historyApiBase?: string;
1359
1512
  historyPageSize?: number;
1360
1513
  historyPathTemplate?: string;
1514
+ /**
1515
+ * Server-side session-token exchange. When set, the SDK exchanges the
1516
+ * caller-supplied `sessionToken` for a chat JWT + conversation requestId
1517
+ * itself — the host app no longer needs a `tokenProvider` callback.
1518
+ */
1519
+ auth?: SessionAuthDescriptor;
1520
+ /**
1521
+ * Built-in upload strategy. `mode: "presigned-3step"` runs sign → PUT →
1522
+ * register entirely from descriptor config; `mode: "direct"` POSTs as
1523
+ * multipart to a single endpoint; `mode: "none"` disables uploads. Host
1524
+ * apps can still override with `opts.uploadAdapter`.
1525
+ */
1526
+ upload?: {
1527
+ mode: 'none';
1528
+ } | {
1529
+ mode: 'direct';
1530
+ endpoint: string;
1531
+ fieldName?: string;
1532
+ extraFields?: Record<string, string>;
1533
+ } | ({
1534
+ mode: 'presigned-3step';
1535
+ } & Presigned3StepAdapterConfig);
1361
1536
  }
1362
1537
 
1363
1538
  export { }
package/dist/headless.mjs CHANGED
@@ -1,37 +1,37 @@
1
- import { E as I } from "./ui-BMGa0gZH.mjs";
2
- import { A as $, b as q, k as N, C as M, l as P, m as D, M as z, T as B, n as H, o as O, p as V, q as W } from "./ui-BMGa0gZH.mjs";
3
- class F extends I {
1
+ import { E as s } from "./MountTenant-DT5Vr6Yr.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-DT5Vr6Yr.mjs";
3
+ class a extends s {
4
4
  registration = null;
5
5
  pendingEdits = [];
6
- constructor(e) {
7
- super(), this.setupListeners(e);
6
+ constructor(t) {
7
+ super(), this.setupListeners(t);
8
8
  }
9
9
  /**
10
10
  * Register a form to receive AI-driven edits.
11
11
  * Only one form can be registered at a time (the active page).
12
12
  */
13
- registerForm(e) {
14
- this.registration = e;
15
- const r = this.pendingEdits.filter(
16
- (i) => i.entity_type === e.entityType && String(i.entity_id) === String(e.entityId)
13
+ registerForm(t) {
14
+ this.registration = t;
15
+ const e = this.pendingEdits.filter(
16
+ (i) => i.entity_type === t.entityType && String(i.entity_id) === String(t.entityId)
17
17
  );
18
- if (r.length > 0) {
19
- for (const i of r)
20
- e.onFieldUpdate(i.fields), this.emit("edit:applied", {
18
+ if (e.length > 0) {
19
+ for (const i of e)
20
+ t.onFieldUpdate(i.fields), this.emit("edit:applied", {
21
21
  entityType: i.entity_type,
22
22
  entityId: i.entity_id,
23
23
  fields: i.fields
24
24
  });
25
25
  this.pendingEdits = this.pendingEdits.filter(
26
- (i) => !(i.entity_type === e.entityType && String(i.entity_id) === String(e.entityId))
26
+ (i) => !(i.entity_type === t.entityType && String(i.entity_id) === String(t.entityId))
27
27
  );
28
28
  }
29
29
  }
30
30
  /**
31
31
  * Unregister the form (call on unmount).
32
32
  */
33
- unregisterForm(e, r) {
34
- this.registration?.entityType === e && String(this.registration?.entityId) === String(r) && (this.registration = null);
33
+ unregisterForm(t, e) {
34
+ this.registration?.entityType === t && String(this.registration?.entityId) === String(e) && (this.registration = null);
35
35
  }
36
36
  /**
37
37
  * Get the current form registration (if any).
@@ -42,13 +42,13 @@ class F extends I {
42
42
  /**
43
43
  * Manually push field updates (for custom tool handling).
44
44
  */
45
- pushFieldUpdates(e, r, i) {
46
- this.registration && this.registration.entityType === e && String(this.registration.entityId) === String(r) ? (this.registration.onFieldUpdate(i), this.emit("edit:applied", { entityType: e, entityId: r, fields: i })) : (this.pendingEdits.push({
45
+ pushFieldUpdates(t, e, i) {
46
+ this.registration && this.registration.entityType === t && String(this.registration.entityId) === String(e) ? (this.registration.onFieldUpdate(i), this.emit("edit:applied", { entityType: t, entityId: e, fields: i })) : (this.pendingEdits.push({
47
47
  action: "edit_entity",
48
- entity_type: e,
49
- entity_id: r,
48
+ entity_type: t,
49
+ entity_id: e,
50
50
  fields: i
51
- }), this.emit("edit:pending", { entityType: e, entityId: r, fields: i }));
51
+ }), this.emit("edit:pending", { entityType: t, entityId: e, fields: i }));
52
52
  }
53
53
  /**
54
54
  * Request the current form to save.
@@ -61,254 +61,57 @@ class F extends I {
61
61
  entityType: this.registration.entityType,
62
62
  entityId: this.registration.entityId
63
63
  }), { success: !0 };
64
- } catch (e) {
65
- const r = e instanceof Error ? e.message : "Save failed";
64
+ } catch (t) {
65
+ const e = t instanceof Error ? t.message : "Save failed";
66
66
  return this.emit("save:error", {
67
67
  entityType: this.registration.entityType,
68
68
  entityId: this.registration.entityId,
69
- error: r
70
- }), { success: !1, error: r };
69
+ error: e
70
+ }), { success: !1, error: e };
71
71
  }
72
72
  }
73
73
  /**
74
74
  * Request the current form to run a test.
75
75
  */
76
- async requestTest(e) {
76
+ async requestTest(t) {
77
77
  if (!this.registration?.onTest)
78
78
  return { success: !1, error: "Current form does not support testing" };
79
79
  try {
80
- return await this.registration.onTest(e), { success: !0 };
81
- } catch (r) {
82
- return { success: !1, error: r instanceof Error ? r.message : "Test failed" };
80
+ return await this.registration.onTest(t), { success: !0 };
81
+ } catch (e) {
82
+ return { success: !1, error: e instanceof Error ? e.message : "Test failed" };
83
83
  }
84
84
  }
85
- setupListeners(e) {
86
- e.on("action:edit_entity", (r) => {
87
- this.pushFieldUpdates(r.entity_type, r.entity_id, r.fields);
88
- }), e.on("action:save_entity", (r) => {
85
+ setupListeners(t) {
86
+ t.on("action:edit_entity", (e) => {
87
+ this.pushFieldUpdates(e.entity_type, e.entity_id, e.fields);
88
+ }), t.on("action:save_entity", (e) => {
89
89
  this.requestSave();
90
- }), e.on("action:test_tool", (r) => {
91
- this.emit("test:triggered", { toolId: r.tool_id, parameters: r.parameters }), this.requestTest(r.parameters);
90
+ }), t.on("action:test_tool", (e) => {
91
+ this.emit("test:triggered", { toolId: e.tool_id, parameters: e.parameters }), this.requestTest(e.parameters);
92
92
  });
93
93
  }
94
94
  }
95
- function T(t) {
96
- return {
97
- async upload(e, r) {
98
- const i = new FormData(), a = t.fieldName ?? "file";
99
- i.append(a, e, e.name);
100
- const n = typeof t.extraFields == "function" ? t.extraFields(r) : t.extraFields;
101
- if (n)
102
- for (const [y, h] of Object.entries(n)) i.append(y, h);
103
- i.append("conversationId", r.conversationId), i.append("userId", r.userId), r.projectId && i.append("projectId", r.projectId);
104
- const o = typeof t.headers == "function" ? await t.headers() : t.headers ?? {}, p = await fetch(t.endpoint, {
105
- method: t.method ?? "POST",
106
- body: i,
107
- headers: o,
108
- credentials: t.credentials
109
- });
110
- if (!p.ok)
111
- throw new Error(`Upload failed: ${p.status} ${p.statusText}`);
112
- const d = await p.json().catch(() => ({}));
113
- if (t.parseResponse) return t.parseResponse(d, r);
114
- const s = d, c = s.url ?? s.fileUrl ?? s.publicUrl, m = s.fileName ?? s.name ?? e.name;
115
- if (!c) throw new Error('Upload response missing "url" / "fileUrl" / "publicUrl"');
116
- return {
117
- url: c,
118
- fileName: m,
119
- cloudFileId: typeof s.cloudFileId == "string" ? s.cloudFileId : void 0,
120
- relativePath: typeof s.path == "string" ? s.path : void 0,
121
- contentType: typeof s.contentType == "string" ? s.contentType : void 0,
122
- byteSize: typeof s.byteSize == "number" ? s.byteSize : void 0,
123
- meta: s
124
- };
125
- }
126
- };
127
- }
128
- const x = "/tilechat/{userId}/conversations/{conversationId}/messages?pageSize={pageSize}";
129
- function v(t) {
130
- const e = t.apiBase.replace(/\/$/, ""), r = t.pageSize ?? 200, i = t.pathTemplate ?? x;
131
- return {
132
- async fetchMessages(a, n) {
133
- const o = i.replace("{userId}", encodeURIComponent(n.userId)).replace("{conversationId}", encodeURIComponent(a)).replace("{appId}", encodeURIComponent(n.appId ?? "tilechat")).replace("{projectId}", encodeURIComponent(n.projectId ?? "")).replace("{pageSize}", String(r)), p = o.startsWith("http") ? o : `${e}${o.startsWith("/") ? o : `/${o}`}`, d = {
134
- accept: "application/json",
135
- // Some Spring/chat21 backends reject GETs without an explicit
136
- // Content-Type — match bandhan's chatapi which sends it on GETs.
137
- "content-type": "application/json",
138
- ...t.extraHeaders ?? {}
139
- };
140
- if (t.getToken) {
141
- const y = await t.getToken();
142
- y && (d.authorization = y);
143
- }
144
- const s = await fetch(p, { method: "GET", headers: d, credentials: "include" }), c = await s.json().catch(() => null);
145
- if (t.parseResponse && c) return t.parseResponse(c);
146
- const m = c;
147
- if (m && Array.isArray(m.result))
148
- return m.result;
149
- if (!s.ok) throw new Error(`History fetch failed: ${s.status} ${s.statusText}`);
150
- return [];
151
- }
152
- };
153
- }
154
- function w() {
155
- const t = typeof crypto < "u" ? crypto : null;
156
- if (t?.randomUUID) return t.randomUUID();
157
- if (t?.getRandomValues) {
158
- const e = new Uint8Array(16);
159
- t.getRandomValues(e), e[6] = e[6] & 15 | 64, e[8] = e[8] & 63 | 128;
160
- const r = [...e].map((i) => i.toString(16).padStart(2, "0")).join("");
161
- return `${r.slice(0, 8)}-${r.slice(8, 12)}-${r.slice(12, 16)}-${r.slice(16, 20)}-${r.slice(20)}`;
162
- }
163
- return "xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx".replace(/[xy]/g, (e) => {
164
- const r = Math.random() * 16 | 0;
165
- return (e === "x" ? r : r & 3 | 8).toString(16);
166
- });
167
- }
168
- const S = "aikaara_chat:requestId";
169
- function f(t, e) {
170
- return `${S}:${t}:${e}`;
171
- }
172
- function b(t, e) {
173
- try {
174
- return localStorage.getItem(f(t, e));
175
- } catch {
176
- return null;
177
- }
178
- }
179
- function k(t, e, r) {
180
- try {
181
- localStorage.setItem(f(t, e), r);
182
- } catch {
183
- }
184
- }
185
- function C(t, e) {
186
- try {
187
- localStorage.removeItem(f(t, e));
188
- } catch {
189
- }
190
- }
191
- async function E(t, e) {
192
- const r = await fetch(t, {
193
- method: "GET",
194
- headers: { accept: "application/json", ...e ?? {} }
195
- });
196
- if (!r.ok) {
197
- const a = await r.text().catch(() => "");
198
- throw new Error(`Widget config fetch failed: ${r.status} ${r.statusText} ${a.slice(0, 200)}`);
199
- }
200
- const i = await r.json();
201
- if (i && typeof i == "object") {
202
- if ("config" in i) return i.config;
203
- if ("data" in i) return i.data;
204
- }
205
- return i;
206
- }
207
- function A(t, e) {
208
- return t.replace("{projectId}", e).replace("{uuid}", w().replace(/-/g, ""));
209
- }
210
- async function j(t) {
211
- const e = {
212
- ...t.config ?? (t.configUrl ? await E(t.configUrl, t.configHeaders) : {}),
213
- ...t.overrides ?? {}
214
- }, r = e.transport ?? "tiledesk", i = e.tiledesk;
215
- if ((r === "tiledesk" || r === "dual") && !i)
216
- throw new Error("mount: descriptor.tiledesk is required for tiledesk/dual transport");
217
- const a = i?.projectId ?? "", n = t.identity.userId, o = t.forceNewConversation ? null : b(n, a), p = i?.requestIdTemplate ?? "support-group-{projectId}-{uuid}", d = t.conversationId ?? o ?? A(p, a);
218
- (!o || t.forceNewConversation) && a && k(n, a, d);
219
- const s = await t.tokenProvider(), c = t.tokenProvider, m = t.historyTokenProvider ?? c, y = i ? {
220
- mqttEndpoint: i.mqttEndpoint,
221
- jwtToken: s,
222
- userId: n,
223
- userName: t.identity.userName,
224
- projectId: i.projectId,
225
- appId: i.appId,
226
- mqttUsername: i.mqttUsername,
227
- protocolId: i.protocolId,
228
- protocolVersion: i.protocolVersion,
229
- keepAliveSec: i.keepAliveSec,
230
- connectTimeoutMs: i.connectTimeoutMs,
231
- maxReconnectAttempts: i.maxReconnectAttempts,
232
- reconnectMaxDelayMs: i.reconnectMaxDelayMs,
233
- wildcardSubscribe: i.wildcardSubscribe,
234
- enablePresence: i.enablePresence,
235
- autoInitiateOnEmpty: i.autoInitiateOnEmpty,
236
- chatInitiatedAttributes: i.chatInitiatedAttributes,
237
- messageDefaults: {
238
- ...i.messageDefaults,
239
- ...t.identity.departmentId ? { departmentId: t.identity.departmentId } : i.messageDefaults?.departmentId ? { departmentId: i.messageDefaults.departmentId } : {}
240
- },
241
- fileTemplate: i.fileTemplate,
242
- topicTemplates: i.topicTemplates,
243
- debug: i.debug,
244
- senderFullname: t.identity.senderFullname ?? t.identity.userName,
245
- tokenProvider: c
246
- } : void 0, h = t.uploadAdapter ?? (e.uploadEndpoint ? T({
247
- endpoint: e.uploadEndpoint,
248
- fieldName: e.uploadFieldName,
249
- extraFields: e.uploadExtraFields
250
- }) : void 0), g = t.historyAdapter ?? (e.historyApiBase ? v({
251
- apiBase: e.historyApiBase,
252
- pageSize: e.historyPageSize ?? 200,
253
- pathTemplate: e.historyPathTemplate,
254
- getToken: m
255
- }) : void 0), l = {
256
- transport: r,
257
- baseUrl: "",
258
- userToken: n,
259
- conversationId: d,
260
- display: e.display ?? "embed",
261
- position: e.position,
262
- primaryColor: e.primaryColor,
263
- title: e.title,
264
- subtitle: e.subtitle,
265
- avatarUrl: e.avatarUrl,
266
- width: e.width,
267
- height: e.height,
268
- borderRadius: e.borderRadius,
269
- fontFamily: e.fontFamily,
270
- welcomeMessage: e.welcomeMessage,
271
- placeholder: e.placeholder,
272
- showTimestamps: e.showTimestamps,
273
- persistConversation: e.persistConversation,
274
- tiledesk: y,
275
- tiledeskIdentity: {
276
- userId: n,
277
- userName: t.identity.userName,
278
- departmentId: t.identity.departmentId,
279
- senderFullname: t.identity.senderFullname ?? t.identity.userName
280
- },
281
- templateActionAttributes: e.templateActionAttributes,
282
- uploadAdapter: h,
283
- historyAdapter: g,
284
- onError: t.onError
285
- }, u = document.createElement("aikaara-chat-widget");
286
- return u.configure(l), l.title && u.setAttribute("title", l.title), l.primaryColor && u.setAttribute("primary-color", l.primaryColor), l.display && u.setAttribute("display", l.display), l.display === "embed" && (u.style.cssText = "display:flex;flex-direction:column;width:100%;height:100%;min-height:0;"), t.container.appendChild(u), {
287
- widget: u,
288
- requestId: d,
289
- config: l,
290
- destroy() {
291
- u.remove();
292
- }
293
- };
294
- }
295
95
  export {
296
- $ as ActionCableClient,
297
- q as AikaaraChatClient,
298
- N as ApiClient,
299
- M as ChannelSubscription,
300
- P as ConnectionManager,
301
- D as ConversationManager,
302
- I as EventEmitter,
303
- F as FormBridge,
304
- z as MessageStore,
305
- B as TiledeskTransport,
306
- C as clearPersistedConversationId,
307
- T as createFetchUploadAdapter,
96
+ p as ActionCableClient,
97
+ g as AikaaraChatClient,
98
+ l as ApiClient,
99
+ h as ChannelSubscription,
100
+ y as ConnectionManager,
101
+ c as ConversationManager,
102
+ s as EventEmitter,
103
+ a as FormBridge,
104
+ u as MessageStore,
105
+ m as SessionAuthAdapter,
106
+ f as TiledeskTransport,
107
+ T as clearPersistedConversationId,
108
+ S as createFetchUploadAdapter,
109
+ _ as createPresigned3StepUploadAdapter,
308
110
  v as createTiledeskHistoryAdapter,
309
- H as extractTiledeskFileEnvelope,
310
- O as inferTiledeskRole,
311
- V as isTiledeskSelfEcho,
312
- j as mountTenantWidget,
313
- W as parseTiledeskTemplate
111
+ E as extractTiledeskFileEnvelope,
112
+ C as inferTiledeskRole,
113
+ F as isTiledeskSelfEcho,
114
+ A as mountFromSlug,
115
+ k as mountTenantWidget,
116
+ I as parseTiledeskTemplate
314
117
  };
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./ui-B0-Np9Dn.cjs"),t=require("./headless.cjs");function l(a){e.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=a[o];i!=null&&r.setAttribute(s,String(i))}return r.configure(a),document.body.appendChild(r),r}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.TiledeskTransport=e.TiledeskTransport;exports.extractTiledeskFileEnvelope=e.extractTiledeskFileEnvelope;exports.inferTiledeskRole=e.inferTiledeskRole;exports.isTiledeskSelfEcho=e.isTiledeskSelfEcho;exports.parseTiledeskTemplate=e.parseTiledeskTemplate;exports.registerComponents=e.registerComponents;exports.FormBridge=t.FormBridge;exports.clearPersistedConversationId=t.clearPersistedConversationId;exports.createFetchUploadAdapter=t.createFetchUploadAdapter;exports.createTiledeskHistoryAdapter=t.createTiledeskHistoryAdapter;exports.mountTenantWidget=t.mountTenantWidget;exports.mount=l;exports.unmount=d;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./MountTenant-B4Py61gI.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;