@holaboss/client 0.2.0-beta.19 → 0.2.0-beta.20
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 +5 -5
- package/dist/index.d.cts +179 -1
- package/dist/index.d.ts +179 -1
- package/dist/index.js +5 -5
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use client'
|
|
2
|
-
var
|
|
3
|
-
`))o.startsWith(":")||(o.startsWith("event:")?t=o.slice(6).trim():o.startsWith("data:")&&r.push(o.slice(5).replace(
|
|
4
|
-
`)}:null},
|
|
2
|
+
var Q=Object.defineProperty;var Ve=Object.getOwnPropertyDescriptor;var je=Object.getOwnPropertyNames;var Ge=Object.prototype.hasOwnProperty;var Be=(e,t)=>{for(var r in t)Q(e,r,{get:t[r],enumerable:!0})},ze=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of je(t))!Ge.call(e,i)&&i!==r&&Q(e,i,{get:()=>t[i],enumerable:!(o=Ve(t,i))||o.enumerable});return e};var Je=e=>ze(Q({},"__esModule",{value:!0}),e);var wt={};Be(wt,{Chat:()=>He,GRID_COLS:()=>te,GRID_MAX_COLS:()=>ne,GRID_MAX_ROWS:()=>re,HolaProvider:()=>Ce,PortalConflict:()=>A,bandOfKind:()=>M,bandOfType:()=>oe,cellValue:()=>he,createApiTransport:()=>Pe,createHolaClient:()=>Ae,createPortalData:()=>Oe,createPortalShop:()=>Ue,createWidgetTransport:()=>B,deliverableCellText:()=>fe,deliverableStatus:()=>ce,deriveFields:()=>Z,emptyTableResponses:()=>$,footprintOf:()=>se,footprintWith:()=>z,formatDeliverableDate:()=>ve,groupDeliverableVersions:()=>X,inferSpec:()=>ee,isDeliverableChecked:()=>ye,mergeMessage:()=>Se,normalizeDeliverableColType:()=>q,normalizeDeliverableItem:()=>K,parseDashboardSpec:()=>de,parseDeliverableItems:()=>pe,parseDeliverableTable:()=>me,parseTableResponses:()=>be,placeWidgets:()=>J,publishedVersionOf:()=>ge,renderModel:()=>ue,setResponse:()=>we,setTableReview:()=>xe,splitLayout:()=>ie,textDeltaOf:()=>_,thinkingDeltaOf:()=>O,toolEventOf:()=>U,useArtifactUrl:()=>F,useChat:()=>j,useHolaClient:()=>V,useShop:()=>Le,useThread:()=>Ne});module.exports=Je(wt);var Re=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="message_update"?t.assistantMessageEvent??null:null},_=e=>{let t=Re(e);return t?.type==="text_delta"&&typeof t.delta=="string"?t.delta:null},O=e=>{let t=Re(e);return t?.type==="thinking_delta"&&typeof t.delta=="string"?t.delta:null},U=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 Ke=/^ /,w=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"}},Xe=e=>{let t="message",r=[];for(let o of e.split(`
|
|
3
|
+
`))o.startsWith(":")||(o.startsWith("event:")?t=o.slice(6).trim():o.startsWith("data:")&&r.push(o.slice(5).replace(Ke,"")));return r.length>0?{event:t,data:r.join(`
|
|
4
|
+
`)}:null},qe=(e,t,r)=>{let o;try{o=JSON.parse(e.data)}catch{return}if(e.event==="session"){let i=o.sessionId;i&&(r(i),t.onSession?.(i));return}if(e.event==="turn_event"){t.onEvent?.(o);let i=_(o);i&&t.onText?.(i);let a=O(o);a&&t.onThinking?.(a);let n=U(o);n&&t.onTool?.(n);return}if(e.event==="chat_completed"){let i=o;r(i.sessionId),t.onComplete?.(i);return}e.event==="chat_error"&&t.onError?.(w(o))},R=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()},Te=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()},ke=async(e,t,r,o)=>{let i=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body,signal:o});if(!(i.ok&&i.body)){t.onError?.({error:`stream_failed_${i.status}`});return}let a=i.body.getReader(),n=new TextDecoder,s="",l=()=>{let d=s.indexOf(`
|
|
5
5
|
|
|
6
|
-
`);for(;d!==-1;){let c=s.slice(0,d);s=s.slice(d+2);let
|
|
6
|
+
`);for(;d!==-1;){let c=s.slice(0,d);s=s.slice(d+2);let g=Xe(c);g&&qe(g,t,r),d=s.indexOf(`
|
|
7
7
|
|
|
8
|
-
`)}},u=async()=>{let d=await l.read();if(!d.done)return s+=n.decode(d.value,{stream:!0}),i(),u()};await u()};var Xe=/\/+$/,Y="/api/v1/end-user",De=e=>{let t=e.baseUrl.replace(Xe,""),r=()=>typeof e.token=="function"?e.token():e.token,o=n=>e.project?`${n}project=${encodeURIComponent(e.project)}`:"",a=async()=>({"content-type":"application/json",authorization:`Bearer ${await r()}`}),l=async n=>{let s=await fetch(`${t}${Y}/chat${o("?")}`,{method:"POST",headers:await a(),body:JSON.stringify({message:n})});if(!s.ok)throw new Error(`hola: message failed (${s.status})`);return{reply:(await s.json()).reply??"",sessionId:"",artifacts:[]}};return{sessionId:()=>"",getInfo:async()=>R(`${t}${Y}/chat/info${o("?")}`,await a()),sendMessage:l,streamMessage:async(n,s)=>{try{let i=await l(n);s.onText?.(i.reply),s.onComplete?.(i)}catch(i){s.onError?.(C(i))}},subscribe:(n,s)=>{let i=s?.since??"0",u=!1,d,c=s?.intervalMs??3e3,m=typeof document<"u",p=()=>m&&document.visibilityState==="hidden",b=!1,w=()=>{if(!u){if(p()){b=!0;return}d=setTimeout(f,c)}},f=async()=>{try{let h=await R(`${t}${Y}/chat/thread?since=${encodeURIComponent(i)}${o("&")}`,await a());for(let P of h.messages)n.onMessage(P);i=h.cursor,n.onHealthy?.()}catch(h){n.onError?.(C(h))}w()},D=()=>{u||!b||p()||(b=!1,d&&clearTimeout(d),d=setTimeout(f,0))};m&&document.addEventListener("visibilitychange",D);let g=()=>{u=!0,d&&clearTimeout(d),m&&document.removeEventListener("visibilitychange",D)};return s?.signal?.addEventListener("abort",g),d=setTimeout(f,0),g}}};var F=require("react"),L=(e,t)=>{let[r,o]=(0,F.useState)("");return(0,F.useEffect)(()=>{if(!e){o("");return}let a=Uint8Array.from(atob(e),n=>n.charCodeAt(0)),l=URL.createObjectURL(new Blob([a],{type:t}));return o(l),()=>URL.revokeObjectURL(l)},[e,t]),r};var j=require("react");var U=require("react"),Pe=require("react/jsx-runtime"),Ce=(0,U.createContext)(null),Se=({client:e,children:t})=>(0,Pe.jsx)(Ce.Provider,{value:e,children:t}),N=()=>{let e=(0,U.useContext)(Ce);if(!e)throw new Error("useHolaClient must be used within <HolaProvider>");return e};var x=require("react"),V=e=>{let[t,r]=(0,x.useState)([]),[o,a]=(0,x.useState)(""),[l,n]=(0,x.useState)(!1),[s,i]=(0,x.useState)(null),u=(0,x.useRef)(0),d=(0,x.useRef)(null);(0,x.useEffect)(()=>()=>d.current?.abort(),[]);let c=(0,x.useCallback)(()=>{let p=u.current;return u.current+=1,p},[]);(0,x.useEffect)(()=>{let p=!0;return e.getInfo().then(b=>{p&&b.greeting&&r([{id:c(),role:"assistant",text:b.greeting}])}).catch(()=>{}),()=>{p=!1}},[e,c]);let m=(0,x.useCallback)(()=>{let p=o.trim();if(!p||l)return;a(""),i(null),n(!0);let b=c(),w=c();r(g=>[...g,{id:b,role:"user",text:p},{id:w,role:"assistant",text:"",streaming:!0}]);let f=g=>{r(h=>h.map(P=>P.id===w?g(P):P))},D=new AbortController;d.current=D,e.streamMessage(p,{onText:g=>f(h=>({...h,text:h.text+g})),onComplete:g=>{f(h=>({...h,text:g.reply||h.text,artifacts:g.artifacts,streaming:!1})),n(!1)},onError:g=>{f(h=>({...h,streaming:!1})),i(g.error),n(!1)}},D.signal).catch(g=>{f(h=>({...h,streaming:!1})),i(g instanceof Error?g.message:"stream_failed"),n(!1)}).finally(()=>{n(!1),f(g=>g.streaming?{...g,streaming:!1}:g)})},[o,l,e,c]);return{messages:t,input:o,setInput:a,send:m,sending:l,error:s}};var v=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"}},Ke=({artifact:e})=>{let t=L(e.dataBase64??"",e.mimeType),r=e.url??t;return r?e.mimeType.startsWith("image/")?(0,v.jsx)("a",{href:r,rel:"noopener noreferrer",target:"_blank",children:(0,v.jsx)("img",{alt:e.filename,src:r,style:k.image})}):(0,v.jsx)("a",{download:e.filename,href:r,style:k.link,children:e.filename}):null},Ie=()=>{let e=N(),{messages:t,input:r,setInput:o,send:a,sending:l,error:n}=V(e),s=(0,j.useRef)(null);(0,j.useEffect)(()=>{let u=s.current;u&&(u.scrollTop=u.scrollHeight)},[t]);let i=u=>{u.preventDefault(),a()};return(0,v.jsxs)("div",{style:k.root,children:[(0,v.jsx)("div",{ref:s,style:k.log,children:t.map(u=>(0,v.jsxs)("div",{style:u.role==="user"?k.user:k.assistant,children:[u.text||(u.streaming?"\u2026":""),u.artifacts&&u.artifacts.length>0?(0,v.jsx)("div",{style:k.artifacts,children:u.artifacts.map(d=>(0,v.jsx)(Ke,{artifact:d},d.filename))}):null]},u.id))}),n?(0,v.jsx)("div",{style:k.error,children:n}):null,(0,v.jsxs)("form",{onSubmit:i,style:k.form,children:[(0,v.jsx)("input",{"aria-label":"Message",onChange:u=>o(u.target.value),placeholder:"Type a message\u2026",style:k.input,value:r}),(0,v.jsx)("button",{disabled:l||r.trim().length===0,style:k.button,type:"submit",children:"Send"})]})]})};var qe=/\/+$/,B=e=>{let t=e.sessionId,r=e.baseUrl.replace(qe,""),o=n=>`${r}/endpoint/${encodeURIComponent(e.token)}${n}`,a={"content-type":"application/json"},l=(n,s)=>({url:o(n),headers:a,body:JSON.stringify({message:s,...t?{sessionId:t}:{},...e.identity?{externalUserId:e.identity.externalUserId,userHmac:e.identity.userHmac}:{}})});return{sessionId:()=>t,getInfo:()=>R(o("/config"),{}),sendMessage:async n=>{let s=await Te(l("/message",n));return t=s.sessionId,s},streamMessage:(n,s,i)=>ke(l("/message/stream",n),s,u=>{t=u},i),subscribe:(n,s)=>{let i=s?.since??"0",u=!1,d,c=s?.intervalMs??3e3,m=async()=>{let b=t;if(b)try{let w=await R(o(`/messages?session=${encodeURIComponent(b)}&since=${encodeURIComponent(i)}`),{});for(let f of w.messages)n.onMessage(f);i=w.cursor,n.onHealthy?.()}catch(w){n.onError?.(C(w))}u||(d=setTimeout(m,c))},p=()=>{u=!0,d&&clearTimeout(d)};return s?.signal?.addEventListener("abort",p),d=setTimeout(m,0),p}}};var He=e=>"transport"in e?e.transport:B(e);var Ye=/^https?:\/\//i,Qe=/^\d{4}-\d{2}-\d{2}(?:[T ]|$)/,Ze=e=>e.replace(/_/g," ").replace(/\b\w/g,t=>t.toUpperCase());function et(e){if(typeof e=="number")return"number";if(typeof e=="boolean")return"boolean";if(typeof e=="string"){if(Ye.test(e))return"url";if(Qe.test(e))return"date"}return"text"}function Q(e){let t=[],r=new Map;for(let o of e)for(let[a,l]of Object.entries(o.data??{})){if(l==null)continue;let n=r.get(a);n||(n=new Map,r.set(a,n),t.push(a));let s=et(l);n.set(s,(n.get(s)??0)+1)}return t.map(o=>{let a=r.get(o)??new Map,l="text",n=-1;for(let[s,i]of a)i>n&&(n=i,l=s);return{key:o,label:Ze(o),type:l}})}var tt=e=>typeof e=="number"?e:Number(e)||0,Ae=e=>/rate|position|rank|score|percent|avg/i.test(e),nt=/posted|published|sent|completed|shipped|launched|_at/i,rt=new Set(["service","order","end_user_id"]);function Z(e,t){let r=e.filter(i=>!rt.has(i.key)),o=r.filter(i=>i.type==="number").slice(0,3),a=r.find(i=>i.key==="status")??r.find(i=>i.type==="select"),l=r.find(i=>i.type==="date"&&nt.test(i.key))??r.find(i=>i.type==="date"),n=r.filter(i=>i.type==="number"&&!Ae(i.key)).map(i=>({field:i,total:t.reduce((u,d)=>u+tt(d.data[i.key]),0)})).sort((i,u)=>u.total-i.total).find(i=>i.total>0)?.field??null,s=[{type:"stat",label:"Items",agg:"count"}];for(let i of o){let u=Ae(i.key);s.push({type:"stat",metric:i.key,agg:u?"avg":"sum",label:u?`Avg ${i.label.toLowerCase()}`:i.label})}return l&&s.push({type:"line",x:l.key,y:n?.key,agg:"sum",title:n?`${n.label} by day`:"Items by day"}),a&&s.push({type:"donut",groupBy:a.key,title:a.label}),s.push({type:"table",columns:r.map(i=>i.key)}),{version:1,widgets:s}}var ee=6,te=6,ne=4,Me={stat:{w:1,h:1},chart:{w:2,h:2},block:{w:6,h:2}},ot=e=>Math.max(1,Math.min(6,Math.round(e))),st=e=>Math.max(1,Math.min(4,Math.round(e)));function A(e){return e==="stat"?"stat":e==="series"||e==="donut"?"chart":"block"}function re(e){return e==="stat"?"stat":e==="line"||e==="bar"||e==="donut"?"chart":"block"}function oe(e){return Me[e]}function G(e,t,r){let o=Me[e];return{w:t===void 0?o.w:ot(t),h:r===void 0?o.h:st(r)}}function z(e){let t=[],r=[],o=(n,s,i,u)=>{if(n<0||n+i>6)return!1;for(let d=0;d<u;d+=1){let c=r[s+d];if(c){for(let m=0;m<i;m+=1)if(c[n+m])return!1}}return!0},a=(n,s,i,u)=>{for(let d=0;d<u;d+=1){let c=r[s+d]??[];for(let m=0;m<i;m+=1)c[n+m]=!0;r[s+d]=c}},l=(n,s)=>{for(let i=0;;i+=1)for(let u=0;u+n<=6;u+=1)if(o(u,i,n,s))return{gx:u,gy:i}};for(let n of e){let s=G(A(n.kind),n.w,n.h),u=n.gx!==void 0&&n.gy!==void 0&&o(n.gx,n.gy,s.w,s.h)&&n.gx!==void 0&&n.gy!==void 0?{gx:n.gx,gy:n.gy}:l(s.w,s.h);a(u.gx,u.gy,s.w,s.h),t.push({widget:n,gx:u.gx,gy:u.gy,w:s.w,h:s.h})}return t}function se(e){let t=[],r=[];for(let o of e)A(o.kind)==="block"?r.push(o):t.push(o);return{tiles:z(t),blocks:r}}var We=new Set(["service","order","end_user_id"]),ie=e=>typeof e=="number"?e:Number(e)||0,Ee=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 r=t.reduce((o,a)=>o+a,0);return e==="avg"?Math.round(r/t.length*100)/100:r}function it(e,t,r,o){let a=new Map;for(let l of e){let n=new Date(Ee(l.data[t]));if(Number.isNaN(n.getTime()))continue;let s=n.toISOString().slice(0,10),i=a.get(s)??[];i.push(r?ie(l.data[r]):1),a.set(s,i)}return[...a.entries()].sort((l,n)=>l[0]<n[0]?-1:1).map(([l,n])=>({label:new Date(`${l}T00:00:00`).toLocaleDateString(void 0,{month:"short",day:"numeric"}),value:r?ae(o,n):n.length}))}function at(e,t,r,o="sum"){let a=new Map;for(let l of e){let n=Ee(l.data[t]).trim();if(!n)continue;let s=a.get(n)??[];s.push(r?ie(l.data[r]):1),a.set(n,s)}return[...a.entries()].map(([l,n])=>({label:l,value:r?ae(o,n):n.length})).sort((l,n)=>n.value-l.value)}function lt(e,t,r,o){switch(e.type){case"stat":{let a=e.metric?t.get(e.metric):void 0;if(e.metric&&!a)return null;if(!a)return{kind:"stat",label:e.label??"Items",value:o.length};let l=o.map(n=>ie(n.data[a.key]));return{kind:"stat",label:e.label??a.label,value:ae(e.agg??"sum",l)}}case"line":case"bar":{if(!t.has(e.x)||e.y&&!t.has(e.y))return null;let a=it(o,e.x,e.y,e.agg??"sum");return a.length<2?null:{kind:"series",draw:e.type,title:e.title??"By day",points:a}}case"donut":{if(!t.has(e.groupBy))return null;let a=at(o,e.groupBy,e.metric,e.agg??"sum");return a.length===0?null:{kind:"donut",title:e.title??t.get(e.groupBy)?.label??"Breakdown",points:a}}case"table":{let a=e.columns?e.columns.map(l=>t.get(l)).filter(l=>l!==void 0&&!We.has(l.key)):r;return a.length===0?null:{kind:"table",title:e.title,columns:a,rows:o}}case"text":return{kind:"text",title:e.title,body:e.body};default:return null}}function le(e,t,r,o={}){let a=new Map,l=i=>({byKey:new Map(i.fields.map(u=>[u.key,u])),cols:i.fields.filter(u=>!We.has(u.key)),rows:i.rows}),n=l({fields:t,rows:r});for(let[i,u]of Object.entries(o))a.set(i,l(u));let s=[];for(let i of e.widgets){let u=i.type==="text"?void 0:i.source,d=u?a.get(u):n;if(!d)continue;let c=lt(i,d.byKey,d.cols,d.rows);c&&s.push({...c,w:i.w,h:i.h,gx:i.gx,gy:i.gy})}return s}var ut=new Set(["sum","avg","count","min","max","last"]),$e=e=>typeof e=="string"&&ut.has(e)?e:void 0,y=e=>typeof e=="string"&&e!==""?e:void 0,M=e=>typeof e=="number"&&e>=1?Math.min(6,Math.round(e)):void 0,W=e=>typeof e=="number"&&e>=1?Math.min(4,Math.round(e)):void 0,S=e=>typeof e=="number"&&e>=0?Math.round(e):void 0;function dt(e){if(typeof e!="object"||e===null)return null;let t=e;switch(t.type){case"stat":return{type:"stat",source:y(t.source),label:y(t.label),metric:y(t.metric)??y(t.column),agg:$e(t.agg),w:M(t.w),h:W(t.h),gx:S(t.gx),gy:S(t.gy)};case"line":case"bar":{let r=y(t.x);return r?{type:t.type,source:y(t.source),title:y(t.title),x:r,y:y(t.y)??y(t.column),agg:$e(t.agg),w:M(t.w),h:W(t.h),gx:S(t.gx),gy:S(t.gy)}:null}case"donut":{let r=y(t.groupBy)??y(t.column);return r?{type:"donut",source:y(t.source),title:y(t.title),groupBy:r,w:M(t.w),h:W(t.h),gx:S(t.gx),gy:S(t.gy)}:null}case"table":{let r=Array.isArray(t.columns)?t.columns.filter(o=>typeof o=="string"):void 0;return{type:"table",source:y(t.source),title:y(t.title),columns:r,w:M(t.w),h:W(t.h),gx:S(t.gx),gy:S(t.gy)}}case"text":{let r=y(t.body);return r?{type:"text",title:y(t.title),body:r,w:M(t.w),h:W(t.h),gx:S(t.gx),gy:S(t.gy)}:null}default:return null}}function ue(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 o=r.map(dt).filter(l=>l!==null);if(o.length===0)return null;let a=t.version;return{version:typeof a=="number"?a:1,title:y(t.title),widgets:o}}function J(e){if(typeof e=="string")return e?{kind:"file",value:e}:null;if(e&&typeof e=="object"){let t=e,r=typeof t.value=="string"?t.value:"",o=t.kind==="link"||t.kind==="text"||t.kind==="table"?t.kind:"file",a=typeof t.v=="number"&&t.v>=1?Math.floor(t.v):void 0;return r?{kind:o,value:r,...a?{v:a}:{}}:null}return null}function X(e){let t=new Map;for(let r of e){let o=r.v??1,a=t.get(o)??[];a.push(r),t.set(o,a)}return[...t.entries()].sort(([r],[o])=>r-o).map(([r,o])=>({v:r,items:o}))}function de(e){let t=e.files;if(typeof t=="string"&&t.trim()!=="")try{let o=JSON.parse(t);if(Array.isArray(o))return o.map(J).filter(a=>a!==null)}catch{}let r=String(e.file??"");return r?[{kind:"file",value:r}]:[]}function ce(e,t,r,o=""){let l=X(e).find(s=>s.v===t)?.items??[],n=l.filter(s=>s.kind==="file").map(s=>r.get(s.value)??"");return l.some(s=>s.kind==="table")&&n.push(o),n.length===0||n.some(s=>s==="")?"awaiting":n.some(s=>s==="revise")?"revise":"accepted"}function pe(e){return Number(e.published_version)||0}function K(e){return e==="number"||e==="date"||e==="boolean"||e==="select"||e==="url"?e:e==="link"?"url":e==="checkbox"?"boolean":"text"}function ge(e){try{let t=JSON.parse(e);if(Array.isArray(t.columns)&&Array.isArray(t.rows)&&t.columns.length){let r=t.columns.map((l,n)=>({key:typeof l.key=="string"&&l.key?l.key:typeof l.id=="string"&&l.id?l.id:`column_${n+1}`,label:typeof l.label=="string"?l.label:"",type:K(l.type),...l.clientEditable===!0?{clientEditable:!0}:{}})),o=t.rows.map((l,n)=>({id:typeof l.id=="string"&&l.id?l.id:`row_${n}`,cells:l.cells&&typeof l.cells=="object"?l.cells:{}})),a=typeof t.name=="string"?t.name:void 0;return{columns:r,rows:o,...a?{name:a}:{}}}}catch{}return null}function me(e){return e==null?"":String(e)}function fe(e){return e===!0||e==="true"||e==="1"||e==="yes"||e==="\u2713"}function E(){return{cells:{},verdict:"",comment:""}}function be(e){if(typeof e!="string"||e.trim()==="")return E();try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t)){let r=t;return{cells:r.cells&&typeof r.cells=="object"?r.cells:r,verdict:r.verdict==="accepted"||r.verdict==="revise"?r.verdict:"",comment:typeof r.comment=="string"?r.comment:""}}}catch{}return E()}function ye(e,t,r){if(e.clientEditable){let o=r.cells[t.id];if(o&&e.key in o)return o[e.key]}return t.cells[e.key]}function he(e,t,r,o){return{...e,cells:{...e.cells,[t]:{...e.cells[t]??{},[r]:o}}}}function we(e,t,r){return{...e,verdict:t,comment:r}}function xe(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 ct=/\/+$/,I="/api/v1/end-user",H=class extends Error{constructor(t){super(t),this.name="PortalConflict"}};function pt(e){let t="";for(let o=0;o<e.length;o+=32768)t+=String.fromCharCode(...e.subarray(o,o+32768));return btoa(t)}var Oe=e=>{let t=e.baseUrl.replace(ct,""),r=()=>typeof e.token=="function"?e.token():e.token,o=async()=>({"content-type":"application/json",authorization:`Bearer ${await r()}`}),a=async(n,s)=>{try{let i=await fetch(`${t}${I}${n}`,{method:s.method,headers:await o(),...s.body===void 0?{}:{body:JSON.stringify(s.body)}});if(i.status===409){let u=await i.json().catch(()=>({}));throw new H(u.message??"Someone else saved this first.")}if(!i.ok){let u=await i.text().catch(()=>""),d=`${s.method} ${n} \u2192 ${String(i.status)}`;try{let c=JSON.parse(u);c.message&&(d=c.message)}catch{d=u?`${d}: ${u}`:d}throw C({error:d})}return await i.json()}catch(i){throw i instanceof H?i:C(i)}},l=n=>`/tables/${encodeURIComponent(n)}`;return{listTables:async()=>(await R(`${t}${I}/tables`,await o())).tables,listRows:async(n,s)=>await R(`${t}${I}${l(n)}/rows?limit=${String(s??100)}`,await o()),insertRow:async(n,s)=>{let{rowIds:i}=await a(`${l(n)}/rows`,{method:"POST",body:{rows:[s]}}),u=i[0];if(!u)throw C(new Error("The row was not created."));return u},patchRow:async(n,s,i)=>(await a(`${l(n)}/rows/${encodeURIComponent(s)}`,{method:"PATCH",body:i})).updated,deleteRow:async(n,s)=>(await a(`/${encodeURIComponent(n)}/${encodeURIComponent(s)}`,{method:"DELETE"})).deleted,listFiles:async()=>(await R(`${t}${I}/tables/files/rows?limit=200`,await o())).rows.map(s=>({id:s.rowId,filename:String(s.data.filename??""),source:String(s.data.source??"client"),campaign:String(s.data.campaign??""),size:typeof s.data.size=="number"?s.data.size:0,createdAt:s.createdAt})),uploadFile:async(n,s)=>{let i=new Uint8Array(await n.arrayBuffer());return await a("/files",{method:"POST",body:{filename:n.name,mime:n.type||"application/octet-stream",data:pt(i),...s===void 0?{}:{message:s}}})},fileLink:async n=>await R(`${t}${I}/files/${encodeURIComponent(n)}/url`,await o()),deleteFile:async n=>(await a(`/files/${encodeURIComponent(n)}`,{method:"DELETE"})).deleted,listDocuments:async()=>(await R(`${t}${I}/documents`,await o())).documents,readDocument:async n=>(await R(`${t}${I}/documents/${encodeURIComponent(n)}`,await o())).document,saveDocument:async(n,s)=>await a(`/documents/${encodeURIComponent(n)}`,{method:"PATCH",body:s})}};var T=require("react"),_e="greeting";function ve(e,t){if(e.some(l=>l.id===t.id))return e;let r=e.filter(l=>l.id!==_e),o=l=>l.author==="client"==(t.author==="client");return[...r.filter(l=>!(l.pending&&o(l)&&l.text===t.text)),t]}var Fe=(e,t)=>{let[r,o]=(0,T.useState)([]),[a,l]=(0,T.useState)(""),[n,s]=(0,T.useState)(!1),[i,u]=(0,T.useState)(null),d=(0,T.useRef)(0),c=t?.pollMs??2e3;(0,T.useEffect)(()=>{let p=!0;return e.getInfo().then(b=>{p&&b.greeting&&o(w=>w.length===0?[{id:_e,cursor:"",author:"agent",text:b.greeting}]:w)}).catch(()=>{}),()=>{p=!1}},[e]),(0,T.useEffect)(()=>e.subscribe?.({onMessage:p=>o(b=>ve(b,p)),onError:p=>u(p.error),onHealthy:()=>u(null)},{intervalMs:c}),[e,c]);let m=(0,T.useCallback)(()=>{let p=a.trim();if(!p||n)return;l(""),u(null),s(!0),d.current+=1;let b=`pending-${d.current}`,w={id:b,cursor:"",author:"client",text:p,pending:!0};o(f=>[...f,w]),e.sendMessage(p).then(f=>{s(!1),f.reply.trim()&&o(g=>g.some(P=>!P.pending&&P.author!=="client"&&P.text===f.reply)?g:(d.current+=1,[...g,{id:`pending-agent-${d.current}`,cursor:"",author:"agent",text:f.reply,pending:!0}]))}).catch(f=>{u(f instanceof Error?f.message:"send_failed"),s(!1),o(D=>D.filter(g=>g.id!==b)),l(D=>D||p)})},[a,n,e]);return{messages:r,input:a,setInput:l,send:m,sending:n,error:i}};0&&(module.exports={Chat,GRID_COLS,GRID_MAX_COLS,GRID_MAX_ROWS,HolaProvider,PortalConflict,bandOfKind,bandOfType,cellValue,createApiTransport,createHolaClient,createPortalData,createWidgetTransport,deliverableCellText,deliverableStatus,deriveFields,emptyTableResponses,footprintOf,footprintWith,formatDeliverableDate,groupDeliverableVersions,inferSpec,isDeliverableChecked,mergeMessage,normalizeDeliverableColType,normalizeDeliverableItem,parseDashboardSpec,parseDeliverableItems,parseDeliverableTable,parseTableResponses,placeWidgets,publishedVersionOf,renderModel,setResponse,setTableReview,splitLayout,textDeltaOf,thinkingDeltaOf,toolEventOf,useArtifactUrl,useChat,useHolaClient,useThread});
|
|
8
|
+
`)}},u=async()=>{let d=await a.read();if(!d.done)return s+=n.decode(d.value,{stream:!0}),l(),u()};await u()};var Qe=/\/+$/,Y="/api/v1/end-user",Pe=e=>{let t=e.baseUrl.replace(Qe,""),r=()=>typeof e.token=="function"?e.token():e.token,o=n=>e.project?`${n}project=${encodeURIComponent(e.project)}`:"",i=async()=>({"content-type":"application/json",authorization:`Bearer ${await r()}`}),a=async n=>{let s=await fetch(`${t}${Y}/chat${o("?")}`,{method:"POST",headers:await i(),body:JSON.stringify({message:n})});if(!s.ok)throw new Error(`hola: message failed (${s.status})`);return{reply:(await s.json()).reply??"",sessionId:"",artifacts:[]}};return{sessionId:()=>"",getInfo:async()=>R(`${t}${Y}/chat/info${o("?")}`,await i()),sendMessage:a,streamMessage:async(n,s)=>{try{let l=await a(n);s.onText?.(l.reply),s.onComplete?.(l)}catch(l){s.onError?.(w(l))}},subscribe:(n,s)=>{let l=s?.since??"0",u=!1,d,c=s?.intervalMs??3e3,g=typeof document<"u",p=()=>g&&document.visibilityState==="hidden",y=!1,x=()=>{if(!u){if(p()){y=!0;return}d=setTimeout(f,c)}},f=async()=>{try{let h=await R(`${t}${Y}/chat/thread?since=${encodeURIComponent(l)}${o("&")}`,await i());for(let I of h.messages)n.onMessage(I);l=h.cursor,n.onHealthy?.()}catch(h){n.onError?.(w(h))}x()},P=()=>{u||!y||p()||(y=!1,d&&clearTimeout(d),d=setTimeout(f,0))};g&&document.addEventListener("visibilitychange",P);let m=()=>{u=!0,d&&clearTimeout(d),g&&document.removeEventListener("visibilitychange",P)};return s?.signal?.addEventListener("abort",m),d=setTimeout(f,0),m}}};var L=require("react"),F=(e,t)=>{let[r,o]=(0,L.useState)("");return(0,L.useEffect)(()=>{if(!e){o("");return}let i=Uint8Array.from(atob(e),n=>n.charCodeAt(0)),a=URL.createObjectURL(new Blob([i],{type:t}));return o(a),()=>URL.revokeObjectURL(a)},[e,t]),r};var G=require("react");var N=require("react"),Ie=require("react/jsx-runtime"),De=(0,N.createContext)(null),Ce=({client:e,children:t})=>(0,Ie.jsx)(De.Provider,{value:e,children:t}),V=()=>{let e=(0,N.useContext)(De);if(!e)throw new Error("useHolaClient must be used within <HolaProvider>");return e};var v=require("react"),j=e=>{let[t,r]=(0,v.useState)([]),[o,i]=(0,v.useState)(""),[a,n]=(0,v.useState)(!1),[s,l]=(0,v.useState)(null),u=(0,v.useRef)(0),d=(0,v.useRef)(null);(0,v.useEffect)(()=>()=>d.current?.abort(),[]);let c=(0,v.useCallback)(()=>{let p=u.current;return u.current+=1,p},[]);(0,v.useEffect)(()=>{let p=!0;return e.getInfo().then(y=>{p&&y.greeting&&r([{id:c(),role:"assistant",text:y.greeting}])}).catch(()=>{}),()=>{p=!1}},[e,c]);let g=(0,v.useCallback)(()=>{let p=o.trim();if(!p||a)return;i(""),l(null),n(!0);let y=c(),x=c();r(m=>[...m,{id:y,role:"user",text:p},{id:x,role:"assistant",text:"",streaming:!0}]);let f=m=>{r(h=>h.map(I=>I.id===x?m(I):I))},P=new AbortController;d.current=P,e.streamMessage(p,{onText:m=>f(h=>({...h,text:h.text+m})),onComplete:m=>{f(h=>({...h,text:m.reply||h.text,artifacts:m.artifacts,streaming:!1})),n(!1)},onError:m=>{f(h=>({...h,streaming:!1})),l(m.error),n(!1)}},P.signal).catch(m=>{f(h=>({...h,streaming:!1})),l(m instanceof Error?m.message:"stream_failed"),n(!1)}).finally(()=>{n(!1),f(m=>m.streaming?{...m,streaming:!1}:m)})},[o,a,e,c]);return{messages:t,input:o,setInput:i,send:g,sending:a,error:s}};var S=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"}},Ye=({artifact:e})=>{let t=F(e.dataBase64??"",e.mimeType),r=e.url??t;return r?e.mimeType.startsWith("image/")?(0,S.jsx)("a",{href:r,rel:"noopener noreferrer",target:"_blank",children:(0,S.jsx)("img",{alt:e.filename,src:r,style:k.image})}):(0,S.jsx)("a",{download:e.filename,href:r,style:k.link,children:e.filename}):null},He=()=>{let e=V(),{messages:t,input:r,setInput:o,send:i,sending:a,error:n}=j(e),s=(0,G.useRef)(null);(0,G.useEffect)(()=>{let u=s.current;u&&(u.scrollTop=u.scrollHeight)},[t]);let l=u=>{u.preventDefault(),i()};return(0,S.jsxs)("div",{style:k.root,children:[(0,S.jsx)("div",{ref:s,style:k.log,children:t.map(u=>(0,S.jsxs)("div",{style:u.role==="user"?k.user:k.assistant,children:[u.text||(u.streaming?"\u2026":""),u.artifacts&&u.artifacts.length>0?(0,S.jsx)("div",{style:k.artifacts,children:u.artifacts.map(d=>(0,S.jsx)(Ye,{artifact:d},d.filename))}):null]},u.id))}),n?(0,S.jsx)("div",{style:k.error,children:n}):null,(0,S.jsxs)("form",{onSubmit:l,style:k.form,children:[(0,S.jsx)("input",{"aria-label":"Message",onChange:u=>o(u.target.value),placeholder:"Type a message\u2026",style:k.input,value:r}),(0,S.jsx)("button",{disabled:a||r.trim().length===0,style:k.button,type:"submit",children:"Send"})]})]})};var Ze=/\/+$/,B=e=>{let t=e.sessionId,r=e.baseUrl.replace(Ze,""),o=n=>`${r}/endpoint/${encodeURIComponent(e.token)}${n}`,i={"content-type":"application/json"},a=(n,s)=>({url:o(n),headers:i,body:JSON.stringify({message:s,...t?{sessionId:t}:{},...e.identity?{externalUserId:e.identity.externalUserId,userHmac:e.identity.userHmac}:{}})});return{sessionId:()=>t,getInfo:()=>R(o("/config"),{}),sendMessage:async n=>{let s=await Te(a("/message",n));return t=s.sessionId,s},streamMessage:(n,s,l)=>ke(a("/message/stream",n),s,u=>{t=u},l),subscribe:(n,s)=>{let l=s?.since??"0",u=!1,d,c=s?.intervalMs??3e3,g=async()=>{let y=t;if(y)try{let x=await R(o(`/messages?session=${encodeURIComponent(y)}&since=${encodeURIComponent(l)}`),{});for(let f of x.messages)n.onMessage(f);l=x.cursor,n.onHealthy?.()}catch(x){n.onError?.(w(x))}u||(d=setTimeout(g,c))},p=()=>{u=!0,d&&clearTimeout(d)};return s?.signal?.addEventListener("abort",p),d=setTimeout(g,0),p}}};var Ae=e=>"transport"in e?e.transport:B(e);var et=/^https?:\/\//i,tt=/^\d{4}-\d{2}-\d{2}(?:[T ]|$)/,nt=e=>e.replace(/_/g," ").replace(/\b\w/g,t=>t.toUpperCase());function rt(e){if(typeof e=="number")return"number";if(typeof e=="boolean")return"boolean";if(typeof e=="string"){if(et.test(e))return"url";if(tt.test(e))return"date"}return"text"}function Z(e){let t=[],r=new Map;for(let o of e)for(let[i,a]of Object.entries(o.data??{})){if(a==null)continue;let n=r.get(i);n||(n=new Map,r.set(i,n),t.push(i));let s=rt(a);n.set(s,(n.get(s)??0)+1)}return t.map(o=>{let i=r.get(o)??new Map,a="text",n=-1;for(let[s,l]of i)l>n&&(n=l,a=s);return{key:o,label:nt(o),type:a}})}var ot=e=>typeof e=="number"?e:Number(e)||0,Me=e=>/rate|position|rank|score|percent|avg/i.test(e),st=/posted|published|sent|completed|shipped|launched|_at/i,it=new Set(["service","order","end_user_id"]);function ee(e,t){let r=e.filter(l=>!it.has(l.key)),o=r.filter(l=>l.type==="number").slice(0,3),i=r.find(l=>l.key==="status")??r.find(l=>l.type==="select"),a=r.find(l=>l.type==="date"&&st.test(l.key))??r.find(l=>l.type==="date"),n=r.filter(l=>l.type==="number"&&!Me(l.key)).map(l=>({field:l,total:t.reduce((u,d)=>u+ot(d.data[l.key]),0)})).sort((l,u)=>u.total-l.total).find(l=>l.total>0)?.field??null,s=[{type:"stat",label:"Items",agg:"count"}];for(let l of o){let u=Me(l.key);s.push({type:"stat",metric:l.key,agg:u?"avg":"sum",label:u?`Avg ${l.label.toLowerCase()}`:l.label})}return a&&s.push({type:"line",x:a.key,y:n?.key,agg:"sum",title:n?`${n.label} by day`:"Items by day"}),i&&s.push({type:"donut",groupBy:i.key,title:i.label}),s.push({type:"table",columns:r.map(l=>l.key)}),{version:1,widgets:s}}var te=6,ne=6,re=4,We={stat:{w:1,h:1},chart:{w:2,h:2},block:{w:6,h:2}},at=e=>Math.max(1,Math.min(6,Math.round(e))),lt=e=>Math.max(1,Math.min(4,Math.round(e)));function M(e){return e==="stat"?"stat":e==="series"||e==="donut"?"chart":"block"}function oe(e){return e==="stat"?"stat":e==="line"||e==="bar"||e==="donut"?"chart":"block"}function se(e){return We[e]}function z(e,t,r){let o=We[e];return{w:t===void 0?o.w:at(t),h:r===void 0?o.h:lt(r)}}function J(e){let t=[],r=[],o=(n,s,l,u)=>{if(n<0||n+l>6)return!1;for(let d=0;d<u;d+=1){let c=r[s+d];if(c){for(let g=0;g<l;g+=1)if(c[n+g])return!1}}return!0},i=(n,s,l,u)=>{for(let d=0;d<u;d+=1){let c=r[s+d]??[];for(let g=0;g<l;g+=1)c[n+g]=!0;r[s+d]=c}},a=(n,s)=>{for(let l=0;;l+=1)for(let u=0;u+n<=6;u+=1)if(o(u,l,n,s))return{gx:u,gy:l}};for(let n of e){let s=z(M(n.kind),n.w,n.h),u=n.gx!==void 0&&n.gy!==void 0&&o(n.gx,n.gy,s.w,s.h)&&n.gx!==void 0&&n.gy!==void 0?{gx:n.gx,gy:n.gy}:a(s.w,s.h);i(u.gx,u.gy,s.w,s.h),t.push({widget:n,gx:u.gx,gy:u.gy,w:s.w,h:s.h})}return t}function ie(e){let t=[],r=[];for(let o of e)M(o.kind)==="block"?r.push(o):t.push(o);return{tiles:J(t),blocks:r}}var Ee=new Set(["service","order","end_user_id"]),ae=e=>typeof e=="number"?e:Number(e)||0,$e=e=>e==null?"":String(e);function le(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((o,i)=>o+i,0);return e==="avg"?Math.round(r/t.length*100)/100:r}function ut(e,t,r,o){let i=new Map;for(let a of e){let n=new Date($e(a.data[t]));if(Number.isNaN(n.getTime()))continue;let s=n.toISOString().slice(0,10),l=i.get(s)??[];l.push(r?ae(a.data[r]):1),i.set(s,l)}return[...i.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:r?le(o,n):n.length}))}function dt(e,t,r,o="sum"){let i=new Map;for(let a of e){let n=$e(a.data[t]).trim();if(!n)continue;let s=i.get(n)??[];s.push(r?ae(a.data[r]):1),i.set(n,s)}return[...i.entries()].map(([a,n])=>({label:a,value:r?le(o,n):n.length})).sort((a,n)=>n.value-a.value)}function pt(e,t,r,o){switch(e.type){case"stat":{let i=e.metric?t.get(e.metric):void 0;if(e.metric&&!i)return null;if(!i)return{kind:"stat",label:e.label??"Items",value:o.length};let a=o.map(n=>ae(n.data[i.key]));return{kind:"stat",label:e.label??i.label,value:le(e.agg??"sum",a)}}case"line":case"bar":{if(!t.has(e.x)||e.y&&!t.has(e.y))return null;let i=ut(o,e.x,e.y,e.agg??"sum");return i.length<2?null:{kind:"series",draw:e.type,title:e.title??"By day",points:i}}case"donut":{if(!t.has(e.groupBy))return null;let i=dt(o,e.groupBy,e.metric,e.agg??"sum");return i.length===0?null:{kind:"donut",title:e.title??t.get(e.groupBy)?.label??"Breakdown",points:i}}case"table":{let i=e.columns?e.columns.map(a=>t.get(a)).filter(a=>a!==void 0&&!Ee.has(a.key)):r;return i.length===0?null:{kind:"table",title:e.title,columns:i,rows:o}}case"text":return{kind:"text",title:e.title,body:e.body};default:return null}}function ue(e,t,r,o={}){let i=new Map,a=l=>({byKey:new Map(l.fields.map(u=>[u.key,u])),cols:l.fields.filter(u=>!Ee.has(u.key)),rows:l.rows}),n=a({fields:t,rows:r});for(let[l,u]of Object.entries(o))i.set(l,a(u));let s=[];for(let l of e.widgets){let u=l.type==="text"?void 0:l.source,d=u?i.get(u):n;if(!d)continue;let c=pt(l,d.byKey,d.cols,d.rows);c&&s.push({...c,w:l.w,h:l.h,gx:l.gx,gy:l.gy})}return s}var ct=new Set(["sum","avg","count","min","max","last"]),_e=e=>typeof e=="string"&&ct.has(e)?e:void 0,b=e=>typeof e=="string"&&e!==""?e:void 0,W=e=>typeof e=="number"&&e>=1?Math.min(6,Math.round(e)):void 0,E=e=>typeof e=="number"&&e>=1?Math.min(4,Math.round(e)):void 0,D=e=>typeof e=="number"&&e>=0?Math.round(e):void 0;function gt(e){if(typeof e!="object"||e===null)return null;let t=e;switch(t.type){case"stat":return{type:"stat",source:b(t.source),label:b(t.label),metric:b(t.metric)??b(t.column),agg:_e(t.agg),w:W(t.w),h:E(t.h),gx:D(t.gx),gy:D(t.gy)};case"line":case"bar":{let r=b(t.x);return r?{type:t.type,source:b(t.source),title:b(t.title),x:r,y:b(t.y)??b(t.column),agg:_e(t.agg),w:W(t.w),h:E(t.h),gx:D(t.gx),gy:D(t.gy)}:null}case"donut":{let r=b(t.groupBy)??b(t.column);return r?{type:"donut",source:b(t.source),title:b(t.title),groupBy:r,w:W(t.w),h:E(t.h),gx:D(t.gx),gy:D(t.gy)}:null}case"table":{let r=Array.isArray(t.columns)?t.columns.filter(o=>typeof o=="string"):void 0;return{type:"table",source:b(t.source),title:b(t.title),columns:r,w:W(t.w),h:E(t.h),gx:D(t.gx),gy:D(t.gy)}}case"text":{let r=b(t.body);return r?{type:"text",title:b(t.title),body:r,w:W(t.w),h:E(t.h),gx:D(t.gx),gy:D(t.gy)}: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 r=t.widgets;if(!Array.isArray(r))return null;let o=r.map(gt).filter(a=>a!==null);if(o.length===0)return null;let i=t.version;return{version:typeof i=="number"?i:1,title:b(t.title),widgets:o}}function K(e){if(typeof e=="string")return e?{kind:"file",value:e}:null;if(e&&typeof e=="object"){let t=e,r=typeof t.value=="string"?t.value:"",o=t.kind==="link"||t.kind==="text"||t.kind==="table"?t.kind:"file",i=typeof t.v=="number"&&t.v>=1?Math.floor(t.v):void 0;return r?{kind:o,value:r,...i?{v:i}:{}}:null}return null}function X(e){let t=new Map;for(let r of e){let o=r.v??1,i=t.get(o)??[];i.push(r),t.set(o,i)}return[...t.entries()].sort(([r],[o])=>r-o).map(([r,o])=>({v:r,items:o}))}function pe(e){let t=e.files;if(typeof t=="string"&&t.trim()!=="")try{let o=JSON.parse(t);if(Array.isArray(o))return o.map(K).filter(i=>i!==null)}catch{}let r=String(e.file??"");return r?[{kind:"file",value:r}]:[]}function ce(e,t,r,o=""){let a=X(e).find(s=>s.v===t)?.items??[],n=a.filter(s=>s.kind==="file").map(s=>r.get(s.value)??"");return a.some(s=>s.kind==="table")&&n.push(o),n.length===0||n.some(s=>s==="")?"awaiting":n.some(s=>s==="revise")?"revise":"accepted"}function ge(e){return Number(e.published_version)||0}function q(e){return e==="number"||e==="date"||e==="boolean"||e==="select"||e==="url"?e:e==="link"?"url":e==="checkbox"?"boolean":"text"}function me(e){try{let t=JSON.parse(e);if(Array.isArray(t.columns)&&Array.isArray(t.rows)&&t.columns.length){let r=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:q(a.type),...a.clientEditable===!0?{clientEditable:!0}:{}})),o=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:{}})),i=typeof t.name=="string"?t.name:void 0;return{columns:r,rows:o,...i?{name:i}:{}}}}catch{}return null}function fe(e){return e==null?"":String(e)}function ye(e){return e===!0||e==="true"||e==="1"||e==="yes"||e==="\u2713"}function $(){return{cells:{},verdict:"",comment:""}}function be(e){if(typeof e!="string"||e.trim()==="")return $();try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t)){let r=t;return{cells:r.cells&&typeof r.cells=="object"?r.cells:r,verdict:r.verdict==="accepted"||r.verdict==="revise"?r.verdict:"",comment:typeof r.comment=="string"?r.comment:""}}}catch{}return $()}function he(e,t,r){if(e.clientEditable){let o=r.cells[t.id];if(o&&e.key in o)return o[e.key]}return t.cells[e.key]}function we(e,t,r,o){return{...e,cells:{...e.cells,[t]:{...e.cells[t]??{},[r]:o}}}}function xe(e,t,r){return{...e,verdict:t,comment:r}}function ve(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 mt=/\/+$/,H="/api/v1/end-user",A=class extends Error{constructor(t){super(t),this.name="PortalConflict"}};function ft(e){let t="";for(let o=0;o<e.length;o+=32768)t+=String.fromCharCode(...e.subarray(o,o+32768));return btoa(t)}var Oe=e=>{let t=e.baseUrl.replace(mt,""),r=()=>typeof e.token=="function"?e.token():e.token,o=async()=>({"content-type":"application/json",authorization:`Bearer ${await r()}`}),i=async(n,s)=>{try{let l=await fetch(`${t}${H}${n}`,{method:s.method,headers:await o(),...s.body===void 0?{}:{body:JSON.stringify(s.body)}});if(l.status===409){let u=await l.json().catch(()=>({}));throw new A(u.message??"Someone else saved this first.")}if(!l.ok){let u=await l.text().catch(()=>""),d=`${s.method} ${n} \u2192 ${String(l.status)}`;try{let c=JSON.parse(u);c.message&&(d=c.message)}catch{d=u?`${d}: ${u}`:d}throw w({error:d})}return await l.json()}catch(l){throw l instanceof A?l:w(l)}},a=n=>`/tables/${encodeURIComponent(n)}`;return{listTables:async()=>(await R(`${t}${H}/tables`,await o())).tables,listRows:async(n,s)=>await R(`${t}${H}${a(n)}/rows?limit=${String(s??100)}`,await o()),insertRow:async(n,s)=>{let{rowIds:l}=await i(`${a(n)}/rows`,{method:"POST",body:{rows:[s]}}),u=l[0];if(!u)throw w(new Error("The row was not created."));return u},patchRow:async(n,s,l)=>(await i(`${a(n)}/rows/${encodeURIComponent(s)}`,{method:"PATCH",body:l})).updated,deleteRow:async(n,s)=>(await i(`/${encodeURIComponent(n)}/${encodeURIComponent(s)}`,{method:"DELETE"})).deleted,listFiles:async()=>(await R(`${t}${H}/tables/files/rows?limit=200`,await o())).rows.map(s=>({id:s.rowId,filename:String(s.data.filename??""),source:String(s.data.source??"client"),campaign:String(s.data.campaign??""),size:typeof s.data.size=="number"?s.data.size:0,createdAt:s.createdAt})),uploadFile:async(n,s)=>{let l=new Uint8Array(await n.arrayBuffer());return await i("/files",{method:"POST",body:{filename:n.name,mime:n.type||"application/octet-stream",data:ft(l),...s===void 0?{}:{message:s}}})},fileLink:async n=>await R(`${t}${H}/files/${encodeURIComponent(n)}/url`,await o()),deleteFile:async n=>(await i(`/files/${encodeURIComponent(n)}`,{method:"DELETE"})).deleted,listDocuments:async()=>(await R(`${t}${H}/documents`,await o())).documents,readDocument:async n=>(await R(`${t}${H}/documents/${encodeURIComponent(n)}`,await o())).document,saveDocument:async(n,s)=>await i(`/documents/${encodeURIComponent(n)}`,{method:"PATCH",body:s})}};var yt=/\/+$/,bt="/api/v1/end-user",Ue=e=>{let t=e.baseUrl.replace(yt,""),r=async(o,i)=>{let a;try{a=await fetch(`${t}${bt}${o}`,i===void 0?{}:{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(i)})}catch(n){throw w(n)}if(a.status===429)throw w({error:"rate_limited",retryable:!0});if(!a.ok)throw w({error:`shop_request_failed_${String(a.status)}`});try{return await a.json()}catch(n){throw w(n)}};return{listProducts:async()=>{let o=await r(`/shop/products?publishable_key=${encodeURIComponent(e.publishableKey)}`);return{products:o.products.map(i=>({...i,currency:typeof i.currency=="string"?i.currency:""})),truncated:o.truncated===!0}},apply:async o=>await r("/shop/apply",{publishable_key:e.publishableKey,name:o.name,email:o.email,...o.phone?{phone:o.phone}:{},...o.message?{message:o.message}:{},...o.productId?{productId:o.productId}:{}})}};var C=require("react"),ht=e=>e&&typeof e=="object"&&typeof e.error=="string"?e.error:e instanceof Error?e.message:"shop_unavailable",Le=e=>{let[t,r]=(0,C.useState)([]),[o,i]=(0,C.useState)(!1),[a,n]=(0,C.useState)(!0),[s,l]=(0,C.useState)(null),[u,d]=(0,C.useState)(0);(0,C.useEffect)(()=>{let g=!0;return n(!0),e.listProducts().then(p=>{g&&(r(p.products),i(p.truncated),l(null))}).catch(p=>{g&&l(ht(p))}).finally(()=>{g&&n(!1)}),()=>{g=!1}},[e,u]);let c=(0,C.useCallback)(()=>d(g=>g+1),[]);return{products:t,truncated:o,loading:a,error:s,reload:c}};var T=require("react"),Fe="greeting";function Se(e,t){if(e.some(a=>a.id===t.id))return e;let r=e.filter(a=>a.id!==Fe),o=a=>a.author==="client"==(t.author==="client");return[...r.filter(a=>!(a.pending&&o(a)&&a.text===t.text)),t]}var Ne=(e,t)=>{let[r,o]=(0,T.useState)([]),[i,a]=(0,T.useState)(""),[n,s]=(0,T.useState)(!1),[l,u]=(0,T.useState)(null),d=(0,T.useRef)(0),c=t?.pollMs??2e3;(0,T.useEffect)(()=>{let p=!0;return e.getInfo().then(y=>{p&&y.greeting&&o(x=>x.length===0?[{id:Fe,cursor:"",author:"agent",text:y.greeting}]:x)}).catch(()=>{}),()=>{p=!1}},[e]),(0,T.useEffect)(()=>e.subscribe?.({onMessage:p=>o(y=>Se(y,p)),onError:p=>u(p.error),onHealthy:()=>u(null)},{intervalMs:c}),[e,c]);let g=(0,T.useCallback)(()=>{let p=i.trim();if(!p||n)return;a(""),u(null),s(!0),d.current+=1;let y=`pending-${d.current}`,x={id:y,cursor:"",author:"client",text:p,pending:!0};o(f=>[...f,x]),e.sendMessage(p).then(f=>{s(!1),f.reply.trim()&&o(m=>m.some(I=>!I.pending&&I.author!=="client"&&I.text===f.reply)?m:(d.current+=1,[...m,{id:`pending-agent-${d.current}`,cursor:"",author:"agent",text:f.reply,pending:!0}]))}).catch(f=>{u(f instanceof Error?f.message:"send_failed"),s(!1),o(P=>P.filter(m=>m.id!==y)),a(P=>P||p)})},[i,n,e]);return{messages:r,input:i,setInput:a,send:g,sending:n,error:l}};0&&(module.exports={Chat,GRID_COLS,GRID_MAX_COLS,GRID_MAX_ROWS,HolaProvider,PortalConflict,bandOfKind,bandOfType,cellValue,createApiTransport,createHolaClient,createPortalData,createPortalShop,createWidgetTransport,deliverableCellText,deliverableStatus,deriveFields,emptyTableResponses,footprintOf,footprintWith,formatDeliverableDate,groupDeliverableVersions,inferSpec,isDeliverableChecked,mergeMessage,normalizeDeliverableColType,normalizeDeliverableItem,parseDashboardSpec,parseDeliverableItems,parseDeliverableTable,parseTableResponses,placeWidgets,publishedVersionOf,renderModel,setResponse,setTableReview,splitLayout,textDeltaOf,thinkingDeltaOf,toolEventOf,useArtifactUrl,useChat,useHolaClient,useShop,useThread});
|
package/dist/index.d.cts
CHANGED
|
@@ -609,6 +609,160 @@ declare const thinkingDeltaOf: (event: unknown) => string | null;
|
|
|
609
609
|
/** Extract a tool-execution start/end from a raw pi turn event, or null. */
|
|
610
610
|
declare const toolEventOf: (event: unknown) => HolaToolEvent | null;
|
|
611
611
|
|
|
612
|
+
type PortalShopConfig = {
|
|
613
|
+
/** API origin, e.g. "https://api.holaos.ai" — or empty for a portal whose own worker answers
|
|
614
|
+
* `/api/v1/end-user/…` same-origin, which is how the iMerch template is wired. */
|
|
615
|
+
baseUrl: string;
|
|
616
|
+
/**
|
|
617
|
+
* The tenant's publishable key, which is the whole of the authentication here.
|
|
618
|
+
*
|
|
619
|
+
* A plain string rather than the getter `ApiTransportConfig.token` takes: an end-user token
|
|
620
|
+
* refreshes and a publishable key does not — it is baked into the page source a visitor can read,
|
|
621
|
+
* which is what makes it publishable. There is deliberately no token field on this config at all,
|
|
622
|
+
* so nothing in a storefront can come to depend on being signed in to browse.
|
|
623
|
+
*/
|
|
624
|
+
publishableKey: string;
|
|
625
|
+
};
|
|
626
|
+
/** How a product is taken: `buy` charges for it, `ask` opens the conversation the customer already
|
|
627
|
+
* has with the company, `apply` posts the form `apply()` sends. */
|
|
628
|
+
type ShopMode = "buy" | "ask" | "apply";
|
|
629
|
+
/**
|
|
630
|
+
* What a product costs — exactly one of four shapes, never two.
|
|
631
|
+
*
|
|
632
|
+
* The number is in whatever unit the OPERATOR prices in: credits for an org that sells them, money
|
|
633
|
+
* for one that does not — and the wire says which, on `ShopProduct.currency` beside this. It used
|
|
634
|
+
* to say otherwise, that the figure travelled bare and the unit "belongs to the template that knows
|
|
635
|
+
* the tenant", which was how this contract was written before `pricing_unit` existed and was false
|
|
636
|
+
* the day the server started sending the field. A template built on that sentence prints a
|
|
637
|
+
* hardcoded `$` in front of a credit price — wrong by the whole book rate. Nothing here should ever
|
|
638
|
+
* print a `$` it did not read off `currency`.
|
|
639
|
+
*
|
|
640
|
+
* `quoted` is not a price. It is the honest answer for everything in a real catalogue that reads
|
|
641
|
+
* `5k – 10k`, `20k+` or 待定 — a statement that a human has to quote this. Render it as words, and
|
|
642
|
+
* never behind a Buy button that cannot compute a total.
|
|
643
|
+
*/
|
|
644
|
+
type ShopPricing = {
|
|
645
|
+
kind: "flat";
|
|
646
|
+
price: number;
|
|
647
|
+
} | {
|
|
648
|
+
kind: "per_unit";
|
|
649
|
+
unit: string;
|
|
650
|
+
unitPrice: number;
|
|
651
|
+
unitStep: number;
|
|
652
|
+
} | {
|
|
653
|
+
kind: "variants";
|
|
654
|
+
variants: {
|
|
655
|
+
name: string;
|
|
656
|
+
price: number | null;
|
|
657
|
+
}[];
|
|
658
|
+
} | {
|
|
659
|
+
kind: "quoted";
|
|
660
|
+
};
|
|
661
|
+
/** One part of a bundle, as the shelf is allowed to describe it: what it is called, what it covers,
|
|
662
|
+
* how long it runs — and no price, for the reason at the top of this file. */
|
|
663
|
+
type ShopInclusion = {
|
|
664
|
+
name: string;
|
|
665
|
+
content?: string;
|
|
666
|
+
period?: string;
|
|
667
|
+
};
|
|
668
|
+
/** A named tier — 基础 / 标准 / 高阶 — and what it covers. Its PRICE is not here: it is in
|
|
669
|
+
* `pricing` (`kind: "variants"`), matched to this by name, so that there is one place the money
|
|
670
|
+
* comes from and no way for the two to disagree. */
|
|
671
|
+
type ShopVariant = {
|
|
672
|
+
name: string;
|
|
673
|
+
includes: ShopInclusion[];
|
|
674
|
+
};
|
|
675
|
+
/** One product as a visitor sees it. */
|
|
676
|
+
type ShopProduct = {
|
|
677
|
+
id: string;
|
|
678
|
+
name: string;
|
|
679
|
+
summary: string;
|
|
680
|
+
description: string;
|
|
681
|
+
/**
|
|
682
|
+
* One of `ShopMode` for anything authored in the console — but typed as the string it is on the
|
|
683
|
+
* wire, because the server sends the row's own value and a product from before the field existed
|
|
684
|
+
* answers `""`. A storefront that switched over the union would be handed a value the type swore
|
|
685
|
+
* could not occur, so match the three and keep a default arm.
|
|
686
|
+
*/
|
|
687
|
+
mode: string;
|
|
688
|
+
category: string;
|
|
689
|
+
platform: string;
|
|
690
|
+
cadence: string;
|
|
691
|
+
period: string;
|
|
692
|
+
/** Image URLs for the card and the product page; empty when the operator set none. */
|
|
693
|
+
media: string[];
|
|
694
|
+
pricing: ShopPricing;
|
|
695
|
+
/** What THIS product's numbers are in — an ISO code, or the literal "credits". It sits on the
|
|
696
|
+
* product rather than on the shelf because a shelf can be mixed: once an org sells credits, its
|
|
697
|
+
* buyable products are priced in them while a 20k engagement it merely quotes stays in money.
|
|
698
|
+
* Empty from a backend older than the field, which is a shelf that has not SAID — and is not the
|
|
699
|
+
* same as one that said dollars, so print the bare figure rather than guessing a symbol. */
|
|
700
|
+
currency: string;
|
|
701
|
+
/** Bounds on a per-unit purchase, when the product states them. Public because the quantity
|
|
702
|
+
* picker has to honour them — a customer who meets a limit they were never shown reads it as a
|
|
703
|
+
* broken shop. */
|
|
704
|
+
minQty?: number;
|
|
705
|
+
maxQty?: number;
|
|
706
|
+
includes: ShopInclusion[];
|
|
707
|
+
/** Present only where the tiers differ in scope; a product without them has one implicit tier,
|
|
708
|
+
* which is its own `pricing` and its own `includes`. */
|
|
709
|
+
variants?: ShopVariant[];
|
|
710
|
+
};
|
|
711
|
+
type ShopShelf = {
|
|
712
|
+
products: ShopProduct[];
|
|
713
|
+
/**
|
|
714
|
+
* The catalogue is bigger than what came back.
|
|
715
|
+
*
|
|
716
|
+
* Kept rather than dropped for the reason `listRows` returns a page: the server caps a shelf read,
|
|
717
|
+
* and a shop that quietly ends at the cap is a customer who cannot see half of it and nobody who
|
|
718
|
+
* can tell. The same argument the server makes when it bothers to send the flag.
|
|
719
|
+
*/
|
|
720
|
+
truncated: boolean;
|
|
721
|
+
};
|
|
722
|
+
/** An application against a product, or against nothing in particular — a general enquiry that
|
|
723
|
+
* names no product is a real thing to receive, so `productId` is optional. */
|
|
724
|
+
type ShopApplication = {
|
|
725
|
+
name: string;
|
|
726
|
+
/**
|
|
727
|
+
* Where the operator answers. Required, and checked by the server — but a malformed one is
|
|
728
|
+
* dropped SILENTLY (see `apply` below), so a form that wants to tell someone their address is
|
|
729
|
+
* wrong has to say so itself, before it sends.
|
|
730
|
+
*/
|
|
731
|
+
email: string;
|
|
732
|
+
phone?: string;
|
|
733
|
+
message?: string;
|
|
734
|
+
productId?: string;
|
|
735
|
+
};
|
|
736
|
+
/** The one answer every application gets. See `apply` for why it never varies. */
|
|
737
|
+
type ShopApplyResult = {
|
|
738
|
+
/**
|
|
739
|
+
* Always `true` — including for a submission that was dropped. It is a receipt that the request
|
|
740
|
+
* was accepted, never evidence that a row exists.
|
|
741
|
+
*/
|
|
742
|
+
ok: boolean;
|
|
743
|
+
/** The server's own thank-you line. Shown as sent rather than reworded, so the operator's copy is
|
|
744
|
+
* the copy the applicant reads. */
|
|
745
|
+
message: string;
|
|
746
|
+
};
|
|
747
|
+
type PortalShop = {
|
|
748
|
+
/** Everything on sale, in the operator's own order. Listed products only — a draft is something
|
|
749
|
+
* still being written and an archived one is off sale but kept because orders point at it. */
|
|
750
|
+
listProducts(): Promise<ShopShelf>;
|
|
751
|
+
/**
|
|
752
|
+
* Send an application. No account, no session — this is the one write on the platform a total
|
|
753
|
+
* stranger can make.
|
|
754
|
+
*
|
|
755
|
+
* It answers the SAME "thanks, we have your details" to an unknown key, a body that did not
|
|
756
|
+
* parse and a write that failed as it does to an application that landed, and that is deliberate:
|
|
757
|
+
* anything else would turn this into a way to ask which publishable keys reach a real company —
|
|
758
|
+
* and, once signups are invite-only, which addresses one already has. The cost is that a
|
|
759
|
+
* miswired form gets a cheerful reply and files nothing, so when applications are not arriving,
|
|
760
|
+
* the answer is in the operator's server logs and cannot be here.
|
|
761
|
+
*/
|
|
762
|
+
apply(application: ShopApplication): Promise<ShopApplyResult>;
|
|
763
|
+
};
|
|
764
|
+
declare const createPortalShop: (config: PortalShopConfig) => PortalShop;
|
|
765
|
+
|
|
612
766
|
/** Provides a `HolaClient` (from `createHolaClient`) to `useChat` / `<Chat/>`.
|
|
613
767
|
* Create the client once (e.g. `useMemo`) so its session persists across renders. */
|
|
614
768
|
declare const HolaProvider: ({ client, children, }: {
|
|
@@ -635,6 +789,30 @@ type UseChat = {
|
|
|
635
789
|
/** Chat state for one employee client: greeting, message list, streaming send. */
|
|
636
790
|
declare const useChat: (client: HolaClient) => UseChat;
|
|
637
791
|
|
|
792
|
+
type UseShop = {
|
|
793
|
+
products: ShopProduct[];
|
|
794
|
+
/** In flight — the first read, and every `reload`. The products from the previous read stay put
|
|
795
|
+
* underneath it, so a refresh does not blank a shop that is already on screen. */
|
|
796
|
+
loading: boolean;
|
|
797
|
+
/** The catalogue is bigger than `products`; the server capped the read. */
|
|
798
|
+
truncated: boolean;
|
|
799
|
+
/** Why the last read failed, as the SDK's own code — `rate_limited` is the one worth wording
|
|
800
|
+
* differently, since it is the only failure that fixes itself. */
|
|
801
|
+
error: string | null;
|
|
802
|
+
reload: () => void;
|
|
803
|
+
};
|
|
804
|
+
/**
|
|
805
|
+
* The public shelf, loaded on mount.
|
|
806
|
+
*
|
|
807
|
+
* Hold `shop` still: build it once at module scope, the way a portal builds its client (`export
|
|
808
|
+
* const holaShop = createPortalShop(config)`), and hand the same object in on every render. A
|
|
809
|
+
* `createPortalShop({...})` written inside the component body is a new object each time, and since
|
|
810
|
+
* that identity is what this re-reads on, the storefront would fetch its own shelf in a loop —
|
|
811
|
+
* against a route that is rate-limited per visitor, so the shop would end up empty for the person
|
|
812
|
+
* least at fault.
|
|
813
|
+
*/
|
|
814
|
+
declare const useShop: (shop: PortalShop) => UseShop;
|
|
815
|
+
|
|
638
816
|
/** A thread message; `pending` marks an optimistic echo of the visitor's own send, shown
|
|
639
817
|
* instantly and replaced by the authoritative message when the receive channel delivers it. */
|
|
640
818
|
type ThreadMessage = HolaMessage & {
|
|
@@ -658,4 +836,4 @@ declare const useThread: (client: HolaClient, options?: {
|
|
|
658
836
|
pollMs?: number;
|
|
659
837
|
}) => UseThread;
|
|
660
838
|
|
|
661
|
-
export { type Agg, type ApiTransportConfig, type Band, type ChartView, Chat, type ChatMessage, type CreateHolaClientOptions, type DashboardLayout, type DashboardSpec, type DeliverableColType, type DeliverableColumn, type DeliverableItem, type DeliverableItemKind, type DeliverableReviewState, type DeliverableRow, type DeliverableTable, type DeliverableVersion, type DonutWidget, GRID_COLS, 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 PlacedWidget, type Point, PortalConflict, type PortalData, type PortalDocument, type PortalDocumentSummary, type PortalField, type PortalFile, type PortalRow, type PortalRowAuthor, type PortalRowPage, type PortalTable, type ResolvedWidget, type SeriesWidget, type StatView, type StatWidget, type TableResponses, type TableReviewVerdict, type TableWidget, type TextWidget, type ThreadMessage, type UseChat, type UseThread, type Widget, type WidgetTransportConfig, type WidgetType, bandOfKind, bandOfType, cellValue, createApiTransport, createHolaClient, createPortalData, createWidgetTransport, deliverableCellText, deliverableStatus, deriveFields, emptyTableResponses, footprintOf, footprintWith, formatDeliverableDate, groupDeliverableVersions, inferSpec, isDeliverableChecked, mergeMessage, normalizeDeliverableColType, normalizeDeliverableItem, parseDashboardSpec, parseDeliverableItems, parseDeliverableTable, parseTableResponses, placeWidgets, publishedVersionOf, renderModel, setResponse, setTableReview, splitLayout, textDeltaOf, thinkingDeltaOf, toolEventOf, useArtifactUrl, useChat, useHolaClient, useThread };
|
|
839
|
+
export { type Agg, type ApiTransportConfig, type Band, type ChartView, Chat, type ChatMessage, type CreateHolaClientOptions, type DashboardLayout, type DashboardSpec, type DataSource, type DeliverableColType, type DeliverableColumn, type DeliverableItem, type DeliverableItemKind, type DeliverableReviewState, type DeliverableRow, type DeliverableTable, type DeliverableVersion, type DonutWidget, GRID_COLS, 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 PlacedWidget, type Point, PortalConflict, type PortalData, type PortalDocument, type PortalDocumentSummary, type PortalField, type PortalFile, type PortalRow, type PortalRowAuthor, type PortalRowPage, type PortalShop, type PortalShopConfig, type PortalTable, type ResolvedWidget, type SeriesWidget, type ShopApplication, type ShopApplyResult, type ShopInclusion, type ShopMode, type ShopPricing, type ShopProduct, type ShopShelf, type ShopVariant, type StatView, type StatWidget, type TableResponses, type TableReviewVerdict, type TableWidget, type TextWidget, type ThreadMessage, type UseChat, type UseShop, type UseThread, type Widget, type WidgetTransportConfig, type WidgetType, bandOfKind, bandOfType, cellValue, createApiTransport, createHolaClient, createPortalData, createPortalShop, createWidgetTransport, deliverableCellText, deliverableStatus, deriveFields, emptyTableResponses, footprintOf, footprintWith, formatDeliverableDate, groupDeliverableVersions, inferSpec, isDeliverableChecked, mergeMessage, normalizeDeliverableColType, normalizeDeliverableItem, parseDashboardSpec, parseDeliverableItems, parseDeliverableTable, parseTableResponses, placeWidgets, publishedVersionOf, renderModel, setResponse, setTableReview, splitLayout, textDeltaOf, thinkingDeltaOf, toolEventOf, useArtifactUrl, useChat, useHolaClient, useShop, useThread };
|
package/dist/index.d.ts
CHANGED
|
@@ -609,6 +609,160 @@ declare const thinkingDeltaOf: (event: unknown) => string | null;
|
|
|
609
609
|
/** Extract a tool-execution start/end from a raw pi turn event, or null. */
|
|
610
610
|
declare const toolEventOf: (event: unknown) => HolaToolEvent | null;
|
|
611
611
|
|
|
612
|
+
type PortalShopConfig = {
|
|
613
|
+
/** API origin, e.g. "https://api.holaos.ai" — or empty for a portal whose own worker answers
|
|
614
|
+
* `/api/v1/end-user/…` same-origin, which is how the iMerch template is wired. */
|
|
615
|
+
baseUrl: string;
|
|
616
|
+
/**
|
|
617
|
+
* The tenant's publishable key, which is the whole of the authentication here.
|
|
618
|
+
*
|
|
619
|
+
* A plain string rather than the getter `ApiTransportConfig.token` takes: an end-user token
|
|
620
|
+
* refreshes and a publishable key does not — it is baked into the page source a visitor can read,
|
|
621
|
+
* which is what makes it publishable. There is deliberately no token field on this config at all,
|
|
622
|
+
* so nothing in a storefront can come to depend on being signed in to browse.
|
|
623
|
+
*/
|
|
624
|
+
publishableKey: string;
|
|
625
|
+
};
|
|
626
|
+
/** How a product is taken: `buy` charges for it, `ask` opens the conversation the customer already
|
|
627
|
+
* has with the company, `apply` posts the form `apply()` sends. */
|
|
628
|
+
type ShopMode = "buy" | "ask" | "apply";
|
|
629
|
+
/**
|
|
630
|
+
* What a product costs — exactly one of four shapes, never two.
|
|
631
|
+
*
|
|
632
|
+
* The number is in whatever unit the OPERATOR prices in: credits for an org that sells them, money
|
|
633
|
+
* for one that does not — and the wire says which, on `ShopProduct.currency` beside this. It used
|
|
634
|
+
* to say otherwise, that the figure travelled bare and the unit "belongs to the template that knows
|
|
635
|
+
* the tenant", which was how this contract was written before `pricing_unit` existed and was false
|
|
636
|
+
* the day the server started sending the field. A template built on that sentence prints a
|
|
637
|
+
* hardcoded `$` in front of a credit price — wrong by the whole book rate. Nothing here should ever
|
|
638
|
+
* print a `$` it did not read off `currency`.
|
|
639
|
+
*
|
|
640
|
+
* `quoted` is not a price. It is the honest answer for everything in a real catalogue that reads
|
|
641
|
+
* `5k – 10k`, `20k+` or 待定 — a statement that a human has to quote this. Render it as words, and
|
|
642
|
+
* never behind a Buy button that cannot compute a total.
|
|
643
|
+
*/
|
|
644
|
+
type ShopPricing = {
|
|
645
|
+
kind: "flat";
|
|
646
|
+
price: number;
|
|
647
|
+
} | {
|
|
648
|
+
kind: "per_unit";
|
|
649
|
+
unit: string;
|
|
650
|
+
unitPrice: number;
|
|
651
|
+
unitStep: number;
|
|
652
|
+
} | {
|
|
653
|
+
kind: "variants";
|
|
654
|
+
variants: {
|
|
655
|
+
name: string;
|
|
656
|
+
price: number | null;
|
|
657
|
+
}[];
|
|
658
|
+
} | {
|
|
659
|
+
kind: "quoted";
|
|
660
|
+
};
|
|
661
|
+
/** One part of a bundle, as the shelf is allowed to describe it: what it is called, what it covers,
|
|
662
|
+
* how long it runs — and no price, for the reason at the top of this file. */
|
|
663
|
+
type ShopInclusion = {
|
|
664
|
+
name: string;
|
|
665
|
+
content?: string;
|
|
666
|
+
period?: string;
|
|
667
|
+
};
|
|
668
|
+
/** A named tier — 基础 / 标准 / 高阶 — and what it covers. Its PRICE is not here: it is in
|
|
669
|
+
* `pricing` (`kind: "variants"`), matched to this by name, so that there is one place the money
|
|
670
|
+
* comes from and no way for the two to disagree. */
|
|
671
|
+
type ShopVariant = {
|
|
672
|
+
name: string;
|
|
673
|
+
includes: ShopInclusion[];
|
|
674
|
+
};
|
|
675
|
+
/** One product as a visitor sees it. */
|
|
676
|
+
type ShopProduct = {
|
|
677
|
+
id: string;
|
|
678
|
+
name: string;
|
|
679
|
+
summary: string;
|
|
680
|
+
description: string;
|
|
681
|
+
/**
|
|
682
|
+
* One of `ShopMode` for anything authored in the console — but typed as the string it is on the
|
|
683
|
+
* wire, because the server sends the row's own value and a product from before the field existed
|
|
684
|
+
* answers `""`. A storefront that switched over the union would be handed a value the type swore
|
|
685
|
+
* could not occur, so match the three and keep a default arm.
|
|
686
|
+
*/
|
|
687
|
+
mode: string;
|
|
688
|
+
category: string;
|
|
689
|
+
platform: string;
|
|
690
|
+
cadence: string;
|
|
691
|
+
period: string;
|
|
692
|
+
/** Image URLs for the card and the product page; empty when the operator set none. */
|
|
693
|
+
media: string[];
|
|
694
|
+
pricing: ShopPricing;
|
|
695
|
+
/** What THIS product's numbers are in — an ISO code, or the literal "credits". It sits on the
|
|
696
|
+
* product rather than on the shelf because a shelf can be mixed: once an org sells credits, its
|
|
697
|
+
* buyable products are priced in them while a 20k engagement it merely quotes stays in money.
|
|
698
|
+
* Empty from a backend older than the field, which is a shelf that has not SAID — and is not the
|
|
699
|
+
* same as one that said dollars, so print the bare figure rather than guessing a symbol. */
|
|
700
|
+
currency: string;
|
|
701
|
+
/** Bounds on a per-unit purchase, when the product states them. Public because the quantity
|
|
702
|
+
* picker has to honour them — a customer who meets a limit they were never shown reads it as a
|
|
703
|
+
* broken shop. */
|
|
704
|
+
minQty?: number;
|
|
705
|
+
maxQty?: number;
|
|
706
|
+
includes: ShopInclusion[];
|
|
707
|
+
/** Present only where the tiers differ in scope; a product without them has one implicit tier,
|
|
708
|
+
* which is its own `pricing` and its own `includes`. */
|
|
709
|
+
variants?: ShopVariant[];
|
|
710
|
+
};
|
|
711
|
+
type ShopShelf = {
|
|
712
|
+
products: ShopProduct[];
|
|
713
|
+
/**
|
|
714
|
+
* The catalogue is bigger than what came back.
|
|
715
|
+
*
|
|
716
|
+
* Kept rather than dropped for the reason `listRows` returns a page: the server caps a shelf read,
|
|
717
|
+
* and a shop that quietly ends at the cap is a customer who cannot see half of it and nobody who
|
|
718
|
+
* can tell. The same argument the server makes when it bothers to send the flag.
|
|
719
|
+
*/
|
|
720
|
+
truncated: boolean;
|
|
721
|
+
};
|
|
722
|
+
/** An application against a product, or against nothing in particular — a general enquiry that
|
|
723
|
+
* names no product is a real thing to receive, so `productId` is optional. */
|
|
724
|
+
type ShopApplication = {
|
|
725
|
+
name: string;
|
|
726
|
+
/**
|
|
727
|
+
* Where the operator answers. Required, and checked by the server — but a malformed one is
|
|
728
|
+
* dropped SILENTLY (see `apply` below), so a form that wants to tell someone their address is
|
|
729
|
+
* wrong has to say so itself, before it sends.
|
|
730
|
+
*/
|
|
731
|
+
email: string;
|
|
732
|
+
phone?: string;
|
|
733
|
+
message?: string;
|
|
734
|
+
productId?: string;
|
|
735
|
+
};
|
|
736
|
+
/** The one answer every application gets. See `apply` for why it never varies. */
|
|
737
|
+
type ShopApplyResult = {
|
|
738
|
+
/**
|
|
739
|
+
* Always `true` — including for a submission that was dropped. It is a receipt that the request
|
|
740
|
+
* was accepted, never evidence that a row exists.
|
|
741
|
+
*/
|
|
742
|
+
ok: boolean;
|
|
743
|
+
/** The server's own thank-you line. Shown as sent rather than reworded, so the operator's copy is
|
|
744
|
+
* the copy the applicant reads. */
|
|
745
|
+
message: string;
|
|
746
|
+
};
|
|
747
|
+
type PortalShop = {
|
|
748
|
+
/** Everything on sale, in the operator's own order. Listed products only — a draft is something
|
|
749
|
+
* still being written and an archived one is off sale but kept because orders point at it. */
|
|
750
|
+
listProducts(): Promise<ShopShelf>;
|
|
751
|
+
/**
|
|
752
|
+
* Send an application. No account, no session — this is the one write on the platform a total
|
|
753
|
+
* stranger can make.
|
|
754
|
+
*
|
|
755
|
+
* It answers the SAME "thanks, we have your details" to an unknown key, a body that did not
|
|
756
|
+
* parse and a write that failed as it does to an application that landed, and that is deliberate:
|
|
757
|
+
* anything else would turn this into a way to ask which publishable keys reach a real company —
|
|
758
|
+
* and, once signups are invite-only, which addresses one already has. The cost is that a
|
|
759
|
+
* miswired form gets a cheerful reply and files nothing, so when applications are not arriving,
|
|
760
|
+
* the answer is in the operator's server logs and cannot be here.
|
|
761
|
+
*/
|
|
762
|
+
apply(application: ShopApplication): Promise<ShopApplyResult>;
|
|
763
|
+
};
|
|
764
|
+
declare const createPortalShop: (config: PortalShopConfig) => PortalShop;
|
|
765
|
+
|
|
612
766
|
/** Provides a `HolaClient` (from `createHolaClient`) to `useChat` / `<Chat/>`.
|
|
613
767
|
* Create the client once (e.g. `useMemo`) so its session persists across renders. */
|
|
614
768
|
declare const HolaProvider: ({ client, children, }: {
|
|
@@ -635,6 +789,30 @@ type UseChat = {
|
|
|
635
789
|
/** Chat state for one employee client: greeting, message list, streaming send. */
|
|
636
790
|
declare const useChat: (client: HolaClient) => UseChat;
|
|
637
791
|
|
|
792
|
+
type UseShop = {
|
|
793
|
+
products: ShopProduct[];
|
|
794
|
+
/** In flight — the first read, and every `reload`. The products from the previous read stay put
|
|
795
|
+
* underneath it, so a refresh does not blank a shop that is already on screen. */
|
|
796
|
+
loading: boolean;
|
|
797
|
+
/** The catalogue is bigger than `products`; the server capped the read. */
|
|
798
|
+
truncated: boolean;
|
|
799
|
+
/** Why the last read failed, as the SDK's own code — `rate_limited` is the one worth wording
|
|
800
|
+
* differently, since it is the only failure that fixes itself. */
|
|
801
|
+
error: string | null;
|
|
802
|
+
reload: () => void;
|
|
803
|
+
};
|
|
804
|
+
/**
|
|
805
|
+
* The public shelf, loaded on mount.
|
|
806
|
+
*
|
|
807
|
+
* Hold `shop` still: build it once at module scope, the way a portal builds its client (`export
|
|
808
|
+
* const holaShop = createPortalShop(config)`), and hand the same object in on every render. A
|
|
809
|
+
* `createPortalShop({...})` written inside the component body is a new object each time, and since
|
|
810
|
+
* that identity is what this re-reads on, the storefront would fetch its own shelf in a loop —
|
|
811
|
+
* against a route that is rate-limited per visitor, so the shop would end up empty for the person
|
|
812
|
+
* least at fault.
|
|
813
|
+
*/
|
|
814
|
+
declare const useShop: (shop: PortalShop) => UseShop;
|
|
815
|
+
|
|
638
816
|
/** A thread message; `pending` marks an optimistic echo of the visitor's own send, shown
|
|
639
817
|
* instantly and replaced by the authoritative message when the receive channel delivers it. */
|
|
640
818
|
type ThreadMessage = HolaMessage & {
|
|
@@ -658,4 +836,4 @@ declare const useThread: (client: HolaClient, options?: {
|
|
|
658
836
|
pollMs?: number;
|
|
659
837
|
}) => UseThread;
|
|
660
838
|
|
|
661
|
-
export { type Agg, type ApiTransportConfig, type Band, type ChartView, Chat, type ChatMessage, type CreateHolaClientOptions, type DashboardLayout, type DashboardSpec, type DeliverableColType, type DeliverableColumn, type DeliverableItem, type DeliverableItemKind, type DeliverableReviewState, type DeliverableRow, type DeliverableTable, type DeliverableVersion, type DonutWidget, GRID_COLS, 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 PlacedWidget, type Point, PortalConflict, type PortalData, type PortalDocument, type PortalDocumentSummary, type PortalField, type PortalFile, type PortalRow, type PortalRowAuthor, type PortalRowPage, type PortalTable, type ResolvedWidget, type SeriesWidget, type StatView, type StatWidget, type TableResponses, type TableReviewVerdict, type TableWidget, type TextWidget, type ThreadMessage, type UseChat, type UseThread, type Widget, type WidgetTransportConfig, type WidgetType, bandOfKind, bandOfType, cellValue, createApiTransport, createHolaClient, createPortalData, createWidgetTransport, deliverableCellText, deliverableStatus, deriveFields, emptyTableResponses, footprintOf, footprintWith, formatDeliverableDate, groupDeliverableVersions, inferSpec, isDeliverableChecked, mergeMessage, normalizeDeliverableColType, normalizeDeliverableItem, parseDashboardSpec, parseDeliverableItems, parseDeliverableTable, parseTableResponses, placeWidgets, publishedVersionOf, renderModel, setResponse, setTableReview, splitLayout, textDeltaOf, thinkingDeltaOf, toolEventOf, useArtifactUrl, useChat, useHolaClient, useThread };
|
|
839
|
+
export { type Agg, type ApiTransportConfig, type Band, type ChartView, Chat, type ChatMessage, type CreateHolaClientOptions, type DashboardLayout, type DashboardSpec, type DataSource, type DeliverableColType, type DeliverableColumn, type DeliverableItem, type DeliverableItemKind, type DeliverableReviewState, type DeliverableRow, type DeliverableTable, type DeliverableVersion, type DonutWidget, GRID_COLS, 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 PlacedWidget, type Point, PortalConflict, type PortalData, type PortalDocument, type PortalDocumentSummary, type PortalField, type PortalFile, type PortalRow, type PortalRowAuthor, type PortalRowPage, type PortalShop, type PortalShopConfig, type PortalTable, type ResolvedWidget, type SeriesWidget, type ShopApplication, type ShopApplyResult, type ShopInclusion, type ShopMode, type ShopPricing, type ShopProduct, type ShopShelf, type ShopVariant, type StatView, type StatWidget, type TableResponses, type TableReviewVerdict, type TableWidget, type TextWidget, type ThreadMessage, type UseChat, type UseShop, type UseThread, type Widget, type WidgetTransportConfig, type WidgetType, bandOfKind, bandOfType, cellValue, createApiTransport, createHolaClient, createPortalData, createPortalShop, createWidgetTransport, deliverableCellText, deliverableStatus, deriveFields, emptyTableResponses, footprintOf, footprintWith, formatDeliverableDate, groupDeliverableVersions, inferSpec, isDeliverableChecked, mergeMessage, normalizeDeliverableColType, normalizeDeliverableItem, parseDashboardSpec, parseDeliverableItems, parseDeliverableTable, parseTableResponses, placeWidgets, publishedVersionOf, renderModel, setResponse, setTableReview, splitLayout, textDeltaOf, thinkingDeltaOf, toolEventOf, useArtifactUrl, useChat, useHolaClient, useShop, useThread };
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use client'
|
|
2
|
-
var Y=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="message_update"?t.assistantMessageEvent??null:null}
|
|
3
|
-
`))
|
|
4
|
-
`)}:null}
|
|
2
|
+
var Y=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="message_update"?t.assistantMessageEvent??null:null},_=e=>{let t=Y(e);return t?.type==="text_delta"&&typeof t.delta=="string"?t.delta:null},O=e=>{let t=Y(e);return t?.type==="thinking_delta"&&typeof t.delta=="string"?t.delta:null},U=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 Ee=/^ /,w=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"}},$e=e=>{let t="message",o=[];for(let r of e.split(`
|
|
3
|
+
`))r.startsWith(":")||(r.startsWith("event:")?t=r.slice(6).trim():r.startsWith("data:")&&o.push(r.slice(5).replace(Ee,"")));return o.length>0?{event:t,data:o.join(`
|
|
4
|
+
`)}:null},_e=(e,t,o)=>{let r;try{r=JSON.parse(e.data)}catch{return}if(e.event==="session"){let l=r.sessionId;l&&(o(l),t.onSession?.(l));return}if(e.event==="turn_event"){t.onEvent?.(r);let l=_(r);l&&t.onText?.(l);let i=O(r);i&&t.onThinking?.(i);let n=U(r);n&&t.onTool?.(n);return}if(e.event==="chat_completed"){let l=r;o(l.sessionId),t.onComplete?.(l);return}e.event==="chat_error"&&t.onError?.(w(r))},v=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()},Z=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()},ee=async(e,t,o,r)=>{let l=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body,signal:r});if(!(l.ok&&l.body)){t.onError?.({error:`stream_failed_${l.status}`});return}let i=l.body.getReader(),n=new TextDecoder,s="",a=()=>{let d=s.indexOf(`
|
|
5
5
|
|
|
6
|
-
`);for(;d!==-1;){let c=s.slice(0,d);s=s.slice(d+2);let
|
|
6
|
+
`);for(;d!==-1;){let c=s.slice(0,d);s=s.slice(d+2);let g=$e(c);g&&_e(g,t,o),d=s.indexOf(`
|
|
7
7
|
|
|
8
|
-
`)}},u=async()=>{let d=await a.read();if(!d.done)return s+=n.decode(d.value,{stream:!0}),i(),u()};await u()};var Oe=/\/+$/,F="/api/v1/end-user",_e=e=>{let t=e.baseUrl.replace(Oe,""),r=()=>typeof e.token=="function"?e.token():e.token,o=n=>e.project?`${n}project=${encodeURIComponent(e.project)}`:"",l=async()=>({"content-type":"application/json",authorization:`Bearer ${await r()}`}),a=async n=>{let s=await fetch(`${t}${F}/chat${o("?")}`,{method:"POST",headers:await l(),body:JSON.stringify({message:n})});if(!s.ok)throw new Error(`hola: message failed (${s.status})`);return{reply:(await s.json()).reply??"",sessionId:"",artifacts:[]}};return{sessionId:()=>"",getInfo:async()=>x(`${t}${F}/chat/info${o("?")}`,await l()),sendMessage:a,streamMessage:async(n,s)=>{try{let i=await a(n);s.onText?.(i.reply),s.onComplete?.(i)}catch(i){s.onError?.(T(i))}},subscribe:(n,s)=>{let i=s?.since??"0",u=!1,d,c=s?.intervalMs??3e3,m=typeof document<"u",p=()=>m&&document.visibilityState==="hidden",b=!1,w=()=>{if(!u){if(p()){b=!0;return}d=setTimeout(f,c)}},f=async()=>{try{let h=await x(`${t}${F}/chat/thread?since=${encodeURIComponent(i)}${o("&")}`,await l());for(let D of h.messages)n.onMessage(D);i=h.cursor,n.onHealthy?.()}catch(h){n.onError?.(T(h))}w()},R=()=>{u||!b||p()||(b=!1,d&&clearTimeout(d),d=setTimeout(f,0))};m&&document.addEventListener("visibilitychange",R);let g=()=>{u=!0,d&&clearTimeout(d),m&&document.removeEventListener("visibilitychange",R)};return s?.signal?.addEventListener("abort",g),d=setTimeout(f,0),g}}};import{useEffect as Fe,useState as Le}from"react";var L=(e,t)=>{let[r,o]=Le("");return Fe(()=>{if(!e){o("");return}let l=Uint8Array.from(atob(e),n=>n.charCodeAt(0)),a=URL.createObjectURL(new Blob([l],{type:t}));return o(a),()=>URL.revokeObjectURL(a)},[e,t]),r};import{useEffect as Be,useRef as Ge}from"react";import{createContext as Ue,useContext as Ne}from"react";import{jsx as je}from"react/jsx-runtime";var ee=Ue(null),Ve=({client:e,children:t})=>je(ee.Provider,{value:e,children:t}),U=()=>{let e=Ne(ee);if(!e)throw new Error("useHolaClient must be used within <HolaProvider>");return e};import{useCallback as te,useEffect as ne,useRef as re,useState as A}from"react";var N=e=>{let[t,r]=A([]),[o,l]=A(""),[a,n]=A(!1),[s,i]=A(null),u=re(0),d=re(null);ne(()=>()=>d.current?.abort(),[]);let c=te(()=>{let p=u.current;return u.current+=1,p},[]);ne(()=>{let p=!0;return e.getInfo().then(b=>{p&&b.greeting&&r([{id:c(),role:"assistant",text:b.greeting}])}).catch(()=>{}),()=>{p=!1}},[e,c]);let m=te(()=>{let p=o.trim();if(!p||a)return;l(""),i(null),n(!0);let b=c(),w=c();r(g=>[...g,{id:b,role:"user",text:p},{id:w,role:"assistant",text:"",streaming:!0}]);let f=g=>{r(h=>h.map(D=>D.id===w?g(D):D))},R=new AbortController;d.current=R,e.streamMessage(p,{onText:g=>f(h=>({...h,text:h.text+g})),onComplete:g=>{f(h=>({...h,text:g.reply||h.text,artifacts:g.artifacts,streaming:!1})),n(!1)},onError:g=>{f(h=>({...h,streaming:!1})),i(g.error),n(!1)}},R.signal).catch(g=>{f(h=>({...h,streaming:!1})),i(g instanceof Error?g.message:"stream_failed"),n(!1)}).finally(()=>{n(!1),f(g=>g.streaming?{...g,streaming:!1}:g)})},[o,a,e,c]);return{messages:t,input:o,setInput:l,send:m,sending:a,error:s}};import{jsx as C,jsxs as V}from"react/jsx-runtime";var v={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"}},ze=({artifact:e})=>{let t=L(e.dataBase64??"",e.mimeType),r=e.url??t;return r?e.mimeType.startsWith("image/")?C("a",{href:r,rel:"noopener noreferrer",target:"_blank",children:C("img",{alt:e.filename,src:r,style:v.image})}):C("a",{download:e.filename,href:r,style:v.link,children:e.filename}):null},Je=()=>{let e=U(),{messages:t,input:r,setInput:o,send:l,sending:a,error:n}=N(e),s=Ge(null);Be(()=>{let u=s.current;u&&(u.scrollTop=u.scrollHeight)},[t]);let i=u=>{u.preventDefault(),l()};return V("div",{style:v.root,children:[C("div",{ref:s,style:v.log,children:t.map(u=>V("div",{style:u.role==="user"?v.user:v.assistant,children:[u.text||(u.streaming?"\u2026":""),u.artifacts&&u.artifacts.length>0?C("div",{style:v.artifacts,children:u.artifacts.map(d=>C(ze,{artifact:d},d.filename))}):null]},u.id))}),n?C("div",{style:v.error,children:n}):null,V("form",{onSubmit:i,style:v.form,children:[C("input",{"aria-label":"Message",onChange:u=>o(u.target.value),placeholder:"Type a message\u2026",style:v.input,value:r}),C("button",{disabled:a||r.trim().length===0,style:v.button,type:"submit",children:"Send"})]})]})};var Xe=/\/+$/,j=e=>{let t=e.sessionId,r=e.baseUrl.replace(Xe,""),o=n=>`${r}/endpoint/${encodeURIComponent(e.token)}${n}`,l={"content-type":"application/json"},a=(n,s)=>({url:o(n),headers:l,body:JSON.stringify({message:s,...t?{sessionId:t}:{},...e.identity?{externalUserId:e.identity.externalUserId,userHmac:e.identity.userHmac}:{}})});return{sessionId:()=>t,getInfo:()=>x(o("/config"),{}),sendMessage:async n=>{let s=await Q(a("/message",n));return t=s.sessionId,s},streamMessage:(n,s,i)=>Z(a("/message/stream",n),s,u=>{t=u},i),subscribe:(n,s)=>{let i=s?.since??"0",u=!1,d,c=s?.intervalMs??3e3,m=async()=>{let b=t;if(b)try{let w=await x(o(`/messages?session=${encodeURIComponent(b)}&since=${encodeURIComponent(i)}`),{});for(let f of w.messages)n.onMessage(f);i=w.cursor,n.onHealthy?.()}catch(w){n.onError?.(T(w))}u||(d=setTimeout(m,c))},p=()=>{u=!0,d&&clearTimeout(d)};return s?.signal?.addEventListener("abort",p),d=setTimeout(m,0),p}}};var Ke=e=>"transport"in e?e.transport:j(e);var qe=/^https?:\/\//i,Ye=/^\d{4}-\d{2}-\d{2}(?:[T ]|$)/,Qe=e=>e.replace(/_/g," ").replace(/\b\w/g,t=>t.toUpperCase());function Ze(e){if(typeof e=="number")return"number";if(typeof e=="boolean")return"boolean";if(typeof e=="string"){if(qe.test(e))return"url";if(Ye.test(e))return"date"}return"text"}function oe(e){let t=[],r=new Map;for(let o of e)for(let[l,a]of Object.entries(o.data??{})){if(a==null)continue;let n=r.get(l);n||(n=new Map,r.set(l,n),t.push(l));let s=Ze(a);n.set(s,(n.get(s)??0)+1)}return t.map(o=>{let l=r.get(o)??new Map,a="text",n=-1;for(let[s,i]of l)i>n&&(n=i,a=s);return{key:o,label:Qe(o),type:a}})}var et=e=>typeof e=="number"?e:Number(e)||0,se=e=>/rate|position|rank|score|percent|avg/i.test(e),tt=/posted|published|sent|completed|shipped|launched|_at/i,nt=new Set(["service","order","end_user_id"]);function ie(e,t){let r=e.filter(i=>!nt.has(i.key)),o=r.filter(i=>i.type==="number").slice(0,3),l=r.find(i=>i.key==="status")??r.find(i=>i.type==="select"),a=r.find(i=>i.type==="date"&&tt.test(i.key))??r.find(i=>i.type==="date"),n=r.filter(i=>i.type==="number"&&!se(i.key)).map(i=>({field:i,total:t.reduce((u,d)=>u+et(d.data[i.key]),0)})).sort((i,u)=>u.total-i.total).find(i=>i.total>0)?.field??null,s=[{type:"stat",label:"Items",agg:"count"}];for(let i of o){let u=se(i.key);s.push({type:"stat",metric:i.key,agg:u?"avg":"sum",label:u?`Avg ${i.label.toLowerCase()}`:i.label})}return a&&s.push({type:"line",x:a.key,y:n?.key,agg:"sum",title:n?`${n.label} by day`:"Items by day"}),l&&s.push({type:"donut",groupBy:l.key,title:l.label}),s.push({type:"table",columns:r.map(i=>i.key)}),{version:1,widgets:s}}var ae=6,le=6,ue=4,de={stat:{w:1,h:1},chart:{w:2,h:2},block:{w:6,h:2}},rt=e=>Math.max(1,Math.min(6,Math.round(e))),ot=e=>Math.max(1,Math.min(4,Math.round(e)));function M(e){return e==="stat"?"stat":e==="series"||e==="donut"?"chart":"block"}function ce(e){return e==="stat"?"stat":e==="line"||e==="bar"||e==="donut"?"chart":"block"}function pe(e){return de[e]}function B(e,t,r){let o=de[e];return{w:t===void 0?o.w:rt(t),h:r===void 0?o.h:ot(r)}}function G(e){let t=[],r=[],o=(n,s,i,u)=>{if(n<0||n+i>6)return!1;for(let d=0;d<u;d+=1){let c=r[s+d];if(c){for(let m=0;m<i;m+=1)if(c[n+m])return!1}}return!0},l=(n,s,i,u)=>{for(let d=0;d<u;d+=1){let c=r[s+d]??[];for(let m=0;m<i;m+=1)c[n+m]=!0;r[s+d]=c}},a=(n,s)=>{for(let i=0;;i+=1)for(let u=0;u+n<=6;u+=1)if(o(u,i,n,s))return{gx:u,gy:i}};for(let n of e){let s=B(M(n.kind),n.w,n.h),u=n.gx!==void 0&&n.gy!==void 0&&o(n.gx,n.gy,s.w,s.h)&&n.gx!==void 0&&n.gy!==void 0?{gx:n.gx,gy:n.gy}:a(s.w,s.h);l(u.gx,u.gy,s.w,s.h),t.push({widget:n,gx:u.gx,gy:u.gy,w:s.w,h:s.h})}return t}function ge(e){let t=[],r=[];for(let o of e)M(o.kind)==="block"?r.push(o):t.push(o);return{tiles:G(t),blocks:r}}var me=new Set(["service","order","end_user_id"]),z=e=>typeof e=="number"?e:Number(e)||0,fe=e=>e==null?"":String(e);function J(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((o,l)=>o+l,0);return e==="avg"?Math.round(r/t.length*100)/100:r}function st(e,t,r,o){let l=new Map;for(let a of e){let n=new Date(fe(a.data[t]));if(Number.isNaN(n.getTime()))continue;let s=n.toISOString().slice(0,10),i=l.get(s)??[];i.push(r?z(a.data[r]):1),l.set(s,i)}return[...l.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:r?J(o,n):n.length}))}function it(e,t,r,o="sum"){let l=new Map;for(let a of e){let n=fe(a.data[t]).trim();if(!n)continue;let s=l.get(n)??[];s.push(r?z(a.data[r]):1),l.set(n,s)}return[...l.entries()].map(([a,n])=>({label:a,value:r?J(o,n):n.length})).sort((a,n)=>n.value-a.value)}function at(e,t,r,o){switch(e.type){case"stat":{let l=e.metric?t.get(e.metric):void 0;if(e.metric&&!l)return null;if(!l)return{kind:"stat",label:e.label??"Items",value:o.length};let a=o.map(n=>z(n.data[l.key]));return{kind:"stat",label:e.label??l.label,value:J(e.agg??"sum",a)}}case"line":case"bar":{if(!t.has(e.x)||e.y&&!t.has(e.y))return null;let l=st(o,e.x,e.y,e.agg??"sum");return l.length<2?null:{kind:"series",draw:e.type,title:e.title??"By day",points:l}}case"donut":{if(!t.has(e.groupBy))return null;let l=it(o,e.groupBy,e.metric,e.agg??"sum");return l.length===0?null:{kind:"donut",title:e.title??t.get(e.groupBy)?.label??"Breakdown",points:l}}case"table":{let l=e.columns?e.columns.map(a=>t.get(a)).filter(a=>a!==void 0&&!me.has(a.key)):r;return l.length===0?null:{kind:"table",title:e.title,columns:l,rows:o}}case"text":return{kind:"text",title:e.title,body:e.body};default:return null}}function be(e,t,r,o={}){let l=new Map,a=i=>({byKey:new Map(i.fields.map(u=>[u.key,u])),cols:i.fields.filter(u=>!me.has(u.key)),rows:i.rows}),n=a({fields:t,rows:r});for(let[i,u]of Object.entries(o))l.set(i,a(u));let s=[];for(let i of e.widgets){let u=i.type==="text"?void 0:i.source,d=u?l.get(u):n;if(!d)continue;let c=at(i,d.byKey,d.cols,d.rows);c&&s.push({...c,w:i.w,h:i.h,gx:i.gx,gy:i.gy})}return s}var lt=new Set(["sum","avg","count","min","max","last"]),ye=e=>typeof e=="string"&<.has(e)?e:void 0,y=e=>typeof e=="string"&&e!==""?e:void 0,P=e=>typeof e=="number"&&e>=1?Math.min(6,Math.round(e)):void 0,I=e=>typeof e=="number"&&e>=1?Math.min(4,Math.round(e)):void 0,k=e=>typeof e=="number"&&e>=0?Math.round(e):void 0;function ut(e){if(typeof e!="object"||e===null)return null;let t=e;switch(t.type){case"stat":return{type:"stat",source:y(t.source),label:y(t.label),metric:y(t.metric)??y(t.column),agg:ye(t.agg),w:P(t.w),h:I(t.h),gx:k(t.gx),gy:k(t.gy)};case"line":case"bar":{let r=y(t.x);return r?{type:t.type,source:y(t.source),title:y(t.title),x:r,y:y(t.y)??y(t.column),agg:ye(t.agg),w:P(t.w),h:I(t.h),gx:k(t.gx),gy:k(t.gy)}:null}case"donut":{let r=y(t.groupBy)??y(t.column);return r?{type:"donut",source:y(t.source),title:y(t.title),groupBy:r,w:P(t.w),h:I(t.h),gx:k(t.gx),gy:k(t.gy)}:null}case"table":{let r=Array.isArray(t.columns)?t.columns.filter(o=>typeof o=="string"):void 0;return{type:"table",source:y(t.source),title:y(t.title),columns:r,w:P(t.w),h:I(t.h),gx:k(t.gx),gy:k(t.gy)}}case"text":{let r=y(t.body);return r?{type:"text",title:y(t.title),body:r,w:P(t.w),h:I(t.h),gx:k(t.gx),gy:k(t.gy)}:null}default:return null}}function he(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 o=r.map(ut).filter(a=>a!==null);if(o.length===0)return null;let l=t.version;return{version:typeof l=="number"?l:1,title:y(t.title),widgets:o}}function X(e){if(typeof e=="string")return e?{kind:"file",value:e}:null;if(e&&typeof e=="object"){let t=e,r=typeof t.value=="string"?t.value:"",o=t.kind==="link"||t.kind==="text"||t.kind==="table"?t.kind:"file",l=typeof t.v=="number"&&t.v>=1?Math.floor(t.v):void 0;return r?{kind:o,value:r,...l?{v:l}:{}}:null}return null}function K(e){let t=new Map;for(let r of e){let o=r.v??1,l=t.get(o)??[];l.push(r),t.set(o,l)}return[...t.entries()].sort(([r],[o])=>r-o).map(([r,o])=>({v:r,items:o}))}function we(e){let t=e.files;if(typeof t=="string"&&t.trim()!=="")try{let o=JSON.parse(t);if(Array.isArray(o))return o.map(X).filter(l=>l!==null)}catch{}let r=String(e.file??"");return r?[{kind:"file",value:r}]:[]}function xe(e,t,r,o=""){let a=K(e).find(s=>s.v===t)?.items??[],n=a.filter(s=>s.kind==="file").map(s=>r.get(s.value)??"");return a.some(s=>s.kind==="table")&&n.push(o),n.length===0||n.some(s=>s==="")?"awaiting":n.some(s=>s==="revise")?"revise":"accepted"}function ve(e){return Number(e.published_version)||0}function q(e){return e==="number"||e==="date"||e==="boolean"||e==="select"||e==="url"?e:e==="link"?"url":e==="checkbox"?"boolean":"text"}function Re(e){try{let t=JSON.parse(e);if(Array.isArray(t.columns)&&Array.isArray(t.rows)&&t.columns.length){let r=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:q(a.type),...a.clientEditable===!0?{clientEditable:!0}:{}})),o=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:{}})),l=typeof t.name=="string"?t.name:void 0;return{columns:r,rows:o,...l?{name:l}:{}}}}catch{}return null}function Te(e){return e==null?"":String(e)}function ke(e){return e===!0||e==="true"||e==="1"||e==="yes"||e==="\u2713"}function W(){return{cells:{},verdict:"",comment:""}}function De(e){if(typeof e!="string"||e.trim()==="")return W();try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t)){let r=t;return{cells:r.cells&&typeof r.cells=="object"?r.cells:r,verdict:r.verdict==="accepted"||r.verdict==="revise"?r.verdict:"",comment:typeof r.comment=="string"?r.comment:""}}}catch{}return W()}function Ce(e,t,r){if(e.clientEditable){let o=r.cells[t.id];if(o&&e.key in o)return o[e.key]}return t.cells[e.key]}function Se(e,t,r,o){return{...e,cells:{...e.cells,[t]:{...e.cells[t]??{},[r]:o}}}}function Pe(e,t,r){return{...e,verdict:t,comment:r}}function Ie(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 dt=/\/+$/,S="/api/v1/end-user",H=class extends Error{constructor(t){super(t),this.name="PortalConflict"}};function ct(e){let t="";for(let o=0;o<e.length;o+=32768)t+=String.fromCharCode(...e.subarray(o,o+32768));return btoa(t)}var pt=e=>{let t=e.baseUrl.replace(dt,""),r=()=>typeof e.token=="function"?e.token():e.token,o=async()=>({"content-type":"application/json",authorization:`Bearer ${await r()}`}),l=async(n,s)=>{try{let i=await fetch(`${t}${S}${n}`,{method:s.method,headers:await o(),...s.body===void 0?{}:{body:JSON.stringify(s.body)}});if(i.status===409){let u=await i.json().catch(()=>({}));throw new H(u.message??"Someone else saved this first.")}if(!i.ok){let u=await i.text().catch(()=>""),d=`${s.method} ${n} \u2192 ${String(i.status)}`;try{let c=JSON.parse(u);c.message&&(d=c.message)}catch{d=u?`${d}: ${u}`:d}throw T({error:d})}return await i.json()}catch(i){throw i instanceof H?i:T(i)}},a=n=>`/tables/${encodeURIComponent(n)}`;return{listTables:async()=>(await x(`${t}${S}/tables`,await o())).tables,listRows:async(n,s)=>await x(`${t}${S}${a(n)}/rows?limit=${String(s??100)}`,await o()),insertRow:async(n,s)=>{let{rowIds:i}=await l(`${a(n)}/rows`,{method:"POST",body:{rows:[s]}}),u=i[0];if(!u)throw T(new Error("The row was not created."));return u},patchRow:async(n,s,i)=>(await l(`${a(n)}/rows/${encodeURIComponent(s)}`,{method:"PATCH",body:i})).updated,deleteRow:async(n,s)=>(await l(`/${encodeURIComponent(n)}/${encodeURIComponent(s)}`,{method:"DELETE"})).deleted,listFiles:async()=>(await x(`${t}${S}/tables/files/rows?limit=200`,await o())).rows.map(s=>({id:s.rowId,filename:String(s.data.filename??""),source:String(s.data.source??"client"),campaign:String(s.data.campaign??""),size:typeof s.data.size=="number"?s.data.size:0,createdAt:s.createdAt})),uploadFile:async(n,s)=>{let i=new Uint8Array(await n.arrayBuffer());return await l("/files",{method:"POST",body:{filename:n.name,mime:n.type||"application/octet-stream",data:ct(i),...s===void 0?{}:{message:s}}})},fileLink:async n=>await x(`${t}${S}/files/${encodeURIComponent(n)}/url`,await o()),deleteFile:async n=>(await l(`/files/${encodeURIComponent(n)}`,{method:"DELETE"})).deleted,listDocuments:async()=>(await x(`${t}${S}/documents`,await o())).documents,readDocument:async n=>(await x(`${t}${S}/documents/${encodeURIComponent(n)}`,await o())).document,saveDocument:async(n,s)=>await l(`/documents/${encodeURIComponent(n)}`,{method:"PATCH",body:s})}};import{useCallback as gt,useEffect as He,useRef as mt,useState as E}from"react";var Ae="greeting";function Me(e,t){if(e.some(a=>a.id===t.id))return e;let r=e.filter(a=>a.id!==Ae),o=a=>a.author==="client"==(t.author==="client");return[...r.filter(a=>!(a.pending&&o(a)&&a.text===t.text)),t]}var ft=(e,t)=>{let[r,o]=E([]),[l,a]=E(""),[n,s]=E(!1),[i,u]=E(null),d=mt(0),c=t?.pollMs??2e3;He(()=>{let p=!0;return e.getInfo().then(b=>{p&&b.greeting&&o(w=>w.length===0?[{id:Ae,cursor:"",author:"agent",text:b.greeting}]:w)}).catch(()=>{}),()=>{p=!1}},[e]),He(()=>e.subscribe?.({onMessage:p=>o(b=>Me(b,p)),onError:p=>u(p.error),onHealthy:()=>u(null)},{intervalMs:c}),[e,c]);let m=gt(()=>{let p=l.trim();if(!p||n)return;a(""),u(null),s(!0),d.current+=1;let b=`pending-${d.current}`,w={id:b,cursor:"",author:"client",text:p,pending:!0};o(f=>[...f,w]),e.sendMessage(p).then(f=>{s(!1),f.reply.trim()&&o(g=>g.some(D=>!D.pending&&D.author!=="client"&&D.text===f.reply)?g:(d.current+=1,[...g,{id:`pending-agent-${d.current}`,cursor:"",author:"agent",text:f.reply,pending:!0}]))}).catch(f=>{u(f instanceof Error?f.message:"send_failed"),s(!1),o(R=>R.filter(g=>g.id!==b)),a(R=>R||p)})},[l,n,e]);return{messages:r,input:l,setInput:a,send:m,sending:n,error:i}};export{Je as Chat,ae as GRID_COLS,le as GRID_MAX_COLS,ue as GRID_MAX_ROWS,Ve as HolaProvider,H as PortalConflict,M as bandOfKind,ce as bandOfType,Ce as cellValue,_e as createApiTransport,Ke as createHolaClient,pt as createPortalData,j as createWidgetTransport,Te as deliverableCellText,xe as deliverableStatus,oe as deriveFields,W as emptyTableResponses,pe as footprintOf,B as footprintWith,Ie as formatDeliverableDate,K as groupDeliverableVersions,ie as inferSpec,ke as isDeliverableChecked,Me as mergeMessage,q as normalizeDeliverableColType,X as normalizeDeliverableItem,he as parseDashboardSpec,we as parseDeliverableItems,Re as parseDeliverableTable,De as parseTableResponses,G as placeWidgets,ve as publishedVersionOf,be as renderModel,Se as setResponse,Pe as setTableReview,ge as splitLayout,$ as textDeltaOf,O as thinkingDeltaOf,_ as toolEventOf,L as useArtifactUrl,N as useChat,U as useHolaClient,ft as useThread};
|
|
8
|
+
`)}},u=async()=>{let d=await i.read();if(!d.done)return s+=n.decode(d.value,{stream:!0}),a(),u()};await u()};var Oe=/\/+$/,L="/api/v1/end-user",Ue=e=>{let t=e.baseUrl.replace(Oe,""),o=()=>typeof e.token=="function"?e.token():e.token,r=n=>e.project?`${n}project=${encodeURIComponent(e.project)}`:"",l=async()=>({"content-type":"application/json",authorization:`Bearer ${await o()}`}),i=async n=>{let s=await fetch(`${t}${L}/chat${r("?")}`,{method:"POST",headers:await l(),body:JSON.stringify({message:n})});if(!s.ok)throw new Error(`hola: message failed (${s.status})`);return{reply:(await s.json()).reply??"",sessionId:"",artifacts:[]}};return{sessionId:()=>"",getInfo:async()=>v(`${t}${L}/chat/info${r("?")}`,await l()),sendMessage:i,streamMessage:async(n,s)=>{try{let a=await i(n);s.onText?.(a.reply),s.onComplete?.(a)}catch(a){s.onError?.(w(a))}},subscribe:(n,s)=>{let a=s?.since??"0",u=!1,d,c=s?.intervalMs??3e3,g=typeof document<"u",p=()=>g&&document.visibilityState==="hidden",y=!1,x=()=>{if(!u){if(p()){y=!0;return}d=setTimeout(f,c)}},f=async()=>{try{let h=await v(`${t}${L}/chat/thread?since=${encodeURIComponent(a)}${r("&")}`,await l());for(let k of h.messages)n.onMessage(k);a=h.cursor,n.onHealthy?.()}catch(h){n.onError?.(w(h))}x()},R=()=>{u||!y||p()||(y=!1,d&&clearTimeout(d),d=setTimeout(f,0))};g&&document.addEventListener("visibilitychange",R);let m=()=>{u=!0,d&&clearTimeout(d),g&&document.removeEventListener("visibilitychange",R)};return s?.signal?.addEventListener("abort",m),d=setTimeout(f,0),m}}};import{useEffect as Le,useState as Fe}from"react";var F=(e,t)=>{let[o,r]=Fe("");return Le(()=>{if(!e){r("");return}let l=Uint8Array.from(atob(e),n=>n.charCodeAt(0)),i=URL.createObjectURL(new Blob([l],{type:t}));return r(i),()=>URL.revokeObjectURL(i)},[e,t]),o};import{useEffect as Be,useRef as ze}from"react";import{createContext as Ne,useContext as Ve}from"react";import{jsx as Ge}from"react/jsx-runtime";var te=Ne(null),je=({client:e,children:t})=>Ge(te.Provider,{value:e,children:t}),N=()=>{let e=Ve(te);if(!e)throw new Error("useHolaClient must be used within <HolaProvider>");return e};import{useCallback as ne,useEffect as re,useRef as oe,useState as M}from"react";var V=e=>{let[t,o]=M([]),[r,l]=M(""),[i,n]=M(!1),[s,a]=M(null),u=oe(0),d=oe(null);re(()=>()=>d.current?.abort(),[]);let c=ne(()=>{let p=u.current;return u.current+=1,p},[]);re(()=>{let p=!0;return e.getInfo().then(y=>{p&&y.greeting&&o([{id:c(),role:"assistant",text:y.greeting}])}).catch(()=>{}),()=>{p=!1}},[e,c]);let g=ne(()=>{let p=r.trim();if(!p||i)return;l(""),a(null),n(!0);let y=c(),x=c();o(m=>[...m,{id:y,role:"user",text:p},{id:x,role:"assistant",text:"",streaming:!0}]);let f=m=>{o(h=>h.map(k=>k.id===x?m(k):k))},R=new AbortController;d.current=R,e.streamMessage(p,{onText:m=>f(h=>({...h,text:h.text+m})),onComplete:m=>{f(h=>({...h,text:m.reply||h.text,artifacts:m.artifacts,streaming:!1})),n(!1)},onError:m=>{f(h=>({...h,streaming:!1})),a(m.error),n(!1)}},R.signal).catch(m=>{f(h=>({...h,streaming:!1})),a(m instanceof Error?m.message:"stream_failed"),n(!1)}).finally(()=>{n(!1),f(m=>m.streaming?{...m,streaming:!1}:m)})},[r,i,e,c]);return{messages:t,input:r,setInput:l,send:g,sending:i,error:s}};import{jsx as P,jsxs as j}from"react/jsx-runtime";var S={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"}},Je=({artifact:e})=>{let t=F(e.dataBase64??"",e.mimeType),o=e.url??t;return o?e.mimeType.startsWith("image/")?P("a",{href:o,rel:"noopener noreferrer",target:"_blank",children:P("img",{alt:e.filename,src:o,style:S.image})}):P("a",{download:e.filename,href:o,style:S.link,children:e.filename}):null},Ke=()=>{let e=N(),{messages:t,input:o,setInput:r,send:l,sending:i,error:n}=V(e),s=ze(null);Be(()=>{let u=s.current;u&&(u.scrollTop=u.scrollHeight)},[t]);let a=u=>{u.preventDefault(),l()};return j("div",{style:S.root,children:[P("div",{ref:s,style:S.log,children:t.map(u=>j("div",{style:u.role==="user"?S.user:S.assistant,children:[u.text||(u.streaming?"\u2026":""),u.artifacts&&u.artifacts.length>0?P("div",{style:S.artifacts,children:u.artifacts.map(d=>P(Je,{artifact:d},d.filename))}):null]},u.id))}),n?P("div",{style:S.error,children:n}):null,j("form",{onSubmit:a,style:S.form,children:[P("input",{"aria-label":"Message",onChange:u=>r(u.target.value),placeholder:"Type a message\u2026",style:S.input,value:o}),P("button",{disabled:i||o.trim().length===0,style:S.button,type:"submit",children:"Send"})]})]})};var Xe=/\/+$/,G=e=>{let t=e.sessionId,o=e.baseUrl.replace(Xe,""),r=n=>`${o}/endpoint/${encodeURIComponent(e.token)}${n}`,l={"content-type":"application/json"},i=(n,s)=>({url:r(n),headers:l,body:JSON.stringify({message:s,...t?{sessionId:t}:{},...e.identity?{externalUserId:e.identity.externalUserId,userHmac:e.identity.userHmac}:{}})});return{sessionId:()=>t,getInfo:()=>v(r("/config"),{}),sendMessage:async n=>{let s=await Z(i("/message",n));return t=s.sessionId,s},streamMessage:(n,s,a)=>ee(i("/message/stream",n),s,u=>{t=u},a),subscribe:(n,s)=>{let a=s?.since??"0",u=!1,d,c=s?.intervalMs??3e3,g=async()=>{let y=t;if(y)try{let x=await v(r(`/messages?session=${encodeURIComponent(y)}&since=${encodeURIComponent(a)}`),{});for(let f of x.messages)n.onMessage(f);a=x.cursor,n.onHealthy?.()}catch(x){n.onError?.(w(x))}u||(d=setTimeout(g,c))},p=()=>{u=!0,d&&clearTimeout(d)};return s?.signal?.addEventListener("abort",p),d=setTimeout(g,0),p}}};var qe=e=>"transport"in e?e.transport:G(e);var Qe=/^https?:\/\//i,Ye=/^\d{4}-\d{2}-\d{2}(?:[T ]|$)/,Ze=e=>e.replace(/_/g," ").replace(/\b\w/g,t=>t.toUpperCase());function et(e){if(typeof e=="number")return"number";if(typeof e=="boolean")return"boolean";if(typeof e=="string"){if(Qe.test(e))return"url";if(Ye.test(e))return"date"}return"text"}function se(e){let t=[],o=new Map;for(let r of e)for(let[l,i]of Object.entries(r.data??{})){if(i==null)continue;let n=o.get(l);n||(n=new Map,o.set(l,n),t.push(l));let s=et(i);n.set(s,(n.get(s)??0)+1)}return t.map(r=>{let l=o.get(r)??new Map,i="text",n=-1;for(let[s,a]of l)a>n&&(n=a,i=s);return{key:r,label:Ze(r),type:i}})}var tt=e=>typeof e=="number"?e:Number(e)||0,ie=e=>/rate|position|rank|score|percent|avg/i.test(e),nt=/posted|published|sent|completed|shipped|launched|_at/i,rt=new Set(["service","order","end_user_id"]);function ae(e,t){let o=e.filter(a=>!rt.has(a.key)),r=o.filter(a=>a.type==="number").slice(0,3),l=o.find(a=>a.key==="status")??o.find(a=>a.type==="select"),i=o.find(a=>a.type==="date"&&nt.test(a.key))??o.find(a=>a.type==="date"),n=o.filter(a=>a.type==="number"&&!ie(a.key)).map(a=>({field:a,total:t.reduce((u,d)=>u+tt(d.data[a.key]),0)})).sort((a,u)=>u.total-a.total).find(a=>a.total>0)?.field??null,s=[{type:"stat",label:"Items",agg:"count"}];for(let a of r){let u=ie(a.key);s.push({type:"stat",metric:a.key,agg:u?"avg":"sum",label:u?`Avg ${a.label.toLowerCase()}`:a.label})}return i&&s.push({type:"line",x:i.key,y:n?.key,agg:"sum",title:n?`${n.label} by day`:"Items by day"}),l&&s.push({type:"donut",groupBy:l.key,title:l.label}),s.push({type:"table",columns:o.map(a=>a.key)}),{version:1,widgets:s}}var le=6,ue=6,de=4,pe={stat:{w:1,h:1},chart:{w:2,h:2},block:{w:6,h:2}},ot=e=>Math.max(1,Math.min(6,Math.round(e))),st=e=>Math.max(1,Math.min(4,Math.round(e)));function W(e){return e==="stat"?"stat":e==="series"||e==="donut"?"chart":"block"}function ce(e){return e==="stat"?"stat":e==="line"||e==="bar"||e==="donut"?"chart":"block"}function ge(e){return pe[e]}function B(e,t,o){let r=pe[e];return{w:t===void 0?r.w:ot(t),h:o===void 0?r.h:st(o)}}function z(e){let t=[],o=[],r=(n,s,a,u)=>{if(n<0||n+a>6)return!1;for(let d=0;d<u;d+=1){let c=o[s+d];if(c){for(let g=0;g<a;g+=1)if(c[n+g])return!1}}return!0},l=(n,s,a,u)=>{for(let d=0;d<u;d+=1){let c=o[s+d]??[];for(let g=0;g<a;g+=1)c[n+g]=!0;o[s+d]=c}},i=(n,s)=>{for(let a=0;;a+=1)for(let u=0;u+n<=6;u+=1)if(r(u,a,n,s))return{gx:u,gy:a}};for(let n of e){let s=B(W(n.kind),n.w,n.h),u=n.gx!==void 0&&n.gy!==void 0&&r(n.gx,n.gy,s.w,s.h)&&n.gx!==void 0&&n.gy!==void 0?{gx:n.gx,gy:n.gy}:i(s.w,s.h);l(u.gx,u.gy,s.w,s.h),t.push({widget:n,gx:u.gx,gy:u.gy,w:s.w,h:s.h})}return t}function me(e){let t=[],o=[];for(let r of e)W(r.kind)==="block"?o.push(r):t.push(r);return{tiles:z(t),blocks:o}}var fe=new Set(["service","order","end_user_id"]),J=e=>typeof e=="number"?e:Number(e)||0,ye=e=>e==null?"":String(e);function K(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((r,l)=>r+l,0);return e==="avg"?Math.round(o/t.length*100)/100:o}function it(e,t,o,r){let l=new Map;for(let i of e){let n=new Date(ye(i.data[t]));if(Number.isNaN(n.getTime()))continue;let s=n.toISOString().slice(0,10),a=l.get(s)??[];a.push(o?J(i.data[o]):1),l.set(s,a)}return[...l.entries()].sort((i,n)=>i[0]<n[0]?-1:1).map(([i,n])=>({label:new Date(`${i}T00:00:00`).toLocaleDateString(void 0,{month:"short",day:"numeric"}),value:o?K(r,n):n.length}))}function at(e,t,o,r="sum"){let l=new Map;for(let i of e){let n=ye(i.data[t]).trim();if(!n)continue;let s=l.get(n)??[];s.push(o?J(i.data[o]):1),l.set(n,s)}return[...l.entries()].map(([i,n])=>({label:i,value:o?K(r,n):n.length})).sort((i,n)=>n.value-i.value)}function lt(e,t,o,r){switch(e.type){case"stat":{let l=e.metric?t.get(e.metric):void 0;if(e.metric&&!l)return null;if(!l)return{kind:"stat",label:e.label??"Items",value:r.length};let i=r.map(n=>J(n.data[l.key]));return{kind:"stat",label:e.label??l.label,value:K(e.agg??"sum",i)}}case"line":case"bar":{if(!t.has(e.x)||e.y&&!t.has(e.y))return null;let l=it(r,e.x,e.y,e.agg??"sum");return l.length<2?null:{kind:"series",draw:e.type,title:e.title??"By day",points:l}}case"donut":{if(!t.has(e.groupBy))return null;let l=at(r,e.groupBy,e.metric,e.agg??"sum");return l.length===0?null:{kind:"donut",title:e.title??t.get(e.groupBy)?.label??"Breakdown",points:l}}case"table":{let l=e.columns?e.columns.map(i=>t.get(i)).filter(i=>i!==void 0&&!fe.has(i.key)):o;return l.length===0?null:{kind:"table",title:e.title,columns:l,rows:r}}case"text":return{kind:"text",title:e.title,body:e.body};default:return null}}function be(e,t,o,r={}){let l=new Map,i=a=>({byKey:new Map(a.fields.map(u=>[u.key,u])),cols:a.fields.filter(u=>!fe.has(u.key)),rows:a.rows}),n=i({fields:t,rows:o});for(let[a,u]of Object.entries(r))l.set(a,i(u));let s=[];for(let a of e.widgets){let u=a.type==="text"?void 0:a.source,d=u?l.get(u):n;if(!d)continue;let c=lt(a,d.byKey,d.cols,d.rows);c&&s.push({...c,w:a.w,h:a.h,gx:a.gx,gy:a.gy})}return s}var ut=new Set(["sum","avg","count","min","max","last"]),he=e=>typeof e=="string"&&ut.has(e)?e:void 0,b=e=>typeof e=="string"&&e!==""?e:void 0,C=e=>typeof e=="number"&&e>=1?Math.min(6,Math.round(e)):void 0,I=e=>typeof e=="number"&&e>=1?Math.min(4,Math.round(e)):void 0,T=e=>typeof e=="number"&&e>=0?Math.round(e):void 0;function dt(e){if(typeof e!="object"||e===null)return null;let t=e;switch(t.type){case"stat":return{type:"stat",source:b(t.source),label:b(t.label),metric:b(t.metric)??b(t.column),agg:he(t.agg),w:C(t.w),h:I(t.h),gx:T(t.gx),gy:T(t.gy)};case"line":case"bar":{let o=b(t.x);return o?{type:t.type,source:b(t.source),title:b(t.title),x:o,y:b(t.y)??b(t.column),agg:he(t.agg),w:C(t.w),h:I(t.h),gx:T(t.gx),gy:T(t.gy)}:null}case"donut":{let o=b(t.groupBy)??b(t.column);return o?{type:"donut",source:b(t.source),title:b(t.title),groupBy:o,w:C(t.w),h:I(t.h),gx:T(t.gx),gy:T(t.gy)}:null}case"table":{let o=Array.isArray(t.columns)?t.columns.filter(r=>typeof r=="string"):void 0;return{type:"table",source:b(t.source),title:b(t.title),columns:o,w:C(t.w),h:I(t.h),gx:T(t.gx),gy:T(t.gy)}}case"text":{let o=b(t.body);return o?{type:"text",title:b(t.title),body:o,w:C(t.w),h:I(t.h),gx:T(t.gx),gy:T(t.gy)}:null}default:return null}}function we(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 r=o.map(dt).filter(i=>i!==null);if(r.length===0)return null;let l=t.version;return{version:typeof l=="number"?l:1,title:b(t.title),widgets:r}}function X(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:"",r=t.kind==="link"||t.kind==="text"||t.kind==="table"?t.kind:"file",l=typeof t.v=="number"&&t.v>=1?Math.floor(t.v):void 0;return o?{kind:r,value:o,...l?{v:l}:{}}:null}return null}function q(e){let t=new Map;for(let o of e){let r=o.v??1,l=t.get(r)??[];l.push(o),t.set(r,l)}return[...t.entries()].sort(([o],[r])=>o-r).map(([o,r])=>({v:o,items:r}))}function xe(e){let t=e.files;if(typeof t=="string"&&t.trim()!=="")try{let r=JSON.parse(t);if(Array.isArray(r))return r.map(X).filter(l=>l!==null)}catch{}let o=String(e.file??"");return o?[{kind:"file",value:o}]:[]}function ve(e,t,o,r=""){let i=q(e).find(s=>s.v===t)?.items??[],n=i.filter(s=>s.kind==="file").map(s=>o.get(s.value)??"");return i.some(s=>s.kind==="table")&&n.push(r),n.length===0||n.some(s=>s==="")?"awaiting":n.some(s=>s==="revise")?"revise":"accepted"}function Se(e){return Number(e.published_version)||0}function Q(e){return e==="number"||e==="date"||e==="boolean"||e==="select"||e==="url"?e:e==="link"?"url":e==="checkbox"?"boolean":"text"}function Re(e){try{let t=JSON.parse(e);if(Array.isArray(t.columns)&&Array.isArray(t.rows)&&t.columns.length){let o=t.columns.map((i,n)=>({key:typeof i.key=="string"&&i.key?i.key:typeof i.id=="string"&&i.id?i.id:`column_${n+1}`,label:typeof i.label=="string"?i.label:"",type:Q(i.type),...i.clientEditable===!0?{clientEditable:!0}:{}})),r=t.rows.map((i,n)=>({id:typeof i.id=="string"&&i.id?i.id:`row_${n}`,cells:i.cells&&typeof i.cells=="object"?i.cells:{}})),l=typeof t.name=="string"?t.name:void 0;return{columns:o,rows:r,...l?{name:l}:{}}}}catch{}return null}function Te(e){return e==null?"":String(e)}function ke(e){return e===!0||e==="true"||e==="1"||e==="yes"||e==="\u2713"}function E(){return{cells:{},verdict:"",comment:""}}function Pe(e){if(typeof e!="string"||e.trim()==="")return E();try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t)){let o=t;return{cells:o.cells&&typeof o.cells=="object"?o.cells:o,verdict:o.verdict==="accepted"||o.verdict==="revise"?o.verdict:"",comment:typeof o.comment=="string"?o.comment:""}}}catch{}return E()}function De(e,t,o){if(e.clientEditable){let r=o.cells[t.id];if(r&&e.key in r)return r[e.key]}return t.cells[e.key]}function Ce(e,t,o,r){return{...e,cells:{...e.cells,[t]:{...e.cells[t]??{},[o]:r}}}}function Ie(e,t,o){return{...e,verdict:t,comment:o}}function He(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 pt=/\/+$/,D="/api/v1/end-user",H=class extends Error{constructor(t){super(t),this.name="PortalConflict"}};function ct(e){let t="";for(let r=0;r<e.length;r+=32768)t+=String.fromCharCode(...e.subarray(r,r+32768));return btoa(t)}var gt=e=>{let t=e.baseUrl.replace(pt,""),o=()=>typeof e.token=="function"?e.token():e.token,r=async()=>({"content-type":"application/json",authorization:`Bearer ${await o()}`}),l=async(n,s)=>{try{let a=await fetch(`${t}${D}${n}`,{method:s.method,headers:await r(),...s.body===void 0?{}:{body:JSON.stringify(s.body)}});if(a.status===409){let u=await a.json().catch(()=>({}));throw new H(u.message??"Someone else saved this first.")}if(!a.ok){let u=await a.text().catch(()=>""),d=`${s.method} ${n} \u2192 ${String(a.status)}`;try{let c=JSON.parse(u);c.message&&(d=c.message)}catch{d=u?`${d}: ${u}`:d}throw w({error:d})}return await a.json()}catch(a){throw a instanceof H?a:w(a)}},i=n=>`/tables/${encodeURIComponent(n)}`;return{listTables:async()=>(await v(`${t}${D}/tables`,await r())).tables,listRows:async(n,s)=>await v(`${t}${D}${i(n)}/rows?limit=${String(s??100)}`,await r()),insertRow:async(n,s)=>{let{rowIds:a}=await l(`${i(n)}/rows`,{method:"POST",body:{rows:[s]}}),u=a[0];if(!u)throw w(new Error("The row was not created."));return u},patchRow:async(n,s,a)=>(await l(`${i(n)}/rows/${encodeURIComponent(s)}`,{method:"PATCH",body:a})).updated,deleteRow:async(n,s)=>(await l(`/${encodeURIComponent(n)}/${encodeURIComponent(s)}`,{method:"DELETE"})).deleted,listFiles:async()=>(await v(`${t}${D}/tables/files/rows?limit=200`,await r())).rows.map(s=>({id:s.rowId,filename:String(s.data.filename??""),source:String(s.data.source??"client"),campaign:String(s.data.campaign??""),size:typeof s.data.size=="number"?s.data.size:0,createdAt:s.createdAt})),uploadFile:async(n,s)=>{let a=new Uint8Array(await n.arrayBuffer());return await l("/files",{method:"POST",body:{filename:n.name,mime:n.type||"application/octet-stream",data:ct(a),...s===void 0?{}:{message:s}}})},fileLink:async n=>await v(`${t}${D}/files/${encodeURIComponent(n)}/url`,await r()),deleteFile:async n=>(await l(`/files/${encodeURIComponent(n)}`,{method:"DELETE"})).deleted,listDocuments:async()=>(await v(`${t}${D}/documents`,await r())).documents,readDocument:async n=>(await v(`${t}${D}/documents/${encodeURIComponent(n)}`,await r())).document,saveDocument:async(n,s)=>await l(`/documents/${encodeURIComponent(n)}`,{method:"PATCH",body:s})}};var mt=/\/+$/,ft="/api/v1/end-user",yt=e=>{let t=e.baseUrl.replace(mt,""),o=async(r,l)=>{let i;try{i=await fetch(`${t}${ft}${r}`,l===void 0?{}:{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(l)})}catch(n){throw w(n)}if(i.status===429)throw w({error:"rate_limited",retryable:!0});if(!i.ok)throw w({error:`shop_request_failed_${String(i.status)}`});try{return await i.json()}catch(n){throw w(n)}};return{listProducts:async()=>{let r=await o(`/shop/products?publishable_key=${encodeURIComponent(e.publishableKey)}`);return{products:r.products.map(l=>({...l,currency:typeof l.currency=="string"?l.currency:""})),truncated:r.truncated===!0}},apply:async r=>await o("/shop/apply",{publishable_key:e.publishableKey,name:r.name,email:r.email,...r.phone?{phone:r.phone}:{},...r.message?{message:r.message}:{},...r.productId?{productId:r.productId}:{}})}};import{useCallback as bt,useEffect as ht,useState as A}from"react";var wt=e=>e&&typeof e=="object"&&typeof e.error=="string"?e.error:e instanceof Error?e.message:"shop_unavailable",xt=e=>{let[t,o]=A([]),[r,l]=A(!1),[i,n]=A(!0),[s,a]=A(null),[u,d]=A(0);ht(()=>{let g=!0;return n(!0),e.listProducts().then(p=>{g&&(o(p.products),l(p.truncated),a(null))}).catch(p=>{g&&a(wt(p))}).finally(()=>{g&&n(!1)}),()=>{g=!1}},[e,u]);let c=bt(()=>d(g=>g+1),[]);return{products:t,truncated:r,loading:i,error:s,reload:c}};import{useCallback as vt,useEffect as Ae,useRef as St,useState as $}from"react";var Me="greeting";function We(e,t){if(e.some(i=>i.id===t.id))return e;let o=e.filter(i=>i.id!==Me),r=i=>i.author==="client"==(t.author==="client");return[...o.filter(i=>!(i.pending&&r(i)&&i.text===t.text)),t]}var Rt=(e,t)=>{let[o,r]=$([]),[l,i]=$(""),[n,s]=$(!1),[a,u]=$(null),d=St(0),c=t?.pollMs??2e3;Ae(()=>{let p=!0;return e.getInfo().then(y=>{p&&y.greeting&&r(x=>x.length===0?[{id:Me,cursor:"",author:"agent",text:y.greeting}]:x)}).catch(()=>{}),()=>{p=!1}},[e]),Ae(()=>e.subscribe?.({onMessage:p=>r(y=>We(y,p)),onError:p=>u(p.error),onHealthy:()=>u(null)},{intervalMs:c}),[e,c]);let g=vt(()=>{let p=l.trim();if(!p||n)return;i(""),u(null),s(!0),d.current+=1;let y=`pending-${d.current}`,x={id:y,cursor:"",author:"client",text:p,pending:!0};r(f=>[...f,x]),e.sendMessage(p).then(f=>{s(!1),f.reply.trim()&&r(m=>m.some(k=>!k.pending&&k.author!=="client"&&k.text===f.reply)?m:(d.current+=1,[...m,{id:`pending-agent-${d.current}`,cursor:"",author:"agent",text:f.reply,pending:!0}]))}).catch(f=>{u(f instanceof Error?f.message:"send_failed"),s(!1),r(R=>R.filter(m=>m.id!==y)),i(R=>R||p)})},[l,n,e]);return{messages:o,input:l,setInput:i,send:g,sending:n,error:a}};export{Ke as Chat,le as GRID_COLS,ue as GRID_MAX_COLS,de as GRID_MAX_ROWS,je as HolaProvider,H as PortalConflict,W as bandOfKind,ce as bandOfType,De as cellValue,Ue as createApiTransport,qe as createHolaClient,gt as createPortalData,yt as createPortalShop,G as createWidgetTransport,Te as deliverableCellText,ve as deliverableStatus,se as deriveFields,E as emptyTableResponses,ge as footprintOf,B as footprintWith,He as formatDeliverableDate,q as groupDeliverableVersions,ae as inferSpec,ke as isDeliverableChecked,We as mergeMessage,Q as normalizeDeliverableColType,X as normalizeDeliverableItem,we as parseDashboardSpec,xe as parseDeliverableItems,Re as parseDeliverableTable,Pe as parseTableResponses,z as placeWidgets,Se as publishedVersionOf,be as renderModel,Ce as setResponse,Ie as setTableReview,me as splitLayout,_ as textDeltaOf,O as thinkingDeltaOf,U as toolEventOf,F as useArtifactUrl,V as useChat,N as useHolaClient,xt as useShop,Rt as useThread};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@holaboss/client",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.20",
|
|
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",
|