@chainlit/react-client
Version:
Websocket client to connect to your chainlit app.
312 lines (296 loc) • 41.3 kB
JavaScript
import { atom, selector, DefaultValue, useRecoilValue, useResetRecoilState, useSetRecoilState, useRecoilState } from 'recoil';
import { isEqual, debounce } from 'lodash';
import { v4 } from 'uuid';
import { createContext, useContext, useMemo, useCallback, useEffect } from 'react';
import Dt, { SWRConfig } from 'swr';
import Kt from 'socket.io-client';
export { Socket } from 'socket.io-client';
import { toast } from 'sonner';
var $e=o=>{let e={},t=new Date;return t.setHours(0,0,0,0),[...o].sort((s,n)=>new Date(n.createdAt).getTime()-new Date(s.createdAt).getTime()).forEach(s=>{let n=new Date(s.createdAt);n.setHours(0,0,0,0);let r=Math.floor((t.getTime()-n.getTime())/864e5),a;r===0?a="Today":r===1?a="Yesterday":r<=7?a="Previous 7 days":r<=30?a="Previous 30 days":a=n.toLocaleString("default",{month:"long",year:"numeric"}),e[a]??(e[a]=[]),e[a].push(s);}),e};var Ne=[4186.01,4434.92,4698.63,4978.03,5274.04,5587.65,5919.91,6271.93,6644.88,7040,7458.62,7902.13],At=["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"],M=[],ue=[];for(let o=1;o<=8;o++)for(let e=0;e<Ne.length;e++){let t=Ne[e];M.push(t/Math.pow(2,8-o)),ue.push(At[e]+o);}var ce=[32,2e3],_e=M.filter((o,e)=>M[e]>ce[0]&&M[e]<ce[1]),ze=ue.filter((o,e)=>M[e]>ce[0]&&M[e]<ce[1]);var D=class o{static getFrequencies(e,t,s,n="frequency",r=-100,a=-30){s||(s=new Float32Array(e.frequencyBinCount),e.getFloatFrequencyData(s));let i=t/2,d=1/s.length*i,f,l,p;if(n==="music"||n==="voice"){let g=n==="voice"?_e:M,y=Array(g.length).fill(r);for(let F=0;F<s.length;F++){let L=F*d,q=s[F];for(let b=g.length-1;b>=0;b--)if(L>g[b]){y[b]=Math.max(y[b],q);break}}f=y,l=n==="voice"?_e:M,p=n==="voice"?ze:ue;}else f=Array.from(s),l=f.map((g,y)=>d*y),p=l.map(g=>`${g.toFixed(2)} Hz`);let k=f.map(g=>Math.max(0,Math.min((g-r)/(a-r),1)));return {values:new Float32Array(k),frequencies:l,labels:p}}constructor(e,t=null){if(this.fftResults=[],t){let{length:s,sampleRate:n}=t,r=new OfflineAudioContext({length:s,sampleRate:n}),a=r.createBufferSource();a.buffer=t;let i=r.createAnalyser();i.fftSize=8192,i.smoothingTimeConstant=.1,a.connect(i);let d=1/60,f=s/n,l=p=>{let k=d*p;k<f&&r.suspend(k).then(()=>{let m=new Float32Array(i.frequencyBinCount);i.getFloatFrequencyData(m),this.fftResults.push(m),l(p+1);}),p===1?r.startRendering():r.resume();};a.start(0),l(1),this.audio=e,this.context=r,this.analyser=i,this.sampleRate=n,this.audioBuffer=t;}else {let s=new AudioContext,n=s.createMediaElementSource(e),r=s.createAnalyser();r.fftSize=8192,r.smoothingTimeConstant=.1,n.connect(r),r.connect(s.destination),this.audio=e,this.context=s,this.analyser=r,this.sampleRate=this.context.sampleRate,this.audioBuffer=null;}}getFrequencies(e="frequency",t=-100,s=-30){let n=null;if(this.audioBuffer&&this.fftResults.length){let r=this.audio.currentTime/this.audio.duration,a=Math.min(r*this.fftResults.length|0,this.fftResults.length-1);n=this.fftResults[a];}return o.getFrequencies(this.analyser,this.sampleRate,n,e,t,s)}async resumeIfSuspended(){return this.context.state==="suspended"&&await this.context.resume(),!0}};globalThis.AudioAnalysis=D;var T=class{static floatTo16BitPCM(e){let t=new ArrayBuffer(e.length*2),s=new DataView(t),n=0;for(let r=0;r<e.length;r++,n+=2){let a=Math.max(-1,Math.min(1,e[r]));s.setInt16(n,a<0?a*32768:a*32767,!0);}return t}static mergeBuffers(e,t){let s=new Uint8Array(e.byteLength+t.byteLength);return s.set(new Uint8Array(e),0),s.set(new Uint8Array(t),e.byteLength),s.buffer}_packData(e,t){return [new Uint8Array([t,t>>8]),new Uint8Array([t,t>>8,t>>16,t>>24])][e]}pack(e,t){if(t?.bitsPerSample)if(t?.channels){if(!t?.data)throw new Error('Missing "data"')}else throw new Error('Missing "channels"');else throw new Error('Missing "bitsPerSample"');let{bitsPerSample:s,channels:n,data:r}=t,a=["RIFF",this._packData(1,4+(8+24)+(8+8)),"WAVE","fmt ",this._packData(1,16),this._packData(0,1),this._packData(0,n.length),this._packData(1,e),this._packData(1,e*n.length*s/8),this._packData(0,n.length*s/8),this._packData(0,s),"data",this._packData(1,n[0].length*n.length*s/8),r],i=new Blob(a,{type:"audio/mpeg"}),d=URL.createObjectURL(i);return {blob:i,url:d,channelCount:n.length,sampleRate:e,duration:r.byteLength/(n.length*e*2)}}};globalThis.WavPacker=T;var Ct=`
class AudioProcessor extends AudioWorkletProcessor {
constructor() {
super();
this.port.onmessage = this.receive.bind(this);
this.initialize();
}
initialize() {
this.foundAudio = false;
this.recording = false;
this.chunks = [];
}
/**
* Concatenates sampled chunks into channels
* Format is chunk[Left[], Right[]]
*/
readChannelData(chunks, channel = -1, maxChannels = 9) {
let channelLimit;
if (channel !== -1) {
if (chunks[0] && chunks[0].length - 1 < channel) {
throw new Error(
\`Channel \${channel} out of range: max \${chunks[0].length}\`
);
}
channelLimit = channel + 1;
} else {
channel = 0;
channelLimit = Math.min(chunks[0] ? chunks[0].length : 1, maxChannels);
}
const channels = [];
for (let n = channel; n < channelLimit; n++) {
const length = chunks.reduce((sum, chunk) => {
return sum + chunk[n].length;
}, 0);
const buffers = chunks.map((chunk) => chunk[n]);
const result = new Float32Array(length);
let offset = 0;
for (let i = 0; i < buffers.length; i++) {
result.set(buffers[i], offset);
offset += buffers[i].length;
}
channels[n] = result;
}
return channels;
}
/**
* Combines parallel audio data into correct format,
* channels[Left[], Right[]] to float32Array[LRLRLRLR...]
*/
formatAudioData(channels) {
if (channels.length === 1) {
// Simple case is only one channel
const float32Array = channels[0].slice();
const meanValues = channels[0].slice();
return { float32Array, meanValues };
} else {
const float32Array = new Float32Array(
channels[0].length * channels.length
);
const meanValues = new Float32Array(channels[0].length);
for (let i = 0; i < channels[0].length; i++) {
const offset = i * channels.length;
let meanValue = 0;
for (let n = 0; n < channels.length; n++) {
float32Array[offset + n] = channels[n][i];
meanValue += channels[n][i];
}
meanValues[i] = meanValue / channels.length;
}
return { float32Array, meanValues };
}
}
/**
* Converts 32-bit float data to 16-bit integers
*/
floatTo16BitPCM(float32Array) {
const buffer = new ArrayBuffer(float32Array.length * 2);
const view = new DataView(buffer);
let offset = 0;
for (let i = 0; i < float32Array.length; i++, offset += 2) {
let s = Math.max(-1, Math.min(1, float32Array[i]));
view.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7fff, true);
}
return buffer;
}
/**
* Retrieves the most recent amplitude values from the audio stream
* @param {number} channel
*/
getValues(channel = -1) {
const channels = this.readChannelData(this.chunks, channel);
const { meanValues } = this.formatAudioData(channels);
return { meanValues, channels };
}
/**
* Exports chunks as an audio/wav file
*/
export() {
const channels = this.readChannelData(this.chunks);
const { float32Array, meanValues } = this.formatAudioData(channels);
const audioData = this.floatTo16BitPCM(float32Array);
return {
meanValues: meanValues,
audio: {
bitsPerSample: 16,
channels: channels,
data: audioData,
},
};
}
receive(e) {
const { event, id } = e.data;
let receiptData = {};
switch (event) {
case 'start':
this.recording = true;
break;
case 'stop':
this.recording = false;
break;
case 'clear':
this.initialize();
break;
case 'export':
receiptData = this.export();
break;
case 'read':
receiptData = this.getValues();
break;
default:
break;
}
// Always send back receipt
this.port.postMessage({ event: 'receipt', id, data: receiptData });
}
sendChunk(chunk) {
const channels = this.readChannelData([chunk]);
const { float32Array, meanValues } = this.formatAudioData(channels);
const rawAudioData = this.floatTo16BitPCM(float32Array);
const monoAudioData = this.floatTo16BitPCM(meanValues);
this.port.postMessage({
event: 'chunk',
data: {
mono: monoAudioData,
raw: rawAudioData,
},
});
}
process(inputList, outputList, parameters) {
// Copy input to output (e.g. speakers)
// Note that this creates choppy sounds with Mac products
const sourceLimit = Math.min(inputList.length, outputList.length);
for (let inputNum = 0; inputNum < sourceLimit; inputNum++) {
const input = inputList[inputNum];
const output = outputList[inputNum];
const channelCount = Math.min(input.length, output.length);
for (let channelNum = 0; channelNum < channelCount; channelNum++) {
input[channelNum].forEach((sample, i) => {
output[channelNum][i] = sample;
});
}
}
const inputs = inputList[0];
// There's latency at the beginning of a stream before recording starts
// Make sure we actually receive audio data before we start storing chunks
let sliceIndex = 0;
if (!this.foundAudio) {
for (const channel of inputs) {
sliceIndex = 0; // reset for each channel
if (this.foundAudio) {
break;
}
if (channel) {
for (const value of channel) {
if (value !== 0) {
// find only one non-zero entry in any channel
this.foundAudio = true;
break;
} else {
sliceIndex++;
}
}
}
}
}
if (inputs && inputs[0] && this.foundAudio && this.recording) {
// We need to copy the TypedArray, because the \`process\`
// internals will reuse the same buffer to hold each input
const chunk = inputs.map((input) => input.slice(sliceIndex));
this.chunks.push(chunk);
this.sendChunk(chunk);
}
return true;
}
}
registerProcessor('audio_processor', AudioProcessor);
`,xt=new Blob([Ct],{type:"application/javascript"}),bt=URL.createObjectURL(xt),We=bt;var $=class{constructor({sampleRate:e=24e3,outputToSpeakers:t=!1,debug:s=!1}={}){this.scriptSrc=We,this.sampleRate=e,this.outputToSpeakers=t,this.debug=!!s,this._deviceChangeCallback=null,this._devices=[],this.stream=null,this.processor=null,this.source=null,this.node=null,this.recording=!1,this._lastEventId=0,this.eventReceipts={},this.eventTimeout=5e3,this._chunkProcessor=()=>{},this._chunkProcessorSize=void 0,this._chunkProcessorBuffer={raw:new ArrayBuffer(0),mono:new ArrayBuffer(0)};}static async decode(e,t=24e3,s=-1){let n=new AudioContext({sampleRate:t}),r,a;if(e instanceof Blob){if(s!==-1)throw new Error('Can not specify "fromSampleRate" when reading from Blob');a=e,r=await a.arrayBuffer();}else if(e instanceof ArrayBuffer){if(s!==-1)throw new Error('Can not specify "fromSampleRate" when reading from ArrayBuffer');r=e,a=new Blob([r],{type:"audio/wav"});}else {let l,p;if(e instanceof Int16Array){p=e,l=new Float32Array(e.length);for(let y=0;y<e.length;y++)l[y]=e[y]/32768;}else if(e instanceof Float32Array)l=e;else if(e instanceof Array)l=new Float32Array(e);else throw new Error('"audioData" must be one of: Blob, Float32Arrray, Int16Array, ArrayBuffer, Array<number>');if(s===-1)throw new Error('Must specify "fromSampleRate" when reading from Float32Array, In16Array or Array');if(s<3e3)throw new Error('Minimum "fromSampleRate" is 3000 (3kHz)');p||(p=T.floatTo16BitPCM(l));let k={bitsPerSample:16,channels:[l],data:p};a=new T().pack(s,k).blob,r=await a.arrayBuffer();}let i=await n.decodeAudioData(r),d=i.getChannelData(0),f=URL.createObjectURL(a);return {blob:a,url:f,values:d,audioBuffer:i}}log(){return this.debug&&this.log(...arguments),!0}getSampleRate(){return this.sampleRate}getStatus(){return this.processor?this.recording?"recording":"paused":"ended"}async _event(e,t={},s=null){if(s=s||this.processor,!s)throw new Error("Can not send events without recording first");let n={event:e,id:this._lastEventId++,data:t};s.port.postMessage(n);let r=new Date().valueOf();for(;!this.eventReceipts[n.id];){if(new Date().valueOf()-r>this.eventTimeout)throw new Error(`Timeout waiting for "${e}" event`);await new Promise(i=>setTimeout(()=>i(!0),1));}let a=this.eventReceipts[n.id];return delete this.eventReceipts[n.id],a}listenForDeviceChange(e){if(e===null&&this._deviceChangeCallback)navigator.mediaDevices.removeEventListener("devicechange",this._deviceChangeCallback),this._deviceChangeCallback=null;else if(e!==null){let t=0,s=[],n=a=>a.map(i=>i.deviceId).sort().join(","),r=async()=>{let a=++t,i=await this.listDevices();a===t&&n(s)!==n(i)&&(s=i,e(i.slice()));};navigator.mediaDevices.addEventListener("devicechange",r),r(),this._deviceChangeCallback=r;}return !0}async requestPermission(){let e=await navigator.permissions.query({name:"microphone"});if(e.state==="denied")window.alert("You must grant microphone access to use this feature.");else if(e.state==="prompt")try{(await navigator.mediaDevices.getUserMedia({audio:!0})).getTracks().forEach(n=>n.stop());}catch{window.alert("You must grant microphone access to use this feature.");}return !0}async listDevices(){if(!navigator.mediaDevices||!("enumerateDevices"in navigator.mediaDevices))throw new Error("Could not request user devices");await this.requestPermission();let t=(await navigator.mediaDevices.enumerateDevices()).filter(r=>r.kind==="audioinput"),s=t.findIndex(r=>r.deviceId==="default"),n=[];if(s!==-1){let r=t.splice(s,1)[0],a=t.findIndex(i=>i.groupId===r.groupId);a!==-1&&(r=t.splice(a,1)[0]),r.default=!0,n.push(r);}return n.concat(t)}async begin(e){if(this.processor)throw new Error("Already connected: please call .end() to start a new session");if(!navigator.mediaDevices||!("getUserMedia"in navigator.mediaDevices))throw new Error("Could not request user media");try{let i={audio:!0};e&&(i.audio={deviceId:{exact:e}}),this.stream=await navigator.mediaDevices.getUserMedia(i);}catch{throw new Error("Could not start media stream")}let t=new AudioContext({sampleRate:this.sampleRate}),s=t.createMediaStreamSource(this.stream);try{await t.audioWorklet.addModule(this.scriptSrc);}catch(i){throw console.error(i),new Error(`Could not add audioWorklet module: ${this.scriptSrc}`)}let n=new AudioWorkletNode(t,"audio_processor");n.port.onmessage=i=>{let{event:d,id:f,data:l}=i.data;if(d==="receipt")this.eventReceipts[f]=l;else if(d==="chunk")if(this._chunkProcessorSize){let p=this._chunkProcessorBuffer;this._chunkProcessorBuffer={raw:T.mergeBuffers(p.raw,l.raw),mono:T.mergeBuffers(p.mono,l.mono)},this._chunkProcessorBuffer.mono.byteLength>=this._chunkProcessorSize&&(this._chunkProcessor(this._chunkProcessorBuffer),this._chunkProcessorBuffer={raw:new ArrayBuffer(0),mono:new ArrayBuffer(0)});}else this._chunkProcessor(l);};let r=s.connect(n),a=t.createAnalyser();return a.fftSize=8192,a.smoothingTimeConstant=.1,r.connect(a),this.outputToSpeakers&&(console.warn(`Warning: Output to speakers may affect sound quality,
especially due to system audio feedback preventative measures.
use only for debugging`),a.connect(t.destination)),this.source=s,this.node=r,this.analyser=a,this.processor=n,!0}getFrequencies(e="frequency",t=-100,s=-30){if(!this.processor)throw new Error("Session ended: please call .begin() first");return D.getFrequencies(this.analyser,this.sampleRate,null,e,t,s)}async pause(){if(this.processor){if(!this.recording)throw new Error("Already paused: please call .record() first")}else throw new Error("Session ended: please call .begin() first");return this._chunkProcessorBuffer.raw.byteLength&&this._chunkProcessor(this._chunkProcessorBuffer),this.log("Pausing ..."),await this._event("stop"),this.recording=!1,!0}async record(e=()=>{},t=8192){if(this.processor){if(this.recording)throw new Error("Already recording: please call .pause() first");if(typeof e!="function")throw new Error("chunkProcessor must be a function")}else throw new Error("Session ended: please call .begin() first");return this._chunkProcessor=e,this._chunkProcessorSize=t,this._chunkProcessorBuffer={raw:new ArrayBuffer(0),mono:new ArrayBuffer(0)},this.log("Recording ..."),await this._event("start"),this.recording=!0,!0}async clear(){if(!this.processor)throw new Error("Session ended: please call .begin() first");return await this._event("clear"),!0}async read(){if(!this.processor)throw new Error("Session ended: please call .begin() first");return this.log("Reading ..."),await this._event("read")}async save(e=!1){if(!this.processor)throw new Error("Session ended: please call .begin() first");if(!e&&this.recording)throw new Error("Currently recording: please call .pause() first, or call .save(true) to force");this.log("Exporting ...");let t=await this._event("export");return new T().pack(this.sampleRate,t.audio)}async end(){if(!this.processor)throw new Error("Session ended: please call .begin() first");let e=this.processor;this.log("Stopping ..."),await this._event("stop"),this.recording=!1,this.stream.getTracks().forEach(a=>a.stop()),this.log("Exporting ...");let s=await this._event("export",{},e);return this.processor.disconnect(),this.source.disconnect(),this.node.disconnect(),this.analyser.disconnect(),this.stream=null,this.processor=null,this.source=null,this.node=null,new T().pack(this.sampleRate,s.audio)}async quit(){return this.listenForDeviceChange(null),this.processor&&await this.end(),!0}};globalThis.WavRecorder=$;var vt=`
class StreamProcessor extends AudioWorkletProcessor {
constructor() {
super();
this.hasStarted = false;
this.hasInterrupted = false;
this.outputBuffers = [];
this.bufferLength = 128;
this.write = { buffer: new Float32Array(this.bufferLength), trackId: null };
this.writeOffset = 0;
this.trackSampleOffsets = {};
this.port.onmessage = (event) => {
if (event.data) {
const payload = event.data;
if (payload.event === 'write') {
const int16Array = payload.buffer;
const float32Array = new Float32Array(int16Array.length);
for (let i = 0; i < int16Array.length; i++) {
float32Array[i] = int16Array[i] / 0x8000; // Convert Int16 to Float32
}
this.writeData(float32Array, payload.trackId);
} else if (
payload.event === 'offset' ||
payload.event === 'interrupt'
) {
const requestId = payload.requestId;
const trackId = this.write.trackId;
const offset = this.trackSampleOffsets[trackId] || 0;
this.port.postMessage({
event: 'offset',
requestId,
trackId,
offset,
});
if (payload.event === 'interrupt') {
this.hasInterrupted = true;
}
} else {
throw new Error(\`Unhandled event "\${payload.event}"\`);
}
}
};
}
writeData(float32Array, trackId = null) {
let { buffer } = this.write;
let offset = this.writeOffset;
for (let i = 0; i < float32Array.length; i++) {
buffer[offset++] = float32Array[i];
if (offset >= buffer.length) {
this.outputBuffers.push(this.write);
this.write = { buffer: new Float32Array(this.bufferLength), trackId };
buffer = this.write.buffer;
offset = 0;
}
}
this.writeOffset = offset;
return true;
}
process(inputs, outputs, parameters) {
const output = outputs[0];
const outputChannelData = output[0];
const outputBuffers = this.outputBuffers;
if (this.hasInterrupted) {
this.port.postMessage({ event: 'stop' });
return false;
} else if (outputBuffers.length) {
this.hasStarted = true;
const { buffer, trackId } = outputBuffers.shift();
for (let i = 0; i < outputChannelData.length; i++) {
outputChannelData[i] = buffer[i] || 0;
}
if (trackId) {
this.trackSampleOffsets[trackId] =
this.trackSampleOffsets[trackId] || 0;
this.trackSampleOffsets[trackId] += buffer.length;
}
return true;
} else if (this.hasStarted) {
this.port.postMessage({ event: 'stop' });
return false;
} else {
return true;
}
}
}
registerProcessor('stream_processor', StreamProcessor);
`,Tt=new Blob([vt],{type:"application/javascript"}),Et=URL.createObjectURL(Tt),He=Et;var N=class{constructor({sampleRate:e=24e3,onStop:t}={}){this.scriptSrc=He,this.onStop=t,this.sampleRate=e,this.context=null,this.stream=null,this.analyser=null,this.trackSampleOffsets={},this.interruptedTrackIds={};}async connect(){this.context=new AudioContext({sampleRate:this.sampleRate}),this.context.state==="suspended"&&await this.context.resume();try{await this.context.audioWorklet.addModule(this.scriptSrc);}catch(t){throw console.error(t),new Error(`Could not add audioWorklet module: ${this.scriptSrc}`)}let e=this.context.createAnalyser();return e.fftSize=8192,e.smoothingTimeConstant=.1,this.analyser=e,!0}getFrequencies(e="frequency",t=-100,s=-30){if(!this.analyser)throw new Error("Not connected, please call .connect() first");return D.getFrequencies(this.analyser,this.sampleRate,null,e,t,s)}_start(){let e=new AudioWorkletNode(this.context,"stream_processor");return e.connect(this.context.destination),e.port.onmessage=t=>{let{event:s}=t.data;if(s==="stop")this.onStop?.(),e.disconnect(),this.stream=null;else if(s==="offset"){let{requestId:n,trackId:r,offset:a}=t.data,i=a/this.sampleRate;this.trackSampleOffsets[n]={trackId:r,offset:a,currentTime:i};}},this.analyser.disconnect(),e.connect(this.analyser),this.stream=e,!0}add16BitPCM(e,t="default"){if(typeof t!="string")throw new Error("trackId must be a string");if(this.interruptedTrackIds[t])return;this.stream||this._start();let s;if(e instanceof Int16Array)s=e;else if(e instanceof ArrayBuffer)s=new Int16Array(e);else throw new Error("argument must be Int16Array or ArrayBuffer");return this.stream.port.postMessage({event:"write",buffer:s,trackId:t}),s}async getTrackSampleOffset(e=!1){if(!this.stream)return null;let t=crypto.randomUUID();this.stream.port.postMessage({event:e?"interrupt":"offset",requestId:t});let s;for(;!s;)s=this.trackSampleOffsets[t],await new Promise(r=>setTimeout(()=>r(),1));let{trackId:n}=s;return e&&n&&(this.interruptedTrackIds[n]=!0),s}async interrupt(){return this.getTrackSampleOffset(!0)}};globalThis.WavStreamPlayer=N;var le=atom({key:"ThreadIdToResume",default:void 0}),Ye=atom({key:"ResumeThreadErrorState",default:void 0}),Qe=atom({key:"ChatProfile",default:void 0}),Ke=atom({key:"SessionId",default:v4()}),ne=selector({key:"SessionIdSelector",get:({get:o})=>o(Ke),set:({set:o},e)=>o(Ke,e instanceof DefaultValue?v4():e)}),z=atom({key:"Session",dangerouslyAllowMutability:!0,default:void 0}),W=atom({key:"Actions",default:[]}),H=atom({key:"Messages",dangerouslyAllowMutability:!0,default:[]}),Xe=atom({key:"Commands",default:[]}),fe=atom({key:"TokenCount",default:0}),K=atom({key:"Loading",default:!1}),G=atom({key:"AskUser",default:void 0}),de=atom({key:"WavRecorder",dangerouslyAllowMutability:!0,default:new $}),he=atom({key:"WavStreamPlayer",dangerouslyAllowMutability:!0,default:new N}),pe=atom({key:"AudioConnection",default:"off"}),me=atom({key:"isAiSpeaking",default:!1}),ge=atom({key:"CallFn",default:void 0}),V=atom({key:"ChatSettings",default:[]}),Me=selector({key:"ChatSettingsValue/Default",get:({get:o})=>o(V).reduce((t,s)=>(t[s.id]=s.initial,t),{})}),O=atom({key:"ChatSettingsValue",default:Me}),J=atom({key:"DisplayElements",default:[]}),Y=atom({key:"TasklistElements",default:[]}),Q=atom({key:"FirstUserInteraction",default:void 0}),Ze=atom({key:"User",default:void 0}),et=atom({key:"ChainlitConfig",default:void 0}),tt=atom({key:"AuthConfig",default:void 0}),st=atom({key:"ThreadHistory",default:{threads:void 0,currentThreadId:void 0,timeGroupedThreads:void 0,pageInfo:void 0},effects:[({setSelf:o,onSet:e})=>{e((t,s)=>{let n=t?.timeGroupedThreads;t?.threads&&!isEqual(t.threads,s?.timeGroupedThreads)&&(n=$e(t.threads)),o({...t,timeGroupedThreads:n});});}]}),ye=atom({key:"SideView",default:void 0}),X=atom({key:"CurrentThreadId",default:void 0}),Mt=o=>({setSelf:e,onSet:t})=>{let s=localStorage.getItem(o);if(s!=null)try{e(JSON.parse(s));}catch(n){console.error(`Error parsing localStorage value for key "${o}":`,n);}t((n,r,a)=>{a?localStorage.removeItem(o):localStorage.setItem(o,JSON.stringify(n));});},nt=atom({key:"Mcp",default:[],effects:[Mt("mcp_storage_key")]});var Ts=()=>{let o=useRecoilValue(K),e=useRecoilValue(J),t=useRecoilValue(Y),s=useRecoilValue(W),n=useRecoilValue(z),r=useRecoilValue(G),a=useRecoilValue(ge),i=useRecoilValue(V),d=useRecoilValue(O),f=useRecoilValue(Me),l=n?.socket.connected&&!n?.error,p=!l||o||r?.spec.type==="file"||r?.spec.type==="action";return {actions:s,askUser:r,callFn:a,chatSettingsDefaultValue:f,chatSettingsInputs:i,chatSettingsValue:d,connected:l,disabled:p,elements:e,error:n?.error,loading:o,tasklists:t}};var _s=o=>{let e=[];for(let t of o)e=R(e,t);return e},Ms=(o,e)=>{if(o.length-1===e)return !0;for(let t=e+1;t<o.length;t++)if(!o[t].streaming)return !1;return !0},R=(o,e)=>we(o,e.id)?ke(o,e.id,e):"parentId"in e&&e.parentId?ot(o,e.parentId,e):"indent"in e&&e.indent&&e.indent>0?rt(o,e.indent,e):[...o,e],rt=(o,e,t,s=0)=>{let n=[...o];if(n.length===0)return [...n,t];{let r=n.length-1,a=n[r];return a.steps=a.steps||[],s+1===e?(a.steps=[...a.steps,t],n[r]={...a},n):(a.steps=rt(a.steps,e,t,s+1),n[r]={...a},n)}},ot=(o,e,t)=>{let s=[...o];for(let n=0;n<s.length;n++){let r=s[n];isEqual(r.id,e)?(r.steps=r.steps?[...r.steps,t]:[t],s[n]={...r}):we(s,e)&&r.steps&&(r.steps=ot(r.steps,e,t),s[n]={...r});}return s},at=(o,e)=>{for(let t of o){if(isEqual(t.id,e))return t;if(t.steps&&t.steps.length>0){let s=at(t.steps,e);if(s)return s}}},we=(o,e)=>at(o,e)!==void 0,ke=(o,e,t)=>{let s=[...o];for(let n=0;n<s.length;n++){let r=s[n];isEqual(r.id,e)?s[n]={steps:r.steps,...t}:we(s,e)&&r.steps&&(r.steps=ke(r.steps,e,t),s[n]={...r});}return s},Re=(o,e)=>{let t=[...o];for(let s=0;s<t.length;s++){let n=t[s];n.id===e?t=[...t.slice(0,s),...t.slice(s+1)]:we(t,e)&&n.steps&&(n.steps=Re(n.steps,e),t[s]={...n});}return t},Fe=(o,e,t,s,n)=>{let r=[...o];for(let a=0;a<r.length;a++){let i=r[a];isEqual(i.id,e)?("content"in i&&i.content!==void 0?s?i.content=t:i.content+=t:n?"input"in i&&i.input!==void 0&&(s?i.input=t:i.input+=t):"output"in i&&i.output!==void 0&&(s?i.output=t:i.output+=t),r[a]={...i}):i.steps&&(i.steps=Fe(i.steps,e,t,s,n),r[a]={...i});}return r};var U=()=>{let[o,e]=useRecoilState(tt),[t,s]=useRecoilState(Ze),n=useSetRecoilState(st);return {authConfig:o,setAuthConfig:e,user:t,setUser:s,setThreadHistory:n}};var Bt=async(o,e)=>(await o.get(e))?.json(),Lt=o=>{let e=new ee("","webapp");return Object.assign(e,o),e};function Z(o,{...e}={}){let t=useContext(B),{setUser:s}=U(),n=useMemo(()=>([a])=>{e.onErrorRetry||(e.onErrorRetry=(...d)=>{let[f]=d;if(f.status===401){s(null);return}return SWRConfig.defaultValue.onErrorRetry(...d)});let i=Lt(t);return i.on401=i.onError=void 0,Bt(i,a)},[t]),r=useMemo(()=>o?[o]:null,[o]);return Dt(r,n,e)}var ut=()=>{let{authConfig:o,setAuthConfig:e}=U(),{data:t,isLoading:s}=Z(o?null:"/auth/config");return useEffect(()=>{t&&e(t);},[t,e]),{authConfig:o,isLoading:s}};var lt=()=>{let o=useContext(B),{setUser:e,setThreadHistory:t}=U();return {logout:async(n=!1)=>{await o.logout(),e(void 0),t(void 0),n&&window.location.reload();}}};var dt=()=>{let{user:o,setUser:e}=U(),{data:t,error:s,isLoading:n,mutate:r}=Z("/user");return useEffect(()=>{t?e(t):n&&e(void 0);},[t,n,e]),useEffect(()=>{s&&e(null);},[s]),{user:o,setUserFromAPI:r}};var ht=()=>{let{authConfig:o}=ut(),{logout:e}=lt(),{user:t,setUserFromAPI:s}=dt(),n=!!o&&(!o.requireLogin||t!==void 0);return o&&!o.requireLogin?{data:o,user:null,isReady:n,isAuthenticated:!0,logout:()=>Promise.resolve(),setUserFromAPI:()=>Promise.resolve()}:{data:o,user:t,isReady:n,isAuthenticated:!!t,logout:e,setUserFromAPI:s}};var Ie=class extends Error{constructor(t,s,n){super(t);this.status=s,this.detail=n;}toString(){return this.detail?`${this.message}: ${this.detail}`:this.message}},De=class{constructor(e,t,s,n){this.httpEndpoint=e;this.type=t;this.on401=s;this.onError=n;}buildEndpoint(e){return this.httpEndpoint.endsWith("/")?`${this.httpEndpoint.slice(0,-1)}${e}`:`${this.httpEndpoint}${e}`}async getDetailFromErrorResponse(e){try{return (await e.json())?.detail}catch(t){console.error("Unable to parse error response",t);}}handleRequestError(e){e instanceof Ie&&(e.status===401&&this.on401&&this.on401(),this.onError&&this.onError(e)),console.error(e);}async fetch(e,t,s,n,r={}){try{let a;s instanceof FormData?a=s:(r["Content-Type"]="application/json",a=s?JSON.stringify(s):null);let i=await fetch(this.buildEndpoint(t),{method:e,credentials:"include",headers:r,signal:n,body:a});if(!i.ok){let d=await this.getDetailFromErrorResponse(i);throw new Ie(i.statusText,i.status,d)}return i}catch(a){throw this.handleRequestError(a),a}}async get(e){return await this.fetch("GET",e)}async post(e,t,s){return await this.fetch("POST",e,t,s)}async put(e,t){return await this.fetch("PUT",e,t)}async patch(e,t){return await this.fetch("PATCH",e,t)}async delete(e,t){return await this.fetch("DELETE",e,t)}},ee=class extends De{async headerAuth(){return (await this.post("/auth/header",{})).json()}async jwtAuth(e){return (await this.fetch("POST","/auth/jwt",void 0,void 0,{Authorization:`Bearer ${e}`})).json()}async passwordAuth(e){return (await this.post("/login",e)).json()}async getUser(){return (await this.get("/user")).json()}async logout(){return (await this.post("/logout",{})).json()}async setFeedback(e){return (await this.put("/feedback",{feedback:e})).json()}async deleteFeedback(e){return (await this.delete("/feedback",{feedbackId:e})).json()}async listThreads(e,t){return (await this.post("/project/threads",{pagination:e,filter:t})).json()}async renameThread(e,t){return (await this.put("/project/thread",{threadId:e,name:t})).json()}async deleteThread(e){return (await this.delete("/project/thread",{threadId:e})).json()}uploadFile(e,t,s){let n=new XMLHttpRequest;n.withCredentials=!0;let r=new Promise((a,i)=>{let d=new FormData;d.append("file",e),n.open("POST",this.buildEndpoint(`/project/file?session_id=${s}`),!0),n.upload.onprogress=function(f){if(f.lengthComputable){let l=f.loaded/f.total*100;t(l);}},n.onload=function(){if(n.status===200){let l=JSON.parse(n.responseText);a(l);return}let f=n.getResponseHeader("Content-Type");if(f&&f.includes("application/json")){let l=JSON.parse(n.responseText);i(l.detail);}else i("Upload failed");},n.onerror=function(){i("Upload error");},n.send(d);});return {xhr:n,promise:r}}async callAction(e,t){return (await this.post("/project/action",{sessionId:t,action:e})).json()}async updateElement(e,t){return (await this.put("/project/element",{sessionId:t,element:e})).json()}async deleteElement(e,t){return (await this.delete("/project/element",{sessionId:t,element:e})).json()}async connectStdioMCP(e,t,s){return (await this.post("/mcp",{sessionId:e,name:t,fullCommand:s,clientType:"stdio"})).json()}async connectSseMCP(e,t,s){return (await this.post("/mcp",{sessionId:e,name:t,url:s,clientType:"sse"})).json()}async disconnectMcp(e,t){return (await this.delete("/mcp",{sessionId:e,name:t})).json()}getElementUrl(e,t){let s=`?session_id=${t}`;return this.buildEndpoint(`/project/file/${e}${s}`)}getLogoEndpoint(e){return this.buildEndpoint(`/logo?theme=${e}`)}getOAuthEndpoint(e){return this.buildEndpoint(`/auth/oauth/${e}`)}};var fn=void 0,B=createContext(new ee("http://localhost:8000","webapp"));var pt=()=>{let o=useContext(B),e=useRecoilValue(z),t=useRecoilValue(G),s=useRecoilValue(ne),n=useResetRecoilState(V),r=useResetRecoilState(ne),a=useResetRecoilState(O),i=useSetRecoilState(Q),d=useSetRecoilState(K),f=useSetRecoilState(H),l=useSetRecoilState(J),p=useSetRecoilState(Y),k=useSetRecoilState(W),m=useSetRecoilState(fe),g=useSetRecoilState(le),y=useSetRecoilState(ye),F=useSetRecoilState(X),L=useCallback(()=>{e?.socket.emit("clear_session"),e?.socket.disconnect(),g(void 0),r(),i(void 0),f([]),l([]),p([]),k([]),m(0),n(),a(),y(void 0),F(void 0);},[e]),q=useCallback((I,x=[])=>{I.id||(I.id=v4()),I.createdAt||(I.createdAt=new Date().toISOString()),f(se=>R(se,I)),e?.socket.emit("client_message",{message:I,fileReferences:x});},[e?.socket]),b=useCallback(I=>{e?.socket.emit("edit_message",{message:I});},[e?.socket]),oe=useCallback(I=>{e?.socket.emit("window_message",I);},[e?.socket]),Ce=useCallback(()=>{e?.socket.emit("audio_start");},[e?.socket]),xe=useCallback((I,x,se,Te)=>{e?.socket.emit("audio_chunk",{isStart:I,mimeType:x,elapsedTime:se,data:Te});},[e?.socket]),j=useCallback(()=>{e?.socket.emit("audio_end");},[e?.socket]),ae=useCallback(I=>{t&&(t.parentId&&(I.parentId=t.parentId),f(x=>R(x,I)),t.callback(I));},[t]),te=useCallback(I=>{e?.socket.emit("chat_settings_change",I);},[e?.socket]),be=useCallback(()=>{f(I=>I.map(x=>(x.streaming=!1,x))),d(!1),e?.socket.emit("stop");},[e?.socket]);return {uploadFile:useCallback((I,x)=>o.uploadFile(I,x,s),[s]),clear:L,replyMessage:ae,sendMessage:q,editMessage:b,windowMessage:oe,startAudioStream:Ce,sendAudioChunk:xe,endAudioStream:j,stopTask:be,setIdToResume:g,updateChatSettings:te}};var An=()=>{let o=useRecoilValue(H),e=useRecoilValue(Q);return {threadId:useRecoilValue(X),messages:o,firstInteraction:e}};var Rn=()=>{let o=useContext(B),e=useRecoilValue(ne),[t,s]=useRecoilState(z),n=useSetRecoilState(me),r=useSetRecoilState(pe),a=useResetRecoilState(O),i=useSetRecoilState(O),d=useSetRecoilState(Q),f=useSetRecoilState(K),l=useSetRecoilState(nt),p=useRecoilValue(he),k=useRecoilValue(de),m=useSetRecoilState(H),g=useSetRecoilState(G),y=useSetRecoilState(ge),F=useSetRecoilState(Xe),L=useSetRecoilState(ye),q=useSetRecoilState(J),b=useSetRecoilState(Y),oe=useSetRecoilState(W),Ce=useSetRecoilState(V),xe=useSetRecoilState(fe),[j,ae]=useRecoilState(Qe),te=useRecoilValue(le),be=useSetRecoilState(Ye),[ve,I]=useRecoilState(X);useEffect(()=>{t?.socket&&(t.socket.auth.threadId=ve||"");},[ve]);let x=useCallback(({transports:gt,userEnv:yt})=>{let{protocol:St,host:wt,pathname:Ee}=new URL(o.httpEndpoint),kt=`${St}//${wt}`,It=Ee&&Ee!=="/"?`${Ee}/ws/socket.io`:"/ws/socket.io",h=Kt(kt,{path:It,withCredentials:!0,transports:gt,auth:{clientType:o.type,sessionId:e,threadId:te||"",userEnv:JSON.stringify(yt),chatProfile:j?encodeURIComponent(j):""}});s(c=>(c?.socket?.removeAllListeners(),c?.socket?.close(),{socket:h})),h.on("connect",()=>{h.emit("connection_successful"),s(c=>({...c,error:!1})),l(c=>c.map(u=>((u.clientType==="sse"?o.connectSseMCP(e,u.name,u.url):o.connectStdioMCP(e,u.name,u.command)).then(async({success:A,mcp:v})=>{l(Pe=>Pe.map(ie=>ie.name===v.name?{...ie,status:A?"connected":"failed",tools:v?v.tools:ie.tools}:ie));}).catch(()=>{l(A=>A.map(v=>v.name===u.name?{...v,status:"failed"}:v));}),{...u,status:"connecting"})));}),h.on("connect_error",c=>{s(u=>({...u,error:!0}));}),h.on("task_start",()=>{f(!0);}),h.on("task_end",()=>{f(!1);}),h.on("reload",()=>{h.emit("clear_session"),window.location.reload();}),h.on("audio_connection",async c=>{if(c==="on"){let u=!0,w=Date.now(),A="pcm16";await k.begin(),await p.connect(),await k.record(async v=>{let Pe=Date.now()-w;h.emit("audio_chunk",{isStart:u,mimeType:A,elapsedTime:Pe,data:v.mono}),u=!1;}),p.onStop=()=>n(!1);}else await k.end(),await p.interrupt();r(c);}),h.on("audio_chunk",c=>{p.add16BitPCM(c.data,c.track),n(!0);}),h.on("audio_interrupt",()=>{p.interrupt();}),h.on("resume_thread",c=>{let u=[];for(let A of c.steps)u=R(u,A);c.metadata?.chat_profile&&ae(c.metadata?.chat_profile),c.metadata?.chat_settings&&i(c.metadata?.chat_settings),m(u);let w=c.elements||[];b(w.filter(A=>A.type==="tasklist")),q(w.filter(A=>["avatar","tasklist"].indexOf(A.type)===-1));}),h.on("resume_thread_error",c=>{be(c);}),h.on("new_message",c=>{m(u=>R(u,c));}),h.on("first_interaction",c=>{d(c.interaction),I(c.thread_id);}),h.on("update_message",c=>{m(u=>ke(u,c.id,c));}),h.on("delete_message",c=>{m(u=>Re(u,c.id));}),h.on("stream_start",c=>{m(u=>R(u,c));}),h.on("stream_token",({id:c,token:u,isSequence:w,isInput:A})=>{m(v=>Fe(v,c,u,w,A));}),h.on("ask",({msg:c,spec:u},w)=>{g({spec:u,callback:w,parentId:c.parentId}),m(A=>R(A,c)),f(!1);}),h.on("ask_timeout",()=>{g(void 0),f(!1);}),h.on("clear_ask",()=>{g(void 0);}),h.on("call_fn",({name:c,args:u},w)=>{y({name:c,args:u,callback:w});}),h.on("clear_call_fn",()=>{y(void 0);}),h.on("call_fn_timeout",()=>{y(void 0);}),h.on("chat_settings",c=>{Ce(c),a();}),h.on("set_commands",c=>{F(c);}),h.on("set_sidebar_title",c=>{L(u=>({title:c,elements:u?.elements||[]}));}),h.on("set_sidebar_elements",c=>{c.length?(c.forEach(u=>{!u.url&&u.chainlitKey&&(u.url=o.getElementUrl(u.chainlitKey,e));}),L(u=>({title:u?.title||"",elements:c}))):L(void 0);}),h.on("element",c=>{!c.url&&c.chainlitKey&&(c.url=o.getElementUrl(c.chainlitKey,e)),c.type==="tasklist"?b(u=>{let w=u.findIndex(A=>A.id===c.id);return w===-1?[...u,c]:[...u.slice(0,w),c,...u.slice(w+1)]}):q(u=>{let w=u.findIndex(A=>A.id===c.id);return w===-1?[...u,c]:[...u.slice(0,w),c,...u.slice(w+1)]});}),h.on("remove_element",c=>{q(u=>u.filter(w=>w.id!==c.id)),b(u=>u.filter(w=>w.id!==c.id));}),h.on("action",c=>{oe(u=>[...u,c]);}),h.on("remove_action",c=>{oe(u=>{let w=u.findIndex(A=>A.id===c.id);return w===-1?u:[...u.slice(0,w),...u.slice(w+1)]});}),h.on("token_usage",c=>{xe(u=>u+c);}),h.on("window_message",c=>{window.parent&&window.parent.postMessage(c,"*");}),h.on("toast",c=>{if(!c.message){console.warn("No message received for toast.");return}switch(c.type){case"info":toast.info(c.message);break;case"error":toast.error(c.message);break;case"success":toast.success(c.message);break;case"warning":toast.warning(c.message);break;default:toast(c.message);break}});},[s,e,te,j]),se=useCallback(debounce(x,200),[x]),Te=useCallback(()=>{t?.socket&&(t.socket.removeAllListeners(),t.socket.close());},[t]);return {connect:se,disconnect:Te,session:t,sessionId:e,chatProfile:j,idToResume:te,setChatProfile:ae}};var qn=()=>{let[o,e]=useRecoilState(pe),t=useRecoilValue(de),s=useRecoilValue(he),n=useRecoilValue(me),{startAudioStream:r,endAudioStream:a}=pt(),i=useCallback(async()=>{e("connecting"),await r();},[r]),d=useCallback(async()=>{e("off"),await t.end(),await s.interrupt(),await a();},[a,t,s]);return {startConversation:i,endConversation:d,audioConnection:o,isAiSpeaking:n,wavRecorder:t,wavStreamPlayer:s}};var zn=()=>{let[o,e]=useRecoilState(et),{isAuthenticated:t}=ht(),s=navigator.language||"en-US",{data:n,error:r,isLoading:a}=Z(!o&&t?`/project/settings?language=${s}`:null);return useEffect(()=>{n&&e(n);},[n,e]),{config:o,error:r,isLoading:a,language:s}};var je=new WeakMap,Qt=(o,e,t=!1,s=!1)=>{let n,r,a;if(s&&(r=e.toString(),a=t.toString(),n=je.has(o)?je.get(o):{},je.set(o,n),n[r]=n[r]||{},n[r][a]))return n[r][a];let i=o.length,d=new Array(e);if(e<=i){d.fill(0);let f=new Array(e).fill(0);for(let l=0;l<i;l++){let p=Math.floor(l*(e/i));t?d[p]=Math.max(d[p],Math.abs(o[l])):d[p]+=Math.abs(o[l]),f[p]++;}if(!t)for(let l=0;l<d.length;l++)d[l]=d[l]/f[l];}else for(let f=0;f<e;f++){let l=f*(i-1)/(e-1),p=Math.floor(l),k=Math.ceil(l),m=l-p;k>=i?d[f]=o[i-1]:d[f]=o[p]*(1-m)+o[k]*m;}return s&&(n[r][a]=d),d},Xt={drawBars:(o,e,t,s,n,r=0,a=0,i=0,d=!1)=>{r=Math.floor(Math.min(r,(t-i)/(Math.max(a,1)+i))),r||(r=Math.floor((t-i)/(Math.max(a,1)+i))),a||(a=(t-i)/r-i);let f=Qt(e,r,!0);for(let l=0;l<r;l++){let p=Math.abs(f[l]),k=Math.max(1,p*s),m=i+l*(a+i),g=d?(s-k)/2:s-k,y=Math.min(a/2,k/2);o.fillStyle=n,o.beginPath(),o.moveTo(m+y,g),o.lineTo(m+a-y,g),o.arcTo(m+a,g,m+a,g+y,y),o.lineTo(m+a,g+k-y),o.arcTo(m+a,g+k,m+a-y,g+k,y),o.lineTo(m+y,g+k),o.arcTo(m,g+k,m,g+k-y,y),o.lineTo(m,g+y),o.arcTo(m,g,m+y,g,y),o.closePath(),o.fill();}}};
export { De as APIBase, ee as ChainlitAPI, B as ChainlitContext, Ie as ClientError, Xt as WavRenderer, W as actionState, R as addMessage, ot as addMessageToParent, G as askUserState, pe as audioConnectionState, tt as authState, ge as callFnState, Qe as chatProfileState, Me as chatSettingsDefaultValueSelector, V as chatSettingsInputsState, O as chatSettingsValueState, Xe as commandsState, et as configState, X as currentThreadIdState, fn as defaultChainlitContext, Re as deleteMessageById, J as elementState, Bt as fetcher, Q as firstUserInteraction, we as hasMessageById, me as isAiSpeakingState, Ms as isLastMessage, K as loadingState, nt as mcpState, H as messagesState, _s as nestMessages, Ye as resumeThreadErrorState, ne as sessionIdState, z as sessionState, ye as sideViewState, Y as tasklistState, st as threadHistoryState, le as threadIdToResumeState, fe as tokenCountState, ke as updateMessageById, Fe as updateMessageContentById, Z as useApi, qn as useAudio, ht as useAuth, Ts as useChatData, pt as useChatInteract, An as useChatMessages, Rn as useChatSession, zn as useConfig, Ze as userState, de as wavRecorderState, he as wavStreamPlayerState };
//# sourceMappingURL=out.js.map
//# sourceMappingURL=index.mjs.map