@rubytech/create-maxy 1.0.498 → 1.0.500

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.
Files changed (118) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/admin/mcp/dist/index.js +34 -4
  3. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  4. package/payload/platform/plugins/admin/skills/stream-log-review/SKILL.md +3 -3
  5. package/payload/platform/scripts/logs-read.sh +40 -5
  6. package/payload/platform/templates/agents/admin/IDENTITY.md +1 -1
  7. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/PLUGIN.md +36 -8
  8. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/index.js +229 -153
  9. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/index.js.map +1 -1
  10. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/lib/loop-api.d.ts +19 -1
  11. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/lib/loop-api.d.ts.map +1 -1
  12. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/lib/loop-api.js +99 -3
  13. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/lib/loop-api.js.map +1 -1
  14. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/customer-preferences.d.ts +10 -0
  15. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/customer-preferences.d.ts.map +1 -0
  16. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/customer-preferences.js +24 -0
  17. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/customer-preferences.js.map +1 -0
  18. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/feedback.d.ts +16 -0
  19. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/feedback.d.ts.map +1 -0
  20. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/feedback.js +35 -0
  21. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/feedback.js.map +1 -0
  22. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/key-register.js +1 -1
  23. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/key-register.js.map +1 -1
  24. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-enquiry.d.ts +13 -0
  25. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-enquiry.d.ts.map +1 -0
  26. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-enquiry.js +41 -0
  27. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-enquiry.js.map +1 -0
  28. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-batch.d.ts +9 -0
  29. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-batch.d.ts.map +1 -0
  30. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-batch.js +16 -0
  31. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-batch.js.map +1 -0
  32. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-request.d.ts +15 -0
  33. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-request.d.ts.map +1 -0
  34. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-request.js +11 -0
  35. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match-request.js.map +1 -0
  36. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match.d.ts +10 -0
  37. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match.d.ts.map +1 -0
  38. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match.js +39 -0
  39. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/marketing-match.js.map +1 -0
  40. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-detail.d.ts +9 -0
  41. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-detail.d.ts.map +1 -0
  42. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-detail.js +33 -0
  43. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-detail.js.map +1 -0
  44. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-search.d.ts +18 -0
  45. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-search.d.ts.map +1 -0
  46. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-search.js +59 -0
  47. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/people-search.js.map +1 -0
  48. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-detail.d.ts +10 -0
  49. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-detail.d.ts.map +1 -0
  50. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-detail.js +39 -0
  51. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-detail.js.map +1 -0
  52. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-listed.d.ts +12 -0
  53. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-listed.d.ts.map +1 -0
  54. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-listed.js +28 -0
  55. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-listed.js.map +1 -0
  56. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-request.d.ts +15 -0
  57. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-request.d.ts.map +1 -0
  58. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-request.js +11 -0
  59. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-request.js.map +1 -0
  60. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-search.d.ts +16 -0
  61. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-search.d.ts.map +1 -0
  62. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-search.js +39 -0
  63. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/property-search.js.map +1 -0
  64. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/supplier.d.ts +13 -0
  65. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/supplier.d.ts.map +1 -0
  66. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/supplier.js +49 -0
  67. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/supplier.js.map +1 -0
  68. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/team-availability.d.ts +7 -0
  69. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/team-availability.d.ts.map +1 -0
  70. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/team-availability.js +15 -0
  71. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/team-availability.js.map +1 -0
  72. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-create.d.ts +14 -0
  73. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-create.d.ts.map +1 -0
  74. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-create.js +11 -0
  75. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-create.js.map +1 -0
  76. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-detail.d.ts +9 -0
  77. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-detail.d.ts.map +1 -0
  78. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-detail.js +40 -0
  79. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-detail.js.map +1 -0
  80. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-search.d.ts +13 -0
  81. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-search.d.ts.map +1 -0
  82. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-search.js +34 -0
  83. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-search.js.map +1 -0
  84. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-update.d.ts +14 -0
  85. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-update.d.ts.map +1 -0
  86. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-update.js +18 -0
  87. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/dist/tools/viewing-update.js.map +1 -0
  88. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/index.ts +335 -158
  89. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/lib/loop-api.ts +140 -3
  90. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/customer-preferences.ts +60 -0
  91. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/feedback.ts +80 -0
  92. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/key-register.ts +1 -1
  93. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/marketing-enquiry.ts +105 -0
  94. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/marketing-match-batch.ts +48 -0
  95. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/marketing-match-request.ts +37 -0
  96. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/marketing-match.ts +78 -0
  97. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/people-detail.ts +63 -0
  98. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/people-search.ts +93 -0
  99. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/property-detail.ts +70 -0
  100. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/property-listed.ts +67 -0
  101. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/property-request.ts +37 -0
  102. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/property-search.ts +80 -0
  103. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/supplier.ts +120 -0
  104. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/team-availability.ts +42 -0
  105. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/viewing-create.ts +36 -0
  106. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/viewing-detail.ts +70 -0
  107. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/viewing-search.ts +74 -0
  108. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/viewing-update.ts +48 -0
  109. package/payload/server/public/assets/{ChatInput-BbMvZgRR.js → ChatInput-Bo9T8v0E.js} +1 -1
  110. package/payload/server/public/assets/{admin-BSHc9LPS.js → admin-CkpknqK7.js} +60 -60
  111. package/payload/server/public/assets/{public-DvDzSq3r.js → public-wDhMuZDR.js} +1 -1
  112. package/payload/server/public/index.html +2 -2
  113. package/payload/server/public/public.html +2 -2
  114. package/payload/server/server.js +89 -2
  115. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/feedback-list.ts +0 -54
  116. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/people-list.ts +0 -52
  117. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/properties-list.ts +0 -52
  118. package/payload/premium-plugins/real-agency/plugins/real-agency-loop/mcp/src/tools/viewings-list.ts +0 -62
