@rubytech/create-maxy 1.0.473 → 1.0.475
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/package.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +2 -2
- package/payload/platform/plugins/docs/references/migration-guide.md +29 -21
- package/payload/platform/plugins/memory/PLUGIN.md +6 -0
- package/payload/platform/plugins/memory/mcp/dist/index.js +58 -22
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.d.ts +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.js +35 -23
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-reindex.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts +5 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +40 -7
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
- package/payload/platform/scripts/migrate-import.sh +17 -11
- package/payload/platform/scripts/seed-neo4j.sh +2 -55
- package/payload/server/public/assets/ChatInput-sDYraTun.css +1 -0
- package/payload/server/public/assets/{admin-BEbxw46k.js → admin-DpmnCxNk.js} +60 -60
- package/payload/server/public/assets/public-BBxDqQvQ.js +5 -0
- package/payload/server/public/index.html +3 -3
- package/payload/server/public/public.html +3 -3
- package/payload/server/server.js +108 -104
- package/payload/platform/plugins/admin/hooks/agent-creation-approval.sh +0 -161
- package/payload/platform/plugins/admin/hooks/agent-creation-gate.sh +0 -317
- package/payload/platform/plugins/admin/hooks/agent-creation-post.sh +0 -165
- package/payload/platform/plugins/admin/hooks/session-start.sh +0 -104
- package/payload/platform/plugins/admin/hooks/test-agent-creation-gate.sh +0 -926
- package/payload/server/public/assets/ChatInput-BEwQxFL9.css +0 -1
- package/payload/server/public/assets/public-OdyNuhVE.js +0 -5
- /package/payload/server/public/assets/{ChatInput-Dnp1FLis.js → ChatInput-DZ0j0Gdp.js} +0 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{C as e,D as t,S as n,T as r,_ as i,a,b as o,d as s,f as c,h as l,i as u,j as d,k as f,m as p,n as m,p as h,r as g,s as _,t as v,u as y,v as b,w as x,x as S,y as C}from"./ChatInput-DZ0j0Gdp.js";var w=t(),T=d(f(),1),E=`image/jpeg,image/png,image/gif,image/webp,application/pdf,text/plain,text/markdown,text/csv,text/html`,D=new Set(E.split(`,`)),O=20*1024*1024,k=typeof window<`u`&&/^(localhost|127\.0\.0\.1|[a-z0-9-]+\.local)(:|$)/.test(window.location.hostname);function A(){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 j(){let e=window.location.pathname.match(/^\/([a-z][a-z0-9-]{2,49})$/);return e?e[1]:void 0}function M(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 N(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 P(e){let[t,n]=(0,T.useState)(null),[r,i]=(0,T.useState)(null),[a,o]=(0,T.useState)(`loading`),[s,c]=(0,T.useState)(``),[l,u]=(0,T.useState)(null),[d,f]=(0,T.useState)(null),[p,m]=(0,T.useState)(!1),[h,g]=(0,T.useState)(null),_=(0,T.useMemo)(()=>j(),[]),v=(0,T.useRef)(_||``),y=(0,T.useRef)(null),b=(0,T.useRef)(null),x=(0,T.useRef)(!1),S=(0,T.useRef)(null),[C,w]=(0,T.useState)(`sign-in`),[E,D]=(0,T.useState)(null),O=(0,T.useRef)(null),M=(0,T.useRef)(null);(0,T.useEffect)(()=>{try{let e=sessionStorage.getItem(`maxy_session`);e&&(M.current=e)}catch{}},[]);let N=(0,T.useCallback)(t=>{y.current=t,n(t);try{sessionStorage.setItem(`maxy_session`,t)}catch{}o(`chat`),e(t)},[e]),P=(0,T.useCallback)(()=>{y.current=null;try{sessionStorage.removeItem(`maxy_session`)}catch{}n(null),o(`auth-required`),w(`sign-in`)},[]),F=(0,T.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,D(r.grant),w(`set-password`),window.history.replaceState({},``,window.location.pathname)):w(`link-expired`)}catch{w(`sign-in`)}},[]);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:(0,T.useCallback)(async()=>{if(y.current)return y.current;if(b.current)return b.current;let e=(async()=>{try{let e=M.current,t=await fetch(`/api/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({session_id:A(),..._?{agent:_}:{},...e?{session_key:e}:{}})});if(!t.ok){let e=await t.json().catch(()=>({error:``}));return k&&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 k&&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]),enterChat:N,enterGate:P,resumedRef:x,resumeMessagesRef:S,gateState:C,setGateState:w,grantInfo:E,setGrantInfo:D,gateSessionKeyRef:O}}function F({sessionKeyRef:e,ensureSession:t,sessionError:n,pageState:r,inputRef:a}){let[o,s]=(0,T.useState)([]),[c,l]=(0,T.useState)(!1),u=(0,T.useRef)(!1),d=e=>{u.current=e,l(e)},f=(0,T.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{}k&&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=``,a=``,c=()=>{a&&(r+=a,a=``,s(e=>{let t=[...e];return t[0]={...t[0],content:r},t}))},l=setInterval(c,60);try{for await(let e of i(n)){if(e.error)throw Object.assign(Error(e.error),{fromSSE:!0});e.text&&(a+=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(k&&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`&&a.current?.focus()}}},[e,t,n,r,a]),p=(0,T.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:a,headers:c}=r(n),l=await fetch(`/api/chat`,{method:`POST`,headers:c,body:a});if(l.status===401){e.current=null;try{sessionStorage.removeItem(`maxy_session`)}catch{}k&&console.warn(`[session-expired] stale key cleared, retrying with fresh session`);let n=await t();if(!n)throw Error(`session`);({body:a,headers:c}=r(n)),l=await fetch(`/api/chat`,{method:`POST`,headers:c,body:a})}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 i(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(k&&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`&&a.current?.focus()}},[e,t,n,r,a]);return{messages:o,setMessages:s,isStreaming:c,sendMessage:p,sendGreeting:f,handleComponentSubmit:(0,T.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 I=c();function L({value:e,onChange:t,onComplete:n,disabled:r}){let i=(0,T.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,I.jsx)(`div`,{className:`gate-otp-field`,children:Array.from({length:6}).map((t,n)=>(0,I.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 R({gateState:e,setGateState:t,grantInfo:n,setGrantInfo:r,gateSessionKeyRef:i,resolvedSlugRef:a,onAuthenticated:o}){let[c,l]=(0,T.useState)(``),[u,d]=(0,T.useState)(``),[f,p]=(0,T.useState)(``),[m,h]=(0,T.useState)(!1),[g,_]=(0,T.useState)(``),[v,b]=(0,T.useState)(``),[x,S]=(0,T.useState)(!1),[C,w]=(0,T.useState)(null),[E,D]=(0,T.useState)(null),[O,k]=(0,T.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:c,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:c,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 P(e){if(e.preventDefault(),!O){if(w(null),u!==f){w(`Passwords do not match`);return}if(!M(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 F(e){if(e.preventDefault(),!(O||!c)){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:c,agentSlug:e})});t.status===429?w((await t.json()).error||`Too many attempts. Please try again later.`):(D(`If an account exists, a reset link has been sent.`),setTimeout(()=>{S(!1),D(null)},4e3))}catch{w(`Unable to connect. Please try again.`)}finally{k(!1)}}}switch(e){case`set-password`:{let e=M(u),t=e.every(e=>e.met),r=u===f,i=t&&r&&f.length>0;return(0,I.jsx)(`div`,{className:`gate-wrap`,children:(0,I.jsxs)(`div`,{className:`gate-card`,children:[n?.expiresAt&&(0,I.jsxs)(`div`,{className:`gate-expiry-badge`,children:[`Access until `,new Date(n.expiresAt).toLocaleDateString(`en-GB`,{day:`numeric`,month:`short`,year:`numeric`})]}),(0,I.jsxs)(`h2`,{className:`gate-title`,children:[`Welcome, `,n?.displayName||`there`]}),(0,I.jsx)(`p`,{className:`gate-subtitle`,children:`Create a password to access this agent in the future.`}),(0,I.jsxs)(`form`,{className:`gate-form`,onSubmit:P,children:[(0,I.jsxs)(`div`,{className:`gate-field`,children:[(0,I.jsx)(`label`,{htmlFor:`gate-display-name`,children:`Display name`}),(0,I.jsx)(`input`,{id:`gate-display-name`,type:`text`,value:n?.displayName||``,disabled:!0})]}),(0,I.jsxs)(`div`,{className:`gate-field gate-pw-row`,children:[(0,I.jsx)(`label`,{htmlFor:`gate-pw`,children:`Password`}),(0,I.jsx)(`div`,{className:`gate-pw-toggle`,children:(0,I.jsx)(s,{checked:m,onChange:h,label:`Show`})}),(0,I.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,I.jsx)(`div`,{className:`gate-strength`,children:e.map(e=>(0,I.jsxs)(`span`,{className:`gate-strength-item${e.met?` met`:``}`,children:[e.met?`✓`:`○`,` `,e.label]},e.key))})]}),(0,I.jsxs)(`div`,{className:`gate-field`,children:[(0,I.jsx)(`label`,{htmlFor:`gate-pw-confirm`,children:`Confirm password`}),(0,I.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,I.jsx)(`div`,{className:`gate-error`,children:`Passwords do not match`})]}),C&&(0,I.jsx)(`div`,{className:`gate-error`,children:C}),(0,I.jsx)(`div`,{className:`gate-submit`,children:(0,I.jsx)(y,{variant:`primary`,type:`submit`,fullWidth:!0,disabled:!i||O,loading:O,children:`Create account & enter chat`})})]})]})})}case`enter-otp`:return(0,I.jsx)(`div`,{className:`gate-wrap`,children:(0,I.jsxs)(`div`,{className:`gate-card`,children:[(0,I.jsx)(`h2`,{className:`gate-title`,children:`Enter your code`}),(0,I.jsxs)(`p`,{className:`gate-subtitle`,children:[`Enter the 6-digit code sent to `,N(v,`phone`)]}),(0,I.jsx)(L,{value:g,onChange:_,onComplete:j,disabled:O}),C&&(0,I.jsx)(`div`,{className:`gate-error`,children:C}),O&&(0,I.jsxs)(`div`,{className:`gate-loading`,children:[(0,I.jsx)(`span`,{className:`spinner`}),`Verifying...`]}),(0,I.jsx)(`div`,{className:`gate-resend`,children:(0,I.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,I.jsx)(`div`,{className:`gate-wrap`,children:(0,I.jsxs)(`div`,{className:`gate-card`,children:[(0,I.jsx)(`h2`,{className:`gate-title`,children:e===`private-agent`?`Private Agent`:`Welcome back`}),(0,I.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,I.jsxs)(`form`,{className:`gate-form`,onSubmit:F,children:[(0,I.jsxs)(`div`,{className:`gate-field`,children:[(0,I.jsx)(`label`,{htmlFor:`gate-forgot-contact`,children:`Email or phone`}),(0,I.jsx)(`input`,{id:`gate-forgot-contact`,type:`text`,value:c,onChange:e=>l(e.target.value),placeholder:`you@example.com`,autoFocus:!0,autoComplete:`email`})]}),C&&(0,I.jsx)(`div`,{className:`gate-error`,children:C}),E&&(0,I.jsx)(`div`,{className:`gate-success`,children:E}),(0,I.jsx)(`div`,{className:`gate-submit`,children:(0,I.jsx)(y,{variant:`primary`,type:`submit`,fullWidth:!0,disabled:!c.trim()||O,loading:O,children:`Send reset link`})}),(0,I.jsx)(`div`,{className:`gate-actions`,children:(0,I.jsx)(`button`,{type:`button`,className:`gate-link`,onClick:()=>{S(!1),w(null),D(null)},children:`Back to sign in`})})]}):(0,I.jsxs)(`form`,{className:`gate-form`,onSubmit:A,children:[(0,I.jsxs)(`div`,{className:`gate-field`,children:[(0,I.jsx)(`label`,{htmlFor:`gate-contact`,children:`Email or phone`}),(0,I.jsx)(`input`,{id:`gate-contact`,type:`text`,value:c,onChange:e=>l(e.target.value),placeholder:`you@example.com`,autoFocus:!0,autoComplete:`email`})]}),(0,I.jsxs)(`div`,{className:`gate-field gate-pw-row`,children:[(0,I.jsx)(`label`,{htmlFor:`gate-login-pw`,children:`Password`}),(0,I.jsx)(`div`,{className:`gate-pw-toggle`,children:(0,I.jsx)(s,{checked:m,onChange:h,label:`Show`})}),(0,I.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,I.jsx)(`div`,{className:`gate-error`,children:C}),(0,I.jsx)(`div`,{className:`gate-submit`,children:(0,I.jsx)(y,{variant:`primary`,type:`submit`,fullWidth:!0,disabled:!c.trim()||!u||O,loading:O,children:`Sign in`})}),(0,I.jsx)(`div`,{className:`gate-actions`,children:(0,I.jsx)(`button`,{type:`button`,className:`gate-link`,onClick:()=>{S(!0),w(null)},children:`Forgot password?`})})]}),e===`private-agent`&&(0,I.jsx)(`p`,{className:`gate-hint`,children:`No account? You need an invitation from the agent owner.`})]})});case`access-expired`:return(0,I.jsx)(`div`,{className:`gate-wrap`,children:(0,I.jsxs)(`div`,{className:`gate-card`,children:[(0,I.jsx)(`div`,{className:`gate-icon`,children:`⏰`}),(0,I.jsx)(`h2`,{className:`gate-title`,children:`Access expired`}),(0,I.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,I.jsx)(`div`,{className:`gate-actions`,children:(0,I.jsx)(y,{variant:`secondary`,onClick:()=>{t(`sign-in`),w(null),d(``)},children:`Sign in with a different account`})})]})});case`link-expired`:return(0,I.jsx)(`div`,{className:`gate-wrap`,children:(0,I.jsxs)(`div`,{className:`gate-card`,children:[(0,I.jsx)(`div`,{className:`gate-icon`,children:`⚠️`}),(0,I.jsx)(`h2`,{className:`gate-title`,children:`Link expired`}),(0,I.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,I.jsx)(`div`,{className:`gate-actions`,children:(0,I.jsx)(y,{variant:`primary`,onClick:()=>{t(`sign-in`),w(null)},children:`Go to sign in`})})]})});case`otp-failed`:return(0,I.jsx)(`div`,{className:`gate-wrap`,children:(0,I.jsxs)(`div`,{className:`gate-card`,children:[(0,I.jsx)(`div`,{className:`gate-icon`,children:`⛔`}),(0,I.jsx)(`h2`,{className:`gate-title`,children:`Too many attempts`}),(0,I.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,I.jsx)(`div`,{className:`gate-actions`,children:(0,I.jsx)(y,{variant:`secondary`,onClick:()=>{t(`sign-in`),w(null),_(``)},children:`Back to sign in`})})]})})}}var z={"single-select":a,"multi-select":u};function B({name:e,data:t,onSubmit:n,submitted:r}){let i=z[e];return i?(0,I.jsx)(i,{data:t,onSubmit:n,submitted:r}):(console.warn(`[PublicComponentRenderer] Unknown component: "${e}". Registered: ${Object.keys(z).join(`, `)}`),(0,I.jsx)(`div`,{className:`component-card component-card--error`,children:(0,I.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 V({messages:t,isStreaming:i,sessionError:a,selectionMode:o,selectedItems:c,toggleSelectItem:l,onComponentSubmit:u,remainingSuggestions:d,onSuggestionClick:f,isAtBottom:p,setIsAtBottom:m}){let[h,v]=(0,T.useState)(new Set),[b,x]=(0,T.useState)(new Set),S=(0,T.useRef)(null),C=(0,T.useRef)(null),w=(0,T.useRef)(null),E=(0,T.useRef)(!1),D=(0,T.useRef)(!1),O=(0,T.useRef)(!1),k=(0,T.useRef)(0),A=(0,T.useRef)(!1),j=(0,T.useRef)(new Map);A.current=i,(0,T.useEffect)(()=>{i&&!E.current&&p&&(D.current=!0)},[i,p]),(0,T.useEffect)(()=>{if(!D.current&&!p){E.current=i,O.current=!1;return}if(E.current&&!i&&w.current&&C.current){let e=w.current;if(e.offsetHeight>C.current.clientHeight){D.current=!1,O.current=!0,e.scrollIntoView({behavior:`smooth`,block:`start`}),E.current=i;return}}(p||D.current)&&!O.current&&S.current?.scrollIntoView({behavior:`smooth`}),E.current=i},[t,p,i]),(0,T.useEffect)(()=>{let e=C.current;if(!e)return;let t=()=>{let t=e.scrollTop;A.current&&t<k.current&&(D.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,T.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,I.jsxs)(`div`,{className:`chat-messages-wrap`,children:[o&&(0,I.jsx)(`div`,{className:`selection-overlay-band`}),(0,I.jsxs)(`div`,{className:`chat-messages`,ref:C,children:[a&&t.length===0&&(0,I.jsx)(`div`,{className:`session-error`,children:(0,I.jsx)(`p`,{children:a})}),t.map((a,d)=>{if(a.hidden)return null;let f=i&&d===t.length-1,p=`${a.timestamp}_${a.role}`,m=c.has(p);return(0,I.jsxs)(`div`,{ref:d===M?w:void 0,className:`message ${a.role}${m?` selected`:``}`,children:[o&&!f&&(0,I.jsx)(`div`,{className:`message-select-check`,children:(0,I.jsx)(s,{checked:m,onChange:()=>l(p)})}),(0,I.jsxs)(`div`,{className:`bubble`,children:[a.role===`visitor`&&a.content?(()=>{let e=h.has(d),t=b.has(d);return(0,I.jsxs)(I.Fragment,{children:[(0,I.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,I.jsx)(`div`,{className:`bubble-expand`,children:(0,I.jsx)(y,{variant:`icon`,className:e?`expanded`:``,onClick:()=>v(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,I.jsx)(r,{size:14})})})]})})():a.content?(0,I.jsx)(_,{content:a.content,timestamp:g(a.timestamp)}):(0,I.jsxs)(`span`,{className:`typing-indicator`,children:[(0,I.jsx)(`span`,{className:`typing-dot`}),(0,I.jsx)(`span`,{className:`typing-dot`}),(0,I.jsx)(`span`,{className:`typing-dot`})]}),a.attachments&&a.attachments.length>0&&(0,I.jsx)(`div`,{className:`message-attachments`,children:a.attachments.map((t,r)=>(0,I.jsxs)(`span`,{className:`message-attachment-chip no-action`,children:[t.mimeType===`application/pdf`?(0,I.jsx)(n,{size:12}):t.mimeType.startsWith(`text/`)?(0,I.jsx)(e,{size:12}):null,(0,I.jsx)(`span`,{children:t.filename})]},r))}),a.role===`visitor`&&(0,I.jsx)(`span`,{className:`message-timestamp`,children:g(a.timestamp)})]}),a.role===`maxy`&&a.components&&a.components.length>0&&(0,I.jsx)(`div`,{className:`public-components`,children:a.components.map((e,t)=>(0,I.jsx)(`div`,{className:`public-component-enter`,children:(0,I.jsx)(B,{name:e.name,data:e.data,onSubmit:e=>u(d,t,e),submitted:e.submitted})},t))})]},d)}),!i&&d.length>0&&(0,I.jsx)(`div`,{className:`chat-suggestions`,children:d.map(e=>(0,I.jsx)(y,{variant:`suggestion`,onClick:()=>f(e),children:e},e))}),(0,I.jsx)(`div`,{ref:S})]}),!p&&(0,I.jsx)(`button`,{className:`scroll-to-bottom`,onClick:()=>S.current?.scrollIntoView({behavior:`smooth`}),"aria-label":`Scroll to bottom`,children:(0,I.jsx)(r,{size:18})})]})}function H({selectedItems:e,messages:t,copySelected:n,exitSelection:r,showCopyToast:i}){let[a,o]=(0,T.useState)(!1),s=(0,T.useRef)(null),c=(0,T.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
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
`)}T.useEffect(()=>{if(!a)return;let e=e=>{e.target.closest(`.selection-copy-wrap`)||o(!1)};return document.addEventListener(`pointerdown`,e),()=>document.removeEventListener(`pointerdown`,e)},[a]);function f(){s.current!==null&&(clearTimeout(s.current),s.current=null)}return(0,I.jsx)(`div`,{className:`chat-input-area`,children:(0,I.jsxs)(`div`,{className:`selection-bar`,children:[(0,I.jsxs)(`span`,{className:`selection-count`,children:[e.size,` Selected`]}),(0,I.jsxs)(`div`,{className:`selection-copy-wrap`,children:[(0,I.jsxs)(`button`,{type:`button`,className:`selection-copy`,onPointerDown:()=>{if(a){o(!1);return}c.current=!1,s.current=setTimeout(()=>{c.current=!0,o(!0),s.current=null},500)},onPointerUp:f,onPointerLeave:f,onPointerCancel:f,onClick:async()=>{c.current||await n(l,u)},children:[(0,I.jsx)(x,{size:18}),(0,I.jsx)(`span`,{children:`Copy`})]}),a&&(0,I.jsx)(`div`,{className:`copy-menu`,children:(0,I.jsx)(`button`,{type:`button`,className:`copy-menu-item`,onClick:async()=>{let e=d();e&&i(await b(e)),r()},children:`Copy all`})})]}),(0,I.jsx)(`button`,{type:`button`,className:`selection-cancel`,onClick:r,children:`Cancel`})]})})}function U({input:t,setInput:r,isStreaming:i,pendingFiles:a,setPendingFiles:o,attachError:s,setAttachError:c,isDragOver:l,setIsDragOver:u,inputRef:d,onSubmit:f}){let p=(0,T.useRef)(null);function h(e){c(null);let t=e.find(e=>!D.has(e.type));if(t){c(`Unsupported file type: "${t.type}". Supported: images, PDF, plain text, markdown, CSV.`);return}let n=e.find(e=>e.size>O);if(n){c(`"${n.name}" exceeds the 20 MB limit.`);return}o(t=>[...t,...e].slice(0,5))}function g(e){e.preventDefault(),u(!0)}function _(){u(!1)}function b(e){e.preventDefault(),u(!1),h([...e.dataTransfer.files])}return(0,I.jsxs)(`div`,{className:`chat-input-area`,children:[(0,I.jsx)(`input`,{ref:p,type:`file`,multiple:!0,accept:E,style:{display:`none`},onChange:e=>{e.target.files&&h([...e.target.files]),e.target.value=``}}),a.length>0&&(0,I.jsx)(`div`,{className:`attachment-strip`,children:a.map((t,r)=>(0,I.jsxs)(`div`,{className:`attachment-chip`,children:[t.type.startsWith(`image/`)?(0,I.jsx)(`img`,{src:URL.createObjectURL(t),alt:t.name,className:`attachment-chip-thumb`}):t.type===`application/pdf`?(0,I.jsx)(n,{size:14}):(0,I.jsx)(e,{size:14}),(0,I.jsx)(`span`,{className:`attachment-chip-name`,children:t.name}),(0,I.jsx)(`button`,{type:`button`,className:`attachment-chip-remove`,onClick:()=>o(e=>e.filter((e,t)=>t!==r)),"aria-label":`Remove ${t.name}`,children:`×`})]},r))}),s&&(0,I.jsx)(`p`,{className:`attach-error`,children:s}),(0,I.jsx)(m,{inputRef:d}),(0,I.jsxs)(`form`,{className:`chat-form${l?` drag-over`:``}`,onSubmit:f,onDragOver:g,onDragLeave:_,onDrop:b,onPaste:e=>{let t=e.clipboardData?.items;if(!t)return;let n=[];for(let e of t){if(e.kind!==`file`)continue;let t=e.getAsFile();if(!t)continue;let r=t.type.split(`/`)[1]?.replace(`jpeg`,`jpg`)||`png`;n.push(new File([t],`pasted-image-${Date.now()}.${r}`,{type:t.type}))}n.length>0&&h(n)},children:[(0,I.jsx)(y,{variant:`icon`,type:`button`,onClick:()=>p.current?.click(),disabled:i,"aria-label":`Attach file`,children:(0,I.jsx)(S,{size:14})}),(0,I.jsx)(v,{ref:d,value:t,onChange:r,placeholder:`Type a message...`}),(0,I.jsx)(y,{variant:`send`,type:`submit`,disabled:i||!t.trim()&&a.length===0,"aria-label":`Send message`,children:(0,I.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,I.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,I.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]})]})}var W=[];function G(){let[e,t]=(0,T.useState)(``),[n,r]=(0,T.useState)([]),[i,a]=(0,T.useState)(!1),[s,c]=(0,T.useState)(null),[u,d]=(0,T.useState)(W),[f,m]=(0,T.useState)(!0),g=(0,T.useRef)(null),{selectionMode:_,selectedItems:v,copyToast:y,exitSelection:b,enterSelection:x,toggleSelectItem:S,copySelected:w,showCopyToast:E}=C(),D=(0,T.useRef)(()=>{}),O=P((0,T.useCallback)(e=>{D.current(e)},[])),{sessionId:k,sessionKeyRef:A,sessionError:j,pageState:M,agentDisplayName:N,agentImage:L,agentImageShape:z,showAgentName:B,branding:G,ensureSession:K,resumedRef:q,resumeMessagesRef:J}=O,{messages:Y,setMessages:X,isStreaming:Z,sendMessage:ee,sendGreeting:Q,handleComponentSubmit:te}=F({sessionKeyRef:A,ensureSession:K,sessionError:j,pageState:M,inputRef:g});(0,T.useEffect)(()=>{D.current=Q},[Q]),(0,T.useEffect)(()=>{let e=!1;return(async()=>{let t=await K();if(!e&&t){if(q.current&&J.current&&J.current.length>0){X(J.current.map(e=>({role:e.role,content:e.content,timestamp:e.timestamp}))),J.current=null;return}Q(t)}})(),()=>{e=!0}},[]),(0,T.useEffect)(()=>{M===`chat`&&g.current?.focus()},[M]),(0,T.useEffect)(()=>{if(!G)return;let e=document.documentElement;if(G.primaryColor&&(e.style.setProperty(`--sage`,G.primaryColor),e.style.setProperty(`--sage-hover`,G.primaryColor),e.style.setProperty(`--sage-subtle`,G.primaryColor+`14`),e.style.setProperty(`--sage-glow`,G.primaryColor+`26`)),G.accentColor&&e.style.setProperty(`--visitor-bubble`,G.accentColor),G.backgroundColor&&e.style.setProperty(`--bg`,G.backgroundColor),document.title=G.name,G.primaryColor){let e=document.querySelector(`meta[name="theme-color"]`);e||(e=document.createElement(`meta`),e.name=`theme-color`,document.head.appendChild(e)),e.content=G.primaryColor}if(G.faviconUrl){let e=document.querySelector(`link[rel="icon"]`);e||(e=document.createElement(`link`),e.rel=`icon`,document.head.appendChild(e)),e.href=G.faviconUrl}},[G]),(0,T.useEffect)(()=>{function e(e){e.key===`Escape`&&_&&b()}return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[_,b]);function $(e){if(!e&&n.length===0||Z)return;X(e=>e.map(e=>e.components?.some(e=>!e.submitted)?{...e,components:e.components.map(e=>e.submitted?e:{...e,submitted:!0})}:e)),d(t=>t.filter(t=>t!==e)),m(!0);let i=[...n];t(``),r([]),c(null),ee(e,{files:i})}function ne(t){t.preventDefault(),$(e.trim()),g.current?.resetHeight()}return(0,I.jsxs)(`div`,{className:`chat-page`,children:[(0,I.jsxs)(`header`,{className:`chat-header`,children:[(0,I.jsx)(`img`,{src:L||G?.logoUrl||l,alt:G?.name||h.productName,className:`chat-logo${L&&z===`circle`?` chat-logo--circle`:``}${L&&z===`rounded`?` chat-logo--rounded`:``}`,onError:e=>{e.target.src=G?.logoUrl||l}}),(0,I.jsxs)(`div`,{className:`chat-header-text`,children:[B!==`none`&&(0,I.jsx)(`h1`,{className:`chat-tagline`,children:B&&N||G?.name||h.productName}),(0,I.jsx)(`p`,{className:`chat-intro`,children:G?.tagline||``})]}),M===`chat`&&!_&&(0,I.jsx)(`button`,{className:`chat-header-select`,onClick:x,title:`Select messages`,"aria-label":`Select messages`,children:(0,I.jsx)(o,{size:16})})]}),M===`loading`&&(0,I.jsx)(`div`,{className:`gate-wrap`,children:(0,I.jsx)(`div`,{className:`gate-loading`,children:(0,I.jsx)(`span`,{className:`spinner`})})}),M===`auth-required`&&(0,I.jsx)(R,{gateState:O.gateState,setGateState:O.setGateState,grantInfo:O.grantInfo,setGrantInfo:O.setGrantInfo,gateSessionKeyRef:O.gateSessionKeyRef,resolvedSlugRef:O.resolvedSlugRef,onAuthenticated:O.enterChat}),M===`chat`&&(0,I.jsxs)(I.Fragment,{children:[(0,I.jsx)(V,{messages:Y,isStreaming:Z,sessionError:j,selectionMode:_,selectedItems:v,toggleSelectItem:S,onComponentSubmit:te,remainingSuggestions:u,onSuggestionClick:$,isAtBottom:f,setIsAtBottom:m}),_?(0,I.jsx)(H,{selectedItems:v,messages:Y,copySelected:w,exitSelection:b,showCopyToast:E}):(0,I.jsx)(U,{input:e,setInput:t,isStreaming:Z,pendingFiles:n,setPendingFiles:r,attachError:s,setAttachError:c,isDragOver:i,setIsDragOver:a,inputRef:g,onSubmit:ne})]}),y&&(0,I.jsx)(`span`,{className:`copy-toast${y===`failed`?` copy-toast-failed`:``}`,children:y===`copied`?`Copied`:`Copy failed`}),(0,I.jsxs)(`footer`,{className:`chat-footer`,children:[(0,I.jsxs)(`a`,{href:p,children:[h.domain,` `,`↗`]}),k&&(0,I.jsxs)(`span`,{style:{opacity:.35,fontSize:`10px`,fontFamily:`monospace`,marginLeft:`1rem`},children:[`Session · `,k.slice(0,8)]})]})]})}(0,w.createRoot)(document.getElementById(`root`)).render((0,I.jsx)(G,{}));
|
|
@@ -5,9 +5,9 @@
|
|
|
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-
|
|
9
|
-
<link rel="modulepreload" crossorigin href="/assets/ChatInput-
|
|
10
|
-
<link rel="stylesheet" crossorigin href="/assets/ChatInput-
|
|
8
|
+
<script type="module" crossorigin src="/assets/admin-DpmnCxNk.js"></script>
|
|
9
|
+
<link rel="modulepreload" crossorigin href="/assets/ChatInput-DZ0j0Gdp.js">
|
|
10
|
+
<link rel="stylesheet" crossorigin href="/assets/ChatInput-sDYraTun.css">
|
|
11
11
|
<link rel="stylesheet" href="/brand-defaults.css">
|
|
12
12
|
</head>
|
|
13
13
|
<body>
|
|
@@ -5,9 +5,9 @@
|
|
|
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-
|
|
9
|
-
<link rel="modulepreload" crossorigin href="/assets/ChatInput-
|
|
10
|
-
<link rel="stylesheet" crossorigin href="/assets/ChatInput-
|
|
8
|
+
<script type="module" crossorigin src="/assets/public-BBxDqQvQ.js"></script>
|
|
9
|
+
<link rel="modulepreload" crossorigin href="/assets/ChatInput-DZ0j0Gdp.js">
|
|
10
|
+
<link rel="stylesheet" crossorigin href="/assets/ChatInput-sDYraTun.css">
|
|
11
11
|
<link rel="stylesheet" href="/brand-defaults.css">
|
|
12
12
|
</head>
|
|
13
13
|
<body>
|
package/payload/server/server.js
CHANGED
|
@@ -2851,7 +2851,7 @@ var serveStatic = (options = { root: "" }) => {
|
|
|
2851
2851
|
};
|
|
2852
2852
|
|
|
2853
2853
|
// server/index.ts
|
|
2854
|
-
import { readFileSync as
|
|
2854
|
+
import { readFileSync as readFileSync19, existsSync as existsSync19, watchFile } from "fs";
|
|
2855
2855
|
import { resolve as resolve18, join as join9, basename as basename4 } from "path";
|
|
2856
2856
|
import { homedir as homedir3 } from "os";
|
|
2857
2857
|
|
|
@@ -7612,7 +7612,8 @@ var SUPPORTED_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
|
7612
7612
|
"application/pdf",
|
|
7613
7613
|
"text/plain",
|
|
7614
7614
|
"text/markdown",
|
|
7615
|
-
"text/csv"
|
|
7615
|
+
"text/csv",
|
|
7616
|
+
"text/html"
|
|
7616
7617
|
]);
|
|
7617
7618
|
var MAX_FILE_SIZE_BYTES = 20 * 1024 * 1024;
|
|
7618
7619
|
var MAX_FILES_PER_MESSAGE = 5;
|
|
@@ -24575,11 +24576,26 @@ function createInboundDebouncer(opts) {
|
|
|
24575
24576
|
// app/lib/whatsapp/manager.ts
|
|
24576
24577
|
var TAG8 = "[whatsapp:manager]";
|
|
24577
24578
|
var MAX_RECONNECT_ATTEMPTS = 10;
|
|
24579
|
+
var MESSAGE_STORE_MAX = 500;
|
|
24578
24580
|
var connections = /* @__PURE__ */ new Map();
|
|
24579
24581
|
var configDir = null;
|
|
24580
24582
|
var whatsAppConfig = {};
|
|
24581
24583
|
var onInboundMessage = null;
|
|
24582
24584
|
var initialized = false;
|
|
24585
|
+
var messageStore = /* @__PURE__ */ new Map();
|
|
24586
|
+
function storeMessage(storeKey, entry) {
|
|
24587
|
+
let entries = messageStore.get(storeKey);
|
|
24588
|
+
if (!entries) {
|
|
24589
|
+
entries = [];
|
|
24590
|
+
messageStore.set(storeKey, entries);
|
|
24591
|
+
}
|
|
24592
|
+
entries.push(entry);
|
|
24593
|
+
if (entries.length > MESSAGE_STORE_MAX) {
|
|
24594
|
+
const trimmed = entries.length - MESSAGE_STORE_MAX;
|
|
24595
|
+
entries.splice(0, trimmed);
|
|
24596
|
+
console.error(`${TAG8} message store trimmed for ${storeKey}: ${trimmed} oldest messages removed`);
|
|
24597
|
+
}
|
|
24598
|
+
}
|
|
24583
24599
|
async function init(opts) {
|
|
24584
24600
|
if (initialized) {
|
|
24585
24601
|
console.error(`${TAG8} already initialized`);
|
|
@@ -24852,9 +24868,48 @@ function monitorInbound(conn) {
|
|
|
24852
24868
|
}
|
|
24853
24869
|
});
|
|
24854
24870
|
sock.ev.on("messages.upsert", async (upsert) => {
|
|
24855
|
-
if (upsert.type !== "notify") return;
|
|
24871
|
+
if (upsert.type !== "notify" && upsert.type !== "append") return;
|
|
24856
24872
|
for (const msg of upsert.messages) {
|
|
24857
24873
|
try {
|
|
24874
|
+
const remoteJid = msg.key.remoteJid;
|
|
24875
|
+
if (!remoteJid || remoteJid === "status@broadcast") continue;
|
|
24876
|
+
if (!msg.message) continue;
|
|
24877
|
+
const extracted = extractMessage(msg);
|
|
24878
|
+
if (extracted.text) {
|
|
24879
|
+
const isGroup = isGroupJid(remoteJid);
|
|
24880
|
+
const senderJid = isGroup ? msg.key.participant ?? remoteJid : remoteJid;
|
|
24881
|
+
const senderPhone = await resolveJidToE164(senderJid, conn.lidMapping) ?? senderJid;
|
|
24882
|
+
const ts = msg.messageTimestamp ? Number(msg.messageTimestamp) : Math.floor(Date.now() / 1e3);
|
|
24883
|
+
const storeKey = `${conn.accountId}:${remoteJid}`;
|
|
24884
|
+
storeMessage(storeKey, {
|
|
24885
|
+
id: msg.key.id ?? `${remoteJid}-${ts}`,
|
|
24886
|
+
sender: senderPhone,
|
|
24887
|
+
senderName: msg.pushName ?? void 0,
|
|
24888
|
+
body: extracted.text,
|
|
24889
|
+
timestamp: ts,
|
|
24890
|
+
fromMe: Boolean(msg.key.fromMe),
|
|
24891
|
+
quoted: extracted.quotedMessage ? { id: extracted.quotedMessage.id, body: extracted.quotedMessage.text, sender: extracted.quotedMessage.sender } : void 0
|
|
24892
|
+
});
|
|
24893
|
+
const entries = messageStore.get(storeKey);
|
|
24894
|
+
console.error(
|
|
24895
|
+
`${TAG8} stored message ${msg.key.id ?? "?"} for ${remoteJid} (type: ${upsert.type}, store size: ${entries?.length ?? 0}/${MESSAGE_STORE_MAX}) account=${conn.accountId}`
|
|
24896
|
+
);
|
|
24897
|
+
}
|
|
24898
|
+
if (upsert.type === "append") {
|
|
24899
|
+
const sendReceipts = whatsAppConfig.accounts?.[conn.accountId]?.sendReadReceipts ?? whatsAppConfig.sendReadReceipts ?? true;
|
|
24900
|
+
if (sendReceipts && msg.key.id) {
|
|
24901
|
+
sendReadReceipt(
|
|
24902
|
+
sock,
|
|
24903
|
+
remoteJid,
|
|
24904
|
+
[msg.key.id],
|
|
24905
|
+
isGroupJid(remoteJid) ? msg.key.participant ?? void 0 : void 0
|
|
24906
|
+
);
|
|
24907
|
+
}
|
|
24908
|
+
console.error(
|
|
24909
|
+
`${TAG8} append-type message ${msg.key.id ?? "?"} stored, dispatch skipped account=${conn.accountId}`
|
|
24910
|
+
);
|
|
24911
|
+
continue;
|
|
24912
|
+
}
|
|
24858
24913
|
await handleInboundMessage(conn, msg);
|
|
24859
24914
|
} catch (err) {
|
|
24860
24915
|
console.error(`${TAG8} inbound handler error account=${conn.accountId}: ${String(err)}`);
|
|
@@ -25590,17 +25645,23 @@ async function POST19(req) {
|
|
|
25590
25645
|
} catch (err) {
|
|
25591
25646
|
console.error(`[session] onboarding query failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
25592
25647
|
}
|
|
25648
|
+
let businessName;
|
|
25649
|
+
try {
|
|
25650
|
+
const branding = await fetchBranding(accountId);
|
|
25651
|
+
businessName = branding?.name || void 0;
|
|
25652
|
+
} catch {
|
|
25653
|
+
}
|
|
25654
|
+
console.log(`[session] businessName=${businessName ?? "\u2013"}`);
|
|
25593
25655
|
return Response.json({
|
|
25594
25656
|
session_key: sessionKey,
|
|
25595
25657
|
agent_id: "admin",
|
|
25596
25658
|
thinkingView,
|
|
25597
|
-
onboardingComplete
|
|
25659
|
+
onboardingComplete,
|
|
25660
|
+
businessName
|
|
25598
25661
|
});
|
|
25599
25662
|
}
|
|
25600
25663
|
|
|
25601
25664
|
// app/api/admin/chat/route.ts
|
|
25602
|
-
import { existsSync as existsSync14, readFileSync as readFileSync14, writeFileSync as writeFileSync9, mkdirSync as mkdirSync6 } from "fs";
|
|
25603
|
-
import { dirname as dirname2 } from "path";
|
|
25604
25665
|
function isComponentDone(parsed) {
|
|
25605
25666
|
return typeof parsed === "object" && parsed !== null && parsed._componentDone === true && typeof parsed.component === "string" && typeof parsed.payload === "string";
|
|
25606
25667
|
}
|
|
@@ -25625,60 +25686,6 @@ ${inner.content}`;
|
|
|
25625
25686
|
}
|
|
25626
25687
|
return payload;
|
|
25627
25688
|
}
|
|
25628
|
-
var VOLATILE_STATE_FILE = "/tmp/maxy-agent-create-state.json";
|
|
25629
|
-
function advanceGateIfNeeded(envelope, accountDir, logFn) {
|
|
25630
|
-
if (!existsSync14(VOLATILE_STATE_FILE)) return;
|
|
25631
|
-
const { component, payload } = envelope;
|
|
25632
|
-
let gateFlag = null;
|
|
25633
|
-
let agentSlug = "";
|
|
25634
|
-
if (component === "document-editor") {
|
|
25635
|
-
try {
|
|
25636
|
-
const inner = typeof payload === "string" ? JSON.parse(payload) : payload;
|
|
25637
|
-
if (typeof inner === "object" && inner !== null && typeof inner.filePath === "string") {
|
|
25638
|
-
const match2 = inner.filePath.match(/agents\/([^/]+)\/(SOUL\.md|KNOWLEDGE\.md)$/);
|
|
25639
|
-
if (match2 && match2[1] !== "admin") {
|
|
25640
|
-
agentSlug = match2[1];
|
|
25641
|
-
gateFlag = match2[2] === "SOUL.md" ? "soul" : "knowledge";
|
|
25642
|
-
}
|
|
25643
|
-
}
|
|
25644
|
-
} catch {
|
|
25645
|
-
}
|
|
25646
|
-
} else if (component === "form") {
|
|
25647
|
-
gateFlag = "config";
|
|
25648
|
-
}
|
|
25649
|
-
if (!gateFlag) return;
|
|
25650
|
-
let state;
|
|
25651
|
-
try {
|
|
25652
|
-
state = JSON.parse(readFileSync14(VOLATILE_STATE_FILE, "utf-8"));
|
|
25653
|
-
} catch (err) {
|
|
25654
|
-
logFn(`ERROR \u2014 failed to read state file for advancement: ${err instanceof Error ? err.message : String(err)}`);
|
|
25655
|
-
return;
|
|
25656
|
-
}
|
|
25657
|
-
const gates = state.gates;
|
|
25658
|
-
if (!gates || typeof gates !== "object") {
|
|
25659
|
-
logFn("WARNING \u2014 state file has unexpected structure, skipping advancement");
|
|
25660
|
-
return;
|
|
25661
|
-
}
|
|
25662
|
-
if (!state.slug && agentSlug) {
|
|
25663
|
-
state.slug = agentSlug;
|
|
25664
|
-
}
|
|
25665
|
-
if (gates[gateFlag] === true) return;
|
|
25666
|
-
gates[gateFlag] = true;
|
|
25667
|
-
try {
|
|
25668
|
-
writeFileSync9(VOLATILE_STATE_FILE, JSON.stringify(state));
|
|
25669
|
-
} catch (err) {
|
|
25670
|
-
logFn(`ERROR \u2014 failed to write volatile state after advancement: ${err instanceof Error ? err.message : String(err)}`);
|
|
25671
|
-
}
|
|
25672
|
-
const durablePath = `${accountDir}/.claude/agent-create-state.json`;
|
|
25673
|
-
try {
|
|
25674
|
-
mkdirSync6(dirname2(durablePath), { recursive: true });
|
|
25675
|
-
writeFileSync9(durablePath, JSON.stringify(state));
|
|
25676
|
-
} catch (err) {
|
|
25677
|
-
logFn(`WARNING \u2014 failed to write durable state after advancement: ${err instanceof Error ? err.message : String(err)}`);
|
|
25678
|
-
}
|
|
25679
|
-
const pending = Object.entries(gates).filter(([, v]) => !v).map(([k]) => k);
|
|
25680
|
-
logFn(`${gateFlag} gate advanced (route-level). Pending: ${pending.length > 0 ? pending.join(", ") : "none"}`);
|
|
25681
|
-
}
|
|
25682
25689
|
async function POST20(req) {
|
|
25683
25690
|
const contentType = req.headers.get("content-type") ?? "";
|
|
25684
25691
|
let message;
|
|
@@ -25822,9 +25829,6 @@ async function POST20(req) {
|
|
|
25822
25829
|
if (isComponentDone(parsed)) {
|
|
25823
25830
|
const componentLog = agentLogStream("component-lifecycle", account.accountDir);
|
|
25824
25831
|
const ts = (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
|
|
25825
|
-
const logFn = (msg) => componentLog.write(`[${ts}] [agent-creation-approval:route] ${msg}
|
|
25826
|
-
`);
|
|
25827
|
-
advanceGateIfNeeded(parsed, account.accountDir, logFn);
|
|
25828
25832
|
message = transformComponentDone(parsed);
|
|
25829
25833
|
componentLog.write(`[${ts}] [component:${parsed.component}] componentDone \u2192 transformed
|
|
25830
25834
|
`);
|
|
@@ -25942,7 +25946,7 @@ async function POST21(req) {
|
|
|
25942
25946
|
}
|
|
25943
25947
|
|
|
25944
25948
|
// app/api/admin/logs/route.ts
|
|
25945
|
-
import { existsSync as
|
|
25949
|
+
import { existsSync as existsSync14, readdirSync as readdirSync3, readFileSync as readFileSync14, statSync as statSync3 } from "fs";
|
|
25946
25950
|
import { resolve as resolve12, basename as basename3 } from "path";
|
|
25947
25951
|
var TAIL_BYTES = 8192;
|
|
25948
25952
|
async function GET4(request) {
|
|
@@ -25958,7 +25962,7 @@ async function GET4(request) {
|
|
|
25958
25962
|
if (!dir) continue;
|
|
25959
25963
|
const filePath = resolve12(dir, safe);
|
|
25960
25964
|
try {
|
|
25961
|
-
const content =
|
|
25965
|
+
const content = readFileSync14(filePath, "utf-8");
|
|
25962
25966
|
const headers = { "Content-Type": "text/plain; charset=utf-8" };
|
|
25963
25967
|
if (download) headers["Content-Disposition"] = `attachment; filename="${safe}"`;
|
|
25964
25968
|
return new Response(content, { headers });
|
|
@@ -25984,7 +25988,7 @@ async function GET4(request) {
|
|
|
25984
25988
|
if (!dir) continue;
|
|
25985
25989
|
const filePath = resolve12(dir, fileName);
|
|
25986
25990
|
try {
|
|
25987
|
-
const content =
|
|
25991
|
+
const content = readFileSync14(filePath, "utf-8");
|
|
25988
25992
|
const headers = { "Content-Type": "text/plain; charset=utf-8" };
|
|
25989
25993
|
if (download) headers["Content-Disposition"] = `attachment; filename="${fileName}"`;
|
|
25990
25994
|
return new Response(content, { headers });
|
|
@@ -25996,7 +26000,7 @@ async function GET4(request) {
|
|
|
25996
26000
|
const seen = /* @__PURE__ */ new Set();
|
|
25997
26001
|
const logs = {};
|
|
25998
26002
|
for (const dir of [accountLogDir, LOG_DIR]) {
|
|
25999
|
-
if (!dir || !
|
|
26003
|
+
if (!dir || !existsSync14(dir)) continue;
|
|
26000
26004
|
let files;
|
|
26001
26005
|
try {
|
|
26002
26006
|
files = readdirSync3(dir).filter((f) => f.endsWith(".log"));
|
|
@@ -26006,7 +26010,7 @@ async function GET4(request) {
|
|
|
26006
26010
|
files.filter((f) => !seen.has(f)).map((f) => ({ name: f, mtime: statSync3(resolve12(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).forEach(({ name }) => {
|
|
26007
26011
|
seen.add(name);
|
|
26008
26012
|
try {
|
|
26009
|
-
const content =
|
|
26013
|
+
const content = readFileSync14(resolve12(dir, name));
|
|
26010
26014
|
const tail = content.length > TAIL_BYTES ? content.subarray(content.length - TAIL_BYTES).toString("utf-8") : content.toString("utf-8");
|
|
26011
26015
|
logs[name] = tail.trim() || "(empty)";
|
|
26012
26016
|
} catch {
|
|
@@ -26041,7 +26045,7 @@ async function GET5() {
|
|
|
26041
26045
|
|
|
26042
26046
|
// app/api/admin/attachment/[attachmentId]/route.ts
|
|
26043
26047
|
import { readFile as readFile3, readdir } from "fs/promises";
|
|
26044
|
-
import { existsSync as
|
|
26048
|
+
import { existsSync as existsSync15 } from "fs";
|
|
26045
26049
|
import { resolve as resolve13 } from "path";
|
|
26046
26050
|
async function GET6(req, attachmentId) {
|
|
26047
26051
|
const sessionKey = new URL(req.url).searchParams.get("session_key") ?? "";
|
|
@@ -26056,11 +26060,11 @@ async function GET6(req, attachmentId) {
|
|
|
26056
26060
|
return new Response("Not found", { status: 404 });
|
|
26057
26061
|
}
|
|
26058
26062
|
const dir = resolve13(ATTACHMENTS_ROOT, accountId, attachmentId);
|
|
26059
|
-
if (!
|
|
26063
|
+
if (!existsSync15(dir)) {
|
|
26060
26064
|
return new Response("Not found", { status: 404 });
|
|
26061
26065
|
}
|
|
26062
26066
|
const metaPath = resolve13(dir, `${attachmentId}.meta.json`);
|
|
26063
|
-
if (!
|
|
26067
|
+
if (!existsSync15(metaPath)) {
|
|
26064
26068
|
return new Response("Not found", { status: 404 });
|
|
26065
26069
|
}
|
|
26066
26070
|
let meta3;
|
|
@@ -26086,7 +26090,7 @@ async function GET6(req, attachmentId) {
|
|
|
26086
26090
|
}
|
|
26087
26091
|
|
|
26088
26092
|
// app/api/admin/account/route.ts
|
|
26089
|
-
import { readFileSync as
|
|
26093
|
+
import { readFileSync as readFileSync15, writeFileSync as writeFileSync9 } from "fs";
|
|
26090
26094
|
import { resolve as resolve14 } from "path";
|
|
26091
26095
|
var VALID_CONTEXT_MODES = ["managed", "claude-code"];
|
|
26092
26096
|
async function PATCH(req) {
|
|
@@ -26112,10 +26116,10 @@ async function PATCH(req) {
|
|
|
26112
26116
|
}
|
|
26113
26117
|
const configPath2 = resolve14(account.accountDir, "account.json");
|
|
26114
26118
|
try {
|
|
26115
|
-
const raw2 =
|
|
26119
|
+
const raw2 = readFileSync15(configPath2, "utf-8");
|
|
26116
26120
|
const config2 = JSON.parse(raw2);
|
|
26117
26121
|
config2.contextMode = contextMode;
|
|
26118
|
-
|
|
26122
|
+
writeFileSync9(configPath2, JSON.stringify(config2, null, 2) + "\n", "utf-8");
|
|
26119
26123
|
console.error(`[account-update] contextMode=${contextMode}`);
|
|
26120
26124
|
return Response.json({ ok: true, contextMode });
|
|
26121
26125
|
} catch (err) {
|
|
@@ -26126,14 +26130,14 @@ async function PATCH(req) {
|
|
|
26126
26130
|
|
|
26127
26131
|
// app/api/admin/agents/route.ts
|
|
26128
26132
|
import { resolve as resolve15 } from "path";
|
|
26129
|
-
import { readdirSync as readdirSync4, readFileSync as
|
|
26133
|
+
import { readdirSync as readdirSync4, readFileSync as readFileSync16, existsSync as existsSync16 } from "fs";
|
|
26130
26134
|
async function GET7() {
|
|
26131
26135
|
const account = resolveAccount();
|
|
26132
26136
|
if (!account) {
|
|
26133
26137
|
return Response.json({ agents: [] });
|
|
26134
26138
|
}
|
|
26135
26139
|
const agentsDir = resolve15(account.accountDir, "agents");
|
|
26136
|
-
if (!
|
|
26140
|
+
if (!existsSync16(agentsDir)) {
|
|
26137
26141
|
return Response.json({ agents: [] });
|
|
26138
26142
|
}
|
|
26139
26143
|
const agents = [];
|
|
@@ -26143,9 +26147,9 @@ async function GET7() {
|
|
|
26143
26147
|
if (!entry.isDirectory()) continue;
|
|
26144
26148
|
if (entry.name === "admin") continue;
|
|
26145
26149
|
const configPath2 = resolve15(agentsDir, entry.name, "config.json");
|
|
26146
|
-
if (!
|
|
26150
|
+
if (!existsSync16(configPath2)) continue;
|
|
26147
26151
|
try {
|
|
26148
|
-
const config2 = JSON.parse(
|
|
26152
|
+
const config2 = JSON.parse(readFileSync16(configPath2, "utf-8"));
|
|
26149
26153
|
agents.push({
|
|
26150
26154
|
slug: entry.name,
|
|
26151
26155
|
displayName: config2.displayName ?? entry.name,
|
|
@@ -26163,15 +26167,15 @@ async function GET7() {
|
|
|
26163
26167
|
}
|
|
26164
26168
|
|
|
26165
26169
|
// app/api/admin/version/route.ts
|
|
26166
|
-
import { readFileSync as
|
|
26170
|
+
import { readFileSync as readFileSync17, existsSync as existsSync17 } from "fs";
|
|
26167
26171
|
import { resolve as resolve16, join as join7 } from "path";
|
|
26168
26172
|
var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve16(process.cwd(), "..");
|
|
26169
26173
|
var brandHostname = "maxy";
|
|
26170
26174
|
var brandNpmPackage = "@rubytech/create-maxy";
|
|
26171
26175
|
var brandJsonPath = join7(PLATFORM_ROOT7, "config", "brand.json");
|
|
26172
|
-
if (
|
|
26176
|
+
if (existsSync17(brandJsonPath)) {
|
|
26173
26177
|
try {
|
|
26174
|
-
const brand = JSON.parse(
|
|
26178
|
+
const brand = JSON.parse(readFileSync17(brandJsonPath, "utf-8"));
|
|
26175
26179
|
if (brand.hostname) brandHostname = brand.hostname;
|
|
26176
26180
|
if (brand.npm?.packageName) brandNpmPackage = brand.npm.packageName;
|
|
26177
26181
|
} catch {
|
|
@@ -26184,8 +26188,8 @@ var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
|
26184
26188
|
var FETCH_TIMEOUT_MS = 5e3;
|
|
26185
26189
|
var latestCache = null;
|
|
26186
26190
|
function readInstalled() {
|
|
26187
|
-
if (!
|
|
26188
|
-
const content =
|
|
26191
|
+
if (!existsSync17(VERSION_FILE)) return "unknown";
|
|
26192
|
+
const content = readFileSync17(VERSION_FILE, "utf-8").trim();
|
|
26189
26193
|
return content || "unknown";
|
|
26190
26194
|
}
|
|
26191
26195
|
async function fetchLatest() {
|
|
@@ -26239,15 +26243,15 @@ async function GET8() {
|
|
|
26239
26243
|
|
|
26240
26244
|
// app/api/admin/version/upgrade/route.ts
|
|
26241
26245
|
import { spawn as spawn4 } from "child_process";
|
|
26242
|
-
import { existsSync as
|
|
26246
|
+
import { existsSync as existsSync18, statSync as statSync4, writeFileSync as writeFileSync10, readFileSync as readFileSync18, openSync as openSync2, closeSync as closeSync2 } from "fs";
|
|
26243
26247
|
import { resolve as resolve17, join as join8 } from "path";
|
|
26244
26248
|
var PLATFORM_ROOT8 = process.env.MAXY_PLATFORM_ROOT ?? resolve17(process.cwd(), "..");
|
|
26245
26249
|
var upgradePkg = "@rubytech/create-maxy";
|
|
26246
26250
|
var upgradeHostname = "maxy";
|
|
26247
26251
|
var brandPath = join8(PLATFORM_ROOT8, "config", "brand.json");
|
|
26248
|
-
if (
|
|
26252
|
+
if (existsSync18(brandPath)) {
|
|
26249
26253
|
try {
|
|
26250
|
-
const brand = JSON.parse(
|
|
26254
|
+
const brand = JSON.parse(readFileSync18(brandPath, "utf-8"));
|
|
26251
26255
|
if (brand.npm?.packageName) upgradePkg = brand.npm.packageName;
|
|
26252
26256
|
if (brand.hostname) upgradeHostname = brand.hostname;
|
|
26253
26257
|
} catch {
|
|
@@ -26257,7 +26261,7 @@ var LOCK_FILE = `/tmp/${upgradeHostname}-upgrade.lock`;
|
|
|
26257
26261
|
var LOG_FILE = `/tmp/${upgradeHostname}-upgrade.log`;
|
|
26258
26262
|
var LOCK_MAX_AGE_MS = 3 * 60 * 1e3;
|
|
26259
26263
|
function isLockFresh() {
|
|
26260
|
-
if (!
|
|
26264
|
+
if (!existsSync18(LOCK_FILE)) return false;
|
|
26261
26265
|
try {
|
|
26262
26266
|
const stat3 = statSync4(LOCK_FILE);
|
|
26263
26267
|
return Date.now() - stat3.mtimeMs < LOCK_MAX_AGE_MS;
|
|
@@ -26283,7 +26287,7 @@ async function POST22(req) {
|
|
|
26283
26287
|
return Response.json({ ok: false, error: "upgrade already in progress" }, { status: 409 });
|
|
26284
26288
|
}
|
|
26285
26289
|
try {
|
|
26286
|
-
|
|
26290
|
+
writeFileSync10(LOCK_FILE, String(Date.now()));
|
|
26287
26291
|
} catch (err) {
|
|
26288
26292
|
console.error("[admin/version/upgrade] failed to write lock file:", err);
|
|
26289
26293
|
}
|
|
@@ -26413,12 +26417,12 @@ async function POST23() {
|
|
|
26413
26417
|
var PLATFORM_ROOT9 = process.env.MAXY_PLATFORM_ROOT || "";
|
|
26414
26418
|
var BRAND_JSON_PATH = PLATFORM_ROOT9 ? join9(PLATFORM_ROOT9, "config", "brand.json") : "";
|
|
26415
26419
|
var BRAND = { productName: "Maxy", hostname: "maxy", configDir: ".maxy", domain: "getmaxy.com" };
|
|
26416
|
-
if (BRAND_JSON_PATH && !
|
|
26420
|
+
if (BRAND_JSON_PATH && !existsSync19(BRAND_JSON_PATH)) {
|
|
26417
26421
|
console.error(`[brand] WARNING: brand.json not found at ${BRAND_JSON_PATH} \u2014 using Maxy defaults`);
|
|
26418
26422
|
}
|
|
26419
|
-
if (BRAND_JSON_PATH &&
|
|
26423
|
+
if (BRAND_JSON_PATH && existsSync19(BRAND_JSON_PATH)) {
|
|
26420
26424
|
try {
|
|
26421
|
-
const parsed = JSON.parse(
|
|
26425
|
+
const parsed = JSON.parse(readFileSync19(BRAND_JSON_PATH, "utf-8"));
|
|
26422
26426
|
BRAND = { ...BRAND, ...parsed };
|
|
26423
26427
|
} catch (err) {
|
|
26424
26428
|
console.error(`[brand] Failed to parse brand.json: ${err.message}`);
|
|
@@ -26433,8 +26437,8 @@ var brandLoginOpts = {
|
|
|
26433
26437
|
var ALIAS_DOMAINS_PATH = join9(homedir3(), BRAND.configDir, "alias-domains.json");
|
|
26434
26438
|
function loadAliasDomains() {
|
|
26435
26439
|
try {
|
|
26436
|
-
if (!
|
|
26437
|
-
const parsed = JSON.parse(
|
|
26440
|
+
if (!existsSync19(ALIAS_DOMAINS_PATH)) return null;
|
|
26441
|
+
const parsed = JSON.parse(readFileSync19(ALIAS_DOMAINS_PATH, "utf-8"));
|
|
26438
26442
|
if (!Array.isArray(parsed)) {
|
|
26439
26443
|
console.error("[alias-domains] malformed alias-domains.json \u2014 expected array");
|
|
26440
26444
|
return null;
|
|
@@ -26805,14 +26809,14 @@ app.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
26805
26809
|
console.error(`[agent-assets] path-traversal-rejected slug=${slug} file=${filename}`);
|
|
26806
26810
|
return c.text("Forbidden", 403);
|
|
26807
26811
|
}
|
|
26808
|
-
if (!
|
|
26812
|
+
if (!existsSync19(filePath)) {
|
|
26809
26813
|
console.error(`[agent-assets] serve slug=${slug} file=${filename} status=404`);
|
|
26810
26814
|
return c.text("Not found", 404);
|
|
26811
26815
|
}
|
|
26812
26816
|
const ext = "." + filename.split(".").pop()?.toLowerCase();
|
|
26813
26817
|
const contentType = IMAGE_MIME[ext] || "application/octet-stream";
|
|
26814
26818
|
console.log(`[agent-assets] serve slug=${slug} file=${filename} status=200`);
|
|
26815
|
-
const body =
|
|
26819
|
+
const body = readFileSync19(filePath);
|
|
26816
26820
|
return c.body(body, 200, {
|
|
26817
26821
|
"Content-Type": contentType,
|
|
26818
26822
|
"Cache-Control": "public, max-age=3600"
|
|
@@ -26821,9 +26825,9 @@ app.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
26821
26825
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
26822
26826
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
26823
26827
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
26824
|
-
if (BRAND_JSON_PATH &&
|
|
26828
|
+
if (BRAND_JSON_PATH && existsSync19(BRAND_JSON_PATH)) {
|
|
26825
26829
|
try {
|
|
26826
|
-
const fullBrand = JSON.parse(
|
|
26830
|
+
const fullBrand = JSON.parse(readFileSync19(BRAND_JSON_PATH, "utf-8"));
|
|
26827
26831
|
if (fullBrand.assets?.logo) brandLogoPath = `/brand/${fullBrand.assets.logo}`;
|
|
26828
26832
|
brandIconPath = fullBrand.assets?.icon ? `/brand/${fullBrand.assets.icon}` : brandLogoPath;
|
|
26829
26833
|
} catch {
|
|
@@ -26840,7 +26844,7 @@ var brandScript = `<script>window.__BRAND__=${JSON.stringify({
|
|
|
26840
26844
|
function cachedHtml(file2) {
|
|
26841
26845
|
let html = htmlCache.get(file2);
|
|
26842
26846
|
if (!html) {
|
|
26843
|
-
html =
|
|
26847
|
+
html = readFileSync19(resolve18(process.cwd(), "public", file2), "utf-8");
|
|
26844
26848
|
html = html.replace("</head>", `${brandScript}
|
|
26845
26849
|
</head>`);
|
|
26846
26850
|
htmlCache.set(file2, html);
|
|
@@ -26852,13 +26856,13 @@ function loadBrandingCache(agentSlug) {
|
|
|
26852
26856
|
const configDir2 = join9(homedir3(), BRAND.configDir);
|
|
26853
26857
|
try {
|
|
26854
26858
|
const accountJsonPath = join9(configDir2, "account.json");
|
|
26855
|
-
if (!
|
|
26856
|
-
const account = JSON.parse(
|
|
26859
|
+
if (!existsSync19(accountJsonPath)) return null;
|
|
26860
|
+
const account = JSON.parse(readFileSync19(accountJsonPath, "utf-8"));
|
|
26857
26861
|
const accountId = account.accountId;
|
|
26858
26862
|
if (!accountId) return null;
|
|
26859
26863
|
const cachePath = join9(configDir2, "branding-cache", accountId, `${agentSlug}.json`);
|
|
26860
|
-
if (!
|
|
26861
|
-
return JSON.parse(
|
|
26864
|
+
if (!existsSync19(cachePath)) return null;
|
|
26865
|
+
return JSON.parse(readFileSync19(cachePath, "utf-8"));
|
|
26862
26866
|
} catch {
|
|
26863
26867
|
return null;
|
|
26864
26868
|
}
|
|
@@ -26867,8 +26871,8 @@ function resolveDefaultSlug() {
|
|
|
26867
26871
|
try {
|
|
26868
26872
|
const configDir2 = join9(homedir3(), BRAND.configDir);
|
|
26869
26873
|
const accountJsonPath = join9(configDir2, "account.json");
|
|
26870
|
-
if (!
|
|
26871
|
-
const account = JSON.parse(
|
|
26874
|
+
if (!existsSync19(accountJsonPath)) return null;
|
|
26875
|
+
const account = JSON.parse(readFileSync19(accountJsonPath, "utf-8"));
|
|
26872
26876
|
return account.defaultAgent || null;
|
|
26873
26877
|
} catch {
|
|
26874
26878
|
return null;
|