PageSourceSearch

https://ecopowerhub.ai/assets/MayaAssistant-DaBbEvQJ.js

js ecopowerhub.ai collected 2026-10-05 14:21:51 UTC 62,076 bytes, 188 lines download raw bytes

1const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/html2pdf-AJTdMZZT.js","assets/vendor-react-DR-s3MyR.js","assets/vendor-pdf-B_1lP-ed.js"])))=>i.map(i=>d[i]);
2import{r as y,j as a,o as Le,l as et,u as tt,p as at}from"./vendor-react-DR-s3MyR.js";import{s as nt}from"./serviceNavigation-CsSu5JiE.js";import{s as re,u as je,d as xe,D as st,l as ot,m as rt,n as it,o as lt,L as ue,I as we,p as ct,B as oe,k as De,q as z,t as _,r as dt,v as ne,S as pt,w as U,x as mt,X as ut,y as Oe,T as We,Z as Ve,z as ht,E as Ie,F as se,G as gt,H as ft,J as yt,K as bt,M as wt}from"./App-DrNoFNrD.js";import{d as xt}from"./ServiceNudgesCard-Bu7t0-PC.js";import{c as he,N as vt}from"./workspaceLink-Jbaw8S1a.js";import{h as ge}from"./hopCheck-BK1DYfNP.js";import{T as Ct}from"./textarea-B5ol1VbS.js";import{s as kt}from"./publicForms-h8Zdxil7.js";import{p as ze}from"./projectStore-DMAugxk9.js";import{c as He,l as Ge,f as P}from"./evm-HSDw6rHN.js";import{c as At,a as St}from"./energyKpis-CGXqDbfo.js";import{u as Et}from"./useSubscription-CnE3nUpn.js";import{F as Pt}from"./file-text-CgI-rr2Z.js";import{C as Nt}from"./clipboard-list-kC_QcGR_.js";import{B as jt}from"./bell-ring-B2g6bTSh.js";import{C as It}from"./calendar-Dl-5ucC_.js";import{L as Tt}from"./life-buoy-TncvvKA2.js";import{M as $t}from"./vendor-content-C_INO5qn.js";import{R as Rt}from"./rotate-ccw-DSIREcel.js";import"./wind-DInBKhtm.js";import"./battery-charging-DKuB1_zX.js";import"./users-IaCrOTH_.js";import"./book-open-CG058Lez.js";import"./index-Bku6MSn9.js";import"./vendor-data-BkyUpT8a.js";import"./radix-toast-D0Eg9mYr.js";import"./radix-primitive-BUriELsH.js";import"./radix-slot-DnLuwATg.js";import"./radix-compose-refs-D6dqqAdo.js";import"./radix-collection-30cVg4Vi.js";import"./radix-context-PrlSO5z7.js";import"./radix-dismissable-layer-6HGUYkYJ.js";import"./radix-use-callback-ref-_8_ho4y0.js";import"./radix-use-escape-keydown-ByAYFp_N.js";import"./radix-portal-xSClgmal.js";import"./radix-use-layout-effect-CIo0b4zP.js";import"./radix-presence-BbBgUYEO.js";import"./radix-use-controllable-state-pUF16jyx.js";import"./radix-visually-hidden-CIGFplQ_.js";import"./radix-tooltip-BUM68zcN.js";import"./radix-id-BRVmICFe.js";import"./radix-popper-B0p01UYd.js";import"./radix-arrow-BfTiT5zn.js";import"./radix-use-size-BbCXqNyQ.js";import"./radix-dialog-BeZ4gGxl.js";import"./radix-focus-scope-C7NswZYd.js";import"./radix-focus-guards-arAEqobq.js";import"./radix-label-B4hKXXVP.js";import"./radix-select-D4l0cAFC.js";import"./radix-number-BdQq_4o_.js";import"./radix-direction-CID-gv9T.js";import"./radix-use-previous-D31bNXQt.js";import"./undo-2-cbCStsxR.js";import"./evmStatus-hvXyUzJ_.js";import"./stripe-BaeDzDOG.js";function _t({service:t}){const[e,n]=y.useState([]),i=()=>re.from("service_nudges").select("id,headline,status,action_kind,suggested_technician_id").eq("service",t).in("status",["open","draft"]).limit(3).then(({data:l})=>n(l??[]));if(y.useEffect(()=>{i()},[t]),!e.length)return null;const m=async(l,o)=>{try{await xt(l,o.id),je.success("Saved — undo from the service page"),i()}catch(v){je.error(v instanceof Error?v.message:"Failed")}};return a.jsx("div",{className:"space-y-1.5 border-t border-border/50 px-3 py-2",children:e.map(l=>a.jsxs("div",{className:"flex flex-wrap items-center gap-1.5 text-xs",children:[a.jsx("span",{className:"flex-1 truncate font-medium",children:l.headline}),l.action_kind==="maintenance_draft"&&l.status==="open"&&a.jsx("button",{type:"button",className:"rounded-full border px-2 py-0.5",onClick:()=>m("draft",l),children:"Draft visit"}),l.status==="draft"&&l.suggested_technician_id&&a.jsx("button",{type:"button",className:"rounded-full border px-2 py-0.5",onClick:()=>m("confirm",l),children:"Confirm"}),a.jsx("button",{type:"button",className:"rounded-full border px-2 py-0.5",onClick:()=>m("dismiss",l),children:"Dismiss"})]},l.id))})}function Ft(){var g;const t=y.useSyncExternalStore(he.subscribe,he.get,he.get),e=y.useSyncExternalStore(ge.subscribe,ge.get,ge.get),[n,i]=y.useState(!1),{user:m}=xe(),l=Le(),[o,v]=y.useState([]);return y.useEffect(()=>{if(!m||t){v([]);return}re.from("user_resume_nudges").select("id,headline,service,site_name").eq("user_id",m.id).is("resolved_at",null).limit(3).then(({data:h})=>v(h??[]))},[m,t]),t?a.jsxs("div",{className:"space-y-1.5 border-t border-border/50 px-3 py-2 text-xs",children:[a.jsx("p",{children:vt}),a.jsxs("div",{className:"flex flex-wrap gap-1.5",children:[t.memberships.map(h=>a.jsxs("button",{type:"button",className:"rounded-full border px-2 py-0.5",onClick:()=>t.attach(h.id),children:["Use ",h.name]},h.id)),t.memberships.length===0&&a.jsx("button",{type:"button",className:"rounded-full border px-2 py-0.5",onClick:t.create,children:"Create my workspace"})]})]}):e?a.jsxs("div",{className:"space-y-1.5 border-t border-border/50 px-3 py-2 text-xs","data-code":e.code,children:[a.jsxs("div",{className:"flex flex-wrap gap-1.5",children:[a.jsx("button",{type:"button",className:"rounded-full border px-2 py-0.5",onClick:()=>i(h=>!h),children:"Explain this error"}),a.jsx("button",{type:"button",className:"rounded-full border px-2 py-0.5",onClick:e.retry,children:"Retry this check"}),a.jsx("button",{type:"button",className:"rounded-full border px-2 py-0.5",onClick:()=>l(`/app/${e.service}#nudges`),children:"Open maintenance draft"})]}),n&&a.jsxs("p",{children:[a.jsx("span",{className:"font-mono",children:e.code}),": ",e.message]}),((g=e.networkAdvisory)==null?void 0:g.code)&&a.jsxs("p",{children:[a.jsx("span",{className:"font-mono",children:e.networkAdvisory.code}),": ",e.networkAdvisory.message]})]}):o.length?a.jsx("div",{className:"space-y-1.5 border-t border-border/50 px-3 py-2 text-xs",children:o.map(h=>a.jsx("button",{type:"button",className:"block w-full truncate rounded-md border px-2 py-1 text-left",onClick:()=>l(`/app/connect?service=${h.service}${h.site_name?`&site=${encodeURIComponent(h.site_name)}`:""}`),children:h.headline},h.id))}):null}const Te="data:image/webp;base64,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",$e="data:image/webp;base64,UklGRtYEAABXRUJQVlA4WAoAAAAUAAAAJwAAJwAAQUxQSE4BAAABkCvbtmlb89q2bdu2bVsZQ2f2vc+Ibdu2bduej2vNdb4gIiYACHXdNZTVQbisR+K+u9s3bgxwVBOTtvTWC/z79v1BIwE2LWeR8fvhLLp25NwQJE0j3XaDB/do0jjdRe4PrTR2d/hwmSqFVO9XghsWFDCBhO9SKJTXU7wOp5AeobjvQAGdFLdsSHyvEAxJkUgt5XsdC7RR95h+IuJmJSLo/YmIP1kWALXDQ+QcIFPezlNPBu0c513prNd8ZeoGgaZXWH4UipCaYblgJgJ8nv3vQwWINBh8+79VciKkR5Fxl6GI7DcsOE+BzuUSMn8qozJpPoWcNzJVCKRdus7/RO4PW6vNORRjFz1A2h9XZ+JVGVyXvUOBH7bG/8fsEAq+H/avfhS+UeUv08vi3kf/VfBNHPb/NYsSuEkBQOOoJFw1BnB5Kgmv/QCSvkjCt3QAVlA4INABAABwCgCdASooACgAPmEokEYkIqGhLjQLMIAMCWoAwQ+cxLiau9BmfyBvAPMB0MN423kdG5zVRMA/UBEOpyNK8QijGdy0/yP8m4E5QhjXQ9tUqw7GWCYOyME641jo4AD+/3yB8NZTVge4N2m2XeFgBILFltkrCVdBmUf1X8qc97oHoSkt75nuERdMdX//Xr8y7RhPvdXfoPrMG8HiDWPPJ5EfA+Lt5W2VjX/HFUlucP+zeR3CPl5sNnc/citsXb9O+9zTfg3GQxvU1KWNM9w5qTzUiGw0usZYfQstRfElXfr+bOqR9LO2wYw/lfs3Ecn1zsHyz3//+yA9Vkki+TmO7QSVAoRFI0iozJH559bPURwyuTc+3Med9dyVDrX7fHfgW5bZ7xih8NXXeIPpQydDFu4KMzxRXDFbijqNcZcoaQ5aFqfTPS/kNSuR7SJ7BVUvVARLj8Tc8lTyr5QSFzzx7BC7w3Tbob9OvNXPhHtPu3/6G//2+///9q5ok2Tm2aRTPR4p+rC9UelW5098a6iCrVOZqWVrR2Nwi4A3Mz38zrATbiGtOb9FBU8TXzHjlka3I/n/j0uqc2PFg5qyc6LT1s1uJCf7tvsIqluadfFVxtoQAFhNUCCJAQAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz48eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIj48cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPjxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOklwdGM0eG1wRXh0PSJodHRwOi8vaXB0Yy5vcmcvc3RkL0lwdGM0eG1wRXh0LzIwMDgtMDItMjkvIiBJcHRjNHhtcEV4dDpEaWdpdGFsU291cmNlVHlwZT0iaHR0cDovL2N2LmlwdGMub3JnL25ld3Njb2Rlcy9kaWdpdGFsc291cmNldHlwZS90cmFpbmVkQWxnb3JpdGhtaWNNZWRpYSIvPjwvcmRmOlJERj48L3g6eG1wbWV0YT48P3hwYWNrZXQgZW5kPSJ3Ij8+AA==",Mt=dt({email:ne().trim().email("Enter a valid email").max(320),name:ne().trim().max(100).optional(),topic:ne().trim().max(120).optional(),message:ne().trim().min(5,"Tell us a bit more").max(5e3)});function Lt({open:t,onOpenChange:e,defaultTopic:n="",defaultMessage:i=""}){const{user:m}=xe(),[l,o]=y.useState(!1),[v,g]=y.useState({email:(m==null?void 0:m.email)??"",name:"",topic:n,message:i});y.useEffect(()=>{t&&g(d=>({email:d.email||(m==null?void 0:m.email)||"",name:d.name,topic:n||d.topic,message:i||d.message}))},[t,m,n,i]);const h=async d=>{var x;d.preventDefault();const b=Mt.safeParse(v);if(!b.success){z({title:"Please check your details",description:((x=b.error.issues[0])==null?void 0:x.message)??"Invalid input",variant:"destructive"});return}o(!0);const f=await kt("support_request",{email:b.data.email,name:b.data.name||null,topic:b.data.topic||null,message:b.data.message,path:typeof window<"u"?window.location.pathname:null});if(o(!1),!f.ok){z({title:"Couldn't send",description:f.message??"Please try again in a moment.",variant:"destructive"});return}await _("help_requested",{topic:b.data.topic||null}),z({title:"Help is on the way",description:"We'll reach out by email shortly."}),e(!1),g({email:(m==null?void 0:m.email)??"",name:"",topic:"",message:""})};return a.jsx(st,{open:t,onOpenChange:e,children:a.jsxs(ot,{className:"sm:max-w-md",children:[a.jsxs(rt,{children:[a.jsx(it,{children:"Talk to a human"}),a.jsx(lt,{children:"Send us a note and someone from the team will reply by email."})]}),a.jsxs("form",{onSubmit:h,className:"grid gap-3",children:[a.jsxs("div",{className:"grid gap-1.5",children:[a.jsx(ue,{htmlFor:"sr-email",children:"Email"}),a.jsx(we,{id:"sr-email",type:"email",required:!0,value:v.email,onChange:d=>g({...v,email:d.target.value}),maxLength:320})]}),a.jsxs("div",{className:"grid gap-1.5",children:[a.jsx(ue,{htmlFor:"sr-topic",children:"Topic (optional)"}),a.jsx(we,{id:"sr-topic",placeholder:"e.g. Billing, MarketFlow, Setup",value:v.topic,onChange:d=>
2g({...v,topic:d.target.value}),maxLength:120})]}),a.jsxs("div",{className:"grid gap-1.5",children:[a.jsx(ue,{htmlFor:"sr-message",children:"Message"}),a.jsx(Ct,{id:"sr-message",required:!0,rows:5,value:v.message,onChange:d=>g({...v,message:d.target.value}),maxLength:5e3,placeholder:"What's going on?"})]}),a.jsx(ct,{children:a.jsxs(oe,{type:"submit",disabled:l,children:[l?a.jsx(De,{className:"mr-2 h-4 w-4 animate-spin"}):null,"Send request"]})})]})]})})}function Dt(t,e){return t<.85||e<.85?"Critical":t<1||e<1?"At Risk":"On Track"}function Ot(t){const e=ze.get(t);return e?Wt(e):null}function Wt(t){var H,Q;const e=He(t),n=new Date,i=new Date(t.endDate),m=Math.round((i.getTime()-n.getTime())/864e5),l=t.workPackages.map(w=>{const j=Ge(w);return{id:w.id,name:w.name,bac:w.bac,percentComplete:(j==null?void 0:j.percentComplete)??0,hasUpdates:w.updates.length>0,lastUpdatePeriod:(j==null?void 0:j.period)??null}}),o=[];l.forEach(w=>{if(!w.hasUpdates)o.push(`No status updates yet for "${w.name}"`);else if(w.percentComplete<100&&w.lastUpdatePeriod){const j=Math.round((n.getTime()-new Date(w.lastUpdatePeriod).getTime())/864e5);j>30&&o.push(`"${w.name}" hasn't been updated in ${j} days`)}}),m<30&&e.percentComplete<90&&o.push(`Only ${m} days until target end date — completion is at ${e.percentComplete.toFixed(0)}%`),e.cpi<.9&&o.push(`Cost performance is below target (CPI ${e.cpi.toFixed(2)})`),e.spi<.9&&o.push(`Schedule is slipping (SPI ${e.spi.toFixed(2)})`);const v=((H=l.find(w=>w.percentComplete>0&&w.percentComplete<100))==null?void 0:H.name)??((Q=l.find(w=>w.percentComplete===0))==null?void 0:Q.name)??null,g=[];e.cpi<.95&&e.cpi>0&&g.push(`Cost overrun — CPI ${e.cpi.toFixed(2)}. Forecast EAC ${P(e.eac2)} vs BAC ${P(e.bac)} (VAC ${P(e.vac)}). Re-baseline or trim scope.`),e.tcpi>1.1&&g.push(`TCPI ${e.tcpi.toFixed(2)} — historically aggressive. Tighten change control on remaining work.`),e.cv<0&&Math.abs(e.cv)>.05*e.bac&&g.push(`Cost variance ${P(e.cv)} (>5% of BAC). Review supplier invoices and reallocate contingency.`),e.percentComplete>60&&e.cpi>=1&&g.push("Cost-efficient past 60% complete — consider releasing contingency to scope upside.");const h=[];let d=[];try{const w=At(t);d=w.tasks.filter(F=>F.isCritical).map(F=>F.name),d.length&&h.push(`Critical path (${d.length}): ${d.slice(0,4).join(" → ")}${d.length>4?" …":""}. Any slip here delays the project.`);const j=w.tasks.filter(F=>!F.isCritical&&F.totalFloat<=5);j.length&&h.push(`${j.length} task(s) with ≤5d float at risk of becoming critical: ${j.slice(0,3).map(F=>F.name).join(", ")}.`)}catch{}e.spi<.9&&e.spi>0&&h.push(`SPI ${e.spi.toFixed(2)} — crash critical path or fast-track parallel packages.`),m<60&&e.percentComplete<80&&h.push(`${m}d remaining at ${e.percentComplete.toFixed(0)}% — propose recovery plan or formal extension.`);const b=St(t,e.percentComplete);let f=null;l.forEach(w=>{w.lastUpdatePeriod&&(!f||w.lastUpdatePeriod>f)&&(f=w.lastUpdatePeriod)});const x=f?Math.round((n.getTime()-new Date(f).getTime())/864e5):null,J=x===null||x>=7;return J&&o.unshift(x===null?"No weekly status logged yet — cadence starts this week.":`${x} days since the last status update — weekly cadence is due.`),{projectId:t.id,name:t.name,category:t.category,startDate:t.startDate,endDate:t.endD
2ate,daysRemaining:m,percentComplete:Math.round(e.percentComplete),cpi:Number(e.cpi.toFixed(2)),spi:Number(e.spi.toFixed(2)),health:Dt(e.cpi,e.spi),workPackages:l,pendingItems:o,nextMilestone:v,financialRecs:g,scheduleRecs:h,criticalPath:d,estCO2TonsAnnual:Number(b.carbonAvoidedTonsAnnual.toFixed(1)),forecastEAC:Math.round(e.eac2),vac:Math.round(e.vac),daysSinceLastUpdate:x,weeklyStatusSuggested:J,bac:Math.round(e.bac),pv:Math.round(e.pv),ev:Math.round(e.ev),ac:Math.round(e.ac),eac1:Math.round(e.eac1),eac2:Math.round(e.eac2),eac3:Math.round(e.eac3),tcpi:Number.isFinite(e.tcpi)?Number(e.tcpi.toFixed(2)):NaN}}function Vt(t){const e=t.workPackages.map(o=>`  - ${o.name}: ${o.percentComplete}% complete${o.hasUpdates?"":" (no updates yet)"}`).join(`
3`),n=t.pendingItems.length?t.pendingItems.map(o=>`  - ${o}`).join(`
4`):"  - (none detected)",i=t.financialRecs.length?t.financialRecs.map(o=>`  - ${o}`).join(`
5`):"  - (none)",m=t.scheduleRecs.length?t.scheduleRecs.map(o=>`  - ${o}`).join(`
6`):"  - (none)",l=Number.isFinite(t.tcpi)?t.tcpi.toFixed(2):"—";return`ACTIVE PROJECT CONTEXT (use this to be proactive, cite exact numbers, and support EVM & what-if questions):
7- Name: ${t.name}
8- Category: ${t.category}
9- Overall completion: ${t.percentComplete}%
10- Health: ${t.health} (CPI ${t.cpi}, SPI ${t.spi}, TCPI ${l})
11- EVM snapshot (USD): BAC $${t.bac.toLocaleString()} · PV $${t.pv.toLocaleString()} · EV $${t.ev.toLocaleString()} · AC $${t.ac.toLocaleString()}
12- Forecast: EAC₁ $${t.eac1.toLocaleString()} · EAC₂ $${t.eac2.toLocaleString()} · EAC₃ $${t.eac3.toLocaleString()} · VAC $${t.vac.toLocaleString()}
13- Days until target end date: ${t.daysRemaining}
14- Days since last status update: ${t.daysSinceLastUpdate??"never"}${t.weeklyStatusSuggested?"  ← weekly status is DUE — offer the one-click PDF":""}
15- Next milestone: ${t.nextMilestone??"—"}
16- Critical path: ${t.criticalPath.length?t.criticalPath.slice(0,5).join(" → "):"(not computed)"}
17- Estimated CO₂ avoided / yr: ${t.estCO2TonsAnnual} t
18- Work packages:
19${e}
20- Pending items / risks:
21${n}
22- FINANCIAL RECOMMENDATIONS (cite when answering money/budget/cost questions):
23${i}
24- SCHEDULE RECOMMENDATIONS (cite when answering schedule/critical-path questions):
25${m}
26- WHAT-IF GUIDANCE: When the user asks "what if" / "scenario" / "if I change …", compute the impact using these numbers and the standard EVM formulas (CPI=EV/AC, SPI=EV/PV, EAC₁=AC+(BAC−EV), EAC₂=BAC/CPI, EAC₃=AC+(BAC−EV)/(CPI×SPI), TCPI=(BAC−EV)/(BAC−AC), VAC=BAC−EAC). Show the delta vs current, then suggest the "Open scenario simulator" button.
27- WEEKLY STATUS GUIDANCE: If weekly status is due, proactively offer to generate the PDF via the "Generate weekly status PDF" action.`}function Re(t){const e=t.pendingItems.length,n=[`👋 Welcome back to **${t.name}**.`,"",`You're **${t.percentComplete}% complete** — health is **${t.health}** (CPI ${t.cpi}, SPI ${t.spi}), with **${t.daysRemaining} days** to your target end date.`];return e>0?(n.push("",`I'm tracking **${e} item${e===1?"":"s"}** that need attention:`),t.pendingItems.slice(0,4).forEach(i=>n.push(`- ${i}`))):n.push("","✅ Nothing flagged right now — you're in a clean state."),t.nextMilestone&&n.push("",`**Suggested next focus:** ${t.nextMilestone}.`),t.weeklyStatusSuggested&&n.push("",`🗓️ **Weekly status is due** — just say *"generate my weekly status PDF"* and I'll build it in one click.`),n.push("","What would you like to do?"),n.join(`
28`)}function zt(t){const e=["What should I do next?","Draft a status report"];t.weeklyStatusSuggested&&e.unshift("Generate my weekly status PDF"),t.financialRecs.length&&e.push("Explain my financial risks"),t.scheduleRecs.length&&e.push("Walk me through the critical path"),t.pendingItems.length>0&&e.unshift("Walk me through the pending items"),t.spi<1&&e.push("How do I recover the schedule?"),t.cpi<1&&e.push("How do I cut cost overrun?"),e.push("What if AC rises 10% next month?");const n=t.category.toLowerCase();return/solar|microgrid|mixed|hybrid|storage/.test(n)&&e.push("Optimize HVAC alongside my solar array for max savings"),Array.from(new Set(e)).slice(0,5)}const Ht="/assets/inverter-exterior-cover-CzNDHqio.jpg",Gt="/assets/gateway-internals-LRNQI92d.jpg",Bt="/assets/inverter-cooling-fan-COeEsEDT.jpg",Ut=[{id:"tesla-powerwall-inverter-cover",vend
28or:"Tesla",product:"Powerwall 3",component:"Inverter exterior cover",photoUrl:Ht,visualCues:["Smooth white shell, wall-mounted, typically on exterior siding","Arc-flash warning label and Tesla serial plate on right edge","Small LED status window (solid green = normal, red = fault)"],commonFaults:["Loose wall bracket — vibration cracks internal solder joints","Faded/peeling serial plate — blocks warranty claims","Red LED indicates fault; do not open, check the Gateway first"],diyNextSteps:["Photograph the serial plate now for warranty records","Rock the top corners; if it moves, re-anchor before winter","Check the Tesla app for a specific error code before opening anything"],safetyStops:["Do not remove the cover if the LED is red or the unit is warm to the touch"],relatedGuide:"/blog/tesla-gateway-inverter-diy-troubleshooting"},{id:"tesla-backup-gateway-comms-board",vendor:"Tesla",product:"Backup Gateway 2",component:"Comms board (LTE + Wi-Fi)",photoUrl:Gt,visualCues:["Green PCB with a silver CR2032 coin-cell battery","Combined LTE + Wi-Fi module in the top-right corner","Ribbon connector to CT (current transformer) harness"],partNumbers:["1112484-14-A"],commonFaults:["Gateway offline in Tesla app — usually Wi-Fi/LTE radio or upstream router","Clock keeps resetting after power loss — dead CR2032 RTC battery","Powerwall reports flow in the wrong direction — CT clamp slipped off busbar"],diyNextSteps:["Power-cycle the Gateway breaker: off 60 s, on, wait 5 min (fixes 70% of comms faults)","Swap the CR2032 coin battery (~$2 at any pharmacy)","Reseat CT clamps around the main panel busbars — snap-fit, no tools"],safetyStops:["No LED on the LTE/Wi-Fi module = radio dead, file warranty; do not desolder"],relatedGuide:"/blog/tesla-gateway-inverter-diy-troubleshooting"},{id:"tesla-powerwall-cooling-fan",vendor:"Tesla",product:"Powerwall 3",component:"Delta cooling fan + liquid loop",photoUrl:Bt,visualCues:["120 mm server-grade fan mounted to a copper cold-plate","Sealed glycol lines wrapping the IGBT stack","4-pin PWM connector on the fan pigtail"],partNumbers:["Delta PFR1212DHE"],commonFaults:["Inverter throttles above 85 °F ambient (app: 'Power Limit Reason: Thermal')","Audible grinding or ticking = worn fan bearing","Fan not spinning through vents = dead fan or blown PWM driver"],diyNextSteps:["Replacement Delta PFR1212DHE fans run ~$45; standard 4-pin PWM swap","Shut down PV, AC, and wait 5 min before opening the shroud","Add a $30 aluminum sun-shade if the inverter faces west sun"],safetyStops:["Do not touch copper cooling-loop fittings — a leak is a factory-return job"],relatedGuide:"/blog/tesla-gateway-inverter-diy-troubleshooting"},{id:"tesla-powerwall-wiring-compartment",vendor:"Tesla",product:"Powerwall 3",component:"AC/DC wiring compartment",photoUrl:"/__l5e/assets-v1/daaff78b-5c08-4b5a-9465-b3221d5134e4/tesla-powerwall-wiring.jpeg",visualCues:["Orange rotary DC isolator (NEC 690.12 rapid-shutdown)","AC terminal block with L1/L2/N and equipment ground","Six MPPT PV terminals across three independent channels","Green ground bar along the bottom"],commonFaults:["One PV string reads flat in the app — bad MC4 on the roof or dead MPPT channel","'Terminal overheat' warning — loose AC lug (retorque to 35 in-lb)","Persistent ground fault — CT harness or PV wire abrasion"],diyNextSteps:["Rotate orange DC isolator to OFF before measuring anything","Multimeter across dead string: 0 V = broken cable; ~380 V = MPPT channel (warranty)","Retorque every AC lug to 35 in-lb every 24 months"],safetyStops:["Never open this compartment without shutting PV, AC, and waiting 5 min for capacitors","Stop immediately on any arc-flash burn marks — call a certified installer"],relatedGuide:"/blog/tesla-gateway-inverter-diy-troubleshooting"}];function Jt(){return`HARDWARE RECOGNITION KB (when a homeowner describes or uploads a photo matching these cues, identify the component by name+PN, then lead with DIY next steps and cite the guide link. Always surface Safety stops first if they apply.):
29
30${Ut.map(e=>{var i;const n=(i=e.partNumbers)!=null&&i.length?` [PN: ${e.partNumbers.join(", ")}]`:"";return[`## ${e.vendor} ${e.product} — ${e.component}${n}`,`Photo: ${e.photoUrl}`,`Visual cues: ${e.visualCues.join("; ")}`,`Common faults: ${e.commonFaults.join("; ")}`,`DIY next steps: ${e.diyNextSteps.join("; ")}`,`Safety stops: ${e.safetyStops.join("; ")}`,`Guide: ${e.relatedGuide}`].join(`
31`)}).join(`
32
33`)}`}const Qt=[{name:"EcoPowerHub.ai",url:"https://ecopowerhub.ai",summary:"Decentralized energy OS and virtual power plant for solar, HVAC, storage and generators.",capabilities:["Solar arrays, HVAC, generators, storage, IoT / FixGrid","Trading hooks and VPP aggregation path toward the ICP solar_shard canister","Site lifecycle from intake through live reporting","Modbus/SCADA-style ingestion, offline buffering and commissioning checks"]},{name:"EcoService OS",url:"https://ecoserviceos.ecopowerhub.ai",summary:"AI field service softw
33are for crews working on land, sea and air assets.",capabilities:["Work orders and crew dispatch","Field commissioning and QR install flows","Trial capture for new companies","AffiliateGrid partner program at https://ecoserviceos.ecopowerhub.ai/affiliates"]},{name:"MarketFlow AI",url:"https://marketflow.ecopowerhub.ai",summary:"The marketing, commerce and content sibling in the family. It is not an HVAC company and not a city AI agency.",capabilities:["Campaign, commerce and content workflows","Shares billing and integration plumbing with the family"]},{name:"EcoPowerHub Academy",url:"https://ecopowerhub.ai/academy",summary:"Technician and operator training in exactly four tracks.",capabilities:["United States — NATE, EPA 608, PV certification language","East Africa","South Africa","Shared core"]},{name:"Integration Hub",url:"https://ecopowerhub.ai/app/integrations",summary:"The single integration layer for the family: staff at /admin/integration-hub, tenants at /app/integrations.",capabilities:["Live connectors: Stripe Connect, Twilio, Resend, QuickBooks","Workspace-bound customer import and export (SDK 0.2.1)","HMAC eph_ scoped, revocable API keys"]},{name:"Campus Packet",url:"https://ecopowerhub.ai/solutions/campus-packet",summary:"Bid-packet software for EPC, ESCO and MEP firms; the signed-in workspace is at /campus-packet.",capabilities:["Load registry and 15-minute interval summary","Shed sequence: HVAC pre-cool, battery discharge, then generator started manually","Commissioning appears only when a site is linked","Campus model, auction record and setpoint queue; say a section is empty when it has no rows","EcoPowerHub is the software vendor; the EPC or MEP remains engineer of record; the product does not replace the BMS"]}],Yt=["intake","audit","provision","field commissioning","mock live","pilot report","live/reporting"],Xt=["The public solar_shard getPublicStats currently reports totalArrays 0. Sites connect through the site lifecycle and public stats appear once arrays are registered.",'Never quote kW totals, device counts, indexed arrays above zero, or claims like "10k devices on mainnet".',"Tesla and Powerwall support is stubs and future VPP hooks only — there is no live auction running.","Edge ingestion, offline buffering and commissioning checks are product capabilities, not evidence that a named customer site is already streaming.","An empty /sites list after reload is valid — never pretend a fleet exists.","Do not claim HubSpot, Salesforce or an official Tesla API integration.","Do not promise Play Store production availability while the listing is in Internal Testing.",'Never send anyone to an "AI digital marketing agency in {city}" page — energy city pages are energy OS pages.',"For Campus Packet, never say an auction is live and never describe the campus model as a digital twin.","For Campus Packet, do not claim OpenADR, BACnet write or Tesla is connected. Point to the packet sections that exist and say a section is empty when it has no rows."],Zt="AffiliateGrid pays partners 8% commission. Recurring commission runs for the first 3 months only, or a partner can take a one-time 8% payout once.";function qt(){return["ECOPOWERHUB FAMILY (use these names exactly)",Qt.map(e=>`- **${e.name}** (${e.url}) — ${e.summary}
34  ${e.capabilities.map(n=>`• ${n}`).join(`
35  `)}`).join(`
36`),"",`SITE LIFECYCLE (routes under /sites): ${Yt.join(" → ")}. Field commissioning writes commissioning_checks; mock live writes device_readings.`,"",`AFFILIATEGRID: ${Zt}`,"","HONESTY RULES — never break these:",Xt.map(e=>`- ${e}`).join(`
37`)].join(`
38`)}function fe(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}const ye=t=>Number.isFinite(t)&&t>0?t.toFixed(2):"—";function Kt(t,e){return t<.85||e<.85?{color:"#b91c1c",label:"Critical",bg:"#fef2f2"}:t<1||e<1?{color:"#b45309",label:"At Risk",bg:"#fffbeb"}:{color:"#15803d",label:"On Track",bg:"#ecfdf5"}}function ea(t){const e=He(t),n=Kt(e.cpi,e.spi),i=new Date,m=new Date(t.endDate),l=Math.round((m.getTime()-i.getTime())/864e5),o=i.toISOString().slice(0,10),v=t.workPackages.map(d=>{const b=Ge(d),f=(b==null?void 0:b.percentComplete)??0,x=d.updates.reduce((Q,w)=>Q+w.actualCost,0),J=f/100*d.bac,H=f>=90?"#15803d":f>=50?"#0369a1":f>0?"#b45309":"#94a3b8";return`
39      <tr>
40        <td style="padding:6px 8px;border-bottom:1px solid #e2e8f0;font-size:11px;">
40${fe(d.name)}</td>
41        <td style="padding:6px 8px;border-bottom:1px solid #e2e8f0;font-size:11px;text-align:right;font-variant-numeric:tabular-nums;">${P(d.bac)}</td>
42        <td style="padding:6px 8px;border-bottom:1px solid #e2e8f0;font-size:11px;text-align:right;font-variant-numeric:tabular-nums;">${P(J)}</td>
43        <td style="padding:6px 8px;border-bottom:1px solid #e2e8f0;font-size:11px;text-align:right;font-variant-numeric:tabular-nums;">${P(x)}</td>
44        <td style="padding:6px 8px;border-bottom:1px solid #e2e8f0;font-size:11px;">
45          <div style="display:flex;align-items:center;gap:6px;">
46            <div style="flex:1;height:6px;background:#e2e8f0;border-radius:3px;overflow:hidden;"><div style="width:${Math.min(100,Math.max(0,f))}%;height:100%;background:${H};"></div></div>
47            <span style="font-variant-numeric:tabular-nums;color:#334155;">${f.toFixed(0)}%</span>
48          </div>
49          <div style="font-size:9px;color:#94a3b8;margin-top:2px;">Last: ${(b==null?void 0:b.period)??"never"}</div>
50        </td>
51      </tr>`}).join(""),g=(d,b,f)=>`
52    <div style="border:1px solid #e2e8f0;border-radius:6px;padding:10px 12px;background:#f8fafc;">
53      <div style="font-size:9px;letter-spacing:0.12em;text-transform:uppercase;color:#64748b;font-weight:700;">${d}</div>
54      <div style="font-size:16px;font-weight:700;color:#0f172a;font-variant-numeric:tabular-nums;margin-top:4px;">${b}</div>
55      <div style="font-size:10px;color:#64748b;margin-top:2px;">${f}</div>
56    </div>`,h=(d,b,f)=>{const x=f==="success"?"#15803d":f==="warning"?"#b45309":"#b91c1c";return`<span style="display:inline-block;padding:3px 10px;border-radius:999px;background:${x}18;color:${x};font-size:11px;font-weight:600;">${d} ${b}</span>`};return`
57    <div style="font-family:Inter,system-ui,Arial,sans-serif;color:#0f172a;background:#ffffff;padding:28px 32px;width:794px;box-sizing:border-box;">
58      <header style="border-bottom:2px solid #059669;padding-bottom:14px;margin-bottom:18px;display:flex;justify-content:space-between;align-items:flex-end;gap:16px;">
59        <div>
60          <div style="font-size:10px;letter-spacing:0.18em;text-transform:uppercase;color:#64748b;font-weight:700;">EcoPowerHub · Weekly EVM Status</div>
61          <div style="font-size:20px;font-weight:700;margin-top:4px;">${fe(t.name)}</div>
62          <div style="font-size:12px;color:#475569;">Category: <strong>${fe(t.category)}</strong> · Period ending: <strong>${o}</strong> · ${l}d to target end</div>
63        </div>
64        <div style="text-align:right;font-size:10px;color:#64748b;">
65          Generated<br/><strong style="color:#0f172a;">${i.toLocaleString()}</strong>
66        </div>
67      </header>
68
69      <section style="margin-bottom:14px;padding:12px 14px;background:${n.bg};border:1px solid ${n.color}55;border-left:4px solid ${n.color};border-radius:6px;">
70        <div style="display:flex;justify-content:space-between;align-items:center;gap:10px;flex-wrap:wrap;">
71          <div style="font-size:14px;font-weight:700;color:${n.color};">Project health: ${n.label}</div>
72          <div style="display:flex;gap:6px;flex-wrap:wrap;">
73            ${h("CPI",ye(e.cpi),e.cpi>=1?"success":e.cpi>=.85?"warning":"destructive")}
74            ${h("SPI",ye(e.spi),e.spi>=1?"success":e.spi>=.85?"warning":"destructive")}
75            ${h("TCPI",ye(e.tcpi),Number.isFinite(e.tcpi)&&e.tcpi<=1?"success":e.tcpi<=1.1?"warning":"destructive")}
76            ${h("% Complete",e.percentComplete.toFixed(0)+"%","success")}
77          </div>
78        </div>
79      </section>
80
81      <section style="margin-bottom:18px;">
82        <div style="font-size:11px;font-weight:700;letter-spacing:0.12em;text-transform:uppercase;color:#059669;margin-bottom:8px;">EVM Snapshot</div>
83        <div style="display:grid;grid-template-columns:repeat(4,1fr);gap:8px;">
84          ${g("PV",P(e.pv),"Planned Value")}
85          ${g("EV",P(e.ev),"Earned Value")}
86          ${g("AC",P(e.ac),"Actual Cost")}
87          ${g("BAC",P(e.bac),"Budget at Completion")}
88          ${g("CV",P(e.cv),"EV − AC")}
89          ${g("SV",P(e.sv),"EV − PV")}
90          ${g("EAC₂",P(e.eac2),"BAC ÷ CPI")}
91          ${g("VAC",P(e.vac),"BAC − EAC")}
92        </div>
93      </section>
94
95      <section style="margin-bottom:18px;">
96        <div style="font-size:11px;font-weight:700;letter-spacing:0.12em;text-transform:uppercase;color:#059669;margin-bottom:8px;">Forecast Variants</div>
97        <div style="display:grid;grid-template-columns:repeat(3,1fr);gap:8px;">
98          ${g("EAC₁",P(e.eac1),"AC + (BAC−EV) · atypical")}
99          ${g("EAC₂",P(e.eac2),"BAC ÷ CPI · typical")}
100          ${g("EAC₃",P(e.eac3),"Cost & schedule pressure")}
101        </div>
102      </section>
103
104      <section style="margin-bottom:18px;">
105        <div style="font-size:11px;font-weight:700;letter-spacing:0.12em;text-transform:uppercase;color:#059669;margin-bottom:8px;">Work Packages</div>
106        <table style="width:100%;border-collapse:collapse;">
107          <thead>
108            <tr style="background:#f1f5f9;">
109              <th style="text-align:left;padding:6px 8px;font-size:10px;text-transform:uppercase;letter-spacing:0.08em;color:#475569;">Package</th>
110              <th style="text-align:right;padding:6px 8px;font-size:10px;text-transform:uppercase;letter-spacing:0.08em;color:#475569;">BAC</th>
111              <th style="text-align:right;padding:6px 8px;font-size:10px;text-transform:uppercase;letter-spacing:0.08em;color:#475569;">EV</th>
112              <th style="text-align:right;padding:6px 8px;font-size:10px;text-transform:uppercase;letter-spacing:0.08em;color:#475569;">AC</th>
113              <th style="text-align:left;padding:6px 8px;font-size:10px;text-transform:uppercase;letter-spacing:0.08em;color:#475569;">Progress</th>
114            </tr>
115          </thead>
116          <tbody>${v||'<tr><td colspan="5" style="padding:10px;text-align:center;color:#94a3b8;font-size:11px;">No work packages yet.</td></tr>'}</tbody>
117        </table>
118      </section>
119
120      <footer style="margin-top:18px;padding-top:10px;border-top:1px solid #e2e8f0;display:flex;justify-content:space-between;font-size:9px;color:#94a3b8;letter-spacing:0.08em;text-transform:uppercase;">
121        <span>EcoPowerHub.ai · Weekly Status · Confidential</span>
122        <span>Generated by Maya Co-Pilot</span>
123      </footer>
124    </div>
125  `}async function ta(t){const e=ea(t),n=document.createElement("div");n.style.cssText="position:fixed;left:-10000px;top:0;z-index:-1;",n.innerHTML=e,document.body.appendChild(n);try{const i=(await et(async()=>{const{default:l}=await import("./html2pdf-AJTdMZZT.js").then(o=>o.h);return{default:l}},__vite__mapDeps([0,1,2]))).default,m=`${t.name}-${new Date().toISOString().slice(0,10)}`.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"");await i().set({margin:[8,8,10,8],filename:`weekly-status-${m}.pdf`,image:{type:"jpeg",quality:.98},html2canvas:{scale:2,useCORS:!0,backgroundColor:"#ffffff"},jsPDF:{unit:"mm",format:"a4",orientation:"portrait"},pagebreak:{mode:["css","legacy"]}}).from(n.firstElementChild).save()}finally{n.remove()}}const aa="https://vntarrsbyecpsbjsvxgr.supabase.co/functions/v1/maya-chat",Be="maya.history.v1.",_e="maya.size.v1",Fe="maya.complianceMode.v1",Me={role:"assistant",content:`Hi, I'm **Maya** — your EcoPowerHub energy co-pilot. ✨
126
127I know the whole family: the energy OS and VPP here, **EcoService OS** for field crews, **MarketFlow AI** for marketing, the four **Academy** tracks and the **Integration Hub** (Stripe Connect, Twilio, Resend, QuickBooks).
128
129Bringing a system online? Sites move through **intake → audit → provision → field commissioning → mock live → pilot report → live/reporting** under **/sites**. Start on the **Connect hub** (/connect), then sign in at **/auth?next=/sites**.`},na=["Walk me through connecting a site","What is EcoService OS vs EcoPowerHub?","How does the VPP path work?","Which Academy track do I need?","What integrations are live?","How does AffiliateGrid pay?"],sa=[{label:"Weekly status PDF",prompt:"Generate my weekly status PDF for this project.",icon:Oe},{label:"What-if scenario",prompt:"Run a what-if scenario on my EVM numbers (e.g. cost or schedule pressure).",icon:We},{label:"Draft status report",prompt:"Draft a concise weekly status report for this project I can share with stakeholders.",icon:Pt},{label:"Next milestone checklist",prompt:"Generate a checklist for my next milestone based on the current project state.",icon:Nt},{label:"Create reminder",prompt:"Suggest a reminder I should set this week, and what it should say.",icon:jt},{label:"Book support call",prompt:"I'd like to book a support call with the EcoPowerHub team.",icon:It}];function oa(t){try{const e=localStorage.getItem(Be+t);if(!e)return null;const n=JSON.parse(e);return Array.isArray(n)?n.filter(i=>
129i&&(i.role==="user"||i.role==="assistant")&&typeof i.content=="string"):null}catch{return null}}function ra(t,e){try{localStorage.setItem(Be+t,JSON.stringify(e.slice(-40)))}catch{}}function mn(){var ve,Ce;const[t,e]=y.useState(!1),[n,i]=y.useState([Me]),[m,l]=y.useState(""),[o,v]=y.useState(!1),[g,h]=y.useState(!1),[d,b]=y.useState(null),[f,x]=y.useState(()=>{try{return localStorage.getItem(Fe)==="1"}catch{return!1}}),{isTrialing:J,trialDaysLeft:H}=Et(),{user:Q}=xe(),w=J&&H!==null?`User is on a paid-plan free trial. Days remaining: ${H}. Card on file; auto-billing begins after trial. Never call it a "Day 1 Sovereign Premium trial" and never make a trial pitch the answer to a connect question.`:null,j=y.useRef(null),F=y.useRef(null),ie=y.useRef(null),[Y,Ue]=y.useState(()=>{try{const r=localStorage.getItem(_e);if(r){const p=JSON.parse(r);if(p&&typeof p.w=="number"&&typeof p.h=="number")return p}}catch{}return{w:420,h:660}});y.useEffect(()=>{try{localStorage.setItem(_e,JSON.stringify(Y))}catch{}},[Y]);const q=tt(),K=at(),le=Le(),I=y.useMemo(()=>{const r=K.pathname.match(/^\/projects\/([^/?#]+)/);return(r==null?void 0:r[1])??(q==null?void 0:q.id)??null},[K.pathname,q]),s=y.useMemo(()=>I?Ot(I):null,[I,t]),ce=y.useMemo(()=>{var r;return((r=nt(K.pathname))==null?void 0:r.key)??null},[K.pathname]),G=I??"general",Je=s?zt(s):na,[ee,Qe]=y.useState(null),Ye=(ve=ee==null?void 0:ee.quickReplies)!=null&&ve.length?ee.quickReplies:Je;y.useEffect(()=>{const r=()=>e(!0),p=u=>{const A=u.detail;A!=null&&A.message&&(Qe(A),i($=>{const M=$[$.length-1];return(M==null?void 0:M.role)==="assistant"&&M.content===A.message?$:[...$,{role:"assistant",content:A.message}]})),e(!0)};return window.addEventListener("maya:open",r),window.addEventListener("maya:openWith",p),()=>{window.removeEventListener("maya:open",r),window.removeEventListener("maya:openWith",p)}},[]);const[de,Xe]=y.useState(null);y.useEffect(()=>{if(!t||de)return;let r=!1;return(async()=>{const{data:p}=await re.from("oem_families").select("manufacturer, family, protocol_pack, vpp_eligible").order("manufacturer");!r&&(p!=null&&p.length)&&Xe(p)})(),()=>{r=!0}},[t,de]),y.useEffect(()=>{t&&_("maya_opened",{project_id:I??null})},[t,I]),y.useEffect(()=>{const r=requestAnimationFrame(()=>{const p=j.current;p&&p.scrollTo({top:p.scrollHeight,behavior:"smooth"})});return()=>cancelAnimationFrame(r)},[n,o]),y.useEffect(()=>{const r=oa(G);if(r&&r.length){if(i(r),s&&ie.current!==G){ie.current=G;const p=r[r.length-1];(p==null?void 0:p.role)==="assistant"&&/Welcome back/i.test(p.content)||i(A=>[...A,{role:"assistant",content:Re(s)}])}return}s?(ie.current=G,i([{role:"assistant",content:Re(s)}])):i([Me])},[G,s]),y.useEffect(()=>{ra(G,n)},[n,G]);const te=async(r,p)=>{const u=r.trim();if(!u||o)return;const A=p??n;/book.*support call|talk to (a )?human/i.test(u)&&h(!0);const $="hvac|thermostat|ac unit|a\\/c|air ?con(?:ditioner)?|heat ?pump|mini ?split|furnace|boiler|solar|inverter|battery|storage|generator|ev ?charger|charger|meter|sub-?meter|system|device|bridge|gateway|hub|controller|nest|ecobee|honeywell|sensi|tado|carrier|trane|lennox|rheem|daikin|mitsubishi|lg|bosch|enphase|solaredge|tesla|fronius|sungrow|huawei|generac",M="connect|reconnect|pair|re-?pair|link|re-?link|hook ?up|set ?up|setup|install|onboard|add|register|enroll|activate|configure|bring online|get.*online|integrate|sync";if(new RegExp(`\\b(?:${M})\\b[\\s\\S]{0,40}\\b(?:${$})\\b`,"i").test(u)||new RegExp(`\\b(?:${$})\\b[\\s\\S]{0,30}\\b(?:won.?t|will not|can.?t|cannot|not|isn.?t|is not|never|keeps|stopped)\\b[\\s\\S]{0,20}\\b(?:connect|connecting|connected|pair|pairing|paired|online|link|sync)\\b`,"i").test(u)||new RegExp(`\\b(?:${$})\\b[\\s\\S]{0,20}\\b(?:offline|unpaired|disconnected|unreachable|not showing)\\b`,"i").test(u)||/\b(connect|pair|link|onboard)\s+(my\s+)?(system|device|bridge|hvac|thermostat|inverter|battery|solar)\b/i.test(u)){const N=Ie(u)??se.how_to_connect,c=gt.map(C=>`${C.step}. **${C.title}** — ${C.detail}`).join(`
130`),S=`${N.answer}
131
132**The path, end to end:**
133${c}
134
135${ft}
136
137Start here: ${N.href??yt} — then sign in at ${bt}.`;i(C=>[...p??C,{role:"user",content:u},{role:"assistant",content:S+`
138
139[__CONNECT_CTA__]`}]),l(""),_("maya_message_sent",{project_id:I??null,intent:"connect_device"});return}const ae=/\bdraft\b/i.test(u);if(!!I&&!ae&&(/\bweekly status (pdf|packet)\b/i.test(u)||/\bstatus (pdf|packet)\b/i.test(u)||/\b(generate|create|export|download|send|build)\b[\s\S]{0,20}\b(weekly status|status pdf|status packet|status report pdf)\b/i.test(u)||/\b(generate|export|download)\b[\s\S]{0,20}\bweekly (status|report|update|packet)\b/i.test(u))&&s){const N=`📄 **Weekly status packet — one click away.**
140
141Snapshot for **${s.name}** (period ending today): **${s.percentComplete}% complete**, health **${s.health}** (CPI ${s.cpi}, SPI ${s.spi}
141), forecast EAC $${s.forecastEAC.toLocaleString()} vs BAC $${s.bac.toLocaleString()} (VAC $${s.vac.toLocaleString()}).
142
143`+(s.pendingItems.length?`**Flagged this week:**
144${s.pendingItems.slice(0,4).map(c=>`- ${c}`).join(`
145`)}
146
147`:`✅ Nothing flagged for this week.
148
149`)+`Tap the button to download the signed PDF you can share with stakeholders. 👇
150
151[__WEEKLY_STATUS_CTA__:${I}]`;i(c=>[...p??c,{role:"user",content:u},{role:"assistant",content:N}]),l(""),_("maya_message_sent",{project_id:I,intent:"weekly_status"});return}if(!!I&&/\b(what[- ]?if|scenario|simulate|forecast if|if (i|we) (change|cut|raise|drop|add|remove|delay|accelerate|slip|extend|shorten)|hypothetical)\b/i.test(u)&&s){const N=Number.isFinite(s.tcpi)?s.tcpi.toFixed(2):"—",c=`🔮 **What-if scenario — let's model it.**
152
153Current baseline for **${s.name}**:
154- BAC **$${s.bac.toLocaleString()}** · EV **$${s.ev.toLocaleString()}** · AC **$${s.ac.toLocaleString()}**
155- CPI **${s.cpi}** · SPI **${s.spi}** · TCPI **${N}**
156- EAC₁ **$${s.eac1.toLocaleString()}** · EAC₂ **$${s.eac2.toLocaleString()}** · EAC₃ **$${s.eac3.toLocaleString()}**
157
158Describe the change (e.g. *"AC rises 10% next month"*, *"schedule slips 2 weeks"*, *"scope drops $50k"*) and I'll recompute CPI, SPI, EAC and VAC. Or open the full simulator: 👇
159
160[__WHATIF_CTA__:${I}]`;i(S=>[...p??S,{role:"user",content:u},{role:"assistant",content:c}]),l(""),_("maya_message_sent",{project_id:I,intent:"what_if"});return}const X=[...A,{role:"user",content:u}];i(X),l(""),v(!0),b(null),_("maya_message_sent",{project_id:I??null}),_("ai_assistant_message",{project_id:I??null});const O=new AbortController;F.current=O;const Ke=window.setTimeout(()=>O.abort("timeout"),45e3);let B="";const Se=N=>{B+=N,i(c=>{const S=c[c.length-1];return(S==null?void 0:S.role)==="assistant"&&S.content===B.slice(0,S.content.length)&&c.length>X.length?c.map((C,E)=>E===c.length-1?{...C,content:B}:C):c.length===X.length?[...c,{role:"assistant",content:B}]:c.map((C,E)=>E===c.length-1?{...C,content:B}:C)})},Ee=async()=>{var N,c,S;try{const{data:{session:C}}=await re.auth.getSession(),E=C==null?void 0:C.access_token;if(!E)return{ok:!1,reason:"unauthorized"};const k=await fetch(aa,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${E}`},body:JSON.stringify({messages:X.map(T=>({role:T.role,content:T.content})),projectContext:s?Vt(s):null,activeService:ce,knowledgeContext:`${qt()}
161
162${wt(de??void 0)}
163
164${Jt()}`,trialContext:w,complianceMode:f}),signal:O.signal});if(!k.ok||!k.body){let T="";try{const Z=await k.json();Z!=null&&Z.error&&(T=String(Z.error))}catch{}return k.status===401||k.status===403?{ok:!1,reason:"unauthorized",status:k.status,rawMsg:T}:k.status===429?{ok:!1,reason:"rate_limit",status:429,rawMsg:T}:k.status===402?{ok:!1,reason:"credits",status:402,rawMsg:T}:k.status>=500?{ok:!1,reason:"server",status:k.status,rawMsg:T}:{ok:!1,reason:"unknown",status:k.status,rawMsg:T}}const R=k.body.getReader(),W=new TextDecoder;let L="",D=!1;for(;!D;){const{done:T,value:Z}=await R.read();if(T)break;L+=W.decode(Z,{stream:!0});let me;for(;(me=L.indexOf(`
165`))!==-1;){let V=L.slice(0,me);if(L=L.slice(me+1),V.endsWith("\r")&&(V=V.slice(0,-1)),!V||V.startsWith(":")||!V.startsWith("data: "))continue;const Pe=V.slice(6).trim();if(Pe==="[DONE]"){D=!0;break}try{const Ne=(S=(c=(N=JSON.parse(Pe).choices)==null?void 0:N[0])==null?void 0:c.delta)==null?void 0:S.content;Ne&&Se(Ne)}catch{L=V+`
166`+L;break}}}return{ok:!0}}catch(C){return C.name==="AbortError"?{ok:!1,reason:O.signal.reason==="timeout"?"timeout":"network"}:(console.error("[maya] fetch error",C),{ok:!1,reason:"network"})}};try{let N=await Ee();if(!N.ok&&!O.signal.aborted){const c=N;if(c.reason==="rate_limit"||c.reason==="server"||c.reason==="network"||c.reason==="timeout"){const C=c.reason==="rate_limit"?2e3:1200;await new Promise(E=>window.setTimeout(E,C)),!O.signal.aborted&&B.length===0&&(N=await Ee())}}if(!N.ok){const c=N,S=Ie(u);if(S&&B.length===0){Se(`${S.answer}${S.href?`
167
168More: ${S.href}`:""}`);return}const C=/\b(hvac|thermostat|ac|air ?con|heat ?pump|furnace)\b/i.test(u);let E="Maya can't respond",k=c.rawMsg||"Maya is taking a breather. Try again in a moment.",R="";const W=`[__RETRY_CTA__:${c.reason}]`;c.reason==="unauthorized"?(E="Maya needs permission to reach your system",C?(k="Sign in again, then retry — the HVAC path starts on the Connect hub.",R=`${se.unauthorized.answer}
169
170For HVAC and facility equipment: ${se.connect_hvac.answer}
171
172[__CONNECT_CTA__]`):(k="Please sign in again, then retry.",R=`${se.unauthorized.answer}
173
174[__CONNECT_CTA__]`)):c.reason==="rate_limit"?(E="Slow down a sec",k="Too many messages right now. Give it a few seconds.",R=`I'm hitting a short rate limit from the model. **Your message is safe** — tap **Try again** in a few seconds, or ask me for a quick recap of the last step while we wait.
175
176`+W):c.reason==="credits"?(E="AI credits exhausted",k="Add funds in Settings → Workspace → Usage.",R=`The workspace is out of AI credits. O
176nce an admin tops up in **Settings → Workspace → Usage**, tap **Try again** below and I'll pick up right where we left off.
177
178`+W):c.reason==="timeout"?(E="Maya timed out",k="The upstream model took too long.",R=`That request took longer than 45 seconds. Sometimes the model is under heavy load. **Fix It Yourself with Confidence** — tap **Try again**, and if it still stalls, try rephrasing more briefly.
179
180`+W):c.reason==="network"?(E="Connection issue",k="Couldn't reach Maya. Check your connection.",R=`I lost the connection while replying. Check your network, then tap **Try again** below — your last message is queued and ready to resend.
181
182`+W):c.reason==="server"?(E="Maya is having a hiccup",k="The AI gateway returned an error. Try again in a moment.",R=`The AI gateway just returned an error (server-side). It usually clears in a few seconds — tap **Try again** below. If it keeps failing, an admin can check the **Edge Health** panel.
183
184`+W):R=`${c.rawMsg||"Something went wrong."}
185
186Tap **Try again** to resend your message.
187
188${W}`,R&&i(L=>{const D=[...L],T=D[D.length-1];return T&&T.role==="assistant"&&!T.content?D[D.length-1]={...T,content:R}:D.push({role:"assistant",content:R}),D}),_("maya_reply_failed",{reason:c.reason,status:c.status??null}),c.reason!=="unauthorized"&&c.reason!=="credits"&&b(u),z({title:E,description:k,variant:"destructive"})}}finally{window.clearTimeout(Ke),v(!1),F.current=null}},Ze=r=>{r.preventDefault();const p=r.clientX,u=r.clientY,A=Y.w,$=Y.h,M=ae=>{const ke=p-ae.clientX,Ae=u-ae.clientY,X=Math.min(720,Math.max(360,A+ke)),O=Math.min(900,Math.max(480,$+Ae));Ue({w:X,h:O})},pe=()=>{window.removeEventListener("pointermove",M),window.removeEventListener("pointerup",pe)};window.addEventListener("pointermove",M),window.addEventListener("pointerup",pe)},qe=!o&&n.filter(r=>r.role==="user").length===0;return a.jsxs(a.Fragment,{children:[!t&&a.jsxs("button",{type:"button",onClick:()=>e(!0),"aria-label":"Open Maya, your project co-pilot",className:"fixed bottom-24 right-4 md:bottom-6 md:right-6 z-40 group",children:[a.jsx("span",{className:"absolute inset-0 rounded-full bg-primary/40 blur-xl group-hover:bg-primary/60 transition"}),a.jsxs("span",{className:"relative flex items-center gap-2 pl-2 pr-4 py-2 rounded-full bg-gradient-to-r from-primary to-primary/80 text-primary-foreground shadow-lg shadow-primary/30 border border-primary/40",children:[a.jsxs("span",{className:"relative h-9 w-9 rounded-full bg-background/90 overflow-hidden",children:[a.jsx("img",{src:$e,srcSet:`${$e} 40w, ${Te} 80w`,sizes:"36px",alt:"Maya, your energy co-pilot",width:36,height:36,loading:"lazy",decoding:"async",fetchPriority:"low",className:"h-full w-full object-cover"}),a.jsx("span",{className:"absolute -bottom-0.5 -right-0.5 h-2.5 w-2.5 rounded-full bg-eco-glow ring-2 ring-background animate-pulse"})]}),a.jsx("span",{className:"text-sm font-semibold tracking-tight",children:"Ask Maya"}),s&&s.pendingItems.length>0&&a.jsx("span",{className:"ml-1 inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-eco-glow px-1.5 text-[10px] font-bold text-background",children:s.pendingItems.length})]})]}),a.jsx("div",{className:U("fixed bottom-0 right-0 z-50 m-0 sm:m-4","transition-all duration-300 ease-out",t?"translate-y-0 opacity-100 pointer-events-auto":"translate-y-6 opacity-0 pointer-events-none"),style:t?{width:typeof window<"u"&&window.innerWidth>=640?`${Y.w}px`:void 0,height:typeof window<"u"&&window.innerWidth>=640?`${Y.h}px`:void 0}:void 0,"aria-hidden":!t,children:a.jsxs("div",{className:U("relative h-[100dvh] sm:h-full w-full sm:w-full flex flex-col rounded-none sm:rounded-2xl","border border-primary/20 bg-card/95 backdrop-blur-xl shadow-2xl shadow-primary/20 overflow-hidden"),children:[a.jsx("div",{onPointerDown:Ze,className:"hidden sm:block absolute top-1 left-1 h-4 w-4 cursor-nwse-resize rounded-sm hover:bg-primary/20 z-10",title:"Drag to resize","aria-label":"Resize Maya panel"}),a.jsxs("div",{className:"relative px-4 py-3 border-b border-border/50 bg-gradient-to-r from-primary/15 via-primary/5 to-transparent",children:[a.jsxs("div",{className:"flex items-center gap-3",children:[a.jsxs("div",{className:"relative h-10 w-10 rounded-full overflow-hidden bg-muted shadow-md shadow-primary/30",children:[a.jsx("img",{src:Te,alt:"Maya",width:40,height:40,loading:"lazy",decoding:"async",className:"h-full w-full object-cover"}),a.jsx("span",{className:"absolute -bottom-0.5 -right-0.5 h-2.5 w-2.5 rounded-full bg-eco-glow ring-2 ring-card animate-pulse"})]}),a.jsxs("div",{className:"min-w-0 flex-1",children:[a.jsxs("div",{className:"flex items-center gap-1.5 font-semibold tracking-tight",children:[f?"ComplianceGuard":"Maya",a.jsx(pt,{className:"h-3.5 w-3.5 text-primary"}),a.jsx("span",{className:U("ml-1 text-[10px] uppercase tracking-wider px-1.5 py-0.5 rounded",f?"bg-amber-500/15 text-amber-500":"bg-primary/15 text-primary"),children:f?"Compliance":"Co-Pilot"})]}),a.jsx("div",{className:"text-[11px] text-muted-foreground truncate",children:f?"
188SOC 2 • ISO 27001 • GDPR • HIPAA • CMMC":s?`Project: ${s.name}`:"EcoPowerHub.ai • online"})]}),a.jsx(oe,{variant:"ghost",size:"icon",onClick:()=>{x(r=>{const p=!r;try{localStorage.setItem(Fe,p?"1":"0")}catch{}return z({title:p?"Compliance mode on":"Compliance mode off",description:p?"Maya is now ComplianceGuard AI — SOC 2, ISO 27001, GDPR, HIPAA, CMMC.":"Back to your EcoPowerHub Project Co-Pilot."}),p})},"aria-label":f?"Switch to Co-Pilot mode":"Switch to Compliance mode",title:f?"Switch to Co-Pilot mode":"Switch to Compliance mode",className:U(f&&"text-amber-500"),children:a.jsx(mt,{className:"h-4 w-4"})}),a.jsx(oe,{variant:"ghost",size:"icon",onClick:()=>e(!1),"aria-label":"Close Maya",children:a.jsx(ut,{className:"h-4 w-4"})})]}),s&&a.jsxs("div",{className:"mt-2 flex flex-wrap items-center gap-1.5 text-[11px]",children:[a.jsx("span",{className:U("px-2 py-0.5 rounded-full font-medium",s.health==="On Track"&&"bg-eco-glow/15 text-eco-glow",s.health==="At Risk"&&"bg-yellow-500/15 text-yellow-400",s.health==="Critical"&&"bg-destructive/15 text-destructive"),children:s.health}),a.jsxs("span",{className:"px-2 py-0.5 rounded-full bg-muted/60 text-muted-foreground",children:[s.percentComplete,"% complete"]}),a.jsxs("span",{className:"px-2 py-0.5 rounded-full bg-muted/60 text-muted-foreground",children:["CPI ",s.cpi," · SPI ",s.spi]}),a.jsxs("span",{className:"px-2 py-0.5 rounded-full bg-muted/60 text-muted-foreground",children:[s.daysRemaining,"d left"]}),s.pendingItems.length>0&&a.jsxs("span",{className:"px-2 py-0.5 rounded-full bg-eco-glow/15 text-eco-glow font-medium",children:[s.pendingItems.length," pending"]})]})]}),a.jsxs("div",{ref:j,className:"flex-1 overflow-y-auto px-4 py-4 space-y-3",children:[n.map((r,p)=>a.jsx(ia,{role:r.role,content:r.content,onConnectClick:()=>{e(!1),le(Q?"/app/connect":"/connect"),_("maya_cta_clicked",{cta:"connect_system"})},onWeeklyStatusClick:async u=>{const A=ze.get(u);if(!A){z({title:"Project not found",description:"Open a project first, then ask again.",variant:"destructive"});return}_("maya_cta_clicked",{cta:"weekly_status_pdf",project_id:u});try{await ta(A),z({title:"Weekly status PDF downloaded",description:`Saved for ${A.name}.`})}catch($){console.error("[maya] weekly status pdf failed",$),z({title:"Couldn't generate PDF",description:"Try again in a moment.",variant:"destructive"})}},onWhatIfClick:u=>{e(!1),le(`/evm/calculator?project=${encodeURIComponent(u)}`),_("maya_cta_clicked",{cta:"what_if_simulator",project_id:u})},onRetry:d&&p===n.length-1&&!o?()=>{var $;const u=d,A=(($=n[n.length-1])==null?void 0:$.role)==="assistant"?n.slice(0,-1):n;i(A),b(null),_("maya_retry_clicked",{}),te(u,A)}:void 0},p)),o&&((Ce=n[n.length-1])==null?void 0:Ce.role)==="user"&&a.jsx(la,{})]}),s&&a.jsxs("div",{className:"px-4 pb-2 flex flex-wrap gap-1.5",children:[sa.map(({label:r,prompt:p,icon:u})=>a.jsxs("button",{type:"button",onClick:()=>te(p),disabled:o,className:"inline-flex items-center gap-1 text-[11px] px-2.5 py-1 rounded-full border border-primary/25 bg-primary/5 text-foreground/90 hover:bg-primary/10 hover:border-primary/40 transition disabled:opacity-50",children:[a.jsx(u,{className:"h-3 w-3 text-primary"})," ",r]},r)),!I&&a.jsxs("button",{type:"button",onClick:()=>{e(!1),le("/projects")},className:"inline-flex items-center gap-1 text-[11px] px-2.5 py-1 rounded-full border border-primary/25 bg-primary/5 text-foreground/90 hover:bg-primary/10 transition",children:[a.jsx(Ve,{className:"h-3 w-3 text-primary"})," Open a project"]})]}),qe&&a.jsx("div",{className:"px-4 pb-2 flex flex-wrap gap-2",children:Ye.map(r=>a.jsx("button",{type:"button",onClick:()=>te(r),className:"text-xs px-3 py-1.5 rounded-full border border-primary/30 bg-primary/5 text-foreground hover:bg-primary/10 hover:border-primary/50 transition",children:r},r))}),a.jsx(Ft,{}),ce&&a.jsx(_t,{service:ce}),a.jsxs("form",{onSubmit:r=>{r.preventDefault(),te(m)},className:"p-3 border-t border-border/50 bg-background/40",children:[a.jsxs("div",{className:"flex items-center gap-2",children:[a.jsx(we,{value:m,onChange:r=>l(r.target.value),placeholder:s?`Ask Maya about ${s.name}…`:"Message Maya…",disabled:o,maxLength:2e3,"aria-label":"Message",className:"bg-background/70"}),a.jsx(oe,{type:"submit",size:"icon",disabled:o||!m.trim(),"aria-label":"Send",children:o?a.jsx(De,{className:"h-4 w-4 animate-spin"}):a.jsx(ht,{className:"h-4 w-4"})})]}),a.jsxs("div",{className:"mt-2 flex items-center justify-between text-[11px] text-muted-foreground",children:[a.jsx("span",{children:"Maya can make mistakes — verify important actions."}),a.jsxs("button",{type:"button",onClick:()=>h(!0),className:"inline-flex items-center gap-1 hover:text-foreground transition",children:[a.jsx(Tt,{className:"h-3 w-3"})," Talk to a human"]})]})]})]})}),a.jsx(Lt,{open:g,onOpenChange:h,defaultTopic:s?`Project: ${s.name}`:"From Maya chat"})]})}function ia({role:t,content:e,onConnectClick:n,onWeeklyStatusClick:i,onWhatIfClick:m,onRetry:l}){const o=t==="user",v=!o&&e.includes("[__CONNECT_CTA__]"),g=o?null:e.match(/\[__RETRY_CTA__:([a-z_]+)\]/),h=!!g,d=(g==null?void 0:g[1])??"",b=o?null:e.match(/\[__WEEKLY_STATUS_CTA__:([^\]]+)\]/),f=o?null:e.match(/\[__WHATIF_CTA__:([^\]]+)\]/);let x=e;return v&&(x=x.replace(/\n*\[__CONNECT_CTA__\]\n*/g,"").trim()),h&&(x=x.replace(/\n*\[__RETRY_CTA__:[a-z_]+\]\n*/g,"").trim()),b&&(x=x.replace(/\n*\[__WEEKLY_STATUS_CTA__:[^\]]+\]\n*/g,"").trim()),f&&(x=x.replace(/\n*\[__WHATIF_CTA__:[^\]]+\]\n*/g,"").trim()),a.jsx("div",{className:U("flex",o?"justify-end":"justify-start"),children:a.jsx("div",{className:U("max-w-[85%] rounded-2xl px-3.5 py-2.5 text-sm leading-relaxed shadow-sm",o?"bg-primary text-primary-foreground rounded-br-md":h?"bg-destructive/5 text-foreground rounded-bl-md border border-destructive/30":"bg-muted/60 text-foreground rounded-bl-md border border-border/50"),children:o?a.jsx("p",{className:"whitespace-pre-wrap",children:e}):a.jsxs("div",{className:"prose prose-sm dark:prose-invert max-w-none prose-p:my-1.5 prose-ul:my-1.5 prose-li:my-0.5 prose-headings:mb-1.5 prose-headings:mt-2 prose-pre:my-2 prose-a:text-primary",children:[a.jsx($t,{children:x||"…"}),v&&n&&a.jsxs("button",{type:"button",onClick:n,className:"not-prose mt-3 inline-flex items-center gap-2 rounded-xl bg-primary px-4 py-2 text-sm font-semibold text-primary-foreground shadow-md shadow-primary/30 hover:opacity-90 transition",children:[a.jsx(Ve,{className:"h-4 w-4"})," Connect My System"]}),b&&i&&a.jsxs("button",{type:"button",onClick:()=>i(b[1]),className:"not-prose mt-3 inline-flex items-center gap-2 rounded-xl bg-primary px-4 py-2 text-sm font-semibold text-primary-foreground shadow-md shadow-primary/30 hover:opacity-90 transition",children:[a.jsx(Oe,{className:"h-4 w-4"})," Generate weekly status PDF"]}),f&&m&&a.jsxs("button",{type:"button",onClick:()=>m(f[1]),className:"not-prose mt-3 inline-flex items-center gap-2 rounded-xl bg-primary px-4 py-2 text-sm font-semibold text-primary-foreground shadow-md shadow-primary/30 hover:opacity-90 transition",children:[a.jsx(We,{className:"h-4 w-4"})," Open scenario simulator"]}),h&&l&&a.jsxs("div",{className:"not-prose mt-3 flex flex-wrap items-center gap-2",children:[a.jsxs("button",{type:"button",onClick:l,className:"inline-flex items-center gap-2 rounded-xl bg-primary px-4 py-2 text-sm font-semibold text-primary-foreground shadow-md shadow-primary/30 hover:opacity-90 transition",children:[a.jsx(Rt,{className:"h-4 w-4"})," Try again"]}),a.jsxs("span",{className:"text-xs text-muted-foreground",children:[d==="rate_limit"&&"Rate limited — waiting helps.",d==="timeout"&&"Took over 45s — a shorter prompt often works.",d==="server"&&"Upstream hiccup — usually clears fast.",d==="network"&&"Network dropped — reconnect then retry.",d==="credits"&&"Credits needed — top up, then retry."]})]})]})})})}function la(){return a.jsx("div",{className:"flex justify-start",children:a.jsxs("div",{className:"rounded-2xl rounded-bl-md bg-muted/60 border border-border/50 px-3.5 py-3 flex items-center gap-1.5",children:[a.jsx(be,{delay:"0ms"}),a.jsx(be,{delay:"150ms"}),a.jsx(be,{delay:"300ms"})]})})}function be({delay:t}){return a.jsx("span",{className:"h-1.5 w-1.5 rounded-full bg-primary animate-pulse",style:{animationDelay:t,animationDuration:"1.2s"}})}function un(){window.dispatchEvent(new CustomEvent("maya:open"))}function hn(t,e){window.dispatchEvent(new CustomEvent("maya:openWith",{detail:{message:t,quickReplies:e}}))}export{mn as MayaAssistant,un as openMaya,hn as openMayaWith};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.