@holaboss/client 0.2.0-beta.0 → 0.2.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  'use client'
2
- var F=Object.defineProperty;var Y=Object.getOwnPropertyDescriptor;var Q=Object.getOwnPropertyNames;var X=Object.prototype.hasOwnProperty;var Z=(e,t)=>{for(var n in t)F(e,n,{get:t[n],enumerable:!0})},ee=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of Q(t))!X.call(e,a)&&a!==n&&F(e,a,{get:()=>t[a],enumerable:!(s=Y(t,a))||s.enumerable});return e};var te=e=>ee(F({},"__esModule",{value:!0}),e);var de={};Z(de,{Chat:()=>B,HolaProvider:()=>J,createApiTransport:()=>j,createHolaClient:()=>G,createPortalData:()=>K,createWidgetTransport:()=>O,mergeMessage:()=>D,textDeltaOf:()=>P,thinkingDeltaOf:()=>I,toolEventOf:()=>R,useArtifactUrl:()=>k,useChat:()=>A,useHolaClient:()=>M,useThread:()=>V});module.exports=te(de);var L=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="message_update"?t.assistantMessageEvent??null:null},P=e=>{let t=L(e);return t?.type==="text_delta"&&typeof t.delta=="string"?t.delta:null},I=e=>{let t=L(e);return t?.type==="thinking_delta"&&typeof t.delta=="string"?t.delta:null},R=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="tool_execution_start"&&t.toolCallId?{phase:"start",id:t.toolCallId,name:t.toolName}:t.type==="tool_execution_end"&&t.toolCallId?{phase:"end",id:t.toolCallId,isError:t.isError}:null};var re=/^ /,T=e=>{if(e&&typeof e=="object"){let t=e,n=typeof t.error=="string"?t.error:"request_failed";return typeof t.retryable=="boolean"?{error:n,retryable:t.retryable}:{error:n}}return{error:"request_failed"}},oe=e=>{let t="message",n=[];for(let s of e.split(`
3
- `))s.startsWith(":")||(s.startsWith("event:")?t=s.slice(6).trim():s.startsWith("data:")&&n.push(s.slice(5).replace(re,"")));return n.length>0?{event:t,data:n.join(`
4
- `)}:null},se=(e,t,n)=>{let s;try{s=JSON.parse(e.data)}catch{return}if(e.event==="session"){let a=s.sessionId;a&&(n(a),t.onSession?.(a));return}if(e.event==="turn_event"){t.onEvent?.(s);let a=P(s);a&&t.onText?.(a);let p=I(s);p&&t.onThinking?.(p);let r=R(s);r&&t.onTool?.(r);return}if(e.event==="chat_completed"){let a=s;n(a.sessionId),t.onComplete?.(a);return}e.event==="chat_error"&&t.onError?.(T(s))},C=async(e,t)=>{let n=await fetch(e,{headers:t});if(!n.ok)throw new Error(`hola: request failed (${n.status})`);return await n.json()},W=async e=>{let t=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body});if(!t.ok)throw new Error(`hola: message failed (${t.status})`);return await t.json()},N=async(e,t,n,s)=>{let a=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body,signal:s});if(!(a.ok&&a.body)){t.onError?.({error:`stream_failed_${a.status}`});return}let p=a.body.getReader(),r=new TextDecoder,o="",d=()=>{let l=o.indexOf(`
2
+ var F=Object.defineProperty;var Y=Object.getOwnPropertyDescriptor;var Q=Object.getOwnPropertyNames;var X=Object.prototype.hasOwnProperty;var Z=(e,t)=>{for(var n in t)F(e,n,{get:t[n],enumerable:!0})},ee=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of Q(t))!X.call(e,a)&&a!==n&&F(e,a,{get:()=>t[a],enumerable:!(o=Y(t,a))||o.enumerable});return e};var te=e=>ee(F({},"__esModule",{value:!0}),e);var de={};Z(de,{Chat:()=>B,HolaProvider:()=>J,createApiTransport:()=>j,createHolaClient:()=>G,createPortalData:()=>K,createWidgetTransport:()=>O,mergeMessage:()=>D,textDeltaOf:()=>P,thinkingDeltaOf:()=>I,toolEventOf:()=>R,useArtifactUrl:()=>k,useChat:()=>A,useHolaClient:()=>M,useThread:()=>V});module.exports=te(de);var L=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="message_update"?t.assistantMessageEvent??null:null},P=e=>{let t=L(e);return t?.type==="text_delta"&&typeof t.delta=="string"?t.delta:null},I=e=>{let t=L(e);return t?.type==="thinking_delta"&&typeof t.delta=="string"?t.delta:null},R=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="tool_execution_start"&&t.toolCallId?{phase:"start",id:t.toolCallId,name:t.toolName}:t.type==="tool_execution_end"&&t.toolCallId?{phase:"end",id:t.toolCallId,isError:t.isError}:null};var re=/^ /,C=e=>{if(e&&typeof e=="object"){let t=e,n=typeof t.error=="string"?t.error:"request_failed";return typeof t.retryable=="boolean"?{error:n,retryable:t.retryable}:{error:n}}return{error:"request_failed"}},oe=e=>{let t="message",n=[];for(let o of e.split(`
3
+ `))o.startsWith(":")||(o.startsWith("event:")?t=o.slice(6).trim():o.startsWith("data:")&&n.push(o.slice(5).replace(re,"")));return n.length>0?{event:t,data:n.join(`
4
+ `)}:null},se=(e,t,n)=>{let o;try{o=JSON.parse(e.data)}catch{return}if(e.event==="session"){let a=o.sessionId;a&&(n(a),t.onSession?.(a));return}if(e.event==="turn_event"){t.onEvent?.(o);let a=P(o);a&&t.onText?.(a);let p=I(o);p&&t.onThinking?.(p);let r=R(o);r&&t.onTool?.(r);return}if(e.event==="chat_completed"){let a=o;n(a.sessionId),t.onComplete?.(a);return}e.event==="chat_error"&&t.onError?.(C(o))},H=async(e,t)=>{let n=await fetch(e,{headers:t});if(!n.ok)throw new Error(`hola: request failed (${n.status})`);return await n.json()},W=async e=>{let t=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body});if(!t.ok)throw new Error(`hola: message failed (${t.status})`);return await t.json()},N=async(e,t,n,o)=>{let a=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body,signal:o});if(!(a.ok&&a.body)){t.onError?.({error:`stream_failed_${a.status}`});return}let p=a.body.getReader(),r=new TextDecoder,s="",d=()=>{let l=s.indexOf(`
5
5
 
6
- `);for(;l!==-1;){let f=o.slice(0,l);o=o.slice(l+2);let u=oe(f);u&&se(u,t,n),l=o.indexOf(`
6
+ `);for(;l!==-1;){let f=s.slice(0,l);s=s.slice(l+2);let u=oe(f);u&&se(u,t,n),l=s.indexOf(`
7
7
 
8
- `)}},i=async()=>{let l=await p.read();if(!l.done)return o+=r.decode(l.value,{stream:!0}),d(),i()};await i()};var ne=/\/+$/,E="/api/v1/end-user",j=e=>{let t=e.baseUrl.replace(ne,""),n=()=>typeof e.token=="function"?e.token():e.token,s=async()=>({"content-type":"application/json",authorization:`Bearer ${await n()}`}),a=async p=>{let r=await fetch(`${t}${E}/chat`,{method:"POST",headers:await s(),body:JSON.stringify({message:p})});if(!r.ok)throw new Error(`hola: message failed (${r.status})`);return{reply:(await r.json()).reply??"",sessionId:"",artifacts:[]}};return{sessionId:()=>"",getInfo:async()=>C(`${t}${E}/chat/info`,await s()),sendMessage:a,streamMessage:async(p,r)=>{try{let o=await a(p);r.onText?.(o.reply),r.onComplete?.(o)}catch(o){r.onError?.(T(o))}},subscribe:(p,r)=>{let o=r?.since??"0",d=!1,i,l=r?.intervalMs??3e3,f=async()=>{try{let c=await C(`${t}${E}/chat/thread?since=${encodeURIComponent(o)}`,await s());for(let y of c.messages)p.onMessage(y);o=c.cursor}catch(c){p.onError?.(T(c))}d||(i=setTimeout(f,l))},u=()=>{d=!0,i&&clearTimeout(i)};return r?.signal?.addEventListener("abort",u),i=setTimeout(f,0),u},requestHuman:async()=>{await fetch(`${t}${E}/chat/request-human`,{method:"POST",headers:await s(),body:"{}"})}}};var S=require("react"),k=(e,t)=>{let[n,s]=(0,S.useState)("");return(0,S.useEffect)(()=>{if(!e){s("");return}let a=Uint8Array.from(atob(e),r=>r.charCodeAt(0)),p=URL.createObjectURL(new Blob([a],{type:t}));return s(p),()=>URL.revokeObjectURL(p)},[e,t]),n};var U=require("react");var $=require("react"),q=require("react/jsx-runtime"),z=(0,$.createContext)(null),J=({client:e,children:t})=>(0,q.jsx)(z.Provider,{value:e,children:t}),M=()=>{let e=(0,$.useContext)(z);if(!e)throw new Error("useHolaClient must be used within <HolaProvider>");return e};var b=require("react"),A=e=>{let[t,n]=(0,b.useState)([]),[s,a]=(0,b.useState)(""),[p,r]=(0,b.useState)(!1),[o,d]=(0,b.useState)(null),i=(0,b.useRef)(0),l=(0,b.useCallback)(()=>{let u=i.current;return i.current+=1,u},[]);(0,b.useEffect)(()=>{let u=!0;return e.getInfo().then(c=>{u&&c.greeting&&n([{id:l(),role:"assistant",text:c.greeting}])}).catch(()=>{}),()=>{u=!1}},[e,l]);let f=(0,b.useCallback)(()=>{let u=s.trim();if(!u||p)return;a(""),d(null),r(!0);let c=l(),y=l();n(m=>[...m,{id:c,role:"user",text:u},{id:y,role:"assistant",text:"",streaming:!0}]);let g=m=>{n(x=>x.map(_=>_.id===y?m(_):_))};e.streamMessage(u,{onText:m=>g(x=>({...x,text:x.text+m})),onComplete:m=>{g(x=>({...x,text:m.reply||x.text,artifacts:m.artifacts,streaming:!1})),r(!1)},onError:m=>{g(x=>({...x,streaming:!1})),d(m.error),r(!1)}}).catch(m=>{g(x=>({...x,streaming:!1})),d(m instanceof Error?m.message:"stream_failed"),r(!1)})},[s,p,e,l]);return{messages:t,input:s,setInput:a,send:f,sending:p,error:o}};var h=require("react/jsx-runtime"),H={root:{display:"flex",flexDirection:"column",height:"100%",fontFamily:"system-ui, -apple-system, sans-serif",fontSize:14,color:"#111827"},log:{flex:1,overflowY:"auto",padding:12,display:"flex",flexDirection:"column",gap:8},user:{alignSelf:"flex-end",background:"#111827",color:"#ffffff",borderRadius:12,padding:"8px 12px",maxWidth:"80%",whiteSpace:"pre-wrap"},assistant:{alignSelf:"flex-start",background:"#f1f1f4",color:"#111827",borderRadius:12,padding:"8px 12px",maxWidth:"80%",whiteSpace:"pre-wrap"},artifacts:{display:"flex",flexDirection:"column",gap:6,marginTop:6},image:{maxHeight:220,borderRadius:8,border:"1px solid #e5e7eb"},link:{color:"#2563eb",textDecoration:"underline",wordBreak:"break-all"},error:{color:"#b91c1c",padding:"4px 12px",fontSize:13},form:{display:"flex",gap:8,borderTop:"1px solid #e5e7eb",padding:8},input:{flex:1,border:"1px solid #d1d5db",borderRadius:8,padding:"8px 10px",fontSize:14,outline:"none"},button:{border:"none",background:"#111827",color:"#ffffff",borderRadius:8,padding:"8px 14px",fontSize:14,cursor:"pointer"}},ae=({artifact:e})=>{let t=k(e.dataBase64??"",e.mimeType),n=e.url??t;return n?e.mimeType.startsWith("image/")?(0,h.jsx)("a",{href:n,rel:"noopener noreferrer",target:"_blank",children:(0,h.jsx)("img",{alt:e.filename,src:n,style:H.image})}):(0,h.jsx)("a",{download:e.filename,href:n,style:H.link,children:e.filename}):null},B=()=>{let e=M(),{messages:t,input:n,setInput:s,send:a,sending:p,error:r}=A(e),o=(0,U.useRef)(null);(0,U.useEffect)(()=>{let i=o.current;i&&(i.scrollTop=i.scrollHeight)},[t]);let d=i=>{i.preventDefault(),a()};return(0,h.jsxs)("div",{style:H.root,children:[(0,h.jsx)("div",{ref:o,style:H.log,children:t.map(i=>(0,h.jsxs)("div",{style:i.role==="user"?H.user:H.assistant,children:[i.text||(i.streaming?"\u2026":""),i.artifacts&&i.artifacts.length>0?(0,h.jsx)("div",{style:H.artifacts,children:i.artifacts.map(l=>(0,h.jsx)(ae,{artifact:l},l.filename))}):null]},i.id))}),r?(0,h.jsx)("div",{style:H.error,children:r}):null,(0,h.jsxs)("form",{onSubmit:d,style:H.form,children:[(0,h.jsx)("input",{"aria-label":"Message",onChange:i=>s(i.target.value),placeholder:"Type a message\u2026",style:H.input,value:n}),(0,h.jsx)("button",{disabled:p||n.trim().length===0,style:H.button,type:"submit",children:"Send"})]})]})};var ie=/\/+$/,O=e=>{let t=e.sessionId,n=e.baseUrl.replace(ie,""),s=r=>`${n}/endpoint/${encodeURIComponent(e.token)}${r}`,a={"content-type":"application/json"},p=(r,o)=>({url:s(r),headers:a,body:JSON.stringify({message:o,...t?{sessionId:t}:{},...e.identity?{externalUserId:e.identity.externalUserId,userHmac:e.identity.userHmac}:{}})});return{sessionId:()=>t,getInfo:()=>C(s("/config"),{}),sendMessage:async r=>{let o=await W(p("/message",r));return t=o.sessionId,o},streamMessage:(r,o,d)=>N(p("/message/stream",r),o,i=>{t=i},d),subscribe:(r,o)=>{let d=o?.since??"0",i=!1,l,f=o?.intervalMs??3e3,u=async()=>{let y=t;if(y)try{let g=await C(s(`/messages?session=${encodeURIComponent(y)}&since=${encodeURIComponent(d)}`),{});for(let m of g.messages)r.onMessage(m);d=g.cursor}catch(g){r.onError?.(T(g))}i||(l=setTimeout(u,f))},c=()=>{i=!0,l&&clearTimeout(l)};return o?.signal?.addEventListener("abort",c),l=setTimeout(u,0),c},requestHuman:async()=>{t&&await fetch(s("/request-human"),{method:"POST",headers:a,body:JSON.stringify({sessionId:t})})}}};var G=e=>"transport"in e?e.transport:O(e);var le=/\/+$/,v="/api/v1/end-user";function pe(e){let t="";for(let s=0;s<e.length;s+=32768)t+=String.fromCharCode(...e.subarray(s,s+32768));return btoa(t)}var K=e=>{let t=e.baseUrl.replace(le,""),n=()=>typeof e.token=="function"?e.token():e.token,s=async()=>({"content-type":"application/json",authorization:`Bearer ${await n()}`}),a=async(r,o)=>{try{let d=await fetch(`${t}${v}${r}`,{method:o.method,headers:await s(),...o.body===void 0?{}:{body:JSON.stringify(o.body)}});if(!d.ok){let i=await d.text().catch(()=>""),l=`${o.method} ${r} \u2192 ${String(d.status)}`;try{let f=JSON.parse(i);f.message&&(l=f.message)}catch{l=i?`${l}: ${i}`:l}throw T(new Error(l))}return await d.json()}catch(d){throw T(d)}},p=r=>`/tables/${encodeURIComponent(r)}`;return{listTables:async()=>(await C(`${t}${v}/tables`,await s())).tables,listRows:async(r,o)=>await C(`${t}${v}${p(r)}/rows?limit=${String(o??100)}`,await s()),insertRow:async(r,o)=>{let{rowIds:d}=await a(`${p(r)}/rows`,{method:"POST",body:{rows:[o]}}),i=d[0];if(!i)throw T(new Error("The row was not created."));return i},patchRow:async(r,o,d)=>(await a(`${p(r)}/rows/${encodeURIComponent(o)}`,{method:"PATCH",body:d})).updated,deleteRow:async(r,o)=>(await a(`/${encodeURIComponent(r)}/${encodeURIComponent(o)}`,{method:"DELETE"})).deleted,listFiles:async()=>(await C(`${t}${v}/tables/files/rows?limit=200`,await s())).rows.map(o=>({id:o.rowId,filename:String(o.data.filename??""),source:String(o.data.source??"client"),campaign:String(o.data.campaign??""),size:typeof o.data.size=="number"?o.data.size:0,createdAt:o.createdAt})),uploadFile:async(r,o)=>{let d=new Uint8Array(await r.arrayBuffer());return await a("/files",{method:"POST",body:{filename:r.name,mime:r.type||"application/octet-stream",data:pe(d),...o===void 0?{}:{message:o}}})},fileUrl:r=>`${t}${v}/files/${encodeURIComponent(r)}/raw`,deleteFile:async r=>(await a(`/files/${encodeURIComponent(r)}`,{method:"DELETE"})).deleted}};var w=require("react");function D(e,t){return e.some(s=>s.id===t.id)?e:[...t.author==="client"?e.filter(s=>!(s.pending&&s.author==="client"&&s.text===t.text)):e,t]}var V=(e,t)=>{let[n,s]=(0,w.useState)([]),[a,p]=(0,w.useState)(""),[r,o]=(0,w.useState)(!1),[d,i]=(0,w.useState)(null),l=(0,w.useRef)(0),f=t?.pollMs??2e3;(0,w.useEffect)(()=>{let c=!0;return e.getInfo().then(y=>{c&&y.greeting&&s(g=>g.length===0?[{id:"greeting",cursor:"",author:"agent",text:y.greeting}]:g)}).catch(()=>{}),()=>{c=!1}},[e]),(0,w.useEffect)(()=>e.subscribe?.({onMessage:c=>s(y=>D(y,c)),onError:c=>i(c.error)},{intervalMs:f}),[e,f]);let u=(0,w.useCallback)(()=>{let c=a.trim();if(!c||r)return;p(""),i(null),o(!0),l.current+=1;let y={id:`pending-${l.current}`,cursor:"",author:"client",text:c,pending:!0};s(g=>[...g,y]),e.sendMessage(c).then(()=>o(!1)).catch(g=>{i(g instanceof Error?g.message:"send_failed"),o(!1)})},[a,r,e]);return{messages:n,input:a,setInput:p,send:u,sending:r,error:d}};0&&(module.exports={Chat,HolaProvider,createApiTransport,createHolaClient,createPortalData,createWidgetTransport,mergeMessage,textDeltaOf,thinkingDeltaOf,toolEventOf,useArtifactUrl,useChat,useHolaClient,useThread});
8
+ `)}},i=async()=>{let l=await p.read();if(!l.done)return s+=r.decode(l.value,{stream:!0}),d(),i()};await i()};var ne=/\/+$/,E="/api/v1/end-user",j=e=>{let t=e.baseUrl.replace(ne,""),n=()=>typeof e.token=="function"?e.token():e.token,o=async()=>({"content-type":"application/json",authorization:`Bearer ${await n()}`}),a=async p=>{let r=await fetch(`${t}${E}/chat`,{method:"POST",headers:await o(),body:JSON.stringify({message:p})});if(!r.ok)throw new Error(`hola: message failed (${r.status})`);return{reply:(await r.json()).reply??"",sessionId:"",artifacts:[]}};return{sessionId:()=>"",getInfo:async()=>H(`${t}${E}/chat/info`,await o()),sendMessage:a,streamMessage:async(p,r)=>{try{let s=await a(p);r.onText?.(s.reply),r.onComplete?.(s)}catch(s){r.onError?.(C(s))}},subscribe:(p,r)=>{let s=r?.since??"0",d=!1,i,l=r?.intervalMs??3e3,f=async()=>{try{let c=await H(`${t}${E}/chat/thread?since=${encodeURIComponent(s)}`,await o());for(let y of c.messages)p.onMessage(y);s=c.cursor}catch(c){p.onError?.(C(c))}d||(i=setTimeout(f,l))},u=()=>{d=!0,i&&clearTimeout(i)};return r?.signal?.addEventListener("abort",u),i=setTimeout(f,0),u},requestHuman:async()=>{await fetch(`${t}${E}/chat/request-human`,{method:"POST",headers:await o(),body:"{}"})}}};var S=require("react"),k=(e,t)=>{let[n,o]=(0,S.useState)("");return(0,S.useEffect)(()=>{if(!e){o("");return}let a=Uint8Array.from(atob(e),r=>r.charCodeAt(0)),p=URL.createObjectURL(new Blob([a],{type:t}));return o(p),()=>URL.revokeObjectURL(p)},[e,t]),n};var U=require("react");var $=require("react"),q=require("react/jsx-runtime"),z=(0,$.createContext)(null),J=({client:e,children:t})=>(0,q.jsx)(z.Provider,{value:e,children:t}),M=()=>{let e=(0,$.useContext)(z);if(!e)throw new Error("useHolaClient must be used within <HolaProvider>");return e};var b=require("react"),A=e=>{let[t,n]=(0,b.useState)([]),[o,a]=(0,b.useState)(""),[p,r]=(0,b.useState)(!1),[s,d]=(0,b.useState)(null),i=(0,b.useRef)(0),l=(0,b.useCallback)(()=>{let u=i.current;return i.current+=1,u},[]);(0,b.useEffect)(()=>{let u=!0;return e.getInfo().then(c=>{u&&c.greeting&&n([{id:l(),role:"assistant",text:c.greeting}])}).catch(()=>{}),()=>{u=!1}},[e,l]);let f=(0,b.useCallback)(()=>{let u=o.trim();if(!u||p)return;a(""),d(null),r(!0);let c=l(),y=l();n(m=>[...m,{id:c,role:"user",text:u},{id:y,role:"assistant",text:"",streaming:!0}]);let g=m=>{n(x=>x.map(_=>_.id===y?m(_):_))};e.streamMessage(u,{onText:m=>g(x=>({...x,text:x.text+m})),onComplete:m=>{g(x=>({...x,text:m.reply||x.text,artifacts:m.artifacts,streaming:!1})),r(!1)},onError:m=>{g(x=>({...x,streaming:!1})),d(m.error),r(!1)}}).catch(m=>{g(x=>({...x,streaming:!1})),d(m instanceof Error?m.message:"stream_failed"),r(!1)})},[o,p,e,l]);return{messages:t,input:o,setInput:a,send:f,sending:p,error:s}};var h=require("react/jsx-runtime"),T={root:{display:"flex",flexDirection:"column",height:"100%",fontFamily:"system-ui, -apple-system, sans-serif",fontSize:14,color:"#111827"},log:{flex:1,overflowY:"auto",padding:12,display:"flex",flexDirection:"column",gap:8},user:{alignSelf:"flex-end",background:"#111827",color:"#ffffff",borderRadius:12,padding:"8px 12px",maxWidth:"80%",whiteSpace:"pre-wrap"},assistant:{alignSelf:"flex-start",background:"#f1f1f4",color:"#111827",borderRadius:12,padding:"8px 12px",maxWidth:"80%",whiteSpace:"pre-wrap"},artifacts:{display:"flex",flexDirection:"column",gap:6,marginTop:6},image:{maxHeight:220,borderRadius:8,border:"1px solid #e5e7eb"},link:{color:"#2563eb",textDecoration:"underline",wordBreak:"break-all"},error:{color:"#b91c1c",padding:"4px 12px",fontSize:13},form:{display:"flex",gap:8,borderTop:"1px solid #e5e7eb",padding:8},input:{flex:1,border:"1px solid #d1d5db",borderRadius:8,padding:"8px 10px",fontSize:14,outline:"none"},button:{border:"none",background:"#111827",color:"#ffffff",borderRadius:8,padding:"8px 14px",fontSize:14,cursor:"pointer"}},ae=({artifact:e})=>{let t=k(e.dataBase64??"",e.mimeType),n=e.url??t;return n?e.mimeType.startsWith("image/")?(0,h.jsx)("a",{href:n,rel:"noopener noreferrer",target:"_blank",children:(0,h.jsx)("img",{alt:e.filename,src:n,style:T.image})}):(0,h.jsx)("a",{download:e.filename,href:n,style:T.link,children:e.filename}):null},B=()=>{let e=M(),{messages:t,input:n,setInput:o,send:a,sending:p,error:r}=A(e),s=(0,U.useRef)(null);(0,U.useEffect)(()=>{let i=s.current;i&&(i.scrollTop=i.scrollHeight)},[t]);let d=i=>{i.preventDefault(),a()};return(0,h.jsxs)("div",{style:T.root,children:[(0,h.jsx)("div",{ref:s,style:T.log,children:t.map(i=>(0,h.jsxs)("div",{style:i.role==="user"?T.user:T.assistant,children:[i.text||(i.streaming?"\u2026":""),i.artifacts&&i.artifacts.length>0?(0,h.jsx)("div",{style:T.artifacts,children:i.artifacts.map(l=>(0,h.jsx)(ae,{artifact:l},l.filename))}):null]},i.id))}),r?(0,h.jsx)("div",{style:T.error,children:r}):null,(0,h.jsxs)("form",{onSubmit:d,style:T.form,children:[(0,h.jsx)("input",{"aria-label":"Message",onChange:i=>o(i.target.value),placeholder:"Type a message\u2026",style:T.input,value:n}),(0,h.jsx)("button",{disabled:p||n.trim().length===0,style:T.button,type:"submit",children:"Send"})]})]})};var ie=/\/+$/,O=e=>{let t=e.sessionId,n=e.baseUrl.replace(ie,""),o=r=>`${n}/endpoint/${encodeURIComponent(e.token)}${r}`,a={"content-type":"application/json"},p=(r,s)=>({url:o(r),headers:a,body:JSON.stringify({message:s,...t?{sessionId:t}:{},...e.identity?{externalUserId:e.identity.externalUserId,userHmac:e.identity.userHmac}:{}})});return{sessionId:()=>t,getInfo:()=>H(o("/config"),{}),sendMessage:async r=>{let s=await W(p("/message",r));return t=s.sessionId,s},streamMessage:(r,s,d)=>N(p("/message/stream",r),s,i=>{t=i},d),subscribe:(r,s)=>{let d=s?.since??"0",i=!1,l,f=s?.intervalMs??3e3,u=async()=>{let y=t;if(y)try{let g=await H(o(`/messages?session=${encodeURIComponent(y)}&since=${encodeURIComponent(d)}`),{});for(let m of g.messages)r.onMessage(m);d=g.cursor}catch(g){r.onError?.(C(g))}i||(l=setTimeout(u,f))},c=()=>{i=!0,l&&clearTimeout(l)};return s?.signal?.addEventListener("abort",c),l=setTimeout(u,0),c},requestHuman:async()=>{t&&await fetch(o("/request-human"),{method:"POST",headers:a,body:JSON.stringify({sessionId:t})})}}};var G=e=>"transport"in e?e.transport:O(e);var le=/\/+$/,v="/api/v1/end-user";function pe(e){let t="";for(let o=0;o<e.length;o+=32768)t+=String.fromCharCode(...e.subarray(o,o+32768));return btoa(t)}var K=e=>{let t=e.baseUrl.replace(le,""),n=()=>typeof e.token=="function"?e.token():e.token,o=async()=>({"content-type":"application/json",authorization:`Bearer ${await n()}`}),a=async(r,s)=>{try{let d=await fetch(`${t}${v}${r}`,{method:s.method,headers:await o(),...s.body===void 0?{}:{body:JSON.stringify(s.body)}});if(!d.ok){let i=await d.text().catch(()=>""),l=`${s.method} ${r} \u2192 ${String(d.status)}`;try{let f=JSON.parse(i);f.message&&(l=f.message)}catch{l=i?`${l}: ${i}`:l}throw C(new Error(l))}return await d.json()}catch(d){throw C(d)}},p=r=>`/tables/${encodeURIComponent(r)}`;return{listTables:async()=>(await H(`${t}${v}/tables`,await o())).tables,listRows:async(r,s)=>await H(`${t}${v}${p(r)}/rows?limit=${String(s??100)}`,await o()),insertRow:async(r,s)=>{let{rowIds:d}=await a(`${p(r)}/rows`,{method:"POST",body:{rows:[s]}}),i=d[0];if(!i)throw C(new Error("The row was not created."));return i},patchRow:async(r,s,d)=>(await a(`${p(r)}/rows/${encodeURIComponent(s)}`,{method:"PATCH",body:d})).updated,deleteRow:async(r,s)=>(await a(`/${encodeURIComponent(r)}/${encodeURIComponent(s)}`,{method:"DELETE"})).deleted,listFiles:async()=>(await H(`${t}${v}/tables/files/rows?limit=200`,await o())).rows.map(s=>({id:s.rowId,filename:String(s.data.filename??""),source:String(s.data.source??"client"),campaign:String(s.data.campaign??""),size:typeof s.data.size=="number"?s.data.size:0,createdAt:s.createdAt})),uploadFile:async(r,s)=>{let d=new Uint8Array(await r.arrayBuffer());return await a("/files",{method:"POST",body:{filename:r.name,mime:r.type||"application/octet-stream",data:pe(d),...s===void 0?{}:{message:s}}})},fileLink:async r=>await H(`${t}${v}/files/${encodeURIComponent(r)}/url`,await o()),deleteFile:async r=>(await a(`/files/${encodeURIComponent(r)}`,{method:"DELETE"})).deleted}};var w=require("react");function D(e,t){return e.some(o=>o.id===t.id)?e:[...t.author==="client"?e.filter(o=>!(o.pending&&o.author==="client"&&o.text===t.text)):e,t]}var V=(e,t)=>{let[n,o]=(0,w.useState)([]),[a,p]=(0,w.useState)(""),[r,s]=(0,w.useState)(!1),[d,i]=(0,w.useState)(null),l=(0,w.useRef)(0),f=t?.pollMs??2e3;(0,w.useEffect)(()=>{let c=!0;return e.getInfo().then(y=>{c&&y.greeting&&o(g=>g.length===0?[{id:"greeting",cursor:"",author:"agent",text:y.greeting}]:g)}).catch(()=>{}),()=>{c=!1}},[e]),(0,w.useEffect)(()=>e.subscribe?.({onMessage:c=>o(y=>D(y,c)),onError:c=>i(c.error)},{intervalMs:f}),[e,f]);let u=(0,w.useCallback)(()=>{let c=a.trim();if(!c||r)return;p(""),i(null),s(!0),l.current+=1;let y={id:`pending-${l.current}`,cursor:"",author:"client",text:c,pending:!0};o(g=>[...g,y]),e.sendMessage(c).then(()=>s(!1)).catch(g=>{i(g instanceof Error?g.message:"send_failed"),s(!1)})},[a,r,e]);return{messages:n,input:a,setInput:p,send:u,sending:r,error:d}};0&&(module.exports={Chat,HolaProvider,createApiTransport,createHolaClient,createPortalData,createWidgetTransport,mergeMessage,textDeltaOf,thinkingDeltaOf,toolEventOf,useArtifactUrl,useChat,useHolaClient,useThread});
package/dist/index.d.cts CHANGED
@@ -222,8 +222,18 @@ type PortalData = {
222
222
  uploadFile(file: File, message?: string): Promise<{
223
223
  rowId: string;
224
224
  }>;
225
- /** A URL to open or download. It redirects to a signed one. */
226
- fileUrl(rowId: string): string;
225
+ /**
226
+ * A link the browser can actually follow.
227
+ *
228
+ * Not a plain URL string: the download route needs the customer's token, and
229
+ * navigation from an `<a href>` carries no Authorization header — so a direct
230
+ * link is a guaranteed 401. This fetches the signed URL with the token, and
231
+ * what comes back needs no header of its own.
232
+ */
233
+ fileLink(rowId: string): Promise<{
234
+ url: string;
235
+ filename: string;
236
+ }>;
227
237
  /** Only files this customer sent, and only before they are filed. */
228
238
  deleteFile(rowId: string): Promise<number>;
229
239
  };
