@holaboss/client 0.2.0-beta.7 → 0.2.0-beta.9

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 L=Object.defineProperty;var ce=Object.getOwnPropertyDescriptor;var ge=Object.getOwnPropertyNames;var me=Object.prototype.hasOwnProperty;var fe=(e,t)=>{for(var r in t)L(e,r,{get:t[r],enumerable:!0})},ye=(e,t,r,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of ge(t))!me.call(e,n)&&n!==r&&L(e,n,{get:()=>t[n],enumerable:!(s=ce(t,n))||s.enumerable});return e};var be=e=>ye(L({},"__esModule",{value:!0}),e);var Oe={};fe(Oe,{Chat:()=>te,HolaProvider:()=>K,PortalConflict:()=>v,createApiTransport:()=>X,createHolaClient:()=>re,createPortalData:()=>de,createWidgetTransport:()=>O,deriveFields:()=>N,inferSpec:()=>j,layoutGroups:()=>G,mergeMessage:()=>V,parseDashboardSpec:()=>J,renderModel:()=>B,textDeltaOf:()=>R,thinkingDeltaOf:()=>I,toolEventOf:()=>E,useArtifactUrl:()=>A,useChat:()=>U,useHolaClient:()=>D,useThread:()=>pe,widgetSpan:()=>z});module.exports=be(Oe);var q=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="message_update"?t.assistantMessageEvent??null:null},R=e=>{let t=q(e);return t?.type==="text_delta"&&typeof t.delta=="string"?t.delta:null},I=e=>{let t=q(e);return t?.type==="thinking_delta"&&typeof t.delta=="string"?t.delta:null},E=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 he=/^ /,H=e=>{if(e&&typeof e=="object"){let t=e,r=typeof t.error=="string"?t.error:"request_failed";return typeof t.retryable=="boolean"?{error:r,retryable:t.retryable}:{error:r}}return{error:"request_failed"}},we=e=>{let t="message",r=[];for(let s of e.split(`
3
- `))s.startsWith(":")||(s.startsWith("event:")?t=s.slice(6).trim():s.startsWith("data:")&&r.push(s.slice(5).replace(he,"")));return r.length>0?{event:t,data:r.join(`
4
- `)}:null},xe=(e,t,r)=>{let s;try{s=JSON.parse(e.data)}catch{return}if(e.event==="session"){let n=s.sessionId;n&&(r(n),t.onSession?.(n));return}if(e.event==="turn_event"){t.onEvent?.(s);let n=R(s);n&&t.onText?.(n);let l=I(s);l&&t.onThinking?.(l);let o=E(s);o&&t.onTool?.(o);return}if(e.event==="chat_completed"){let n=s;r(n.sessionId),t.onComplete?.(n);return}e.event==="chat_error"&&t.onError?.(H(s))},h=async(e,t)=>{let r=await fetch(e,{headers:t});if(!r.ok)throw new Error(`hola: request failed (${r.status})`);return await r.json()},Y=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()},Q=async(e,t,r,s)=>{let n=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body,signal:s});if(!(n.ok&&n.body)){t.onError?.({error:`stream_failed_${n.status}`});return}let l=n.body.getReader(),o=new TextDecoder,a="",i=()=>{let u=a.indexOf(`
2
+ var q=Object.defineProperty;var Ie=Object.getOwnPropertyDescriptor;var He=Object.getOwnPropertyNames;var Me=Object.prototype.hasOwnProperty;var We=(e,t)=>{for(var o in t)q(e,o,{get:t[o],enumerable:!0})},Ae=(e,t,o,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of He(t))!Me.call(e,r)&&r!==o&&q(e,r,{get:()=>t[r],enumerable:!(s=Ie(t,r))||s.enumerable});return e};var Ee=e=>Ae(q({},"__esModule",{value:!0}),e);var rt={};We(rt,{Chat:()=>be,GRID_MAX_COLS:()=>L,GRID_MAX_ROWS:()=>N,HolaProvider:()=>ge,PortalConflict:()=>P,bandOfKind:()=>B,bandOfType:()=>Y,createApiTransport:()=>me,createHolaClient:()=>he,createPortalData:()=>Ce,createWidgetTransport:()=>F,deliverableCellText:()=>ie,deliverableStatus:()=>re,deriveFields:()=>X,footprintOf:()=>Q,footprintWith:()=>j,formatDeliverableDate:()=>le,groupDeliverableVersions:()=>G,inferSpec:()=>K,isDeliverableChecked:()=>ae,layoutSegments:()=>Z,mergeMessage:()=>ue,normalizeDeliverableColType:()=>z,normalizeDeliverableItem:()=>V,parseDashboardSpec:()=>te,parseDeliverableItems:()=>ne,parseDeliverableTable:()=>se,publishedVersionOf:()=>oe,renderModel:()=>ee,textDeltaOf:()=>I,thinkingDeltaOf:()=>H,toolEventOf:()=>M,useArtifactUrl:()=>E,useChat:()=>_,useHolaClient:()=>O,useThread:()=>Pe});module.exports=Ee(rt);var de=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="message_update"?t.assistantMessageEvent??null:null},I=e=>{let t=de(e);return t?.type==="text_delta"&&typeof t.delta=="string"?t.delta:null},H=e=>{let t=de(e);return t?.type==="thinking_delta"&&typeof t.delta=="string"?t.delta:null},M=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 $e=/^ /,D=e=>{if(e&&typeof e=="object"){let t=e,o=typeof t.error=="string"?t.error:"request_failed";return typeof t.retryable=="boolean"?{error:o,retryable:t.retryable}:{error:o}}return{error:"request_failed"}},Oe=e=>{let t="message",o=[];for(let s of e.split(`
3
+ `))s.startsWith(":")||(s.startsWith("event:")?t=s.slice(6).trim():s.startsWith("data:")&&o.push(s.slice(5).replace($e,"")));return o.length>0?{event:t,data:o.join(`
4
+ `)}:null},_e=(e,t,o)=>{let s;try{s=JSON.parse(e.data)}catch{return}if(e.event==="session"){let r=s.sessionId;r&&(o(r),t.onSession?.(r));return}if(e.event==="turn_event"){t.onEvent?.(s);let r=I(s);r&&t.onText?.(r);let a=H(s);a&&t.onThinking?.(a);let n=M(s);n&&t.onTool?.(n);return}if(e.event==="chat_completed"){let r=s;o(r.sessionId),t.onComplete?.(r);return}e.event==="chat_error"&&t.onError?.(D(s))},h=async(e,t)=>{let o=await fetch(e,{headers:t});if(!o.ok)throw new Error(`hola: request failed (${o.status})`);return await o.json()},pe=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()},ce=async(e,t,o,s)=>{let r=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body,signal:s});if(!(r.ok&&r.body)){t.onError?.({error:`stream_failed_${r.status}`});return}let a=r.body.getReader(),n=new TextDecoder,i="",l=()=>{let d=i.indexOf(`
5
5
 
6
- `);for(;u!==-1;){let b=a.slice(0,u);a=a.slice(u+2);let c=we(b);c&&xe(c,t,r),u=a.indexOf(`
6
+ `);for(;d!==-1;){let b=i.slice(0,d);i=i.slice(d+2);let c=Oe(b);c&&_e(c,t,o),d=i.indexOf(`
7
7
 
8
- `)}},d=async()=>{let u=await l.read();if(!u.done)return a+=o.decode(u.value,{stream:!0}),i(),d()};await d()};var Te=/\/+$/,M="/api/v1/end-user",X=e=>{let t=e.baseUrl.replace(Te,""),r=()=>typeof e.token=="function"?e.token():e.token,s=o=>e.project?`${o}project=${encodeURIComponent(e.project)}`:"",n=async()=>({"content-type":"application/json",authorization:`Bearer ${await r()}`}),l=async o=>{let a=await fetch(`${t}${M}/chat${s("?")}`,{method:"POST",headers:await n(),body:JSON.stringify({message:o})});if(!a.ok)throw new Error(`hola: message failed (${a.status})`);return{reply:(await a.json()).reply??"",sessionId:"",artifacts:[]}};return{sessionId:()=>"",getInfo:async()=>h(`${t}${M}/chat/info${s("?")}`,await n()),sendMessage:l,streamMessage:async(o,a)=>{try{let i=await l(o);a.onText?.(i.reply),a.onComplete?.(i)}catch(i){a.onError?.(H(i))}},subscribe:(o,a)=>{let i=a?.since??"0",d=!1,u,b=a?.intervalMs??3e3,c=async()=>{try{let m=await h(`${t}${M}/chat/thread?since=${encodeURIComponent(i)}${s("&")}`,await n());for(let g of m.messages)o.onMessage(g);i=m.cursor,o.onHealthy?.()}catch(m){o.onError?.(H(m))}d||(u=setTimeout(c,b))},p=()=>{d=!0,u&&clearTimeout(u)};return a?.signal?.addEventListener("abort",p),u=setTimeout(c,0),p},requestHuman:async()=>{await fetch(`${t}${M}/chat/request-human${s("?")}`,{method:"POST",headers:await n(),body:"{}"})}}};var $=require("react"),A=(e,t)=>{let[r,s]=(0,$.useState)("");return(0,$.useEffect)(()=>{if(!e){s("");return}let n=Uint8Array.from(atob(e),o=>o.charCodeAt(0)),l=URL.createObjectURL(new Blob([n],{type:t}));return s(l),()=>URL.revokeObjectURL(l)},[e,t]),r};var F=require("react");var W=require("react"),ee=require("react/jsx-runtime"),Z=(0,W.createContext)(null),K=({client:e,children:t})=>(0,ee.jsx)(Z.Provider,{value:e,children:t}),D=()=>{let e=(0,W.useContext)(Z);if(!e)throw new Error("useHolaClient must be used within <HolaProvider>");return e};var w=require("react"),U=e=>{let[t,r]=(0,w.useState)([]),[s,n]=(0,w.useState)(""),[l,o]=(0,w.useState)(!1),[a,i]=(0,w.useState)(null),d=(0,w.useRef)(0),u=(0,w.useCallback)(()=>{let c=d.current;return d.current+=1,c},[]);(0,w.useEffect)(()=>{let c=!0;return e.getInfo().then(p=>{c&&p.greeting&&r([{id:u(),role:"assistant",text:p.greeting}])}).catch(()=>{}),()=>{c=!1}},[e,u]);let b=(0,w.useCallback)(()=>{let c=s.trim();if(!c||l)return;n(""),i(null),o(!0);let p=u(),m=u();r(f=>[...f,{id:p,role:"user",text:c},{id:m,role:"assistant",text:"",streaming:!0}]);let g=f=>{r(T=>T.map(_=>_.id===m?f(_):_))};e.streamMessage(c,{onText:f=>g(T=>({...T,text:T.text+f})),onComplete:f=>{g(T=>({...T,text:f.reply||T.text,artifacts:f.artifacts,streaming:!1})),o(!1)},onError:f=>{g(T=>({...T,streaming:!1})),i(f.error),o(!1)}}).catch(f=>{g(T=>({...T,streaming:!1})),i(f instanceof Error?f.message:"stream_failed"),o(!1)})},[s,l,e,u]);return{messages:t,input:s,setInput:n,send:b,sending:l,error:a}};var y=require("react/jsx-runtime"),P={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"}},Pe=({artifact:e})=>{let t=A(e.dataBase64??"",e.mimeType),r=e.url??t;return r?e.mimeType.startsWith("image/")?(0,y.jsx)("a",{href:r,rel:"noopener noreferrer",target:"_blank",children:(0,y.jsx)("img",{alt:e.filename,src:r,style:P.image})}):(0,y.jsx)("a",{download:e.filename,href:r,style:P.link,children:e.filename}):null},te=()=>{let e=D(),{messages:t,input:r,setInput:s,send:n,sending:l,error:o}=U(e),a=(0,F.useRef)(null);(0,F.useEffect)(()=>{let d=a.current;d&&(d.scrollTop=d.scrollHeight)},[t]);let i=d=>{d.preventDefault(),n()};return(0,y.jsxs)("div",{style:P.root,children:[(0,y.jsx)("div",{ref:a,style:P.log,children:t.map(d=>(0,y.jsxs)("div",{style:d.role==="user"?P.user:P.assistant,children:[d.text||(d.streaming?"\u2026":""),d.artifacts&&d.artifacts.length>0?(0,y.jsx)("div",{style:P.artifacts,children:d.artifacts.map(u=>(0,y.jsx)(Pe,{artifact:u},u.filename))}):null]},d.id))}),o?(0,y.jsx)("div",{style:P.error,children:o}):null,(0,y.jsxs)("form",{onSubmit:i,style:P.form,children:[(0,y.jsx)("input",{"aria-label":"Message",onChange:d=>s(d.target.value),placeholder:"Type a message\u2026",style:P.input,value:r}),(0,y.jsx)("button",{disabled:l||r.trim().length===0,style:P.button,type:"submit",children:"Send"})]})]})};var ke=/\/+$/,O=e=>{let t=e.sessionId,r=e.baseUrl.replace(ke,""),s=o=>`${r}/endpoint/${encodeURIComponent(e.token)}${o}`,n={"content-type":"application/json"},l=(o,a)=>({url:s(o),headers:n,body:JSON.stringify({message:a,...t?{sessionId:t}:{},...e.identity?{externalUserId:e.identity.externalUserId,userHmac:e.identity.userHmac}:{}})});return{sessionId:()=>t,getInfo:()=>h(s("/config"),{}),sendMessage:async o=>{let a=await Y(l("/message",o));return t=a.sessionId,a},streamMessage:(o,a,i)=>Q(l("/message/stream",o),a,d=>{t=d},i),subscribe:(o,a)=>{let i=a?.since??"0",d=!1,u,b=a?.intervalMs??3e3,c=async()=>{let m=t;if(m)try{let g=await h(s(`/messages?session=${encodeURIComponent(m)}&since=${encodeURIComponent(i)}`),{});for(let f of g.messages)o.onMessage(f);i=g.cursor,o.onHealthy?.()}catch(g){o.onError?.(H(g))}d||(u=setTimeout(c,b))},p=()=>{d=!0,u&&clearTimeout(u)};return a?.signal?.addEventListener("abort",p),u=setTimeout(c,0),p},requestHuman:async()=>{t&&await fetch(s("/request-human"),{method:"POST",headers:n,body:JSON.stringify({sessionId:t})})}}};var re=e=>"transport"in e?e.transport:O(e);var He=/^https?:\/\//i,Se=/^\d{4}-\d{2}-\d{2}(?:[T ]|$)/,Ce=e=>e.replace(/_/g," ").replace(/\b\w/g,t=>t.toUpperCase());function ve(e){if(typeof e=="number")return"number";if(typeof e=="boolean")return"boolean";if(typeof e=="string"){if(He.test(e))return"url";if(Se.test(e))return"date"}return"text"}function N(e){let t=[],r=new Map;for(let s of e)for(let[n,l]of Object.entries(s.data??{})){if(l==null)continue;let o=r.get(n);o||(o=new Map,r.set(n,o),t.push(n));let a=ve(l);o.set(a,(o.get(a)??0)+1)}return t.map(s=>{let n=r.get(s)??new Map,l="text",o=-1;for(let[a,i]of n)i>o&&(o=i,l=a);return{key:s,label:Ce(s),type:l}})}var Re=e=>typeof e=="number"?e:Number(e)||0,ne=e=>/rate|position|rank|score|percent|avg/i.test(e),Ie=/posted|published|sent|completed|shipped|launched|_at|date/i,Ee=new Set(["service","order","end_user_id"]);function j(e,t){let r=e.filter(i=>!Ee.has(i.key)),s=r.filter(i=>i.type==="number").slice(0,3),n=r.find(i=>i.key==="status")??r.find(i=>i.type==="select"),l=r.find(i=>i.type==="date"&&Ie.test(i.key))??r.find(i=>i.type==="date"),o=r.filter(i=>i.type==="number"&&!ne(i.key)).map(i=>({field:i,total:t.reduce((d,u)=>d+Re(u.data[i.key]),0)})).sort((i,d)=>d.total-i.total).find(i=>i.total>0)?.field??null,a=[{type:"stat",label:"Items",agg:"count"}];for(let i of s){let d=ne(i.key);a.push({type:"stat",metric:i.key,agg:d?"avg":"sum",label:d?`Avg ${i.label.toLowerCase()}`:i.label})}return l&&a.push({type:"line",x:l.key,y:o?.key,agg:"sum",title:o?`${o.label} by day`:"Items by day"}),n&&a.push({type:"donut",groupBy:n.key,title:n.label}),a.push({type:"table",columns:r.map(i=>i.key)}),{version:1,widgets:a}}function G(e){let t=[];for(let r of e){let s=t.length>0?t[t.length-1]:void 0;r.kind==="stat"?s?.kind==="stats"?s.items.push(r):t.push({kind:"stats",items:[r]}):r.kind==="series"||r.kind==="donut"?s?.kind==="charts"?s.items.push(r):t.push({kind:"charts",items:[r]}):t.push({kind:"block",item:r})}return t}var oe=new Set(["service","order","end_user_id"]),se=e=>typeof e=="number"?e:Number(e)||0,ae=e=>e==null?"":String(e);function ie(e,t){if(e==="count")return t.length;if(t.length===0)return 0;if(e==="last")return t[t.length-1]??0;if(e==="min")return Math.min(...t);if(e==="max")return Math.max(...t);let r=t.reduce((s,n)=>s+n,0);return e==="avg"?Math.round(r/t.length):r}function Me(e,t,r,s){let n=new Map;for(let l of e){let o=new Date(ae(l.data[t]));if(Number.isNaN(o.getTime()))continue;let a=o.toISOString().slice(0,10),i=n.get(a)??[];i.push(r?se(l.data[r]):1),n.set(a,i)}return[...n.entries()].sort((l,o)=>l[0]<o[0]?-1:1).map(([l,o])=>({label:new Date(`${l}T00:00:00`).toLocaleDateString(void 0,{month:"short",day:"numeric"}),value:r?ie(s,o):o.length}))}function $e(e,t){let r=new Map;for(let s of e){let n=ae(s.data[t]).trim();n&&r.set(n,(r.get(n)??0)+1)}return[...r.entries()].sort((s,n)=>n[1]-s[1]).map(([s,n])=>({label:s,value:n}))}function Ae(e,t,r,s){switch(e.type){case"stat":{let n=e.metric?t.get(e.metric):void 0;if(e.metric&&!n)return null;if(!n)return{kind:"stat",label:e.label??"Items",value:s.length};let l=s.map(o=>se(o.data[n.key]));return{kind:"stat",label:e.label??n.label,value:ie(e.agg??"sum",l)}}case"line":case"bar":{if(!t.has(e.x)||e.y&&!t.has(e.y))return null;let n=Me(s,e.x,e.y,e.agg??"sum");return n.length<2?null:{kind:"series",draw:e.type,title:e.title??"By day",points:n}}case"donut":{if(!t.has(e.groupBy))return null;let n=$e(s,e.groupBy);return n.length===0?null:{kind:"donut",title:e.title??t.get(e.groupBy)?.label??"Breakdown",points:n}}case"table":{let n=e.columns?e.columns.map(l=>t.get(l)).filter(l=>l!==void 0&&!oe.has(l.key)):r;return n.length===0?null:{kind:"table",title:e.title,columns:n,rows:s}}case"text":return{kind:"text",title:e.title,body:e.body};default:return null}}function B(e,t,r){let s=t.filter(o=>!oe.has(o.key)),n=new Map(t.map(o=>[o.key,o])),l=[];for(let o of e.widgets){let a=Ae(o,n,s,r);a&&l.push({...a,w:o.w})}return l}function z(e,t,r){return e&&e>=1?Math.min(4,Math.round(e)):t==="stat"?1:t==="chart"?r?4:2:4}var We=new Set(["sum","avg","count","min","max","last"]),le=e=>typeof e=="string"&&We.has(e)?e:void 0,k=e=>typeof e=="string"&&e!==""?e:void 0,C=e=>typeof e=="number"&&e>=1?Math.min(4,Math.round(e)):void 0;function De(e){if(typeof e!="object"||e===null)return null;let t=e;switch(t.type){case"stat":return{type:"stat",label:k(t.label),metric:k(t.metric),agg:le(t.agg),w:C(t.w)};case"line":case"bar":{let r=k(t.x);return r?{type:t.type,title:k(t.title),x:r,y:k(t.y),agg:le(t.agg),w:C(t.w)}:null}case"donut":{let r=k(t.groupBy);return r?{type:"donut",title:k(t.title),groupBy:r,w:C(t.w)}:null}case"table":{let r=Array.isArray(t.columns)?t.columns.filter(s=>typeof s=="string"):void 0;return{type:"table",title:k(t.title),columns:r,w:C(t.w)}}case"text":{let r=k(t.body);return r?{type:"text",title:k(t.title),body:r,w:C(t.w)}:null}default:return null}}function J(e){let t=e;if(typeof e=="string"){if(e.trim()==="")return null;try{t=JSON.parse(e)}catch{return null}}if(typeof t!="object"||t===null)return null;let r=t.widgets;if(!Array.isArray(r))return null;let s=r.map(De).filter(l=>l!==null);if(s.length===0)return null;let n=t.version;return{version:typeof n=="number"?n:1,title:k(t.title),widgets:s}}var Ue=/\/+$/,S="/api/v1/end-user",v=class extends Error{constructor(t){super(t),this.name="PortalConflict"}};function Fe(e){let t="";for(let s=0;s<e.length;s+=32768)t+=String.fromCharCode(...e.subarray(s,s+32768));return btoa(t)}var de=e=>{let t=e.baseUrl.replace(Ue,""),r=()=>typeof e.token=="function"?e.token():e.token,s=async()=>({"content-type":"application/json",authorization:`Bearer ${await r()}`}),n=async(o,a)=>{try{let i=await fetch(`${t}${S}${o}`,{method:a.method,headers:await s(),...a.body===void 0?{}:{body:JSON.stringify(a.body)}});if(i.status===409){let d=await i.json().catch(()=>({}));throw new v(d.message??"Someone else saved this first.")}if(!i.ok){let d=await i.text().catch(()=>""),u=`${a.method} ${o} \u2192 ${String(i.status)}`;try{let b=JSON.parse(d);b.message&&(u=b.message)}catch{u=d?`${u}: ${d}`:u}throw H(new Error(u))}return await i.json()}catch(i){throw H(i)}},l=o=>`/tables/${encodeURIComponent(o)}`;return{listTables:async()=>(await h(`${t}${S}/tables`,await s())).tables,listRows:async(o,a)=>await h(`${t}${S}${l(o)}/rows?limit=${String(a??100)}`,await s()),insertRow:async(o,a)=>{let{rowIds:i}=await n(`${l(o)}/rows`,{method:"POST",body:{rows:[a]}}),d=i[0];if(!d)throw H(new Error("The row was not created."));return d},patchRow:async(o,a,i)=>(await n(`${l(o)}/rows/${encodeURIComponent(a)}`,{method:"PATCH",body:i})).updated,deleteRow:async(o,a)=>(await n(`/${encodeURIComponent(o)}/${encodeURIComponent(a)}`,{method:"DELETE"})).deleted,listFiles:async()=>(await h(`${t}${S}/tables/files/rows?limit=200`,await s())).rows.map(a=>({id:a.rowId,filename:String(a.data.filename??""),source:String(a.data.source??"client"),campaign:String(a.data.campaign??""),size:typeof a.data.size=="number"?a.data.size:0,createdAt:a.createdAt})),uploadFile:async(o,a)=>{let i=new Uint8Array(await o.arrayBuffer());return await n("/files",{method:"POST",body:{filename:o.name,mime:o.type||"application/octet-stream",data:Fe(i),...a===void 0?{}:{message:a}}})},fileLink:async o=>await h(`${t}${S}/files/${encodeURIComponent(o)}/url`,await s()),deleteFile:async o=>(await n(`/files/${encodeURIComponent(o)}`,{method:"DELETE"})).deleted,listDocuments:async()=>(await h(`${t}${S}/documents`,await s())).documents,readDocument:async o=>(await h(`${t}${S}/documents/${encodeURIComponent(o)}`,await s())).document,saveDocument:async(o,a)=>await n(`/documents/${encodeURIComponent(o)}`,{method:"PATCH",body:a})}};var x=require("react"),ue="greeting";function V(e,t){if(e.some(n=>n.id===t.id))return e;let r=e.filter(n=>n.id!==ue);return[...t.author==="client"?r.filter(n=>!(n.pending&&n.author==="client"&&n.text===t.text)):r,t]}var pe=(e,t)=>{let[r,s]=(0,x.useState)([]),[n,l]=(0,x.useState)(""),[o,a]=(0,x.useState)(!1),[i,d]=(0,x.useState)(null),u=(0,x.useRef)(0),b=t?.pollMs??2e3;(0,x.useEffect)(()=>{let p=!0;return e.getInfo().then(m=>{p&&m.greeting&&s(g=>g.length===0?[{id:ue,cursor:"",author:"agent",text:m.greeting}]:g)}).catch(()=>{}),()=>{p=!1}},[e]),(0,x.useEffect)(()=>e.subscribe?.({onMessage:p=>s(m=>V(m,p)),onError:p=>d(p.error),onHealthy:()=>d(null)},{intervalMs:b}),[e,b]);let c=(0,x.useCallback)(()=>{let p=n.trim();if(!p||o)return;l(""),d(null),a(!0),u.current+=1;let m={id:`pending-${u.current}`,cursor:"",author:"client",text:p,pending:!0};s(g=>[...g,m]),e.sendMessage(p).then(()=>a(!1)).catch(g=>{d(g instanceof Error?g.message:"send_failed"),a(!1)})},[n,o,e]);return{messages:r,input:n,setInput:l,send:c,sending:o,error:i}};0&&(module.exports={Chat,HolaProvider,PortalConflict,createApiTransport,createHolaClient,createPortalData,createWidgetTransport,deriveFields,inferSpec,layoutGroups,mergeMessage,parseDashboardSpec,renderModel,textDeltaOf,thinkingDeltaOf,toolEventOf,useArtifactUrl,useChat,useHolaClient,useThread,widgetSpan});
8
+ `)}},u=async()=>{let d=await a.read();if(!d.done)return i+=n.decode(d.value,{stream:!0}),l(),u()};await u()};var Ue=/\/+$/,W="/api/v1/end-user",me=e=>{let t=e.baseUrl.replace(Ue,""),o=()=>typeof e.token=="function"?e.token():e.token,s=n=>e.project?`${n}project=${encodeURIComponent(e.project)}`:"",r=async()=>({"content-type":"application/json",authorization:`Bearer ${await o()}`}),a=async n=>{let i=await fetch(`${t}${W}/chat${s("?")}`,{method:"POST",headers:await r(),body:JSON.stringify({message:n})});if(!i.ok)throw new Error(`hola: message failed (${i.status})`);return{reply:(await i.json()).reply??"",sessionId:"",artifacts:[]}};return{sessionId:()=>"",getInfo:async()=>h(`${t}${W}/chat/info${s("?")}`,await r()),sendMessage:a,streamMessage:async(n,i)=>{try{let l=await a(n);i.onText?.(l.reply),i.onComplete?.(l)}catch(l){i.onError?.(D(l))}},subscribe:(n,i)=>{let l=i?.since??"0",u=!1,d,b=i?.intervalMs??3e3,c=async()=>{try{let f=await h(`${t}${W}/chat/thread?since=${encodeURIComponent(l)}${s("&")}`,await r());for(let m of f.messages)n.onMessage(m);l=f.cursor,n.onHealthy?.()}catch(f){n.onError?.(D(f))}u||(d=setTimeout(c,b))},p=()=>{u=!0,d&&clearTimeout(d)};return i?.signal?.addEventListener("abort",p),d=setTimeout(c,0),p},requestHuman:async()=>{await fetch(`${t}${W}/chat/request-human${s("?")}`,{method:"POST",headers:await r(),body:"{}"})}}};var A=require("react"),E=(e,t)=>{let[o,s]=(0,A.useState)("");return(0,A.useEffect)(()=>{if(!e){s("");return}let r=Uint8Array.from(atob(e),n=>n.charCodeAt(0)),a=URL.createObjectURL(new Blob([r],{type:t}));return s(a),()=>URL.revokeObjectURL(a)},[e,t]),o};var U=require("react");var $=require("react"),ye=require("react/jsx-runtime"),fe=(0,$.createContext)(null),ge=({client:e,children:t})=>(0,ye.jsx)(fe.Provider,{value:e,children:t}),O=()=>{let e=(0,$.useContext)(fe);if(!e)throw new Error("useHolaClient must be used within <HolaProvider>");return e};var w=require("react"),_=e=>{let[t,o]=(0,w.useState)([]),[s,r]=(0,w.useState)(""),[a,n]=(0,w.useState)(!1),[i,l]=(0,w.useState)(null),u=(0,w.useRef)(0),d=(0,w.useCallback)(()=>{let c=u.current;return u.current+=1,c},[]);(0,w.useEffect)(()=>{let c=!0;return e.getInfo().then(p=>{c&&p.greeting&&o([{id:d(),role:"assistant",text:p.greeting}])}).catch(()=>{}),()=>{c=!1}},[e,d]);let b=(0,w.useCallback)(()=>{let c=s.trim();if(!c||a)return;r(""),l(null),n(!0);let p=d(),f=d();o(g=>[...g,{id:p,role:"user",text:c},{id:f,role:"assistant",text:"",streaming:!0}]);let m=g=>{o(v=>v.map(J=>J.id===f?g(J):J))};e.streamMessage(c,{onText:g=>m(v=>({...v,text:v.text+g})),onComplete:g=>{m(v=>({...v,text:g.reply||v.text,artifacts:g.artifacts,streaming:!1})),n(!1)},onError:g=>{m(v=>({...v,streaming:!1})),l(g.error),n(!1)}}).catch(g=>{m(v=>({...v,streaming:!1})),l(g instanceof Error?g.message:"stream_failed"),n(!1)})},[s,a,e,d]);return{messages:t,input:s,setInput:r,send:b,sending:a,error:i}};var y=require("react/jsx-runtime"),k={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"}},Fe=({artifact:e})=>{let t=E(e.dataBase64??"",e.mimeType),o=e.url??t;return o?e.mimeType.startsWith("image/")?(0,y.jsx)("a",{href:o,rel:"noopener noreferrer",target:"_blank",children:(0,y.jsx)("img",{alt:e.filename,src:o,style:k.image})}):(0,y.jsx)("a",{download:e.filename,href:o,style:k.link,children:e.filename}):null},be=()=>{let e=O(),{messages:t,input:o,setInput:s,send:r,sending:a,error:n}=_(e),i=(0,U.useRef)(null);(0,U.useEffect)(()=>{let u=i.current;u&&(u.scrollTop=u.scrollHeight)},[t]);let l=u=>{u.preventDefault(),r()};return(0,y.jsxs)("div",{style:k.root,children:[(0,y.jsx)("div",{ref:i,style:k.log,children:t.map(u=>(0,y.jsxs)("div",{style:u.role==="user"?k.user:k.assistant,children:[u.text||(u.streaming?"\u2026":""),u.artifacts&&u.artifacts.length>0?(0,y.jsx)("div",{style:k.artifacts,children:u.artifacts.map(d=>(0,y.jsx)(Fe,{artifact:d},d.filename))}):null]},u.id))}),n?(0,y.jsx)("div",{style:k.error,children:n}):null,(0,y.jsxs)("form",{onSubmit:l,style:k.form,children:[(0,y.jsx)("input",{"aria-label":"Message",onChange:u=>s(u.target.value),placeholder:"Type a message\u2026",style:k.input,value:o}),(0,y.jsx)("button",{disabled:a||o.trim().length===0,style:k.button,type:"submit",children:"Send"})]})]})};var Le=/\/+$/,F=e=>{let t=e.sessionId,o=e.baseUrl.replace(Le,""),s=n=>`${o}/endpoint/${encodeURIComponent(e.token)}${n}`,r={"content-type":"application/json"},a=(n,i)=>({url:s(n),headers:r,body:JSON.stringify({message:i,...t?{sessionId:t}:{},...e.identity?{externalUserId:e.identity.externalUserId,userHmac:e.identity.userHmac}:{}})});return{sessionId:()=>t,getInfo:()=>h(s("/config"),{}),sendMessage:async n=>{let i=await pe(a("/message",n));return t=i.sessionId,i},streamMessage:(n,i,l)=>ce(a("/message/stream",n),i,u=>{t=u},l),subscribe:(n,i)=>{let l=i?.since??"0",u=!1,d,b=i?.intervalMs??3e3,c=async()=>{let f=t;if(f)try{let m=await h(s(`/messages?session=${encodeURIComponent(f)}&since=${encodeURIComponent(l)}`),{});for(let g of m.messages)n.onMessage(g);l=m.cursor,n.onHealthy?.()}catch(m){n.onError?.(D(m))}u||(d=setTimeout(c,b))},p=()=>{u=!0,d&&clearTimeout(d)};return i?.signal?.addEventListener("abort",p),d=setTimeout(c,0),p},requestHuman:async()=>{t&&await fetch(s("/request-human"),{method:"POST",headers:r,body:JSON.stringify({sessionId:t})})}}};var he=e=>"transport"in e?e.transport:F(e);var Ne=/^https?:\/\//i,Be=/^\d{4}-\d{2}-\d{2}(?:[T ]|$)/,je=e=>e.replace(/_/g," ").replace(/\b\w/g,t=>t.toUpperCase());function Ve(e){if(typeof e=="number")return"number";if(typeof e=="boolean")return"boolean";if(typeof e=="string"){if(Ne.test(e))return"url";if(Be.test(e))return"date"}return"text"}function X(e){let t=[],o=new Map;for(let s of e)for(let[r,a]of Object.entries(s.data??{})){if(a==null)continue;let n=o.get(r);n||(n=new Map,o.set(r,n),t.push(r));let i=Ve(a);n.set(i,(n.get(i)??0)+1)}return t.map(s=>{let r=o.get(s)??new Map,a="text",n=-1;for(let[i,l]of r)l>n&&(n=l,a=i);return{key:s,label:je(s),type:a}})}var Ge=e=>typeof e=="number"?e:Number(e)||0,we=e=>/rate|position|rank|score|percent|avg/i.test(e),ze=/posted|published|sent|completed|shipped|launched|_at|date/i,Je=new Set(["service","order","end_user_id"]);function K(e,t){let o=e.filter(l=>!Je.has(l.key)),s=o.filter(l=>l.type==="number").slice(0,3),r=o.find(l=>l.key==="status")??o.find(l=>l.type==="select"),a=o.find(l=>l.type==="date"&&ze.test(l.key))??o.find(l=>l.type==="date"),n=o.filter(l=>l.type==="number"&&!we(l.key)).map(l=>({field:l,total:t.reduce((u,d)=>u+Ge(d.data[l.key]),0)})).sort((l,u)=>u.total-l.total).find(l=>l.total>0)?.field??null,i=[{type:"stat",label:"Items",agg:"count"}];for(let l of s){let u=we(l.key);i.push({type:"stat",metric:l.key,agg:u?"avg":"sum",label:u?`Avg ${l.label.toLowerCase()}`:l.label})}return a&&i.push({type:"line",x:a.key,y:n?.key,agg:"sum",title:n?`${n.label} by day`:"Items by day"}),r&&i.push({type:"donut",groupBy:r.key,title:r.label}),i.push({type:"table",columns:o.map(l=>l.key)}),{version:1,widgets:i}}var xe={stat:{span:1,h:1},chart:{span:2,h:2},block:{span:0,h:0}},L=6,N=4,qe=e=>Math.max(1,Math.min(L,Math.round(e))),Xe=e=>Math.max(1,Math.min(N,Math.round(e)));function B(e){return e==="stat"?"stat":e==="series"||e==="donut"?"chart":"block"}function Y(e){return e==="stat"?"stat":e==="line"||e==="bar"||e==="donut"?"chart":"block"}function Q(e){return xe[e]}function j(e,t,o){let s=xe[e];return{span:t===void 0?s.span:qe(t),h:o===void 0?s.h:Xe(o)}}function Z(e){let t=[],o=null;for(let s of e){let r=B(s.kind);if(r==="block"){t.push({kind:"block",widget:s}),o=null;continue}let a=j(r,s.w,s.h),n={widget:s,span:a.span,h:a.h,band:r};o?o.cells.push(n):(o={kind:"grid",cells:[n]},t.push(o))}return t}var ve=new Set(["service","order","end_user_id"]),ke=e=>typeof e=="number"?e:Number(e)||0,Te=e=>e==null?"":String(e);function De(e,t){if(e==="count")return t.length;if(t.length===0)return 0;if(e==="last")return t[t.length-1]??0;if(e==="min")return Math.min(...t);if(e==="max")return Math.max(...t);let o=t.reduce((s,r)=>s+r,0);return e==="avg"?Math.round(o/t.length):o}function Ke(e,t,o,s){let r=new Map;for(let a of e){let n=new Date(Te(a.data[t]));if(Number.isNaN(n.getTime()))continue;let i=n.toISOString().slice(0,10),l=r.get(i)??[];l.push(o?ke(a.data[o]):1),r.set(i,l)}return[...r.entries()].sort((a,n)=>a[0]<n[0]?-1:1).map(([a,n])=>({label:new Date(`${a}T00:00:00`).toLocaleDateString(void 0,{month:"short",day:"numeric"}),value:o?De(s,n):n.length}))}function Ye(e,t){let o=new Map;for(let s of e){let r=Te(s.data[t]).trim();r&&o.set(r,(o.get(r)??0)+1)}return[...o.entries()].sort((s,r)=>r[1]-s[1]).map(([s,r])=>({label:s,value:r}))}function Qe(e,t,o,s){switch(e.type){case"stat":{let r=e.metric?t.get(e.metric):void 0;if(e.metric&&!r)return null;if(!r)return{kind:"stat",label:e.label??"Items",value:s.length};let a=s.map(n=>ke(n.data[r.key]));return{kind:"stat",label:e.label??r.label,value:De(e.agg??"sum",a)}}case"line":case"bar":{if(!t.has(e.x)||e.y&&!t.has(e.y))return null;let r=Ke(s,e.x,e.y,e.agg??"sum");return r.length<2?null:{kind:"series",draw:e.type,title:e.title??"By day",points:r}}case"donut":{if(!t.has(e.groupBy))return null;let r=Ye(s,e.groupBy);return r.length===0?null:{kind:"donut",title:e.title??t.get(e.groupBy)?.label??"Breakdown",points:r}}case"table":{let r=e.columns?e.columns.map(a=>t.get(a)).filter(a=>a!==void 0&&!ve.has(a.key)):o;return r.length===0?null:{kind:"table",title:e.title,columns:r,rows:s}}case"text":return{kind:"text",title:e.title,body:e.body};default:return null}}function ee(e,t,o){let s=t.filter(n=>!ve.has(n.key)),r=new Map(t.map(n=>[n.key,n])),a=[];for(let n of e.widgets){let i=Qe(n,r,s,o);i&&a.push({...i,w:n.w,h:n.h})}return a}var Ze=new Set(["sum","avg","count","min","max","last"]),Se=e=>typeof e=="string"&&Ze.has(e)?e:void 0,T=e=>typeof e=="string"&&e!==""?e:void 0,C=e=>typeof e=="number"&&e>=1?Math.min(6,Math.round(e)):void 0,R=e=>typeof e=="number"&&e>=1?Math.min(4,Math.round(e)):void 0;function et(e){if(typeof e!="object"||e===null)return null;let t=e;switch(t.type){case"stat":return{type:"stat",label:T(t.label),metric:T(t.metric),agg:Se(t.agg),w:C(t.w),h:R(t.h)};case"line":case"bar":{let o=T(t.x);return o?{type:t.type,title:T(t.title),x:o,y:T(t.y),agg:Se(t.agg),w:C(t.w),h:R(t.h)}:null}case"donut":{let o=T(t.groupBy);return o?{type:"donut",title:T(t.title),groupBy:o,w:C(t.w),h:R(t.h)}:null}case"table":{let o=Array.isArray(t.columns)?t.columns.filter(s=>typeof s=="string"):void 0;return{type:"table",title:T(t.title),columns:o,w:C(t.w),h:R(t.h)}}case"text":{let o=T(t.body);return o?{type:"text",title:T(t.title),body:o,w:C(t.w),h:R(t.h)}:null}default:return null}}function te(e){let t=e;if(typeof e=="string"){if(e.trim()==="")return null;try{t=JSON.parse(e)}catch{return null}}if(typeof t!="object"||t===null)return null;let o=t.widgets;if(!Array.isArray(o))return null;let s=o.map(et).filter(a=>a!==null);if(s.length===0)return null;let r=t.version;return{version:typeof r=="number"?r:1,title:T(t.title),widgets:s}}function V(e){if(typeof e=="string")return e?{kind:"file",value:e}:null;if(e&&typeof e=="object"){let t=e,o=typeof t.value=="string"?t.value:"",s=t.kind==="link"||t.kind==="text"||t.kind==="table"?t.kind:"file",r=typeof t.v=="number"&&t.v>=1?Math.floor(t.v):void 0;return o?{kind:s,value:o,...r?{v:r}:{}}:null}return null}function G(e){let t=new Map;for(let o of e){let s=o.v??1,r=t.get(s)??[];r.push(o),t.set(s,r)}return[...t.entries()].sort(([o],[s])=>o-s).map(([o,s])=>({v:o,items:s}))}function ne(e){let t=e.files;if(typeof t=="string"&&t.trim()!=="")try{let s=JSON.parse(t);if(Array.isArray(s))return s.map(V).filter(r=>r!==null)}catch{}let o=String(e.file??"");return o?[{kind:"file",value:o}]:[]}function re(e,t,o){let r=(G(e).find(n=>n.v===t)?.items??[]).filter(n=>n.kind==="file").map(n=>n.value),a=r.map(n=>o.get(n)??"");return r.length===0||a.some(n=>n==="")?"awaiting":a.some(n=>n==="revise")?"revise":"accepted"}function oe(e){return Number(e.published_version)||0}function z(e){return e==="number"||e==="date"||e==="boolean"||e==="select"||e==="url"?e:e==="link"?"url":e==="checkbox"?"boolean":"text"}function se(e){try{let t=JSON.parse(e);if(Array.isArray(t.columns)&&Array.isArray(t.rows)&&t.columns.length){let o=t.columns.map((a,n)=>({key:typeof a.key=="string"&&a.key?a.key:typeof a.id=="string"&&a.id?a.id:`column_${n+1}`,label:typeof a.label=="string"?a.label:"",type:z(a.type)})),s=t.rows.map((a,n)=>({id:typeof a.id=="string"&&a.id?a.id:`row_${n}`,cells:a.cells&&typeof a.cells=="object"?a.cells:{}})),r=typeof t.name=="string"?t.name:void 0;return{columns:o,rows:s,...r?{name:r}:{}}}}catch{}return null}function ie(e){return e==null?"":String(e)}function ae(e){return e===!0||e==="true"||e==="1"||e==="yes"||e==="\u2713"}function le(e){let t=new Date(`${e}T00:00:00`);return Number.isNaN(t.getTime())?e:t.toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"})}var tt=/\/+$/,S="/api/v1/end-user",P=class extends Error{constructor(t){super(t),this.name="PortalConflict"}};function nt(e){let t="";for(let s=0;s<e.length;s+=32768)t+=String.fromCharCode(...e.subarray(s,s+32768));return btoa(t)}var Ce=e=>{let t=e.baseUrl.replace(tt,""),o=()=>typeof e.token=="function"?e.token():e.token,s=async()=>({"content-type":"application/json",authorization:`Bearer ${await o()}`}),r=async(n,i)=>{try{let l=await fetch(`${t}${S}${n}`,{method:i.method,headers:await s(),...i.body===void 0?{}:{body:JSON.stringify(i.body)}});if(l.status===409){let u=await l.json().catch(()=>({}));throw new P(u.message??"Someone else saved this first.")}if(!l.ok){let u=await l.text().catch(()=>""),d=`${i.method} ${n} \u2192 ${String(l.status)}`;try{let b=JSON.parse(u);b.message&&(d=b.message)}catch{d=u?`${d}: ${u}`:d}throw D(new Error(d))}return await l.json()}catch(l){throw D(l)}},a=n=>`/tables/${encodeURIComponent(n)}`;return{listTables:async()=>(await h(`${t}${S}/tables`,await s())).tables,listRows:async(n,i)=>await h(`${t}${S}${a(n)}/rows?limit=${String(i??100)}`,await s()),insertRow:async(n,i)=>{let{rowIds:l}=await r(`${a(n)}/rows`,{method:"POST",body:{rows:[i]}}),u=l[0];if(!u)throw D(new Error("The row was not created."));return u},patchRow:async(n,i,l)=>(await r(`${a(n)}/rows/${encodeURIComponent(i)}`,{method:"PATCH",body:l})).updated,deleteRow:async(n,i)=>(await r(`/${encodeURIComponent(n)}/${encodeURIComponent(i)}`,{method:"DELETE"})).deleted,listFiles:async()=>(await h(`${t}${S}/tables/files/rows?limit=200`,await s())).rows.map(i=>({id:i.rowId,filename:String(i.data.filename??""),source:String(i.data.source??"client"),campaign:String(i.data.campaign??""),size:typeof i.data.size=="number"?i.data.size:0,createdAt:i.createdAt})),uploadFile:async(n,i)=>{let l=new Uint8Array(await n.arrayBuffer());return await r("/files",{method:"POST",body:{filename:n.name,mime:n.type||"application/octet-stream",data:nt(l),...i===void 0?{}:{message:i}}})},fileLink:async n=>await h(`${t}${S}/files/${encodeURIComponent(n)}/url`,await s()),deleteFile:async n=>(await r(`/files/${encodeURIComponent(n)}`,{method:"DELETE"})).deleted,listDocuments:async()=>(await h(`${t}${S}/documents`,await s())).documents,readDocument:async n=>(await h(`${t}${S}/documents/${encodeURIComponent(n)}`,await s())).document,saveDocument:async(n,i)=>await r(`/documents/${encodeURIComponent(n)}`,{method:"PATCH",body:i})}};var x=require("react"),Re="greeting";function ue(e,t){if(e.some(r=>r.id===t.id))return e;let o=e.filter(r=>r.id!==Re);return[...t.author==="client"?o.filter(r=>!(r.pending&&r.author==="client"&&r.text===t.text)):o,t]}var Pe=(e,t)=>{let[o,s]=(0,x.useState)([]),[r,a]=(0,x.useState)(""),[n,i]=(0,x.useState)(!1),[l,u]=(0,x.useState)(null),d=(0,x.useRef)(0),b=t?.pollMs??2e3;(0,x.useEffect)(()=>{let p=!0;return e.getInfo().then(f=>{p&&f.greeting&&s(m=>m.length===0?[{id:Re,cursor:"",author:"agent",text:f.greeting}]:m)}).catch(()=>{}),()=>{p=!1}},[e]),(0,x.useEffect)(()=>e.subscribe?.({onMessage:p=>s(f=>ue(f,p)),onError:p=>u(p.error),onHealthy:()=>u(null)},{intervalMs:b}),[e,b]);let c=(0,x.useCallback)(()=>{let p=r.trim();if(!p||n)return;a(""),u(null),i(!0),d.current+=1;let f={id:`pending-${d.current}`,cursor:"",author:"client",text:p,pending:!0};s(m=>[...m,f]),e.sendMessage(p).then(()=>i(!1)).catch(m=>{u(m instanceof Error?m.message:"send_failed"),i(!1)})},[r,n,e]);return{messages:o,input:r,setInput:a,send:c,sending:n,error:l}};0&&(module.exports={Chat,GRID_MAX_COLS,GRID_MAX_ROWS,HolaProvider,PortalConflict,bandOfKind,bandOfType,createApiTransport,createHolaClient,createPortalData,createWidgetTransport,deliverableCellText,deliverableStatus,deriveFields,footprintOf,footprintWith,formatDeliverableDate,groupDeliverableVersions,inferSpec,isDeliverableChecked,layoutSegments,mergeMessage,normalizeDeliverableColType,normalizeDeliverableItem,parseDashboardSpec,parseDeliverableItems,parseDeliverableTable,publishedVersionOf,renderModel,textDeltaOf,thinkingDeltaOf,toolEventOf,useArtifactUrl,useChat,useHolaClient,useThread});
package/dist/index.d.cts CHANGED
@@ -307,6 +307,7 @@ interface StatWidget {
307
307
  metric?: string | undefined;
308
308
  agg?: Agg | undefined;
309
309
  w?: number | undefined;
310
+ h?: number | undefined;
310
311
  }
