@prodact.ai/sdk 0.0.9 → 0.0.10
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/cdn/sdk.global.js +1 -1
- package/dist/cdn/sdk.global.js.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -2
- package/dist/index.mjs.map +1 -1
- package/dist/react.js +78 -2
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +78 -2
- package/dist/react.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cdn/sdk.global.js
CHANGED
|
@@ -70,7 +70,7 @@ Make sure your backend is running and the URL is correct.`),await this.log("erro
|
|
|
70
70
|
3. The backend server is unreachable
|
|
71
71
|
|
|
72
72
|
Current apiUrl: ${this.config.apiUrl}
|
|
73
|
-
Check the Network tab in DevTools for more details.`),await this.log("error","SDK initialization failed",{error:n}),this.emit("error",s),s}}register(e,t){this.actions.set(e,t),this.log("info","Action handler registered",{actionKey:e,totalActions:this.actions.size})}unregister(e){this.actions.delete(e),this.log("info","Action handler unregistered",{actionKey:e,remainingActions:this.actions.size})}async sendMessage(e){var r,s;if(!this.isReady||!this.sessionToken)throw new Error("SDK not initialized. Call init() first.");let t=Date.now();await this.log("info","sendMessage called",{message:e});try{let n,o={"Content-Type":"application/json"};this.config.sdkKey?(n=`${this.config.apiUrl}/sdk/match-intent`,o["X-SDK-Key"]=this.config.sdkKey):n=`${this.config.apiUrl}/sdk/public/${this.config.guiderId}/match-intent`;let a=await fetch(n,{method:"POST",headers:o,body:JSON.stringify({userMessage:e})});if(await this.log("info","Match-intent response received",{status:a.status}),a.ok){let h=await a.json();if(h.matched&&h.type==="flow"&&h.flow){await this.log("info","Flow matched",{flowId:h.flow.flowId,name:h.flow.name,stepCount:(r=h.flow.steps)==null?void 0:r.length}),await this.sendLogToBackend({userMessage:e,matched:!0,actionKey:`flow:${h.flow.flowId}`,responseMessage:h.responseMessage,executionTimeMs:Date.now()-t});let d=await this.executeFlow(h.flow),p={role:"assistant",content:h.responseMessage||`I've completed the "${h.flow.name}" flow for you.`,flow:h.flow,flowResult:d};return this.emit("message",p),p}if(h.matched&&(h.type==="operation"||h.action)){let d=h.action;await this.log("info","Action matched",{actionKey:d.actionKey,actionType:d.actionType,responseMessage:d.responseMessage}),await this.sendLogToBackend({userMessage:e,matched:!0,actionKey:d.actionKey,responseMessage:d.responseMessage,executionTimeMs:Date.now()-t}),await this.executeAction(d);let p={role:"assistant",content:d.responseMessage||`I've triggered the "${d.name}" action for you.`,action:d};return this.emit("message",p),p}else await this.sendLogToBackend({userMessage:e,matched:!1,executionTimeMs:Date.now()-t})}let l=await fetch(`${this.config.apiUrl}/chat/sessions/${this.sessionToken}/message`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:e})});if(!l.ok)throw new Error(`Failed to send message: ${l.status}`);let c=await l.json(),u={role:"assistant",content:((s=c.message)==null?void 0:s.content)||c.response||"",visualFlows:c.flows||[],images:c.images||[]};return await this.log("info","Chat response received",{hasFlows:(c.flows||[]).length>0,hasImages:(c.images||[]).length>0}),this.emit("message",u),u}catch(n){throw await this.log("error","Error in sendMessage",{error:n instanceof Error?n.message:String(n)}),this.emit("error",n),n}}async executeFlow(e){await this.log("info","executeFlow started",{flowId:e.flowId,name:e.name,stepCount:e.steps.length}),this.emit("flowStart",e),this.config.onFlowStart&&this.config.onFlowStart(e);let t=[],r={},s=[...e.steps].sort((o,a)=>o.order-a.order);for(let o of s){await this.log("info","Executing flow step",{flowId:e.flowId,operationId:o.operationId,order:o.order});let a={operationId:o.operationId,order:o.order,success:!1};try{let l=this.actions.get(o.operationId);if(l){let c={actionKey:o.operationId,name:o.operationId,actionType:"callback",actionConfig:{flowContext:r,inputMapping:o.inputMapping}},u=await l(c);a.success=!0,a.data=u,r={...r,[`step_${o.order}`]:u,previousResult:u},await this.log("info","Flow step completed successfully",{flowId:e.flowId,operationId:o.operationId,order:o.order})}else await this.log("warn","No handler registered for flow step",{flowId:e.flowId,operationId:o.operationId}),a.success=!0,a.data={skipped:!0,reason:"No handler registered"}}catch(l){a.success=!1,a.error=l instanceof Error?l.message:String(l),await this.log("error","Flow step failed",{flowId:e.flowId,operationId:o.operationId,error:a.error})}t.push(a),this.emit("flowStepComplete",{step:a,flow:e}),this.config.onFlowStepComplete&&this.config.onFlowStepComplete(a,e)}let n={flowId:e.flowId,name:e.name,steps:t,completed:!0,totalSteps:e.steps.length,successfulSteps:t.filter(o=>o.success).length};return await this.log("info","Flow execution completed",{flowId:e.flowId,totalSteps:n.totalSteps,successfulSteps:n.successfulSteps}),this.emit("flowComplete",n),this.config.onFlowComplete&&this.config.onFlowComplete(n),n}async sendLogToBackend(e){try{let t={"Content-Type":"application/json"};this.config.sdkKey&&(t["X-SDK-Key"]=this.config.sdkKey);let r=`${this.config.apiUrl}/sdk-logs/client`;await fetch(r,{method:"POST",headers:t,body:JSON.stringify({...e,timestamp:new Date().toISOString(),sessionToken:this.sessionToken})})}catch(t){}}async log(e,t,r){try{let s={"Content-Type":"application/json"};this.config.sdkKey&&(s["X-SDK-Key"]=this.config.sdkKey);let n=`${this.config.apiUrl}/sdk-logs/client`;await fetch(n,{method:"POST",headers:s,body:JSON.stringify({level:e,message:t,data:r,timestamp:new Date().toISOString(),sessionToken:this.sessionToken})})}catch(s){}}async executeAction(e){var s,n;let t=Array.from(this.actions.keys());typeof window!="undefined"&&console.log("%c\u{1F3AF} SDK executeAction","background: #ff0; color: #000; font-size: 20px; padding: 10px;",{actionKey:e.actionKey,totalRegistered:this.actions.size,registeredKeys:t}),await this.log("info","executeAction called",{actionKey:e.actionKey,actionType:typeof e.actionKey,totalRegistered:this.actions.size,registeredKeys:t,keyComparisons:t.map(o=>({key:o,matches:o===e.actionKey,keyLength:o.length,actionKeyLength:e.actionKey.length}))});let r=this.actions.get(e.actionKey);if(typeof window!="undefined"&&console.log("%c\u{1F50D} SDK Handler Lookup","background: #0ff; color: #000; font-size: 16px; padding: 5px;",{actionKey:e.actionKey,found:!!r,hasConfigOnAction:!!this.config.onAction,registeredKeys:Array.from(this.actions.keys())}),r)try{let o=Date.now();await r(e);let a=Date.now()-o;await this.log("info","Handler executed successfully",{actionKey:e.actionKey,executionTime:a}),await this.sendLogToBackend({userMessage:`Action executed: ${e.actionKey}`,matched:!0,actionKey:e.actionKey,responseMessage:e.responseMessage||`Executed ${e.name}`,executionTimeMs:a}),this.emit("action",e),(n=(s=this.config).onAction)==null||n.call(s,e.actionKey,e)}catch(o){await this.log("error","Handler execution failed",{actionKey:e.actionKey,error:o instanceof Error?o.message:String(o),stack:o instanceof Error?o.stack:void 0}),await this.sendLogToBackend({userMessage:`Action execution failed: ${e.actionKey}`,matched:!0,actionKey:e.actionKey,error:o instanceof Error?o.message:String(o)}),this.emit("error",o)}else{if(this.config.onAction){await this.log("info","No internal handler, trying config.onAction callback",{actionKey:e.actionKey});try{this.config.onAction(e.actionKey,e),this.emit("action",e),await this.log("info","Action dispatched via config.onAction",{actionKey:e.actionKey}),await this.sendLogToBackend({userMessage:`Action dispatched: ${e.actionKey}`,matched:!0,actionKey:e.actionKey,responseMessage:e.responseMessage||`Dispatched ${e.name}`});return}catch(o){await this.log("error","config.onAction callback failed",{actionKey:e.actionKey,error:o instanceof Error?o.message:String(o)})}}await this.log("warn","No handler registered for action",{actionKey:e.actionKey,registeredActions:Array.from(this.actions.keys())}),await this.sendLogToBackend({userMessage:`No handler for action: ${e.actionKey}`,matched:!1,actionKey:e.actionKey,error:`Handler not registered. Available: ${Array.from(this.actions.keys()).join(", ")}`})}}on(e,t){this.eventListeners.has(e)||this.eventListeners.set(e,new Set),this.eventListeners.get(e).add(t)}off(e,t){var r;(r=this.eventListeners.get(e))==null||r.delete(t)}emit(e,t){var r;(r=this.eventListeners.get(e))==null||r.forEach(s=>s(t))}getSessionToken(){return this.sessionToken}getIsReady(){return this.isReady}getRegisteredActions(){return Array.from(this.actions.keys())}getGuiderId(){return this.config.guiderId}async getVisualFlow(e){let t=this.config.guiderId;if(!t)return await this.log("warn","Cannot fetch visual flow without guiderId"),null;try{let r=await fetch(`${this.config.apiUrl}/visual-flows/chat/${t}/${e}`);if(!r.ok)return await this.log("warn","Visual flow not found",{flowId:e,status:r.status}),null;let s=await r.json();return!s.found||!s.flow?null:s.flow}catch(r){return await this.log("error","Error fetching visual flow",{flowId:e,error:r}),null}}async initRecording(){try{this.recorder=new at(this.config.recording),this.recorder.initialize(this.sessionToken,this.config.apiUrl,this.config.sdkKey);let e=await this.recorder.start();e&&await this.log("info","Session recording started",{recordingSessionId:e})}catch(e){await this.log("warn","Failed to initialize session recording",{error:e instanceof Error?e.message:String(e)})}}async startRecording(){return this.isReady?(this.recorder||(this.recorder=new at(this.config.recording),this.recorder.initialize(this.sessionToken,this.config.apiUrl,this.config.sdkKey)),this.recorder.start()):(console.warn("[SDK] Cannot start recording before SDK is initialized"),null)}async stopRecording(){this.recorder&&await this.recorder.stop()}pauseRecording(){var e;(e=this.recorder)==null||e.pause()}resumeRecording(){var e;(e=this.recorder)==null||e.resume()}addRecordingEvent(e){var t;(t=this.recorder)==null||t.addCustomEvent(e)}getRecordingStats(){var e,t;return(t=(e=this.recorder)==null?void 0:e.getStats())!=null?t:null}isRecordingActive(){var e,t;return(t=(e=this.recorder)==null?void 0:e.isRecording())!=null?t:!1}getRecordingSessionId(){var e,t;return(t=(e=this.recorder)==null?void 0:e.getSessionId())!=null?t:null}initProactive(){this.config.proactive&&(this.proactiveTracker=new Qr(this.config.proactive,{onTrigger:async(e,t)=>{this.emit("proactive",{context:e,message:t}),this.config.onProactiveMessage&&this.config.onProactiveMessage(t,e);try{await this.getProactiveAIMessage(e,t)}catch(r){await this.log("warn","Failed to get AI proactive message",{error:r})}}}),this.proactiveTracker.start(),this.log("info","Proactive behavior tracking initialized"))}async getProactiveAIMessage(e,t){try{let r={"Content-Type":"application/json"};this.config.sdkKey&&(r["X-SDK-Key"]=this.config.sdkKey);let s=await fetch(`${this.config.apiUrl}/sdk/proactive-message`,{method:"POST",headers:r,body:JSON.stringify({context:e,fallbackMessage:t,sessionToken:this.sessionToken})});if(!s.ok)return t;let o=(await s.json()).message||t,a={role:"assistant",content:o};return this.emit("message",a),o}catch(r){return t}}async sendInitialMessage(){let e=this.config.initialMessage;if(e)if(this.config.streamInitialMessage)await this.streamMessage(e);else{let t={role:"assistant",content:e};this.emit("message",t),this.config.onMessage&&this.config.onMessage(t)}}async streamMessage(e,t=30){let r="";for(let s=0;s<e.length;s++){r+=e[s];let n={role:"assistant",content:r};this.emit("message",n),await new Promise(o=>setTimeout(o,t))}}startProactiveTracking(){this.proactiveTracker&&this.proactiveTracker.start()}stopProactiveTracking(){this.proactiveTracker&&this.proactiveTracker.stop()}getProactiveStats(){var e,t;return(t=(e=this.proactiveTracker)==null?void 0:e.getStats())!=null?t:null}triggerProactiveMessage(e,t){if(this.proactiveTracker)this.proactiveTracker.triggerManual(e,t);else{let r={role:"assistant",content:e};this.emit("message",r),this.config.onMessage&&this.config.onMessage(r)}}optOutProactive(){var e;(e=this.proactiveTracker)==null||e.optOut()}optInProactive(){var e;(e=this.proactiveTracker)==null||e.optIn()}async initUserFlowTracking(){var e,t;try{console.log("%c\u{1F4CA} Initializing User Flow Tracking","background: #8b5cf6; color: #fff; padding: 2px 6px; border-radius: 3px;",{config:this.config.userFlows,apiUrl:this.config.apiUrl,sdkKey:this.config.sdkKey?"present":"missing"}),this.userFlowTracker=new lt(this.config.userFlows),this.userFlowTracker.initialize(this.sessionToken,this.config.apiUrl,this.config.sdkKey);let r=((t=(e=this.recorder)==null?void 0:e.getSessionId)==null?void 0:t.call(e))||null,s=await this.userFlowTracker.start(r);s?(console.log("%c\u2705 User Flow Tracking Started","background: #10b981; color: #fff; padding: 2px 6px; border-radius: 3px;",{flowSessionId:s,linkedRecordingSession:r}),await this.log("info","User flow tracking started",{flowSessionId:s,linkedRecordingSession:r})):console.warn("%c\u26A0\uFE0F User Flow Tracking: No session ID returned","background: #f59e0b; color: #000; padding: 2px 6px; border-radius: 3px;")}catch(r){console.error("%c\u274C User Flow Tracking Failed","background: #ef4444; color: #fff; padding: 2px 6px; border-radius: 3px;",r),await this.log("warn","Failed to initialize user flow tracking",{error:r instanceof Error?r.message:String(r)})}}identify(e){this.userFlowTracker&&this.userFlowTracker.identify(e),this.log("info","User identified",{hasEmail:!!e.email,hasName:!!e.name,hasTags:!!e.tags&&Object.keys(e.tags).length>0})}async startUserFlowTracking(){return this.isReady?(this.userFlowTracker||(this.userFlowTracker=new lt(this.config.userFlows),this.userFlowTracker.initialize(this.sessionToken,this.config.apiUrl,this.config.sdkKey)),this.userFlowTracker.start()):(console.warn("[SDK] Cannot start flow tracking before SDK is initialized"),null)}async stopUserFlowTracking(){this.userFlowTracker&&await this.userFlowTracker.stop()}pauseUserFlowTracking(){var e;(e=this.userFlowTracker)==null||e.pause()}resumeUserFlowTracking(){var e;(e=this.userFlowTracker)==null||e.resume()}trackEvent(e){var t;(t=this.userFlowTracker)==null||t.addCustomEvent(e)}getUserFlowStats(){var e,t;return(t=(e=this.userFlowTracker)==null?void 0:e.getStats())!=null?t:null}isUserFlowTrackingActive(){var e,t;return(t=(e=this.userFlowTracker)==null?void 0:e.isTracking())!=null?t:!1}destroy(){this.recorder&&(this.recorder.destroy(),this.recorder=null),this.proactiveTracker&&(this.proactiveTracker.stop(),this.proactiveTracker=null),this.userFlowTracker&&(this.userFlowTracker.stop(),this.userFlowTracker=null),this.actions.clear(),this.eventListeners.clear(),this.sessionToken=null,this.isReady=!1}};var F={instance:null,container:null,config:null,isOpen:!1};function am(i){var n,o,a,l,c,u,h,d;let e=document.createElement("div");e.id="produck-chat-widget";let r=(i.position||"bottom-right")==="bottom-right",s=document.createElement("style");return s.textContent=`
|
|
73
|
+
Check the Network tab in DevTools for more details.`),await this.log("error","SDK initialization failed",{error:n}),this.emit("error",s),s}}register(e,t){this.actions.set(e,t),this.log("info","Action handler registered",{actionKey:e,totalActions:this.actions.size})}unregister(e){this.actions.delete(e),this.log("info","Action handler unregistered",{actionKey:e,remainingActions:this.actions.size})}async sendMessage(e){var r,s;if(!this.isReady||!this.sessionToken)throw new Error("SDK not initialized. Call init() first.");let t=Date.now();await this.log("info","sendMessage called",{message:e});try{let n,o={"Content-Type":"application/json"};this.config.sdkKey?(n=`${this.config.apiUrl}/sdk/match-intent`,o["X-SDK-Key"]=this.config.sdkKey):n=`${this.config.apiUrl}/sdk/public/${this.config.guiderId}/match-intent`;let a=await fetch(n,{method:"POST",headers:o,body:JSON.stringify({userMessage:e})});if(await this.log("info","Match-intent response received",{status:a.status}),a.ok){let h=await a.json();if(h.matched&&h.type==="flow"&&h.flow){await this.log("info","Flow matched",{flowId:h.flow.flowId,name:h.flow.name,stepCount:(r=h.flow.steps)==null?void 0:r.length}),await this.sendLogToBackend({userMessage:e,matched:!0,actionKey:`flow:${h.flow.flowId}`,responseMessage:h.responseMessage,executionTimeMs:Date.now()-t});let d=await this.executeFlow(h.flow),p={role:"assistant",content:h.responseMessage||`I've completed the "${h.flow.name}" flow for you.`,flow:h.flow,flowResult:d};return this.emit("message",p),p}if(h.matched&&(h.type==="operation"||h.action)){let d=h.action;await this.log("info","Action matched",{actionKey:d.actionKey,actionType:d.actionType,responseMessage:d.responseMessage}),await this.sendLogToBackend({userMessage:e,matched:!0,actionKey:d.actionKey,responseMessage:d.responseMessage,executionTimeMs:Date.now()-t}),await this.executeAction(d);let p={role:"assistant",content:d.responseMessage||`I've triggered the "${d.name}" action for you.`,action:d};return this.emit("message",p),p}else await this.sendLogToBackend({userMessage:e,matched:!1,executionTimeMs:Date.now()-t})}let l=await fetch(`${this.config.apiUrl}/chat/sessions/${this.sessionToken}/message`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:e})});if(!l.ok)throw new Error(`Failed to send message: ${l.status}`);let c=await l.json(),u={role:"assistant",content:((s=c.message)==null?void 0:s.content)||c.response||"",visualFlows:c.flows||[],images:c.images||[],userFlows:c.userFlows||[]};return await this.log("info","Chat response received",{hasFlows:(c.flows||[]).length>0,hasImages:(c.images||[]).length>0,hasUserFlows:(c.userFlows||[]).length>0}),this.emit("message",u),u}catch(n){throw await this.log("error","Error in sendMessage",{error:n instanceof Error?n.message:String(n)}),this.emit("error",n),n}}async executeFlow(e){await this.log("info","executeFlow started",{flowId:e.flowId,name:e.name,stepCount:e.steps.length}),this.emit("flowStart",e),this.config.onFlowStart&&this.config.onFlowStart(e);let t=[],r={},s=[...e.steps].sort((o,a)=>o.order-a.order);for(let o of s){await this.log("info","Executing flow step",{flowId:e.flowId,operationId:o.operationId,order:o.order});let a={operationId:o.operationId,order:o.order,success:!1};try{let l=this.actions.get(o.operationId);if(l){let c={actionKey:o.operationId,name:o.operationId,actionType:"callback",actionConfig:{flowContext:r,inputMapping:o.inputMapping}},u=await l(c);a.success=!0,a.data=u,r={...r,[`step_${o.order}`]:u,previousResult:u},await this.log("info","Flow step completed successfully",{flowId:e.flowId,operationId:o.operationId,order:o.order})}else await this.log("warn","No handler registered for flow step",{flowId:e.flowId,operationId:o.operationId}),a.success=!0,a.data={skipped:!0,reason:"No handler registered"}}catch(l){a.success=!1,a.error=l instanceof Error?l.message:String(l),await this.log("error","Flow step failed",{flowId:e.flowId,operationId:o.operationId,error:a.error})}t.push(a),this.emit("flowStepComplete",{step:a,flow:e}),this.config.onFlowStepComplete&&this.config.onFlowStepComplete(a,e)}let n={flowId:e.flowId,name:e.name,steps:t,completed:!0,totalSteps:e.steps.length,successfulSteps:t.filter(o=>o.success).length};return await this.log("info","Flow execution completed",{flowId:e.flowId,totalSteps:n.totalSteps,successfulSteps:n.successfulSteps}),this.emit("flowComplete",n),this.config.onFlowComplete&&this.config.onFlowComplete(n),n}async sendLogToBackend(e){try{let t={"Content-Type":"application/json"};this.config.sdkKey&&(t["X-SDK-Key"]=this.config.sdkKey);let r=`${this.config.apiUrl}/sdk-logs/client`;await fetch(r,{method:"POST",headers:t,body:JSON.stringify({...e,timestamp:new Date().toISOString(),sessionToken:this.sessionToken})})}catch(t){}}async log(e,t,r){try{let s={"Content-Type":"application/json"};this.config.sdkKey&&(s["X-SDK-Key"]=this.config.sdkKey);let n=`${this.config.apiUrl}/sdk-logs/client`;await fetch(n,{method:"POST",headers:s,body:JSON.stringify({level:e,message:t,data:r,timestamp:new Date().toISOString(),sessionToken:this.sessionToken})})}catch(s){}}async executeAction(e){var s,n;let t=Array.from(this.actions.keys());typeof window!="undefined"&&console.log("%c\u{1F3AF} SDK executeAction","background: #ff0; color: #000; font-size: 20px; padding: 10px;",{actionKey:e.actionKey,totalRegistered:this.actions.size,registeredKeys:t}),await this.log("info","executeAction called",{actionKey:e.actionKey,actionType:typeof e.actionKey,totalRegistered:this.actions.size,registeredKeys:t,keyComparisons:t.map(o=>({key:o,matches:o===e.actionKey,keyLength:o.length,actionKeyLength:e.actionKey.length}))});let r=this.actions.get(e.actionKey);if(typeof window!="undefined"&&console.log("%c\u{1F50D} SDK Handler Lookup","background: #0ff; color: #000; font-size: 16px; padding: 5px;",{actionKey:e.actionKey,found:!!r,hasConfigOnAction:!!this.config.onAction,registeredKeys:Array.from(this.actions.keys())}),r)try{let o=Date.now();await r(e);let a=Date.now()-o;await this.log("info","Handler executed successfully",{actionKey:e.actionKey,executionTime:a}),await this.sendLogToBackend({userMessage:`Action executed: ${e.actionKey}`,matched:!0,actionKey:e.actionKey,responseMessage:e.responseMessage||`Executed ${e.name}`,executionTimeMs:a}),this.emit("action",e),(n=(s=this.config).onAction)==null||n.call(s,e.actionKey,e)}catch(o){await this.log("error","Handler execution failed",{actionKey:e.actionKey,error:o instanceof Error?o.message:String(o),stack:o instanceof Error?o.stack:void 0}),await this.sendLogToBackend({userMessage:`Action execution failed: ${e.actionKey}`,matched:!0,actionKey:e.actionKey,error:o instanceof Error?o.message:String(o)}),this.emit("error",o)}else{if(this.config.onAction){await this.log("info","No internal handler, trying config.onAction callback",{actionKey:e.actionKey});try{this.config.onAction(e.actionKey,e),this.emit("action",e),await this.log("info","Action dispatched via config.onAction",{actionKey:e.actionKey}),await this.sendLogToBackend({userMessage:`Action dispatched: ${e.actionKey}`,matched:!0,actionKey:e.actionKey,responseMessage:e.responseMessage||`Dispatched ${e.name}`});return}catch(o){await this.log("error","config.onAction callback failed",{actionKey:e.actionKey,error:o instanceof Error?o.message:String(o)})}}await this.log("warn","No handler registered for action",{actionKey:e.actionKey,registeredActions:Array.from(this.actions.keys())}),await this.sendLogToBackend({userMessage:`No handler for action: ${e.actionKey}`,matched:!1,actionKey:e.actionKey,error:`Handler not registered. Available: ${Array.from(this.actions.keys()).join(", ")}`})}}on(e,t){this.eventListeners.has(e)||this.eventListeners.set(e,new Set),this.eventListeners.get(e).add(t)}off(e,t){var r;(r=this.eventListeners.get(e))==null||r.delete(t)}emit(e,t){var r;(r=this.eventListeners.get(e))==null||r.forEach(s=>s(t))}getSessionToken(){return this.sessionToken}getIsReady(){return this.isReady}getRegisteredActions(){return Array.from(this.actions.keys())}getGuiderId(){return this.config.guiderId}async getVisualFlow(e){let t=this.config.guiderId;if(!t)return await this.log("warn","Cannot fetch visual flow without guiderId"),null;try{let r=await fetch(`${this.config.apiUrl}/visual-flows/chat/${t}/${e}`);if(!r.ok)return await this.log("warn","Visual flow not found",{flowId:e,status:r.status}),null;let s=await r.json();return!s.found||!s.flow?null:s.flow}catch(r){return await this.log("error","Error fetching visual flow",{flowId:e,error:r}),null}}async initRecording(){try{this.recorder=new at(this.config.recording),this.recorder.initialize(this.sessionToken,this.config.apiUrl,this.config.sdkKey);let e=await this.recorder.start();e&&await this.log("info","Session recording started",{recordingSessionId:e})}catch(e){await this.log("warn","Failed to initialize session recording",{error:e instanceof Error?e.message:String(e)})}}async startRecording(){return this.isReady?(this.recorder||(this.recorder=new at(this.config.recording),this.recorder.initialize(this.sessionToken,this.config.apiUrl,this.config.sdkKey)),this.recorder.start()):(console.warn("[SDK] Cannot start recording before SDK is initialized"),null)}async stopRecording(){this.recorder&&await this.recorder.stop()}pauseRecording(){var e;(e=this.recorder)==null||e.pause()}resumeRecording(){var e;(e=this.recorder)==null||e.resume()}addRecordingEvent(e){var t;(t=this.recorder)==null||t.addCustomEvent(e)}getRecordingStats(){var e,t;return(t=(e=this.recorder)==null?void 0:e.getStats())!=null?t:null}isRecordingActive(){var e,t;return(t=(e=this.recorder)==null?void 0:e.isRecording())!=null?t:!1}getRecordingSessionId(){var e,t;return(t=(e=this.recorder)==null?void 0:e.getSessionId())!=null?t:null}initProactive(){this.config.proactive&&(this.proactiveTracker=new Qr(this.config.proactive,{onTrigger:async(e,t)=>{this.emit("proactive",{context:e,message:t}),this.config.onProactiveMessage&&this.config.onProactiveMessage(t,e);try{await this.getProactiveAIMessage(e,t)}catch(r){await this.log("warn","Failed to get AI proactive message",{error:r})}}}),this.proactiveTracker.start(),this.log("info","Proactive behavior tracking initialized"))}async getProactiveAIMessage(e,t){try{let r={"Content-Type":"application/json"};this.config.sdkKey&&(r["X-SDK-Key"]=this.config.sdkKey);let s=await fetch(`${this.config.apiUrl}/sdk/proactive-message`,{method:"POST",headers:r,body:JSON.stringify({context:e,fallbackMessage:t,sessionToken:this.sessionToken})});if(!s.ok)return t;let o=(await s.json()).message||t,a={role:"assistant",content:o};return this.emit("message",a),o}catch(r){return t}}async sendInitialMessage(){let e=this.config.initialMessage;if(e)if(this.config.streamInitialMessage)await this.streamMessage(e);else{let t={role:"assistant",content:e};this.emit("message",t),this.config.onMessage&&this.config.onMessage(t)}}async streamMessage(e,t=30){let r="";for(let s=0;s<e.length;s++){r+=e[s];let n={role:"assistant",content:r};this.emit("message",n),await new Promise(o=>setTimeout(o,t))}}startProactiveTracking(){this.proactiveTracker&&this.proactiveTracker.start()}stopProactiveTracking(){this.proactiveTracker&&this.proactiveTracker.stop()}getProactiveStats(){var e,t;return(t=(e=this.proactiveTracker)==null?void 0:e.getStats())!=null?t:null}triggerProactiveMessage(e,t){if(this.proactiveTracker)this.proactiveTracker.triggerManual(e,t);else{let r={role:"assistant",content:e};this.emit("message",r),this.config.onMessage&&this.config.onMessage(r)}}optOutProactive(){var e;(e=this.proactiveTracker)==null||e.optOut()}optInProactive(){var e;(e=this.proactiveTracker)==null||e.optIn()}async initUserFlowTracking(){var e,t;try{console.log("%c\u{1F4CA} Initializing User Flow Tracking","background: #8b5cf6; color: #fff; padding: 2px 6px; border-radius: 3px;",{config:this.config.userFlows,apiUrl:this.config.apiUrl,sdkKey:this.config.sdkKey?"present":"missing"}),this.userFlowTracker=new lt(this.config.userFlows),this.userFlowTracker.initialize(this.sessionToken,this.config.apiUrl,this.config.sdkKey);let r=((t=(e=this.recorder)==null?void 0:e.getSessionId)==null?void 0:t.call(e))||null,s=await this.userFlowTracker.start(r);s?(console.log("%c\u2705 User Flow Tracking Started","background: #10b981; color: #fff; padding: 2px 6px; border-radius: 3px;",{flowSessionId:s,linkedRecordingSession:r}),await this.log("info","User flow tracking started",{flowSessionId:s,linkedRecordingSession:r})):console.warn("%c\u26A0\uFE0F User Flow Tracking: No session ID returned","background: #f59e0b; color: #000; padding: 2px 6px; border-radius: 3px;")}catch(r){console.error("%c\u274C User Flow Tracking Failed","background: #ef4444; color: #fff; padding: 2px 6px; border-radius: 3px;",r),await this.log("warn","Failed to initialize user flow tracking",{error:r instanceof Error?r.message:String(r)})}}identify(e){this.userFlowTracker&&this.userFlowTracker.identify(e),this.log("info","User identified",{hasEmail:!!e.email,hasName:!!e.name,hasTags:!!e.tags&&Object.keys(e.tags).length>0})}async startUserFlowTracking(){return this.isReady?(this.userFlowTracker||(this.userFlowTracker=new lt(this.config.userFlows),this.userFlowTracker.initialize(this.sessionToken,this.config.apiUrl,this.config.sdkKey)),this.userFlowTracker.start()):(console.warn("[SDK] Cannot start flow tracking before SDK is initialized"),null)}async stopUserFlowTracking(){this.userFlowTracker&&await this.userFlowTracker.stop()}pauseUserFlowTracking(){var e;(e=this.userFlowTracker)==null||e.pause()}resumeUserFlowTracking(){var e;(e=this.userFlowTracker)==null||e.resume()}trackEvent(e){var t;(t=this.userFlowTracker)==null||t.addCustomEvent(e)}getUserFlowStats(){var e,t;return(t=(e=this.userFlowTracker)==null?void 0:e.getStats())!=null?t:null}isUserFlowTrackingActive(){var e,t;return(t=(e=this.userFlowTracker)==null?void 0:e.isTracking())!=null?t:!1}destroy(){this.recorder&&(this.recorder.destroy(),this.recorder=null),this.proactiveTracker&&(this.proactiveTracker.stop(),this.proactiveTracker=null),this.userFlowTracker&&(this.userFlowTracker.stop(),this.userFlowTracker=null),this.actions.clear(),this.eventListeners.clear(),this.sessionToken=null,this.isReady=!1}};var F={instance:null,container:null,config:null,isOpen:!1};function am(i){var n,o,a,l,c,u,h,d;let e=document.createElement("div");e.id="produck-chat-widget";let r=(i.position||"bottom-right")==="bottom-right",s=document.createElement("style");return s.textContent=`
|
|
74
74
|
#produck-chat-widget {
|
|
75
75
|
position: fixed;
|
|
76
76
|
bottom: 20px;
|