package/dist/index.d.ts CHANGED
@@ -222,8 +222,18 @@ type PortalData = {
222
222
  uploadFile(file: File, message?: string): Promise<{
223
223
  rowId: string;
224
224
  }>;
225
- /** A URL to open or download. It redirects to a signed one. */
226
- fileUrl(rowId: string): string;
225
+ /**
226
+ * A link the browser can actually follow.
227
+ *
228
+ * Not a plain URL string: the download route needs the customer's token, and
229
+ * navigation from an `<a href>` carries no Authorization header — so a direct
230
+ * link is a guaranteed 401. This fetches the signed URL with the token, and
231
+ * what comes back needs no header of its own.
232
+ */
233
+ fileLink(rowId: string): Promise<{
234
+ url: string;
235
+ filename: string;
236
+ }>;
227
237
  /** Only files this customer sent, and only before they are filed. */
228
238
  deleteFile(rowId: string): Promise<number>;
229
239
  };
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  'use client'
2
- var O=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="message_update"?t.assistantMessageEvent??null:null},R=e=>{let t=O(e);return t?.type==="text_delta"&&typeof t.delta=="string"?t.delta:null},E=e=>{let t=O(e);return t?.type==="thinking_delta"&&typeof t.delta=="string"?t.delta:null},S=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="tool_execution_start"&&t.toolCallId?{phase:"start",id:t.toolCallId,name:t.toolName}:t.type==="tool_execution_end"&&t.toolCallId?{phase:"end",id:t.toolCallId,isError:t.isError}:null};var j=/^ /,w=e=>{if(e&&typeof e=="object"){let t=e,a=typeof t.error=="string"?t.error:"request_failed";return typeof t.retryable=="boolean"?{error:a,retryable:t.retryable}:{error:a}}return{error:"request_failed"}},z=e=>{let t="message",a=[];for(let s of e.split(`
2
+ var O=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="message_update"?t.assistantMessageEvent??null:null},R=e=>{let t=O(e);return t?.type==="text_delta"&&typeof t.delta=="string"?t.delta:null},E=e=>{let t=O(e);return t?.type==="thinking_delta"&&typeof t.delta=="string"?t.delta:null},S=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="tool_execution_start"&&t.toolCallId?{phase:"start",id:t.toolCallId,name:t.toolName}:t.type==="tool_execution_end"&&t.toolCallId?{phase:"end",id:t.toolCallId,isError:t.isError}:null};var j=/^ /,x=e=>{if(e&&typeof e=="object"){let t=e,a=typeof t.error=="string"?t.error:"request_failed";return typeof t.retryable=="boolean"?{error:a,retryable:t.retryable}:{error:a}}return{error:"request_failed"}},z=e=>{let t="message",a=[];for(let s of e.split(`
3
3
  `))s.startsWith(":")||(s.startsWith("event:")?t=s.slice(6).trim():s.startsWith("data:")&&a.push(s.slice(5).replace(j,"")));return a.length>0?{event:t,data:a.join(`
4
- `)}:null},J=(e,t,a)=>{let s;try{s=JSON.parse(e.data)}catch{return}if(e.event==="session"){let i=s.sessionId;i&&(a(i),t.onSession?.(i));return}if(e.event==="turn_event"){t.onEvent?.(s);let i=R(s);i&&t.onText?.(i);let p=E(s);p&&t.onThinking?.(p);let r=S(s);r&&t.onTool?.(r);return}if(e.event==="chat_completed"){let i=s;a(i.sessionId),t.onComplete?.(i);return}e.event==="chat_error"&&t.onError?.(w(s))},x=async(e,t)=>{let a=await fetch(e,{headers:t});if(!a.ok)throw new Error(`hola: request failed (${a.status})`);return await a.json()},_=async e=>{let t=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body});if(!t.ok)throw new Error(`hola: message failed (${t.status})`);return await t.json()},F=async(e,t,a,s)=>{let i=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body,signal:s});if(!(i.ok&&i.body)){t.onError?.({error:`stream_failed_${i.status}`});return}let p=i.body.getReader(),r=new TextDecoder,o="",d=()=>{let l=o.indexOf(`
4
+ `)}:null},J=(e,t,a)=>{let s;try{s=JSON.parse(e.data)}catch{return}if(e.event==="session"){let i=s.sessionId;i&&(a(i),t.onSession?.(i));return}if(e.event==="turn_event"){t.onEvent?.(s);let i=R(s);i&&t.onText?.(i);let p=E(s);p&&t.onThinking?.(p);let r=S(s);r&&t.onTool?.(r);return}if(e.event==="chat_completed"){let i=s;a(i.sessionId),t.onComplete?.(i);return}e.event==="chat_error"&&t.onError?.(x(s))},b=async(e,t)=>{let a=await fetch(e,{headers:t});if(!a.ok)throw new Error(`hola: request failed (${a.status})`);return await a.json()},_=async e=>{let t=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body});if(!t.ok)throw new Error(`hola: message failed (${t.status})`);return await t.json()},F=async(e,t,a,s)=>{let i=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body,signal:s});if(!(i.ok&&i.body)){t.onError?.({error:`stream_failed_${i.status}`});return}let p=i.body.getReader(),r=new TextDecoder,o="",d=()=>{let l=o.indexOf(`
5
5
 
6
6
  `);for(;l!==-1;){let f=o.slice(0,l);o=o.slice(l+2);let u=z(f);u&&J(u,t,a),l=o.indexOf(`
7
7
 
8
- `)}},n=async()=>{let l=await p.read();if(!l.done)return o+=r.decode(l.value,{stream:!0}),d(),n()};await n()};var q=/\/+$/,C="/api/v1/end-user",B=e=>{let t=e.baseUrl.replace(q,""),a=()=>typeof e.token=="function"?e.token():e.token,s=async()=>({"content-type":"application/json",authorization:`Bearer ${await a()}`}),i=async p=>{let r=await fetch(`${t}${C}/chat`,{method:"POST",headers:await s(),body:JSON.stringify({message:p})});if(!r.ok)throw new Error(`hola: message failed (${r.status})`);return{reply:(await r.json()).reply??"",sessionId:"",artifacts:[]}};return{sessionId:()=>"",getInfo:async()=>x(`${t}${C}/chat/info`,await s()),sendMessage:i,streamMessage:async(p,r)=>{try{let o=await i(p);r.onText?.(o.reply),r.onComplete?.(o)}catch(o){r.onError?.(w(o))}},subscribe:(p,r)=>{let o=r?.since??"0",d=!1,n,l=r?.intervalMs??3e3,f=async()=>{try{let c=await x(`${t}${C}/chat/thread?since=${encodeURIComponent(o)}`,await s());for(let y of c.messages)p.onMessage(y);o=c.cursor}catch(c){p.onError?.(w(c))}d||(n=setTimeout(f,l))},u=()=>{d=!0,n&&clearTimeout(n)};return r?.signal?.addEventListener("abort",u),n=setTimeout(f,0),u},requestHuman:async()=>{await fetch(`${t}${C}/chat/request-human`,{method:"POST",headers:await s(),body:"{}"})}}};import{useEffect as G,useState as K}from"react";var k=(e,t)=>{let[a,s]=K("");return G(()=>{if(!e){s("");return}let i=Uint8Array.from(atob(e),r=>r.charCodeAt(0)),p=URL.createObjectURL(new Blob([i],{type:t}));return s(p),()=>URL.revokeObjectURL(p)},[e,t]),a};import{useEffect as te,useRef as re}from"react";import{createContext as V,useContext as Y}from"react";import{jsx as X}from"react/jsx-runtime";var D=V(null),Q=({client:e,children:t})=>X(D.Provider,{value:e,children:t}),$=()=>{let e=Y(D);if(!e)throw new Error("useHolaClient must be used within <HolaProvider>");return e};import{useCallback as L,useEffect as Z,useRef as ee,useState as v}from"react";var M=e=>{let[t,a]=v([]),[s,i]=v(""),[p,r]=v(!1),[o,d]=v(null),n=ee(0),l=L(()=>{let u=n.current;return n.current+=1,u},[]);Z(()=>{let u=!0;return e.getInfo().then(c=>{u&&c.greeting&&a([{id:l(),role:"assistant",text:c.greeting}])}).catch(()=>{}),()=>{u=!1}},[e,l]);let f=L(()=>{let u=s.trim();if(!u||p)return;i(""),d(null),r(!0);let c=l(),y=l();a(m=>[...m,{id:c,role:"user",text:u},{id:y,role:"assistant",text:"",streaming:!0}]);let g=m=>{a(h=>h.map(I=>I.id===y?m(I):I))};e.streamMessage(u,{onText:m=>g(h=>({...h,text:h.text+m})),onComplete:m=>{g(h=>({...h,text:m.reply||h.text,artifacts:m.artifacts,streaming:!1})),r(!1)},onError:m=>{g(h=>({...h,streaming:!1})),d(m.error),r(!1)}}).catch(m=>{g(h=>({...h,streaming:!1})),d(m instanceof Error?m.message:"stream_failed"),r(!1)})},[s,p,e,l]);return{messages:t,input:s,setInput:i,send:f,sending:p,error:o}};import{jsx as H,jsxs as A}from"react/jsx-runtime";var b={root:{display:"flex",flexDirection:"column",height:"100%",fontFamily:"system-ui, -apple-system, sans-serif",fontSize:14,color:"#111827"},log:{flex:1,overflowY:"auto",padding:12,display:"flex",flexDirection:"column",gap:8},user:{alignSelf:"flex-end",background:"#111827",color:"#ffffff",borderRadius:12,padding:"8px 12px",maxWidth:"80%",whiteSpace:"pre-wrap"},assistant:{alignSelf:"flex-start",background:"#f1f1f4",color:"#111827",borderRadius:12,padding:"8px 12px",maxWidth:"80%",whiteSpace:"pre-wrap"},artifacts:{display:"flex",flexDirection:"column",gap:6,marginTop:6},image:{maxHeight:220,borderRadius:8,border:"1px solid #e5e7eb"},link:{color:"#2563eb",textDecoration:"underline",wordBreak:"break-all"},error:{color:"#b91c1c",padding:"4px 12px",fontSize:13},form:{display:"flex",gap:8,borderTop:"1px solid #e5e7eb",padding:8},input:{flex:1,border:"1px solid #d1d5db",borderRadius:8,padding:"8px 10px",fontSize:14,outline:"none"},button:{border:"none",background:"#111827",color:"#ffffff",borderRadius:8,padding:"8px 14px",fontSize:14,cursor:"pointer"}},oe=({artifact:e})=>{let t=k(e.dataBase64??"",e.mimeType),a=e.url??t;return a?e.mimeType.startsWith("image/")?H("a",{href:a,rel:"noopener noreferrer",target:"_blank",children:H("img",{alt:e.filename,src:a,style:b.image})}):H("a",{download:e.filename,href:a,style:b.link,children:e.filename}):null},se=()=>{let e=$(),{messages:t,input:a,setInput:s,send:i,sending:p,error:r}=M(e),o=re(null);te(()=>{let n=o.current;n&&(n.scrollTop=n.scrollHeight)},[t]);let d=n=>{n.preventDefault(),i()};return A("div",{style:b.root,children:[H("div",{ref:o,style:b.log,children:t.map(n=>A("div",{style:n.role==="user"?b.user:b.assistant,children:[n.text||(n.streaming?"\u2026":""),n.artifacts&&n.artifacts.length>0?H("div",{style:b.artifacts,children:n.artifacts.map(l=>H(oe,{artifact:l},l.filename))}):null]},n.id))}),r?H("div",{style:b.error,children:r}):null,A("form",{onSubmit:d,style:b.form,children:[H("input",{"aria-label":"Message",onChange:n=>s(n.target.value),placeholder:"Type a message\u2026",style:b.input,value:a}),H("button",{disabled:p||a.trim().length===0,style:b.button,type:"submit",children:"Send"})]})]})};var ne=/\/+$/,U=e=>{let t=e.sessionId,a=e.baseUrl.replace(ne,""),s=r=>`${a}/endpoint/${encodeURIComponent(e.token)}${r}`,i={"content-type":"application/json"},p=(r,o)=>({url:s(r),headers:i,body:JSON.stringify({message:o,...t?{sessionId:t}:{},...e.identity?{externalUserId:e.identity.externalUserId,userHmac:e.identity.userHmac}:{}})});return{sessionId:()=>t,getInfo:()=>x(s("/config"),{}),sendMessage:async r=>{let o=await _(p("/message",r));return t=o.sessionId,o},streamMessage:(r,o,d)=>F(p("/message/stream",r),o,n=>{t=n},d),subscribe:(r,o)=>{let d=o?.since??"0",n=!1,l,f=o?.intervalMs??3e3,u=async()=>{let y=t;if(y)try{let g=await x(s(`/messages?session=${encodeURIComponent(y)}&since=${encodeURIComponent(d)}`),{});for(let m of g.messages)r.onMessage(m);d=g.cursor}catch(g){r.onError?.(w(g))}n||(l=setTimeout(u,f))},c=()=>{n=!0,l&&clearTimeout(l)};return o?.signal?.addEventListener("abort",c),l=setTimeout(u,0),c},requestHuman:async()=>{t&&await fetch(s("/request-human"),{method:"POST",headers:i,body:JSON.stringify({sessionId:t})})}}};var ae=e=>"transport"in e?e.transport:U(e);var ie=/\/+$/,T="/api/v1/end-user";function le(e){let t="";for(let s=0;s<e.length;s+=32768)t+=String.fromCharCode(...e.subarray(s,s+32768));return btoa(t)}var pe=e=>{let t=e.baseUrl.replace(ie,""),a=()=>typeof e.token=="function"?e.token():e.token,s=async()=>({"content-type":"application/json",authorization:`Bearer ${await a()}`}),i=async(r,o)=>{try{let d=await fetch(`${t}${T}${r}`,{method:o.method,headers:await s(),...o.body===void 0?{}:{body:JSON.stringify(o.body)}});if(!d.ok){let n=await d.text().catch(()=>""),l=`${o.method} ${r} \u2192 ${String(d.status)}`;try{let f=JSON.parse(n);f.message&&(l=f.message)}catch{l=n?`${l}: ${n}`:l}throw w(new Error(l))}return await d.json()}catch(d){throw w(d)}},p=r=>`/tables/${encodeURIComponent(r)}`;return{listTables:async()=>(await x(`${t}${T}/tables`,await s())).tables,listRows:async(r,o)=>await x(`${t}${T}${p(r)}/rows?limit=${String(o??100)}`,await s()),insertRow:async(r,o)=>{let{rowIds:d}=await i(`${p(r)}/rows`,{method:"POST",body:{rows:[o]}}),n=d[0];if(!n)throw w(new Error("The row was not created."));return n},patchRow:async(r,o,d)=>(await i(`${p(r)}/rows/${encodeURIComponent(o)}`,{method:"PATCH",body:d})).updated,deleteRow:async(r,o)=>(await i(`/${encodeURIComponent(r)}/${encodeURIComponent(o)}`,{method:"DELETE"})).deleted,listFiles:async()=>(await x(`${t}${T}/tables/files/rows?limit=200`,await s())).rows.map(o=>({id:o.rowId,filename:String(o.data.filename??""),source:String(o.data.source??"client"),campaign:String(o.data.campaign??""),size:typeof o.data.size=="number"?o.data.size:0,createdAt:o.createdAt})),uploadFile:async(r,o)=>{let d=new Uint8Array(await r.arrayBuffer());return await i("/files",{method:"POST",body:{filename:r.name,mime:r.type||"application/octet-stream",data:le(d),...o===void 0?{}:{message:o}}})},fileUrl:r=>`${t}${T}/files/${encodeURIComponent(r)}/raw`,deleteFile:async r=>(await i(`/files/${encodeURIComponent(r)}`,{method:"DELETE"})).deleted}};import{useCallback as de,useEffect as W,useRef as ce,useState as P}from"react";function N(e,t){return e.some(s=>s.id===t.id)?e:[...t.author==="client"?e.filter(s=>!(s.pending&&s.author==="client"&&s.text===t.text)):e,t]}var ue=(e,t)=>{let[a,s]=P([]),[i,p]=P(""),[r,o]=P(!1),[d,n]=P(null),l=ce(0),f=t?.pollMs??2e3;W(()=>{let c=!0;return e.getInfo().then(y=>{c&&y.greeting&&s(g=>g.length===0?[{id:"greeting",cursor:"",author:"agent",text:y.greeting}]:g)}).catch(()=>{}),()=>{c=!1}},[e]),W(()=>e.subscribe?.({onMessage:c=>s(y=>N(y,c)),onError:c=>n(c.error)},{intervalMs:f}),[e,f]);let u=de(()=>{let c=i.trim();if(!c||r)return;p(""),n(null),o(!0),l.current+=1;let y={id:`pending-${l.current}`,cursor:"",author:"client",text:c,pending:!0};s(g=>[...g,y]),e.sendMessage(c).then(()=>o(!1)).catch(g=>{n(g instanceof Error?g.message:"send_failed"),o(!1)})},[i,r,e]);return{messages:a,input:i,setInput:p,send:u,sending:r,error:d}};export{se as Chat,Q as HolaProvider,B as createApiTransport,ae as createHolaClient,pe as createPortalData,U as createWidgetTransport,N as mergeMessage,R as textDeltaOf,E as thinkingDeltaOf,S as toolEventOf,k as useArtifactUrl,M as useChat,$ as useHolaClient,ue as useThread};
8
+ `)}},n=async()=>{let l=await p.read();if(!l.done)return o+=r.decode(l.value,{stream:!0}),d(),n()};await n()};var q=/\/+$/,C="/api/v1/end-user",B=e=>{let t=e.baseUrl.replace(q,""),a=()=>typeof e.token=="function"?e.token():e.token,s=async()=>({"content-type":"application/json",authorization:`Bearer ${await a()}`}),i=async p=>{let r=await fetch(`${t}${C}/chat`,{method:"POST",headers:await s(),body:JSON.stringify({message:p})});if(!r.ok)throw new Error(`hola: message failed (${r.status})`);return{reply:(await r.json()).reply??"",sessionId:"",artifacts:[]}};return{sessionId:()=>"",getInfo:async()=>b(`${t}${C}/chat/info`,await s()),sendMessage:i,streamMessage:async(p,r)=>{try{let o=await i(p);r.onText?.(o.reply),r.onComplete?.(o)}catch(o){r.onError?.(x(o))}},subscribe:(p,r)=>{let o=r?.since??"0",d=!1,n,l=r?.intervalMs??3e3,f=async()=>{try{let c=await b(`${t}${C}/chat/thread?since=${encodeURIComponent(o)}`,await s());for(let y of c.messages)p.onMessage(y);o=c.cursor}catch(c){p.onError?.(x(c))}d||(n=setTimeout(f,l))},u=()=>{d=!0,n&&clearTimeout(n)};return r?.signal?.addEventListener("abort",u),n=setTimeout(f,0),u},requestHuman:async()=>{await fetch(`${t}${C}/chat/request-human`,{method:"POST",headers:await s(),body:"{}"})}}};import{useEffect as G,useState as K}from"react";var k=(e,t)=>{let[a,s]=K("");return G(()=>{if(!e){s("");return}let i=Uint8Array.from(atob(e),r=>r.charCodeAt(0)),p=URL.createObjectURL(new Blob([i],{type:t}));return s(p),()=>URL.revokeObjectURL(p)},[e,t]),a};import{useEffect as te,useRef as re}from"react";import{createContext as V,useContext as Y}from"react";import{jsx as X}from"react/jsx-runtime";var D=V(null),Q=({client:e,children:t})=>X(D.Provider,{value:e,children:t}),$=()=>{let e=Y(D);if(!e)throw new Error("useHolaClient must be used within <HolaProvider>");return e};import{useCallback as L,useEffect as Z,useRef as ee,useState as v}from"react";var M=e=>{let[t,a]=v([]),[s,i]=v(""),[p,r]=v(!1),[o,d]=v(null),n=ee(0),l=L(()=>{let u=n.current;return n.current+=1,u},[]);Z(()=>{let u=!0;return e.getInfo().then(c=>{u&&c.greeting&&a([{id:l(),role:"assistant",text:c.greeting}])}).catch(()=>{}),()=>{u=!1}},[e,l]);let f=L(()=>{let u=s.trim();if(!u||p)return;i(""),d(null),r(!0);let c=l(),y=l();a(m=>[...m,{id:c,role:"user",text:u},{id:y,role:"assistant",text:"",streaming:!0}]);let g=m=>{a(h=>h.map(I=>I.id===y?m(I):I))};e.streamMessage(u,{onText:m=>g(h=>({...h,text:h.text+m})),onComplete:m=>{g(h=>({...h,text:m.reply||h.text,artifacts:m.artifacts,streaming:!1})),r(!1)},onError:m=>{g(h=>({...h,streaming:!1})),d(m.error),r(!1)}}).catch(m=>{g(h=>({...h,streaming:!1})),d(m instanceof Error?m.message:"stream_failed"),r(!1)})},[s,p,e,l]);return{messages:t,input:s,setInput:i,send:f,sending:p,error:o}};import{jsx as H,jsxs as A}from"react/jsx-runtime";var w={root:{display:"flex",flexDirection:"column",height:"100%",fontFamily:"system-ui, -apple-system, sans-serif",fontSize:14,color:"#111827"},log:{flex:1,overflowY:"auto",padding:12,display:"flex",flexDirection:"column",gap:8},user:{alignSelf:"flex-end",background:"#111827",color:"#ffffff",borderRadius:12,padding:"8px 12px",maxWidth:"80%",whiteSpace:"pre-wrap"},assistant:{alignSelf:"flex-start",background:"#f1f1f4",color:"#111827",borderRadius:12,padding:"8px 12px",maxWidth:"80%",whiteSpace:"pre-wrap"},artifacts:{display:"flex",flexDirection:"column",gap:6,marginTop:6},image:{maxHeight:220,borderRadius:8,border:"1px solid #e5e7eb"},link:{color:"#2563eb",textDecoration:"underline",wordBreak:"break-all"},error:{color:"#b91c1c",padding:"4px 12px",fontSize:13},form:{display:"flex",gap:8,borderTop:"1px solid #e5e7eb",padding:8},input:{flex:1,border:"1px solid #d1d5db",borderRadius:8,padding:"8px 10px",fontSize:14,outline:"none"},button:{border:"none",background:"#111827",color:"#ffffff",borderRadius:8,padding:"8px 14px",fontSize:14,cursor:"pointer"}},oe=({artifact:e})=>{let t=k(e.dataBase64??"",e.mimeType),a=e.url??t;return a?e.mimeType.startsWith("image/")?H("a",{href:a,rel:"noopener noreferrer",target:"_blank",children:H("img",{alt:e.filename,src:a,style:w.image})}):H("a",{download:e.filename,href:a,style:w.link,children:e.filename}):null},se=()=>{let e=$(),{messages:t,input:a,setInput:s,send:i,sending:p,error:r}=M(e),o=re(null);te(()=>{let n=o.current;n&&(n.scrollTop=n.scrollHeight)},[t]);let d=n=>{n.preventDefault(),i()};return A("div",{style:w.root,children:[H("div",{ref:o,style:w.log,children:t.map(n=>A("div",{style:n.role==="user"?w.user:w.assistant,children:[n.text||(n.streaming?"\u2026":""),n.artifacts&&n.artifacts.length>0?H("div",{style:w.artifacts,children:n.artifacts.map(l=>H(oe,{artifact:l},l.filename))}):null]},n.id))}),r?H("div",{style:w.error,children:r}):null,A("form",{onSubmit:d,style:w.form,children:[H("input",{"aria-label":"Message",onChange:n=>s(n.target.value),placeholder:"Type a message\u2026",style:w.input,value:a}),H("button",{disabled:p||a.trim().length===0,style:w.button,type:"submit",children:"Send"})]})]})};var ne=/\/+$/,U=e=>{let t=e.sessionId,a=e.baseUrl.replace(ne,""),s=r=>`${a}/endpoint/${encodeURIComponent(e.token)}${r}`,i={"content-type":"application/json"},p=(r,o)=>({url:s(r),headers:i,body:JSON.stringify({message:o,...t?{sessionId:t}:{},...e.identity?{externalUserId:e.identity.externalUserId,userHmac:e.identity.userHmac}:{}})});return{sessionId:()=>t,getInfo:()=>b(s("/config"),{}),sendMessage:async r=>{let o=await _(p("/message",r));return t=o.sessionId,o},streamMessage:(r,o,d)=>F(p("/message/stream",r),o,n=>{t=n},d),subscribe:(r,o)=>{let d=o?.since??"0",n=!1,l,f=o?.intervalMs??3e3,u=async()=>{let y=t;if(y)try{let g=await b(s(`/messages?session=${encodeURIComponent(y)}&since=${encodeURIComponent(d)}`),{});for(let m of g.messages)r.onMessage(m);d=g.cursor}catch(g){r.onError?.(x(g))}n||(l=setTimeout(u,f))},c=()=>{n=!0,l&&clearTimeout(l)};return o?.signal?.addEventListener("abort",c),l=setTimeout(u,0),c},requestHuman:async()=>{t&&await fetch(s("/request-human"),{method:"POST",headers:i,body:JSON.stringify({sessionId:t})})}}};var ae=e=>"transport"in e?e.transport:U(e);var ie=/\/+$/,T="/api/v1/end-user";function le(e){let t="";for(let s=0;s<e.length;s+=32768)t+=String.fromCharCode(...e.subarray(s,s+32768));return btoa(t)}var pe=e=>{let t=e.baseUrl.replace(ie,""),a=()=>typeof e.token=="function"?e.token():e.token,s=async()=>({"content-type":"application/json",authorization:`Bearer ${await a()}`}),i=async(r,o)=>{try{let d=await fetch(`${t}${T}${r}`,{method:o.method,headers:await s(),...o.body===void 0?{}:{body:JSON.stringify(o.body)}});if(!d.ok){let n=await d.text().catch(()=>""),l=`${o.method} ${r} \u2192 ${String(d.status)}`;try{let f=JSON.parse(n);f.message&&(l=f.message)}catch{l=n?`${l}: ${n}`:l}throw x(new Error(l))}return await d.json()}catch(d){throw x(d)}},p=r=>`/tables/${encodeURIComponent(r)}`;return{listTables:async()=>(await b(`${t}${T}/tables`,await s())).tables,listRows:async(r,o)=>await b(`${t}${T}${p(r)}/rows?limit=${String(o??100)}`,await s()),insertRow:async(r,o)=>{let{rowIds:d}=await i(`${p(r)}/rows`,{method:"POST",body:{rows:[o]}}),n=d[0];if(!n)throw x(new Error("The row was not created."));return n},patchRow:async(r,o,d)=>(await i(`${p(r)}/rows/${encodeURIComponent(o)}`,{method:"PATCH",body:d})).updated,deleteRow:async(r,o)=>(await i(`/${encodeURIComponent(r)}/${encodeURIComponent(o)}`,{method:"DELETE"})).deleted,listFiles:async()=>(await b(`${t}${T}/tables/files/rows?limit=200`,await s())).rows.map(o=>({id:o.rowId,filename:String(o.data.filename??""),source:String(o.data.source??"client"),campaign:String(o.data.campaign??""),size:typeof o.data.size=="number"?o.data.size:0,createdAt:o.createdAt})),uploadFile:async(r,o)=>{let d=new Uint8Array(await r.arrayBuffer());return await i("/files",{method:"POST",body:{filename:r.name,mime:r.type||"application/octet-stream",data:le(d),...o===void 0?{}:{message:o}}})},fileLink:async r=>await b(`${t}${T}/files/${encodeURIComponent(r)}/url`,await s()),deleteFile:async r=>(await i(`/files/${encodeURIComponent(r)}`,{method:"DELETE"})).deleted}};import{useCallback as de,useEffect as W,useRef as ce,useState as P}from"react";function N(e,t){return e.some(s=>s.id===t.id)?e:[...t.author==="client"?e.filter(s=>!(s.pending&&s.author==="client"&&s.text===t.text)):e,t]}var ue=(e,t)=>{let[a,s]=P([]),[i,p]=P(""),[r,o]=P(!1),[d,n]=P(null),l=ce(0),f=t?.pollMs??2e3;W(()=>{let c=!0;return e.getInfo().then(y=>{c&&y.greeting&&s(g=>g.length===0?[{id:"greeting",cursor:"",author:"agent",text:y.greeting}]:g)}).catch(()=>{}),()=>{c=!1}},[e]),W(()=>e.subscribe?.({onMessage:c=>s(y=>N(y,c)),onError:c=>n(c.error)},{intervalMs:f}),[e,f]);let u=de(()=>{let c=i.trim();if(!c||r)return;p(""),n(null),o(!0),l.current+=1;let y={id:`pending-${l.current}`,cursor:"",author:"client",text:c,pending:!0};s(g=>[...g,y]),e.sendMessage(c).then(()=>o(!1)).catch(g=>{n(g instanceof Error?g.message:"send_failed"),o(!1)})},[i,r,e]);return{messages:a,input:i,setInput:p,send:u,sending:r,error:d}};export{se as Chat,Q as HolaProvider,B as createApiTransport,ae as createHolaClient,pe as createPortalData,U as createWidgetTransport,N as mergeMessage,R as textDeltaOf,E as thinkingDeltaOf,S as toolEventOf,k as useArtifactUrl,M as useChat,$ as useHolaClient,ue as useThread};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holaboss/client",
3
- "version": "0.2.0-beta.0",
3
+ "version": "0.2.0-beta.1",
4
4
  "description": "Injectable client SDK for embedding a Holaboss AI employee (chat today; dashboard + artifacts next) into your own web app.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",