@holaboss/client 0.2.0-beta.28 → 0.2.0-beta.30
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 +157 -6
- package/dist/index.d.ts +157 -6
- 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 ee=Object.defineProperty;var
|
|
3
|
-
`))
|
|
4
|
-
`)}:null},
|
|
2
|
+
var ee=Object.defineProperty;var lt=Object.getOwnPropertyDescriptor;var ut=Object.getOwnPropertyNames;var dt=Object.prototype.hasOwnProperty;var pt=(e,t)=>{for(var n in t)ee(e,n,{get:t[n],enumerable:!0})},ct=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of ut(t))!dt.call(e,s)&&s!==n&&ee(e,s,{get:()=>t[s],enumerable:!(r=lt(t,s))||r.enumerable});return e};var mt=e=>ct(ee({},"__esModule",{value:!0}),e);var Bt={};pt(Bt,{Chat:()=>Oe,CreditRefused:()=>E,GRID_COLS:()=>oe,GRID_MAX_COLS:()=>se,GRID_MAX_ROWS:()=>ie,HolaProvider:()=>$e,PortalConflict:()=>M,QUOTE_BALANCE_LABEL:()=>Ce,QUOTE_DEPOSIT_LABEL:()=>ke,bandOfKind:()=>$,bandOfType:()=>ae,buyRequestText:()=>nt,cellValue:()=>Se,createApiTransport:()=>Ee,createHolaClient:()=>Fe,createPortalCredits:()=>je,createPortalData:()=>Ge,createPortalShop:()=>Qe,createWidgetTransport:()=>z,deliverableCellText:()=>he,deliverableStatus:()=>fe,deriveFields:()=>ne,emptyTableResponses:()=>F,facetValues:()=>tt,footprintOf:()=>le,footprintWith:()=>J,formatDeliverableDate:()=>Te,groupDeliverableVersions:()=>Y,includesFor:()=>et,inferSpec:()=>re,isDeliverableChecked:()=>xe,mergeMessage:()=>De,modeOf:()=>ze,money:()=>_,normalizeDeliverableColType:()=>Z,normalizeDeliverableItem:()=>X,orderBilling:()=>Ve,parseDashboardSpec:()=>me,parseDeliverableItems:()=>ge,parseDeliverableTable:()=>be,parseTableResponses:()=>we,placeWidgets:()=>K,priceFor:()=>Xe,priceLabel:()=>Re,publishedVersionOf:()=>ye,quantityRange:()=>Ze,quoteSchedule:()=>Be,renderModel:()=>ce,setResponse:()=>ve,setTableReview:()=>Pe,shelfPriceLabel:()=>Ke,shelfProblem:()=>rt,splitLayout:()=>ue,textDeltaOf:()=>L,thinkingDeltaOf:()=>U,toolEventOf:()=>q,totalFor:()=>Ye,useArtifactUrl:()=>B,useChat:()=>G,useCredits:()=>ot,useHolaClient:()=>j,useShop:()=>st,useThread:()=>at});module.exports=mt(Bt);var Ie=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="message_update"?t.assistantMessageEvent??null:null},L=e=>{let t=Ie(e);return t?.type==="text_delta"&&typeof t.delta=="string"?t.delta:null},U=e=>{let t=Ie(e);return t?.type==="thinking_delta"&&typeof t.delta=="string"?t.delta:null},q=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="tool_execution_start"&&t.toolCallId?{phase:"start",id:t.toolCallId,name:t.toolName}:t.type==="tool_execution_end"&&t.toolCallId?{phase:"end",id:t.toolCallId,isError:t.isError}:null};var gt=/^ /,w=e=>{if(e&&typeof e=="object"){let t=e,n=typeof t.error=="string"?t.error:"request_failed";return typeof t.retryable=="boolean"?{error:n,retryable:t.retryable}:{error:n}}return{error:"request_failed"}},ft=e=>{let t="message",n=[];for(let r of e.split(`
|
|
3
|
+
`))r.startsWith(":")||(r.startsWith("event:")?t=r.slice(6).trim():r.startsWith("data:")&&n.push(r.slice(5).replace(gt,"")));return n.length>0?{event:t,data:n.join(`
|
|
4
|
+
`)}:null},yt=(e,t,n)=>{let r;try{r=JSON.parse(e.data)}catch{return}if(e.event==="session"){let s=r.sessionId;s&&(n(s),t.onSession?.(s));return}if(e.event==="turn_event"){t.onEvent?.(r);let s=L(r);s&&t.onText?.(s);let i=U(r);i&&t.onThinking?.(i);let o=q(r);o&&t.onTool?.(o);return}if(e.event==="chat_completed"){let s=r;n(s.sessionId),t.onComplete?.(s);return}e.event==="chat_error"&&t.onError?.(w(r))},P=async(e,t)=>{let n=await fetch(e,{headers:t});if(!n.ok)throw new Error(`hola: request failed (${n.status})`);return await n.json()},Ae=async e=>{let t=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body});if(!t.ok)throw new Error(`hola: message failed (${t.status})`);return await t.json()},He=async(e,t,n,r)=>{let s=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body,signal:r});if(!(s.ok&&s.body)){t.onError?.({error:`stream_failed_${s.status}`});return}let i=s.body.getReader(),o=new TextDecoder,a="",l=()=>{let d=a.indexOf(`
|
|
5
5
|
|
|
6
|
-
`);for(;d!==-1;){let p=a.slice(0,d);a=a.slice(d+2);let f=
|
|
6
|
+
`);for(;d!==-1;){let p=a.slice(0,d);a=a.slice(d+2);let f=ft(p);f&&yt(f,t,n),d=a.indexOf(`
|
|
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 gt=/\/+$/,te="/api/v1/end-user",Ae=e=>{let t=e.baseUrl.replace(gt,""),r=()=>typeof e.token=="function"?e.token():e.token,n=o=>e.project?`${o}project=${encodeURIComponent(e.project)}`:"",s=async()=>({"content-type":"application/json",authorization:`Bearer ${await r()}`}),i=async o=>{let a=await fetch(`${t}${te}/chat${n("?")}`,{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${n("?")}`,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)}${n("&")}`,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 q=require("react"),V=(e,t)=>{let[r,n]=(0,q.useState)("");return(0,q.useEffect)(()=>{if(!e){n("");return}let s=Uint8Array.from(atob(e),o=>o.charCodeAt(0)),i=URL.createObjectURL(new Blob([s],{type:t}));return n(i),()=>URL.revokeObjectURL(i)},[e,t]),r};var z=require("react");var j=require("react"),$e=require("react/jsx-runtime"),He=(0,j.createContext)(null),Me=({client:e,children:t})=>(0,$e.jsx)(He.Provider,{value:e,children:t}),B=()=>{let e=(0,j.useContext)(He);if(!e)throw new Error("useHolaClient must be used within <HolaProvider>");return e};var v=require("react"),G=e=>{let[t,r]=(0,v.useState)([]),[n,s]=(0,v.useState)(""),[i,o]=(0,v.useState)(!1),[a,l]=(0,v.useState)(null),u=(0,v.useRef)(0),d=(0,v.useRef)(null);(0,v.useEffect)(()=>()=>d.current?.abort(),[]);let p=(0,v.useCallback)(()=>{let c=u.current;return u.current+=1,c},[]);(0,v.useEffect)(()=>{let c=!0;return e.getInfo().then(m=>{c&&m.greeting&&r([{id:p(),role:"assistant",text:m.greeting}])}).catch(()=>{}),()=>{c=!1}},[e,p]);let f=(0,v.useCallback)(()=>{let c=n.trim();if(!c||i)return;s(""),l(null),o(!0);let m=p(),y=p();r(g=>[...g,{id:m,role:"user",text:c},{id:y,role:"assistant",text:"",streaming:!0}]);let b=g=>{r(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)})},[n,i,e,p]);return{messages:t,input:n,setInput:s,send:f,sending:i,error:a}};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"}},ft=({artifact:e})=>{let t=V(e.dataBase64??"",e.mimeType),r=e.url??t;return r?e.mimeType.startsWith("image/")?(0,S.jsx)("a",{href:r,rel:"noopener noreferrer",target:"_blank",children:(0,S.jsx)("img",{alt:e.filename,src:r,style:T.image})}):(0,S.jsx)("a",{download:e.filename,href:r,style:T.link,children:e.filename}):null},We=()=>{let e=B(),{messages:t,input:r,setInput:n,send:s,sending:i,error:o}=G(e),a=(0,z.useRef)(null);(0,z.useEffect)(()=>{let u=a.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:a,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)(ft,{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=>n(u.target.value),placeholder:"Type a message\u2026",style:T.input,value:r}),(0,S.jsx)("button",{disabled:i||r.trim().length===0,style:T.button,type:"submit",children:"Send"})]})]})};var yt=/\/+$/,J=e=>{let t=e.sessionId,r=e.baseUrl.replace(yt,""),n=o=>`${r}/endpoint/${encodeURIComponent(e.token)}${o}`,s={"content-type":"application/json"},i=(o,a)=>({url:n(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(n("/config"),{}),sendMessage:async o=>{let a=await De(i("/message",o));return t=a.sessionId,a},streamMessage:(o,a,l)=>Ie(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(n(`/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 Ee=e=>"transport"in e?e.transport:J(e);var bt=/^https?:\/\//i,ht=/^\d{4}-\d{2}-\d{2}(?:[T ]|$)/,xt=e=>e.replace(/_/g," ").replace(/\b\w/g,t=>t.toUpperCase());function wt(e){if(typeof e=="number")return"number";if(typeof e=="boolean")return"boolean";if(typeof e=="string"){if(bt.test(e))return"url";if(ht.test(e))return"date"}return"text"}function re(e){let t=[],r=new Map;for(let n of e)for(let[s,i]of Object.entries(n.data??{})){if(i==null)continue;let o=r.get(s);o||(o=new Map,r.set(s,o),t.push(s));let a=wt(i);o.set(a,(o.get(a)??0)+1)}return t.map(n=>{let s=r.get(n)??new Map,i="text",o=-1;for(let[a,l]of s)l>o&&(o=l,i=a);return{key:n,label:xt(n),type:i}})}var vt=e=>typeof e=="number"?e:Number(e)||0,Fe=e=>/rate|position|rank|score|percent|avg/i.test(e),St=/posted|published|sent|completed|shipped|launched|_at/i,Pt=new Set(["service","order","end_user_id"]);function ne(e,t){let r=e.filter(l=>!Pt.has(l.key)),n=r.filter(l=>l.type==="number").slice(0,3),s=r.find(l=>l.key==="status")??r.find(l=>l.type==="select"),i=r.find(l=>l.type==="date"&&St.test(l.key))??r.find(l=>l.type==="date"),o=r.filter(l=>l.type==="number"&&!Fe(l.key)).map(l=>({field:l,total:t.reduce((u,d)=>u+vt(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 n){let u=Fe(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:r.map(l=>l.key)}),{version:1,widgets:a}}var oe=6,se=6,ie=4,Oe={stat:{w:1,h:1},chart:{w:2,h:2},block:{w:6,h:2}},kt=e=>Math.max(1,Math.min(6,Math.round(e))),Tt=e=>Math.max(1,Math.min(4,Math.round(e)));function W(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 Oe[e]}function K(e,t,r){let n=Oe[e];return{w:t===void 0?n.w:kt(t),h:r===void 0?n.h:Tt(r)}}function X(e){let t=[],r=[],n=(o,a,l,u)=>{if(o<0||o+l>6)return!1;for(let d=0;d<u;d+=1){let p=r[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=r[a+d]??[];for(let f=0;f<l;f+=1)p[o+f]=!0;r[a+d]=p}},i=(o,a)=>{for(let l=0;;l+=1)for(let u=0;u+o<=6;u+=1)if(n(u,l,o,a))return{gx:u,gy:l}};for(let o of e){let a=K(W(o.kind),o.w,o.h),u=o.gx!==void 0&&o.gy!==void 0&&n(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=[],r=[];for(let n of e)W(n.kind)==="block"?r.push(n):t.push(n);return{tiles:X(t),blocks:r}}var _e=new Set(["service","order","end_user_id"]),de=e=>typeof e=="number"?e:Number(e)||0,Le=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 r=t.reduce((n,s)=>n+s,0);return e==="avg"?Math.round(r/t.length*100)/100:r}function Ct(e,t,r,n){let s=new Map;for(let i of e){let o=new Date(Le(i.data[t]));if(Number.isNaN(o.getTime()))continue;let a=o.toISOString().slice(0,10),l=s.get(a)??[];l.push(r?de(i.data[r]):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:r?pe(n,o):o.length}))}function Rt(e,t,r,n="sum"){let s=new Map;for(let i of e){let o=Le(i.data[t]).trim();if(!o)continue;let a=s.get(o)??[];a.push(r?de(i.data[r]):1),s.set(o,a)}return[...s.entries()].map(([i,o])=>({label:i,value:r?pe(n,o):o.length})).sort((i,o)=>o.value-i.value)}function Dt(e,t,r,n){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:n.length};let i=n.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=Ct(n,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=Rt(n,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&&!_e.has(i.key)):r;return s.length===0?null:{kind:"table",title:e.title,columns:s,rows:n}}case"text":return{kind:"text",title:e.title,body:e.body};default:return null}}function ce(e,t,r,n={}){let s=new Map,i=l=>({byKey:new Map(l.fields.map(u=>[u.key,u])),cols:l.fields.filter(u=>!_e.has(u.key)),rows:l.rows}),o=i({fields:t,rows:r});for(let[l,u]of Object.entries(n))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=Dt(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 It=new Set(["sum","avg","count","min","max","last"]),Ue=e=>typeof e=="string"&&It.has(e)?e:void 0,h=e=>typeof e=="string"&&e!==""?e:void 0,E=e=>typeof e=="number"&&e>=1?Math.min(6,Math.round(e)):void 0,F=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 At(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:Ue(t.agg),w:E(t.w),h:F(t.h),gx:D(t.gx),gy:D(t.gy)};case"line":case"bar":{let r=h(t.x);return r?{type:t.type,source:h(t.source),title:h(t.title),x:r,y:h(t.y)??h(t.column),agg:Ue(t.agg),w:E(t.w),h:F(t.h),gx:D(t.gx),gy:D(t.gy)}:null}case"donut":{let r=h(t.groupBy)??h(t.column);return r?{type:"donut",source:h(t.source),title:h(t.title),groupBy:r,w:E(t.w),h:F(t.h),gx:D(t.gx),gy:D(t.gy)}:null}case"table":{let r=Array.isArray(t.columns)?t.columns.filter(n=>typeof n=="string"):void 0;return{type:"table",source:h(t.source),title:h(t.title),columns:r,w:E(t.w),h:F(t.h),gx:D(t.gx),gy:D(t.gy)}}case"text":{let r=h(t.body);return r?{type:"text",title:h(t.title),body:r,w:E(t.w),h:F(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 r=t.widgets;if(!Array.isArray(r))return null;let n=r.map(At).filter(i=>i!==null);if(n.length===0)return null;let s=t.version;return{version:typeof s=="number"?s:1,title:h(t.title),widgets:n}}function Q(e){if(typeof e=="string")return e?{kind:"file",value:e}:null;if(e&&typeof e=="object"){let t=e,r=typeof t.value=="string"?t.value:"",n=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 r?{kind:n,value:r,...s?{v:s}:{}}:null}return null}function Y(e){let t=new Map;for(let r of e){let n=r.v??1,s=t.get(n)??[];s.push(r),t.set(n,s)}return[...t.entries()].sort(([r],[n])=>r-n).map(([r,n])=>({v:r,items:n}))}function ge(e){let t=e.files;if(typeof t=="string"&&t.trim()!=="")try{let n=JSON.parse(t);if(Array.isArray(n))return n.map(Q).filter(s=>s!==null)}catch{}let r=String(e.file??"");return r?[{kind:"file",value:r}]:[]}function fe(e,t,r,n=""){let i=Y(e).find(a=>a.v===t)?.items??[],o=i.filter(a=>a.kind==="file").map(a=>r.get(a.value)??"");return i.some(a=>a.kind==="table")&&o.push(n),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 r=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}:{}})),n=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:r,rows:n,...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 O(){return{cells:{},verdict:"",comment:""}}function we(e){if(typeof e!="string"||e.trim()==="")return O();try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t)){let r=t;return{cells:r.cells&&typeof r.cells=="object"?r.cells:r,verdict:r.verdict==="accepted"||r.verdict==="revise"?r.verdict:"",comment:typeof r.comment=="string"?r.comment:""}}}catch{}return O()}function ve(e,t,r){if(e.clientEditable){let n=r.cells[t.id];if(n&&e.key in n)return n[e.key]}return t.cells[e.key]}function Se(e,t,r,n){return{...e,cells:{...e.cells,[t]:{...e.cells[t]??{},[r]:n}}}}function Pe(e,t,r){return{...e,verdict:t,comment:r}}function ke(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,r,n){super(r),this.name="CreditRefused",this.code=t,this.status=n}},Ht=/\/+$/,Mt="/api/v1/end-user",Ne=(e,t,r)=>{let n=t.filter(l=>l.order===r),s=n.reduce((l,u)=>l+u.amount,0),i=n.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:[...n].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}},qe=e=>{let t=e.baseUrl.replace(Ht,""),r=()=>typeof e.token=="function"?e.token():e.token,n=async(s,i={method:"GET"})=>{try{let o=await fetch(`${t}${Mt}${s}`,{method:i.method,headers:{"content-type":"application/json",authorization:`Bearer ${await r()}`},...i.body===void 0?{}:{body:JSON.stringify(i.body)}});if(!o.ok){let a=await o.json().catch(()=>({}));throw new M(a.error??"request_failed",a.message??`${i.method} ${s} \u2192 ${String(o.status)}`,o.status)}return await o.json()}catch(o){throw o instanceof M?o:w(o)}};return{wallet:()=>n("/credits"),history:()=>n("/credits/history"),topup:s=>n("/credits/checkout",{method:"POST",body:{packId:s}}),checkout:s=>n("/shop/checkout",{method:"POST",body:s}),payments:()=>n("/payments"),paymentMethods:()=>n("/payment-methods"),markPaymentSent:(s,i)=>n(`/payments/${encodeURIComponent(s)}/sent`,{method:"POST",body:{reference:i??""}}),acceptInquiry:s=>n(`/inquiries/${encodeURIComponent(s)}/accept`,{method:"POST"}),enquire:(s,i,o)=>n("/shop/enquire",{method:"POST",body:{productId:s,answers:i,name:o??""}})}};var $t=/\/+$/,H="/api/v1/end-user",$=class extends Error{constructor(t){super(t),this.name="PortalConflict"}};function Wt(e){let t="";for(let n=0;n<e.length;n+=32768)t+=String.fromCharCode(...e.subarray(n,n+32768));return btoa(t)}var Ve=e=>{let t=e.baseUrl.replace($t,""),r=()=>typeof e.token=="function"?e.token():e.token,n=async()=>({"content-type":"application/json",authorization:`Bearer ${await r()}`}),s=async(o,a)=>{try{let l=await fetch(`${t}${H}${o}`,{method:a.method,headers:await n(),...a.body===void 0?{}:{body:JSON.stringify(a.body)}});if(l.status===409){let u=await l.json().catch(()=>({}));throw new $(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 $?l:w(l)}},i=o=>`/tables/${encodeURIComponent(o)}`;return{listTables:async()=>(await P(`${t}${H}/tables`,await n())).tables,listRows:async(o,a)=>await P(`${t}${H}${i(o)}/rows?limit=${String(a??100)}`,await n()),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 n())).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:Wt(l),...a===void 0?{}:{message:a}}})},fileLink:async o=>await P(`${t}${H}/files/${encodeURIComponent(o)}/url`,await n()),deleteFile:async o=>(await s(`/files/${encodeURIComponent(o)}`,{method:"DELETE"})).deleted,listDocuments:async()=>(await P(`${t}${H}/documents`,await n())).documents,readDocument:async o=>(await P(`${t}${H}/documents/${encodeURIComponent(o)}`,await n())).document,saveDocument:async(o,a)=>await s(`/documents/${encodeURIComponent(o)}`,{method:"PATCH",body:a})}};var Et=/\/+$/,Ft="/api/v1/end-user",je=e=>{let t=e.baseUrl.replace(Et,""),r=async(n,s)=>{let i;try{i=await fetch(`${t}${Ft}${n}`,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 n=await r(`/shop/products?publishable_key=${encodeURIComponent(e.publishableKey)}`);return{products:n.products.map(s=>({...s,currency:typeof s.currency=="string"?s.currency:""})),truncated:n.truncated===!0,enquiryForm:Array.isArray(n.enquiryForm)?n.enquiryForm:[]}},apply:async n=>await r("/shop/apply",{publishable_key:e.publishableKey,name:n.name,email:n.email,...n.phone?{phone:n.phone}:{},...n.message?{message:n.message}:{},...n.productId?{productId:n.productId}:{}})}};var Ot=new Set(["buy","ask"]);function Be(e){return Ot.has(e.mode)?e.mode:"ask"}var _t={kind:"quoted"};function _(e,t){if(!t)return e.toLocaleString();if(t.toLowerCase()==="credits")return`${e.toLocaleString()} ${e===1?"credit":"credits"}`;let r=Number.isInteger(e)?0:2;try{return new Intl.NumberFormat(void 0,{style:"currency",currency:t,minimumFractionDigits:r,maximumFractionDigits:r}).format(e)}catch{return`${t} ${e.toLocaleString()}`}}function Ge(e,t){let r=/^[a-z]+$/i.test(t)&&!t.endsWith("s")?"s":"";return`${e.toLocaleString()} ${t}${r}`}function Te(e,t){return e.kind==="quoted"?"Priced on enquiry":e.kind==="flat"?_(e.price,t):`${_(e.unitPrice,t)} per ${e.unitStep===1?e.unit:Ge(e.unitStep,e.unit)}`}function ze(e){let t=e.currency,r=e.pricing;if(r.kind!=="variants")return Te(r,t);let n=r.variants.map(s=>s.price).filter(s=>typeof s=="number");return n.length>0?`From ${_(Math.min(...n),t)}`:"Priced on enquiry"}function Je(e,t){if(e.kind!=="variants")return e;let r=e.variants.find(n=>n.name===t);return typeof r?.price=="number"?{kind:"flat",price:r.price}:_t}function Ke(e,t){return e.kind==="flat"?e.price:e.kind==="per_unit"?e.unitPrice*Math.ceil(t/Math.max(e.unitStep,1)):null}function Xe(e,t){let r=t.kind==="per_unit"?Math.max(t.unitStep,1):1;return{min:Math.max(e.minQty??r,r),max:e.maxQty??null,step:r}}function Qe(e,t){let r=e.variants?.find(n=>n.name===t);return r&&r.includes.length>0?r.includes:e.includes}function Ye(e,t){let r=[];for(let n of e){let s=t(n).trim();s&&!r.includes(s)&&r.push(s)}return r}function Ze(e,t,r,n){let s=t?`${e.name} \u2014 ${t}`:e.name,i=r.kind==="per_unit"?`, ${Ge(n,r.unit)}`:"";return`I'd like to buy ${s}${i}. How do I go ahead?`}function et(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"),tt=e=>{let[t,r]=(0,A.useState)(null),[n,s]=(0,A.useState)(!0),[i,o]=(0,A.useState)(null),a=(0,A.useCallback)(async()=>{try{r(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:n,failure:i,refresh:l}};var C=require("react"),Lt=e=>e&&typeof e=="object"&&typeof e.error=="string"?e.error:e instanceof Error?e.message:"shop_unavailable",rt=e=>{let[t,r]=(0,C.useState)([]),[n,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&&(r(y.products),s(y.enquiryForm),o(y.truncated),d(null))}).catch(y=>{m&&d(Lt(y))}).finally(()=>{m&&l(!1)}),()=>{m=!1}},[e,p]);let c=(0,C.useCallback)(()=>f(m=>m+1),[]);return{products:t,enquiryForm:n,truncated:i,loading:a,error:u,reload:c}};var k=require("react"),nt="greeting";function Ce(e,t){if(e.some(i=>i.id===t.id))return e;let r=e.filter(i=>i.id!==nt),n=i=>i.author==="client"==(t.author==="client");return[...r.filter(i=>!(i.pending&&n(i)&&i.text===t.text)),t]}var ot=(e,t)=>{let[r,n]=(0,k.useState)([]),[s,i]=(0,k.useState)(""),[o,a]=(0,k.useState)(!1),[l,u]=(0,k.useState)(null),d=(0,k.useRef)(0),p=t?.pollMs??2e3;(0,k.useEffect)(()=>{let c=!0;return e.getInfo().then(m=>{c&&m.greeting&&n(y=>y.length===0?[{id:nt,cursor:"",author:"agent",text:m.greeting}]:y)}).catch(()=>{}),()=>{c=!1}},[e]),(0,k.useEffect)(()=>e.subscribe?.({onMessage:c=>n(m=>Ce(m,c)),onError:c=>u(c.error),onHealthy:()=>u(null)},{intervalMs:p}),[e,p]);let f=(0,k.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};n(b=>[...b,y]),e.sendMessage(c).then(b=>{a(!1),b.reply.trim()&&n(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),n(R=>R.filter(g=>g.id!==m)),i(R=>R||c)})},[s,o,e]);return{messages:r,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,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,renderModel,setResponse,setTableReview,shelfPriceLabel,shelfProblem,splitLayout,textDeltaOf,thinkingDeltaOf,toolEventOf,totalFor,useArtifactUrl,useChat,useCredits,useHolaClient,useShop,useThread});
|
|
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});
|
package/dist/index.d.cts
CHANGED
|
@@ -745,6 +745,118 @@ type Purchased = {
|
|
|
745
745
|
* operator's money surfaces. NOT what the customer paid: they paid credits. */
|
|
746
746
|
value: number;
|
|
747
747
|
};
|
|
748
|
+
/**
|
|
749
|
+
* What the customer agrees to pay, and when.
|
|
750
|
+
*
|
|
751
|
+
* Carried BY THE QUOTE rather than left to the order, because accepting a total without a schedule
|
|
752
|
+
* is half an agreement — nobody should discover "50% up front" after saying yes — and because it is
|
|
753
|
+
* what lets the order's payment rows be raised from something they have actually seen.
|
|
754
|
+
*
|
|
755
|
+
* MONEY, in the same unit `total` is. Not the shelf unit the LINES are priced in: the two travel
|
|
756
|
+
* together in one payload and telling them apart is the whole of what `QuotedLine.price` warns
|
|
757
|
+
* about below.
|
|
758
|
+
*/
|
|
759
|
+
type QuoteTerms = {
|
|
760
|
+
/** Taken before the work starts. The deposit IS the starting gun — nothing runs until it lands. */
|
|
761
|
+
upfront?: number;
|
|
762
|
+
/** Taken on delivery. ADVISORY: see `quoteSchedule`, which derives the balance as the remainder
|
|
763
|
+
* instead, so what a customer is shown and what they are billed cannot drift apart. */
|
|
764
|
+
onDelivery?: number;
|
|
765
|
+
/** Anything the operator wants said about the schedule, in their own words. */
|
|
766
|
+
note?: string;
|
|
767
|
+
};
|
|
768
|
+
/**
|
|
769
|
+
* One service being quoted, as the customer may see it.
|
|
770
|
+
*
|
|
771
|
+
* An ALLOWLIST assembled server-side, field by field, and not a projection of the stored item. The
|
|
772
|
+
* durable shape behind it carries the INTERNAL checklist, the skill row ids and the dashboard spec
|
|
773
|
+
* in the same object as the customer-facing `deliverables` — so the rule is that a new field
|
|
774
|
+
* upstream stays invisible here until somebody adds it on purpose.
|
|
775
|
+
*/
|
|
776
|
+
type QuotedLine = {
|
|
777
|
+
name: string;
|
|
778
|
+
/** A line of scope in the operator's words. */
|
|
779
|
+
notes?: string;
|
|
780
|
+
/** Longer scope — what this service actually covers, when it needs a paragraph. */
|
|
781
|
+
content?: string;
|
|
782
|
+
/**
|
|
783
|
+
* MONEY, in the same unit `total` is — safe to print with a currency symbol.
|
|
784
|
+
*
|
|
785
|
+
* IT DID NOT USED TO BE. This was handed over in the org's SHELF unit (credits on a credits org)
|
|
786
|
+
* beside a `total` that was money, in a payload naming no unit at all, and no portal could fix
|
|
787
|
+
* that from where it stood: `5,000` next to `$8,000` reads as dollars and is wrong by the whole
|
|
788
|
+
* book rate. It is converted server-side now, where the rate lives, so one payload is in one
|
|
789
|
+
* unit.
|
|
790
|
+
*
|
|
791
|
+
* Absent is still a real answer and is NOT a price of 0 — work thrown in is an agreement like
|
|
792
|
+
* any other. The lines also need not add up to `total`: `total` wins, exactly as `orders.value`
|
|
793
|
+
* beats the sum of its services, because a bundle priced below its parts is a real deal.
|
|
794
|
+
*/
|
|
795
|
+
price?: number;
|
|
796
|
+
/** "per month", "one-off" — how often this recurs, when it recurs. */
|
|
797
|
+
period?: string;
|
|
798
|
+
/** What they get: the client-visible deliverables this line buys. */
|
|
799
|
+
deliverables: string[];
|
|
800
|
+
};
|
|
801
|
+
/**
|
|
802
|
+
* The live quote on a 询单, or the fact that there isn't one.
|
|
803
|
+
*
|
|
804
|
+
* A UNION rather than a nullable object so "not quoted yet" cannot be read as "quoted at nothing".
|
|
805
|
+
* They are opposite states — one is the team still working, the other is an offer of an empty
|
|
806
|
+
* basket — and a portal that conflated them would put an Accept button under a quote nobody sent.
|
|
807
|
+
*/
|
|
808
|
+
type InquiryQuote = {
|
|
809
|
+
quoted: false;
|
|
810
|
+
} | {
|
|
811
|
+
quoted: true;
|
|
812
|
+
/** THE VERSION IN THIS PAYLOAD, and the number `acceptInquiry` must be given. Once they have
|
|
813
|
+
* accepted one it is that one — what somebody signed does not change because the operator
|
|
814
|
+
* sent another afterwards — and until then it is the newest sent. */
|
|
815
|
+
version: number;
|
|
816
|
+
/** The newest version that EXISTS. Equal to `version` in the ordinary case; greater when they
|
|
817
|
+
* accepted one and the operator has sent another since, which is the only way a portal can
|
|
818
|
+
* know to say so. Never a thing to accept: `version` is what is on screen, and accepting
|
|
819
|
+
* something nobody has read is the failure the whole scheme exists to prevent. */
|
|
820
|
+
latest: number;
|
|
821
|
+
sentAt: string;
|
|
822
|
+
lines: QuotedLine[];
|
|
823
|
+
/** MONEY, whatever the lines are priced in. The one figure to print as a price. */
|
|
824
|
+
total: number;
|
|
825
|
+
terms?: QuoteTerms;
|
|
826
|
+
/** Which version they have ALREADY accepted; 0 for none. So a reload after accepting shows
|
|
827
|
+
* the agreement rather than the button again. `accepted === version` is the ordinary way a
|
|
828
|
+
* portal knows it is looking at the contract rather than at an offer. */
|
|
829
|
+
accepted: number;
|
|
830
|
+
};
|
|
831
|
+
/** One line of the payment schedule: what is owed, and what it is called. */
|
|
832
|
+
type QuoteScheduleLine = {
|
|
833
|
+
label: string;
|
|
834
|
+
amount: number;
|
|
835
|
+
};
|
|
836
|
+
/** The two labels the platform raises payment rows under. Stated here so a portal can show a
|
|
837
|
+
* customer the SAME words before they accept that they will read on the bill afterwards — a
|
|
838
|
+
* schedule that says "Deposit" and a bill that says "Pre-payment" is two documents about one
|
|
839
|
+
* agreement, and the customer is the one left reconciling them. */
|
|
840
|
+
declare const QUOTE_DEPOSIT_LABEL = "Pre-payment";
|
|
841
|
+
declare const QUOTE_BALANCE_LABEL = "After-payment";
|
|
842
|
+
/**
|
|
843
|
+
* The schedule a quote's terms come to, as lines. MONEY in, money out.
|
|
844
|
+
*
|
|
845
|
+
* THE BALANCE IS THE REMAINDER, never a second stated figure, and this is the reason the function
|
|
846
|
+
* exists rather than a portal reading `terms.upfront` and `terms.onDelivery` straight out. Those
|
|
847
|
+
* two are typed by a human into two boxes and do not have to add up to the contract; the server
|
|
848
|
+
* bills the remainder regardless. A portal printing both would show a customer a schedule that
|
|
849
|
+
* silently forgives or double-charges the difference against the bill they actually receive.
|
|
850
|
+
*
|
|
851
|
+
* It mirrors the server's own `scheduleFrom` deliberately — same clamp, same rounding, same labels
|
|
852
|
+
* — because the point is that the customer sees, before they say yes, exactly the lines that will
|
|
853
|
+
* be raised when they do. In the SDK for the reason `orderBilling` is: the second portal to write
|
|
854
|
+
* this by hand would inherit nothing the first one learned, and being subtly wrong here is money.
|
|
855
|
+
*
|
|
856
|
+
* No terms at all means the whole thing up front — the honest reading of "they agreed a price and
|
|
857
|
+
* said nothing about instalments", and it never bills more than the contract.
|
|
858
|
+
*/
|
|
859
|
+
declare function quoteSchedule(total: number, terms: QuoteTerms | undefined): QuoteScheduleLine[];
|
|
748
860
|
type PortalCredits = {
|
|
749
861
|
/** Balance, packs and anything in flight — one call, because they are one question. A balance
|
|
750
862
|
* without the packs cannot be acted on, and a balance without the pending top-ups looks wrong to
|
|
@@ -803,11 +915,50 @@ type PortalCredits = {
|
|
|
803
915
|
inquiryId: string;
|
|
804
916
|
name: string;
|
|
805
917
|
}>;
|
|
806
|
-
/**
|
|
807
|
-
*
|
|
808
|
-
*
|
|
809
|
-
*
|
|
810
|
-
|
|
918
|
+
/**
|
|
919
|
+
* The quote on a 询单: the services being offered, at the prices being offered.
|
|
920
|
+
*
|
|
921
|
+
* ITS OWN ROUTE, not a field on the inquiry row, and that is load-bearing rather than tidy. The
|
|
922
|
+
* spine's read permission is per TABLE and never per column, so a basket parked on the
|
|
923
|
+
* externally-visible `inquiries` row would hand the customer the internal checklist, the skill
|
|
924
|
+
* row ids and the dashboard spec along with their price. The server reads it as the org and
|
|
925
|
+
* projects an allowlist; there is one door, and `QuotedLine` is the whole of what fits through it.
|
|
926
|
+
*
|
|
927
|
+
* `{quoted: false}` is a REAL answer and not an error — nobody has sent anything yet, which is
|
|
928
|
+
* what a portal draws "we're working on your proposal" from. It is also what an inquiry quoted
|
|
929
|
+
* the old way answers, so a portal reading this keeps working against one.
|
|
930
|
+
*
|
|
931
|
+
* WHAT THEY SIGNED WINS over what has been sent since: once a version is accepted this returns
|
|
932
|
+
* THAT one, with `latest` naming the newest that exists. Before, it always returned the newest
|
|
933
|
+
* and left `accepted` as a bare number — so a customer whose operator revised after they said
|
|
934
|
+
* yes had a screen that knew which version was the contract and displayed a different one.
|
|
935
|
+
*/
|
|
936
|
+
inquiryQuote(inquiryId: string): Promise<InquiryQuote>;
|
|
937
|
+
/**
|
|
938
|
+
* Accept the quote on a 询单 — and, when there is one, get the order written from it.
|
|
939
|
+
*
|
|
940
|
+
* THE VERSION IS REQUIRED, and deliberately not defaulted to the latest. Defaulting would make
|
|
941
|
+
* the stale case unrepresentable: a tab left open on v1 would silently agree to whatever price is
|
|
942
|
+
* current, which is the exact failure versioning exists to prevent. Pass the `version` off the
|
|
943
|
+
* quote that was actually on screen; pass 0 for an inquiry with no quote, which keeps today's
|
|
944
|
+
* behaviour (it moves to `accepted` and the operator writes the order by hand).
|
|
945
|
+
*
|
|
946
|
+
* Idempotent — `changed: false` means they had already accepted, which is what a double-tap on a
|
|
947
|
+
* slow connection looks like and is not an error.
|
|
948
|
+
*
|
|
949
|
+
* Refuses with `CreditRefused`, and the code says which of three things happened. Each wants a
|
|
950
|
+
* different sentence, which is why they are three:
|
|
951
|
+
*
|
|
952
|
+
* - `quote_revised` — the version is no longer the current one. The ONLY correct response is to
|
|
953
|
+
* re-read `inquiryQuote` and show what came back: retrying with the version named in the
|
|
954
|
+
* refusal is the stale accept again, one round trip later. (Which is why that number is not
|
|
955
|
+
* surfaced here — the re-read answers it, and answers it as of now rather than as of then.)
|
|
956
|
+
* - `not_quoted` — nobody has sent anything. There is nothing to accept, and there is nothing
|
|
957
|
+
* for the customer to do but wait.
|
|
958
|
+
* - `inquiry_closed` — it is already closed, or already an order. Someone else moved it, so the
|
|
959
|
+
* page should re-read rather than argue.
|
|
960
|
+
*/
|
|
961
|
+
acceptInquiry(inquiryId: string, version: number): Promise<{
|
|
811
962
|
status: string;
|
|
812
963
|
changed: boolean;
|
|
813
964
|
}>;
|
|
@@ -1254,4 +1405,4 @@ declare const useThread: (client: HolaClient, options?: {
|
|
|
1254
1405
|
pollMs?: number;
|
|
1255
1406
|
}) => UseThread;
|
|
1256
1407
|
|
|
1257
|
-
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 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, 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, renderModel, setResponse, setTableReview, shelfPriceLabel, shelfProblem, splitLayout, textDeltaOf, thinkingDeltaOf, toolEventOf, totalFor, useArtifactUrl, useChat, useCredits, useHolaClient, useShop, useThread };
|
|
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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -745,6 +745,118 @@ type Purchased = {
|
|
|
745
745
|
* operator's money surfaces. NOT what the customer paid: they paid credits. */
|
|
746
746
|
value: number;
|
|
747
747
|
};
|
|
748
|
+
/**
|
|
749
|
+
* What the customer agrees to pay, and when.
|
|
750
|
+
*
|
|
751
|
+
* Carried BY THE QUOTE rather than left to the order, because accepting a total without a schedule
|
|
752
|
+
* is half an agreement — nobody should discover "50% up front" after saying yes — and because it is
|
|
753
|
+
* what lets the order's payment rows be raised from something they have actually seen.
|
|
754
|
+
*
|
|
755
|
+
* MONEY, in the same unit `total` is. Not the shelf unit the LINES are priced in: the two travel
|
|
756
|
+
* together in one payload and telling them apart is the whole of what `QuotedLine.price` warns
|
|
757
|
+
* about below.
|
|
758
|
+
*/
|
|
759
|
+
type QuoteTerms = {
|
|
760
|
+
/** Taken before the work starts. The deposit IS the starting gun — nothing runs until it lands. */
|
|
761
|
+
upfront?: number;
|
|
762
|
+
/** Taken on delivery. ADVISORY: see `quoteSchedule`, which derives the balance as the remainder
|
|
763
|
+
* instead, so what a customer is shown and what they are billed cannot drift apart. */
|
|
764
|
+
onDelivery?: number;
|
|
765
|
+
/** Anything the operator wants said about the schedule, in their own words. */
|
|
766
|
+
note?: string;
|
|
767
|
+
};
|
|
768
|
+
/**
|
|
769
|
+
* One service being quoted, as the customer may see it.
|
|
770
|
+
*
|
|
771
|
+
* An ALLOWLIST assembled server-side, field by field, and not a projection of the stored item. The
|
|
772
|
+
* durable shape behind it carries the INTERNAL checklist, the skill row ids and the dashboard spec
|
|
773
|
+
* in the same object as the customer-facing `deliverables` — so the rule is that a new field
|
|
774
|
+
* upstream stays invisible here until somebody adds it on purpose.
|
|
775
|
+
*/
|
|
776
|
+
type QuotedLine = {
|
|
777
|
+
name: string;
|
|
778
|
+
/** A line of scope in the operator's words. */
|
|
779
|
+
notes?: string;
|
|
780
|
+
/** Longer scope — what this service actually covers, when it needs a paragraph. */
|
|
781
|
+
content?: string;
|
|
782
|
+
/**
|
|
783
|
+
* MONEY, in the same unit `total` is — safe to print with a currency symbol.
|
|
784
|
+
*
|
|
785
|
+
* IT DID NOT USED TO BE. This was handed over in the org's SHELF unit (credits on a credits org)
|
|
786
|
+
* beside a `total` that was money, in a payload naming no unit at all, and no portal could fix
|
|
787
|
+
* that from where it stood: `5,000` next to `$8,000` reads as dollars and is wrong by the whole
|
|
788
|
+
* book rate. It is converted server-side now, where the rate lives, so one payload is in one
|
|
789
|
+
* unit.
|
|
790
|
+
*
|
|
791
|
+
* Absent is still a real answer and is NOT a price of 0 — work thrown in is an agreement like
|
|
792
|
+
* any other. The lines also need not add up to `total`: `total` wins, exactly as `orders.value`
|
|
793
|
+
* beats the sum of its services, because a bundle priced below its parts is a real deal.
|
|
794
|
+
*/
|
|
795
|
+
price?: number;
|
|
796
|
+
/** "per month", "one-off" — how often this recurs, when it recurs. */
|
|
797
|
+
period?: string;
|
|
798
|
+
/** What they get: the client-visible deliverables this line buys. */
|
|
799
|
+
deliverables: string[];
|
|
800
|
+
};
|
|
801
|
+
/**
|
|
802
|
+
* The live quote on a 询单, or the fact that there isn't one.
|
|
803
|
+
*
|
|
804
|
+
* A UNION rather than a nullable object so "not quoted yet" cannot be read as "quoted at nothing".
|
|
805
|
+
* They are opposite states — one is the team still working, the other is an offer of an empty
|
|
806
|
+
* basket — and a portal that conflated them would put an Accept button under a quote nobody sent.
|
|
807
|
+
*/
|
|
808
|
+
type InquiryQuote = {
|
|
809
|
+
quoted: false;
|
|
810
|
+
} | {
|
|
811
|
+
quoted: true;
|
|
812
|
+
/** THE VERSION IN THIS PAYLOAD, and the number `acceptInquiry` must be given. Once they have
|
|
813
|
+
* accepted one it is that one — what somebody signed does not change because the operator
|
|
814
|
+
* sent another afterwards — and until then it is the newest sent. */
|
|
815
|
+
version: number;
|
|
816
|
+
/** The newest version that EXISTS. Equal to `version` in the ordinary case; greater when they
|
|
817
|
+
* accepted one and the operator has sent another since, which is the only way a portal can
|
|
818
|
+
* know to say so. Never a thing to accept: `version` is what is on screen, and accepting
|
|
819
|
+
* something nobody has read is the failure the whole scheme exists to prevent. */
|
|
820
|
+
latest: number;
|
|
821
|
+
sentAt: string;
|
|
822
|
+
lines: QuotedLine[];
|
|
823
|
+
/** MONEY, whatever the lines are priced in. The one figure to print as a price. */
|
|
824
|
+
total: number;
|
|
825
|
+
terms?: QuoteTerms;
|
|
826
|
+
/** Which version they have ALREADY accepted; 0 for none. So a reload after accepting shows
|
|
827
|
+
* the agreement rather than the button again. `accepted === version` is the ordinary way a
|
|
828
|
+
* portal knows it is looking at the contract rather than at an offer. */
|
|
829
|
+
accepted: number;
|
|
830
|
+
};
|
|
831
|
+
/** One line of the payment schedule: what is owed, and what it is called. */
|
|
832
|
+
type QuoteScheduleLine = {
|
|
833
|
+
label: string;
|
|
834
|
+
amount: number;
|
|
835
|
+
};
|
|
836
|
+
/** The two labels the platform raises payment rows under. Stated here so a portal can show a
|
|
837
|
+
* customer the SAME words before they accept that they will read on the bill afterwards — a
|
|
838
|
+
* schedule that says "Deposit" and a bill that says "Pre-payment" is two documents about one
|
|
839
|
+
* agreement, and the customer is the one left reconciling them. */
|
|
840
|
+
declare const QUOTE_DEPOSIT_LABEL = "Pre-payment";
|
|
841
|
+
declare const QUOTE_BALANCE_LABEL = "After-payment";
|
|
842
|
+
/**
|
|
843
|
+
* The schedule a quote's terms come to, as lines. MONEY in, money out.
|
|
844
|
+
*
|
|
845
|
+
* THE BALANCE IS THE REMAINDER, never a second stated figure, and this is the reason the function
|
|
846
|
+
* exists rather than a portal reading `terms.upfront` and `terms.onDelivery` straight out. Those
|
|
847
|
+
* two are typed by a human into two boxes and do not have to add up to the contract; the server
|
|
848
|
+
* bills the remainder regardless. A portal printing both would show a customer a schedule that
|
|
849
|
+
* silently forgives or double-charges the difference against the bill they actually receive.
|
|
850
|
+
*
|
|
851
|
+
* It mirrors the server's own `scheduleFrom` deliberately — same clamp, same rounding, same labels
|
|
852
|
+
* — because the point is that the customer sees, before they say yes, exactly the lines that will
|
|
853
|
+
* be raised when they do. In the SDK for the reason `orderBilling` is: the second portal to write
|
|
854
|
+
* this by hand would inherit nothing the first one learned, and being subtly wrong here is money.
|
|
855
|
+
*
|
|
856
|
+
* No terms at all means the whole thing up front — the honest reading of "they agreed a price and
|
|
857
|
+
* said nothing about instalments", and it never bills more than the contract.
|
|
858
|
+
*/
|
|
859
|
+
declare function quoteSchedule(total: number, terms: QuoteTerms | undefined): QuoteScheduleLine[];
|
|
748
860
|
type PortalCredits = {
|
|
749
861
|
/** Balance, packs and anything in flight — one call, because they are one question. A balance
|
|
750
862
|
* without the packs cannot be acted on, and a balance without the pending top-ups looks wrong to
|
|
@@ -803,11 +915,50 @@ type PortalCredits = {
|
|
|
803
915
|
inquiryId: string;
|
|
804
916
|
name: string;
|
|
805
917
|
}>;
|
|
806
|
-
/**
|
|
807
|
-
*
|
|
808
|
-
*
|
|
809
|
-
*
|
|
810
|
-
|
|
918
|
+
/**
|
|
919
|
+
* The quote on a 询单: the services being offered, at the prices being offered.
|
|
920
|
+
*
|
|
921
|
+
* ITS OWN ROUTE, not a field on the inquiry row, and that is load-bearing rather than tidy. The
|
|
922
|
+
* spine's read permission is per TABLE and never per column, so a basket parked on the
|
|
923
|
+
* externally-visible `inquiries` row would hand the customer the internal checklist, the skill
|
|
924
|
+
* row ids and the dashboard spec along with their price. The server reads it as the org and
|
|
925
|
+
* projects an allowlist; there is one door, and `QuotedLine` is the whole of what fits through it.
|
|
926
|
+
*
|
|
927
|
+
* `{quoted: false}` is a REAL answer and not an error — nobody has sent anything yet, which is
|
|
928
|
+
* what a portal draws "we're working on your proposal" from. It is also what an inquiry quoted
|
|
929
|
+
* the old way answers, so a portal reading this keeps working against one.
|
|
930
|
+
*
|
|
931
|
+
* WHAT THEY SIGNED WINS over what has been sent since: once a version is accepted this returns
|
|
932
|
+
* THAT one, with `latest` naming the newest that exists. Before, it always returned the newest
|
|
933
|
+
* and left `accepted` as a bare number — so a customer whose operator revised after they said
|
|
934
|
+
* yes had a screen that knew which version was the contract and displayed a different one.
|
|
935
|
+
*/
|
|
936
|
+
inquiryQuote(inquiryId: string): Promise<InquiryQuote>;
|
|
937
|
+
/**
|
|
938
|
+
* Accept the quote on a 询单 — and, when there is one, get the order written from it.
|
|
939
|
+
*
|
|
940
|
+
* THE VERSION IS REQUIRED, and deliberately not defaulted to the latest. Defaulting would make
|
|
941
|
+
* the stale case unrepresentable: a tab left open on v1 would silently agree to whatever price is
|
|
942
|
+
* current, which is the exact failure versioning exists to prevent. Pass the `version` off the
|
|
943
|
+
* quote that was actually on screen; pass 0 for an inquiry with no quote, which keeps today's
|
|
944
|
+
* behaviour (it moves to `accepted` and the operator writes the order by hand).
|
|
945
|
+
*
|
|
946
|
+
* Idempotent — `changed: false` means they had already accepted, which is what a double-tap on a
|
|
947
|
+
* slow connection looks like and is not an error.
|
|
948
|
+
*
|
|
949
|
+
* Refuses with `CreditRefused`, and the code says which of three things happened. Each wants a
|
|
950
|
+
* different sentence, which is why they are three:
|
|
951
|
+
*
|
|
952
|
+
* - `quote_revised` — the version is no longer the current one. The ONLY correct response is to
|
|
953
|
+
* re-read `inquiryQuote` and show what came back: retrying with the version named in the
|
|
954
|
+
* refusal is the stale accept again, one round trip later. (Which is why that number is not
|
|
955
|
+
* surfaced here — the re-read answers it, and answers it as of now rather than as of then.)
|
|
956
|
+
* - `not_quoted` — nobody has sent anything. There is nothing to accept, and there is nothing
|
|
957
|
+
* for the customer to do but wait.
|
|
958
|
+
* - `inquiry_closed` — it is already closed, or already an order. Someone else moved it, so the
|
|
959
|
+
* page should re-read rather than argue.
|
|
960
|
+
*/
|
|
961
|
+
acceptInquiry(inquiryId: string, version: number): Promise<{
|
|
811
962
|
status: string;
|
|
812
963
|
changed: boolean;
|
|
813
964
|
}>;
|
|
@@ -1254,4 +1405,4 @@ declare const useThread: (client: HolaClient, options?: {
|
|
|
1254
1405
|
pollMs?: number;
|
|
1255
1406
|
}) => UseThread;
|
|
1256
1407
|
|
|
1257
|
-
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 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, 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, renderModel, setResponse, setTableReview, shelfPriceLabel, shelfProblem, splitLayout, textDeltaOf, thinkingDeltaOf, toolEventOf, totalFor, useArtifactUrl, useChat, useCredits, useHolaClient, useShop, useThread };
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use client'
|
|
2
|
-
var te=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="message_update"?t.assistantMessageEvent??null:null},_=e=>{let t=te(e);return t?.type==="text_delta"&&typeof t.delta=="string"?t.delta:null},L=e=>{let t=te(e);return t?.type==="thinking_delta"&&typeof t.delta=="string"?t.delta:null},U=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="tool_execution_start"&&t.toolCallId?{phase:"start",id:t.toolCallId,name:t.toolName}:t.type==="tool_execution_end"&&t.toolCallId?{phase:"end",id:t.toolCallId,isError:t.isError}:null};var
|
|
3
|
-
`))
|
|
4
|
-
`)}:null},
|
|
2
|
+
var te=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="message_update"?t.assistantMessageEvent??null:null},_=e=>{let t=te(e);return t?.type==="text_delta"&&typeof t.delta=="string"?t.delta:null},L=e=>{let t=te(e);return t?.type==="thinking_delta"&&typeof t.delta=="string"?t.delta:null},U=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="tool_execution_start"&&t.toolCallId?{phase:"start",id:t.toolCallId,name:t.toolName}:t.type==="tool_execution_end"&&t.toolCallId?{phase:"end",id:t.toolCallId,isError:t.isError}:null};var Ne=/^ /,w=e=>{if(e&&typeof e=="object"){let t=e,n=typeof t.error=="string"?t.error:"request_failed";return typeof t.retryable=="boolean"?{error:n,retryable:t.retryable}:{error:n}}return{error:"request_failed"}},Be=e=>{let t="message",n=[];for(let r of e.split(`
|
|
3
|
+
`))r.startsWith(":")||(r.startsWith("event:")?t=r.slice(6).trim():r.startsWith("data:")&&n.push(r.slice(5).replace(Ne,"")));return n.length>0?{event:t,data:n.join(`
|
|
4
|
+
`)}:null},Ve=(e,t,n)=>{let r;try{r=JSON.parse(e.data)}catch{return}if(e.event==="session"){let s=r.sessionId;s&&(n(s),t.onSession?.(s));return}if(e.event==="turn_event"){t.onEvent?.(r);let s=_(r);s&&t.onText?.(s);let i=L(r);i&&t.onThinking?.(i);let o=U(r);o&&t.onTool?.(o);return}if(e.event==="chat_completed"){let s=r;n(s.sessionId),t.onComplete?.(s);return}e.event==="chat_error"&&t.onError?.(w(r))},S=async(e,t)=>{let n=await fetch(e,{headers:t});if(!n.ok)throw new Error(`hola: request failed (${n.status})`);return await n.json()},ne=async e=>{let t=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body});if(!t.ok)throw new Error(`hola: message failed (${t.status})`);return await t.json()},re=async(e,t,n,r)=>{let s=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body,signal:r});if(!(s.ok&&s.body)){t.onError?.({error:`stream_failed_${s.status}`});return}let i=s.body.getReader(),o=new TextDecoder,a="",l=()=>{let d=a.indexOf(`
|
|
5
5
|
|
|
6
|
-
`);for(;d!==-1;){let p=a.slice(0,d);a=a.slice(d+2);let f=
|
|
6
|
+
`);for(;d!==-1;){let p=a.slice(0,d);a=a.slice(d+2);let f=Be(p);f&&Ve(f,t,n),d=a.indexOf(`
|
|
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 Ve=/\/+$/,N="/api/v1/end-user",je=e=>{let t=e.baseUrl.replace(Ve,""),r=()=>typeof e.token=="function"?e.token():e.token,n=o=>e.project?`${o}project=${encodeURIComponent(e.project)}`:"",s=async()=>({"content-type":"application/json",authorization:`Bearer ${await r()}`}),i=async o=>{let a=await fetch(`${t}${N}/chat${n("?")}`,{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()=>v(`${t}${N}/chat/info${n("?")}`,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 v(`${t}${N}/chat/thread?since=${encodeURIComponent(l)}${n("&")}`,await s());for(let T of x.messages)o.onMessage(T);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 Be,useState as Ge}from"react";var q=(e,t)=>{let[r,n]=Ge("");return Be(()=>{if(!e){n("");return}let s=Uint8Array.from(atob(e),o=>o.charCodeAt(0)),i=URL.createObjectURL(new Blob([s],{type:t}));return n(i),()=>URL.revokeObjectURL(i)},[e,t]),r};import{useEffect as Qe,useRef as Ye}from"react";import{createContext as ze,useContext as Je}from"react";import{jsx as Xe}from"react/jsx-runtime";var oe=ze(null),Ke=({client:e,children:t})=>Xe(oe.Provider,{value:e,children:t}),V=()=>{let e=Je(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 $}from"react";var j=e=>{let[t,r]=$([]),[n,s]=$(""),[i,o]=$(!1),[a,l]=$(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&&r([{id:p(),role:"assistant",text:m.greeting}])}).catch(()=>{}),()=>{c=!1}},[e,p]);let f=se(()=>{let c=n.trim();if(!c||i)return;s(""),l(null),o(!0);let m=p(),y=p();r(g=>[...g,{id:m,role:"user",text:c},{id:y,role:"assistant",text:"",streaming:!0}]);let b=g=>{r(x=>x.map(T=>T.id===y?g(T):T))},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)})},[n,i,e,p]);return{messages:t,input:n,setInput:s,send:f,sending:i,error:a}};import{jsx as C,jsxs as B}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"}},Ze=({artifact:e})=>{let t=q(e.dataBase64??"",e.mimeType),r=e.url??t;return r?e.mimeType.startsWith("image/")?C("a",{href:r,rel:"noopener noreferrer",target:"_blank",children:C("img",{alt:e.filename,src:r,style:S.image})}):C("a",{download:e.filename,href:r,style:S.link,children:e.filename}):null},et=()=>{let e=V(),{messages:t,input:r,setInput:n,send:s,sending:i,error:o}=j(e),a=Ye(null);Qe(()=>{let u=a.current;u&&(u.scrollTop=u.scrollHeight)},[t]);let l=u=>{u.preventDefault(),s()};return B("div",{style:S.root,children:[C("div",{ref:a,style:S.log,children:t.map(u=>B("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(Ze,{artifact:d},d.filename))}):null]},u.id))}),o?C("div",{style:S.error,children:o}):null,B("form",{onSubmit:l,style:S.form,children:[C("input",{"aria-label":"Message",onChange:u=>n(u.target.value),placeholder:"Type a message\u2026",style:S.input,value:r}),C("button",{disabled:i||r.trim().length===0,style:S.button,type:"submit",children:"Send"})]})]})};var tt=/\/+$/,G=e=>{let t=e.sessionId,r=e.baseUrl.replace(tt,""),n=o=>`${r}/endpoint/${encodeURIComponent(e.token)}${o}`,s={"content-type":"application/json"},i=(o,a)=>({url:n(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:()=>v(n("/config"),{}),sendMessage:async o=>{let a=await re(i("/message",o));return t=a.sessionId,a},streamMessage:(o,a,l)=>ne(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 v(n(`/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 rt=e=>"transport"in e?e.transport:G(e);var nt=/^https?:\/\//i,ot=/^\d{4}-\d{2}-\d{2}(?:[T ]|$)/,st=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(nt.test(e))return"url";if(ot.test(e))return"date"}return"text"}function le(e){let t=[],r=new Map;for(let n of e)for(let[s,i]of Object.entries(n.data??{})){if(i==null)continue;let o=r.get(s);o||(o=new Map,r.set(s,o),t.push(s));let a=it(i);o.set(a,(o.get(a)??0)+1)}return t.map(n=>{let s=r.get(n)??new Map,i="text",o=-1;for(let[a,l]of s)l>o&&(o=l,i=a);return{key:n,label:st(n),type:i}})}var at=e=>typeof e=="number"?e:Number(e)||0,ue=e=>/rate|position|rank|score|percent|avg/i.test(e),lt=/posted|published|sent|completed|shipped|launched|_at/i,ut=new Set(["service","order","end_user_id"]);function de(e,t){let r=e.filter(l=>!ut.has(l.key)),n=r.filter(l=>l.type==="number").slice(0,3),s=r.find(l=>l.key==="status")??r.find(l=>l.type==="select"),i=r.find(l=>l.type==="date"&<.test(l.key))??r.find(l=>l.type==="date"),o=r.filter(l=>l.type==="number"&&!ue(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,a=[{type:"stat",label:"Items",agg:"count"}];for(let l of n){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:r.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}},dt=e=>Math.max(1,Math.min(6,Math.round(e))),pt=e=>Math.max(1,Math.min(4,Math.round(e)));function W(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 z(e,t,r){let n=ge[e];return{w:t===void 0?n.w:dt(t),h:r===void 0?n.h:pt(r)}}function J(e){let t=[],r=[],n=(o,a,l,u)=>{if(o<0||o+l>6)return!1;for(let d=0;d<u;d+=1){let p=r[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=r[a+d]??[];for(let f=0;f<l;f+=1)p[o+f]=!0;r[a+d]=p}},i=(o,a)=>{for(let l=0;;l+=1)for(let u=0;u+o<=6;u+=1)if(n(u,l,o,a))return{gx:u,gy:l}};for(let o of e){let a=z(W(o.kind),o.w,o.h),u=o.gx!==void 0&&o.gy!==void 0&&n(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=[],r=[];for(let n of e)W(n.kind)==="block"?r.push(n):t.push(n);return{tiles:J(t),blocks:r}}var he=new Set(["service","order","end_user_id"]),K=e=>typeof e=="number"?e:Number(e)||0,xe=e=>e==null?"":String(e);function X(e,t){if(e==="count")return t.length;if(t.length===0)return 0;if(e==="last")return t[t.length-1]??0;if(e==="min")return Math.min(...t);if(e==="max")return Math.max(...t);let r=t.reduce((n,s)=>n+s,0);return e==="avg"?Math.round(r/t.length*100)/100:r}function ct(e,t,r,n){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(r?K(i.data[r]):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:r?X(n,o):o.length}))}function mt(e,t,r,n="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(r?K(i.data[r]):1),s.set(o,a)}return[...s.entries()].map(([i,o])=>({label:i,value:r?X(n,o):o.length})).sort((i,o)=>o.value-i.value)}function gt(e,t,r,n){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:n.length};let i=n.map(o=>K(o.data[s.key]));return{kind:"stat",label:e.label??s.label,value:X(e.agg??"sum",i)}}case"line":case"bar":{if(!t.has(e.x)||e.y&&!t.has(e.y))return null;let s=ct(n,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=mt(n,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)):r;return s.length===0?null:{kind:"table",title:e.title,columns:s,rows:n}}case"text":return{kind:"text",title:e.title,body:e.body};default:return null}}function we(e,t,r,n={}){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:r});for(let[l,u]of Object.entries(n))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=gt(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 ft=new Set(["sum","avg","count","min","max","last"]),ve=e=>typeof e=="string"&&ft.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,k=e=>typeof e=="number"&&e>=0?Math.round(e):void 0;function yt(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:ve(t.agg),w:I(t.w),h:A(t.h),gx:k(t.gx),gy:k(t.gy)};case"line":case"bar":{let r=h(t.x);return r?{type:t.type,source:h(t.source),title:h(t.title),x:r,y:h(t.y)??h(t.column),agg:ve(t.agg),w:I(t.w),h:A(t.h),gx:k(t.gx),gy:k(t.gy)}:null}case"donut":{let r=h(t.groupBy)??h(t.column);return r?{type:"donut",source:h(t.source),title:h(t.title),groupBy:r,w:I(t.w),h:A(t.h),gx:k(t.gx),gy:k(t.gy)}:null}case"table":{let r=Array.isArray(t.columns)?t.columns.filter(n=>typeof n=="string"):void 0;return{type:"table",source:h(t.source),title:h(t.title),columns:r,w:I(t.w),h:A(t.h),gx:k(t.gx),gy:k(t.gy)}}case"text":{let r=h(t.body);return r?{type:"text",title:h(t.title),body:r,w:I(t.w),h:A(t.h),gx:k(t.gx),gy:k(t.gy)}:null}default:return null}}function Se(e){let t=e;if(typeof e=="string"){if(e.trim()==="")return null;try{t=JSON.parse(e)}catch{return null}}if(typeof t!="object"||t===null)return null;let r=t.widgets;if(!Array.isArray(r))return null;let n=r.map(yt).filter(i=>i!==null);if(n.length===0)return null;let s=t.version;return{version:typeof s=="number"?s:1,title:h(t.title),widgets:n}}function Q(e){if(typeof e=="string")return e?{kind:"file",value:e}:null;if(e&&typeof e=="object"){let t=e,r=typeof t.value=="string"?t.value:"",n=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 r?{kind:n,value:r,...s?{v:s}:{}}:null}return null}function Y(e){let t=new Map;for(let r of e){let n=r.v??1,s=t.get(n)??[];s.push(r),t.set(n,s)}return[...t.entries()].sort(([r],[n])=>r-n).map(([r,n])=>({v:r,items:n}))}function Pe(e){let t=e.files;if(typeof t=="string"&&t.trim()!=="")try{let n=JSON.parse(t);if(Array.isArray(n))return n.map(Q).filter(s=>s!==null)}catch{}let r=String(e.file??"");return r?[{kind:"file",value:r}]:[]}function ke(e,t,r,n=""){let i=Y(e).find(a=>a.v===t)?.items??[],o=i.filter(a=>a.kind==="file").map(a=>r.get(a.value)??"");return i.some(a=>a.kind==="table")&&o.push(n),o.length===0||o.some(a=>a==="")?"awaiting":o.some(a=>a==="revise")?"revise":"accepted"}function Te(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 r=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}:{}})),n=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:r,rows:n,...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 E(){return{cells:{},verdict:"",comment:""}}function Ie(e){if(typeof e!="string"||e.trim()==="")return E();try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t)){let r=t;return{cells:r.cells&&typeof r.cells=="object"?r.cells:r,verdict:r.verdict==="accepted"||r.verdict==="revise"?r.verdict:"",comment:typeof r.comment=="string"?r.comment:""}}}catch{}return E()}function Ae(e,t,r){if(e.clientEditable){let n=r.cells[t.id];if(n&&e.key in n)return n[e.key]}return t.cells[e.key]}function He(e,t,r,n){return{...e,cells:{...e.cells,[t]:{...e.cells[t]??{},[r]:n}}}}function Me(e,t,r){return{...e,verdict:t,comment:r}}function $e(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,r,n){super(r),this.name="CreditRefused",this.code=t,this.status=n}},bt=/\/+$/,ht="/api/v1/end-user",xt=(e,t,r)=>{let n=t.filter(l=>l.order===r),s=n.reduce((l,u)=>l+u.amount,0),i=n.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:[...n].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}},wt=e=>{let t=e.baseUrl.replace(bt,""),r=()=>typeof e.token=="function"?e.token():e.token,n=async(s,i={method:"GET"})=>{try{let o=await fetch(`${t}${ht}${s}`,{method:i.method,headers:{"content-type":"application/json",authorization:`Bearer ${await r()}`},...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:()=>n("/credits"),history:()=>n("/credits/history"),topup:s=>n("/credits/checkout",{method:"POST",body:{packId:s}}),checkout:s=>n("/shop/checkout",{method:"POST",body:s}),payments:()=>n("/payments"),paymentMethods:()=>n("/payment-methods"),markPaymentSent:(s,i)=>n(`/payments/${encodeURIComponent(s)}/sent`,{method:"POST",body:{reference:i??""}}),acceptInquiry:s=>n(`/inquiries/${encodeURIComponent(s)}/accept`,{method:"POST"}),enquire:(s,i,o)=>n("/shop/enquire",{method:"POST",body:{productId:s,answers:i,name:o??""}})}};var vt=/\/+$/,R="/api/v1/end-user",M=class extends Error{constructor(t){super(t),this.name="PortalConflict"}};function St(e){let t="";for(let n=0;n<e.length;n+=32768)t+=String.fromCharCode(...e.subarray(n,n+32768));return btoa(t)}var Pt=e=>{let t=e.baseUrl.replace(vt,""),r=()=>typeof e.token=="function"?e.token():e.token,n=async()=>({"content-type":"application/json",authorization:`Bearer ${await r()}`}),s=async(o,a)=>{try{let l=await fetch(`${t}${R}${o}`,{method:a.method,headers:await n(),...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 v(`${t}${R}/tables`,await n())).tables,listRows:async(o,a)=>await v(`${t}${R}${i(o)}/rows?limit=${String(a??100)}`,await n()),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 v(`${t}${R}/tables/files/rows?limit=200`,await n())).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:St(l),...a===void 0?{}:{message:a}}})},fileLink:async o=>await v(`${t}${R}/files/${encodeURIComponent(o)}/url`,await n()),deleteFile:async o=>(await s(`/files/${encodeURIComponent(o)}`,{method:"DELETE"})).deleted,listDocuments:async()=>(await v(`${t}${R}/documents`,await n())).documents,readDocument:async o=>(await v(`${t}${R}/documents/${encodeURIComponent(o)}`,await n())).document,saveDocument:async(o,a)=>await s(`/documents/${encodeURIComponent(o)}`,{method:"PATCH",body:a})}};var kt=/\/+$/,Tt="/api/v1/end-user",Ct=e=>{let t=e.baseUrl.replace(kt,""),r=async(n,s)=>{let i;try{i=await fetch(`${t}${Tt}${n}`,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 n=await r(`/shop/products?publishable_key=${encodeURIComponent(e.publishableKey)}`);return{products:n.products.map(s=>({...s,currency:typeof s.currency=="string"?s.currency:""})),truncated:n.truncated===!0,enquiryForm:Array.isArray(n.enquiryForm)?n.enquiryForm:[]}},apply:async n=>await r("/shop/apply",{publishable_key:e.publishableKey,name:n.name,email:n.email,...n.phone?{phone:n.phone}:{},...n.message?{message:n.message}:{},...n.productId?{productId:n.productId}:{}})}};var Rt=new Set(["buy","ask"]);function Dt(e){return Rt.has(e.mode)?e.mode:"ask"}var It={kind:"quoted"};function F(e,t){if(!t)return e.toLocaleString();if(t.toLowerCase()==="credits")return`${e.toLocaleString()} ${e===1?"credit":"credits"}`;let r=Number.isInteger(e)?0:2;try{return new Intl.NumberFormat(void 0,{style:"currency",currency:t,minimumFractionDigits:r,maximumFractionDigits:r}).format(e)}catch{return`${t} ${e.toLocaleString()}`}}function We(e,t){let r=/^[a-z]+$/i.test(t)&&!t.endsWith("s")?"s":"";return`${e.toLocaleString()} ${t}${r}`}function Ee(e,t){return e.kind==="quoted"?"Priced on enquiry":e.kind==="flat"?F(e.price,t):`${F(e.unitPrice,t)} per ${e.unitStep===1?e.unit:We(e.unitStep,e.unit)}`}function At(e){let t=e.currency,r=e.pricing;if(r.kind!=="variants")return Ee(r,t);let n=r.variants.map(s=>s.price).filter(s=>typeof s=="number");return n.length>0?`From ${F(Math.min(...n),t)}`:"Priced on enquiry"}function Ht(e,t){if(e.kind!=="variants")return e;let r=e.variants.find(n=>n.name===t);return typeof r?.price=="number"?{kind:"flat",price:r.price}:It}function Mt(e,t){return e.kind==="flat"?e.price:e.kind==="per_unit"?e.unitPrice*Math.ceil(t/Math.max(e.unitStep,1)):null}function $t(e,t){let r=t.kind==="per_unit"?Math.max(t.unitStep,1):1;return{min:Math.max(e.minQty??r,r),max:e.maxQty??null,step:r}}function Wt(e,t){let r=e.variants?.find(n=>n.name===t);return r&&r.includes.length>0?r.includes:e.includes}function Et(e,t){let r=[];for(let n of e){let s=t(n).trim();s&&!r.includes(s)&&r.push(s)}return r}function Ft(e,t,r,n){let s=t?`${e.name} \u2014 ${t}`:e.name,i=r.kind==="per_unit"?`, ${We(n,r.unit)}`:"";return`I'd like to buy ${s}${i}. How do I go ahead?`}function Ot(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 Fe,useEffect as _t,useState as ee}from"react";var Lt=e=>{let[t,r]=ee(null),[n,s]=ee(!0),[i,o]=ee(null),a=Fe(async()=>{try{r(await e.wallet()),o(null)}catch{o("Couldn't read your balance just now.")}finally{s(!1)}},[e]),l=Fe(()=>{a().catch(()=>{})},[a]);return _t(()=>(l(),window.addEventListener("focus",l),()=>{window.removeEventListener("focus",l)}),[l]),{wallet:t,loading:n,failure:i,refresh:l}};import{useCallback as Ut,useEffect as Nt,useState as D}from"react";var qt=e=>e&&typeof e=="object"&&typeof e.error=="string"?e.error:e instanceof Error?e.message:"shop_unavailable",Vt=e=>{let[t,r]=D([]),[n,s]=D([]),[i,o]=D(!1),[a,l]=D(!0),[u,d]=D(null),[p,f]=D(0);Nt(()=>{let m=!0;return l(!0),e.listProducts().then(y=>{m&&(r(y.products),s(y.enquiryForm),o(y.truncated),d(null))}).catch(y=>{m&&d(qt(y))}).finally(()=>{m&&l(!1)}),()=>{m=!1}},[e,p]);let c=Ut(()=>f(m=>m+1),[]);return{products:t,enquiryForm:n,truncated:i,loading:a,error:u,reload:c}};import{useCallback as jt,useEffect as Oe,useRef as Bt,useState as O}from"react";var _e="greeting";function Le(e,t){if(e.some(i=>i.id===t.id))return e;let r=e.filter(i=>i.id!==_e),n=i=>i.author==="client"==(t.author==="client");return[...r.filter(i=>!(i.pending&&n(i)&&i.text===t.text)),t]}var Gt=(e,t)=>{let[r,n]=O([]),[s,i]=O(""),[o,a]=O(!1),[l,u]=O(null),d=Bt(0),p=t?.pollMs??2e3;Oe(()=>{let c=!0;return e.getInfo().then(m=>{c&&m.greeting&&n(y=>y.length===0?[{id:_e,cursor:"",author:"agent",text:m.greeting}]:y)}).catch(()=>{}),()=>{c=!1}},[e]),Oe(()=>e.subscribe?.({onMessage:c=>n(m=>Le(m,c)),onError:c=>u(c.error),onHealthy:()=>u(null)},{intervalMs:p}),[e,p]);let f=jt(()=>{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};n(b=>[...b,y]),e.sendMessage(c).then(b=>{a(!1),b.reply.trim()&&n(g=>g.some(T=>!T.pending&&T.author!=="client"&&T.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),n(P=>P.filter(g=>g.id!==m)),i(P=>P||c)})},[s,o,e]);return{messages:r,input:s,setInput:i,send:f,sending:o,error:l}};export{et as Chat,H as CreditRefused,pe as GRID_COLS,ce as GRID_MAX_COLS,me as GRID_MAX_ROWS,Ke as HolaProvider,M as PortalConflict,W as bandOfKind,fe as bandOfType,Ft as buyRequestText,Ae as cellValue,je as createApiTransport,rt as createHolaClient,wt as createPortalCredits,Pt as createPortalData,Ct as createPortalShop,G as createWidgetTransport,Re as deliverableCellText,ke as deliverableStatus,le as deriveFields,E as emptyTableResponses,Et as facetValues,ye as footprintOf,z as footprintWith,$e as formatDeliverableDate,Y as groupDeliverableVersions,Wt as includesFor,de as inferSpec,De as isDeliverableChecked,Le as mergeMessage,Dt as modeOf,F as money,Z as normalizeDeliverableColType,Q as normalizeDeliverableItem,xt as orderBilling,Se as parseDashboardSpec,Pe as parseDeliverableItems,Ce as parseDeliverableTable,Ie as parseTableResponses,J as placeWidgets,Ht as priceFor,Ee as priceLabel,Te as publishedVersionOf,$t as quantityRange,we as renderModel,He as setResponse,Me as setTableReview,At as shelfPriceLabel,Ot as shelfProblem,be as splitLayout,_ as textDeltaOf,L as thinkingDeltaOf,U as toolEventOf,Mt as totalFor,q as useArtifactUrl,j as useChat,Lt as useCredits,V as useHolaClient,Vt as useShop,Gt as useThread};
|
|
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};
|
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.30",
|
|
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",
|