@holaboss/client 0.2.0-beta.30 → 0.2.0-beta.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  'use client'
2
- var ee=Object.defineProperty;var lt=Object.getOwnPropertyDescriptor;var ut=Object.getOwnPropertyNames;var dt=Object.prototype.hasOwnProperty;var pt=(e,t)=>{for(var n in t)ee(e,n,{get:t[n],enumerable:!0})},ct=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of ut(t))!dt.call(e,s)&&s!==n&&ee(e,s,{get:()=>t[s],enumerable:!(r=lt(t,s))||r.enumerable});return e};var mt=e=>ct(ee({},"__esModule",{value:!0}),e);var Bt={};pt(Bt,{Chat:()=>Oe,CreditRefused:()=>E,GRID_COLS:()=>oe,GRID_MAX_COLS:()=>se,GRID_MAX_ROWS:()=>ie,HolaProvider:()=>$e,PortalConflict:()=>M,QUOTE_BALANCE_LABEL:()=>Ce,QUOTE_DEPOSIT_LABEL:()=>ke,bandOfKind:()=>$,bandOfType:()=>ae,buyRequestText:()=>nt,cellValue:()=>Se,createApiTransport:()=>Ee,createHolaClient:()=>Fe,createPortalCredits:()=>je,createPortalData:()=>Ge,createPortalShop:()=>Qe,createWidgetTransport:()=>z,deliverableCellText:()=>he,deliverableStatus:()=>fe,deriveFields:()=>ne,emptyTableResponses:()=>F,facetValues:()=>tt,footprintOf:()=>le,footprintWith:()=>J,formatDeliverableDate:()=>Te,groupDeliverableVersions:()=>Y,includesFor:()=>et,inferSpec:()=>re,isDeliverableChecked:()=>xe,mergeMessage:()=>De,modeOf:()=>ze,money:()=>_,normalizeDeliverableColType:()=>Z,normalizeDeliverableItem:()=>X,orderBilling:()=>Ve,parseDashboardSpec:()=>me,parseDeliverableItems:()=>ge,parseDeliverableTable:()=>be,parseTableResponses:()=>we,placeWidgets:()=>K,priceFor:()=>Xe,priceLabel:()=>Re,publishedVersionOf:()=>ye,quantityRange:()=>Ze,quoteSchedule:()=>Be,renderModel:()=>ce,setResponse:()=>ve,setTableReview:()=>Pe,shelfPriceLabel:()=>Ke,shelfProblem:()=>rt,splitLayout:()=>ue,textDeltaOf:()=>L,thinkingDeltaOf:()=>U,toolEventOf:()=>q,totalFor:()=>Ye,useArtifactUrl:()=>B,useChat:()=>G,useCredits:()=>ot,useHolaClient:()=>j,useShop:()=>st,useThread:()=>at});module.exports=mt(Bt);var Ie=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="message_update"?t.assistantMessageEvent??null:null},L=e=>{let t=Ie(e);return t?.type==="text_delta"&&typeof t.delta=="string"?t.delta:null},U=e=>{let t=Ie(e);return t?.type==="thinking_delta"&&typeof t.delta=="string"?t.delta:null},q=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 gt=/^ /,w=e=>{if(e&&typeof e=="object"){let t=e,n=typeof t.error=="string"?t.error:"request_failed";return typeof t.retryable=="boolean"?{error:n,retryable:t.retryable}:{error:n}}return{error:"request_failed"}},ft=e=>{let t="message",n=[];for(let r of e.split(`
3
- `))r.startsWith(":")||(r.startsWith("event:")?t=r.slice(6).trim():r.startsWith("data:")&&n.push(r.slice(5).replace(gt,"")));return n.length>0?{event:t,data:n.join(`
4
- `)}:null},yt=(e,t,n)=>{let r;try{r=JSON.parse(e.data)}catch{return}if(e.event==="session"){let s=r.sessionId;s&&(n(s),t.onSession?.(s));return}if(e.event==="turn_event"){t.onEvent?.(r);let s=L(r);s&&t.onText?.(s);let i=U(r);i&&t.onThinking?.(i);let o=q(r);o&&t.onTool?.(o);return}if(e.event==="chat_completed"){let s=r;n(s.sessionId),t.onComplete?.(s);return}e.event==="chat_error"&&t.onError?.(w(r))},P=async(e,t)=>{let n=await fetch(e,{headers:t});if(!n.ok)throw new Error(`hola: request failed (${n.status})`);return await n.json()},Ae=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()},He=async(e,t,n,r)=>{let s=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body,signal:r});if(!(s.ok&&s.body)){t.onError?.({error:`stream_failed_${s.status}`});return}let i=s.body.getReader(),o=new TextDecoder,a="",l=()=>{let d=a.indexOf(`
2
+ var ie=Object.defineProperty;var gt=Object.getOwnPropertyDescriptor;var ft=Object.getOwnPropertyNames;var yt=Object.prototype.hasOwnProperty;var bt=(e,t)=>{for(var n in t)ie(e,n,{get:t[n],enumerable:!0})},ht=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of ft(t))!yt.call(e,s)&&s!==n&&ie(e,s,{get:()=>t[s],enumerable:!(r=gt(t,s))||r.enumerable});return e};var xt=e=>ht(ie({},"__esModule",{value:!0}),e);var Kt={};bt(Kt,{Chat:()=>Ue,CreditRefused:()=>M,GRID_COLS:()=>de,GRID_MAX_COLS:()=>pe,GRID_MAX_ROWS:()=>ce,HolaProvider:()=>_e,InsufficientCredits:()=>_,PortalConflict:()=>E,QUOTE_BALANCE_LABEL:()=>se,QUOTE_DEPOSIT_LABEL:()=>oe,bandOfKind:()=>W,bandOfType:()=>me,buyRequestText:()=>lt,cellValue:()=>Re,createApiTransport:()=>Oe,createHolaClient:()=>Ne,createPortalCredits:()=>Xe,createPortalData:()=>Ye,createPortalShop:()=>Ze,createWidgetTransport:()=>J,creditsOfMoney:()=>Je,deliverableCellText:()=>te,deliverableCellValues:()=>ke,deliverableStatus:()=>Pe,deriveFields:()=>le,emptyTableResponses:()=>F,facetValues:()=>at,footprintOf:()=>ge,footprintWith:()=>K,formatDeliverableDate:()=>Ae,groupDeliverableVersions:()=>Z,includesFor:()=>it,inferSpec:()=>ue,isDeliverableChecked:()=>Te,mergeMessage:()=>He,modeOf:()=>et,money:()=>L,normalizeDeliverableColType:()=>ee,normalizeDeliverableItem:()=>Y,orderBilling:()=>Ke,parseDashboardSpec:()=>xe,parseDeliverableItems:()=>we,parseDeliverableTable:()=>ve,parseTableResponses:()=>Ce,paymentAsked:()=>re,paymentPayMethods:()=>ze,placeWidgets:()=>X,priceFor:()=>rt,priceLabel:()=>Me,publishedVersionOf:()=>Se,quantityRange:()=>st,quoteSchedule:()=>Qe,renderModel:()=>he,setResponse:()=>De,setTableReview:()=>Ie,shelfPriceLabel:()=>nt,shelfProblem:()=>ut,splitLayout:()=>fe,textDeltaOf:()=>U,thinkingDeltaOf:()=>N,toolEventOf:()=>q,totalFor:()=>ot,useArtifactUrl:()=>B,useChat:()=>Q,useCredits:()=>dt,useHolaClient:()=>G,useShop:()=>pt,useThread:()=>mt});module.exports=xt(Kt);var Ee=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="message_update"?t.assistantMessageEvent??null:null},U=e=>{let t=Ee(e);return t?.type==="text_delta"&&typeof t.delta=="string"?t.delta:null},N=e=>{let t=Ee(e);return t?.type==="thinking_delta"&&typeof t.delta=="string"?t.delta:null},q=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 wt=/^ /,w=e=>{if(e&&typeof e=="object"){let t=e,n=typeof t.error=="string"?t.error:"request_failed";return typeof t.retryable=="boolean"?{error:n,retryable:t.retryable}:{error:n}}return{error:"request_failed"}},Pt=e=>{let t="message",n=[];for(let r of e.split(`
3
+ `))r.startsWith(":")||(r.startsWith("event:")?t=r.slice(6).trim():r.startsWith("data:")&&n.push(r.slice(5).replace(wt,"")));return n.length>0?{event:t,data:n.join(`
4
+ `)}:null},St=(e,t,n)=>{let r;try{r=JSON.parse(e.data)}catch{return}if(e.event==="session"){let s=r.sessionId;s&&(n(s),t.onSession?.(s));return}if(e.event==="turn_event"){t.onEvent?.(r);let s=U(r);s&&t.onText?.(s);let a=N(r);a&&t.onThinking?.(a);let o=q(r);o&&t.onTool?.(o);return}if(e.event==="chat_completed"){let s=r;n(s.sessionId),t.onComplete?.(s);return}e.event==="chat_error"&&t.onError?.(w(r))},v=async(e,t)=>{let n=await fetch(e,{headers:t});if(!n.ok)throw new Error(`hola: request failed (${n.status})`);return await n.json()},We=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()},$e=async(e,t,n,r)=>{let s=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body,signal:r});if(!(s.ok&&s.body)){t.onError?.({error:`stream_failed_${s.status}`});return}let a=s.body.getReader(),o=new TextDecoder,i="",l=()=>{let d=i.indexOf(`
5
5
 
6
- `);for(;d!==-1;){let p=a.slice(0,d);a=a.slice(d+2);let f=ft(p);f&&yt(f,t,n),d=a.indexOf(`
6
+ `);for(;d!==-1;){let m=i.slice(0,d);i=i.slice(d+2);let p=Pt(m);p&&St(p,t,n),d=i.indexOf(`
7
7
 
8
- `)}},u=async()=>{let d=await i.read();if(!d.done)return a+=o.decode(d.value,{stream:!0}),l(),u()};await u()};var bt=/\/+$/,te="/api/v1/end-user",Ee=e=>{let t=e.baseUrl.replace(bt,""),n=()=>typeof e.token=="function"?e.token():e.token,r=o=>e.project?`${o}project=${encodeURIComponent(e.project)}`:"",s=async()=>({"content-type":"application/json",authorization:`Bearer ${await n()}`}),i=async o=>{let a=await fetch(`${t}${te}/chat${r("?")}`,{method:"POST",headers:await s(),body:JSON.stringify({message:o})});if(!a.ok)throw new Error(`hola: message failed (${a.status})`);return{reply:(await a.json()).reply??"",sessionId:"",artifacts:[]}};return{sessionId:()=>"",getInfo:async()=>P(`${t}${te}/chat/info${r("?")}`,await s()),sendMessage:i,streamMessage:async(o,a)=>{try{let l=await i(o);a.onText?.(l.reply),a.onComplete?.(l)}catch(l){a.onError?.(w(l))}},subscribe:(o,a)=>{let l=a?.since??"0",u=!1,d,p=a?.intervalMs??3e3,f=typeof document<"u",c=()=>f&&document.visibilityState==="hidden",m=!1,y=()=>{if(!u){if(c()){m=!0;return}d=setTimeout(b,p)}},b=async()=>{try{let x=await P(`${t}${te}/chat/thread?since=${encodeURIComponent(l)}${r("&")}`,await s());for(let I of x.messages)o.onMessage(I);l=x.cursor,o.onHealthy?.()}catch(x){o.onError?.(w(x))}y()},R=()=>{u||!m||c()||(m=!1,d&&clearTimeout(d),d=setTimeout(b,0))};f&&document.addEventListener("visibilitychange",R);let g=()=>{u=!0,d&&clearTimeout(d),f&&document.removeEventListener("visibilitychange",R)};return a?.signal?.addEventListener("abort",g),d=setTimeout(b,0),g}}};var N=require("react"),B=(e,t)=>{let[n,r]=(0,N.useState)("");return(0,N.useEffect)(()=>{if(!e){r("");return}let s=Uint8Array.from(atob(e),o=>o.charCodeAt(0)),i=URL.createObjectURL(new Blob([s],{type:t}));return r(i),()=>URL.revokeObjectURL(i)},[e,t]),n};var Q=require("react");var V=require("react"),We=require("react/jsx-runtime"),Me=(0,V.createContext)(null),$e=({client:e,children:t})=>(0,We.jsx)(Me.Provider,{value:e,children:t}),j=()=>{let e=(0,V.useContext)(Me);if(!e)throw new Error("useHolaClient must be used within <HolaProvider>");return e};var S=require("react"),G=e=>{let[t,n]=(0,S.useState)([]),[r,s]=(0,S.useState)(""),[i,o]=(0,S.useState)(!1),[a,l]=(0,S.useState)(null),u=(0,S.useRef)(0),d=(0,S.useRef)(null);(0,S.useEffect)(()=>()=>d.current?.abort(),[]);let p=(0,S.useCallback)(()=>{let c=u.current;return u.current+=1,c},[]);(0,S.useEffect)(()=>{let c=!0;return e.getInfo().then(m=>{c&&m.greeting&&n([{id:p(),role:"assistant",text:m.greeting}])}).catch(()=>{}),()=>{c=!1}},[e,p]);let f=(0,S.useCallback)(()=>{let c=r.trim();if(!c||i)return;s(""),l(null),o(!0);let m=p(),y=p();n(g=>[...g,{id:m,role:"user",text:c},{id:y,role:"assistant",text:"",streaming:!0}]);let b=g=>{n(x=>x.map(I=>I.id===y?g(I):I))},R=new AbortController;d.current=R,e.streamMessage(c,{onText:g=>b(x=>({...x,text:x.text+g})),onComplete:g=>{b(x=>({...x,text:g.reply||x.text,artifacts:g.artifacts,streaming:!1})),o(!1)},onError:g=>{b(x=>({...x,streaming:!1})),l(g.error),o(!1)}},R.signal).catch(g=>{b(x=>({...x,streaming:!1})),l(g instanceof Error?g.message:"stream_failed"),o(!1)}).finally(()=>{o(!1),b(g=>g.streaming?{...g,streaming:!1}:g)})},[r,i,e,p]);return{messages:t,input:r,setInput:s,send:f,sending:i,error:a}};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"}},ht=({artifact:e})=>{let t=B(e.dataBase64??"",e.mimeType),n=e.url??t;return n?e.mimeType.startsWith("image/")?(0,v.jsx)("a",{href:n,rel:"noopener noreferrer",target:"_blank",children:(0,v.jsx)("img",{alt:e.filename,src:n,style:k.image})}):(0,v.jsx)("a",{download:e.filename,href:n,style:k.link,children:e.filename}):null},Oe=()=>{let e=j(),{messages:t,input:n,setInput:r,send:s,sending:i,error:o}=G(e),a=(0,Q.useRef)(null);(0,Q.useEffect)(()=>{let u=a.current;u&&(u.scrollTop=u.scrollHeight)},[t]);let l=u=>{u.preventDefault(),s()};return(0,v.jsxs)("div",{style:k.root,children:[(0,v.jsx)("div",{ref:a,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)(ht,{artifact:d},d.filename))}):null]},u.id))}),o?(0,v.jsx)("div",{style:k.error,children:o}):null,(0,v.jsxs)("form",{onSubmit:l,style:k.form,children:[(0,v.jsx)("input",{"aria-label":"Message",onChange:u=>r(u.target.value),placeholder:"Type a message\u2026",style:k.input,value:n}),(0,v.jsx)("button",{disabled:i||n.trim().length===0,style:k.button,type:"submit",children:"Send"})]})]})};var xt=/\/+$/,z=e=>{let t=e.sessionId,n=e.baseUrl.replace(xt,""),r=o=>`${n}/endpoint/${encodeURIComponent(e.token)}${o}`,s={"content-type":"application/json"},i=(o,a)=>({url:r(o),headers:s,body:JSON.stringify({message:a,...t?{sessionId:t}:{},...e.identity?{externalUserId:e.identity.externalUserId,userHmac:e.identity.userHmac}:{}})});return{sessionId:()=>t,getInfo:()=>P(r("/config"),{}),sendMessage:async o=>{let a=await Ae(i("/message",o));return t=a.sessionId,a},streamMessage:(o,a,l)=>He(i("/message/stream",o),a,u=>{t=u},l),subscribe:(o,a)=>{let l=a?.since??"0",u=!1,d,p=a?.intervalMs??3e3,f=async()=>{let m=t;if(m)try{let y=await P(r(`/messages?session=${encodeURIComponent(m)}&since=${encodeURIComponent(l)}`),{});for(let b of y.messages)o.onMessage(b);l=y.cursor,o.onHealthy?.()}catch(y){o.onError?.(w(y))}u||(d=setTimeout(f,p))},c=()=>{u=!0,d&&clearTimeout(d)};return a?.signal?.addEventListener("abort",c),d=setTimeout(f,0),c}}};var Fe=e=>"transport"in e?e.transport:z(e);var wt=/^https?:\/\//i,St=/^\d{4}-\d{2}-\d{2}(?:[T ]|$)/,vt=e=>e.replace(/_/g," ").replace(/\b\w/g,t=>t.toUpperCase());function Pt(e){if(typeof e=="number")return"number";if(typeof e=="boolean")return"boolean";if(typeof e=="string"){if(wt.test(e))return"url";if(St.test(e))return"date"}return"text"}function ne(e){let t=[],n=new Map;for(let r of e)for(let[s,i]of Object.entries(r.data??{})){if(i==null)continue;let o=n.get(s);o||(o=new Map,n.set(s,o),t.push(s));let a=Pt(i);o.set(a,(o.get(a)??0)+1)}return t.map(r=>{let s=n.get(r)??new Map,i="text",o=-1;for(let[a,l]of s)l>o&&(o=l,i=a);return{key:r,label:vt(r),type:i}})}var Tt=e=>typeof e=="number"?e:Number(e)||0,_e=e=>/rate|position|rank|score|percent|avg/i.test(e),kt=/posted|published|sent|completed|shipped|launched|_at/i,Ct=new Set(["service","order","end_user_id"]);function re(e,t){let n=e.filter(l=>!Ct.has(l.key)),r=n.filter(l=>l.type==="number").slice(0,3),s=n.find(l=>l.key==="status")??n.find(l=>l.type==="select"),i=n.find(l=>l.type==="date"&&kt.test(l.key))??n.find(l=>l.type==="date"),o=n.filter(l=>l.type==="number"&&!_e(l.key)).map(l=>({field:l,total:t.reduce((u,d)=>u+Tt(d.data[l.key]),0)})).sort((l,u)=>u.total-l.total).find(l=>l.total>0)?.field??null,a=[{type:"stat",label:"Items",agg:"count"}];for(let l of r){let u=_e(l.key);a.push({type:"stat",metric:l.key,agg:u?"avg":"sum",label:u?`Avg ${l.label.toLowerCase()}`:l.label})}return i&&a.push({type:"line",x:i.key,y:o?.key,agg:"sum",title:o?`${o.label} by day`:"Items by day"}),s&&a.push({type:"donut",groupBy:s.key,title:s.label}),a.push({type:"table",columns:n.map(l=>l.key)}),{version:1,widgets:a}}var oe=6,se=6,ie=4,Le={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))),Dt=e=>Math.max(1,Math.min(4,Math.round(e)));function $(e){return e==="stat"?"stat":e==="series"||e==="donut"?"chart":"block"}function ae(e){return e==="stat"?"stat":e==="line"||e==="bar"||e==="donut"?"chart":"block"}function le(e){return Le[e]}function J(e,t,n){let r=Le[e];return{w:t===void 0?r.w:Rt(t),h:n===void 0?r.h:Dt(n)}}function K(e){let t=[],n=[],r=(o,a,l,u)=>{if(o<0||o+l>6)return!1;for(let d=0;d<u;d+=1){let p=n[a+d];if(p){for(let f=0;f<l;f+=1)if(p[o+f])return!1}}return!0},s=(o,a,l,u)=>{for(let d=0;d<u;d+=1){let p=n[a+d]??[];for(let f=0;f<l;f+=1)p[o+f]=!0;n[a+d]=p}},i=(o,a)=>{for(let l=0;;l+=1)for(let u=0;u+o<=6;u+=1)if(r(u,l,o,a))return{gx:u,gy:l}};for(let o of e){let a=J($(o.kind),o.w,o.h),u=o.gx!==void 0&&o.gy!==void 0&&r(o.gx,o.gy,a.w,a.h)&&o.gx!==void 0&&o.gy!==void 0?{gx:o.gx,gy:o.gy}:i(a.w,a.h);s(u.gx,u.gy,a.w,a.h),t.push({widget:o,gx:u.gx,gy:u.gy,w:a.w,h:a.h})}return t}function ue(e){let t=[],n=[];for(let r of e)$(r.kind)==="block"?n.push(r):t.push(r);return{tiles:K(t),blocks:n}}var Ue=new Set(["service","order","end_user_id"]),de=e=>typeof e=="number"?e:Number(e)||0,qe=e=>e==null?"":String(e);function pe(e,t){if(e==="count")return t.length;if(t.length===0)return 0;if(e==="last")return t[t.length-1]??0;if(e==="min")return Math.min(...t);if(e==="max")return Math.max(...t);let n=t.reduce((r,s)=>r+s,0);return e==="avg"?Math.round(n/t.length*100)/100:n}function It(e,t,n,r){let s=new Map;for(let i of e){let o=new Date(qe(i.data[t]));if(Number.isNaN(o.getTime()))continue;let a=o.toISOString().slice(0,10),l=s.get(a)??[];l.push(n?de(i.data[n]):1),s.set(a,l)}return[...s.entries()].sort((i,o)=>i[0]<o[0]?-1:1).map(([i,o])=>({label:new Date(`${i}T00:00:00`).toLocaleDateString(void 0,{month:"short",day:"numeric"}),value:n?pe(r,o):o.length}))}function At(e,t,n,r="sum"){let s=new Map;for(let i of e){let o=qe(i.data[t]).trim();if(!o)continue;let a=s.get(o)??[];a.push(n?de(i.data[n]):1),s.set(o,a)}return[...s.entries()].map(([i,o])=>({label:i,value:n?pe(r,o):o.length})).sort((i,o)=>o.value-i.value)}function Ht(e,t,n,r){switch(e.type){case"stat":{let s=e.metric?t.get(e.metric):void 0;if(e.metric&&!s)return null;if(!s)return{kind:"stat",label:e.label??"Items",value:r.length};let i=r.map(o=>de(o.data[s.key]));return{kind:"stat",label:e.label??s.label,value:pe(e.agg??"sum",i)}}case"line":case"bar":{if(!t.has(e.x)||e.y&&!t.has(e.y))return null;let s=It(r,e.x,e.y,e.agg??"sum");return s.length<2?null:{kind:"series",draw:e.type,title:e.title??"By day",points:s}}case"donut":{if(!t.has(e.groupBy))return null;let s=At(r,e.groupBy,e.metric,e.agg??"sum");return s.length===0?null:{kind:"donut",title:e.title??t.get(e.groupBy)?.label??"Breakdown",points:s}}case"table":{let s=e.columns?e.columns.map(i=>t.get(i)).filter(i=>i!==void 0&&!Ue.has(i.key)):n;return s.length===0?null:{kind:"table",title:e.title,columns:s,rows:r}}case"text":return{kind:"text",title:e.title,body:e.body};default:return null}}function ce(e,t,n,r={}){let s=new Map,i=l=>({byKey:new Map(l.fields.map(u=>[u.key,u])),cols:l.fields.filter(u=>!Ue.has(u.key)),rows:l.rows}),o=i({fields:t,rows:n});for(let[l,u]of Object.entries(r))s.set(l,i(u));let a=[];for(let l of e.widgets){let u=l.type==="text"?void 0:l.source,d=u?s.get(u):o;if(!d)continue;let p=Ht(l,d.byKey,d.cols,d.rows);p&&a.push({...p,w:l.w,h:l.h,gx:l.gx,gy:l.gy})}return a}var Et=new Set(["sum","avg","count","min","max","last"]),Ne=e=>typeof e=="string"&&Et.has(e)?e:void 0,h=e=>typeof e=="string"&&e!==""?e:void 0,W=e=>typeof e=="number"&&e>=1?Math.min(6,Math.round(e)):void 0,O=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 Mt(e){if(typeof e!="object"||e===null)return null;let t=e;switch(t.type){case"stat":return{type:"stat",source:h(t.source),label:h(t.label),metric:h(t.metric)??h(t.column),agg:Ne(t.agg),w:W(t.w),h:O(t.h),gx:D(t.gx),gy:D(t.gy)};case"line":case"bar":{let n=h(t.x);return n?{type:t.type,source:h(t.source),title:h(t.title),x:n,y:h(t.y)??h(t.column),agg:Ne(t.agg),w:W(t.w),h:O(t.h),gx:D(t.gx),gy:D(t.gy)}:null}case"donut":{let n=h(t.groupBy)??h(t.column);return n?{type:"donut",source:h(t.source),title:h(t.title),groupBy:n,w:W(t.w),h:O(t.h),gx:D(t.gx),gy:D(t.gy)}:null}case"table":{let n=Array.isArray(t.columns)?t.columns.filter(r=>typeof r=="string"):void 0;return{type:"table",source:h(t.source),title:h(t.title),columns:n,w:W(t.w),h:O(t.h),gx:D(t.gx),gy:D(t.gy)}}case"text":{let n=h(t.body);return n?{type:"text",title:h(t.title),body:n,w:W(t.w),h:O(t.h),gx:D(t.gx),gy:D(t.gy)}:null}default:return null}}function me(e){let t=e;if(typeof e=="string"){if(e.trim()==="")return null;try{t=JSON.parse(e)}catch{return null}}if(typeof t!="object"||t===null)return null;let n=t.widgets;if(!Array.isArray(n))return null;let r=n.map(Mt).filter(i=>i!==null);if(r.length===0)return null;let s=t.version;return{version:typeof s=="number"?s:1,title:h(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,n=typeof t.value=="string"?t.value:"",r=t.kind==="link"||t.kind==="text"||t.kind==="table"?t.kind:"file",s=typeof t.v=="number"&&t.v>=1?Math.floor(t.v):void 0;return n?{kind:r,value:n,...s?{v:s}:{}}:null}return null}function Y(e){let t=new Map;for(let n of e){let r=n.v??1,s=t.get(r)??[];s.push(n),t.set(r,s)}return[...t.entries()].sort(([n],[r])=>n-r).map(([n,r])=>({v:n,items:r}))}function ge(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(s=>s!==null)}catch{}let n=String(e.file??"");return n?[{kind:"file",value:n}]:[]}function fe(e,t,n,r=""){let i=Y(e).find(a=>a.v===t)?.items??[],o=i.filter(a=>a.kind==="file").map(a=>n.get(a.value)??"");return i.some(a=>a.kind==="table")&&o.push(r),o.length===0||o.some(a=>a==="")?"awaiting":o.some(a=>a==="revise")?"revise":"accepted"}function ye(e){return Number(e.published_version)||0}function Z(e){return e==="number"||e==="date"||e==="boolean"||e==="select"||e==="url"?e:e==="link"?"url":e==="checkbox"?"boolean":"text"}function be(e){try{let t=JSON.parse(e);if(Array.isArray(t.columns)&&Array.isArray(t.rows)&&t.columns.length){let n=t.columns.map((i,o)=>({key:typeof i.key=="string"&&i.key?i.key:typeof i.id=="string"&&i.id?i.id:`column_${o+1}`,label:typeof i.label=="string"?i.label:"",type:Z(i.type),...i.clientEditable===!0?{clientEditable:!0}:{}})),r=t.rows.map((i,o)=>({id:typeof i.id=="string"&&i.id?i.id:`row_${o}`,cells:i.cells&&typeof i.cells=="object"?i.cells:{}})),s=typeof t.name=="string"?t.name:void 0;return{columns:n,rows:r,...s?{name:s}:{}}}}catch{}return null}function he(e){return e==null?"":String(e)}function xe(e){return e===!0||e==="true"||e==="1"||e==="yes"||e==="\u2713"}function F(){return{cells:{},verdict:"",comment:""}}function we(e){if(typeof e!="string"||e.trim()==="")return F();try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t)){let n=t;return{cells:n.cells&&typeof n.cells=="object"?n.cells:n,verdict:n.verdict==="accepted"||n.verdict==="revise"?n.verdict:"",comment:typeof n.comment=="string"?n.comment:""}}}catch{}return F()}function Se(e,t,n){if(e.clientEditable){let r=n.cells[t.id];if(r&&e.key in r)return r[e.key]}return t.cells[e.key]}function ve(e,t,n,r){return{...e,cells:{...e.cells,[t]:{...e.cells[t]??{},[n]:r}}}}function Pe(e,t,n){return{...e,verdict:t,comment:n}}function Te(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 E=class extends Error{code;status;constructor(t,n,r){super(n),this.name="CreditRefused",this.code=t,this.status=r}},$t=/\/+$/,Wt="/api/v1/end-user",ke="Pre-payment",Ce="After-payment";function Be(e,t){if(e<=0)return[];let n=t&&typeof t.upfront=="number"&&Number.isFinite(t.upfront)?Math.max(0,Math.min(t.upfront,e)):e,r=Math.round((e-n)*100)/100,s=[];return n>0&&s.push({label:ke,amount:n}),r>0&&s.push({label:Ce,amount:r}),s}var Ve=(e,t,n)=>{let r=t.filter(l=>l.order===n),s=r.reduce((l,u)=>l+u.amount,0),i=r.filter(l=>l.status==="paid").reduce((l,u)=>l+u.amount,0),o=e.value>0,a=s>0?s-i:e.value-i;return{value:e.value,priced:o,billed:s,paid:i,due:Math.max(0,a),lines:[...r].sort((l,u)=>l.status!==u.status?l.status==="due"?-1:1:(l.dueDate||l.paidAt).localeCompare(u.dueDate||u.paidAt)),awaitingPayment:o&&i<=0}},je=e=>{let t=e.baseUrl.replace($t,""),n=()=>typeof e.token=="function"?e.token():e.token,r=async(s,i={method:"GET"})=>{try{let o=await fetch(`${t}${Wt}${s}`,{method:i.method,headers:{"content-type":"application/json",authorization:`Bearer ${await n()}`},...i.body===void 0?{}:{body:JSON.stringify(i.body)}});if(!o.ok){let a=await o.json().catch(()=>({}));throw new E(a.error??"request_failed",a.message??`${i.method} ${s} \u2192 ${String(o.status)}`,o.status)}return await o.json()}catch(o){throw o instanceof E?o:w(o)}};return{wallet:()=>r("/credits"),history:()=>r("/credits/history"),topup:s=>r("/credits/checkout",{method:"POST",body:{packId:s}}),checkout:s=>r("/shop/checkout",{method:"POST",body:s}),payments:()=>r("/payments"),paymentMethods:()=>r("/payment-methods"),markPaymentSent:(s,i)=>r(`/payments/${encodeURIComponent(s)}/sent`,{method:"POST",body:{reference:i??""}}),inquiryQuote:s=>r(`/inquiries/${encodeURIComponent(s)}/quote`),acceptInquiry:(s,i)=>r(`/inquiries/${encodeURIComponent(s)}/accept`,{method:"POST",body:{version:i}}),enquire:(s,i,o)=>r("/shop/enquire",{method:"POST",body:{productId:s,answers:i,name:o??""}})}};var Ot=/\/+$/,H="/api/v1/end-user",M=class extends Error{constructor(t){super(t),this.name="PortalConflict"}};function Ft(e){let t="";for(let r=0;r<e.length;r+=32768)t+=String.fromCharCode(...e.subarray(r,r+32768));return btoa(t)}var Ge=e=>{let t=e.baseUrl.replace(Ot,""),n=()=>typeof e.token=="function"?e.token():e.token,r=async()=>({"content-type":"application/json",authorization:`Bearer ${await n()}`}),s=async(o,a)=>{try{let l=await fetch(`${t}${H}${o}`,{method:a.method,headers:await r(),...a.body===void 0?{}:{body:JSON.stringify(a.body)}});if(l.status===409){let u=await l.json().catch(()=>({}));throw new M(u.message??"Someone else saved this first.")}if(!l.ok){let u=await l.text().catch(()=>""),d=`${a.method} ${o} \u2192 ${String(l.status)}`;try{let p=JSON.parse(u);p.message&&(d=p.message)}catch{d=u?`${d}: ${u}`:d}throw w({error:d})}return await l.json()}catch(l){throw l instanceof M?l:w(l)}},i=o=>`/tables/${encodeURIComponent(o)}`;return{listTables:async()=>(await P(`${t}${H}/tables`,await r())).tables,listRows:async(o,a)=>await P(`${t}${H}${i(o)}/rows?limit=${String(a??100)}`,await r()),insertRow:async(o,a)=>{let{rowIds:l}=await s(`${i(o)}/rows`,{method:"POST",body:{rows:[a]}}),u=l[0];if(!u)throw w(new Error("The row was not created."));return u},patchRow:async(o,a,l)=>(await s(`${i(o)}/rows/${encodeURIComponent(a)}`,{method:"PATCH",body:l})).updated,deleteRow:async(o,a)=>(await s(`/${encodeURIComponent(o)}/${encodeURIComponent(a)}`,{method:"DELETE"})).deleted,listFiles:async()=>(await P(`${t}${H}/tables/files/rows?limit=200`,await r())).rows.map(a=>({id:a.rowId,filename:String(a.data.filename??""),source:String(a.data.source??"client"),campaign:String(a.data.campaign??""),size:typeof a.data.size=="number"?a.data.size:0,createdAt:a.createdAt})),uploadFile:async(o,a)=>{let l=new Uint8Array(await o.arrayBuffer());return await s("/files",{method:"POST",body:{filename:o.name,mime:o.type||"application/octet-stream",data:Ft(l),...a===void 0?{}:{message:a}}})},fileLink:async o=>await P(`${t}${H}/files/${encodeURIComponent(o)}/url`,await r()),deleteFile:async o=>(await s(`/files/${encodeURIComponent(o)}`,{method:"DELETE"})).deleted,listDocuments:async()=>(await P(`${t}${H}/documents`,await r())).documents,readDocument:async o=>(await P(`${t}${H}/documents/${encodeURIComponent(o)}`,await r())).document,saveDocument:async(o,a)=>await s(`/documents/${encodeURIComponent(o)}`,{method:"PATCH",body:a})}};var _t=/\/+$/,Lt="/api/v1/end-user",Qe=e=>{let t=e.baseUrl.replace(_t,""),n=async(r,s)=>{let i;try{i=await fetch(`${t}${Lt}${r}`,s===void 0?{}:{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(s)})}catch(o){throw w(o)}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(o){throw w(o)}};return{listProducts:async()=>{let r=await n(`/shop/products?publishable_key=${encodeURIComponent(e.publishableKey)}`);return{products:r.products.map(s=>({...s,currency:typeof s.currency=="string"?s.currency:""})),truncated:r.truncated===!0,enquiryForm:Array.isArray(r.enquiryForm)?r.enquiryForm:[]}},apply:async r=>await n("/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}:{}})}};var Ut=new Set(["buy","ask"]);function ze(e){return Ut.has(e.mode)?e.mode:"ask"}var qt={kind:"quoted"};function _(e,t){if(!t)return e.toLocaleString();if(t.toLowerCase()==="credits")return`${e.toLocaleString()} ${e===1?"credit":"credits"}`;let n=Number.isInteger(e)?0:2;try{return new Intl.NumberFormat(void 0,{style:"currency",currency:t,minimumFractionDigits:n,maximumFractionDigits:n}).format(e)}catch{return`${t} ${e.toLocaleString()}`}}function Je(e,t){let n=/^[a-z]+$/i.test(t)&&!t.endsWith("s")?"s":"";return`${e.toLocaleString()} ${t}${n}`}function Re(e,t){return e.kind==="quoted"?"Priced on enquiry":e.kind==="flat"?_(e.price,t):`${_(e.unitPrice,t)} per ${e.unitStep===1?e.unit:Je(e.unitStep,e.unit)}`}function Ke(e){let t=e.currency,n=e.pricing;if(n.kind!=="variants")return Re(n,t);let r=n.variants.map(s=>s.price).filter(s=>typeof s=="number");return r.length>0?`From ${_(Math.min(...r),t)}`:"Priced on enquiry"}function Xe(e,t){if(e.kind!=="variants")return e;let n=e.variants.find(r=>r.name===t);return typeof n?.price=="number"?{kind:"flat",price:n.price}:qt}function Ye(e,t){return e.kind==="flat"?e.price:e.kind==="per_unit"?e.unitPrice*Math.ceil(t/Math.max(e.unitStep,1)):null}function Ze(e,t){let n=t.kind==="per_unit"?Math.max(t.unitStep,1):1;return{min:Math.max(e.minQty??n,n),max:e.maxQty??null,step:n}}function et(e,t){let n=e.variants?.find(r=>r.name===t);return n&&n.includes.length>0?n.includes:e.includes}function tt(e,t){let n=[];for(let r of e){let s=t(r).trim();s&&!n.includes(s)&&n.push(s)}return n}function nt(e,t,n,r){let s=t?`${e.name} \u2014 ${t}`:e.name,i=n.kind==="per_unit"?`, ${Je(r,n.unit)}`:"";return`I'd like to buy ${s}${i}. How do I go ahead?`}function rt(e){return e?(e&&typeof e=="object"&&"error"in e?String(e.error):"")==="rate_limited"?"That's a lot of looking at once \u2014 give it a moment, then reload.":"The shop isn't loading right now. Please try again shortly.":null}var A=require("react"),ot=e=>{let[t,n]=(0,A.useState)(null),[r,s]=(0,A.useState)(!0),[i,o]=(0,A.useState)(null),a=(0,A.useCallback)(async()=>{try{n(await e.wallet()),o(null)}catch{o("Couldn't read your balance just now.")}finally{s(!1)}},[e]),l=(0,A.useCallback)(()=>{a().catch(()=>{})},[a]);return(0,A.useEffect)(()=>(l(),window.addEventListener("focus",l),()=>{window.removeEventListener("focus",l)}),[l]),{wallet:t,loading:r,failure:i,refresh:l}};var C=require("react"),Nt=e=>e&&typeof e=="object"&&typeof e.error=="string"?e.error:e instanceof Error?e.message:"shop_unavailable",st=e=>{let[t,n]=(0,C.useState)([]),[r,s]=(0,C.useState)([]),[i,o]=(0,C.useState)(!1),[a,l]=(0,C.useState)(!0),[u,d]=(0,C.useState)(null),[p,f]=(0,C.useState)(0);(0,C.useEffect)(()=>{let m=!0;return l(!0),e.listProducts().then(y=>{m&&(n(y.products),s(y.enquiryForm),o(y.truncated),d(null))}).catch(y=>{m&&d(Nt(y))}).finally(()=>{m&&l(!1)}),()=>{m=!1}},[e,p]);let c=(0,C.useCallback)(()=>f(m=>m+1),[]);return{products:t,enquiryForm:r,truncated:i,loading:a,error:u,reload:c}};var T=require("react"),it="greeting";function De(e,t){if(e.some(i=>i.id===t.id))return e;let n=e.filter(i=>i.id!==it),r=i=>i.author==="client"==(t.author==="client");return[...n.filter(i=>!(i.pending&&r(i)&&i.text===t.text)),t]}var at=(e,t)=>{let[n,r]=(0,T.useState)([]),[s,i]=(0,T.useState)(""),[o,a]=(0,T.useState)(!1),[l,u]=(0,T.useState)(null),d=(0,T.useRef)(0),p=t?.pollMs??2e3;(0,T.useEffect)(()=>{let c=!0;return e.getInfo().then(m=>{c&&m.greeting&&r(y=>y.length===0?[{id:it,cursor:"",author:"agent",text:m.greeting}]:y)}).catch(()=>{}),()=>{c=!1}},[e]),(0,T.useEffect)(()=>e.subscribe?.({onMessage:c=>r(m=>De(m,c)),onError:c=>u(c.error),onHealthy:()=>u(null)},{intervalMs:p}),[e,p]);let f=(0,T.useCallback)(()=>{let c=s.trim();if(!c||o)return;i(""),u(null),a(!0),d.current+=1;let m=`pending-${d.current}`,y={id:m,cursor:"",author:"client",text:c,pending:!0};r(b=>[...b,y]),e.sendMessage(c).then(b=>{a(!1),b.reply.trim()&&r(g=>g.some(I=>!I.pending&&I.author!=="client"&&I.text===b.reply)?g:(d.current+=1,[...g,{id:`pending-agent-${d.current}`,cursor:"",author:"agent",text:b.reply,pending:!0}]))}).catch(b=>{u(b instanceof Error?b.message:"send_failed"),a(!1),r(R=>R.filter(g=>g.id!==m)),i(R=>R||c)})},[s,o,e]);return{messages:n,input:s,setInput:i,send:f,sending:o,error:l}};0&&(module.exports={Chat,CreditRefused,GRID_COLS,GRID_MAX_COLS,GRID_MAX_ROWS,HolaProvider,PortalConflict,QUOTE_BALANCE_LABEL,QUOTE_DEPOSIT_LABEL,bandOfKind,bandOfType,buyRequestText,cellValue,createApiTransport,createHolaClient,createPortalCredits,createPortalData,createPortalShop,createWidgetTransport,deliverableCellText,deliverableStatus,deriveFields,emptyTableResponses,facetValues,footprintOf,footprintWith,formatDeliverableDate,groupDeliverableVersions,includesFor,inferSpec,isDeliverableChecked,mergeMessage,modeOf,money,normalizeDeliverableColType,normalizeDeliverableItem,orderBilling,parseDashboardSpec,parseDeliverableItems,parseDeliverableTable,parseTableResponses,placeWidgets,priceFor,priceLabel,publishedVersionOf,quantityRange,quoteSchedule,renderModel,setResponse,setTableReview,shelfPriceLabel,shelfProblem,splitLayout,textDeltaOf,thinkingDeltaOf,toolEventOf,totalFor,useArtifactUrl,useChat,useCredits,useHolaClient,useShop,useThread});
8
+ `)}},u=async()=>{let d=await a.read();if(!d.done)return i+=o.decode(d.value,{stream:!0}),l(),u()};await u()};var vt=/\/+$/,ae="/api/v1/end-user",Oe=e=>{let t=e.baseUrl.replace(vt,""),n=()=>typeof e.token=="function"?e.token():e.token,r=o=>e.project?`${o}project=${encodeURIComponent(e.project)}`:"",s=async()=>({"content-type":"application/json",authorization:`Bearer ${await n()}`}),a=async o=>{let i=await fetch(`${t}${ae}/chat${r("?")}`,{method:"POST",headers:await s(),body:JSON.stringify({message:o})});if(!i.ok)throw new Error(`hola: message failed (${i.status})`);return{reply:(await i.json()).reply??"",sessionId:"",artifacts:[]}};return{sessionId:()=>"",getInfo:async()=>v(`${t}${ae}/chat/info${r("?")}`,await s()),sendMessage:a,streamMessage:async(o,i)=>{try{let l=await a(o);i.onText?.(l.reply),i.onComplete?.(l)}catch(l){i.onError?.(w(l))}},subscribe:(o,i)=>{let l=i?.since??"0",u=!1,d,m=i?.intervalMs??3e3,p=typeof document<"u",c=()=>p&&document.visibilityState==="hidden",g=!1,y=()=>{if(!u){if(c()){g=!0;return}d=setTimeout(b,m)}},b=async()=>{try{let x=await v(`${t}${ae}/chat/thread?since=${encodeURIComponent(l)}${r("&")}`,await s());for(let I of x.messages)o.onMessage(I);l=x.cursor,o.onHealthy?.()}catch(x){o.onError?.(w(x))}y()},R=()=>{u||!g||c()||(g=!1,d&&clearTimeout(d),d=setTimeout(b,0))};p&&document.addEventListener("visibilitychange",R);let f=()=>{u=!0,d&&clearTimeout(d),p&&document.removeEventListener("visibilitychange",R)};return i?.signal?.addEventListener("abort",f),d=setTimeout(b,0),f}}};var V=require("react"),B=(e,t)=>{let[n,r]=(0,V.useState)("");return(0,V.useEffect)(()=>{if(!e){r("");return}let s=Uint8Array.from(atob(e),o=>o.charCodeAt(0)),a=URL.createObjectURL(new Blob([s],{type:t}));return r(a),()=>URL.revokeObjectURL(a)},[e,t]),n};var z=require("react");var j=require("react"),Le=require("react/jsx-runtime"),Fe=(0,j.createContext)(null),_e=({client:e,children:t})=>(0,Le.jsx)(Fe.Provider,{value:e,children:t}),G=()=>{let e=(0,j.useContext)(Fe);if(!e)throw new Error("useHolaClient must be used within <HolaProvider>");return e};var P=require("react"),Q=e=>{let[t,n]=(0,P.useState)([]),[r,s]=(0,P.useState)(""),[a,o]=(0,P.useState)(!1),[i,l]=(0,P.useState)(null),u=(0,P.useRef)(0),d=(0,P.useRef)(null);(0,P.useEffect)(()=>()=>d.current?.abort(),[]);let m=(0,P.useCallback)(()=>{let c=u.current;return u.current+=1,c},[]);(0,P.useEffect)(()=>{let c=!0;return e.getInfo().then(g=>{c&&g.greeting&&n([{id:m(),role:"assistant",text:g.greeting}])}).catch(()=>{}),()=>{c=!1}},[e,m]);let p=(0,P.useCallback)(()=>{let c=r.trim();if(!c||a)return;s(""),l(null),o(!0);let g=m(),y=m();n(f=>[...f,{id:g,role:"user",text:c},{id:y,role:"assistant",text:"",streaming:!0}]);let b=f=>{n(x=>x.map(I=>I.id===y?f(I):I))},R=new AbortController;d.current=R,e.streamMessage(c,{onText:f=>b(x=>({...x,text:x.text+f})),onComplete:f=>{b(x=>({...x,text:f.reply||x.text,artifacts:f.artifacts,streaming:!1})),o(!1)},onError:f=>{b(x=>({...x,streaming:!1})),l(f.error),o(!1)}},R.signal).catch(f=>{b(x=>({...x,streaming:!1})),l(f instanceof Error?f.message:"stream_failed"),o(!1)}).finally(()=>{o(!1),b(f=>f.streaming?{...f,streaming:!1}:f)})},[r,a,e,m]);return{messages:t,input:r,setInput:s,send:p,sending:a,error:i}};var S=require("react/jsx-runtime"),T={root:{display:"flex",flexDirection:"column",height:"100%",fontFamily:"system-ui, -apple-system, sans-serif",fontSize:14,color:"#111827"},log:{flex:1,overflowY:"auto",padding:12,display:"flex",flexDirection:"column",gap:8},user:{alignSelf:"flex-end",background:"#111827",color:"#ffffff",borderRadius:12,padding:"8px 12px",maxWidth:"80%",whiteSpace:"pre-wrap"},assistant:{alignSelf:"flex-start",background:"#f1f1f4",color:"#111827",borderRadius:12,padding:"8px 12px",maxWidth:"80%",whiteSpace:"pre-wrap"},artifacts:{display:"flex",flexDirection:"column",gap:6,marginTop:6},image:{maxHeight:220,borderRadius:8,border:"1px solid #e5e7eb"},link:{color:"#2563eb",textDecoration:"underline",wordBreak:"break-all"},error:{color:"#b91c1c",padding:"4px 12px",fontSize:13},form:{display:"flex",gap:8,borderTop:"1px solid #e5e7eb",padding:8},input:{flex:1,border:"1px solid #d1d5db",borderRadius:8,padding:"8px 10px",fontSize:14,outline:"none"},button:{border:"none",background:"#111827",color:"#ffffff",borderRadius:8,padding:"8px 14px",fontSize:14,cursor:"pointer"}},kt=({artifact:e})=>{let t=B(e.dataBase64??"",e.mimeType),n=e.url??t;return n?e.mimeType.startsWith("image/")?(0,S.jsx)("a",{href:n,rel:"noopener noreferrer",target:"_blank",children:(0,S.jsx)("img",{alt:e.filename,src:n,style:T.image})}):(0,S.jsx)("a",{download:e.filename,href:n,style:T.link,children:e.filename}):null},Ue=()=>{let e=G(),{messages:t,input:n,setInput:r,send:s,sending:a,error:o}=Q(e),i=(0,z.useRef)(null);(0,z.useEffect)(()=>{let u=i.current;u&&(u.scrollTop=u.scrollHeight)},[t]);let l=u=>{u.preventDefault(),s()};return(0,S.jsxs)("div",{style:T.root,children:[(0,S.jsx)("div",{ref:i,style:T.log,children:t.map(u=>(0,S.jsxs)("div",{style:u.role==="user"?T.user:T.assistant,children:[u.text||(u.streaming?"\u2026":""),u.artifacts&&u.artifacts.length>0?(0,S.jsx)("div",{style:T.artifacts,children:u.artifacts.map(d=>(0,S.jsx)(kt,{artifact:d},d.filename))}):null]},u.id))}),o?(0,S.jsx)("div",{style:T.error,children:o}):null,(0,S.jsxs)("form",{onSubmit:l,style:T.form,children:[(0,S.jsx)("input",{"aria-label":"Message",onChange:u=>r(u.target.value),placeholder:"Type a message\u2026",style:T.input,value:n}),(0,S.jsx)("button",{disabled:a||n.trim().length===0,style:T.button,type:"submit",children:"Send"})]})]})};var Tt=/\/+$/,J=e=>{let t=e.sessionId,n=e.baseUrl.replace(Tt,""),r=o=>`${n}/endpoint/${encodeURIComponent(e.token)}${o}`,s={"content-type":"application/json"},a=(o,i)=>({url:r(o),headers:s,body:JSON.stringify({message:i,...t?{sessionId:t}:{},...e.identity?{externalUserId:e.identity.externalUserId,userHmac:e.identity.userHmac}:{}})});return{sessionId:()=>t,getInfo:()=>v(r("/config"),{}),sendMessage:async o=>{let i=await We(a("/message",o));return t=i.sessionId,i},streamMessage:(o,i,l)=>$e(a("/message/stream",o),i,u=>{t=u},l),subscribe:(o,i)=>{let l=i?.since??"0",u=!1,d,m=i?.intervalMs??3e3,p=async()=>{let g=t;if(g)try{let y=await v(r(`/messages?session=${encodeURIComponent(g)}&since=${encodeURIComponent(l)}`),{});for(let b of y.messages)o.onMessage(b);l=y.cursor,o.onHealthy?.()}catch(y){o.onError?.(w(y))}u||(d=setTimeout(p,m))},c=()=>{u=!0,d&&clearTimeout(d)};return i?.signal?.addEventListener("abort",c),d=setTimeout(p,0),c}}};var Ne=e=>"transport"in e?e.transport:J(e);var Ct=/^https?:\/\//i,Rt=/^\d{4}-\d{2}-\d{2}(?:[T ]|$)/,Dt=e=>e.replace(/_/g," ").replace(/\b\w/g,t=>t.toUpperCase());function It(e){if(typeof e=="number")return"number";if(typeof e=="boolean")return"boolean";if(typeof e=="string"){if(Ct.test(e))return"url";if(Rt.test(e))return"date"}return"text"}function le(e){let t=[],n=new Map;for(let r of e)for(let[s,a]of Object.entries(r.data??{})){if(a==null)continue;let o=n.get(s);o||(o=new Map,n.set(s,o),t.push(s));let i=It(a);o.set(i,(o.get(i)??0)+1)}return t.map(r=>{let s=n.get(r)??new Map,a="text",o=-1;for(let[i,l]of s)l>o&&(o=l,a=i);return{key:r,label:Dt(r),type:a}})}var At=e=>typeof e=="number"?e:Number(e)||0,qe=e=>/rate|position|rank|score|percent|avg/i.test(e),Mt=/posted|published|sent|completed|shipped|launched|_at/i,Ht=new Set(["service","order","end_user_id"]);function ue(e,t){let n=e.filter(l=>!Ht.has(l.key)),r=n.filter(l=>l.type==="number").slice(0,3),s=n.find(l=>l.key==="status")??n.find(l=>l.type==="select"),a=n.find(l=>l.type==="date"&&Mt.test(l.key))??n.find(l=>l.type==="date"),o=n.filter(l=>l.type==="number"&&!qe(l.key)).map(l=>({field:l,total:t.reduce((u,d)=>u+At(d.data[l.key]),0)})).sort((l,u)=>u.total-l.total).find(l=>l.total>0)?.field??null,i=[{type:"stat",label:"Items",agg:"count"}];for(let l of r){let u=qe(l.key);i.push({type:"stat",metric:l.key,agg:u?"avg":"sum",label:u?`Avg ${l.label.toLowerCase()}`:l.label})}return a&&i.push({type:"line",x:a.key,y:o?.key,agg:"sum",title:o?`${o.label} by day`:"Items by day"}),s&&i.push({type:"donut",groupBy:s.key,title:s.label}),i.push({type:"table",columns:n.map(l=>l.key)}),{version:1,widgets:i}}var de=6,pe=6,ce=4,Ve={stat:{w:1,h:1},chart:{w:2,h:2},block:{w:6,h:2}},Et=e=>Math.max(1,Math.min(6,Math.round(e))),Wt=e=>Math.max(1,Math.min(4,Math.round(e)));function W(e){return e==="stat"?"stat":e==="series"||e==="donut"?"chart":"block"}function me(e){return e==="stat"?"stat":e==="line"||e==="bar"||e==="donut"?"chart":"block"}function ge(e){return Ve[e]}function K(e,t,n){let r=Ve[e];return{w:t===void 0?r.w:Et(t),h:n===void 0?r.h:Wt(n)}}function X(e){let t=[],n=[],r=(o,i,l,u)=>{if(o<0||o+l>6)return!1;for(let d=0;d<u;d+=1){let m=n[i+d];if(m){for(let p=0;p<l;p+=1)if(m[o+p])return!1}}return!0},s=(o,i,l,u)=>{for(let d=0;d<u;d+=1){let m=n[i+d]??[];for(let p=0;p<l;p+=1)m[o+p]=!0;n[i+d]=m}},a=(o,i)=>{for(let l=0;;l+=1)for(let u=0;u+o<=6;u+=1)if(r(u,l,o,i))return{gx:u,gy:l}};for(let o of e){let i=K(W(o.kind),o.w,o.h),u=o.gx!==void 0&&o.gy!==void 0&&r(o.gx,o.gy,i.w,i.h)&&o.gx!==void 0&&o.gy!==void 0?{gx:o.gx,gy:o.gy}:a(i.w,i.h);s(u.gx,u.gy,i.w,i.h),t.push({widget:o,gx:u.gx,gy:u.gy,w:i.w,h:i.h})}return t}function fe(e){let t=[],n=[];for(let r of e)W(r.kind)==="block"?n.push(r):t.push(r);return{tiles:X(t),blocks:n}}var Be=new Set(["service","order","end_user_id"]),ye=e=>typeof e=="number"?e:Number(e)||0,je=e=>e==null?"":String(e);function be(e,t){if(e==="count")return t.length;if(t.length===0)return 0;if(e==="last")return t[t.length-1]??0;if(e==="min")return Math.min(...t);if(e==="max")return Math.max(...t);let n=t.reduce((r,s)=>r+s,0);return e==="avg"?Math.round(n/t.length*100)/100:n}function $t(e,t,n,r){let s=new Map;for(let a of e){let o=new Date(je(a.data[t]));if(Number.isNaN(o.getTime()))continue;let i=o.toISOString().slice(0,10),l=s.get(i)??[];l.push(n?ye(a.data[n]):1),s.set(i,l)}return[...s.entries()].sort((a,o)=>a[0]<o[0]?-1:1).map(([a,o])=>({label:new Date(`${a}T00:00:00`).toLocaleDateString(void 0,{month:"short",day:"numeric"}),value:n?be(r,o):o.length}))}function Ot(e,t,n,r="sum"){let s=new Map;for(let a of e){let o=je(a.data[t]).trim();if(!o)continue;let i=s.get(o)??[];i.push(n?ye(a.data[n]):1),s.set(o,i)}return[...s.entries()].map(([a,o])=>({label:a,value:n?be(r,o):o.length})).sort((a,o)=>o.value-a.value)}function Ft(e,t,n,r){switch(e.type){case"stat":{let s=e.metric?t.get(e.metric):void 0;if(e.metric&&!s)return null;if(!s)return{kind:"stat",label:e.label??"Items",value:r.length};let a=r.map(o=>ye(o.data[s.key]));return{kind:"stat",label:e.label??s.label,value:be(e.agg??"sum",a)}}case"line":case"bar":{if(!t.has(e.x)||e.y&&!t.has(e.y))return null;let s=$t(r,e.x,e.y,e.agg??"sum");return s.length<2?null:{kind:"series",draw:e.type,title:e.title??"By day",points:s}}case"donut":{if(!t.has(e.groupBy))return null;let s=Ot(r,e.groupBy,e.metric,e.agg??"sum");return s.length===0?null:{kind:"donut",title:e.title??t.get(e.groupBy)?.label??"Breakdown",points:s}}case"table":{let s=e.columns?e.columns.map(a=>t.get(a)).filter(a=>a!==void 0&&!Be.has(a.key)):n;return s.length===0?null:{kind:"table",title:e.title,columns:s,rows:r}}case"text":return{kind:"text",title:e.title,body:e.body};default:return null}}function he(e,t,n,r={}){let s=new Map,a=l=>({byKey:new Map(l.fields.map(u=>[u.key,u])),cols:l.fields.filter(u=>!Be.has(u.key)),rows:l.rows}),o=a({fields:t,rows:n});for(let[l,u]of Object.entries(r))s.set(l,a(u));let i=[];for(let l of e.widgets){let u=l.type==="text"?void 0:l.source,d=u?s.get(u):o;if(!d)continue;let m=Ft(l,d.byKey,d.cols,d.rows);m&&i.push({...m,w:l.w,h:l.h,gx:l.gx,gy:l.gy})}return i}var _t=new Set(["sum","avg","count","min","max","last"]),Ge=e=>typeof e=="string"&&_t.has(e)?e:void 0,h=e=>typeof e=="string"&&e!==""?e:void 0,$=e=>typeof e=="number"&&e>=1?Math.min(6,Math.round(e)):void 0,O=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 Lt(e){if(typeof e!="object"||e===null)return null;let t=e;switch(t.type){case"stat":return{type:"stat",source:h(t.source),label:h(t.label),metric:h(t.metric)??h(t.column),agg:Ge(t.agg),w:$(t.w),h:O(t.h),gx:D(t.gx),gy:D(t.gy)};case"line":case"bar":{let n=h(t.x);return n?{type:t.type,source:h(t.source),title:h(t.title),x:n,y:h(t.y)??h(t.column),agg:Ge(t.agg),w:$(t.w),h:O(t.h),gx:D(t.gx),gy:D(t.gy)}:null}case"donut":{let n=h(t.groupBy)??h(t.column);return n?{type:"donut",source:h(t.source),title:h(t.title),groupBy:n,w:$(t.w),h:O(t.h),gx:D(t.gx),gy:D(t.gy)}:null}case"table":{let n=Array.isArray(t.columns)?t.columns.filter(r=>typeof r=="string"):void 0;return{type:"table",source:h(t.source),title:h(t.title),columns:n,w:$(t.w),h:O(t.h),gx:D(t.gx),gy:D(t.gy)}}case"text":{let n=h(t.body);return n?{type:"text",title:h(t.title),body:n,w:$(t.w),h:O(t.h),gx:D(t.gx),gy:D(t.gy)}:null}default:return null}}function xe(e){let t=e;if(typeof e=="string"){if(e.trim()==="")return null;try{t=JSON.parse(e)}catch{return null}}if(typeof t!="object"||t===null)return null;let n=t.widgets;if(!Array.isArray(n))return null;let r=n.map(Lt).filter(a=>a!==null);if(r.length===0)return null;let s=t.version;return{version:typeof s=="number"?s:1,title:h(t.title),widgets:r}}function Y(e){if(typeof e=="string")return e?{kind:"file",value:e}:null;if(e&&typeof e=="object"){let t=e,n=typeof t.value=="string"?t.value:"",r=t.kind==="link"||t.kind==="text"||t.kind==="table"?t.kind:"file",s=typeof t.v=="number"&&t.v>=1?Math.floor(t.v):void 0;return n?{kind:r,value:n,...s?{v:s}:{}}:null}return null}function Z(e){let t=new Map;for(let n of e){let r=n.v??1,s=t.get(r)??[];s.push(n),t.set(r,s)}return[...t.entries()].sort(([n],[r])=>n-r).map(([n,r])=>({v:n,items:r}))}function we(e){let t=e.files;if(typeof t=="string"&&t.trim()!=="")try{let r=JSON.parse(t);if(Array.isArray(r))return r.map(Y).filter(s=>s!==null)}catch{}let n=String(e.file??"");return n?[{kind:"file",value:n}]:[]}function Pe(e,t,n,r=""){let a=Z(e).find(i=>i.v===t)?.items??[],o=a.filter(i=>i.kind==="file").map(i=>n.get(i.value)??"");return a.some(i=>i.kind==="table")&&o.push(r),o.length===0||o.some(i=>i==="")?"awaiting":o.some(i=>i==="revise")?"revise":"accepted"}function Se(e){return Number(e.published_version)||0}function ee(e){return e==="number"||e==="date"||e==="boolean"||e==="select"||e==="multi_select"||e==="url"?e:e==="link"?"url":e==="checkbox"?"boolean":"text"}function ve(e){try{let t=JSON.parse(e);if(Array.isArray(t.columns)&&Array.isArray(t.rows)&&t.columns.length){let n=t.columns.map((a,o)=>({key:typeof a.key=="string"&&a.key?a.key:typeof a.id=="string"&&a.id?a.id:`column_${o+1}`,label:typeof a.label=="string"?a.label:"",type:ee(a.type),...(()=>{let i=Array.isArray(a.options)?[...new Set(a.options.map(l=>String(l).trim()).filter(l=>l!==""))]:[];return i.length>0?{options:i}:{}})(),...a.clientEditable===!0?{clientEditable:!0}:{}})),r=t.rows.map((a,o)=>({id:typeof a.id=="string"&&a.id?a.id:`row_${o}`,cells:a.cells&&typeof a.cells=="object"?a.cells:{}})),s=typeof t.name=="string"?t.name:void 0;return{columns:n,rows:r,...s?{name:s}:{}}}}catch{}return null}function te(e){return e==null?"":String(e)}function ke(e){let t=te(e).trim();if(t==="")return[];try{let n=JSON.parse(t);if(Array.isArray(n))return n.map(r=>String(r).trim()).filter(r=>r!=="")}catch{}return t.split(",").map(n=>n.trim()).filter(n=>n!=="")}function Te(e){return e===!0||e==="true"||e==="1"||e==="yes"||e==="\u2713"}function F(){return{cells:{},verdict:"",comment:""}}function Ce(e){if(typeof e!="string"||e.trim()==="")return F();try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t)){let n=t;return{cells:n.cells&&typeof n.cells=="object"?n.cells:n,verdict:n.verdict==="accepted"||n.verdict==="revise"?n.verdict:"",comment:typeof n.comment=="string"?n.comment:""}}}catch{}return F()}function Re(e,t,n){if(e.clientEditable){let r=n.cells[t.id];if(r&&e.key in r)return r[e.key]}return t.cells[e.key]}function De(e,t,n,r){return{...e,cells:{...e.cells,[t]:{...e.cells[t]??{},[n]:r}}}}function Ie(e,t,n){return{...e,verdict:t,comment:n}}function Ae(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 M=class extends Error{code;status;constructor(t,n,r){super(n),this.name="CreditRefused",this.code=t,this.status=r}},_=class extends M{credits;balance;short;constructor(t,n){super("insufficient_credits",t,402),this.name="InsufficientCredits",this.credits=n.credits,this.balance=n.balance,this.short=n.short}},Ut=/\/+$/,Nt="/api/v1/end-user",oe="Pre-payment",se="After-payment";function Qe(e,t){if(e<=0)return[];let n=t&&typeof t.upfront=="number"&&Number.isFinite(t.upfront)?Math.max(0,Math.min(t.upfront,e)):e,r=Math.round((e-n)*100)/100,s=[];return n>0&&s.push({label:oe,amount:n}),r>0&&s.push({label:se,amount:r}),s}var re=e=>e.status!=="paid"&&e.asked!==!1,ze=(e,t)=>e.payMethods&&e.payMethods.length>0?[...e.payMethods]:[...t],Je=(e,t)=>{let n=typeof t=="number"&&Number.isFinite(t)&&t>0?t:1;return!Number.isFinite(e)||e<=0?0:Math.ceil(e*n)},ne=e=>{let t=e.label.trim().toLowerCase();return t===oe.toLowerCase()?0:t===se.toLowerCase()?2:1},Ke=(e,t,n)=>{let r=t.filter(p=>p.order===n),s=p=>p.reduce((c,g)=>c+g.amount,0),a=s(r),o=s(r.filter(p=>p.status==="paid")),i=e.value>0,l=[...r].sort((p,c)=>ne(p)!==ne(c)?ne(p)-ne(c):(p.dueDate||p.paidAt).localeCompare(c.dueDate||c.paidAt)),u=l.filter(re),d=l.filter(p=>p.status!=="paid"&&!re(p)),m=a>0?s(u):e.value-o;return{value:e.value,priced:i,billed:a,paid:o,due:Math.max(0,m),scheduled:s(d),lines:l,asked:u,upcoming:d,awaitingPayment:i&&o<=0}},qt=e=>{let{credits:t,balance:n,short:r}=e;return typeof t!="number"||typeof n!="number"||typeof r!="number"||!(Number.isFinite(t)&&Number.isFinite(n)&&Number.isFinite(r))?null:{credits:t,balance:n,short:r}},Xe=e=>{let t=e.baseUrl.replace(Ut,""),n=()=>typeof e.token=="function"?e.token():e.token,r=async(s,a={method:"GET"})=>{try{let o=await fetch(`${t}${Nt}${s}`,{method:a.method,headers:{"content-type":"application/json",authorization:`Bearer ${await n()}`},...a.body===void 0?{}:{body:JSON.stringify(a.body)}});if(!o.ok){let i=await o.json().catch(()=>({})),l=i.message??`${a.method} ${s} \u2192 ${String(o.status)}`,u=qt(i);throw o.status===402&&i.error==="insufficient_credits"&&u?new _(l,u):new M(i.error??"request_failed",l,o.status)}return await o.json()}catch(o){throw o instanceof M?o:w(o)}};return{wallet:()=>r("/credits"),history:()=>r("/credits/history"),topup:s=>r("/credits/checkout",{method:"POST",body:{packId:s}}),checkout:s=>r("/shop/checkout",{method:"POST",body:s}),payments:()=>r("/payments"),paymentMethods:()=>r("/payment-methods"),markPaymentSent:(s,a)=>r(`/payments/${encodeURIComponent(s)}/sent`,{method:"POST",body:{reference:a??""}}),payWithCredits:s=>r(`/payments/${encodeURIComponent(s)}/pay-with-credits`,{method:"POST",body:{}}),inquiryQuote:s=>r(`/inquiries/${encodeURIComponent(s)}/quote`),acceptInquiry:(s,a)=>r(`/inquiries/${encodeURIComponent(s)}/accept`,{method:"POST",body:{version:a}}),enquire:(s,a,o)=>r("/shop/enquire",{method:"POST",body:{productId:s,answers:a,name:o??""}})}};var Vt=/\/+$/,H="/api/v1/end-user",E=class extends Error{constructor(t){super(t),this.name="PortalConflict"}};function Bt(e){let t="";for(let r=0;r<e.length;r+=32768)t+=String.fromCharCode(...e.subarray(r,r+32768));return btoa(t)}var Ye=e=>{let t=e.baseUrl.replace(Vt,""),n=()=>typeof e.token=="function"?e.token():e.token,r=async()=>({"content-type":"application/json",authorization:`Bearer ${await n()}`}),s=async(o,i)=>{try{let l=await fetch(`${t}${H}${o}`,{method:i.method,headers:await r(),...i.body===void 0?{}:{body:JSON.stringify(i.body)}});if(l.status===409){let u=await l.json().catch(()=>({}));throw new E(u.message??"Someone else saved this first.")}if(!l.ok){let u=await l.text().catch(()=>""),d=`${i.method} ${o} \u2192 ${String(l.status)}`;try{let m=JSON.parse(u);m.message&&(d=m.message)}catch{d=u?`${d}: ${u}`:d}throw w({error:d})}return await l.json()}catch(l){throw l instanceof E?l:w(l)}},a=o=>`/tables/${encodeURIComponent(o)}`;return{listTables:async()=>(await v(`${t}${H}/tables`,await r())).tables,listRows:async(o,i)=>await v(`${t}${H}${a(o)}/rows?limit=${String(i??100)}`,await r()),insertRow:async(o,i)=>{let{rowIds:l}=await s(`${a(o)}/rows`,{method:"POST",body:{rows:[i]}}),u=l[0];if(!u)throw w(new Error("The row was not created."));return u},patchRow:async(o,i,l)=>(await s(`${a(o)}/rows/${encodeURIComponent(i)}`,{method:"PATCH",body:l})).updated,deleteRow:async(o,i)=>(await s(`/${encodeURIComponent(o)}/${encodeURIComponent(i)}`,{method:"DELETE"})).deleted,listFiles:async()=>(await v(`${t}${H}/tables/files/rows?limit=200`,await r())).rows.map(i=>({id:i.rowId,filename:String(i.data.filename??""),source:String(i.data.source??"client"),campaign:String(i.data.campaign??""),size:typeof i.data.size=="number"?i.data.size:0,createdAt:i.createdAt})),uploadFile:async(o,i)=>{let l=new Uint8Array(await o.arrayBuffer());return await s("/files",{method:"POST",body:{filename:o.name,mime:o.type||"application/octet-stream",data:Bt(l),...i===void 0?{}:{message:i}}})},fileLink:async o=>await v(`${t}${H}/files/${encodeURIComponent(o)}/url`,await r()),deleteFile:async o=>(await s(`/files/${encodeURIComponent(o)}`,{method:"DELETE"})).deleted,listDocuments:async()=>(await v(`${t}${H}/documents`,await r())).documents,readDocument:async o=>(await v(`${t}${H}/documents/${encodeURIComponent(o)}`,await r())).document,saveDocument:async(o,i)=>await s(`/documents/${encodeURIComponent(o)}`,{method:"PATCH",body:i})}};var jt=/\/+$/,Gt="/api/v1/end-user",Ze=e=>{let t=e.baseUrl.replace(jt,""),n=async(r,s)=>{let a;try{a=await fetch(`${t}${Gt}${r}`,s===void 0?{}:{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(s)})}catch(o){throw w(o)}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(o){throw w(o)}};return{listProducts:async()=>{let r=await n(`/shop/products?publishable_key=${encodeURIComponent(e.publishableKey)}`);return{products:r.products.map(s=>({...s,currency:typeof s.currency=="string"?s.currency:""})),truncated:r.truncated===!0,enquiryForm:Array.isArray(r.enquiryForm)?r.enquiryForm:[]}},apply:async r=>await n("/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}:{}})}};var Qt=new Set(["buy","ask"]);function et(e){return Qt.has(e.mode)?e.mode:"ask"}var zt={kind:"quoted"};function L(e,t){if(!t)return e.toLocaleString();if(t.toLowerCase()==="credits")return`${e.toLocaleString()} ${e===1?"credit":"credits"}`;let n=Number.isInteger(e)?0:2;try{return new Intl.NumberFormat(void 0,{style:"currency",currency:t,minimumFractionDigits:n,maximumFractionDigits:n}).format(e)}catch{return`${t} ${e.toLocaleString()}`}}function tt(e,t){let n=/^[a-z]+$/i.test(t)&&!t.endsWith("s")?"s":"";return`${e.toLocaleString()} ${t}${n}`}function Me(e,t){return e.kind==="quoted"?"Priced on enquiry":e.kind==="flat"?L(e.price,t):`${L(e.unitPrice,t)} per ${e.unitStep===1?e.unit:tt(e.unitStep,e.unit)}`}function nt(e){let t=e.currency,n=e.pricing;if(n.kind!=="variants")return Me(n,t);let r=n.variants.map(s=>s.price).filter(s=>typeof s=="number");return r.length>0?`From ${L(Math.min(...r),t)}`:"Priced on enquiry"}function rt(e,t){if(e.kind!=="variants")return e;let n=e.variants.find(r=>r.name===t);return typeof n?.price=="number"?{kind:"flat",price:n.price}:zt}function ot(e,t){return e.kind==="flat"?e.price:e.kind==="per_unit"?e.unitPrice*Math.ceil(t/Math.max(e.unitStep,1)):null}function st(e,t){let n=t.kind==="per_unit"?Math.max(t.unitStep,1):1;return{min:Math.max(e.minQty??n,n),max:e.maxQty??null,step:n}}function it(e,t){let n=e.variants?.find(r=>r.name===t);return n&&n.includes.length>0?n.includes:e.includes}function at(e,t){let n=[];for(let r of e){let s=t(r).trim();s&&!n.includes(s)&&n.push(s)}return n}function lt(e,t,n,r){let s=t?`${e.name} \u2014 ${t}`:e.name,a=n.kind==="per_unit"?`, ${tt(r,n.unit)}`:"";return`I'd like to buy ${s}${a}. How do I go ahead?`}function ut(e){return e?(e&&typeof e=="object"&&"error"in e?String(e.error):"")==="rate_limited"?"That's a lot of looking at once \u2014 give it a moment, then reload.":"The shop isn't loading right now. Please try again shortly.":null}var A=require("react"),dt=e=>{let[t,n]=(0,A.useState)(null),[r,s]=(0,A.useState)(!0),[a,o]=(0,A.useState)(null),i=(0,A.useCallback)(async()=>{try{n(await e.wallet()),o(null)}catch{o("Couldn't read your balance just now.")}finally{s(!1)}},[e]),l=(0,A.useCallback)(()=>{i().catch(()=>{})},[i]);return(0,A.useEffect)(()=>(l(),window.addEventListener("focus",l),()=>{window.removeEventListener("focus",l)}),[l]),{wallet:t,loading:r,failure:a,refresh:l}};var C=require("react"),Jt=e=>e&&typeof e=="object"&&typeof e.error=="string"?e.error:e instanceof Error?e.message:"shop_unavailable",pt=e=>{let[t,n]=(0,C.useState)([]),[r,s]=(0,C.useState)([]),[a,o]=(0,C.useState)(!1),[i,l]=(0,C.useState)(!0),[u,d]=(0,C.useState)(null),[m,p]=(0,C.useState)(0);(0,C.useEffect)(()=>{let g=!0;return l(!0),e.listProducts().then(y=>{g&&(n(y.products),s(y.enquiryForm),o(y.truncated),d(null))}).catch(y=>{g&&d(Jt(y))}).finally(()=>{g&&l(!1)}),()=>{g=!1}},[e,m]);let c=(0,C.useCallback)(()=>p(g=>g+1),[]);return{products:t,enquiryForm:r,truncated:a,loading:i,error:u,reload:c}};var k=require("react"),ct="greeting";function He(e,t){if(e.some(a=>a.id===t.id))return e;let n=e.filter(a=>a.id!==ct),r=a=>a.author==="client"==(t.author==="client");return[...n.filter(a=>!(a.pending&&r(a)&&a.text===t.text)),t]}var mt=(e,t)=>{let[n,r]=(0,k.useState)([]),[s,a]=(0,k.useState)(""),[o,i]=(0,k.useState)(!1),[l,u]=(0,k.useState)(null),d=(0,k.useRef)(0),m=t?.pollMs??2e3;(0,k.useEffect)(()=>{let c=!0;return e.getInfo().then(g=>{c&&g.greeting&&r(y=>y.length===0?[{id:ct,cursor:"",author:"agent",text:g.greeting}]:y)}).catch(()=>{}),()=>{c=!1}},[e]),(0,k.useEffect)(()=>e.subscribe?.({onMessage:c=>r(g=>He(g,c)),onError:c=>u(c.error),onHealthy:()=>u(null)},{intervalMs:m}),[e,m]);let p=(0,k.useCallback)(()=>{let c=s.trim();if(!c||o)return;a(""),u(null),i(!0),d.current+=1;let g=`pending-${d.current}`,y={id:g,cursor:"",author:"client",text:c,pending:!0};r(b=>[...b,y]),e.sendMessage(c).then(b=>{i(!1),b.reply.trim()&&r(f=>f.some(I=>!I.pending&&I.author!=="client"&&I.text===b.reply)?f:(d.current+=1,[...f,{id:`pending-agent-${d.current}`,cursor:"",author:"agent",text:b.reply,pending:!0}]))}).catch(b=>{u(b instanceof Error?b.message:"send_failed"),i(!1),r(R=>R.filter(f=>f.id!==g)),a(R=>R||c)})},[s,o,e]);return{messages:n,input:s,setInput:a,send:p,sending:o,error:l}};0&&(module.exports={Chat,CreditRefused,GRID_COLS,GRID_MAX_COLS,GRID_MAX_ROWS,HolaProvider,InsufficientCredits,PortalConflict,QUOTE_BALANCE_LABEL,QUOTE_DEPOSIT_LABEL,bandOfKind,bandOfType,buyRequestText,cellValue,createApiTransport,createHolaClient,createPortalCredits,createPortalData,createPortalShop,createWidgetTransport,creditsOfMoney,deliverableCellText,deliverableCellValues,deliverableStatus,deriveFields,emptyTableResponses,facetValues,footprintOf,footprintWith,formatDeliverableDate,groupDeliverableVersions,includesFor,inferSpec,isDeliverableChecked,mergeMessage,modeOf,money,normalizeDeliverableColType,normalizeDeliverableItem,orderBilling,parseDashboardSpec,parseDeliverableItems,parseDeliverableTable,parseTableResponses,paymentAsked,paymentPayMethods,placeWidgets,priceFor,priceLabel,publishedVersionOf,quantityRange,quoteSchedule,renderModel,setResponse,setTableReview,shelfPriceLabel,shelfProblem,splitLayout,textDeltaOf,thinkingDeltaOf,toolEventOf,totalFor,useArtifactUrl,useChat,useCredits,useHolaClient,useShop,useThread});
package/dist/index.d.cts CHANGED
@@ -548,12 +548,21 @@ tableVerdict?: "" | "accepted" | "revise"): DeliverableReviewState;
548
548
  * version the team delivered would auto-appear to the client before it was published. */
549
549
  declare function publishedVersionOf(data: Record<string, unknown>): number;
550
550
 
551
- /** A column type. `select` is an open enum edited as text; the rest drive how a cell reads. */
552
- type DeliverableColType = "text" | "number" | "url" | "date" | "boolean" | "select";
551
+ /** A column type.
552
+ *
553
+ * KEPT IN STEP WITH THE SERVICE-SLICE VOCABULARY on purpose: this is the same primitive, authored
554
+ * in the same grid with the same components, and a type the operator can pick on one and not the
555
+ * other is a column that changes meaning depending on where it was made. Widening it is a release
556
+ * — a tenant App pins its copy of this package — so the reader below stays tolerant and anything
557
+ * it does not recognise still lands as `text` rather than throwing. */
558
+ type DeliverableColType = "text" | "number" | "url" | "date" | "boolean" | "select" | "multi_select";
553
559
  type DeliverableColumn = {
554
560
  key: string;
555
561
  label: string;
556
562
  type: DeliverableColType;
563
+ /** The closed vocabulary for a `select` / `multi_select`. Absent or empty = an OPEN enum, which is
564
+ * what every select was before this existed and what they all still are on older payloads. */
565
+ options?: string[];
557
566
  /** The customer may fill this column in from their portal — their values live in the deliverable's
558
567
  * `responses`, layered over the operator's cells. Absent = read-only (the default). */
559
568
  clientEditable?: boolean;
@@ -576,6 +585,14 @@ declare function normalizeDeliverableColType(t: unknown): DeliverableColType;
576
585
  declare function parseDeliverableTable(value: string): DeliverableTable | null;
577
586
  /** A cell value as display text (a stored null/undefined reads as empty). */
578
587
  declare function deliverableCellText(v: unknown): string;
588
+ /** The members of a `multi_select` cell.
589
+ *
590
+ * Stored as a JSON array so the members stay separable — a joined string reads back as one value
591
+ * and nothing downstream can tell where one ends and the next begins. Tolerant of the
592
+ * comma-separated form a person types and of a bare single value, because both reach the column by
593
+ * ordinary means, and an App on an OLDER copy of this package reads such a cell as plain text: it
594
+ * will show the raw JSON rather than chips, which is why this is a release and not an edit. */
595
+ declare function deliverableCellValues(v: unknown): string[];
579
596
  /** Whether a `boolean` cell is checked — tolerant of a real boolean or the string forms it was stored
580
597
  * as across versions. */
581
598
  declare function isDeliverableChecked(v: unknown): boolean;
@@ -627,6 +644,37 @@ declare class CreditRefused extends Error {
627
644
  readonly status: number;
628
645
  constructor(code: string, message: string, status: number);
629
646
  }
647
+ /**
648
+ * "You cannot cover this" — carrying the three numbers that make it a QUOTE rather than a refusal.
649
+ *
650
+ * A SUBCLASS, not a second class, and that is load-bearing: every caller in every portal already
651
+ * branches on `instanceof CreditRefused` and reads `.code`, and a sibling class would fall out of
652
+ * all of them at once — the exact failure the comment above `CreditRefused` warns about, arriving
653
+ * from the other direction. Anything that handled the refusal before goes on handling it; the three
654
+ * numbers are additive.
655
+ *
656
+ * `short` is `credits - balance`, computed server-side, because the two figures it is derived from
657
+ * are read there under the same lock the debit takes. A portal recomputing it from a balance it
658
+ * fetched a minute ago would show a shortfall that has already been topped up.
659
+ *
660
+ * Minted ONLY when the server actually sent the numbers. Two surfaces answer 402
661
+ * `insufficient_credits` — settling a bill and buying from the shelf — and only the first sends
662
+ * them, so a shop refusal stays a plain `CreditRefused` rather than one carrying three zeros
663
+ * dressed as facts.
664
+ */
665
+ declare class InsufficientCredits extends CreditRefused {
666
+ /** What the line costs, in credits. ROUNDED UP: see `creditsOfMoney`. */
667
+ readonly credits: number;
668
+ /** What they have right now. */
669
+ readonly balance: number;
670
+ /** The difference, and the size of the top-up that would fix it. */
671
+ readonly short: number;
672
+ constructor(message: string, figures: {
673
+ credits: number;
674
+ balance: number;
675
+ short: number;
676
+ });
677
+ }
630
678
  /** One pack on sale: what it grants, and what it costs in real money.
631
679
  *
632
680
  * `credits` and `price` are different units and the pair is the point — 500 credits for $99 is a
@@ -985,6 +1033,35 @@ type PortalCredits = {
985
1033
  claimed: boolean;
986
1034
  status: string;
987
1035
  }>;
1036
+ /**
1037
+ * Settle one payment line out of the customer's own prepaid balance.
1038
+ *
1039
+ * THE THIRD DOOR ONTO ONE TRANSITION, and the only self-service one that works. A transfer
1040
+ * settles in a bank this product cannot see and needs an operator to confirm it; `pay_url` has no
1041
+ * writer anywhere, so the card button never renders. This one closes itself — the balance moves,
1042
+ * the line flips to paid, the work starts — and it does NOT invent a second notion of paid:
1043
+ * `payments.status` stays the one definition, which is what keeps the console's badge, the
1044
+ * worklist and this page telling one story about the same order.
1045
+ *
1046
+ * `paymentId` names a LINE, not an order. That is what lets somebody pay the deposit today and
1047
+ * the balance on delivery, and it is what the server's idempotency key is cut from: a double tap
1048
+ * on a slow connection takes the credits once.
1049
+ *
1050
+ * Show the customer `creditsOfMoney(line.amount, wallet.bookRate)` before they press it. The
1051
+ * rounding is up, it is applied server-side, and a page that only ever showed the money figure
1052
+ * would take a credit more than the number on screen.
1053
+ *
1054
+ * REFUSALS, and each wants a different sentence:
1055
+ *
1056
+ * - `InsufficientCredits` (402) — they cannot cover it. Not a fault: it is a quote for a top-up,
1057
+ * carrying what the line costs, what they hold and the difference. The other ways to pay are
1058
+ * still on screen and must stay there.
1059
+ * - `CreditRefused` with `credits_not_sold` (409) — this company does not price in credits at
1060
+ * all. A portal should never have offered the option; treat it as the wallet being stale.
1061
+ * - `CreditRefused` with `rate_limited` (429) — too many in a row. Wait.
1062
+ * - Anything else is ours and the credits are safe; the sentence is the server's.
1063
+ */
1064
+ payWithCredits(paymentId: string): Promise<PaidWithCredits>;
988
1065
  };
989
1066
  /** One line on a customer's bill. Mirrors the projection holaapp-backend's `customerPayment`
990
1067
  * emits — an allowlist, not the stored row. */
@@ -998,6 +1075,19 @@ type CustomerPayment = {
998
1075
  /** Anything the server could not read as `paid` comes back as `due`. */
999
1076
  status: "due" | "paid";
1000
1077
  method: string;
1078
+ /**
1079
+ * Which doors THIS line opens — `credits`, `transfer`, or both.
1080
+ *
1081
+ * A LINE AND ITS ORDER CAN DISAGREE, on purpose: a company takes the deposit by transfer and lets
1082
+ * the balance come off a prepaid balance, or the reverse. So the restriction is asked of the line
1083
+ * first and the order second.
1084
+ *
1085
+ * EMPTY OR ABSENT IS NOT "NONE" — it means this line says nothing and the order's own answer
1086
+ * applies, which empty in its turn means everything the company offers. Absent also covers a
1087
+ * portal pinned to this SDK talking to a backend older than the field, and reads the same way it
1088
+ * did then. Resolve it with `paymentPayMethods`, never by hand.
1089
+ */
1090
+ payMethods?: string[];
1001
1091
  dueDate: string;
1002
1092
  paidAt: string;
1003
1093
  /** Where to pay this online, when the money can be taken that way. Empty for a bank transfer,
@@ -1008,7 +1098,53 @@ type CustomerPayment = {
1008
1098
  * money is what changes `status`. */
1009
1099
  claimedAt: string;
1010
1100
  reference: string;
1101
+ /**
1102
+ * Whether the customer is being ASKED for this line right now, as opposed to merely shown it as
1103
+ * part of the schedule they agreed to.
1104
+ *
1105
+ * RAISED IS NOT OWED. The whole schedule is written the moment the order is — that is what makes
1106
+ * the contract complete and the terms visible — but a balance falling due ON DELIVERY is not owed
1107
+ * while the work is still being done. With only `status` to go on, a portal drew a bank-transfer
1108
+ * form for the balance the instant the deposit landed: account numbers and an "I've sent the
1109
+ * transfer" button for money nobody was owed yet.
1110
+ *
1111
+ * DERIVED SERVER-SIDE, and the rule stays there. It is structural (which label, and whether the
1112
+ * operator has requested it) rather than a stamp, and a second copy of it here is a second copy
1113
+ * that can disagree with the operator's console about what a customer owes. Read it, never
1114
+ * recompute it — `paymentAsked` below is the whole of the reading.
1115
+ *
1116
+ * OPTIONAL because a portal is pinned to a published SDK and talks to whatever backend the
1117
+ * operator is on. Absent means the backend predates the field; see `paymentAsked` for why that
1118
+ * has to read as asked rather than as scheduled.
1119
+ */
1120
+ asked?: boolean;
1011
1121
  };
1122
+ /**
1123
+ * Whether this line has a pay surface — the transfer details, the credits button, the claim form.
1124
+ *
1125
+ * ABSENT READS AS ASKED, and the direction is not a coin toss. A backend older than the field sends
1126
+ * nothing, and reading that as "scheduled" would take the pay surface off every line in the portal
1127
+ * at once — a customer who owes a deposit with no way to pay it, which is worse than the bug
1128
+ * `asked` was added to fix. Reading it as asked reproduces exactly the behaviour that backend
1129
+ * already has.
1130
+ *
1131
+ * A settled line is never asked for, whatever the flag says: the server agrees, and stating it here
1132
+ * as well means a portal cannot draw a payment form over a receipt because one stale row disagreed.
1133
+ */
1134
+ declare const paymentAsked: (p: CustomerPayment) => boolean;
1135
+ /**
1136
+ * Which ways this one line may actually be paid — the line's own restriction, else the order's.
1137
+ *
1138
+ * TWO FALLBACKS, BOTH PERMISSIVE, and that direction is the whole of it. Empty on the line means
1139
+ * "the order decides", empty on the order means "everything we offer", and reading either as
1140
+ * "nothing" would take every door away from every bill written before the field existed — a
1141
+ * customer holding an invoice with no way to settle it.
1142
+ *
1143
+ * It stays a FILTER at the end of it: the caller intersects this with what the company has actually
1144
+ * set up, because a method named here that no bank details or credit shelf stands behind shows
1145
+ * nothing at all.
1146
+ */
1147
+ declare const paymentPayMethods: (p: CustomerPayment, orderMethods: readonly string[]) => string[];
1012
1148
  /** How to pay this company by transfer. Null when the operator has published nothing you could
1013
1149
  * actually send money to — no details is not an empty form, it is no transfer option. */
1014
1150
  type TransferDetails = {
@@ -1019,6 +1155,56 @@ type TransferDetails = {
1019
1155
  swift: string;
1020
1156
  note: string;
1021
1157
  };
1158
+ /**
1159
+ * What settling a bill from the balance came back as.
1160
+ *
1161
+ * BOTH ARMS SAY `paid: true`, and that is the whole shape of this type. The second one is the line
1162
+ * having already been settled — by an earlier tap of the same button on a slow connection, by the
1163
+ * operator marking a transfer while the customer was looking at the page, or by a retry whose first
1164
+ * attempt got further than the caller saw. From the customer's side the thing they wanted is TRUE,
1165
+ * so it is not an error and must not be drawn as one; a portal that showed "couldn't pay that" over
1166
+ * a bill that is paid would send somebody to pay it a second time.
1167
+ *
1168
+ * The zeros on that arm are LITERAL because they are not readings. Nothing was taken (`credits: 0`)
1169
+ * and nobody looked at the balance (`balance: 0`) — the row was already settled before a debit was
1170
+ * attempted. Re-read the wallet rather than printing that 0 at anybody.
1171
+ */
1172
+ type PaidWithCredits =
1173
+ /** Settled just now. `balance` is what is LEFT, after this line. */
1174
+ {
1175
+ paid: true;
1176
+ alreadyPaid?: false;
1177
+ credits: number;
1178
+ balance: number;
1179
+ }
1180
+ /** It was already settled. Neither number is a reading — see above. */
1181
+ | {
1182
+ paid: true;
1183
+ alreadyPaid: true;
1184
+ credits: 0;
1185
+ balance: 0;
1186
+ };
1187
+ /**
1188
+ * What a MONEY figure costs in credits, at the company's book rate.
1189
+ *
1190
+ * A MIRROR of the server's `creditsOfMoney`, deliberately, and here for the same reason
1191
+ * `quoteSchedule` is: the customer has to be shown the credit figure BEFORE they press the button,
1192
+ * and the only figure worth showing is the one that will actually be taken.
1193
+ *
1194
+ * IT ROUNDS UP, and that is why showing it matters rather than being a nicety. The ledger moves in
1195
+ * whole credits, so a $10.50 line at rate 1 costs 11 — more than the exact conversion of the money
1196
+ * on the row. Up costs the customer at most one credit and never leaves the operator short, which
1197
+ * is the only direction that is safe to apply without asking; what makes it HONEST is that they
1198
+ * read the number first.
1199
+ *
1200
+ * Only good for a line that is still due. A settled one carries what was actually taken, stamped on
1201
+ * the row at the moment it was paid — the book rate is a setting an operator can change, and a
1202
+ * receipt re-derived through today's rate is a receipt that rewrites itself.
1203
+ */
1204
+ declare const creditsOfMoney: (amount: number,
1205
+ /** Credits per one unit of currency — `CreditWallet.bookRate`. Absent or nonsense reads as 1,
1206
+ * which is what `normaliseBookRate` does server-side. */
1207
+ bookRate?: number) => number;
1022
1208
  /** Where one order stands financially, and therefore whether it has started. */
1023
1209
  type OrderBilling = {
1024
1210
  /** The agreed contract value. 0 when nobody priced it — not the same as free, which is what
@@ -1029,12 +1215,33 @@ type OrderBilling = {
1029
1215
  * record of what was billed, not a derivation of the contract. */
1030
1216
  billed: number;
1031
1217
  paid: number;
1032
- /** Still owed. Falls back to the whole contract value when the order is priced but no line has
1033
- * been raised yet — the ordinary case the moment an order is written, where the customer is owed
1034
- * a figure rather than a shrug. Never negative. */
1218
+ /**
1219
+ * What the customer is being ASKED FOR right now. Never negative.
1220
+ *
1221
+ * NOT "everything raised and unsettled", which is the figure this used to be and is a bill the
1222
+ * customer does not owe: a deposit paid and a balance falling due on delivery came to "$4,000
1223
+ * due" over an order whose work was under way and whose next payment nobody had requested. Only
1224
+ * `asked` lines are counted — see `CustomerPayment.asked`.
1225
+ *
1226
+ * Falls back to the whole contract value when the order is priced and NOTHING has been raised
1227
+ * yet — the ordinary case the moment an order is written, where the customer is owed a figure
1228
+ * rather than a shrug. Deliberately not applied when lines exist but none is asked for: that is
1229
+ * a real state (all settled, or the rest merely scheduled) and answering it with the contract
1230
+ * value would re-bill a paid order.
1231
+ */
1035
1232
  due: number;
1036
- /** The lines, what is owed first. */
1233
+ /** Raised, unsettled, and NOT being asked for yet — the rest of the schedule. Listed so a
1234
+ * customer can see the terms they agreed to; never given a payment form. */
1235
+ scheduled: number;
1236
+ /** Every line, in SCHEDULE order: the deposit, then any milestones, then the balance — settled
1237
+ * or not. A bill's history reads forwards; what is owed *now* is `asked`, not a sort. */
1037
1238
  lines: CustomerPayment[];
1239
+ /** The lines with a pay surface: unsettled and asked for, in the order above. What a portal draws
1240
+ * a transfer form, a credits button or a claim under — and nothing else. */
1241
+ asked: CustomerPayment[];
1242
+ /** Raised, unsettled, and merely COMING. Listed with their dates and no way to pay them: asking
1243
+ * for money against work nobody has handed over is the bug `asked` exists to prevent. */
1244
+ upcoming: CustomerPayment[];
1038
1245
  /**
1039
1246
  * Whether the work is waiting on money — and so has not started.
1040
1247
  *
@@ -1046,14 +1253,6 @@ type OrderBilling = {
1046
1253
  */
1047
1254
  awaitingPayment: boolean;
1048
1255
  };
1049
- /**
1050
- * Fold an order's payment lines into where it stands.
1051
- *
1052
- * In the SDK rather than in each portal for the reason the whole of this file is: every portal that
1053
- * shows a bill needs exactly this, and the second one to write it by hand would inherit nothing the
1054
- * first one learned. Pure, so the arithmetic that decides whether somebody is told "this hasn't
1055
- * started" is testable without a server.
1056
- */
1057
1256
  declare const orderBilling: (order: {
1058
1257
  value: number;
1059
1258
  }, all: CustomerPayment[], orderId: string) => OrderBilling;
@@ -1405,4 +1604,4 @@ declare const useThread: (client: HolaClient, options?: {
1405
1604
  pollMs?: number;
1406
1605
  }) => UseThread;
1407
1606
 
1408
- export { type Agg, type ApiTransportConfig, type Band, type ChartView, Chat, type ChatMessage, type ChosenPrice, type CreateHolaClientOptions, type CreditEntry, type CreditHistory, type CreditPack, CreditRefused, type CreditTotals, type CreditWallet, type CustomerPayment, 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 InquiryQuote, type OrderBilling, type PendingTopup, type PlacedWidget, type Point, PortalConflict, type PortalCredits, type PortalData, type PortalDocument, type PortalDocumentSummary, type PortalField, type PortalFile, type PortalRow, type PortalRowAuthor, type PortalRowPage, type PortalShop, type PortalShopConfig, type PortalTable, type Purchased, QUOTE_BALANCE_LABEL, QUOTE_DEPOSIT_LABEL, type QuoteScheduleLine, type QuoteTerms, type QuotedLine, type ResolvedWidget, type SeriesWidget, type ShopApplication, type ShopApplyResult, type ShopFormField, 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 TopupStarted, type TransferDetails, type UseChat, type UseCredits, type UseShop, type UseThread, type Widget, type WidgetTransportConfig, type WidgetType, bandOfKind, bandOfType, buyRequestText, cellValue, createApiTransport, createHolaClient, createPortalCredits, createPortalData, createPortalShop, createWidgetTransport, deliverableCellText, deliverableStatus, deriveFields, emptyTableResponses, facetValues, footprintOf, footprintWith, formatDeliverableDate, groupDeliverableVersions, includesFor, inferSpec, isDeliverableChecked, mergeMessage, modeOf, money, normalizeDeliverableColType, normalizeDeliverableItem, orderBilling, parseDashboardSpec, parseDeliverableItems, parseDeliverableTable, parseTableResponses, placeWidgets, priceFor, priceLabel, publishedVersionOf, quantityRange, quoteSchedule, renderModel, setResponse, setTableReview, shelfPriceLabel, shelfProblem, splitLayout, textDeltaOf, thinkingDeltaOf, toolEventOf, totalFor, useArtifactUrl, useChat, useCredits, useHolaClient, useShop, useThread };
1607
+ export { type Agg, type ApiTransportConfig, type Band, type ChartView, Chat, type ChatMessage, type ChosenPrice, type CreateHolaClientOptions, type CreditEntry, type CreditHistory, type CreditPack, CreditRefused, type CreditTotals, type CreditWallet, type CustomerPayment, 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 InquiryQuote, InsufficientCredits, type OrderBilling, type PaidWithCredits, type PendingTopup, type PlacedWidget, type Point, PortalConflict, type PortalCredits, type PortalData, type PortalDocument, type PortalDocumentSummary, type PortalField, type PortalFile, type PortalRow, type PortalRowAuthor, type PortalRowPage, type PortalShop, type PortalShopConfig, type PortalTable, type Purchased, QUOTE_BALANCE_LABEL, QUOTE_DEPOSIT_LABEL, type QuoteScheduleLine, type QuoteTerms, type QuotedLine, type ResolvedWidget, type SeriesWidget, type ShopApplication, type ShopApplyResult, type ShopFormField, 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 TopupStarted, type TransferDetails, type UseChat, type UseCredits, type UseShop, type UseThread, type Widget, type WidgetTransportConfig, type WidgetType, bandOfKind, bandOfType, buyRequestText, cellValue, createApiTransport, createHolaClient, createPortalCredits, createPortalData, createPortalShop, createWidgetTransport, creditsOfMoney, deliverableCellText, deliverableCellValues, deliverableStatus, deriveFields, emptyTableResponses, facetValues, footprintOf, footprintWith, formatDeliverableDate, groupDeliverableVersions, includesFor, inferSpec, isDeliverableChecked, mergeMessage, modeOf, money, normalizeDeliverableColType, normalizeDeliverableItem, orderBilling, parseDashboardSpec, parseDeliverableItems, parseDeliverableTable, parseTableResponses, paymentAsked, paymentPayMethods, placeWidgets, priceFor, priceLabel, publishedVersionOf, quantityRange, quoteSchedule, renderModel, setResponse, setTableReview, shelfPriceLabel, shelfProblem, splitLayout, textDeltaOf, thinkingDeltaOf, toolEventOf, totalFor, useArtifactUrl, useChat, useCredits, useHolaClient, useShop, useThread };
package/dist/index.d.ts CHANGED
@@ -548,12 +548,21 @@ tableVerdict?: "" | "accepted" | "revise"): DeliverableReviewState;
548
548
  * version the team delivered would auto-appear to the client before it was published. */
549
549
  declare function publishedVersionOf(data: Record<string, unknown>): number;
550
550
 
551
- /** A column type. `select` is an open enum edited as text; the rest drive how a cell reads. */
552
- type DeliverableColType = "text" | "number" | "url" | "date" | "boolean" | "select";
551
+ /** A column type.
552
+ *
553
+ * KEPT IN STEP WITH THE SERVICE-SLICE VOCABULARY on purpose: this is the same primitive, authored
554
+ * in the same grid with the same components, and a type the operator can pick on one and not the
555
+ * other is a column that changes meaning depending on where it was made. Widening it is a release
556
+ * — a tenant App pins its copy of this package — so the reader below stays tolerant and anything
557
+ * it does not recognise still lands as `text` rather than throwing. */
558
+ type DeliverableColType = "text" | "number" | "url" | "date" | "boolean" | "select" | "multi_select";
553
559
  type DeliverableColumn = {
554
560
  key: string;
555
561
  label: string;
556
562
  type: DeliverableColType;
563
+ /** The closed vocabulary for a `select` / `multi_select`. Absent or empty = an OPEN enum, which is
564
+ * what every select was before this existed and what they all still are on older payloads. */
565
+ options?: string[];
557
566
  /** The customer may fill this column in from their portal — their values live in the deliverable's
558
567
  * `responses`, layered over the operator's cells. Absent = read-only (the default). */
559
568
  clientEditable?: boolean;
@@ -576,6 +585,14 @@ declare function normalizeDeliverableColType(t: unknown): DeliverableColType;
576
585
  declare function parseDeliverableTable(value: string): DeliverableTable | null;
577
586
  /** A cell value as display text (a stored null/undefined reads as empty). */
578
587
  declare function deliverableCellText(v: unknown): string;
588
+ /** The members of a `multi_select` cell.
589
+ *
590
+ * Stored as a JSON array so the members stay separable — a joined string reads back as one value
591
+ * and nothing downstream can tell where one ends and the next begins. Tolerant of the
592
+ * comma-separated form a person types and of a bare single value, because both reach the column by
593
+ * ordinary means, and an App on an OLDER copy of this package reads such a cell as plain text: it
594
+ * will show the raw JSON rather than chips, which is why this is a release and not an edit. */
595
+ declare function deliverableCellValues(v: unknown): string[];
579
596
  /** Whether a `boolean` cell is checked — tolerant of a real boolean or the string forms it was stored
580
597
  * as across versions. */
581
598
  declare function isDeliverableChecked(v: unknown): boolean;
@@ -627,6 +644,37 @@ declare class CreditRefused extends Error {
627
644
  readonly status: number;
628
645
  constructor(code: string, message: string, status: number);
629
646
  }
647
+ /**
648
+ * "You cannot cover this" — carrying the three numbers that make it a QUOTE rather than a refusal.
649
+ *
650
+ * A SUBCLASS, not a second class, and that is load-bearing: every caller in every portal already
651
+ * branches on `instanceof CreditRefused` and reads `.code`, and a sibling class would fall out of
652
+ * all of them at once — the exact failure the comment above `CreditRefused` warns about, arriving
653
+ * from the other direction. Anything that handled the refusal before goes on handling it; the three
654
+ * numbers are additive.
655
+ *
656
+ * `short` is `credits - balance`, computed server-side, because the two figures it is derived from
657
+ * are read there under the same lock the debit takes. A portal recomputing it from a balance it
658
+ * fetched a minute ago would show a shortfall that has already been topped up.
659
+ *
660
+ * Minted ONLY when the server actually sent the numbers. Two surfaces answer 402
661
+ * `insufficient_credits` — settling a bill and buying from the shelf — and only the first sends
662
+ * them, so a shop refusal stays a plain `CreditRefused` rather than one carrying three zeros
663
+ * dressed as facts.
664
+ */
665
+ declare class InsufficientCredits extends CreditRefused {
666
+ /** What the line costs, in credits. ROUNDED UP: see `creditsOfMoney`. */
667
+ readonly credits: number;
668
+ /** What they have right now. */
669
+ readonly balance: number;
670
+ /** The difference, and the size of the top-up that would fix it. */
671
+ readonly short: number;
672
+ constructor(message: string, figures: {
673
+ credits: number;
674
+ balance: number;
675
+ short: number;
676
+ });
677
+ }
630
678
  /** One pack on sale: what it grants, and what it costs in real money.
631
679
  *
632
680
  * `credits` and `price` are different units and the pair is the point — 500 credits for $99 is a
@@ -985,6 +1033,35 @@ type PortalCredits = {
985
1033
  claimed: boolean;
986
1034
  status: string;
987
1035
  }>;
1036
+ /**
1037
+ * Settle one payment line out of the customer's own prepaid balance.
1038
+ *
1039
+ * THE THIRD DOOR ONTO ONE TRANSITION, and the only self-service one that works. A transfer
1040
+ * settles in a bank this product cannot see and needs an operator to confirm it; `pay_url` has no
1041
+ * writer anywhere, so the card button never renders. This one closes itself — the balance moves,
1042
+ * the line flips to paid, the work starts — and it does NOT invent a second notion of paid:
1043
+ * `payments.status` stays the one definition, which is what keeps the console's badge, the
1044
+ * worklist and this page telling one story about the same order.
1045
+ *
1046
+ * `paymentId` names a LINE, not an order. That is what lets somebody pay the deposit today and
1047
+ * the balance on delivery, and it is what the server's idempotency key is cut from: a double tap
1048
+ * on a slow connection takes the credits once.
1049
+ *
1050
+ * Show the customer `creditsOfMoney(line.amount, wallet.bookRate)` before they press it. The
1051
+ * rounding is up, it is applied server-side, and a page that only ever showed the money figure
1052
+ * would take a credit more than the number on screen.
1053
+ *
1054
+ * REFUSALS, and each wants a different sentence:
1055
+ *
1056
+ * - `InsufficientCredits` (402) — they cannot cover it. Not a fault: it is a quote for a top-up,
1057
+ * carrying what the line costs, what they hold and the difference. The other ways to pay are
1058
+ * still on screen and must stay there.
1059
+ * - `CreditRefused` with `credits_not_sold` (409) — this company does not price in credits at
1060
+ * all. A portal should never have offered the option; treat it as the wallet being stale.
1061
+ * - `CreditRefused` with `rate_limited` (429) — too many in a row. Wait.
1062
+ * - Anything else is ours and the credits are safe; the sentence is the server's.
1063
+ */
1064
+ payWithCredits(paymentId: string): Promise<PaidWithCredits>;
988
1065
  };
989
1066
  /** One line on a customer's bill. Mirrors the projection holaapp-backend's `customerPayment`
990
1067
  * emits — an allowlist, not the stored row. */
@@ -998,6 +1075,19 @@ type CustomerPayment = {
998
1075
  /** Anything the server could not read as `paid` comes back as `due`. */
999
1076
  status: "due" | "paid";
1000
1077
  method: string;
1078
+ /**
1079
+ * Which doors THIS line opens — `credits`, `transfer`, or both.
1080
+ *
1081
+ * A LINE AND ITS ORDER CAN DISAGREE, on purpose: a company takes the deposit by transfer and lets
1082
+ * the balance come off a prepaid balance, or the reverse. So the restriction is asked of the line
1083
+ * first and the order second.
1084
+ *
1085
+ * EMPTY OR ABSENT IS NOT "NONE" — it means this line says nothing and the order's own answer
1086
+ * applies, which empty in its turn means everything the company offers. Absent also covers a
1087
+ * portal pinned to this SDK talking to a backend older than the field, and reads the same way it
1088
+ * did then. Resolve it with `paymentPayMethods`, never by hand.
1089
+ */
1090
+ payMethods?: string[];
1001
1091
  dueDate: string;
1002
1092
  paidAt: string;
1003
1093
  /** Where to pay this online, when the money can be taken that way. Empty for a bank transfer,
@@ -1008,7 +1098,53 @@ type CustomerPayment = {
1008
1098
  * money is what changes `status`. */
1009
1099
  claimedAt: string;
1010
1100
  reference: string;
1101
+ /**
1102
+ * Whether the customer is being ASKED for this line right now, as opposed to merely shown it as
1103
+ * part of the schedule they agreed to.
1104
+ *
1105
+ * RAISED IS NOT OWED. The whole schedule is written the moment the order is — that is what makes
1106
+ * the contract complete and the terms visible — but a balance falling due ON DELIVERY is not owed
1107
+ * while the work is still being done. With only `status` to go on, a portal drew a bank-transfer
1108
+ * form for the balance the instant the deposit landed: account numbers and an "I've sent the
1109
+ * transfer" button for money nobody was owed yet.
1110
+ *
1111
+ * DERIVED SERVER-SIDE, and the rule stays there. It is structural (which label, and whether the
1112
+ * operator has requested it) rather than a stamp, and a second copy of it here is a second copy
1113
+ * that can disagree with the operator's console about what a customer owes. Read it, never
1114
+ * recompute it — `paymentAsked` below is the whole of the reading.
1115
+ *
1116
+ * OPTIONAL because a portal is pinned to a published SDK and talks to whatever backend the
1117
+ * operator is on. Absent means the backend predates the field; see `paymentAsked` for why that
1118
+ * has to read as asked rather than as scheduled.
1119
+ */
1120
+ asked?: boolean;
1011
1121
  };
1122
+ /**
1123
+ * Whether this line has a pay surface — the transfer details, the credits button, the claim form.
1124
+ *
1125
+ * ABSENT READS AS ASKED, and the direction is not a coin toss. A backend older than the field sends
1126
+ * nothing, and reading that as "scheduled" would take the pay surface off every line in the portal
1127
+ * at once — a customer who owes a deposit with no way to pay it, which is worse than the bug
1128
+ * `asked` was added to fix. Reading it as asked reproduces exactly the behaviour that backend
1129
+ * already has.
1130
+ *
1131
+ * A settled line is never asked for, whatever the flag says: the server agrees, and stating it here
1132
+ * as well means a portal cannot draw a payment form over a receipt because one stale row disagreed.
1133
+ */
1134
+ declare const paymentAsked: (p: CustomerPayment) => boolean;
1135
+ /**
1136
+ * Which ways this one line may actually be paid — the line's own restriction, else the order's.
1137
+ *
1138
+ * TWO FALLBACKS, BOTH PERMISSIVE, and that direction is the whole of it. Empty on the line means
1139
+ * "the order decides", empty on the order means "everything we offer", and reading either as
1140
+ * "nothing" would take every door away from every bill written before the field existed — a
1141
+ * customer holding an invoice with no way to settle it.
1142
+ *
1143
+ * It stays a FILTER at the end of it: the caller intersects this with what the company has actually
1144
+ * set up, because a method named here that no bank details or credit shelf stands behind shows
1145
+ * nothing at all.
1146
+ */
1147
+ declare const paymentPayMethods: (p: CustomerPayment, orderMethods: readonly string[]) => string[];
1012
1148
  /** How to pay this company by transfer. Null when the operator has published nothing you could
1013
1149
  * actually send money to — no details is not an empty form, it is no transfer option. */
1014
1150
  type TransferDetails = {
@@ -1019,6 +1155,56 @@ type TransferDetails = {
1019
1155
  swift: string;
1020
1156
  note: string;
1021
1157
  };
1158
+ /**
1159
+ * What settling a bill from the balance came back as.
1160
+ *
1161
+ * BOTH ARMS SAY `paid: true`, and that is the whole shape of this type. The second one is the line
1162
+ * having already been settled — by an earlier tap of the same button on a slow connection, by the
1163
+ * operator marking a transfer while the customer was looking at the page, or by a retry whose first
1164
+ * attempt got further than the caller saw. From the customer's side the thing they wanted is TRUE,
1165
+ * so it is not an error and must not be drawn as one; a portal that showed "couldn't pay that" over
1166
+ * a bill that is paid would send somebody to pay it a second time.
1167
+ *
1168
+ * The zeros on that arm are LITERAL because they are not readings. Nothing was taken (`credits: 0`)
1169
+ * and nobody looked at the balance (`balance: 0`) — the row was already settled before a debit was
1170
+ * attempted. Re-read the wallet rather than printing that 0 at anybody.
1171
+ */
1172
+ type PaidWithCredits =
1173
+ /** Settled just now. `balance` is what is LEFT, after this line. */
1174
+ {
1175
+ paid: true;
1176
+ alreadyPaid?: false;
1177
+ credits: number;
1178
+ balance: number;
1179
+ }
1180
+ /** It was already settled. Neither number is a reading — see above. */
1181
+ | {
1182
+ paid: true;
1183
+ alreadyPaid: true;
1184
+ credits: 0;
1185
+ balance: 0;
1186
+ };
1187
+ /**
1188
+ * What a MONEY figure costs in credits, at the company's book rate.
1189
+ *
1190
+ * A MIRROR of the server's `creditsOfMoney`, deliberately, and here for the same reason
1191
+ * `quoteSchedule` is: the customer has to be shown the credit figure BEFORE they press the button,
1192
+ * and the only figure worth showing is the one that will actually be taken.
1193
+ *
1194
+ * IT ROUNDS UP, and that is why showing it matters rather than being a nicety. The ledger moves in
1195
+ * whole credits, so a $10.50 line at rate 1 costs 11 — more than the exact conversion of the money
1196
+ * on the row. Up costs the customer at most one credit and never leaves the operator short, which
1197
+ * is the only direction that is safe to apply without asking; what makes it HONEST is that they
1198
+ * read the number first.
1199
+ *
1200
+ * Only good for a line that is still due. A settled one carries what was actually taken, stamped on
1201
+ * the row at the moment it was paid — the book rate is a setting an operator can change, and a
1202
+ * receipt re-derived through today's rate is a receipt that rewrites itself.
1203
+ */
1204
+ declare const creditsOfMoney: (amount: number,
1205
+ /** Credits per one unit of currency — `CreditWallet.bookRate`. Absent or nonsense reads as 1,
1206
+ * which is what `normaliseBookRate` does server-side. */
1207
+ bookRate?: number) => number;
1022
1208
  /** Where one order stands financially, and therefore whether it has started. */
1023
1209
  type OrderBilling = {
1024
1210
  /** The agreed contract value. 0 when nobody priced it — not the same as free, which is what
@@ -1029,12 +1215,33 @@ type OrderBilling = {
1029
1215
  * record of what was billed, not a derivation of the contract. */
1030
1216
  billed: number;
1031
1217
  paid: number;
1032
- /** Still owed. Falls back to the whole contract value when the order is priced but no line has
1033
- * been raised yet — the ordinary case the moment an order is written, where the customer is owed
1034
- * a figure rather than a shrug. Never negative. */
1218
+ /**
1219
+ * What the customer is being ASKED FOR right now. Never negative.
1220
+ *
1221
+ * NOT "everything raised and unsettled", which is the figure this used to be and is a bill the
1222
+ * customer does not owe: a deposit paid and a balance falling due on delivery came to "$4,000
1223
+ * due" over an order whose work was under way and whose next payment nobody had requested. Only
1224
+ * `asked` lines are counted — see `CustomerPayment.asked`.
1225
+ *
1226
+ * Falls back to the whole contract value when the order is priced and NOTHING has been raised
1227
+ * yet — the ordinary case the moment an order is written, where the customer is owed a figure
1228
+ * rather than a shrug. Deliberately not applied when lines exist but none is asked for: that is
1229
+ * a real state (all settled, or the rest merely scheduled) and answering it with the contract
1230
+ * value would re-bill a paid order.
1231
+ */
1035
1232
  due: number;
1036
- /** The lines, what is owed first. */
1233
+ /** Raised, unsettled, and NOT being asked for yet — the rest of the schedule. Listed so a
1234
+ * customer can see the terms they agreed to; never given a payment form. */
1235
+ scheduled: number;
1236
+ /** Every line, in SCHEDULE order: the deposit, then any milestones, then the balance — settled
1237
+ * or not. A bill's history reads forwards; what is owed *now* is `asked`, not a sort. */
1037
1238
  lines: CustomerPayment[];
1239
+ /** The lines with a pay surface: unsettled and asked for, in the order above. What a portal draws
1240
+ * a transfer form, a credits button or a claim under — and nothing else. */
1241
+ asked: CustomerPayment[];
1242
+ /** Raised, unsettled, and merely COMING. Listed with their dates and no way to pay them: asking
1243
+ * for money against work nobody has handed over is the bug `asked` exists to prevent. */
1244
+ upcoming: CustomerPayment[];
1038
1245
  /**
1039
1246
  * Whether the work is waiting on money — and so has not started.
1040
1247
  *
@@ -1046,14 +1253,6 @@ type OrderBilling = {
1046
1253
  */
1047
1254
  awaitingPayment: boolean;
1048
1255
  };
1049
- /**
1050
- * Fold an order's payment lines into where it stands.
1051
- *
1052
- * In the SDK rather than in each portal for the reason the whole of this file is: every portal that
1053
- * shows a bill needs exactly this, and the second one to write it by hand would inherit nothing the
1054
- * first one learned. Pure, so the arithmetic that decides whether somebody is told "this hasn't
1055
- * started" is testable without a server.
1056
- */
1057
1256
  declare const orderBilling: (order: {
1058
1257
  value: number;
1059
1258
  }, all: CustomerPayment[], orderId: string) => OrderBilling;
@@ -1405,4 +1604,4 @@ declare const useThread: (client: HolaClient, options?: {
1405
1604
  pollMs?: number;
1406
1605
  }) => UseThread;
1407
1606
 
1408
- export { type Agg, type ApiTransportConfig, type Band, type ChartView, Chat, type ChatMessage, type ChosenPrice, type CreateHolaClientOptions, type CreditEntry, type CreditHistory, type CreditPack, CreditRefused, type CreditTotals, type CreditWallet, type CustomerPayment, 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 InquiryQuote, type OrderBilling, type PendingTopup, type PlacedWidget, type Point, PortalConflict, type PortalCredits, type PortalData, type PortalDocument, type PortalDocumentSummary, type PortalField, type PortalFile, type PortalRow, type PortalRowAuthor, type PortalRowPage, type PortalShop, type PortalShopConfig, type PortalTable, type Purchased, QUOTE_BALANCE_LABEL, QUOTE_DEPOSIT_LABEL, type QuoteScheduleLine, type QuoteTerms, type QuotedLine, type ResolvedWidget, type SeriesWidget, type ShopApplication, type ShopApplyResult, type ShopFormField, 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 TopupStarted, type TransferDetails, type UseChat, type UseCredits, type UseShop, type UseThread, type Widget, type WidgetTransportConfig, type WidgetType, bandOfKind, bandOfType, buyRequestText, cellValue, createApiTransport, createHolaClient, createPortalCredits, createPortalData, createPortalShop, createWidgetTransport, deliverableCellText, deliverableStatus, deriveFields, emptyTableResponses, facetValues, footprintOf, footprintWith, formatDeliverableDate, groupDeliverableVersions, includesFor, inferSpec, isDeliverableChecked, mergeMessage, modeOf, money, normalizeDeliverableColType, normalizeDeliverableItem, orderBilling, parseDashboardSpec, parseDeliverableItems, parseDeliverableTable, parseTableResponses, placeWidgets, priceFor, priceLabel, publishedVersionOf, quantityRange, quoteSchedule, renderModel, setResponse, setTableReview, shelfPriceLabel, shelfProblem, splitLayout, textDeltaOf, thinkingDeltaOf, toolEventOf, totalFor, useArtifactUrl, useChat, useCredits, useHolaClient, useShop, useThread };
1607
+ export { type Agg, type ApiTransportConfig, type Band, type ChartView, Chat, type ChatMessage, type ChosenPrice, type CreateHolaClientOptions, type CreditEntry, type CreditHistory, type CreditPack, CreditRefused, type CreditTotals, type CreditWallet, type CustomerPayment, 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 InquiryQuote, InsufficientCredits, type OrderBilling, type PaidWithCredits, type PendingTopup, type PlacedWidget, type Point, PortalConflict, type PortalCredits, type PortalData, type PortalDocument, type PortalDocumentSummary, type PortalField, type PortalFile, type PortalRow, type PortalRowAuthor, type PortalRowPage, type PortalShop, type PortalShopConfig, type PortalTable, type Purchased, QUOTE_BALANCE_LABEL, QUOTE_DEPOSIT_LABEL, type QuoteScheduleLine, type QuoteTerms, type QuotedLine, type ResolvedWidget, type SeriesWidget, type ShopApplication, type ShopApplyResult, type ShopFormField, 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 TopupStarted, type TransferDetails, type UseChat, type UseCredits, type UseShop, type UseThread, type Widget, type WidgetTransportConfig, type WidgetType, bandOfKind, bandOfType, buyRequestText, cellValue, createApiTransport, createHolaClient, createPortalCredits, createPortalData, createPortalShop, createWidgetTransport, creditsOfMoney, deliverableCellText, deliverableCellValues, deliverableStatus, deriveFields, emptyTableResponses, facetValues, footprintOf, footprintWith, formatDeliverableDate, groupDeliverableVersions, includesFor, inferSpec, isDeliverableChecked, mergeMessage, modeOf, money, normalizeDeliverableColType, normalizeDeliverableItem, orderBilling, parseDashboardSpec, parseDeliverableItems, parseDeliverableTable, parseTableResponses, paymentAsked, paymentPayMethods, placeWidgets, priceFor, priceLabel, publishedVersionOf, quantityRange, quoteSchedule, renderModel, setResponse, setTableReview, shelfPriceLabel, shelfProblem, splitLayout, textDeltaOf, thinkingDeltaOf, toolEventOf, totalFor, useArtifactUrl, useChat, useCredits, useHolaClient, useShop, useThread };
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  'use client'
2
- var te=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="message_update"?t.assistantMessageEvent??null:null},_=e=>{let t=te(e);return t?.type==="text_delta"&&typeof t.delta=="string"?t.delta:null},L=e=>{let t=te(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 Ne=/^ /,w=e=>{if(e&&typeof e=="object"){let t=e,n=typeof t.error=="string"?t.error:"request_failed";return typeof t.retryable=="boolean"?{error:n,retryable:t.retryable}:{error:n}}return{error:"request_failed"}},Be=e=>{let t="message",n=[];for(let r of e.split(`
3
- `))r.startsWith(":")||(r.startsWith("event:")?t=r.slice(6).trim():r.startsWith("data:")&&n.push(r.slice(5).replace(Ne,"")));return n.length>0?{event:t,data:n.join(`
4
- `)}:null},Ve=(e,t,n)=>{let r;try{r=JSON.parse(e.data)}catch{return}if(e.event==="session"){let s=r.sessionId;s&&(n(s),t.onSession?.(s));return}if(e.event==="turn_event"){t.onEvent?.(r);let s=_(r);s&&t.onText?.(s);let i=L(r);i&&t.onThinking?.(i);let o=U(r);o&&t.onTool?.(o);return}if(e.event==="chat_completed"){let s=r;n(s.sessionId),t.onComplete?.(s);return}e.event==="chat_error"&&t.onError?.(w(r))},S=async(e,t)=>{let n=await fetch(e,{headers:t});if(!n.ok)throw new Error(`hola: request failed (${n.status})`);return await n.json()},ne=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()},re=async(e,t,n,r)=>{let s=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body,signal:r});if(!(s.ok&&s.body)){t.onError?.({error:`stream_failed_${s.status}`});return}let i=s.body.getReader(),o=new TextDecoder,a="",l=()=>{let d=a.indexOf(`
2
+ var ae=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="message_update"?t.assistantMessageEvent??null:null},U=e=>{let t=ae(e);return t?.type==="text_delta"&&typeof t.delta=="string"?t.delta:null},N=e=>{let t=ae(e);return t?.type==="thinking_delta"&&typeof t.delta=="string"?t.delta:null},q=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 Ge=/^ /,w=e=>{if(e&&typeof e=="object"){let t=e,n=typeof t.error=="string"?t.error:"request_failed";return typeof t.retryable=="boolean"?{error:n,retryable:t.retryable}:{error:n}}return{error:"request_failed"}},Qe=e=>{let t="message",n=[];for(let r of e.split(`
3
+ `))r.startsWith(":")||(r.startsWith("event:")?t=r.slice(6).trim():r.startsWith("data:")&&n.push(r.slice(5).replace(Ge,"")));return n.length>0?{event:t,data:n.join(`
4
+ `)}:null},ze=(e,t,n)=>{let r;try{r=JSON.parse(e.data)}catch{return}if(e.event==="session"){let s=r.sessionId;s&&(n(s),t.onSession?.(s));return}if(e.event==="turn_event"){t.onEvent?.(r);let s=U(r);s&&t.onText?.(s);let a=N(r);a&&t.onThinking?.(a);let o=q(r);o&&t.onTool?.(o);return}if(e.event==="chat_completed"){let s=r;n(s.sessionId),t.onComplete?.(s);return}e.event==="chat_error"&&t.onError?.(w(r))},P=async(e,t)=>{let n=await fetch(e,{headers:t});if(!n.ok)throw new Error(`hola: request failed (${n.status})`);return await n.json()},le=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()},ue=async(e,t,n,r)=>{let s=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body,signal:r});if(!(s.ok&&s.body)){t.onError?.({error:`stream_failed_${s.status}`});return}let a=s.body.getReader(),o=new TextDecoder,i="",l=()=>{let d=i.indexOf(`
5
5
 
6
- `);for(;d!==-1;){let p=a.slice(0,d);a=a.slice(d+2);let f=Be(p);f&&Ve(f,t,n),d=a.indexOf(`
6
+ `);for(;d!==-1;){let m=i.slice(0,d);i=i.slice(d+2);let p=Qe(m);p&&ze(p,t,n),d=i.indexOf(`
7
7
 
8
- `)}},u=async()=>{let d=await i.read();if(!d.done)return a+=o.decode(d.value,{stream:!0}),l(),u()};await u()};var je=/\/+$/,q="/api/v1/end-user",Ge=e=>{let t=e.baseUrl.replace(je,""),n=()=>typeof e.token=="function"?e.token():e.token,r=o=>e.project?`${o}project=${encodeURIComponent(e.project)}`:"",s=async()=>({"content-type":"application/json",authorization:`Bearer ${await n()}`}),i=async o=>{let a=await fetch(`${t}${q}/chat${r("?")}`,{method:"POST",headers:await s(),body:JSON.stringify({message:o})});if(!a.ok)throw new Error(`hola: message failed (${a.status})`);return{reply:(await a.json()).reply??"",sessionId:"",artifacts:[]}};return{sessionId:()=>"",getInfo:async()=>S(`${t}${q}/chat/info${r("?")}`,await s()),sendMessage:i,streamMessage:async(o,a)=>{try{let l=await i(o);a.onText?.(l.reply),a.onComplete?.(l)}catch(l){a.onError?.(w(l))}},subscribe:(o,a)=>{let l=a?.since??"0",u=!1,d,p=a?.intervalMs??3e3,f=typeof document<"u",c=()=>f&&document.visibilityState==="hidden",m=!1,y=()=>{if(!u){if(c()){m=!0;return}d=setTimeout(b,p)}},b=async()=>{try{let x=await S(`${t}${q}/chat/thread?since=${encodeURIComponent(l)}${r("&")}`,await s());for(let k of x.messages)o.onMessage(k);l=x.cursor,o.onHealthy?.()}catch(x){o.onError?.(w(x))}y()},P=()=>{u||!m||c()||(m=!1,d&&clearTimeout(d),d=setTimeout(b,0))};f&&document.addEventListener("visibilitychange",P);let g=()=>{u=!0,d&&clearTimeout(d),f&&document.removeEventListener("visibilitychange",P)};return a?.signal?.addEventListener("abort",g),d=setTimeout(b,0),g}}};import{useEffect as Qe,useState as ze}from"react";var N=(e,t)=>{let[n,r]=ze("");return Qe(()=>{if(!e){r("");return}let s=Uint8Array.from(atob(e),o=>o.charCodeAt(0)),i=URL.createObjectURL(new Blob([s],{type:t}));return r(i),()=>URL.revokeObjectURL(i)},[e,t]),n};import{useEffect as Ze,useRef as et}from"react";import{createContext as Je,useContext as Ke}from"react";import{jsx as Ye}from"react/jsx-runtime";var oe=Je(null),Xe=({client:e,children:t})=>Ye(oe.Provider,{value:e,children:t}),B=()=>{let e=Ke(oe);if(!e)throw new Error("useHolaClient must be used within <HolaProvider>");return e};import{useCallback as se,useEffect as ie,useRef as ae,useState as M}from"react";var V=e=>{let[t,n]=M([]),[r,s]=M(""),[i,o]=M(!1),[a,l]=M(null),u=ae(0),d=ae(null);ie(()=>()=>d.current?.abort(),[]);let p=se(()=>{let c=u.current;return u.current+=1,c},[]);ie(()=>{let c=!0;return e.getInfo().then(m=>{c&&m.greeting&&n([{id:p(),role:"assistant",text:m.greeting}])}).catch(()=>{}),()=>{c=!1}},[e,p]);let f=se(()=>{let c=r.trim();if(!c||i)return;s(""),l(null),o(!0);let m=p(),y=p();n(g=>[...g,{id:m,role:"user",text:c},{id:y,role:"assistant",text:"",streaming:!0}]);let b=g=>{n(x=>x.map(k=>k.id===y?g(k):k))},P=new AbortController;d.current=P,e.streamMessage(c,{onText:g=>b(x=>({...x,text:x.text+g})),onComplete:g=>{b(x=>({...x,text:g.reply||x.text,artifacts:g.artifacts,streaming:!1})),o(!1)},onError:g=>{b(x=>({...x,streaming:!1})),l(g.error),o(!1)}},P.signal).catch(g=>{b(x=>({...x,streaming:!1})),l(g instanceof Error?g.message:"stream_failed"),o(!1)}).finally(()=>{o(!1),b(g=>g.streaming?{...g,streaming:!1}:g)})},[r,i,e,p]);return{messages:t,input:r,setInput:s,send:f,sending:i,error:a}};import{jsx as C,jsxs as j}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"}},tt=({artifact:e})=>{let t=N(e.dataBase64??"",e.mimeType),n=e.url??t;return n?e.mimeType.startsWith("image/")?C("a",{href:n,rel:"noopener noreferrer",target:"_blank",children:C("img",{alt:e.filename,src:n,style:v.image})}):C("a",{download:e.filename,href:n,style:v.link,children:e.filename}):null},nt=()=>{let e=B(),{messages:t,input:n,setInput:r,send:s,sending:i,error:o}=V(e),a=et(null);Ze(()=>{let u=a.current;u&&(u.scrollTop=u.scrollHeight)},[t]);let l=u=>{u.preventDefault(),s()};return j("div",{style:v.root,children:[C("div",{ref:a,style:v.log,children:t.map(u=>j("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(tt,{artifact:d},d.filename))}):null]},u.id))}),o?C("div",{style:v.error,children:o}):null,j("form",{onSubmit:l,style:v.form,children:[C("input",{"aria-label":"Message",onChange:u=>r(u.target.value),placeholder:"Type a message\u2026",style:v.input,value:n}),C("button",{disabled:i||n.trim().length===0,style:v.button,type:"submit",children:"Send"})]})]})};var rt=/\/+$/,G=e=>{let t=e.sessionId,n=e.baseUrl.replace(rt,""),r=o=>`${n}/endpoint/${encodeURIComponent(e.token)}${o}`,s={"content-type":"application/json"},i=(o,a)=>({url:r(o),headers:s,body:JSON.stringify({message:a,...t?{sessionId:t}:{},...e.identity?{externalUserId:e.identity.externalUserId,userHmac:e.identity.userHmac}:{}})});return{sessionId:()=>t,getInfo:()=>S(r("/config"),{}),sendMessage:async o=>{let a=await ne(i("/message",o));return t=a.sessionId,a},streamMessage:(o,a,l)=>re(i("/message/stream",o),a,u=>{t=u},l),subscribe:(o,a)=>{let l=a?.since??"0",u=!1,d,p=a?.intervalMs??3e3,f=async()=>{let m=t;if(m)try{let y=await S(r(`/messages?session=${encodeURIComponent(m)}&since=${encodeURIComponent(l)}`),{});for(let b of y.messages)o.onMessage(b);l=y.cursor,o.onHealthy?.()}catch(y){o.onError?.(w(y))}u||(d=setTimeout(f,p))},c=()=>{u=!0,d&&clearTimeout(d)};return a?.signal?.addEventListener("abort",c),d=setTimeout(f,0),c}}};var ot=e=>"transport"in e?e.transport:G(e);var st=/^https?:\/\//i,it=/^\d{4}-\d{2}-\d{2}(?:[T ]|$)/,at=e=>e.replace(/_/g," ").replace(/\b\w/g,t=>t.toUpperCase());function lt(e){if(typeof e=="number")return"number";if(typeof e=="boolean")return"boolean";if(typeof e=="string"){if(st.test(e))return"url";if(it.test(e))return"date"}return"text"}function le(e){let t=[],n=new Map;for(let r of e)for(let[s,i]of Object.entries(r.data??{})){if(i==null)continue;let o=n.get(s);o||(o=new Map,n.set(s,o),t.push(s));let a=lt(i);o.set(a,(o.get(a)??0)+1)}return t.map(r=>{let s=n.get(r)??new Map,i="text",o=-1;for(let[a,l]of s)l>o&&(o=l,i=a);return{key:r,label:at(r),type:i}})}var ut=e=>typeof e=="number"?e:Number(e)||0,ue=e=>/rate|position|rank|score|percent|avg/i.test(e),dt=/posted|published|sent|completed|shipped|launched|_at/i,pt=new Set(["service","order","end_user_id"]);function de(e,t){let n=e.filter(l=>!pt.has(l.key)),r=n.filter(l=>l.type==="number").slice(0,3),s=n.find(l=>l.key==="status")??n.find(l=>l.type==="select"),i=n.find(l=>l.type==="date"&&dt.test(l.key))??n.find(l=>l.type==="date"),o=n.filter(l=>l.type==="number"&&!ue(l.key)).map(l=>({field:l,total:t.reduce((u,d)=>u+ut(d.data[l.key]),0)})).sort((l,u)=>u.total-l.total).find(l=>l.total>0)?.field??null,a=[{type:"stat",label:"Items",agg:"count"}];for(let l of r){let u=ue(l.key);a.push({type:"stat",metric:l.key,agg:u?"avg":"sum",label:u?`Avg ${l.label.toLowerCase()}`:l.label})}return i&&a.push({type:"line",x:i.key,y:o?.key,agg:"sum",title:o?`${o.label} by day`:"Items by day"}),s&&a.push({type:"donut",groupBy:s.key,title:s.label}),a.push({type:"table",columns:n.map(l=>l.key)}),{version:1,widgets:a}}var pe=6,ce=6,me=4,ge={stat:{w:1,h:1},chart:{w:2,h:2},block:{w:6,h:2}},ct=e=>Math.max(1,Math.min(6,Math.round(e))),mt=e=>Math.max(1,Math.min(4,Math.round(e)));function $(e){return e==="stat"?"stat":e==="series"||e==="donut"?"chart":"block"}function fe(e){return e==="stat"?"stat":e==="line"||e==="bar"||e==="donut"?"chart":"block"}function ye(e){return ge[e]}function Q(e,t,n){let r=ge[e];return{w:t===void 0?r.w:ct(t),h:n===void 0?r.h:mt(n)}}function z(e){let t=[],n=[],r=(o,a,l,u)=>{if(o<0||o+l>6)return!1;for(let d=0;d<u;d+=1){let p=n[a+d];if(p){for(let f=0;f<l;f+=1)if(p[o+f])return!1}}return!0},s=(o,a,l,u)=>{for(let d=0;d<u;d+=1){let p=n[a+d]??[];for(let f=0;f<l;f+=1)p[o+f]=!0;n[a+d]=p}},i=(o,a)=>{for(let l=0;;l+=1)for(let u=0;u+o<=6;u+=1)if(r(u,l,o,a))return{gx:u,gy:l}};for(let o of e){let a=Q($(o.kind),o.w,o.h),u=o.gx!==void 0&&o.gy!==void 0&&r(o.gx,o.gy,a.w,a.h)&&o.gx!==void 0&&o.gy!==void 0?{gx:o.gx,gy:o.gy}:i(a.w,a.h);s(u.gx,u.gy,a.w,a.h),t.push({widget:o,gx:u.gx,gy:u.gy,w:a.w,h:a.h})}return t}function be(e){let t=[],n=[];for(let r of e)$(r.kind)==="block"?n.push(r):t.push(r);return{tiles:z(t),blocks:n}}var he=new Set(["service","order","end_user_id"]),J=e=>typeof e=="number"?e:Number(e)||0,xe=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 n=t.reduce((r,s)=>r+s,0);return e==="avg"?Math.round(n/t.length*100)/100:n}function gt(e,t,n,r){let s=new Map;for(let i of e){let o=new Date(xe(i.data[t]));if(Number.isNaN(o.getTime()))continue;let a=o.toISOString().slice(0,10),l=s.get(a)??[];l.push(n?J(i.data[n]):1),s.set(a,l)}return[...s.entries()].sort((i,o)=>i[0]<o[0]?-1:1).map(([i,o])=>({label:new Date(`${i}T00:00:00`).toLocaleDateString(void 0,{month:"short",day:"numeric"}),value:n?K(r,o):o.length}))}function ft(e,t,n,r="sum"){let s=new Map;for(let i of e){let o=xe(i.data[t]).trim();if(!o)continue;let a=s.get(o)??[];a.push(n?J(i.data[n]):1),s.set(o,a)}return[...s.entries()].map(([i,o])=>({label:i,value:n?K(r,o):o.length})).sort((i,o)=>o.value-i.value)}function yt(e,t,n,r){switch(e.type){case"stat":{let s=e.metric?t.get(e.metric):void 0;if(e.metric&&!s)return null;if(!s)return{kind:"stat",label:e.label??"Items",value:r.length};let i=r.map(o=>J(o.data[s.key]));return{kind:"stat",label:e.label??s.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 s=gt(r,e.x,e.y,e.agg??"sum");return s.length<2?null:{kind:"series",draw:e.type,title:e.title??"By day",points:s}}case"donut":{if(!t.has(e.groupBy))return null;let s=ft(r,e.groupBy,e.metric,e.agg??"sum");return s.length===0?null:{kind:"donut",title:e.title??t.get(e.groupBy)?.label??"Breakdown",points:s}}case"table":{let s=e.columns?e.columns.map(i=>t.get(i)).filter(i=>i!==void 0&&!he.has(i.key)):n;return s.length===0?null:{kind:"table",title:e.title,columns:s,rows:r}}case"text":return{kind:"text",title:e.title,body:e.body};default:return null}}function we(e,t,n,r={}){let s=new Map,i=l=>({byKey:new Map(l.fields.map(u=>[u.key,u])),cols:l.fields.filter(u=>!he.has(u.key)),rows:l.rows}),o=i({fields:t,rows:n});for(let[l,u]of Object.entries(r))s.set(l,i(u));let a=[];for(let l of e.widgets){let u=l.type==="text"?void 0:l.source,d=u?s.get(u):o;if(!d)continue;let p=yt(l,d.byKey,d.cols,d.rows);p&&a.push({...p,w:l.w,h:l.h,gx:l.gx,gy:l.gy})}return a}var bt=new Set(["sum","avg","count","min","max","last"]),Se=e=>typeof e=="string"&&bt.has(e)?e:void 0,h=e=>typeof e=="string"&&e!==""?e:void 0,I=e=>typeof e=="number"&&e>=1?Math.min(6,Math.round(e)):void 0,A=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 ht(e){if(typeof e!="object"||e===null)return null;let t=e;switch(t.type){case"stat":return{type:"stat",source:h(t.source),label:h(t.label),metric:h(t.metric)??h(t.column),agg:Se(t.agg),w:I(t.w),h:A(t.h),gx:T(t.gx),gy:T(t.gy)};case"line":case"bar":{let n=h(t.x);return n?{type:t.type,source:h(t.source),title:h(t.title),x:n,y:h(t.y)??h(t.column),agg:Se(t.agg),w:I(t.w),h:A(t.h),gx:T(t.gx),gy:T(t.gy)}:null}case"donut":{let n=h(t.groupBy)??h(t.column);return n?{type:"donut",source:h(t.source),title:h(t.title),groupBy:n,w:I(t.w),h:A(t.h),gx:T(t.gx),gy:T(t.gy)}:null}case"table":{let n=Array.isArray(t.columns)?t.columns.filter(r=>typeof r=="string"):void 0;return{type:"table",source:h(t.source),title:h(t.title),columns:n,w:I(t.w),h:A(t.h),gx:T(t.gx),gy:T(t.gy)}}case"text":{let n=h(t.body);return n?{type:"text",title:h(t.title),body:n,w:I(t.w),h:A(t.h),gx:T(t.gx),gy:T(t.gy)}:null}default:return null}}function ve(e){let t=e;if(typeof e=="string"){if(e.trim()==="")return null;try{t=JSON.parse(e)}catch{return null}}if(typeof t!="object"||t===null)return null;let n=t.widgets;if(!Array.isArray(n))return null;let r=n.map(ht).filter(i=>i!==null);if(r.length===0)return null;let s=t.version;return{version:typeof s=="number"?s:1,title:h(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,n=typeof t.value=="string"?t.value:"",r=t.kind==="link"||t.kind==="text"||t.kind==="table"?t.kind:"file",s=typeof t.v=="number"&&t.v>=1?Math.floor(t.v):void 0;return n?{kind:r,value:n,...s?{v:s}:{}}:null}return null}function Y(e){let t=new Map;for(let n of e){let r=n.v??1,s=t.get(r)??[];s.push(n),t.set(r,s)}return[...t.entries()].sort(([n],[r])=>n-r).map(([n,r])=>({v:n,items:r}))}function Pe(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(s=>s!==null)}catch{}let n=String(e.file??"");return n?[{kind:"file",value:n}]:[]}function Te(e,t,n,r=""){let i=Y(e).find(a=>a.v===t)?.items??[],o=i.filter(a=>a.kind==="file").map(a=>n.get(a.value)??"");return i.some(a=>a.kind==="table")&&o.push(r),o.length===0||o.some(a=>a==="")?"awaiting":o.some(a=>a==="revise")?"revise":"accepted"}function ke(e){return Number(e.published_version)||0}function Z(e){return e==="number"||e==="date"||e==="boolean"||e==="select"||e==="url"?e:e==="link"?"url":e==="checkbox"?"boolean":"text"}function Ce(e){try{let t=JSON.parse(e);if(Array.isArray(t.columns)&&Array.isArray(t.rows)&&t.columns.length){let n=t.columns.map((i,o)=>({key:typeof i.key=="string"&&i.key?i.key:typeof i.id=="string"&&i.id?i.id:`column_${o+1}`,label:typeof i.label=="string"?i.label:"",type:Z(i.type),...i.clientEditable===!0?{clientEditable:!0}:{}})),r=t.rows.map((i,o)=>({id:typeof i.id=="string"&&i.id?i.id:`row_${o}`,cells:i.cells&&typeof i.cells=="object"?i.cells:{}})),s=typeof t.name=="string"?t.name:void 0;return{columns:n,rows:r,...s?{name:s}:{}}}}catch{}return null}function Re(e){return e==null?"":String(e)}function De(e){return e===!0||e==="true"||e==="1"||e==="yes"||e==="\u2713"}function W(){return{cells:{},verdict:"",comment:""}}function Ie(e){if(typeof e!="string"||e.trim()==="")return W();try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t)){let n=t;return{cells:n.cells&&typeof n.cells=="object"?n.cells:n,verdict:n.verdict==="accepted"||n.verdict==="revise"?n.verdict:"",comment:typeof n.comment=="string"?n.comment:""}}}catch{}return W()}function Ae(e,t,n){if(e.clientEditable){let r=n.cells[t.id];if(r&&e.key in r)return r[e.key]}return t.cells[e.key]}function He(e,t,n,r){return{...e,cells:{...e.cells,[t]:{...e.cells[t]??{},[n]:r}}}}function Ee(e,t,n){return{...e,verdict:t,comment:n}}function Me(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 H=class extends Error{code;status;constructor(t,n,r){super(n),this.name="CreditRefused",this.code=t,this.status=r}},xt=/\/+$/,wt="/api/v1/end-user",$e="Pre-payment",We="After-payment";function St(e,t){if(e<=0)return[];let n=t&&typeof t.upfront=="number"&&Number.isFinite(t.upfront)?Math.max(0,Math.min(t.upfront,e)):e,r=Math.round((e-n)*100)/100,s=[];return n>0&&s.push({label:$e,amount:n}),r>0&&s.push({label:We,amount:r}),s}var vt=(e,t,n)=>{let r=t.filter(l=>l.order===n),s=r.reduce((l,u)=>l+u.amount,0),i=r.filter(l=>l.status==="paid").reduce((l,u)=>l+u.amount,0),o=e.value>0,a=s>0?s-i:e.value-i;return{value:e.value,priced:o,billed:s,paid:i,due:Math.max(0,a),lines:[...r].sort((l,u)=>l.status!==u.status?l.status==="due"?-1:1:(l.dueDate||l.paidAt).localeCompare(u.dueDate||u.paidAt)),awaitingPayment:o&&i<=0}},Pt=e=>{let t=e.baseUrl.replace(xt,""),n=()=>typeof e.token=="function"?e.token():e.token,r=async(s,i={method:"GET"})=>{try{let o=await fetch(`${t}${wt}${s}`,{method:i.method,headers:{"content-type":"application/json",authorization:`Bearer ${await n()}`},...i.body===void 0?{}:{body:JSON.stringify(i.body)}});if(!o.ok){let a=await o.json().catch(()=>({}));throw new H(a.error??"request_failed",a.message??`${i.method} ${s} \u2192 ${String(o.status)}`,o.status)}return await o.json()}catch(o){throw o instanceof H?o:w(o)}};return{wallet:()=>r("/credits"),history:()=>r("/credits/history"),topup:s=>r("/credits/checkout",{method:"POST",body:{packId:s}}),checkout:s=>r("/shop/checkout",{method:"POST",body:s}),payments:()=>r("/payments"),paymentMethods:()=>r("/payment-methods"),markPaymentSent:(s,i)=>r(`/payments/${encodeURIComponent(s)}/sent`,{method:"POST",body:{reference:i??""}}),inquiryQuote:s=>r(`/inquiries/${encodeURIComponent(s)}/quote`),acceptInquiry:(s,i)=>r(`/inquiries/${encodeURIComponent(s)}/accept`,{method:"POST",body:{version:i}}),enquire:(s,i,o)=>r("/shop/enquire",{method:"POST",body:{productId:s,answers:i,name:o??""}})}};var Tt=/\/+$/,R="/api/v1/end-user",E=class extends Error{constructor(t){super(t),this.name="PortalConflict"}};function kt(e){let t="";for(let r=0;r<e.length;r+=32768)t+=String.fromCharCode(...e.subarray(r,r+32768));return btoa(t)}var Ct=e=>{let t=e.baseUrl.replace(Tt,""),n=()=>typeof e.token=="function"?e.token():e.token,r=async()=>({"content-type":"application/json",authorization:`Bearer ${await n()}`}),s=async(o,a)=>{try{let l=await fetch(`${t}${R}${o}`,{method:a.method,headers:await r(),...a.body===void 0?{}:{body:JSON.stringify(a.body)}});if(l.status===409){let u=await l.json().catch(()=>({}));throw new E(u.message??"Someone else saved this first.")}if(!l.ok){let u=await l.text().catch(()=>""),d=`${a.method} ${o} \u2192 ${String(l.status)}`;try{let p=JSON.parse(u);p.message&&(d=p.message)}catch{d=u?`${d}: ${u}`:d}throw w({error:d})}return await l.json()}catch(l){throw l instanceof E?l:w(l)}},i=o=>`/tables/${encodeURIComponent(o)}`;return{listTables:async()=>(await S(`${t}${R}/tables`,await r())).tables,listRows:async(o,a)=>await S(`${t}${R}${i(o)}/rows?limit=${String(a??100)}`,await r()),insertRow:async(o,a)=>{let{rowIds:l}=await s(`${i(o)}/rows`,{method:"POST",body:{rows:[a]}}),u=l[0];if(!u)throw w(new Error("The row was not created."));return u},patchRow:async(o,a,l)=>(await s(`${i(o)}/rows/${encodeURIComponent(a)}`,{method:"PATCH",body:l})).updated,deleteRow:async(o,a)=>(await s(`/${encodeURIComponent(o)}/${encodeURIComponent(a)}`,{method:"DELETE"})).deleted,listFiles:async()=>(await S(`${t}${R}/tables/files/rows?limit=200`,await r())).rows.map(a=>({id:a.rowId,filename:String(a.data.filename??""),source:String(a.data.source??"client"),campaign:String(a.data.campaign??""),size:typeof a.data.size=="number"?a.data.size:0,createdAt:a.createdAt})),uploadFile:async(o,a)=>{let l=new Uint8Array(await o.arrayBuffer());return await s("/files",{method:"POST",body:{filename:o.name,mime:o.type||"application/octet-stream",data:kt(l),...a===void 0?{}:{message:a}}})},fileLink:async o=>await S(`${t}${R}/files/${encodeURIComponent(o)}/url`,await r()),deleteFile:async o=>(await s(`/files/${encodeURIComponent(o)}`,{method:"DELETE"})).deleted,listDocuments:async()=>(await S(`${t}${R}/documents`,await r())).documents,readDocument:async o=>(await S(`${t}${R}/documents/${encodeURIComponent(o)}`,await r())).document,saveDocument:async(o,a)=>await s(`/documents/${encodeURIComponent(o)}`,{method:"PATCH",body:a})}};var Rt=/\/+$/,Dt="/api/v1/end-user",It=e=>{let t=e.baseUrl.replace(Rt,""),n=async(r,s)=>{let i;try{i=await fetch(`${t}${Dt}${r}`,s===void 0?{}:{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(s)})}catch(o){throw w(o)}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(o){throw w(o)}};return{listProducts:async()=>{let r=await n(`/shop/products?publishable_key=${encodeURIComponent(e.publishableKey)}`);return{products:r.products.map(s=>({...s,currency:typeof s.currency=="string"?s.currency:""})),truncated:r.truncated===!0,enquiryForm:Array.isArray(r.enquiryForm)?r.enquiryForm:[]}},apply:async r=>await n("/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}:{}})}};var At=new Set(["buy","ask"]);function Ht(e){return At.has(e.mode)?e.mode:"ask"}var Et={kind:"quoted"};function O(e,t){if(!t)return e.toLocaleString();if(t.toLowerCase()==="credits")return`${e.toLocaleString()} ${e===1?"credit":"credits"}`;let n=Number.isInteger(e)?0:2;try{return new Intl.NumberFormat(void 0,{style:"currency",currency:t,minimumFractionDigits:n,maximumFractionDigits:n}).format(e)}catch{return`${t} ${e.toLocaleString()}`}}function Oe(e,t){let n=/^[a-z]+$/i.test(t)&&!t.endsWith("s")?"s":"";return`${e.toLocaleString()} ${t}${n}`}function Fe(e,t){return e.kind==="quoted"?"Priced on enquiry":e.kind==="flat"?O(e.price,t):`${O(e.unitPrice,t)} per ${e.unitStep===1?e.unit:Oe(e.unitStep,e.unit)}`}function Mt(e){let t=e.currency,n=e.pricing;if(n.kind!=="variants")return Fe(n,t);let r=n.variants.map(s=>s.price).filter(s=>typeof s=="number");return r.length>0?`From ${O(Math.min(...r),t)}`:"Priced on enquiry"}function $t(e,t){if(e.kind!=="variants")return e;let n=e.variants.find(r=>r.name===t);return typeof n?.price=="number"?{kind:"flat",price:n.price}:Et}function Wt(e,t){return e.kind==="flat"?e.price:e.kind==="per_unit"?e.unitPrice*Math.ceil(t/Math.max(e.unitStep,1)):null}function Ot(e,t){let n=t.kind==="per_unit"?Math.max(t.unitStep,1):1;return{min:Math.max(e.minQty??n,n),max:e.maxQty??null,step:n}}function Ft(e,t){let n=e.variants?.find(r=>r.name===t);return n&&n.includes.length>0?n.includes:e.includes}function _t(e,t){let n=[];for(let r of e){let s=t(r).trim();s&&!n.includes(s)&&n.push(s)}return n}function Lt(e,t,n,r){let s=t?`${e.name} \u2014 ${t}`:e.name,i=n.kind==="per_unit"?`, ${Oe(r,n.unit)}`:"";return`I'd like to buy ${s}${i}. How do I go ahead?`}function Ut(e){return e?(e&&typeof e=="object"&&"error"in e?String(e.error):"")==="rate_limited"?"That's a lot of looking at once \u2014 give it a moment, then reload.":"The shop isn't loading right now. Please try again shortly.":null}import{useCallback as _e,useEffect as qt,useState as ee}from"react";var Nt=e=>{let[t,n]=ee(null),[r,s]=ee(!0),[i,o]=ee(null),a=_e(async()=>{try{n(await e.wallet()),o(null)}catch{o("Couldn't read your balance just now.")}finally{s(!1)}},[e]),l=_e(()=>{a().catch(()=>{})},[a]);return qt(()=>(l(),window.addEventListener("focus",l),()=>{window.removeEventListener("focus",l)}),[l]),{wallet:t,loading:r,failure:i,refresh:l}};import{useCallback as Bt,useEffect as Vt,useState as D}from"react";var jt=e=>e&&typeof e=="object"&&typeof e.error=="string"?e.error:e instanceof Error?e.message:"shop_unavailable",Gt=e=>{let[t,n]=D([]),[r,s]=D([]),[i,o]=D(!1),[a,l]=D(!0),[u,d]=D(null),[p,f]=D(0);Vt(()=>{let m=!0;return l(!0),e.listProducts().then(y=>{m&&(n(y.products),s(y.enquiryForm),o(y.truncated),d(null))}).catch(y=>{m&&d(jt(y))}).finally(()=>{m&&l(!1)}),()=>{m=!1}},[e,p]);let c=Bt(()=>f(m=>m+1),[]);return{products:t,enquiryForm:r,truncated:i,loading:a,error:u,reload:c}};import{useCallback as Qt,useEffect as Le,useRef as zt,useState as F}from"react";var Ue="greeting";function qe(e,t){if(e.some(i=>i.id===t.id))return e;let n=e.filter(i=>i.id!==Ue),r=i=>i.author==="client"==(t.author==="client");return[...n.filter(i=>!(i.pending&&r(i)&&i.text===t.text)),t]}var Jt=(e,t)=>{let[n,r]=F([]),[s,i]=F(""),[o,a]=F(!1),[l,u]=F(null),d=zt(0),p=t?.pollMs??2e3;Le(()=>{let c=!0;return e.getInfo().then(m=>{c&&m.greeting&&r(y=>y.length===0?[{id:Ue,cursor:"",author:"agent",text:m.greeting}]:y)}).catch(()=>{}),()=>{c=!1}},[e]),Le(()=>e.subscribe?.({onMessage:c=>r(m=>qe(m,c)),onError:c=>u(c.error),onHealthy:()=>u(null)},{intervalMs:p}),[e,p]);let f=Qt(()=>{let c=s.trim();if(!c||o)return;i(""),u(null),a(!0),d.current+=1;let m=`pending-${d.current}`,y={id:m,cursor:"",author:"client",text:c,pending:!0};r(b=>[...b,y]),e.sendMessage(c).then(b=>{a(!1),b.reply.trim()&&r(g=>g.some(k=>!k.pending&&k.author!=="client"&&k.text===b.reply)?g:(d.current+=1,[...g,{id:`pending-agent-${d.current}`,cursor:"",author:"agent",text:b.reply,pending:!0}]))}).catch(b=>{u(b instanceof Error?b.message:"send_failed"),a(!1),r(P=>P.filter(g=>g.id!==m)),i(P=>P||c)})},[s,o,e]);return{messages:n,input:s,setInput:i,send:f,sending:o,error:l}};export{nt as Chat,H as CreditRefused,pe as GRID_COLS,ce as GRID_MAX_COLS,me as GRID_MAX_ROWS,Xe as HolaProvider,E as PortalConflict,We as QUOTE_BALANCE_LABEL,$e as QUOTE_DEPOSIT_LABEL,$ as bandOfKind,fe as bandOfType,Lt as buyRequestText,Ae as cellValue,Ge as createApiTransport,ot as createHolaClient,Pt as createPortalCredits,Ct as createPortalData,It as createPortalShop,G as createWidgetTransport,Re as deliverableCellText,Te as deliverableStatus,le as deriveFields,W as emptyTableResponses,_t as facetValues,ye as footprintOf,Q as footprintWith,Me as formatDeliverableDate,Y as groupDeliverableVersions,Ft as includesFor,de as inferSpec,De as isDeliverableChecked,qe as mergeMessage,Ht as modeOf,O as money,Z as normalizeDeliverableColType,X as normalizeDeliverableItem,vt as orderBilling,ve as parseDashboardSpec,Pe as parseDeliverableItems,Ce as parseDeliverableTable,Ie as parseTableResponses,z as placeWidgets,$t as priceFor,Fe as priceLabel,ke as publishedVersionOf,Ot as quantityRange,St as quoteSchedule,we as renderModel,He as setResponse,Ee as setTableReview,Mt as shelfPriceLabel,Ut as shelfProblem,be as splitLayout,_ as textDeltaOf,L as thinkingDeltaOf,U as toolEventOf,Wt as totalFor,N as useArtifactUrl,V as useChat,Nt as useCredits,B as useHolaClient,Gt as useShop,Jt as useThread};
8
+ `)}},u=async()=>{let d=await a.read();if(!d.done)return i+=o.decode(d.value,{stream:!0}),l(),u()};await u()};var Je=/\/+$/,V="/api/v1/end-user",Ke=e=>{let t=e.baseUrl.replace(Je,""),n=()=>typeof e.token=="function"?e.token():e.token,r=o=>e.project?`${o}project=${encodeURIComponent(e.project)}`:"",s=async()=>({"content-type":"application/json",authorization:`Bearer ${await n()}`}),a=async o=>{let i=await fetch(`${t}${V}/chat${r("?")}`,{method:"POST",headers:await s(),body:JSON.stringify({message:o})});if(!i.ok)throw new Error(`hola: message failed (${i.status})`);return{reply:(await i.json()).reply??"",sessionId:"",artifacts:[]}};return{sessionId:()=>"",getInfo:async()=>P(`${t}${V}/chat/info${r("?")}`,await s()),sendMessage:a,streamMessage:async(o,i)=>{try{let l=await a(o);i.onText?.(l.reply),i.onComplete?.(l)}catch(l){i.onError?.(w(l))}},subscribe:(o,i)=>{let l=i?.since??"0",u=!1,d,m=i?.intervalMs??3e3,p=typeof document<"u",c=()=>p&&document.visibilityState==="hidden",g=!1,y=()=>{if(!u){if(c()){g=!0;return}d=setTimeout(b,m)}},b=async()=>{try{let x=await P(`${t}${V}/chat/thread?since=${encodeURIComponent(l)}${r("&")}`,await s());for(let T of x.messages)o.onMessage(T);l=x.cursor,o.onHealthy?.()}catch(x){o.onError?.(w(x))}y()},v=()=>{u||!g||c()||(g=!1,d&&clearTimeout(d),d=setTimeout(b,0))};p&&document.addEventListener("visibilitychange",v);let f=()=>{u=!0,d&&clearTimeout(d),p&&document.removeEventListener("visibilitychange",v)};return i?.signal?.addEventListener("abort",f),d=setTimeout(b,0),f}}};import{useEffect as Xe,useState as Ye}from"react";var B=(e,t)=>{let[n,r]=Ye("");return Xe(()=>{if(!e){r("");return}let s=Uint8Array.from(atob(e),o=>o.charCodeAt(0)),a=URL.createObjectURL(new Blob([s],{type:t}));return r(a),()=>URL.revokeObjectURL(a)},[e,t]),n};import{useEffect as rt,useRef as ot}from"react";import{createContext as Ze,useContext as et}from"react";import{jsx as nt}from"react/jsx-runtime";var de=Ze(null),tt=({client:e,children:t})=>nt(de.Provider,{value:e,children:t}),j=()=>{let e=et(de);if(!e)throw new Error("useHolaClient must be used within <HolaProvider>");return e};import{useCallback as pe,useEffect as ce,useRef as me,useState as E}from"react";var G=e=>{let[t,n]=E([]),[r,s]=E(""),[a,o]=E(!1),[i,l]=E(null),u=me(0),d=me(null);ce(()=>()=>d.current?.abort(),[]);let m=pe(()=>{let c=u.current;return u.current+=1,c},[]);ce(()=>{let c=!0;return e.getInfo().then(g=>{c&&g.greeting&&n([{id:m(),role:"assistant",text:g.greeting}])}).catch(()=>{}),()=>{c=!1}},[e,m]);let p=pe(()=>{let c=r.trim();if(!c||a)return;s(""),l(null),o(!0);let g=m(),y=m();n(f=>[...f,{id:g,role:"user",text:c},{id:y,role:"assistant",text:"",streaming:!0}]);let b=f=>{n(x=>x.map(T=>T.id===y?f(T):T))},v=new AbortController;d.current=v,e.streamMessage(c,{onText:f=>b(x=>({...x,text:x.text+f})),onComplete:f=>{b(x=>({...x,text:f.reply||x.text,artifacts:f.artifacts,streaming:!1})),o(!1)},onError:f=>{b(x=>({...x,streaming:!1})),l(f.error),o(!1)}},v.signal).catch(f=>{b(x=>({...x,streaming:!1})),l(f instanceof Error?f.message:"stream_failed"),o(!1)}).finally(()=>{o(!1),b(f=>f.streaming?{...f,streaming:!1}:f)})},[r,a,e,m]);return{messages:t,input:r,setInput:s,send:p,sending:a,error:i}};import{jsx as C,jsxs as Q}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"}},st=({artifact:e})=>{let t=B(e.dataBase64??"",e.mimeType),n=e.url??t;return n?e.mimeType.startsWith("image/")?C("a",{href:n,rel:"noopener noreferrer",target:"_blank",children:C("img",{alt:e.filename,src:n,style:S.image})}):C("a",{download:e.filename,href:n,style:S.link,children:e.filename}):null},it=()=>{let e=j(),{messages:t,input:n,setInput:r,send:s,sending:a,error:o}=G(e),i=ot(null);rt(()=>{let u=i.current;u&&(u.scrollTop=u.scrollHeight)},[t]);let l=u=>{u.preventDefault(),s()};return Q("div",{style:S.root,children:[C("div",{ref:i,style:S.log,children:t.map(u=>Q("div",{style:u.role==="user"?S.user:S.assistant,children:[u.text||(u.streaming?"\u2026":""),u.artifacts&&u.artifacts.length>0?C("div",{style:S.artifacts,children:u.artifacts.map(d=>C(st,{artifact:d},d.filename))}):null]},u.id))}),o?C("div",{style:S.error,children:o}):null,Q("form",{onSubmit:l,style:S.form,children:[C("input",{"aria-label":"Message",onChange:u=>r(u.target.value),placeholder:"Type a message\u2026",style:S.input,value:n}),C("button",{disabled:a||n.trim().length===0,style:S.button,type:"submit",children:"Send"})]})]})};var at=/\/+$/,z=e=>{let t=e.sessionId,n=e.baseUrl.replace(at,""),r=o=>`${n}/endpoint/${encodeURIComponent(e.token)}${o}`,s={"content-type":"application/json"},a=(o,i)=>({url:r(o),headers:s,body:JSON.stringify({message:i,...t?{sessionId:t}:{},...e.identity?{externalUserId:e.identity.externalUserId,userHmac:e.identity.userHmac}:{}})});return{sessionId:()=>t,getInfo:()=>P(r("/config"),{}),sendMessage:async o=>{let i=await le(a("/message",o));return t=i.sessionId,i},streamMessage:(o,i,l)=>ue(a("/message/stream",o),i,u=>{t=u},l),subscribe:(o,i)=>{let l=i?.since??"0",u=!1,d,m=i?.intervalMs??3e3,p=async()=>{let g=t;if(g)try{let y=await P(r(`/messages?session=${encodeURIComponent(g)}&since=${encodeURIComponent(l)}`),{});for(let b of y.messages)o.onMessage(b);l=y.cursor,o.onHealthy?.()}catch(y){o.onError?.(w(y))}u||(d=setTimeout(p,m))},c=()=>{u=!0,d&&clearTimeout(d)};return i?.signal?.addEventListener("abort",c),d=setTimeout(p,0),c}}};var lt=e=>"transport"in e?e.transport:z(e);var ut=/^https?:\/\//i,dt=/^\d{4}-\d{2}-\d{2}(?:[T ]|$)/,pt=e=>e.replace(/_/g," ").replace(/\b\w/g,t=>t.toUpperCase());function ct(e){if(typeof e=="number")return"number";if(typeof e=="boolean")return"boolean";if(typeof e=="string"){if(ut.test(e))return"url";if(dt.test(e))return"date"}return"text"}function ge(e){let t=[],n=new Map;for(let r of e)for(let[s,a]of Object.entries(r.data??{})){if(a==null)continue;let o=n.get(s);o||(o=new Map,n.set(s,o),t.push(s));let i=ct(a);o.set(i,(o.get(i)??0)+1)}return t.map(r=>{let s=n.get(r)??new Map,a="text",o=-1;for(let[i,l]of s)l>o&&(o=l,a=i);return{key:r,label:pt(r),type:a}})}var mt=e=>typeof e=="number"?e:Number(e)||0,fe=e=>/rate|position|rank|score|percent|avg/i.test(e),gt=/posted|published|sent|completed|shipped|launched|_at/i,ft=new Set(["service","order","end_user_id"]);function ye(e,t){let n=e.filter(l=>!ft.has(l.key)),r=n.filter(l=>l.type==="number").slice(0,3),s=n.find(l=>l.key==="status")??n.find(l=>l.type==="select"),a=n.find(l=>l.type==="date"&&gt.test(l.key))??n.find(l=>l.type==="date"),o=n.filter(l=>l.type==="number"&&!fe(l.key)).map(l=>({field:l,total:t.reduce((u,d)=>u+mt(d.data[l.key]),0)})).sort((l,u)=>u.total-l.total).find(l=>l.total>0)?.field??null,i=[{type:"stat",label:"Items",agg:"count"}];for(let l of r){let u=fe(l.key);i.push({type:"stat",metric:l.key,agg:u?"avg":"sum",label:u?`Avg ${l.label.toLowerCase()}`:l.label})}return a&&i.push({type:"line",x:a.key,y:o?.key,agg:"sum",title:o?`${o.label} by day`:"Items by day"}),s&&i.push({type:"donut",groupBy:s.key,title:s.label}),i.push({type:"table",columns:n.map(l=>l.key)}),{version:1,widgets:i}}var be=6,he=6,xe=4,we={stat:{w:1,h:1},chart:{w:2,h:2},block:{w:6,h:2}},yt=e=>Math.max(1,Math.min(6,Math.round(e))),bt=e=>Math.max(1,Math.min(4,Math.round(e)));function W(e){return e==="stat"?"stat":e==="series"||e==="donut"?"chart":"block"}function Pe(e){return e==="stat"?"stat":e==="line"||e==="bar"||e==="donut"?"chart":"block"}function Se(e){return we[e]}function J(e,t,n){let r=we[e];return{w:t===void 0?r.w:yt(t),h:n===void 0?r.h:bt(n)}}function K(e){let t=[],n=[],r=(o,i,l,u)=>{if(o<0||o+l>6)return!1;for(let d=0;d<u;d+=1){let m=n[i+d];if(m){for(let p=0;p<l;p+=1)if(m[o+p])return!1}}return!0},s=(o,i,l,u)=>{for(let d=0;d<u;d+=1){let m=n[i+d]??[];for(let p=0;p<l;p+=1)m[o+p]=!0;n[i+d]=m}},a=(o,i)=>{for(let l=0;;l+=1)for(let u=0;u+o<=6;u+=1)if(r(u,l,o,i))return{gx:u,gy:l}};for(let o of e){let i=J(W(o.kind),o.w,o.h),u=o.gx!==void 0&&o.gy!==void 0&&r(o.gx,o.gy,i.w,i.h)&&o.gx!==void 0&&o.gy!==void 0?{gx:o.gx,gy:o.gy}:a(i.w,i.h);s(u.gx,u.gy,i.w,i.h),t.push({widget:o,gx:u.gx,gy:u.gy,w:i.w,h:i.h})}return t}function ve(e){let t=[],n=[];for(let r of e)W(r.kind)==="block"?n.push(r):t.push(r);return{tiles:K(t),blocks:n}}var ke=new Set(["service","order","end_user_id"]),X=e=>typeof e=="number"?e:Number(e)||0,Te=e=>e==null?"":String(e);function Y(e,t){if(e==="count")return t.length;if(t.length===0)return 0;if(e==="last")return t[t.length-1]??0;if(e==="min")return Math.min(...t);if(e==="max")return Math.max(...t);let n=t.reduce((r,s)=>r+s,0);return e==="avg"?Math.round(n/t.length*100)/100:n}function ht(e,t,n,r){let s=new Map;for(let a of e){let o=new Date(Te(a.data[t]));if(Number.isNaN(o.getTime()))continue;let i=o.toISOString().slice(0,10),l=s.get(i)??[];l.push(n?X(a.data[n]):1),s.set(i,l)}return[...s.entries()].sort((a,o)=>a[0]<o[0]?-1:1).map(([a,o])=>({label:new Date(`${a}T00:00:00`).toLocaleDateString(void 0,{month:"short",day:"numeric"}),value:n?Y(r,o):o.length}))}function xt(e,t,n,r="sum"){let s=new Map;for(let a of e){let o=Te(a.data[t]).trim();if(!o)continue;let i=s.get(o)??[];i.push(n?X(a.data[n]):1),s.set(o,i)}return[...s.entries()].map(([a,o])=>({label:a,value:n?Y(r,o):o.length})).sort((a,o)=>o.value-a.value)}function wt(e,t,n,r){switch(e.type){case"stat":{let s=e.metric?t.get(e.metric):void 0;if(e.metric&&!s)return null;if(!s)return{kind:"stat",label:e.label??"Items",value:r.length};let a=r.map(o=>X(o.data[s.key]));return{kind:"stat",label:e.label??s.label,value:Y(e.agg??"sum",a)}}case"line":case"bar":{if(!t.has(e.x)||e.y&&!t.has(e.y))return null;let s=ht(r,e.x,e.y,e.agg??"sum");return s.length<2?null:{kind:"series",draw:e.type,title:e.title??"By day",points:s}}case"donut":{if(!t.has(e.groupBy))return null;let s=xt(r,e.groupBy,e.metric,e.agg??"sum");return s.length===0?null:{kind:"donut",title:e.title??t.get(e.groupBy)?.label??"Breakdown",points:s}}case"table":{let s=e.columns?e.columns.map(a=>t.get(a)).filter(a=>a!==void 0&&!ke.has(a.key)):n;return s.length===0?null:{kind:"table",title:e.title,columns:s,rows:r}}case"text":return{kind:"text",title:e.title,body:e.body};default:return null}}function Ce(e,t,n,r={}){let s=new Map,a=l=>({byKey:new Map(l.fields.map(u=>[u.key,u])),cols:l.fields.filter(u=>!ke.has(u.key)),rows:l.rows}),o=a({fields:t,rows:n});for(let[l,u]of Object.entries(r))s.set(l,a(u));let i=[];for(let l of e.widgets){let u=l.type==="text"?void 0:l.source,d=u?s.get(u):o;if(!d)continue;let m=wt(l,d.byKey,d.cols,d.rows);m&&i.push({...m,w:l.w,h:l.h,gx:l.gx,gy:l.gy})}return i}var Pt=new Set(["sum","avg","count","min","max","last"]),Re=e=>typeof e=="string"&&Pt.has(e)?e:void 0,h=e=>typeof e=="string"&&e!==""?e:void 0,A=e=>typeof e=="number"&&e>=1?Math.min(6,Math.round(e)):void 0,M=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 St(e){if(typeof e!="object"||e===null)return null;let t=e;switch(t.type){case"stat":return{type:"stat",source:h(t.source),label:h(t.label),metric:h(t.metric)??h(t.column),agg:Re(t.agg),w:A(t.w),h:M(t.h),gx:k(t.gx),gy:k(t.gy)};case"line":case"bar":{let n=h(t.x);return n?{type:t.type,source:h(t.source),title:h(t.title),x:n,y:h(t.y)??h(t.column),agg:Re(t.agg),w:A(t.w),h:M(t.h),gx:k(t.gx),gy:k(t.gy)}:null}case"donut":{let n=h(t.groupBy)??h(t.column);return n?{type:"donut",source:h(t.source),title:h(t.title),groupBy:n,w:A(t.w),h:M(t.h),gx:k(t.gx),gy:k(t.gy)}:null}case"table":{let n=Array.isArray(t.columns)?t.columns.filter(r=>typeof r=="string"):void 0;return{type:"table",source:h(t.source),title:h(t.title),columns:n,w:A(t.w),h:M(t.h),gx:k(t.gx),gy:k(t.gy)}}case"text":{let n=h(t.body);return n?{type:"text",title:h(t.title),body:n,w:A(t.w),h:M(t.h),gx:k(t.gx),gy:k(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 n=t.widgets;if(!Array.isArray(n))return null;let r=n.map(St).filter(a=>a!==null);if(r.length===0)return null;let s=t.version;return{version:typeof s=="number"?s:1,title:h(t.title),widgets:r}}function Z(e){if(typeof e=="string")return e?{kind:"file",value:e}:null;if(e&&typeof e=="object"){let t=e,n=typeof t.value=="string"?t.value:"",r=t.kind==="link"||t.kind==="text"||t.kind==="table"?t.kind:"file",s=typeof t.v=="number"&&t.v>=1?Math.floor(t.v):void 0;return n?{kind:r,value:n,...s?{v:s}:{}}:null}return null}function ee(e){let t=new Map;for(let n of e){let r=n.v??1,s=t.get(r)??[];s.push(n),t.set(r,s)}return[...t.entries()].sort(([n],[r])=>n-r).map(([n,r])=>({v:n,items:r}))}function Ie(e){let t=e.files;if(typeof t=="string"&&t.trim()!=="")try{let r=JSON.parse(t);if(Array.isArray(r))return r.map(Z).filter(s=>s!==null)}catch{}let n=String(e.file??"");return n?[{kind:"file",value:n}]:[]}function Ae(e,t,n,r=""){let a=ee(e).find(i=>i.v===t)?.items??[],o=a.filter(i=>i.kind==="file").map(i=>n.get(i.value)??"");return a.some(i=>i.kind==="table")&&o.push(r),o.length===0||o.some(i=>i==="")?"awaiting":o.some(i=>i==="revise")?"revise":"accepted"}function Me(e){return Number(e.published_version)||0}function te(e){return e==="number"||e==="date"||e==="boolean"||e==="select"||e==="multi_select"||e==="url"?e:e==="link"?"url":e==="checkbox"?"boolean":"text"}function He(e){try{let t=JSON.parse(e);if(Array.isArray(t.columns)&&Array.isArray(t.rows)&&t.columns.length){let n=t.columns.map((a,o)=>({key:typeof a.key=="string"&&a.key?a.key:typeof a.id=="string"&&a.id?a.id:`column_${o+1}`,label:typeof a.label=="string"?a.label:"",type:te(a.type),...(()=>{let i=Array.isArray(a.options)?[...new Set(a.options.map(l=>String(l).trim()).filter(l=>l!==""))]:[];return i.length>0?{options:i}:{}})(),...a.clientEditable===!0?{clientEditable:!0}:{}})),r=t.rows.map((a,o)=>({id:typeof a.id=="string"&&a.id?a.id:`row_${o}`,cells:a.cells&&typeof a.cells=="object"?a.cells:{}})),s=typeof t.name=="string"?t.name:void 0;return{columns:n,rows:r,...s?{name:s}:{}}}}catch{}return null}function ne(e){return e==null?"":String(e)}function Ee(e){let t=ne(e).trim();if(t==="")return[];try{let n=JSON.parse(t);if(Array.isArray(n))return n.map(r=>String(r).trim()).filter(r=>r!=="")}catch{}return t.split(",").map(n=>n.trim()).filter(n=>n!=="")}function We(e){return e===!0||e==="true"||e==="1"||e==="yes"||e==="\u2713"}function $(){return{cells:{},verdict:"",comment:""}}function $e(e){if(typeof e!="string"||e.trim()==="")return $();try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t)){let n=t;return{cells:n.cells&&typeof n.cells=="object"?n.cells:n,verdict:n.verdict==="accepted"||n.verdict==="revise"?n.verdict:"",comment:typeof n.comment=="string"?n.comment:""}}}catch{}return $()}function Oe(e,t,n){if(e.clientEditable){let r=n.cells[t.id];if(r&&e.key in r)return r[e.key]}return t.cells[e.key]}function Fe(e,t,n,r){return{...e,cells:{...e.cells,[t]:{...e.cells[t]??{},[n]:r}}}}function _e(e,t,n){return{...e,verdict:t,comment:n}}function Le(e){let t=new Date(`${e}T00:00:00`);return Number.isNaN(t.getTime())?e:t.toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"})}var D=class extends Error{code;status;constructor(t,n,r){super(n),this.name="CreditRefused",this.code=t,this.status=r}},F=class extends D{credits;balance;short;constructor(t,n){super("insufficient_credits",t,402),this.name="InsufficientCredits",this.credits=n.credits,this.balance=n.balance,this.short=n.short}},vt=/\/+$/,kt="/api/v1/end-user",oe="Pre-payment",se="After-payment";function Tt(e,t){if(e<=0)return[];let n=t&&typeof t.upfront=="number"&&Number.isFinite(t.upfront)?Math.max(0,Math.min(t.upfront,e)):e,r=Math.round((e-n)*100)/100,s=[];return n>0&&s.push({label:oe,amount:n}),r>0&&s.push({label:se,amount:r}),s}var re=e=>e.status!=="paid"&&e.asked!==!1,Ct=(e,t)=>e.payMethods&&e.payMethods.length>0?[...e.payMethods]:[...t],Rt=(e,t)=>{let n=typeof t=="number"&&Number.isFinite(t)&&t>0?t:1;return!Number.isFinite(e)||e<=0?0:Math.ceil(e*n)},O=e=>{let t=e.label.trim().toLowerCase();return t===oe.toLowerCase()?0:t===se.toLowerCase()?2:1},Dt=(e,t,n)=>{let r=t.filter(p=>p.order===n),s=p=>p.reduce((c,g)=>c+g.amount,0),a=s(r),o=s(r.filter(p=>p.status==="paid")),i=e.value>0,l=[...r].sort((p,c)=>O(p)!==O(c)?O(p)-O(c):(p.dueDate||p.paidAt).localeCompare(c.dueDate||c.paidAt)),u=l.filter(re),d=l.filter(p=>p.status!=="paid"&&!re(p)),m=a>0?s(u):e.value-o;return{value:e.value,priced:i,billed:a,paid:o,due:Math.max(0,m),scheduled:s(d),lines:l,asked:u,upcoming:d,awaitingPayment:i&&o<=0}},It=e=>{let{credits:t,balance:n,short:r}=e;return typeof t!="number"||typeof n!="number"||typeof r!="number"||!(Number.isFinite(t)&&Number.isFinite(n)&&Number.isFinite(r))?null:{credits:t,balance:n,short:r}},At=e=>{let t=e.baseUrl.replace(vt,""),n=()=>typeof e.token=="function"?e.token():e.token,r=async(s,a={method:"GET"})=>{try{let o=await fetch(`${t}${kt}${s}`,{method:a.method,headers:{"content-type":"application/json",authorization:`Bearer ${await n()}`},...a.body===void 0?{}:{body:JSON.stringify(a.body)}});if(!o.ok){let i=await o.json().catch(()=>({})),l=i.message??`${a.method} ${s} \u2192 ${String(o.status)}`,u=It(i);throw o.status===402&&i.error==="insufficient_credits"&&u?new F(l,u):new D(i.error??"request_failed",l,o.status)}return await o.json()}catch(o){throw o instanceof D?o:w(o)}};return{wallet:()=>r("/credits"),history:()=>r("/credits/history"),topup:s=>r("/credits/checkout",{method:"POST",body:{packId:s}}),checkout:s=>r("/shop/checkout",{method:"POST",body:s}),payments:()=>r("/payments"),paymentMethods:()=>r("/payment-methods"),markPaymentSent:(s,a)=>r(`/payments/${encodeURIComponent(s)}/sent`,{method:"POST",body:{reference:a??""}}),payWithCredits:s=>r(`/payments/${encodeURIComponent(s)}/pay-with-credits`,{method:"POST",body:{}}),inquiryQuote:s=>r(`/inquiries/${encodeURIComponent(s)}/quote`),acceptInquiry:(s,a)=>r(`/inquiries/${encodeURIComponent(s)}/accept`,{method:"POST",body:{version:a}}),enquire:(s,a,o)=>r("/shop/enquire",{method:"POST",body:{productId:s,answers:a,name:o??""}})}};var Mt=/\/+$/,R="/api/v1/end-user",H=class extends Error{constructor(t){super(t),this.name="PortalConflict"}};function Ht(e){let t="";for(let r=0;r<e.length;r+=32768)t+=String.fromCharCode(...e.subarray(r,r+32768));return btoa(t)}var Et=e=>{let t=e.baseUrl.replace(Mt,""),n=()=>typeof e.token=="function"?e.token():e.token,r=async()=>({"content-type":"application/json",authorization:`Bearer ${await n()}`}),s=async(o,i)=>{try{let l=await fetch(`${t}${R}${o}`,{method:i.method,headers:await r(),...i.body===void 0?{}:{body:JSON.stringify(i.body)}});if(l.status===409){let u=await l.json().catch(()=>({}));throw new H(u.message??"Someone else saved this first.")}if(!l.ok){let u=await l.text().catch(()=>""),d=`${i.method} ${o} \u2192 ${String(l.status)}`;try{let m=JSON.parse(u);m.message&&(d=m.message)}catch{d=u?`${d}: ${u}`:d}throw w({error:d})}return await l.json()}catch(l){throw l instanceof H?l:w(l)}},a=o=>`/tables/${encodeURIComponent(o)}`;return{listTables:async()=>(await P(`${t}${R}/tables`,await r())).tables,listRows:async(o,i)=>await P(`${t}${R}${a(o)}/rows?limit=${String(i??100)}`,await r()),insertRow:async(o,i)=>{let{rowIds:l}=await s(`${a(o)}/rows`,{method:"POST",body:{rows:[i]}}),u=l[0];if(!u)throw w(new Error("The row was not created."));return u},patchRow:async(o,i,l)=>(await s(`${a(o)}/rows/${encodeURIComponent(i)}`,{method:"PATCH",body:l})).updated,deleteRow:async(o,i)=>(await s(`/${encodeURIComponent(o)}/${encodeURIComponent(i)}`,{method:"DELETE"})).deleted,listFiles:async()=>(await P(`${t}${R}/tables/files/rows?limit=200`,await r())).rows.map(i=>({id:i.rowId,filename:String(i.data.filename??""),source:String(i.data.source??"client"),campaign:String(i.data.campaign??""),size:typeof i.data.size=="number"?i.data.size:0,createdAt:i.createdAt})),uploadFile:async(o,i)=>{let l=new Uint8Array(await o.arrayBuffer());return await s("/files",{method:"POST",body:{filename:o.name,mime:o.type||"application/octet-stream",data:Ht(l),...i===void 0?{}:{message:i}}})},fileLink:async o=>await P(`${t}${R}/files/${encodeURIComponent(o)}/url`,await r()),deleteFile:async o=>(await s(`/files/${encodeURIComponent(o)}`,{method:"DELETE"})).deleted,listDocuments:async()=>(await P(`${t}${R}/documents`,await r())).documents,readDocument:async o=>(await P(`${t}${R}/documents/${encodeURIComponent(o)}`,await r())).document,saveDocument:async(o,i)=>await s(`/documents/${encodeURIComponent(o)}`,{method:"PATCH",body:i})}};var Wt=/\/+$/,$t="/api/v1/end-user",Ot=e=>{let t=e.baseUrl.replace(Wt,""),n=async(r,s)=>{let a;try{a=await fetch(`${t}${$t}${r}`,s===void 0?{}:{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(s)})}catch(o){throw w(o)}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(o){throw w(o)}};return{listProducts:async()=>{let r=await n(`/shop/products?publishable_key=${encodeURIComponent(e.publishableKey)}`);return{products:r.products.map(s=>({...s,currency:typeof s.currency=="string"?s.currency:""})),truncated:r.truncated===!0,enquiryForm:Array.isArray(r.enquiryForm)?r.enquiryForm:[]}},apply:async r=>await n("/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}:{}})}};var Ft=new Set(["buy","ask"]);function _t(e){return Ft.has(e.mode)?e.mode:"ask"}var Lt={kind:"quoted"};function _(e,t){if(!t)return e.toLocaleString();if(t.toLowerCase()==="credits")return`${e.toLocaleString()} ${e===1?"credit":"credits"}`;let n=Number.isInteger(e)?0:2;try{return new Intl.NumberFormat(void 0,{style:"currency",currency:t,minimumFractionDigits:n,maximumFractionDigits:n}).format(e)}catch{return`${t} ${e.toLocaleString()}`}}function Ue(e,t){let n=/^[a-z]+$/i.test(t)&&!t.endsWith("s")?"s":"";return`${e.toLocaleString()} ${t}${n}`}function Ne(e,t){return e.kind==="quoted"?"Priced on enquiry":e.kind==="flat"?_(e.price,t):`${_(e.unitPrice,t)} per ${e.unitStep===1?e.unit:Ue(e.unitStep,e.unit)}`}function Ut(e){let t=e.currency,n=e.pricing;if(n.kind!=="variants")return Ne(n,t);let r=n.variants.map(s=>s.price).filter(s=>typeof s=="number");return r.length>0?`From ${_(Math.min(...r),t)}`:"Priced on enquiry"}function Nt(e,t){if(e.kind!=="variants")return e;let n=e.variants.find(r=>r.name===t);return typeof n?.price=="number"?{kind:"flat",price:n.price}:Lt}function qt(e,t){return e.kind==="flat"?e.price:e.kind==="per_unit"?e.unitPrice*Math.ceil(t/Math.max(e.unitStep,1)):null}function Vt(e,t){let n=t.kind==="per_unit"?Math.max(t.unitStep,1):1;return{min:Math.max(e.minQty??n,n),max:e.maxQty??null,step:n}}function Bt(e,t){let n=e.variants?.find(r=>r.name===t);return n&&n.includes.length>0?n.includes:e.includes}function jt(e,t){let n=[];for(let r of e){let s=t(r).trim();s&&!n.includes(s)&&n.push(s)}return n}function Gt(e,t,n,r){let s=t?`${e.name} \u2014 ${t}`:e.name,a=n.kind==="per_unit"?`, ${Ue(r,n.unit)}`:"";return`I'd like to buy ${s}${a}. How do I go ahead?`}function Qt(e){return e?(e&&typeof e=="object"&&"error"in e?String(e.error):"")==="rate_limited"?"That's a lot of looking at once \u2014 give it a moment, then reload.":"The shop isn't loading right now. Please try again shortly.":null}import{useCallback as qe,useEffect as zt,useState as ie}from"react";var Jt=e=>{let[t,n]=ie(null),[r,s]=ie(!0),[a,o]=ie(null),i=qe(async()=>{try{n(await e.wallet()),o(null)}catch{o("Couldn't read your balance just now.")}finally{s(!1)}},[e]),l=qe(()=>{i().catch(()=>{})},[i]);return zt(()=>(l(),window.addEventListener("focus",l),()=>{window.removeEventListener("focus",l)}),[l]),{wallet:t,loading:r,failure:a,refresh:l}};import{useCallback as Kt,useEffect as Xt,useState as I}from"react";var Yt=e=>e&&typeof e=="object"&&typeof e.error=="string"?e.error:e instanceof Error?e.message:"shop_unavailable",Zt=e=>{let[t,n]=I([]),[r,s]=I([]),[a,o]=I(!1),[i,l]=I(!0),[u,d]=I(null),[m,p]=I(0);Xt(()=>{let g=!0;return l(!0),e.listProducts().then(y=>{g&&(n(y.products),s(y.enquiryForm),o(y.truncated),d(null))}).catch(y=>{g&&d(Yt(y))}).finally(()=>{g&&l(!1)}),()=>{g=!1}},[e,m]);let c=Kt(()=>p(g=>g+1),[]);return{products:t,enquiryForm:r,truncated:a,loading:i,error:u,reload:c}};import{useCallback as en,useEffect as Ve,useRef as tn,useState as L}from"react";var Be="greeting";function je(e,t){if(e.some(a=>a.id===t.id))return e;let n=e.filter(a=>a.id!==Be),r=a=>a.author==="client"==(t.author==="client");return[...n.filter(a=>!(a.pending&&r(a)&&a.text===t.text)),t]}var nn=(e,t)=>{let[n,r]=L([]),[s,a]=L(""),[o,i]=L(!1),[l,u]=L(null),d=tn(0),m=t?.pollMs??2e3;Ve(()=>{let c=!0;return e.getInfo().then(g=>{c&&g.greeting&&r(y=>y.length===0?[{id:Be,cursor:"",author:"agent",text:g.greeting}]:y)}).catch(()=>{}),()=>{c=!1}},[e]),Ve(()=>e.subscribe?.({onMessage:c=>r(g=>je(g,c)),onError:c=>u(c.error),onHealthy:()=>u(null)},{intervalMs:m}),[e,m]);let p=en(()=>{let c=s.trim();if(!c||o)return;a(""),u(null),i(!0),d.current+=1;let g=`pending-${d.current}`,y={id:g,cursor:"",author:"client",text:c,pending:!0};r(b=>[...b,y]),e.sendMessage(c).then(b=>{i(!1),b.reply.trim()&&r(f=>f.some(T=>!T.pending&&T.author!=="client"&&T.text===b.reply)?f:(d.current+=1,[...f,{id:`pending-agent-${d.current}`,cursor:"",author:"agent",text:b.reply,pending:!0}]))}).catch(b=>{u(b instanceof Error?b.message:"send_failed"),i(!1),r(v=>v.filter(f=>f.id!==g)),a(v=>v||c)})},[s,o,e]);return{messages:n,input:s,setInput:a,send:p,sending:o,error:l}};export{it as Chat,D as CreditRefused,be as GRID_COLS,he as GRID_MAX_COLS,xe as GRID_MAX_ROWS,tt as HolaProvider,F as InsufficientCredits,H as PortalConflict,se as QUOTE_BALANCE_LABEL,oe as QUOTE_DEPOSIT_LABEL,W as bandOfKind,Pe as bandOfType,Gt as buyRequestText,Oe as cellValue,Ke as createApiTransport,lt as createHolaClient,At as createPortalCredits,Et as createPortalData,Ot as createPortalShop,z as createWidgetTransport,Rt as creditsOfMoney,ne as deliverableCellText,Ee as deliverableCellValues,Ae as deliverableStatus,ge as deriveFields,$ as emptyTableResponses,jt as facetValues,Se as footprintOf,J as footprintWith,Le as formatDeliverableDate,ee as groupDeliverableVersions,Bt as includesFor,ye as inferSpec,We as isDeliverableChecked,je as mergeMessage,_t as modeOf,_ as money,te as normalizeDeliverableColType,Z as normalizeDeliverableItem,Dt as orderBilling,De as parseDashboardSpec,Ie as parseDeliverableItems,He as parseDeliverableTable,$e as parseTableResponses,re as paymentAsked,Ct as paymentPayMethods,K as placeWidgets,Nt as priceFor,Ne as priceLabel,Me as publishedVersionOf,Vt as quantityRange,Tt as quoteSchedule,Ce as renderModel,Fe as setResponse,_e as setTableReview,Ut as shelfPriceLabel,Qt as shelfProblem,ve as splitLayout,U as textDeltaOf,N as thinkingDeltaOf,q as toolEventOf,qt as totalFor,B as useArtifactUrl,G as useChat,Jt as useCredits,j as useHolaClient,Zt as useShop,nn as useThread};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holaboss/client",
3
- "version": "0.2.0-beta.30",
3
+ "version": "0.2.0-beta.32",
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",