@@ -1,4 +1,4 @@
1
- import{C as e,D as t,E as n,S as r,T as i,_ as a,a as o,b as s,d as c,f as l,h as u,i as d,j as f,k as p,m,n as h,p as g,r as _,s as v,t as y,u as b,v as x,w as S,x as C,y as w}from"./ChatInput-BbMvZgRR.js";var T=n(`square-plus`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M8 12h8`,key:`1wcyev`}],[`path`,{d:`M12 8v8`,key:`napkw2`}]]),E=t(),D=f(p(),1),O=`image/jpeg,image/png,image/gif,image/webp,application/pdf,text/plain,text/markdown,text/csv,text/html`,k=new Set(O.split(`,`)),A=20*1024*1024,j=typeof window<`u`&&/^(localhost|127\.0\.0\.1|[a-z0-9-]+\.local)(:|$)/.test(window.location.hostname);function M(){let e=crypto.getRandomValues(new Uint8Array(16));e[6]=e[6]&15|64,e[8]=e[8]&63|128;let t=[...e].map(e=>e.toString(16).padStart(2,`0`)).join(``);return`${t.slice(0,8)}-${t.slice(8,12)}-${t.slice(12,16)}-${t.slice(16,20)}-${t.slice(20)}`}function N(){let e=window.location.pathname.match(/^\/([a-z][a-z0-9-]{2,49})$/);return e?e[1]:void 0}function P(e){return[{key:`length`,label:`At least 8 characters`,met:e.length>=8},{key:`number`,label:`Contains a number`,met:/\d/.test(e)},{key:`special`,label:`Contains a special character`,met:/[^A-Za-z0-9]/.test(e)},{key:`whitespace`,label:`No leading or trailing spaces`,met:e.length>0&&e===e.trim()}]}function F(e,t){if(t===`phone`)return e.length>4?e.slice(0,e.length-4).replace(/\d/g,`•`)+` `+e.slice(-4):e;let n=e.indexOf(`@`);return n<=2?e:e.slice(0,2)+`•••`+e.slice(n)}function I(e){let[t,n]=(0,D.useState)(null),[r,i]=(0,D.useState)(null),[a,o]=(0,D.useState)(`loading`),[s,c]=(0,D.useState)(``),[l,u]=(0,D.useState)(null),[d,f]=(0,D.useState)(null),[p,m]=(0,D.useState)(!1),[h,g]=(0,D.useState)(null),_=(0,D.useMemo)(()=>N(),[]),v=(0,D.useRef)(_||``),y=(0,D.useRef)(null),b=(0,D.useRef)(null),x=(0,D.useRef)(!1),S=(0,D.useRef)(null),[C,w]=(0,D.useState)(`sign-in`),[T,E]=(0,D.useState)(null),O=(0,D.useRef)(null),k=(0,D.useRef)(null);(0,D.useEffect)(()=>{try{let e=sessionStorage.getItem(`maxy_session`);e&&(k.current=e)}catch{}},[]);let A=(0,D.useCallback)(t=>{y.current=t,n(t);try{sessionStorage.setItem(`maxy_session`,t)}catch{}o(`chat`),e(t)},[e]),P=(0,D.useCallback)(()=>{y.current=null;try{sessionStorage.removeItem(`maxy_session`)}catch{}n(null),o(`auth-required`),w(`sign-in`)},[]),F=(0,D.useCallback)(async e=>{try{let t=v.current,n=await fetch(`/api/access/verify-token`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({token:e,agentSlug:t})}),r=await n.json();n.ok?(O.current=r.session_key,E(r.grant),w(`set-password`),window.history.replaceState({},``,window.location.pathname)):w(`link-expired`)}catch{w(`sign-in`)}},[]),I=(0,D.useCallback)(async()=>{if(y.current)return y.current;if(b.current)return b.current;let e=(async()=>{try{let e=k.current,t=await fetch(`/api/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({session_id:M(),..._?{agent:_}:{},...e?{session_key:e}:{}})});if(!t.ok){let e=await t.json().catch(()=>({error:``}));return j&&console.error(`[session] POST /api/session failed: ${t.status} ${t.statusText}`,e),t.status===404?i(e.error||`Agent not found`):t.status===503&&i(e.error||`Service unavailable`),null}let r=await t.json();if(r.auth_required){r.agent_id&&(v.current=r.agent_id),c(r.displayName||``),r.agentImage&&u(r.agentImage),r.agentImageShape&&f(r.agentImageShape),r.showAgentName&&m(r.showAgentName),r.branding&&g(r.branding),o(`auth-required`);let e=new URLSearchParams(window.location.search).get(`token`);return e?F(e):w(`sign-in`),null}y.current=r.session_key,n(r.session_key),r.displayName&&c(r.displayName),r.agentImage&&u(r.agentImage),r.agentImageShape&&f(r.agentImageShape),r.showAgentName&&m(r.showAgentName),r.branding&&g(r.branding),o(`chat`),r.resumed&&r.messages&&(x.current=!0,S.current=r.messages);try{sessionStorage.setItem(`maxy_session`,r.session_key)}catch{}return r.session_key}catch(e){return j&&console.error(`[session] fetch /api/session threw:`,e),i(`Unable to connect. Please check your connection and try again.`),null}finally{b.current=null}})();return b.current=e,e},[_,F]);return{sessionId:t,sessionKeyRef:y,sessionError:r,pageState:a,setPageState:o,agentDisplayName:s,agentImage:l,agentImageShape:d,showAgentName:p,agentSlug:_,branding:h,resolvedSlugRef:v,ensureSession:I,startNewSession:(0,D.useCallback)(async()=>{y.current=null,b.current=null,k.current=null,x.current=!1,S.current=null,n(null),i(null);try{sessionStorage.removeItem(`maxy_session`)}catch{}let t=await I();t&&e(t)},[I,e]),enterChat:A,enterGate:P,resumedRef:x,resumeMessagesRef:S,gateState:C,setGateState:w,grantInfo:T,setGrantInfo:E,gateSessionKeyRef:O}}function L({sessionKeyRef:e,ensureSession:t,sessionError:n,pageState:r,inputRef:i}){let[o,s]=(0,D.useState)([]),[c,l]=(0,D.useState)(!1),u=(0,D.useRef)(!1),d=e=>{u.current=e,l(e)},f=(0,D.useCallback)(async o=>{if(!u.current){d(!0),s([{role:`maxy`,content:``,timestamp:Date.now()}]);try{let n=await fetch(`/api/chat`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({greeting:!0,session_key:o})});if(n.status===401){e.current=null;try{sessionStorage.removeItem(`maxy_session`)}catch{}j&&console.warn(`[greeting] stale session, retrying with fresh session`);let r=await t();if(!r)return;n=await fetch(`/api/chat`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({greeting:!0,session_key:r})})}if(!n.ok){let e=await n.json().catch(()=>({}));throw Error(e.error||`Something went wrong`)}let r=``,i=``,c=()=>{i&&(r+=i,i=``,s(e=>{let t=[...e];return t[0]={...t[0],content:r},t}))},l=setInterval(c,60);try{for await(let e of a(n)){if(e.error)throw Object.assign(Error(e.error),{fromSSE:!0});e.text&&(i+=e.text),e.type===`component`&&(c(),s(t=>{let n=[...t],r={...n[0]},i=[...r.components||[]];return i.push({name:e.name,data:e.data,submitted:!1}),n[0]={...r,components:i},n}))}}finally{clearInterval(l),c()}}catch(e){if(j&&console.error(`[chat] greeting failed:`,e),r===`auth-required`)return;let t=e instanceof Error?e.message:String(e);s([{role:`maxy`,content:e instanceof Error&&e.fromSSE?t:n??`I'm having trouble connecting right now. Try refreshing the page.`,timestamp:Date.now()}])}finally{d(!1),r===`chat`&&i.current?.focus()}}},[e,t,n,r,i]),p=(0,D.useCallback)(async(o,c)=>{let l=c?.hidden??!1,f=c?.files??[];if(!o&&f.length===0||u.current)return;d(!0);let p=f.map(e=>({filename:e.name,mimeType:e.type})),m={role:`visitor`,content:o,attachments:p.length>0?p:void 0,timestamp:Date.now(),hidden:l},h;s(e=>{let t=[...e,m,{role:`maxy`,content:``,timestamp:Date.now()}];return h=t.length-1,t});try{let n=await t();if(!n)throw Error(`session`);let r=e=>{if(f.length>0){let t=new FormData;t.append(`message`,o),t.append(`session_key`,e);for(let e of f)t.append(`attachments`,e);return{body:t,headers:{}}}return{body:JSON.stringify({message:o,session_key:e}),headers:{"Content-Type":`application/json`}}},{body:i,headers:c}=r(n),l=await fetch(`/api/chat`,{method:`POST`,headers:c,body:i});if(l.status===401){e.current=null;try{sessionStorage.removeItem(`maxy_session`)}catch{}j&&console.warn(`[session-expired] stale key cleared, retrying with fresh session`);let n=await t();if(!n)throw Error(`session`);({body:i,headers:c}=r(n)),l=await fetch(`/api/chat`,{method:`POST`,headers:c,body:i})}if(!l.ok){let e=await l.json().catch(()=>({}));throw Error(e.error||`Something went wrong`)}let u=``,d=``,p=()=>{d&&(u+=d,d=``,s(e=>{let t=[...e];return t[h]={...t[h],content:u},t}))},m=setInterval(p,60);try{for await(let e of a(l)){if(e.error)throw Object.assign(Error(e.error),{fromSSE:!0});e.text&&(d+=e.text),e.type===`component`&&(p(),s(t=>{let n=[...t],r={...n[h]},i=[...r.components||[]];return i.push({name:e.name,data:e.data,submitted:!1}),n[h]={...r,components:i},n}))}}finally{clearInterval(m),p()}}catch(e){if(j&&console.error(`[chat] sendMessage failed:`,e),r===`auth-required`)return;let t=e instanceof Error?e.message:String(e),i=e instanceof Error&&e.fromSSE;s(e=>{let r=[...e];return r[h]={...r[h],content:i?t:t===`session`?n??`I'm having trouble connecting right now. Try refreshing the page.`:`Sorry, I hit a snag. Try again in a moment.`},r})}finally{d(!1),r===`chat`&&i.current?.focus()}},[e,t,n,r,i]);return{messages:o,setMessages:s,isStreaming:c,sendMessage:p,sendGreeting:f,handleComponentSubmit:(0,D.useCallback)((e,t,n)=>{s(n=>{let r=[...n],i={...r[e]},a=[...i.components||[]];return a[t]={...a[t],submitted:!0},r[e]={...i,components:a},r}),p(n,{hidden:!0})},[p])}}var R=l();function z({value:e,onChange:t,onComplete:n,disabled:r}){let i=(0,D.useRef)([]);function a(n,r){r.key===`Backspace`?(r.preventDefault(),e[n]?t(e.slice(0,n)+e.slice(n+1)):n>0&&(t(e.slice(0,n-1)+e.slice(n)),i.current[n-1]?.focus())):r.key===`ArrowLeft`&&n>0?i.current[n-1]?.focus():r.key===`ArrowRight`&&n<5&&i.current[n+1]?.focus()}function o(r,a){let o=a.nativeEvent.data;if(!o||!/^\d$/.test(o))return;let s=e.split(``);for(s[r]=o;s.length<r;)s.push(``);let c=s.join(``).replace(/\D/g,``).slice(0,6);t(c),c.length===6?n(c):r<5&&i.current[r+1]?.focus()}function s(e){e.preventDefault();let r=e.clipboardData.getData(`text`).replace(/\D/g,``).slice(0,6);r&&(t(r),r.length===6?n(r):i.current[r.length]?.focus())}return(0,R.jsx)(`div`,{className:`gate-otp-field`,children:Array.from({length:6}).map((t,n)=>(0,R.jsx)(`input`,{ref:e=>{i.current[n]=e},type:`text`,inputMode:`numeric`,className:`pin-box${e[n]?` pin-box-filled`:``}`,value:e[n]||``,onKeyDown:e=>a(n,e),onInput:e=>o(n,e),onPaste:s,onFocus:e=>e.target.select(),autoFocus:n===0,autoComplete:`off`,maxLength:1,disabled:r,"aria-label":`Code digit ${n+1}`},n))})}function B({gateState:e,setGateState:t,grantInfo:n,setGrantInfo:r,gateSessionKeyRef:i,resolvedSlugRef:a,onAuthenticated:o}){let[s,l]=(0,D.useState)(``),[u,d]=(0,D.useState)(``),[f,p]=(0,D.useState)(``),[m,h]=(0,D.useState)(!1),[g,_]=(0,D.useState)(``),[v,y]=(0,D.useState)(``),[x,S]=(0,D.useState)(!1),[C,w]=(0,D.useState)(null),[T,E]=(0,D.useState)(null),[O,k]=(0,D.useState)(!1);async function A(e){if(e.preventDefault(),!O){w(null),k(!0);try{let e=a.current,n=await fetch(`/api/access/login`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({contact:s,password:u,agentSlug:e})}),i=await n.json();n.ok?o(i.session_key):n.status===401?i.error?.includes(`setup not complete`)||i.error?.includes(`invitation link`)?(t(`private-agent`),w(null)):w(i.error||`Invalid credentials`):n.status===403?(t(`access-expired`),i.expiresAt&&r(e=>e?{...e,expiresAt:i.expiresAt}:{displayName:null,contactValue:s,contactMethod:`email`,expiresAt:i.expiresAt,status:`expired`})):n.status===429?w(i.error||`Too many attempts. Please try again later.`):w(i.error||`Something went wrong`)}catch{w(`Unable to connect. Please try again.`)}finally{k(!1)}}}async function j(e){if(!O){w(null),k(!0);try{let n=a.current,o=await fetch(`/api/access/verify-otp`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({phone:v,code:e,agentSlug:n})}),s=await o.json();o.ok?(i.current=s.session_key,r(s.grant),t(`set-password`)):o.status===429?t(`otp-failed`):(w(s.error||`Invalid code`),_(``))}catch{w(`Unable to connect. Please try again.`)}finally{k(!1)}}}async function M(e){if(e.preventDefault(),!O){if(w(null),u!==f){w(`Passwords do not match`);return}if(!P(u).every(e=>e.met)){w(`Password does not meet requirements`);return}k(!0);try{let e=i.current;if(!e){w(`Session expired. Please use your invitation link again.`);return}let t=await fetch(`/api/access/create-credentials`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({session_key:e,password:u})}),n=await t.json();t.ok?o(n.session_key):t.status===400&&n.requirements?w(n.requirements.filter(e=>!e.met).map(e=>e.label).join(`, `)):w(n.error||`Something went wrong`)}catch{w(`Unable to connect. Please try again.`)}finally{k(!1)}}}async function N(e){if(e.preventDefault(),!(O||!s)){w(null),k(!0);try{let e=a.current,t=await fetch(`/api/access/forgot-password`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({contact:s,agentSlug:e})});t.status===429?w((await t.json()).error||`Too many attempts. Please try again later.`):(E(`If an account exists, a reset link has been sent.`),setTimeout(()=>{S(!1),E(null)},4e3))}catch{w(`Unable to connect. Please try again.`)}finally{k(!1)}}}switch(e){case`set-password`:{let e=P(u),t=e.every(e=>e.met),r=u===f,i=t&&r&&f.length>0;return(0,R.jsx)(`div`,{className:`gate-wrap`,children:(0,R.jsxs)(`div`,{className:`gate-card`,children:[n?.expiresAt&&(0,R.jsxs)(`div`,{className:`gate-expiry-badge`,children:[`Access until `,new Date(n.expiresAt).toLocaleDateString(`en-GB`,{day:`numeric`,month:`short`,year:`numeric`})]}),(0,R.jsxs)(`h2`,{className:`gate-title`,children:[`Welcome, `,n?.displayName||`there`]}),(0,R.jsx)(`p`,{className:`gate-subtitle`,children:`Create a password to access this agent in the future.`}),(0,R.jsxs)(`form`,{className:`gate-form`,onSubmit:M,children:[(0,R.jsxs)(`div`,{className:`gate-field`,children:[(0,R.jsx)(`label`,{htmlFor:`gate-display-name`,children:`Display name`}),(0,R.jsx)(`input`,{id:`gate-display-name`,type:`text`,value:n?.displayName||``,disabled:!0})]}),(0,R.jsxs)(`div`,{className:`gate-field gate-pw-row`,children:[(0,R.jsx)(`label`,{htmlFor:`gate-pw`,children:`Password`}),(0,R.jsx)(`div`,{className:`gate-pw-toggle`,children:(0,R.jsx)(c,{checked:m,onChange:h,label:`Show`})}),(0,R.jsx)(`input`,{id:`gate-pw`,type:m?`text`:`password`,value:u,onChange:e=>d(e.target.value),placeholder:`Your password`,autoFocus:!0,autoComplete:`new-password`}),u.length>0&&(0,R.jsx)(`div`,{className:`gate-strength`,children:e.map(e=>(0,R.jsxs)(`span`,{className:`gate-strength-item${e.met?` met`:``}`,children:[e.met?`✓`:`○`,` `,e.label]},e.key))})]}),(0,R.jsxs)(`div`,{className:`gate-field`,children:[(0,R.jsx)(`label`,{htmlFor:`gate-pw-confirm`,children:`Confirm password`}),(0,R.jsx)(`input`,{id:`gate-pw-confirm`,type:m?`text`:`password`,value:f,onChange:e=>p(e.target.value),placeholder:`Confirm your password`,autoComplete:`new-password`}),f.length>0&&!r&&(0,R.jsx)(`div`,{className:`gate-error`,children:`Passwords do not match`})]}),C&&(0,R.jsx)(`div`,{className:`gate-error`,children:C}),(0,R.jsx)(`div`,{className:`gate-submit`,children:(0,R.jsx)(b,{variant:`primary`,type:`submit`,fullWidth:!0,disabled:!i||O,loading:O,children:`Create account & enter chat`})})]})]})})}case`enter-otp`:return(0,R.jsx)(`div`,{className:`gate-wrap`,children:(0,R.jsxs)(`div`,{className:`gate-card`,children:[(0,R.jsx)(`h2`,{className:`gate-title`,children:`Enter your code`}),(0,R.jsxs)(`p`,{className:`gate-subtitle`,children:[`Enter the 6-digit code sent to `,F(v,`phone`)]}),(0,R.jsx)(z,{value:g,onChange:_,onComplete:j,disabled:O}),C&&(0,R.jsx)(`div`,{className:`gate-error`,children:C}),O&&(0,R.jsxs)(`div`,{className:`gate-loading`,children:[(0,R.jsx)(`span`,{className:`spinner`}),`Verifying...`]}),(0,R.jsx)(`div`,{className:`gate-resend`,children:(0,R.jsx)(`button`,{type:`button`,className:`gate-link`,onClick:()=>{t(`sign-in`),_(``),w(null)},children:`Use a different number`})})]})});case`sign-in`:case`private-agent`:return(0,R.jsx)(`div`,{className:`gate-wrap`,children:(0,R.jsxs)(`div`,{className:`gate-card`,children:[(0,R.jsx)(`h2`,{className:`gate-title`,children:e===`private-agent`?`Private Agent`:`Welcome back`}),(0,R.jsx)(`p`,{className:`gate-subtitle`,children:e===`private-agent`?`This agent is invitation-only. If you have an account, sign in below.`:`Sign in to continue your conversation.`}),x?(0,R.jsxs)(`form`,{className:`gate-form`,onSubmit:N,children:[(0,R.jsxs)(`div`,{className:`gate-field`,children:[(0,R.jsx)(`label`,{htmlFor:`gate-forgot-contact`,children:`Email or phone`}),(0,R.jsx)(`input`,{id:`gate-forgot-contact`,type:`text`,value:s,onChange:e=>l(e.target.value),placeholder:`you@example.com`,autoFocus:!0,autoComplete:`email`})]}),C&&(0,R.jsx)(`div`,{className:`gate-error`,children:C}),T&&(0,R.jsx)(`div`,{className:`gate-success`,children:T}),(0,R.jsx)(`div`,{className:`gate-submit`,children:(0,R.jsx)(b,{variant:`primary`,type:`submit`,fullWidth:!0,disabled:!s.trim()||O,loading:O,children:`Send reset link`})}),(0,R.jsx)(`div`,{className:`gate-actions`,children:(0,R.jsx)(`button`,{type:`button`,className:`gate-link`,onClick:()=>{S(!1),w(null),E(null)},children:`Back to sign in`})})]}):(0,R.jsxs)(`form`,{className:`gate-form`,onSubmit:A,children:[(0,R.jsxs)(`div`,{className:`gate-field`,children:[(0,R.jsx)(`label`,{htmlFor:`gate-contact`,children:`Email or phone`}),(0,R.jsx)(`input`,{id:`gate-contact`,type:`text`,value:s,onChange:e=>l(e.target.value),placeholder:`you@example.com`,autoFocus:!0,autoComplete:`email`})]}),(0,R.jsxs)(`div`,{className:`gate-field gate-pw-row`,children:[(0,R.jsx)(`label`,{htmlFor:`gate-login-pw`,children:`Password`}),(0,R.jsx)(`div`,{className:`gate-pw-toggle`,children:(0,R.jsx)(c,{checked:m,onChange:h,label:`Show`})}),(0,R.jsx)(`input`,{id:`gate-login-pw`,type:m?`text`:`password`,value:u,onChange:e=>d(e.target.value),placeholder:`Your password`,autoComplete:`current-password`})]}),C&&(0,R.jsx)(`div`,{className:`gate-error`,children:C}),(0,R.jsx)(`div`,{className:`gate-submit`,children:(0,R.jsx)(b,{variant:`primary`,type:`submit`,fullWidth:!0,disabled:!s.trim()||!u||O,loading:O,children:`Sign in`})}),(0,R.jsx)(`div`,{className:`gate-actions`,children:(0,R.jsx)(`button`,{type:`button`,className:`gate-link`,onClick:()=>{S(!0),w(null)},children:`Forgot password?`})})]}),e===`private-agent`&&(0,R.jsx)(`p`,{className:`gate-hint`,children:`No account? You need an invitation from the agent owner.`})]})});case`access-expired`:return(0,R.jsx)(`div`,{className:`gate-wrap`,children:(0,R.jsxs)(`div`,{className:`gate-card`,children:[(0,R.jsx)(`div`,{className:`gate-icon`,children:`⏰`}),(0,R.jsx)(`h2`,{className:`gate-title`,children:`Access expired`}),(0,R.jsxs)(`p`,{className:`gate-subtitle`,children:[n?.expiresAt?`Your access expired on ${new Date(n.expiresAt).toLocaleDateString(`en-GB`,{day:`numeric`,month:`long`,year:`numeric`})}.`:`Your access to this agent has expired.`,` `,`Contact the agent owner to renew.`]}),(0,R.jsx)(`div`,{className:`gate-actions`,children:(0,R.jsx)(b,{variant:`secondary`,onClick:()=>{t(`sign-in`),w(null),d(``)},children:`Sign in with a different account`})})]})});case`link-expired`:return(0,R.jsx)(`div`,{className:`gate-wrap`,children:(0,R.jsxs)(`div`,{className:`gate-card`,children:[(0,R.jsx)(`div`,{className:`gate-icon`,children:`⚠️`}),(0,R.jsx)(`h2`,{className:`gate-title`,children:`Link expired`}),(0,R.jsx)(`p`,{className:`gate-subtitle`,children:`This invitation link has expired or has already been used. If you already set your password, sign in below. Otherwise, ask the agent owner to send a new invitation.`}),(0,R.jsx)(`div`,{className:`gate-actions`,children:(0,R.jsx)(b,{variant:`primary`,onClick:()=>{t(`sign-in`),w(null)},children:`Go to sign in`})})]})});case`otp-failed`:return(0,R.jsx)(`div`,{className:`gate-wrap`,children:(0,R.jsxs)(`div`,{className:`gate-card`,children:[(0,R.jsx)(`div`,{className:`gate-icon`,children:`⛔`}),(0,R.jsx)(`h2`,{className:`gate-title`,children:`Too many attempts`}),(0,R.jsx)(`p`,{className:`gate-subtitle`,children:`You've entered the wrong code too many times. Ask the agent owner to send a new code.`}),(0,R.jsx)(`div`,{className:`gate-actions`,children:(0,R.jsx)(b,{variant:`secondary`,onClick:()=>{t(`sign-in`),w(null),_(``)},children:`Back to sign in`})})]})})}}var V={"single-select":o,"multi-select":d};function H({name:e,data:t,onSubmit:n,submitted:r}){let i=V[e];return i?(0,R.jsx)(i,{data:t,onSubmit:n,submitted:r}):(console.warn(`[PublicComponentRenderer] Unknown component: "${e}". Registered: ${Object.keys(V).join(`, `)}`),(0,R.jsx)(`div`,{className:`component-card component-card--error`,children:(0,R.jsxs)(`p`,{style:{fontFamily:`var(--font-body)`,fontSize:12,color:`var(--text-secondary)`},children:[`Component “`,e,`” is not available. This may require a platform update.`]})}))}function U({messages:t,isStreaming:n,sessionError:a,selectionMode:o,selectedItems:s,toggleSelectItem:l,onComponentSubmit:u,remainingSuggestions:d,onSuggestionClick:f,isAtBottom:p,setIsAtBottom:m}){let[h,g]=(0,D.useState)(new Set),[y,x]=(0,D.useState)(new Set),S=(0,D.useRef)(null),C=(0,D.useRef)(null),w=(0,D.useRef)(null),T=(0,D.useRef)(!1),E=(0,D.useRef)(!1),O=(0,D.useRef)(!1),k=(0,D.useRef)(0),A=(0,D.useRef)(!1),j=(0,D.useRef)(new Map);A.current=n,(0,D.useEffect)(()=>{n&&!T.current&&p&&(E.current=!0)},[n,p]),(0,D.useEffect)(()=>{if(!E.current&&!p){T.current=n,O.current=!1;return}if(T.current&&!n&&w.current&&C.current){let e=w.current;if(e.offsetHeight>C.current.clientHeight){E.current=!1,O.current=!0,e.scrollIntoView({behavior:`smooth`,block:`start`}),T.current=n;return}}(p||E.current)&&!O.current&&S.current?.scrollIntoView({behavior:`smooth`}),T.current=n},[t,p,n]),(0,D.useEffect)(()=>{let e=C.current;if(!e)return;let t=()=>{let t=e.scrollTop;A.current&&t<k.current&&(E.current=!1),k.current=t,m(e.scrollHeight-e.scrollTop-e.clientHeight<80)};return e.addEventListener(`scroll`,t,{passive:!0}),t(),()=>e.removeEventListener(`scroll`,t)},[m]),(0,D.useEffect)(()=>{function e(){x(e=>{let t=new Set;return j.current.forEach((n,r)=>{n.isConnected&&(h.has(r)?e.has(r)&&t.add(r):n.scrollHeight>n.clientHeight+2&&t.add(r))}),e.size===t.size&&[...e].every(e=>t.has(e))?e:t})}e();let t=new ResizeObserver(e);return j.current.forEach(e=>t.observe(e)),()=>t.disconnect()},[t.length,h]);let M=t.reduce((e,t,n)=>t.role===`maxy`&&!t.hidden?n:e,-1);return(0,R.jsxs)(`div`,{className:`chat-messages-wrap`,children:[o&&(0,R.jsx)(`div`,{className:`selection-overlay-band`}),(0,R.jsxs)(`div`,{className:`chat-messages`,ref:C,children:[a&&t.length===0&&(0,R.jsx)(`div`,{className:`session-error`,children:(0,R.jsx)(`p`,{children:a})}),t.map((a,d)=>{if(a.hidden)return null;let f=n&&d===t.length-1,p=`${a.timestamp}_${a.role}`,m=s.has(p);return(0,R.jsxs)(`div`,{ref:d===M?w:void 0,className:`message ${a.role}${m?` selected`:``}`,children:[o&&!f&&(0,R.jsx)(`div`,{className:`message-select-check`,children:(0,R.jsx)(c,{checked:m,onChange:()=>l(p)})}),(0,R.jsxs)(`div`,{className:`bubble`,children:[a.role===`visitor`&&a.content?(()=>{let e=h.has(d),t=y.has(d);return(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`div`,{ref:e=>{e?j.current.set(d,e):j.current.delete(d)},className:e?`bubble-content`:`bubble-content clamped${t?` overflowing`:``}`,children:a.content}),t&&(0,R.jsx)(`div`,{className:`bubble-expand`,children:(0,R.jsx)(b,{variant:`icon`,className:e?`expanded`:``,onClick:()=>g(e=>{let t=new Set(e);return t.has(d)?t.delete(d):t.add(d),t}),"aria-label":e?`Collapse message`:`Expand message`,children:(0,R.jsx)(i,{size:14})})})]})})():a.content?(0,R.jsx)(v,{content:a.content,timestamp:_(a.timestamp)}):(0,R.jsxs)(`span`,{className:`typing-indicator`,children:[(0,R.jsx)(`span`,{className:`typing-dot`}),(0,R.jsx)(`span`,{className:`typing-dot`}),(0,R.jsx)(`span`,{className:`typing-dot`})]}),a.attachments&&a.attachments.length>0&&(0,R.jsx)(`div`,{className:`message-attachments`,children:a.attachments.map((t,n)=>(0,R.jsxs)(`span`,{className:`message-attachment-chip no-action`,children:[t.mimeType===`application/pdf`?(0,R.jsx)(r,{size:12}):t.mimeType.startsWith(`text/`)?(0,R.jsx)(e,{size:12}):null,(0,R.jsx)(`span`,{children:t.filename})]},n))}),a.role===`visitor`&&(0,R.jsx)(`span`,{className:`message-timestamp`,children:_(a.timestamp)})]}),a.role===`maxy`&&a.components&&a.components.length>0&&(0,R.jsx)(`div`,{className:`public-components`,children:a.components.map((e,t)=>(0,R.jsx)(`div`,{className:`public-component-enter`,children:(0,R.jsx)(H,{name:e.name,data:e.data,onSubmit:e=>u(d,t,e),submitted:e.submitted})},t))})]},d)}),!n&&d.length>0&&(0,R.jsx)(`div`,{className:`chat-suggestions`,children:d.map(e=>(0,R.jsx)(b,{variant:`suggestion`,onClick:()=>f(e),children:e},e))}),(0,R.jsx)(`div`,{ref:S})]}),!p&&(0,R.jsx)(`button`,{className:`scroll-to-bottom`,onClick:()=>S.current?.scrollIntoView({behavior:`smooth`}),"aria-label":`Scroll to bottom`,children:(0,R.jsx)(i,{size:18})})]})}function W({selectedItems:e,messages:t,copySelected:n,exitSelection:r,showCopyToast:i}){let[a,o]=(0,D.useState)(!1),s=(0,D.useRef)(null),c=(0,D.useRef)(!1);function l(e){let n=e.lastIndexOf(`_`),r=e.slice(0,n),i=e.slice(n+1),a=parseInt(r,10);return t.find(e=>e.timestamp===a&&e.role===i)?.content??``}function u(e,t){return parseInt(e.slice(0,e.lastIndexOf(`_`)),10)-parseInt(t.slice(0,t.lastIndexOf(`_`)),10)}function d(){let e=[...t].sort((e,t)=>e.timestamp-t.timestamp),n=[];for(let t of e){if(t.hidden||!t.content)continue;let e=t.role===`visitor`?`Visitor`:`Maxy`;n.push(`${e}:\n${t.content}`)}return n.join(`
1
+ import{C as e,D as t,E as n,S as r,T as i,_ as a,a as o,b as s,d as c,f as l,h as u,i as d,j as f,k as p,m,n as h,p as g,r as _,s as v,t as y,u as b,v as x,w as S,x as C,y as w}from"./ChatInput-Bo9T8v0E.js";var T=n(`square-plus`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M8 12h8`,key:`1wcyev`}],[`path`,{d:`M12 8v8`,key:`napkw2`}]]),E=t(),D=f(p(),1),O=`image/jpeg,image/png,image/gif,image/webp,application/pdf,text/plain,text/markdown,text/csv,text/html`,k=new Set(O.split(`,`)),A=20*1024*1024,j=typeof window<`u`&&/^(localhost|127\.0\.0\.1|[a-z0-9-]+\.local)(:|$)/.test(window.location.hostname);function M(){let e=crypto.getRandomValues(new Uint8Array(16));e[6]=e[6]&15|64,e[8]=e[8]&63|128;let t=[...e].map(e=>e.toString(16).padStart(2,`0`)).join(``);return`${t.slice(0,8)}-${t.slice(8,12)}-${t.slice(12,16)}-${t.slice(16,20)}-${t.slice(20)}`}function N(){let e=window.location.pathname.match(/^\/([a-z][a-z0-9-]{2,49})$/);return e?e[1]:void 0}function P(e){return[{key:`length`,label:`At least 8 characters`,met:e.length>=8},{key:`number`,label:`Contains a number`,met:/\d/.test(e)},{key:`special`,label:`Contains a special character`,met:/[^A-Za-z0-9]/.test(e)},{key:`whitespace`,label:`No leading or trailing spaces`,met:e.length>0&&e===e.trim()}]}function F(e,t){if(t===`phone`)return e.length>4?e.slice(0,e.length-4).replace(/\d/g,`•`)+` `+e.slice(-4):e;let n=e.indexOf(`@`);return n<=2?e:e.slice(0,2)+`•••`+e.slice(n)}function I(e){let[t,n]=(0,D.useState)(null),[r,i]=(0,D.useState)(null),[a,o]=(0,D.useState)(`loading`),[s,c]=(0,D.useState)(``),[l,u]=(0,D.useState)(null),[d,f]=(0,D.useState)(null),[p,m]=(0,D.useState)(!1),[h,g]=(0,D.useState)(null),_=(0,D.useMemo)(()=>N(),[]),v=(0,D.useRef)(_||``),y=(0,D.useRef)(null),b=(0,D.useRef)(null),x=(0,D.useRef)(!1),S=(0,D.useRef)(null),[C,w]=(0,D.useState)(`sign-in`),[T,E]=(0,D.useState)(null),O=(0,D.useRef)(null),k=(0,D.useRef)(null);(0,D.useEffect)(()=>{try{let e=sessionStorage.getItem(`maxy_session`);e&&(k.current=e)}catch{}},[]);let A=(0,D.useCallback)(t=>{y.current=t,n(t);try{sessionStorage.setItem(`maxy_session`,t)}catch{}o(`chat`),e(t)},[e]),P=(0,D.useCallback)(()=>{y.current=null;try{sessionStorage.removeItem(`maxy_session`)}catch{}n(null),o(`auth-required`),w(`sign-in`)},[]),F=(0,D.useCallback)(async e=>{try{let t=v.current,n=await fetch(`/api/access/verify-token`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({token:e,agentSlug:t})}),r=await n.json();n.ok?(O.current=r.session_key,E(r.grant),w(`set-password`),window.history.replaceState({},``,window.location.pathname)):w(`link-expired`)}catch{w(`sign-in`)}},[]),I=(0,D.useCallback)(async()=>{if(y.current)return y.current;if(b.current)return b.current;let e=(async()=>{try{let e=k.current,t=await fetch(`/api/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({session_id:M(),..._?{agent:_}:{},...e?{session_key:e}:{}})});if(!t.ok){let e=await t.json().catch(()=>({error:``}));return j&&console.error(`[session] POST /api/session failed: ${t.status} ${t.statusText}`,e),t.status===404?i(e.error||`Agent not found`):t.status===503&&i(e.error||`Service unavailable`),null}let r=await t.json();if(r.auth_required){r.agent_id&&(v.current=r.agent_id),c(r.displayName||``),r.agentImage&&u(r.agentImage),r.agentImageShape&&f(r.agentImageShape),r.showAgentName&&m(r.showAgentName),r.branding&&g(r.branding),o(`auth-required`);let e=new URLSearchParams(window.location.search).get(`token`);return e?F(e):w(`sign-in`),null}y.current=r.session_key,n(r.session_key),r.displayName&&c(r.displayName),r.agentImage&&u(r.agentImage),r.agentImageShape&&f(r.agentImageShape),r.showAgentName&&m(r.showAgentName),r.branding&&g(r.branding),o(`chat`),r.resumed&&r.messages&&(x.current=!0,S.current=r.messages);try{sessionStorage.setItem(`maxy_session`,r.session_key)}catch{}return r.session_key}catch(e){return j&&console.error(`[session] fetch /api/session threw:`,e),i(`Unable to connect. Please check your connection and try again.`),null}finally{b.current=null}})();return b.current=e,e},[_,F]);return{sessionId:t,sessionKeyRef:y,sessionError:r,pageState:a,setPageState:o,agentDisplayName:s,agentImage:l,agentImageShape:d,showAgentName:p,agentSlug:_,branding:h,resolvedSlugRef:v,ensureSession:I,startNewSession:(0,D.useCallback)(async()=>{y.current=null,b.current=null,k.current=null,x.current=!1,S.current=null,n(null),i(null);try{sessionStorage.removeItem(`maxy_session`)}catch{}let t=await I();t&&e(t)},[I,e]),enterChat:A,enterGate:P,resumedRef:x,resumeMessagesRef:S,gateState:C,setGateState:w,grantInfo:T,setGrantInfo:E,gateSessionKeyRef:O}}function L({sessionKeyRef:e,ensureSession:t,sessionError:n,pageState:r,inputRef:i}){let[o,s]=(0,D.useState)([]),[c,l]=(0,D.useState)(!1),u=(0,D.useRef)(!1),d=e=>{u.current=e,l(e)},f=(0,D.useCallback)(async o=>{if(!u.current){d(!0),s([{role:`maxy`,content:``,timestamp:Date.now()}]);try{let n=await fetch(`/api/chat`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({greeting:!0,session_key:o})});if(n.status===401){e.current=null;try{sessionStorage.removeItem(`maxy_session`)}catch{}j&&console.warn(`[greeting] stale session, retrying with fresh session`);let r=await t();if(!r)return;n=await fetch(`/api/chat`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({greeting:!0,session_key:r})})}if(!n.ok){let e=await n.json().catch(()=>({}));throw Error(e.error||`Something went wrong`)}let r=``,i=``,c=()=>{i&&(r+=i,i=``,s(e=>{let t=[...e];return t[0]={...t[0],content:r},t}))},l=setInterval(c,60);try{for await(let e of a(n)){if(e.error)throw Object.assign(Error(e.error),{fromSSE:!0});e.text&&(i+=e.text),e.type===`component`&&(c(),s(t=>{let n=[...t],r={...n[0]},i=[...r.components||[]];return i.push({name:e.name,data:e.data,submitted:!1}),n[0]={...r,components:i},n}))}}finally{clearInterval(l),c()}}catch(e){if(j&&console.error(`[chat] greeting failed:`,e),r===`auth-required`)return;let t=e instanceof Error?e.message:String(e);s([{role:`maxy`,content:e instanceof Error&&e.fromSSE?t:n??`I'm having trouble connecting right now. Try refreshing the page.`,timestamp:Date.now()}])}finally{d(!1),r===`chat`&&i.current?.focus()}}},[e,t,n,r,i]),p=(0,D.useCallback)(async(o,c)=>{let l=c?.hidden??!1,f=c?.files??[];if(!o&&f.length===0||u.current)return;d(!0);let p=f.map(e=>({filename:e.name,mimeType:e.type})),m={role:`visitor`,content:o,attachments:p.length>0?p:void 0,timestamp:Date.now(),hidden:l},h;s(e=>{let t=[...e,m,{role:`maxy`,content:``,timestamp:Date.now()}];return h=t.length-1,t});try{let n=await t();if(!n)throw Error(`session`);let r=e=>{if(f.length>0){let t=new FormData;t.append(`message`,o),t.append(`session_key`,e);for(let e of f)t.append(`attachments`,e);return{body:t,headers:{}}}return{body:JSON.stringify({message:o,session_key:e}),headers:{"Content-Type":`application/json`}}},{body:i,headers:c}=r(n),l=await fetch(`/api/chat`,{method:`POST`,headers:c,body:i});if(l.status===401){e.current=null;try{sessionStorage.removeItem(`maxy_session`)}catch{}j&&console.warn(`[session-expired] stale key cleared, retrying with fresh session`);let n=await t();if(!n)throw Error(`session`);({body:i,headers:c}=r(n)),l=await fetch(`/api/chat`,{method:`POST`,headers:c,body:i})}if(!l.ok){let e=await l.json().catch(()=>({}));throw Error(e.error||`Something went wrong`)}let u=``,d=``,p=()=>{d&&(u+=d,d=``,s(e=>{let t=[...e];return t[h]={...t[h],content:u},t}))},m=setInterval(p,60);try{for await(let e of a(l)){if(e.error)throw Object.assign(Error(e.error),{fromSSE:!0});e.text&&(d+=e.text),e.type===`component`&&(p(),s(t=>{let n=[...t],r={...n[h]},i=[...r.components||[]];return i.push({name:e.name,data:e.data,submitted:!1}),n[h]={...r,components:i},n}))}}finally{clearInterval(m),p()}}catch(e){if(j&&console.error(`[chat] sendMessage failed:`,e),r===`auth-required`)return;let t=e instanceof Error?e.message:String(e),i=e instanceof Error&&e.fromSSE;s(e=>{let r=[...e];return r[h]={...r[h],content:i?t:t===`session`?n??`I'm having trouble connecting right now. Try refreshing the page.`:`Sorry, I hit a snag. Try again in a moment.`},r})}finally{d(!1),r===`chat`&&i.current?.focus()}},[e,t,n,r,i]);return{messages:o,setMessages:s,isStreaming:c,sendMessage:p,sendGreeting:f,handleComponentSubmit:(0,D.useCallback)((e,t,n)=>{s(n=>{let r=[...n],i={...r[e]},a=[...i.components||[]];return a[t]={...a[t],submitted:!0},r[e]={...i,components:a},r}),p(n,{hidden:!0})},[p])}}var R=l();function z({value:e,onChange:t,onComplete:n,disabled:r}){let i=(0,D.useRef)([]);function a(n,r){r.key===`Backspace`?(r.preventDefault(),e[n]?t(e.slice(0,n)+e.slice(n+1)):n>0&&(t(e.slice(0,n-1)+e.slice(n)),i.current[n-1]?.focus())):r.key===`ArrowLeft`&&n>0?i.current[n-1]?.focus():r.key===`ArrowRight`&&n<5&&i.current[n+1]?.focus()}function o(r,a){let o=a.nativeEvent.data;if(!o||!/^\d$/.test(o))return;let s=e.split(``);for(s[r]=o;s.length<r;)s.push(``);let c=s.join(``).replace(/\D/g,``).slice(0,6);t(c),c.length===6?n(c):r<5&&i.current[r+1]?.focus()}function s(e){e.preventDefault();let r=e.clipboardData.getData(`text`).replace(/\D/g,``).slice(0,6);r&&(t(r),r.length===6?n(r):i.current[r.length]?.focus())}return(0,R.jsx)(`div`,{className:`gate-otp-field`,children:Array.from({length:6}).map((t,n)=>(0,R.jsx)(`input`,{ref:e=>{i.current[n]=e},type:`text`,inputMode:`numeric`,className:`pin-box${e[n]?` pin-box-filled`:``}`,value:e[n]||``,onKeyDown:e=>a(n,e),onInput:e=>o(n,e),onPaste:s,onFocus:e=>e.target.select(),autoFocus:n===0,autoComplete:`off`,maxLength:1,disabled:r,"aria-label":`Code digit ${n+1}`},n))})}function B({gateState:e,setGateState:t,grantInfo:n,setGrantInfo:r,gateSessionKeyRef:i,resolvedSlugRef:a,onAuthenticated:o}){let[s,l]=(0,D.useState)(``),[u,d]=(0,D.useState)(``),[f,p]=(0,D.useState)(``),[m,h]=(0,D.useState)(!1),[g,_]=(0,D.useState)(``),[v,y]=(0,D.useState)(``),[x,S]=(0,D.useState)(!1),[C,w]=(0,D.useState)(null),[T,E]=(0,D.useState)(null),[O,k]=(0,D.useState)(!1);async function A(e){if(e.preventDefault(),!O){w(null),k(!0);try{let e=a.current,n=await fetch(`/api/access/login`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({contact:s,password:u,agentSlug:e})}),i=await n.json();n.ok?o(i.session_key):n.status===401?i.error?.includes(`setup not complete`)||i.error?.includes(`invitation link`)?(t(`private-agent`),w(null)):w(i.error||`Invalid credentials`):n.status===403?(t(`access-expired`),i.expiresAt&&r(e=>e?{...e,expiresAt:i.expiresAt}:{displayName:null,contactValue:s,contactMethod:`email`,expiresAt:i.expiresAt,status:`expired`})):n.status===429?w(i.error||`Too many attempts. Please try again later.`):w(i.error||`Something went wrong`)}catch{w(`Unable to connect. Please try again.`)}finally{k(!1)}}}async function j(e){if(!O){w(null),k(!0);try{let n=a.current,o=await fetch(`/api/access/verify-otp`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({phone:v,code:e,agentSlug:n})}),s=await o.json();o.ok?(i.current=s.session_key,r(s.grant),t(`set-password`)):o.status===429?t(`otp-failed`):(w(s.error||`Invalid code`),_(``))}catch{w(`Unable to connect. Please try again.`)}finally{k(!1)}}}async function M(e){if(e.preventDefault(),!O){if(w(null),u!==f){w(`Passwords do not match`);return}if(!P(u).every(e=>e.met)){w(`Password does not meet requirements`);return}k(!0);try{let e=i.current;if(!e){w(`Session expired. Please use your invitation link again.`);return}let t=await fetch(`/api/access/create-credentials`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({session_key:e,password:u})}),n=await t.json();t.ok?o(n.session_key):t.status===400&&n.requirements?w(n.requirements.filter(e=>!e.met).map(e=>e.label).join(`, `)):w(n.error||`Something went wrong`)}catch{w(`Unable to connect. Please try again.`)}finally{k(!1)}}}async function N(e){if(e.preventDefault(),!(O||!s)){w(null),k(!0);try{let e=a.current,t=await fetch(`/api/access/forgot-password`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({contact:s,agentSlug:e})});t.status===429?w((await t.json()).error||`Too many attempts. Please try again later.`):(E(`If an account exists, a reset link has been sent.`),setTimeout(()=>{S(!1),E(null)},4e3))}catch{w(`Unable to connect. Please try again.`)}finally{k(!1)}}}switch(e){case`set-password`:{let e=P(u),t=e.every(e=>e.met),r=u===f,i=t&&r&&f.length>0;return(0,R.jsx)(`div`,{className:`gate-wrap`,children:(0,R.jsxs)(`div`,{className:`gate-card`,children:[n?.expiresAt&&(0,R.jsxs)(`div`,{className:`gate-expiry-badge`,children:[`Access until `,new Date(n.expiresAt).toLocaleDateString(`en-GB`,{day:`numeric`,month:`short`,year:`numeric`})]}),(0,R.jsxs)(`h2`,{className:`gate-title`,children:[`Welcome, `,n?.displayName||`there`]}),(0,R.jsx)(`p`,{className:`gate-subtitle`,children:`Create a password to access this agent in the future.`}),(0,R.jsxs)(`form`,{className:`gate-form`,onSubmit:M,children:[(0,R.jsxs)(`div`,{className:`gate-field`,children:[(0,R.jsx)(`label`,{htmlFor:`gate-display-name`,children:`Display name`}),(0,R.jsx)(`input`,{id:`gate-display-name`,type:`text`,value:n?.displayName||``,disabled:!0})]}),(0,R.jsxs)(`div`,{className:`gate-field gate-pw-row`,children:[(0,R.jsx)(`label`,{htmlFor:`gate-pw`,children:`Password`}),(0,R.jsx)(`div`,{className:`gate-pw-toggle`,children:(0,R.jsx)(c,{checked:m,onChange:h,label:`Show`})}),(0,R.jsx)(`input`,{id:`gate-pw`,type:m?`text`:`password`,value:u,onChange:e=>d(e.target.value),placeholder:`Your password`,autoFocus:!0,autoComplete:`new-password`}),u.length>0&&(0,R.jsx)(`div`,{className:`gate-strength`,children:e.map(e=>(0,R.jsxs)(`span`,{className:`gate-strength-item${e.met?` met`:``}`,children:[e.met?`✓`:`○`,` `,e.label]},e.key))})]}),(0,R.jsxs)(`div`,{className:`gate-field`,children:[(0,R.jsx)(`label`,{htmlFor:`gate-pw-confirm`,children:`Confirm password`}),(0,R.jsx)(`input`,{id:`gate-pw-confirm`,type:m?`text`:`password`,value:f,onChange:e=>p(e.target.value),placeholder:`Confirm your password`,autoComplete:`new-password`}),f.length>0&&!r&&(0,R.jsx)(`div`,{className:`gate-error`,children:`Passwords do not match`})]}),C&&(0,R.jsx)(`div`,{className:`gate-error`,children:C}),(0,R.jsx)(`div`,{className:`gate-submit`,children:(0,R.jsx)(b,{variant:`primary`,type:`submit`,fullWidth:!0,disabled:!i||O,loading:O,children:`Create account & enter chat`})})]})]})})}case`enter-otp`:return(0,R.jsx)(`div`,{className:`gate-wrap`,children:(0,R.jsxs)(`div`,{className:`gate-card`,children:[(0,R.jsx)(`h2`,{className:`gate-title`,children:`Enter your code`}),(0,R.jsxs)(`p`,{className:`gate-subtitle`,children:[`Enter the 6-digit code sent to `,F(v,`phone`)]}),(0,R.jsx)(z,{value:g,onChange:_,onComplete:j,disabled:O}),C&&(0,R.jsx)(`div`,{className:`gate-error`,children:C}),O&&(0,R.jsxs)(`div`,{className:`gate-loading`,children:[(0,R.jsx)(`span`,{className:`spinner`}),`Verifying...`]}),(0,R.jsx)(`div`,{className:`gate-resend`,children:(0,R.jsx)(`button`,{type:`button`,className:`gate-link`,onClick:()=>{t(`sign-in`),_(``),w(null)},children:`Use a different number`})})]})});case`sign-in`:case`private-agent`:return(0,R.jsx)(`div`,{className:`gate-wrap`,children:(0,R.jsxs)(`div`,{className:`gate-card`,children:[(0,R.jsx)(`h2`,{className:`gate-title`,children:e===`private-agent`?`Private Agent`:`Welcome back`}),(0,R.jsx)(`p`,{className:`gate-subtitle`,children:e===`private-agent`?`This agent is invitation-only. If you have an account, sign in below.`:`Sign in to continue your conversation.`}),x?(0,R.jsxs)(`form`,{className:`gate-form`,onSubmit:N,children:[(0,R.jsxs)(`div`,{className:`gate-field`,children:[(0,R.jsx)(`label`,{htmlFor:`gate-forgot-contact`,children:`Email or phone`}),(0,R.jsx)(`input`,{id:`gate-forgot-contact`,type:`text`,value:s,onChange:e=>l(e.target.value),placeholder:`you@example.com`,autoFocus:!0,autoComplete:`email`})]}),C&&(0,R.jsx)(`div`,{className:`gate-error`,children:C}),T&&(0,R.jsx)(`div`,{className:`gate-success`,children:T}),(0,R.jsx)(`div`,{className:`gate-submit`,children:(0,R.jsx)(b,{variant:`primary`,type:`submit`,fullWidth:!0,disabled:!s.trim()||O,loading:O,children:`Send reset link`})}),(0,R.jsx)(`div`,{className:`gate-actions`,children:(0,R.jsx)(`button`,{type:`button`,className:`gate-link`,onClick:()=>{S(!1),w(null),E(null)},children:`Back to sign in`})})]}):(0,R.jsxs)(`form`,{className:`gate-form`,onSubmit:A,children:[(0,R.jsxs)(`div`,{className:`gate-field`,children:[(0,R.jsx)(`label`,{htmlFor:`gate-contact`,children:`Email or phone`}),(0,R.jsx)(`input`,{id:`gate-contact`,type:`text`,value:s,onChange:e=>l(e.target.value),placeholder:`you@example.com`,autoFocus:!0,autoComplete:`email`})]}),(0,R.jsxs)(`div`,{className:`gate-field gate-pw-row`,children:[(0,R.jsx)(`label`,{htmlFor:`gate-login-pw`,children:`Password`}),(0,R.jsx)(`div`,{className:`gate-pw-toggle`,children:(0,R.jsx)(c,{checked:m,onChange:h,label:`Show`})}),(0,R.jsx)(`input`,{id:`gate-login-pw`,type:m?`text`:`password`,value:u,onChange:e=>d(e.target.value),placeholder:`Your password`,autoComplete:`current-password`})]}),C&&(0,R.jsx)(`div`,{className:`gate-error`,children:C}),(0,R.jsx)(`div`,{className:`gate-submit`,children:(0,R.jsx)(b,{variant:`primary`,type:`submit`,fullWidth:!0,disabled:!s.trim()||!u||O,loading:O,children:`Sign in`})}),(0,R.jsx)(`div`,{className:`gate-actions`,children:(0,R.jsx)(`button`,{type:`button`,className:`gate-link`,onClick:()=>{S(!0),w(null)},children:`Forgot password?`})})]}),e===`private-agent`&&(0,R.jsx)(`p`,{className:`gate-hint`,children:`No account? You need an invitation from the agent owner.`})]})});case`access-expired`:return(0,R.jsx)(`div`,{className:`gate-wrap`,children:(0,R.jsxs)(`div`,{className:`gate-card`,children:[(0,R.jsx)(`div`,{className:`gate-icon`,children:`⏰`}),(0,R.jsx)(`h2`,{className:`gate-title`,children:`Access expired`}),(0,R.jsxs)(`p`,{className:`gate-subtitle`,children:[n?.expiresAt?`Your access expired on ${new Date(n.expiresAt).toLocaleDateString(`en-GB`,{day:`numeric`,month:`long`,year:`numeric`})}.`:`Your access to this agent has expired.`,` `,`Contact the agent owner to renew.`]}),(0,R.jsx)(`div`,{className:`gate-actions`,children:(0,R.jsx)(b,{variant:`secondary`,onClick:()=>{t(`sign-in`),w(null),d(``)},children:`Sign in with a different account`})})]})});case`link-expired`:return(0,R.jsx)(`div`,{className:`gate-wrap`,children:(0,R.jsxs)(`div`,{className:`gate-card`,children:[(0,R.jsx)(`div`,{className:`gate-icon`,children:`⚠️`}),(0,R.jsx)(`h2`,{className:`gate-title`,children:`Link expired`}),(0,R.jsx)(`p`,{className:`gate-subtitle`,children:`This invitation link has expired or has already been used. If you already set your password, sign in below. Otherwise, ask the agent owner to send a new invitation.`}),(0,R.jsx)(`div`,{className:`gate-actions`,children:(0,R.jsx)(b,{variant:`primary`,onClick:()=>{t(`sign-in`),w(null)},children:`Go to sign in`})})]})});case`otp-failed`:return(0,R.jsx)(`div`,{className:`gate-wrap`,children:(0,R.jsxs)(`div`,{className:`gate-card`,children:[(0,R.jsx)(`div`,{className:`gate-icon`,children:`⛔`}),(0,R.jsx)(`h2`,{className:`gate-title`,children:`Too many attempts`}),(0,R.jsx)(`p`,{className:`gate-subtitle`,children:`You've entered the wrong code too many times. Ask the agent owner to send a new code.`}),(0,R.jsx)(`div`,{className:`gate-actions`,children:(0,R.jsx)(b,{variant:`secondary`,onClick:()=>{t(`sign-in`),w(null),_(``)},children:`Back to sign in`})})]})})}}var V={"single-select":o,"multi-select":d};function H({name:e,data:t,onSubmit:n,submitted:r}){let i=V[e];return i?(0,R.jsx)(i,{data:t,onSubmit:n,submitted:r}):(console.warn(`[PublicComponentRenderer] Unknown component: "${e}". Registered: ${Object.keys(V).join(`, `)}`),(0,R.jsx)(`div`,{className:`component-card component-card--error`,children:(0,R.jsxs)(`p`,{style:{fontFamily:`var(--font-body)`,fontSize:12,color:`var(--text-secondary)`},children:[`Component “`,e,`” is not available. This may require a platform update.`]})}))}function U({messages:t,isStreaming:n,sessionError:a,selectionMode:o,selectedItems:s,toggleSelectItem:l,onComponentSubmit:u,remainingSuggestions:d,onSuggestionClick:f,isAtBottom:p,setIsAtBottom:m}){let[h,g]=(0,D.useState)(new Set),[y,x]=(0,D.useState)(new Set),S=(0,D.useRef)(null),C=(0,D.useRef)(null),w=(0,D.useRef)(null),T=(0,D.useRef)(!1),E=(0,D.useRef)(!1),O=(0,D.useRef)(!1),k=(0,D.useRef)(0),A=(0,D.useRef)(!1),j=(0,D.useRef)(new Map);A.current=n,(0,D.useEffect)(()=>{n&&!T.current&&p&&(E.current=!0)},[n,p]),(0,D.useEffect)(()=>{if(!E.current&&!p){T.current=n,O.current=!1;return}if(T.current&&!n&&w.current&&C.current){let e=w.current;if(e.offsetHeight>C.current.clientHeight){E.current=!1,O.current=!0,e.scrollIntoView({behavior:`smooth`,block:`start`}),T.current=n;return}}(p||E.current)&&!O.current&&S.current?.scrollIntoView({behavior:`smooth`}),T.current=n},[t,p,n]),(0,D.useEffect)(()=>{let e=C.current;if(!e)return;let t=()=>{let t=e.scrollTop;A.current&&t<k.current&&(E.current=!1),k.current=t,m(e.scrollHeight-e.scrollTop-e.clientHeight<80)};return e.addEventListener(`scroll`,t,{passive:!0}),t(),()=>e.removeEventListener(`scroll`,t)},[m]),(0,D.useEffect)(()=>{function e(){x(e=>{let t=new Set;return j.current.forEach((n,r)=>{n.isConnected&&(h.has(r)?e.has(r)&&t.add(r):n.scrollHeight>n.clientHeight+2&&t.add(r))}),e.size===t.size&&[...e].every(e=>t.has(e))?e:t})}e();let t=new ResizeObserver(e);return j.current.forEach(e=>t.observe(e)),()=>t.disconnect()},[t.length,h]);let M=t.reduce((e,t,n)=>t.role===`maxy`&&!t.hidden?n:e,-1);return(0,R.jsxs)(`div`,{className:`chat-messages-wrap`,children:[o&&(0,R.jsx)(`div`,{className:`selection-overlay-band`}),(0,R.jsxs)(`div`,{className:`chat-messages`,ref:C,children:[a&&t.length===0&&(0,R.jsx)(`div`,{className:`session-error`,children:(0,R.jsx)(`p`,{children:a})}),t.map((a,d)=>{if(a.hidden)return null;let f=n&&d===t.length-1,p=`${a.timestamp}_${a.role}`,m=s.has(p);return(0,R.jsxs)(`div`,{ref:d===M?w:void 0,className:`message ${a.role}${m?` selected`:``}`,children:[o&&!f&&(0,R.jsx)(`div`,{className:`message-select-check`,children:(0,R.jsx)(c,{checked:m,onChange:()=>l(p)})}),(0,R.jsxs)(`div`,{className:`bubble`,children:[a.role===`visitor`&&a.content?(()=>{let e=h.has(d),t=y.has(d);return(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`div`,{ref:e=>{e?j.current.set(d,e):j.current.delete(d)},className:e?`bubble-content`:`bubble-content clamped${t?` overflowing`:``}`,children:a.content}),t&&(0,R.jsx)(`div`,{className:`bubble-expand`,children:(0,R.jsx)(b,{variant:`icon`,className:e?`expanded`:``,onClick:()=>g(e=>{let t=new Set(e);return t.has(d)?t.delete(d):t.add(d),t}),"aria-label":e?`Collapse message`:`Expand message`,children:(0,R.jsx)(i,{size:14})})})]})})():a.content?(0,R.jsx)(v,{content:a.content,timestamp:_(a.timestamp)}):(0,R.jsxs)(`span`,{className:`typing-indicator`,children:[(0,R.jsx)(`span`,{className:`typing-dot`}),(0,R.jsx)(`span`,{className:`typing-dot`}),(0,R.jsx)(`span`,{className:`typing-dot`})]}),a.attachments&&a.attachments.length>0&&(0,R.jsx)(`div`,{className:`message-attachments`,children:a.attachments.map((t,n)=>(0,R.jsxs)(`span`,{className:`message-attachment-chip no-action`,children:[t.mimeType===`application/pdf`?(0,R.jsx)(r,{size:12}):t.mimeType.startsWith(`text/`)?(0,R.jsx)(e,{size:12}):null,(0,R.jsx)(`span`,{children:t.filename})]},n))}),a.role===`visitor`&&(0,R.jsx)(`span`,{className:`message-timestamp`,children:_(a.timestamp)})]}),a.role===`maxy`&&a.components&&a.components.length>0&&(0,R.jsx)(`div`,{className:`public-components`,children:a.components.map((e,t)=>(0,R.jsx)(`div`,{className:`public-component-enter`,children:(0,R.jsx)(H,{name:e.name,data:e.data,onSubmit:e=>u(d,t,e),submitted:e.submitted})},t))})]},d)}),!n&&d.length>0&&(0,R.jsx)(`div`,{className:`chat-suggestions`,children:d.map(e=>(0,R.jsx)(b,{variant:`suggestion`,onClick:()=>f(e),children:e},e))}),(0,R.jsx)(`div`,{ref:S})]}),!p&&(0,R.jsx)(`button`,{className:`scroll-to-bottom`,onClick:()=>S.current?.scrollIntoView({behavior:`smooth`}),"aria-label":`Scroll to bottom`,children:(0,R.jsx)(i,{size:18})})]})}function W({selectedItems:e,messages:t,copySelected:n,exitSelection:r,showCopyToast:i}){let[a,o]=(0,D.useState)(!1),s=(0,D.useRef)(null),c=(0,D.useRef)(!1);function l(e){let n=e.lastIndexOf(`_`),r=e.slice(0,n),i=e.slice(n+1),a=parseInt(r,10);return t.find(e=>e.timestamp===a&&e.role===i)?.content??``}function u(e,t){return parseInt(e.slice(0,e.lastIndexOf(`_`)),10)-parseInt(t.slice(0,t.lastIndexOf(`_`)),10)}function d(){let e=[...t].sort((e,t)=>e.timestamp-t.timestamp),n=[];for(let t of e){if(t.hidden||!t.content)continue;let e=t.role===`visitor`?`Visitor`:`Maxy`;n.push(`${e}:\n${t.content}`)}return n.join(`
2
2
 
3
3
  ---
4
4
 
@@ -5,8 +5,8 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>Maxy</title>
7
7
  <link rel="icon" href="/favicon.ico">
8
- <script type="module" crossorigin src="/assets/admin-BSHc9LPS.js"></script>
9
- <link rel="modulepreload" crossorigin href="/assets/ChatInput-BbMvZgRR.js">
8
+ <script type="module" crossorigin src="/assets/admin-CkpknqK7.js"></script>
9
+ <link rel="modulepreload" crossorigin href="/assets/ChatInput-Bo9T8v0E.js">
10
10
  <link rel="stylesheet" crossorigin href="/assets/ChatInput-LydJYAYE.css">
11
11
  <link rel="stylesheet" href="/brand-defaults.css">
12
12
  </head>
@@ -5,8 +5,8 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>Maxy</title>
7
7
  <link rel="icon" href="/favicon.ico">
8
- <script type="module" crossorigin src="/assets/public-DvDzSq3r.js"></script>
9
- <link rel="modulepreload" crossorigin href="/assets/ChatInput-BbMvZgRR.js">
8
+ <script type="module" crossorigin src="/assets/public-wDhMuZDR.js"></script>
9
+ <link rel="modulepreload" crossorigin href="/assets/ChatInput-Bo9T8v0E.js">
10
10
  <link rel="stylesheet" crossorigin href="/assets/ChatInput-LydJYAYE.css">
11
11
  <link rel="stylesheet" href="/brand-defaults.css">
12
12
  </head>
@@ -3258,8 +3258,8 @@ async function GET() {
3258
3258
  // app/lib/claude-agent.ts
3259
3259
  import Anthropic from "@anthropic-ai/sdk";
3260
3260
  import { spawn as spawn2 } from "child_process";
3261
- import { resolve as resolve5 } from "path";
3262
- import { readFileSync as readFileSync5, readdirSync, existsSync as existsSync6, mkdirSync as mkdirSync3, createWriteStream, statSync as statSync2, unlinkSync } from "fs";
3261
+ import { resolve as resolve5, join as join4 } from "path";
3262
+ import { readFileSync as readFileSync5, readdirSync, existsSync as existsSync6, mkdirSync as mkdirSync3, createWriteStream, statSync as statSync2, unlinkSync, cpSync } from "fs";
3263
3263
 
3264
3264
  // app/lib/vnc.ts
3265
3265
  import { spawnSync, execFileSync } from "child_process";
@@ -4703,6 +4703,90 @@ function parsePluginFrontmatter(pluginDir) {
4703
4703
  platform
4704
4704
  };
4705
4705
  }
4706
+ function autoDeliverPremiumPlugins(purchasedPlugins) {
4707
+ if (!purchasedPlugins || purchasedPlugins.length === 0) return;
4708
+ const TAG14 = "[premium-auto-deliver]";
4709
+ const stagingRoot = resolve5(PLATFORM_ROOT4, "../premium-plugins");
4710
+ const pluginsDir = resolve5(PLATFORM_ROOT4, "plugins");
4711
+ if (!existsSync6(stagingRoot)) {
4712
+ console.log(`${TAG14} no staging directory \u2014 skipping`);
4713
+ return;
4714
+ }
4715
+ for (const pluginName of purchasedPlugins) {
4716
+ const stagingDir = resolve5(stagingRoot, pluginName);
4717
+ if (!existsSync6(stagingDir)) {
4718
+ console.log(`${TAG14} ${pluginName}: not in staging \u2014 skipping`);
4719
+ continue;
4720
+ }
4721
+ const bundlePath = join4(stagingDir, "BUNDLE.md");
4722
+ const isBundle = existsSync6(bundlePath);
4723
+ if (isBundle) {
4724
+ let bundleRaw;
4725
+ try {
4726
+ bundleRaw = readFileSync5(bundlePath, "utf-8");
4727
+ } catch (err) {
4728
+ console.log(`${TAG14} ${pluginName}: cannot read BUNDLE.md \u2014 ${err instanceof Error ? err.message : String(err)}`);
4729
+ continue;
4730
+ }
4731
+ const fmMatch = bundleRaw.match(/^---\n([\s\S]*?)\n---/);
4732
+ const subPlugins = [];
4733
+ if (fmMatch) {
4734
+ let inPlugins = false;
4735
+ for (const line of fmMatch[1].split("\n")) {
4736
+ if (/^plugins:/.test(line)) {
4737
+ inPlugins = true;
4738
+ continue;
4739
+ }
4740
+ if (inPlugins) {
4741
+ const m = line.match(/^\s+- (.+)/);
4742
+ if (m) {
4743
+ subPlugins.push(m[1].trim());
4744
+ } else {
4745
+ break;
4746
+ }
4747
+ }
4748
+ }
4749
+ }
4750
+ if (subPlugins.length === 0) {
4751
+ console.log(`${TAG14} ${pluginName}: BUNDLE.md has no plugins list \u2014 skipping`);
4752
+ continue;
4753
+ }
4754
+ let delivered = 0;
4755
+ let skipped = 0;
4756
+ for (const sub of subPlugins) {
4757
+ const target = resolve5(pluginsDir, sub);
4758
+ if (existsSync6(resolve5(target, "PLUGIN.md"))) {
4759
+ skipped++;
4760
+ continue;
4761
+ }
4762
+ const source = resolve5(stagingDir, "plugins", sub);
4763
+ if (!existsSync6(source)) {
4764
+ console.log(`${TAG14} ${pluginName}/${sub}: source missing in staging \u2014 skipping`);
4765
+ continue;
4766
+ }
4767
+ try {
4768
+ cpSync(source, target, { recursive: true });
4769
+ delivered++;
4770
+ } catch (err) {
4771
+ console.log(`${TAG14} ${pluginName}/${sub}: copy failed \u2014 ${err instanceof Error ? err.message : String(err)}`);
4772
+ }
4773
+ }
4774
+ console.log(`${TAG14} ${pluginName} (bundle): ${delivered} delivered, ${skipped} already present`);
4775
+ } else {
4776
+ const target = resolve5(pluginsDir, pluginName);
4777
+ if (existsSync6(resolve5(target, "PLUGIN.md"))) {
4778
+ console.log(`${TAG14} ${pluginName}: already present \u2014 skipping`);
4779
+ continue;
4780
+ }
4781
+ try {
4782
+ cpSync(stagingDir, target, { recursive: true });
4783
+ console.log(`${TAG14} ${pluginName} (standalone): delivered`);
4784
+ } catch (err) {
4785
+ console.log(`${TAG14} ${pluginName}: copy failed \u2014 ${err instanceof Error ? err.message : String(err)}`);
4786
+ }
4787
+ }
4788
+ }
4789
+ }
4706
4790
  function assemblePublicPluginContent(pluginDir) {
4707
4791
  const pluginRoot = resolve5(PLATFORM_ROOT4, "plugins", pluginDir);
4708
4792
  const pluginPath = resolve5(pluginRoot, "PLUGIN.md");
@@ -7457,6 +7541,9 @@ ${soul}` : identityPrompt;
7457
7541
  ${isoTimestamp}
7458
7542
  ${humanReadable} (${effectiveTimezone})
7459
7543
  </datetime>`;
7544
+ if (agentType === "admin") {
7545
+ autoDeliverPremiumPlugins(account.config.purchasedPlugins);
7546
+ }
7460
7547
  if (agentType === "admin") {
7461
7548
  if (sessionUserId) {
7462
7549
  baseSystemPrompt += `
@@ -1,54 +0,0 @@
1
- import {
2
- aggregateAcrossTeams,
3
- formatAggregationResult,
4
- loopGet,
5
- } from "../lib/loop-api.js";
6
-
7
- interface LoopFeedback {
8
- id?: string;
9
- propertyAddress?: string;
10
- viewingDate?: string;
11
- feedback?: string;
12
- rating?: number;
13
- attendeeName?: string;
14
- status?: string;
15
- [key: string]: unknown;
16
- }
17
-
18
- export async function feedbackList(params: {
19
- accountId: string;
20
- teamName?: string;
21
- limit?: number;
22
- }): Promise<string> {
23
- const { accountId, teamName, limit } = params;
24
-
25
- const result = await aggregateAcrossTeams<LoopFeedback>(
26
- accountId,
27
- "feedback",
28
- "loop-feedback-list",
29
- async (apiKey, team) => {
30
- const data = await loopGet<LoopFeedback[]>(
31
- apiKey,
32
- "/feedback",
33
- "loop-feedback-list",
34
- team
35
- );
36
- return Array.isArray(data) ? data : [];
37
- },
38
- { teamName, limitPerTeam: limit ?? 50, limitTotal: limit ?? 200 }
39
- );
40
-
41
- return formatAggregationResult(
42
- result,
43
- (f) => {
44
- const addr = f.propertyAddress ?? "Unknown property";
45
- const date = f.viewingDate ?? "";
46
- const attendee = f.attendeeName ? ` (${f.attendeeName})` : "";
47
- const rating = f.rating != null ? ` ★${f.rating}` : "";
48
- const text = f.feedback ? `: "${f.feedback}"` : "";
49
- const status = f.status ? ` [${f.status}]` : "";
50
- return `- ${addr} ${date}${attendee}${rating}${status}${text}`;
51
- },
52
- "feedback"
53
- );
54
- }
@@ -1,52 +0,0 @@
1
- import {
2
- aggregateAcrossTeams,
3
- formatAggregationResult,
4
- loopGet,
5
- } from "../lib/loop-api.js";
6
-
7
- interface LoopPerson {
8
- id?: string;
9
- firstName?: string;
10
- lastName?: string;
11
- email?: string;
12
- phone?: string;
13
- type?: string;
14
- [key: string]: unknown;
15
- }
16
-
17
- export async function peopleList(params: {
18
- accountId: string;
19
- search?: string;
20
- teamName?: string;
21
- limit?: number;
22
- }): Promise<string> {
23
- const { accountId, search, teamName, limit } = params;
24
-
25
- const result = await aggregateAcrossTeams<LoopPerson>(
26
- accountId,
27
- "people",
28
- "loop-people-list",
29
- async (apiKey, team) => {
30
- const searchParam = search ? `?search=${encodeURIComponent(search)}` : "";
31
- const data = await loopGet<LoopPerson[]>(
32
- apiKey,
33
- `/people${searchParam}`,
34
- "loop-people-list",
35
- team
36
- );
37
- return Array.isArray(data) ? data : [];
38
- },
39
- { teamName, limitPerTeam: limit ?? 50, limitTotal: limit ?? 200 }
40
- );
41
-
42
- return formatAggregationResult(
43
- result,
44
- (p) => {
45
- const name = [p.firstName, p.lastName].filter(Boolean).join(" ") || "Unknown";
46
- const contact = p.email ?? p.phone ?? "";
47
- const type = p.type ? ` (${p.type})` : "";
48
- return `- ${name}${contact ? ` <${contact}>` : ""}${type}`;
49
- },
50
- "people"
51
- );
52
- }
@@ -1,52 +0,0 @@
1
- import {
2
- aggregateAcrossTeams,
3
- formatAggregationResult,
4
- loopGet,
5
- } from "../lib/loop-api.js";
6
-
7
- interface LoopProperty {
8
- id?: string;
9
- address?: string;
10
- price?: number;
11
- status?: string;
12
- type?: string;
13
- bedrooms?: number;
14
- bathrooms?: number;
15
- description?: string;
16
- [key: string]: unknown;
17
- }
18
-
19
- export async function propertiesList(params: {
20
- accountId: string;
21
- type?: string;
22
- teamName?: string;
23
- limit?: number;
24
- }): Promise<string> {
25
- const { accountId, type, teamName, limit } = params;
26
-
27
- const result = await aggregateAcrossTeams<LoopProperty>(
28
- accountId,
29
- "properties",
30
- "loop-properties-list",
31
- async (apiKey, team) => {
32
- const path = type && type !== "both"
33
- ? `/properties?type=${encodeURIComponent(type)}`
34
- : "/properties";
35
- const data = await loopGet<LoopProperty[]>(apiKey, path, "loop-properties-list", team);
36
- return Array.isArray(data) ? data : [];
37
- },
38
- { teamName, limitPerTeam: limit ?? 50, limitTotal: limit ?? 200 }
39
- );
40
-
41
- return formatAggregationResult(
42
- result,
43
- (p) => {
44
- const price = p.price ? ` — £${p.price.toLocaleString("en-GB")}` : "";
45
- const beds = p.bedrooms ? ` ${p.bedrooms}bed` : "";
46
- const status = p.status ? ` [${p.status}]` : "";
47
- const propType = p.type ? ` (${p.type})` : "";
48
- return `- ${p.address ?? "Unknown address"}${price}${beds}${propType}${status}`;
49
- },
50
- "properties"
51
- );
52
- }
@@ -1,62 +0,0 @@
1
- import {
2
- aggregateAcrossTeams,
3
- formatAggregationResult,
4
- loopGet,
5
- } from "../lib/loop-api.js";
6
-
7
- interface LoopViewing {
8
- id?: string;
9
- propertyAddress?: string;
10
- date?: string;
11
- time?: string;
12
- status?: string;
13
- type?: string;
14
- attendeeName?: string;
15
- [key: string]: unknown;
16
- }
17
-
18
- export async function viewingsList(params: {
19
- accountId: string;
20
- type?: string;
21
- teamName?: string;
22
- dateFrom?: string;
23
- dateTo?: string;
24
- limit?: number;
25
- }): Promise<string> {
26
- const { accountId, type, teamName, dateFrom, dateTo, limit } = params;
27
-
28
- const result = await aggregateAcrossTeams<LoopViewing>(
29
- accountId,
30
- "viewings",
31
- "loop-viewings-list",
32
- async (apiKey, team) => {
33
- const queryParts: string[] = [];
34
- if (type && type !== "both") queryParts.push(`type=${encodeURIComponent(type)}`);
35
- if (dateFrom) queryParts.push(`dateFrom=${encodeURIComponent(dateFrom)}`);
36
- if (dateTo) queryParts.push(`dateTo=${encodeURIComponent(dateTo)}`);
37
- const query = queryParts.length > 0 ? `?${queryParts.join("&")}` : "";
38
-
39
- const data = await loopGet<LoopViewing[]>(
40
- apiKey,
41
- `/viewings${query}`,
42
- "loop-viewings-list",
43
- team
44
- );
45
- return Array.isArray(data) ? data : [];
46
- },
47
- { teamName, limitPerTeam: limit ?? 50, limitTotal: limit ?? 200 }
48
- );
49
-
50
- return formatAggregationResult(
51
- result,
52
- (v) => {
53
- const addr = v.propertyAddress ?? "Unknown property";
54
- const when = [v.date, v.time].filter(Boolean).join(" ");
55
- const status = v.status ? ` [${v.status}]` : "";
56
- const attendee = v.attendeeName ? ` — ${v.attendeeName}` : "";
57
- const viewType = v.type ? ` (${v.type})` : "";
58
- return `- ${addr} — ${when || "No date"}${viewType}${attendee}${status}`;
59
- },
60
- "viewings"
61
- );
62
- }