@holaboss/client 0.2.0-beta.23 → 0.2.0-beta.24
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 +3 -3
- package/dist/index.d.cts +204 -186
- package/dist/index.d.ts +204 -186
- package/dist/index.js +4 -4
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use client'
|
|
2
|
-
var ee=Object.defineProperty;var ot=Object.getOwnPropertyDescriptor;var st=Object.getOwnPropertyNames;var it=Object.prototype.hasOwnProperty;var at=(e,t)=>{for(var r in t)ee(e,r,{get:t[r],enumerable:!0})},lt=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of st(t))!it.call(e,s)&&s!==r&&ee(e,s,{get:()=>t[s],enumerable:!(n=ot(t,s))||n.enumerable});return e};var ut=e=>lt(ee({},"__esModule",{value:!0}),e);var Lt={};at(Lt,{Chat:()=>We,CreditRefused:()
|
|
2
|
+
var ee=Object.defineProperty;var ot=Object.getOwnPropertyDescriptor;var st=Object.getOwnPropertyNames;var it=Object.prototype.hasOwnProperty;var at=(e,t)=>{for(var r in t)ee(e,r,{get:t[r],enumerable:!0})},lt=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of st(t))!it.call(e,s)&&s!==r&&ee(e,s,{get:()=>t[s],enumerable:!(n=ot(t,s))||n.enumerable});return e};var ut=e=>lt(ee({},"__esModule",{value:!0}),e);var Lt={};at(Lt,{Chat:()=>We,CreditRefused:()=>M,GRID_COLS:()=>oe,GRID_MAX_COLS:()=>se,GRID_MAX_ROWS:()=>ie,HolaProvider:()=>Me,PortalConflict:()=>$,bandOfKind:()=>W,bandOfType:()=>ae,buyRequestText:()=>Ye,cellValue:()=>ve,createApiTransport:()=>He,createHolaClient:()=>Ee,createPortalCredits:()=>Ne,createPortalData:()=>Ve,createPortalShop:()=>je,createWidgetTransport:()=>J,deliverableCellText:()=>he,deliverableStatus:()=>fe,deriveFields:()=>re,emptyTableResponses:()=>_,facetValues:()=>Qe,footprintOf:()=>le,footprintWith:()=>K,formatDeliverableDate:()=>ke,groupDeliverableVersions:()=>Y,includesFor:()=>Xe,inferSpec:()=>ne,isDeliverableChecked:()=>xe,mergeMessage:()=>Re,modeOf:()=>Ge,money:()=>F,normalizeDeliverableColType:()=>Z,normalizeDeliverableItem:()=>Q,parseDashboardSpec:()=>me,parseDeliverableItems:()=>ge,parseDeliverableTable:()=>be,parseTableResponses:()=>we,placeWidgets:()=>X,priceFor:()=>ze,priceLabel:()=>Te,publishedVersionOf:()=>ye,quantityRange:()=>Ke,renderModel:()=>ce,setResponse:()=>Se,setTableReview:()=>Pe,shelfPriceLabel:()=>Be,shelfProblem:()=>Ze,splitLayout:()=>ue,textDeltaOf:()=>L,thinkingDeltaOf:()=>U,toolEventOf:()=>N,totalFor:()=>Je,useArtifactUrl:()=>j,useChat:()=>B,useCredits:()=>et,useHolaClient:()=>q,useShop:()=>tt,useThread:()=>nt});module.exports=ut(Lt);var Ce=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="message_update"?t.assistantMessageEvent??null:null},L=e=>{let t=Ce(e);return t?.type==="text_delta"&&typeof t.delta=="string"?t.delta:null},U=e=>{let t=Ce(e);return t?.type==="thinking_delta"&&typeof t.delta=="string"?t.delta:null},N=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 dt=/^ /,x=e=>{if(e&&typeof e=="object"){let t=e,r=typeof t.error=="string"?t.error:"request_failed";return typeof t.retryable=="boolean"?{error:r,retryable:t.retryable}:{error:r}}return{error:"request_failed"}},pt=e=>{let t="message",r=[];for(let n of e.split(`
|
|
3
3
|
`))n.startsWith(":")||(n.startsWith("event:")?t=n.slice(6).trim():n.startsWith("data:")&&r.push(n.slice(5).replace(dt,"")));return r.length>0?{event:t,data:r.join(`
|
|
4
|
-
`)}:null},ct=(e,t,r)=>{let n;try{n=JSON.parse(e.data)}catch{return}if(e.event==="session"){let s=n.sessionId;s&&(r(s),t.onSession?.(s));return}if(e.event==="turn_event"){t.onEvent?.(n);let s=L(n);s&&t.onText?.(s);let a=U(n);a&&t.onThinking?.(a);let o=N(n);o&&t.onTool?.(o);return}if(e.event==="chat_completed"){let s=n;r(s.sessionId),t.onComplete?.(s);return}e.event==="chat_error"&&t.onError?.(x(n))},
|
|
4
|
+
`)}:null},ct=(e,t,r)=>{let n;try{n=JSON.parse(e.data)}catch{return}if(e.event==="session"){let s=n.sessionId;s&&(r(s),t.onSession?.(s));return}if(e.event==="turn_event"){t.onEvent?.(n);let s=L(n);s&&t.onText?.(s);let a=U(n);a&&t.onThinking?.(a);let o=N(n);o&&t.onTool?.(o);return}if(e.event==="chat_completed"){let s=n;r(s.sessionId),t.onComplete?.(s);return}e.event==="chat_error"&&t.onError?.(x(n))},P=async(e,t)=>{let r=await fetch(e,{headers:t});if(!r.ok)throw new Error(`hola: request failed (${r.status})`);return await r.json()},De=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()},Ie=async(e,t,r,n)=>{let s=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body,signal:n});if(!(s.ok&&s.body)){t.onError?.({error:`stream_failed_${s.status}`});return}let a=s.body.getReader(),o=new TextDecoder,i="",l=()=>{let d=i.indexOf(`
|
|
5
5
|
|
|
6
6
|
`);for(;d!==-1;){let c=i.slice(0,d);i=i.slice(d+2);let m=pt(c);m&&ct(m,t,r),d=i.indexOf(`
|
|
7
7
|
|
|
8
|
-
`)}},u=async()=>{let d=await a.read();if(!d.done)return i+=o.decode(d.value,{stream:!0}),l(),u()};await u()};var mt=/\/+$/,te="/api/v1/end-user",He=e=>{let t=e.baseUrl.replace(mt,""),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()}`}),a=async o=>{let i=await fetch(`${t}${te}/chat${n("?")}`,{method:"POST",headers:await s(),body:JSON.stringify({message:o})});if(!i.ok)throw new Error(`hola: message failed (${i.status})`);return{reply:(await i.json()).reply??"",sessionId:"",artifacts:[]}};return{sessionId:()=>"",getInfo:async()=>k(`${t}${te}/chat/info${n("?")}`,await s()),sendMessage:a,streamMessage:async(o,i)=>{try{let l=await a(o);i.onText?.(l.reply),i.onComplete?.(l)}catch(l){i.onError?.(x(l))}},subscribe:(o,i)=>{let l=i?.since??"0",u=!1,d,c=i?.intervalMs??3e3,m=typeof document<"u",p=()=>m&&document.visibilityState==="hidden",y=!1,w=()=>{if(!u){if(p()){y=!0;return}d=setTimeout(f,c)}},f=async()=>{try{let h=await k(`${t}${te}/chat/thread?since=${encodeURIComponent(l)}${n("&")}`,await s());for(let I of h.messages)o.onMessage(I);l=h.cursor,o.onHealthy?.()}catch(h){o.onError?.(x(h))}w()},R=()=>{u||!y||p()||(y=!1,d&&clearTimeout(d),d=setTimeout(f,0))};m&&document.addEventListener("visibilitychange",R);let g=()=>{u=!0,d&&clearTimeout(d),m&&document.removeEventListener("visibilitychange",R)};return i?.signal?.addEventListener("abort",g),d=setTimeout(f,0),g}}};var V=require("react"),j=(e,t)=>{let[r,n]=(0,V.useState)("");return(0,V.useEffect)(()=>{if(!e){n("");return}let s=Uint8Array.from(atob(e),o=>o.charCodeAt(0)),a=URL.createObjectURL(new Blob([s],{type:t}));return n(a),()=>URL.revokeObjectURL(a)},[e,t]),r};var z=require("react");var G=require("react"),$e=require("react/jsx-runtime"),Ae=(0,G.createContext)(null),Me=({client:e,children:t})=>(0,$e.jsx)(Ae.Provider,{value:e,children:t}),B=()=>{let e=(0,G.useContext)(Ae);if(!e)throw new Error("useHolaClient must be used within <HolaProvider>");return e};var v=require("react"),q=e=>{let[t,r]=(0,v.useState)([]),[n,s]=(0,v.useState)(""),[a,o]=(0,v.useState)(!1),[i,l]=(0,v.useState)(null),u=(0,v.useRef)(0),d=(0,v.useRef)(null);(0,v.useEffect)(()=>()=>d.current?.abort(),[]);let c=(0,v.useCallback)(()=>{let p=u.current;return u.current+=1,p},[]);(0,v.useEffect)(()=>{let p=!0;return e.getInfo().then(y=>{p&&y.greeting&&r([{id:c(),role:"assistant",text:y.greeting}])}).catch(()=>{}),()=>{p=!1}},[e,c]);let m=(0,v.useCallback)(()=>{let p=n.trim();if(!p||a)return;s(""),l(null),o(!0);let y=c(),w=c();r(g=>[...g,{id:y,role:"user",text:p},{id:w,role:"assistant",text:"",streaming:!0}]);let f=g=>{r(h=>h.map(I=>I.id===w?g(I):I))},R=new AbortController;d.current=R,e.streamMessage(p,{onText:g=>f(h=>({...h,text:h.text+g})),onComplete:g=>{f(h=>({...h,text:g.reply||h.text,artifacts:g.artifacts,streaming:!1})),o(!1)},onError:g=>{f(h=>({...h,streaming:!1})),l(g.error),o(!1)}},R.signal).catch(g=>{f(h=>({...h,streaming:!1})),l(g instanceof Error?g.message:"stream_failed"),o(!1)}).finally(()=>{o(!1),f(g=>g.streaming?{...g,streaming:!1}:g)})},[n,a,e,c]);return{messages:t,input:n,setInput:s,send:m,sending:a,error:i}};var S=require("react/jsx-runtime"),T={root:{display:"flex",flexDirection:"column",height:"100%",fontFamily:"system-ui, -apple-system, sans-serif",fontSize:14,color:"#111827"},log:{flex:1,overflowY:"auto",padding:12,display:"flex",flexDirection:"column",gap:8},user:{alignSelf:"flex-end",background:"#111827",color:"#ffffff",borderRadius:12,padding:"8px 12px",maxWidth:"80%",whiteSpace:"pre-wrap"},assistant:{alignSelf:"flex-start",background:"#f1f1f4",color:"#111827",borderRadius:12,padding:"8px 12px",maxWidth:"80%",whiteSpace:"pre-wrap"},artifacts:{display:"flex",flexDirection:"column",gap:6,marginTop:6},image:{maxHeight:220,borderRadius:8,border:"1px solid #e5e7eb"},link:{color:"#2563eb",textDecoration:"underline",wordBreak:"break-all"},error:{color:"#b91c1c",padding:"4px 12px",fontSize:13},form:{display:"flex",gap:8,borderTop:"1px solid #e5e7eb",padding:8},input:{flex:1,border:"1px solid #d1d5db",borderRadius:8,padding:"8px 10px",fontSize:14,outline:"none"},button:{border:"none",background:"#111827",color:"#ffffff",borderRadius:8,padding:"8px 14px",fontSize:14,cursor:"pointer"}},gt=({artifact:e})=>{let t=j(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:a,error:o}=q(e),i=(0,z.useRef)(null);(0,z.useEffect)(()=>{let u=i.current;u&&(u.scrollTop=u.scrollHeight)},[t]);let l=u=>{u.preventDefault(),s()};return(0,S.jsxs)("div",{style:T.root,children:[(0,S.jsx)("div",{ref:i,style:T.log,children:t.map(u=>(0,S.jsxs)("div",{style:u.role==="user"?T.user:T.assistant,children:[u.text||(u.streaming?"\u2026":""),u.artifacts&&u.artifacts.length>0?(0,S.jsx)("div",{style:T.artifacts,children:u.artifacts.map(d=>(0,S.jsx)(gt,{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:a||r.trim().length===0,style:T.button,type:"submit",children:"Send"})]})]})};var ft=/\/+$/,J=e=>{let t=e.sessionId,r=e.baseUrl.replace(ft,""),n=o=>`${r}/endpoint/${encodeURIComponent(e.token)}${o}`,s={"content-type":"application/json"},a=(o,i)=>({url:n(o),headers:s,body:JSON.stringify({message:i,...t?{sessionId:t}:{},...e.identity?{externalUserId:e.identity.externalUserId,userHmac:e.identity.userHmac}:{}})});return{sessionId:()=>t,getInfo:()=>k(n("/config"),{}),sendMessage:async o=>{let i=await De(a("/message",o));return t=i.sessionId,i},streamMessage:(o,i,l)=>Ie(a("/message/stream",o),i,u=>{t=u},l),subscribe:(o,i)=>{let l=i?.since??"0",u=!1,d,c=i?.intervalMs??3e3,m=async()=>{let y=t;if(y)try{let w=await k(n(`/messages?session=${encodeURIComponent(y)}&since=${encodeURIComponent(l)}`),{});for(let f of w.messages)o.onMessage(f);l=w.cursor,o.onHealthy?.()}catch(w){o.onError?.(x(w))}u||(d=setTimeout(m,c))},p=()=>{u=!0,d&&clearTimeout(d)};return i?.signal?.addEventListener("abort",p),d=setTimeout(m,0),p}}};var Ee=e=>"transport"in e?e.transport:J(e);var yt=/^https?:\/\//i,bt=/^\d{4}-\d{2}-\d{2}(?:[T ]|$)/,ht=e=>e.replace(/_/g," ").replace(/\b\w/g,t=>t.toUpperCase());function xt(e){if(typeof e=="number")return"number";if(typeof e=="boolean")return"boolean";if(typeof e=="string"){if(yt.test(e))return"url";if(bt.test(e))return"date"}return"text"}function re(e){let t=[],r=new Map;for(let n of e)for(let[s,a]of Object.entries(n.data??{})){if(a==null)continue;let o=r.get(s);o||(o=new Map,r.set(s,o),t.push(s));let i=xt(a);o.set(i,(o.get(i)??0)+1)}return t.map(n=>{let s=r.get(n)??new Map,a="text",o=-1;for(let[i,l]of s)l>o&&(o=l,a=i);return{key:n,label:ht(n),type:a}})}var wt=e=>typeof e=="number"?e:Number(e)||0,Oe=e=>/rate|position|rank|score|percent|avg/i.test(e),vt=/posted|published|sent|completed|shipped|launched|_at/i,St=new Set(["service","order","end_user_id"]);function ne(e,t){let r=e.filter(l=>!St.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"),a=r.find(l=>l.type==="date"&&vt.test(l.key))??r.find(l=>l.type==="date"),o=r.filter(l=>l.type==="number"&&!Oe(l.key)).map(l=>({field:l,total:t.reduce((u,d)=>u+wt(d.data[l.key]),0)})).sort((l,u)=>u.total-l.total).find(l=>l.total>0)?.field??null,i=[{type:"stat",label:"Items",agg:"count"}];for(let l of n){let u=Oe(l.key);i.push({type:"stat",metric:l.key,agg:u?"avg":"sum",label:u?`Avg ${l.label.toLowerCase()}`:l.label})}return a&&i.push({type:"line",x:a.key,y:o?.key,agg:"sum",title:o?`${o.label} by day`:"Items by day"}),s&&i.push({type:"donut",groupBy:s.key,title:s.label}),i.push({type:"table",columns:r.map(l=>l.key)}),{version:1,widgets:i}}var oe=6,se=6,ie=4,_e={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))),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 ae(e){return e==="stat"?"stat":e==="line"||e==="bar"||e==="donut"?"chart":"block"}function le(e){return _e[e]}function K(e,t,r){let n=_e[e];return{w:t===void 0?n.w:kt(t),h:r===void 0?n.h:Pt(r)}}function X(e){let t=[],r=[],n=(o,i,l,u)=>{if(o<0||o+l>6)return!1;for(let d=0;d<u;d+=1){let c=r[i+d];if(c){for(let m=0;m<l;m+=1)if(c[o+m])return!1}}return!0},s=(o,i,l,u)=>{for(let d=0;d<u;d+=1){let c=r[i+d]??[];for(let m=0;m<l;m+=1)c[o+m]=!0;r[i+d]=c}},a=(o,i)=>{for(let l=0;;l+=1)for(let u=0;u+o<=6;u+=1)if(n(u,l,o,i))return{gx:u,gy:l}};for(let o of e){let i=K(W(o.kind),o.w,o.h),u=o.gx!==void 0&&o.gy!==void 0&&n(o.gx,o.gy,i.w,i.h)&&o.gx!==void 0&&o.gy!==void 0?{gx:o.gx,gy:o.gy}:a(i.w,i.h);s(u.gx,u.gy,i.w,i.h),t.push({widget:o,gx:u.gx,gy:u.gy,w:i.w,h:i.h})}return t}function 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 Fe=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 Tt(e,t,r,n){let s=new Map;for(let a of e){let o=new Date(Le(a.data[t]));if(Number.isNaN(o.getTime()))continue;let i=o.toISOString().slice(0,10),l=s.get(i)??[];l.push(r?de(a.data[r]):1),s.set(i,l)}return[...s.entries()].sort((a,o)=>a[0]<o[0]?-1:1).map(([a,o])=>({label:new Date(`${a}T00:00:00`).toLocaleDateString(void 0,{month:"short",day:"numeric"}),value:r?pe(n,o):o.length}))}function Rt(e,t,r,n="sum"){let s=new Map;for(let a of e){let o=Le(a.data[t]).trim();if(!o)continue;let i=s.get(o)??[];i.push(r?de(a.data[r]):1),s.set(o,i)}return[...s.entries()].map(([a,o])=>({label:a,value:r?pe(n,o):o.length})).sort((a,o)=>o.value-a.value)}function Ct(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 a=n.map(o=>de(o.data[s.key]));return{kind:"stat",label:e.label??s.label,value:pe(e.agg??"sum",a)}}case"line":case"bar":{if(!t.has(e.x)||e.y&&!t.has(e.y))return null;let s=Tt(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(a=>t.get(a)).filter(a=>a!==void 0&&!Fe.has(a.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,a=l=>({byKey:new Map(l.fields.map(u=>[u.key,u])),cols:l.fields.filter(u=>!Fe.has(u.key)),rows:l.rows}),o=a({fields:t,rows:r});for(let[l,u]of Object.entries(n))s.set(l,a(u));let i=[];for(let l of e.widgets){let u=l.type==="text"?void 0:l.source,d=u?s.get(u):o;if(!d)continue;let c=Ct(l,d.byKey,d.cols,d.rows);c&&i.push({...c,w:l.w,h:l.h,gx:l.gx,gy:l.gy})}return i}var Dt=new Set(["sum","avg","count","min","max","last"]),Ue=e=>typeof e=="string"&&Dt.has(e)?e:void 0,b=e=>typeof e=="string"&&e!==""?e:void 0,E=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,C=e=>typeof e=="number"&&e>=0?Math.round(e):void 0;function It(e){if(typeof e!="object"||e===null)return null;let t=e;switch(t.type){case"stat":return{type:"stat",source:b(t.source),label:b(t.label),metric:b(t.metric)??b(t.column),agg:Ue(t.agg),w:E(t.w),h:O(t.h),gx:C(t.gx),gy:C(t.gy)};case"line":case"bar":{let r=b(t.x);return r?{type:t.type,source:b(t.source),title:b(t.title),x:r,y:b(t.y)??b(t.column),agg:Ue(t.agg),w:E(t.w),h:O(t.h),gx:C(t.gx),gy:C(t.gy)}:null}case"donut":{let r=b(t.groupBy)??b(t.column);return r?{type:"donut",source:b(t.source),title:b(t.title),groupBy:r,w:E(t.w),h:O(t.h),gx:C(t.gx),gy:C(t.gy)}:null}case"table":{let r=Array.isArray(t.columns)?t.columns.filter(n=>typeof n=="string"):void 0;return{type:"table",source:b(t.source),title:b(t.title),columns:r,w:E(t.w),h:O(t.h),gx:C(t.gx),gy:C(t.gy)}}case"text":{let r=b(t.body);return r?{type:"text",title:b(t.title),body:r,w:E(t.w),h:O(t.h),gx:C(t.gx),gy:C(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(It).filter(a=>a!==null);if(n.length===0)return null;let s=t.version;return{version:typeof s=="number"?s:1,title:b(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 a=Y(e).find(i=>i.v===t)?.items??[],o=a.filter(i=>i.kind==="file").map(i=>r.get(i.value)??"");return a.some(i=>i.kind==="table")&&o.push(n),o.length===0||o.some(i=>i==="")?"awaiting":o.some(i=>i==="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((a,o)=>({key:typeof a.key=="string"&&a.key?a.key:typeof a.id=="string"&&a.id?a.id:`column_${o+1}`,label:typeof a.label=="string"?a.label:"",type:Z(a.type),...a.clientEditable===!0?{clientEditable:!0}:{}})),n=t.rows.map((a,o)=>({id:typeof a.id=="string"&&a.id?a.id:`row_${o}`,cells:a.cells&&typeof a.cells=="object"?a.cells:{}})),s=typeof t.name=="string"?t.name:void 0;return{columns: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 _(){return{cells:{},verdict:"",comment:""}}function we(e){if(typeof e!="string"||e.trim()==="")return _();try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t)){let r=t;return{cells:r.cells&&typeof r.cells=="object"?r.cells:r,verdict:r.verdict==="accepted"||r.verdict==="revise"?r.verdict:"",comment:typeof r.comment=="string"?r.comment:""}}}catch{}return _()}function 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 ke(e,t,r){return{...e,verdict:t,comment:r}}function Pe(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 Ht=/\/+$/,A="/api/v1/end-user",M=class extends Error{constructor(t){super(t),this.name="PortalConflict"}};function At(e){let t="";for(let n=0;n<e.length;n+=32768)t+=String.fromCharCode(...e.subarray(n,n+32768));return btoa(t)}var Ne=e=>{let t=e.baseUrl.replace(Ht,""),r=()=>typeof e.token=="function"?e.token():e.token,n=async()=>({"content-type":"application/json",authorization:`Bearer ${await r()}`}),s=async(o,i)=>{try{let l=await fetch(`${t}${A}${o}`,{method:i.method,headers:await n(),...i.body===void 0?{}:{body:JSON.stringify(i.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=`${i.method} ${o} \u2192 ${String(l.status)}`;try{let c=JSON.parse(u);c.message&&(d=c.message)}catch{d=u?`${d}: ${u}`:d}throw x({error:d})}return await l.json()}catch(l){throw l instanceof M?l:x(l)}},a=o=>`/tables/${encodeURIComponent(o)}`;return{listTables:async()=>(await k(`${t}${A}/tables`,await n())).tables,listRows:async(o,i)=>await k(`${t}${A}${a(o)}/rows?limit=${String(i??100)}`,await n()),insertRow:async(o,i)=>{let{rowIds:l}=await s(`${a(o)}/rows`,{method:"POST",body:{rows:[i]}}),u=l[0];if(!u)throw x(new Error("The row was not created."));return u},patchRow:async(o,i,l)=>(await s(`${a(o)}/rows/${encodeURIComponent(i)}`,{method:"PATCH",body:l})).updated,deleteRow:async(o,i)=>(await s(`/${encodeURIComponent(o)}/${encodeURIComponent(i)}`,{method:"DELETE"})).deleted,listFiles:async()=>(await k(`${t}${A}/tables/files/rows?limit=200`,await n())).rows.map(i=>({id:i.rowId,filename:String(i.data.filename??""),source:String(i.data.source??"client"),campaign:String(i.data.campaign??""),size:typeof i.data.size=="number"?i.data.size:0,createdAt:i.createdAt})),uploadFile:async(o,i)=>{let l=new Uint8Array(await o.arrayBuffer());return await s("/files",{method:"POST",body:{filename:o.name,mime:o.type||"application/octet-stream",data:At(l),...i===void 0?{}:{message:i}}})},fileLink:async o=>await k(`${t}${A}/files/${encodeURIComponent(o)}/url`,await n()),deleteFile:async o=>(await s(`/files/${encodeURIComponent(o)}`,{method:"DELETE"})).deleted,listDocuments:async()=>(await k(`${t}${A}/documents`,await n())).documents,readDocument:async o=>(await k(`${t}${A}/documents/${encodeURIComponent(o)}`,await n())).document,saveDocument:async(o,i)=>await s(`/documents/${encodeURIComponent(o)}`,{method:"PATCH",body:i})}};var Mt=/\/+$/,$t="/api/v1/end-user",Ve=e=>{let t=e.baseUrl.replace(Mt,""),r=async(n,s)=>{let a;try{a=await fetch(`${t}${$t}${n}`,s===void 0?{}:{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(s)})}catch(o){throw x(o)}if(a.status===429)throw x({error:"rate_limited",retryable:!0});if(!a.ok)throw x({error:`shop_request_failed_${String(a.status)}`});try{return await a.json()}catch(o){throw x(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}},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 $=class extends Error{code;status;constructor(t,r,n){super(r),this.name="CreditRefused",this.code=t,this.status=n}},Wt=/\/+$/,Et="/api/v1/end-user",je=e=>{let t=e.baseUrl.replace(Wt,""),r=()=>typeof e.token=="function"?e.token():e.token,n=async(s,a={method:"GET"})=>{try{let o=await fetch(`${t}${Et}${s}`,{method:a.method,headers:{"content-type":"application/json",authorization:`Bearer ${await r()}`},...a.body===void 0?{}:{body:JSON.stringify(a.body)}});if(!o.ok){let i=await o.json().catch(()=>({}));throw new $(i.error??"request_failed",i.message??`${a.method} ${s} \u2192 ${String(o.status)}`,o.status)}return await o.json()}catch(o){throw o instanceof $?o:x(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}),enquire:(s,a)=>n("/shop/enquire",{method:"POST",body:{productId:s,answers:a}})}};var H=require("react"),Ge=e=>{let[t,r]=(0,H.useState)(null),[n,s]=(0,H.useState)(!0),[a,o]=(0,H.useState)(null),i=(0,H.useCallback)(async()=>{try{r(await e.wallet()),o(null)}catch{o("Couldn't read your balance just now.")}finally{s(!1)}},[e]),l=(0,H.useCallback)(()=>{i().catch(()=>{})},[i]);return(0,H.useEffect)(()=>(l(),window.addEventListener("focus",l),()=>{window.removeEventListener("focus",l)}),[l]),{wallet:t,loading:n,failure:a,refresh:l}};var Ot=new Set(["buy","ask","apply"]);function Be(e){return Ot.has(e.mode)?e.mode:"ask"}var _t={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 qe(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"?F(e.price,t):`${F(e.unitPrice,t)} per ${e.unitStep===1?e.unit:qe(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 ${F(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,a=r.kind==="per_unit"?`, ${qe(n,r.unit)}`:"";return`I'd like to buy ${s}${a}. 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 D=require("react"),Ft=e=>e&&typeof e=="object"&&typeof e.error=="string"?e.error:e instanceof Error?e.message:"shop_unavailable",tt=e=>{let[t,r]=(0,D.useState)([]),[n,s]=(0,D.useState)(!1),[a,o]=(0,D.useState)(!0),[i,l]=(0,D.useState)(null),[u,d]=(0,D.useState)(0);(0,D.useEffect)(()=>{let m=!0;return o(!0),e.listProducts().then(p=>{m&&(r(p.products),s(p.truncated),l(null))}).catch(p=>{m&&l(Ft(p))}).finally(()=>{m&&o(!1)}),()=>{m=!1}},[e,u]);let c=(0,D.useCallback)(()=>d(m=>m+1),[]);return{products:t,truncated:n,loading:a,error:i,reload:c}};var P=require("react"),rt="greeting";function Re(e,t){if(e.some(a=>a.id===t.id))return e;let r=e.filter(a=>a.id!==rt),n=a=>a.author==="client"==(t.author==="client");return[...r.filter(a=>!(a.pending&&n(a)&&a.text===t.text)),t]}var nt=(e,t)=>{let[r,n]=(0,P.useState)([]),[s,a]=(0,P.useState)(""),[o,i]=(0,P.useState)(!1),[l,u]=(0,P.useState)(null),d=(0,P.useRef)(0),c=t?.pollMs??2e3;(0,P.useEffect)(()=>{let p=!0;return e.getInfo().then(y=>{p&&y.greeting&&n(w=>w.length===0?[{id:rt,cursor:"",author:"agent",text:y.greeting}]:w)}).catch(()=>{}),()=>{p=!1}},[e]),(0,P.useEffect)(()=>e.subscribe?.({onMessage:p=>n(y=>Re(y,p)),onError:p=>u(p.error),onHealthy:()=>u(null)},{intervalMs:c}),[e,c]);let m=(0,P.useCallback)(()=>{let p=s.trim();if(!p||o)return;a(""),u(null),i(!0),d.current+=1;let y=`pending-${d.current}`,w={id:y,cursor:"",author:"client",text:p,pending:!0};n(f=>[...f,w]),e.sendMessage(p).then(f=>{i(!1),f.reply.trim()&&n(g=>g.some(I=>!I.pending&&I.author!=="client"&&I.text===f.reply)?g:(d.current+=1,[...g,{id:`pending-agent-${d.current}`,cursor:"",author:"agent",text:f.reply,pending:!0}]))}).catch(f=>{u(f instanceof Error?f.message:"send_failed"),i(!1),n(R=>R.filter(g=>g.id!==y)),a(R=>R||p)})},[s,o,e]);return{messages:r,input:s,setInput:a,send:m,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,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 a.read();if(!d.done)return i+=o.decode(d.value,{stream:!0}),l(),u()};await u()};var mt=/\/+$/,te="/api/v1/end-user",He=e=>{let t=e.baseUrl.replace(mt,""),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()}`}),a=async o=>{let i=await fetch(`${t}${te}/chat${n("?")}`,{method:"POST",headers:await s(),body:JSON.stringify({message:o})});if(!i.ok)throw new Error(`hola: message failed (${i.status})`);return{reply:(await i.json()).reply??"",sessionId:"",artifacts:[]}};return{sessionId:()=>"",getInfo:async()=>P(`${t}${te}/chat/info${n("?")}`,await s()),sendMessage:a,streamMessage:async(o,i)=>{try{let l=await a(o);i.onText?.(l.reply),i.onComplete?.(l)}catch(l){i.onError?.(x(l))}},subscribe:(o,i)=>{let l=i?.since??"0",u=!1,d,c=i?.intervalMs??3e3,m=typeof document<"u",p=()=>m&&document.visibilityState==="hidden",y=!1,w=()=>{if(!u){if(p()){y=!0;return}d=setTimeout(f,c)}},f=async()=>{try{let h=await P(`${t}${te}/chat/thread?since=${encodeURIComponent(l)}${n("&")}`,await s());for(let I of h.messages)o.onMessage(I);l=h.cursor,o.onHealthy?.()}catch(h){o.onError?.(x(h))}w()},R=()=>{u||!y||p()||(y=!1,d&&clearTimeout(d),d=setTimeout(f,0))};m&&document.addEventListener("visibilitychange",R);let g=()=>{u=!0,d&&clearTimeout(d),m&&document.removeEventListener("visibilitychange",R)};return i?.signal?.addEventListener("abort",g),d=setTimeout(f,0),g}}};var V=require("react"),j=(e,t)=>{let[r,n]=(0,V.useState)("");return(0,V.useEffect)(()=>{if(!e){n("");return}let s=Uint8Array.from(atob(e),o=>o.charCodeAt(0)),a=URL.createObjectURL(new Blob([s],{type:t}));return n(a),()=>URL.revokeObjectURL(a)},[e,t]),r};var z=require("react");var G=require("react"),$e=require("react/jsx-runtime"),Ae=(0,G.createContext)(null),Me=({client:e,children:t})=>(0,$e.jsx)(Ae.Provider,{value:e,children:t}),q=()=>{let e=(0,G.useContext)(Ae);if(!e)throw new Error("useHolaClient must be used within <HolaProvider>");return e};var v=require("react"),B=e=>{let[t,r]=(0,v.useState)([]),[n,s]=(0,v.useState)(""),[a,o]=(0,v.useState)(!1),[i,l]=(0,v.useState)(null),u=(0,v.useRef)(0),d=(0,v.useRef)(null);(0,v.useEffect)(()=>()=>d.current?.abort(),[]);let c=(0,v.useCallback)(()=>{let p=u.current;return u.current+=1,p},[]);(0,v.useEffect)(()=>{let p=!0;return e.getInfo().then(y=>{p&&y.greeting&&r([{id:c(),role:"assistant",text:y.greeting}])}).catch(()=>{}),()=>{p=!1}},[e,c]);let m=(0,v.useCallback)(()=>{let p=n.trim();if(!p||a)return;s(""),l(null),o(!0);let y=c(),w=c();r(g=>[...g,{id:y,role:"user",text:p},{id:w,role:"assistant",text:"",streaming:!0}]);let f=g=>{r(h=>h.map(I=>I.id===w?g(I):I))},R=new AbortController;d.current=R,e.streamMessage(p,{onText:g=>f(h=>({...h,text:h.text+g})),onComplete:g=>{f(h=>({...h,text:g.reply||h.text,artifacts:g.artifacts,streaming:!1})),o(!1)},onError:g=>{f(h=>({...h,streaming:!1})),l(g.error),o(!1)}},R.signal).catch(g=>{f(h=>({...h,streaming:!1})),l(g instanceof Error?g.message:"stream_failed"),o(!1)}).finally(()=>{o(!1),f(g=>g.streaming?{...g,streaming:!1}:g)})},[n,a,e,c]);return{messages:t,input:n,setInput:s,send:m,sending:a,error:i}};var S=require("react/jsx-runtime"),T={root:{display:"flex",flexDirection:"column",height:"100%",fontFamily:"system-ui, -apple-system, sans-serif",fontSize:14,color:"#111827"},log:{flex:1,overflowY:"auto",padding:12,display:"flex",flexDirection:"column",gap:8},user:{alignSelf:"flex-end",background:"#111827",color:"#ffffff",borderRadius:12,padding:"8px 12px",maxWidth:"80%",whiteSpace:"pre-wrap"},assistant:{alignSelf:"flex-start",background:"#f1f1f4",color:"#111827",borderRadius:12,padding:"8px 12px",maxWidth:"80%",whiteSpace:"pre-wrap"},artifacts:{display:"flex",flexDirection:"column",gap:6,marginTop:6},image:{maxHeight:220,borderRadius:8,border:"1px solid #e5e7eb"},link:{color:"#2563eb",textDecoration:"underline",wordBreak:"break-all"},error:{color:"#b91c1c",padding:"4px 12px",fontSize:13},form:{display:"flex",gap:8,borderTop:"1px solid #e5e7eb",padding:8},input:{flex:1,border:"1px solid #d1d5db",borderRadius:8,padding:"8px 10px",fontSize:14,outline:"none"},button:{border:"none",background:"#111827",color:"#ffffff",borderRadius:8,padding:"8px 14px",fontSize:14,cursor:"pointer"}},gt=({artifact:e})=>{let t=j(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=q(),{messages:t,input:r,setInput:n,send:s,sending:a,error:o}=B(e),i=(0,z.useRef)(null);(0,z.useEffect)(()=>{let u=i.current;u&&(u.scrollTop=u.scrollHeight)},[t]);let l=u=>{u.preventDefault(),s()};return(0,S.jsxs)("div",{style:T.root,children:[(0,S.jsx)("div",{ref:i,style:T.log,children:t.map(u=>(0,S.jsxs)("div",{style:u.role==="user"?T.user:T.assistant,children:[u.text||(u.streaming?"\u2026":""),u.artifacts&&u.artifacts.length>0?(0,S.jsx)("div",{style:T.artifacts,children:u.artifacts.map(d=>(0,S.jsx)(gt,{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:a||r.trim().length===0,style:T.button,type:"submit",children:"Send"})]})]})};var ft=/\/+$/,J=e=>{let t=e.sessionId,r=e.baseUrl.replace(ft,""),n=o=>`${r}/endpoint/${encodeURIComponent(e.token)}${o}`,s={"content-type":"application/json"},a=(o,i)=>({url:n(o),headers:s,body:JSON.stringify({message:i,...t?{sessionId:t}:{},...e.identity?{externalUserId:e.identity.externalUserId,userHmac:e.identity.userHmac}:{}})});return{sessionId:()=>t,getInfo:()=>P(n("/config"),{}),sendMessage:async o=>{let i=await De(a("/message",o));return t=i.sessionId,i},streamMessage:(o,i,l)=>Ie(a("/message/stream",o),i,u=>{t=u},l),subscribe:(o,i)=>{let l=i?.since??"0",u=!1,d,c=i?.intervalMs??3e3,m=async()=>{let y=t;if(y)try{let w=await P(n(`/messages?session=${encodeURIComponent(y)}&since=${encodeURIComponent(l)}`),{});for(let f of w.messages)o.onMessage(f);l=w.cursor,o.onHealthy?.()}catch(w){o.onError?.(x(w))}u||(d=setTimeout(m,c))},p=()=>{u=!0,d&&clearTimeout(d)};return i?.signal?.addEventListener("abort",p),d=setTimeout(m,0),p}}};var Ee=e=>"transport"in e?e.transport:J(e);var yt=/^https?:\/\//i,bt=/^\d{4}-\d{2}-\d{2}(?:[T ]|$)/,ht=e=>e.replace(/_/g," ").replace(/\b\w/g,t=>t.toUpperCase());function xt(e){if(typeof e=="number")return"number";if(typeof e=="boolean")return"boolean";if(typeof e=="string"){if(yt.test(e))return"url";if(bt.test(e))return"date"}return"text"}function re(e){let t=[],r=new Map;for(let n of e)for(let[s,a]of Object.entries(n.data??{})){if(a==null)continue;let o=r.get(s);o||(o=new Map,r.set(s,o),t.push(s));let i=xt(a);o.set(i,(o.get(i)??0)+1)}return t.map(n=>{let s=r.get(n)??new Map,a="text",o=-1;for(let[i,l]of s)l>o&&(o=l,a=i);return{key:n,label:ht(n),type:a}})}var wt=e=>typeof e=="number"?e:Number(e)||0,Oe=e=>/rate|position|rank|score|percent|avg/i.test(e),vt=/posted|published|sent|completed|shipped|launched|_at/i,St=new Set(["service","order","end_user_id"]);function ne(e,t){let r=e.filter(l=>!St.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"),a=r.find(l=>l.type==="date"&&vt.test(l.key))??r.find(l=>l.type==="date"),o=r.filter(l=>l.type==="number"&&!Oe(l.key)).map(l=>({field:l,total:t.reduce((u,d)=>u+wt(d.data[l.key]),0)})).sort((l,u)=>u.total-l.total).find(l=>l.total>0)?.field??null,i=[{type:"stat",label:"Items",agg:"count"}];for(let l of n){let u=Oe(l.key);i.push({type:"stat",metric:l.key,agg:u?"avg":"sum",label:u?`Avg ${l.label.toLowerCase()}`:l.label})}return a&&i.push({type:"line",x:a.key,y:o?.key,agg:"sum",title:o?`${o.label} by day`:"Items by day"}),s&&i.push({type:"donut",groupBy:s.key,title:s.label}),i.push({type:"table",columns:r.map(l=>l.key)}),{version:1,widgets:i}}var oe=6,se=6,ie=4,_e={stat:{w:1,h:1},chart:{w:2,h:2},block:{w:6,h:2}},Pt=e=>Math.max(1,Math.min(6,Math.round(e))),kt=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 _e[e]}function K(e,t,r){let n=_e[e];return{w:t===void 0?n.w:Pt(t),h:r===void 0?n.h:kt(r)}}function X(e){let t=[],r=[],n=(o,i,l,u)=>{if(o<0||o+l>6)return!1;for(let d=0;d<u;d+=1){let c=r[i+d];if(c){for(let m=0;m<l;m+=1)if(c[o+m])return!1}}return!0},s=(o,i,l,u)=>{for(let d=0;d<u;d+=1){let c=r[i+d]??[];for(let m=0;m<l;m+=1)c[o+m]=!0;r[i+d]=c}},a=(o,i)=>{for(let l=0;;l+=1)for(let u=0;u+o<=6;u+=1)if(n(u,l,o,i))return{gx:u,gy:l}};for(let o of e){let i=K(W(o.kind),o.w,o.h),u=o.gx!==void 0&&o.gy!==void 0&&n(o.gx,o.gy,i.w,i.h)&&o.gx!==void 0&&o.gy!==void 0?{gx:o.gx,gy:o.gy}:a(i.w,i.h);s(u.gx,u.gy,i.w,i.h),t.push({widget:o,gx:u.gx,gy:u.gy,w:i.w,h:i.h})}return t}function 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 Fe=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 Tt(e,t,r,n){let s=new Map;for(let a of e){let o=new Date(Le(a.data[t]));if(Number.isNaN(o.getTime()))continue;let i=o.toISOString().slice(0,10),l=s.get(i)??[];l.push(r?de(a.data[r]):1),s.set(i,l)}return[...s.entries()].sort((a,o)=>a[0]<o[0]?-1:1).map(([a,o])=>({label:new Date(`${a}T00:00:00`).toLocaleDateString(void 0,{month:"short",day:"numeric"}),value:r?pe(n,o):o.length}))}function Rt(e,t,r,n="sum"){let s=new Map;for(let a of e){let o=Le(a.data[t]).trim();if(!o)continue;let i=s.get(o)??[];i.push(r?de(a.data[r]):1),s.set(o,i)}return[...s.entries()].map(([a,o])=>({label:a,value:r?pe(n,o):o.length})).sort((a,o)=>o.value-a.value)}function Ct(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 a=n.map(o=>de(o.data[s.key]));return{kind:"stat",label:e.label??s.label,value:pe(e.agg??"sum",a)}}case"line":case"bar":{if(!t.has(e.x)||e.y&&!t.has(e.y))return null;let s=Tt(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(a=>t.get(a)).filter(a=>a!==void 0&&!Fe.has(a.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,a=l=>({byKey:new Map(l.fields.map(u=>[u.key,u])),cols:l.fields.filter(u=>!Fe.has(u.key)),rows:l.rows}),o=a({fields:t,rows:r});for(let[l,u]of Object.entries(n))s.set(l,a(u));let i=[];for(let l of e.widgets){let u=l.type==="text"?void 0:l.source,d=u?s.get(u):o;if(!d)continue;let c=Ct(l,d.byKey,d.cols,d.rows);c&&i.push({...c,w:l.w,h:l.h,gx:l.gx,gy:l.gy})}return i}var Dt=new Set(["sum","avg","count","min","max","last"]),Ue=e=>typeof e=="string"&&Dt.has(e)?e:void 0,b=e=>typeof e=="string"&&e!==""?e:void 0,E=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,C=e=>typeof e=="number"&&e>=0?Math.round(e):void 0;function It(e){if(typeof e!="object"||e===null)return null;let t=e;switch(t.type){case"stat":return{type:"stat",source:b(t.source),label:b(t.label),metric:b(t.metric)??b(t.column),agg:Ue(t.agg),w:E(t.w),h:O(t.h),gx:C(t.gx),gy:C(t.gy)};case"line":case"bar":{let r=b(t.x);return r?{type:t.type,source:b(t.source),title:b(t.title),x:r,y:b(t.y)??b(t.column),agg:Ue(t.agg),w:E(t.w),h:O(t.h),gx:C(t.gx),gy:C(t.gy)}:null}case"donut":{let r=b(t.groupBy)??b(t.column);return r?{type:"donut",source:b(t.source),title:b(t.title),groupBy:r,w:E(t.w),h:O(t.h),gx:C(t.gx),gy:C(t.gy)}:null}case"table":{let r=Array.isArray(t.columns)?t.columns.filter(n=>typeof n=="string"):void 0;return{type:"table",source:b(t.source),title:b(t.title),columns:r,w:E(t.w),h:O(t.h),gx:C(t.gx),gy:C(t.gy)}}case"text":{let r=b(t.body);return r?{type:"text",title:b(t.title),body:r,w:E(t.w),h:O(t.h),gx:C(t.gx),gy:C(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(It).filter(a=>a!==null);if(n.length===0)return null;let s=t.version;return{version:typeof s=="number"?s:1,title:b(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 a=Y(e).find(i=>i.v===t)?.items??[],o=a.filter(i=>i.kind==="file").map(i=>r.get(i.value)??"");return a.some(i=>i.kind==="table")&&o.push(n),o.length===0||o.some(i=>i==="")?"awaiting":o.some(i=>i==="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((a,o)=>({key:typeof a.key=="string"&&a.key?a.key:typeof a.id=="string"&&a.id?a.id:`column_${o+1}`,label:typeof a.label=="string"?a.label:"",type:Z(a.type),...a.clientEditable===!0?{clientEditable:!0}:{}})),n=t.rows.map((a,o)=>({id:typeof a.id=="string"&&a.id?a.id:`row_${o}`,cells:a.cells&&typeof a.cells=="object"?a.cells:{}})),s=typeof t.name=="string"?t.name:void 0;return{columns: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 _(){return{cells:{},verdict:"",comment:""}}function we(e){if(typeof e!="string"||e.trim()==="")return _();try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t)){let r=t;return{cells:r.cells&&typeof r.cells=="object"?r.cells:r,verdict:r.verdict==="accepted"||r.verdict==="revise"?r.verdict:"",comment:typeof r.comment=="string"?r.comment:""}}}catch{}return _()}function 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=/\/+$/,At="/api/v1/end-user",Ne=e=>{let t=e.baseUrl.replace(Ht,""),r=()=>typeof e.token=="function"?e.token():e.token,n=async(s,a={method:"GET"})=>{try{let o=await fetch(`${t}${At}${s}`,{method:a.method,headers:{"content-type":"application/json",authorization:`Bearer ${await r()}`},...a.body===void 0?{}:{body:JSON.stringify(a.body)}});if(!o.ok){let i=await o.json().catch(()=>({}));throw new M(i.error??"request_failed",i.message??`${a.method} ${s} \u2192 ${String(o.status)}`,o.status)}return await o.json()}catch(o){throw o instanceof M?o:x(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}),acceptInquiry:s=>n(`/inquiries/${encodeURIComponent(s)}/accept`,{method:"POST"}),enquire:(s,a)=>n("/shop/enquire",{method:"POST",body:{productId:s,answers:a}})}};var Mt=/\/+$/,A="/api/v1/end-user",$=class extends Error{constructor(t){super(t),this.name="PortalConflict"}};function $t(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(Mt,""),r=()=>typeof e.token=="function"?e.token():e.token,n=async()=>({"content-type":"application/json",authorization:`Bearer ${await r()}`}),s=async(o,i)=>{try{let l=await fetch(`${t}${A}${o}`,{method:i.method,headers:await n(),...i.body===void 0?{}:{body:JSON.stringify(i.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=`${i.method} ${o} \u2192 ${String(l.status)}`;try{let c=JSON.parse(u);c.message&&(d=c.message)}catch{d=u?`${d}: ${u}`:d}throw x({error:d})}return await l.json()}catch(l){throw l instanceof $?l:x(l)}},a=o=>`/tables/${encodeURIComponent(o)}`;return{listTables:async()=>(await P(`${t}${A}/tables`,await n())).tables,listRows:async(o,i)=>await P(`${t}${A}${a(o)}/rows?limit=${String(i??100)}`,await n()),insertRow:async(o,i)=>{let{rowIds:l}=await s(`${a(o)}/rows`,{method:"POST",body:{rows:[i]}}),u=l[0];if(!u)throw x(new Error("The row was not created."));return u},patchRow:async(o,i,l)=>(await s(`${a(o)}/rows/${encodeURIComponent(i)}`,{method:"PATCH",body:l})).updated,deleteRow:async(o,i)=>(await s(`/${encodeURIComponent(o)}/${encodeURIComponent(i)}`,{method:"DELETE"})).deleted,listFiles:async()=>(await P(`${t}${A}/tables/files/rows?limit=200`,await n())).rows.map(i=>({id:i.rowId,filename:String(i.data.filename??""),source:String(i.data.source??"client"),campaign:String(i.data.campaign??""),size:typeof i.data.size=="number"?i.data.size:0,createdAt:i.createdAt})),uploadFile:async(o,i)=>{let l=new Uint8Array(await o.arrayBuffer());return await s("/files",{method:"POST",body:{filename:o.name,mime:o.type||"application/octet-stream",data:$t(l),...i===void 0?{}:{message:i}}})},fileLink:async o=>await P(`${t}${A}/files/${encodeURIComponent(o)}/url`,await n()),deleteFile:async o=>(await s(`/files/${encodeURIComponent(o)}`,{method:"DELETE"})).deleted,listDocuments:async()=>(await P(`${t}${A}/documents`,await n())).documents,readDocument:async o=>(await P(`${t}${A}/documents/${encodeURIComponent(o)}`,await n())).document,saveDocument:async(o,i)=>await s(`/documents/${encodeURIComponent(o)}`,{method:"PATCH",body:i})}};var Wt=/\/+$/,Et="/api/v1/end-user",je=e=>{let t=e.baseUrl.replace(Wt,""),r=async(n,s)=>{let a;try{a=await fetch(`${t}${Et}${n}`,s===void 0?{}:{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(s)})}catch(o){throw x(o)}if(a.status===429)throw x({error:"rate_limited",retryable:!0});if(!a.ok)throw x({error:`shop_request_failed_${String(a.status)}`});try{return await a.json()}catch(o){throw x(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}},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 Ge(e){return Ot.has(e.mode)?e.mode:"ask"}var _t={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 qe(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"?F(e.price,t):`${F(e.unitPrice,t)} per ${e.unitStep===1?e.unit:qe(e.unitStep,e.unit)}`}function Be(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 ${F(Math.min(...n),t)}`:"Priced on enquiry"}function ze(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 Je(e,t){return e.kind==="flat"?e.price:e.kind==="per_unit"?e.unitPrice*Math.ceil(t/Math.max(e.unitStep,1)):null}function Ke(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 Xe(e,t){let r=e.variants?.find(n=>n.name===t);return r&&r.includes.length>0?r.includes:e.includes}function Qe(e,t){let r=[];for(let n of e){let s=t(n).trim();s&&!r.includes(s)&&r.push(s)}return r}function Ye(e,t,r,n){let s=t?`${e.name} \u2014 ${t}`:e.name,a=r.kind==="per_unit"?`, ${qe(n,r.unit)}`:"";return`I'd like to buy ${s}${a}. How do I go ahead?`}function Ze(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 H=require("react"),et=e=>{let[t,r]=(0,H.useState)(null),[n,s]=(0,H.useState)(!0),[a,o]=(0,H.useState)(null),i=(0,H.useCallback)(async()=>{try{r(await e.wallet()),o(null)}catch{o("Couldn't read your balance just now.")}finally{s(!1)}},[e]),l=(0,H.useCallback)(()=>{i().catch(()=>{})},[i]);return(0,H.useEffect)(()=>(l(),window.addEventListener("focus",l),()=>{window.removeEventListener("focus",l)}),[l]),{wallet:t,loading:n,failure:a,refresh:l}};var D=require("react"),Ft=e=>e&&typeof e=="object"&&typeof e.error=="string"?e.error:e instanceof Error?e.message:"shop_unavailable",tt=e=>{let[t,r]=(0,D.useState)([]),[n,s]=(0,D.useState)(!1),[a,o]=(0,D.useState)(!0),[i,l]=(0,D.useState)(null),[u,d]=(0,D.useState)(0);(0,D.useEffect)(()=>{let m=!0;return o(!0),e.listProducts().then(p=>{m&&(r(p.products),s(p.truncated),l(null))}).catch(p=>{m&&l(Ft(p))}).finally(()=>{m&&o(!1)}),()=>{m=!1}},[e,u]);let c=(0,D.useCallback)(()=>d(m=>m+1),[]);return{products:t,truncated:n,loading:a,error:i,reload:c}};var k=require("react"),rt="greeting";function Re(e,t){if(e.some(a=>a.id===t.id))return e;let r=e.filter(a=>a.id!==rt),n=a=>a.author==="client"==(t.author==="client");return[...r.filter(a=>!(a.pending&&n(a)&&a.text===t.text)),t]}var nt=(e,t)=>{let[r,n]=(0,k.useState)([]),[s,a]=(0,k.useState)(""),[o,i]=(0,k.useState)(!1),[l,u]=(0,k.useState)(null),d=(0,k.useRef)(0),c=t?.pollMs??2e3;(0,k.useEffect)(()=>{let p=!0;return e.getInfo().then(y=>{p&&y.greeting&&n(w=>w.length===0?[{id:rt,cursor:"",author:"agent",text:y.greeting}]:w)}).catch(()=>{}),()=>{p=!1}},[e]),(0,k.useEffect)(()=>e.subscribe?.({onMessage:p=>n(y=>Re(y,p)),onError:p=>u(p.error),onHealthy:()=>u(null)},{intervalMs:c}),[e,c]);let m=(0,k.useCallback)(()=>{let p=s.trim();if(!p||o)return;a(""),u(null),i(!0),d.current+=1;let y=`pending-${d.current}`,w={id:y,cursor:"",author:"client",text:p,pending:!0};n(f=>[...f,w]),e.sendMessage(p).then(f=>{i(!1),f.reply.trim()&&n(g=>g.some(I=>!I.pending&&I.author!=="client"&&I.text===f.reply)?g:(d.current+=1,[...g,{id:`pending-agent-${d.current}`,cursor:"",author:"agent",text:f.reply,pending:!0}]))}).catch(f=>{u(f instanceof Error?f.message:"send_failed"),i(!1),n(R=>R.filter(g=>g.id!==y)),a(R=>R||p)})},[s,o,e]);return{messages:r,input:s,setInput:a,send:m,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,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});
|
package/dist/index.d.cts
CHANGED
|
@@ -609,174 +609,6 @@ declare const thinkingDeltaOf: (event: unknown) => string | null;
|
|
|
609
609
|
/** Extract a tool-execution start/end from a raw pi turn event, or null. */
|
|
610
610
|
declare const toolEventOf: (event: unknown) => HolaToolEvent | null;
|
|
611
611
|
|
|
612
|
-
type PortalShopConfig = {
|
|
613
|
-
/** API origin, e.g. "https://api.holaos.ai" — or empty for a portal whose own worker answers
|
|
614
|
-
* `/api/v1/end-user/…` same-origin, which is how the iMerch template is wired. */
|
|
615
|
-
baseUrl: string;
|
|
616
|
-
/**
|
|
617
|
-
* The tenant's publishable key, which is the whole of the authentication here.
|
|
618
|
-
*
|
|
619
|
-
* A plain string rather than the getter `ApiTransportConfig.token` takes: an end-user token
|
|
620
|
-
* refreshes and a publishable key does not — it is baked into the page source a visitor can read,
|
|
621
|
-
* which is what makes it publishable. There is deliberately no token field on this config at all,
|
|
622
|
-
* so nothing in a storefront can come to depend on being signed in to browse.
|
|
623
|
-
*/
|
|
624
|
-
publishableKey: string;
|
|
625
|
-
};
|
|
626
|
-
/** How a product is taken: `buy` charges for it, `ask` opens the conversation the customer already
|
|
627
|
-
* has with the company, `apply` posts the form `apply()` sends. */
|
|
628
|
-
type ShopMode = "buy" | "ask" | "apply";
|
|
629
|
-
/**
|
|
630
|
-
* What a product costs — exactly one of four shapes, never two.
|
|
631
|
-
*
|
|
632
|
-
* The number is in whatever unit the OPERATOR prices in: credits for an org that sells them, money
|
|
633
|
-
* for one that does not — and the wire says which, on `ShopProduct.currency` beside this. It used
|
|
634
|
-
* to say otherwise, that the figure travelled bare and the unit "belongs to the template that knows
|
|
635
|
-
* the tenant", which was how this contract was written before `pricing_unit` existed and was false
|
|
636
|
-
* the day the server started sending the field. A template built on that sentence prints a
|
|
637
|
-
* hardcoded `$` in front of a credit price — wrong by the whole book rate. Nothing here should ever
|
|
638
|
-
* print a `$` it did not read off `currency`.
|
|
639
|
-
*
|
|
640
|
-
* `quoted` is not a price. It is the honest answer for everything in a real catalogue that reads
|
|
641
|
-
* `5k – 10k`, `20k+` or 待定 — a statement that a human has to quote this. Render it as words, and
|
|
642
|
-
* never behind a Buy button that cannot compute a total.
|
|
643
|
-
*/
|
|
644
|
-
type ShopPricing = {
|
|
645
|
-
kind: "flat";
|
|
646
|
-
price: number;
|
|
647
|
-
} | {
|
|
648
|
-
kind: "per_unit";
|
|
649
|
-
unit: string;
|
|
650
|
-
unitPrice: number;
|
|
651
|
-
unitStep: number;
|
|
652
|
-
} | {
|
|
653
|
-
kind: "variants";
|
|
654
|
-
variants: {
|
|
655
|
-
name: string;
|
|
656
|
-
price: number | null;
|
|
657
|
-
}[];
|
|
658
|
-
} | {
|
|
659
|
-
kind: "quoted";
|
|
660
|
-
};
|
|
661
|
-
/** One part of a bundle, as the shelf is allowed to describe it: what it is called, what it covers,
|
|
662
|
-
* how long it runs — and no price, for the reason at the top of this file. */
|
|
663
|
-
type ShopInclusion = {
|
|
664
|
-
name: string;
|
|
665
|
-
content?: string;
|
|
666
|
-
period?: string;
|
|
667
|
-
};
|
|
668
|
-
/** A named tier — 基础 / 标准 / 高阶 — and what it covers. Its PRICE is not here: it is in
|
|
669
|
-
* `pricing` (`kind: "variants"`), matched to this by name, so that there is one place the money
|
|
670
|
-
* comes from and no way for the two to disagree. */
|
|
671
|
-
/** One question an `ask` product asks before it can be quoted. Authored by the operator on the
|
|
672
|
-
* product row; the storefront draws it and sends back answers keyed to it. */
|
|
673
|
-
type ShopFormField = {
|
|
674
|
-
key: string;
|
|
675
|
-
label: string;
|
|
676
|
-
type: "text" | "textarea" | "number" | "date" | "select";
|
|
677
|
-
required?: boolean;
|
|
678
|
-
options?: string[];
|
|
679
|
-
help?: string;
|
|
680
|
-
};
|
|
681
|
-
type ShopVariant = {
|
|
682
|
-
name: string;
|
|
683
|
-
includes: ShopInclusion[];
|
|
684
|
-
};
|
|
685
|
-
/** One product as a visitor sees it. */
|
|
686
|
-
type ShopProduct = {
|
|
687
|
-
id: string;
|
|
688
|
-
name: string;
|
|
689
|
-
summary: string;
|
|
690
|
-
description: string;
|
|
691
|
-
/**
|
|
692
|
-
* One of `ShopMode` for anything authored in the console — but typed as the string it is on the
|
|
693
|
-
* wire, because the server sends the row's own value and a product from before the field existed
|
|
694
|
-
* answers `""`. A storefront that switched over the union would be handed a value the type swore
|
|
695
|
-
* could not occur, so match the three and keep a default arm.
|
|
696
|
-
*/
|
|
697
|
-
mode: string;
|
|
698
|
-
category: string;
|
|
699
|
-
platform: string;
|
|
700
|
-
cadence: string;
|
|
701
|
-
period: string;
|
|
702
|
-
/** Image URLs for the card and the product page; empty when the operator set none. */
|
|
703
|
-
media: string[];
|
|
704
|
-
pricing: ShopPricing;
|
|
705
|
-
/** What THIS product's numbers are in — an ISO code, or the literal "credits". It sits on the
|
|
706
|
-
* product rather than on the shelf because a shelf can be mixed: once an org sells credits, its
|
|
707
|
-
* buyable products are priced in them while a 20k engagement it merely quotes stays in money.
|
|
708
|
-
* Empty from a backend older than the field, which is a shelf that has not SAID — and is not the
|
|
709
|
-
* same as one that said dollars, so print the bare figure rather than guessing a symbol. */
|
|
710
|
-
currency: string;
|
|
711
|
-
/** Bounds on a per-unit purchase, when the product states them. Public because the quantity
|
|
712
|
-
* picker has to honour them — a customer who meets a limit they were never shown reads it as a
|
|
713
|
-
* broken shop. */
|
|
714
|
-
minQty?: number;
|
|
715
|
-
maxQty?: number;
|
|
716
|
-
includes: ShopInclusion[];
|
|
717
|
-
/** The enquiry form, on an `ask` product only. Never empty when present — a product that asks
|
|
718
|
-
* nothing still gets one box, because a Send button over nothing collects an enquiry that says
|
|
719
|
-
* only that somebody was interested. Absent on `buy` and `apply`, which are not asked. */
|
|
720
|
-
form?: ShopFormField[];
|
|
721
|
-
/** Present only where the tiers differ in scope; a product without them has one implicit tier,
|
|
722
|
-
* which is its own `pricing` and its own `includes`. */
|
|
723
|
-
variants?: ShopVariant[];
|
|
724
|
-
};
|
|
725
|
-
type ShopShelf = {
|
|
726
|
-
products: ShopProduct[];
|
|
727
|
-
/**
|
|
728
|
-
* The catalogue is bigger than what came back.
|
|
729
|
-
*
|
|
730
|
-
* Kept rather than dropped for the reason `listRows` returns a page: the server caps a shelf read,
|
|
731
|
-
* and a shop that quietly ends at the cap is a customer who cannot see half of it and nobody who
|
|
732
|
-
* can tell. The same argument the server makes when it bothers to send the flag.
|
|
733
|
-
*/
|
|
734
|
-
truncated: boolean;
|
|
735
|
-
};
|
|
736
|
-
/** An application against a product, or against nothing in particular — a general enquiry that
|
|
737
|
-
* names no product is a real thing to receive, so `productId` is optional. */
|
|
738
|
-
type ShopApplication = {
|
|
739
|
-
name: string;
|
|
740
|
-
/**
|
|
741
|
-
* Where the operator answers. Required, and checked by the server — but a malformed one is
|
|
742
|
-
* dropped SILENTLY (see `apply` below), so a form that wants to tell someone their address is
|
|
743
|
-
* wrong has to say so itself, before it sends.
|
|
744
|
-
*/
|
|
745
|
-
email: string;
|
|
746
|
-
phone?: string;
|
|
747
|
-
message?: string;
|
|
748
|
-
productId?: string;
|
|
749
|
-
};
|
|
750
|
-
/** The one answer every application gets. See `apply` for why it never varies. */
|
|
751
|
-
type ShopApplyResult = {
|
|
752
|
-
/**
|
|
753
|
-
* Always `true` — including for a submission that was dropped. It is a receipt that the request
|
|
754
|
-
* was accepted, never evidence that a row exists.
|
|
755
|
-
*/
|
|
756
|
-
ok: boolean;
|
|
757
|
-
/** The server's own thank-you line. Shown as sent rather than reworded, so the operator's copy is
|
|
758
|
-
* the copy the applicant reads. */
|
|
759
|
-
message: string;
|
|
760
|
-
};
|
|
761
|
-
type PortalShop = {
|
|
762
|
-
/** Everything on sale, in the operator's own order. Listed products only — a draft is something
|
|
763
|
-
* still being written and an archived one is off sale but kept because orders point at it. */
|
|
764
|
-
listProducts(): Promise<ShopShelf>;
|
|
765
|
-
/**
|
|
766
|
-
* Send an application. No account, no session — this is the one write on the platform a total
|
|
767
|
-
* stranger can make.
|
|
768
|
-
*
|
|
769
|
-
* It answers the SAME "thanks, we have your details" to an unknown key, a body that did not
|
|
770
|
-
* parse and a write that failed as it does to an application that landed, and that is deliberate:
|
|
771
|
-
* anything else would turn this into a way to ask which publishable keys reach a real company —
|
|
772
|
-
* and, once signups are invite-only, which addresses one already has. The cost is that a
|
|
773
|
-
* miswired form gets a cheerful reply and files nothing, so when applications are not arriving,
|
|
774
|
-
* the answer is in the operator's server logs and cannot be here.
|
|
775
|
-
*/
|
|
776
|
-
apply(application: ShopApplication): Promise<ShopApplyResult>;
|
|
777
|
-
};
|
|
778
|
-
declare const createPortalShop: (config: PortalShopConfig) => PortalShop;
|
|
779
|
-
|
|
780
612
|
/**
|
|
781
613
|
* A refusal this surface makes on purpose, carrying both halves of it.
|
|
782
614
|
*
|
|
@@ -816,6 +648,11 @@ type PendingTopup = {
|
|
|
816
648
|
* "we are waiting for you" and "we are waiting for us", which a customer should never have to
|
|
817
649
|
* guess at. */
|
|
818
650
|
paid: boolean;
|
|
651
|
+
/** Where this top-up stands, as one value rather than two booleans a reader has to combine:
|
|
652
|
+
* `waiting` on the customer, `paid` on the operator, `failed` on nobody — the payment was
|
|
653
|
+
* declined and this is terminal. Absent from a backend older than the field, where the two
|
|
654
|
+
* live states are all there were; treat a missing value as `paid ? "paid" : "waiting"`. */
|
|
655
|
+
state?: "waiting" | "paid" | "failed";
|
|
819
656
|
createdAt: string;
|
|
820
657
|
/** The server's own sentence for the state above. Rendered rather than re-derived: a second
|
|
821
658
|
* account of it written portal-side is one that can disagree with the first. */
|
|
@@ -947,26 +784,204 @@ type PortalCredits = {
|
|
|
947
784
|
* somebody, so it takes the customer's bearer. (The public shelf's `apply` is the stranger's
|
|
948
785
|
* door, and it leaves an inquiry instead — there is no customer to write an order against.)
|
|
949
786
|
*/
|
|
787
|
+
/** Raise a 询单 on an `ask` product. Returns the inquiry it created, so the caller can open it.
|
|
788
|
+
*
|
|
789
|
+
* It used to return `orderId`: an enquiry wrote an ORDER in `ask` status, which was the wrong
|
|
790
|
+
* object — an order with no money, no services and no agreed price, and a dead row in the
|
|
791
|
+
* customer's order list for every quote that went nowhere. */
|
|
950
792
|
enquire(productId: string, answers: {
|
|
951
793
|
key: string;
|
|
952
794
|
value: string;
|
|
953
795
|
}[]): Promise<{
|
|
954
|
-
|
|
796
|
+
inquiryId: string;
|
|
955
797
|
name: string;
|
|
956
798
|
}>;
|
|
799
|
+
/** Accept the quote on a 询单. Moves it to `accepted` — the ORDER is the operator's to write,
|
|
800
|
+
* because what is finally agreed is rarely exactly what was quoted and a customer cannot conjure
|
|
801
|
+
* services and terms into existence. Idempotent: a double-tap on a slow connection is the
|
|
802
|
+
* ordinary way this happens. */
|
|
803
|
+
acceptInquiry(inquiryId: string): Promise<{
|
|
804
|
+
status: string;
|
|
805
|
+
changed: boolean;
|
|
806
|
+
}>;
|
|
957
807
|
};
|
|
958
808
|
declare const createPortalCredits: (config: ApiTransportConfig) => PortalCredits;
|
|
959
809
|
|
|
960
|
-
type
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
810
|
+
type PortalShopConfig = {
|
|
811
|
+
/** API origin, e.g. "https://api.holaos.ai" — or empty for a portal whose own worker answers
|
|
812
|
+
* `/api/v1/end-user/…` same-origin, which is how the iMerch template is wired. */
|
|
813
|
+
baseUrl: string;
|
|
814
|
+
/**
|
|
815
|
+
* The tenant's publishable key, which is the whole of the authentication here.
|
|
816
|
+
*
|
|
817
|
+
* A plain string rather than the getter `ApiTransportConfig.token` takes: an end-user token
|
|
818
|
+
* refreshes and a publishable key does not — it is baked into the page source a visitor can read,
|
|
819
|
+
* which is what makes it publishable. There is deliberately no token field on this config at all,
|
|
820
|
+
* so nothing in a storefront can come to depend on being signed in to browse.
|
|
821
|
+
*/
|
|
822
|
+
publishableKey: string;
|
|
968
823
|
};
|
|
969
|
-
|
|
824
|
+
/** How a product is taken: `buy` charges for it, `ask` opens the conversation the customer already
|
|
825
|
+
* has with the company, `apply` posts the form `apply()` sends. */
|
|
826
|
+
type ShopMode = "buy" | "ask";
|
|
827
|
+
/**
|
|
828
|
+
* What a product costs — exactly one of four shapes, never two.
|
|
829
|
+
*
|
|
830
|
+
* The number is in whatever unit the OPERATOR prices in: credits for an org that sells them, money
|
|
831
|
+
* for one that does not — and the wire says which, on `ShopProduct.currency` beside this. It used
|
|
832
|
+
* to say otherwise, that the figure travelled bare and the unit "belongs to the template that knows
|
|
833
|
+
* the tenant", which was how this contract was written before `pricing_unit` existed and was false
|
|
834
|
+
* the day the server started sending the field. A template built on that sentence prints a
|
|
835
|
+
* hardcoded `$` in front of a credit price — wrong by the whole book rate. Nothing here should ever
|
|
836
|
+
* print a `$` it did not read off `currency`.
|
|
837
|
+
*
|
|
838
|
+
* `quoted` is not a price. It is the honest answer for everything in a real catalogue that reads
|
|
839
|
+
* `5k – 10k`, `20k+` or 待定 — a statement that a human has to quote this. Render it as words, and
|
|
840
|
+
* never behind a Buy button that cannot compute a total.
|
|
841
|
+
*/
|
|
842
|
+
type ShopPricing = {
|
|
843
|
+
kind: "flat";
|
|
844
|
+
price: number;
|
|
845
|
+
} | {
|
|
846
|
+
kind: "per_unit";
|
|
847
|
+
unit: string;
|
|
848
|
+
unitPrice: number;
|
|
849
|
+
unitStep: number;
|
|
850
|
+
} | {
|
|
851
|
+
kind: "variants";
|
|
852
|
+
variants: {
|
|
853
|
+
name: string;
|
|
854
|
+
price: number | null;
|
|
855
|
+
}[];
|
|
856
|
+
} | {
|
|
857
|
+
kind: "quoted";
|
|
858
|
+
};
|
|
859
|
+
/** One part of a bundle, as the shelf is allowed to describe it: what it is called, what it covers,
|
|
860
|
+
* how long it runs — and no price, for the reason at the top of this file. */
|
|
861
|
+
type ShopInclusion = {
|
|
862
|
+
name: string;
|
|
863
|
+
content?: string;
|
|
864
|
+
period?: string;
|
|
865
|
+
};
|
|
866
|
+
/** A named tier — 基础 / 标准 / 高阶 — and what it covers. Its PRICE is not here: it is in
|
|
867
|
+
* `pricing` (`kind: "variants"`), matched to this by name, so that there is one place the money
|
|
868
|
+
* comes from and no way for the two to disagree. */
|
|
869
|
+
/** One question an `ask` product asks before it can be quoted. Authored by the operator on the
|
|
870
|
+
* product row; the storefront draws it and sends back answers keyed to it. */
|
|
871
|
+
type ShopFormField = {
|
|
872
|
+
key: string;
|
|
873
|
+
label: string;
|
|
874
|
+
type: "text" | "textarea" | "number" | "date" | "select";
|
|
875
|
+
required?: boolean;
|
|
876
|
+
options?: string[];
|
|
877
|
+
help?: string;
|
|
878
|
+
};
|
|
879
|
+
type ShopVariant = {
|
|
880
|
+
name: string;
|
|
881
|
+
includes: ShopInclusion[];
|
|
882
|
+
};
|
|
883
|
+
/** One product as a visitor sees it. */
|
|
884
|
+
type ShopProduct = {
|
|
885
|
+
id: string;
|
|
886
|
+
name: string;
|
|
887
|
+
summary: string;
|
|
888
|
+
description: string;
|
|
889
|
+
/**
|
|
890
|
+
* One of `ShopMode` for anything authored in the console — but typed as the string it is on the
|
|
891
|
+
* wire, because the server sends the row's own value and a product from before the field existed
|
|
892
|
+
* answers `""`. A storefront that switched over the union would be handed a value the type swore
|
|
893
|
+
* could not occur, so match the three and keep a default arm.
|
|
894
|
+
*/
|
|
895
|
+
mode: string;
|
|
896
|
+
category: string;
|
|
897
|
+
platform: string;
|
|
898
|
+
cadence: string;
|
|
899
|
+
period: string;
|
|
900
|
+
/** Image URLs for the card and the product page; empty when the operator set none. */
|
|
901
|
+
media: string[];
|
|
902
|
+
pricing: ShopPricing;
|
|
903
|
+
/** What THIS product's numbers are in — an ISO code, or the literal "credits". It sits on the
|
|
904
|
+
* product rather than on the shelf because a shelf can be mixed: once an org sells credits, its
|
|
905
|
+
* buyable products are priced in them while a 20k engagement it merely quotes stays in money.
|
|
906
|
+
* Empty from a backend older than the field, which is a shelf that has not SAID — and is not the
|
|
907
|
+
* same as one that said dollars, so print the bare figure rather than guessing a symbol. */
|
|
908
|
+
currency: string;
|
|
909
|
+
/** Bounds on a per-unit purchase, when the product states them. Public because the quantity
|
|
910
|
+
* picker has to honour them — a customer who meets a limit they were never shown reads it as a
|
|
911
|
+
* broken shop. */
|
|
912
|
+
minQty?: number;
|
|
913
|
+
maxQty?: number;
|
|
914
|
+
includes: ShopInclusion[];
|
|
915
|
+
/** The enquiry form, on an `ask` product only. Never empty when present — a product that asks
|
|
916
|
+
* nothing still gets one box, because a Send button over nothing collects an enquiry that says
|
|
917
|
+
* only that somebody was interested. Absent on `buy` and `apply`, which are not asked. */
|
|
918
|
+
form?: ShopFormField[];
|
|
919
|
+
/** Present only where the tiers differ in scope; a product without them has one implicit tier,
|
|
920
|
+
* which is its own `pricing` and its own `includes`. */
|
|
921
|
+
variants?: ShopVariant[];
|
|
922
|
+
};
|
|
923
|
+
type ShopShelf = {
|
|
924
|
+
products: ShopProduct[];
|
|
925
|
+
/**
|
|
926
|
+
* The catalogue is bigger than what came back.
|
|
927
|
+
*
|
|
928
|
+
* Kept rather than dropped for the reason `listRows` returns a page: the server caps a shelf read,
|
|
929
|
+
* and a shop that quietly ends at the cap is a customer who cannot see half of it and nobody who
|
|
930
|
+
* can tell. The same argument the server makes when it bothers to send the flag.
|
|
931
|
+
*/
|
|
932
|
+
truncated: boolean;
|
|
933
|
+
};
|
|
934
|
+
/** An application against a product, or against nothing in particular — a general enquiry that
|
|
935
|
+
* names no product is a real thing to receive, so `productId` is optional. */
|
|
936
|
+
type ShopApplication = {
|
|
937
|
+
name: string;
|
|
938
|
+
/**
|
|
939
|
+
* Where the operator answers. Required, and checked by the server — but a malformed one is
|
|
940
|
+
* dropped SILENTLY (see `apply` below), so a form that wants to tell someone their address is
|
|
941
|
+
* wrong has to say so itself, before it sends.
|
|
942
|
+
*/
|
|
943
|
+
email: string;
|
|
944
|
+
phone?: string;
|
|
945
|
+
message?: string;
|
|
946
|
+
productId?: string;
|
|
947
|
+
};
|
|
948
|
+
/** The one answer every application gets. See `apply` for why it never varies. */
|
|
949
|
+
type ShopApplyResult = {
|
|
950
|
+
/**
|
|
951
|
+
* Always `true` — including for a submission that was dropped. It is a receipt that the request
|
|
952
|
+
* was accepted, never evidence that a row exists.
|
|
953
|
+
*/
|
|
954
|
+
ok: boolean;
|
|
955
|
+
/** The server's own thank-you line. Shown as sent rather than reworded, so the operator's copy is
|
|
956
|
+
* the copy the applicant reads. */
|
|
957
|
+
message: string;
|
|
958
|
+
};
|
|
959
|
+
type PortalShop = {
|
|
960
|
+
/** Everything on sale, in the operator's own order. Listed products only — a draft is something
|
|
961
|
+
* still being written and an archived one is off sale but kept because orders point at it. */
|
|
962
|
+
listProducts(): Promise<ShopShelf>;
|
|
963
|
+
/**
|
|
964
|
+
* Send an application. No account, no session — this is the one write on the platform a total
|
|
965
|
+
* stranger can make.
|
|
966
|
+
*
|
|
967
|
+
* It answers the SAME "thanks, we have your details" to an unknown key, a body that did not
|
|
968
|
+
* parse and a write that failed as it does to an application that landed, and that is deliberate:
|
|
969
|
+
* anything else would turn this into a way to ask which publishable keys reach a real company —
|
|
970
|
+
* and, once signups are invite-only, which addresses one already has. The cost is that a
|
|
971
|
+
* miswired form gets a cheerful reply and files nothing, so when applications are not arriving,
|
|
972
|
+
* the answer is in the operator's server logs and cannot be here.
|
|
973
|
+
*/
|
|
974
|
+
apply(application: ShopApplication): Promise<ShopApplyResult>;
|
|
975
|
+
};
|
|
976
|
+
declare const createPortalShop: (config: PortalShopConfig) => PortalShop;
|
|
977
|
+
|
|
978
|
+
/** Provides a `HolaClient` (from `createHolaClient`) to `useChat` / `<Chat/>`.
|
|
979
|
+
* Create the client once (e.g. `useMemo`) so its session persists across renders. */
|
|
980
|
+
declare const HolaProvider: ({ client, children, }: {
|
|
981
|
+
client: HolaClient;
|
|
982
|
+
children: ReactNode;
|
|
983
|
+
}) => react.JSX.Element;
|
|
984
|
+
declare const useHolaClient: () => HolaClient;
|
|
970
985
|
|
|
971
986
|
/**
|
|
972
987
|
* How this product is taken.
|
|
@@ -1053,14 +1068,6 @@ declare function facetValues(products: ShopProduct[], of: (product: ShopProduct)
|
|
|
1053
1068
|
declare function buyRequestText(product: ShopProduct, variant: string | null, price: ChosenPrice, qty: number): string;
|
|
1054
1069
|
declare function shelfProblem(error: unknown): string | null;
|
|
1055
1070
|
|
|
1056
|
-
/** Provides a `HolaClient` (from `createHolaClient`) to `useChat` / `<Chat/>`.
|
|
1057
|
-
* Create the client once (e.g. `useMemo`) so its session persists across renders. */
|
|
1058
|
-
declare const HolaProvider: ({ client, children, }: {
|
|
1059
|
-
client: HolaClient;
|
|
1060
|
-
children: ReactNode;
|
|
1061
|
-
}) => react.JSX.Element;
|
|
1062
|
-
declare const useHolaClient: () => HolaClient;
|
|
1063
|
-
|
|
1064
1071
|
type ChatMessage = {
|
|
1065
1072
|
id: number;
|
|
1066
1073
|
role: "user" | "assistant";
|
|
@@ -1079,6 +1086,17 @@ type UseChat = {
|
|
|
1079
1086
|
/** Chat state for one employee client: greeting, message list, streaming send. */
|
|
1080
1087
|
declare const useChat: (client: HolaClient) => UseChat;
|
|
1081
1088
|
|
|
1089
|
+
type UseCredits = {
|
|
1090
|
+
wallet: CreditWallet | null;
|
|
1091
|
+
/** The FIRST read only. A refresh keeps the numbers on screen and swaps them when the answer
|
|
1092
|
+
* lands: blanking a balance somebody is reading, to show a spinner, to show the same balance
|
|
1093
|
+
* again, is a flicker that reads as a fault. */
|
|
1094
|
+
loading: boolean;
|
|
1095
|
+
failure: string | null;
|
|
1096
|
+
refresh: () => void;
|
|
1097
|
+
};
|
|
1098
|
+
declare const useCredits: (credits: PortalCredits) => UseCredits;
|
|
1099
|
+
|
|
1082
1100
|
type UseShop = {
|
|
1083
1101
|
products: ShopProduct[];
|
|
1084
1102
|
/** In flight — the first read, and every `reload`. The products from the previous read stay put
|
package/dist/index.d.ts
CHANGED
|
@@ -609,174 +609,6 @@ declare const thinkingDeltaOf: (event: unknown) => string | null;
|
|
|
609
609
|
/** Extract a tool-execution start/end from a raw pi turn event, or null. */
|
|
610
610
|
declare const toolEventOf: (event: unknown) => HolaToolEvent | null;
|
|
611
611
|
|
|
612
|
-
type PortalShopConfig = {
|
|
613
|
-
/** API origin, e.g. "https://api.holaos.ai" — or empty for a portal whose own worker answers
|
|
614
|
-
* `/api/v1/end-user/…` same-origin, which is how the iMerch template is wired. */
|
|
615
|
-
baseUrl: string;
|
|
616
|
-
/**
|
|
617
|
-
* The tenant's publishable key, which is the whole of the authentication here.
|
|
618
|
-
*
|
|
619
|
-
* A plain string rather than the getter `ApiTransportConfig.token` takes: an end-user token
|
|
620
|
-
* refreshes and a publishable key does not — it is baked into the page source a visitor can read,
|
|
621
|
-
* which is what makes it publishable. There is deliberately no token field on this config at all,
|
|
622
|
-
* so nothing in a storefront can come to depend on being signed in to browse.
|
|
623
|
-
*/
|
|
624
|
-
publishableKey: string;
|
|
625
|
-
};
|
|
626
|
-
/** How a product is taken: `buy` charges for it, `ask` opens the conversation the customer already
|
|
627
|
-
* has with the company, `apply` posts the form `apply()` sends. */
|
|
628
|
-
type ShopMode = "buy" | "ask" | "apply";
|
|
629
|
-
/**
|
|
630
|
-
* What a product costs — exactly one of four shapes, never two.
|
|
631
|
-
*
|
|
632
|
-
* The number is in whatever unit the OPERATOR prices in: credits for an org that sells them, money
|
|
633
|
-
* for one that does not — and the wire says which, on `ShopProduct.currency` beside this. It used
|
|
634
|
-
* to say otherwise, that the figure travelled bare and the unit "belongs to the template that knows
|
|
635
|
-
* the tenant", which was how this contract was written before `pricing_unit` existed and was false
|
|
636
|
-
* the day the server started sending the field. A template built on that sentence prints a
|
|
637
|
-
* hardcoded `$` in front of a credit price — wrong by the whole book rate. Nothing here should ever
|
|
638
|
-
* print a `$` it did not read off `currency`.
|
|
639
|
-
*
|
|
640
|
-
* `quoted` is not a price. It is the honest answer for everything in a real catalogue that reads
|
|
641
|
-
* `5k – 10k`, `20k+` or 待定 — a statement that a human has to quote this. Render it as words, and
|
|
642
|
-
* never behind a Buy button that cannot compute a total.
|
|
643
|
-
*/
|
|
644
|
-
type ShopPricing = {
|
|
645
|
-
kind: "flat";
|
|
646
|
-
price: number;
|
|
647
|
-
} | {
|
|
648
|
-
kind: "per_unit";
|
|
649
|
-
unit: string;
|
|
650
|
-
unitPrice: number;
|
|
651
|
-
unitStep: number;
|
|
652
|
-
} | {
|
|
653
|
-
kind: "variants";
|
|
654
|
-
variants: {
|
|
655
|
-
name: string;
|
|
656
|
-
price: number | null;
|
|
657
|
-
}[];
|
|
658
|
-
} | {
|
|
659
|
-
kind: "quoted";
|
|
660
|
-
};
|
|
661
|
-
/** One part of a bundle, as the shelf is allowed to describe it: what it is called, what it covers,
|
|
662
|
-
* how long it runs — and no price, for the reason at the top of this file. */
|
|
663
|
-
type ShopInclusion = {
|
|
664
|
-
name: string;
|
|
665
|
-
content?: string;
|
|
666
|
-
period?: string;
|
|
667
|
-
};
|
|
668
|
-
/** A named tier — 基础 / 标准 / 高阶 — and what it covers. Its PRICE is not here: it is in
|
|
669
|
-
* `pricing` (`kind: "variants"`), matched to this by name, so that there is one place the money
|
|
670
|
-
* comes from and no way for the two to disagree. */
|
|
671
|
-
/** One question an `ask` product asks before it can be quoted. Authored by the operator on the
|
|
672
|
-
* product row; the storefront draws it and sends back answers keyed to it. */
|
|
673
|
-
type ShopFormField = {
|
|
674
|
-
key: string;
|
|
675
|
-
label: string;
|
|
676
|
-
type: "text" | "textarea" | "number" | "date" | "select";
|
|
677
|
-
required?: boolean;
|
|
678
|
-
options?: string[];
|
|
679
|
-
help?: string;
|
|
680
|
-
};
|
|
681
|
-
type ShopVariant = {
|
|
682
|
-
name: string;
|
|
683
|
-
includes: ShopInclusion[];
|
|
684
|
-
};
|
|
685
|
-
/** One product as a visitor sees it. */
|
|
686
|
-
type ShopProduct = {
|
|
687
|
-
id: string;
|
|
688
|
-
name: string;
|
|
689
|
-
summary: string;
|
|
690
|
-
description: string;
|
|
691
|
-
/**
|
|
692
|
-
* One of `ShopMode` for anything authored in the console — but typed as the string it is on the
|
|
693
|
-
* wire, because the server sends the row's own value and a product from before the field existed
|
|
694
|
-
* answers `""`. A storefront that switched over the union would be handed a value the type swore
|
|
695
|
-
* could not occur, so match the three and keep a default arm.
|
|
696
|
-
*/
|
|
697
|
-
mode: string;
|
|
698
|
-
category: string;
|
|
699
|
-
platform: string;
|
|
700
|
-
cadence: string;
|
|
701
|
-
period: string;
|
|
702
|
-
/** Image URLs for the card and the product page; empty when the operator set none. */
|
|
703
|
-
media: string[];
|
|
704
|
-
pricing: ShopPricing;
|
|
705
|
-
/** What THIS product's numbers are in — an ISO code, or the literal "credits". It sits on the
|
|
706
|
-
* product rather than on the shelf because a shelf can be mixed: once an org sells credits, its
|
|
707
|
-
* buyable products are priced in them while a 20k engagement it merely quotes stays in money.
|
|
708
|
-
* Empty from a backend older than the field, which is a shelf that has not SAID — and is not the
|
|
709
|
-
* same as one that said dollars, so print the bare figure rather than guessing a symbol. */
|
|
710
|
-
currency: string;
|
|
711
|
-
/** Bounds on a per-unit purchase, when the product states them. Public because the quantity
|
|
712
|
-
* picker has to honour them — a customer who meets a limit they were never shown reads it as a
|
|
713
|
-
* broken shop. */
|
|
714
|
-
minQty?: number;
|
|
715
|
-
maxQty?: number;
|
|
716
|
-
includes: ShopInclusion[];
|
|
717
|
-
/** The enquiry form, on an `ask` product only. Never empty when present — a product that asks
|
|
718
|
-
* nothing still gets one box, because a Send button over nothing collects an enquiry that says
|
|
719
|
-
* only that somebody was interested. Absent on `buy` and `apply`, which are not asked. */
|
|
720
|
-
form?: ShopFormField[];
|
|
721
|
-
/** Present only where the tiers differ in scope; a product without them has one implicit tier,
|
|
722
|
-
* which is its own `pricing` and its own `includes`. */
|
|
723
|
-
variants?: ShopVariant[];
|
|
724
|
-
};
|
|
725
|
-
type ShopShelf = {
|
|
726
|
-
products: ShopProduct[];
|
|
727
|
-
/**
|
|
728
|
-
* The catalogue is bigger than what came back.
|
|
729
|
-
*
|
|
730
|
-
* Kept rather than dropped for the reason `listRows` returns a page: the server caps a shelf read,
|
|
731
|
-
* and a shop that quietly ends at the cap is a customer who cannot see half of it and nobody who
|
|
732
|
-
* can tell. The same argument the server makes when it bothers to send the flag.
|
|
733
|
-
*/
|
|
734
|
-
truncated: boolean;
|
|
735
|
-
};
|
|
736
|
-
/** An application against a product, or against nothing in particular — a general enquiry that
|
|
737
|
-
* names no product is a real thing to receive, so `productId` is optional. */
|
|
738
|
-
type ShopApplication = {
|
|
739
|
-
name: string;
|
|
740
|
-
/**
|
|
741
|
-
* Where the operator answers. Required, and checked by the server — but a malformed one is
|
|
742
|
-
* dropped SILENTLY (see `apply` below), so a form that wants to tell someone their address is
|
|
743
|
-
* wrong has to say so itself, before it sends.
|
|
744
|
-
*/
|
|
745
|
-
email: string;
|
|
746
|
-
phone?: string;
|
|
747
|
-
message?: string;
|
|
748
|
-
productId?: string;
|
|
749
|
-
};
|
|
750
|
-
/** The one answer every application gets. See `apply` for why it never varies. */
|
|
751
|
-
type ShopApplyResult = {
|
|
752
|
-
/**
|
|
753
|
-
* Always `true` — including for a submission that was dropped. It is a receipt that the request
|
|
754
|
-
* was accepted, never evidence that a row exists.
|
|
755
|
-
*/
|
|
756
|
-
ok: boolean;
|
|
757
|
-
/** The server's own thank-you line. Shown as sent rather than reworded, so the operator's copy is
|
|
758
|
-
* the copy the applicant reads. */
|
|
759
|
-
message: string;
|
|
760
|
-
};
|
|
761
|
-
type PortalShop = {
|
|
762
|
-
/** Everything on sale, in the operator's own order. Listed products only — a draft is something
|
|
763
|
-
* still being written and an archived one is off sale but kept because orders point at it. */
|
|
764
|
-
listProducts(): Promise<ShopShelf>;
|
|
765
|
-
/**
|
|
766
|
-
* Send an application. No account, no session — this is the one write on the platform a total
|
|
767
|
-
* stranger can make.
|
|
768
|
-
*
|
|
769
|
-
* It answers the SAME "thanks, we have your details" to an unknown key, a body that did not
|
|
770
|
-
* parse and a write that failed as it does to an application that landed, and that is deliberate:
|
|
771
|
-
* anything else would turn this into a way to ask which publishable keys reach a real company —
|
|
772
|
-
* and, once signups are invite-only, which addresses one already has. The cost is that a
|
|
773
|
-
* miswired form gets a cheerful reply and files nothing, so when applications are not arriving,
|
|
774
|
-
* the answer is in the operator's server logs and cannot be here.
|
|
775
|
-
*/
|
|
776
|
-
apply(application: ShopApplication): Promise<ShopApplyResult>;
|
|
777
|
-
};
|
|
778
|
-
declare const createPortalShop: (config: PortalShopConfig) => PortalShop;
|
|
779
|
-
|
|
780
612
|
/**
|
|
781
613
|
* A refusal this surface makes on purpose, carrying both halves of it.
|
|
782
614
|
*
|
|
@@ -816,6 +648,11 @@ type PendingTopup = {
|
|
|
816
648
|
* "we are waiting for you" and "we are waiting for us", which a customer should never have to
|
|
817
649
|
* guess at. */
|
|
818
650
|
paid: boolean;
|
|
651
|
+
/** Where this top-up stands, as one value rather than two booleans a reader has to combine:
|
|
652
|
+
* `waiting` on the customer, `paid` on the operator, `failed` on nobody — the payment was
|
|
653
|
+
* declined and this is terminal. Absent from a backend older than the field, where the two
|
|
654
|
+
* live states are all there were; treat a missing value as `paid ? "paid" : "waiting"`. */
|
|
655
|
+
state?: "waiting" | "paid" | "failed";
|
|
819
656
|
createdAt: string;
|
|
820
657
|
/** The server's own sentence for the state above. Rendered rather than re-derived: a second
|
|
821
658
|
* account of it written portal-side is one that can disagree with the first. */
|
|
@@ -947,26 +784,204 @@ type PortalCredits = {
|
|
|
947
784
|
* somebody, so it takes the customer's bearer. (The public shelf's `apply` is the stranger's
|
|
948
785
|
* door, and it leaves an inquiry instead — there is no customer to write an order against.)
|
|
949
786
|
*/
|
|
787
|
+
/** Raise a 询单 on an `ask` product. Returns the inquiry it created, so the caller can open it.
|
|
788
|
+
*
|
|
789
|
+
* It used to return `orderId`: an enquiry wrote an ORDER in `ask` status, which was the wrong
|
|
790
|
+
* object — an order with no money, no services and no agreed price, and a dead row in the
|
|
791
|
+
* customer's order list for every quote that went nowhere. */
|
|
950
792
|
enquire(productId: string, answers: {
|
|
951
793
|
key: string;
|
|
952
794
|
value: string;
|
|
953
795
|
}[]): Promise<{
|
|
954
|
-
|
|
796
|
+
inquiryId: string;
|
|
955
797
|
name: string;
|
|
956
798
|
}>;
|
|
799
|
+
/** Accept the quote on a 询单. Moves it to `accepted` — the ORDER is the operator's to write,
|
|
800
|
+
* because what is finally agreed is rarely exactly what was quoted and a customer cannot conjure
|
|
801
|
+
* services and terms into existence. Idempotent: a double-tap on a slow connection is the
|
|
802
|
+
* ordinary way this happens. */
|
|
803
|
+
acceptInquiry(inquiryId: string): Promise<{
|
|
804
|
+
status: string;
|
|
805
|
+
changed: boolean;
|
|
806
|
+
}>;
|
|
957
807
|
};
|
|
958
808
|
declare const createPortalCredits: (config: ApiTransportConfig) => PortalCredits;
|
|
959
809
|
|
|
960
|
-
type
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
810
|
+
type PortalShopConfig = {
|
|
811
|
+
/** API origin, e.g. "https://api.holaos.ai" — or empty for a portal whose own worker answers
|
|
812
|
+
* `/api/v1/end-user/…` same-origin, which is how the iMerch template is wired. */
|
|
813
|
+
baseUrl: string;
|
|
814
|
+
/**
|
|
815
|
+
* The tenant's publishable key, which is the whole of the authentication here.
|
|
816
|
+
*
|
|
817
|
+
* A plain string rather than the getter `ApiTransportConfig.token` takes: an end-user token
|
|
818
|
+
* refreshes and a publishable key does not — it is baked into the page source a visitor can read,
|
|
819
|
+
* which is what makes it publishable. There is deliberately no token field on this config at all,
|
|
820
|
+
* so nothing in a storefront can come to depend on being signed in to browse.
|
|
821
|
+
*/
|
|
822
|
+
publishableKey: string;
|
|
968
823
|
};
|
|
969
|
-
|
|
824
|
+
/** How a product is taken: `buy` charges for it, `ask` opens the conversation the customer already
|
|
825
|
+
* has with the company, `apply` posts the form `apply()` sends. */
|
|
826
|
+
type ShopMode = "buy" | "ask";
|
|
827
|
+
/**
|
|
828
|
+
* What a product costs — exactly one of four shapes, never two.
|
|
829
|
+
*
|
|
830
|
+
* The number is in whatever unit the OPERATOR prices in: credits for an org that sells them, money
|
|
831
|
+
* for one that does not — and the wire says which, on `ShopProduct.currency` beside this. It used
|
|
832
|
+
* to say otherwise, that the figure travelled bare and the unit "belongs to the template that knows
|
|
833
|
+
* the tenant", which was how this contract was written before `pricing_unit` existed and was false
|
|
834
|
+
* the day the server started sending the field. A template built on that sentence prints a
|
|
835
|
+
* hardcoded `$` in front of a credit price — wrong by the whole book rate. Nothing here should ever
|
|
836
|
+
* print a `$` it did not read off `currency`.
|
|
837
|
+
*
|
|
838
|
+
* `quoted` is not a price. It is the honest answer for everything in a real catalogue that reads
|
|
839
|
+
* `5k – 10k`, `20k+` or 待定 — a statement that a human has to quote this. Render it as words, and
|
|
840
|
+
* never behind a Buy button that cannot compute a total.
|
|
841
|
+
*/
|
|
842
|
+
type ShopPricing = {
|
|
843
|
+
kind: "flat";
|
|
844
|
+
price: number;
|
|
845
|
+
} | {
|
|
846
|
+
kind: "per_unit";
|
|
847
|
+
unit: string;
|
|
848
|
+
unitPrice: number;
|
|
849
|
+
unitStep: number;
|
|
850
|
+
} | {
|
|
851
|
+
kind: "variants";
|
|
852
|
+
variants: {
|
|
853
|
+
name: string;
|
|
854
|
+
price: number | null;
|
|
855
|
+
}[];
|
|
856
|
+
} | {
|
|
857
|
+
kind: "quoted";
|
|
858
|
+
};
|
|
859
|
+
/** One part of a bundle, as the shelf is allowed to describe it: what it is called, what it covers,
|
|
860
|
+
* how long it runs — and no price, for the reason at the top of this file. */
|
|
861
|
+
type ShopInclusion = {
|
|
862
|
+
name: string;
|
|
863
|
+
content?: string;
|
|
864
|
+
period?: string;
|
|
865
|
+
};
|
|
866
|
+
/** A named tier — 基础 / 标准 / 高阶 — and what it covers. Its PRICE is not here: it is in
|
|
867
|
+
* `pricing` (`kind: "variants"`), matched to this by name, so that there is one place the money
|
|
868
|
+
* comes from and no way for the two to disagree. */
|
|
869
|
+
/** One question an `ask` product asks before it can be quoted. Authored by the operator on the
|
|
870
|
+
* product row; the storefront draws it and sends back answers keyed to it. */
|
|
871
|
+
type ShopFormField = {
|
|
872
|
+
key: string;
|
|
873
|
+
label: string;
|
|
874
|
+
type: "text" | "textarea" | "number" | "date" | "select";
|
|
875
|
+
required?: boolean;
|
|
876
|
+
options?: string[];
|
|
877
|
+
help?: string;
|
|
878
|
+
};
|
|
879
|
+
type ShopVariant = {
|
|
880
|
+
name: string;
|
|
881
|
+
includes: ShopInclusion[];
|
|
882
|
+
};
|
|
883
|
+
/** One product as a visitor sees it. */
|
|
884
|
+
type ShopProduct = {
|
|
885
|
+
id: string;
|
|
886
|
+
name: string;
|
|
887
|
+
summary: string;
|
|
888
|
+
description: string;
|
|
889
|
+
/**
|
|
890
|
+
* One of `ShopMode` for anything authored in the console — but typed as the string it is on the
|
|
891
|
+
* wire, because the server sends the row's own value and a product from before the field existed
|
|
892
|
+
* answers `""`. A storefront that switched over the union would be handed a value the type swore
|
|
893
|
+
* could not occur, so match the three and keep a default arm.
|
|
894
|
+
*/
|
|
895
|
+
mode: string;
|
|
896
|
+
category: string;
|
|
897
|
+
platform: string;
|
|
898
|
+
cadence: string;
|
|
899
|
+
period: string;
|
|
900
|
+
/** Image URLs for the card and the product page; empty when the operator set none. */
|
|
901
|
+
media: string[];
|
|
902
|
+
pricing: ShopPricing;
|
|
903
|
+
/** What THIS product's numbers are in — an ISO code, or the literal "credits". It sits on the
|
|
904
|
+
* product rather than on the shelf because a shelf can be mixed: once an org sells credits, its
|
|
905
|
+
* buyable products are priced in them while a 20k engagement it merely quotes stays in money.
|
|
906
|
+
* Empty from a backend older than the field, which is a shelf that has not SAID — and is not the
|
|
907
|
+
* same as one that said dollars, so print the bare figure rather than guessing a symbol. */
|
|
908
|
+
currency: string;
|
|
909
|
+
/** Bounds on a per-unit purchase, when the product states them. Public because the quantity
|
|
910
|
+
* picker has to honour them — a customer who meets a limit they were never shown reads it as a
|
|
911
|
+
* broken shop. */
|
|
912
|
+
minQty?: number;
|
|
913
|
+
maxQty?: number;
|
|
914
|
+
includes: ShopInclusion[];
|
|
915
|
+
/** The enquiry form, on an `ask` product only. Never empty when present — a product that asks
|
|
916
|
+
* nothing still gets one box, because a Send button over nothing collects an enquiry that says
|
|
917
|
+
* only that somebody was interested. Absent on `buy` and `apply`, which are not asked. */
|
|
918
|
+
form?: ShopFormField[];
|
|
919
|
+
/** Present only where the tiers differ in scope; a product without them has one implicit tier,
|
|
920
|
+
* which is its own `pricing` and its own `includes`. */
|
|
921
|
+
variants?: ShopVariant[];
|
|
922
|
+
};
|
|
923
|
+
type ShopShelf = {
|
|
924
|
+
products: ShopProduct[];
|
|
925
|
+
/**
|
|
926
|
+
* The catalogue is bigger than what came back.
|
|
927
|
+
*
|
|
928
|
+
* Kept rather than dropped for the reason `listRows` returns a page: the server caps a shelf read,
|
|
929
|
+
* and a shop that quietly ends at the cap is a customer who cannot see half of it and nobody who
|
|
930
|
+
* can tell. The same argument the server makes when it bothers to send the flag.
|
|
931
|
+
*/
|
|
932
|
+
truncated: boolean;
|
|
933
|
+
};
|
|
934
|
+
/** An application against a product, or against nothing in particular — a general enquiry that
|
|
935
|
+
* names no product is a real thing to receive, so `productId` is optional. */
|
|
936
|
+
type ShopApplication = {
|
|
937
|
+
name: string;
|
|
938
|
+
/**
|
|
939
|
+
* Where the operator answers. Required, and checked by the server — but a malformed one is
|
|
940
|
+
* dropped SILENTLY (see `apply` below), so a form that wants to tell someone their address is
|
|
941
|
+
* wrong has to say so itself, before it sends.
|
|
942
|
+
*/
|
|
943
|
+
email: string;
|
|
944
|
+
phone?: string;
|
|
945
|
+
message?: string;
|
|
946
|
+
productId?: string;
|
|
947
|
+
};
|
|
948
|
+
/** The one answer every application gets. See `apply` for why it never varies. */
|
|
949
|
+
type ShopApplyResult = {
|
|
950
|
+
/**
|
|
951
|
+
* Always `true` — including for a submission that was dropped. It is a receipt that the request
|
|
952
|
+
* was accepted, never evidence that a row exists.
|
|
953
|
+
*/
|
|
954
|
+
ok: boolean;
|
|
955
|
+
/** The server's own thank-you line. Shown as sent rather than reworded, so the operator's copy is
|
|
956
|
+
* the copy the applicant reads. */
|
|
957
|
+
message: string;
|
|
958
|
+
};
|
|
959
|
+
type PortalShop = {
|
|
960
|
+
/** Everything on sale, in the operator's own order. Listed products only — a draft is something
|
|
961
|
+
* still being written and an archived one is off sale but kept because orders point at it. */
|
|
962
|
+
listProducts(): Promise<ShopShelf>;
|
|
963
|
+
/**
|
|
964
|
+
* Send an application. No account, no session — this is the one write on the platform a total
|
|
965
|
+
* stranger can make.
|
|
966
|
+
*
|
|
967
|
+
* It answers the SAME "thanks, we have your details" to an unknown key, a body that did not
|
|
968
|
+
* parse and a write that failed as it does to an application that landed, and that is deliberate:
|
|
969
|
+
* anything else would turn this into a way to ask which publishable keys reach a real company —
|
|
970
|
+
* and, once signups are invite-only, which addresses one already has. The cost is that a
|
|
971
|
+
* miswired form gets a cheerful reply and files nothing, so when applications are not arriving,
|
|
972
|
+
* the answer is in the operator's server logs and cannot be here.
|
|
973
|
+
*/
|
|
974
|
+
apply(application: ShopApplication): Promise<ShopApplyResult>;
|
|
975
|
+
};
|
|
976
|
+
declare const createPortalShop: (config: PortalShopConfig) => PortalShop;
|
|
977
|
+
|
|
978
|
+
/** Provides a `HolaClient` (from `createHolaClient`) to `useChat` / `<Chat/>`.
|
|
979
|
+
* Create the client once (e.g. `useMemo`) so its session persists across renders. */
|
|
980
|
+
declare const HolaProvider: ({ client, children, }: {
|
|
981
|
+
client: HolaClient;
|
|
982
|
+
children: ReactNode;
|
|
983
|
+
}) => react.JSX.Element;
|
|
984
|
+
declare const useHolaClient: () => HolaClient;
|
|
970
985
|
|
|
971
986
|
/**
|
|
972
987
|
* How this product is taken.
|
|
@@ -1053,14 +1068,6 @@ declare function facetValues(products: ShopProduct[], of: (product: ShopProduct)
|
|
|
1053
1068
|
declare function buyRequestText(product: ShopProduct, variant: string | null, price: ChosenPrice, qty: number): string;
|
|
1054
1069
|
declare function shelfProblem(error: unknown): string | null;
|
|
1055
1070
|
|
|
1056
|
-
/** Provides a `HolaClient` (from `createHolaClient`) to `useChat` / `<Chat/>`.
|
|
1057
|
-
* Create the client once (e.g. `useMemo`) so its session persists across renders. */
|
|
1058
|
-
declare const HolaProvider: ({ client, children, }: {
|
|
1059
|
-
client: HolaClient;
|
|
1060
|
-
children: ReactNode;
|
|
1061
|
-
}) => react.JSX.Element;
|
|
1062
|
-
declare const useHolaClient: () => HolaClient;
|
|
1063
|
-
|
|
1064
1071
|
type ChatMessage = {
|
|
1065
1072
|
id: number;
|
|
1066
1073
|
role: "user" | "assistant";
|
|
@@ -1079,6 +1086,17 @@ type UseChat = {
|
|
|
1079
1086
|
/** Chat state for one employee client: greeting, message list, streaming send. */
|
|
1080
1087
|
declare const useChat: (client: HolaClient) => UseChat;
|
|
1081
1088
|
|
|
1089
|
+
type UseCredits = {
|
|
1090
|
+
wallet: CreditWallet | null;
|
|
1091
|
+
/** The FIRST read only. A refresh keeps the numbers on screen and swaps them when the answer
|
|
1092
|
+
* lands: blanking a balance somebody is reading, to show a spinner, to show the same balance
|
|
1093
|
+
* again, is a flicker that reads as a fault. */
|
|
1094
|
+
loading: boolean;
|
|
1095
|
+
failure: string | null;
|
|
1096
|
+
refresh: () => void;
|
|
1097
|
+
};
|
|
1098
|
+
declare const useCredits: (credits: PortalCredits) => UseCredits;
|
|
1099
|
+
|
|
1082
1100
|
type UseShop = {
|
|
1083
1101
|
products: ShopProduct[];
|
|
1084
1102
|
/** In flight — the first read, and every `reload`. The products from the previous read stay put
|
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},F=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 Ue=/^ /,x=e=>{if(e&&typeof e=="object"){let t=e,r=typeof t.error=="string"?t.error:"request_failed";return typeof t.retryable=="boolean"?{error:r,retryable:t.retryable}:{error:r}}return{error:"request_failed"}},Ne=e=>{let t="message",r=[];for(let
|
|
3
|
-
`))
|
|
4
|
-
`)}:null},Ve=(e,t,r)=>{let
|
|
2
|
+
var te=e=>{if(!e||typeof e!="object")return null;let t=e;return t.type==="message_update"?t.assistantMessageEvent??null:null},F=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 Ue=/^ /,x=e=>{if(e&&typeof e=="object"){let t=e,r=typeof t.error=="string"?t.error:"request_failed";return typeof t.retryable=="boolean"?{error:r,retryable:t.retryable}:{error:r}}return{error:"request_failed"}},Ne=e=>{let t="message",r=[];for(let n of e.split(`
|
|
3
|
+
`))n.startsWith(":")||(n.startsWith("event:")?t=n.slice(6).trim():n.startsWith("data:")&&r.push(n.slice(5).replace(Ue,"")));return r.length>0?{event:t,data:r.join(`
|
|
4
|
+
`)}:null},Ve=(e,t,r)=>{let n;try{n=JSON.parse(e.data)}catch{return}if(e.event==="session"){let s=n.sessionId;s&&(r(s),t.onSession?.(s));return}if(e.event==="turn_event"){t.onEvent?.(n);let s=F(n);s&&t.onText?.(s);let a=L(n);a&&t.onThinking?.(a);let o=U(n);o&&t.onTool?.(o);return}if(e.event==="chat_completed"){let s=n;r(s.sessionId),t.onComplete?.(s);return}e.event==="chat_error"&&t.onError?.(x(n))},v=async(e,t)=>{let r=await fetch(e,{headers:t});if(!r.ok)throw new Error(`hola: request failed (${r.status})`);return await r.json()},re=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()},ne=async(e,t,r,n)=>{let s=await fetch(e.url,{method:"POST",headers:e.headers,body:e.body,signal:n});if(!(s.ok&&s.body)){t.onError?.({error:`stream_failed_${s.status}`});return}let a=s.body.getReader(),o=new TextDecoder,i="",l=()=>{let d=i.indexOf(`
|
|
5
5
|
|
|
6
6
|
`);for(;d!==-1;){let c=i.slice(0,d);i=i.slice(d+2);let m=Ne(c);m&&Ve(m,t,r),d=i.indexOf(`
|
|
7
7
|
|
|
8
|
-
`)}},u=async()=>{let d=await a.read();if(!d.done)return i+=n.decode(d.value,{stream:!0}),l(),u()};await u()};var je=/\/+$/,N="/api/v1/end-user",Ge=e=>{let t=e.baseUrl.replace(je,""),r=()=>typeof e.token=="function"?e.token():e.token,o=n=>e.project?`${n}project=${encodeURIComponent(e.project)}`:"",s=async()=>({"content-type":"application/json",authorization:`Bearer ${await r()}`}),a=async n=>{let i=await fetch(`${t}${N}/chat${o("?")}`,{method:"POST",headers:await s(),body:JSON.stringify({message:n})});if(!i.ok)throw new Error(`hola: message failed (${i.status})`);return{reply:(await i.json()).reply??"",sessionId:"",artifacts:[]}};return{sessionId:()=>"",getInfo:async()=>v(`${t}${N}/chat/info${o("?")}`,await s()),sendMessage:a,streamMessage:async(n,i)=>{try{let l=await a(n);i.onText?.(l.reply),i.onComplete?.(l)}catch(l){i.onError?.(x(l))}},subscribe:(n,i)=>{let l=i?.since??"0",u=!1,d,c=i?.intervalMs??3e3,m=typeof document<"u",p=()=>m&&document.visibilityState==="hidden",y=!1,w=()=>{if(!u){if(p()){y=!0;return}d=setTimeout(f,c)}},f=async()=>{try{let h=await v(`${t}${N}/chat/thread?since=${encodeURIComponent(l)}${o("&")}`,await s());for(let T of h.messages)n.onMessage(T);l=h.cursor,n.onHealthy?.()}catch(h){n.onError?.(x(h))}w()},k=()=>{u||!y||p()||(y=!1,d&&clearTimeout(d),d=setTimeout(f,0))};m&&document.addEventListener("visibilitychange",k);let g=()=>{u=!0,d&&clearTimeout(d),m&&document.removeEventListener("visibilitychange",k)};return i?.signal?.addEventListener("abort",g),d=setTimeout(f,0),g}}};import{useEffect as Be,useState as qe}from"react";var V=(e,t)=>{let[r,o]=qe("");return Be(()=>{if(!e){o("");return}let s=Uint8Array.from(atob(e),n=>n.charCodeAt(0)),a=URL.createObjectURL(new Blob([s],{type:t}));return o(a),()=>URL.revokeObjectURL(a)},[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}),j=()=>{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 G=e=>{let[t,r]=$([]),[o,s]=$(""),[a,n]=$(!1),[i,l]=$(null),u=ae(0),d=ae(null);ie(()=>()=>d.current?.abort(),[]);let c=se(()=>{let p=u.current;return u.current+=1,p},[]);ie(()=>{let p=!0;return e.getInfo().then(y=>{p&&y.greeting&&r([{id:c(),role:"assistant",text:y.greeting}])}).catch(()=>{}),()=>{p=!1}},[e,c]);let m=se(()=>{let p=o.trim();if(!p||a)return;s(""),l(null),n(!0);let y=c(),w=c();r(g=>[...g,{id:y,role:"user",text:p},{id:w,role:"assistant",text:"",streaming:!0}]);let f=g=>{r(h=>h.map(T=>T.id===w?g(T):T))},k=new AbortController;d.current=k,e.streamMessage(p,{onText:g=>f(h=>({...h,text:h.text+g})),onComplete:g=>{f(h=>({...h,text:g.reply||h.text,artifacts:g.artifacts,streaming:!1})),n(!1)},onError:g=>{f(h=>({...h,streaming:!1})),l(g.error),n(!1)}},k.signal).catch(g=>{f(h=>({...h,streaming:!1})),l(g instanceof Error?g.message:"stream_failed"),n(!1)}).finally(()=>{n(!1),f(g=>g.streaming?{...g,streaming:!1}:g)})},[o,a,e,c]);return{messages:t,input:o,setInput:s,send:m,sending:a,error:i}};import{jsx as R,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=V(e.dataBase64??"",e.mimeType),r=e.url??t;return r?e.mimeType.startsWith("image/")?R("a",{href:r,rel:"noopener noreferrer",target:"_blank",children:R("img",{alt:e.filename,src:r,style:S.image})}):R("a",{download:e.filename,href:r,style:S.link,children:e.filename}):null},et=()=>{let e=j(),{messages:t,input:r,setInput:o,send:s,sending:a,error:n}=G(e),i=Ye(null);Qe(()=>{let u=i.current;u&&(u.scrollTop=u.scrollHeight)},[t]);let l=u=>{u.preventDefault(),s()};return B("div",{style:S.root,children:[R("div",{ref:i,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?R("div",{style:S.artifacts,children:u.artifacts.map(d=>R(Ze,{artifact:d},d.filename))}):null]},u.id))}),n?R("div",{style:S.error,children:n}):null,B("form",{onSubmit:l,style:S.form,children:[R("input",{"aria-label":"Message",onChange:u=>o(u.target.value),placeholder:"Type a message\u2026",style:S.input,value:r}),R("button",{disabled:a||r.trim().length===0,style:S.button,type:"submit",children:"Send"})]})]})};var tt=/\/+$/,q=e=>{let t=e.sessionId,r=e.baseUrl.replace(tt,""),o=n=>`${r}/endpoint/${encodeURIComponent(e.token)}${n}`,s={"content-type":"application/json"},a=(n,i)=>({url:o(n),headers:s,body:JSON.stringify({message:i,...t?{sessionId:t}:{},...e.identity?{externalUserId:e.identity.externalUserId,userHmac:e.identity.userHmac}:{}})});return{sessionId:()=>t,getInfo:()=>v(o("/config"),{}),sendMessage:async n=>{let i=await re(a("/message",n));return t=i.sessionId,i},streamMessage:(n,i,l)=>ne(a("/message/stream",n),i,u=>{t=u},l),subscribe:(n,i)=>{let l=i?.since??"0",u=!1,d,c=i?.intervalMs??3e3,m=async()=>{let y=t;if(y)try{let w=await v(o(`/messages?session=${encodeURIComponent(y)}&since=${encodeURIComponent(l)}`),{});for(let f of w.messages)n.onMessage(f);l=w.cursor,n.onHealthy?.()}catch(w){n.onError?.(x(w))}u||(d=setTimeout(m,c))},p=()=>{u=!0,d&&clearTimeout(d)};return i?.signal?.addEventListener("abort",p),d=setTimeout(m,0),p}}};var rt=e=>"transport"in e?e.transport:q(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 o of e)for(let[s,a]of Object.entries(o.data??{})){if(a==null)continue;let n=r.get(s);n||(n=new Map,r.set(s,n),t.push(s));let i=it(a);n.set(i,(n.get(i)??0)+1)}return t.map(o=>{let s=r.get(o)??new Map,a="text",n=-1;for(let[i,l]of s)l>n&&(n=l,a=i);return{key:o,label:st(o),type:a}})}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)),o=r.filter(l=>l.type==="number").slice(0,3),s=r.find(l=>l.key==="status")??r.find(l=>l.type==="select"),a=r.find(l=>l.type==="date"&<.test(l.key))??r.find(l=>l.type==="date"),n=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,i=[{type:"stat",label:"Items",agg:"count"}];for(let l of o){let u=ue(l.key);i.push({type:"stat",metric:l.key,agg:u?"avg":"sum",label:u?`Avg ${l.label.toLowerCase()}`:l.label})}return a&&i.push({type:"line",x:a.key,y:n?.key,agg:"sum",title:n?`${n.label} by day`:"Items by day"}),s&&i.push({type:"donut",groupBy:s.key,title:s.label}),i.push({type:"table",columns:r.map(l=>l.key)}),{version:1,widgets:i}}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 o=ge[e];return{w:t===void 0?o.w:dt(t),h:r===void 0?o.h:pt(r)}}function J(e){let t=[],r=[],o=(n,i,l,u)=>{if(n<0||n+l>6)return!1;for(let d=0;d<u;d+=1){let c=r[i+d];if(c){for(let m=0;m<l;m+=1)if(c[n+m])return!1}}return!0},s=(n,i,l,u)=>{for(let d=0;d<u;d+=1){let c=r[i+d]??[];for(let m=0;m<l;m+=1)c[n+m]=!0;r[i+d]=c}},a=(n,i)=>{for(let l=0;;l+=1)for(let u=0;u+n<=6;u+=1)if(o(u,l,n,i))return{gx:u,gy:l}};for(let n of e){let i=z(W(n.kind),n.w,n.h),u=n.gx!==void 0&&n.gy!==void 0&&o(n.gx,n.gy,i.w,i.h)&&n.gx!==void 0&&n.gy!==void 0?{gx:n.gx,gy:n.gy}:a(i.w,i.h);s(u.gx,u.gy,i.w,i.h),t.push({widget:n,gx:u.gx,gy:u.gy,w:i.w,h:i.h})}return t}function be(e){let t=[],r=[];for(let o of e)W(o.kind)==="block"?r.push(o):t.push(o);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((o,s)=>o+s,0);return e==="avg"?Math.round(r/t.length*100)/100:r}function ct(e,t,r,o){let s=new Map;for(let a of e){let n=new Date(xe(a.data[t]));if(Number.isNaN(n.getTime()))continue;let i=n.toISOString().slice(0,10),l=s.get(i)??[];l.push(r?K(a.data[r]):1),s.set(i,l)}return[...s.entries()].sort((a,n)=>a[0]<n[0]?-1:1).map(([a,n])=>({label:new Date(`${a}T00:00:00`).toLocaleDateString(void 0,{month:"short",day:"numeric"}),value:r?X(o,n):n.length}))}function mt(e,t,r,o="sum"){let s=new Map;for(let a of e){let n=xe(a.data[t]).trim();if(!n)continue;let i=s.get(n)??[];i.push(r?K(a.data[r]):1),s.set(n,i)}return[...s.entries()].map(([a,n])=>({label:a,value:r?X(o,n):n.length})).sort((a,n)=>n.value-a.value)}function gt(e,t,r,o){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:o.length};let a=o.map(n=>K(n.data[s.key]));return{kind:"stat",label:e.label??s.label,value:X(e.agg??"sum",a)}}case"line":case"bar":{if(!t.has(e.x)||e.y&&!t.has(e.y))return null;let s=ct(o,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(o,e.groupBy,e.metric,e.agg??"sum");return s.length===0?null:{kind:"donut",title:e.title??t.get(e.groupBy)?.label??"Breakdown",points:s}}case"table":{let s=e.columns?e.columns.map(a=>t.get(a)).filter(a=>a!==void 0&&!he.has(a.key)):r;return s.length===0?null:{kind:"table",title:e.title,columns:s,rows:o}}case"text":return{kind:"text",title:e.title,body:e.body};default:return null}}function we(e,t,r,o={}){let s=new Map,a=l=>({byKey:new Map(l.fields.map(u=>[u.key,u])),cols:l.fields.filter(u=>!he.has(u.key)),rows:l.rows}),n=a({fields:t,rows:r});for(let[l,u]of Object.entries(o))s.set(l,a(u));let i=[];for(let l of e.widgets){let u=l.type==="text"?void 0:l.source,d=u?s.get(u):n;if(!d)continue;let c=gt(l,d.byKey,d.cols,d.rows);c&&i.push({...c,w:l.w,h:l.h,gx:l.gx,gy:l.gy})}return i}var ft=new Set(["sum","avg","count","min","max","last"]),ve=e=>typeof e=="string"&&ft.has(e)?e:void 0,b=e=>typeof e=="string"&&e!==""?e:void 0,D=e=>typeof e=="number"&&e>=1?Math.min(6,Math.round(e)):void 0,I=e=>typeof e=="number"&&e>=1?Math.min(4,Math.round(e)):void 0,P=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:b(t.source),label:b(t.label),metric:b(t.metric)??b(t.column),agg:ve(t.agg),w:D(t.w),h:I(t.h),gx:P(t.gx),gy:P(t.gy)};case"line":case"bar":{let r=b(t.x);return r?{type:t.type,source:b(t.source),title:b(t.title),x:r,y:b(t.y)??b(t.column),agg:ve(t.agg),w:D(t.w),h:I(t.h),gx:P(t.gx),gy:P(t.gy)}:null}case"donut":{let r=b(t.groupBy)??b(t.column);return r?{type:"donut",source:b(t.source),title:b(t.title),groupBy:r,w:D(t.w),h:I(t.h),gx:P(t.gx),gy:P(t.gy)}:null}case"table":{let r=Array.isArray(t.columns)?t.columns.filter(o=>typeof o=="string"):void 0;return{type:"table",source:b(t.source),title:b(t.title),columns:r,w:D(t.w),h:I(t.h),gx:P(t.gx),gy:P(t.gy)}}case"text":{let r=b(t.body);return r?{type:"text",title:b(t.title),body:r,w:D(t.w),h:I(t.h),gx:P(t.gx),gy:P(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 o=r.map(yt).filter(a=>a!==null);if(o.length===0)return null;let s=t.version;return{version:typeof s=="number"?s:1,title:b(t.title),widgets:o}}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:"",o=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:o,value:r,...s?{v:s}:{}}:null}return null}function Y(e){let t=new Map;for(let r of e){let o=r.v??1,s=t.get(o)??[];s.push(r),t.set(o,s)}return[...t.entries()].sort(([r],[o])=>r-o).map(([r,o])=>({v:r,items:o}))}function ke(e){let t=e.files;if(typeof t=="string"&&t.trim()!=="")try{let o=JSON.parse(t);if(Array.isArray(o))return o.map(Q).filter(s=>s!==null)}catch{}let r=String(e.file??"");return r?[{kind:"file",value:r}]:[]}function Pe(e,t,r,o=""){let a=Y(e).find(i=>i.v===t)?.items??[],n=a.filter(i=>i.kind==="file").map(i=>r.get(i.value)??"");return a.some(i=>i.kind==="table")&&n.push(o),n.length===0||n.some(i=>i==="")?"awaiting":n.some(i=>i==="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 Re(e){try{let t=JSON.parse(e);if(Array.isArray(t.columns)&&Array.isArray(t.rows)&&t.columns.length){let r=t.columns.map((a,n)=>({key:typeof a.key=="string"&&a.key?a.key:typeof a.id=="string"&&a.id?a.id:`column_${n+1}`,label:typeof a.label=="string"?a.label:"",type:Z(a.type),...a.clientEditable===!0?{clientEditable:!0}:{}})),o=t.rows.map((a,n)=>({id:typeof a.id=="string"&&a.id?a.id:`row_${n}`,cells:a.cells&&typeof a.cells=="object"?a.cells:{}})),s=typeof t.name=="string"?t.name:void 0;return{columns:r,rows:o,...s?{name:s}:{}}}}catch{}return null}function Ce(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 He(e,t,r){if(e.clientEditable){let o=r.cells[t.id];if(o&&e.key in o)return o[e.key]}return t.cells[e.key]}function Ae(e,t,r,o){return{...e,cells:{...e.cells,[t]:{...e.cells[t]??{},[r]:o}}}}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 bt=/\/+$/,C="/api/v1/end-user",H=class extends Error{constructor(t){super(t),this.name="PortalConflict"}};function ht(e){let t="";for(let o=0;o<e.length;o+=32768)t+=String.fromCharCode(...e.subarray(o,o+32768));return btoa(t)}var xt=e=>{let t=e.baseUrl.replace(bt,""),r=()=>typeof e.token=="function"?e.token():e.token,o=async()=>({"content-type":"application/json",authorization:`Bearer ${await r()}`}),s=async(n,i)=>{try{let l=await fetch(`${t}${C}${n}`,{method:i.method,headers:await o(),...i.body===void 0?{}:{body:JSON.stringify(i.body)}});if(l.status===409){let u=await l.json().catch(()=>({}));throw new H(u.message??"Someone else saved this first.")}if(!l.ok){let u=await l.text().catch(()=>""),d=`${i.method} ${n} \u2192 ${String(l.status)}`;try{let c=JSON.parse(u);c.message&&(d=c.message)}catch{d=u?`${d}: ${u}`:d}throw x({error:d})}return await l.json()}catch(l){throw l instanceof H?l:x(l)}},a=n=>`/tables/${encodeURIComponent(n)}`;return{listTables:async()=>(await v(`${t}${C}/tables`,await o())).tables,listRows:async(n,i)=>await v(`${t}${C}${a(n)}/rows?limit=${String(i??100)}`,await o()),insertRow:async(n,i)=>{let{rowIds:l}=await s(`${a(n)}/rows`,{method:"POST",body:{rows:[i]}}),u=l[0];if(!u)throw x(new Error("The row was not created."));return u},patchRow:async(n,i,l)=>(await s(`${a(n)}/rows/${encodeURIComponent(i)}`,{method:"PATCH",body:l})).updated,deleteRow:async(n,i)=>(await s(`/${encodeURIComponent(n)}/${encodeURIComponent(i)}`,{method:"DELETE"})).deleted,listFiles:async()=>(await v(`${t}${C}/tables/files/rows?limit=200`,await o())).rows.map(i=>({id:i.rowId,filename:String(i.data.filename??""),source:String(i.data.source??"client"),campaign:String(i.data.campaign??""),size:typeof i.data.size=="number"?i.data.size:0,createdAt:i.createdAt})),uploadFile:async(n,i)=>{let l=new Uint8Array(await n.arrayBuffer());return await s("/files",{method:"POST",body:{filename:n.name,mime:n.type||"application/octet-stream",data:ht(l),...i===void 0?{}:{message:i}}})},fileLink:async n=>await v(`${t}${C}/files/${encodeURIComponent(n)}/url`,await o()),deleteFile:async n=>(await s(`/files/${encodeURIComponent(n)}`,{method:"DELETE"})).deleted,listDocuments:async()=>(await v(`${t}${C}/documents`,await o())).documents,readDocument:async n=>(await v(`${t}${C}/documents/${encodeURIComponent(n)}`,await o())).document,saveDocument:async(n,i)=>await s(`/documents/${encodeURIComponent(n)}`,{method:"PATCH",body:i})}};var wt=/\/+$/,vt="/api/v1/end-user",St=e=>{let t=e.baseUrl.replace(wt,""),r=async(o,s)=>{let a;try{a=await fetch(`${t}${vt}${o}`,s===void 0?{}:{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(s)})}catch(n){throw x(n)}if(a.status===429)throw x({error:"rate_limited",retryable:!0});if(!a.ok)throw x({error:`shop_request_failed_${String(a.status)}`});try{return await a.json()}catch(n){throw x(n)}};return{listProducts:async()=>{let o=await r(`/shop/products?publishable_key=${encodeURIComponent(e.publishableKey)}`);return{products:o.products.map(s=>({...s,currency:typeof s.currency=="string"?s.currency:""})),truncated:o.truncated===!0}},apply:async o=>await r("/shop/apply",{publishable_key:e.publishableKey,name:o.name,email:o.email,...o.phone?{phone:o.phone}:{},...o.message?{message:o.message}:{},...o.productId?{productId:o.productId}:{}})}};var A=class extends Error{code;status;constructor(t,r,o){super(r),this.name="CreditRefused",this.code=t,this.status=o}},kt=/\/+$/,Pt="/api/v1/end-user",Tt=e=>{let t=e.baseUrl.replace(kt,""),r=()=>typeof e.token=="function"?e.token():e.token,o=async(s,a={method:"GET"})=>{try{let n=await fetch(`${t}${Pt}${s}`,{method:a.method,headers:{"content-type":"application/json",authorization:`Bearer ${await r()}`},...a.body===void 0?{}:{body:JSON.stringify(a.body)}});if(!n.ok){let i=await n.json().catch(()=>({}));throw new A(i.error??"request_failed",i.message??`${a.method} ${s} \u2192 ${String(n.status)}`,n.status)}return await n.json()}catch(n){throw n instanceof A?n:x(n)}};return{wallet:()=>o("/credits"),history:()=>o("/credits/history"),topup:s=>o("/credits/checkout",{method:"POST",body:{packId:s}}),checkout:s=>o("/shop/checkout",{method:"POST",body:s}),enquire:(s,a)=>o("/shop/enquire",{method:"POST",body:{productId:s,answers:a}})}};import{useCallback as We,useEffect as Rt,useState as ee}from"react";var Ct=e=>{let[t,r]=ee(null),[o,s]=ee(!0),[a,n]=ee(null),i=We(async()=>{try{r(await e.wallet()),n(null)}catch{n("Couldn't read your balance just now.")}finally{s(!1)}},[e]),l=We(()=>{i().catch(()=>{})},[i]);return Rt(()=>(l(),window.addEventListener("focus",l),()=>{window.removeEventListener("focus",l)}),[l]),{wallet:t,loading:o,failure:a,refresh:l}};var Dt=new Set(["buy","ask","apply"]);function It(e){return Dt.has(e.mode)?e.mode:"ask"}var Ht={kind:"quoted"};function O(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 Ee(e,t){let r=/^[a-z]+$/i.test(t)&&!t.endsWith("s")?"s":"";return`${e.toLocaleString()} ${t}${r}`}function Oe(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:Ee(e.unitStep,e.unit)}`}function At(e){let t=e.currency,r=e.pricing;if(r.kind!=="variants")return Oe(r,t);let o=r.variants.map(s=>s.price).filter(s=>typeof s=="number");return o.length>0?`From ${O(Math.min(...o),t)}`:"Priced on enquiry"}function Mt(e,t){if(e.kind!=="variants")return e;let r=e.variants.find(o=>o.name===t);return typeof r?.price=="number"?{kind:"flat",price:r.price}:Ht}function $t(e,t){return e.kind==="flat"?e.price:e.kind==="per_unit"?e.unitPrice*Math.ceil(t/Math.max(e.unitStep,1)):null}function Wt(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 Et(e,t){let r=e.variants?.find(o=>o.name===t);return r&&r.includes.length>0?r.includes:e.includes}function Ot(e,t){let r=[];for(let o of e){let s=t(o).trim();s&&!r.includes(s)&&r.push(s)}return r}function _t(e,t,r,o){let s=t?`${e.name} \u2014 ${t}`:e.name,a=r.kind==="per_unit"?`, ${Ee(o,r.unit)}`:"";return`I'd like to buy ${s}${a}. How do I go ahead?`}function Ft(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 Lt,useEffect as Ut,useState as M}from"react";var Nt=e=>e&&typeof e=="object"&&typeof e.error=="string"?e.error:e instanceof Error?e.message:"shop_unavailable",Vt=e=>{let[t,r]=M([]),[o,s]=M(!1),[a,n]=M(!0),[i,l]=M(null),[u,d]=M(0);Ut(()=>{let m=!0;return n(!0),e.listProducts().then(p=>{m&&(r(p.products),s(p.truncated),l(null))}).catch(p=>{m&&l(Nt(p))}).finally(()=>{m&&n(!1)}),()=>{m=!1}},[e,u]);let c=Lt(()=>d(m=>m+1),[]);return{products:t,truncated:o,loading:a,error:i,reload:c}};import{useCallback as jt,useEffect as _e,useRef as Gt,useState as _}from"react";var Fe="greeting";function Le(e,t){if(e.some(a=>a.id===t.id))return e;let r=e.filter(a=>a.id!==Fe),o=a=>a.author==="client"==(t.author==="client");return[...r.filter(a=>!(a.pending&&o(a)&&a.text===t.text)),t]}var Bt=(e,t)=>{let[r,o]=_([]),[s,a]=_(""),[n,i]=_(!1),[l,u]=_(null),d=Gt(0),c=t?.pollMs??2e3;_e(()=>{let p=!0;return e.getInfo().then(y=>{p&&y.greeting&&o(w=>w.length===0?[{id:Fe,cursor:"",author:"agent",text:y.greeting}]:w)}).catch(()=>{}),()=>{p=!1}},[e]),_e(()=>e.subscribe?.({onMessage:p=>o(y=>Le(y,p)),onError:p=>u(p.error),onHealthy:()=>u(null)},{intervalMs:c}),[e,c]);let m=jt(()=>{let p=s.trim();if(!p||n)return;a(""),u(null),i(!0),d.current+=1;let y=`pending-${d.current}`,w={id:y,cursor:"",author:"client",text:p,pending:!0};o(f=>[...f,w]),e.sendMessage(p).then(f=>{i(!1),f.reply.trim()&&o(g=>g.some(T=>!T.pending&&T.author!=="client"&&T.text===f.reply)?g:(d.current+=1,[...g,{id:`pending-agent-${d.current}`,cursor:"",author:"agent",text:f.reply,pending:!0}]))}).catch(f=>{u(f instanceof Error?f.message:"send_failed"),i(!1),o(k=>k.filter(g=>g.id!==y)),a(k=>k||p)})},[s,n,e]);return{messages:r,input:s,setInput:a,send:m,sending:n,error:l}};export{et as Chat,A as CreditRefused,pe as GRID_COLS,ce as GRID_MAX_COLS,me as GRID_MAX_ROWS,Ke as HolaProvider,H as PortalConflict,W as bandOfKind,fe as bandOfType,_t as buyRequestText,He as cellValue,Ge as createApiTransport,rt as createHolaClient,Tt as createPortalCredits,xt as createPortalData,St as createPortalShop,q as createWidgetTransport,Ce as deliverableCellText,Pe as deliverableStatus,le as deriveFields,E as emptyTableResponses,Ot as facetValues,ye as footprintOf,z as footprintWith,$e as formatDeliverableDate,Y as groupDeliverableVersions,Et as includesFor,de as inferSpec,De as isDeliverableChecked,Le as mergeMessage,It as modeOf,O as money,Z as normalizeDeliverableColType,Q as normalizeDeliverableItem,Se as parseDashboardSpec,ke as parseDeliverableItems,Re as parseDeliverableTable,Ie as parseTableResponses,J as placeWidgets,Mt as priceFor,Oe as priceLabel,Te as publishedVersionOf,Wt as quantityRange,we as renderModel,Ae as setResponse,Me as setTableReview,At as shelfPriceLabel,Ft as shelfProblem,be as splitLayout,F as textDeltaOf,L as thinkingDeltaOf,U as toolEventOf,$t as totalFor,V as useArtifactUrl,G as useChat,Ct as useCredits,j as useHolaClient,Vt as useShop,Bt as useThread};
|
|
8
|
+
`)}},u=async()=>{let d=await a.read();if(!d.done)return i+=o.decode(d.value,{stream:!0}),l(),u()};await u()};var je=/\/+$/,N="/api/v1/end-user",Ge=e=>{let t=e.baseUrl.replace(je,""),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()}`}),a=async o=>{let i=await fetch(`${t}${N}/chat${n("?")}`,{method:"POST",headers:await s(),body:JSON.stringify({message:o})});if(!i.ok)throw new Error(`hola: message failed (${i.status})`);return{reply:(await i.json()).reply??"",sessionId:"",artifacts:[]}};return{sessionId:()=>"",getInfo:async()=>v(`${t}${N}/chat/info${n("?")}`,await s()),sendMessage:a,streamMessage:async(o,i)=>{try{let l=await a(o);i.onText?.(l.reply),i.onComplete?.(l)}catch(l){i.onError?.(x(l))}},subscribe:(o,i)=>{let l=i?.since??"0",u=!1,d,c=i?.intervalMs??3e3,m=typeof document<"u",p=()=>m&&document.visibilityState==="hidden",y=!1,w=()=>{if(!u){if(p()){y=!0;return}d=setTimeout(f,c)}},f=async()=>{try{let h=await v(`${t}${N}/chat/thread?since=${encodeURIComponent(l)}${n("&")}`,await s());for(let T of h.messages)o.onMessage(T);l=h.cursor,o.onHealthy?.()}catch(h){o.onError?.(x(h))}w()},P=()=>{u||!y||p()||(y=!1,d&&clearTimeout(d),d=setTimeout(f,0))};m&&document.addEventListener("visibilitychange",P);let g=()=>{u=!0,d&&clearTimeout(d),m&&document.removeEventListener("visibilitychange",P)};return i?.signal?.addEventListener("abort",g),d=setTimeout(f,0),g}}};import{useEffect as qe,useState as Be}from"react";var V=(e,t)=>{let[r,n]=Be("");return qe(()=>{if(!e){n("");return}let s=Uint8Array.from(atob(e),o=>o.charCodeAt(0)),a=URL.createObjectURL(new Blob([s],{type:t}));return n(a),()=>URL.revokeObjectURL(a)},[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}),j=()=>{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 G=e=>{let[t,r]=$([]),[n,s]=$(""),[a,o]=$(!1),[i,l]=$(null),u=ae(0),d=ae(null);ie(()=>()=>d.current?.abort(),[]);let c=se(()=>{let p=u.current;return u.current+=1,p},[]);ie(()=>{let p=!0;return e.getInfo().then(y=>{p&&y.greeting&&r([{id:c(),role:"assistant",text:y.greeting}])}).catch(()=>{}),()=>{p=!1}},[e,c]);let m=se(()=>{let p=n.trim();if(!p||a)return;s(""),l(null),o(!0);let y=c(),w=c();r(g=>[...g,{id:y,role:"user",text:p},{id:w,role:"assistant",text:"",streaming:!0}]);let f=g=>{r(h=>h.map(T=>T.id===w?g(T):T))},P=new AbortController;d.current=P,e.streamMessage(p,{onText:g=>f(h=>({...h,text:h.text+g})),onComplete:g=>{f(h=>({...h,text:g.reply||h.text,artifacts:g.artifacts,streaming:!1})),o(!1)},onError:g=>{f(h=>({...h,streaming:!1})),l(g.error),o(!1)}},P.signal).catch(g=>{f(h=>({...h,streaming:!1})),l(g instanceof Error?g.message:"stream_failed"),o(!1)}).finally(()=>{o(!1),f(g=>g.streaming?{...g,streaming:!1}:g)})},[n,a,e,c]);return{messages:t,input:n,setInput:s,send:m,sending:a,error:i}};import{jsx as R,jsxs as q}from"react/jsx-runtime";var S={root:{display:"flex",flexDirection:"column",height:"100%",fontFamily:"system-ui, -apple-system, sans-serif",fontSize:14,color:"#111827"},log:{flex:1,overflowY:"auto",padding:12,display:"flex",flexDirection:"column",gap:8},user:{alignSelf:"flex-end",background:"#111827",color:"#ffffff",borderRadius:12,padding:"8px 12px",maxWidth:"80%",whiteSpace:"pre-wrap"},assistant:{alignSelf:"flex-start",background:"#f1f1f4",color:"#111827",borderRadius:12,padding:"8px 12px",maxWidth:"80%",whiteSpace:"pre-wrap"},artifacts:{display:"flex",flexDirection:"column",gap:6,marginTop:6},image:{maxHeight:220,borderRadius:8,border:"1px solid #e5e7eb"},link:{color:"#2563eb",textDecoration:"underline",wordBreak:"break-all"},error:{color:"#b91c1c",padding:"4px 12px",fontSize:13},form:{display:"flex",gap:8,borderTop:"1px solid #e5e7eb",padding:8},input:{flex:1,border:"1px solid #d1d5db",borderRadius:8,padding:"8px 10px",fontSize:14,outline:"none"},button:{border:"none",background:"#111827",color:"#ffffff",borderRadius:8,padding:"8px 14px",fontSize:14,cursor:"pointer"}},Ze=({artifact:e})=>{let t=V(e.dataBase64??"",e.mimeType),r=e.url??t;return r?e.mimeType.startsWith("image/")?R("a",{href:r,rel:"noopener noreferrer",target:"_blank",children:R("img",{alt:e.filename,src:r,style:S.image})}):R("a",{download:e.filename,href:r,style:S.link,children:e.filename}):null},et=()=>{let e=j(),{messages:t,input:r,setInput:n,send:s,sending:a,error:o}=G(e),i=Ye(null);Qe(()=>{let u=i.current;u&&(u.scrollTop=u.scrollHeight)},[t]);let l=u=>{u.preventDefault(),s()};return q("div",{style:S.root,children:[R("div",{ref:i,style:S.log,children:t.map(u=>q("div",{style:u.role==="user"?S.user:S.assistant,children:[u.text||(u.streaming?"\u2026":""),u.artifacts&&u.artifacts.length>0?R("div",{style:S.artifacts,children:u.artifacts.map(d=>R(Ze,{artifact:d},d.filename))}):null]},u.id))}),o?R("div",{style:S.error,children:o}):null,q("form",{onSubmit:l,style:S.form,children:[R("input",{"aria-label":"Message",onChange:u=>n(u.target.value),placeholder:"Type a message\u2026",style:S.input,value:r}),R("button",{disabled:a||r.trim().length===0,style:S.button,type:"submit",children:"Send"})]})]})};var tt=/\/+$/,B=e=>{let t=e.sessionId,r=e.baseUrl.replace(tt,""),n=o=>`${r}/endpoint/${encodeURIComponent(e.token)}${o}`,s={"content-type":"application/json"},a=(o,i)=>({url:n(o),headers:s,body:JSON.stringify({message:i,...t?{sessionId:t}:{},...e.identity?{externalUserId:e.identity.externalUserId,userHmac:e.identity.userHmac}:{}})});return{sessionId:()=>t,getInfo:()=>v(n("/config"),{}),sendMessage:async o=>{let i=await re(a("/message",o));return t=i.sessionId,i},streamMessage:(o,i,l)=>ne(a("/message/stream",o),i,u=>{t=u},l),subscribe:(o,i)=>{let l=i?.since??"0",u=!1,d,c=i?.intervalMs??3e3,m=async()=>{let y=t;if(y)try{let w=await v(n(`/messages?session=${encodeURIComponent(y)}&since=${encodeURIComponent(l)}`),{});for(let f of w.messages)o.onMessage(f);l=w.cursor,o.onHealthy?.()}catch(w){o.onError?.(x(w))}u||(d=setTimeout(m,c))},p=()=>{u=!0,d&&clearTimeout(d)};return i?.signal?.addEventListener("abort",p),d=setTimeout(m,0),p}}};var rt=e=>"transport"in e?e.transport:B(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,a]of Object.entries(n.data??{})){if(a==null)continue;let o=r.get(s);o||(o=new Map,r.set(s,o),t.push(s));let i=it(a);o.set(i,(o.get(i)??0)+1)}return t.map(n=>{let s=r.get(n)??new Map,a="text",o=-1;for(let[i,l]of s)l>o&&(o=l,a=i);return{key:n,label:st(n),type:a}})}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"),a=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,i=[{type:"stat",label:"Items",agg:"count"}];for(let l of n){let u=ue(l.key);i.push({type:"stat",metric:l.key,agg:u?"avg":"sum",label:u?`Avg ${l.label.toLowerCase()}`:l.label})}return a&&i.push({type:"line",x:a.key,y:o?.key,agg:"sum",title:o?`${o.label} by day`:"Items by day"}),s&&i.push({type:"donut",groupBy:s.key,title:s.label}),i.push({type:"table",columns:r.map(l=>l.key)}),{version:1,widgets:i}}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,i,l,u)=>{if(o<0||o+l>6)return!1;for(let d=0;d<u;d+=1){let c=r[i+d];if(c){for(let m=0;m<l;m+=1)if(c[o+m])return!1}}return!0},s=(o,i,l,u)=>{for(let d=0;d<u;d+=1){let c=r[i+d]??[];for(let m=0;m<l;m+=1)c[o+m]=!0;r[i+d]=c}},a=(o,i)=>{for(let l=0;;l+=1)for(let u=0;u+o<=6;u+=1)if(n(u,l,o,i))return{gx:u,gy:l}};for(let o of e){let i=z(W(o.kind),o.w,o.h),u=o.gx!==void 0&&o.gy!==void 0&&n(o.gx,o.gy,i.w,i.h)&&o.gx!==void 0&&o.gy!==void 0?{gx:o.gx,gy:o.gy}:a(i.w,i.h);s(u.gx,u.gy,i.w,i.h),t.push({widget:o,gx:u.gx,gy:u.gy,w:i.w,h:i.h})}return t}function 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 a of e){let o=new Date(xe(a.data[t]));if(Number.isNaN(o.getTime()))continue;let i=o.toISOString().slice(0,10),l=s.get(i)??[];l.push(r?K(a.data[r]):1),s.set(i,l)}return[...s.entries()].sort((a,o)=>a[0]<o[0]?-1:1).map(([a,o])=>({label:new Date(`${a}T00:00:00`).toLocaleDateString(void 0,{month:"short",day:"numeric"}),value:r?X(n,o):o.length}))}function mt(e,t,r,n="sum"){let s=new Map;for(let a of e){let o=xe(a.data[t]).trim();if(!o)continue;let i=s.get(o)??[];i.push(r?K(a.data[r]):1),s.set(o,i)}return[...s.entries()].map(([a,o])=>({label:a,value:r?X(n,o):o.length})).sort((a,o)=>o.value-a.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 a=n.map(o=>K(o.data[s.key]));return{kind:"stat",label:e.label??s.label,value:X(e.agg??"sum",a)}}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(a=>t.get(a)).filter(a=>a!==void 0&&!he.has(a.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,a=l=>({byKey:new Map(l.fields.map(u=>[u.key,u])),cols:l.fields.filter(u=>!he.has(u.key)),rows:l.rows}),o=a({fields:t,rows:r});for(let[l,u]of Object.entries(n))s.set(l,a(u));let i=[];for(let l of e.widgets){let u=l.type==="text"?void 0:l.source,d=u?s.get(u):o;if(!d)continue;let c=gt(l,d.byKey,d.cols,d.rows);c&&i.push({...c,w:l.w,h:l.h,gx:l.gx,gy:l.gy})}return i}var ft=new Set(["sum","avg","count","min","max","last"]),ve=e=>typeof e=="string"&&ft.has(e)?e:void 0,b=e=>typeof e=="string"&&e!==""?e:void 0,D=e=>typeof e=="number"&&e>=1?Math.min(6,Math.round(e)):void 0,I=e=>typeof e=="number"&&e>=1?Math.min(4,Math.round(e)):void 0,k=e=>typeof e=="number"&&e>=0?Math.round(e):void 0;function yt(e){if(typeof e!="object"||e===null)return null;let t=e;switch(t.type){case"stat":return{type:"stat",source:b(t.source),label:b(t.label),metric:b(t.metric)??b(t.column),agg:ve(t.agg),w:D(t.w),h:I(t.h),gx:k(t.gx),gy:k(t.gy)};case"line":case"bar":{let r=b(t.x);return r?{type:t.type,source:b(t.source),title:b(t.title),x:r,y:b(t.y)??b(t.column),agg:ve(t.agg),w:D(t.w),h:I(t.h),gx:k(t.gx),gy:k(t.gy)}:null}case"donut":{let r=b(t.groupBy)??b(t.column);return r?{type:"donut",source:b(t.source),title:b(t.title),groupBy:r,w:D(t.w),h:I(t.h),gx:k(t.gx),gy:k(t.gy)}:null}case"table":{let r=Array.isArray(t.columns)?t.columns.filter(n=>typeof n=="string"):void 0;return{type:"table",source:b(t.source),title:b(t.title),columns:r,w:D(t.w),h:I(t.h),gx:k(t.gx),gy:k(t.gy)}}case"text":{let r=b(t.body);return r?{type:"text",title:b(t.title),body:r,w:D(t.w),h:I(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(a=>a!==null);if(n.length===0)return null;let s=t.version;return{version:typeof s=="number"?s:1,title:b(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 a=Y(e).find(i=>i.v===t)?.items??[],o=a.filter(i=>i.kind==="file").map(i=>r.get(i.value)??"");return a.some(i=>i.kind==="table")&&o.push(n),o.length===0||o.some(i=>i==="")?"awaiting":o.some(i=>i==="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 Re(e){try{let t=JSON.parse(e);if(Array.isArray(t.columns)&&Array.isArray(t.rows)&&t.columns.length){let r=t.columns.map((a,o)=>({key:typeof a.key=="string"&&a.key?a.key:typeof a.id=="string"&&a.id?a.id:`column_${o+1}`,label:typeof a.label=="string"?a.label:"",type:Z(a.type),...a.clientEditable===!0?{clientEditable:!0}:{}})),n=t.rows.map((a,o)=>({id:typeof a.id=="string"&&a.id?a.id:`row_${o}`,cells:a.cells&&typeof a.cells=="object"?a.cells:{}})),s=typeof t.name=="string"?t.name:void 0;return{columns:r,rows:n,...s?{name:s}:{}}}}catch{}return null}function Ce(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 He(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 Ae(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=>{let t=e.baseUrl.replace(bt,""),r=()=>typeof e.token=="function"?e.token():e.token,n=async(s,a={method:"GET"})=>{try{let o=await fetch(`${t}${ht}${s}`,{method:a.method,headers:{"content-type":"application/json",authorization:`Bearer ${await r()}`},...a.body===void 0?{}:{body:JSON.stringify(a.body)}});if(!o.ok){let i=await o.json().catch(()=>({}));throw new H(i.error??"request_failed",i.message??`${a.method} ${s} \u2192 ${String(o.status)}`,o.status)}return await o.json()}catch(o){throw o instanceof H?o:x(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}),acceptInquiry:s=>n(`/inquiries/${encodeURIComponent(s)}/accept`,{method:"POST"}),enquire:(s,a)=>n("/shop/enquire",{method:"POST",body:{productId:s,answers:a}})}};var wt=/\/+$/,C="/api/v1/end-user",A=class extends Error{constructor(t){super(t),this.name="PortalConflict"}};function vt(e){let t="";for(let n=0;n<e.length;n+=32768)t+=String.fromCharCode(...e.subarray(n,n+32768));return btoa(t)}var St=e=>{let t=e.baseUrl.replace(wt,""),r=()=>typeof e.token=="function"?e.token():e.token,n=async()=>({"content-type":"application/json",authorization:`Bearer ${await r()}`}),s=async(o,i)=>{try{let l=await fetch(`${t}${C}${o}`,{method:i.method,headers:await n(),...i.body===void 0?{}:{body:JSON.stringify(i.body)}});if(l.status===409){let u=await l.json().catch(()=>({}));throw new A(u.message??"Someone else saved this first.")}if(!l.ok){let u=await l.text().catch(()=>""),d=`${i.method} ${o} \u2192 ${String(l.status)}`;try{let c=JSON.parse(u);c.message&&(d=c.message)}catch{d=u?`${d}: ${u}`:d}throw x({error:d})}return await l.json()}catch(l){throw l instanceof A?l:x(l)}},a=o=>`/tables/${encodeURIComponent(o)}`;return{listTables:async()=>(await v(`${t}${C}/tables`,await n())).tables,listRows:async(o,i)=>await v(`${t}${C}${a(o)}/rows?limit=${String(i??100)}`,await n()),insertRow:async(o,i)=>{let{rowIds:l}=await s(`${a(o)}/rows`,{method:"POST",body:{rows:[i]}}),u=l[0];if(!u)throw x(new Error("The row was not created."));return u},patchRow:async(o,i,l)=>(await s(`${a(o)}/rows/${encodeURIComponent(i)}`,{method:"PATCH",body:l})).updated,deleteRow:async(o,i)=>(await s(`/${encodeURIComponent(o)}/${encodeURIComponent(i)}`,{method:"DELETE"})).deleted,listFiles:async()=>(await v(`${t}${C}/tables/files/rows?limit=200`,await n())).rows.map(i=>({id:i.rowId,filename:String(i.data.filename??""),source:String(i.data.source??"client"),campaign:String(i.data.campaign??""),size:typeof i.data.size=="number"?i.data.size:0,createdAt:i.createdAt})),uploadFile:async(o,i)=>{let l=new Uint8Array(await o.arrayBuffer());return await s("/files",{method:"POST",body:{filename:o.name,mime:o.type||"application/octet-stream",data:vt(l),...i===void 0?{}:{message:i}}})},fileLink:async o=>await v(`${t}${C}/files/${encodeURIComponent(o)}/url`,await n()),deleteFile:async o=>(await s(`/files/${encodeURIComponent(o)}`,{method:"DELETE"})).deleted,listDocuments:async()=>(await v(`${t}${C}/documents`,await n())).documents,readDocument:async o=>(await v(`${t}${C}/documents/${encodeURIComponent(o)}`,await n())).document,saveDocument:async(o,i)=>await s(`/documents/${encodeURIComponent(o)}`,{method:"PATCH",body:i})}};var Pt=/\/+$/,kt="/api/v1/end-user",Tt=e=>{let t=e.baseUrl.replace(Pt,""),r=async(n,s)=>{let a;try{a=await fetch(`${t}${kt}${n}`,s===void 0?{}:{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(s)})}catch(o){throw x(o)}if(a.status===429)throw x({error:"rate_limited",retryable:!0});if(!a.ok)throw x({error:`shop_request_failed_${String(a.status)}`});try{return await a.json()}catch(o){throw x(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}},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 Ct(e){return Rt.has(e.mode)?e.mode:"ask"}var Dt={kind:"quoted"};function O(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"?O(e.price,t):`${O(e.unitPrice,t)} per ${e.unitStep===1?e.unit:We(e.unitStep,e.unit)}`}function It(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 ${O(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}:Dt}function At(e,t){return e.kind==="flat"?e.price:e.kind==="per_unit"?e.unitPrice*Math.ceil(t/Math.max(e.unitStep,1)):null}function Mt(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 $t(e,t){let r=e.variants?.find(n=>n.name===t);return r&&r.includes.length>0?r.includes:e.includes}function Wt(e,t){let r=[];for(let n of e){let s=t(n).trim();s&&!r.includes(s)&&r.push(s)}return r}function Et(e,t,r,n){let s=t?`${e.name} \u2014 ${t}`:e.name,a=r.kind==="per_unit"?`, ${We(n,r.unit)}`:"";return`I'd like to buy ${s}${a}. 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 Oe,useEffect as _t,useState as ee}from"react";var Ft=e=>{let[t,r]=ee(null),[n,s]=ee(!0),[a,o]=ee(null),i=Oe(async()=>{try{r(await e.wallet()),o(null)}catch{o("Couldn't read your balance just now.")}finally{s(!1)}},[e]),l=Oe(()=>{i().catch(()=>{})},[i]);return _t(()=>(l(),window.addEventListener("focus",l),()=>{window.removeEventListener("focus",l)}),[l]),{wallet:t,loading:n,failure:a,refresh:l}};import{useCallback as Lt,useEffect as Ut,useState as M}from"react";var Nt=e=>e&&typeof e=="object"&&typeof e.error=="string"?e.error:e instanceof Error?e.message:"shop_unavailable",Vt=e=>{let[t,r]=M([]),[n,s]=M(!1),[a,o]=M(!0),[i,l]=M(null),[u,d]=M(0);Ut(()=>{let m=!0;return o(!0),e.listProducts().then(p=>{m&&(r(p.products),s(p.truncated),l(null))}).catch(p=>{m&&l(Nt(p))}).finally(()=>{m&&o(!1)}),()=>{m=!1}},[e,u]);let c=Lt(()=>d(m=>m+1),[]);return{products:t,truncated:n,loading:a,error:i,reload:c}};import{useCallback as jt,useEffect as _e,useRef as Gt,useState as _}from"react";var Fe="greeting";function Le(e,t){if(e.some(a=>a.id===t.id))return e;let r=e.filter(a=>a.id!==Fe),n=a=>a.author==="client"==(t.author==="client");return[...r.filter(a=>!(a.pending&&n(a)&&a.text===t.text)),t]}var qt=(e,t)=>{let[r,n]=_([]),[s,a]=_(""),[o,i]=_(!1),[l,u]=_(null),d=Gt(0),c=t?.pollMs??2e3;_e(()=>{let p=!0;return e.getInfo().then(y=>{p&&y.greeting&&n(w=>w.length===0?[{id:Fe,cursor:"",author:"agent",text:y.greeting}]:w)}).catch(()=>{}),()=>{p=!1}},[e]),_e(()=>e.subscribe?.({onMessage:p=>n(y=>Le(y,p)),onError:p=>u(p.error),onHealthy:()=>u(null)},{intervalMs:c}),[e,c]);let m=jt(()=>{let p=s.trim();if(!p||o)return;a(""),u(null),i(!0),d.current+=1;let y=`pending-${d.current}`,w={id:y,cursor:"",author:"client",text:p,pending:!0};n(f=>[...f,w]),e.sendMessage(p).then(f=>{i(!1),f.reply.trim()&&n(g=>g.some(T=>!T.pending&&T.author!=="client"&&T.text===f.reply)?g:(d.current+=1,[...g,{id:`pending-agent-${d.current}`,cursor:"",author:"agent",text:f.reply,pending:!0}]))}).catch(f=>{u(f instanceof Error?f.message:"send_failed"),i(!1),n(P=>P.filter(g=>g.id!==y)),a(P=>P||p)})},[s,o,e]);return{messages:r,input:s,setInput:a,send:m,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,A as PortalConflict,W as bandOfKind,fe as bandOfType,Et as buyRequestText,He as cellValue,Ge as createApiTransport,rt as createHolaClient,xt as createPortalCredits,St as createPortalData,Tt as createPortalShop,B as createWidgetTransport,Ce as deliverableCellText,ke as deliverableStatus,le as deriveFields,E as emptyTableResponses,Wt as facetValues,ye as footprintOf,z as footprintWith,$e as formatDeliverableDate,Y as groupDeliverableVersions,$t as includesFor,de as inferSpec,De as isDeliverableChecked,Le as mergeMessage,Ct as modeOf,O as money,Z as normalizeDeliverableColType,Q as normalizeDeliverableItem,Se as parseDashboardSpec,Pe as parseDeliverableItems,Re as parseDeliverableTable,Ie as parseTableResponses,J as placeWidgets,Ht as priceFor,Ee as priceLabel,Te as publishedVersionOf,Mt as quantityRange,we as renderModel,Ae as setResponse,Me as setTableReview,It as shelfPriceLabel,Ot as shelfProblem,be as splitLayout,F as textDeltaOf,L as thinkingDeltaOf,U as toolEventOf,At as totalFor,V as useArtifactUrl,G as useChat,Ft as useCredits,j as useHolaClient,Vt as useShop,qt 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.24",
|
|
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",
|