@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 +5 -5
- package/dist/index.d.cts +214 -15
- package/dist/index.d.ts +214 -15
- package/dist/index.js +5 -5
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use client'
|
|
2
|
-
var
|
|
3
|
-
`))r.startsWith(":")||(r.startsWith("event:")?t=r.slice(6).trim():r.startsWith("data:")&&n.push(r.slice(5).replace(
|
|
4
|
-
`)}:null},
|
|
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
|
|
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.
|
|
552
|
-
|
|
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
|
-
/**
|
|
1033
|
-
*
|
|
1034
|
-
*
|
|
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
|
-
/**
|
|
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.
|
|
552
|
-
|
|
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
|
-
/**
|
|
1033
|
-
*
|
|
1034
|
-
*
|
|
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
|
-
/**
|
|
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
|
|
3
|
-
`))r.startsWith(":")||(r.startsWith("event:")?t=r.slice(6).trim():r.startsWith("data:")&&n.push(r.slice(5).replace(
|
|
4
|
-
`)}:null},
|
|
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
|
|
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"&>.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.
|
|
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",
|