@characterxyz/web 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +40 -4
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -11,7 +11,9 @@ type CxErrorCode = 'unauthorized' | 'forbidden' | 'not_found' | 'invalid' | 'rat
|
|
|
11
11
|
declare class CxError extends Error {
|
|
12
12
|
readonly code: CxErrorCode;
|
|
13
13
|
readonly status: number;
|
|
14
|
-
|
|
14
|
+
/** On `invalid`: what is wrong with each field, by its name (`email`, `name`…). */
|
|
15
|
+
readonly fields: Record<string, string>;
|
|
16
|
+
constructor(code: CxErrorCode, message: string, status?: number, fields?: Record<string, string>);
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
/** What the server says about the agent a session talks to. */
|
|
@@ -86,6 +88,26 @@ interface ChatMessage {
|
|
|
86
88
|
error?: string;
|
|
87
89
|
/** On a reply just written: what the visitor might ask next. Not kept in the history. */
|
|
88
90
|
suggestions?: string[];
|
|
91
|
+
/** On a reply just written: she invited the visitor to leave their details; show this card. */
|
|
92
|
+
askDetails?: DetailsForm;
|
|
93
|
+
/** On a reply just written: the card's settings while details may still be left (not an invitation). */
|
|
94
|
+
detailsForm?: DetailsForm;
|
|
95
|
+
}
|
|
96
|
+
/** The contact card: which fields to ask, and the consent line to show. */
|
|
97
|
+
interface DetailsForm {
|
|
98
|
+
/** Always `name` and `email`; `phone` and `company` when the key asks for them. */
|
|
99
|
+
fields: ('name' | 'email' | 'phone' | 'company')[];
|
|
100
|
+
/** The brand's privacy policy, linked from the consent line. */
|
|
101
|
+
privacyUrl: string | null;
|
|
102
|
+
/** Shown under the card; sending is the consent. */
|
|
103
|
+
consent: string;
|
|
104
|
+
}
|
|
105
|
+
/** What a visitor leaves. */
|
|
106
|
+
interface ContactDetails {
|
|
107
|
+
name: string;
|
|
108
|
+
email: string;
|
|
109
|
+
phone?: string;
|
|
110
|
+
company?: string;
|
|
89
111
|
}
|
|
90
112
|
/**
|
|
91
113
|
* How the agent opens the conversation on this site, written by the agent
|
|
@@ -100,6 +122,8 @@ interface Opening {
|
|
|
100
122
|
teaser: string;
|
|
101
123
|
/** What a visitor would most likely ask first. May be empty. */
|
|
102
124
|
suggestions: string[];
|
|
125
|
+
/** The contact card to offer before a call; null when nothing receives leads or this conversation was asked. */
|
|
126
|
+
details?: DetailsForm | null;
|
|
103
127
|
}
|
|
104
128
|
type CallPhase = 'idle' | 'joining' | 'queued' | 'ready' | 'connecting' | 'live' | 'ended';
|
|
105
129
|
type CallEndReason = 'hangup' | 'left' | 'missed' | 'timeout' | 'limit' | 'credits' | 'busy' | 'failed' | 'mic-denied' | 'unavailable'
|
|
@@ -285,6 +309,11 @@ declare class Chat extends Emitter<ChatEvents> {
|
|
|
285
309
|
* Resolves with the finished reply.
|
|
286
310
|
*/
|
|
287
311
|
send(text: string): Promise<ChatMessage>;
|
|
312
|
+
/**
|
|
313
|
+
* Start a new conversation. The old one is archived by the server, not
|
|
314
|
+
* deleted; the visitor simply starts fresh.
|
|
315
|
+
*/
|
|
316
|
+
reset(): Promise<void>;
|
|
288
317
|
/** Send a failed message again. */
|
|
289
318
|
retry(id: string): Promise<ChatMessage>;
|
|
290
319
|
/** Stop listening to a reply in progress (the server still finishes it). */
|
|
@@ -347,7 +376,14 @@ declare class CharacterXYZ extends Emitter<ClientEvents> {
|
|
|
347
376
|
* line, a teaser and likely first questions — written by her and cached by
|
|
348
377
|
* the server. Fetched once per page; null if it could not be had.
|
|
349
378
|
*/
|
|
350
|
-
opening(): Promise<Opening | null>;
|
|
379
|
+
opening(refresh?: boolean): Promise<Opening | null>;
|
|
380
|
+
/**
|
|
381
|
+
* Leave the visitor's details for the brand's team. Sending is the consent
|
|
382
|
+
* (the card says so). Fails `invalid` with `fields` naming each problem.
|
|
383
|
+
*/
|
|
384
|
+
sendDetails(details: ContactDetails): Promise<void>;
|
|
385
|
+
/** "Not now" on the details card: she will not ask again in this conversation. */
|
|
386
|
+
declineDetails(): Promise<void>;
|
|
351
387
|
/** Start a voice call. Call from a click: it needs the microphone and audio unlocked. */
|
|
352
388
|
startCall(opts?: CallOptions): Promise<Call>;
|
|
353
389
|
destroy(): void;
|
|
@@ -373,6 +409,6 @@ declare class CharacterXYZ extends Emitter<ClientEvents> {
|
|
|
373
409
|
* is built on, for brands who want their own UI.
|
|
374
410
|
*/
|
|
375
411
|
|
|
376
|
-
declare const VERSION = "0.
|
|
412
|
+
declare const VERSION = "0.3.0";
|
|
377
413
|
|
|
378
|
-
export { type AgentCard, Call, type CallEndReason, type CallEvents, type CallOptions, type CallPhase, type CallState, type Caption, CharacterXYZ, Chat, type ChatEvents, type ChatMessage, type ClientEvents, CxError, type CxErrorCode, DEFAULT_API_URL, Emitter, type Features, type InitOptions, type Opening, type SessionInfo, VERSION, type VideoCharacter, type VideoClip, type VisitorStore };
|
|
414
|
+
export { type AgentCard, Call, type CallEndReason, type CallEvents, type CallOptions, type CallPhase, type CallState, type Caption, CharacterXYZ, Chat, type ChatEvents, type ChatMessage, type ClientEvents, type ContactDetails, CxError, type CxErrorCode, DEFAULT_API_URL, type DetailsForm, Emitter, type Features, type InitOptions, type Opening, type SessionInfo, VERSION, type VideoCharacter, type VideoClip, type VisitorStore };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var
|
|
1
|
+
var N=Object.defineProperty;var j=(r,n,e)=>n in r?N(r,n,{enumerable:true,configurable:true,writable:true,value:e}):r[n]=e;var i=(r,n,e)=>j(r,typeof n!="symbol"?n+"":n,e);var w=null;function I(){return (!w||w.state==="closed")&&(w=new AudioContext({latencyHint:"interactive"})),w.state==="suspended"&&w.resume().catch(()=>{}),w}var C=class{constructor(n={}){i(this,"opts",n);i(this,"ctx");i(this,"gain");i(this,"analyser");i(this,"data");i(this,"nextAt",0);i(this,"started",false);i(this,"ended",false);i(this,"finishing",false);i(this,"sources",new Set);i(this,"startedAt",0);i(this,"sampleRate");this.ctx=I(),this.sampleRate=n.sampleRate??16e3,this.gain=this.ctx.createGain(),this.gain.gain.value=n.volume??1,this.analyser=this.ctx.createAnalyser(),this.analyser.fftSize=512,this.data=new Uint8Array(new ArrayBuffer(this.analyser.fftSize)),this.gain.connect(this.analyser).connect(this.ctx.destination);}enqueue(n){if(this.ended||n.byteLength<2)return;let e=Math.floor(n.byteLength/2),t=new DataView(n.buffer,n.byteOffset,e*2),s=this.ctx.createBuffer(1,e,this.sampleRate),o=s.getChannelData(0);for(let h=0;h<e;h++)o[h]=t.getInt16(h*2,true)/32768;let a=this.ctx.createBufferSource();a.buffer=s,a.connect(this.gain);let c=this.ctx.currentTime;if(this.nextAt<c&&(this.nextAt=c+(this.started?.02:.12)),a.start(this.nextAt),!this.started){this.started=true;let h=Math.max(0,(this.nextAt-c)*1e3);this.startedAt=performance.now()+h,setTimeout(()=>this.opts.onStart?.(),h);}this.nextAt+=s.duration,this.sources.add(a),a.onended=()=>{this.sources.delete(a),this.finishing&&this.sources.size===0&&this.finish();};}end(){this.finishing=true,this.sources.size===0&&this.finish();}stop(){this.ended=true;for(let n of this.sources)try{n.stop();}catch{}this.sources.clear(),this.gain.disconnect();}playedMs(){return this.started?Math.max(0,performance.now()-this.startedAt):0}level(){this.analyser.getByteTimeDomainData(this.data);let n=0;for(let e=0;e<this.data.length;e++){let t=(this.data[e]-128)/128;n+=t*t;}return Math.min(1,Math.sqrt(n/this.data.length)*3)}finish(){this.ended||(this.ended=true,this.gain.disconnect(),this.opts.onEnd?.());}};var K=`
|
|
2
2
|
class CxyzMic extends AudioWorkletProcessor {
|
|
3
3
|
constructor(o) {
|
|
4
4
|
super();
|
|
@@ -30,13 +30,13 @@ class CxyzMic extends AudioWorkletProcessor {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
registerProcessor('cxyz-mic', CxyzMic);
|
|
33
|
-
`;function q(r){let n=new Int16Array(r);if(!n.length)return 0;let e=0;for(let t=0;t<n.length;t++){let s=n[t]/32768;e+=s*s;}return Math.sqrt(e/n.length)}async function
|
|
33
|
+
`;function q(r){let n=new Int16Array(r);if(!n.length)return 0;let e=0;for(let t=0;t<n.length;t++){let s=n[t]/32768;e+=s*s;}return Math.sqrt(e/n.length)}async function _(r){if(!navigator.mediaDevices?.getUserMedia)throw new Error("This browser cannot use a microphone here.");let n=await navigator.mediaDevices.getUserMedia({audio:{deviceId:r.deviceId?{exact:r.deviceId}:void 0,channelCount:1,echoCancellation:true,noiseSuppression:true,autoGainControl:true}}),e=new AudioContext({latencyHint:"interactive"}),t=e.createMediaStreamSource(n),s=false,o=l=>{if(s){r.onFrame(new ArrayBuffer(l.byteLength),0);return}r.onFrame(l,q(l));},a,c;try{let l=URL.createObjectURL(new Blob([K],{type:"application/javascript"}));try{await e.audioWorklet.addModule(l);}finally{URL.revokeObjectURL(l);}let p=new AudioWorkletNode(e,"cxyz-mic");p.port.onmessage=f=>o(f.data),a=p,c=()=>{p.port.onmessage=null;};}catch{let l=e.createScriptProcessor(4096,1,1),p=e.sampleRate/16e3,f=0,m=new Int16Array(480),u=0;l.onaudioprocess=x=>{let b=x.inputBuffer.getChannelData(0);for(let M=0;M<b.length;M++)if(f+=1,f>=p){f-=p;let R=Math.max(-1,Math.min(1,b[M]));m[u++]=R<0?R*32768:R*32767,u===480&&(o(m.buffer),m=new Int16Array(480),u=0);}},a=l,c=()=>{l.onaudioprocess=null;};}t.connect(a);let h=e.createGain();return h.gain.value=0,a.connect(h).connect(e.destination),e.state==="suspended"&&await e.resume().catch(()=>{}),{get muted(){return s},setMuted(l){s=l;for(let p of n.getAudioTracks())p.enabled=!l;},stop(){c();try{t.disconnect(),a.disconnect();}catch{}for(let l of n.getTracks())l.stop();e.close().catch(()=>{});}}}var y=class{constructor(){i(this,"handlers",{});}on(n,e){var t;return ((t=this.handlers)[n]??(t[n]=new Set)).add(e),()=>this.handlers[n]?.delete(e)}emit(n,e){for(let t of this.handlers[n]??[])try{t(e);}catch(s){console.error("[characterxyz] listener threw",s);}}clear(){this.handlers={};}};var d=class extends Error{constructor(e,t,s=0,o={}){super(t);i(this,"code");i(this,"status");i(this,"fields");this.name="CxError",this.code=e,this.status=s,this.fields=o;}};function T(r){switch(r){case 401:return "unauthorized";case 403:return "forbidden";case 404:return "not_found";case 402:return "payment_required";case 422:return "invalid";case 429:return "rate_limited";case 503:return "unavailable";default:return "unknown"}}async function z(r){let n="",e={};try{let t=await r.json();typeof t?.message=="string"&&(n=t.message);for(let s of Array.isArray(t?.errors)?t.errors:[])typeof s?.path=="string"&&typeof s?.message=="string"&&(e[s.path]=s.message);}catch{}return new d(T(r.status),n||`Request failed (${r.status})`,r.status,e)}async function v(r,n,e={}){let t={};e.body!==void 0&&(t["Content-Type"]="application/json"),e.token&&(t.Authorization=`Bearer ${e.token}`);let s;try{s=await fetch(r+n,{method:e.method??(e.body===void 0?"GET":"POST"),headers:t,body:e.body===void 0?void 0:JSON.stringify(e.body),signal:e.signal,credentials:"omit",cache:"no-store"});}catch(o){throw o?.name==="AbortError"?o:new d("network","Could not reach Character XYZ. Check your connection.")}if(!s.ok)throw await z(s);return s}async function g(r,n,e={}){return (await(await v(r,n,e)).json()).data}async function A(r,n,e){let t=r.body;if(!t)return;let s=t.getReader(),o=new TextDecoder,a="",c=()=>{s.cancel().catch(()=>{});};e?.addEventListener("abort",c);try{for(;;){let{value:h,done:l}=await s.read();if(l)break;a+=o.decode(h,{stream:!0}),a=U(a,n);}a+=o.decode(),U(a+`
|
|
34
34
|
|
|
35
35
|
`,n);}finally{e?.removeEventListener("abort",c);}}function U(r,n){let t=r.replace(/\r\n/g,`
|
|
36
36
|
`),s;for(;(s=t.indexOf(`
|
|
37
37
|
|
|
38
|
-
`))!==-1;){let o=t.slice(0,s);t=t.slice(s+2);let a="message",c=[];for(let
|
|
39
|
-
`)){if(!
|
|
40
|
-
`),l=h;try{l=JSON.parse(h);}catch{}n({event:a,data:l});}return t}function O(r){if(r.byteLength<25)return null;let n=new DataView(r);if(n.getUint8(0)!==67||n.getUint8(1)!==88||n.getUint8(2)!==89||n.getUint8(3)!==90||n.getUint8(4)!==1)return null;let e=n.getUint8(5),t=(n.getUint8(6)&1)!==0,s=7,o=n.getUint16(s,true);if(s+=2,s+o+20>r.byteLength)return null;let a=new TextDecoder().decode(new Uint8Array(r,s,o));s+=o+4+8+4;let c=n.getUint32(s,true);return s+=4,s+c>r.byteLength?null:{kind:e,final:t,corr:a,payload:new Uint8Array(r,s,c)}}var $=.09,V=350,J=25e3,W=()=>({phase:"idle",callId:null,position:null,etaSeconds:null,holdSeconds:null,maxSeconds:null,startedAt:null,endReason:null,muted:false,speaking:false,agentState:"idle",error:null}),S=class extends y{constructor(e,t,s,o={}){super();i(this,"apiUrl",e);i(this,"session",t);i(this,"agentId",s);i(this,"opts",o);i(this,"s",W());i(this,"ticket",null);i(this,"eventsAbort",null);i(this,"ws",null);i(this,"mic",null);i(this,"players",new Map);i(this,"sampleRates",new Map);i(this,"cancelled",new Set);i(this,"speakingCorr",null);i(this,"heartbeat",null);i(this,"loudSince",null);}get state(){return this.s}audible(){let e=this.speakingCorr,t=e?this.players.get(e):void 0;return e&&t?{corr:e,ms:t.playedMs()}:null}voiceLevel(){let e=this.speakingCorr?this.players.get(this.speakingCorr):void 0;return e?e.level():0}set(e){this.s={...this.s,...e},this.emit("state",this.s);}async start(){if(this.s.phase==="idle"){this.set({phase:"joining"}),I();try{this.mic=await P({deviceId:this.opts.deviceId,onFrame:(e,t)=>this.onMicFrame(e,t)});}catch{this.finish("mic-denied","Allow the microphone to talk, or chat instead.");return}try{let e=await this.session.token(),t=await g(this.apiUrl,"/sdk/v1/calls",{method:"POST",body:{},token:e});this.set({callId:t.callId,phase:t.state==="ready"?"joining":"queued",position:t.position??null,etaSeconds:t.etaSeconds??null}),this.follow();}catch(e){let t=e instanceof d?e:new d("unknown","Could not start the call."),s=t.code==="rate_limited"?"busy":"unavailable";this.finish(s,t.message),this.emit("error",t);}}}async follow(){let e=0;for(;this.s.callId&&this.s.phase!=="ended"&&this.s.phase!=="idle";){this.eventsAbort=new AbortController;try{let t=await this.session.token(),s=await w(this.apiUrl,`/sdk/v1/calls/${encodeURIComponent(this.s.callId)}/events`,{token:t,signal:this.eventsAbort.signal});e=0,await A(s,o=>this.onServerEvent(o.event,o.data),this.eventsAbort.signal);}catch(t){if(t?.name==="AbortError")return;if(t instanceof d&&t.code==="not_found"){this.finish("failed","The call ended.");return}if(e+=1,e>5){this.finish("failed","Lost the connection to the call.");return}}if(this.ended())return;await new Promise(t=>setTimeout(t,Math.min(4e3,500*2**e)));}}onServerEvent(e,t){switch(e){case "queued":(this.s.phase==="joining"||this.s.phase==="queued")&&this.set({phase:"queued",position:Number(t.position)||1,etaSeconds:Number(t.etaSeconds)||null});break;case "ready":{typeof t.ticket=="string"&&t.ticket&&(this.ticket=t.ticket);let s=Number(t.holdSeconds)||0;this.s.phase!=="ready"&&this.s.phase!=="connecting"&&this.s.phase!=="live"?(this.set({phase:"ready",holdSeconds:s,position:null,etaSeconds:null}),this.emit("ready",{holdSeconds:s}),this.opts.autoAccept!==false&&this.accept()):this.s.phase==="ready"&&this.set({holdSeconds:s});break}case "live":this.set({phase:"live",maxSeconds:Number(t.maxSeconds)||null,startedAt:this.s.startedAt??Date.now()-(Number(t.elapsedSeconds)||0)*1e3});break;case "ended":this.finish(String(t.reason||"hangup")||"hangup",null);break}}ended(){return this.s.phase==="ended"}accept(){if(this.s.phase!=="ready"||!this.ticket||this.ws)return;this.set({phase:"connecting"});let e=this.apiUrl.replace(/^http/,"ws")+"/sdk/v1/calls/socket",t=new WebSocket(e,[`cxyz-ticket.${this.ticket}`]);this.ticket=null,t.binaryType="arraybuffer",this.ws=t,t.onopen=()=>{let s=this.opts.face,o=s?.emotion?.()??null;t.send(JSON.stringify({type:"agent_identity",agent_id:this.agentId,skin_index:0,blendshapes:!!s,...s?{blendshape_stream:true}:{},...s&&o?{face_emotion:o}:{}})),t.send(JSON.stringify({type:"mic_state",silero:"off",denoise:false})),this.heartbeat=setInterval(()=>this.sendJson({type:"heartbeat"}),J),this.set({phase:"live",startedAt:this.s.startedAt??Date.now()});},t.onmessage=s=>this.onSocket(s.data),t.onclose=()=>{this.ws=null,setTimeout(()=>{(this.s.phase==="live"||this.s.phase==="connecting")&&this.finish("hangup",null);},1500);};}sendJson(e){this.ws?.readyState===WebSocket.OPEN&&this.ws.send(JSON.stringify(e));}onMicFrame(e,t){let s=this.ws;if(!(!s||s.readyState!==WebSocket.OPEN)){if(this.speakingCorr){let o=performance.now();if(t>$){if(this.loudSince??(this.loudSince=o),o-this.loudSince>=V){this.loudSince=null,this.interrupt(),s.send(e);return}}else this.loudSince=null;s.send(new ArrayBuffer(e.byteLength));return}s.send(e);}}onSocket(e){if(e instanceof ArrayBuffer){let s=O(e);if(!s||this.cancelled.has(s.corr))return;if(s.kind===3){this.opts.face&&this.emit("face",{corr:s.corr,payload:s.payload.slice()});return}if(s.kind!==1)return;let o=this.players.get(s.corr);if(!o){for(let[c,h]of this.players)h.stop(),this.players.delete(c);let a=s.corr;o=new C({sampleRate:this.sampleRates.get(a)??16e3,onStart:()=>{this.speakingCorr=a,this.set({speaking:true}),this.emit("line",{corr:a,event:"audible"}),this.sendJson({type:"playback_started",correlationId:a,timestampMs:Date.now()});},onEnd:()=>{this.players.delete(a),this.speakingCorr===a&&(this.speakingCorr=null),this.set({speaking:false}),this.emit("line",{corr:a,event:"end"}),this.sendJson({type:"playback_ended",correlationId:a,timestampMs:Date.now(),reason:"natural"}),this.sendJson({type:"speech_ended"});}}),this.players.set(a,o);}o.enqueue(s.payload),s.final&&o.end();return}if(typeof e!="string")return;let t;try{t=JSON.parse(e);}catch{return}if("AgentSpeechMeta"in t){let s=t.AgentSpeechMeta;s?.correlation_id&&s.sample_rate&&this.sampleRates.set(s.correlation_id,s.sample_rate);return}if("InteractorTranscript"in t){let s=t.InteractorTranscript;s?.text&&this.emit("caption",{id:`v:${s.correlation_id}`,role:"visitor",text:s.text});return}if("AgentReplyTranscript"in t){let s=t.AgentReplyTranscript;s?.text&&!this.cancelled.has(s.correlation_id)&&this.emit("caption",{id:`a:${s.correlation_id}`,role:"agent",text:s.text});return}if(t.type==="turn_cancelled"&&typeof t.correlationId=="string"){let s=t.correlationId;this.cancelled.add(s),this.players.get(s)?.stop(),this.players.delete(s),this.emit("line",{corr:s,event:"end"}),this.speakingCorr===s&&(this.speakingCorr=null,this.set({speaking:false})),this.emit("captionRemoved",`a:${s}`);return}t.kind==="agent_status"&&typeof t.state=="string"&&this.set({agentState:t.state.toLowerCase()});}interrupt(){let e=this.speakingCorr;if(!e)return;let t=this.players.get(e),s=Math.round(t?.playedMs()??0);t?.stop(),this.players.delete(e),this.cancelled.add(e),this.speakingCorr=null,this.set({speaking:false}),this.emit("line",{corr:e,event:"end"}),this.sendJson({type:"playback_ended",correlationId:e,timestampMs:Date.now(),reason:"interrupted"}),this.sendJson({type:"interrupt",correlationId:e,heardMs:s,timestampMs:Date.now()});}setMuted(e){this.mic?.setMuted(e),this.set({muted:e});}async hangUp(){let e=this.s.callId,t=this.s.phase;if(this.finish(t==="live"?"hangup":"left",null),!!e)try{let s=await this.session.token();await w(this.apiUrl,`/sdk/v1/calls/${encodeURIComponent(e)}`,{method:"DELETE",token:s});}catch{}}finish(e,t){if(this.s.phase==="ended")return;this.eventsAbort?.abort(),this.eventsAbort=null,this.heartbeat&&clearInterval(this.heartbeat),this.heartbeat=null;for(let o of this.players.values())o.stop();this.players.clear(),this.speakingCorr=null,this.mic?.stop(),this.mic=null;let s=this.ws;this.ws=null,s&&s.readyState<=WebSocket.OPEN&&s.close(1e3),this.ticket=null,this.set({phase:"ended",endReason:e,speaking:false,holdSeconds:null,error:t});}};var G=0,L=r=>`${r}_${Date.now().toString(36)}_${(G++).toString(36)}`,x=class extends y{constructor(e,t){super();i(this,"apiUrl",e);i(this,"session",t);i(this,"list",[]);i(this,"loaded",false);i(this,"busy",false);i(this,"abort",null);}get messages(){return this.list}get isBusy(){return this.busy}publish(){this.list=[...this.list],this.emit("messages",this.list);}async load(){if(this.loaded)return this.list;let e=await this.session.token(),t=await g(this.apiUrl,"/sdk/v1/chat/messages?limit=50",{token:e}),s=this.list;return this.list=[...t?.messages??[],...s],this.loaded=true,this.publish(),this.list}async send(e){let t=e.trim();if(!t)throw new d("invalid","Say something first.");if(this.busy)throw new d("rate_limited","Wait for the reply first.");this.setBusy(true);let s={id:L("local"),role:"visitor",text:t,createdAt:new Date().toISOString()},o={id:L("reply"),role:"agent",text:"",createdAt:new Date().toISOString(),streaming:true};this.list.push(s,o),this.publish(),this.abort=new AbortController;try{let a=await this.session.token(),c=await w(this.apiUrl,"/sdk/v1/chat/messages",{method:"POST",body:{text:t},token:a,signal:this.abort.signal}),h=null,l=null;if(await A(c,({event:f,data:m})=>{let p=m;if(f==="delta"&&typeof p?.text=="string")o.text+=p.text,this.publish();else if(f==="done"){let k=Array.isArray(p.suggestions)?p.suggestions.filter(b=>typeof b=="string"&&b.trim()!==""):[];h={id:String(p.id),role:"agent",text:String(p.text??o.text),createdAt:String(p.createdAt??o.createdAt),...k.length?{suggestions:k}:{}};}else f==="error"&&(l=typeof p?.message=="string"?p.message:"Something went wrong.");},this.abort.signal),l||!h)throw new d("unknown",l??"The reply was cut off. Try again.");let u=h;return this.replace(o.id,u),u}catch(a){let c=a instanceof d?a:new d("network","The reply was cut off. Try again.");this.list=this.list.filter(l=>l.id!==o.id);let h=this.list.findIndex(l=>l.id===s.id);throw h!==-1&&(this.list[h]={...s,failed:true,...c.status===429?{error:c.message}:{}}),this.publish(),a?.name!=="AbortError"&&this.emit("error",c),c}finally{this.abort=null,this.setBusy(false);}}retry(e){let t=this.list.find(s=>s.id===e&&s.failed);if(!t)throw new d("not_found","Nothing to retry.");return this.list=this.list.filter(s=>s.id!==e),this.publish(),this.send(t.text)}stop(){this.abort?.abort();}replace(e,t){let s=this.list.findIndex(o=>o.id===e);s!==-1&&(this.list[s]=t),this.publish();}setBusy(e){this.busy=e,this.emit("busy",e);}};var B=()=>{let r=new Map;return {get:n=>r.get(n)??null,set:(n,e)=>{r.set(n,e);}}},N=()=>({get(r){try{return globalThis.localStorage?.getItem(r)??null}catch{return null}},set(r,n){try{globalThis.localStorage?.setItem(r,n);}catch{}}}),H=60,E=class{constructor(n){i(this,"src",n);i(this,"current",null);i(this,"inflight",null);if(!n.publishableKey&&!n.getSessionToken)throw new d("invalid","Pass a publishableKey, or getSessionToken for sessions your server mints.")}visitorKey(){return `cxyz:visitor:${(this.src.publishableKey??"server").slice(-12)}`}get info(){return this.current}async token(){let n=Date.now()/1e3;return this.current&&this.current.expiresAt-H>n?this.current.token:(await this.refresh()).token}refresh(){return this.inflight??(this.inflight=this.mint().finally(()=>{this.inflight=null;})),this.inflight}async mint(){let n;if(this.src.getSessionToken){let e=await this.src.getSessionToken();typeof e=="string"?n=await this.describe(e):n=e;}else {let e=this.src.store.get(this.visitorKey())??void 0;n=await g(this.src.apiUrl,"/sdk/v1/sessions",{method:"POST",body:{publishableKey:this.src.publishableKey,agentId:this.src.agentId,visitorId:e}}),this.src.store.set(this.visitorKey(),n.visitorId);}return this.current=n,n}async describe(n){return {...await g(this.src.apiUrl,"/sdk/v1/session",{token:n}),token:n}}};var D="https://api.character.xyz",_=class r extends y{constructor(e,t,s){super();i(this,"apiUrl",e);i(this,"session",t);i(this,"info",s);i(this,"chat");i(this,"currentCall",null);i(this,"destroyed",false);i(this,"openingP",null);this.chat=new x(e,t);}static async init(e){let t=(e.apiUrl??D).replace(/\/+$/,"");if(e.publishableKey&&/^cxyz_sk_/.test(e.publishableKey))throw new d("invalid","That is a SECRET key. Never put it in a web page: use a publishable key (cxyz_pk_\u2026). Revoke the secret key now.");let s=e.storage==="memory"?B():e.storage&&typeof e.storage=="object"?e.storage:N(),o=new E({apiUrl:t,agentId:e.agentId,publishableKey:e.publishableKey,getSessionToken:e.getSessionToken,store:s}),a=await o.refresh();return new r(t,o,a)}get agent(){return (this.session.info??this.info).agent}get features(){return (this.session.info??this.info).features}get appearance(){return (this.session.info??this.info).appearance??{}}get visitorId(){return (this.session.info??this.info).visitorId}get mode(){return (this.session.info??this.info).mode}get call(){return this.currentCall&&this.currentCall.state.phase!=="ended"?this.currentCall:null}async videoAvatar(){let e=await this.session.token();return g(this.apiUrl,"/sdk/v1/agent/video-avatar",{token:e})}opening(){return this.openingP??(this.openingP=this.session.token().then(e=>g(this.apiUrl,"/sdk/v1/agent/opening",{token:e})).catch(()=>null)),this.openingP}async startCall(e={}){if(this.destroyed)throw new d("invalid","This client was destroyed.");if(!this.features.call)throw new d("forbidden","Calls are not available on this site.");if(this.call)return this.call;let t=new S(this.apiUrl,this.session,this.agent.id,e);return this.currentCall=t,t.on("state",s=>{s.phase==="ended"&&this.currentCall===t&&this.emit("call",null);}),t.on("error",s=>this.emit("error",s)),this.emit("call",t),await t.start(),t}destroy(){this.destroyed=true,this.currentCall?.hangUp(),this.chat.stop(),this.chat.clear(),this.clear();}};var Te="0.2.0";
|
|
41
|
-
export{
|
|
38
|
+
`))!==-1;){let o=t.slice(0,s);t=t.slice(s+2);let a="message",c=[];for(let p of o.split(`
|
|
39
|
+
`)){if(!p||p.startsWith(":"))continue;let f=p.indexOf(":"),m=f===-1?p:p.slice(0,f),u=f===-1?"":p.slice(f+1).replace(/^ /,"");m==="event"?a=u:m==="data"&&c.push(u);}if(!c.length)continue;let h=c.join(`
|
|
40
|
+
`),l=h;try{l=JSON.parse(h);}catch{}n({event:a,data:l});}return t}function O(r){if(r.byteLength<25)return null;let n=new DataView(r);if(n.getUint8(0)!==67||n.getUint8(1)!==88||n.getUint8(2)!==89||n.getUint8(3)!==90||n.getUint8(4)!==1)return null;let e=n.getUint8(5),t=(n.getUint8(6)&1)!==0,s=7,o=n.getUint16(s,true);if(s+=2,s+o+20>r.byteLength)return null;let a=new TextDecoder().decode(new Uint8Array(r,s,o));s+=o+4+8+4;let c=n.getUint32(s,true);return s+=4,s+c>r.byteLength?null:{kind:e,final:t,corr:a,payload:new Uint8Array(r,s,c)}}var $=.09,V=350,J=25e3,W=()=>({phase:"idle",callId:null,position:null,etaSeconds:null,holdSeconds:null,maxSeconds:null,startedAt:null,endReason:null,muted:false,speaking:false,agentState:"idle",error:null}),k=class extends y{constructor(e,t,s,o={}){super();i(this,"apiUrl",e);i(this,"session",t);i(this,"agentId",s);i(this,"opts",o);i(this,"s",W());i(this,"ticket",null);i(this,"eventsAbort",null);i(this,"ws",null);i(this,"mic",null);i(this,"players",new Map);i(this,"sampleRates",new Map);i(this,"cancelled",new Set);i(this,"speakingCorr",null);i(this,"heartbeat",null);i(this,"loudSince",null);}get state(){return this.s}audible(){let e=this.speakingCorr,t=e?this.players.get(e):void 0;return e&&t?{corr:e,ms:t.playedMs()}:null}voiceLevel(){let e=this.speakingCorr?this.players.get(this.speakingCorr):void 0;return e?e.level():0}set(e){this.s={...this.s,...e},this.emit("state",this.s);}async start(){if(this.s.phase==="idle"){this.set({phase:"joining"}),I();try{this.mic=await _({deviceId:this.opts.deviceId,onFrame:(e,t)=>this.onMicFrame(e,t)});}catch{this.finish("mic-denied","Allow the microphone to talk, or chat instead.");return}try{let e=await this.session.token(),t=await g(this.apiUrl,"/sdk/v1/calls",{method:"POST",body:{},token:e});this.set({callId:t.callId,phase:t.state==="ready"?"joining":"queued",position:t.position??null,etaSeconds:t.etaSeconds??null}),this.follow();}catch(e){let t=e instanceof d?e:new d("unknown","Could not start the call."),s=t.code==="rate_limited"?"busy":"unavailable";this.finish(s,t.message),this.emit("error",t);}}}async follow(){let e=0;for(;this.s.callId&&this.s.phase!=="ended"&&this.s.phase!=="idle";){this.eventsAbort=new AbortController;try{let t=await this.session.token(),s=await v(this.apiUrl,`/sdk/v1/calls/${encodeURIComponent(this.s.callId)}/events`,{token:t,signal:this.eventsAbort.signal});e=0,await A(s,o=>this.onServerEvent(o.event,o.data),this.eventsAbort.signal);}catch(t){if(t?.name==="AbortError")return;if(t instanceof d&&t.code==="not_found"){this.finish("failed","The call ended.");return}if(e+=1,e>5){this.finish("failed","Lost the connection to the call.");return}}if(this.ended())return;await new Promise(t=>setTimeout(t,Math.min(4e3,500*2**e)));}}onServerEvent(e,t){switch(e){case "queued":(this.s.phase==="joining"||this.s.phase==="queued")&&this.set({phase:"queued",position:Number(t.position)||1,etaSeconds:Number(t.etaSeconds)||null});break;case "ready":{typeof t.ticket=="string"&&t.ticket&&(this.ticket=t.ticket);let s=Number(t.holdSeconds)||0;this.s.phase!=="ready"&&this.s.phase!=="connecting"&&this.s.phase!=="live"?(this.set({phase:"ready",holdSeconds:s,position:null,etaSeconds:null}),this.emit("ready",{holdSeconds:s}),this.opts.autoAccept!==false&&this.accept()):this.s.phase==="ready"&&this.set({holdSeconds:s});break}case "live":this.set({phase:"live",maxSeconds:Number(t.maxSeconds)||null,startedAt:this.s.startedAt??Date.now()-(Number(t.elapsedSeconds)||0)*1e3});break;case "ended":this.finish(String(t.reason||"hangup")||"hangup",null);break}}ended(){return this.s.phase==="ended"}accept(){if(this.s.phase!=="ready"||!this.ticket||this.ws)return;this.set({phase:"connecting"});let e=this.apiUrl.replace(/^http/,"ws")+"/sdk/v1/calls/socket",t=new WebSocket(e,[`cxyz-ticket.${this.ticket}`]);this.ticket=null,t.binaryType="arraybuffer",this.ws=t,t.onopen=()=>{let s=this.opts.face,o=s?.emotion?.()??null;t.send(JSON.stringify({type:"agent_identity",agent_id:this.agentId,skin_index:0,blendshapes:!!s,...s?{blendshape_stream:true}:{},...s&&o?{face_emotion:o}:{}})),t.send(JSON.stringify({type:"mic_state",silero:"off",denoise:false})),this.heartbeat=setInterval(()=>this.sendJson({type:"heartbeat"}),J),this.set({phase:"live",startedAt:this.s.startedAt??Date.now()});},t.onmessage=s=>this.onSocket(s.data),t.onclose=()=>{this.ws=null,setTimeout(()=>{(this.s.phase==="live"||this.s.phase==="connecting")&&this.finish("hangup",null);},1500);};}sendJson(e){this.ws?.readyState===WebSocket.OPEN&&this.ws.send(JSON.stringify(e));}onMicFrame(e,t){let s=this.ws;if(!(!s||s.readyState!==WebSocket.OPEN)){if(this.speakingCorr){let o=performance.now();if(t>$){if(this.loudSince??(this.loudSince=o),o-this.loudSince>=V){this.loudSince=null,this.interrupt(),s.send(e);return}}else this.loudSince=null;s.send(new ArrayBuffer(e.byteLength));return}s.send(e);}}onSocket(e){if(e instanceof ArrayBuffer){let s=O(e);if(!s||this.cancelled.has(s.corr))return;if(s.kind===3){this.opts.face&&this.emit("face",{corr:s.corr,payload:s.payload.slice()});return}if(s.kind!==1)return;let o=this.players.get(s.corr);if(!o){for(let[c,h]of this.players)h.stop(),this.players.delete(c);let a=s.corr;o=new C({sampleRate:this.sampleRates.get(a)??16e3,onStart:()=>{this.speakingCorr=a,this.set({speaking:true}),this.emit("line",{corr:a,event:"audible"}),this.sendJson({type:"playback_started",correlationId:a,timestampMs:Date.now()});},onEnd:()=>{this.players.delete(a),this.speakingCorr===a&&(this.speakingCorr=null),this.set({speaking:false}),this.emit("line",{corr:a,event:"end"}),this.sendJson({type:"playback_ended",correlationId:a,timestampMs:Date.now(),reason:"natural"}),this.sendJson({type:"speech_ended"});}}),this.players.set(a,o);}o.enqueue(s.payload),s.final&&o.end();return}if(typeof e!="string")return;let t;try{t=JSON.parse(e);}catch{return}if("AgentSpeechMeta"in t){let s=t.AgentSpeechMeta;s?.correlation_id&&s.sample_rate&&this.sampleRates.set(s.correlation_id,s.sample_rate);return}if("InteractorTranscript"in t){let s=t.InteractorTranscript;s?.text&&this.emit("caption",{id:`v:${s.correlation_id}`,role:"visitor",text:s.text});return}if("AgentReplyTranscript"in t){let s=t.AgentReplyTranscript;s?.text&&!this.cancelled.has(s.correlation_id)&&this.emit("caption",{id:`a:${s.correlation_id}`,role:"agent",text:s.text});return}if(t.type==="turn_cancelled"&&typeof t.correlationId=="string"){let s=t.correlationId;this.cancelled.add(s),this.players.get(s)?.stop(),this.players.delete(s),this.emit("line",{corr:s,event:"end"}),this.speakingCorr===s&&(this.speakingCorr=null,this.set({speaking:false})),this.emit("captionRemoved",`a:${s}`);return}t.kind==="agent_status"&&typeof t.state=="string"&&this.set({agentState:t.state.toLowerCase()});}interrupt(){let e=this.speakingCorr;if(!e)return;let t=this.players.get(e),s=Math.round(t?.playedMs()??0);t?.stop(),this.players.delete(e),this.cancelled.add(e),this.speakingCorr=null,this.set({speaking:false}),this.emit("line",{corr:e,event:"end"}),this.sendJson({type:"playback_ended",correlationId:e,timestampMs:Date.now(),reason:"interrupted"}),this.sendJson({type:"interrupt",correlationId:e,heardMs:s,timestampMs:Date.now()});}setMuted(e){this.mic?.setMuted(e),this.set({muted:e});}async hangUp(){let e=this.s.callId,t=this.s.phase;if(this.finish(t==="live"?"hangup":"left",null),!!e)try{let s=await this.session.token();await v(this.apiUrl,`/sdk/v1/calls/${encodeURIComponent(e)}`,{method:"DELETE",token:s});}catch{}}finish(e,t){if(this.s.phase==="ended")return;this.eventsAbort?.abort(),this.eventsAbort=null,this.heartbeat&&clearInterval(this.heartbeat),this.heartbeat=null;for(let o of this.players.values())o.stop();this.players.clear(),this.speakingCorr=null,this.mic?.stop(),this.mic=null;let s=this.ws;this.ws=null,s&&s.readyState<=WebSocket.OPEN&&s.close(1e3),this.ticket=null,this.set({phase:"ended",endReason:e,speaking:false,holdSeconds:null,error:t});}};var G=0,L=r=>`${r}_${Date.now().toString(36)}_${(G++).toString(36)}`,S=class extends y{constructor(e,t){super();i(this,"apiUrl",e);i(this,"session",t);i(this,"list",[]);i(this,"loaded",false);i(this,"busy",false);i(this,"abort",null);}get messages(){return this.list}get isBusy(){return this.busy}publish(){this.list=[...this.list],this.emit("messages",this.list);}async load(){if(this.loaded)return this.list;let e=await this.session.token(),t=await g(this.apiUrl,"/sdk/v1/chat/messages?limit=50",{token:e}),s=this.list;return this.list=[...t?.messages??[],...s],this.loaded=true,this.publish(),this.list}async send(e){let t=e.trim();if(!t)throw new d("invalid","Say something first.");if(this.busy)throw new d("rate_limited","Wait for the reply first.");this.setBusy(true);let s={id:L("local"),role:"visitor",text:t,createdAt:new Date().toISOString()},o={id:L("reply"),role:"agent",text:"",createdAt:new Date().toISOString(),streaming:true};this.list.push(s,o),this.publish(),this.abort=new AbortController;try{let a=await this.session.token(),c=await v(this.apiUrl,"/sdk/v1/chat/messages",{method:"POST",body:{text:t},token:a,signal:this.abort.signal}),h=null,l=null;if(await A(c,({event:f,data:m})=>{let u=m;if(f==="delta"&&typeof u?.text=="string")o.text+=u.text,this.publish();else if(f==="done"){let x=Array.isArray(u.suggestions)?u.suggestions.filter(b=>typeof b=="string"&&b.trim()!==""):[];h={id:String(u.id),role:"agent",text:String(u.text??o.text),createdAt:String(u.createdAt??o.createdAt),...x.length?{suggestions:x}:{},...u.askDetails&&typeof u.askDetails=="object"?{askDetails:u.askDetails}:{},...u.detailsForm&&typeof u.detailsForm=="object"?{detailsForm:u.detailsForm}:{}};}else f==="error"&&(l=typeof u?.message=="string"?u.message:"Something went wrong.");},this.abort.signal),l||!h)throw new d("unknown",l??"The reply was cut off. Try again.");let p=h;return this.replace(o.id,p),p}catch(a){let c=a instanceof d?a:new d("network","The reply was cut off. Try again.");this.list=this.list.filter(l=>l.id!==o.id);let h=this.list.findIndex(l=>l.id===s.id);throw h!==-1&&(this.list[h]={...s,failed:true,...c.status===429?{error:c.message}:{}}),this.publish(),a?.name!=="AbortError"&&this.emit("error",c),c}finally{this.abort=null,this.setBusy(false);}}async reset(){this.stop();let e=await this.session.token();await v(this.apiUrl,"/sdk/v1/chat/messages",{method:"DELETE",token:e}),this.list=[],this.loaded=true,this.publish();}retry(e){let t=this.list.find(s=>s.id===e&&s.failed);if(!t)throw new d("not_found","Nothing to retry.");return this.list=this.list.filter(s=>s.id!==e),this.publish(),this.send(t.text)}stop(){this.abort?.abort();}replace(e,t){let s=this.list.findIndex(o=>o.id===e);s!==-1&&(this.list[s]=t),this.publish();}setBusy(e){this.busy=e,this.emit("busy",e);}};var D=()=>{let r=new Map;return {get:n=>r.get(n)??null,set:(n,e)=>{r.set(n,e);}}},B=()=>({get(r){try{return globalThis.localStorage?.getItem(r)??null}catch{return null}},set(r,n){try{globalThis.localStorage?.setItem(r,n);}catch{}}}),H=60,E=class{constructor(n){i(this,"src",n);i(this,"current",null);i(this,"inflight",null);if(!n.publishableKey&&!n.getSessionToken)throw new d("invalid","Pass a publishableKey, or getSessionToken for sessions your server mints.")}visitorKey(){return `cxyz:visitor:${(this.src.publishableKey??"server").slice(-12)}`}get info(){return this.current}async token(){let n=Date.now()/1e3;return this.current&&this.current.expiresAt-H>n?this.current.token:(await this.refresh()).token}refresh(){return this.inflight??(this.inflight=this.mint().finally(()=>{this.inflight=null;})),this.inflight}async mint(){let n;if(this.src.getSessionToken){let e=await this.src.getSessionToken();typeof e=="string"?n=await this.describe(e):n=e;}else {let e=this.src.store.get(this.visitorKey())??void 0;n=await g(this.src.apiUrl,"/sdk/v1/sessions",{method:"POST",body:{publishableKey:this.src.publishableKey,agentId:this.src.agentId,visitorId:e}}),this.src.store.set(this.visitorKey(),n.visitorId);}return this.current=n,n}async describe(n){return {...await g(this.src.apiUrl,"/sdk/v1/session",{token:n}),token:n}}};var F="https://api.character.xyz",P=class r extends y{constructor(e,t,s){super();i(this,"apiUrl",e);i(this,"session",t);i(this,"info",s);i(this,"chat");i(this,"currentCall",null);i(this,"destroyed",false);i(this,"openingP",null);this.chat=new S(e,t);}static async init(e){let t=(e.apiUrl??F).replace(/\/+$/,"");if(e.publishableKey&&/^cxyz_sk_/.test(e.publishableKey))throw new d("invalid","That is a SECRET key. Never put it in a web page: use a publishable key (cxyz_pk_\u2026). Revoke the secret key now.");let s=e.storage==="memory"?D():e.storage&&typeof e.storage=="object"?e.storage:B(),o=new E({apiUrl:t,agentId:e.agentId,publishableKey:e.publishableKey,getSessionToken:e.getSessionToken,store:s}),a=await o.refresh();return new r(t,o,a)}get agent(){return (this.session.info??this.info).agent}get features(){return (this.session.info??this.info).features}get appearance(){return (this.session.info??this.info).appearance??{}}get visitorId(){return (this.session.info??this.info).visitorId}get mode(){return (this.session.info??this.info).mode}get call(){return this.currentCall&&this.currentCall.state.phase!=="ended"?this.currentCall:null}async videoAvatar(){let e=await this.session.token();return g(this.apiUrl,"/sdk/v1/agent/video-avatar",{token:e})}opening(e=false){return e&&(this.openingP=null),this.openingP??(this.openingP=this.session.token().then(t=>g(this.apiUrl,"/sdk/v1/agent/opening",{token:t})).catch(()=>null)),this.openingP}async sendDetails(e){let t=await this.session.token(),s=typeof location<"u"?location.href:void 0;await g(this.apiUrl,"/sdk/v1/lead",{token:t,body:{...e,consent:true,...s?{page:s}:{}}});}async declineDetails(){let e=await this.session.token();await g(this.apiUrl,"/sdk/v1/lead/decline",{token:e,method:"POST",body:{}});}async startCall(e={}){if(this.destroyed)throw new d("invalid","This client was destroyed.");if(!this.features.call)throw new d("forbidden","Calls are not available on this site.");if(this.call)return this.call;let t=new k(this.apiUrl,this.session,this.agent.id,e);return this.currentCall=t,t.on("state",s=>{s.phase==="ended"&&this.currentCall===t&&this.emit("call",null);}),t.on("error",s=>this.emit("error",s)),this.emit("call",t),await t.start(),t}destroy(){this.destroyed=true,this.currentCall?.hangUp(),this.chat.stop(),this.chat.clear(),this.clear();}};var Te="0.3.0";
|
|
41
|
+
export{k as Call,P as CharacterXYZ,S as Chat,d as CxError,F as DEFAULT_API_URL,y as Emitter,Te as VERSION};//# sourceMappingURL=index.js.map
|
|
42
42
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/audio/player.ts","../src/audio/mic.ts","../src/emitter.ts","../src/errors.ts","../src/http.ts","../src/protocol.ts","../src/call.ts","../src/chat.ts","../src/session.ts","../src/client.ts","../src/index.ts"],"names":["shared","audioContext","PcmPlayer","opts","__publicField","bytes","count","view","buf","ch","i","src","now","delayMs","s","sum","v","WORKLET","levelOf","pcm","openMic","stream","ctx","source","muted","deliver","node","teardown","url","w","e","sp","ratio","pos","out","n","sink","m","t","Emitter","event","fn","_a","payload","CxError","code","message","status","codeForStatus","errorFrom","res","j","send","apiUrl","path","headers","request","readEvents","onEvent","signal","body","reader","decoder","onAbort","value","done","drain","rest","idx","block","data","line","colon","field","raw","parsed","parsePacket","kind","final","o","corrLen","corr","len","BARGE_IN_LEVEL","BARGE_IN_MS","HEARTBEAT_MS","initial","Call","session","agentId","p","patch","level","token","r","err","reason","failures","d","hold","ws","face","emotion","player","old","cid","heardMs","id","was","error","localSeq","localId","Chat","pending","text","mine","reply","finished","failure","next","q","x","b","memoryStore","k","localStore","RENEW_EARLY_S","SessionManager","info","got","visitorId","DEFAULT_API_URL","CharacterXYZ","_CharacterXYZ","store","call","VERSION"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Plays the agent's streamed voice (PCM16 chunks) gaplessly, and reports how\n * loud it is right now so a UI can draw a ring that follows the voice.\n *\n * Each chunk becomes an AudioBuffer scheduled right after the last one; the\n * first waits a short pre-roll so a slow second chunk does not open a gap.\n */\n\nexport interface PlayerOptions {\n sampleRate?: number;\n onStart?: () => void;\n onEnd?: () => void;\n volume?: number;\n}\n\nconst PREROLL_S = 0.12;\n\nlet shared: AudioContext | null = null;\n\n/** One output context for the page, created on first use (after a gesture). */\nexport function audioContext(): AudioContext {\n if (!shared || shared.state === 'closed') shared = new AudioContext({ latencyHint: 'interactive' });\n if (shared.state === 'suspended') void shared.resume().catch(() => {});\n return shared;\n}\n\nexport class PcmPlayer {\n private readonly ctx: AudioContext;\n private readonly gain: GainNode;\n private readonly analyser: AnalyserNode;\n private readonly data: Uint8Array<ArrayBuffer>;\n private nextAt = 0;\n private started = false;\n private ended = false;\n private finishing = false;\n private sources = new Set<AudioBufferSourceNode>();\n private startedAt = 0;\n readonly sampleRate: number;\n\n constructor(private readonly opts: PlayerOptions = {}) {\n this.ctx = audioContext();\n this.sampleRate = opts.sampleRate ?? 16_000;\n this.gain = this.ctx.createGain();\n this.gain.gain.value = opts.volume ?? 1;\n this.analyser = this.ctx.createAnalyser();\n this.analyser.fftSize = 512;\n this.data = new Uint8Array(new ArrayBuffer(this.analyser.fftSize));\n this.gain.connect(this.analyser).connect(this.ctx.destination);\n }\n\n /** Queue PCM16 little-endian mono bytes. */\n enqueue(bytes: Uint8Array): void {\n if (this.ended || bytes.byteLength < 2) return;\n const count = Math.floor(bytes.byteLength / 2);\n const view = new DataView(bytes.buffer, bytes.byteOffset, count * 2);\n const buf = this.ctx.createBuffer(1, count, this.sampleRate);\n const ch = buf.getChannelData(0);\n for (let i = 0; i < count; i++) ch[i] = view.getInt16(i * 2, true) / 32768;\n const src = this.ctx.createBufferSource();\n src.buffer = buf;\n src.connect(this.gain);\n const now = this.ctx.currentTime;\n if (this.nextAt < now) this.nextAt = now + (this.started ? 0.02 : PREROLL_S);\n src.start(this.nextAt);\n if (!this.started) {\n this.started = true;\n const delayMs = Math.max(0, (this.nextAt - now) * 1000);\n this.startedAt = performance.now() + delayMs;\n setTimeout(() => this.opts.onStart?.(), delayMs);\n }\n this.nextAt += buf.duration;\n this.sources.add(src);\n src.onended = () => {\n this.sources.delete(src);\n if (this.finishing && this.sources.size === 0) this.finish();\n };\n }\n\n /** No more chunks: report the end once the queue has played out. */\n end(): void {\n this.finishing = true;\n if (this.sources.size === 0) this.finish();\n }\n\n /** Silence now (an interruption). Does not call `onEnd`. */\n stop(): void {\n this.ended = true;\n for (const s of this.sources) {\n try {\n s.stop();\n } catch {\n /* not started */\n }\n }\n this.sources.clear();\n this.gain.disconnect();\n }\n\n /** Milliseconds of audio actually heard so far. */\n playedMs(): number {\n return this.started ? Math.max(0, performance.now() - this.startedAt) : 0;\n }\n\n /** Loudness now, 0..1. */\n level(): number {\n this.analyser.getByteTimeDomainData(this.data);\n let sum = 0;\n for (let i = 0; i < this.data.length; i++) {\n const v = (this.data[i]! - 128) / 128;\n sum += v * v;\n }\n return Math.min(1, Math.sqrt(sum / this.data.length) * 3);\n }\n\n private finish() {\n if (this.ended) return;\n this.ended = true;\n this.gain.disconnect();\n this.opts.onEnd?.();\n }\n}\n","/**\n * The microphone as the agent socket wants it: 16 kHz mono PCM16, 30 ms\n * (480-sample) frames, sent continuously.\n *\n * Resampled in an AudioWorklet from whatever rate the device runs at. A\n * context forced to 16 kHz would be simpler and is refused by Firefox for a\n * MediaStream source at another rate, so the worklet does it.\n */\n\nexport const TARGET_RATE = 16_000;\nexport const FRAME_SAMPLES = 480;\n\nconst WORKLET = `\nclass CxyzMic extends AudioWorkletProcessor {\n constructor(o) {\n super();\n this.ratio = sampleRate / ${TARGET_RATE};\n this.pos = 0;\n this.lp = 0;\n this.alpha = Math.min(1, 2 * Math.PI * 7000 / sampleRate / (1 + 2 * Math.PI * 7000 / sampleRate));\n this.out = new Int16Array(${FRAME_SAMPLES});\n this.n = 0;\n }\n process(inputs) {\n const ch = inputs[0] && inputs[0][0];\n if (!ch) return true;\n for (let i = 0; i < ch.length; i++) {\n this.lp += this.alpha * (ch[i] - this.lp);\n this.pos += 1;\n if (this.pos >= this.ratio) {\n this.pos -= this.ratio;\n const s = Math.max(-1, Math.min(1, this.lp));\n this.out[this.n++] = s < 0 ? s * 0x8000 : s * 0x7fff;\n if (this.n === ${FRAME_SAMPLES}) {\n this.port.postMessage(this.out.buffer, [this.out.buffer]);\n this.out = new Int16Array(${FRAME_SAMPLES});\n this.n = 0;\n }\n }\n }\n return true;\n }\n}\nregisterProcessor('cxyz-mic', CxyzMic);\n`;\n\nexport interface MicOptions {\n onFrame: (pcm: ArrayBuffer, level: number) => void;\n deviceId?: string;\n}\n\nexport interface Mic {\n stop(): void;\n setMuted(m: boolean): void;\n readonly muted: boolean;\n}\n\n/** RMS of a PCM16 frame, 0..1. */\nexport function levelOf(pcm: ArrayBuffer): number {\n const s = new Int16Array(pcm);\n if (!s.length) return 0;\n let sum = 0;\n for (let i = 0; i < s.length; i++) {\n const v = s[i]! / 32768;\n sum += v * v;\n }\n return Math.sqrt(sum / s.length);\n}\n\nexport async function openMic(opts: MicOptions): Promise<Mic> {\n if (!navigator.mediaDevices?.getUserMedia) throw new Error('This browser cannot use a microphone here.');\n const stream = await navigator.mediaDevices.getUserMedia({\n audio: {\n deviceId: opts.deviceId ? { exact: opts.deviceId } : undefined,\n channelCount: 1,\n // The agent's voice comes out of the speakers; without cancellation it\n // would hear itself and answer.\n echoCancellation: true,\n noiseSuppression: true,\n autoGainControl: true,\n },\n });\n const ctx = new AudioContext({ latencyHint: 'interactive' });\n const source = ctx.createMediaStreamSource(stream);\n let muted = false;\n const deliver = (buf: ArrayBuffer) => {\n if (muted) {\n // Silence, not nothing: the server keeps a pre-roll of the last frames\n // and splices it onto the next utterance.\n opts.onFrame(new ArrayBuffer(buf.byteLength), 0);\n return;\n }\n opts.onFrame(buf, levelOf(buf));\n };\n\n let node: AudioNode;\n let teardown: () => void;\n try {\n const url = URL.createObjectURL(new Blob([WORKLET], { type: 'application/javascript' }));\n try {\n await ctx.audioWorklet.addModule(url);\n } finally {\n URL.revokeObjectURL(url);\n }\n const w = new AudioWorkletNode(ctx, 'cxyz-mic');\n w.port.onmessage = (e) => deliver(e.data as ArrayBuffer);\n node = w;\n teardown = () => {\n w.port.onmessage = null;\n };\n } catch {\n // A strict Content-Security-Policy can refuse a blob: worklet. The old\n // ScriptProcessor path is deprecated but universal.\n const sp = ctx.createScriptProcessor(4096, 1, 1);\n const ratio = ctx.sampleRate / TARGET_RATE;\n let pos = 0;\n let out = new Int16Array(FRAME_SAMPLES);\n let n = 0;\n sp.onaudioprocess = (e) => {\n const ch = e.inputBuffer.getChannelData(0);\n for (let i = 0; i < ch.length; i++) {\n pos += 1;\n if (pos >= ratio) {\n pos -= ratio;\n const s = Math.max(-1, Math.min(1, ch[i]!));\n out[n++] = s < 0 ? s * 0x8000 : s * 0x7fff;\n if (n === FRAME_SAMPLES) {\n deliver(out.buffer);\n out = new Int16Array(FRAME_SAMPLES);\n n = 0;\n }\n }\n }\n };\n node = sp;\n teardown = () => {\n sp.onaudioprocess = null;\n };\n }\n source.connect(node);\n // A worklet/processor only runs while connected to the destination; a gain\n // of zero keeps the room from hearing itself.\n const sink = ctx.createGain();\n sink.gain.value = 0;\n node.connect(sink).connect(ctx.destination);\n if (ctx.state === 'suspended') await ctx.resume().catch(() => {});\n\n return {\n get muted() {\n return muted;\n },\n setMuted(m: boolean) {\n muted = m;\n for (const t of stream.getAudioTracks()) t.enabled = !m;\n },\n stop() {\n teardown();\n try {\n source.disconnect();\n node.disconnect();\n } catch {\n /* already disconnected */\n }\n for (const t of stream.getTracks()) t.stop();\n void ctx.close().catch(() => {});\n },\n };\n}\n","/** A tiny typed event emitter. `on` returns the unsubscribe. */\nexport class Emitter<Events extends Record<string, unknown>> {\n private handlers: { [K in keyof Events]?: Set<(payload: Events[K]) => void> } = {};\n\n on<K extends keyof Events>(event: K, fn: (payload: Events[K]) => void): () => void {\n (this.handlers[event] ??= new Set()).add(fn);\n return () => this.handlers[event]?.delete(fn);\n }\n\n emit<K extends keyof Events>(event: K, payload: Events[K]): void {\n for (const fn of this.handlers[event] ?? []) {\n try {\n fn(payload);\n } catch (e) {\n // A listener's bug must never break the SDK's own state machine.\n console.error('[characterxyz] listener threw', e);\n }\n }\n }\n\n clear(): void {\n this.handlers = {};\n }\n}\n","export type CxErrorCode =\n | 'unauthorized'\n | 'forbidden'\n | 'not_found'\n | 'invalid'\n | 'rate_limited'\n | 'payment_required'\n | 'unavailable'\n | 'network'\n | 'unknown';\n\n/** Every failure the SDK reports, with a message fit to show a visitor. */\nexport class CxError extends Error {\n readonly code: CxErrorCode;\n readonly status: number;\n\n constructor(code: CxErrorCode, message: string, status = 0) {\n super(message);\n this.name = 'CxError';\n this.code = code;\n this.status = status;\n }\n}\n\nexport function codeForStatus(status: number): CxErrorCode {\n switch (status) {\n case 401:\n return 'unauthorized';\n case 403:\n return 'forbidden';\n case 404:\n return 'not_found';\n case 402:\n return 'payment_required';\n case 422:\n return 'invalid';\n case 429:\n return 'rate_limited';\n case 503:\n return 'unavailable';\n default:\n return 'unknown';\n }\n}\n","import { CxError, codeForStatus } from './errors.js';\n\nexport interface RequestOptions {\n method?: string;\n body?: unknown;\n token?: string;\n signal?: AbortSignal;\n}\n\nasync function errorFrom(res: Response): Promise<CxError> {\n let message = '';\n try {\n const j = (await res.json()) as { message?: unknown };\n if (typeof j?.message === 'string') message = j.message;\n } catch {\n // not JSON: the status says enough\n }\n return new CxError(codeForStatus(res.status), message || `Request failed (${res.status})`, res.status);\n}\n\nexport async function send(apiUrl: string, path: string, opts: RequestOptions = {}): Promise<Response> {\n const headers: Record<string, string> = {};\n if (opts.body !== undefined) headers['Content-Type'] = 'application/json';\n if (opts.token) headers.Authorization = `Bearer ${opts.token}`;\n let res: Response;\n try {\n res = await fetch(apiUrl + path, {\n method: opts.method ?? (opts.body === undefined ? 'GET' : 'POST'),\n headers,\n body: opts.body === undefined ? undefined : JSON.stringify(opts.body),\n signal: opts.signal,\n // No cookies, ever: the SDK authenticates with its own bearer token, and\n // a credentialed request would carry the brand page's cookies to us.\n credentials: 'omit',\n cache: 'no-store',\n });\n } catch (e) {\n if ((e as Error)?.name === 'AbortError') throw e;\n throw new CxError('network', 'Could not reach Character XYZ. Check your connection.');\n }\n if (!res.ok) throw await errorFrom(res);\n return res;\n}\n\n/** JSON request; unwraps the API's `{message, data}` envelope. */\nexport async function request<T>(apiUrl: string, path: string, opts: RequestOptions = {}): Promise<T> {\n const res = await send(apiUrl, path, opts);\n const j = (await res.json()) as { data?: T };\n return j.data as T;\n}\n\nexport interface ServerEvent {\n event: string;\n data: unknown;\n}\n\n/**\n * Read a `text/event-stream` body, calling `onEvent` per event, until the\n * stream ends or `signal` aborts. Fetch-based on purpose: `EventSource` cannot\n * send an Authorization header, so it would need the token in the URL.\n */\nexport async function readEvents(res: Response, onEvent: (e: ServerEvent) => void, signal?: AbortSignal): Promise<void> {\n const body = res.body;\n if (!body) return;\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buf = '';\n const onAbort = () => void reader.cancel().catch(() => {});\n signal?.addEventListener('abort', onAbort);\n try {\n for (;;) {\n const { value, done } = await reader.read();\n if (done) break;\n buf += decoder.decode(value, { stream: true });\n buf = drain(buf, onEvent);\n }\n buf += decoder.decode();\n drain(buf + '\\n\\n', onEvent);\n } finally {\n signal?.removeEventListener('abort', onAbort);\n }\n}\n\n/** Dispatch every complete event in `buf`; return what is left over. */\nexport function drain(buf: string, onEvent: (e: ServerEvent) => void): string {\n const normalised = buf.replace(/\\r\\n/g, '\\n');\n let rest = normalised;\n let idx: number;\n while ((idx = rest.indexOf('\\n\\n')) !== -1) {\n const block = rest.slice(0, idx);\n rest = rest.slice(idx + 2);\n let event = 'message';\n const data: string[] = [];\n for (const line of block.split('\\n')) {\n if (!line || line.startsWith(':')) continue;\n const colon = line.indexOf(':');\n const field = colon === -1 ? line : line.slice(0, colon);\n const value = colon === -1 ? '' : line.slice(colon + 1).replace(/^ /, '');\n if (field === 'event') event = value;\n else if (field === 'data') data.push(value);\n }\n if (!data.length) continue;\n const raw = data.join('\\n');\n let parsed: unknown = raw;\n try {\n parsed = JSON.parse(raw);\n } catch {\n // plain text data\n }\n onEvent({ event, data: parsed });\n }\n return rest;\n}\n","/**\n * The agent socket's binary packet (the same one the Stage reads):\n *\n * \"CXYZ\" | version u8 (1) | kind u8 | flags u8 (bit 0 = final)\n * | corrLen u16 | corr utf8 | seq u32 | timestamp u64 | duration u32\n * | payloadLen u32 | payload\n *\n * All little-endian. Kind 1 is voice (PCM16), kind 2/3 are face data, which\n * this SDK does not draw yet.\n */\nexport interface Packet {\n kind: number;\n final: boolean;\n corr: string;\n payload: Uint8Array;\n}\n\nexport function parsePacket(buf: ArrayBuffer): Packet | null {\n if (buf.byteLength < 25) return null;\n const v = new DataView(buf);\n if (v.getUint8(0) !== 0x43 || v.getUint8(1) !== 0x58 || v.getUint8(2) !== 0x59 || v.getUint8(3) !== 0x5a) return null;\n if (v.getUint8(4) !== 1) return null;\n const kind = v.getUint8(5);\n const final = (v.getUint8(6) & 1) !== 0;\n let o = 7;\n const corrLen = v.getUint16(o, true);\n o += 2;\n if (o + corrLen + 20 > buf.byteLength) return null;\n const corr = new TextDecoder().decode(new Uint8Array(buf, o, corrLen));\n o += corrLen + 4 + 8 + 4;\n const len = v.getUint32(o, true);\n o += 4;\n if (o + len > buf.byteLength) return null;\n return { kind, final, corr, payload: new Uint8Array(buf, o, len) };\n}\n\n/** Build one (for tests and tools). */\nexport function buildPacket(p: { kind: number; final: boolean; corr: string; payload: Uint8Array }): ArrayBuffer {\n const corr = new TextEncoder().encode(p.corr);\n const head = 7 + 2 + corr.length + 4 + 8 + 4 + 4;\n const buf = new ArrayBuffer(head + p.payload.byteLength);\n const v = new DataView(buf);\n const bytes = new Uint8Array(buf);\n bytes.set([0x43, 0x58, 0x59, 0x5a], 0);\n v.setUint8(4, 1);\n v.setUint8(5, p.kind);\n v.setUint8(6, p.final ? 1 : 0);\n let o = 7;\n v.setUint16(o, corr.length, true);\n o += 2;\n bytes.set(corr, o);\n o += corr.length + 4 + 8 + 4;\n v.setUint32(o, p.payload.byteLength, true);\n o += 4;\n bytes.set(p.payload, o);\n return buf;\n}\n","import { audioContext, PcmPlayer } from './audio/player.js';\nimport { openMic, type Mic } from './audio/mic.js';\nimport { Emitter } from './emitter.js';\nimport { CxError } from './errors.js';\nimport { readEvents, request, send } from './http.js';\nimport { parsePacket } from './protocol.js';\nimport type { SessionManager } from './session.js';\nimport type { CallEndReason, CallState, Caption } from './types.js';\n\nexport interface CallEvents extends Record<string, unknown> {\n state: CallState;\n /** The visitor's words and the agent's reply, as they are recognised. */\n caption: Caption;\n /** A caption the server withdrew (the visitor was not finished). */\n captionRemoved: string;\n /** The turn is ready: accept() within `holdSeconds`. */\n ready: { holdSeconds: number };\n /** One streamed face batch (kind-3 msgpack payload) for line `corr` — only with `face`. */\n face: { corr: string; payload: Uint8Array };\n /** A line of the agent's voice became audible, or ended (naturally or interrupted). */\n line: { corr: string; event: 'audible' | 'end' };\n error: CxError;\n}\n\nexport interface CallOptions {\n /** Join the moment it is this visitor's turn (default true). */\n autoAccept?: boolean;\n deviceId?: string;\n /**\n * Ask for the agent's face streamed with the voice (Neural Lip Sync), for a\n * UI that draws it. `emotion()` is read when the call connects: the face's\n * mood as the face service takes it (`joy:0.3`), or null for neutral.\n */\n face?: { emotion?: () => string | null };\n}\n\n/** Talking over the agent this loud, this long, stops her. */\nconst BARGE_IN_LEVEL = 0.09;\nconst BARGE_IN_MS = 350;\nconst HEARTBEAT_MS = 25_000;\n\nconst initial = (): CallState => ({\n phase: 'idle',\n callId: null,\n position: null,\n etaSeconds: null,\n holdSeconds: null,\n maxSeconds: null,\n startedAt: null,\n endReason: null,\n muted: false,\n speaking: false,\n agentState: 'idle',\n error: null,\n});\n\n/**\n * One voice call: join the line, wait (chatting is fine meanwhile), accept,\n * talk, hang up. A call is single-use; start another for the next one.\n */\nexport class Call extends Emitter<CallEvents> {\n private s: CallState = initial();\n private ticket: string | null = null;\n private eventsAbort: AbortController | null = null;\n private ws: WebSocket | null = null;\n private mic: Mic | null = null;\n private players = new Map<string, PcmPlayer>();\n private sampleRates = new Map<string, number>();\n private cancelled = new Set<string>();\n private speakingCorr: string | null = null;\n private heartbeat: ReturnType<typeof setInterval> | null = null;\n private loudSince: number | null = null;\n\n constructor(\n private readonly apiUrl: string,\n private readonly session: SessionManager,\n private readonly agentId: string,\n private readonly opts: CallOptions = {},\n ) {\n super();\n }\n\n get state(): CallState {\n return this.s;\n }\n\n /** The line being voiced now, and how much of it has been heard (ms). */\n audible(): { corr: string; ms: number } | null {\n const corr = this.speakingCorr;\n const p = corr ? this.players.get(corr) : undefined;\n return corr && p ? { corr, ms: p.playedMs() } : null;\n }\n\n /** Loudness of the agent's voice right now, 0..1. */\n voiceLevel(): number {\n const p = this.speakingCorr ? this.players.get(this.speakingCorr) : undefined;\n return p ? p.level() : 0;\n }\n\n private set(patch: Partial<CallState>) {\n this.s = { ...this.s, ...patch };\n this.emit('state', this.s);\n }\n\n /**\n * Call from a click: it unlocks audio, asks for the microphone, then joins\n * the line (or goes straight through when a slot is free).\n */\n async start(): Promise<void> {\n if (this.s.phase !== 'idle') return;\n this.set({ phase: 'joining' });\n // Created inside the gesture, or the browser keeps it suspended.\n audioContext();\n try {\n this.mic = await openMic({ deviceId: this.opts.deviceId, onFrame: (pcm, level) => this.onMicFrame(pcm, level) });\n } catch {\n this.finish('mic-denied', 'Allow the microphone to talk, or chat instead.');\n return;\n }\n try {\n const token = await this.session.token();\n const r = await request<{ callId: string; state: string; position?: number; etaSeconds?: number }>(this.apiUrl, '/sdk/v1/calls', {\n method: 'POST',\n body: {},\n token,\n });\n this.set({ callId: r.callId, phase: r.state === 'ready' ? 'joining' : 'queued', position: r.position ?? null, etaSeconds: r.etaSeconds ?? null });\n void this.follow();\n } catch (e) {\n const err = e instanceof CxError ? e : new CxError('unknown', 'Could not start the call.');\n const reason: CallEndReason = err.code === 'rate_limited' ? 'busy' : 'unavailable';\n this.finish(reason, err.message);\n this.emit('error', err);\n }\n }\n\n /** Follow the call's server-side state, reconnecting the stream if it drops. */\n private async follow(): Promise<void> {\n let failures = 0;\n while (this.s.callId && this.s.phase !== 'ended' && this.s.phase !== 'idle') {\n this.eventsAbort = new AbortController();\n try {\n const token = await this.session.token();\n const res = await send(this.apiUrl, `/sdk/v1/calls/${encodeURIComponent(this.s.callId)}/events`, { token, signal: this.eventsAbort.signal });\n failures = 0;\n await readEvents(res, (e) => this.onServerEvent(e.event, e.data as Record<string, unknown>), this.eventsAbort.signal);\n } catch (e) {\n if ((e as Error)?.name === 'AbortError') return;\n if (e instanceof CxError && e.code === 'not_found') {\n this.finish('failed', 'The call ended.');\n return;\n }\n failures += 1;\n if (failures > 5) {\n this.finish('failed', 'Lost the connection to the call.');\n return;\n }\n }\n if (this.ended()) return;\n await new Promise((r) => setTimeout(r, Math.min(4000, 500 * 2 ** failures)));\n }\n }\n\n private onServerEvent(event: string, d: Record<string, unknown>) {\n switch (event) {\n case 'queued':\n if (this.s.phase === 'joining' || this.s.phase === 'queued') {\n this.set({ phase: 'queued', position: Number(d.position) || 1, etaSeconds: Number(d.etaSeconds) || null });\n }\n break;\n case 'ready': {\n if (typeof d.ticket === 'string' && d.ticket) this.ticket = d.ticket;\n const hold = Number(d.holdSeconds) || 0;\n if (this.s.phase !== 'ready' && this.s.phase !== 'connecting' && this.s.phase !== 'live') {\n this.set({ phase: 'ready', holdSeconds: hold, position: null, etaSeconds: null });\n this.emit('ready', { holdSeconds: hold });\n if (this.opts.autoAccept !== false) this.accept();\n } else if (this.s.phase === 'ready') {\n this.set({ holdSeconds: hold });\n }\n break;\n }\n case 'live':\n this.set({ phase: 'live', maxSeconds: Number(d.maxSeconds) || null, startedAt: this.s.startedAt ?? Date.now() - (Number(d.elapsedSeconds) || 0) * 1000 });\n break;\n case 'ended':\n this.finish((String(d.reason || 'hangup') as CallEndReason) || 'hangup', null);\n break;\n }\n }\n\n // A method, not an inline comparison: the phase changes across an await,\n // which TypeScript's narrowing cannot see.\n private ended(): boolean {\n return this.s.phase === 'ended';\n }\n\n /** Take the call now that it is this visitor's turn. */\n accept(): void {\n if (this.s.phase !== 'ready' || !this.ticket || this.ws) return;\n this.set({ phase: 'connecting' });\n const url = this.apiUrl.replace(/^http/, 'ws') + '/sdk/v1/calls/socket';\n const ws = new WebSocket(url, [`cxyz-ticket.${this.ticket}`]);\n this.ticket = null;\n ws.binaryType = 'arraybuffer';\n this.ws = ws;\n ws.onopen = () => {\n const face = this.opts.face;\n const emotion = face?.emotion?.() ?? null;\n ws.send(\n JSON.stringify({\n type: 'agent_identity',\n agent_id: this.agentId,\n skin_index: 0,\n blendshapes: !!face,\n ...(face ? { blendshape_stream: true } : {}),\n ...(face && emotion ? { face_emotion: emotion } : {}),\n }),\n );\n // This page does not gate the microphone: the server's own voice\n // detection judges every frame.\n ws.send(JSON.stringify({ type: 'mic_state', silero: 'off', denoise: false }));\n this.heartbeat = setInterval(() => this.sendJson({ type: 'heartbeat' }), HEARTBEAT_MS);\n this.set({ phase: 'live', startedAt: this.s.startedAt ?? Date.now() });\n };\n ws.onmessage = (e) => this.onSocket(e.data);\n ws.onclose = () => {\n this.ws = null;\n // The event stream says why; give it a moment before calling it ourselves.\n setTimeout(() => {\n if (this.s.phase === 'live' || this.s.phase === 'connecting') this.finish('hangup', null);\n }, 1500);\n };\n }\n\n private sendJson(o: unknown) {\n if (this.ws?.readyState === WebSocket.OPEN) this.ws.send(JSON.stringify(o));\n }\n\n private onMicFrame(pcm: ArrayBuffer, level: number) {\n const ws = this.ws;\n if (!ws || ws.readyState !== WebSocket.OPEN) return;\n if (this.speakingCorr) {\n // The agent must not hear itself: while she talks the frames go up as\n // silence, unless the visitor is clearly talking over her.\n const now = performance.now();\n if (level > BARGE_IN_LEVEL) {\n this.loudSince ??= now;\n if (now - this.loudSince >= BARGE_IN_MS) {\n this.loudSince = null;\n this.interrupt();\n ws.send(pcm);\n return;\n }\n } else {\n this.loudSince = null;\n }\n ws.send(new ArrayBuffer(pcm.byteLength));\n return;\n }\n ws.send(pcm);\n }\n\n private onSocket(data: unknown) {\n if (data instanceof ArrayBuffer) {\n const p = parsePacket(data);\n if (!p || this.cancelled.has(p.corr)) return;\n if (p.kind === 3) {\n // A copy, so the receiver may keep or transfer it.\n if (this.opts.face) this.emit('face', { corr: p.corr, payload: p.payload.slice() });\n return;\n }\n if (p.kind !== 1) return;\n let player = this.players.get(p.corr);\n if (!player) {\n // A new line: whatever was playing is over.\n for (const [c, old] of this.players) {\n old.stop();\n this.players.delete(c);\n }\n const corr = p.corr;\n player = new PcmPlayer({\n sampleRate: this.sampleRates.get(corr) ?? 16_000,\n onStart: () => {\n this.speakingCorr = corr;\n this.set({ speaking: true });\n this.emit('line', { corr, event: 'audible' });\n this.sendJson({ type: 'playback_started', correlationId: corr, timestampMs: Date.now() });\n },\n onEnd: () => {\n this.players.delete(corr);\n if (this.speakingCorr === corr) this.speakingCorr = null;\n this.set({ speaking: false });\n this.emit('line', { corr, event: 'end' });\n this.sendJson({ type: 'playback_ended', correlationId: corr, timestampMs: Date.now(), reason: 'natural' });\n this.sendJson({ type: 'speech_ended' });\n },\n });\n this.players.set(corr, player);\n }\n player.enqueue(p.payload);\n if (p.final) player.end();\n return;\n }\n if (typeof data !== 'string') return;\n let o: Record<string, unknown>;\n try {\n o = JSON.parse(data);\n } catch {\n return;\n }\n if ('AgentSpeechMeta' in o) {\n const m = o.AgentSpeechMeta as { correlation_id?: string; sample_rate?: number };\n if (m?.correlation_id && m.sample_rate) this.sampleRates.set(m.correlation_id, m.sample_rate);\n return;\n }\n if ('InteractorTranscript' in o) {\n const t = o.InteractorTranscript as { correlation_id: string; text: string };\n if (t?.text) this.emit('caption', { id: `v:${t.correlation_id}`, role: 'visitor', text: t.text });\n return;\n }\n if ('AgentReplyTranscript' in o) {\n const t = o.AgentReplyTranscript as { correlation_id: string; text: string };\n if (t?.text && !this.cancelled.has(t.correlation_id)) this.emit('caption', { id: `a:${t.correlation_id}`, role: 'agent', text: t.text });\n return;\n }\n if (o.type === 'turn_cancelled' && typeof o.correlationId === 'string') {\n const cid = o.correlationId;\n this.cancelled.add(cid);\n this.players.get(cid)?.stop();\n this.players.delete(cid);\n this.emit('line', { corr: cid, event: 'end' });\n if (this.speakingCorr === cid) {\n this.speakingCorr = null;\n this.set({ speaking: false });\n }\n this.emit('captionRemoved', `a:${cid}`);\n return;\n }\n if (o.kind === 'agent_status' && typeof o.state === 'string') {\n this.set({ agentState: o.state.toLowerCase() });\n }\n }\n\n /** Stop the agent mid-sentence (the visitor wants to speak). */\n interrupt(): void {\n const corr = this.speakingCorr;\n if (!corr) return;\n const p = this.players.get(corr);\n const heardMs = Math.round(p?.playedMs() ?? 0);\n p?.stop();\n this.players.delete(corr);\n this.cancelled.add(corr);\n this.speakingCorr = null;\n this.set({ speaking: false });\n this.emit('line', { corr, event: 'end' });\n this.sendJson({ type: 'playback_ended', correlationId: corr, timestampMs: Date.now(), reason: 'interrupted' });\n this.sendJson({ type: 'interrupt', correlationId: corr, heardMs, timestampMs: Date.now() });\n }\n\n setMuted(muted: boolean): void {\n this.mic?.setMuted(muted);\n this.set({ muted });\n }\n\n /** Leave the line, or hang up. */\n async hangUp(): Promise<void> {\n const id = this.s.callId;\n const was = this.s.phase;\n this.finish(was === 'live' ? 'hangup' : 'left', null);\n if (!id) return;\n try {\n const token = await this.session.token();\n await send(this.apiUrl, `/sdk/v1/calls/${encodeURIComponent(id)}`, { method: 'DELETE', token });\n } catch {\n // The server notices a closed socket / abandoned line on its own.\n }\n }\n\n private finish(reason: CallEndReason, error: string | null) {\n if (this.s.phase === 'ended') return;\n this.eventsAbort?.abort();\n this.eventsAbort = null;\n if (this.heartbeat) clearInterval(this.heartbeat);\n this.heartbeat = null;\n for (const p of this.players.values()) p.stop();\n this.players.clear();\n this.speakingCorr = null;\n this.mic?.stop();\n this.mic = null;\n const ws = this.ws;\n this.ws = null;\n if (ws && ws.readyState <= WebSocket.OPEN) ws.close(1000);\n this.ticket = null;\n this.set({ phase: 'ended', endReason: reason, speaking: false, holdSeconds: null, error });\n }\n}\n","import { Emitter } from './emitter.js';\nimport { CxError } from './errors.js';\nimport { readEvents, request, send } from './http.js';\nimport type { SessionManager } from './session.js';\nimport type { ChatMessage } from './types.js';\n\nexport interface ChatEvents extends Record<string, unknown> {\n /** The whole list, after any change. */\n messages: ChatMessage[];\n /** True from send until the reply is complete. */\n busy: boolean;\n error: CxError;\n}\n\nlet localSeq = 0;\nconst localId = (p: string) => `${p}_${Date.now().toString(36)}_${(localSeq++).toString(36)}`;\n\n/**\n * Text chat with the agent. History lives on the server, so it follows the\n * visitor across page loads (and, for an identified visitor, devices).\n */\nexport class Chat extends Emitter<ChatEvents> {\n private list: ChatMessage[] = [];\n private loaded = false;\n private busy = false;\n private abort: AbortController | null = null;\n\n constructor(\n private readonly apiUrl: string,\n private readonly session: SessionManager,\n ) {\n super();\n }\n\n get messages(): readonly ChatMessage[] {\n return this.list;\n }\n\n get isBusy(): boolean {\n return this.busy;\n }\n\n private publish() {\n this.list = [...this.list];\n this.emit('messages', this.list);\n }\n\n /** Load earlier messages (once; later calls return what is held). */\n async load(): Promise<readonly ChatMessage[]> {\n if (this.loaded) return this.list;\n const token = await this.session.token();\n const res = await request<{ messages: ChatMessage[] }>(this.apiUrl, '/sdk/v1/chat/messages?limit=50', { token });\n // Anything sent while the history was loading stays after it.\n const pending = this.list;\n this.list = [...(res?.messages ?? []), ...pending];\n this.loaded = true;\n this.publish();\n return this.list;\n }\n\n /**\n * Send a message; the reply streams into `messages` as it is written.\n * Resolves with the finished reply.\n */\n async send(text: string): Promise<ChatMessage> {\n const t = text.trim();\n if (!t) throw new CxError('invalid', 'Say something first.');\n if (this.busy) throw new CxError('rate_limited', 'Wait for the reply first.');\n this.setBusy(true);\n const mine: ChatMessage = { id: localId('local'), role: 'visitor', text: t, createdAt: new Date().toISOString() };\n const reply: ChatMessage = { id: localId('reply'), role: 'agent', text: '', createdAt: new Date().toISOString(), streaming: true };\n this.list.push(mine, reply);\n this.publish();\n\n this.abort = new AbortController();\n try {\n const token = await this.session.token();\n const res = await send(this.apiUrl, '/sdk/v1/chat/messages', { method: 'POST', body: { text: t }, token, signal: this.abort.signal });\n let finished: ChatMessage | null = null;\n let failure: string | null = null;\n await readEvents(\n res,\n ({ event, data }) => {\n const d = data as Record<string, unknown>;\n if (event === 'delta' && typeof d?.text === 'string') {\n reply.text += d.text;\n this.publish();\n } else if (event === 'done') {\n const next = Array.isArray(d.suggestions) ? d.suggestions.filter((q): q is string => typeof q === 'string' && q.trim() !== '') : [];\n finished = {\n id: String(d.id),\n role: 'agent',\n text: String(d.text ?? reply.text),\n createdAt: String(d.createdAt ?? reply.createdAt),\n ...(next.length ? { suggestions: next } : {}),\n };\n } else if (event === 'error') {\n failure = typeof d?.message === 'string' ? d.message : 'Something went wrong.';\n }\n },\n this.abort.signal,\n );\n if (failure || !finished) throw new CxError('unknown', failure ?? 'The reply was cut off. Try again.');\n const done: ChatMessage = finished;\n this.replace(reply.id, done);\n return done;\n } catch (e) {\n const err = e instanceof CxError ? e : new CxError('network', 'The reply was cut off. Try again.');\n this.list = this.list.filter((m) => m.id !== reply.id);\n const idx = this.list.findIndex((m) => m.id === mine.id);\n // A refusal the server explained (a daily limit, a slow-down) is shown as\n // it was said; anything else is the generic \"not sent\".\n if (idx !== -1) this.list[idx] = { ...mine, failed: true, ...(err.status === 429 ? { error: err.message } : {}) };\n this.publish();\n if ((e as Error)?.name !== 'AbortError') this.emit('error', err);\n throw err;\n } finally {\n this.abort = null;\n this.setBusy(false);\n }\n }\n\n /** Send a failed message again. */\n retry(id: string): Promise<ChatMessage> {\n const m = this.list.find((x) => x.id === id && x.failed);\n if (!m) throw new CxError('not_found', 'Nothing to retry.');\n this.list = this.list.filter((x) => x.id !== id);\n this.publish();\n return this.send(m.text);\n }\n\n /** Stop listening to a reply in progress (the server still finishes it). */\n stop(): void {\n this.abort?.abort();\n }\n\n private replace(id: string, next: ChatMessage) {\n const i = this.list.findIndex((m) => m.id === id);\n if (i !== -1) this.list[i] = next;\n this.publish();\n }\n\n private setBusy(b: boolean) {\n this.busy = b;\n this.emit('busy', b);\n }\n}\n","import { CxError } from './errors.js';\nimport { request } from './http.js';\nimport type { SessionInfo } from './types.js';\n\n/** Where the SDK may remember this browser's anonymous visitor id. */\nexport interface VisitorStore {\n get(key: string): string | null;\n set(key: string, value: string): void;\n}\n\nexport const memoryStore = (): VisitorStore => {\n const m = new Map<string, string>();\n return { get: (k) => m.get(k) ?? null, set: (k, v) => void m.set(k, v) };\n};\n\nexport const localStore = (): VisitorStore => ({\n get(k) {\n try {\n return globalThis.localStorage?.getItem(k) ?? null;\n } catch {\n return null;\n }\n },\n set(k, v) {\n try {\n globalThis.localStorage?.setItem(k, v);\n } catch {\n // private mode / blocked storage: the visitor is simply new each time\n }\n },\n});\n\nexport interface SessionSource {\n apiUrl: string;\n agentId?: string;\n /** Browser path: a publishable key, exchanged from this page's origin. */\n publishableKey?: string;\n /**\n * Server path: your backend mints the session with a secret key (an\n * identified visitor) and hands the token to the page. Called again when\n * the session is about to run out.\n */\n getSessionToken?: () => Promise<string | SessionInfo>;\n store: VisitorStore;\n}\n\n/** Renew this long before expiry. */\nconst RENEW_EARLY_S = 60;\n\n/**\n * Holds the current session, renews it before it runs out, and never runs\n * two renewals at once.\n */\nexport class SessionManager {\n private current: SessionInfo | null = null;\n private inflight: Promise<SessionInfo> | null = null;\n\n constructor(private readonly src: SessionSource) {\n if (!src.publishableKey && !src.getSessionToken) {\n throw new CxError('invalid', 'Pass a publishableKey, or getSessionToken for sessions your server mints.');\n }\n }\n\n private visitorKey(): string {\n // Per key, so two brands on one domain never share a visitor.\n const k = this.src.publishableKey ?? 'server';\n return `cxyz:visitor:${k.slice(-12)}`;\n }\n\n get info(): SessionInfo | null {\n return this.current;\n }\n\n /** A token valid for at least the next minute. */\n async token(): Promise<string> {\n const now = Date.now() / 1000;\n if (this.current && this.current.expiresAt - RENEW_EARLY_S > now) return this.current.token;\n return (await this.refresh()).token;\n }\n\n refresh(): Promise<SessionInfo> {\n this.inflight ??= this.mint().finally(() => {\n this.inflight = null;\n });\n return this.inflight;\n }\n\n private async mint(): Promise<SessionInfo> {\n let info: SessionInfo;\n if (this.src.getSessionToken) {\n const got = await this.src.getSessionToken();\n if (typeof got === 'string') {\n // A bare token: ask the server what it unlocks.\n info = await this.describe(got);\n } else {\n info = got;\n }\n } else {\n const visitorId = this.src.store.get(this.visitorKey()) ?? undefined;\n info = await request<SessionInfo>(this.src.apiUrl, '/sdk/v1/sessions', {\n method: 'POST',\n body: { publishableKey: this.src.publishableKey, agentId: this.src.agentId, visitorId },\n });\n this.src.store.set(this.visitorKey(), info.visitorId);\n }\n this.current = info;\n return info;\n }\n\n /** The session behind a token minted elsewhere (`getSessionToken` returned a string). */\n private async describe(token: string): Promise<SessionInfo> {\n const info = await request<SessionInfo>(this.src.apiUrl, '/sdk/v1/session', { token });\n return { ...info, token };\n }\n}\n","import { Call, type CallOptions } from './call.js';\nimport { Chat } from './chat.js';\nimport { Emitter } from './emitter.js';\nimport { CxError } from './errors.js';\nimport { request } from './http.js';\nimport { localStore, memoryStore, SessionManager, type VisitorStore } from './session.js';\nimport type { AgentCard, Features, Opening, SessionInfo } from './types.js';\n\nexport const DEFAULT_API_URL = 'https://api.character.xyz';\n\nexport interface InitOptions {\n /** `cxyz_pk_live_…` — safe in the page; works only from the key's allowed sites. */\n publishableKey?: string;\n /**\n * For signed-in visitors: return a session your server minted with its\n * secret key (see `@characterxyz/server`). Called again before expiry.\n */\n getSessionToken?: () => Promise<string | SessionInfo>;\n /** Which of the key's agents to talk to. Defaults to the key's first. */\n agentId?: string;\n /** Override the API (staging, local development). */\n apiUrl?: string;\n /** Remember the anonymous visitor across visits (default) or not at all. */\n storage?: 'local' | 'memory' | VisitorStore;\n}\n\nexport interface ClientEvents extends Record<string, unknown> {\n /** A call started or ended; the widget swaps its view on this. */\n call: Call | null;\n error: CxError;\n}\n\n/**\n * The headless SDK. `await CharacterXYZ.init({ publishableKey })`, then use\n * `chat` and `startCall()`. Everything the widget does goes through here, so\n * a brand can build its own UI on the same calls.\n */\nexport class CharacterXYZ extends Emitter<ClientEvents> {\n readonly chat: Chat;\n private currentCall: Call | null = null;\n private destroyed = false;\n\n private constructor(\n readonly apiUrl: string,\n private readonly session: SessionManager,\n private info: SessionInfo,\n ) {\n super();\n this.chat = new Chat(apiUrl, session);\n }\n\n static async init(opts: InitOptions): Promise<CharacterXYZ> {\n const apiUrl = (opts.apiUrl ?? DEFAULT_API_URL).replace(/\\/+$/, '');\n if (opts.publishableKey && /^cxyz_sk_/.test(opts.publishableKey)) {\n // A secret key in a page is a leak. Refuse loudly, before it is sent anywhere.\n throw new CxError('invalid', 'That is a SECRET key. Never put it in a web page: use a publishable key (cxyz_pk_…). Revoke the secret key now.');\n }\n const store = opts.storage === 'memory' ? memoryStore() : opts.storage && typeof opts.storage === 'object' ? opts.storage : localStore();\n const session = new SessionManager({ apiUrl, agentId: opts.agentId, publishableKey: opts.publishableKey, getSessionToken: opts.getSessionToken, store });\n const info = await session.refresh();\n return new CharacterXYZ(apiUrl, session, info);\n }\n\n get agent(): AgentCard {\n return (this.session.info ?? this.info).agent;\n }\n\n get features(): Features {\n return (this.session.info ?? this.info).features;\n }\n\n get appearance(): Record<string, unknown> {\n return (this.session.info ?? this.info).appearance ?? {};\n }\n\n get visitorId(): string {\n return (this.session.info ?? this.info).visitorId;\n }\n\n get mode(): 'live' | 'test' {\n return (this.session.info ?? this.info).mode;\n }\n\n /** The call in progress (queued, ready or live), if any. */\n get call(): Call | null {\n return this.currentCall && this.currentCall.state.phase !== 'ended' ? this.currentCall : null;\n }\n\n /**\n * The worn video character's full render data (the public projection the\n * app's Stage reads), for a UI that draws the face — the widget hands it to\n * the app's renderer. Null when the agent wears none.\n */\n async videoAvatar(): Promise<Record<string, unknown> | null> {\n const token = await this.session.token();\n return request<Record<string, unknown> | null>(this.apiUrl, '/sdk/v1/agent/video-avatar', { token });\n }\n\n private openingP: Promise<Opening | null> | null = null;\n\n /**\n * How the agent opens the conversation here — her greeting, a welcome-back\n * line, a teaser and likely first questions — written by her and cached by\n * the server. Fetched once per page; null if it could not be had.\n */\n opening(): Promise<Opening | null> {\n this.openingP ??= this.session\n .token()\n .then((token) => request<Opening>(this.apiUrl, '/sdk/v1/agent/opening', { token }))\n .catch(() => null);\n return this.openingP;\n }\n\n /** Start a voice call. Call from a click: it needs the microphone and audio unlocked. */\n async startCall(opts: CallOptions = {}): Promise<Call> {\n if (this.destroyed) throw new CxError('invalid', 'This client was destroyed.');\n if (!this.features.call) throw new CxError('forbidden', 'Calls are not available on this site.');\n if (this.call) return this.call;\n const call = new Call(this.apiUrl, this.session, this.agent.id, opts);\n this.currentCall = call;\n call.on('state', (s) => {\n if (s.phase === 'ended' && this.currentCall === call) this.emit('call', null);\n });\n call.on('error', (e) => this.emit('error', e));\n this.emit('call', call);\n await call.start();\n return call;\n }\n\n destroy(): void {\n this.destroyed = true;\n void this.currentCall?.hangUp();\n this.chat.stop();\n this.chat.clear();\n this.clear();\n }\n}\n","/**\n * `@characterxyz/web` — Character XYZ on any web page, headless.\n *\n * ```ts\n * import { CharacterXYZ } from '@characterxyz/web';\n *\n * const cx = await CharacterXYZ.init({ publishableKey: 'cxyz_pk_live_…' });\n * cx.chat.on('messages', render);\n * await cx.chat.send('Hi!');\n *\n * button.onclick = async () => {\n * const call = await cx.startCall();\n * call.on('state', (s) => show(s.phase, s.position));\n * };\n * ```\n *\n * The ready-made widget is `@characterxyz/widget`; this package is what it\n * is built on, for brands who want their own UI.\n */\nexport { CharacterXYZ, DEFAULT_API_URL, type InitOptions, type ClientEvents } from './client.js';\nexport { Chat, type ChatEvents } from './chat.js';\nexport { Call, type CallEvents, type CallOptions } from './call.js';\nexport { CxError, type CxErrorCode } from './errors.js';\nexport { Emitter } from './emitter.js';\nexport type { VisitorStore } from './session.js';\nexport type {\n AgentCard,\n CallEndReason,\n CallPhase,\n CallState,\n Caption,\n ChatMessage,\n Features,\n Opening,\n SessionInfo,\n VideoCharacter,\n VideoClip,\n} from './types.js';\nexport const VERSION = '0.2.0';\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/audio/player.ts","../src/audio/mic.ts","../src/emitter.ts","../src/errors.ts","../src/http.ts","../src/protocol.ts","../src/call.ts","../src/chat.ts","../src/session.ts","../src/client.ts","../src/index.ts"],"names":["shared","audioContext","PcmPlayer","opts","__publicField","bytes","count","view","buf","ch","i","src","now","delayMs","s","sum","v","WORKLET","levelOf","pcm","openMic","stream","ctx","source","muted","deliver","node","teardown","url","w","e","sp","ratio","pos","out","n","sink","m","t","Emitter","event","fn","_a","payload","CxError","code","message","status","fields","codeForStatus","errorFrom","res","j","send","apiUrl","path","headers","request","readEvents","onEvent","signal","body","reader","decoder","onAbort","value","done","drain","rest","idx","block","data","line","colon","field","raw","parsed","parsePacket","kind","final","o","corrLen","corr","len","BARGE_IN_LEVEL","BARGE_IN_MS","HEARTBEAT_MS","initial","Call","session","agentId","p","patch","level","token","r","err","reason","failures","d","hold","ws","face","emotion","player","old","cid","heardMs","id","was","error","localSeq","localId","Chat","pending","text","mine","reply","finished","failure","next","q","x","b","memoryStore","k","localStore","RENEW_EARLY_S","SessionManager","info","got","visitorId","DEFAULT_API_URL","CharacterXYZ","_CharacterXYZ","store","refresh","details","page","call","VERSION"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Plays the agent's streamed voice (PCM16 chunks) gaplessly, and reports how\n * loud it is right now so a UI can draw a ring that follows the voice.\n *\n * Each chunk becomes an AudioBuffer scheduled right after the last one; the\n * first waits a short pre-roll so a slow second chunk does not open a gap.\n */\n\nexport interface PlayerOptions {\n sampleRate?: number;\n onStart?: () => void;\n onEnd?: () => void;\n volume?: number;\n}\n\nconst PREROLL_S = 0.12;\n\nlet shared: AudioContext | null = null;\n\n/** One output context for the page, created on first use (after a gesture). */\nexport function audioContext(): AudioContext {\n if (!shared || shared.state === 'closed') shared = new AudioContext({ latencyHint: 'interactive' });\n if (shared.state === 'suspended') void shared.resume().catch(() => {});\n return shared;\n}\n\nexport class PcmPlayer {\n private readonly ctx: AudioContext;\n private readonly gain: GainNode;\n private readonly analyser: AnalyserNode;\n private readonly data: Uint8Array<ArrayBuffer>;\n private nextAt = 0;\n private started = false;\n private ended = false;\n private finishing = false;\n private sources = new Set<AudioBufferSourceNode>();\n private startedAt = 0;\n readonly sampleRate: number;\n\n constructor(private readonly opts: PlayerOptions = {}) {\n this.ctx = audioContext();\n this.sampleRate = opts.sampleRate ?? 16_000;\n this.gain = this.ctx.createGain();\n this.gain.gain.value = opts.volume ?? 1;\n this.analyser = this.ctx.createAnalyser();\n this.analyser.fftSize = 512;\n this.data = new Uint8Array(new ArrayBuffer(this.analyser.fftSize));\n this.gain.connect(this.analyser).connect(this.ctx.destination);\n }\n\n /** Queue PCM16 little-endian mono bytes. */\n enqueue(bytes: Uint8Array): void {\n if (this.ended || bytes.byteLength < 2) return;\n const count = Math.floor(bytes.byteLength / 2);\n const view = new DataView(bytes.buffer, bytes.byteOffset, count * 2);\n const buf = this.ctx.createBuffer(1, count, this.sampleRate);\n const ch = buf.getChannelData(0);\n for (let i = 0; i < count; i++) ch[i] = view.getInt16(i * 2, true) / 32768;\n const src = this.ctx.createBufferSource();\n src.buffer = buf;\n src.connect(this.gain);\n const now = this.ctx.currentTime;\n if (this.nextAt < now) this.nextAt = now + (this.started ? 0.02 : PREROLL_S);\n src.start(this.nextAt);\n if (!this.started) {\n this.started = true;\n const delayMs = Math.max(0, (this.nextAt - now) * 1000);\n this.startedAt = performance.now() + delayMs;\n setTimeout(() => this.opts.onStart?.(), delayMs);\n }\n this.nextAt += buf.duration;\n this.sources.add(src);\n src.onended = () => {\n this.sources.delete(src);\n if (this.finishing && this.sources.size === 0) this.finish();\n };\n }\n\n /** No more chunks: report the end once the queue has played out. */\n end(): void {\n this.finishing = true;\n if (this.sources.size === 0) this.finish();\n }\n\n /** Silence now (an interruption). Does not call `onEnd`. */\n stop(): void {\n this.ended = true;\n for (const s of this.sources) {\n try {\n s.stop();\n } catch {\n /* not started */\n }\n }\n this.sources.clear();\n this.gain.disconnect();\n }\n\n /** Milliseconds of audio actually heard so far. */\n playedMs(): number {\n return this.started ? Math.max(0, performance.now() - this.startedAt) : 0;\n }\n\n /** Loudness now, 0..1. */\n level(): number {\n this.analyser.getByteTimeDomainData(this.data);\n let sum = 0;\n for (let i = 0; i < this.data.length; i++) {\n const v = (this.data[i]! - 128) / 128;\n sum += v * v;\n }\n return Math.min(1, Math.sqrt(sum / this.data.length) * 3);\n }\n\n private finish() {\n if (this.ended) return;\n this.ended = true;\n this.gain.disconnect();\n this.opts.onEnd?.();\n }\n}\n","/**\n * The microphone as the agent socket wants it: 16 kHz mono PCM16, 30 ms\n * (480-sample) frames, sent continuously.\n *\n * Resampled in an AudioWorklet from whatever rate the device runs at. A\n * context forced to 16 kHz would be simpler and is refused by Firefox for a\n * MediaStream source at another rate, so the worklet does it.\n */\n\nexport const TARGET_RATE = 16_000;\nexport const FRAME_SAMPLES = 480;\n\nconst WORKLET = `\nclass CxyzMic extends AudioWorkletProcessor {\n constructor(o) {\n super();\n this.ratio = sampleRate / ${TARGET_RATE};\n this.pos = 0;\n this.lp = 0;\n this.alpha = Math.min(1, 2 * Math.PI * 7000 / sampleRate / (1 + 2 * Math.PI * 7000 / sampleRate));\n this.out = new Int16Array(${FRAME_SAMPLES});\n this.n = 0;\n }\n process(inputs) {\n const ch = inputs[0] && inputs[0][0];\n if (!ch) return true;\n for (let i = 0; i < ch.length; i++) {\n this.lp += this.alpha * (ch[i] - this.lp);\n this.pos += 1;\n if (this.pos >= this.ratio) {\n this.pos -= this.ratio;\n const s = Math.max(-1, Math.min(1, this.lp));\n this.out[this.n++] = s < 0 ? s * 0x8000 : s * 0x7fff;\n if (this.n === ${FRAME_SAMPLES}) {\n this.port.postMessage(this.out.buffer, [this.out.buffer]);\n this.out = new Int16Array(${FRAME_SAMPLES});\n this.n = 0;\n }\n }\n }\n return true;\n }\n}\nregisterProcessor('cxyz-mic', CxyzMic);\n`;\n\nexport interface MicOptions {\n onFrame: (pcm: ArrayBuffer, level: number) => void;\n deviceId?: string;\n}\n\nexport interface Mic {\n stop(): void;\n setMuted(m: boolean): void;\n readonly muted: boolean;\n}\n\n/** RMS of a PCM16 frame, 0..1. */\nexport function levelOf(pcm: ArrayBuffer): number {\n const s = new Int16Array(pcm);\n if (!s.length) return 0;\n let sum = 0;\n for (let i = 0; i < s.length; i++) {\n const v = s[i]! / 32768;\n sum += v * v;\n }\n return Math.sqrt(sum / s.length);\n}\n\nexport async function openMic(opts: MicOptions): Promise<Mic> {\n if (!navigator.mediaDevices?.getUserMedia) throw new Error('This browser cannot use a microphone here.');\n const stream = await navigator.mediaDevices.getUserMedia({\n audio: {\n deviceId: opts.deviceId ? { exact: opts.deviceId } : undefined,\n channelCount: 1,\n // The agent's voice comes out of the speakers; without cancellation it\n // would hear itself and answer.\n echoCancellation: true,\n noiseSuppression: true,\n autoGainControl: true,\n },\n });\n const ctx = new AudioContext({ latencyHint: 'interactive' });\n const source = ctx.createMediaStreamSource(stream);\n let muted = false;\n const deliver = (buf: ArrayBuffer) => {\n if (muted) {\n // Silence, not nothing: the server keeps a pre-roll of the last frames\n // and splices it onto the next utterance.\n opts.onFrame(new ArrayBuffer(buf.byteLength), 0);\n return;\n }\n opts.onFrame(buf, levelOf(buf));\n };\n\n let node: AudioNode;\n let teardown: () => void;\n try {\n const url = URL.createObjectURL(new Blob([WORKLET], { type: 'application/javascript' }));\n try {\n await ctx.audioWorklet.addModule(url);\n } finally {\n URL.revokeObjectURL(url);\n }\n const w = new AudioWorkletNode(ctx, 'cxyz-mic');\n w.port.onmessage = (e) => deliver(e.data as ArrayBuffer);\n node = w;\n teardown = () => {\n w.port.onmessage = null;\n };\n } catch {\n // A strict Content-Security-Policy can refuse a blob: worklet. The old\n // ScriptProcessor path is deprecated but universal.\n const sp = ctx.createScriptProcessor(4096, 1, 1);\n const ratio = ctx.sampleRate / TARGET_RATE;\n let pos = 0;\n let out = new Int16Array(FRAME_SAMPLES);\n let n = 0;\n sp.onaudioprocess = (e) => {\n const ch = e.inputBuffer.getChannelData(0);\n for (let i = 0; i < ch.length; i++) {\n pos += 1;\n if (pos >= ratio) {\n pos -= ratio;\n const s = Math.max(-1, Math.min(1, ch[i]!));\n out[n++] = s < 0 ? s * 0x8000 : s * 0x7fff;\n if (n === FRAME_SAMPLES) {\n deliver(out.buffer);\n out = new Int16Array(FRAME_SAMPLES);\n n = 0;\n }\n }\n }\n };\n node = sp;\n teardown = () => {\n sp.onaudioprocess = null;\n };\n }\n source.connect(node);\n // A worklet/processor only runs while connected to the destination; a gain\n // of zero keeps the room from hearing itself.\n const sink = ctx.createGain();\n sink.gain.value = 0;\n node.connect(sink).connect(ctx.destination);\n if (ctx.state === 'suspended') await ctx.resume().catch(() => {});\n\n return {\n get muted() {\n return muted;\n },\n setMuted(m: boolean) {\n muted = m;\n for (const t of stream.getAudioTracks()) t.enabled = !m;\n },\n stop() {\n teardown();\n try {\n source.disconnect();\n node.disconnect();\n } catch {\n /* already disconnected */\n }\n for (const t of stream.getTracks()) t.stop();\n void ctx.close().catch(() => {});\n },\n };\n}\n","/** A tiny typed event emitter. `on` returns the unsubscribe. */\nexport class Emitter<Events extends Record<string, unknown>> {\n private handlers: { [K in keyof Events]?: Set<(payload: Events[K]) => void> } = {};\n\n on<K extends keyof Events>(event: K, fn: (payload: Events[K]) => void): () => void {\n (this.handlers[event] ??= new Set()).add(fn);\n return () => this.handlers[event]?.delete(fn);\n }\n\n emit<K extends keyof Events>(event: K, payload: Events[K]): void {\n for (const fn of this.handlers[event] ?? []) {\n try {\n fn(payload);\n } catch (e) {\n // A listener's bug must never break the SDK's own state machine.\n console.error('[characterxyz] listener threw', e);\n }\n }\n }\n\n clear(): void {\n this.handlers = {};\n }\n}\n","export type CxErrorCode =\n | 'unauthorized'\n | 'forbidden'\n | 'not_found'\n | 'invalid'\n | 'rate_limited'\n | 'payment_required'\n | 'unavailable'\n | 'network'\n | 'unknown';\n\n/** Every failure the SDK reports, with a message fit to show a visitor. */\nexport class CxError extends Error {\n readonly code: CxErrorCode;\n readonly status: number;\n /** On `invalid`: what is wrong with each field, by its name (`email`, `name`…). */\n readonly fields: Record<string, string>;\n\n constructor(code: CxErrorCode, message: string, status = 0, fields: Record<string, string> = {}) {\n super(message);\n this.name = 'CxError';\n this.code = code;\n this.status = status;\n this.fields = fields;\n }\n}\n\nexport function codeForStatus(status: number): CxErrorCode {\n switch (status) {\n case 401:\n return 'unauthorized';\n case 403:\n return 'forbidden';\n case 404:\n return 'not_found';\n case 402:\n return 'payment_required';\n case 422:\n return 'invalid';\n case 429:\n return 'rate_limited';\n case 503:\n return 'unavailable';\n default:\n return 'unknown';\n }\n}\n","import { CxError, codeForStatus } from './errors.js';\n\nexport interface RequestOptions {\n method?: string;\n body?: unknown;\n token?: string;\n signal?: AbortSignal;\n}\n\nasync function errorFrom(res: Response): Promise<CxError> {\n let message = '';\n const fields: Record<string, string> = {};\n try {\n const j = (await res.json()) as { message?: unknown; errors?: { path?: unknown; message?: unknown }[] };\n if (typeof j?.message === 'string') message = j.message;\n for (const e of Array.isArray(j?.errors) ? j.errors : []) {\n if (typeof e?.path === 'string' && typeof e?.message === 'string') fields[e.path] = e.message;\n }\n } catch {\n // not JSON: the status says enough\n }\n return new CxError(codeForStatus(res.status), message || `Request failed (${res.status})`, res.status, fields);\n}\n\nexport async function send(apiUrl: string, path: string, opts: RequestOptions = {}): Promise<Response> {\n const headers: Record<string, string> = {};\n if (opts.body !== undefined) headers['Content-Type'] = 'application/json';\n if (opts.token) headers.Authorization = `Bearer ${opts.token}`;\n let res: Response;\n try {\n res = await fetch(apiUrl + path, {\n method: opts.method ?? (opts.body === undefined ? 'GET' : 'POST'),\n headers,\n body: opts.body === undefined ? undefined : JSON.stringify(opts.body),\n signal: opts.signal,\n // No cookies, ever: the SDK authenticates with its own bearer token, and\n // a credentialed request would carry the brand page's cookies to us.\n credentials: 'omit',\n cache: 'no-store',\n });\n } catch (e) {\n if ((e as Error)?.name === 'AbortError') throw e;\n throw new CxError('network', 'Could not reach Character XYZ. Check your connection.');\n }\n if (!res.ok) throw await errorFrom(res);\n return res;\n}\n\n/** JSON request; unwraps the API's `{message, data}` envelope. */\nexport async function request<T>(apiUrl: string, path: string, opts: RequestOptions = {}): Promise<T> {\n const res = await send(apiUrl, path, opts);\n const j = (await res.json()) as { data?: T };\n return j.data as T;\n}\n\nexport interface ServerEvent {\n event: string;\n data: unknown;\n}\n\n/**\n * Read a `text/event-stream` body, calling `onEvent` per event, until the\n * stream ends or `signal` aborts. Fetch-based on purpose: `EventSource` cannot\n * send an Authorization header, so it would need the token in the URL.\n */\nexport async function readEvents(res: Response, onEvent: (e: ServerEvent) => void, signal?: AbortSignal): Promise<void> {\n const body = res.body;\n if (!body) return;\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buf = '';\n const onAbort = () => void reader.cancel().catch(() => {});\n signal?.addEventListener('abort', onAbort);\n try {\n for (;;) {\n const { value, done } = await reader.read();\n if (done) break;\n buf += decoder.decode(value, { stream: true });\n buf = drain(buf, onEvent);\n }\n buf += decoder.decode();\n drain(buf + '\\n\\n', onEvent);\n } finally {\n signal?.removeEventListener('abort', onAbort);\n }\n}\n\n/** Dispatch every complete event in `buf`; return what is left over. */\nexport function drain(buf: string, onEvent: (e: ServerEvent) => void): string {\n const normalised = buf.replace(/\\r\\n/g, '\\n');\n let rest = normalised;\n let idx: number;\n while ((idx = rest.indexOf('\\n\\n')) !== -1) {\n const block = rest.slice(0, idx);\n rest = rest.slice(idx + 2);\n let event = 'message';\n const data: string[] = [];\n for (const line of block.split('\\n')) {\n if (!line || line.startsWith(':')) continue;\n const colon = line.indexOf(':');\n const field = colon === -1 ? line : line.slice(0, colon);\n const value = colon === -1 ? '' : line.slice(colon + 1).replace(/^ /, '');\n if (field === 'event') event = value;\n else if (field === 'data') data.push(value);\n }\n if (!data.length) continue;\n const raw = data.join('\\n');\n let parsed: unknown = raw;\n try {\n parsed = JSON.parse(raw);\n } catch {\n // plain text data\n }\n onEvent({ event, data: parsed });\n }\n return rest;\n}\n","/**\n * The agent socket's binary packet (the same one the Stage reads):\n *\n * \"CXYZ\" | version u8 (1) | kind u8 | flags u8 (bit 0 = final)\n * | corrLen u16 | corr utf8 | seq u32 | timestamp u64 | duration u32\n * | payloadLen u32 | payload\n *\n * All little-endian. Kind 1 is voice (PCM16), kind 2/3 are face data, which\n * this SDK does not draw yet.\n */\nexport interface Packet {\n kind: number;\n final: boolean;\n corr: string;\n payload: Uint8Array;\n}\n\nexport function parsePacket(buf: ArrayBuffer): Packet | null {\n if (buf.byteLength < 25) return null;\n const v = new DataView(buf);\n if (v.getUint8(0) !== 0x43 || v.getUint8(1) !== 0x58 || v.getUint8(2) !== 0x59 || v.getUint8(3) !== 0x5a) return null;\n if (v.getUint8(4) !== 1) return null;\n const kind = v.getUint8(5);\n const final = (v.getUint8(6) & 1) !== 0;\n let o = 7;\n const corrLen = v.getUint16(o, true);\n o += 2;\n if (o + corrLen + 20 > buf.byteLength) return null;\n const corr = new TextDecoder().decode(new Uint8Array(buf, o, corrLen));\n o += corrLen + 4 + 8 + 4;\n const len = v.getUint32(o, true);\n o += 4;\n if (o + len > buf.byteLength) return null;\n return { kind, final, corr, payload: new Uint8Array(buf, o, len) };\n}\n\n/** Build one (for tests and tools). */\nexport function buildPacket(p: { kind: number; final: boolean; corr: string; payload: Uint8Array }): ArrayBuffer {\n const corr = new TextEncoder().encode(p.corr);\n const head = 7 + 2 + corr.length + 4 + 8 + 4 + 4;\n const buf = new ArrayBuffer(head + p.payload.byteLength);\n const v = new DataView(buf);\n const bytes = new Uint8Array(buf);\n bytes.set([0x43, 0x58, 0x59, 0x5a], 0);\n v.setUint8(4, 1);\n v.setUint8(5, p.kind);\n v.setUint8(6, p.final ? 1 : 0);\n let o = 7;\n v.setUint16(o, corr.length, true);\n o += 2;\n bytes.set(corr, o);\n o += corr.length + 4 + 8 + 4;\n v.setUint32(o, p.payload.byteLength, true);\n o += 4;\n bytes.set(p.payload, o);\n return buf;\n}\n","import { audioContext, PcmPlayer } from './audio/player.js';\nimport { openMic, type Mic } from './audio/mic.js';\nimport { Emitter } from './emitter.js';\nimport { CxError } from './errors.js';\nimport { readEvents, request, send } from './http.js';\nimport { parsePacket } from './protocol.js';\nimport type { SessionManager } from './session.js';\nimport type { CallEndReason, CallState, Caption } from './types.js';\n\nexport interface CallEvents extends Record<string, unknown> {\n state: CallState;\n /** The visitor's words and the agent's reply, as they are recognised. */\n caption: Caption;\n /** A caption the server withdrew (the visitor was not finished). */\n captionRemoved: string;\n /** The turn is ready: accept() within `holdSeconds`. */\n ready: { holdSeconds: number };\n /** One streamed face batch (kind-3 msgpack payload) for line `corr` — only with `face`. */\n face: { corr: string; payload: Uint8Array };\n /** A line of the agent's voice became audible, or ended (naturally or interrupted). */\n line: { corr: string; event: 'audible' | 'end' };\n error: CxError;\n}\n\nexport interface CallOptions {\n /** Join the moment it is this visitor's turn (default true). */\n autoAccept?: boolean;\n deviceId?: string;\n /**\n * Ask for the agent's face streamed with the voice (Neural Lip Sync), for a\n * UI that draws it. `emotion()` is read when the call connects: the face's\n * mood as the face service takes it (`joy:0.3`), or null for neutral.\n */\n face?: { emotion?: () => string | null };\n}\n\n/** Talking over the agent this loud, this long, stops her. */\nconst BARGE_IN_LEVEL = 0.09;\nconst BARGE_IN_MS = 350;\nconst HEARTBEAT_MS = 25_000;\n\nconst initial = (): CallState => ({\n phase: 'idle',\n callId: null,\n position: null,\n etaSeconds: null,\n holdSeconds: null,\n maxSeconds: null,\n startedAt: null,\n endReason: null,\n muted: false,\n speaking: false,\n agentState: 'idle',\n error: null,\n});\n\n/**\n * One voice call: join the line, wait (chatting is fine meanwhile), accept,\n * talk, hang up. A call is single-use; start another for the next one.\n */\nexport class Call extends Emitter<CallEvents> {\n private s: CallState = initial();\n private ticket: string | null = null;\n private eventsAbort: AbortController | null = null;\n private ws: WebSocket | null = null;\n private mic: Mic | null = null;\n private players = new Map<string, PcmPlayer>();\n private sampleRates = new Map<string, number>();\n private cancelled = new Set<string>();\n private speakingCorr: string | null = null;\n private heartbeat: ReturnType<typeof setInterval> | null = null;\n private loudSince: number | null = null;\n\n constructor(\n private readonly apiUrl: string,\n private readonly session: SessionManager,\n private readonly agentId: string,\n private readonly opts: CallOptions = {},\n ) {\n super();\n }\n\n get state(): CallState {\n return this.s;\n }\n\n /** The line being voiced now, and how much of it has been heard (ms). */\n audible(): { corr: string; ms: number } | null {\n const corr = this.speakingCorr;\n const p = corr ? this.players.get(corr) : undefined;\n return corr && p ? { corr, ms: p.playedMs() } : null;\n }\n\n /** Loudness of the agent's voice right now, 0..1. */\n voiceLevel(): number {\n const p = this.speakingCorr ? this.players.get(this.speakingCorr) : undefined;\n return p ? p.level() : 0;\n }\n\n private set(patch: Partial<CallState>) {\n this.s = { ...this.s, ...patch };\n this.emit('state', this.s);\n }\n\n /**\n * Call from a click: it unlocks audio, asks for the microphone, then joins\n * the line (or goes straight through when a slot is free).\n */\n async start(): Promise<void> {\n if (this.s.phase !== 'idle') return;\n this.set({ phase: 'joining' });\n // Created inside the gesture, or the browser keeps it suspended.\n audioContext();\n try {\n this.mic = await openMic({ deviceId: this.opts.deviceId, onFrame: (pcm, level) => this.onMicFrame(pcm, level) });\n } catch {\n this.finish('mic-denied', 'Allow the microphone to talk, or chat instead.');\n return;\n }\n try {\n const token = await this.session.token();\n const r = await request<{ callId: string; state: string; position?: number; etaSeconds?: number }>(this.apiUrl, '/sdk/v1/calls', {\n method: 'POST',\n body: {},\n token,\n });\n this.set({ callId: r.callId, phase: r.state === 'ready' ? 'joining' : 'queued', position: r.position ?? null, etaSeconds: r.etaSeconds ?? null });\n void this.follow();\n } catch (e) {\n const err = e instanceof CxError ? e : new CxError('unknown', 'Could not start the call.');\n const reason: CallEndReason = err.code === 'rate_limited' ? 'busy' : 'unavailable';\n this.finish(reason, err.message);\n this.emit('error', err);\n }\n }\n\n /** Follow the call's server-side state, reconnecting the stream if it drops. */\n private async follow(): Promise<void> {\n let failures = 0;\n while (this.s.callId && this.s.phase !== 'ended' && this.s.phase !== 'idle') {\n this.eventsAbort = new AbortController();\n try {\n const token = await this.session.token();\n const res = await send(this.apiUrl, `/sdk/v1/calls/${encodeURIComponent(this.s.callId)}/events`, { token, signal: this.eventsAbort.signal });\n failures = 0;\n await readEvents(res, (e) => this.onServerEvent(e.event, e.data as Record<string, unknown>), this.eventsAbort.signal);\n } catch (e) {\n if ((e as Error)?.name === 'AbortError') return;\n if (e instanceof CxError && e.code === 'not_found') {\n this.finish('failed', 'The call ended.');\n return;\n }\n failures += 1;\n if (failures > 5) {\n this.finish('failed', 'Lost the connection to the call.');\n return;\n }\n }\n if (this.ended()) return;\n await new Promise((r) => setTimeout(r, Math.min(4000, 500 * 2 ** failures)));\n }\n }\n\n private onServerEvent(event: string, d: Record<string, unknown>) {\n switch (event) {\n case 'queued':\n if (this.s.phase === 'joining' || this.s.phase === 'queued') {\n this.set({ phase: 'queued', position: Number(d.position) || 1, etaSeconds: Number(d.etaSeconds) || null });\n }\n break;\n case 'ready': {\n if (typeof d.ticket === 'string' && d.ticket) this.ticket = d.ticket;\n const hold = Number(d.holdSeconds) || 0;\n if (this.s.phase !== 'ready' && this.s.phase !== 'connecting' && this.s.phase !== 'live') {\n this.set({ phase: 'ready', holdSeconds: hold, position: null, etaSeconds: null });\n this.emit('ready', { holdSeconds: hold });\n if (this.opts.autoAccept !== false) this.accept();\n } else if (this.s.phase === 'ready') {\n this.set({ holdSeconds: hold });\n }\n break;\n }\n case 'live':\n this.set({ phase: 'live', maxSeconds: Number(d.maxSeconds) || null, startedAt: this.s.startedAt ?? Date.now() - (Number(d.elapsedSeconds) || 0) * 1000 });\n break;\n case 'ended':\n this.finish((String(d.reason || 'hangup') as CallEndReason) || 'hangup', null);\n break;\n }\n }\n\n // A method, not an inline comparison: the phase changes across an await,\n // which TypeScript's narrowing cannot see.\n private ended(): boolean {\n return this.s.phase === 'ended';\n }\n\n /** Take the call now that it is this visitor's turn. */\n accept(): void {\n if (this.s.phase !== 'ready' || !this.ticket || this.ws) return;\n this.set({ phase: 'connecting' });\n const url = this.apiUrl.replace(/^http/, 'ws') + '/sdk/v1/calls/socket';\n const ws = new WebSocket(url, [`cxyz-ticket.${this.ticket}`]);\n this.ticket = null;\n ws.binaryType = 'arraybuffer';\n this.ws = ws;\n ws.onopen = () => {\n const face = this.opts.face;\n const emotion = face?.emotion?.() ?? null;\n ws.send(\n JSON.stringify({\n type: 'agent_identity',\n agent_id: this.agentId,\n skin_index: 0,\n blendshapes: !!face,\n ...(face ? { blendshape_stream: true } : {}),\n ...(face && emotion ? { face_emotion: emotion } : {}),\n }),\n );\n // This page does not gate the microphone: the server's own voice\n // detection judges every frame.\n ws.send(JSON.stringify({ type: 'mic_state', silero: 'off', denoise: false }));\n this.heartbeat = setInterval(() => this.sendJson({ type: 'heartbeat' }), HEARTBEAT_MS);\n this.set({ phase: 'live', startedAt: this.s.startedAt ?? Date.now() });\n };\n ws.onmessage = (e) => this.onSocket(e.data);\n ws.onclose = () => {\n this.ws = null;\n // The event stream says why; give it a moment before calling it ourselves.\n setTimeout(() => {\n if (this.s.phase === 'live' || this.s.phase === 'connecting') this.finish('hangup', null);\n }, 1500);\n };\n }\n\n private sendJson(o: unknown) {\n if (this.ws?.readyState === WebSocket.OPEN) this.ws.send(JSON.stringify(o));\n }\n\n private onMicFrame(pcm: ArrayBuffer, level: number) {\n const ws = this.ws;\n if (!ws || ws.readyState !== WebSocket.OPEN) return;\n if (this.speakingCorr) {\n // The agent must not hear itself: while she talks the frames go up as\n // silence, unless the visitor is clearly talking over her.\n const now = performance.now();\n if (level > BARGE_IN_LEVEL) {\n this.loudSince ??= now;\n if (now - this.loudSince >= BARGE_IN_MS) {\n this.loudSince = null;\n this.interrupt();\n ws.send(pcm);\n return;\n }\n } else {\n this.loudSince = null;\n }\n ws.send(new ArrayBuffer(pcm.byteLength));\n return;\n }\n ws.send(pcm);\n }\n\n private onSocket(data: unknown) {\n if (data instanceof ArrayBuffer) {\n const p = parsePacket(data);\n if (!p || this.cancelled.has(p.corr)) return;\n if (p.kind === 3) {\n // A copy, so the receiver may keep or transfer it.\n if (this.opts.face) this.emit('face', { corr: p.corr, payload: p.payload.slice() });\n return;\n }\n if (p.kind !== 1) return;\n let player = this.players.get(p.corr);\n if (!player) {\n // A new line: whatever was playing is over.\n for (const [c, old] of this.players) {\n old.stop();\n this.players.delete(c);\n }\n const corr = p.corr;\n player = new PcmPlayer({\n sampleRate: this.sampleRates.get(corr) ?? 16_000,\n onStart: () => {\n this.speakingCorr = corr;\n this.set({ speaking: true });\n this.emit('line', { corr, event: 'audible' });\n this.sendJson({ type: 'playback_started', correlationId: corr, timestampMs: Date.now() });\n },\n onEnd: () => {\n this.players.delete(corr);\n if (this.speakingCorr === corr) this.speakingCorr = null;\n this.set({ speaking: false });\n this.emit('line', { corr, event: 'end' });\n this.sendJson({ type: 'playback_ended', correlationId: corr, timestampMs: Date.now(), reason: 'natural' });\n this.sendJson({ type: 'speech_ended' });\n },\n });\n this.players.set(corr, player);\n }\n player.enqueue(p.payload);\n if (p.final) player.end();\n return;\n }\n if (typeof data !== 'string') return;\n let o: Record<string, unknown>;\n try {\n o = JSON.parse(data);\n } catch {\n return;\n }\n if ('AgentSpeechMeta' in o) {\n const m = o.AgentSpeechMeta as { correlation_id?: string; sample_rate?: number };\n if (m?.correlation_id && m.sample_rate) this.sampleRates.set(m.correlation_id, m.sample_rate);\n return;\n }\n if ('InteractorTranscript' in o) {\n const t = o.InteractorTranscript as { correlation_id: string; text: string };\n if (t?.text) this.emit('caption', { id: `v:${t.correlation_id}`, role: 'visitor', text: t.text });\n return;\n }\n if ('AgentReplyTranscript' in o) {\n const t = o.AgentReplyTranscript as { correlation_id: string; text: string };\n if (t?.text && !this.cancelled.has(t.correlation_id)) this.emit('caption', { id: `a:${t.correlation_id}`, role: 'agent', text: t.text });\n return;\n }\n if (o.type === 'turn_cancelled' && typeof o.correlationId === 'string') {\n const cid = o.correlationId;\n this.cancelled.add(cid);\n this.players.get(cid)?.stop();\n this.players.delete(cid);\n this.emit('line', { corr: cid, event: 'end' });\n if (this.speakingCorr === cid) {\n this.speakingCorr = null;\n this.set({ speaking: false });\n }\n this.emit('captionRemoved', `a:${cid}`);\n return;\n }\n if (o.kind === 'agent_status' && typeof o.state === 'string') {\n this.set({ agentState: o.state.toLowerCase() });\n }\n }\n\n /** Stop the agent mid-sentence (the visitor wants to speak). */\n interrupt(): void {\n const corr = this.speakingCorr;\n if (!corr) return;\n const p = this.players.get(corr);\n const heardMs = Math.round(p?.playedMs() ?? 0);\n p?.stop();\n this.players.delete(corr);\n this.cancelled.add(corr);\n this.speakingCorr = null;\n this.set({ speaking: false });\n this.emit('line', { corr, event: 'end' });\n this.sendJson({ type: 'playback_ended', correlationId: corr, timestampMs: Date.now(), reason: 'interrupted' });\n this.sendJson({ type: 'interrupt', correlationId: corr, heardMs, timestampMs: Date.now() });\n }\n\n setMuted(muted: boolean): void {\n this.mic?.setMuted(muted);\n this.set({ muted });\n }\n\n /** Leave the line, or hang up. */\n async hangUp(): Promise<void> {\n const id = this.s.callId;\n const was = this.s.phase;\n this.finish(was === 'live' ? 'hangup' : 'left', null);\n if (!id) return;\n try {\n const token = await this.session.token();\n await send(this.apiUrl, `/sdk/v1/calls/${encodeURIComponent(id)}`, { method: 'DELETE', token });\n } catch {\n // The server notices a closed socket / abandoned line on its own.\n }\n }\n\n private finish(reason: CallEndReason, error: string | null) {\n if (this.s.phase === 'ended') return;\n this.eventsAbort?.abort();\n this.eventsAbort = null;\n if (this.heartbeat) clearInterval(this.heartbeat);\n this.heartbeat = null;\n for (const p of this.players.values()) p.stop();\n this.players.clear();\n this.speakingCorr = null;\n this.mic?.stop();\n this.mic = null;\n const ws = this.ws;\n this.ws = null;\n if (ws && ws.readyState <= WebSocket.OPEN) ws.close(1000);\n this.ticket = null;\n this.set({ phase: 'ended', endReason: reason, speaking: false, holdSeconds: null, error });\n }\n}\n","import { Emitter } from './emitter.js';\nimport { CxError } from './errors.js';\nimport { readEvents, request, send } from './http.js';\nimport type { SessionManager } from './session.js';\nimport type { ChatMessage } from './types.js';\n\nexport interface ChatEvents extends Record<string, unknown> {\n /** The whole list, after any change. */\n messages: ChatMessage[];\n /** True from send until the reply is complete. */\n busy: boolean;\n error: CxError;\n}\n\nlet localSeq = 0;\nconst localId = (p: string) => `${p}_${Date.now().toString(36)}_${(localSeq++).toString(36)}`;\n\n/**\n * Text chat with the agent. History lives on the server, so it follows the\n * visitor across page loads (and, for an identified visitor, devices).\n */\nexport class Chat extends Emitter<ChatEvents> {\n private list: ChatMessage[] = [];\n private loaded = false;\n private busy = false;\n private abort: AbortController | null = null;\n\n constructor(\n private readonly apiUrl: string,\n private readonly session: SessionManager,\n ) {\n super();\n }\n\n get messages(): readonly ChatMessage[] {\n return this.list;\n }\n\n get isBusy(): boolean {\n return this.busy;\n }\n\n private publish() {\n this.list = [...this.list];\n this.emit('messages', this.list);\n }\n\n /** Load earlier messages (once; later calls return what is held). */\n async load(): Promise<readonly ChatMessage[]> {\n if (this.loaded) return this.list;\n const token = await this.session.token();\n const res = await request<{ messages: ChatMessage[] }>(this.apiUrl, '/sdk/v1/chat/messages?limit=50', { token });\n // Anything sent while the history was loading stays after it.\n const pending = this.list;\n this.list = [...(res?.messages ?? []), ...pending];\n this.loaded = true;\n this.publish();\n return this.list;\n }\n\n /**\n * Send a message; the reply streams into `messages` as it is written.\n * Resolves with the finished reply.\n */\n async send(text: string): Promise<ChatMessage> {\n const t = text.trim();\n if (!t) throw new CxError('invalid', 'Say something first.');\n if (this.busy) throw new CxError('rate_limited', 'Wait for the reply first.');\n this.setBusy(true);\n const mine: ChatMessage = { id: localId('local'), role: 'visitor', text: t, createdAt: new Date().toISOString() };\n const reply: ChatMessage = { id: localId('reply'), role: 'agent', text: '', createdAt: new Date().toISOString(), streaming: true };\n this.list.push(mine, reply);\n this.publish();\n\n this.abort = new AbortController();\n try {\n const token = await this.session.token();\n const res = await send(this.apiUrl, '/sdk/v1/chat/messages', { method: 'POST', body: { text: t }, token, signal: this.abort.signal });\n let finished: ChatMessage | null = null;\n let failure: string | null = null;\n await readEvents(\n res,\n ({ event, data }) => {\n const d = data as Record<string, unknown>;\n if (event === 'delta' && typeof d?.text === 'string') {\n reply.text += d.text;\n this.publish();\n } else if (event === 'done') {\n const next = Array.isArray(d.suggestions) ? d.suggestions.filter((q): q is string => typeof q === 'string' && q.trim() !== '') : [];\n finished = {\n id: String(d.id),\n role: 'agent',\n text: String(d.text ?? reply.text),\n createdAt: String(d.createdAt ?? reply.createdAt),\n ...(next.length ? { suggestions: next } : {}),\n ...(d.askDetails && typeof d.askDetails === 'object' ? { askDetails: d.askDetails as ChatMessage['askDetails'] } : {}),\n ...(d.detailsForm && typeof d.detailsForm === 'object' ? { detailsForm: d.detailsForm as ChatMessage['detailsForm'] } : {}),\n };\n } else if (event === 'error') {\n failure = typeof d?.message === 'string' ? d.message : 'Something went wrong.';\n }\n },\n this.abort.signal,\n );\n if (failure || !finished) throw new CxError('unknown', failure ?? 'The reply was cut off. Try again.');\n const done: ChatMessage = finished;\n this.replace(reply.id, done);\n return done;\n } catch (e) {\n const err = e instanceof CxError ? e : new CxError('network', 'The reply was cut off. Try again.');\n this.list = this.list.filter((m) => m.id !== reply.id);\n const idx = this.list.findIndex((m) => m.id === mine.id);\n // A refusal the server explained (a daily limit, a slow-down) is shown as\n // it was said; anything else is the generic \"not sent\".\n if (idx !== -1) this.list[idx] = { ...mine, failed: true, ...(err.status === 429 ? { error: err.message } : {}) };\n this.publish();\n if ((e as Error)?.name !== 'AbortError') this.emit('error', err);\n throw err;\n } finally {\n this.abort = null;\n this.setBusy(false);\n }\n }\n\n /**\n * Start a new conversation. The old one is archived by the server, not\n * deleted; the visitor simply starts fresh.\n */\n async reset(): Promise<void> {\n this.stop();\n const token = await this.session.token();\n await send(this.apiUrl, '/sdk/v1/chat/messages', { method: 'DELETE', token });\n this.list = [];\n this.loaded = true;\n this.publish();\n }\n\n /** Send a failed message again. */\n retry(id: string): Promise<ChatMessage> {\n const m = this.list.find((x) => x.id === id && x.failed);\n if (!m) throw new CxError('not_found', 'Nothing to retry.');\n this.list = this.list.filter((x) => x.id !== id);\n this.publish();\n return this.send(m.text);\n }\n\n /** Stop listening to a reply in progress (the server still finishes it). */\n stop(): void {\n this.abort?.abort();\n }\n\n private replace(id: string, next: ChatMessage) {\n const i = this.list.findIndex((m) => m.id === id);\n if (i !== -1) this.list[i] = next;\n this.publish();\n }\n\n private setBusy(b: boolean) {\n this.busy = b;\n this.emit('busy', b);\n }\n}\n","import { CxError } from './errors.js';\nimport { request } from './http.js';\nimport type { SessionInfo } from './types.js';\n\n/** Where the SDK may remember this browser's anonymous visitor id. */\nexport interface VisitorStore {\n get(key: string): string | null;\n set(key: string, value: string): void;\n}\n\nexport const memoryStore = (): VisitorStore => {\n const m = new Map<string, string>();\n return { get: (k) => m.get(k) ?? null, set: (k, v) => void m.set(k, v) };\n};\n\nexport const localStore = (): VisitorStore => ({\n get(k) {\n try {\n return globalThis.localStorage?.getItem(k) ?? null;\n } catch {\n return null;\n }\n },\n set(k, v) {\n try {\n globalThis.localStorage?.setItem(k, v);\n } catch {\n // private mode / blocked storage: the visitor is simply new each time\n }\n },\n});\n\nexport interface SessionSource {\n apiUrl: string;\n agentId?: string;\n /** Browser path: a publishable key, exchanged from this page's origin. */\n publishableKey?: string;\n /**\n * Server path: your backend mints the session with a secret key (an\n * identified visitor) and hands the token to the page. Called again when\n * the session is about to run out.\n */\n getSessionToken?: () => Promise<string | SessionInfo>;\n store: VisitorStore;\n}\n\n/** Renew this long before expiry. */\nconst RENEW_EARLY_S = 60;\n\n/**\n * Holds the current session, renews it before it runs out, and never runs\n * two renewals at once.\n */\nexport class SessionManager {\n private current: SessionInfo | null = null;\n private inflight: Promise<SessionInfo> | null = null;\n\n constructor(private readonly src: SessionSource) {\n if (!src.publishableKey && !src.getSessionToken) {\n throw new CxError('invalid', 'Pass a publishableKey, or getSessionToken for sessions your server mints.');\n }\n }\n\n private visitorKey(): string {\n // Per key, so two brands on one domain never share a visitor.\n const k = this.src.publishableKey ?? 'server';\n return `cxyz:visitor:${k.slice(-12)}`;\n }\n\n get info(): SessionInfo | null {\n return this.current;\n }\n\n /** A token valid for at least the next minute. */\n async token(): Promise<string> {\n const now = Date.now() / 1000;\n if (this.current && this.current.expiresAt - RENEW_EARLY_S > now) return this.current.token;\n return (await this.refresh()).token;\n }\n\n refresh(): Promise<SessionInfo> {\n this.inflight ??= this.mint().finally(() => {\n this.inflight = null;\n });\n return this.inflight;\n }\n\n private async mint(): Promise<SessionInfo> {\n let info: SessionInfo;\n if (this.src.getSessionToken) {\n const got = await this.src.getSessionToken();\n if (typeof got === 'string') {\n // A bare token: ask the server what it unlocks.\n info = await this.describe(got);\n } else {\n info = got;\n }\n } else {\n const visitorId = this.src.store.get(this.visitorKey()) ?? undefined;\n info = await request<SessionInfo>(this.src.apiUrl, '/sdk/v1/sessions', {\n method: 'POST',\n body: { publishableKey: this.src.publishableKey, agentId: this.src.agentId, visitorId },\n });\n this.src.store.set(this.visitorKey(), info.visitorId);\n }\n this.current = info;\n return info;\n }\n\n /** The session behind a token minted elsewhere (`getSessionToken` returned a string). */\n private async describe(token: string): Promise<SessionInfo> {\n const info = await request<SessionInfo>(this.src.apiUrl, '/sdk/v1/session', { token });\n return { ...info, token };\n }\n}\n","import { Call, type CallOptions } from './call.js';\nimport { Chat } from './chat.js';\nimport { Emitter } from './emitter.js';\nimport { CxError } from './errors.js';\nimport { request } from './http.js';\nimport { localStore, memoryStore, SessionManager, type VisitorStore } from './session.js';\nimport type { AgentCard, ContactDetails, Features, Opening, SessionInfo } from './types.js';\n\nexport const DEFAULT_API_URL = 'https://api.character.xyz';\n\nexport interface InitOptions {\n /** `cxyz_pk_live_…` — safe in the page; works only from the key's allowed sites. */\n publishableKey?: string;\n /**\n * For signed-in visitors: return a session your server minted with its\n * secret key (see `@characterxyz/server`). Called again before expiry.\n */\n getSessionToken?: () => Promise<string | SessionInfo>;\n /** Which of the key's agents to talk to. Defaults to the key's first. */\n agentId?: string;\n /** Override the API (staging, local development). */\n apiUrl?: string;\n /** Remember the anonymous visitor across visits (default) or not at all. */\n storage?: 'local' | 'memory' | VisitorStore;\n}\n\nexport interface ClientEvents extends Record<string, unknown> {\n /** A call started or ended; the widget swaps its view on this. */\n call: Call | null;\n error: CxError;\n}\n\n/**\n * The headless SDK. `await CharacterXYZ.init({ publishableKey })`, then use\n * `chat` and `startCall()`. Everything the widget does goes through here, so\n * a brand can build its own UI on the same calls.\n */\nexport class CharacterXYZ extends Emitter<ClientEvents> {\n readonly chat: Chat;\n private currentCall: Call | null = null;\n private destroyed = false;\n\n private constructor(\n readonly apiUrl: string,\n private readonly session: SessionManager,\n private info: SessionInfo,\n ) {\n super();\n this.chat = new Chat(apiUrl, session);\n }\n\n static async init(opts: InitOptions): Promise<CharacterXYZ> {\n const apiUrl = (opts.apiUrl ?? DEFAULT_API_URL).replace(/\\/+$/, '');\n if (opts.publishableKey && /^cxyz_sk_/.test(opts.publishableKey)) {\n // A secret key in a page is a leak. Refuse loudly, before it is sent anywhere.\n throw new CxError('invalid', 'That is a SECRET key. Never put it in a web page: use a publishable key (cxyz_pk_…). Revoke the secret key now.');\n }\n const store = opts.storage === 'memory' ? memoryStore() : opts.storage && typeof opts.storage === 'object' ? opts.storage : localStore();\n const session = new SessionManager({ apiUrl, agentId: opts.agentId, publishableKey: opts.publishableKey, getSessionToken: opts.getSessionToken, store });\n const info = await session.refresh();\n return new CharacterXYZ(apiUrl, session, info);\n }\n\n get agent(): AgentCard {\n return (this.session.info ?? this.info).agent;\n }\n\n get features(): Features {\n return (this.session.info ?? this.info).features;\n }\n\n get appearance(): Record<string, unknown> {\n return (this.session.info ?? this.info).appearance ?? {};\n }\n\n get visitorId(): string {\n return (this.session.info ?? this.info).visitorId;\n }\n\n get mode(): 'live' | 'test' {\n return (this.session.info ?? this.info).mode;\n }\n\n /** The call in progress (queued, ready or live), if any. */\n get call(): Call | null {\n return this.currentCall && this.currentCall.state.phase !== 'ended' ? this.currentCall : null;\n }\n\n /**\n * The worn video character's full render data (the public projection the\n * app's Stage reads), for a UI that draws the face — the widget hands it to\n * the app's renderer. Null when the agent wears none.\n */\n async videoAvatar(): Promise<Record<string, unknown> | null> {\n const token = await this.session.token();\n return request<Record<string, unknown> | null>(this.apiUrl, '/sdk/v1/agent/video-avatar', { token });\n }\n\n private openingP: Promise<Opening | null> | null = null;\n\n /**\n * How the agent opens the conversation here — her greeting, a welcome-back\n * line, a teaser and likely first questions — written by her and cached by\n * the server. Fetched once per page; null if it could not be had.\n */\n opening(refresh = false): Promise<Opening | null> {\n if (refresh) this.openingP = null;\n this.openingP ??= this.session\n .token()\n .then((token) => request<Opening>(this.apiUrl, '/sdk/v1/agent/opening', { token }))\n .catch(() => null);\n return this.openingP;\n }\n\n /**\n * Leave the visitor's details for the brand's team. Sending is the consent\n * (the card says so). Fails `invalid` with `fields` naming each problem.\n */\n async sendDetails(details: ContactDetails): Promise<void> {\n const token = await this.session.token();\n const page = typeof location !== 'undefined' ? location.href : undefined;\n await request(this.apiUrl, '/sdk/v1/lead', { token, body: { ...details, consent: true, ...(page ? { page } : {}) } });\n }\n\n /** \"Not now\" on the details card: she will not ask again in this conversation. */\n async declineDetails(): Promise<void> {\n const token = await this.session.token();\n await request(this.apiUrl, '/sdk/v1/lead/decline', { token, method: 'POST', body: {} });\n }\n\n /** Start a voice call. Call from a click: it needs the microphone and audio unlocked. */\n async startCall(opts: CallOptions = {}): Promise<Call> {\n if (this.destroyed) throw new CxError('invalid', 'This client was destroyed.');\n if (!this.features.call) throw new CxError('forbidden', 'Calls are not available on this site.');\n if (this.call) return this.call;\n const call = new Call(this.apiUrl, this.session, this.agent.id, opts);\n this.currentCall = call;\n call.on('state', (s) => {\n if (s.phase === 'ended' && this.currentCall === call) this.emit('call', null);\n });\n call.on('error', (e) => this.emit('error', e));\n this.emit('call', call);\n await call.start();\n return call;\n }\n\n destroy(): void {\n this.destroyed = true;\n void this.currentCall?.hangUp();\n this.chat.stop();\n this.chat.clear();\n this.clear();\n }\n}\n","/**\n * `@characterxyz/web` — Character XYZ on any web page, headless.\n *\n * ```ts\n * import { CharacterXYZ } from '@characterxyz/web';\n *\n * const cx = await CharacterXYZ.init({ publishableKey: 'cxyz_pk_live_…' });\n * cx.chat.on('messages', render);\n * await cx.chat.send('Hi!');\n *\n * button.onclick = async () => {\n * const call = await cx.startCall();\n * call.on('state', (s) => show(s.phase, s.position));\n * };\n * ```\n *\n * The ready-made widget is `@characterxyz/widget`; this package is what it\n * is built on, for brands who want their own UI.\n */\nexport { CharacterXYZ, DEFAULT_API_URL, type InitOptions, type ClientEvents } from './client.js';\nexport { Chat, type ChatEvents } from './chat.js';\nexport { Call, type CallEvents, type CallOptions } from './call.js';\nexport { CxError, type CxErrorCode } from './errors.js';\nexport { Emitter } from './emitter.js';\nexport type { VisitorStore } from './session.js';\nexport type {\n AgentCard,\n CallEndReason,\n CallPhase,\n CallState,\n Caption,\n ChatMessage,\n ContactDetails,\n DetailsForm,\n Features,\n Opening,\n SessionInfo,\n VideoCharacter,\n VideoClip,\n} from './types.js';\nexport const VERSION = '0.3.0';\n"]}
|
package/package.json
CHANGED