311
312
  /** A time series: `y` (a numeric column) aggregated per day of `x` (a date column); omit `y` to count
312
313
  * rows per day. `line` and `bar` differ only in how the renderer draws the same points. */
@@ -317,6 +318,7 @@ interface SeriesWidget {
317
318
  y?: string | undefined;
318
319
  agg?: Agg | undefined;
319
320
  w?: number | undefined;
321
+ h?: number | undefined;
320
322
  }
321
323
  /** A breakdown: the count of rows per distinct value of `groupBy`. */
322
324
  interface DonutWidget {
@@ -324,6 +326,7 @@ interface DonutWidget {
324
326
  title?: string | undefined;
325
327
  groupBy: string;
326
328
  w?: number | undefined;
329
+ h?: number | undefined;
327
330
  }
328
331
  /** A row table: `columns` (by key, in order) or every non-plumbing column when omitted. */
329
332
  interface TableWidget {
@@ -331,6 +334,7 @@ interface TableWidget {
331
334
  title?: string | undefined;
332
335
  columns?: string[] | undefined;
333
336
  w?: number | undefined;
337
+ h?: number | undefined;
334
338
  }
335
339
  /** Static prose — a note above or between the data widgets. */
336
340
  interface TextWidget {
@@ -338,6 +342,7 @@ interface TextWidget {
338
342
  title?: string | undefined;
339
343
  body: string;
340
344
  w?: number | undefined;
345
+ h?: number | undefined;
341
346
  }
342
347
  type Widget = StatWidget | SeriesWidget | DonutWidget | TableWidget | TextWidget;
343
348
  interface DashboardSpec {
@@ -363,57 +368,144 @@ type ResolvedWidget = {
363
368
  label: string;
364
369
  value: number;
365
370
  w?: number | undefined;
371
+ h?: number | undefined;
366
372
  } | {
367
373
  kind: "series";
368
374
  draw: "line" | "bar";
369
375
  title: string;
370
376
  points: Point[];
371
377
  w?: number | undefined;
378
+ h?: number | undefined;
372
379
  } | {
373
380
  kind: "donut";
374
381
  title: string;
375
382
  points: Point[];
376
383
  w?: number | undefined;
384
+ h?: number | undefined;
377
385
  } | {
378
386
  kind: "table";
379
387
  title?: string | undefined;
380
388
  columns: PortalField[];
381
389
  rows: PortalRow[];
382
390
  w?: number | undefined;
391
+ h?: number | undefined;
383
392
  } | {
384
393
  kind: "text";
385
394
  title?: string | undefined;
386
395
  body: string;
387
396
  w?: number | undefined;
397
+ h?: number | undefined;
388
398
  };
389
399
  /** Resolve a whole spec against the data. The result is render-ready and free of widgets that would
390
400
  * draw nothing. */
391
401
  declare function renderModel(spec: DashboardSpec, fields: PortalField[], rows: PortalRow[]): ResolvedWidget[];
392
- /** The column span (1–4, in a 4-col grid) a widget occupies: its explicit `w` clamped, else a sensible
393
- * default by its layout run — a stat is a quarter (1); a chart is full (4) on its own row or a half
394
- * (2) when it shares one; a table or note is full (4). Apps map the number to their own grid classes,
395
- * so the operator console and the customer portal lay a dashboard out identically. */
396
- declare function widgetSpan(explicit: number | undefined, run: "stat" | "chart" | "block", alone: boolean): number;
397
402
 
403
+ type Band = "stat" | "chart" | "block";
398
404
  type StatView = Extract<ResolvedWidget, {
399
405
  kind: "stat";
400
406
  }>;
401
407
  type ChartView = Extract<ResolvedWidget, {
402
408
  kind: "series" | "donut";
403
409
  }>;
404
- type LayoutGroup = {
405
- kind: "stats";
406
- items: StatView[];
407
- } | {
408
- kind: "charts";
409
- items: ChartView[];
410
+ declare const GRID_MAX_COLS = 6;
411
+ declare const GRID_MAX_ROWS = 4;
412
+ /** The band a resolved widget belongs to. */
413
+ declare function bandOfKind(kind: ResolvedWidget["kind"]): Band;
414
+ /** The band a spec widget TYPE belongs to — for the editor canvas, which lays out widgets before they
415
+ * resolve (a half-configured widget still needs a cell). Mirrors bandOfKind. */
416
+ declare function bandOfType(type: WidgetType): Band;
417
+ /** A band's fixed bento footprint — `span` cells wide × `h` cells tall. The editable canvas lays out
418
+ * spec widgets before they resolve, so it reads this directly to match the rendered dashboard. */
419
+ declare function footprintOf(band: Band): {
420
+ span: number;
421
+ h: number;
422
+ };
423
+ /** A widget's effective footprint: its hand-dragged `w`×`h` override (clamped to the grid), else the
424
+ * band default. The renderers and the editable canvas both size cells through this, so a resized
425
+ * widget looks the same everywhere. */
426
+ declare function footprintWith(band: Band, w: number | undefined, h: number | undefined): {
427
+ span: number;
428
+ h: number;
429
+ };
430
+ /** A resolved widget placed in the grid — the view-model plus its cell footprint (column span `span`,
431
+ * row span `h`) and band, ready to render. */
432
+ interface LaidOutWidget {
433
+ widget: ResolvedWidget;
434
+ span: number;
435
+ h: number;
436
+ band: Band;
437
+ }
438
+ /** A run of the dashboard: either a fixed-cell BENTO grid (stats + charts, whose cells are squares
439
+ * that align to the grid), or a full-width BLOCK (a table/note, whose height is its content). Splitting
440
+ * them keeps the fixed grid strict — a variable-height table never gets crammed into a fixed cell —
441
+ * while everything that snaps to a cell, does. Order is preserved. */
442
+ type LayoutSegment = {
443
+ kind: "grid";
444
+ cells: LaidOutWidget[];
410
445
  } | {
411
446
  kind: "block";
412
- item: ResolvedWidget;
447
+ widget: ResolvedWidget;
448
+ };
449
+ /** Arrange resolved widgets into bento segments: consecutive stats/charts coalesce into one grid (a
450
+ * flat run of cells — the renderer flows them into the 4-cell rows); each table/note becomes its own
451
+ * full-width block. This is the arrangement every surface renders, so a dashboard reads identically
452
+ * everywhere. */
453
+ declare function layoutSegments(resolved: ResolvedWidget[]): LayoutSegment[];
454
+
455
+ type DeliverableItemKind = "file" | "link" | "text" | "table";
456
+ type DeliverableItem = {
457
+ kind: DeliverableItemKind;
458
+ value: string;
459
+ /** Version this item was delivered in, numbered from 1 (absent = v1). */
460
+ v?: number;
461
+ };
462
+ /** One delivered version — a bundle of items sent together, numbered from 1. */
463
+ type DeliverableVersion = {
464
+ v: number;
465
+ items: DeliverableItem[];
466
+ };
467
+ declare function normalizeDeliverableItem(x: unknown): DeliverableItem | null;
468
+ declare function groupDeliverableVersions(items: DeliverableItem[]): DeliverableVersion[];
469
+ /** Parse a deliverable row's items from its `data`. Tolerant of the legacy single `file` field and of
470
+ * bare-string refs; returns [] when there is nothing. */
471
+ declare function parseDeliverableItems(data: Record<string, unknown>): DeliverableItem[];
472
+ type DeliverableReviewState = "awaiting" | "accepted" | "revise";
473
+ declare function deliverableStatus(items: DeliverableItem[], publishedVersion: number, verdictById: Map<string, string>): DeliverableReviewState;
474
+ /** The version the client currently sees — the EXPLICIT `published_version` pointer the operator set
475
+ * (0 = nothing published). No `done → latest` fallback: that followed the latest version, so a new
476
+ * version the team delivered would auto-appear to the client before it was published. */
477
+ declare function publishedVersionOf(data: Record<string, unknown>): number;
478
+
479
+ /** A column type. `select` is an open enum edited as text; the rest drive how a cell reads. */
480
+ type DeliverableColType = "text" | "number" | "url" | "date" | "boolean" | "select";
481
+ type DeliverableColumn = {
482
+ key: string;
483
+ label: string;
484
+ type: DeliverableColType;
485
+ };
486
+ type DeliverableRow = {
487
+ id: string;
488
+ cells: Record<string, unknown>;
489
+ };
490
+ type DeliverableTable = {
491
+ /** The operator's name for this table (e.g. "Twitter influencers"). Optional for older payloads. */
492
+ name?: string;
493
+ columns: DeliverableColumn[];
494
+ rows: DeliverableRow[];
413
495
  };
414
- /** Fold resolved widgets into layout groups: a run of adjacent stat tiles becomes one tile row, a run
415
- * of adjacent charts becomes one chart row, and a table or note stands alone. Order is preserved. */
416
- declare function layoutGroups(resolved: ResolvedWidget[]): LayoutGroup[];
496
+ /** Legacy tables used `link`/`checkbox`; the current vocabulary is `url`/`boolean`. */
497
+ declare function normalizeDeliverableColType(t: unknown): DeliverableColType;
498
+ /** Parse a table item's JSON `value` into the grid model, tolerating the legacy id-keyed shape (its
499
+ * columns carried `id` not `key`, so a legacy column keeps its cells by keying on that id). Returns
500
+ * null when `value` is not a table payload. */
501
+ declare function parseDeliverableTable(value: string): DeliverableTable | null;
502
+ /** A cell value as display text (a stored null/undefined reads as empty). */
503
+ declare function deliverableCellText(v: unknown): string;
504
+ /** Whether a `boolean` cell is checked — tolerant of a real boolean or the string forms it was stored
505
+ * as across versions. */
506
+ declare function isDeliverableChecked(v: unknown): boolean;
507
+ /** A `date` cell stores YYYY-MM-DD; format it as e.g. "Aug 18, 2026" (raw string if unparseable). */
508
+ declare function formatDeliverableDate(v: string): string;
417
509
 
418
510
  /** Extract a streamed text delta from a raw pi turn event, or null. */
419
511
  declare const textDeltaOf: (event: unknown) => string | null;
@@ -471,4 +563,4 @@ declare const useThread: (client: HolaClient, options?: {
471
563
  pollMs?: number;
472
564
  }) => UseThread;
473
565
 
474
- export { type Agg, type ApiTransportConfig, type ChartView, Chat, type ChatMessage, type CreateHolaClientOptions, type DashboardSpec, type DonutWidget, type HolaArtifact, type HolaAuthor, type HolaClient, type HolaCompletion, type HolaEmployeeInfo, type HolaError, type HolaIdentity, type HolaMessage, HolaProvider, type HolaStreamHandlers, type HolaSubscribeHandlers, type HolaSubscribeOptions, type HolaToolEvent, type HolaTransport, type LayoutGroup, type Point, PortalConflict, type PortalData, type PortalDocument, type PortalDocumentSummary, type PortalField, type PortalFile, type PortalRow, type PortalRowPage, type PortalTable, type ResolvedWidget, type SeriesWidget, type StatView, type StatWidget, type TableWidget, type TextWidget, type ThreadMessage, type UseChat, type UseThread, type Widget, type WidgetTransportConfig, type WidgetType, createApiTransport, createHolaClient, createPortalData, createWidgetTransport, deriveFields, inferSpec, layoutGroups, mergeMessage, parseDashboardSpec, renderModel, textDeltaOf, thinkingDeltaOf, toolEventOf, useArtifactUrl, useChat, useHolaClient, useThread, widgetSpan };
566
+ export { type Agg, type ApiTransportConfig, type Band, type ChartView, Chat, type ChatMessage, type CreateHolaClientOptions, type DashboardSpec, type DeliverableColType, type DeliverableColumn, type DeliverableItem, type DeliverableItemKind, type DeliverableReviewState, type DeliverableRow, type DeliverableTable, type DeliverableVersion, type DonutWidget, GRID_MAX_COLS, GRID_MAX_ROWS, type HolaArtifact, type HolaAuthor, type HolaClient, type HolaCompletion, type HolaEmployeeInfo, type HolaError, type HolaIdentity, type HolaMessage, HolaProvider, type HolaStreamHandlers, type HolaSubscribeHandlers, type HolaSubscribeOptions, type HolaToolEvent, type HolaTransport, type LaidOutWidget, type LayoutSegment, type Point, PortalConflict, type PortalData, type PortalDocument, type PortalDocumentSummary, type PortalField, type PortalFile, type PortalRow, type PortalRowPage, type PortalTable, type ResolvedWidget, type SeriesWidget, type StatView, type StatWidget, type TableWidget, type TextWidget, type ThreadMessage, type UseChat, type UseThread, type Widget, type WidgetTransportConfig, type WidgetType, bandOfKind, bandOfType, createApiTransport, createHolaClient, createPortalData, createWidgetTransport, deliverableCellText, deliverableStatus, deriveFields, footprintOf, footprintWith, formatDeliverableDate, groupDeliverableVersions, inferSpec, isDeliverableChecked, layoutSegments, mergeMessage, normalizeDeliverableColType, normalizeDeliverableItem, parseDashboardSpec, parseDeliverableItems, parseDeliverableTable, publishedVersionOf, renderModel, textDeltaOf, thinkingDeltaOf, toolEventOf, useArtifactUrl, useChat, useHolaClient, useThread };
package/dist/index.d.ts CHANGED
@@ -307,6 +307,7 @@ interface StatWidget {
307
307
  metric?: string | undefined;
308
308
  agg?: Agg | undefined;
309
309
  w?: number | undefined;
310
+ h?: number | undefined;
310
311
  }
311
312
  /** A time series: `y` (a numeric column) aggregated per day of `x` (a date column); omit `y` to count
312
313
  * rows per day. `line` and `bar` differ only in how the renderer draws the same points. */
@@ -317,6 +318,7 @@ interface SeriesWidget {
317
318
  y?: string | undefined;
318
319
  agg?: Agg | undefined;
319
320
  w?: number | undefined;
321
+ h?: number | undefined;
320
322
  }
321
323
  /** A breakdown: the count of rows per distinct value of `groupBy`. */
322
324
  interface DonutWidget {
@@ -324,6 +326,7 @@ interface DonutWidget {
324
326
  title?: string | undefined;
325
327
  groupBy: string;
326
328
  w?: number | undefined;
329
+ h?: number | undefined;
327
330
  }
328
331
  /** A row table: `columns` (by key, in order) or every non-plumbing column when omitted. */
329
332
  interface TableWidget {
@@ -331,6 +334,7 @@ interface TableWidget {
331
334
  title?: string | undefined;
332
335
  columns?: string[] | undefined;
333
336
  w?: number | undefined;
337
+ h?: number | undefined;
334
338
  }
335
339
  /** Static prose — a note above or between the data widgets. */
336
340
  interface TextWidget {
@@ -338,6 +342,7 @@ interface TextWidget {
338
342
  title?: string | undefined;
339
343
  body: string;
340
344
  w?: number | undefined;
345
+ h?: number | undefined;
341
346
  }
342
347
  type Widget = StatWidget | SeriesWidget | DonutWidget | TableWidget | TextWidget;
343
348
  interface DashboardSpec {
@@ -363,57 +368,144 @@ type ResolvedWidget = {
363
368
  label: string;
364
369
  value: number;
365
370
  w?: number | undefined;
371
+ h?: number | undefined;
366
372
  } | {
367
373
  kind: "series";
368
374
  draw: "line" | "bar";
369
375
  title: string;
370
376
  points: Point[];
371
377
  w?: number | undefined;
378
+ h?: number | undefined;
372
379
  } | {
373
380
  kind: "donut";
374
381
  title: string;
375
382
  points: Point[];
376
383
  w?: number | undefined;
384
+ h?: number | undefined;
377
385
  } | {
378
386
  kind: "table";
379
387
  title?: string | undefined;
380
388
  columns: PortalField[];
381
389
  rows: PortalRow[];
382
390
  w?: number | undefined;
391
+ h?: number | undefined;
383
392
  } | {
384
393
  kind: "text";
385
394
  title?: string | undefined;
386
395
  body: string;
387
396
  w?: number | undefined;
397
+ h?: number | undefined;
388
398
  };
389
399
  /** Resolve a whole spec against the data. The result is render-ready and free of widgets that would
390
400
  * draw nothing. */
391
401
  declare function renderModel(spec: DashboardSpec, fields: PortalField[], rows: PortalRow[]): ResolvedWidget[];
392
- /** The column span (1–4, in a 4-col grid) a widget occupies: its explicit `w` clamped, else a sensible
393
- * default by its layout run — a stat is a quarter (1); a chart is full (4) on its own row or a half
394
- * (2) when it shares one; a table or note is full (4). Apps map the number to their own grid classes,
395
- * so the operator console and the customer portal lay a dashboard out identically. */
396
- declare function widgetSpan(explicit: number | undefined, run: "stat" | "chart" | "block", alone: boolean): number;
397
402
 
403
+ type Band = "stat" | "chart" | "block";
398
404
  type StatView = Extract<ResolvedWidget, {
399
405
  kind: "stat";
400
406
  }>;
401
407
  type ChartView = Extract<ResolvedWidget, {
402
408
  kind: "series" | "donut";
403
409
  }>;
404
- type LayoutGroup = {
405
- kind: "stats";
406
- items: StatView[];
407
- } | {
408
- kind: "charts";
409
- items: ChartView[];
410
+ declare const GRID_MAX_COLS = 6;
411
+ declare const GRID_MAX_ROWS = 4;
412
+ /** The band a resolved widget belongs to. */
413
+ declare function bandOfKind(kind: ResolvedWidget["kind"]): Band;
414
+ /** The band a spec widget TYPE belongs to — for the editor canvas, which lays out widgets before they
415
+ * resolve (a half-configured widget still needs a cell). Mirrors bandOfKind. */
416
+ declare function bandOfType(type: WidgetType): Band;
417
+ /** A band's fixed bento footprint — `span` cells wide × `h` cells tall. The editable canvas lays out
418
+ * spec widgets before they resolve, so it reads this directly to match the rendered dashboard. */
419
+ declare function footprintOf(band: Band): {
420
+ span: number;
421
+ h: number;
422
+ };
423
+ /** A widget's effective footprint: its hand-dragged `w`×`h` override (clamped to the grid), else the
424
+ * band default. The renderers and the editable canvas both size cells through this, so a resized
425
+ * widget looks the same everywhere. */
426
+ declare function footprintWith(band: Band, w: number | undefined, h: number | undefined): {
427
+ span: number;
428
+ h: number;
429
+ };
430
+ /** A resolved widget placed in the grid — the view-model plus its cell footprint (column span `span`,
431
+ * row span `h`) and band, ready to render. */
432
+ interface LaidOutWidget {
433
+ widget: ResolvedWidget;
434
+ span: number;
435
+ h: number;
436
+ band: Band;
437
+ }
438
+ /** A run of the dashboard: either a fixed-cell BENTO grid (stats + charts, whose cells are squares
439
+ * that align to the grid), or a full-width BLOCK (a table/note, whose height is its content). Splitting
440
+ * them keeps the fixed grid strict — a variable-height table never gets crammed into a fixed cell —
441
+ * while everything that snaps to a cell, does. Order is preserved. */
442
+ type LayoutSegment = {
443
+ kind: "grid";
444
+ cells: LaidOutWidget[];
410
445
  } | {
411
446
  kind: "block";
412
- item: ResolvedWidget;
447
+ widget: ResolvedWidget;
448
+ };
449
+ /** Arrange resolved widgets into bento segments: consecutive stats/charts coalesce into one grid (a
450
+ * flat run of cells — the renderer flows them into the 4-cell rows); each table/note becomes its own
451
+ * full-width block. This is the arrangement every surface renders, so a dashboard reads identically
452
+ * everywhere. */
453
+ declare function layoutSegments(resolved: ResolvedWidget[]): LayoutSegment[];
454
+
455
+ type DeliverableItemKind = "file" | "link" | "text" | "table";
456
+ type DeliverableItem = {
457
+ kind: DeliverableItemKind;
458
+ value: string;
459
+ /** Version this item was delivered in, numbered from 1 (absent = v1). */
460
+ v?: number;
461
+ };
462
+ /** One delivered version — a bundle of items sent together, numbered from 1. */
463
+ type DeliverableVersion = {
464
+ v: number;
465
+ items: DeliverableItem[];
466
+ };
467
+ declare function normalizeDeliverableItem(x: unknown): DeliverableItem | null;
468
+ declare function groupDeliverableVersions(items: DeliverableItem[]): DeliverableVersion[];
469
+ /** Parse a deliverable row's items from its `data`. Tolerant of the legacy single `file` field and of
470
+ * bare-string refs; returns [] when there is nothing. */
471
+ declare function parseDeliverableItems(data: Record<string, unknown>): DeliverableItem[];
472
+ type DeliverableReviewState = "awaiting" | "accepted" | "revise";
473
+ declare function deliverableStatus(items: DeliverableItem[], publishedVersion: number, verdictById: Map<string, string>): DeliverableReviewState;
474
+ /** The version the client currently sees — the EXPLICIT `published_version` pointer the operator set
475
+ * (0 = nothing published). No `done → latest` fallback: that followed the latest version, so a new
476
+ * version the team delivered would auto-appear to the client before it was published. */
477
+ declare function publishedVersionOf(data: Record<string, unknown>): number;
478
+
479
+ /** A column type. `select` is an open enum edited as text; the rest drive how a cell reads. */
480
+ type DeliverableColType = "text" | "number" | "url" | "date" | "boolean" | "select";
481
+ type DeliverableColumn = {
482
+ key: string;
483
+ label: string;
484
+ type: DeliverableColType;
485
+ };
486
+ type DeliverableRow = {
487
+ id: string;
488
+ cells: Record<string, unknown>;
489
+ };
490
+ type DeliverableTable = {
491
+ /** The operator's name for this table (e.g. "Twitter influencers"). Optional for older payloads. */
492
+ name?: string;
493
+ columns: DeliverableColumn[];
494
+ rows: DeliverableRow[];
413
495
  };
414
- /** Fold resolved widgets into layout groups: a run of adjacent stat tiles becomes one tile row, a run
415
- * of adjacent charts becomes one chart row, and a table or note stands alone. Order is preserved. */
416
- declare function layoutGroups(resolved: ResolvedWidget[]): LayoutGroup[];
496
+ /** Legacy tables used `link`/`checkbox`; the current vocabulary is `url`/`boolean`. */
497
+ declare function normalizeDeliverableColType(t: unknown): DeliverableColType;
498
+ /** Parse a table item's JSON `value` into the grid model, tolerating the legacy id-keyed shape (its
499
+ * columns carried `id` not `key`, so a legacy column keeps its cells by keying on that id). Returns
500
+ * null when `value` is not a table payload. */
501
+ declare function parseDeliverableTable(value: string): DeliverableTable | null;
502
+ /** A cell value as display text (a stored null/undefined reads as empty). */
503
+ declare function deliverableCellText(v: unknown): string;
504
+ /** Whether a `boolean` cell is checked — tolerant of a real boolean or the string forms it was stored
505
+ * as across versions. */
506
+ declare function isDeliverableChecked(v: unknown): boolean;
507
+ /** A `date` cell stores YYYY-MM-DD; format it as e.g. "Aug 18, 2026" (raw string if unparseable). */
508
+ declare function formatDeliverableDate(v: string): string;
417
509
 
418
510
  /** Extract a streamed text delta from a raw pi turn event, or null. */
419
511
  declare const textDeltaOf: (event: unknown) => string | null;
@@ -471,4 +563,4 @@ declare const useThread: (client: HolaClient, options?: {
471
563
  pollMs?: number;
472
564
  }) => UseThread;
473
565
 
474
- export { type Agg, type ApiTransportConfig, type ChartView, Chat, type ChatMessage, type CreateHolaClientOptions, type DashboardSpec, type DonutWidget, type HolaArtifact, type HolaAuthor, type HolaClient, type HolaCompletion, type HolaEmployeeInfo, type HolaError, type HolaIdentity, type HolaMessage, HolaProvider, type HolaStreamHandlers, type HolaSubscribeHandlers, type HolaSubscribeOptions, type HolaToolEvent, type HolaTransport, type LayoutGroup, type Point, PortalConflict, type PortalData, type PortalDocument, type PortalDocumentSummary, type PortalField, type PortalFile, type PortalRow, type PortalRowPage, type PortalTable, type ResolvedWidget, type SeriesWidget, type StatView, type StatWidget, type TableWidget, type TextWidget, type ThreadMessage, type UseChat, type UseThread, type Widget, type WidgetTransportConfig, type WidgetType, createApiTransport, createHolaClient, createPortalData, createWidgetTransport, deriveFields, inferSpec, layoutGroups, mergeMessage, parseDashboardSpec, renderModel, textDeltaOf, thinkingDeltaOf, toolEventOf, useArtifactUrl, useChat, useHolaClient, useThread, widgetSpan };
566
+ export { type Agg, type ApiTransportConfig, type Band, type ChartView, Chat, type ChatMessage, type CreateHolaClientOptions, type DashboardSpec, type DeliverableColType, type DeliverableColumn, type DeliverableItem, type DeliverableItemKind, type DeliverableReviewState, type DeliverableRow, type DeliverableTable, type DeliverableVersion, type DonutWidget, GRID_MAX_COLS, GRID_MAX_ROWS, type HolaArtifact, type HolaAuthor, type HolaClient, type HolaCompletion, type HolaEmployeeInfo, type HolaError, type HolaIdentity, type HolaMessage, HolaProvider, type HolaStreamHandlers, type HolaSubscribeHandlers, type HolaSubscribeOptions, type HolaToolEvent, type HolaTransport, type LaidOutWidget, type LayoutSegment, type Point, PortalConflict, type PortalData, type PortalDocument, type PortalDocumentSummary, type PortalField, type PortalFile, type PortalRow, type PortalRowPage, type PortalTable, type ResolvedWidget, type SeriesWidget, type StatView, type StatWidget, type TableWidget, type TextWidget, type ThreadMessage, type UseChat, type UseThread, type Widget, type WidgetTransportConfig, type WidgetType, bandOfKind, bandOfType, createApiTransport, createHolaClient, createPortalData, createWidgetTransport, deliverableCellText, deliverableStatus, deriveFields, footprintOf, footprintWith, formatDeliverableDate, groupDeliverableVersions, inferSpec, isDeliverableChecked, layoutSegments, mergeMessage, normalizeDeliverableColType, normalizeDeliverableItem, parseDashboardSpec, parseDeliverableItems, parseDeliverableTable, publishedVersionOf, renderModel, textDeltaOf, thinkingDeltaOf, toolEventOf, useArtifactUrl, useChat, useHolaClient, useThread };
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},E=e=>{let t=O(e);return t?.type==="text_delta"&&typeof t.delta=="string"?t.delta:null},M=e=>{let t=O(e);return t?.type==="thinking_delta"&&typeof t.delta=="string"?t.delta:null},$=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 oe=/^ /,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"}},se=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(oe,"")));return n.length>0?{event:t,data:n.join(`
4
- `)}:null},ae=(e,t,n)=>{let s;try{s=JSON.parse(e.data)}catch{return}if(e.event==="session"){let o=s.sessionId;o&&(n(o),t.onSession?.(o));return}if(e.event==="turn_event"){t.onEvent?.(s);let o=E(s);o&&t.onText?.(o);let l=M(s);l&&t.onThinking?.(l);let r=$(s);r&&t.onTool?.(r);return}if(e.event==="chat_completed"){let o=s;n(o.sessionId),t.onComplete?.(o);return}e.event==="chat_error"&&t.onError?.(T(s))},b=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()},_=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()},L=async(e,t,n,s)=>{let o=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body,signal:s});if(!(o.ok&&o.body)){t.onError?.({error:`stream_failed_${o.status}`});return}let l=o.body.getReader(),r=new TextDecoder,a="",i=()=>{let u=a.indexOf(`
2
+ var z=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="message_update"?t.assistantMessageEvent??null:null},M=e=>{let t=z(e);return t?.type==="text_delta"&&typeof t.delta=="string"?t.delta:null},W=e=>{let t=z(e);return t?.type==="thinking_delta"&&typeof t.delta=="string"?t.delta:null},A=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 ve=/^ /,v=e=>{if(e&&typeof e=="object"){let t=e,o=typeof t.error=="string"?t.error:"request_failed";return typeof t.retryable=="boolean"?{error:o,retryable:t.retryable}:{error:o}}return{error:"request_failed"}},ke=e=>{let t="message",o=[];for(let s of e.split(`
3
+ `))s.startsWith(":")||(s.startsWith("event:")?t=s.slice(6).trim():s.startsWith("data:")&&o.push(s.slice(5).replace(ve,"")));return o.length>0?{event:t,data:o.join(`
4
+ `)}:null},Te=(e,t,o)=>{let s;try{s=JSON.parse(e.data)}catch{return}if(e.event==="session"){let r=s.sessionId;r&&(o(r),t.onSession?.(r));return}if(e.event==="turn_event"){t.onEvent?.(s);let r=M(s);r&&t.onText?.(r);let a=W(s);a&&t.onThinking?.(a);let n=A(s);n&&t.onTool?.(n);return}if(e.event==="chat_completed"){let r=s;o(r.sessionId),t.onComplete?.(r);return}e.event==="chat_error"&&t.onError?.(v(s))},b=async(e,t)=>{let o=await fetch(e,{headers:t});if(!o.ok)throw new Error(`hola: request failed (${o.status})`);return await o.json()},J=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()},q=async(e,t,o,s)=>{let r=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body,signal:s});if(!(r.ok&&r.body)){t.onError?.({error:`stream_failed_${r.status}`});return}let a=r.body.getReader(),n=new TextDecoder,i="",l=()=>{let d=i.indexOf(`
5
5
 
6
- `);for(;u!==-1;){let y=a.slice(0,u);a=a.slice(u+2);let c=se(y);c&&ae(c,t,n),u=a.indexOf(`
6
+ `);for(;d!==-1;){let y=i.slice(0,d);i=i.slice(d+2);let c=ke(y);c&&Te(c,t,o),d=i.indexOf(`
7
7
 
8
- `)}},d=async()=>{let u=await l.read();if(!u.done)return a+=r.decode(u.value,{stream:!0}),i(),d()};await d()};var ie=/\/+$/,S="/api/v1/end-user",le=e=>{let t=e.baseUrl.replace(ie,""),n=()=>typeof e.token=="function"?e.token():e.token,s=r=>e.project?`${r}project=${encodeURIComponent(e.project)}`:"",o=async()=>({"content-type":"application/json",authorization:`Bearer ${await n()}`}),l=async r=>{let a=await fetch(`${t}${S}/chat${s("?")}`,{method:"POST",headers:await o(),body:JSON.stringify({message:r})});if(!a.ok)throw new Error(`hola: message failed (${a.status})`);return{reply:(await a.json()).reply??"",sessionId:"",artifacts:[]}};return{sessionId:()=>"",getInfo:async()=>b(`${t}${S}/chat/info${s("?")}`,await o()),sendMessage:l,streamMessage:async(r,a)=>{try{let i=await l(r);a.onText?.(i.reply),a.onComplete?.(i)}catch(i){a.onError?.(T(i))}},subscribe:(r,a)=>{let i=a?.since??"0",d=!1,u,y=a?.intervalMs??3e3,c=async()=>{try{let m=await b(`${t}${S}/chat/thread?since=${encodeURIComponent(i)}${s("&")}`,await o());for(let g of m.messages)r.onMessage(g);i=m.cursor,r.onHealthy?.()}catch(m){r.onError?.(T(m))}d||(u=setTimeout(c,y))},p=()=>{d=!0,u&&clearTimeout(u)};return a?.signal?.addEventListener("abort",p),u=setTimeout(c,0),p},requestHuman:async()=>{await fetch(`${t}${S}/chat/request-human${s("?")}`,{method:"POST",headers:await o(),body:"{}"})}}};import{useEffect as de,useState as ue}from"react";var A=(e,t)=>{let[n,s]=ue("");return de(()=>{if(!e){s("");return}let o=Uint8Array.from(atob(e),r=>r.charCodeAt(0)),l=URL.createObjectURL(new Blob([o],{type:t}));return s(l),()=>URL.revokeObjectURL(l)},[e,t]),n};import{useEffect as be,useRef as he}from"react";import{createContext as pe,useContext as ce}from"react";import{jsx as me}from"react/jsx-runtime";var N=pe(null),ge=({client:e,children:t})=>me(N.Provider,{value:e,children:t}),W=()=>{let e=ce(N);if(!e)throw new Error("useHolaClient must be used within <HolaProvider>");return e};import{useCallback as j,useEffect as fe,useRef as ye,useState as C}from"react";var D=e=>{let[t,n]=C([]),[s,o]=C(""),[l,r]=C(!1),[a,i]=C(null),d=ye(0),u=j(()=>{let c=d.current;return d.current+=1,c},[]);fe(()=>{let c=!0;return e.getInfo().then(p=>{c&&p.greeting&&n([{id:u(),role:"assistant",text:p.greeting}])}).catch(()=>{}),()=>{c=!1}},[e,u]);let y=j(()=>{let c=s.trim();if(!c||l)return;o(""),i(null),r(!0);let p=u(),m=u();n(f=>[...f,{id:p,role:"user",text:c},{id:m,role:"assistant",text:"",streaming:!0}]);let g=f=>{n(h=>h.map(I=>I.id===m?f(I):I))};e.streamMessage(c,{onText:f=>g(h=>({...h,text:h.text+f})),onComplete:f=>{g(h=>({...h,text:f.reply||h.text,artifacts:f.artifacts,streaming:!1})),r(!1)},onError:f=>{g(h=>({...h,streaming:!1})),i(f.error),r(!1)}}).catch(f=>{g(h=>({...h,streaming:!1})),i(f instanceof Error?f.message:"stream_failed"),r(!1)})},[s,l,e,u]);return{messages:t,input:s,setInput:o,send:y,sending:l,error:a}};import{jsx as P,jsxs as U}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"}},we=({artifact:e})=>{let t=A(e.dataBase64??"",e.mimeType),n=e.url??t;return n?e.mimeType.startsWith("image/")?P("a",{href:n,rel:"noopener noreferrer",target:"_blank",children:P("img",{alt:e.filename,src:n,style:w.image})}):P("a",{download:e.filename,href:n,style:w.link,children:e.filename}):null},xe=()=>{let e=W(),{messages:t,input:n,setInput:s,send:o,sending:l,error:r}=D(e),a=he(null);be(()=>{let d=a.current;d&&(d.scrollTop=d.scrollHeight)},[t]);let i=d=>{d.preventDefault(),o()};return U("div",{style:w.root,children:[P("div",{ref:a,style:w.log,children:t.map(d=>U("div",{style:d.role==="user"?w.user:w.assistant,children:[d.text||(d.streaming?"\u2026":""),d.artifacts&&d.artifacts.length>0?P("div",{style:w.artifacts,children:d.artifacts.map(u=>P(we,{artifact:u},u.filename))}):null]},d.id))}),r?P("div",{style:w.error,children:r}):null,U("form",{onSubmit:i,style:w.form,children:[P("input",{"aria-label":"Message",onChange:d=>s(d.target.value),placeholder:"Type a message\u2026",style:w.input,value:n}),P("button",{disabled:l||n.trim().length===0,style:w.button,type:"submit",children:"Send"})]})]})};var Te=/\/+$/,F=e=>{let t=e.sessionId,n=e.baseUrl.replace(Te,""),s=r=>`${n}/endpoint/${encodeURIComponent(e.token)}${r}`,o={"content-type":"application/json"},l=(r,a)=>({url:s(r),headers:o,body:JSON.stringify({message:a,...t?{sessionId:t}:{},...e.identity?{externalUserId:e.identity.externalUserId,userHmac:e.identity.userHmac}:{}})});return{sessionId:()=>t,getInfo:()=>b(s("/config"),{}),sendMessage:async r=>{let a=await _(l("/message",r));return t=a.sessionId,a},streamMessage:(r,a,i)=>L(l("/message/stream",r),a,d=>{t=d},i),subscribe:(r,a)=>{let i=a?.since??"0",d=!1,u,y=a?.intervalMs??3e3,c=async()=>{let m=t;if(m)try{let g=await b(s(`/messages?session=${encodeURIComponent(m)}&since=${encodeURIComponent(i)}`),{});for(let f of g.messages)r.onMessage(f);i=g.cursor,r.onHealthy?.()}catch(g){r.onError?.(T(g))}d||(u=setTimeout(c,y))},p=()=>{d=!0,u&&clearTimeout(u)};return a?.signal?.addEventListener("abort",p),u=setTimeout(c,0),p},requestHuman:async()=>{t&&await fetch(s("/request-human"),{method:"POST",headers:o,body:JSON.stringify({sessionId:t})})}}};var Pe=e=>"transport"in e?e.transport:F(e);var ke=/^https?:\/\//i,He=/^\d{4}-\d{2}-\d{2}(?:[T ]|$)/,Se=e=>e.replace(/_/g," ").replace(/\b\w/g,t=>t.toUpperCase());function Ce(e){if(typeof e=="number")return"number";if(typeof e=="boolean")return"boolean";if(typeof e=="string"){if(ke.test(e))return"url";if(He.test(e))return"date"}return"text"}function G(e){let t=[],n=new Map;for(let s of e)for(let[o,l]of Object.entries(s.data??{})){if(l==null)continue;let r=n.get(o);r||(r=new Map,n.set(o,r),t.push(o));let a=Ce(l);r.set(a,(r.get(a)??0)+1)}return t.map(s=>{let o=n.get(s)??new Map,l="text",r=-1;for(let[a,i]of o)i>r&&(r=i,l=a);return{key:s,label:Se(s),type:l}})}var ve=e=>typeof e=="number"?e:Number(e)||0,B=e=>/rate|position|rank|score|percent|avg/i.test(e),Re=/posted|published|sent|completed|shipped|launched|_at|date/i,Ie=new Set(["service","order","end_user_id"]);function z(e,t){let n=e.filter(i=>!Ie.has(i.key)),s=n.filter(i=>i.type==="number").slice(0,3),o=n.find(i=>i.key==="status")??n.find(i=>i.type==="select"),l=n.find(i=>i.type==="date"&&Re.test(i.key))??n.find(i=>i.type==="date"),r=n.filter(i=>i.type==="number"&&!B(i.key)).map(i=>({field:i,total:t.reduce((d,u)=>d+ve(u.data[i.key]),0)})).sort((i,d)=>d.total-i.total).find(i=>i.total>0)?.field??null,a=[{type:"stat",label:"Items",agg:"count"}];for(let i of s){let d=B(i.key);a.push({type:"stat",metric:i.key,agg:d?"avg":"sum",label:d?`Avg ${i.label.toLowerCase()}`:i.label})}return l&&a.push({type:"line",x:l.key,y:r?.key,agg:"sum",title:r?`${r.label} by day`:"Items by day"}),o&&a.push({type:"donut",groupBy:o.key,title:o.label}),a.push({type:"table",columns:n.map(i=>i.key)}),{version:1,widgets:a}}function J(e){let t=[];for(let n of e){let s=t.length>0?t[t.length-1]:void 0;n.kind==="stat"?s?.kind==="stats"?s.items.push(n):t.push({kind:"stats",items:[n]}):n.kind==="series"||n.kind==="donut"?s?.kind==="charts"?s.items.push(n):t.push({kind:"charts",items:[n]}):t.push({kind:"block",item:n})}return t}var V=new Set(["service","order","end_user_id"]),q=e=>typeof e=="number"?e:Number(e)||0,Y=e=>e==null?"":String(e);function Q(e,t){if(e==="count")return t.length;if(t.length===0)return 0;if(e==="last")return t[t.length-1]??0;if(e==="min")return Math.min(...t);if(e==="max")return Math.max(...t);let n=t.reduce((s,o)=>s+o,0);return e==="avg"?Math.round(n/t.length):n}function Ee(e,t,n,s){let o=new Map;for(let l of e){let r=new Date(Y(l.data[t]));if(Number.isNaN(r.getTime()))continue;let a=r.toISOString().slice(0,10),i=o.get(a)??[];i.push(n?q(l.data[n]):1),o.set(a,i)}return[...o.entries()].sort((l,r)=>l[0]<r[0]?-1:1).map(([l,r])=>({label:new Date(`${l}T00:00:00`).toLocaleDateString(void 0,{month:"short",day:"numeric"}),value:n?Q(s,r):r.length}))}function Me(e,t){let n=new Map;for(let s of e){let o=Y(s.data[t]).trim();o&&n.set(o,(n.get(o)??0)+1)}return[...n.entries()].sort((s,o)=>o[1]-s[1]).map(([s,o])=>({label:s,value:o}))}function $e(e,t,n,s){switch(e.type){case"stat":{let o=e.metric?t.get(e.metric):void 0;if(e.metric&&!o)return null;if(!o)return{kind:"stat",label:e.label??"Items",value:s.length};let l=s.map(r=>q(r.data[o.key]));return{kind:"stat",label:e.label??o.label,value:Q(e.agg??"sum",l)}}case"line":case"bar":{if(!t.has(e.x)||e.y&&!t.has(e.y))return null;let o=Ee(s,e.x,e.y,e.agg??"sum");return o.length<2?null:{kind:"series",draw:e.type,title:e.title??"By day",points:o}}case"donut":{if(!t.has(e.groupBy))return null;let o=Me(s,e.groupBy);return o.length===0?null:{kind:"donut",title:e.title??t.get(e.groupBy)?.label??"Breakdown",points:o}}case"table":{let o=e.columns?e.columns.map(l=>t.get(l)).filter(l=>l!==void 0&&!V.has(l.key)):n;return o.length===0?null:{kind:"table",title:e.title,columns:o,rows:s}}case"text":return{kind:"text",title:e.title,body:e.body};default:return null}}function X(e,t,n){let s=t.filter(r=>!V.has(r.key)),o=new Map(t.map(r=>[r.key,r])),l=[];for(let r of e.widgets){let a=$e(r,o,s,n);a&&l.push({...a,w:r.w})}return l}function Z(e,t,n){return e&&e>=1?Math.min(4,Math.round(e)):t==="stat"?1:t==="chart"?n?4:2:4}var Ae=new Set(["sum","avg","count","min","max","last"]),K=e=>typeof e=="string"&&Ae.has(e)?e:void 0,x=e=>typeof e=="string"&&e!==""?e:void 0,H=e=>typeof e=="number"&&e>=1?Math.min(4,Math.round(e)):void 0;function We(e){if(typeof e!="object"||e===null)return null;let t=e;switch(t.type){case"stat":return{type:"stat",label:x(t.label),metric:x(t.metric),agg:K(t.agg),w:H(t.w)};case"line":case"bar":{let n=x(t.x);return n?{type:t.type,title:x(t.title),x:n,y:x(t.y),agg:K(t.agg),w:H(t.w)}:null}case"donut":{let n=x(t.groupBy);return n?{type:"donut",title:x(t.title),groupBy:n,w:H(t.w)}:null}case"table":{let n=Array.isArray(t.columns)?t.columns.filter(s=>typeof s=="string"):void 0;return{type:"table",title:x(t.title),columns:n,w:H(t.w)}}case"text":{let n=x(t.body);return n?{type:"text",title:x(t.title),body:n,w:H(t.w)}:null}default:return null}}function ee(e){let t=e;if(typeof e=="string"){if(e.trim()==="")return null;try{t=JSON.parse(e)}catch{return null}}if(typeof t!="object"||t===null)return null;let n=t.widgets;if(!Array.isArray(n))return null;let s=n.map(We).filter(l=>l!==null);if(s.length===0)return null;let o=t.version;return{version:typeof o=="number"?o:1,title:x(t.title),widgets:s}}var De=/\/+$/,k="/api/v1/end-user",v=class extends Error{constructor(t){super(t),this.name="PortalConflict"}};function Ue(e){let t="";for(let s=0;s<e.length;s+=32768)t+=String.fromCharCode(...e.subarray(s,s+32768));return btoa(t)}var Fe=e=>{let t=e.baseUrl.replace(De,""),n=()=>typeof e.token=="function"?e.token():e.token,s=async()=>({"content-type":"application/json",authorization:`Bearer ${await n()}`}),o=async(r,a)=>{try{let i=await fetch(`${t}${k}${r}`,{method:a.method,headers:await s(),...a.body===void 0?{}:{body:JSON.stringify(a.body)}});if(i.status===409){let d=await i.json().catch(()=>({}));throw new v(d.message??"Someone else saved this first.")}if(!i.ok){let d=await i.text().catch(()=>""),u=`${a.method} ${r} \u2192 ${String(i.status)}`;try{let y=JSON.parse(d);y.message&&(u=y.message)}catch{u=d?`${u}: ${d}`:u}throw T(new Error(u))}return await i.json()}catch(i){throw T(i)}},l=r=>`/tables/${encodeURIComponent(r)}`;return{listTables:async()=>(await b(`${t}${k}/tables`,await s())).tables,listRows:async(r,a)=>await b(`${t}${k}${l(r)}/rows?limit=${String(a??100)}`,await s()),insertRow:async(r,a)=>{let{rowIds:i}=await o(`${l(r)}/rows`,{method:"POST",body:{rows:[a]}}),d=i[0];if(!d)throw T(new Error("The row was not created."));return d},patchRow:async(r,a,i)=>(await o(`${l(r)}/rows/${encodeURIComponent(a)}`,{method:"PATCH",body:i})).updated,deleteRow:async(r,a)=>(await o(`/${encodeURIComponent(r)}/${encodeURIComponent(a)}`,{method:"DELETE"})).deleted,listFiles:async()=>(await b(`${t}${k}/tables/files/rows?limit=200`,await s())).rows.map(a=>({id:a.rowId,filename:String(a.data.filename??""),source:String(a.data.source??"client"),campaign:String(a.data.campaign??""),size:typeof a.data.size=="number"?a.data.size:0,createdAt:a.createdAt})),uploadFile:async(r,a)=>{let i=new Uint8Array(await r.arrayBuffer());return await o("/files",{method:"POST",body:{filename:r.name,mime:r.type||"application/octet-stream",data:Ue(i),...a===void 0?{}:{message:a}}})},fileLink:async r=>await b(`${t}${k}/files/${encodeURIComponent(r)}/url`,await s()),deleteFile:async r=>(await o(`/files/${encodeURIComponent(r)}`,{method:"DELETE"})).deleted,listDocuments:async()=>(await b(`${t}${k}/documents`,await s())).documents,readDocument:async r=>(await b(`${t}${k}/documents/${encodeURIComponent(r)}`,await s())).document,saveDocument:async(r,a)=>await o(`/documents/${encodeURIComponent(r)}`,{method:"PATCH",body:a})}};import{useCallback as Oe,useEffect as te,useRef as _e,useState as R}from"react";var re="greeting";function ne(e,t){if(e.some(o=>o.id===t.id))return e;let n=e.filter(o=>o.id!==re);return[...t.author==="client"?n.filter(o=>!(o.pending&&o.author==="client"&&o.text===t.text)):n,t]}var Le=(e,t)=>{let[n,s]=R([]),[o,l]=R(""),[r,a]=R(!1),[i,d]=R(null),u=_e(0),y=t?.pollMs??2e3;te(()=>{let p=!0;return e.getInfo().then(m=>{p&&m.greeting&&s(g=>g.length===0?[{id:re,cursor:"",author:"agent",text:m.greeting}]:g)}).catch(()=>{}),()=>{p=!1}},[e]),te(()=>e.subscribe?.({onMessage:p=>s(m=>ne(m,p)),onError:p=>d(p.error),onHealthy:()=>d(null)},{intervalMs:y}),[e,y]);let c=Oe(()=>{let p=o.trim();if(!p||r)return;l(""),d(null),a(!0),u.current+=1;let m={id:`pending-${u.current}`,cursor:"",author:"client",text:p,pending:!0};s(g=>[...g,m]),e.sendMessage(p).then(()=>a(!1)).catch(g=>{d(g instanceof Error?g.message:"send_failed"),a(!1)})},[o,r,e]);return{messages:n,input:o,setInput:l,send:c,sending:r,error:i}};export{xe as Chat,ge as HolaProvider,v as PortalConflict,le as createApiTransport,Pe as createHolaClient,Fe as createPortalData,F as createWidgetTransport,G as deriveFields,z as inferSpec,J as layoutGroups,ne as mergeMessage,ee as parseDashboardSpec,X as renderModel,E as textDeltaOf,M as thinkingDeltaOf,$ as toolEventOf,A as useArtifactUrl,D as useChat,W as useHolaClient,Le as useThread,Z as widgetSpan};
8
+ `)}},u=async()=>{let d=await a.read();if(!d.done)return i+=n.decode(d.value,{stream:!0}),l(),u()};await u()};var De=/\/+$/,C="/api/v1/end-user",Se=e=>{let t=e.baseUrl.replace(De,""),o=()=>typeof e.token=="function"?e.token():e.token,s=n=>e.project?`${n}project=${encodeURIComponent(e.project)}`:"",r=async()=>({"content-type":"application/json",authorization:`Bearer ${await o()}`}),a=async n=>{let i=await fetch(`${t}${C}/chat${s("?")}`,{method:"POST",headers:await r(),body:JSON.stringify({message:n})});if(!i.ok)throw new Error(`hola: message failed (${i.status})`);return{reply:(await i.json()).reply??"",sessionId:"",artifacts:[]}};return{sessionId:()=>"",getInfo:async()=>b(`${t}${C}/chat/info${s("?")}`,await r()),sendMessage:a,streamMessage:async(n,i)=>{try{let l=await a(n);i.onText?.(l.reply),i.onComplete?.(l)}catch(l){i.onError?.(v(l))}},subscribe:(n,i)=>{let l=i?.since??"0",u=!1,d,y=i?.intervalMs??3e3,c=async()=>{try{let f=await b(`${t}${C}/chat/thread?since=${encodeURIComponent(l)}${s("&")}`,await r());for(let m of f.messages)n.onMessage(m);l=f.cursor,n.onHealthy?.()}catch(f){n.onError?.(v(f))}u||(d=setTimeout(c,y))},p=()=>{u=!0,d&&clearTimeout(d)};return i?.signal?.addEventListener("abort",p),d=setTimeout(c,0),p},requestHuman:async()=>{await fetch(`${t}${C}/chat/request-human${s("?")}`,{method:"POST",headers:await r(),body:"{}"})}}};import{useEffect as Ce,useState as Re}from"react";var E=(e,t)=>{let[o,s]=Re("");return Ce(()=>{if(!e){s("");return}let r=Uint8Array.from(atob(e),n=>n.charCodeAt(0)),a=URL.createObjectURL(new Blob([r],{type:t}));return s(a),()=>URL.revokeObjectURL(a)},[e,t]),o};import{useEffect as Ee,useRef as $e}from"react";import{createContext as Pe,useContext as Ie}from"react";import{jsx as Me}from"react/jsx-runtime";var X=Pe(null),He=({client:e,children:t})=>Me(X.Provider,{value:e,children:t}),$=()=>{let e=Ie(X);if(!e)throw new Error("useHolaClient must be used within <HolaProvider>");return e};import{useCallback as K,useEffect as We,useRef as Ae,useState as R}from"react";var O=e=>{let[t,o]=R([]),[s,r]=R(""),[a,n]=R(!1),[i,l]=R(null),u=Ae(0),d=K(()=>{let c=u.current;return u.current+=1,c},[]);We(()=>{let c=!0;return e.getInfo().then(p=>{c&&p.greeting&&o([{id:d(),role:"assistant",text:p.greeting}])}).catch(()=>{}),()=>{c=!1}},[e,d]);let y=K(()=>{let c=s.trim();if(!c||a)return;r(""),l(null),n(!0);let p=d(),f=d();o(g=>[...g,{id:p,role:"user",text:c},{id:f,role:"assistant",text:"",streaming:!0}]);let m=g=>{o(h=>h.map(H=>H.id===f?g(H):H))};e.streamMessage(c,{onText:g=>m(h=>({...h,text:h.text+g})),onComplete:g=>{m(h=>({...h,text:g.reply||h.text,artifacts:g.artifacts,streaming:!1})),n(!1)},onError:g=>{m(h=>({...h,streaming:!1})),l(g.error),n(!1)}}).catch(g=>{m(h=>({...h,streaming:!1})),l(g instanceof Error?g.message:"stream_failed"),n(!1)})},[s,a,e,d]);return{messages:t,input:s,setInput:r,send:y,sending:a,error:i}};import{jsx as k,jsxs as _}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=E(e.dataBase64??"",e.mimeType),o=e.url??t;return o?e.mimeType.startsWith("image/")?k("a",{href:o,rel:"noopener noreferrer",target:"_blank",children:k("img",{alt:e.filename,src:o,style:w.image})}):k("a",{download:e.filename,href:o,style:w.link,children:e.filename}):null},_e=()=>{let e=$(),{messages:t,input:o,setInput:s,send:r,sending:a,error:n}=O(e),i=$e(null);Ee(()=>{let u=i.current;u&&(u.scrollTop=u.scrollHeight)},[t]);let l=u=>{u.preventDefault(),r()};return _("div",{style:w.root,children:[k("div",{ref:i,style:w.log,children:t.map(u=>_("div",{style:u.role==="user"?w.user:w.assistant,children:[u.text||(u.streaming?"\u2026":""),u.artifacts&&u.artifacts.length>0?k("div",{style:w.artifacts,children:u.artifacts.map(d=>k(Oe,{artifact:d},d.filename))}):null]},u.id))}),n?k("div",{style:w.error,children:n}):null,_("form",{onSubmit:l,style:w.form,children:[k("input",{"aria-label":"Message",onChange:u=>s(u.target.value),placeholder:"Type a message\u2026",style:w.input,value:o}),k("button",{disabled:a||o.trim().length===0,style:w.button,type:"submit",children:"Send"})]})]})};var Ue=/\/+$/,U=e=>{let t=e.sessionId,o=e.baseUrl.replace(Ue,""),s=n=>`${o}/endpoint/${encodeURIComponent(e.token)}${n}`,r={"content-type":"application/json"},a=(n,i)=>({url:s(n),headers:r,body:JSON.stringify({message:i,...t?{sessionId:t}:{},...e.identity?{externalUserId:e.identity.externalUserId,userHmac:e.identity.userHmac}:{}})});return{sessionId:()=>t,getInfo:()=>b(s("/config"),{}),sendMessage:async n=>{let i=await J(a("/message",n));return t=i.sessionId,i},streamMessage:(n,i,l)=>q(a("/message/stream",n),i,u=>{t=u},l),subscribe:(n,i)=>{let l=i?.since??"0",u=!1,d,y=i?.intervalMs??3e3,c=async()=>{let f=t;if(f)try{let m=await b(s(`/messages?session=${encodeURIComponent(f)}&since=${encodeURIComponent(l)}`),{});for(let g of m.messages)n.onMessage(g);l=m.cursor,n.onHealthy?.()}catch(m){n.onError?.(v(m))}u||(d=setTimeout(c,y))},p=()=>{u=!0,d&&clearTimeout(d)};return i?.signal?.addEventListener("abort",p),d=setTimeout(c,0),p},requestHuman:async()=>{t&&await fetch(s("/request-human"),{method:"POST",headers:r,body:JSON.stringify({sessionId:t})})}}};var Fe=e=>"transport"in e?e.transport:U(e);var Le=/^https?:\/\//i,Ne=/^\d{4}-\d{2}-\d{2}(?:[T ]|$)/,Be=e=>e.replace(/_/g," ").replace(/\b\w/g,t=>t.toUpperCase());function je(e){if(typeof e=="number")return"number";if(typeof e=="boolean")return"boolean";if(typeof e=="string"){if(Le.test(e))return"url";if(Ne.test(e))return"date"}return"text"}function Y(e){let t=[],o=new Map;for(let s of e)for(let[r,a]of Object.entries(s.data??{})){if(a==null)continue;let n=o.get(r);n||(n=new Map,o.set(r,n),t.push(r));let i=je(a);n.set(i,(n.get(i)??0)+1)}return t.map(s=>{let r=o.get(s)??new Map,a="text",n=-1;for(let[i,l]of r)l>n&&(n=l,a=i);return{key:s,label:Be(s),type:a}})}var Ve=e=>typeof e=="number"?e:Number(e)||0,Q=e=>/rate|position|rank|score|percent|avg/i.test(e),Ge=/posted|published|sent|completed|shipped|launched|_at|date/i,ze=new Set(["service","order","end_user_id"]);function Z(e,t){let o=e.filter(l=>!ze.has(l.key)),s=o.filter(l=>l.type==="number").slice(0,3),r=o.find(l=>l.key==="status")??o.find(l=>l.type==="select"),a=o.find(l=>l.type==="date"&&Ge.test(l.key))??o.find(l=>l.type==="date"),n=o.filter(l=>l.type==="number"&&!Q(l.key)).map(l=>({field:l,total:t.reduce((u,d)=>u+Ve(d.data[l.key]),0)})).sort((l,u)=>u.total-l.total).find(l=>l.total>0)?.field??null,i=[{type:"stat",label:"Items",agg:"count"}];for(let l of s){let u=Q(l.key);i.push({type:"stat",metric:l.key,agg:u?"avg":"sum",label:u?`Avg ${l.label.toLowerCase()}`:l.label})}return a&&i.push({type:"line",x:a.key,y:n?.key,agg:"sum",title:n?`${n.label} by day`:"Items by day"}),r&&i.push({type:"donut",groupBy:r.key,title:r.label}),i.push({type:"table",columns:o.map(l=>l.key)}),{version:1,widgets:i}}var ee={stat:{span:1,h:1},chart:{span:2,h:2},block:{span:0,h:0}},F=6,L=4,Je=e=>Math.max(1,Math.min(F,Math.round(e))),qe=e=>Math.max(1,Math.min(L,Math.round(e)));function N(e){return e==="stat"?"stat":e==="series"||e==="donut"?"chart":"block"}function te(e){return e==="stat"?"stat":e==="line"||e==="bar"||e==="donut"?"chart":"block"}function ne(e){return ee[e]}function B(e,t,o){let s=ee[e];return{span:t===void 0?s.span:Je(t),h:o===void 0?s.h:qe(o)}}function re(e){let t=[],o=null;for(let s of e){let r=N(s.kind);if(r==="block"){t.push({kind:"block",widget:s}),o=null;continue}let a=B(r,s.w,s.h),n={widget:s,span:a.span,h:a.h,band:r};o?o.cells.push(n):(o={kind:"grid",cells:[n]},t.push(o))}return t}var oe=new Set(["service","order","end_user_id"]),se=e=>typeof e=="number"?e:Number(e)||0,ie=e=>e==null?"":String(e);function ae(e,t){if(e==="count")return t.length;if(t.length===0)return 0;if(e==="last")return t[t.length-1]??0;if(e==="min")return Math.min(...t);if(e==="max")return Math.max(...t);let o=t.reduce((s,r)=>s+r,0);return e==="avg"?Math.round(o/t.length):o}function Xe(e,t,o,s){let r=new Map;for(let a of e){let n=new Date(ie(a.data[t]));if(Number.isNaN(n.getTime()))continue;let i=n.toISOString().slice(0,10),l=r.get(i)??[];l.push(o?se(a.data[o]):1),r.set(i,l)}return[...r.entries()].sort((a,n)=>a[0]<n[0]?-1:1).map(([a,n])=>({label:new Date(`${a}T00:00:00`).toLocaleDateString(void 0,{month:"short",day:"numeric"}),value:o?ae(s,n):n.length}))}function Ke(e,t){let o=new Map;for(let s of e){let r=ie(s.data[t]).trim();r&&o.set(r,(o.get(r)??0)+1)}return[...o.entries()].sort((s,r)=>r[1]-s[1]).map(([s,r])=>({label:s,value:r}))}function Ye(e,t,o,s){switch(e.type){case"stat":{let r=e.metric?t.get(e.metric):void 0;if(e.metric&&!r)return null;if(!r)return{kind:"stat",label:e.label??"Items",value:s.length};let a=s.map(n=>se(n.data[r.key]));return{kind:"stat",label:e.label??r.label,value:ae(e.agg??"sum",a)}}case"line":case"bar":{if(!t.has(e.x)||e.y&&!t.has(e.y))return null;let r=Xe(s,e.x,e.y,e.agg??"sum");return r.length<2?null:{kind:"series",draw:e.type,title:e.title??"By day",points:r}}case"donut":{if(!t.has(e.groupBy))return null;let r=Ke(s,e.groupBy);return r.length===0?null:{kind:"donut",title:e.title??t.get(e.groupBy)?.label??"Breakdown",points:r}}case"table":{let r=e.columns?e.columns.map(a=>t.get(a)).filter(a=>a!==void 0&&!oe.has(a.key)):o;return r.length===0?null:{kind:"table",title:e.title,columns:r,rows:s}}case"text":return{kind:"text",title:e.title,body:e.body};default:return null}}function le(e,t,o){let s=t.filter(n=>!oe.has(n.key)),r=new Map(t.map(n=>[n.key,n])),a=[];for(let n of e.widgets){let i=Ye(n,r,s,o);i&&a.push({...i,w:n.w,h:n.h})}return a}var Qe=new Set(["sum","avg","count","min","max","last"]),ue=e=>typeof e=="string"&&Qe.has(e)?e:void 0,x=e=>typeof e=="string"&&e!==""?e:void 0,D=e=>typeof e=="number"&&e>=1?Math.min(6,Math.round(e)):void 0,S=e=>typeof e=="number"&&e>=1?Math.min(4,Math.round(e)):void 0;function Ze(e){if(typeof e!="object"||e===null)return null;let t=e;switch(t.type){case"stat":return{type:"stat",label:x(t.label),metric:x(t.metric),agg:ue(t.agg),w:D(t.w),h:S(t.h)};case"line":case"bar":{let o=x(t.x);return o?{type:t.type,title:x(t.title),x:o,y:x(t.y),agg:ue(t.agg),w:D(t.w),h:S(t.h)}:null}case"donut":{let o=x(t.groupBy);return o?{type:"donut",title:x(t.title),groupBy:o,w:D(t.w),h:S(t.h)}:null}case"table":{let o=Array.isArray(t.columns)?t.columns.filter(s=>typeof s=="string"):void 0;return{type:"table",title:x(t.title),columns:o,w:D(t.w),h:S(t.h)}}case"text":{let o=x(t.body);return o?{type:"text",title:x(t.title),body:o,w:D(t.w),h:S(t.h)}:null}default:return null}}function de(e){let t=e;if(typeof e=="string"){if(e.trim()==="")return null;try{t=JSON.parse(e)}catch{return null}}if(typeof t!="object"||t===null)return null;let o=t.widgets;if(!Array.isArray(o))return null;let s=o.map(Ze).filter(a=>a!==null);if(s.length===0)return null;let r=t.version;return{version:typeof r=="number"?r:1,title:x(t.title),widgets:s}}function j(e){if(typeof e=="string")return e?{kind:"file",value:e}:null;if(e&&typeof e=="object"){let t=e,o=typeof t.value=="string"?t.value:"",s=t.kind==="link"||t.kind==="text"||t.kind==="table"?t.kind:"file",r=typeof t.v=="number"&&t.v>=1?Math.floor(t.v):void 0;return o?{kind:s,value:o,...r?{v:r}:{}}:null}return null}function V(e){let t=new Map;for(let o of e){let s=o.v??1,r=t.get(s)??[];r.push(o),t.set(s,r)}return[...t.entries()].sort(([o],[s])=>o-s).map(([o,s])=>({v:o,items:s}))}function pe(e){let t=e.files;if(typeof t=="string"&&t.trim()!=="")try{let s=JSON.parse(t);if(Array.isArray(s))return s.map(j).filter(r=>r!==null)}catch{}let o=String(e.file??"");return o?[{kind:"file",value:o}]:[]}function ce(e,t,o){let r=(V(e).find(n=>n.v===t)?.items??[]).filter(n=>n.kind==="file").map(n=>n.value),a=r.map(n=>o.get(n)??"");return r.length===0||a.some(n=>n==="")?"awaiting":a.some(n=>n==="revise")?"revise":"accepted"}function me(e){return Number(e.published_version)||0}function G(e){return e==="number"||e==="date"||e==="boolean"||e==="select"||e==="url"?e:e==="link"?"url":e==="checkbox"?"boolean":"text"}function fe(e){try{let t=JSON.parse(e);if(Array.isArray(t.columns)&&Array.isArray(t.rows)&&t.columns.length){let o=t.columns.map((a,n)=>({key:typeof a.key=="string"&&a.key?a.key:typeof a.id=="string"&&a.id?a.id:`column_${n+1}`,label:typeof a.label=="string"?a.label:"",type:G(a.type)})),s=t.rows.map((a,n)=>({id:typeof a.id=="string"&&a.id?a.id:`row_${n}`,cells:a.cells&&typeof a.cells=="object"?a.cells:{}})),r=typeof t.name=="string"?t.name:void 0;return{columns:o,rows:s,...r?{name:r}:{}}}}catch{}return null}function ge(e){return e==null?"":String(e)}function ye(e){return e===!0||e==="true"||e==="1"||e==="yes"||e==="\u2713"}function be(e){let t=new Date(`${e}T00:00:00`);return Number.isNaN(t.getTime())?e:t.toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"})}var et=/\/+$/,T="/api/v1/end-user",P=class extends Error{constructor(t){super(t),this.name="PortalConflict"}};function tt(e){let t="";for(let s=0;s<e.length;s+=32768)t+=String.fromCharCode(...e.subarray(s,s+32768));return btoa(t)}var nt=e=>{let t=e.baseUrl.replace(et,""),o=()=>typeof e.token=="function"?e.token():e.token,s=async()=>({"content-type":"application/json",authorization:`Bearer ${await o()}`}),r=async(n,i)=>{try{let l=await fetch(`${t}${T}${n}`,{method:i.method,headers:await s(),...i.body===void 0?{}:{body:JSON.stringify(i.body)}});if(l.status===409){let u=await l.json().catch(()=>({}));throw new P(u.message??"Someone else saved this first.")}if(!l.ok){let u=await l.text().catch(()=>""),d=`${i.method} ${n} \u2192 ${String(l.status)}`;try{let y=JSON.parse(u);y.message&&(d=y.message)}catch{d=u?`${d}: ${u}`:d}throw v(new Error(d))}return await l.json()}catch(l){throw v(l)}},a=n=>`/tables/${encodeURIComponent(n)}`;return{listTables:async()=>(await b(`${t}${T}/tables`,await s())).tables,listRows:async(n,i)=>await b(`${t}${T}${a(n)}/rows?limit=${String(i??100)}`,await s()),insertRow:async(n,i)=>{let{rowIds:l}=await r(`${a(n)}/rows`,{method:"POST",body:{rows:[i]}}),u=l[0];if(!u)throw v(new Error("The row was not created."));return u},patchRow:async(n,i,l)=>(await r(`${a(n)}/rows/${encodeURIComponent(i)}`,{method:"PATCH",body:l})).updated,deleteRow:async(n,i)=>(await r(`/${encodeURIComponent(n)}/${encodeURIComponent(i)}`,{method:"DELETE"})).deleted,listFiles:async()=>(await b(`${t}${T}/tables/files/rows?limit=200`,await s())).rows.map(i=>({id:i.rowId,filename:String(i.data.filename??""),source:String(i.data.source??"client"),campaign:String(i.data.campaign??""),size:typeof i.data.size=="number"?i.data.size:0,createdAt:i.createdAt})),uploadFile:async(n,i)=>{let l=new Uint8Array(await n.arrayBuffer());return await r("/files",{method:"POST",body:{filename:n.name,mime:n.type||"application/octet-stream",data:tt(l),...i===void 0?{}:{message:i}}})},fileLink:async n=>await b(`${t}${T}/files/${encodeURIComponent(n)}/url`,await s()),deleteFile:async n=>(await r(`/files/${encodeURIComponent(n)}`,{method:"DELETE"})).deleted,listDocuments:async()=>(await b(`${t}${T}/documents`,await s())).documents,readDocument:async n=>(await b(`${t}${T}/documents/${encodeURIComponent(n)}`,await s())).document,saveDocument:async(n,i)=>await r(`/documents/${encodeURIComponent(n)}`,{method:"PATCH",body:i})}};import{useCallback as rt,useEffect as he,useRef as ot,useState as I}from"react";var we="greeting";function xe(e,t){if(e.some(r=>r.id===t.id))return e;let o=e.filter(r=>r.id!==we);return[...t.author==="client"?o.filter(r=>!(r.pending&&r.author==="client"&&r.text===t.text)):o,t]}var st=(e,t)=>{let[o,s]=I([]),[r,a]=I(""),[n,i]=I(!1),[l,u]=I(null),d=ot(0),y=t?.pollMs??2e3;he(()=>{let p=!0;return e.getInfo().then(f=>{p&&f.greeting&&s(m=>m.length===0?[{id:we,cursor:"",author:"agent",text:f.greeting}]:m)}).catch(()=>{}),()=>{p=!1}},[e]),he(()=>e.subscribe?.({onMessage:p=>s(f=>xe(f,p)),onError:p=>u(p.error),onHealthy:()=>u(null)},{intervalMs:y}),[e,y]);let c=rt(()=>{let p=r.trim();if(!p||n)return;a(""),u(null),i(!0),d.current+=1;let f={id:`pending-${d.current}`,cursor:"",author:"client",text:p,pending:!0};s(m=>[...m,f]),e.sendMessage(p).then(()=>i(!1)).catch(m=>{u(m instanceof Error?m.message:"send_failed"),i(!1)})},[r,n,e]);return{messages:o,input:r,setInput:a,send:c,sending:n,error:l}};export{_e as Chat,F as GRID_MAX_COLS,L as GRID_MAX_ROWS,He as HolaProvider,P as PortalConflict,N as bandOfKind,te as bandOfType,Se as createApiTransport,Fe as createHolaClient,nt as createPortalData,U as createWidgetTransport,ge as deliverableCellText,ce as deliverableStatus,Y as deriveFields,ne as footprintOf,B as footprintWith,be as formatDeliverableDate,V as groupDeliverableVersions,Z as inferSpec,ye as isDeliverableChecked,re as layoutSegments,xe as mergeMessage,G as normalizeDeliverableColType,j as normalizeDeliverableItem,de as parseDashboardSpec,pe as parseDeliverableItems,fe as parseDeliverableTable,me as publishedVersionOf,le as renderModel,M as textDeltaOf,W as thinkingDeltaOf,A as toolEventOf,E as useArtifactUrl,O as useChat,$ as useHolaClient,st as useThread};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holaboss/client",
3
- "version": "0.2.0-beta.7",
3
+ "version": "0.2.0-beta.9",
4
4
  "description": "Injectable client SDK for embedding a Holaboss AI employee (chat + configurable dashboards today; artifacts next) into your own web app.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",