vibespot 1.2.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +54 -5
  2. package/assets/blog-rules.md +251 -0
  3. package/assets/email-rules.md +390 -0
  4. package/assets/humanify-guide.md +300 -101
  5. package/assets/plan-templates/blog-content-hub.md +18 -9
  6. package/assets/plan-templates/email-announcement.md +41 -0
  7. package/assets/plan-templates/email-event-invite.md +43 -0
  8. package/assets/plan-templates/email-newsletter.md +41 -0
  9. package/assets/plan-templates/email-re-engagement.md +42 -0
  10. package/assets/plan-templates/email-welcome.md +41 -0
  11. package/dist/index.js +1460 -387
  12. package/dist/index.js.map +1 -1
  13. package/package.json +5 -5
  14. package/starters/06-blog-content-hub.json +75 -0
  15. package/starters/06-email-welcome.json +60 -0
  16. package/starters/07-email-announcement.json +60 -0
  17. package/starters/08-email-newsletter.json +52 -0
  18. package/ui/chat.js +777 -63
  19. package/ui/code-editor.js +49 -7
  20. package/ui/dashboard.js +379 -93
  21. package/ui/docs/docs.css +29 -0
  22. package/ui/docs/index.html +416 -119
  23. package/ui/docs/screenshots/asset-type-cards.png +0 -0
  24. package/ui/docs/screenshots/brand-kit-preview.png +0 -0
  25. package/ui/docs/screenshots/content-type-dropdown.png +0 -0
  26. package/ui/docs/screenshots/deploy-progress.png +0 -0
  27. package/ui/docs/screenshots/editor-full-layout.png +0 -0
  28. package/ui/docs/screenshots/email-client-preview.png +0 -0
  29. package/ui/docs/screenshots/inline-wysiwyg-editing.png +0 -0
  30. package/ui/docs/screenshots/module-overview-slideout.png +0 -0
  31. package/ui/docs/screenshots/multi-page-tree.png +0 -0
  32. package/ui/docs/screenshots/onboarding-walkthrough.png +0 -0
  33. package/ui/docs/screenshots/pipeline-progress.png +0 -0
  34. package/ui/docs/screenshots/project-overview-table.png +0 -0
  35. package/ui/docs/screenshots/split-pane-view.png +0 -0
  36. package/ui/docs/screenshots/visual-controls-toolbar.png +0 -0
  37. package/ui/docs/screenshots/workspace-tabs.png +0 -0
  38. package/ui/email-preview.js +109 -0
  39. package/ui/field-editor.js +72 -1
  40. package/ui/icons.js +120 -0
  41. package/ui/index.html +877 -629
  42. package/ui/inline-edit.js +710 -0
  43. package/ui/plan.js +0 -0
  44. package/ui/preview.js +101 -198
  45. package/ui/section-controls.js +628 -0
  46. package/ui/settings.js +58 -16
  47. package/ui/setup.js +750 -140
  48. package/ui/styles.css +3430 -952
  49. package/ui/upload-panel.js +47 -20
package/dist/index.js CHANGED
@@ -1,9 +1,16 @@
1
- var $u=Object.defineProperty;var G=(e,t)=>()=>(e&&(t=e(e=0)),t);var _e=(e,t)=>{for(var n in t)$u(e,n,{get:t[n],enumerable:!0})};import Zh from"path";import{fileURLToPath as ey}from"url";var g=G(()=>{"use strict"});import{readFileSync as jo,writeFileSync as Iu,mkdirSync as Mr,existsSync as ns}from"fs";import{dirname as Rr,join as at}from"path";import{fileURLToPath as Eu}from"url";function T(e){return jo(e,"utf-8")}function L(e,t){Mr(Rr(e),{recursive:!0}),Iu(e,t,"utf-8")}function b(e){return ns(e)}function Ae(e){Mr(e,{recursive:!0})}function ss(e){let t=[at(Wt,"../../assets",e),at(Wt,"../assets",e),at(process.cwd(),"assets",e)];for(let n of t)if(ns(n))return n;throw new Error(`Asset not found: ${e}`)}function Vt(){if(Gt)return Gt;let e=[at(Wt,"../../package.json"),at(Wt,"../package.json"),at(process.cwd(),"package.json")];for(let t of e)if(ns(t))try{let n=JSON.parse(jo(t,"utf-8"));if(n.name==="vibespot"&&n.version)return Gt=n.version,Gt}catch{}return Gt="dev",Gt}function _r(){if(ts)return ts;let e=[at(Wt,"../../CHANGELOG.md"),at(Wt,"../CHANGELOG.md"),at(process.cwd(),"CHANGELOG.md")];for(let t of e)if(ns(t))try{return ts=jo(t,"utf-8"),ts}catch{}return""}var Wt,Gt,ts,Q=G(()=>{"use strict";g();Wt=Rr(Eu(import.meta.url));Gt="";ts=""});import{execSync as Pr}from"child_process";function D(e,t={}){try{return{stdout:Pr(e,{encoding:"utf-8",stdio:["pipe","pipe","pipe"],timeout:12e4,...t}).trim(),stderr:"",success:!0}}catch(n){let s=n,o=(s.stdout??"").toString().trim(),i=(s.stderr??"").toString().trim();return{stdout:o,stderr:i,success:!1}}}function Nr(e,t={}){try{return Pr(e,{stdio:"inherit",timeout:3e5,...t}),!0}catch{return!1}}var Et=G(()=>{"use strict";g()});var jr={};_e(jr,{addHubSpotAccount:()=>fn,getActiveHubSpotAccount:()=>xt,getApiKeyForEngine:()=>Te,getConfigDir:()=>_u,getHubSpotPak:()=>$e,isCliToolEnabled:()=>gn,loadConfig:()=>R,maskApiKey:()=>is,removeHubSpotAccount:()=>Do,saveConfig:()=>V,setActiveHubSpotAccount:()=>Jo,setCliToolEnabled:()=>Lo});import{join as Or}from"path";import{homedir as Mu}from"os";import{chmodSync as Ru}from"fs";function R(){if(!b(os))return{};try{let e=JSON.parse(T(os));return e.aiEngine==="api"&&(e.aiEngine="anthropic-api"),e}catch{return{}}}function Te(e,t){let n=t||R();switch(e){case"anthropic-api":case"api":return n.anthropicApiKey||process.env.ANTHROPIC_API_KEY;case"openai-api":return n.openaiApiKey||process.env.OPENAI_API_KEY;case"gemini-api":return n.geminiApiKey||process.env.GEMINI_API_KEY||process.env.GOOGLE_AI_API_KEY;default:return}}function is(e){return e.length<=12?"***":e.slice(0,7)+"..."+e.slice(-4)}function V(e){let n={...R(),...e};if(L(os,JSON.stringify(n,null,2)),process.platform!=="win32")try{Ru(os,384)}catch{}}function _u(){return Fr}function xt(){let e=R();if(!e.hubspotAccounts?.length)return null;let t=e.activeHubSpotAccount;if(t){let n=e.hubspotAccounts.find(s=>s.portalId===t);if(n)return n}return e.hubspotAccounts[0]||null}function fn(e,t,n,s){let i=R().hubspotAccounts||[],r=i.findIndex(l=>l.portalId===t),a={portalId:t,portalName:n,personalAccessKey:e,dataCenter:s,addedAt:new Date().toISOString()};r>=0?i[r]=a:i.push(a),V({hubspotAccounts:i,activeHubSpotAccount:t})}function Do(e){let t=R(),n=(t.hubspotAccounts||[]).filter(o=>o.portalId!==e),s={hubspotAccounts:n};t.activeHubSpotAccount===e&&(s.activeHubSpotAccount=n[0]?.portalId||void 0),V(s)}function Jo(e){V({activeHubSpotAccount:e})}function $e(){return xt()?.personalAccessKey||null}function gn(e){return R().enabledCLITools?.includes(e)??!1}function Lo(e,t){let n=R(),s=new Set(n.enabledCLITools||[]);t?s.add(e):s.delete(e),V({enabledCLITools:[...s]})}var Fr,os,X=G(()=>{"use strict";g();Q();Fr=Or(Mu(),".vibespot"),os=Or(Fr,"config.json")});var Uo={};_e(Uo,{OAUTH_EXTRA_HEADERS:()=>hn,OAUTH_SYSTEM_PREFIX:()=>Kt,clearOAuthTokens:()=>ls,getOAuthTokenInfo:()=>yn,getValidAccessToken:()=>Bo,hasValidOAuthToken:()=>Ye,saveInitialToken:()=>Ho});import{join as Pu}from"path";import{homedir as Nu}from"os";import{chmodSync as Ou,unlinkSync as Fu}from"fs";function as(){if(!b(zt))return null;try{return JSON.parse(T(zt))}catch{return null}}function Dr(e){if(L(zt,JSON.stringify(e,null,2)),process.platform!=="win32")try{Ou(zt,384)}catch{}}async function Lu(e){let t=await fetch(Du,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({grant_type:"refresh_token",refresh_token:e,client_id:ju})});if(!t.ok)throw ls(),new Error("Claude OAuth session expired. Please re-authenticate in Settings.");let n=await t.json();Dr({access_token:n.access_token,refresh_token:n.refresh_token||e,expires_at:Date.now()+(n.expires_in||28800)*1e3})}function Ho(e,t=""){Dr({access_token:e,refresh_token:t,expires_at:Date.now()+28800*1e3})}function Ye(){let e=as();return e?e.expires_at>Date.now():!1}async function Bo(){let e=as();if(!e)return null;if(e.expires_at-Date.now()>Ju)return e.access_token;if(e.refresh_token){rs||(rs=Lu(e.refresh_token).finally(()=>{rs=null}));try{await rs}catch{return null}return as()?.access_token??null}return e.access_token}function yn(){let e=as();return e?{expiresAt:new Date(e.expires_at).toISOString()}:null}function ls(){if(b(zt))try{Fu(zt)}catch{}}var ju,Du,zt,Ju,hn,Kt,rs,lt=G(()=>{"use strict";g();Q();ju="9d1c250a-e61b-44d9-88ed-5944d1962f5e",Du="https://console.anthropic.com/v1/oauth/token",zt=Pu(Nu(),".vibespot","claude-oauth.json"),Ju=300*1e3,hn={"user-agent":"claude-cli/2.1.75","x-app":"cli","anthropic-beta":"oauth-2025-04-20"},Kt="You are Claude Code, Anthropic's official CLI for Claude.";rs=null});import{readFileSync as Uu}from"fs";import{basename as Gu}from"path";async function Ur(e){let t=Br.get(e);if(t&&t.expiresAt-Date.now()>zu)return t;let n=await fetch(`${ct}/localdevauth/v1/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({encodedOAuthRefreshToken:e})});if(!n.ok){let i=await n.text().catch(()=>"");throw new Error(n.status===401||n.status===403?"Invalid or expired Personal Access Key":`Token exchange failed (${n.status}): ${i.slice(0,200)}`)}let s=await n.json(),o={accessToken:s.oauthAccessToken,expiresAt:s.expiresAtMillis,hubId:s.hubId,hubName:s.hubName||""};return Br.set(e,o),o}async function Yt(e){let{accessToken:t}=await Ur(e);return{Authorization:`Bearer ${t}`}}function fs(e){return e.replace(/^\/+/,"").split("/").filter(Boolean).map(encodeURIComponent).join("/")}function Ku(e){return e.startsWith("pat-eu1-")?"eu1":e.startsWith("pat-na1-")?"na1":e.startsWith("CiRldTE")?"eu1":"na1"}function Yu(e){return new Promise(t=>setTimeout(t,e))}async function kn(e,t){let n=`HTTP ${e.status}`,s,o;try{let i=await e.json();if(i.message&&typeof i.message=="string"&&(n=i.message),i.category&&typeof i.category=="string"&&(s=i.category),i.errors&&Array.isArray(i.errors)&&i.errors.length>0){let r=i.errors[0];o=r.message||JSON.stringify(r)}}catch{try{let i=await e.text();i&&(n=i.slice(0,500))}catch{}}return{status:e.status,message:t?`${n} (${t})`:n,category:s,detail:o}}async function An(e,t,n=Wu){for(let s=0;s<=n;s++){let o=await fetch(e,t);if(o.status===429||o.status>=500&&s<n){let i=Vu*Math.pow(2,s);await Yu(i);continue}return o}return fetch(e,t)}async function gs(e){let t=await Ur(e),n=`${ct}/account-info/v3/details`,s=await An(n,{headers:await Yt(e)});if(!s.ok){let a=await kn(s);throw new Error(`Failed to get account info: ${a.message}`)}let o=await s.json(),i=String(o.portalId||t.hubId||""),r=t.hubName||o.uiDomain||i;return{portalId:i,portalName:r,dataCenter:Ku(e)}}async function Gr(e,t,n){let s=Uu(n),o=Gu(n),i=new FormData,r=new Blob([s]);i.append("file",r,o);let a=`${ct}/cms/v3/source-code/published/content/${fs(t)}`,l=await An(a,{method:"PUT",headers:await Yt(e),body:i});if(!l.ok){let c=await kn(l,t);return{success:!1,path:t,error:c}}return{success:!0,path:t}}async function zo(e,t){let n=`${ct}/cms/v3/source-code/published/content/${fs(t)}`,s=await An(n,{method:"DELETE",headers:await Yt(e)});if(!s.ok&&s.status!==404){let o=await kn(s,t);throw new Error(`Failed to delete ${t}: ${o.message}`)}}async function Wr(e,t){let n=`${ct}/cms/v3/source-code/published/content/${fs(t)}`,s=await An(n,{method:"GET",headers:await Yt(e)});if(!s.ok){let i=await kn(s,t);throw new Error(`Failed to download ${t}: ${i.message}`)}let o=await s.arrayBuffer();return Buffer.from(o)}async function hs(e,t){let n=`${ct}/cms/v3/source-code/published/metadata/${fs(t)}`,s=await An(n,{method:"GET",headers:await Yt(e)});if(s.status===404)return null;if(!s.ok){let o=await kn(s,t);throw new Error(`Failed to get metadata for ${t}: ${o.message}`)}return await s.json()}async function Vr(e){let t=await Yt(e),n=[`${ct}/cms/v3/source-code/published/metadata`,`${ct}/cms/v3/source-code/published/metadata/`,`${ct}/designmanager/v1/portals/content/listing`];for(let s of n)try{let o=await fetch(s,{method:"GET",headers:t});if(o.ok){let i=await o.json(),r=i.children||i.objects||(Array.isArray(i)?i:null);if(r&&r.length>0)return r.filter(a=>a.folder)}}catch{}return[]}var ct,Wu,Vu,zu,Br,Rt=G(()=>{"use strict";g();ct="https://api.hubapi.com",Wu=3,Vu=1e3,zu=300*1e3,Br=new Map});var Xr={};_e(Xr,{createThemeScaffold:()=>Tn});import{mkdirSync as vt,writeFileSync as Ss}from"fs";import{join as Le}from"path";function Tn(e,t){vt(e,{recursive:!0}),vt(Le(e,"templates"),{recursive:!0}),vt(Le(e,"modules"),{recursive:!0}),vt(Le(e,"css"),{recursive:!0}),vt(Le(e,"js"),{recursive:!0}),vt(Le(e,"images"),{recursive:!0}),vt(Le(e,"assets"),{recursive:!0});let n={label:t,preview_path:"./templates/home.html",screenshot_path:"./images/template-previews/home.png",enable_domain_stylesheets:!1,version:"1.0.0",author:{name:"vibeSpot",url:"https://github.com/borismichel/vibespot"}};Ss(Le(e,"theme.json"),JSON.stringify(n,null,2)+`
2
- `),Ss(Le(e,"fields.json"),`[]
1
+ var tp=Object.defineProperty;var R=(t,e)=>()=>(t&&(e=t(t=0)),e);var Be=(t,e)=>{for(var n in e)tp(t,n,{get:e[n],enumerable:!0})};import Gb from"path";import{fileURLToPath as Kb}from"url";var y=R(()=>{"use strict"});import en from"chalk";function bt(t){return ia?en:en.hex(t)}var rt,ia,_,at=R(()=>{"use strict";y();rt={accent:"#FF7A59",accentBright:"#FF9A7A",success:"#00BDA5",info:"#0066FF",warn:"#FFB020",error:"#E23D2D",muted:"#8B8D91",vibes:"#00BDD6"},ia=!!process.env.NO_COLOR;_={accent:bt(rt.accent),accentBright:bt(rt.accentBright),success:bt(rt.success),info:bt(rt.info),warn:bt(rt.warn),error:bt(rt.error),muted:bt(rt.muted),vibes:bt(rt.vibes),heading:ia?en.bold:en.bold.hex(rt.accent),command:bt(rt.accentBright),dim:en.dim,bold:en.bold}});import{readFileSync as li,writeFileSync as np,mkdirSync as ra,existsSync as ks}from"fs";import{dirname as aa,join as St}from"path";import{fileURLToPath as sp}from"url";function M(t){return li(t,"utf-8")}function J(t,e){ra(aa(t),{recursive:!0}),np(t,e,"utf-8")}function v(t){return ks(t)}function Ie(t){ra(t,{recursive:!0})}function Ts(t){let e=[St(nn,"../../assets",t),St(nn,"../assets",t),St(process.cwd(),"assets",t)];for(let n of e)if(ks(n))return n;throw new Error(`Asset not found: ${t}`)}function sn(){if(tn)return tn;let t=[St(nn,"../../package.json"),St(nn,"../package.json"),St(process.cwd(),"package.json")];for(let e of t)if(ks(e))try{let n=JSON.parse(li(e,"utf-8"));if(n.name==="vibespot"&&n.version)return tn=n.version,tn}catch{}return tn="dev",tn}function la(){if(Cs)return Cs;let t=[St(nn,"../../CHANGELOG.md"),St(nn,"../CHANGELOG.md"),St(process.cwd(),"CHANGELOG.md")];for(let e of t)if(ks(e))try{return Cs=li(e,"utf-8"),Cs}catch{}return""}var nn,tn,Cs,ne=R(()=>{"use strict";y();nn=aa(sp(import.meta.url));tn="";Cs=""});import{execSync as ca,execFileSync as op}from"child_process";function te(t,e={}){try{return{stdout:ca(t,{encoding:"utf-8",stdio:["pipe","pipe","pipe"],timeout:12e4,...e}).trim(),stderr:"",success:!0}}catch(n){let s=n,o=(s.stdout??"").toString().trim(),i=(s.stderr??"").toString().trim();return{stdout:o,stderr:i,success:!1}}}function X(t,e={}){try{return{stdout:op("git",t,{encoding:"utf-8",stdio:["pipe","pipe","pipe"],timeout:12e4,...e}).toString().trim(),stderr:"",success:!0}}catch(n){let s=n,o=(s.stdout??"").toString().trim(),i=(s.stderr??"").toString().trim();return{stdout:o,stderr:i,success:!1}}}function da(t,e={}){try{return ca(t,{stdio:"inherit",timeout:3e5,...e}),!0}catch{return!1}}var Jt=R(()=>{"use strict";y()});var pa={};Be(pa,{addHubSpotAccount:()=>An,getActiveHubSpotAccount:()=>It,getApiKeyForEngine:()=>Oe,getConfigDir:()=>ap,getHubSpotPak:()=>Fe,isCliToolEnabled:()=>$n,loadConfig:()=>O,maskApiKey:()=>$s,removeHubSpotAccount:()=>ci,saveConfig:()=>Y,setActiveHubSpotAccount:()=>di,setCliToolEnabled:()=>ui});import{join as ua}from"path";import{homedir as ip}from"os";import{chmodSync as rp}from"fs";function O(){if(!v(As))return{};try{let t=JSON.parse(M(As));return t.aiEngine==="api"&&(t.aiEngine="anthropic-api"),t}catch{return{}}}function Oe(t,e){let n=e||O();switch(t){case"anthropic-api":case"api":return n.anthropicApiKey||process.env.ANTHROPIC_API_KEY;case"openai-api":return n.openaiApiKey||process.env.OPENAI_API_KEY;case"gemini-api":return n.geminiApiKey||process.env.GEMINI_API_KEY||process.env.GOOGLE_AI_API_KEY;default:return}}function $s(t){return t.length<=12?"***":t.slice(0,7)+"..."+t.slice(-4)}function Y(t){let n={...O(),...t};if(J(As,JSON.stringify(n,null,2)),process.platform!=="win32")try{rp(As,384)}catch{}}function ap(){return ma}function It(){let t=O();if(!t.hubspotAccounts?.length)return null;let e=t.activeHubSpotAccount;if(e){let n=t.hubspotAccounts.find(s=>s.portalId===e);if(n)return n}return t.hubspotAccounts[0]||null}function An(t,e,n,s){let i=O().hubspotAccounts||[],r=i.findIndex(l=>l.portalId===e),a={portalId:e,portalName:n,personalAccessKey:t,dataCenter:s,addedAt:new Date().toISOString()};r>=0?i[r]=a:i.push(a),Y({hubspotAccounts:i,activeHubSpotAccount:e})}function ci(t){let e=O(),n=(e.hubspotAccounts||[]).filter(o=>o.portalId!==t),s={hubspotAccounts:n};e.activeHubSpotAccount===t&&(s.activeHubSpotAccount=n[0]?.portalId||void 0),Y(s)}function di(t){Y({activeHubSpotAccount:t})}function Fe(){return It()?.personalAccessKey||null}function $n(t){return O().enabledCLITools?.includes(t)??!1}function ui(t,e){let n=O(),s=new Set(n.enabledCLITools||[]);e?s.add(t):s.delete(t),Y({enabledCLITools:[...s]})}var ma,As,Q=R(()=>{"use strict";y();ne();ma=ua(ip(),".vibespot"),As=ua(ma,"config.json")});var gi={};Be(gi,{OAUTH_EXTRA_HEADERS:()=>_n,OAUTH_SYSTEM_PREFIX:()=>rn,clearOAuthTokens:()=>Es,getOAuthTokenInfo:()=>Mn,getValidAccessToken:()=>pi,hasValidOAuthToken:()=>lt,saveInitialToken:()=>mi});import{join as lp}from"path";import{homedir as cp}from"os";import{chmodSync as dp,unlinkSync as up}from"fs";function Ms(){if(!v(on))return null;try{return JSON.parse(M(on))}catch{return null}}function ga(t){if(J(on,JSON.stringify(t,null,2)),process.platform!=="win32")try{dp(on,384)}catch{}}async function fp(t){let e=await fetch(pp,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({grant_type:"refresh_token",refresh_token:t,client_id:mp})});if(!e.ok)throw Es(),new Error("Claude OAuth session expired. Please re-authenticate in Settings.");let n=await e.json();ga({access_token:n.access_token,refresh_token:n.refresh_token||t,expires_at:Date.now()+(n.expires_in||28800)*1e3})}function mi(t,e=""){ga({access_token:t,refresh_token:e,expires_at:Date.now()+28800*1e3})}function lt(){let t=Ms();return t?t.expires_at>Date.now():!1}async function pi(){let t=Ms();if(!t)return null;if(t.expires_at-Date.now()>gp)return t.access_token;if(t.refresh_token){_s||(_s=fp(t.refresh_token).finally(()=>{_s=null}));try{await _s}catch{return null}return Ms()?.access_token??null}return t.access_token}function Mn(){let t=Ms();return t?{expiresAt:new Date(t.expires_at).toISOString()}:null}function Es(){if(v(on))try{up(on)}catch{}}var mp,pp,on,gp,_n,rn,_s,xt=R(()=>{"use strict";y();ne();mp="9d1c250a-e61b-44d9-88ed-5944d1962f5e",pp="https://console.anthropic.com/v1/oauth/token",on=lp(cp(),".vibespot","claude-oauth.json"),gp=300*1e3,_n={"user-agent":"claude-cli/2.1.75","x-app":"cli","anthropic-beta":"oauth-2025-04-20"},rn="You are Claude Code, Anthropic's official CLI for Claude.";_s=null});import{join as Is}from"path";import{homedir as Ps}from"os";import{readFileSync as fa,existsSync as Rs,readdirSync as hp}from"fs";function En(){let t=te("node --version");return{name:"Node.js",found:t.success,version:t.stdout.replace(/^v/,""),path:te(`${Bt} node`).stdout}}function In(){let t=te("git --version");return{name:"Git",found:t.success,version:t.stdout.replace("git version ",""),path:te(`${Bt} git`).stdout}}function ct(){let t=te("hs --version");return{name:"HubSpot CLI",found:t.success,version:t.stdout,path:te(`${Bt} hs`).stdout}}function Pn(){let t=te("claude --version");if(!t.success)return{name:"Claude Code",found:!1,version:"",path:"",authenticated:!1,authDetail:"Not installed"};let e=Is(Ps(),".claude"),n=!1,s="Not signed in \u2014 run `claude` to authenticate";try{if(Rs(e)){let o=hp(e);(o.some(r=>r.includes("credentials")||r.includes("auth")||r.includes("token")||r===".credentials.json")||o.length>2)&&(n=!0,s="Authenticated")}}catch{}return{name:"Claude Code",found:!0,version:t.stdout,path:te(`${Bt} claude`).stdout,authenticated:n,authDetail:s}}function Rn(t){try{let e=Is(Ps(),".hscli","config.yml");if(!Rs(e))return"na1";let n=fa(e,"utf-8"),s=n.indexOf(`accountId: ${t}`);if(s===-1)return"na1";let o=n.indexOf("personalAccessKey:",s);if(o===-1)return"na1";let r=n.slice(o,o+300).match(/personalAccessKey:[\s>-]*\n\s+(\S+)/);if(!r)return"na1";if(r[1].startsWith("CiRldTE"))return"eu1"}catch{}return"na1"}function dt(){let t=te("hs accounts list");if(!t.success||!t.stdout)return{authenticated:!1,portalName:"",portalId:"",accounts:[]};let e=[],n="",s="",o=t.stdout.match(/Account:\s*(.+?)\s*\((\d+)\)/);o&&(n=o[1].trim(),s=o[2].trim());let i=t.stdout.split(`
2
+ `);for(let r of i){let a=r.match(/^\s*(.+?)\s+(\d{5,})\s+(.*)/);if(a&&!/Account ID/i.test(r)&&!/^-+$/.test(r.trim())&&!/^Name\s/i.test(r.trim())){let l=a[1].trim(),c=a[2].trim(),d=a[3]?.trim()||"unknown";e.push({name:l,portalId:c,authType:d,isDefault:c===s})}}return o?{authenticated:!0,portalName:n,portalId:s,accounts:e}:e.length>0?{authenticated:!0,portalName:e[0].name,portalId:e[0].portalId,accounts:e}:{authenticated:t.stdout.length>0,portalName:"",portalId:"",accounts:[]}}function Nn(){let t=te("gemini --version");if(!t.success)return{name:"Gemini CLI",found:!1,version:"",path:"",authenticated:!1,authDetail:"Not installed"};let e=Is(Ps(),".config","gcloud","application_default_credentials.json"),n=Rs(e),s=!!(process.env.GEMINI_API_KEY||process.env.GOOGLE_API_KEY||process.env.GOOGLE_AI_API_KEY),o=n||s;return{name:"Gemini CLI",found:!0,version:t.stdout,path:te(`${Bt} gemini`).stdout,authenticated:o,authDetail:o?"Authenticated":"Run `gemini` to sign in with Google"}}function On(){let t=te("codex --version");if(!t.success)return{name:"OpenAI Codex CLI",found:!1,version:"",path:"",authenticated:!1,authDetail:"Not installed"};let e=!!process.env.OPENAI_API_KEY,n=!1;try{let i=Is(Ps(),".codex","auth.json");Rs(i)&&(n=fa(i,"utf-8").length>10)}catch{}let s=e||n,o=n?"Authenticated (OAuth)":e?"Authenticated (API key)":"Not authenticated";return{name:"OpenAI Codex CLI",found:!0,version:t.stdout,path:te(`${Bt} codex`).stdout,authenticated:s,authDetail:o}}function hi(){let t=te("gh --version");return{name:"GitHub CLI",found:t.success,version:t.stdout.split(`
3
+ `)[0]?.replace("gh version ","").split(" ")[0]||"",path:te(`${Bt} gh`).stdout}}function yi(){let t=te("gh auth status 2>&1");if(!t.success&&!t.stdout)return{authenticated:!1,username:""};let e=t.stdout||t.stderr||"",n=e.match(/Logged in to github\.com.*account\s+(\S+)/);if(n)return{authenticated:!0,username:n[1]};let s=e.match(/account\s+(\S+)/);return s&&e.includes("Logged in")?{authenticated:!0,username:s[1]}:{authenticated:e.includes("Logged in"),username:""}}function ha(){return!!process.env.ANTHROPIC_API_KEY}function Ns(t){return parseInt(t.split(".")[0],10)>=18}function ya(t){let e=parseInt(t.split(".")[0],10);return!isNaN(e)&&e>=8}function yp(){let t=O(),e=t.hubspotUploadMode||"api",n=t.hubspotAccounts||[],s=n.map(i=>({name:i.portalName,portalId:i.portalId,authType:"personalaccesskey",isDefault:i.portalId===(t.activeHubSpotAccount||n[0]?.portalId)})),o=It();return{authenticated:!!o,portalName:o?.portalName||"",portalId:o?.portalId||"",dataCenter:o?o.dataCenter:"na1",accounts:s,uploadMode:e}}function Os(){let t=O(),e=En(),n=In(),s=t.hubspotUploadMode||"api",o;if(s==="cli"){let S=ct(),x=S.found?dt():{authenticated:!1,portalName:"",portalId:"",accounts:[]},w=x.portalId?Rn(x.portalId):"na1";o={...S,...x,dataCenter:w,uploadMode:"cli"}}else o={name:"HubSpot API",found:!0,version:"v3",path:"",...yp()};let i=hi(),r=i.found?yi():{authenticated:!1,username:""},a={authenticated:lt(),expiresAt:Mn()?.expiresAt},l=t.enabledCLITools||[],c=$n("claude-code")?Pn():{...fi,name:"Claude Code"},d=$n("gemini-cli")?Nn():{...fi,name:"Gemini CLI"},u=$n("codex-cli")?On():{...fi,name:"OpenAI Codex CLI"};function m(S,...x){if(S)return{configured:!0,masked:$s(S),source:"config"};for(let w of x)if(process.env[w])return{configured:!0,masked:$s(process.env[w]),source:"env"};return{configured:!1,masked:"",source:null}}let g=m(t.anthropicApiKey,"ANTHROPIC_API_KEY"),h=m(t.openaiApiKey,"OPENAI_API_KEY"),f=m(t.geminiApiKey,"GEMINI_API_KEY","GOOGLE_AI_API_KEY"),b=[];return c.found&&c.authenticated&&b.push("claude-code"),a.authenticated&&b.push("claude-oauth"),g.configured&&b.push("anthropic-api"),h.configured&&b.push("openai-api"),d.found&&d.authenticated&&b.push("gemini-cli"),f.configured&&b.push("gemini-api"),u.found&&u.authenticated&&b.push("codex-cli"),{tools:{node:e,git:n,hubspot:o,github:{...i,...r},claudeCode:c,claudeOAuth:a,geminiCli:d,codexCli:u},apiKeys:{anthropic:g,openai:h,gemini:f},activeEngine:t.aiEngine||null,availableEngines:b,enabledCLITools:l}}var Bt,fi,Ht=R(()=>{"use strict";y();Jt();Q();xt();Bt=process.platform==="win32"?"where":"which";fi={name:"",found:!1,version:"",path:"",authenticated:!1,authDetail:"Disabled"}});import{readFileSync as bp}from"fs";import{basename as Sp}from"path";async function Sa(t){let e=ba.get(t);if(e&&e.expiresAt-Date.now()>wp)return e;let n=await fetch(`${vt}/localdevauth/v1/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({encodedOAuthRefreshToken:t})});if(!n.ok){let i=await n.text().catch(()=>"");throw new Error(n.status===401||n.status===403?"Invalid or expired Personal Access Key":`Token exchange failed (${n.status}): ${i.slice(0,200)}`)}let s=await n.json(),o={accessToken:s.oauthAccessToken,expiresAt:s.expiresAtMillis,hubId:s.hubId,hubName:s.hubName||""};return ba.set(t,o),o}async function an(t){let{accessToken:e}=await Sa(t);return{Authorization:`Bearer ${e}`}}function Fs(t){return t.replace(/^\/+/,"").split("/").filter(Boolean).map(encodeURIComponent).join("/")}function Cp(t){return t.startsWith("pat-eu1-")?"eu1":t.startsWith("pat-na1-")?"na1":t.startsWith("CiRldTE")?"eu1":"na1"}function kp(t){return new Promise(e=>setTimeout(e,t))}async function Fn(t,e){let n=`HTTP ${t.status}`,s,o;try{let i=await t.json();if(i.message&&typeof i.message=="string"&&(n=i.message),i.category&&typeof i.category=="string"&&(s=i.category),i.errors&&Array.isArray(i.errors)&&i.errors.length>0){let r=i.errors[0];o=r.message||JSON.stringify(r)}}catch{try{let i=await t.text();i&&(n=i.slice(0,500))}catch{}}return{status:t.status,message:e?`${n} (${e})`:n,category:s,detail:o}}async function jn(t,e,n=xp){for(let s=0;s<=n;s++){let o=await fetch(t,e);if(o.status===429||o.status>=500&&s<n){let i=vp*Math.pow(2,s);await kp(i);continue}return o}return fetch(t,e)}async function js(t){let e=await Sa(t),n=`${vt}/account-info/v3/details`,s=await jn(n,{headers:await an(t)});if(!s.ok){let a=await Fn(s);throw new Error(`Failed to get account info: ${a.message}`)}let o=await s.json(),i=String(o.portalId||e.hubId||""),r=e.hubName||o.uiDomain||i;return{portalId:i,portalName:r,dataCenter:Cp(t)}}async function xa(t,e,n){let s=bp(n),o=Sp(n),i=new FormData,r=new Blob([s]);i.append("file",r,o);let a=`${vt}/cms/v3/source-code/published/content/${Fs(e)}`,l=await jn(a,{method:"PUT",headers:await an(t),body:i});if(!l.ok){let c=await Fn(l,e);return{success:!1,path:e,error:c}}return{success:!0,path:e}}async function bi(t,e){let n=`${vt}/cms/v3/source-code/published/content/${Fs(e)}`,s=await jn(n,{method:"DELETE",headers:await an(t)});if(!s.ok&&s.status!==404){let o=await Fn(s,e);throw new Error(`Failed to delete ${e}: ${o.message}`)}}async function va(t,e){let n=`${vt}/cms/v3/source-code/published/content/${Fs(e)}`,s=await jn(n,{method:"GET",headers:await an(t)});if(!s.ok){let i=await Fn(s,e);throw new Error(`Failed to download ${e}: ${i.message}`)}let o=await s.arrayBuffer();return Buffer.from(o)}async function Ds(t,e){let n=`${vt}/cms/v3/source-code/published/metadata/${Fs(e)}`,s=await jn(n,{method:"GET",headers:await an(t)});if(s.status===404)return null;if(!s.ok){let o=await Fn(s,e);throw new Error(`Failed to get metadata for ${e}: ${o.message}`)}return await s.json()}async function wa(t){let e=await an(t),n=[`${vt}/cms/v3/source-code/published/metadata`,`${vt}/cms/v3/source-code/published/metadata/`,`${vt}/designmanager/v1/portals/content/listing`];for(let s of n)try{let o=await fetch(s,{method:"GET",headers:e});if(o.ok){let i=await o.json(),r=i.children||i.objects||(Array.isArray(i)?i:null);if(r&&r.length>0)return r.filter(a=>a.folder)}}catch{}return[]}var vt,xp,vp,wp,ba,Ut=R(()=>{"use strict";y();vt="https://api.hubapi.com",xp=3,vp=1e3,wp=300*1e3,ba=new Map});import*as se from"@clack/prompts";function Si(t){se.isCancel(t)&&(se.cancel(_.muted("Operation cancelled.")),process.exit(0))}async function me(t){se.intro(_.heading(t))}async function pe(t){se.outro(_.success(t))}async function ut(t,e){se.note(t,e?_.heading(e):void 0)}async function be(t){let e=await se.text({message:_.accent(t.message),placeholder:t.placeholder,defaultValue:t.defaultValue,validate:t.validate});return Si(e),e}async function Ae(t){let e=await se.confirm({message:_.accent(t.message),initialValue:t.initialValue??!0});return Si(e),e}async function wt(t){let e=await se.select({message:_.accent(t.message),options:t.options});return Si(e),e}async function Pe(){let t=se.spinner();return{start:e=>t.start(_.muted(e)),stop:e=>t.stop(_.success(e)),message:e=>t.message(_.muted(e))}}function j(t){se.log.info(t)}function G(t){se.log.success(_.success(t))}function ee(t){se.log.warn(_.warn(t))}function z(t){se.log.error(_.error(t))}var Ye=R(()=>{"use strict";y();at()});import{readdirSync as xi,statSync as Tp}from"fs";import{join as ge,basename as vi,extname as Ap}from"path";function Ca(t){return typeof t!="string"||t.length===0||t.length>2048||/[\s;&|`$()<>\\]/.test(t)?!1:!!(/^https?:\/\/[^\s]+$/.test(t)||/^git@[\w.-]+:[\w./~+-]+$/.test(t))}function ka(t){let e=[],n=[ge(t,"src/components/landing"),ge(t,"src/components/sections"),ge(t,"src/components"),ge(t,"src/pages"),ge(t,"app/components"),ge(t,"components")];for(let s of n)if(v(s))try{let o=xi(s);for(let i of o){let r=ge(s,i);if(!Tp(r).isFile())continue;let l=Ap(i);if(![".tsx",".jsx"].includes(l))continue;let c=vi(i,l);if(c.startsWith("ui")||c==="index")continue;let d=M(r),u=$p(c,d);e.push({name:c,path:r,description:u})}}catch{}return e}function $p(t,e){let n=[];return/carousel|slider|swiper|embla/i.test(e)&&n.push("carousel"),/accordion|collapsible|expand/i.test(e)&&n.push("accordion"),/form|submit|input.*email/i.test(e)&&n.push("form"),/nav|navigation|menu/i.test(e)&&n.push("navigation"),/hero|headline|tagline/i.test(e)&&n.push("hero"),/footer|copyright/i.test(e)&&n.push("footer"),/testimonial|quote|review/i.test(e)&&n.push("testimonials"),/pricing|plan|tier/i.test(e)&&n.push("pricing"),/faq|question.*answer/i.test(e)&&n.push("FAQ"),/feature|benefit|advantage/i.test(e)&&n.push("features"),/contact|get.in.touch/i.test(e)&&n.push("contact"),/cta|call.to.action/i.test(e)&&n.push("CTA"),/team|member|bio/i.test(e)&&n.push("team"),n.length===0?t.replace(/Section$/,"").replace(/([A-Z])/g," $1").trim():n.join(", ")}function Ta(t){let e=[ge(t,"src/index.css"),ge(t,"src/globals.css"),ge(t,"src/app/globals.css"),ge(t,"app/globals.css")],n=0,s=[];for(let o of e){if(!v(o))continue;let i=M(o),r=i.match(/--[\w-]+:/g);r&&(n+=r.length);let a=i.match(/font-family:\s*['"]([^'"]+)['"]/g);if(a)for(let c of a){let d=c.match(/['"]([^'"]+)['"]/)?.[1];d&&!s.includes(d)&&s.push(d)}let l=i.match(/@import\s+url\([^)]*fonts\.googleapis\.com[^)]*family=([^&)]+)/g);if(l)for(let c of l){let d=c.match(/family=([^&)]+)/)?.[1]?.replace(/\+/g," ");d&&!s.includes(d)&&s.push(d)}}return{varCount:n,fonts:s}}function Aa(t){let e=[],n=ge(t,"src/hooks");if(v(n))try{let o=xi(n);for(let i of o)/scroll/i.test(i)&&e.push("Scroll animations"),/intersection/i.test(i)&&e.push("Scroll animations")}catch{}let s=ge(t,"src/components/landing");if(v(s))try{let o=xi(s);for(let i of o){if(!i.endsWith(".tsx")&&!i.endsWith(".jsx"))continue;let r=M(ge(s,i));/carousel|embla|swiper/i.test(r)&&!e.includes("Carousel")&&e.push("Carousel"),/accordion|collapsible/i.test(r)&&!e.includes("Accordion")&&e.push("Accordion"),/typing|typewriter/i.test(r)&&!e.includes("Typing animation")&&e.push("Typing animation"),/parallax|requestAnimationFrame/i.test(r)&&!e.includes("Parallax")&&e.push("Parallax")}}catch{}return e.length===0&&e.push("Scroll animations"),e}function $a(t){let e,n=!1;if(t.startsWith("http")||t.startsWith("git@")){if(!Ca(t))throw new Error(`Refusing to clone unsafe source URL: ${t}. Only http(s):// and git@host:path URLs without shell metacharacters are allowed.`);n=!0;let l=vi(t.replace(/\.git$/,""))||"react-source";if(e=ge(process.cwd(),"workspace",l),!v(e)){let c=X(["clone","--depth","1","--",t,e]);if(!c.success)throw new Error(`Failed to clone ${t}: ${c.stderr}`)}}else if(e=t,!v(e))throw new Error(`Directory not found: ${e}`);let s=ka(e),o=v(ge(e,"tailwind.config.ts"))||v(ge(e,"tailwind.config.js")),{varCount:i,fonts:r}=Ta(e),a=Aa(e);return{sourceDir:e,wasCloned:n,components:s,hasTailwind:o,cssVarCount:i,fonts:r,interactions:a}}async function Js(){await me("Source Project");let t=await be({message:"GitHub URL or local path to your React project:",placeholder:"https://github.com/user/my-lovable-page",validate:h=>{if(!h.trim())return"Please enter a URL or path"}}),e,n=!1;if(t.startsWith("http")||t.startsWith("git@")){Ca(t)||(z("Refusing to clone unsafe source URL. Only http(s):// and git@host:path URLs without shell metacharacters are allowed."),process.exit(1)),n=!0;let h=vi(t.replace(/\.git$/,""))||"react-source";if(e=ge(process.cwd(),"workspace",h),v(e))G(`Using existing clone: ${_.dim(e)}`);else{let f=await Pe();f.start("Cloning repository..."),X(["clone","--depth","1","--",t,e]).success||(f.stop("Clone failed"),z(`Failed to clone ${t}. Check the URL and your access permissions.`),process.exit(1)),f.stop(`Cloned to ${_.dim(e)}`)}}else e=t,v(e)||(z(`Directory not found: ${e}`),process.exit(1)),G(`Using local source: ${_.dim(e)}`);let s=await Pe();s.start("Analyzing project structure...");let o=ka(e),i=v(ge(e,"tailwind.config.ts"))||v(ge(e,"tailwind.config.js")),{varCount:r,fonts:a}=Ta(e),l=Aa(e);s.stop(`Found ${o.length} landing page components`),o.length===0&&(ee("No components found. Make sure the React source has .tsx/.jsx files in src/components/"),process.exit(1));let c=o.map((h,f)=>` ${_.dim(`${f+1}.`)} ${_.bold(h.name)} ${_.muted(`\u2014 ${h.description}`)}`).join(`
4
+ `),d=i?`Tailwind + custom CSS (${r} variables)`:`Custom CSS (${r} variables)`,u=a.length>0?a.join(", "):"System fonts",m=l.join(", ");return await ut(`${c}
5
+
6
+ CSS: ${d}
7
+ JS: ${m}
8
+ Font: ${u}`,`${o.length} components detected`),await Ae({message:"Does this look right?"})||(z("Please adjust your source directory and try again."),process.exit(0)),await pe("Source analyzed!"),{sourceDir:e,wasCloned:n,components:o,hasTailwind:i,cssVarCount:r,fonts:a,interactions:l}}var Bs=R(()=>{"use strict";y();Jt();ne();Ye();at()});var _a={};Be(_a,{addEmailTemplateToTheme:()=>ln,createThemeScaffold:()=>Ln});import{mkdirSync as Ct,writeFileSync as Dn}from"fs";import{join as He}from"path";function Ln(t,e){Ct(t,{recursive:!0}),Ct(He(t,"templates"),{recursive:!0}),Ct(He(t,"modules"),{recursive:!0}),Ct(He(t,"css"),{recursive:!0}),Ct(He(t,"js"),{recursive:!0}),Ct(He(t,"images"),{recursive:!0}),Ct(He(t,"assets"),{recursive:!0});let n={label:e,preview_path:"./templates/home.html",screenshot_path:"./images/template-previews/home.png",enable_domain_stylesheets:!1,version:"1.0.0",author:{name:"vibeSpot",url:"https://github.com/borismichel/vibespot"}};Dn(He(t,"theme.json"),JSON.stringify(n,null,2)+`
9
+ `),Dn(He(t,"fields.json"),`[]
3
10
  `);let s=`<!--
4
11
  templateType: page
5
12
  isAvailableForNewContent: false
6
- label: ${t} (placeholder)
13
+ label: ${e} (placeholder)
7
14
  screenshotPath: ../images/template-previews/home.png
8
15
  -->
9
16
  {% extends "./layouts/base.html" %}
@@ -11,11 +18,11 @@ var $u=Object.defineProperty;var G=(e,t)=>()=>(e&&(t=e(e=0)),t);var _e=(e,t)=>{f
11
18
  {% block body %}
12
19
  {% dnd_area "main_content"
13
20
  label="Main Content",
14
- class="body-container body-container--${t}"
21
+ class="body-container body-container--${e}"
15
22
  %}
16
23
  {% end_dnd_area %}
17
24
  {% endblock body %}
18
- `;Ss(Le(e,"templates","home.html"),s);let o=`<!--
25
+ `;Dn(He(t,"templates","home.html"),s);let o=`<!--
19
26
  templateType: none
20
27
  isAvailableForNewContent: false
21
28
  label: Base Layout
@@ -38,8 +45,47 @@ var $u=Object.defineProperty;var G=(e,t)=>()=>(e&&(t=e(e=0)),t);var _e=(e,t)=>{f
38
45
  {{ standard_footer_includes }}
39
46
  </body>
40
47
  </html>
41
- `;vt(Le(e,"templates","layouts"),{recursive:!0}),Ss(Le(e,"templates","layouts","base.html"),o)}var xs=G(()=>{"use strict";g()});var Qr={};_e(Qr,{fetchTheme:()=>$n});import{mkdirSync as Zr,writeFileSync as Qu}from"fs";import{join as em,dirname as tm}from"path";async function Xo(e,t){let n=await hs(e,t);if(!n)return[];if(!n.folder)return[n.path||t];let s=[],o=n.children||[];for(let i of o){let r=typeof i=="string"?i:i.name;if(!r)continue;let a=`${t}/${r}`;if(typeof i=="string")s.push(...await Xo(e,a));else{let l=i;l.folder?s.push(...await Xo(e,l.path||a)):s.push(l.path||a)}}return s}async function nm(e,t,n){let s=0;async function o(){for(;s<e.length;){let r=s++;await n(e[r])}}let i=Array.from({length:Math.min(t,e.length)},()=>o());await Promise.all(i)}async function $n(e,t,n,s={}){let o=s.concurrency??5,i=await Xo(e,t);if(i.length===0)throw new Error(`Theme "${t}" not found on HubSpot or is empty`);Zr(n,{recursive:!0}),await nm(i,o,async r=>{let a=r.startsWith(t+"/")?r.slice(t.length+1):r,l=em(n,a);Zr(tm(l),{recursive:!0});let c=await Wr(e,r);Qu(l,c),s.onFile?.(a)})}var vs=G(()=>{"use strict";g();Rt()});function qt(e){let t=ea.get(e);if(t!==void 0)return t;try{t=T(ss(e))}catch{t=""}return ea.set(e,t),t}function ge(){return qt("conversion-guide.md")||"Conversion guide not found. Using built-in rules."}function Zo(){return qt("design-guide.md")}function Qo(){return qt("content-guide.md")}function He(){return qt("hubspot-rules.md")}function ei(){return qt("humanify-guide.md")}function ti(e){let t=qt("page-types.md");if(!t)return"";let s={landing_page:"## Landing Page",blog_post:"## Blog Post",website_page:"## Website Page",module_only:"## Module Only"}[e];if(!s)return"";let o=t.indexOf(s);if(o<0)return"";let i=t.indexOf(`
42
- ## `,o+s.length);return i>=0?t.slice(o,i).trim():t.slice(o).trim()}function ta(e){return`You are a HubSpot CMS expert converting React/Tailwind pages to native HubSpot modules.
48
+ `;Ct(He(t,"templates","layouts"),{recursive:!0}),Dn(He(t,"templates","layouts","base.html"),o)}function ln(t,e){let n=`<!--
49
+ templateType: email
50
+ isAvailableForNewContent: true
51
+ label: ${e} Email Template
52
+ screenshotPath: ../images/template-previews/email.png
53
+ -->
54
+ <!DOCTYPE html>
55
+ <html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
56
+ <head>
57
+ <meta charset="utf-8">
58
+ <meta name="viewport" content="width=device-width, initial-scale=1">
59
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
60
+ <!--[if mso]>
61
+ <noscript>
62
+ <xml>
63
+ <o:OfficeDocumentSettings>
64
+ <o:AllowPNG/>
65
+ <o:PixelsPerInch>96</o:PixelsPerInch>
66
+ </o:OfficeDocumentSettings>
67
+ </xml>
68
+ </noscript>
69
+ <![endif]-->
70
+ {{ standard_header_includes }}
71
+ {{ dnd_area_stylesheet }}
72
+ </head>
73
+ <body style="margin:0;padding:0;background-color:#f4f4f4;font-family:Arial,Helvetica,sans-serif;-webkit-font-smoothing:antialiased;">
74
+ <table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="background-color:#f4f4f4;">
75
+ <tr>
76
+ <td align="center" style="padding:20px 0;">
77
+ {% dnd_area "main"
78
+ label="Email Content"
79
+ %}
80
+ {% end_dnd_area %}
81
+ </td>
82
+ </tr>
83
+ </table>
84
+ {{ standard_footer_includes }}
85
+ </body>
86
+ </html>
87
+ `;Ct(He(t,"templates"),{recursive:!0}),Dn(He(t,"templates","email.html"),n)}var Jn=R(()=>{"use strict";y()});var Ea={};Be(Ea,{fetchTheme:()=>Bn});import{mkdirSync as Ma,writeFileSync as _p}from"fs";import{join as Mp,dirname as Ep}from"path";async function wi(t,e){let n=await Ds(t,e);if(!n)return[];if(!n.folder)return[n.path||e];let s=[],o=n.children||[];for(let i of o){let r=typeof i=="string"?i:i.name;if(!r)continue;let a=`${e}/${r}`;if(typeof i=="string")s.push(...await wi(t,a));else{let l=i;l.folder?s.push(...await wi(t,l.path||a)):s.push(l.path||a)}}return s}async function Ip(t,e,n){let s=0;async function o(){for(;s<t.length;){let r=s++;await n(t[r])}}let i=Array.from({length:Math.min(e,t.length)},()=>o());await Promise.all(i)}async function Bn(t,e,n,s={}){let o=s.concurrency??5,i=await wi(t,e);if(i.length===0)throw new Error(`Theme "${e}" not found on HubSpot or is empty`);Ma(n,{recursive:!0}),await Ip(i,o,async r=>{let a=r.startsWith(e+"/")?r.slice(e.length+1):r,l=Mp(n,a);Ma(Ep(l),{recursive:!0});let c=await va(t,r);_p(l,c),s.onFile?.(a)})}var Hs=R(()=>{"use strict";y();Ut()});function Pt(t){let e=Ia.get(t);if(e!==void 0)return e;try{e=M(Ts(t))}catch{e=""}return Ia.set(t,e),e}function fe(){return Pt("conversion-guide.md")||"Conversion guide not found. Using built-in rules."}function Un(){return Pt("design-guide.md")}function Ci(){return Pt("content-guide.md")}function je(){return Pt("hubspot-rules.md")}function ki(){return Pt("humanify-guide.md")}function Pa(){return Pt("email-rules.md")}function Ra(){return Pt("blog-rules.md")}function Ti(t){let e=Pt("page-types.md");if(!e)return"";let s={landing_page:"## Landing Page",blog_post:"## Blog Post",website_page:"## Website Page",module_only:"## Module Only"}[t];if(!s)return"";let o=e.indexOf(s);if(o<0)return"";let i=e.indexOf(`
88
+ ## `,o+s.length);return i>=0?e.slice(o,i).trim():e.slice(o).trim()}function Na(t){return`You are a HubSpot CMS expert converting React/Tailwind pages to native HubSpot modules.
43
89
 
44
90
  ## Rules
45
91
  Follow the conversion guide below EXACTLY. Key rules:
@@ -56,10 +102,10 @@ Follow the conversion guide below EXACTLY. Key rules:
56
102
  - Convert React hooks to vanilla JS (no React, no npm packages)
57
103
 
58
104
  ## HubSpot CMS Rules
59
- ${He()}
105
+ ${je()}
60
106
 
61
107
  ## Conversion Guide
62
- ${e}`}function na(e,t,n){return`Convert this React component to a HubSpot module named "${t}".
108
+ ${t}`}function Oa(t,e,n){return`Convert this React component to a HubSpot module named "${e}".
63
109
 
64
110
  Return a JSON object with these keys:
65
111
  - fieldsJson: complete fields.json content (as JSON string)
@@ -72,9 +118,9 @@ Design system CSS variables available:
72
118
  ${n}
73
119
 
74
120
  React component source:
75
- ${e}
121
+ ${t}
76
122
 
77
- Return ONLY valid JSON, no markdown fences.`}function sa(e,t,n){return`Create a shared CSS file for a HubSpot CMS landing page.
123
+ Return ONLY valid JSON, no markdown fences.`}function Fa(t,e,n){return`Create a shared CSS file for a HubSpot CMS landing page.
78
124
 
79
125
  Extract the design system from the source CSS and Tailwind config below.
80
126
  Use the class prefix ".${n}-" for all custom classes.
@@ -93,12 +139,12 @@ Requirements:
93
139
  - Responsive grid fallbacks
94
140
 
95
141
  Source CSS:
96
- ${e}
142
+ ${t}
97
143
 
98
144
  Tailwind config:
99
- ${t}
145
+ ${e}
100
146
 
101
- Return ONLY the CSS content, no markdown fences.`}function oa(e,t,n){return`Create a shared vanilla JS file for a HubSpot CMS landing page.
147
+ Return ONLY the CSS content, no markdown fences.`}function ja(t,e,n){return`Create a shared vanilla JS file for a HubSpot CMS landing page.
102
148
 
103
149
  Convert the React hooks and interactive components below to plain JavaScript.
104
150
  Use the class prefix "${n}-" to match the CSS.
@@ -111,14 +157,14 @@ Requirements:
111
157
  - DOMContentLoaded / readyState check
112
158
 
113
159
  React hooks source:
114
- ${e}
160
+ ${t}
115
161
 
116
162
  Interactive component sources:
117
- ${t}
163
+ ${e}
118
164
 
119
- Return ONLY the JavaScript content, no markdown fences.`}function ia(e,t,n){return`Create a HubSpot page template that assembles these modules:
165
+ Return ONLY the JavaScript content, no markdown fences.`}function Da(t,e,n){return`Create a HubSpot page template that assembles these modules:
120
166
 
121
- ${e.map((s,o)=>`${o+1}. ${s}.module`).join(`
167
+ ${t.map((s,o)=>`${o+1}. ${s}.module`).join(`
122
168
  `)}
123
169
 
124
170
  Template requirements:
@@ -129,36 +175,39 @@ Template requirements:
129
175
  - Empty header and footer blocks (modules handle them)
130
176
  - Wrap content in <div class="${n}-page">
131
177
  - Each module in its own dnd_section with padding zeroed and full_width=true
132
- - dnd_area label: "${t} Landing Page"
133
-
134
- Return ONLY the template HTML content, no markdown fences.`}var ea,ut=G(()=>{"use strict";g();Q();ea=new Map});var Ea=G(()=>{"use strict";g()});import{existsSync as pt,writeFileSync as Mm,mkdirSync as Rm}from"fs";import{join as et}from"path";function Ra(e){return/^[0-9a-f]{4,40}$/i.test(e)}function Be(){return Ns!==null||(Ns=D("git --version").success),Ns}function Os(e){if(!Be())return!1;if(pt(et(e,".git")))return Ma(e),!0;let t=D("git init",{cwd:e});return t.success?(_m(e),Ma(e),D("git add -A",{cwd:e}),D('git commit -m "Initial theme"',{cwd:e}),!0):(console.warn(`[project-git] git init failed in ${e}: ${t.stderr}`),!1)}function Ma(e){let t=et(e,".vibespot");pt(t)||Rm(t,{recursive:!0})}function _m(e){let t=et(e,".gitignore");Mm(t,[".vibespot/","node_modules/",""].join(`
135
- `),"utf-8")}function _t(e,t){if(!Be()||!pt(et(e,".git"))||(D("git add -A",{cwd:e}),D("git diff --cached --quiet",{cwd:e}).success))return null;let s=t.length>72?t.slice(0,69)+"...":t,o=D(`git commit -m "${s.replace(/"/g,'\\"')}"`,{cwd:e});if(!o.success)return console.warn(`[project-git] commit failed: ${o.stderr}`),null;let i=D("git rev-parse --short HEAD",{cwd:e});return i.success?i.stdout:null}function si(e,t,n,s){if(!Be()||!pt(et(e,".git")))return null;for(let u of s){let m=et(e,u);pt(m)&&D(`git add "${u}"`,{cwd:e})}if(D("git diff --cached --quiet",{cwd:e}).success)return null;let i=`[${t}] `,r=72-i.length,a=n.length>r?n.slice(0,r-3)+"...":n,l=i+a,c=D(`git commit -m "${l.replace(/"/g,'\\"')}"`,{cwd:e});if(!c.success)return console.warn(`[project-git] template commit failed: ${c.stderr}`),null;let d=D("git rev-parse --short HEAD",{cwd:e});return d.success?d.stdout:null}function _a(e){let t=[],n=null;for(let s of e.split(`
136
- `)){let o=s.trimEnd();if(o.startsWith("COMMIT|")){n&&t.push(n);let i=o.slice(7).split("|");if(i.length<4){n=null;continue}let r=parseInt(i[3],10)*1e3;n={hash:i[0],fullHash:i[1],message:i[2],timestamp:r,date:new Date(r).toISOString(),changedFiles:[],changedModules:[]}}else o&&n&&n.changedFiles.push(o)}n&&t.push(n);for(let s of t){if(!s.changedFiles)continue;let o=new Set;for(let i of s.changedFiles){let r=i.match(/^modules\/([^/]+)\.module(?:\/|$)/);r&&o.add(r[1])}s.changedModules=[...o]}return t}function Pa(e,t=50){if(!Be())return[];if(!pt(et(e,".git")))return[];let n=D(`git log --name-only --pretty=format:"COMMIT|%h|%H|%s|%at" -n ${t}`,{cwd:e});return!n.success||!n.stdout.trim()?[]:_a(n.stdout)}function Na(e,t,n=50){if(!Be())return[];if(!pt(et(e,".git")))return[];let s=t.replace(/[[\]\\]/g,"\\$&"),o=D(`git log --grep="\\[${s}\\]" --name-only --pretty=format:"COMMIT|%h|%H|%s|%at" -n ${n}`,{cwd:e});return!o.success||!o.stdout.trim()?[]:_a(o.stdout)}function Oa(e,t){if(!Be())return{success:!1,error:"Git not available"};if(!pt(et(e,".git")))return{success:!1,error:"Not a git repo"};if(!Ra(t))return{success:!1,error:"Invalid commit hash"};let n=D(`git cat-file -t ${t}`,{cwd:e});if(!n.success||n.stdout.trim()!=="commit")return{success:!1,error:`Commit ${t} not found`};let s=D(`git log --format="%s" -1 ${t}`,{cwd:e}),o=s.success?s.stdout:t,i=D(`git checkout ${t} -- .`,{cwd:e});if(!i.success)return{success:!1,error:`Checkout failed: ${i.stderr}`};let r=`Rollback to: ${o}`.slice(0,72);return D(`git commit -m "${r.replace(/"/g,'\\"')}"`,{cwd:e}),{success:!0}}function Fa(e,t,n,s){if(!Be())return{success:!1,error:"Git not available"};if(!pt(et(e,".git")))return{success:!1,error:"Not a git repo"};if(!Ra(n))return{success:!1,error:"Invalid commit hash"};let o=D(`git cat-file -t ${n}`,{cwd:e});if(!o.success||o.stdout.trim()!=="commit")return{success:!1,error:`Commit ${n} not found`};let i=D(`git log --format="%s" -1 ${n}`,{cwd:e}),r=i.success?i.stdout:n,a=0;for(let d of s)D(`git checkout ${n} -- "${d}"`,{cwd:e}).success&&a++;if(a===0)return{success:!1,error:"No files could be restored from that commit"};D("git add -A",{cwd:e});let c=`${`[${t}] `}Rollback to: ${r}`.slice(0,72);return D(`git commit -m "${c.replace(/"/g,'\\"')}"`,{cwd:e}),{success:!0}}var Ns,Zt=G(()=>{"use strict";g();Et();Ns=null});import{appendFileSync as Pm,mkdirSync as Nm,readdirSync as Om,unlinkSync as Fm}from"fs";import{join as ai}from"path";import{homedir as jm}from"os";function Jm(){if(!ii)try{Nm(Fs,{recursive:!0}),ii=!0}catch{}}function Lm(){if(!ri){ri=!0;try{let e=Date.now()-Dm*864e5;for(let t of Om(Fs)){if(!t.startsWith("vibespot-")||!t.endsWith(".log"))continue;let n=t.slice(9,19),s=new Date(n).getTime();if(s&&s<e)try{Fm(ai(Fs,t))}catch{}}}catch{}}}function Hm(){let t=new Date().toISOString().slice(0,10);return ai(Fs,`vibespot-${t}.log`)}function Bm(){return new Date().toISOString().slice(11,23)}function oi(e,t){if(Jm(),!!ii){ri||Lm();try{Pm(Hm(),`${Bm()} ${e} ${t}
137
- `)}catch{}}}var Fs,Dm,ii,ri,E,re=G(()=>{"use strict";g();Fs=ai(jm(),".vibespot","logs"),Dm=7,ii=!1,ri=!1;E={info(e,t,n){let s=n?`[${e}] ${t} ${JSON.stringify(n)}`:`[${e}] ${t}`;console.log(s),oi("INFO",s)},warn(e,t,n){let s=n?`[${e}] ${t} ${JSON.stringify(n)}`:`[${e}] ${t}`;console.warn(s),oi("WARN",s)},error(e,t,n){let s=n instanceof Error?n.message:n?String(n):"",o=s?`[${e}] ${t}: ${s}`:`[${e}] ${t}`;console.error(o),oi("ERROR",o)}}});import{readFileSync as Um,existsSync as Da,writeFileSync as Gm,mkdirSync as Wm,rmSync as Vm}from"fs";import{join as js}from"path";function Pt(e){let t=C();t&&(t.modules=e.modules,t.moduleOrder=e.moduleOrder,t.sharedCss=e.sharedCss,t.sharedJs=e.sharedJs,t.template=e.template,t.messages=e.messages,t.brandAssets||(t.brandAssets={}),t.brandAssets.plan=e.plan)}function Ue(){let e=C();if(!e)return;let t=ye();t&&(t.modules=e.modules,t.moduleOrder=e.moduleOrder,t.sharedCss=e.sharedCss,t.sharedJs=e.sharedJs,t.template=e.template,t.messages=e.messages,t.plan=e.brandAssets?.plan)}function Ge(e,t,n){let s=C();if(!s)return;let o={role:e,content:t,timestamp:Date.now()};n&&(o.pipeline=n),s.messages.push(o),s.updatedAt=Date.now(),Ue(),Km()}function Ja(e){let t=C();t&&(t.assets||(t.assets=[]),t.assets.push(e),t.updatedAt=Date.now(),J())}function ja(e){return e.toLowerCase().replace(/[\s\-_]+/g,"")}function zm(e,t){let n=ja(e),s=ja(t);return n===s?!0:n.length<4||s.length<4?!1:n.includes(s)||s.includes(n)}function Ie(e){let t=C();if(t){if(e.sharedCss!==void 0&&(t.sharedCss=e.sharedCss),e.sharedJs!==void 0&&(t.sharedJs=e.sharedJs),e.template!==void 0&&(t.template=e.template),e.modules)for(let n of e.modules){let s=n.moduleName.toLowerCase(),o=t.modules.findIndex(i=>i.moduleName.toLowerCase()===s);if(o>=0)t.modules[o]=n;else{let i=t.modules.find(r=>zm(r.moduleName,n.moduleName));i&&E.warn("session-state",`Module "${n.moduleName}" looks like a renamed variant of existing "${i.moduleName}" \u2014 adding as a new module. This usually indicates the Module Planner re-named an existing module. Check the prompt's "preserve existing names" rule.`),t.modules.push(n),t.moduleOrder.some(r=>r.toLowerCase()===s)||t.moduleOrder.push(n.moduleName)}}t.updatedAt=Date.now(),Ue()}}function wt(e){let t=C();t&&(t.moduleOrder=e,t.updatedAt=Date.now(),Ue())}function La(e){let t=C();if(t){t.modules=t.modules.filter(n=>n.moduleName!==e),t.moduleOrder=t.moduleOrder.filter(n=>n!==e);for(let n of t.templates)n.modules=n.modules.filter(s=>s.moduleName!==e),n.moduleOrder=n.moduleOrder.filter(s=>s!==e);if(t.themePath){let n=js(t.themePath,"modules",`${e}.module`);Da(n)&&Vm(n,{recursive:!0,force:!0})}t.updatedAt=Date.now(),Ue()}}function Ha(e){let t=C();t&&(t.moduleOrder=t.moduleOrder.filter(n=>n!==e),t.updatedAt=Date.now(),Ue())}function Ba(e,t,n){let s=C();if(!s)return;let o=s.modules.find(i=>i.moduleName===e);if(o)try{let i=JSON.parse(o.fieldsJson);Ga(i,t,n),o.fieldsJson=JSON.stringify(i,null,2),s.updatedAt=Date.now(),Ue()}catch{}}function ce(){let e=C();if(!e)return[];let t=[];for(let n of e.moduleOrder){let s=e.modules.find(o=>o.moduleName===n);s&&t.push(s)}for(let n of e.modules)e.moduleOrder.includes(n.moduleName)||t.push(n);return t}function Km(){let e=C();if(e)try{let t=js(e.themePath,".vibespot");Wm(t,{recursive:!0});let n={sessionId:e.id,themeName:e.themeName,messages:e.messages,updatedAt:Date.now()};Gm(js(t,"chat.json"),JSON.stringify(n,null,2),"utf-8")}catch{}}function Ua(e){let t=js(e,".vibespot","chat.json");if(!Da(t))return[];try{let n=JSON.parse(Um(t,"utf-8"));return Array.isArray(n.messages)?n.messages:[]}catch{return[]}}function Ga(e,t,n){let s=t.split("."),o=s[0],i=e.find(r=>r.name===o);i&&(s.length===1?i.default=n:i.children&&Ga(i.children,s.slice(1).join("."),n))}var Mn=G(()=>{"use strict";g();Rn();Nt();re()});import{existsSync as Ds,rmSync as Js}from"fs";import{join as Qt}from"path";function Ls(e){if(e.templates&&e.templates.length>0)return;if(!e.modules||e.modules.length===0){e.templates=[],e.activeTemplateId="";return}let t=`lp-${e.themeName}`,n={id:t,label:`${e.themeName} Landing Page`,pageType:"landing_page",templateFile:`templates/lp-${e.themeName}.html`,modules:[...e.modules],moduleOrder:[...e.moduleOrder],sharedCss:e.sharedCss||"",sharedJs:e.sharedJs||"",template:e.template||"",messages:[...e.messages]};e.templates=[n],e.activeTemplateId=t}function ye(){let e=C();return!e||!e.activeTemplateId||!e.templates?.length?null:e.templates.find(t=>t.id===e.activeTemplateId)||null}function li(e){let t=C();if(!t)return!1;let n=t.templates.find(s=>s.id===e);return n?(t.activeTemplateId=e,Pt(n),t.updatedAt=Date.now(),!0):!1}function Hs(e,t){let n=C();if(!n)throw new Error("No active session");let s=t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,""),i=`${e==="blog_post"?"bp":e==="website_page"?"wp":e==="module_only"?"mo":"lp"}-${s}`,r={id:i,label:t,pageType:e,templateFile:e==="module_only"?"":`templates/${i}.html`,modules:[],moduleOrder:[],sharedCss:"",sharedJs:"",template:"",messages:[]};return n.templates.push(r),n.activeTemplateId=i,Pt(r),n.updatedAt=Date.now(),r}function Wa(e,t){let n=C();if(!n)return null;let s=n.templates.find(c=>c.id===e);if(!s)return null;let o=t||`${s.label} (Copy)`,i=o.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,""),a=`${s.pageType==="blog_post"?"bp":s.pageType==="website_page"?"wp":s.pageType==="module_only"?"mo":"lp"}-${i}`,l={id:a,label:o,pageType:s.pageType,templateFile:s.pageType==="module_only"?"":`templates/${a}.html`,modules:s.modules.map(c=>({...c})),moduleOrder:[...s.moduleOrder],sharedCss:s.sharedCss,sharedJs:s.sharedJs,template:s.template,messages:[],plan:s.plan};return n.templates.push(l),n.activeTemplateId=a,Pt(l),n.updatedAt=Date.now(),l}function Va(e,t){let n=C();if(!n)return!1;let s=n.templates.find(o=>o.id===e);return s?(s.label=t,n.updatedAt=Date.now(),!0):!1}function za(e,t=!1){let n=C();if(!n)return!1;let s=n.templates.findIndex(i=>i.id===e);if(s<0)return!1;let o=n.templates.splice(s,1)[0];if(n.themePath){let i=Qt(n.themePath,"templates"),r=`${o.id}.html`,a=Qt(i,r);if(Ds(a)&&Js(a,{force:!0}),o.pageType==="blog_post"){let l=Qt(i,`${o.id}-listing.html`);Ds(l)&&Js(l,{force:!0})}}if(t&&o.modules.length>0){let i=new Set;for(let a of n.templates)for(let l of a.modules)i.add(l.moduleName);for(let a of n.modules)i.add(a.moduleName);let r=o.modules.map(a=>a.moduleName).filter(a=>!i.has(a));if(n.themePath&&r.length>0){let a=Qt(n.themePath,"modules");for(let l of r){let c=Qt(a,`${l}.module`);Ds(c)&&Js(c,{recursive:!0,force:!0})}}}if(n.activeTemplateId===e&&(n.templates.length>0?li(n.templates[0].id):(n.activeTemplateId="",n.modules=[],n.moduleOrder=[],n.sharedCss="",n.sharedJs="",n.template="",n.messages=[],n.brandAssets&&delete n.brandAssets.plan)),o.plan&&n.themePath&&!n.templates.some(r=>!!r.plan)){let r=Qt(n.themePath,".vibespot","plan.md");Ds(r)&&Js(r,{force:!0})}return n.updatedAt=Date.now(),!0}function ft(){let e=C();if(!e)return[];let t=new Map;for(let n of e.templates)for(let s of n.modules){let o=t.get(s.moduleName);o?o.usedIn.push(n.label):t.set(s.moduleName,{module:s,usedIn:[n.label]})}return Array.from(t.values())}var Nt=G(()=>{"use strict";g();Rn();Mn()});import{readFileSync as gt,readdirSync as pi,existsSync as Ee,writeFileSync as Bs,mkdirSync as Ka,rmSync as ci,renameSync as di}from"fs";import{join as be,dirname as Ym}from"path";import{homedir as qm}from"os";function Us(){if(en)return en;try{return Ee(ui)?(en=JSON.parse(gt(ui,"utf-8")),en):mi()}catch{return mi()}}function Gs(e){en=e;try{Ka(de,{recursive:!0}),Bs(ui,JSON.stringify(e),"utf-8")}catch{}}function mi(){if(!Ee(de))return[];let e=[];for(let t of pi(de).filter(n=>n.endsWith(".json")&&n!=="_index.json"))try{let n=JSON.parse(gt(be(de,t),"utf-8")),s=n.templates||[];e.push({id:n.id,themeName:n.themeName,updatedAt:n.updatedAt,moduleCount:s.reduce((o,i)=>o+(i.modules?.length||0),0),templateCount:s.length,isImported:!!n.isImported})}catch{}return en=e,Gs(e),e}function Xm(e){let t=Us(),n=e.templates||[],s={id:e.id,themeName:e.themeName,updatedAt:e.updatedAt,moduleCount:n.reduce((i,r)=>i+(r.modules?.length||0),0),templateCount:n.length,isImported:!!e.isImported},o=t.findIndex(i=>i.id===e.id);o>=0?t[o]=s:t.push(s),Gs(t)}function Zm(e){let t=Us().filter(n=>n.id!==e);Gs(t)}function Qm(e){let t=Us().filter(n=>n.themeName!==e);Gs(t)}function C(){return Me}function ep(){return`vibe-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`}function tn(e,t,n={}){let s={id:ep(),themePath:e,themeName:t,isImported:!!n.isImported,templates:[],activeTemplateId:"",messages:[],modules:[],sharedCss:"",sharedJs:"",template:"",moduleOrder:[],createdAt:Date.now(),updatedAt:Date.now()};return Me=s,Os(e),s}function J(){if(!Me)return;Ka(de,{recursive:!0});let e=be(de,`${Me.id}.json`);Bs(e,JSON.stringify(Me,null,2),"utf-8"),Xm(Me)}function Ws(e){let t=be(de,e+".json");if(!Ee(t))return null;try{let n=JSON.parse(gt(t,"utf-8"));if(n.templates||(n.templates=[]),n.activeTemplateId||(n.activeTemplateId=""),Ls(n),n.brandAssets?.plan&&n.templates?.length>0){let s=n.templates.find(o=>o.id===n.activeTemplateId)||n.templates[0];s.plan||(s.plan=n.brandAssets.plan)}return Me=n,n}catch{return null}}function nn(){return Ee(de)?Us():[]}function Ya(e,t=!1){let n=be(de,e+".json"),s="";if(t)try{let o=JSON.parse(gt(n,"utf-8"));s=o.themeName||"",o.themePath&&Ee(o.themePath)&&ci(o.themePath,{recursive:!0,force:!0})}catch{}else try{s=JSON.parse(gt(n,"utf-8")).themeName||""}catch{}try{Ee(n)&&ci(n)}catch{}if(s&&Ee(de)){for(let o of pi(de).filter(i=>i.endsWith(".json")&&i!=="_index.json"))try{JSON.parse(gt(be(de,o),"utf-8")).themeName===s&&ci(be(de,o))}catch{}Qm(s)}else Zm(e);Me?.id===e&&(Me=null)}function qa(e,t){let n=be(de,e+".json");if(!Ee(n))return{ok:!1,error:"Session not found"};let s;try{s=JSON.parse(gt(n,"utf-8"))}catch{return{ok:!1,error:"Failed to read session"}}let o=s.themeName;if(o===t)return{ok:!0};let i=s.themePath,r=be(Ym(i),t);if(Ee(i)){if(Ee(r))return{ok:!1,error:"A project with that name already exists"};try{di(i,r)}catch(m){return{ok:!1,error:`Failed to rename folder: ${m instanceof Error?m.message:String(m)}`}}let a=be(r,"css",`${o}-theme.css`),l=be(r,"css",`${t}-theme.css`);if(Ee(a))try{di(a,l)}catch{}let c=be(r,"js",`${o}-animations.js`),d=be(r,"js",`${t}-animations.js`);if(Ee(c))try{di(c,d)}catch{}let u=be(r,"theme.json");if(Ee(u))try{let m=JSON.parse(gt(u,"utf-8"));m.label=t,m.name=t,Bs(u,JSON.stringify(m,null,2),"utf-8")}catch{}}if(Ee(de))for(let a of pi(de).filter(l=>l.endsWith(".json")&&l!=="_index.json"))try{let l=JSON.parse(gt(be(de,a),"utf-8"));l.themeName===o&&(l.themeName=t,l.themePath=r,l.updatedAt=Date.now(),Bs(be(de,a),JSON.stringify(l,null,2),"utf-8"))}catch{}return Me&&Me.themeName===o&&(Me.themeName=t,Me.themePath=r,Me.updatedAt=Date.now()),mi(),{ok:!0}}var de,ui,en,Me,Rn=G(()=>{"use strict";g();Zt();Nt();de=be(qm(),".vibespot","sessions"),ui=be(de,"_index.json"),en=null;Me=null});import{readFileSync as tp,readdirSync as Qa,statSync as fi}from"fs";import{createHash as np}from"crypto";import{join as ae,relative as sp}from"path";function Ks(e){let t=[];if(!b(e))return Ip(e,[{severity:"error",rule:"theme.path.missing",message:`Theme directory not found: ${e}`}]);let n=sn(e),s=kp(e),o=Tp(e),i=$p(e),r=lp(e);Object.keys(n.cssVariables).length===0&&t.push({severity:"info",rule:"design.cssVariables.empty",message:"No :root CSS custom properties found in theme CSS.",fix:"Run with --apply-tokens to seed a :root block from inferred palette/typography."}),n.palette.length===0&&t.push({severity:"info",rule:"design.palette.empty",message:"Could not infer a colour palette from the theme CSS."}),s.orphanModules.length>0&&t.push({severity:"warning",rule:"modules.orphan",message:`${s.orphanModules.length} module(s) are not referenced by any template: ${s.orphanModules.join(", ")}`,fix:"Either reference these modules from a template or remove them."}),s.templates.length===0&&s.modules.length>0&&t.push({severity:"warning",rule:"templates.missing",message:"Theme has modules but no page templates wiring them together.",fix:"Add a templates/<name>.html that includes the modules via dnd_module."});for(let l of o)t.push({severity:"info",rule:"field.unsupported-pattern",file:`modules/${l.module}.module/fields.json`,message:`${l.module}.${l.field}: ${l.reason}`,fix:"vibeSpot will preserve this field as-is. Edit it in HubSpot if changes are needed."});for(let l of i)t.push({severity:"warning",rule:"roundtrip.preserve-pattern",file:l.file,message:`${l.pattern}: ${l.detail}`,fix:"vibeSpot avoids modifying this. Don't ask the AI to refactor it."});r.hasSnapshot&&r.filesChanged>0&&t.push({severity:"info",rule:"roundtrip.snapshot.diff",message:`${r.filesChanged} file(s) differ from the imported theme snapshot.`,fix:"Review report.roundTripDiff before re-uploading if you need to preserve imported files exactly."});let a=i.filter(l=>l.pattern==="hubl.macro").length;return{themePath:e,designTokens:n,graph:s,fieldFlags:o,roundTripRisks:i,roundTripDiff:r,findings:t,summary:{moduleCount:s.modules.length,templateCount:s.templates.length,orphanCount:s.orphanModules.length,paletteSize:n.palette.length,cssVarCount:Object.keys(n.cssVariables).length,customMacroCount:a,roundTripChangedCount:r.filesChanged}}}function _n(e){let t=[];for(let[n,s]of Object.entries(e.cssVariables))t.push(` ${n}: ${s};`);return Object.keys(e.cssVariables).length===0&&(e.palette.slice(0,8).forEach((n,s)=>{let o=s===0?"primary":s===1?"secondary":`accent-${s-1}`;t.push(` --color-${o}: ${n.value};`)}),e.fontFamilies[0]&&t.push(` --font-family-base: ${e.fontFamilies[0]};`),e.fontFamilies[1]&&t.push(` --font-family-heading: ${e.fontFamilies[1]};`)),t.length===0?"":`:root {
138
- ${t.join(`
178
+ - dnd_area label: "${e} Landing Page"
179
+
180
+ Return ONLY the template HTML content, no markdown fences.`}var Ia,Ue=R(()=>{"use strict";y();ne();Ia=new Map});import{join as ce}from"path";import{readdirSync as Ze,rmSync as Vp}from"fs";function Xs(t){let e=[];for(let n of t){let s=`${n.message}${n.detail?` \u2014 ${n.detail}`:""}`,o=!1;/textarea|unknown.*field.*type/i.test(s)&&(o=!0),/reserved.*name|missing field name|field null/i.test(s)&&(o=!0),/could not resolve.*now/i.test(s)&&(o=!0),/hubdb|do not have access/i.test(s)&&(o=!0),/invalid default value|link.*invalid|deserializ/i.test(s)&&(o=!0),/color.*invalid/i.test(s)&&(o=!0),/dnd.area.*only.*have.*name.*main/i.test(s)&&(o=!0),e.push({file:n.file||"unknown",message:s,fixable:o})}return e}function Zs(t){let e=[];if(/textarea.*not.*valid|unknown.*field.*type/i.test(t)){let n=t.match(/(?:in|file:?)\s+(\S+fields\.json)/i);e.push({file:n?.[1]||"fields.json",message:'"textarea" is not a valid field type',fixable:!0})}if(/missing field name|field null/i.test(t)){let n=t.match(/(?:in|file:?)\s+(\S+fields\.json)/i);e.push({file:n?.[1]||"fields.json",message:'"name" is a reserved field name',fixable:!0})}if(/could not resolve.*now/i.test(t)&&e.push({file:"module.html",message:"now() is not a valid HubL function",fixable:!0}),/hubdb|do not have access to hubdb/i.test(t)&&e.push({file:"templates",message:"HubDB requires CMS Hub Pro/Enterprise",fixable:!0}),/invalid default value|link.*field.*invalid/i.test(t)){let n=t.match(/field.*?(\w+)\s+has an invalid/i);e.push({file:n?.[1]||"fields.json",message:"Link field has invalid default value",fixable:!0})}if(/failed to deserialize/i.test(t)){let n=t.match(/file '([^']+)'/i);e.push({file:n?.[1]||"fields.json",message:"fields.json deserialization error",fixable:!0})}return/format for the color value is invalid/i.test(t)&&e.push({file:"fields.json",message:"Color field has invalid format (rgba/rgb/named \u2014 must be hex)",fixable:!0}),/dnd.area.*only.*have.*name.*main/i.test(t)&&e.push({file:"templates/email.html",message:'Dnd area can only have name "main"',fixable:!0}),e}function Qs(t){let e=[];return Wa(t)&&e.push("textarea \u2192 text"),Ka(t)&&e.push("name \u2192 item_name"),Va(t)&&e.push("now() \u2192 local_dt"),za(t)&&e.push("Removed HubDB templates"),Ya(t)&&e.push("Fixed link field defaults"),qa(t)&&e.push("Fixed rgba/invalid color values \u2192 hex"),zp(t)&&e.push("Stripped CDN @import statements"),Za(t)&&e.push('dnd_area \u2192 "main" in email templates'),Qa(t)&&e.push("Added {{ dnd_area_stylesheet }} to email templates"),e}function Ga(t,e){return e.message.includes("textarea")?Wa(t):e.message.includes("reserved field name")?Ka(t):e.message.includes("now()")?Va(t):e.message.includes("HubDB")?za(t):e.message.includes("invalid default value")||e.message.includes("deserialization")?Ya(t):e.message.includes("invalid format")&&e.message.includes("color")?qa(t):e.message.includes("dnd")||e.message.includes("Dnd area")?Za(t):e.message.includes("dnd_area_stylesheet")?Qa(t):!1}function Wa(t){let e=!1,n=ce(t,"modules");if(!v(n))return!1;for(let s of Ze(n)){if(!s.endsWith(".module"))continue;let o=ce(n,s,"fields.json");if(!v(o))continue;let i=M(o);i.includes('"textarea"')&&(i=i.replace(/"textarea"/g,'"text"'),J(o,i),e=!0)}return e}function Ka(t){let e=!1,n=ce(t,"modules");if(!v(n))return!1;for(let s of Ze(n)){if(!s.endsWith(".module"))continue;let o=ce(n,s,"fields.json");if(!v(o))continue;let i=M(o);/"name":\s*"name"/g.test(i)&&(i=i.replace(/"name":\s*"name"/g,'"name": "item_name"'),J(o,i),e=!0)}return e}function Va(t){let e=!1,n=ce(t,"modules");if(!v(n))return!1;for(let s of Ze(n)){if(!s.endsWith(".module"))continue;let o=ce(n,s,"module.html");if(!v(o))continue;let i=M(o);i.includes("now()")&&(i=i.replace(/now\(\)/g,"local_dt"),J(o,i),e=!0)}return e}function za(t){let e=!1,n=ce(t,"templates");if(!v(n))return!1;for(let s of Ze(n)){if(!s.endsWith(".html"))continue;let o=ce(n,s),i=M(o);(i.includes("hubdb_table")||i.includes("hubdb_table_rows"))&&(Vp(o),e=!0)}return e}function Ya(t){let e=!1,n=ce(t,"modules");if(!v(n))return!1;for(let s of Ze(n)){if(!s.endsWith(".module"))continue;let o=ce(n,s,"fields.json");if(v(o))try{let i=JSON.parse(M(o));el(i)&&(J(o,JSON.stringify(i,null,2)+`
181
+ `),e=!0)}catch{}}return e}function zp(t){let e=!1,n=ce(t,"css");if(v(n))for(let o of Ze(n)){if(!o.endsWith(".css"))continue;let i=ce(n,o),r=M(i),a=r.replace(/@import\s+url\(['"]?https?:\/\/[^)]+['"]?\)\s*;?/gi,"");a!==r&&(J(i,a),e=!0)}let s=ce(t,"modules");if(v(s))for(let o of Ze(s)){if(!o.endsWith(".module"))continue;let i=ce(s,o,"module.css");if(!v(i))continue;let r=M(i),a=r.replace(/@import\s+url\(['"]?https?:\/\/[^)]+['"]?\)\s*;?/gi,"");a!==r&&(J(i,a),e=!0)}if(v(s))for(let o of Ze(s)){if(!o.endsWith(".module"))continue;let i=ce(s,o,"module.html");if(!v(i))continue;let r=M(i),a=r.replace(/<link[^>]+href=['"]https?:\/\/[^'"]+['"][^>]*>/gi,"");a!==r&&(J(i,a),e=!0)}return e}function qa(t){let e=!1,n=ce(t,"modules");if(!v(n))return!1;for(let s of Ze(n)){if(!s.endsWith(".module"))continue;let o=ce(n,s,"fields.json");if(v(o))try{let i=JSON.parse(M(o));Xa(i)&&(J(o,JSON.stringify(i,null,2)+`
182
+ `),e=!0)}catch{}}return e}function Xa(t){let e=!1;for(let n of t){if(typeof n!="object"||n===null)continue;let s=n;if(s.type==="color"&&s.default&&typeof s.default=="object"){let o=s.default,i=o.color;if(typeof i=="string"&&!Yp(i)){let r=qp(i);r&&(o.color=r.hex,r.opacity!==void 0&&(o.opacity=r.opacity),e=!0)}}Array.isArray(s.children)&&Xa(s.children)&&(e=!0)}return e}function Yp(t){return/^#[0-9a-fA-F]{6}$/.test(t)}function qp(t){let e=t.match(/^#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])$/);if(e)return{hex:`#${e[1]}${e[1]}${e[2]}${e[2]}${e[3]}${e[3]}`};let n=t.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([\d.]+))?\s*\)/i);if(n){let i=Math.min(255,parseInt(n[1])),r=Math.min(255,parseInt(n[2])),a=Math.min(255,parseInt(n[3])),l=`#${i.toString(16).padStart(2,"0")}${r.toString(16).padStart(2,"0")}${a.toString(16).padStart(2,"0")}`,c=n[4]!==void 0?Math.round(parseFloat(n[4])*100):void 0;return{hex:l,opacity:c}}let s={white:"#ffffff",black:"#000000",red:"#ff0000",green:"#008000",blue:"#0000ff",yellow:"#ffff00",orange:"#ffa500",purple:"#800080",gray:"#808080",grey:"#808080",transparent:"#000000"},o=t.toLowerCase().trim();return s[o]?{hex:s[o],opacity:o==="transparent"?0:void 0}:null}function Za(t){let e=!1,n=ce(t,"templates");if(!v(n))return!1;for(let s of Ze(n)){if(!s.endsWith(".html"))continue;let o=ce(n,s),i=M(o);if(!/templateType:\s*email/i.test(i))continue;let r=i.replace(/\{%\s*dnd_area\s+"(?!main")([^"]+)"/g,'{% dnd_area "main"');r!==i&&(J(o,r),e=!0)}return e}function Qa(t){let e=!1,n=ce(t,"templates");if(!v(n))return!1;for(let s of Ze(n)){if(!s.endsWith(".html"))continue;let o=ce(n,s),i=M(o);if(!/templateType:\s*email/i.test(i)||i.includes("dnd_area_stylesheet"))continue;let r=i.replace(/(\{\{\s*standard_header_includes\s*\}\})/,`$1
183
+ {{ dnd_area_stylesheet }}`);r!==i&&(J(o,r),e=!0)}return e}function el(t){let e=!1;for(let n of t){if(typeof n!="object"||n===null)continue;let s=n;if(s.type==="link"){let o=s.default;if(typeof o=="string"||o===void 0||o===null||typeof o=="object"&&!o.url){let r=typeof o=="string"?o:"";s.default={url:{href:r,type:"EXTERNAL"},open_in_new_tab:!1,no_follow:!1},e=!0}}Array.isArray(s.children)&&el(s.children)&&(e=!0)}return e}var eo=R(()=>{"use strict";y();ne()});import{readdirSync as Xp}from"fs";import{join as Zp,relative as Qp}from"path";function tl(t){let e=[];for(let n of Xp(t,{withFileTypes:!0})){if(eg.has(n.name)||n.name.startsWith(".")&&n.name!==".gitkeep")continue;let s=Zp(t,n.name);n.isDirectory()?e.push(...tl(s)):n.isFile()&&e.push(s)}return e}async function tg(t,e,n){let s=0;async function o(){for(;s<t.length;){let r=s++;await n(t[r])}}let i=Array.from({length:Math.min(e,t.length)},()=>o());await Promise.all(i)}async function to(t,e,n,s={}){let o=s.concurrency??5,i=tl(e),r=i.length,a=0,l=0,c=[];return await tg(i,o,async d=>{let u=Qp(e,d).replace(/\\/g,"/"),m=`${n}/${u}`;s.onFileStart?.(u);let g=await xa(t,m,d);if(g.success)a++,s.onFileComplete?.(u);else{l++;let h={file:u,status:g.error?.status||0,message:g.error?.message||"Unknown error",category:g.error?.category,detail:g.error?.detail};c.push(h),s.onFileError?.(u,h)}s.onProgress?.(a+l,r)}),{success:l===0,uploaded:a,failed:l,total:r,errors:c}}var eg,Ai=R(()=>{"use strict";y();Ut();Ut();eg=new Set([".git","node_modules",".vibespot",".DS_Store"])});var dl=R(()=>{"use strict";y()});import{existsSync as kt,writeFileSync as ig,mkdirSync as rg}from"fs";import{join as pt}from"path";function ml(t){return/^[0-9a-f]{4,40}$/i.test(t)}function pl(t){return Number.isInteger(t)&&t>0&&t<1e3}function Qe(){return no!==null||(no=X(["--version"]).success),no}function so(t){if(!Qe())return!1;if(kt(pt(t,".git")))return ul(t),!0;let e=X(["init"],{cwd:t});return e.success?(ag(t),ul(t),X(["add","-A"],{cwd:t}),X(["commit","-m","Initial theme"],{cwd:t}),!0):(console.warn(`[project-git] git init failed in ${t}: ${e.stderr}`),!1)}function ul(t){let e=pt(t,".vibespot");kt(e)||rg(e,{recursive:!0})}function ag(t){let e=pt(t,".gitignore");ig(e,[".vibespot/","node_modules/",""].join(`
184
+ `),"utf-8")}function Gt(t,e){if(!Qe()||!kt(pt(t,".git"))||(X(["add","-A"],{cwd:t}),X(["diff","--cached","--quiet"],{cwd:t}).success))return null;let s=e.length>72?e.slice(0,69)+"...":e,o=X(["commit","-m",s],{cwd:t});if(!o.success)return console.warn(`[project-git] commit failed: ${o.stderr}`),null;let i=X(["rev-parse","--short","HEAD"],{cwd:t});return i.success?i.stdout:null}function _i(t,e,n,s){if(!Qe()||!kt(pt(t,".git")))return null;for(let u of s){let m=pt(t,u);kt(m)&&X(["add","--",u],{cwd:t})}if(X(["diff","--cached","--quiet"],{cwd:t}).success)return null;let i=`[${e}] `,r=72-i.length,a=n.length>r?n.slice(0,r-3)+"...":n,l=i+a,c=X(["commit","-m",l],{cwd:t});if(!c.success)return console.warn(`[project-git] template commit failed: ${c.stderr}`),null;let d=X(["rev-parse","--short","HEAD"],{cwd:t});return d.success?d.stdout:null}function gl(t){let e=[],n=null;for(let s of t.split(`
185
+ `)){let o=s.trimEnd();if(o.startsWith("COMMIT|")){n&&e.push(n);let i=o.slice(7).split("|");if(i.length<4){n=null;continue}let r=parseInt(i[3],10)*1e3;n={hash:i[0],fullHash:i[1],message:i[2],timestamp:r,date:new Date(r).toISOString(),changedFiles:[],changedModules:[]}}else o&&n&&n.changedFiles.push(o)}n&&e.push(n);for(let s of e){if(!s.changedFiles)continue;let o=new Set;for(let i of s.changedFiles){let r=i.match(/^modules\/([^/]+)\.module(?:\/|$)/);r&&o.add(r[1])}s.changedModules=[...o]}return e}function fl(t,e=50){if(!Qe())return[];if(!kt(pt(t,".git")))return[];if(!pl(e))return[];let n=X(["log","--name-only","--pretty=format:COMMIT|%h|%H|%s|%at","-n",String(e)],{cwd:t});return!n.success||!n.stdout.trim()?[]:gl(n.stdout)}function hl(t,e,n=50){if(!Qe())return[];if(!kt(pt(t,".git")))return[];if(!pl(n))return[];let s=e.replace(/[\\.*+?^${}()|[\]/]/g,"\\$&"),o=X(["log",`--grep=\\[${s}\\]`,"--name-only","--pretty=format:COMMIT|%h|%H|%s|%at","-n",String(n)],{cwd:t});return!o.success||!o.stdout.trim()?[]:gl(o.stdout)}function yl(t,e){if(!Qe())return{success:!1,error:"Git not available"};if(!kt(pt(t,".git")))return{success:!1,error:"Not a git repo"};if(!ml(e))return{success:!1,error:"Invalid commit hash"};let n=X(["cat-file","-t",e],{cwd:t});if(!n.success||n.stdout.trim()!=="commit")return{success:!1,error:`Commit ${e} not found`};let s=X(["log","--format=%s","-1",e],{cwd:t}),o=s.success?s.stdout:e,i=X(["checkout",e,"--","."],{cwd:t});if(!i.success)return{success:!1,error:`Checkout failed: ${i.stderr}`};let r=`Rollback to: ${o}`.slice(0,72);return X(["commit","-m",r],{cwd:t}),{success:!0}}function bl(t,e,n,s){if(!Qe())return{success:!1,error:"Git not available"};if(!kt(pt(t,".git")))return{success:!1,error:"Not a git repo"};if(!ml(n))return{success:!1,error:"Invalid commit hash"};let o=X(["cat-file","-t",n],{cwd:t});if(!o.success||o.stdout.trim()!=="commit")return{success:!1,error:`Commit ${n} not found`};let i=X(["log","--format=%s","-1",n],{cwd:t}),r=i.success?i.stdout:n,a=0;for(let d of s)X(["checkout",n,"--",d],{cwd:t}).success&&a++;if(a===0)return{success:!1,error:"No files could be restored from that commit"};X(["add","-A"],{cwd:t});let c=`${`[${e}] `}Rollback to: ${r}`.slice(0,72);return X(["commit","-m",c],{cwd:t}),{success:!0}}var no,dn=R(()=>{"use strict";y();Jt();no=null});import{appendFileSync as lg,mkdirSync as cg,readdirSync as dg,unlinkSync as ug}from"fs";import{join as Pi}from"path";import{homedir as mg}from"os";function gg(){if(!Ei)try{cg(oo,{recursive:!0}),Ei=!0}catch{}}function fg(){if(!Ii){Ii=!0;try{let t=Date.now()-pg*864e5;for(let e of dg(oo)){if(!e.startsWith("vibespot-")||!e.endsWith(".log"))continue;let n=e.slice(9,19),s=new Date(n).getTime();if(s&&s<t)try{ug(Pi(oo,e))}catch{}}}catch{}}}function hg(){let e=new Date().toISOString().slice(0,10);return Pi(oo,`vibespot-${e}.log`)}function yg(){return new Date().toISOString().slice(11,23)}function Mi(t,e){if(gg(),!!Ei){Ii||fg();try{lg(hg(),`${yg()} ${t} ${e}
186
+ `)}catch{}}}var oo,pg,Ei,Ii,E,de=R(()=>{"use strict";y();oo=Pi(mg(),".vibespot","logs"),pg=7,Ei=!1,Ii=!1;E={info(t,e,n){let s=n?`[${t}] ${e} ${JSON.stringify(n)}`:`[${t}] ${e}`;console.log(s),Mi("INFO",s)},warn(t,e,n){let s=n?`[${t}] ${e} ${JSON.stringify(n)}`:`[${t}] ${e}`;console.warn(s),Mi("WARN",s)},error(t,e,n){let s=n instanceof Error?n.message:n?String(n):"",o=s?`[${t}] ${e}: ${s}`:`[${t}] ${e}`;console.error(o),Mi("ERROR",o)}}});import{readFileSync as bg,existsSync as xl,writeFileSync as Sg,mkdirSync as xg,rmSync as vg}from"fs";import{join as io}from"path";function Wt(t){let e=C();e&&(e.modules=t.modules,e.moduleOrder=t.moduleOrder,e.sharedCss=t.sharedCss,e.sharedJs=t.sharedJs,e.template=t.template,e.messages=t.messages,e.brandAssets||(e.brandAssets={}),e.brandAssets.plan=t.plan)}function et(){let t=C();if(!t)return;let e=Ce();if(!e){if(t.modules.length===0)return;let n={modules:t.modules,moduleOrder:t.moduleOrder,sharedCss:t.sharedCss,sharedJs:t.sharedJs,template:t.template,messages:t.messages,plan:t.brandAssets?.plan};e=Tt("landing_page",`${t.themeName} Landing Page`),t.activeTemplateId=e.id,t.modules=n.modules,t.moduleOrder=n.moduleOrder,t.sharedCss=n.sharedCss,t.sharedJs=n.sharedJs,t.template=n.template,t.messages=n.messages,t.brandAssets&&(t.brandAssets.plan=n.plan)}e.modules=t.modules,e.moduleOrder=t.moduleOrder,e.sharedCss=t.sharedCss,e.sharedJs=t.sharedJs,e.template=t.template,e.messages=t.messages,e.plan=t.brandAssets?.plan}function tt(t,e,n){let s=C();if(!s)return;let o={role:t,content:e,timestamp:Date.now()};n&&(o.pipeline=n),s.messages.push(o),s.updatedAt=Date.now(),et(),Cg()}function vl(t){let e=C();e&&(e.assets||(e.assets=[]),e.assets.push(t),e.updatedAt=Date.now(),D())}function Sl(t){return t.toLowerCase().replace(/[\s\-_]+/g,"")}function wg(t,e){let n=Sl(t),s=Sl(e);if(n===s)return!0;if(n.length<4||s.length<4)return!1;let o=n.length<=s.length?n:s,i=n.length<=s.length?s:n;return i.includes(o)?o.length/i.length>=.8:!1}function De(t){let e=C();if(e){if(t.sharedCss!==void 0&&(e.sharedCss=t.sharedCss),t.sharedJs!==void 0&&(e.sharedJs=t.sharedJs),t.template!==void 0&&(e.template=t.template),t.modules)for(let n of t.modules){let s=n.moduleName.toLowerCase(),o=e.modules.findIndex(i=>i.moduleName.toLowerCase()===s);if(o>=0)e.modules[o]=n;else{let i=e.modules.find(r=>wg(r.moduleName,n.moduleName));i&&E.warn("session-state",`Module "${n.moduleName}" looks like a renamed variant of existing "${i.moduleName}" \u2014 adding as a new module. This usually indicates the Module Planner re-named an existing module. Check the prompt's "preserve existing names" rule.`),e.modules.push(n),e.moduleOrder.some(r=>r.toLowerCase()===s)||e.moduleOrder.push(n.moduleName)}}e.updatedAt=Date.now(),et()}}function Rt(t){let e=C();e&&(e.moduleOrder=t,e.updatedAt=Date.now(),et())}function wl(t){let e=C();if(e){e.modules=e.modules.filter(n=>n.moduleName!==t),e.moduleOrder=e.moduleOrder.filter(n=>n!==t);for(let n of e.templates)n.modules=n.modules.filter(s=>s.moduleName!==t),n.moduleOrder=n.moduleOrder.filter(s=>s!==t);if(e.themePath){let n=io(e.themePath,"modules",`${t}.module`);xl(n)&&vg(n,{recursive:!0,force:!0})}e.updatedAt=Date.now(),et()}}function Cl(t){let e=C();e&&(e.moduleOrder=e.moduleOrder.filter(n=>n!==t),e.updatedAt=Date.now(),et())}function kl(t,e,n){let s=C();if(!s)return;let o=s.modules.find(i=>i.moduleName===t);if(o)try{let i=JSON.parse(o.fieldsJson);$l(i,e,n),o.fieldsJson=JSON.stringify(i,null,2),s.updatedAt=Date.now(),et()}catch{}}function Se(){let t=C();if(!t)return[];let e=[];for(let n of t.moduleOrder){let s=t.modules.find(o=>o.moduleName===n);s&&e.push(s)}for(let n of t.modules)t.moduleOrder.includes(n.moduleName)||e.push(n);return e}function Cg(){let t=C();if(t)try{let e=io(t.themePath,".vibespot");xg(e,{recursive:!0});let n={sessionId:t.id,themeName:t.themeName,messages:t.messages,updatedAt:Date.now()};Sg(io(e,"chat.json"),JSON.stringify(n,null,2),"utf-8")}catch{}}function Tl(t){let e=io(t,".vibespot","chat.json");if(!xl(e))return[];try{let n=JSON.parse(bg(e,"utf-8"));return Array.isArray(n.messages)?n.messages:[]}catch{return[]}}function Al(t){let e=C();if(e){for(let n of e.templates)n.sharedCss=t.sharedCss,n.sharedJs=t.sharedJs;e.sharedCss=t.sharedCss,e.sharedJs=t.sharedJs;for(let n of t.pages){let s=t.pageLabels.get(n.pageId),o=s?.label||n.pageId,i=s?.pageType||"website_page",r=e.templates.find(a=>a.id===n.templateId);r||(r=Tt(i,o),r.id=n.templateId,r.templateFile=`templates/${n.templateId}.html`),r.modules=n.modules,r.moduleOrder=n.moduleOrder,r.sharedCss=t.sharedCss,r.sharedJs=t.sharedJs}t.pages.length>0&&Kn(t.pages[0].templateId),e.updatedAt=Date.now()}}function $l(t,e,n){let s=e.split("."),o=s[0],i=t.find(r=>r.name===o);i&&(s.length===1?i.default=n:i.children&&$l(i.children,s.slice(1).join("."),n))}var Wn=R(()=>{"use strict";y();Vn();Nt();de()});import{existsSync as ro,rmSync as ao}from"fs";import{join as un}from"path";function lo(t){if(t.templates&&t.templates.length>0)return;if(!t.modules||t.modules.length===0){t.templates=[],t.activeTemplateId="";return}let e=`lp-${t.themeName}`,n={id:e,label:`${t.themeName} Landing Page`,pageType:"landing_page",templateFile:`templates/lp-${t.themeName}.html`,modules:[...t.modules],moduleOrder:[...t.moduleOrder],sharedCss:t.sharedCss||"",sharedJs:t.sharedJs||"",template:t.template||"",messages:[...t.messages]};t.templates=[n],t.activeTemplateId=e}function Ce(){let t=C();return!t||!t.activeTemplateId||!t.templates?.length?null:t.templates.find(e=>e.id===t.activeTemplateId)||null}function Kn(t){let e=C();if(!e)return!1;let n=e.templates.find(s=>s.id===t);return n?(e.activeTemplateId=t,Wt(n),e.updatedAt=Date.now(),!0):!1}function Tt(t,e,n){let s=C();if(!s)throw new Error("No active session");let o=e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,""),i=n==="email",a=`${i?"email":t==="blog_post"?"bp":t==="website_page"?"wp":t==="module_only"?"mo":"lp"}-${o}`,l={id:a,label:e,pageType:t,contentMode:n,templateFile:i?"templates/email.html":t==="module_only"?"":`templates/${a}.html`,modules:[],moduleOrder:[],sharedCss:"",sharedJs:"",template:"",messages:[]};return s.templates.push(l),s.activeTemplateId=a,Wt(l),s.updatedAt=Date.now(),l}function _l(t,e){let n=C();if(!n)return null;let s=n.templates.find(c=>c.id===t);if(!s)return null;let o=e||`${s.label} (Copy)`,i=o.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,""),a=`${s.pageType==="blog_post"?"bp":s.pageType==="website_page"?"wp":s.pageType==="module_only"?"mo":"lp"}-${i}`,l={id:a,label:o,pageType:s.pageType,templateFile:s.pageType==="module_only"?"":`templates/${a}.html`,modules:s.modules.map(c=>({...c})),moduleOrder:[...s.moduleOrder],sharedCss:s.sharedCss,sharedJs:s.sharedJs,template:s.template,messages:[],plan:s.plan};return n.templates.push(l),n.activeTemplateId=a,Wt(l),n.updatedAt=Date.now(),l}function Ml(t){let e=C();if(!e||!Array.isArray(t)||t.length===0)return!1;let n=new Map(e.templates.map(i=>[i.id,i])),s=new Set,o=[];for(let i of t){let r=n.get(i);!r||s.has(i)||(o.push(r),s.add(i))}for(let i of e.templates)s.has(i.id)||o.push(i);return o.length!==e.templates.length?!1:(e.templates=o,e.updatedAt=Date.now(),!0)}function El(t,e){let n=C();if(!n)return!1;let s=n.templates.find(o=>o.id===t);return s?(s.label=e,n.updatedAt=Date.now(),!0):!1}function Il(t,e=!1){let n=C();if(!n)return!1;let s=n.templates.findIndex(i=>i.id===t);if(s<0)return!1;let o=n.templates.splice(s,1)[0];if(n.themePath){let i=un(n.themePath,"templates"),r=`${o.id}.html`,a=un(i,r);if(ro(a)&&ao(a,{force:!0}),o.pageType==="blog_post"){let l=un(i,`${o.id}-listing.html`);ro(l)&&ao(l,{force:!0})}}if(e&&o.modules.length>0){let i=new Set;for(let a of n.templates)for(let l of a.modules)i.add(l.moduleName);for(let a of n.modules)i.add(a.moduleName);let r=o.modules.map(a=>a.moduleName).filter(a=>!i.has(a));if(n.themePath&&r.length>0){let a=un(n.themePath,"modules");for(let l of r){let c=un(a,`${l}.module`);ro(c)&&ao(c,{recursive:!0,force:!0})}}}if(n.activeTemplateId===t&&(n.templates.length>0?Kn(n.templates[0].id):(n.activeTemplateId="",n.modules=[],n.moduleOrder=[],n.sharedCss="",n.sharedJs="",n.template="",n.messages=[],n.brandAssets&&delete n.brandAssets.plan)),o.plan&&n.themePath&&!n.templates.some(r=>!!r.plan)){let r=un(n.themePath,".vibespot","plan.md");ro(r)&&ao(r,{force:!0})}return n.updatedAt=Date.now(),!0}function At(){let t=C();if(!t)return[];let e=new Map;for(let n of t.templates)for(let s of n.modules){let o=e.get(s.moduleName);o?o.usedIn.push(n.label):e.set(s.moduleName,{module:s,usedIn:[n.label]})}for(let n of t.modules)e.has(n.moduleName)||e.set(n.moduleName,{module:n,usedIn:[]});return Array.from(e.values())}var Nt=R(()=>{"use strict";y();Vn();Wn()});import{readFileSync as gt,readdirSync as ji,existsSync as $e,writeFileSync as zn,mkdirSync as co,rmSync as Ri,renameSync as Ni,cpSync as kg}from"fs";import{join as ue,dirname as Pl}from"path";import{homedir as Tg}from"os";function uo(){if(mn)return mn;try{return $e(Oi)?(mn=JSON.parse(gt(Oi,"utf-8")),mn):Fi()}catch{return Fi()}}function mo(t){mn=t;try{co(ae,{recursive:!0}),zn(Oi,JSON.stringify(t),"utf-8")}catch{}}function Fi(){if(!$e(ae))return[];let t=[];for(let e of ji(ae).filter(n=>n.endsWith(".json")&&n!=="_index.json"))try{let n=JSON.parse(gt(ue(ae,e),"utf-8")),s=n.templates||[];t.push({id:n.id,themeName:n.themeName,updatedAt:n.updatedAt,moduleCount:s.reduce((o,i)=>o+(i.modules?.length||0),0),templateCount:s.length,pageCount:s.filter(o=>o.contentMode!=="email").length,emailCount:s.filter(o=>o.contentMode==="email").length,hasBrandAssets:!!(n.brandAssets&&(n.brandAssets.styleguide||n.brandAssets.brandvoice||n.brandAssets.brandKit)),isImported:!!n.isImported})}catch{}return mn=t,mo(t),t}function Rl(t){let e=uo(),n=t.templates||[],s={id:t.id,themeName:t.themeName,updatedAt:t.updatedAt,moduleCount:n.reduce((i,r)=>i+(r.modules?.length||0),0),templateCount:n.length,pageCount:n.filter(i=>i.contentMode!=="email").length,emailCount:n.filter(i=>i.contentMode==="email").length,hasBrandAssets:!!(t.brandAssets&&(t.brandAssets.styleguide||t.brandAssets.brandvoice||t.brandAssets.brandKit)),isImported:!!t.isImported},o=e.findIndex(i=>i.id===t.id);o>=0?e[o]=s:e.push(s),mo(e)}function Ag(t){let e=uo().filter(n=>n.id!==t);mo(e)}function $g(t){let e=uo().filter(n=>n.themeName!==t);mo(e)}function C(){return Le}function Nl(){return`vibe-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`}function pn(t,e,n={}){let s={id:Nl(),themePath:t,themeName:e,isImported:!!n.isImported,templates:[],activeTemplateId:"",messages:[],modules:[],sharedCss:"",sharedJs:"",template:"",moduleOrder:[],createdAt:Date.now(),updatedAt:Date.now()};return Le=s,so(t),s}function D(){if(!Le)return;co(ae,{recursive:!0});let t=ue(ae,`${Le.id}.json`);zn(t,JSON.stringify(Le,null,2),"utf-8"),Rl(Le)}function po(t){let e=ue(ae,t+".json");if(!$e(e))return null;try{let n=JSON.parse(gt(e,"utf-8"));if(n.templates||(n.templates=[]),n.activeTemplateId||(n.activeTemplateId=""),lo(n),n.brandAssets?.plan&&n.templates?.length>0){let s=n.templates.find(o=>o.id===n.activeTemplateId)||n.templates[0];s.plan||(s.plan=n.brandAssets.plan)}return Le=n,n}catch{return null}}function gn(){return $e(ae)?uo():[]}function Ol(t,e=!1){let n=ue(ae,t+".json"),s="";if(e)try{let o=JSON.parse(gt(n,"utf-8"));s=o.themeName||"",o.themePath&&$e(o.themePath)&&Ri(o.themePath,{recursive:!0,force:!0})}catch{}else try{s=JSON.parse(gt(n,"utf-8")).themeName||""}catch{}try{$e(n)&&Ri(n)}catch{}if(s&&$e(ae)){for(let o of ji(ae).filter(i=>i.endsWith(".json")&&i!=="_index.json"))try{JSON.parse(gt(ue(ae,o),"utf-8")).themeName===s&&Ri(ue(ae,o))}catch{}$g(s)}else Ag(t);Le?.id===t&&(Le=null)}function Fl(t,e){let n=ue(ae,t+".json");if(!$e(n))return{ok:!1,error:"Session not found"};let s;try{s=JSON.parse(gt(n,"utf-8"))}catch{return{ok:!1,error:"Failed to read session"}}let o=s.themeName;if(o===e)return{ok:!0};let i=s.themePath,r=ue(Pl(i),e);if($e(i)){if($e(r))return{ok:!1,error:"A project with that name already exists"};try{Ni(i,r)}catch(m){return{ok:!1,error:`Failed to rename folder: ${m instanceof Error?m.message:String(m)}`}}let a=ue(r,"css",`${o}-theme.css`),l=ue(r,"css",`${e}-theme.css`);if($e(a))try{Ni(a,l)}catch{}let c=ue(r,"js",`${o}-animations.js`),d=ue(r,"js",`${e}-animations.js`);if($e(c))try{Ni(c,d)}catch{}let u=ue(r,"theme.json");if($e(u))try{let m=JSON.parse(gt(u,"utf-8"));m.label=e,m.name=e,zn(u,JSON.stringify(m,null,2),"utf-8")}catch{}}if($e(ae))for(let a of ji(ae).filter(l=>l.endsWith(".json")&&l!=="_index.json"))try{let l=JSON.parse(gt(ue(ae,a),"utf-8"));l.themeName===o&&(l.themeName=e,l.themePath=r,l.updatedAt=Date.now(),zn(ue(ae,a),JSON.stringify(l,null,2),"utf-8"))}catch{}return Le&&Le.themeName===o&&(Le.themeName=e,Le.themePath=r,Le.updatedAt=Date.now()),Fi(),{ok:!0}}function jl(t){let e=ue(ae,t+".json");if(!$e(e))return{ok:!1,error:"Session not found"};let n;try{n=JSON.parse(gt(e,"utf-8"))}catch{return{ok:!1,error:"Failed to read session"}}let s=n.themeName.replace(/-copy(-\d+)?$/,""),o=Pl(n.themePath),i=`${s}-copy`,r=1;for(;$e(ue(o,i));)r++,i=`${s}-copy-${r}`;let a=ue(o,i);if($e(n.themePath))try{kg(n.themePath,a,{recursive:!0})}catch(d){return{ok:!1,error:`Failed to copy files: ${d instanceof Error?d.message:String(d)}`}}else co(a,{recursive:!0});let l=Nl(),c={...JSON.parse(JSON.stringify(n)),id:l,themeName:i,themePath:a,createdAt:Date.now(),updatedAt:Date.now(),messages:[]};return co(ae,{recursive:!0}),zn(ue(ae,`${l}.json`),JSON.stringify(c,null,2),"utf-8"),Rl(c),{ok:!0,newName:i,newSessionId:l}}var ae,Oi,mn,Le,Vn=R(()=>{"use strict";y();dn();Nt();ae=ue(Tg(),".vibespot","sessions"),Oi=ue(ae,"_index.json"),mn=null;Le=null});import{readFileSync as _g,readdirSync as Jl,statSync as Di}from"fs";import{createHash as Mg}from"crypto";import{join as he,relative as Eg}from"path";function ho(t){let e=[];if(!v(t))return tf(t,[{severity:"error",rule:"theme.path.missing",message:`Theme directory not found: ${t}`}]);let n=fn(t),s=Xg(t),o=Qg(t),i=ef(t),r=Og(t);Object.keys(n.cssVariables).length===0&&e.push({severity:"info",rule:"design.cssVariables.empty",message:"No :root CSS custom properties found in theme CSS.",fix:"Run with --apply-tokens to seed a :root block from inferred palette/typography."}),n.palette.length===0&&e.push({severity:"info",rule:"design.palette.empty",message:"Could not infer a colour palette from the theme CSS."}),s.orphanModules.length>0&&e.push({severity:"warning",rule:"modules.orphan",message:`${s.orphanModules.length} module(s) are not referenced by any template: ${s.orphanModules.join(", ")}`,fix:"Either reference these modules from a template or remove them."}),s.templates.length===0&&s.modules.length>0&&e.push({severity:"warning",rule:"templates.missing",message:"Theme has modules but no page templates wiring them together.",fix:"Add a templates/<name>.html that includes the modules via dnd_module."});for(let l of o)e.push({severity:"info",rule:"field.unsupported-pattern",file:`modules/${l.module}.module/fields.json`,message:`${l.module}.${l.field}: ${l.reason}`,fix:"vibeSpot will preserve this field as-is. Edit it in HubSpot if changes are needed."});for(let l of i)e.push({severity:"warning",rule:"roundtrip.preserve-pattern",file:l.file,message:`${l.pattern}: ${l.detail}`,fix:"vibeSpot avoids modifying this. Don't ask the AI to refactor it."});r.hasSnapshot&&r.filesChanged>0&&e.push({severity:"info",rule:"roundtrip.snapshot.diff",message:`${r.filesChanged} file(s) differ from the imported theme snapshot.`,fix:"Review report.roundTripDiff before re-uploading if you need to preserve imported files exactly."});let a=i.filter(l=>l.pattern==="hubl.macro").length;return{themePath:t,designTokens:n,graph:s,fieldFlags:o,roundTripRisks:i,roundTripDiff:r,findings:e,summary:{moduleCount:s.modules.length,templateCount:s.templates.length,orphanCount:s.orphanModules.length,paletteSize:n.palette.length,cssVarCount:Object.keys(n.cssVariables).length,customMacroCount:a,roundTripChangedCount:r.filesChanged}}}function Yn(t){let e=[];for(let[n,s]of Object.entries(t.cssVariables))e.push(` ${n}: ${s};`);return Object.keys(t.cssVariables).length===0&&(t.palette.slice(0,8).forEach((n,s)=>{let o=s===0?"primary":s===1?"secondary":`accent-${s-1}`;e.push(` --color-${o}: ${n.value};`)}),t.fontFamilies[0]&&e.push(` --font-family-base: ${t.fontFamilies[0]};`),t.fontFamilies[1]&&e.push(` --font-family-heading: ${t.fontFamilies[1]};`)),e.length===0?"":`:root {
187
+ ${e.join(`
139
188
  `)}
140
189
  }
141
- `}function Ys(e,t){let n=ae(e,"css");if(b(n))try{for(let r of Qa(n))if(r.endsWith("-theme.css"))return null}catch{}let s=sn(e),o=_n(s);if(!o)return null;let i=ae(n,`${t}-theme.css`);return L(i,o),i}function Pn(e){return ae(e,op)}function rp(e,t=new Date().toISOString()){return{version:1,createdAt:t,files:nl(e)}}function gi(e,t){let n=rp(e,t),s=Pn(e);return L(s,JSON.stringify(n,null,2)+`
142
- `),s}function el(e){let t=Pn(e);return b(t)?null:gi(e)}function ap(e){let t=Pn(e);if(!b(t))return null;try{let n=JSON.parse(T(t));return Mp(n)?n:null}catch{return null}}function lp(e){let t=Pn(e),n=ap(e);if(!n)return{hasSnapshot:!1,snapshotPath:t,filesChanged:0,added:0,modified:0,deleted:0,files:[]};let s=new Map(n.files.map(d=>[d.path,d])),o=nl(e),i=new Map(o.map(d=>[d.path,d])),r=[];for(let d of n.files){let u=i.get(d.path);u?u.sha256!==d.sha256&&r.push({file:d.path,status:"modified",beforeSha256:d.sha256,afterSha256:u.sha256,beforeSize:d.size,afterSize:u.size,beforeLines:zs(d.text),afterLines:zs(u.text)}):r.push({file:d.path,status:"deleted",beforeSha256:d.sha256,beforeSize:d.size,beforeLines:zs(d.text)})}for(let d of o)s.has(d.path)||r.push({file:d.path,status:"added",afterSha256:d.sha256,afterSize:d.size,afterLines:zs(d.text)});r.sort((d,u)=>d.file.localeCompare(u.file));let a=r.filter(d=>d.status==="added").length,l=r.filter(d=>d.status==="modified").length,c=r.filter(d=>d.status==="deleted").length;return{hasSnapshot:!0,snapshotPath:t,filesChanged:r.length,added:a,modified:l,deleted:c,files:r}}function sn(e){let t=Cp(e),n={},s=new Map,o=new Map,i=new Set,r=new Set,a=new Set,l=new Set,c=new Set;for(let u of t){let m;try{m=T(u)}catch{continue}let f,y=new RegExp(yp.source,"g");for(;(f=y.exec(m))!==null;){let h=f[1],S=new RegExp(bp.source,"g"),x;for(;(x=S.exec(h))!==null;){let w=x[1].trim(),v=x[2].trim();n[w]||(n[w]=v);let N=v.match(/#[0-9a-fA-F]{3,8}\b|rgba?\([^)]+\)|hsla?\([^)]+\)/);if(N){let O=Xa(N[0]);o.set(O,w)}}}for(let h of[cp,dp,up]){let S=new RegExp(h.source,"g"),x;for(;(x=S.exec(m))!==null;){let w=Xa(x[0]);w&&s.set(w,(s.get(w)??0)+1)}}Vs(m,mp,i,xp),Vs(m,pp,r,h=>h.trim()),Sp(m,a),Vs(m,gp,l,h=>h.trim()),Vs(m,hp,c,h=>h.trim())}let d=[...s.entries()].filter(([u])=>!wp(u)).sort((u,m)=>m[1]-u[1]).slice(0,12).map(([u,m])=>({value:u,count:m,varName:o.get(u)}));return{cssVariables:n,palette:d,fontFamilies:[...i].slice(0,8),fontSizes:[...r].slice(0,16),spacing:[...a].slice(0,16),radii:[...l].slice(0,8),shadows:[...c].slice(0,8)}}function Vs(e,t,n,s){let o=new RegExp(t.source,"g"),i;for(;(i=o.exec(e))!==null;){let r=s(i[1]);r&&!r.startsWith("var(")&&n.add(r)}}function Sp(e,t){let n=new RegExp(fp.source,"g"),s;for(;(s=n.exec(e))!==null;){let o=s[1].trim();if(!o.startsWith("var("))for(let i of o.split(/\s+/))/^-?\d+(\.\d+)?(rem|em|px|%)$/.test(i)&&t.add(i)}}function xp(e){return e.split(",")[0].trim().replace(/^["']|["']$/g,"")}function Xa(e){let t=e.trim().toLowerCase();if(t.startsWith("#")){if(/^#[0-9a-f]{3}$/.test(t)){let[,n,s,o]=t.match(/^#([0-9a-f])([0-9a-f])([0-9a-f])$/);return`#${n}${n}${s}${s}${o}${o}`}return t}return t.replace(/\s+/g,"")}function wp(e){return vp.has(e)}function Cp(e){let t=[],n=ae(e,"css");if(b(n))for(let o of Ct(n))o.endsWith(".css")&&t.push(ae(n,o));let s=ae(e,"modules");if(b(s))for(let o of Ct(s)){if(!o.endsWith(".module"))continue;let i=ae(s,o,"module.css");b(i)&&t.push(i)}return t}function kp(e){let t=ae(e,"modules"),n=ae(e,"templates"),s=new Set,o=new Map;if(b(t))for(let c of Ct(t)){if(!c.endsWith(".module"))continue;let d=c.replace(/\.module$/,"");s.add(d),o.set(d,b(ae(t,c,"module.js")))}let i=[],r=new Map;if(b(n))for(let c of Ct(n)){if(!c.endsWith(".html")||c==="home.html")continue;let d=ae(n,c),u;try{u=fi(d)}catch{continue}if(!u.isFile())continue;let m;try{m=T(d)}catch{continue}let f=hi(m);for(let h of f){let S=r.get(h)??new Set;S.add(c),r.set(h,S)}let y=c.replace(/\.html$/,"");i.push({id:y,file:`templates/${c}`,modules:Rp(f)})}let a=[...s].sort().map(c=>({name:c,templates:[...r.get(c)??[]].sort(),hasJs:o.get(c)??!1})),l=a.filter(c=>c.templates.length===0).map(c=>c.name);return{templates:i,modules:a,orphanModules:l}}function hi(e){let t=[],n=/{%\s*dnd_module\b[\s\S]*?%}/g,s;for(;(s=n.exec(e))!==null;){let o=s[0].match(/\bpath\s*=\s*["']([^"']+)["']/);if(!o)continue;let i=o[1].match(/(?:^|\/)modules\/(.+)$/);if(!i)continue;let r=i[1].replace(/\.module$/,"");r&&t.push(r)}return t}function Tp(e){let t=[],n=ae(e,"modules");if(!b(n))return t;for(let s of Ct(n)){if(!s.endsWith(".module"))continue;let o=s.replace(/\.module$/,""),i=ae(n,s,"fields.json");if(!b(i))continue;let r;try{r=JSON.parse(T(i))}catch{continue}Array.isArray(r)&&tl(r,o,t,0)}return t}function tl(e,t,n,s){for(let o of e){if(typeof o!="object"||o===null)continue;let i=o,r=typeof i.name=="string"?i.name:"(unnamed)",a=typeof i.type=="string"?i.type:"";if(a==="group"&&s>=1&&n.push({module:t,field:r,reason:"deeply nested group (>1 level)"}),(a==="group"||a==="module")&&i.occurrence){let l=i.occurrence;l.max!==void 0&&l.max!==1&&n.push({module:t,field:r,reason:"repeater (occurrence) field"})}(a==="hubdb_table"||a==="hubdbtable")&&n.push({module:t,field:r,reason:"HubDB-backed field"}),(a==="crm_object"||a==="crm_object_property")&&n.push({module:t,field:r,reason:"CRM object field"}),a==="embed"&&typeof i.embed=="object"&&n.push({module:t,field:r,reason:"rich embed field"}),a&&!Ap.has(a)&&a!=="module"&&n.push({module:t,field:r,reason:`field type "${a}" not in vibeSpot's generation set`}),i.visibility&&typeof i.visibility=="object"&&n.push({module:t,field:r,reason:"conditional visibility rule"}),Array.isArray(i.children)&&tl(i.children,t,n,s+1)}}function $p(e){let t=[],n=ae(e,"modules");if(b(n))for(let i of Ct(n)){if(!i.endsWith(".module"))continue;let r=i.replace(/\.module$/,""),a=ae(n,i,"module.html");b(a)&&Za(a,e,r,t);let l=ae(n,i,"module.js");if(b(l))try{T(l).trim().length>0&&t.push({file:yi(e,l),pattern:"module.js.custom",detail:`${r}: module ships custom JS \u2014 preserve verbatim`})}catch{}}let s=ae(e,"templates");if(b(s))for(let i of Ct(s)){if(!i.endsWith(".html"))continue;let r=ae(s,i);if(!b(r))continue;let a;try{a=fi(r)}catch{continue}a.isFile()&&Za(r,e,i,t)}let o=ae(e,"import_modules.json");return b(o)&&t.push({file:"import_modules.json",pattern:"theme.import_modules",detail:"Theme declares import_modules.json \u2014 preserve to avoid breaking HubSpot pre-install"}),t}function Za(e,t,n,s){let o;try{o=T(e)}catch{return}let i=yi(t,e);/{%\s*macro\s+\w+/.test(o)&&s.push({file:i,pattern:"hubl.macro",detail:`${n}: contains custom HubL {% macro %}`}),/{%\s*raw\s*%}/.test(o)&&s.push({file:i,pattern:"hubl.raw",detail:`${n}: contains {% raw %} block`});let r=/{%\s*include\s+["']([^"']+)["']/g,a;for(;(a=r.exec(o))!==null;){let l=a[1];!l.startsWith("../modules/")&&!l.startsWith("./modules/")&&!l.includes("/layouts/")&&s.push({file:i,pattern:"hubl.include",detail:`${n}: includes partial "${l}" outside modules/`})}}function Ip(e,t){let n={hasSnapshot:!1,snapshotPath:Pn(e),filesChanged:0,added:0,modified:0,deleted:0,files:[]};return{themePath:e,designTokens:{cssVariables:{},palette:[],fontFamilies:[],fontSizes:[],spacing:[],radii:[],shadows:[]},graph:{templates:[],modules:[],orphanModules:[]},fieldFlags:[],roundTripRisks:[],roundTripDiff:n,findings:t,summary:{moduleCount:0,templateCount:0,orphanCount:0,paletteSize:0,cssVarCount:0,customMacroCount:0,roundTripChangedCount:0}}}function nl(e){let t=[];function n(s){for(let o of Ct(s)){if(o===".git"||o===".vibespot"||o==="node_modules")continue;let i=ae(s,o),r;try{r=fi(i)}catch{continue}if(r.isDirectory()){n(i);continue}if(!r.isFile())continue;let a=yi(e,i),l=tp(i),c={path:a,sha256:np("sha256").update(l).digest("hex"),size:l.length};Ep(a)&&(c.text=l.toString("utf8")),t.push(c)}}return n(e),t.sort((s,o)=>s.path.localeCompare(o.path))}function Ep(e){let t=e.lastIndexOf(".");return t<0?!1:ip.has(e.slice(t).toLowerCase())}function Mp(e){if(typeof e!="object"||e===null)return!1;let t=e;return t.version!==1||typeof t.createdAt!="string"||!Array.isArray(t.files)?!1:t.files.every(n=>{if(typeof n!="object"||n===null)return!1;let s=n;return typeof s.path=="string"&&typeof s.sha256=="string"&&typeof s.size=="number"&&(s.text===void 0||typeof s.text=="string")})}function zs(e){if(e!==void 0)return e.length===0?0:e.split(/\r\n|\r|\n/).length}function Ct(e){try{return Qa(e)}catch{return[]}}function yi(e,t){return sp(e,t).split("\\").join("/")}function Rp(e){return[...new Set(e)]}var op,ip,cp,dp,up,mp,pp,fp,gp,hp,yp,bp,vp,Ap,qs=G(()=>{"use strict";g();Q();op=".vibespot/import-snapshot.json",ip=new Set([".css",".html",".htm",".js",".json",".md",".txt",".svg",".yml",".yaml"]);cp=/#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})\b/g,dp=/\brgba?\([^)]+\)/g,up=/\bhsla?\([^)]+\)/g,mp=/font-family\s*:\s*([^;}\n]+)/g,pp=/font-size\s*:\s*([^;}\n]+)/g,fp=/(?:padding|margin|gap)(?:-(?:top|right|bottom|left))?\s*:\s*([^;}\n]+)/g,gp=/border-radius\s*:\s*([^;}\n]+)/g,hp=/box-shadow\s*:\s*([^;}\n]+)/g,yp=/:root\s*\{([\s\S]*?)\}/g,bp=/(--[\w-]+)\s*:\s*([^;}\n]+)/g;vp=new Set(["#000000","#ffffff","transparent","currentcolor","inherit","initial"]);Ap=new Set(["text","richtext","image","url","boolean","choice","number","color","icon","link","menu","video","form","cta","blog","tag","page","email","logo","embed","alignment","border","spacing","font","background","gradient","textalignment","group"])});import{readFileSync as bi,readdirSync as On,existsSync as Se,writeFileSync as De,mkdirSync as Nn,rmSync as sl}from"fs";import{join as B}from"path";function ue(e){try{return bi(e,"utf-8")}catch{return""}}function _p(e){let t=[];for(let n of e.moduleOrder){let s=e.modules.find(o=>o.moduleName===n);s&&t.push(s)}for(let n of e.modules)e.moduleOrder.includes(n.moduleName)||t.push(n);return t}function Pp(e,t){let n=ue(e);if(!n||t==="home.html"||t.endsWith("-listing.html"))return null;let s=t.replace(/\.html$/,""),o="landing_page";s.startsWith("bp-")?o="blog_post":s.startsWith("wp-")?o="website_page":s.startsWith("mo-")&&(o="module_only");let i=s,r=n.match(/<!--[\s\S]*?label:\s*"?([^"\n]+)"?\s*[\s\S]*?-->/);r&&(i=r[1].trim());let a=hi(n);return{id:s,label:i,pageType:o,moduleNames:a,templateContent:n,filename:t}}function Np(e,t,n,s,o){if(!Se(e))return[];let i=[],r=On(e).filter(a=>a.endsWith(".html")&&a!=="home.html");for(let a of r){let l=B(e,a),c=Pp(l,a);if(!c||c.moduleNames.length===0&&i.length>0)continue;let d=[],u=[];for(let m of c.moduleNames){let f=t.get(m);f&&(d.push(f),u.push(m))}i.push({id:c.id,label:c.label,pageType:c.pageType,templateFile:`templates/${c.filename}`,modules:d,moduleOrder:u,sharedCss:n,sharedJs:s,template:c.templateContent,messages:i.length===0?[...o]:[]})}return i}function Xs(e){let t=C();if(!t)return;let n=Ua(e);n.length>0&&t.messages.length===0&&(t.messages=n),Os(e),el(e);let s=B(e,"modules");if(!Se(s))return;let o=On(s,{withFileTypes:!0});for(let S of o){if(!S.isDirectory()||!S.name.endsWith(".module"))continue;let x=B(s,S.name),w=S.name.replace(/\.module$/,""),v={moduleName:w,fieldsJson:ue(B(x,"fields.json")),metaJson:ue(B(x,"meta.json")),moduleHtml:ue(B(x,"module.html")),moduleCss:ue(B(x,"module.css")),moduleJs:ue(B(x,"module.js"))||void 0};v.fieldsJson&&v.moduleHtml&&(t.modules.push(v),t.moduleOrder.push(w))}let i=B(e,"css"),r=B(e,"js"),a="",l="";if(Se(i)){let S=On(i).filter(x=>x.endsWith("-theme.css"));S.length>0&&(a=ue(B(i,S[0])),t.sharedCss=a)}if(Se(r)){let S=On(r).filter(x=>x.endsWith("-animations.js"));S.length>0&&(l=ue(B(r,S[0])),t.sharedJs=l)}if(!a&&t.modules.length>0){let S=sn(e),x=_n(S);x&&(t.sharedCss=x,a=x)}let c=B(e,".vibespot","styleguide.md"),d=B(e,".vibespot","brandvoice.md"),u=B(e,".vibespot","theme-context.md"),m=B(e,".vibespot","plan.md");(Se(c)||Se(d)||Se(u)||Se(m))&&(t.brandAssets||(t.brandAssets={}),Se(c)&&(t.brandAssets.styleguide=ue(c)),Se(d)&&(t.brandAssets.brandvoice=ue(d)),Se(u)&&(t.brandAssets.themeContext=ue(u)),Se(m)&&(t.brandAssets.plan=ue(m)));let f=B(e,"templates"),y=new Map(t.modules.map(S=>[S.moduleName,S])),h=Np(f,y,a,l,t.messages);if(h.length>0){t.templates=h,t.activeTemplateId=h[0].id,t.brandAssets?.plan&&!h[0].plan&&(h[0].plan=t.brandAssets.plan);let S=h[0].moduleOrder;if(S.length>0){let x=new Set(t.moduleOrder),w=S.filter(v=>x.has(v));for(let v of t.moduleOrder)w.includes(v)||w.push(v);t.moduleOrder=w}Pt(h[0])}else t.templates||(t.templates=[]),t.activeTemplateId||(t.activeTemplateId=""),Ls(t)}function we(){let e=C();if(!e)return;let t=e.themePath,n=new Map;if(e.templates.length>0)for(let l of e.templates)for(let c of l.modules)n.set(c.moduleName,c);for(let l of e.modules)n.set(l.moduleName,l);let s=B(t,"modules");Nn(s,{recursive:!0});for(let l of n.values())Nn(B(s,`${l.moduleName}.module`),{recursive:!0});for(let l of n.values()){let c=B(s,`${l.moduleName}.module`);De(B(c,"fields.json"),l.fieldsJson,"utf-8"),De(B(c,"meta.json"),l.metaJson,"utf-8"),De(B(c,"module.html"),l.moduleHtml,"utf-8"),De(B(c,"module.css"),l.moduleCss,"utf-8"),l.moduleJs&&De(B(c,"module.js"),l.moduleJs,"utf-8")}if(e.sharedCss){let l=B(t,"css");Nn(l,{recursive:!0}),De(B(l,`${e.themeName}-theme.css`),e.sharedCss,"utf-8")}if(e.sharedJs){let l=B(t,"js");Nn(l,{recursive:!0}),De(B(l,`${e.themeName}-animations.js`),e.sharedJs,"utf-8")}let o=B(t,"templates");Nn(o,{recursive:!0});let i=B(o,"home.html");(e.templates.length>0||e.modules.length>0)&&Se(i)&&sl(i,{force:!0});let a=new Set;if(e.templates.length>0)for(let l of e.templates){if(l.pageType==="module_only"||l.modules.length===0)continue;let c=l.template||jp(l),d=ol(c,l.label,l.pageType),u=`${l.id}.html`;De(B(o,u),d,"utf-8"),a.add(u),l.pageType==="blog_post"&&(Dp(o,l),a.add(`${l.id}-listing.html`))}else if(e.modules.length>0){let l=e.template||Jp(),c=ol(l,`${e.themeName} Landing Page`),d=`lp-${e.themeName}.html`;De(B(o,d),c,"utf-8"),a.add(d)}try{for(let l of On(o))l.startsWith("lp-")&&l.endsWith(".html")&&!a.has(l)&&sl(B(o,l),{force:!0})}catch{}Op(),Fp()}function il(){let e=C();e&&(e.modules=[],e.moduleOrder=[],e.sharedCss="",e.sharedJs="",e.template="",Xs(e.themePath),e.updatedAt=Date.now(),Ue())}function rl(){let e=C();if(!e)return;let t=ye();if(!t)return;let n=e.themePath,s=B(n,"modules");t.modules=[];for(let o of t.moduleOrder){let i=B(s,`${o}.module`);if(!Se(i))continue;let r={moduleName:o,fieldsJson:ue(B(i,"fields.json")),metaJson:ue(B(i,"meta.json")),moduleHtml:ue(B(i,"module.html")),moduleCss:ue(B(i,"module.css")),moduleJs:ue(B(i,"module.js"))||void 0};r.fieldsJson&&r.moduleHtml&&t.modules.push(r)}if(t.templateFile){let o=B(n,t.templateFile);Se(o)&&(t.template=ue(o))}Pt(t),e.updatedAt=Date.now()}function Op(){let e=C();if(!e)return;let t=B(e.themePath,"templates","layouts","base.html");if(Se(t))try{let n=bi(t,"utf-8");if(n.includes("template_js"))return;let s='{{ require_js(get_asset_url("../../js/main.js")) }}';n.includes(s)?n=n.replace(s,s+`
190
+ `}function yo(t,e){let n=he(t,"css");if(v(n))try{for(let r of Jl(n))if(r.endsWith("-theme.css"))return null}catch{}let s=fn(t),o=Yn(s);if(!o)return null;let i=he(n,`${e}-theme.css`);return J(i,o),i}function qn(t){return he(t,Ig)}function Rg(t,e=new Date().toISOString()){return{version:1,createdAt:e,files:Ul(t)}}function Li(t,e){let n=Rg(t,e),s=qn(t);return J(s,JSON.stringify(n,null,2)+`
191
+ `),s}function Bl(t){let e=qn(t);return v(e)?null:Li(t)}function Ng(t){let e=qn(t);if(!v(e))return null;try{let n=JSON.parse(M(e));return sf(n)?n:null}catch{return null}}function Og(t){let e=qn(t),n=Ng(t);if(!n)return{hasSnapshot:!1,snapshotPath:e,filesChanged:0,added:0,modified:0,deleted:0,files:[]};let s=new Map(n.files.map(d=>[d.path,d])),o=Ul(t),i=new Map(o.map(d=>[d.path,d])),r=[];for(let d of n.files){let u=i.get(d.path);u?u.sha256!==d.sha256&&r.push({file:d.path,status:"modified",beforeSha256:d.sha256,afterSha256:u.sha256,beforeSize:d.size,afterSize:u.size,beforeLines:fo(d.text),afterLines:fo(u.text)}):r.push({file:d.path,status:"deleted",beforeSha256:d.sha256,beforeSize:d.size,beforeLines:fo(d.text)})}for(let d of o)s.has(d.path)||r.push({file:d.path,status:"added",afterSha256:d.sha256,afterSize:d.size,afterLines:fo(d.text)});r.sort((d,u)=>d.file.localeCompare(u.file));let a=r.filter(d=>d.status==="added").length,l=r.filter(d=>d.status==="modified").length,c=r.filter(d=>d.status==="deleted").length;return{hasSnapshot:!0,snapshotPath:e,filesChanged:r.length,added:a,modified:l,deleted:c,files:r}}function fn(t){let e=qg(t),n={},s=new Map,o=new Map,i=new Set,r=new Set,a=new Set,l=new Set,c=new Set;for(let u of e){let m;try{m=M(u)}catch{continue}let g,h=new RegExp(Gg.source,"g");for(;(g=h.exec(m))!==null;){let f=g[1],b=new RegExp(Wg.source,"g"),S;for(;(S=b.exec(f))!==null;){let x=S[1].trim(),w=S[2].trim();n[x]||(n[x]=w);let P=w.match(/#[0-9a-fA-F]{3,8}\b|rgba?\([^)]+\)|hsla?\([^)]+\)/);if(P){let F=Dl(P[0]);o.set(F,x)}}}for(let f of[Fg,jg,Dg]){let b=new RegExp(f.source,"g"),S;for(;(S=b.exec(m))!==null;){let x=Dl(S[0]);x&&s.set(x,(s.get(x)??0)+1)}}go(m,Lg,i,Vg),go(m,Jg,r,f=>f.trim()),Kg(m,a),go(m,Hg,l,f=>f.trim()),go(m,Ug,c,f=>f.trim())}let d=[...s.entries()].filter(([u])=>!Yg(u)).sort((u,m)=>m[1]-u[1]).slice(0,12).map(([u,m])=>({value:u,count:m,varName:o.get(u)}));return{cssVariables:n,palette:d,fontFamilies:[...i].slice(0,8),fontSizes:[...r].slice(0,16),spacing:[...a].slice(0,16),radii:[...l].slice(0,8),shadows:[...c].slice(0,8)}}function go(t,e,n,s){let o=new RegExp(e.source,"g"),i;for(;(i=o.exec(t))!==null;){let r=s(i[1]);r&&!r.startsWith("var(")&&n.add(r)}}function Kg(t,e){let n=new RegExp(Bg.source,"g"),s;for(;(s=n.exec(t))!==null;){let o=s[1].trim();if(!o.startsWith("var("))for(let i of o.split(/\s+/))/^-?\d+(\.\d+)?(rem|em|px|%)$/.test(i)&&e.add(i)}}function Vg(t){return t.split(",")[0].trim().replace(/^["']|["']$/g,"")}function Dl(t){let e=t.trim().toLowerCase();if(e.startsWith("#")){if(/^#[0-9a-f]{3}$/.test(e)){let[,n,s,o]=e.match(/^#([0-9a-f])([0-9a-f])([0-9a-f])$/);return`#${n}${n}${s}${s}${o}${o}`}return e}return e.replace(/\s+/g,"")}function Yg(t){return zg.has(t)}function qg(t){let e=[],n=he(t,"css");if(v(n))for(let o of Ot(n))o.endsWith(".css")&&e.push(he(n,o));let s=he(t,"modules");if(v(s))for(let o of Ot(s)){if(!o.endsWith(".module"))continue;let i=he(s,o,"module.css");v(i)&&e.push(i)}return e}function Xg(t){let e=he(t,"modules"),n=he(t,"templates"),s=new Set,o=new Map;if(v(e))for(let c of Ot(e)){if(!c.endsWith(".module"))continue;let d=c.replace(/\.module$/,"");s.add(d),o.set(d,v(he(e,c,"module.js")))}let i=[],r=new Map;if(v(n))for(let c of Ot(n)){if(!c.endsWith(".html")||c==="home.html")continue;let d=he(n,c),u;try{u=Di(d)}catch{continue}if(!u.isFile())continue;let m;try{m=M(d)}catch{continue}let g=Ji(m);for(let f of g){let b=r.get(f)??new Set;b.add(c),r.set(f,b)}let h=c.replace(/\.html$/,"");i.push({id:h,file:`templates/${c}`,modules:of(g)})}let a=[...s].sort().map(c=>({name:c,templates:[...r.get(c)??[]].sort(),hasJs:o.get(c)??!1})),l=a.filter(c=>c.templates.length===0).map(c=>c.name);return{templates:i,modules:a,orphanModules:l}}function Ji(t){let e=[],n=/{%\s*dnd_module\b[\s\S]*?%}/g,s;for(;(s=n.exec(t))!==null;){let o=s[0].match(/\bpath\s*=\s*["']([^"']+)["']/);if(!o)continue;let i=o[1].match(/(?:^|\/)modules\/(.+)$/);if(!i)continue;let r=i[1].replace(/\.module$/,"");r&&e.push(r)}return e}function Qg(t){let e=[],n=he(t,"modules");if(!v(n))return e;for(let s of Ot(n)){if(!s.endsWith(".module"))continue;let o=s.replace(/\.module$/,""),i=he(n,s,"fields.json");if(!v(i))continue;let r;try{r=JSON.parse(M(i))}catch{continue}Array.isArray(r)&&Hl(r,o,e,0)}return e}function Hl(t,e,n,s){for(let o of t){if(typeof o!="object"||o===null)continue;let i=o,r=typeof i.name=="string"?i.name:"(unnamed)",a=typeof i.type=="string"?i.type:"";if(a==="group"&&s>=1&&n.push({module:e,field:r,reason:"deeply nested group (>1 level)"}),(a==="group"||a==="module")&&i.occurrence){let l=i.occurrence;l.max!==void 0&&l.max!==1&&n.push({module:e,field:r,reason:"repeater (occurrence) field"})}(a==="hubdb_table"||a==="hubdbtable")&&n.push({module:e,field:r,reason:"HubDB-backed field"}),(a==="crm_object"||a==="crm_object_property")&&n.push({module:e,field:r,reason:"CRM object field"}),a==="embed"&&typeof i.embed=="object"&&n.push({module:e,field:r,reason:"rich embed field"}),a&&!Zg.has(a)&&a!=="module"&&n.push({module:e,field:r,reason:`field type "${a}" not in vibeSpot's generation set`}),i.visibility&&typeof i.visibility=="object"&&n.push({module:e,field:r,reason:"conditional visibility rule"}),Array.isArray(i.children)&&Hl(i.children,e,n,s+1)}}function ef(t){let e=[],n=he(t,"modules");if(v(n))for(let i of Ot(n)){if(!i.endsWith(".module"))continue;let r=i.replace(/\.module$/,""),a=he(n,i,"module.html");v(a)&&Ll(a,t,r,e);let l=he(n,i,"module.js");if(v(l))try{M(l).trim().length>0&&e.push({file:Bi(t,l),pattern:"module.js.custom",detail:`${r}: module ships custom JS \u2014 preserve verbatim`})}catch{}}let s=he(t,"templates");if(v(s))for(let i of Ot(s)){if(!i.endsWith(".html"))continue;let r=he(s,i);if(!v(r))continue;let a;try{a=Di(r)}catch{continue}a.isFile()&&Ll(r,t,i,e)}let o=he(t,"import_modules.json");return v(o)&&e.push({file:"import_modules.json",pattern:"theme.import_modules",detail:"Theme declares import_modules.json \u2014 preserve to avoid breaking HubSpot pre-install"}),e}function Ll(t,e,n,s){let o;try{o=M(t)}catch{return}let i=Bi(e,t);/{%\s*macro\s+\w+/.test(o)&&s.push({file:i,pattern:"hubl.macro",detail:`${n}: contains custom HubL {% macro %}`}),/{%\s*raw\s*%}/.test(o)&&s.push({file:i,pattern:"hubl.raw",detail:`${n}: contains {% raw %} block`});let r=/{%\s*include\s+["']([^"']+)["']/g,a;for(;(a=r.exec(o))!==null;){let l=a[1];!l.startsWith("../modules/")&&!l.startsWith("./modules/")&&!l.includes("/layouts/")&&s.push({file:i,pattern:"hubl.include",detail:`${n}: includes partial "${l}" outside modules/`})}}function tf(t,e){let n={hasSnapshot:!1,snapshotPath:qn(t),filesChanged:0,added:0,modified:0,deleted:0,files:[]};return{themePath:t,designTokens:{cssVariables:{},palette:[],fontFamilies:[],fontSizes:[],spacing:[],radii:[],shadows:[]},graph:{templates:[],modules:[],orphanModules:[]},fieldFlags:[],roundTripRisks:[],roundTripDiff:n,findings:e,summary:{moduleCount:0,templateCount:0,orphanCount:0,paletteSize:0,cssVarCount:0,customMacroCount:0,roundTripChangedCount:0}}}function Ul(t){let e=[];function n(s){for(let o of Ot(s)){if(o===".git"||o===".vibespot"||o==="node_modules")continue;let i=he(s,o),r;try{r=Di(i)}catch{continue}if(r.isDirectory()){n(i);continue}if(!r.isFile())continue;let a=Bi(t,i),l=_g(i),c={path:a,sha256:Mg("sha256").update(l).digest("hex"),size:l.length};nf(a)&&(c.text=l.toString("utf8")),e.push(c)}}return n(t),e.sort((s,o)=>s.path.localeCompare(o.path))}function nf(t){let e=t.lastIndexOf(".");return e<0?!1:Pg.has(t.slice(e).toLowerCase())}function sf(t){if(typeof t!="object"||t===null)return!1;let e=t;return e.version!==1||typeof e.createdAt!="string"||!Array.isArray(e.files)?!1:e.files.every(n=>{if(typeof n!="object"||n===null)return!1;let s=n;return typeof s.path=="string"&&typeof s.sha256=="string"&&typeof s.size=="number"&&(s.text===void 0||typeof s.text=="string")})}function fo(t){if(t!==void 0)return t.length===0?0:t.split(/\r\n|\r|\n/).length}function Ot(t){try{return Jl(t)}catch{return[]}}function Bi(t,e){return Eg(t,e).split("\\").join("/")}function of(t){return[...new Set(t)]}var Ig,Pg,Fg,jg,Dg,Lg,Jg,Bg,Hg,Ug,Gg,Wg,zg,Zg,bo=R(()=>{"use strict";y();ne();Ig=".vibespot/import-snapshot.json",Pg=new Set([".css",".html",".htm",".js",".json",".md",".txt",".svg",".yml",".yaml"]);Fg=/#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})\b/g,jg=/\brgba?\([^)]+\)/g,Dg=/\bhsla?\([^)]+\)/g,Lg=/font-family\s*:\s*([^;}\n]+)/g,Jg=/font-size\s*:\s*([^;}\n]+)/g,Bg=/(?:padding|margin|gap)(?:-(?:top|right|bottom|left))?\s*:\s*([^;}\n]+)/g,Hg=/border-radius\s*:\s*([^;}\n]+)/g,Ug=/box-shadow\s*:\s*([^;}\n]+)/g,Gg=/:root\s*\{([\s\S]*?)\}/g,Wg=/(--[\w-]+)\s*:\s*([^;}\n]+)/g;zg=new Set(["#000000","#ffffff","transparent","currentcolor","inherit","initial"]);Zg=new Set(["text","richtext","image","url","boolean","choice","number","color","icon","link","menu","video","form","cta","blog","tag","page","email","logo","embed","alignment","border","spacing","font","background","gradient","textalignment","group"])});import{readFileSync as Hi,readdirSync as Zn,existsSync as xe,writeFileSync as Ke,mkdirSync as Xn,rmSync as Gl}from"fs";import{join as U}from"path";function ve(t){try{return Hi(t,"utf-8")}catch{return""}}function Kl(t){let e=[];for(let n of t.moduleOrder){let s=t.modules.find(o=>o.moduleName===n);s&&e.push(s)}for(let n of t.modules)t.moduleOrder.includes(n.moduleName)||e.push(n);return e}function rf(t,e){let n=ve(t);if(!n||e==="home.html"||e.endsWith("-listing.html"))return null;let s=e.replace(/\.html$/,""),o=/templateType:\s*email\b/i.test(n),i="landing_page",r;o?(i="module_only",r="email"):s.startsWith("bp-")?i="blog_post":s.startsWith("wp-")?i="website_page":s.startsWith("mo-")&&(i="module_only");let a=s,l=n.match(/<!--[\s\S]*?label:\s*"?([^"\n]+)"?\s*[\s\S]*?-->/);l&&(a=l[1].trim());let c=Ji(n);return{id:s,label:a,pageType:i,contentMode:r,moduleNames:c,templateContent:n,filename:e}}function af(t,e,n,s,o){if(!xe(t))return[];let i=[],r=Zn(t).filter(a=>a.endsWith(".html")&&a!=="home.html");for(let a of r){let l=U(t,a),c=rf(l,a);if(!c||c.moduleNames.length===0&&i.length>0)continue;let d=[],u=[];for(let m of c.moduleNames){let g=e.get(m);g&&(d.push(g),u.push(m))}i.push({id:c.id,label:c.label,pageType:c.pageType,contentMode:c.contentMode,templateFile:`templates/${c.filename}`,modules:d,moduleOrder:u,sharedCss:c.contentMode==="email"?"":n,sharedJs:c.contentMode==="email"?"":s,template:c.templateContent,messages:i.length===0?[...o]:[]})}return i}function So(t){let e=C();if(!e)return;let n=Tl(t);n.length>0&&e.messages.length===0&&(e.messages=n),so(t),Bl(t);let s=U(t,"modules");if(!xe(s))return;let o=Zn(s,{withFileTypes:!0});for(let S of o){if(!S.isDirectory()||!S.name.endsWith(".module"))continue;let x=U(s,S.name),w=S.name.replace(/\.module$/,""),P={moduleName:w,fieldsJson:ve(U(x,"fields.json")),metaJson:ve(U(x,"meta.json")),moduleHtml:ve(U(x,"module.html")),moduleCss:ve(U(x,"module.css")),moduleJs:ve(U(x,"module.js"))||void 0};P.fieldsJson&&P.moduleHtml&&(e.modules.push(P),e.moduleOrder.push(w))}let i=U(t,"css"),r=U(t,"js"),a="",l="";if(xe(i)){let S=Zn(i).filter(x=>x.endsWith("-theme.css"));S.length>0&&(a=ve(U(i,S[0])),e.sharedCss=a)}if(xe(r)){let S=Zn(r).filter(x=>x.endsWith("-animations.js"));S.length>0&&(l=ve(U(r,S[0])),e.sharedJs=l)}if(!a&&e.modules.length>0){let S=fn(t),x=Yn(S);x&&(e.sharedCss=x,a=x)}let c=U(t,".vibespot","styleguide.md"),d=U(t,".vibespot","brandvoice.md"),u=U(t,".vibespot","theme-context.md"),m=U(t,".vibespot","plan.md"),g=U(t,".vibespot","brand-kit.json");if((xe(c)||xe(d)||xe(u)||xe(m)||xe(g))&&(e.brandAssets||(e.brandAssets={}),xe(c)&&(e.brandAssets.styleguide=ve(c)),xe(d)&&(e.brandAssets.brandvoice=ve(d)),xe(u)&&(e.brandAssets.themeContext=ve(u)),xe(m)&&(e.brandAssets.plan=ve(m)),xe(g)))try{e.brandAssets.brandKit=JSON.parse(ve(g))}catch{}let h=U(t,"templates"),f=new Map(e.modules.map(S=>[S.moduleName,S])),b=af(h,f,a,l,e.messages);if(b.length>0){e.templates=b,e.activeTemplateId=b[0].id,e.brandAssets?.plan&&!b[0].plan&&(b[0].plan=e.brandAssets.plan);let S=b[0].moduleOrder;if(S.length>0){let x=new Set(e.moduleOrder),w=S.filter(P=>x.has(P));for(let P of e.moduleOrder)w.includes(P)||w.push(P);e.moduleOrder=w}Wt(b[0])}else e.templates||(e.templates=[]),e.activeTemplateId||(e.activeTemplateId=""),lo(e)}function ke(){let t=C();if(!t)return;let e=t.themePath,n=new Map;if(t.templates.length>0)for(let l of t.templates)for(let c of l.modules)n.set(c.moduleName,c);for(let l of t.modules)n.set(l.moduleName,l);let s=U(e,"modules");Xn(s,{recursive:!0});for(let l of n.values())Xn(U(s,`${l.moduleName}.module`),{recursive:!0});for(let l of n.values()){let c=U(s,`${l.moduleName}.module`);Ke(U(c,"fields.json"),l.fieldsJson,"utf-8"),Ke(U(c,"meta.json"),l.metaJson,"utf-8"),Ke(U(c,"module.html"),l.moduleHtml,"utf-8"),Ke(U(c,"module.css"),l.moduleCss,"utf-8"),l.moduleJs&&Ke(U(c,"module.js"),l.moduleJs,"utf-8")}if(t.sharedCss){let l=U(e,"css");Xn(l,{recursive:!0}),Ke(U(l,`${t.themeName}-theme.css`),t.sharedCss,"utf-8")}if(t.sharedJs){let l=U(e,"js");Xn(l,{recursive:!0}),Ke(U(l,`${t.themeName}-animations.js`),t.sharedJs,"utf-8")}let o=U(e,"templates");Xn(o,{recursive:!0});let i=U(o,"home.html");(t.templates.length>0||t.modules.length>0)&&xe(i)&&Gl(i,{force:!0});let a=new Set;if(t.templates.length>0)for(let l of t.templates){if(l.contentMode==="email"){if(l.modules.length===0)continue;let m=uf(l),g=l.templateFile?l.templateFile.replace("templates/",""):"email.html";Ke(U(o,g),m,"utf-8"),a.add(g);continue}if(l.pageType==="module_only"||l.modules.length===0)continue;let c=l.template||df(l),d=Wl(c,l.label,l.pageType),u=`${l.id}.html`;Ke(U(o,u),d,"utf-8"),a.add(u),l.pageType==="blog_post"&&(mf(o,l),a.add(`${l.id}-listing.html`))}else if(t.modules.length>0){let l=t.template||pf(),c=Wl(l,`${t.themeName} Landing Page`),d=`lp-${t.themeName}.html`;Ke(U(o,d),c,"utf-8"),a.add(d)}try{for(let l of Zn(o))l.startsWith("lp-")&&l.endsWith(".html")&&!a.has(l)&&Gl(U(o,l),{force:!0})}catch{}lf(),cf()}function Vl(){let t=C();t&&(t.modules=[],t.moduleOrder=[],t.sharedCss="",t.sharedJs="",t.template="",So(t.themePath),t.updatedAt=Date.now(),et())}function zl(){let t=C();if(!t)return;let e=Ce();if(!e)return;let n=t.themePath,s=U(n,"modules");e.modules=[];for(let o of e.moduleOrder){let i=U(s,`${o}.module`);if(!xe(i))continue;let r={moduleName:o,fieldsJson:ve(U(i,"fields.json")),metaJson:ve(U(i,"meta.json")),moduleHtml:ve(U(i,"module.html")),moduleCss:ve(U(i,"module.css")),moduleJs:ve(U(i,"module.js"))||void 0};r.fieldsJson&&r.moduleHtml&&e.modules.push(r)}if(e.templateFile){let o=U(n,e.templateFile);xe(o)&&(e.template=ve(o))}Wt(e),t.updatedAt=Date.now()}function lf(){let t=C();if(!t)return;let e=U(t.themePath,"templates","layouts","base.html");if(xe(e))try{let n=Hi(e,"utf-8");if(n.includes("template_js"))return;let s='{{ require_js(get_asset_url("../../js/main.js")) }}';n.includes(s)?n=n.replace(s,s+`
143
192
  {% if template_js %}
144
193
  {{ require_js(get_asset_url(template_js)) }}
145
194
  {% endif %}`):n=n.replace("{{ standard_footer_includes }}",`{% if template_js %}
146
195
  {{ require_js(get_asset_url(template_js)) }}
147
196
  {% endif %}
148
- {{ standard_footer_includes }}`),De(t,n,"utf-8")}catch{}}function Fp(){let e=C();if(!e)return;let t=B(e.themePath,"theme.json");if(Se(t))try{let n=JSON.parse(bi(t,"utf-8"));n.label=e.themeName,n.name=e.themeName,De(t,JSON.stringify(n,null,2),"utf-8")}catch{}}function ol(e,t,n="landing_page"){return e.includes("templateType")?e:`<!--
197
+ {{ standard_footer_includes }}`),Ke(e,n,"utf-8")}catch{}}function cf(){let t=C();if(!t)return;let e=U(t.themePath,"theme.json");if(xe(e))try{let n=JSON.parse(Hi(e,"utf-8"));n.label=t.themeName,n.name=t.themeName,Ke(e,JSON.stringify(n,null,2),"utf-8")}catch{}}function Wl(t,e,n="landing_page"){return t.includes("templateType")?t:`<!--
149
198
  templateType: ${n==="blog_post"?"blog_post":"page"}
150
199
  isAvailableForNewContent: true
151
- label: "${t}"
200
+ label: "${e}"
152
201
  -->
153
- `+e}function jp(e){if(e.modules.length===0)return"";let n=C().themeName,o=_p(e).map(r=>` {% dnd_section padding={"top":"0","bottom":"0","left":"0","right":"0"}, full_width=true %}
202
+ `+t}function df(t){if(t.modules.length===0)return"";let n=C().themeName,o=Kl(t).map(r=>` {% dnd_section padding={"top":"0","bottom":"0","left":"0","right":"0"}, full_width=true %}
154
203
  {% dnd_module path="../modules/${r.moduleName}.module" %}
155
204
  {% end_dnd_module %}
156
205
  {% end_dnd_section %}`).join(`
157
206
 
158
207
  `);return`<!--
159
- templateType: ${e.pageType==="blog_post"?"blog_post":"page"}
208
+ templateType: ${t.pageType==="blog_post"?"blog_post":"page"}
160
209
  isAvailableForNewContent: true
161
- label: "${e.label}"
210
+ label: "${t.label}"
162
211
  -->
163
212
  {% extends "./layouts/base.html" %}
164
213
 
@@ -170,7 +219,7 @@ ${t.join(`
170
219
 
171
220
  {% block body %}
172
221
  <div class="${n}-page">
173
- {% dnd_area "main_content" label="${e.label}" %}
222
+ {% dnd_area "main_content" label="${t.label}" %}
174
223
 
175
224
  ${o}
176
225
 
@@ -181,10 +230,57 @@ ${o}
181
230
 
182
231
  {% block footer %}
183
232
  {% endblock footer %}
184
- `}function Dp(e,t){let n=`<!--
233
+ `}function uf(t){let n=Kl(t).map(s=>` {% dnd_section %}
234
+ {% dnd_module path="../modules/${s.moduleName}.module" %}
235
+ {% end_dnd_module %}
236
+ {% end_dnd_section %}`).join(`
237
+
238
+ `);return`<!--
239
+ templateType: email
240
+ isAvailableForNewContent: true
241
+ label: "${t.label}"
242
+ screenshotPath: ../images/template-previews/email.png
243
+ -->
244
+ <!DOCTYPE html>
245
+ <html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
246
+ <head>
247
+ <meta charset="utf-8">
248
+ <meta name="viewport" content="width=device-width, initial-scale=1">
249
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
250
+ <!--[if mso]>
251
+ <noscript>
252
+ <xml>
253
+ <o:OfficeDocumentSettings>
254
+ <o:AllowPNG/>
255
+ <o:PixelsPerInch>96</o:PixelsPerInch>
256
+ </o:OfficeDocumentSettings>
257
+ </xml>
258
+ </noscript>
259
+ <![endif]-->
260
+ {{ standard_header_includes }}
261
+ {{ dnd_area_stylesheet }}
262
+ </head>
263
+ <body style="margin:0;padding:0;background-color:#f4f4f4;font-family:Arial,Helvetica,sans-serif;-webkit-font-smoothing:antialiased;">
264
+ <table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="background-color:#f4f4f4;">
265
+ <tr>
266
+ <td align="center" style="padding:20px 0;">
267
+ {% dnd_area "main"
268
+ label="Email Content"
269
+ %}
270
+
271
+ ${n}
272
+
273
+ {% end_dnd_area %}
274
+ </td>
275
+ </tr>
276
+ </table>
277
+ {{ standard_footer_includes }}
278
+ </body>
279
+ </html>
280
+ `}function mf(t,e){let n=`<!--
185
281
  templateType: blog_listing
186
282
  isAvailableForNewContent: true
187
- label: "${t.label} - Listing"
283
+ label: "${e.label} - Listing"
188
284
  -->
189
285
  {% extends "./layouts/base.html" %}
190
286
 
@@ -206,7 +302,7 @@ ${o}
206
302
  {% endif %}
207
303
  </div>
208
304
  {% endblock body %}
209
- `;De(B(e,`${t.id}-listing.html`),n,"utf-8")}function Jp(){let e=C();if(!e||e.modules.length===0)return"";let t=e.themeName,s=ce().map(o=>` {% dnd_section padding={"top":"0","bottom":"0","left":"0","right":"0"}, full_width=true %}
305
+ `;Ke(U(t,`${e.id}-listing.html`),n,"utf-8")}function pf(){let t=C();if(!t||t.modules.length===0)return"";let e=t.themeName,s=Se().map(o=>` {% dnd_section padding={"top":"0","bottom":"0","left":"0","right":"0"}, full_width=true %}
210
306
  {% dnd_module path="../modules/${o.moduleName}.module" %}
211
307
  {% end_dnd_module %}
212
308
  {% end_dnd_section %}`).join(`
@@ -214,38 +310,38 @@ ${o}
214
310
  `);return`<!--
215
311
  templateType: page
216
312
  isAvailableForNewContent: true
217
- label: "${t} Landing Page"
313
+ label: "${e} Landing Page"
218
314
  -->
219
315
  {% extends "./layouts/base.html" %}
220
316
 
221
- {% set template_css = "../../css/${t}-theme.css" %}
222
- {% set template_js = "../../js/${t}-animations.js" %}
317
+ {% set template_css = "../../css/${e}-theme.css" %}
318
+ {% set template_js = "../../js/${e}-animations.js" %}
223
319
 
224
320
  {% block header %}
225
321
  {% endblock header %}
226
322
 
227
323
  {% block body %}
228
- <div class="${t}-page">
229
- {% dnd_area "main_content" label="${t} Landing Page" %}
324
+ <div class="${e}-page">
325
+ {% dnd_area "main_content" label="${e} Landing Page" %}
230
326
 
231
327
  ${s}
232
328
 
233
329
  {% end_dnd_area %}
234
330
  </div>
235
- {{ require_js(get_asset_url("../../js/${t}-animations.js")) }}
331
+ {{ require_js(get_asset_url("../../js/${e}-animations.js")) }}
236
332
  {% endblock body %}
237
333
 
238
334
  {% block footer %}
239
335
  {% endblock footer %}
240
- `}var Si=G(()=>{"use strict";g();Rn();Mn();Nt();Zt();qs()});var al=G(()=>{"use strict";g();Ea();Rn();Mn();Si();Nt()});var me=G(()=>{"use strict";g();al()});function Zs(e){let t={};for(let n of e)n.type==="group"&&n.occurrence&&Array.isArray(n.default)?t[n.name]=n.default:n.type==="group"&&n.children?t[n.name]=Zs(n.children):t[n.name]=n.default??"";return t}function vi(e,t){let n=e;return n=Kp(n),n=ul(n,t),n=ml(n,t),n=pl(n,t),n=qp(n),n}function wi(e){let t=[e.sharedCss||"",...e.moduleCssArray].filter(Boolean).map(o=>`<style>${o}</style>`).join(`
241
- `),n=[e.sharedJs||"",...e.moduleJsArray].filter(Boolean).map(o=>`<script>${o}</script>`).join(`
242
- `),s=e.renderedModules.join(`
336
+ `}var Ui=R(()=>{"use strict";y();Vn();Wn();Nt();dn();bo()});var Yl=R(()=>{"use strict";y();dl();Vn();Wn();Ui();Nt()});var we=R(()=>{"use strict";y();Yl()});function Qn(t){let e={};for(let n of t)n.type==="group"&&n.occurrence&&Array.isArray(n.default)?e[n.name]=n.default:n.type==="group"&&n.children?e[n.name]=Qn(n.children):e[n.name]=n.default??"";return e}function xo(t,e){let n=t;return n=wf(n),n=Ql(n,e),n=ec(n,e),n=tc(n,e),n=kf(n),n}function Wi(t){let e=[t.sharedCss||"",...t.moduleCssArray].filter(Boolean).map(o=>`<style>${o}</style>`).join(`
337
+ `),n=[t.sharedJs||"",...t.moduleJsArray].filter(Boolean).map(o=>`<script>${o}</script>`).join(`
338
+ `),s=t.renderedModules.join(`
243
339
  `);return`<!DOCTYPE html>
244
340
  <html lang="en">
245
341
  <head>
246
342
  <meta charset="utf-8">
247
343
  <meta name="viewport" content="width=device-width, initial-scale=1">
248
- ${t}
344
+ ${e}
249
345
  <style>
250
346
  html{scroll-behavior:smooth}
251
347
  .vsp-img-wrap{position:relative;display:inline-block}
@@ -284,11 +380,11 @@ document.querySelectorAll('img').forEach(function(img){
284
380
  });
285
381
  </script>
286
382
  </body>
287
- </html>`}function Kp(e){return e=e.replace(Lp,""),e=e.replace(Hp,""),e=e.replace(Bp,""),ll.lastIndex=0,e=e.replace(ll,(t,n)=>`/theme-assets/${n}`),cl.lastIndex=0,e=e.replace(cl,""),e=e.replace(Up,""),e=e.replace(Gp,""),e=e.replace(Wp,""),e=e.replace(Vp,""),e=e.replace(zp,""),e}function ul(e,t){let n=e,s=0;for(;s<30;){s++;let o=Yp(n);if(!o)break;let{varName:i,iterExpr:r,body:a,start:l,end:c}=o,d=Xp(r,t),u="";Array.isArray(d)&&(u=d.map((m,f)=>{let y={...t,[i]:m,loop:{index:f+1,index0:f,first:f===0,last:f===d.length-1,length:d.length}},h=ul(a,y);return h=ml(h,y),h=pl(h,y),h}).join("")),n=n.slice(0,l)+u+n.slice(c)}return n}function Yp(e){let t=/\{%[-\s]*for\s+(\w+)\s+in\s+([\w.]+(?:\([^)]*\))?(?:\|[\w(),"' ]+)*)\s*-?%\}/g,n=/\{%[-\s]*(for\s|endfor)\s*.*?-?%\}/g,s=t.exec(e);if(!s)return null;let o=s[1],i=s[2],r=s.index+s[0].length;n.lastIndex=r;let a=1,l;for(;(l=n.exec(e))!==null;)if(l[1].startsWith("for"))a++;else if(a--,a===0){let c=e.slice(r,l.index);return{varName:o,iterExpr:i,body:c,start:s.index,end:l.index+l[0].length}}return null}function ml(e,t){let n=e,s=0;for(;xi.test(n)&&s<50;)s++,n=n.replace(xi,(o,i,r)=>{let a=r.split(/\{%[-\s]*else\s*-?%\}/),l=a[0],c=a[1]||"",d=l.split(/\{%[-\s]*elif\s+(.*?)\s*-?%\}/);if(d.length>1){if(on(i,t))return d[0];for(let u=1;u<d.length;u+=2){let m=d[u],f=d[u+1]||"";if(on(m,t))return f}return c}return on(i,t)?l:c}),xi.lastIndex=0;return n}function pl(e,t){return e.replace(/\{\{[-\s]*(.*?)[-\s]*\}\}/g,(n,s)=>{let i=s.trim().split("|"),r=i[0].trim(),a=Ot(t,r);for(let c=1;c<i.length;c++)a=gl(a,i[c].trim());if(a==null)return"";if(typeof a=="object")return JSON.stringify(a);let l=String(a);return l=l.replace(/\\n/g," ").replace(/\n/g," "),l})}function qp(e){return e=e.replace(/\{%.*?%\}/gs,""),e=e.replace(/\{\{.*?\}\}/gs,""),e}function Xp(e,t){let n=e.match(/^range\(\s*(.+?)\s*,\s*(.+?)\s*\)$/);if(n){let o=dl(n[1],t),i=dl(n[2],t),r=[];for(let a=o;a<i;a++)r.push(a);return r}let s=e.match(/^(.+?)\|split\(['"](.+?)['"]\)$/);if(s){let o=Ot(t,s[1].trim());return typeof o=="string"?o.split(s[2]):[]}return Ot(t,e)}function dl(e,t){let s=e.trim().split("|"),o=s[0].trim();if(!isNaN(Number(o)))return Number(o);let i=Ot(t,o);for(let r=1;r<s.length;r++)i=gl(i,s[r].trim());return Number(i)||0}function Ot(e,t){let n=t.split("."),s=e;for(let o of n){if(s==null||typeof s!="object")return;s=s[o]}return s}function on(e,t){let n=e.trim();if(n.startsWith("not "))return!on(n.slice(4),t);if(n.includes(" and "))return n.split(" and ").every(i=>on(i,t));if(n.includes(" or "))return n.split(" or ").some(i=>on(i,t));let s=n.match(/^(.+?)\s*(==|!=|>=|<=|>|<)\s*(.+)$/);if(s){let i=Ot(t,s[1].trim()),r=s[2],a=s[3].trim();switch(typeof a=="string"&&a.startsWith('"')&&a.endsWith('"')||typeof a=="string"&&a.startsWith("'")&&a.endsWith("'")?a=a.slice(1,-1):isNaN(Number(a))?a=Ot(t,a):a=Number(a),r){case"==":return i==a;case"!=":return i!=a;case">":return Number(i)>Number(a);case"<":return Number(i)<Number(a);case">=":return Number(i)>=Number(a);case"<=":return Number(i)<=Number(a)}}let o=Ot(t,n);return fl(o)}function fl(e){return!(e==null||e===""||e===0||e===!1||Array.isArray(e)&&e.length===0)}function gl(e,t){let n=e==null?"":String(e),s=t.match(/^(\w+)\((.*)\)$/),o=s?s[1]:t,i=s?s[2].replace(/^["']|["']$/g,""):void 0;switch(o){case"escape":case"e":return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");case"lower":return n.toLowerCase();case"upper":return n.toUpperCase();case"capitalize":return n.charAt(0).toUpperCase()+n.slice(1);case"trim":return n.trim();case"truncate":if(i){let r=parseInt(i,10);return n.length>r?n.slice(0,r)+"...":n}return n;case"default":return fl(e)?e:i??"";case"length":return Array.isArray(e)?e.length:n.length;case"join":return Array.isArray(e)?e.join(i??", "):n;case"int":case"float":return Number(n)||0;case"abs":return Math.abs(Number(n));case"round":return Math.round(Number(n));default:return e}}var Lp,Hp,Bp,ll,cl,Up,Gp,Wp,Vp,zp,xi,hl=G(()=>{"use strict";g();Lp=/\{%[-\s]*require_(css|js)\b.*?%\}/gs,Hp=/\{%[-\s]*end_require_(css|js)\s*%\}/gs,Bp=/\{\{[-\s]*require_(css|js)\(.*?\)\s*\}\}/gs,ll=/\{\{[-\s]*get_asset_url\(["'](?:[^"'\/]+\/)?assets\/(.*?)["']\)\s*\}\}/gs,cl=/\{\{[-\s]*get_asset_url\(.*?\)\s*\}\}/gs,Up=/\{%[-\s]*(end_)?(dnd_area|dnd_section|dnd_column|dnd_row|dnd_module)\b.*?%\}/gs,Gp=/\{%[-\s]*module\b.*?%\}/gs,Wp=/\{%[-\s]*(extends|block|endblock|set)\b.*?%\}/gs,Vp=/\{#.*?#\}/gs,zp=/\{\{[-\s]*content\.\w+.*?\}\}/gs,xi=/\{%[-\s]*if\s+(.*?)\s*-?%\}((?:(?!\{%[-\s]*if\s)[\s\S])*?)\{%[-\s]*endif\s*-?%\}/g});var Qs={};_e(Qs,{buildModulePreviewHtml:()=>ki,buildPreviewHtml:()=>Ci});function Zp(e){if(!e)return{bg:"#0f0f14",surface:"#1a1a20",text:"#ffffff",textMuted:"#666",border:"#333"};let t=(a,l)=>{for(let c of a){let d=new RegExp(`${c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}\\s*:\\s*([^;})]+)`,"i"),u=e.match(d);if(u)return u[1].trim()}return l},n=t(["--bg","--background","--color-bg","--bg-primary","--body-bg"],"#0f0f14"),s=t(["--surface","--bg-secondary","--card-bg","--color-surface"],n),o=t(["--text","--color-text","--text-primary","--fg","--foreground"],"#ffffff"),i=t(["--text-muted","--text-secondary","--muted","--color-text-muted"],"#666"),r=t(["--border","--border-color","--color-border"],"#333");return{bg:n,surface:s,text:o,textMuted:i,border:r}}function Ci(){let e=C();if(!e)return yl();let t=ce(),n=e.moduleOrder||[];if(t.length===0&&n.length===0)return yl();let s=[],o=[],i=[],r=new Set;for(let c of t){if(c.moduleHtml.includes("dnd_area")||c.moduleHtml.includes("extends "))continue;let d;try{let f=JSON.parse(c.fieldsJson);d={module:Zs(f)}}catch{d={module:{}}}let u=vi(c.moduleHtml,d),m=c.moduleName.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"");s.push(`<div class="vibespot-module" id="${m}" data-module="${c.moduleName}">${u}</div>`),r.add(c.moduleName),c.moduleCss&&o.push(c.moduleCss),c.moduleJs&&i.push(c.moduleJs)}let a=Zp(e.sharedCss);for(let c of n)if(!r.has(c)){let d=c.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"");s.push(`<div class="vibespot-module vibespot-module--pending" id="${d}" data-module="${c}">
383
+ </html>`}function wf(t){return t=t.replace(gf,""),t=t.replace(ff,""),t=t.replace(hf,""),ql.lastIndex=0,t=t.replace(ql,(e,n)=>`/theme-assets/${n}`),Xl.lastIndex=0,t=t.replace(Xl,""),t=t.replace(yf,""),t=t.replace(bf,""),t=t.replace(Sf,""),t=t.replace(xf,""),t=t.replace(vf,""),t}function Ql(t,e){let n=t,s=0;for(;s<30;){s++;let o=Cf(n);if(!o)break;let{varName:i,iterExpr:r,body:a,start:l,end:c}=o,d=Tf(r,e),u="";Array.isArray(d)&&(u=d.map((m,g)=>{let h={...e,[i]:m,loop:{index:g+1,index0:g,first:g===0,last:g===d.length-1,length:d.length}},f=Ql(a,h);return f=ec(f,h),f=tc(f,h),f}).join("")),n=n.slice(0,l)+u+n.slice(c)}return n}function Cf(t){let e=/\{%[-\s]*for\s+(\w+)\s+in\s+([\w.]+(?:\([^)]*\))?(?:\|[\w(),"' ]+)*)\s*-?%\}/g,n=/\{%[-\s]*(for\s|endfor)\s*.*?-?%\}/g,s=e.exec(t);if(!s)return null;let o=s[1],i=s[2],r=s.index+s[0].length;n.lastIndex=r;let a=1,l;for(;(l=n.exec(t))!==null;)if(l[1].startsWith("for"))a++;else if(a--,a===0){let c=t.slice(r,l.index);return{varName:o,iterExpr:i,body:c,start:s.index,end:l.index+l[0].length}}return null}function ec(t,e){let n=t,s=0;for(;Gi.test(n)&&s<50;)s++,n=n.replace(Gi,(o,i,r)=>{let a=r.split(/\{%[-\s]*else\s*-?%\}/),l=a[0],c=a[1]||"",d=l.split(/\{%[-\s]*elif\s+(.*?)\s*-?%\}/);if(d.length>1){if(hn(i,e))return d[0];for(let u=1;u<d.length;u+=2){let m=d[u],g=d[u+1]||"";if(hn(m,e))return g}return c}return hn(i,e)?l:c}),Gi.lastIndex=0;return n}function tc(t,e){return t.replace(/\{\{[-\s]*(.*?)[-\s]*\}\}/g,(n,s)=>{let i=s.trim().split("|"),r=i[0].trim(),a=Kt(e,r);for(let c=1;c<i.length;c++)a=sc(a,i[c].trim());if(a==null)return"";if(typeof a=="object")return JSON.stringify(a);let l=String(a);return l=l.replace(/\\n/g," ").replace(/\n/g," "),l})}function kf(t){return t=t.replace(/\{%.*?%\}/gs,""),t=t.replace(/\{\{.*?\}\}/gs,""),t}function Tf(t,e){let n=t.match(/^range\(\s*(.+?)\s*,\s*(.+?)\s*\)$/);if(n){let o=Zl(n[1],e),i=Zl(n[2],e),r=[];for(let a=o;a<i;a++)r.push(a);return r}let s=t.match(/^(.+?)\|split\(['"](.+?)['"]\)$/);if(s){let o=Kt(e,s[1].trim());return typeof o=="string"?o.split(s[2]):[]}return Kt(e,t)}function Zl(t,e){let s=t.trim().split("|"),o=s[0].trim();if(!isNaN(Number(o)))return Number(o);let i=Kt(e,o);for(let r=1;r<s.length;r++)i=sc(i,s[r].trim());return Number(i)||0}function Kt(t,e){let n=e.split("."),s=t;for(let o of n){if(s==null||typeof s!="object")return;s=s[o]}return s}function hn(t,e){let n=t.trim();if(n.startsWith("not "))return!hn(n.slice(4),e);if(n.includes(" and "))return n.split(" and ").every(i=>hn(i,e));if(n.includes(" or "))return n.split(" or ").some(i=>hn(i,e));let s=n.match(/^(.+?)\s*(==|!=|>=|<=|>|<)\s*(.+)$/);if(s){let i=Kt(e,s[1].trim()),r=s[2],a=s[3].trim();switch(typeof a=="string"&&a.startsWith('"')&&a.endsWith('"')||typeof a=="string"&&a.startsWith("'")&&a.endsWith("'")?a=a.slice(1,-1):isNaN(Number(a))?a=Kt(e,a):a=Number(a),r){case"==":return i==a;case"!=":return i!=a;case">":return Number(i)>Number(a);case"<":return Number(i)<Number(a);case">=":return Number(i)>=Number(a);case"<=":return Number(i)<=Number(a)}}let o=Kt(e,n);return nc(o)}function nc(t){return!(t==null||t===""||t===0||t===!1||Array.isArray(t)&&t.length===0)}function sc(t,e){let n=t==null?"":String(t),s=e.match(/^(\w+)\((.*)\)$/),o=s?s[1]:e,i=s?s[2].replace(/^["']|["']$/g,""):void 0;switch(o){case"escape":case"e":return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");case"lower":return n.toLowerCase();case"upper":return n.toUpperCase();case"capitalize":return n.charAt(0).toUpperCase()+n.slice(1);case"trim":return n.trim();case"truncate":if(i){let r=parseInt(i,10);return n.length>r?n.slice(0,r)+"...":n}return n;case"default":return nc(t)?t:i??"";case"length":return Array.isArray(t)?t.length:n.length;case"join":return Array.isArray(t)?t.join(i??", "):n;case"int":case"float":return Number(n)||0;case"abs":return Math.abs(Number(n));case"round":return Math.round(Number(n));default:return t}}var gf,ff,hf,ql,Xl,yf,bf,Sf,xf,vf,Gi,oc=R(()=>{"use strict";y();gf=/\{%[-\s]*require_(css|js)\b.*?%\}/gs,ff=/\{%[-\s]*end_require_(css|js)\s*%\}/gs,hf=/\{\{[-\s]*require_(css|js)\(.*?\)\s*\}\}/gs,ql=/\{\{[-\s]*get_asset_url\(["'](?:[^"'\/]+\/)?assets\/(.*?)["']\)\s*\}\}/gs,Xl=/\{\{[-\s]*get_asset_url\(.*?\)\s*\}\}/gs,yf=/\{%[-\s]*(end_)?(dnd_area|dnd_section|dnd_column|dnd_row|dnd_module)\b.*?%\}/gs,bf=/\{%[-\s]*module\b.*?%\}/gs,Sf=/\{%[-\s]*(extends|block|endblock|set)\b.*?%\}/gs,xf=/\{#.*?#\}/gs,vf=/\{\{[-\s]*content\.\w+.*?\}\}/gs,Gi=/\{%[-\s]*if\s+(.*?)\s*-?%\}((?:(?!\{%[-\s]*if\s)[\s\S])*?)\{%[-\s]*endif\s*-?%\}/g});var vo={};Be(vo,{buildModulePreviewHtml:()=>zi,buildPreviewHtml:()=>Vi});function Af(t){if(yn()==="email")return!0;for(let e of t)try{let n=JSON.parse(e.metaJson);if(Array.isArray(n.host_template_types)&&n.host_template_types.includes("EMAIL"))return!0}catch{}return!1}function $f(t){if(!t)return{bg:"#0f0f14",surface:"#1a1a20",text:"#ffffff",textMuted:"#666",border:"#333"};let e=(a,l)=>{for(let c of a){let d=new RegExp(`${c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}\\s*:\\s*([^;})]+)`,"i"),u=t.match(d);if(u)return u[1].trim()}return l},n=e(["--bg","--background","--color-bg","--bg-primary","--body-bg"],"#0f0f14"),s=e(["--surface","--bg-secondary","--card-bg","--color-surface"],n),o=e(["--text","--color-text","--text-primary","--fg","--foreground"],"#ffffff"),i=e(["--text-muted","--text-secondary","--muted","--color-text-muted"],"#666"),r=e(["--border","--border-color","--color-border"],"#333");return{bg:n,surface:s,text:o,textMuted:i,border:r}}function Ki(t,e){if(!Array.isArray(e))return t;let n=new Map;for(let o of e)n.set(o.name,o.type);let s=t;return s=s.replace(/(<([a-zA-Z]\w*)(\s[^>]*)?>)\s*(\{\{\s*module\.(\w+)(?:\.\w+)*(?:\|[^}]*)?\s*\}\})\s*(<\/\2>)/g,(o,i,r,a,l,c,d)=>{if(i.includes("data-vs-field"))return o;let u=n.get(c)||"text";return`${i.replace(/>$/,` data-vs-field="${c}" data-vs-type="${u}">`)}${l}${d}`}),s=s.replace(/(<img\b)([^>]*?)\bsrc\s*=\s*["']\{\{\s*module\.(\w+)\.src\s*\}\}["']([^>]*?>)/g,(o,i,r,a)=>o.includes("data-vs-field")?o:o.replace("<img",`<img data-vs-field="${a}" data-vs-type="image"`)),s=s.replace(/(<a\b)([^>]*?)\bhref\s*=\s*["']\{\{\s*module\.(\w+)\.url\.href\s*\}\}["']([^>]*?>)/g,(o,i,r,a)=>o.includes("data-vs-link")?o:o.replace("<a",`<a data-vs-link="${a}"`)),s}function Vi(){let t=C();if(!t)return ic();let e=Se(),n=t.moduleOrder||[];if(e.length===0&&n.length===0)return ic();if(Af(e))return _f(e,n);let s=[],o=[],i=[],r=new Set;for(let c of e){if(c.moduleHtml.includes("dnd_area")||c.moduleHtml.includes("extends "))continue;let d,u=[];try{let f=JSON.parse(c.fieldsJson);u=Array.isArray(f)?f:[],d={module:Qn(u)}}catch{d={module:{}}}let m=Ki(c.moduleHtml,u),g=xo(m,d),h=c.moduleName.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"");s.push(`<div class="vibespot-module" id="${h}" data-module="${c.moduleName}">${g}</div>`),r.add(c.moduleName),c.moduleCss&&o.push(c.moduleCss),c.moduleJs&&i.push(c.moduleJs)}let a=$f(t.sharedCss);for(let c of n)if(!r.has(c)){let d=c.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"");s.push(`<div class="vibespot-module vibespot-module--pending" id="${d}" data-module="${c}">
288
384
  <div class="vibespot-placeholder">
289
385
  <div class="vibespot-placeholder__name">${c}</div>
290
386
  </div>
291
- </div>`)}let l=`body{background:${a.bg}}.vibespot-placeholder{display:flex;align-items:center;justify-content:center;min-height:200px;padding:3rem;background:${a.surface};border:1px dashed ${a.border};border-radius:12px;margin:1rem 0}.vibespot-placeholder__name{font-size:1.5rem;font-weight:600;font-family:system-ui,sans-serif;color:${a.textMuted};letter-spacing:.5px;animation:vp-fade 2s ease-in-out infinite}@keyframes vp-fade{0%,100%{opacity:.3}50%{opacity:.8}}`;return wi({renderedModules:s,sharedCss:e.sharedCss,moduleCssArray:[l,...o],sharedJs:e.sharedJs,moduleJsArray:i})}function yl(){return`<!DOCTYPE html>
387
+ </div>`)}let l=`body{background:${a.bg}}.vibespot-placeholder{display:flex;align-items:center;justify-content:center;min-height:200px;padding:3rem;background:${a.surface};border:1px dashed ${a.border};border-radius:12px;margin:1rem 0}.vibespot-placeholder__name{font-size:1.5rem;font-weight:600;font-family:system-ui,sans-serif;color:${a.textMuted};letter-spacing:.5px;animation:vp-fade 2s ease-in-out infinite}@keyframes vp-fade{0%,100%{opacity:.3}50%{opacity:.8}}`;return Wi({renderedModules:s,sharedCss:t.sharedCss,moduleCssArray:[l,...o],sharedJs:t.sharedJs,moduleJsArray:i})}function ic(){return`<!DOCTYPE html>
292
388
  <html lang="en">
293
389
  <head>
294
390
  <meta charset="utf-8">
@@ -339,11 +435,61 @@ document.querySelectorAll('img').forEach(function(img){
339
435
  <div class="welcome__sub">Build Something Great</div>
340
436
  </div>
341
437
  </body>
342
- </html>`}function ki(e){let t=C();if(!t)return"";let n;for(let i of t.templates)if(n=i.modules.find(r=>r.moduleName===e),n)break;if(n||(n=t.modules.find(i=>i.moduleName===e)),!n)return"";let s;try{let i=JSON.parse(n.fieldsJson);s={module:Zs(i)}}catch{s={module:{}}}let o=vi(n.moduleHtml,s);return wi({renderedModules:[`<div class="vibespot-module" data-module="${n.moduleName}">${o}</div>`],sharedCss:t.sharedCss,moduleCssArray:n.moduleCss?[n.moduleCss]:[],sharedJs:t.sharedJs,moduleJsArray:n.moduleJs?[n.moduleJs]:[]})}var Fn=G(()=>{"use strict";g();hl();me()});function tt(e){try{return JSON.parse(e)}catch{}let t=e,n=-1;for(let s=0;s<20;s++)try{return JSON.parse(t)}catch(o){if(!(o instanceof SyntaxError))return null;let i=/position (\d+)/.exec(o.message);if(!i)return null;let r=parseInt(i[1],10);if(r<=n)return null;n=r;let a=Math.max(0,r-5),c=t.slice(a,r+1).lastIndexOf('"');if(c===-1)return null;let d=a+c;if(d>0&&t[d-1]==="\\")return null;t=t.slice(0,d)+'\\"'+t.slice(d+1)}return null}function jn(e){let t=e.indexOf('"modules"');if(t===-1)return null;let n=e.indexOf("[",t);if(n===-1)return null;let s=-1,o=0,i=!1,r=!1;for(let d=n+1;d<e.length;d++){let u=e[d];if(r){r=!1;continue}if(u==="\\"){r=!0;continue}if(u==='"'){i=!i;continue}i||(u==="{"&&o++,u==="}"&&(o--,o===0&&(s=d)))}if(s===-1)return null;let l=e.slice(0,s+1)+"]}",c=l.trimStart().startsWith("{")?l:"{"+l;return tt(c)}function Ai(e){return{moduleName:String(e.moduleName||""),fieldsJson:typeof e.fieldsJson=="string"?e.fieldsJson:JSON.stringify(e.fieldsJson,null,2),metaJson:typeof e.metaJson=="string"?e.metaJson:JSON.stringify(e.metaJson,null,2),moduleHtml:String(e.moduleHtml||""),moduleCss:String(e.moduleCss||""),moduleJs:e.moduleJs?String(e.moduleJs):void 0}}function bl(e,t){let n=!1,s,o=/```vibespot-modules\s*\n?([\s\S]*?)```/g;for(;(s=o.exec(e))!==null;)try{E.info("parse","Found vibespot-modules block",{length:s[1].length});let i=tt(s[1]);if(!i||typeof i!="object")throw E.warn("parse","tryParseJSON returned non-object",{result:typeof i}),new Error("Invalid JSON after repair");let r=i;r.modules&&Array.isArray(r.modules)&&(Ie({modules:r.modules.map(a=>Ai(a)),sharedCss:r.sharedCss!==void 0?String(r.sharedCss):void 0,sharedJs:r.sharedJs!==void 0?String(r.sharedJs):void 0}),n=!0)}catch(i){E.warn("parse","Failed to parse vibespot-modules block",{error:i instanceof Error?i.message:String(i)})}if(!n){let i=/```(?:json)?\s*\n([\s\S]*?)```/g;for(;(s=i.exec(e))!==null;)if(s[1].includes('"modules"'))try{let r=tt(s[1]);if(!r||typeof r!="object")throw new Error("Invalid JSON after repair");let a=r;a.modules&&Array.isArray(a.modules)&&(Ie({modules:a.modules.map(l=>Ai(l)),sharedCss:a.sharedCss!==void 0?String(a.sharedCss):void 0,sharedJs:a.sharedJs!==void 0?String(a.sharedJs):void 0}),n=!0)}catch(r){E.warn("parse","Failed to parse JSON module block",{error:r instanceof Error?r.message:String(r)})}}if(!n&&(e.match(/```/g)||[]).length%2!==0&&e.includes('"modules"')){E.info("parse","Detected truncated response (odd fence count), attempting salvage");let r=e.lastIndexOf("```"),a=e.slice(r+3);a=a.replace(/^[\w-]*\s*\n?/,"");let l=jn(a);if(l){let c=l;c.modules&&Array.isArray(c.modules)&&c.modules.length>0&&(E.info("parse","Salvaged modules from truncated response",{count:c.modules.length}),Ie({modules:c.modules.map(d=>Ai(d)),sharedCss:c.sharedCss!==void 0?String(c.sharedCss):void 0,sharedJs:c.sharedJs!==void 0?String(c.sharedJs):void 0}),n=!0,t&&t("Response was truncated \u2014 some modules may be incomplete. Try sending your request again for the full set."))}}if(!n){E.info("parse","No modules applied",{responseLength:e.length,hasVibespot:e.includes("vibespot-modules"),hasModules:e.includes('"modules"'),fenceCount:(e.match(/```/g)||[]).length});let i=e.includes("vibespot-modules")||e.includes('"modules"'),r=/\bmodule|modul/i.test(e)&&(/\bcreated?\b|\berstellt\b|\bgenerat/i.test(e)||/\|.*\|.*\|/m.test(e));if(i||r){let a=i?"Module changes could not be applied \u2014 the AI response contained invalid JSON. Try sending your request again.":"The AI described modules but did not include the required structured data. Try sending your request again.";E.warn("parse",a),t&&t(a)}}}var eo=G(()=>{"use strict";g();me();re()});function rn(){let e=C();return e?{pageType:ye()?.pageType,brandAssets:e.brandAssets}:{}}function Sl(e,t,n=!1,s,o){let r=[{type:"text",text:ef(t,n)}];if(n){let l=`## HubSpot CMS Rules
343
- ${He()}
438
+ </html>`}function zi(t){let e=C();if(!e)return"";let n;for(let a of e.templates)if(n=a.modules.find(l=>l.moduleName===t),n)break;if(n||(n=e.modules.find(a=>a.moduleName===t)),!n)return"";let s,o=[];try{let a=JSON.parse(n.fieldsJson);o=Array.isArray(a)?a:[],s={module:Qn(o)}}catch{s={module:{}}}let i=Ki(n.moduleHtml,o),r=xo(i,s);return Wi({renderedModules:[`<div class="vibespot-module" data-module="${n.moduleName}">${r}</div>`],sharedCss:e.sharedCss,moduleCssArray:n.moduleCss?[n.moduleCss]:[],sharedJs:e.sharedJs,moduleJsArray:n.moduleJs?[n.moduleJs]:[]})}function _f(t,e){let n=[],s=new Set;for(let i of t){let r,a=[];try{let u=JSON.parse(i.fieldsJson);a=Array.isArray(u)?u:[],r={module:Qn(a)}}catch{r={module:{}}}let l=Ki(i.moduleHtml,a),c=xo(l,r),d=i.moduleName.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"");n.push(`<div class="vibespot-module" id="${d}" data-module="${i.moduleName}">${c}</div>`),s.add(i.moduleName)}for(let i of e)if(!s.has(i)){let r=i.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"");n.push(`<div class="vibespot-module vibespot-module--pending" id="${r}" data-module="${i}">
439
+ <table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="max-width:600px;margin:0 auto;">
440
+ <tr><td style="padding:40px 30px;text-align:center;background-color:#ffffff;border:1px dashed #ddd;">
441
+ <p style="font-family:Arial,Helvetica,sans-serif;font-size:14px;color:#999;">${i}</p>
442
+ </td></tr>
443
+ </table>
444
+ </div>`)}return`<!DOCTYPE html>
445
+ <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
446
+ <head>
447
+ <meta charset="utf-8">
448
+ <meta name="viewport" content="width=device-width, initial-scale=1">
449
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
450
+ <title>Email Preview</title>
451
+ <style>
452
+ html, body { margin: 0; padding: 0; overflow-x: hidden; }
453
+ body {
454
+ background-color: #e8e8e8;
455
+ font-family: Arial, Helvetica, sans-serif;
456
+ -webkit-font-smoothing: antialiased;
457
+ }
458
+ .vibespot-email-wrapper {
459
+ padding: 30px 20px;
460
+ background-color: #e8e8e8;
461
+ min-height: 100vh;
462
+ }
463
+ .vibespot-module { margin: 0 auto; max-width: 600px; }
464
+ .vibespot-module--pending table { opacity: 0.6; }
465
+ html { scroll-behavior: smooth; }
466
+ img { max-width: 100% !important; height: auto !important; }
467
+ table { max-width: 100% !important; }
468
+ td { word-break: break-word; }
469
+ @media screen and (max-width: 620px) {
470
+ .vibespot-email-wrapper { padding: 10px 8px; }
471
+ table[width] { width: 100% !important; }
472
+ img[width] { width: 100% !important; height: auto !important; }
473
+ }
474
+ </style>
475
+ </head>
476
+ <body>
477
+ <div class="vibespot-email-wrapper">
478
+ ${n.join(`
479
+ `)}
480
+ </div>
481
+ <script>
482
+ document.addEventListener('click', function(e) {
483
+ var a = e.target.closest('a[href^="#"]');
484
+ if (a) { e.preventDefault(); var t = document.querySelector(a.getAttribute('href')); if (t) t.scrollIntoView({ behavior: 'smooth' }); }
485
+ });
486
+ </script>
487
+ </body>
488
+ </html>`}var es=R(()=>{"use strict";y();oc();we();ts()});function ft(t){try{return JSON.parse(t)}catch{}let e=t,n=-1;for(let s=0;s<20;s++)try{return JSON.parse(e)}catch(o){if(!(o instanceof SyntaxError))return null;let i=/position (\d+)/.exec(o.message);if(!i)return null;let r=parseInt(i[1],10);if(r<=n)return null;n=r;let a=Math.max(0,r-5),c=e.slice(a,r+1).lastIndexOf('"');if(c===-1)return null;let d=a+c;if(d>0&&e[d-1]==="\\")return null;e=e.slice(0,d)+'\\"'+e.slice(d+1)}return null}function ns(t){let e=t.indexOf('"modules"');if(e===-1)return null;let n=t.indexOf("[",e);if(n===-1)return null;let s=-1,o=0,i=!1,r=!1;for(let d=n+1;d<t.length;d++){let u=t[d];if(r){r=!1;continue}if(u==="\\"){r=!0;continue}if(u==='"'){i=!i;continue}i||(u==="{"&&o++,u==="}"&&(o--,o===0&&(s=d)))}if(s===-1)return null;let l=t.slice(0,s+1)+"]}",c=l.trimStart().startsWith("{")?l:"{"+l;return ft(c)}function Yi(t){return{moduleName:String(t.moduleName||""),fieldsJson:typeof t.fieldsJson=="string"?t.fieldsJson:JSON.stringify(t.fieldsJson,null,2),metaJson:typeof t.metaJson=="string"?t.metaJson:JSON.stringify(t.metaJson,null,2),moduleHtml:String(t.moduleHtml||""),moduleCss:String(t.moduleCss||""),moduleJs:t.moduleJs?String(t.moduleJs):void 0}}function rc(t,e){let n=!1,s,o=/```vibespot-modules\s*\n?([\s\S]*?)```/g;for(;(s=o.exec(t))!==null;)try{E.info("parse","Found vibespot-modules block",{length:s[1].length});let i=ft(s[1]);if(!i||typeof i!="object")throw E.warn("parse","tryParseJSON returned non-object",{result:typeof i}),new Error("Invalid JSON after repair");let r=i;r.modules&&Array.isArray(r.modules)&&(De({modules:r.modules.map(a=>Yi(a)),sharedCss:r.sharedCss!==void 0?String(r.sharedCss):void 0,sharedJs:r.sharedJs!==void 0?String(r.sharedJs):void 0}),n=!0)}catch(i){E.warn("parse","Failed to parse vibespot-modules block",{error:i instanceof Error?i.message:String(i)})}if(!n){let i=/```(?:json)?\s*\n([\s\S]*?)```/g;for(;(s=i.exec(t))!==null;)if(s[1].includes('"modules"'))try{let r=ft(s[1]);if(!r||typeof r!="object")throw new Error("Invalid JSON after repair");let a=r;a.modules&&Array.isArray(a.modules)&&(De({modules:a.modules.map(l=>Yi(l)),sharedCss:a.sharedCss!==void 0?String(a.sharedCss):void 0,sharedJs:a.sharedJs!==void 0?String(a.sharedJs):void 0}),n=!0)}catch(r){E.warn("parse","Failed to parse JSON module block",{error:r instanceof Error?r.message:String(r)})}}if(!n&&(t.match(/```/g)||[]).length%2!==0&&t.includes('"modules"')){E.info("parse","Detected truncated response (odd fence count), attempting salvage");let r=t.lastIndexOf("```"),a=t.slice(r+3);a=a.replace(/^[\w-]*\s*\n?/,"");let l=ns(a);if(l){let c=l;c.modules&&Array.isArray(c.modules)&&c.modules.length>0&&(E.info("parse","Salvaged modules from truncated response",{count:c.modules.length}),De({modules:c.modules.map(d=>Yi(d)),sharedCss:c.sharedCss!==void 0?String(c.sharedCss):void 0,sharedJs:c.sharedJs!==void 0?String(c.sharedJs):void 0}),n=!0,e&&e("Response was truncated \u2014 some modules may be incomplete. Try sending your request again for the full set."))}}if(!n){E.info("parse","No modules applied",{responseLength:t.length,hasVibespot:t.includes("vibespot-modules"),hasModules:t.includes('"modules"'),fenceCount:(t.match(/```/g)||[]).length});let i=t.includes("vibespot-modules")||t.includes('"modules"'),r=/\bmodule|modul/i.test(t)&&(/\bcreated?\b|\berstellt\b|\bgenerat/i.test(t)||/\|.*\|.*\|/m.test(t));if(i||r){let a=i?"Module changes could not be applied \u2014 the AI response contained invalid JSON. Try sending your request again.":"The AI described modules but did not include the required structured data. Try sending your request again.";E.warn("parse",a),e&&e(a)}}}var wo=R(()=>{"use strict";y();we();de()});function bn(){let t=C();return t?{pageType:Ce()?.pageType,brandAssets:t.brandAssets}:{}}function ac(t,e,n=!1,s,o){let r=[{type:"text",text:Ef(e,n)}];if(n){let l=`## HubSpot CMS Rules
489
+ ${je()}
344
490
 
345
491
  ## Conversion Guide Reference
346
- ${e}`;r.push({type:"text",text:l,cache_control:{type:"ephemeral"}})}else{let l=`## Design Quality
492
+ ${t}`;r.push({type:"text",text:l,cache_control:{type:"ephemeral"}})}else{let l=`## Design Quality
347
493
  - Use modern, clean design with proper spacing and typography
348
494
  - Include responsive CSS (mobile breakpoint at 767px)
349
495
  - Add scroll animation classes where appropriate
@@ -366,22 +512,22 @@ When using scroll-animate classes (opacity: 0 \u2192 visible), you MUST include
366
512
  This makes elements appear after 3 seconds if JS never adds the .visible class. Once JS runs normally and adds .visible, the animation is cancelled.
367
513
 
368
514
  ## Design Guide
369
- ${Zo()}
515
+ ${Un()}
370
516
 
371
517
  ## Content & Copywriting Guide
372
- ${Qo()}
518
+ ${Ci()}
373
519
 
374
520
  ## HubSpot CMS Rules
375
- ${He()}
521
+ ${je()}
376
522
 
377
523
  ## Conversion Guide Reference
378
- ${e}`;r.push({type:"text",text:l,cache_control:{type:"ephemeral"}})}let a=Qp(s,o);return a&&r.push({type:"text",text:a}),r.push({type:"text",text:"## REMINDER \u2014 Output Format (CRITICAL)\nYour response MUST contain a ```vibespot-modules code block with the full JSON. Without this block, no modules will be created. Do NOT respond with only text, tables, or descriptions. The JSON block is mandatory."}),r}function Qp(e,t){let n=[];if(e){let s=ti(e);s&&n.push(`## Page Type Context
379
- ${s}`)}if(t?.styleguide&&n.push(`## Brand Style Guide
380
- ${t.styleguide}`),t?.brandvoice&&n.push(`## Brand Voice
381
- ${t.brandvoice}`),t?.humanify!==!1){let s=ei();s&&n.push(`## Anti-AI Copy Rules (Humanify)
524
+ ${t}`;r.push({type:"text",text:l,cache_control:{type:"ephemeral"}})}let a=Mf(s,o);return a&&r.push({type:"text",text:a}),r.push({type:"text",text:"## REMINDER \u2014 Output Format (CRITICAL)\nYour response MUST contain a ```vibespot-modules code block with the full JSON. Without this block, no modules will be created. Do NOT respond with only text, tables, or descriptions. The JSON block is mandatory."}),r}function Mf(t,e){let n=[];if(t){let s=Ti(t);s&&n.push(`## Page Type Context
525
+ ${s}`)}if(e?.styleguide&&n.push(`## Brand Style Guide
526
+ ${e.styleguide}`),e?.brandvoice&&n.push(`## Brand Voice
527
+ ${e.brandvoice}`),e?.humanify!==!1){let s=ki();s&&n.push(`## Anti-AI Copy Rules (Humanify)
382
528
  ${s}`)}return n.join(`
383
529
 
384
- `)}function ef(e,t){return`You are vibeSpot, an AI that builds HubSpot CMS landing pages from natural language descriptions.
530
+ `)}function Ef(t,e){return`You are vibeSpot, an AI that builds HubSpot CMS landing pages from natural language descriptions.
385
531
 
386
532
  ## Your Role
387
533
  You generate native HubSpot CMS modules directly from user descriptions. Every module you create is immediately compatible with HubSpot's drag-and-drop page editor.
@@ -423,8 +569,8 @@ NEVER respond with only a text summary. The vibespot-modules JSON block is manda
423
569
  - NEVER use "name": "name" (reserved) \u2014 use "item_name" instead
424
570
  - NEVER put literal \\n newline sequences in field default values \u2014 use plain text without line breaks
425
571
  - Wrap style fields in a "styles" group with "tab": "STYLE"
426
- - All CSS classes must use a unique prefix "${e}-" to avoid theme conflicts
427
- - Use BEM naming: ${e}-module__element--modifier
572
+ - All CSS classes must use a unique prefix "${t}-" to avoid theme conflicts
573
+ - Use BEM naming: ${t}-module__element--modifier
428
574
  - metaJson must include: host_template_types: ["PAGE"], is_available_for_new_content: true
429
575
  - For repeater groups, use "occurrence": { "min": 0, "max": 100 } and iterate with {% for %}
430
576
  - Color fields: type "color", default { "color": "#hex", "opacity": 100 }
@@ -433,9 +579,9 @@ NEVER respond with only a text summary. The vibespot-modules JSON block is manda
433
579
 
434
580
  ## Images & Media
435
581
  - Users can upload images that get placed in the theme's assets/ folder automatically
436
- - When the user uploads an image and wants it on the page, reference it with: {{ get_asset_url("${e}/assets/filename.ext") }}
437
- - IMPORTANT: get_asset_url() paths must include the theme name prefix "${e}/" because HubSpot resolves from the Design Manager root
438
- - For background images with uploaded assets: style="background-image: url('{{ get_asset_url(\\"${e}/assets/filename.ext\\") }}')"
582
+ - When the user uploads an image and wants it on the page, reference it with: {{ get_asset_url("${t}/assets/filename.ext") }}
583
+ - IMPORTANT: get_asset_url() paths must include the theme name prefix "${t}/" because HubSpot resolves from the Design Manager root
584
+ - For background images with uploaded assets: style="background-image: url('{{ get_asset_url(\\"${t}/assets/filename.ext\\") }}')"
439
585
  - For images without an uploaded asset, use image fields (type "image") with placehold.co defaults
440
586
  - ALWAYS use image fields (type "image") so users can swap images in the page editor
441
587
  - Use placehold.co URLs as defaults so the preview looks complete (e.g. https://placehold.co/800x600/1a1a2e/ffffff?text=Hero+Image)
@@ -450,7 +596,7 @@ NEVER respond with only a text summary. The vibespot-modules JSON block is manda
450
596
  - The id should be the moduleName lowercased with spaces replaced by hyphens (e.g. "Pricing Cards" \u2192 id="pricing-cards")
451
597
  - For navigation/menu modules, use anchor links that match these ids: e.g. href="#features"
452
598
  - Always include smooth scrolling behavior in navigation link clicks
453
- - For nav modules, make menu items editable via a repeater group with "label" (text) and "anchor" (text) fields`+(t?`
599
+ - For nav modules, make menu items editable via a repeater group with "label" (text) and "anchor" (text) fields`+(e?`
454
600
 
455
601
  ## When modifying existing modules
456
602
  The current template's modules are listed in page order in the user message. This sequence forms the page narrative.
@@ -460,7 +606,7 @@ The current template's modules are listed in page order in the user message. Thi
460
606
  - **Rearrange**: When the user asks to reorder sections, include a "moduleOrder" array in the vibespot-modules JSON with the new sequence of module names.
461
607
  - **Remove**: When the user asks to remove a section, omit it from the output.
462
608
  - **Preserve**: Always include ALL modules you want to keep (modified + unchanged) in your output. Modules omitted from the output will be removed from the page.
463
- - **Design consistency**: Match the existing theme's design language \u2014 reuse the same CSS custom properties, class naming prefix, spacing scale, and typography.`:"")}function Dn(e,t,n=!1,s,o){let i=`You are vibeSpot, an AI that builds HubSpot CMS landing pages from natural language descriptions.
609
+ - **Design consistency**: Match the existing theme's design language \u2014 reuse the same CSS custom properties, class naming prefix, spacing scale, and typography.`:"")}function ss(t,e,n=!1,s,o){let i=`You are vibeSpot, an AI that builds HubSpot CMS landing pages from natural language descriptions.
464
610
 
465
611
  ## Your Role
466
612
  You generate native HubSpot CMS modules directly from user descriptions. Every module you create is immediately compatible with HubSpot's drag-and-drop page editor.
@@ -502,8 +648,8 @@ NEVER respond with only a text summary. The vibespot-modules JSON block is manda
502
648
  - NEVER use "name": "name" (reserved) \u2014 use "item_name" instead
503
649
  - NEVER put literal \\n newline sequences in field default values \u2014 use plain text without line breaks
504
650
  - Wrap style fields in a "styles" group with "tab": "STYLE"
505
- - All CSS classes must use a unique prefix "${t}-" to avoid theme conflicts
506
- - Use BEM naming: ${t}-module__element--modifier
651
+ - All CSS classes must use a unique prefix "${e}-" to avoid theme conflicts
652
+ - Use BEM naming: ${e}-module__element--modifier
507
653
  - metaJson must include: host_template_types: ["PAGE"], is_available_for_new_content: true
508
654
  - For repeater groups, use "occurrence": { "min": 0, "max": 100 } and iterate with {% for %}
509
655
  - Color fields: type "color", default { "color": "#hex", "opacity": 100 }
@@ -512,9 +658,9 @@ NEVER respond with only a text summary. The vibespot-modules JSON block is manda
512
658
 
513
659
  ## Images & Media
514
660
  - Users can upload images that get placed in the theme's assets/ folder automatically
515
- - When the user uploads an image and wants it on the page, reference it with: {{ get_asset_url("${t}/assets/filename.ext") }}
516
- - IMPORTANT: get_asset_url() paths must include the theme name prefix "${t}/" because HubSpot resolves from the Design Manager root
517
- - For background images with uploaded assets: style="background-image: url('{{ get_asset_url(\\"${t}/assets/filename.ext\\") }}')"
661
+ - When the user uploads an image and wants it on the page, reference it with: {{ get_asset_url("${e}/assets/filename.ext") }}
662
+ - IMPORTANT: get_asset_url() paths must include the theme name prefix "${e}/" because HubSpot resolves from the Design Manager root
663
+ - For background images with uploaded assets: style="background-image: url('{{ get_asset_url(\\"${e}/assets/filename.ext\\") }}')"
518
664
  - For images without an uploaded asset, use image fields (type "image") with placehold.co defaults
519
665
  - ALWAYS use image fields (type "image") so users can swap images in the page editor
520
666
  - Use placehold.co URLs as defaults so the preview looks complete (e.g. https://placehold.co/800x600/1a1a2e/ffffff?text=Hero+Image)
@@ -539,7 +685,7 @@ The current template's modules are listed in page order in the user message. Thi
539
685
  - **Rearrange**: When the user asks to reorder sections, include a "moduleOrder" array in the vibespot-modules JSON with the new sequence of module names.
540
686
  - **Remove**: When the user asks to remove a section, omit it from the output.
541
687
  - **Preserve**: Always include ALL modules you want to keep (modified + unchanged) in your output. Modules omitted from the output will be removed from the page.
542
- - **Design consistency**: Match the existing theme's design language \u2014 reuse the same CSS custom properties, class naming prefix, spacing scale, and typography.`,r=s?ti(s):"",a=r?`
688
+ - **Design consistency**: Match the existing theme's design language \u2014 reuse the same CSS custom properties, class naming prefix, spacing scale, and typography.`,r=s?Ti(s):"",a=r?`
543
689
 
544
690
  ## Page Type Context
545
691
  ${r}`:"",l="";if(o?.styleguide&&(l+=`
@@ -548,16 +694,16 @@ ${r}`:"",l="";if(o?.styleguide&&(l+=`
548
694
  ${o.styleguide}`),o?.brandvoice&&(l+=`
549
695
 
550
696
  ## Brand Voice
551
- ${o.brandvoice}`),o?.humanify!==!1){let d=ei();d&&(l+=`
697
+ ${o.brandvoice}`),o?.humanify!==!1){let d=ki();d&&(l+=`
552
698
 
553
699
  ## Anti-AI Copy Rules (Humanify)
554
700
  ${d}`)}let c="\n\n## REMINDER \u2014 Output Format (CRITICAL)\nYour response MUST contain a ```vibespot-modules code block with the full JSON. Without this block, no modules will be created. Do NOT respond with only text, tables, or descriptions. The JSON block is mandatory.";return n?i+a+l+`
555
701
 
556
702
  ## HubSpot CMS Rules
557
- ${He()}
703
+ ${je()}
558
704
 
559
705
  ## Conversion Guide Reference
560
- ${e}`+c:i+a+l+`
706
+ ${t}`+c:i+a+l+`
561
707
 
562
708
  ## Design Quality
563
709
  - Use modern, clean design with proper spacing and typography
@@ -582,140 +728,173 @@ When using scroll-animate classes (opacity: 0 \u2192 visible), you MUST include
582
728
  This makes elements appear after 3 seconds if JS never adds the .visible class. Once JS runs normally and adds .visible, the animation is cancelled.
583
729
 
584
730
  ## Design Guide
585
- ${Zo()}
731
+ ${Un()}
586
732
 
587
733
  ## Content & Copywriting Guide
588
- ${Qo()}
734
+ ${Ci()}
589
735
 
590
736
  ## HubSpot CMS Rules
591
- ${He()}
737
+ ${je()}
592
738
 
593
739
  ## Conversion Guide Reference
594
- ${e}`+c}function Jn(){let e=C(),t=[],n=e.modules,s=n.length;if(s>0){t.push(`
740
+ ${t}`+c}function os(){let t=C(),e=[],n=t.modules,s=n.length;if(s>0){e.push(`
595
741
 
596
742
  ## Page Narrative (module sequence)
597
- `),t.push(`This template has ${s} module${s===1?"":"s"} in this order:
598
- `);for(let a=0;a<s;a++)t.push(`${a+1}. ${n[a].moduleName}
599
- `);t.push(`
743
+ `),e.push(`This template has ${s} module${s===1?"":"s"} in this order:
744
+ `);for(let a=0;a<s;a++)e.push(`${a+1}. ${n[a].moduleName}
745
+ `);e.push(`
600
746
  When the user asks to modify this page, decide whether to MODIFY existing modules, ADD new ones at the right narrative position, REARRANGE the sequence, or REMOVE sections. Always include ALL modules you want to keep in your output.
601
- `),t.push(`
747
+ `),e.push(`
602
748
  ## Current Module State
603
- `);for(let a=0;a<s;a++){let l=n[a];t.push(`
749
+ `);for(let a=0;a<s;a++){let l=n[a];e.push(`
604
750
  ### ${a+1}/${s}: ${l.moduleName}.module
605
- `),t.push(`**fields.json:**
751
+ `),e.push(`**fields.json:**
606
752
  \`\`\`json
607
753
  ${l.fieldsJson}
608
754
  \`\`\`
609
- `),t.push(`**module.html:**
755
+ `),e.push(`**module.html:**
610
756
  \`\`\`html
611
757
  ${l.moduleHtml}
612
758
  \`\`\`
613
- `),t.push(`**module.css:**
759
+ `),e.push(`**module.css:**
614
760
  \`\`\`css
615
761
  ${l.moduleCss}
616
762
  \`\`\`
617
- `),l.moduleJs&&t.push(`**module.js:**
763
+ `),l.moduleJs&&e.push(`**module.js:**
618
764
  \`\`\`js
619
765
  ${l.moduleJs}
620
766
  \`\`\`
621
- `)}e.sharedCss&&t.push(`
767
+ `)}t.sharedCss&&e.push(`
622
768
  ### Shared CSS
623
769
  \`\`\`css
624
- ${e.sharedCss}
770
+ ${t.sharedCss}
625
771
  \`\`\`
626
- `),e.sharedJs&&t.push(`
772
+ `),t.sharedJs&&e.push(`
627
773
  ### Shared JS
628
774
  \`\`\`js
629
- ${e.sharedJs}
775
+ ${t.sharedJs}
630
776
  \`\`\`
631
- `)}let o=ft(),i=new Set(e.modules.map(a=>a.moduleName)),r=o.filter(a=>!i.has(a.module.moduleName));if(r.length>0){t.push(`
777
+ `)}let o=At(),i=new Set(t.modules.map(a=>a.moduleName)),r=o.filter(a=>!i.has(a.module.moduleName));if(r.length>0){e.push(`
632
778
 
633
779
  ## Available modules in this theme (reusable)
634
- `);for(let a of r)t.push(`- ${a.module.moduleName} (used in: ${a.usedIn.join(", ")})
635
- `);t.push(`
780
+ `);for(let a of r)e.push(`- ${a.module.moduleName} (used in: ${a.usedIn.join(", ")})
781
+ `);e.push(`
636
782
  The user can ask to reuse any of these modules by name.
637
- `)}return t.join("")}function Ti(e,t){let n=C(),s=n.messages.slice(-20);s.length>0&&s[s.length-1].role==="user"&&s[s.length-1].content===e&&(s=s.slice(0,-1));let o=s.map(d=>({role:d.role,content:d.content})),i=Jn(),r="";if(n.assets?.length){let d=n.assets.filter(u=>u.type==="image"&&u.usage==="asset");d.length>0&&(r=`
783
+ `)}return e.join("")}function qi(t,e){let n=C(),s=n.messages.slice(-20);s.length>0&&s[s.length-1].role==="user"&&s[s.length-1].content===t&&(s=s.slice(0,-1));let o=s.map(d=>({role:d.role,content:d.content})),i=os(),r="";if(n.assets?.length){let d=n.assets.filter(u=>u.type==="image"&&u.usage==="asset");d.length>0&&(r=`
638
784
 
639
785
  ## Available Theme Assets
640
786
  These images are in the theme's assets/ folder. Reference them with get_asset_url("${n.themeName}/assets/filename"):
641
787
  ${d.map(u=>`- ${u.filename} (${u.originalName}) \u2192 get_asset_url("${n.themeName}/assets/${u.filename}")`).join(`
642
- `)}`)}let a=e;i&&(a+=`
788
+ `)}`)}let a=t;i&&(a+=`
643
789
 
644
790
  ---
645
- ${i}`),r&&(a+=r),a+="\n\n---\nRemember: respond with a ```vibespot-modules JSON block containing ALL modules. No text-only responses.";let l=t&&t.length>0;if(l)for(let d of t)d.type==="document"&&d.extractedText&&(a+=`
791
+ ${i}`),r&&(a+=r),a+="\n\n---\nRemember: respond with a ```vibespot-modules JSON block containing ALL modules. No text-only responses.";let l=e&&e.length>0;if(l)for(let d of e)d.type==="document"&&d.extractedText&&(a+=`
646
792
 
647
793
  ---
648
794
  [Attached document: ${d.originalName}]
649
795
  ${d.extractedText}`),d.type==="image"&&d.usage==="asset"&&d.assetPath&&(a+=`
650
796
 
651
- [Uploaded image: ${d.originalName} \u2192 available as get_asset_url("${d.assetPath}")]`);let c=l?t.filter(d=>d.type==="image"&&d.base64):[];if(c.length>0){let d=[];for(let u of c)d.push({type:"image",source:{type:"base64",media_type:u.mimeType,data:u.base64}});d.push({type:"text",text:a}),o.push({role:"user",content:d})}else o.push({role:"user",content:a});return o}var xl=G(()=>{"use strict";g();ut();me()});import{spawn as vl}from"child_process";async function wl(){return $i||($i=(await import("@anthropic-ai/sdk")).default),$i}function Cl(e){if(!e?.length)return"";let t=[];for(let n of e)n.type==="image"&&n.usage==="asset"&&n.assetPath&&t.push(`
652
- [Uploaded image: ${n.originalName} \u2192 use get_asset_url("${n.assetPath}")]`),n.type==="document"&&n.extractedText&&t.push(`
797
+ [Uploaded image: ${d.originalName} \u2192 available as get_asset_url("${d.assetPath}")]`);let c=l?e.filter(d=>d.type==="image"&&d.base64):[];if(c.length>0){let d=[];for(let u of c)d.push({type:"image",source:{type:"base64",media_type:u.mimeType,data:u.base64}});d.push({type:"text",text:a}),o.push({role:"user",content:d})}else o.push({role:"user",content:a});return o}var lc=R(()=>{"use strict";y();Ue();we()});import{spawn as cc}from"child_process";async function dc(){return Xi||(Xi=(await import("@anthropic-ai/sdk")).default),Xi}function uc(t){if(!t?.length)return"";let e=[];for(let n of t)n.type==="image"&&n.usage==="asset"&&n.assetPath&&e.push(`
798
+ [Uploaded image: ${n.originalName} \u2192 use get_asset_url("${n.assetPath}")]`),n.type==="document"&&n.extractedText&&e.push(`
653
799
 
654
800
  ---
655
801
  [Attached document: ${n.originalName}]
656
- ${n.extractedText}`);return t.join("")}async function kl(e,t,n,s,o,i,r){for(let a=0;;a++)try{let l="",c=0,d=i||(()=>{});d(ke[0]);let u=setInterval(()=>{c++,d(ke[Math.min(c,ke.length-1)])},6e3);try{let m=e.messages.stream({model:s,max_tokens:48e3,system:t,messages:n});for await(let f of m)if(f.type==="content_block_delta"&&f.delta.type==="text_delta"){let y=f.delta.text;l+=y,o(y)}}finally{clearInterval(u)}r&&r(l);return}catch(l){let c=l.status,d=l.error?.type;if(!(c===429||d==="rate_limit_error"||l instanceof Error&&l.message.includes("429"))||a>=Ii.length)throw l;let m=Ii[a];E.warn("ai-engine",`Rate limited (429), attempt ${a+1}/${Ii.length} \u2014 waiting ${m}s`),i&&i(`Rate limited by Anthropic API \u2014 retrying in ${m}s...`),await new Promise(f=>setTimeout(f,m*1e3)),i&&i("Retrying...")}}function Al(e,t,n){let s=ge(),i=C().modules.length>0,r=Ti(e,n),a=rn(),l=Sl(s,t,i,a.pageType,a.brandAssets);return{messages:r,systemBlocks:l,conversionGuide:s,editMode:i}}async function Tl(e,t,n,s,o,i,r,a){let l=await wl(),c=new l({apiKey:t}),{messages:d,systemBlocks:u}=Al(e,n,a);E.info("anthropic","API call",{model:s,systemBlockCount:u.length,cachedBlocks:u.filter(m=>m.cache_control).length,messageCount:d.length}),await kl(c,u,d,s,o,i,r)}async function $l(e,t,n,s,o,i,r){let a=await Bo();if(!a)throw new Error("Claude OAuth session expired. Please re-authenticate in Settings.");let l=await wl(),c=new l({authToken:a,defaultHeaders:hn}),{messages:d,systemBlocks:u}=Al(e,t,r),m=[{type:"text",text:Kt},...u];E.info("anthropic-oauth","API call",{model:n,systemBlockCount:m.length,cachedBlocks:m.filter(f=>f.cache_control).length,messageCount:d.length}),await kl(c,m,d,n,s,o,i)}async function Il(e,t,n,s,o,i,r,a){let l=ge(),c=C().modules.length>0,d=Ti(e,a),u=rn(),m=d.map(O=>typeof O.content=="string"?O:{role:O.role,content:O.content.map(F=>F.type==="text"?{type:"text",text:F.text}:{type:"image_url",image_url:{url:`data:${F.source.media_type};base64,${F.source.data}`}})}),f=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify({model:s,max_tokens:48e3,stream:!0,messages:[{role:"system",content:Dn(l,n,c,u.pageType,u.brandAssets)},...m]})});if(!f.ok){let O=await f.text();throw new Error(`OpenAI API error (${f.status}): ${O}`)}let y=0,h=i||(()=>{});h(ke[0]);let S=setInterval(()=>{y++,h(ke[Math.min(y,ke.length-1)])},6e3),x="",w=f.body.getReader(),v=new TextDecoder,N="";try{for(;;){let{done:O,value:F}=await w.read();if(O)break;N+=v.decode(F,{stream:!0});let U=N.split(`
657
- `);N=U.pop()||"";for(let q of U){if(!q.startsWith("data: "))continue;let _=q.slice(6).trim();if(_==="[DONE]")break;try{let k=JSON.parse(_).choices?.[0]?.delta?.content;k&&(x+=k,o(k))}catch{}}}}finally{clearInterval(S)}r&&r(x)}async function El(e,t,n,s,o,i,r){let a=ge(),l=C(),c=l.modules.length>0,d=Jn(),u=rn(),m=[];for(let _ of l.messages.slice(-20))m.push({role:_.role==="assistant"?"model":"user",parts:[{text:_.content}]});let f=d?`${e}
802
+ ${n.extractedText}`);return e.join("")}async function mc(t,e,n,s,o,i,r){for(let a=0;;a++)try{let l="",c=0,d=i||(()=>{});d(Re[0]);let u=setInterval(()=>{c++,d(Re[Math.min(c,Re.length-1)])},6e3);try{let m=t.messages.stream({model:s,max_tokens:48e3,system:e,messages:n});for await(let g of m)if(g.type==="content_block_delta"&&g.delta.type==="text_delta"){let h=g.delta.text;l+=h,o(h)}}finally{clearInterval(u)}r&&r(l);return}catch(l){let c=l.status,d=l.error?.type;if(!(c===429||d==="rate_limit_error"||l instanceof Error&&l.message.includes("429"))||a>=Zi.length)throw l;let m=Zi[a];E.warn("ai-engine",`Rate limited (429), attempt ${a+1}/${Zi.length} \u2014 waiting ${m}s`),i&&i(`Rate limited by Anthropic API \u2014 retrying in ${m}s...`),await new Promise(g=>setTimeout(g,m*1e3)),i&&i("Retrying...")}}function pc(t,e,n){let s=fe(),i=C().modules.length>0,r=qi(t,n),a=bn(),l=ac(s,e,i,a.pageType,a.brandAssets);return{messages:r,systemBlocks:l,conversionGuide:s,editMode:i}}async function gc(t,e,n,s,o,i,r,a){let l=await dc(),c=new l({apiKey:e}),{messages:d,systemBlocks:u}=pc(t,n,a);E.info("anthropic","API call",{model:s,systemBlockCount:u.length,cachedBlocks:u.filter(m=>m.cache_control).length,messageCount:d.length}),await mc(c,u,d,s,o,i,r)}async function fc(t,e,n,s,o,i,r){let a=await pi();if(!a)throw new Error("Claude OAuth session expired. Please re-authenticate in Settings.");let l=await dc(),c=new l({authToken:a,defaultHeaders:_n}),{messages:d,systemBlocks:u}=pc(t,e,r),m=[{type:"text",text:rn},...u];E.info("anthropic-oauth","API call",{model:n,systemBlockCount:m.length,cachedBlocks:m.filter(g=>g.cache_control).length,messageCount:d.length}),await mc(c,m,d,n,s,o,i)}async function hc(t,e,n,s,o,i,r,a){let l=fe(),c=C().modules.length>0,d=qi(t,a),u=bn(),m=d.map(F=>typeof F.content=="string"?F:{role:F.role,content:F.content.map(H=>H.type==="text"?{type:"text",text:H.text}:{type:"image_url",image_url:{url:`data:${H.source.media_type};base64,${H.source.data}`}})}),g=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({model:s,max_tokens:48e3,stream:!0,messages:[{role:"system",content:ss(l,n,c,u.pageType,u.brandAssets)},...m]})});if(!g.ok){let F=await g.text();throw new Error(`OpenAI API error (${g.status}): ${F}`)}let h=0,f=i||(()=>{});f(Re[0]);let b=setInterval(()=>{h++,f(Re[Math.min(h,Re.length-1)])},6e3),S="",x=g.body.getReader(),w=new TextDecoder,P="";try{for(;;){let{done:F,value:H}=await x.read();if(F)break;P+=w.decode(H,{stream:!0});let L=P.split(`
803
+ `);P=L.pop()||"";for(let V of L){if(!V.startsWith("data: "))continue;let B=V.slice(6).trim();if(B==="[DONE]")break;try{let T=JSON.parse(B).choices?.[0]?.delta?.content;T&&(S+=T,o(T))}catch{}}}}finally{clearInterval(b)}r&&r(S)}async function yc(t,e,n,s,o,i,r){let a=fe(),l=C(),c=l.modules.length>0,d=os(),u=bn(),m=[];for(let B of l.messages.slice(-20))m.push({role:B.role==="assistant"?"model":"user",parts:[{text:B.content}]});let g=d?`${t}
658
804
 
659
805
  ---
660
- ${d}`:e;if(r?.length)for(let _ of r)_.type==="document"&&_.extractedText&&(f+=`
806
+ ${d}`:t;if(r?.length)for(let B of r)B.type==="document"&&B.extractedText&&(g+=`
661
807
 
662
808
  ---
663
- [Attached document: ${_.originalName}]
664
- ${_.extractedText}`),_.type==="image"&&_.usage==="asset"&&_.assetPath&&(f+=`
809
+ [Attached document: ${B.originalName}]
810
+ ${B.extractedText}`),B.type==="image"&&B.usage==="asset"&&B.assetPath&&(g+=`
665
811
 
666
- [Uploaded image: ${_.originalName} \u2192 available as get_asset_url("${_.assetPath}")]`);let y=[];if(r?.length)for(let _ of r)_.type==="image"&&_.base64&&y.push({inlineData:{mimeType:_.mimeType,data:_.base64}});y.push({text:f}),m.push({role:"user",parts:y});let S=`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse&key=${t}`,x=await fetch(S,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({systemInstruction:{parts:[{text:Dn(a,n,c,u.pageType,u.brandAssets)}]},contents:m,generationConfig:{maxOutputTokens:48e3}})});if(!x.ok){let _=await x.text();throw new Error(`Gemini API error (${x.status}): ${_}`)}let w=0,v=o||(()=>{});v(ke[0]);let N=setInterval(()=>{w++,v(ke[Math.min(w,ke.length-1)])},6e3),O="",F=x.body.getReader(),U=new TextDecoder,q="";try{for(;;){let{done:_,value:j}=await F.read();if(_)break;q+=U.decode(j,{stream:!0});let k=q.split(`
667
- `);q=k.pop()||"";for(let M of k){if(!M.startsWith("data: "))continue;let te=M.slice(6).trim();try{let It=JSON.parse(te).candidates?.[0]?.content?.parts?.[0]?.text;It&&(O+=It,s(It))}catch{}}}}finally{clearInterval(N)}i&&i(O)}function Ei(e,t,n={},s){return new Promise((o,i)=>{let r={...process.env};delete r.CLAUDECODE;let a=vl("claude",e,{stdio:["pipe","pipe","pipe"],env:r}),l="",c="",d="",u=!1,m=null,f=v=>{u||(u=!0,v())},y=v=>{try{if(v.type==="assistant"&&v.message?.content){for(let N of v.message.content)if(N.type==="text"&&typeof N.text=="string"){let O=N.text;l+=O,n.onChunk&&n.onChunk(O)}else if(N.type==="tool_use"){let O=N;O.name&&n.onToolUse&&n.onToolUse(O.name,O.input)}}v.type==="result"&&(m=v,!l&&typeof v.result=="string"&&(l=v.result,n.onChunk&&n.onChunk(v.result))),n.onEvent&&n.onEvent(v)}catch{}};a.stdout.on("data",v=>{d+=v.toString();let N;for(;(N=d.indexOf(`
668
- `))>=0;){let O=d.slice(0,N).trim();if(d=d.slice(N+1),!!O)try{y(JSON.parse(O))}catch{}}}),a.stderr.on("data",v=>{c+=v.toString()}),a.on("error",v=>f(()=>i(new Error(`claude failed to start: ${v.message}`)))),a.on("close",v=>{if(d.trim()){try{y(JSON.parse(d.trim()))}catch{}d=""}f(()=>{v!==0||m&&m.is_error?i(new Error(`claude exited with code ${v}.
812
+ [Uploaded image: ${B.originalName} \u2192 available as get_asset_url("${B.assetPath}")]`);let h=[];if(r?.length)for(let B of r)B.type==="image"&&B.base64&&h.push({inlineData:{mimeType:B.mimeType,data:B.base64}});h.push({text:g}),m.push({role:"user",parts:h});let b=`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse&key=${e}`,S=await fetch(b,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({systemInstruction:{parts:[{text:ss(a,n,c,u.pageType,u.brandAssets)}]},contents:m,generationConfig:{maxOutputTokens:48e3}})});if(!S.ok){let B=await S.text();throw new Error(`Gemini API error (${S.status}): ${B}`)}let x=0,w=o||(()=>{});w(Re[0]);let P=setInterval(()=>{x++,w(Re[Math.min(x,Re.length-1)])},6e3),F="",H=S.body.getReader(),L=new TextDecoder,V="";try{for(;;){let{done:B,value:N}=await H.read();if(B)break;V+=L.decode(N,{stream:!0});let T=V.split(`
813
+ `);V=T.pop()||"";for(let I of T){if(!I.startsWith("data: "))continue;let k=I.slice(6).trim();try{let oe=JSON.parse(k).candidates?.[0]?.content?.parts?.[0]?.text;oe&&(F+=oe,s(oe))}catch{}}}}finally{clearInterval(P)}i&&i(F)}function Qi(t,e,n={},s){return new Promise((o,i)=>{let r={...process.env};delete r.CLAUDECODE;let a=cc("claude",t,{stdio:["pipe","pipe","pipe"],env:r}),l="",c="",d="",u=!1,m=null,g=w=>{u||(u=!0,w())},h=w=>{try{if(w.type==="assistant"&&w.message?.content){for(let P of w.message.content)if(P.type==="text"&&typeof P.text=="string"){let F=P.text;l+=F,n.onChunk&&n.onChunk(F)}else if(P.type==="tool_use"){let F=P;F.name&&n.onToolUse&&n.onToolUse(F.name,F.input)}}w.type==="result"&&(m=w,!l&&typeof w.result=="string"&&(l=w.result,n.onChunk&&n.onChunk(w.result))),n.onEvent&&n.onEvent(w)}catch{}};a.stdout.on("data",w=>{d+=w.toString();let P;for(;(P=d.indexOf(`
814
+ `))>=0;){let F=d.slice(0,P).trim();if(d=d.slice(P+1),!!F)try{h(JSON.parse(F))}catch{}}}),a.stderr.on("data",w=>{c+=w.toString()}),a.on("error",w=>g(()=>i(new Error(`claude failed to start: ${w.message}`)))),a.on("close",w=>{if(d.trim()){try{h(JSON.parse(d.trim()))}catch{}d=""}g(()=>{w!==0||m&&m.is_error?i(new Error(`claude exited with code ${w}.
669
815
  `+(c?`Stderr: ${c.slice(0,500)}
670
- `:"")+(l?`Output: ${l.slice(0,500)}`:"No output"))):o(l)})}),a.stdin.on("error",()=>{}),a.stdin.write(t)?a.stdin.end():a.stdin.once("drain",()=>a.stdin.end());let S=s||6e5,x=Math.round(S/6e4),w=setTimeout(()=>{a.kill(),f(()=>i(new Error(`claude (stream-json) timed out after ${x} minutes.
816
+ `:"")+(l?`Output: ${l.slice(0,500)}`:"No output"))):o(l)})}),a.stdin.on("error",()=>{}),a.stdin.write(e)?a.stdin.end():a.stdin.once("drain",()=>a.stdin.end());let b=s||6e5,S=Math.round(b/6e4),x=setTimeout(()=>{a.kill(),g(()=>i(new Error(`claude (stream-json) timed out after ${S} minutes.
671
817
  `+(c?`Stderr: ${c.slice(0,500)}
672
- `:"")+`Partial output (${l.length} chars): ${l.slice(0,500)}`)))},S);a.on("close",()=>clearTimeout(w))})}function Mi(e,t,n,s,o){return new Promise((i,r)=>{let a={...process.env};delete a.CLAUDECODE;let l=vl(e,t,{stdio:["pipe","pipe","pipe"],env:a}),c="",d="",u=!1,m=x=>{u||(u=!0,x())};l.stdout.on("data",x=>{let w=x.toString();c+=w,s&&s(w)}),l.stderr.on("data",x=>{d+=x.toString()}),l.on("error",x=>m(()=>r(new Error(`${e} failed to start: ${x.message}`)))),l.on("close",x=>{m(()=>{x!==0?r(new Error(`${e} exited with code ${x}.
818
+ `:"")+`Partial output (${l.length} chars): ${l.slice(0,500)}`)))},b);a.on("close",()=>clearTimeout(x))})}function er(t,e,n,s,o){return new Promise((i,r)=>{let a={...process.env};delete a.CLAUDECODE;let l=cc(t,e,{stdio:["pipe","pipe","pipe"],env:a}),c="",d="",u=!1,m=S=>{u||(u=!0,S())};l.stdout.on("data",S=>{let x=S.toString();c+=x,s&&s(x)}),l.stderr.on("data",S=>{d+=S.toString()}),l.on("error",S=>m(()=>r(new Error(`${t} failed to start: ${S.message}`)))),l.on("close",S=>{m(()=>{S!==0?r(new Error(`${t} exited with code ${S}.
673
819
  `+(d?`Stderr: ${d.slice(0,500)}
674
- `:"")+(c?`Output: ${c.slice(0,500)}`:"No output"))):i(c)})}),l.stdin.on("error",()=>{}),l.stdin.write(n)?l.stdin.end():l.stdin.once("drain",()=>l.stdin.end());let y=o||6e5,h=Math.round(y/6e4),S=setTimeout(()=>{l.kill(),m(()=>r(new Error(`${e} timed out after ${h} minutes.
820
+ `:"")+(c?`Output: ${c.slice(0,500)}`:"No output"))):i(c)})}),l.stdin.on("error",()=>{}),l.stdin.write(n)?l.stdin.end():l.stdin.once("drain",()=>l.stdin.end());let h=o||6e5,f=Math.round(h/6e4),b=setTimeout(()=>{l.kill(),m(()=>r(new Error(`${t} timed out after ${f} minutes.
675
821
  `+(d?`Stderr: ${d.slice(0,500)}
676
- `:"")+`Partial output (${c.length} chars): ${c.slice(0,500)}`)))},y);l.on("close",()=>clearTimeout(S))})}async function Ml(e,t,n,s,o,i){let r=ge(),a=R(),l=C().modules.length>0,c=rn(),d=Dn(r,t,l,c.pageType,c.brandAssets);d+=`
822
+ `:"")+`Partial output (${c.length} chars): ${c.slice(0,500)}`)))},h);l.on("close",()=>clearTimeout(b))})}async function bc(t,e,n,s,o,i){let r=fe(),a=O(),l=C().modules.length>0,c=bn(),d=ss(r,e,l,c.pageType,c.brandAssets);d+=`
677
823
 
678
824
  ## User Request
679
- `+e,d+=Jn(),d+=Cl(i),d+="\n\n---\nRemember: respond with a ```vibespot-modules JSON block containing ALL modules. No text-only responses.";let u=["--print"];a.claudeCodeModel&&u.push("--model",a.claudeCodeModel),a.webSearch&&u.push("--allowedTools=WebSearch"),u.push("--output-format","stream-json","--include-partial-messages","--verbose");let m=0,f=s||(()=>{});f(ke[0]);let y=setInterval(()=>{m++;let h=ke[Math.min(m,ke.length-1)];f(h)},6e3);try{let h=await Ei(u,d,{onChunk:S=>n(S),onToolUse:(S,x)=>{f(tf(S,x))}});o&&o(h)}finally{clearInterval(y)}}function tf(e,t){let n=t||{};switch(e){case"WebSearch":case"web_search":return`Searching: "${String(n.query||"")}"`;case"WebFetch":return`Fetching: ${String(n.url||"")}`;case"Read":return`Reading ${String(n.file_path||n.path||"file")}`;case"Edit":case"Write":return`Editing ${String(n.file_path||n.path||"file")}`;case"Bash":return`Running: ${String(n.command||"").slice(0,60)}`;case"Grep":return`Searching for "${String(n.pattern||"")}"`;case"Glob":return`Globbing ${String(n.pattern||"")}`;default:return`Using ${e}`}}async function Ri(e,t,n,s,o,i,r){let a=ge(),l=C().modules.length>0,c=rn(),d=Dn(a,n,l,c.pageType,c.brandAssets);d+=`
825
+ `+t,d+=os(),d+=uc(i),d+="\n\n---\nRemember: respond with a ```vibespot-modules JSON block containing ALL modules. No text-only responses.";let u=["--print"];a.claudeCodeModel&&u.push("--model",a.claudeCodeModel),a.webSearch&&u.push("--allowedTools=WebSearch"),u.push("--output-format","stream-json","--include-partial-messages","--verbose");let m=0,g=s||(()=>{});g(Re[0]);let h=setInterval(()=>{m++;let f=Re[Math.min(m,Re.length-1)];g(f)},6e3);try{let f=await Qi(u,d,{onChunk:b=>n(b),onToolUse:(b,S)=>{g(If(b,S))}});o&&o(f)}finally{clearInterval(h)}}function If(t,e){let n=e||{};switch(t){case"WebSearch":case"web_search":return`Searching: "${String(n.query||"")}"`;case"WebFetch":return`Fetching: ${String(n.url||"")}`;case"Read":return`Reading ${String(n.file_path||n.path||"file")}`;case"Edit":case"Write":return`Editing ${String(n.file_path||n.path||"file")}`;case"Bash":return`Running: ${String(n.command||"").slice(0,60)}`;case"Grep":return`Searching for "${String(n.pattern||"")}"`;case"Glob":return`Globbing ${String(n.pattern||"")}`;default:return`Using ${t}`}}async function tr(t,e,n,s,o,i,r){let a=fe(),l=C().modules.length>0,c=bn(),d=ss(a,n,l,c.pageType,c.brandAssets);d+=`
680
826
 
681
827
  ## User Request
682
- `+t,d+=Jn(),d+=Cl(r),d+="\n\n---\nRemember: respond with a ```vibespot-modules JSON block containing ALL modules. No text-only responses.";let u,m;e==="gemini"?(u="gemini",m=[]):(u="codex",m=["exec","--full-auto"]);let f=0,y=o||(()=>{});y(ke[0]);let h=setInterval(()=>{f++;let S=ke[Math.min(f,ke.length-1)];y(S)},6e3);try{let S=await Mi(u,m,d,x=>{s(x)});i&&i(S)}finally{clearInterval(h)}}var $i,ke,Ii,_i=G(()=>{"use strict";g();ut();X();lt();me();xl();re();$i=null;ke=["Analyzing your request...","Reading the conversion guide...","Planning module structure...","Generating HTML templates...","Writing CSS styles...","Creating field definitions...","Building module metadata...","Assembling theme assets...","Polishing the output...","Almost there \u2014 hang tight..."],Ii=[10,20,40,60,120]});function p(e,t,n){e.writeHead(t,{"Content-Type":"application/json"}),e.end(JSON.stringify(n))}function W(e,t){let n=[];e.on("data",s=>n.push(s)),e.on("end",()=>t(Buffer.concat(n).toString("utf-8")))}function Oe(e,t,n){W(e,s=>{try{n(JSON.parse(s||"{}"))}catch{p(t,400,{error:"Invalid JSON in request body"})}})}var Fe=G(()=>{"use strict";g()});import{createWriteStream as nf,mkdirSync as Rl,existsSync as Pi,readFileSync as Ni}from"fs";import{join as Ft,extname as sf}from"path";import{randomUUID as of}from"crypto";import rf from"busboy";function df(e,t){if(Pl.has(t))return t;let n=e.slice(e.lastIndexOf(".")).toLowerCase();return cf[n]??t}function uf(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_").replace(/_{2,}/g,"_").replace(/^_+|_+$/g,"").toLowerCase()}function mf(e,t){if(!Pi(Ft(e,t)))return t;let n=sf(t),s=t.slice(0,-n.length||void 0),o=1;for(;Pi(Ft(e,`${s}-${o}${n}`));)o++;return`${s}-${o}${n}`}async function pf(e){let t=(await import("pdf-parse")).default,n=Ni(e);return(await t(n)).text}async function ff(e){return(await(await import("mammoth")).extractRawText({path:e})).value}function gf(e){return Ni(e,"utf-8")}function Nl(e,t){let n=C();if(!n){p(t,400,{error:"No active session"});return}if(!(e.headers["content-type"]||"").includes("multipart/form-data")){p(t,400,{error:"Expected multipart/form-data"});return}let o=[],i=[],r=0,a=[],l=rf({headers:e.headers,limits:{fileSize:af,files:10}});l.on("file",(c,d,u)=>{let{filename:m,mimeType:f}=u;r++;let y=df(m,f);if(!Pl.has(y)){i.push(`Unsupported file type: ${m} (${f})`),d.resume();return}let h=_l.has(y),S=uf(m),x=of(),w,v;h?(w=Ft(n.themePath,"assets"),Rl(w,{recursive:!0}),v=mf(w,S)):(w=Ft(n.themePath,".vibespot","uploads"),Rl(w,{recursive:!0}),v=`${x}-${S}`);let N=Ft(w,v),O=nf(N),F=0,U=!1;d.on("data",q=>{F+=q.length}),d.on("limit",()=>{U=!0,i.push(`File too large (>10MB): ${m}`)}),d.pipe(O),a.push(new Promise(q=>{O.on("finish",()=>{if(!U){let _={id:x,filename:v,originalName:m,type:h?"image":"document",usage:h?"asset":"context",mimeType:y,size:F,addedAt:new Date().toISOString()};o.push(_),Ja(_)}q()}),O.on("error",()=>{i.push(`Failed to write: ${m}`),q()})}))}),l.on("finish",async()=>{await Promise.all(a);for(let c of o)if(c.type==="document"){let d=Ft(n.themePath,".vibespot","uploads",c.filename);try{c.mimeType==="application/pdf"?c.extractedText=await pf(d):c.mimeType==="application/vnd.openxmlformats-officedocument.wordprocessingml.document"?c.extractedText=await ff(d):c.extractedText=gf(d),E.info("upload",`Extracted text from ${c.originalName} (${c.extractedText.length} chars)`)}catch(u){E.warn("upload",`Failed to extract text from ${c.originalName}: ${u}`),c.extractedText=`[Could not extract text from ${c.originalName}]`}}if(r===0){p(t,400,{error:"No files uploaded"});return}p(t,200,{files:o.map(c=>({id:c.id,filename:c.filename,originalName:c.originalName,type:c.type,usage:c.usage,size:c.size})),errors:i.length>0?i:void 0})}),l.on("error",c=>{E.error("upload",`Busboy error: ${c}`),p(t,500,{error:"Upload failed"})}),e.pipe(l)}function to(e){let t=C();return t?.assets?e.map(n=>{let s=t.assets.find(i=>i.id===n);if(!s)return null;let o={id:s.id,filename:s.filename,originalName:s.originalName,type:s.type,usage:s.usage,mimeType:s.mimeType};if(s.type==="image"){let i=Ft(t.themePath,"assets",s.filename);Pi(i)&&(o.base64=Ni(i).toString("base64")),o.assetPath=`${t.themeName}/assets/${s.filename}`}else s.type==="document"&&(o.extractedText=s.extractedText);return o}).filter(n=>n!==null):[]}var af,_l,lf,Pl,cf,Oi=G(()=>{"use strict";g();Fe();me();re();af=10*1024*1024,_l=new Set(["image/png","image/jpeg","image/jpg","image/svg+xml","image/webp","image/gif"]),lf=new Set(["application/pdf","application/vnd.openxmlformats-officedocument.wordprocessingml.document","text/markdown","text/plain"]),Pl=new Set([..._l,...lf]),cf={".md":"text/markdown",".txt":"text/plain",".markdown":"text/markdown"}});var Dl={};_e(Dl,{callAgent:()=>Re,callAgentAPI:()=>jl,isAgenticCapable:()=>Hn,isCLIEngine:()=>an,resolveThinkingBudget:()=>Ji});async function no(e,t){for(let n=0;;n++)try{return await e()}catch(s){let o=s.status,i=s.error?.type;if(!(o===429||i==="rate_limit_error"||s instanceof Error&&s.message.includes("429"))||n>=Fi.length)throw s;let a=Fi[n];E.warn("agent-adapter",`Rate limited (429), attempt ${n+1}/${Fi.length} \u2014 waiting ${a}s`),t&&t(`Rate limited \u2014 retrying in ${a}s...`),await new Promise(l=>setTimeout(l,a*1e3)),t&&t("Retrying...")}}function Ln(e){if(e&&typeof e=="object"&&!Array.isArray(e)){let t=e;for(let n of["fieldsJson","metaJson"])t[n]&&typeof t[n]=="object"&&(t[n]=JSON.stringify(t[n]))}return e}async function Ol(){return ji||(ji=(await import("@anthropic-ai/sdk")).default),ji}async function hf(e,t,n,s,o){let i=await Ol(),r=new i({apiKey:e,...s?{defaultHeaders:s}:{}}),a=n.messages,l=n.systemPrompt;if(n.systemBlocks?l=o?[{type:"text",text:o},...n.systemBlocks]:n.systemBlocks:o&&(l=[{type:"text",text:o},{type:"text",text:n.systemPrompt}]),n.structuredOutput){let c={name:n.structuredOutput.name,description:`Return the result as structured JSON matching the ${n.structuredOutput.name} schema.`,input_schema:n.structuredOutput.schema,cache_control:{type:"ephemeral"}};return no(async()=>{let d=await r.messages.create({model:t,max_tokens:n.maxTokens||16e3,system:l,messages:a,tools:[c],tool_choice:{type:"tool",name:n.structuredOutput.name},...n.thinkingBudgetTokens?{thinking:{type:"enabled",budget_tokens:n.thinkingBudgetTokens}}:{}});for(let m of d.content)if(m.type==="tool_use")return{type:"structured",data:Ln(m.input)};return{type:"text",text:d.content.filter(m=>m.type==="text").map(m=>m.text).join("")}},n.onStatus)}return no(async()=>{let c="",d=r.messages.stream({model:t,max_tokens:n.maxTokens||16e3,system:l,messages:a,...n.enableWebSearch?{tools:[{type:"web_search_20250305",name:"web_search"}]}:{},...n.thinkingBudgetTokens?{thinking:{type:"enabled",budget_tokens:n.thinkingBudgetTokens}}:{}});for await(let u of d)u.type==="content_block_delta"&&u.delta.type==="text_delta"&&(c+=u.delta.text,n.onChunk&&n.onChunk(u.delta.text));return{type:"text",text:c}},n.onStatus)}async function yf(e,t,n){let s=await Ol(),o=new s({authToken:e,defaultHeaders:hn}),i=n.messages,r;if(n.systemBlocks?r=[{type:"text",text:Kt},...n.systemBlocks]:r=[{type:"text",text:Kt},{type:"text",text:n.systemPrompt}],n.structuredOutput){let a={name:n.structuredOutput.name,description:`Return the result as structured JSON matching the ${n.structuredOutput.name} schema.`,input_schema:n.structuredOutput.schema,cache_control:{type:"ephemeral"}};return no(async()=>{let l=await o.messages.create({model:t,max_tokens:n.maxTokens||16e3,system:r,messages:i,tools:[a],tool_choice:{type:"tool",name:n.structuredOutput.name},...n.thinkingBudgetTokens?{thinking:{type:"enabled",budget_tokens:n.thinkingBudgetTokens}}:{}});for(let d of l.content)if(d.type==="tool_use")return{type:"structured",data:Ln(d.input)};return{type:"text",text:l.content.filter(d=>d.type==="text").map(d=>d.text).join("")}},n.onStatus)}return no(async()=>{let a="",l=o.messages.stream({model:t,max_tokens:n.maxTokens||16e3,system:r,messages:i,...n.enableWebSearch?{tools:[{type:"web_search_20250305",name:"web_search"}]}:{},...n.thinkingBudgetTokens?{thinking:{type:"enabled",budget_tokens:n.thinkingBudgetTokens}}:{}});for await(let c of l)c.type==="content_block_delta"&&c.delta.type==="text_delta"&&(a+=c.delta.text,n.onChunk&&n.onChunk(c.delta.text));return{type:"text",text:a}},n.onStatus)}function Di(e){let t={...e};if(t.type==="object"&&(t.additionalProperties=!1,t.properties&&typeof t.properties=="object")){let n={};for(let[s,o]of Object.entries(t.properties))n[s]=o&&typeof o=="object"?Di(o):o;t.properties=n}return t.items&&typeof t.items=="object"&&(t.items=Di(t.items)),t}async function bf(e,t,n){let s=[{role:"system",content:n.systemPrompt},...n.messages.map(l=>({role:l.role,content:typeof l.content=="string"?l.content:l.content.map(c=>({type:"text",text:c.text}))}))],o={model:t,max_tokens:n.maxTokens||16e3,messages:s};n.structuredOutput&&(o.response_format={type:"json_schema",json_schema:{name:n.structuredOutput.name,strict:!0,schema:Di(n.structuredOutput.schema)}});let i=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(o)});if(!i.ok){let l=await i.text(),c=i.status;if(c===429){let d=new Error(`OpenAI rate limit: ${l}`);throw d.status=429,d}throw new Error(`OpenAI API error (${c}): ${l}`)}let a=(await i.json()).choices?.[0]?.message?.content||"";if(n.structuredOutput)try{return{type:"structured",data:Ln(JSON.parse(a))}}catch{return E.warn("agent-adapter","OpenAI structured output parse failed, returning raw text"),{type:"text",text:a}}return{type:"text",text:a}}async function Sf(e,t,n){let s=t||"gemini-2.5-flash",o=n.messages.map(d=>({role:d.role==="assistant"?"model":"user",parts:typeof d.content=="string"?[{text:d.content}]:d.content.map(u=>({text:u.text}))})),i={systemInstruction:{parts:[{text:n.systemPrompt}]},contents:o,generationConfig:{maxOutputTokens:n.maxTokens||16e3,...n.structuredOutput?{responseMimeType:"application/json",responseSchema:n.structuredOutput.schema}:{}}},r=`https://generativelanguage.googleapis.com/v1beta/models/${s}:generateContent?key=${e}`,a=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)});if(!a.ok){let d=await a.text(),u=a.status;if(u===429){let m=new Error(`Gemini rate limit: ${d}`);throw m.status=429,m}throw new Error(`Gemini API error (${u}): ${d}`)}let c=(await a.json()).candidates?.[0]?.content?.parts?.[0]?.text||"";if(n.structuredOutput)try{return{type:"structured",data:Ln(JSON.parse(c))}}catch{return E.warn("agent-adapter","Gemini structured output parse failed, returning raw text"),{type:"text",text:c}}return{type:"text",text:c}}function xf(e,t,n){switch(e){case"claude-code":{let s=["--print"];return t&&s.push("--model",t),n?.enableWebSearch&&s.push("--allowedTools=WebSearch"),{bin:"claude",args:s}}case"gemini-cli":{let s=[];return t&&s.push("-m",t),{bin:"gemini",args:s}}case"codex-cli":{let s=["exec","--full-auto"];return t&&s.push("-m",t),{bin:"codex",args:s}}default:throw new Error(`Not a CLI engine: ${e}`)}}function vf(e){let t=[e.systemPrompt];for(let n of e.messages){let s=n.role==="user"?"User":"Assistant",o=typeof n.content=="string"?n.content:n.content.map(i=>i.text).join(`
683
- `);t.push(`
828
+ `+e,d+=os(),d+=uc(r),d+="\n\n---\nRemember: respond with a ```vibespot-modules JSON block containing ALL modules. No text-only responses.";let u,m;t==="gemini"?(u="gemini",m=[]):(u="codex",m=["exec","--full-auto"]);let g=0,h=o||(()=>{});h(Re[0]);let f=setInterval(()=>{g++;let b=Re[Math.min(g,Re.length-1)];h(b)},6e3);try{let b=await er(u,m,d,S=>{s(S)});i&&i(b)}finally{clearInterval(f)}}var Xi,Re,Zi,nr=R(()=>{"use strict";y();Ue();Q();xt();we();lc();de();Xi=null;Re=["Analyzing your request...","Reading the conversion guide...","Planning module structure...","Generating HTML templates...","Writing CSS styles...","Creating field definitions...","Building module metadata...","Assembling theme assets...","Polishing the output...","Almost there \u2014 hang tight..."],Zi=[10,20,40,60,120]});function p(t,e,n){t.writeHead(e,{"Content-Type":"application/json"}),t.end(JSON.stringify(n))}function W(t,e){let n=[];t.on("data",s=>n.push(s)),t.on("end",()=>e(Buffer.concat(n).toString("utf-8")))}function Ve(t,e,n){W(t,s=>{try{n(JSON.parse(s||"{}"))}catch{p(e,400,{error:"Invalid JSON in request body"})}})}var ze=R(()=>{"use strict";y()});import{createWriteStream as Pf,mkdirSync as Sc,existsSync as sr,readFileSync as or}from"fs";import{join as Vt,extname as Rf}from"path";import{randomUUID as Nf}from"crypto";import Of from"busboy";function Lf(t,e){if(vc.has(e))return e;let n=t.slice(t.lastIndexOf(".")).toLowerCase();return Df[n]??e}function Jf(t){return t.replace(/[^a-zA-Z0-9._-]/g,"_").replace(/_{2,}/g,"_").replace(/^_+|_+$/g,"").toLowerCase()}function Bf(t,e){if(!sr(Vt(t,e)))return e;let n=Rf(e),s=e.slice(0,-n.length||void 0),o=1;for(;sr(Vt(t,`${s}-${o}${n}`));)o++;return`${s}-${o}${n}`}async function Hf(t){let e=(await import("pdf-parse")).default,n=or(t);return(await e(n)).text}async function Uf(t){return(await(await import("mammoth")).extractRawText({path:t})).value}function Gf(t){return or(t,"utf-8")}function wc(t,e){let n=C();if(!n){p(e,400,{error:"No active session"});return}if(!(t.headers["content-type"]||"").includes("multipart/form-data")){p(e,400,{error:"Expected multipart/form-data"});return}let o=[],i=[],r=0,a=[],l=Of({headers:t.headers,limits:{fileSize:Ff,files:10}});l.on("file",(c,d,u)=>{let{filename:m,mimeType:g}=u;r++;let h=Lf(m,g);if(!vc.has(h)){i.push(`Unsupported file type: ${m} (${g})`),d.resume();return}let f=xc.has(h),b=Jf(m),S=Nf(),x,w;f?(x=Vt(n.themePath,"assets"),Sc(x,{recursive:!0}),w=Bf(x,b)):(x=Vt(n.themePath,".vibespot","uploads"),Sc(x,{recursive:!0}),w=`${S}-${b}`);let P=Vt(x,w),F=Pf(P),H=0,L=!1;d.on("data",V=>{H+=V.length}),d.on("limit",()=>{L=!0,i.push(`File too large (>10MB): ${m}`)}),d.pipe(F),a.push(new Promise(V=>{F.on("finish",()=>{if(!L){let B={id:S,filename:w,originalName:m,type:f?"image":"document",usage:f?"asset":"context",mimeType:h,size:H,addedAt:new Date().toISOString()};o.push(B),vl(B)}V()}),F.on("error",()=>{i.push(`Failed to write: ${m}`),V()})}))}),l.on("finish",async()=>{await Promise.all(a);for(let c of o)if(c.type==="document"){let d=Vt(n.themePath,".vibespot","uploads",c.filename);try{c.mimeType==="application/pdf"?c.extractedText=await Hf(d):c.mimeType==="application/vnd.openxmlformats-officedocument.wordprocessingml.document"?c.extractedText=await Uf(d):c.extractedText=Gf(d),E.info("upload",`Extracted text from ${c.originalName} (${c.extractedText.length} chars)`)}catch(u){E.warn("upload",`Failed to extract text from ${c.originalName}: ${u}`),c.extractedText=`[Could not extract text from ${c.originalName}]`}}if(r===0){p(e,400,{error:"No files uploaded"});return}p(e,200,{files:o.map(c=>({id:c.id,filename:c.filename,originalName:c.originalName,type:c.type,usage:c.usage,size:c.size})),errors:i.length>0?i:void 0})}),l.on("error",c=>{E.error("upload",`Busboy error: ${c}`),p(e,500,{error:"Upload failed"})}),t.pipe(l)}function Co(t){let e=C();return e?.assets?t.map(n=>{let s=e.assets.find(i=>i.id===n);if(!s)return null;let o={id:s.id,filename:s.filename,originalName:s.originalName,type:s.type,usage:s.usage,mimeType:s.mimeType};if(s.type==="image"){let i=Vt(e.themePath,"assets",s.filename);sr(i)&&(o.base64=or(i).toString("base64")),o.assetPath=`${e.themeName}/assets/${s.filename}`}else s.type==="document"&&(o.extractedText=s.extractedText);return o}).filter(n=>n!==null):[]}var Ff,xc,jf,vc,Df,ir=R(()=>{"use strict";y();ze();we();de();Ff=10*1024*1024,xc=new Set(["image/png","image/jpeg","image/jpg","image/svg+xml","image/webp","image/gif"]),jf=new Set(["application/pdf","application/vnd.openxmlformats-officedocument.wordprocessingml.document","text/markdown","text/plain"]),vc=new Set([...xc,...jf]),Df={".md":"text/markdown",".txt":"text/plain",".markdown":"text/markdown"}});var Ac={};Be(Ac,{callAgent:()=>_e,callAgentAPI:()=>Tc,isAgenticCapable:()=>rs,isCLIEngine:()=>xn,resolveThinkingBudget:()=>Sn});async function ko(t,e){for(let n=0;;n++)try{return await t()}catch(s){let o=s.status,i=s.error?.type;if(!(o===429||i==="rate_limit_error"||s instanceof Error&&s.message.includes("429"))||n>=rr.length)throw s;let a=rr[n];E.warn("agent-adapter",`Rate limited (429), attempt ${n+1}/${rr.length} \u2014 waiting ${a}s`),e&&e(`Rate limited \u2014 retrying in ${a}s...`),await new Promise(l=>setTimeout(l,a*1e3)),e&&e("Retrying...")}}function is(t){if(t&&typeof t=="object"&&!Array.isArray(t)){let e=t;for(let n of["fieldsJson","metaJson"])e[n]&&typeof e[n]=="object"&&(e[n]=JSON.stringify(e[n]))}return t}async function Cc(){return ar||(ar=(await import("@anthropic-ai/sdk")).default),ar}async function Wf(t,e,n,s,o){let i=await Cc(),r=new i({apiKey:t,...s?{defaultHeaders:s}:{}}),a=n.messages,l=n.systemPrompt;if(n.systemBlocks?l=o?[{type:"text",text:o},...n.systemBlocks]:n.systemBlocks:o&&(l=[{type:"text",text:o},{type:"text",text:n.systemPrompt}]),n.structuredOutput){let c={name:n.structuredOutput.name,description:`Return the result as structured JSON matching the ${n.structuredOutput.name} schema.`,input_schema:n.structuredOutput.schema,cache_control:{type:"ephemeral"}};return ko(async()=>{let d=await r.messages.create({model:e,max_tokens:n.maxTokens||16e3,system:l,messages:a,tools:[c],tool_choice:{type:"tool",name:n.structuredOutput.name},...n.thinkingBudgetTokens?{thinking:{type:"enabled",budget_tokens:n.thinkingBudgetTokens}}:{}});for(let m of d.content)if(m.type==="tool_use")return{type:"structured",data:is(m.input)};return{type:"text",text:d.content.filter(m=>m.type==="text").map(m=>m.text).join("")}},n.onStatus)}return ko(async()=>{let c="",d=r.messages.stream({model:e,max_tokens:n.maxTokens||16e3,system:l,messages:a,...n.enableWebSearch?{tools:[{type:"web_search_20250305",name:"web_search"}]}:{},...n.thinkingBudgetTokens?{thinking:{type:"enabled",budget_tokens:n.thinkingBudgetTokens}}:{}});for await(let u of d)u.type==="content_block_delta"&&u.delta.type==="text_delta"&&(c+=u.delta.text,n.onChunk&&n.onChunk(u.delta.text));return{type:"text",text:c}},n.onStatus)}async function Kf(t,e,n){let s=await Cc(),o=new s({authToken:t,defaultHeaders:_n}),i=n.messages,r;if(n.systemBlocks?r=[{type:"text",text:rn},...n.systemBlocks]:r=[{type:"text",text:rn},{type:"text",text:n.systemPrompt}],n.structuredOutput){let a={name:n.structuredOutput.name,description:`Return the result as structured JSON matching the ${n.structuredOutput.name} schema.`,input_schema:n.structuredOutput.schema,cache_control:{type:"ephemeral"}};return ko(async()=>{let l=await o.messages.create({model:e,max_tokens:n.maxTokens||16e3,system:r,messages:i,tools:[a],tool_choice:{type:"tool",name:n.structuredOutput.name},...n.thinkingBudgetTokens?{thinking:{type:"enabled",budget_tokens:n.thinkingBudgetTokens}}:{}});for(let d of l.content)if(d.type==="tool_use")return{type:"structured",data:is(d.input)};return{type:"text",text:l.content.filter(d=>d.type==="text").map(d=>d.text).join("")}},n.onStatus)}return ko(async()=>{let a="",l=o.messages.stream({model:e,max_tokens:n.maxTokens||16e3,system:r,messages:i,...n.enableWebSearch?{tools:[{type:"web_search_20250305",name:"web_search"}]}:{},...n.thinkingBudgetTokens?{thinking:{type:"enabled",budget_tokens:n.thinkingBudgetTokens}}:{}});for await(let c of l)c.type==="content_block_delta"&&c.delta.type==="text_delta"&&(a+=c.delta.text,n.onChunk&&n.onChunk(c.delta.text));return{type:"text",text:a}},n.onStatus)}function lr(t){let e={...t};if(e.type==="object"&&(e.additionalProperties=!1,e.properties&&typeof e.properties=="object")){let n={};for(let[s,o]of Object.entries(e.properties))n[s]=o&&typeof o=="object"?lr(o):o;e.properties=n}return e.items&&typeof e.items=="object"&&(e.items=lr(e.items)),e}async function Vf(t,e,n){let s=[{role:"system",content:n.systemPrompt},...n.messages.map(l=>({role:l.role,content:typeof l.content=="string"?l.content:l.content.map(c=>({type:"text",text:c.text}))}))],o={model:e,max_tokens:n.maxTokens||16e3,messages:s};n.structuredOutput&&(o.response_format={type:"json_schema",json_schema:{name:n.structuredOutput.name,strict:!0,schema:lr(n.structuredOutput.schema)}});let i=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify(o)});if(!i.ok){let l=await i.text(),c=i.status;if(c===429){let d=new Error(`OpenAI rate limit: ${l}`);throw d.status=429,d}throw new Error(`OpenAI API error (${c}): ${l}`)}let a=(await i.json()).choices?.[0]?.message?.content||"";if(n.structuredOutput)try{return{type:"structured",data:is(JSON.parse(a))}}catch{return E.warn("agent-adapter","OpenAI structured output parse failed, returning raw text"),{type:"text",text:a}}return{type:"text",text:a}}async function zf(t,e,n){let s=e||"gemini-2.5-flash",o=n.messages.map(d=>({role:d.role==="assistant"?"model":"user",parts:typeof d.content=="string"?[{text:d.content}]:d.content.map(u=>({text:u.text}))})),i={systemInstruction:{parts:[{text:n.systemPrompt}]},contents:o,generationConfig:{maxOutputTokens:n.maxTokens||16e3,...n.structuredOutput?{responseMimeType:"application/json",responseSchema:n.structuredOutput.schema}:{}}},r=`https://generativelanguage.googleapis.com/v1beta/models/${s}:generateContent?key=${t}`,a=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)});if(!a.ok){let d=await a.text(),u=a.status;if(u===429){let m=new Error(`Gemini rate limit: ${d}`);throw m.status=429,m}throw new Error(`Gemini API error (${u}): ${d}`)}let c=(await a.json()).candidates?.[0]?.content?.parts?.[0]?.text||"";if(n.structuredOutput)try{return{type:"structured",data:is(JSON.parse(c))}}catch{return E.warn("agent-adapter","Gemini structured output parse failed, returning raw text"),{type:"text",text:c}}return{type:"text",text:c}}function Yf(t,e,n){switch(t){case"claude-code":{let s=["--print"];return e&&s.push("--model",e),n?.enableWebSearch&&s.push("--allowedTools=WebSearch"),{bin:"claude",args:s}}case"gemini-cli":{let s=[];return e&&s.push("-m",e),{bin:"gemini",args:s}}case"codex-cli":{let s=["exec","--full-auto"];return e&&s.push("-m",e),{bin:"codex",args:s}}default:throw new Error(`Not a CLI engine: ${t}`)}}function qf(t){let e=[t.systemPrompt];for(let n of t.messages){let s=n.role==="user"?"User":"Assistant",o=typeof n.content=="string"?n.content:n.content.map(i=>i.text).join(`
829
+ `);e.push(`
684
830
 
685
831
  ## ${s}
686
- ${o}`)}if(e.structuredOutput){let n=Fl(e.structuredOutput.schema);t.push(`
832
+ ${o}`)}if(t.structuredOutput){let n=kc(t.structuredOutput.schema);e.push(`
687
833
 
688
834
  ## Output Format \u2014 CRITICAL
689
835
  Respond with a JSON code block. Wrap your JSON in \`\`\`json fences. No prose or explanation before or after the code block.
690
836
 
691
837
  The JSON must match this structure:
692
- ${n}`)}return t.join("")}function Fl(e,t=0){let n=" ".repeat(t),s=e.properties,o=e.required||[];if(!s)return`${n}${JSON.stringify(e)}`;let i=["{"];for(let[r,a]of Object.entries(s)){let l=o.includes(r)?" (required)":"",c=a.type||"any",d=a.description?` \u2014 ${a.description}`:"",u=a.enum?` [${a.enum.join(", ")}]`:"";if(c==="array"&&a.items){let m=a.items.type||"object";i.push(`${n} "${r}": ${c}<${m}>${l}${d}${u}`)}else c==="object"&&a.properties?i.push(`${n} "${r}": ${Fl(a,t+1)}${l}${d}`):i.push(`${n} "${r}": ${c}${l}${d}${u}`)}return i.push(`${n}}`),i.join(`
693
- `)}function wf(e){let t=e.trim(),n=tt(t);if(n&&typeof n=="object")return n;let s=t.match(/```(?:json|vibespot-modules)?\s*\n([\s\S]*?)```/i);if(s){let a=s[1].trim(),l=tt(a);if(l&&typeof l=="object")return l;let c=jn(a);if(c&&typeof c=="object")return c}let o=t.indexOf("{"),i=t.lastIndexOf("}");if(o!==-1&&i>o){let a=t.slice(o,i+1),l=tt(a);if(l&&typeof l=="object")return l;let c=jn(a);if(c&&typeof c=="object")return c}let r=jn(t);return r&&typeof r=="object"?r:null}async function Cf(e,t,n){let{bin:s,args:o}=xf(e,t,n),i=vf(n),r;if(e==="claude-code"){let l=[...o,"--output-format","stream-json","--include-partial-messages","--verbose"];r=await Ei(l,i,{onChunk:n.onChunk,onToolUse:(c,d)=>{if(!n.onStatus)return;let u=kf(c,d);n.onStatus(u)}})}else r=await Mi(s,o,i,n.onChunk);if(!n.structuredOutput)return{type:"text",text:r};let a=wf(r);return a?{type:"structured",data:Ln(a)}:(E.warn("agent-cli",`${e}: failed to parse structured output, returning text`,{outputPreview:r.slice(0,500),outputLength:r.length}),{type:"text",text:r})}function kf(e,t){let n=t||{};switch(e){case"WebSearch":case"web_search":return`Searching: "${String(n.query||"")}"`;case"WebFetch":return`Fetching: ${String(n.url||"")}`;case"Read":return`Reading ${String(n.file_path||n.path||"file")}`;case"Edit":case"Write":return`Editing ${String(n.file_path||n.path||"file")}`;case"Bash":return`Running: ${String(n.command||"").slice(0,60)}`;case"Grep":return`Searching for "${String(n.pattern||"")}"`;case"Glob":return`Globbing ${String(n.pattern||"")}`;default:return`Using ${e}`}}async function jl(e,t,n,s){switch(E.info("agent-adapter",`${e} API call`,{model:n,structured:!!s.structuredOutput,schemaName:s.structuredOutput?.name,systemPromptLength:s.systemPrompt.length,messageCount:s.messages.length}),e){case"anthropic-api":return hf(t,n,s);case"claude-oauth":{let{getValidAccessToken:o}=await Promise.resolve().then(()=>(lt(),Uo)),i=await o();if(!i)throw new Error("Claude OAuth session expired. Please re-authenticate in Settings.");return yf(i,n,s)}case"openai-api":return bf(t,n,s);case"gemini-api":return Sf(t,n,s);default:throw new Error(`Unsupported API engine: ${e}`)}}async function Re(e,t,n,s){return Af.has(e)?jl(e,t,n,s):(E.info("agent-adapter",`${e} CLI call`,{structured:!!s.structuredOutput,schemaName:s.structuredOutput?.name,systemPromptLength:s.systemPrompt.length,messageCount:s.messages.length}),Cf(e,n,s))}function Ji(e){if(e!=="anthropic-api"&&e!=="claude-oauth")return 0;let t=R();if(!t.extendedThinking)return 0;switch(t.extendedThinkingBudget){case"high":return 32e3;case"low":return 4e3;default:return 16e3}}function Hn(e){return e==="anthropic-api"||e==="claude-oauth"||e==="openai-api"||e==="gemini-api"||e==="claude-code"||e==="gemini-cli"||e==="codex-cli"}function an(e){return e==="claude-code"||e==="gemini-cli"||e==="codex-cli"}var Fi,ji,Af,nt=G(()=>{"use strict";g();_i();eo();X();lt();re();Fi=[10,20,40,60,120];ji=null;Af=new Set(["anthropic-api","claude-oauth","openai-api","gemini-api"])});function Jl(e,t,n,s){let o=t.length>0?`Current template modules (in page order):
694
- ${t.map((a,l)=>`${l+1}. ${a}`).join(`
695
- `)}`:"No modules yet (new page).",i=n.length>0?`
838
+ ${n}`)}return e.join("")}function kc(t,e=0){let n=" ".repeat(e),s=t.properties,o=t.required||[];if(!s)return`${n}${JSON.stringify(t)}`;let i=["{"];for(let[r,a]of Object.entries(s)){let l=o.includes(r)?" (required)":"",c=a.type||"any",d=a.description?` \u2014 ${a.description}`:"",u=a.enum?` [${a.enum.join(", ")}]`:"";if(c==="array"&&a.items){let m=a.items.type||"object";i.push(`${n} "${r}": ${c}<${m}>${l}${d}${u}`)}else c==="object"&&a.properties?i.push(`${n} "${r}": ${kc(a,e+1)}${l}${d}`):i.push(`${n} "${r}": ${c}${l}${d}${u}`)}return i.push(`${n}}`),i.join(`
839
+ `)}function Xf(t){let e=t.trim(),n=ft(e);if(n&&typeof n=="object")return n;let s=e.match(/```(?:json|vibespot-modules)?\s*\n([\s\S]*?)```/i);if(s){let a=s[1].trim(),l=ft(a);if(l&&typeof l=="object")return l;let c=ns(a);if(c&&typeof c=="object")return c}let o=e.indexOf("{"),i=e.lastIndexOf("}");if(o!==-1&&i>o){let a=e.slice(o,i+1),l=ft(a);if(l&&typeof l=="object")return l;let c=ns(a);if(c&&typeof c=="object")return c}let r=ns(e);return r&&typeof r=="object"?r:null}async function Zf(t,e,n){let{bin:s,args:o}=Yf(t,e,n),i=qf(n),r;if(t==="claude-code"){let l=[...o,"--output-format","stream-json","--include-partial-messages","--verbose"];r=await Qi(l,i,{onChunk:n.onChunk,onToolUse:(c,d)=>{if(!n.onStatus)return;let u=Qf(c,d);n.onStatus(u)}})}else r=await er(s,o,i,n.onChunk);if(!n.structuredOutput)return{type:"text",text:r};let a=Xf(r);return a?{type:"structured",data:is(a)}:(E.warn("agent-cli",`${t}: failed to parse structured output, returning text`,{outputPreview:r.slice(0,500),outputLength:r.length}),{type:"text",text:r})}function Qf(t,e){let n=e||{};switch(t){case"WebSearch":case"web_search":return`Searching: "${String(n.query||"")}"`;case"WebFetch":return`Fetching: ${String(n.url||"")}`;case"Read":return`Reading ${String(n.file_path||n.path||"file")}`;case"Edit":case"Write":return`Editing ${String(n.file_path||n.path||"file")}`;case"Bash":return`Running: ${String(n.command||"").slice(0,60)}`;case"Grep":return`Searching for "${String(n.pattern||"")}"`;case"Glob":return`Globbing ${String(n.pattern||"")}`;default:return`Using ${t}`}}async function Tc(t,e,n,s){switch(E.info("agent-adapter",`${t} API call`,{model:n,structured:!!s.structuredOutput,schemaName:s.structuredOutput?.name,systemPromptLength:s.systemPrompt.length,messageCount:s.messages.length}),t){case"anthropic-api":return Wf(e,n,s);case"claude-oauth":{let{getValidAccessToken:o}=await Promise.resolve().then(()=>(xt(),gi)),i=await o();if(!i)throw new Error("Claude OAuth session expired. Please re-authenticate in Settings.");return Kf(i,n,s)}case"openai-api":return Vf(e,n,s);case"gemini-api":return zf(e,n,s);default:throw new Error(`Unsupported API engine: ${t}`)}}async function _e(t,e,n,s){return eh.has(t)?Tc(t,e,n,s):(E.info("agent-adapter",`${t} CLI call`,{structured:!!s.structuredOutput,schemaName:s.structuredOutput?.name,systemPromptLength:s.systemPrompt.length,messageCount:s.messages.length}),Zf(t,n,s))}function Sn(t){if(t!=="anthropic-api"&&t!=="claude-oauth")return 0;let e=O();if(!e.extendedThinking)return 0;switch(e.extendedThinkingBudget){case"high":return 32e3;case"low":return 4e3;default:return 16e3}}function rs(t){return t==="anthropic-api"||t==="claude-oauth"||t==="openai-api"||t==="gemini-api"||t==="claude-code"||t==="gemini-cli"||t==="codex-cli"}function xn(t){return t==="claude-code"||t==="gemini-cli"||t==="codex-cli"}var rr,ar,eh,nt=R(()=>{"use strict";y();nr();wo();Q();xt();de();rr=[10,20,40,60,120];ar=null;eh=new Set(["anthropic-api","claude-oauth","openai-api","gemini-api"])});function $c(t,e,n,s,o){let i=e.length>0?`Current template modules (in page order):
840
+ ${e.map((c,d)=>`${d+1}. ${c}`).join(`
841
+ `)}`:"No modules yet (new page).",r=n.length>0?`
696
842
 
697
843
  Module library (reusable from other templates):
698
- ${n.map(a=>`- ${a.name} (used in: ${a.usedIn.join(", ")})`).join(`
699
- `)}`:"",r=s?`
844
+ ${n.map(c=>`- ${c.name} (used in: ${c.usedIn.join(", ")})`).join(`
845
+ `)}`:"",a=s?`
700
846
 
701
847
  ## Product Context
702
- ${s}`:"";return`You are the Intent Analyzer for vibeSpot, a HubSpot CMS page builder.
848
+ ${s}`:"",l=o?.pages&&o.pages.length>1?`
849
+
850
+ ## Multi-Page Site Context
851
+ This is a multi-page site. Currently editing: **${o.activePageLabel||"unknown"}**
852
+ All pages:
853
+ ${o.pages.map(c=>`- ${c.label} (${c.id}, ${c.moduleCount} modules)`).join(`
854
+ `)}
855
+
856
+ The user's message applies to the current page unless they reference another page by name or say "all pages" / "every page" / "the whole site".`:"";return`You are the Intent Analyzer for vibeSpot, a HubSpot CMS builder that generates pages, email templates, and blog templates.
857
+
858
+ Your job: classify the user's request, determine the content type (page, email, or blog), and plan which modules need work. You do NOT generate module code \u2014 you only plan.
859
+
860
+ ## Theme: "${t}"
861
+
862
+ ${i}${r}${a}${l}
703
863
 
704
- Your job: classify the user's request and plan which modules need work. You do NOT generate module code \u2014 you only plan.
864
+ ## Content Type Detection
705
865
 
706
- ## Theme: "${e}"
866
+ Set \`contentType\` based on the user's request:
867
+ - **"page"** (default) \u2014 Landing pages, website pages, any page-type content
868
+ - **"email"** \u2014 Email templates, newsletters, email campaigns, transactional emails
869
+ - **"blog"** \u2014 Blog listing pages, blog post templates, content hubs, article layouts
707
870
 
708
- ${o}${i}${r}
871
+ Trigger words for email: "email", "email template", "newsletter", "email campaign", "welcome email", "announcement email", "drip", "email sequence", "email blast", "transactional email".
872
+
873
+ Trigger words for blog: "blog", "blog post", "blog listing", "blog template", "article", "content hub", "blog page", "blog layout", "editorial", "publication", "magazine layout", "posts page".
874
+
875
+ If ambiguous, default to "page". The content type affects downstream pipeline behavior (email uses table-based layout; blog uses HubSpot blog variables and reading-optimized design).
709
876
 
710
877
  ## Classification Rules
711
878
 
712
- 1. **create** \u2014 User wants a new page from scratch (e.g., "build me a landing page for...")
713
- 2. **modify** \u2014 User wants to change existing modules (e.g., "make the hero button red", "update the pricing")
714
- 3. **add** \u2014 User wants new modules added to the existing page (e.g., "add a testimonials section")
715
- 4. **remove** \u2014 User wants modules removed (e.g., "remove the footer")
716
- 5. **rearrange** \u2014 User wants to reorder modules (e.g., "move pricing above features")
717
- 6. **style_change** \u2014 User wants design system changes that affect shared CSS/multiple modules (e.g., "change the color scheme to blue")
718
- 7. **question** \u2014 User is asking a question, not requesting changes (e.g., "what modules do I have?"). Provide the answer directly.
879
+ 1. **create** \u2014 User wants a new single page/email/blog from scratch (e.g., "build me a landing page for...", "create a welcome email", "build a blog for my company")
880
+ 2. **create_site** \u2014 User wants a multi-page website (e.g., "build a website with home, about, and contact pages", "create a 5-page site for..."). Use when the user mentions multiple pages, a website (not just a page), or a site with navigation. Output \`pages\` array with each page's label, purpose, pageType, and slug, plus \`sharedModules\` listing shared module names (e.g., "site-header", "site-footer").
881
+ 3. **modify** \u2014 User wants to change existing modules (e.g., "make the hero button red", "update the pricing")
882
+ 4. **add** \u2014 User wants new modules added to the existing page/email (e.g., "add a testimonials section")
883
+ 5. **remove** \u2014 User wants modules removed (e.g., "remove the footer")
884
+ 6. **rearrange** \u2014 User wants to reorder modules (e.g., "move pricing above features")
885
+ 7. **style_change** \u2014 User wants design system changes that affect shared CSS/multiple modules (e.g., "change the color scheme to blue")
886
+ 8. **question** \u2014 User is asking a question, not requesting changes (e.g., "what modules do I have?"). Provide the answer directly.
887
+
888
+ ## Multi-Page Site Rules (create_site only)
889
+
890
+ When classifying as \`create_site\`:
891
+ - Populate the \`pages\` array with one entry per page. Each page needs: id (kebab-case), label (human-readable), pageType ("landing_page" or "website_page"), purpose (1-sentence), slug (URL path without leading /).
892
+ - Populate \`sharedModules\` with names of modules shared across all pages (typically ["site-header", "site-footer"]).
893
+ - Always include at least a header and footer in sharedModules.
894
+ - Page IDs should be descriptive: "wp-home", "wp-about", "wp-contact", etc.
895
+ - Set \`designSystemChanges: true\` (site creation always needs a design system)
896
+ - If the user says "website" or "site" without specifying pages, infer reasonable pages (e.g., Home, About, Contact)
897
+ - All guides are needed for site creation: design, content, conversion, hubspot_rules, humanify
719
898
 
720
899
  ## Key Rules
721
900
 
@@ -746,11 +925,15 @@ CRITICAL: When the user corrects a misclassification (e.g., "I was referencing t
746
925
  If the user asks for multiple things (e.g., "make hero taller AND add testimonials"), capture ALL parts:
747
926
  - Affected existing modules in \`affectedModules\`
748
927
  - New modules in \`newModules\`
749
- - Set the broadest applicable intent (prefer "modify" + newModules over splitting)`}var Ll,Hl=G(()=>{"use strict";g();Ll={type:"object",properties:{intent:{type:"string",enum:["create","modify","add","remove","rearrange","style_change","question"]},affectedModules:{type:"array",items:{type:"string"},description:"Names of existing modules that need changes"},unchangedModules:{type:"array",items:{type:"string"},description:"Names of existing modules that stay as-is"},newModules:{type:"array",items:{type:"object",properties:{name:{type:"string"},description:{type:"string"},position:{type:"number"}},required:["name","description","position"]},description:"New modules to create"},reuseModules:{type:"array",items:{type:"object",properties:{name:{type:"string"},sourceTemplate:{type:"string"},position:{type:"number"}},required:["name","sourceTemplate","position"]},description:"Modules to copy from the library (immutable structure)"},guidesNeeded:{type:"array",items:{type:"string",enum:["design","content","conversion","hubspot_rules","humanify"]}},designSystemChanges:{type:"boolean",description:"True if shared CSS / design system needs regeneration"},answer:{type:"string",description:'For "question" intent only \u2014 the answer to return directly'}},required:["intent","affectedModules","unchangedModules","newModules","guidesNeeded","designSystemChanges"]}});async function Bl(e,t,n,s,o,i,r){i({type:"agent_step",step:"analyzing",label:"Analyzing your request..."});let a=t.modules.map(f=>f.moduleName),l=Jl(t.themeName,a,r,t.brandAssets?.themeContext),c=[],d=t.messages.slice(-6);for(let f of d)if(f.role==="user"||f.role==="assistant"){let y=f.role==="assistant"&&f.content.length>300?f.content.slice(0,300)+"...":f.content;c.push({role:f.role,content:y})}c.push({role:"user",content:e});let u=await Re(n,s,o,{systemPrompt:l,messages:c,structuredOutput:{schema:Ll,name:"pipeline_plan"},maxTokens:2e3});if(u.type!=="structured"){E.warn("intent-analyzer","Did not get structured output, falling back");let f=t.modules.length===0;return{intent:f?"create":"modify",affectedModules:f?[]:a,unchangedModules:[],newModules:[],guidesNeeded:["design","content","conversion","hubspot_rules","humanify"],designSystemChanges:f}}let m=u.data;return m.affectedModules=m.affectedModules||[],m.unchangedModules=m.unchangedModules||[],m.newModules=m.newModules||[],m.guidesNeeded=m.guidesNeeded||[],E.info("intent-analyzer","Plan",{intent:m.intent,affected:m.affectedModules.length,unchanged:m.unchangedModules.length,new:m.newModules.length,reuse:m.reuseModules?.length||0,designSystem:m.designSystemChanges}),i({type:"agent_decision",step:"analyzing",decision:Tf(m)}),m}function Tf(e){let t=[`Intent: ${e.intent}`];return e.affectedModules.length>0&&t.push(`Modifying: ${e.affectedModules.join(", ")}`),e.unchangedModules.length>0&&t.push(`Unchanged: ${e.unchangedModules.join(", ")}`),e.newModules.length>0&&t.push(`New: ${e.newModules.map(n=>n.name).join(", ")}`),e.reuseModules?.length&&t.push(`Reuse: ${e.reuseModules.map(n=>`${n.name} from ${n.sourceTemplate}`).join(", ")}`),e.designSystemChanges&&t.push("Design system changes: yes"),t.join(" | ")}var Ul=G(()=>{"use strict";g();nt();Hl();re()});function Li(e,t){let n=[];return n.push(`You are the Design System Architect for vibeSpot, a HubSpot CMS page builder.
928
+ - Set the broadest applicable intent (prefer "modify" + newModules over splitting)
929
+
930
+ ## Content Type Detection
931
+
932
+ Set \`contentType\` to "email" when the user explicitly asks for an email template, newsletter, email campaign, welcome email, promotional email, or similar email content. Leave as "page" (default) for landing pages, websites, and web content.`}var _c,Mc=R(()=>{"use strict";y();_c={type:"object",properties:{intent:{type:"string",enum:["create","create_site","modify","add","remove","rearrange","style_change","question"]},contentType:{type:"string",enum:["page","email","blog"],description:'Content type: "page" (default), "email" for email templates, or "blog" for blog templates'},affectedModules:{type:"array",items:{type:"string"},description:"Names of existing modules that need changes"},unchangedModules:{type:"array",items:{type:"string"},description:"Names of existing modules that stay as-is"},newModules:{type:"array",items:{type:"object",properties:{name:{type:"string"},description:{type:"string"},position:{type:"number"}},required:["name","description","position"]},description:"New modules to create"},reuseModules:{type:"array",items:{type:"object",properties:{name:{type:"string"},sourceTemplate:{type:"string"},position:{type:"number"}},required:["name","sourceTemplate","position"]},description:"Modules to copy from the library (immutable structure)"},guidesNeeded:{type:"array",items:{type:"string",enum:["design","content","conversion","hubspot_rules","humanify"]}},designSystemChanges:{type:"boolean",description:"True if shared CSS / design system needs regeneration"},answer:{type:"string",description:'For "question" intent only \u2014 the answer to return directly'},pages:{type:"array",items:{type:"object",properties:{id:{type:"string",description:"Kebab-case page ID (e.g. wp-home)"},label:{type:"string",description:"Human-readable page name"},pageType:{type:"string",enum:["landing_page","website_page","blog_post"]},purpose:{type:"string",description:"One-sentence page purpose"},slug:{type:"string",description:"URL path without leading /"}},required:["id","label","pageType","purpose","slug"]},description:'For "create_site" intent \u2014 list of pages to generate'},sharedModules:{type:"array",items:{type:"string"},description:'For "create_site" intent \u2014 module names shared across all pages (e.g. site-header, site-footer)'}},required:["intent","affectedModules","unchangedModules","newModules","guidesNeeded","designSystemChanges"]}});async function Ec(t,e,n,s,o,i,r){i({type:"agent_step",step:"analyzing",label:"Analyzing your request..."});let a=e.modules.map(g=>g.moduleName),l=$c(e.themeName,a,r,e.brandAssets?.themeContext,e.sitePages?{activePageLabel:e.activePageLabel,pages:e.sitePages}:void 0),c=[],d=e.messages.slice(-6);for(let g of d)if(g.role==="user"||g.role==="assistant"){let h=g.role==="assistant"&&g.content.length>300?g.content.slice(0,300)+"...":g.content;c.push({role:g.role,content:h})}c.push({role:"user",content:t});let u=await _e(n,s,o,{systemPrompt:l,messages:c,structuredOutput:{schema:_c,name:"pipeline_plan"},maxTokens:2e3});if(u.type!=="structured"){E.warn("intent-analyzer","Did not get structured output, falling back");let g=e.modules.length===0;return{intent:g?"create":"modify",affectedModules:g?[]:a,unchangedModules:[],newModules:[],guidesNeeded:["design","content","conversion","hubspot_rules","humanify"],designSystemChanges:g}}let m=u.data;return m.affectedModules=m.affectedModules||[],m.unchangedModules=m.unchangedModules||[],m.newModules=m.newModules||[],m.guidesNeeded=m.guidesNeeded||[],e.contentMode==="email"?m.contentType="email":m.contentType=m.contentType==="email"?"email":"page",E.info("intent-analyzer","Plan",{intent:m.intent,affected:m.affectedModules.length,unchanged:m.unchangedModules.length,new:m.newModules.length,reuse:m.reuseModules?.length||0,designSystem:m.designSystemChanges}),i({type:"agent_decision",step:"analyzing",decision:th(m)}),m}function th(t){let e=[`Intent: ${t.intent}`];return t.affectedModules.length>0&&e.push(`Modifying: ${t.affectedModules.join(", ")}`),t.unchangedModules.length>0&&e.push(`Unchanged: ${t.unchangedModules.join(", ")}`),t.newModules.length>0&&e.push(`New: ${t.newModules.map(n=>n.name).join(", ")}`),t.reuseModules?.length&&e.push(`Reuse: ${t.reuseModules.map(n=>`${n.name} from ${n.sourceTemplate}`).join(", ")}`),t.designSystemChanges&&e.push("Design system changes: yes"),e.join(" | ")}var Ic=R(()=>{"use strict";y();nt();Mc();de()});function To(t,e){let n=[];n.push(`You are the Design System Architect for vibeSpot, a HubSpot CMS page builder.
750
933
 
751
934
  Your job: create a complete, production-ready CSS design system for a landing page theme. You produce the :root custom properties, shared utility/component CSS, and optional shared JS (scroll animations). Downstream agents will use YOUR CSS classes and variables to build individual modules.
752
935
 
753
- ## Theme: "${e}"
936
+ ## Theme: "${t}"
754
937
 
755
938
  ## Output Requirements
756
939
 
@@ -758,36 +941,36 @@ Your job: create a complete, production-ready CSS design system for a landing pa
758
941
  A flat object mapping CSS custom property names to values. Every variable your CSS references MUST be defined here. Include ALL of these categories:
759
942
 
760
943
  **Colors** (at minimum):
761
- - --${e}-color-bg: page background
762
- - --${e}-color-surface: card/section background
763
- - --${e}-color-dark: dark section background
764
- - --${e}-color-dark-surface: card bg inside dark sections
765
- - --${e}-color-text: primary text color
766
- - --${e}-color-text-inverse: text on dark backgrounds
767
- - --${e}-color-text-muted: secondary/muted text
768
- - --${e}-color-primary: primary brand color
769
- - --${e}-color-primary-dark: darker variant for hover states
770
- - --${e}-color-accent: accent/highlight color
771
- - --${e}-color-accent-light: light tint for pill/badge backgrounds
772
- - --${e}-color-border: default border color
773
- - --${e}-color-border-hover: border on hover
944
+ - --${t}-color-bg: page background
945
+ - --${t}-color-surface: card/section background
946
+ - --${t}-color-dark: dark section background
947
+ - --${t}-color-dark-surface: card bg inside dark sections
948
+ - --${t}-color-text: primary text color
949
+ - --${t}-color-text-inverse: text on dark backgrounds
950
+ - --${t}-color-text-muted: secondary/muted text
951
+ - --${t}-color-primary: primary brand color
952
+ - --${t}-color-primary-dark: darker variant for hover states
953
+ - --${t}-color-accent: accent/highlight color
954
+ - --${t}-color-accent-light: light tint for pill/badge backgrounds
955
+ - --${t}-color-border: default border color
956
+ - --${t}-color-border-hover: border on hover
774
957
 
775
958
  **Typography**:
776
- - --${e}-font-display: display/heading font stack (system fonts only)
777
- - --${e}-font-body: body text font stack (system fonts only)
778
- - --${e}-size-h1 through --${e}-size-h3: heading sizes using clamp()
779
- - --${e}-size-body, --${e}-size-lg, --${e}-size-small, --${e}-size-label
780
- - --${e}-leading-tight, --${e}-leading-snug, --${e}-leading-body: line heights
781
- - --${e}-tracking-tight, --${e}-tracking-wide: letter spacing
959
+ - --${t}-font-display: display/heading font stack (system fonts only)
960
+ - --${t}-font-body: body text font stack (system fonts only)
961
+ - --${t}-size-h1 through --${t}-size-h3: heading sizes using clamp()
962
+ - --${t}-size-body, --${t}-size-lg, --${t}-size-small, --${t}-size-label
963
+ - --${t}-leading-tight, --${t}-leading-snug, --${t}-leading-body: line heights
964
+ - --${t}-tracking-tight, --${t}-tracking-wide: letter spacing
782
965
 
783
966
  **Spacing**:
784
- - --${e}-space-xs through --${e}-space-xl, --${e}-space-section
785
- - --${e}-max-width: content max-width (1152-1280px)
967
+ - --${t}-space-xs through --${t}-space-xl, --${t}-space-section
968
+ - --${t}-max-width: content max-width (1152-1280px)
786
969
 
787
970
  **Effects**:
788
- - --${e}-radius-sm, --${e}-radius-md, --${e}-radius-lg, --${e}-radius-full
789
- - --${e}-shadow-card-hover, --${e}-shadow-button
790
- - --${e}-transition-fast, --${e}-transition-base, --${e}-transition-slow
971
+ - --${t}-radius-sm, --${t}-radius-md, --${t}-radius-lg, --${t}-radius-full
972
+ - --${t}-shadow-card-hover, --${t}-shadow-button
973
+ - --${t}-transition-fast, --${t}-transition-base, --${t}-transition-slow
791
974
 
792
975
  ### sharedCss
793
976
  Complete CSS file content. MUST include:
@@ -795,15 +978,15 @@ Complete CSS file content. MUST include:
795
978
  2. Reset (box-sizing, margin, padding)
796
979
  3. Body styles referencing your variables
797
980
  4. Typography rules (h1-h6, p)
798
- 5. Layout utilities (.${e}-container, .${e}-section, .${e}-section--dark)
799
- 6. Grid system (.${e}-grid, .${e}-grid--2/3/4 with responsive breakpoints)
800
- 7. Card component (.${e}-card with hover lift)
801
- 8. Button component (.${e}-btn, .${e}-btn--primary, .${e}-btn--secondary)
981
+ 5. Layout utilities (.${t}-container, .${t}-section, .${t}-section--dark)
982
+ 6. Grid system (.${t}-grid, .${t}-grid--2/3/4 with responsive breakpoints)
983
+ 7. Card component (.${t}-card with hover lift)
984
+ 8. Button component (.${t}-btn, .${t}-btn--primary, .${t}-btn--secondary)
802
985
  CRITICAL: Re-declare color, text-decoration:none, and font-family on :hover/:focus \u2014 HubSpot overrides link hover styles
803
- 9. Pill/badge (.${e}-pill)
986
+ 9. Pill/badge (.${t}-pill)
804
987
  10. Decorative elements (at least one background treatment: grid pattern, noise, gradient orb)
805
988
  11. Scroll animation CSS ([data-animate], [data-animate-stagger]) with 3s CSS-only fallback
806
- 12. Section label (.${e}-label) \u2014 uppercase, letter-spacing, accent color
989
+ 12. Section label (.${t}-label) \u2014 uppercase, letter-spacing, accent color
807
990
  13. Stat number styling
808
991
  14. Responsive mobile styles (@media max-width: 767px)
809
992
 
@@ -811,8 +994,8 @@ Complete CSS file content. MUST include:
811
994
  IntersectionObserver-based scroll animation JS. Wrap in IIFE.
812
995
 
813
996
  ## CSS Rules \u2014 CRITICAL
814
- - All classes MUST use prefix "${e}-"
815
- - Use BEM naming: ${e}-module__element--modifier
997
+ - All classes MUST use prefix "${t}-"
998
+ - Use BEM naming: ${t}-module__element--modifier
816
999
  - Use system font stacks ONLY (no Google Fonts @import, no external CDN)
817
1000
  - Every var() reference in CSS must have a matching declaration in :root
818
1001
  - No Tailwind, no Sass, no PostCSS
@@ -820,41 +1003,60 @@ IntersectionObserver-based scroll animation JS. Wrap in IIFE.
820
1003
 
821
1004
  ## Font Strategy
822
1005
  Use system font stacks that approximate the desired aesthetic. Pick TWO stacks:
823
- - Display: for headings (e.g., Georgia, "Times New Roman", serif for editorial)
824
- - Body: for text (e.g., system-ui, -apple-system, "Segoe UI", sans-serif)
825
-
826
- Good system font stacks by style:
827
- | Style | Display Stack | Body Stack |
828
- |-------|--------------|------------|
829
- | Editorial | Georgia, Cambria, "Times New Roman", serif | system-ui, -apple-system, "Segoe UI", sans-serif |
830
- | Modern | system-ui, -apple-system, sans-serif | "Segoe UI", Roboto, sans-serif |
831
- | Warm | Optima, Candara, "Noto Sans", sans-serif | "Trebuchet MS", system-ui, sans-serif |
832
- | Monospace/Tech | "SF Mono", "Cascadia Code", "Fira Code", monospace | system-ui, sans-serif |
833
- | Geometric | Futura, "Century Gothic", "Trebuchet MS", sans-serif | system-ui, sans-serif |`),n.push(`
1006
+ - Display: for headings
1007
+ - Body: for text
1008
+
1009
+ **Choose the pairing that best fits the content's mood** \u2014 don't default to the same one every time:
1010
+ | Style | Display Stack | Body Stack | Best for |
1011
+ |-------|--------------|------------|----------|
1012
+ | Editorial | Georgia, Cambria, "Times New Roman", serif | system-ui, -apple-system, "Segoe UI", sans-serif | Media, luxury, culture |
1013
+ | Modern | system-ui, -apple-system, sans-serif | "Segoe UI", Roboto, sans-serif | SaaS, tech, startups |
1014
+ | Warm | Optima, Candara, "Noto Sans", sans-serif | "Trebuchet MS", system-ui, sans-serif | Local business, food, wellness |
1015
+ | Monospace/Tech | "SF Mono", "Cascadia Code", "Fira Code", monospace | system-ui, sans-serif | Developer tools, data, cyber |
1016
+ | Geometric | Futura, "Century Gothic", "Trebuchet MS", sans-serif | system-ui, sans-serif | Architecture, design, fashion |
1017
+ | Classic | "Book Antiqua", Palatino, "Palatino Linotype", serif | Georgia, "Times New Roman", serif | Law, finance, heritage |
1018
+ | Friendly | "Comic Sans MS", Chalkboard, cursive | "Trebuchet MS", system-ui, sans-serif | Kids, casual, fun brands |
1019
+ | Contrast pair | Georgia, serif (display) | system-ui, sans-serif (body) | When you want serif/sans tension |`),n.push(`
834
1020
 
835
1021
  ## Design Guide
836
- ${Kl()}`),t?.styleguide&&n.push(`
1022
+ ${Fc()}`),e?.styleguide&&n.push(`
837
1023
 
838
1024
  ## Brand Style Guide
839
- ${t.styleguide}`),t?.themeContext&&n.push(`
1025
+ ${e.styleguide}`),e?.themeContext&&n.push(`
840
1026
 
841
1027
  ## Product Context
842
- ${t.themeContext}`),n.join("")}function Gl(e,t){let n=Li(e),o=n.indexOf(`
1028
+ ${e.themeContext}`);let s=e?.brandKit&&(e.brandKit.colors?.primary||e.brandKit.colors?.secondary||e.brandKit.colors?.accent||e.brandKit.fonts?.heading||e.brandKit.fonts?.body);if(s){let o=[],i=e.brandKit;i.colors?.primary&&o.push(`- Primary color: ${i.colors.primary}`),i.colors?.secondary&&o.push(`- Secondary color: ${i.colors.secondary}`),i.colors?.accent&&o.push(`- Accent color: ${i.colors.accent}`),i.fonts?.heading&&o.push(`- Heading font: ${i.fonts.heading}`),i.fonts?.body&&o.push(`- Body font: ${i.fonts.body}`),i.logoUrl&&o.push(`- Logo URL: ${i.logoUrl}`),o.length>0&&n.push(`
1029
+
1030
+ ## Brand Kit \u2014 MANDATORY Design Constraints
1031
+ The following brand identity values MUST be used. Do NOT substitute or override them:
1032
+ ${o.join(`
1033
+ `)}`)}return!s&&!e?.styleguide&&n.push(`
1034
+
1035
+ ## No Brand Provided \u2014 Follow the Generation Recipe
1036
+ No brand colors, fonts, or styleguide have been set. You MUST follow these rules to create a unique design:
1037
+
1038
+ ${Oc()}`),n.join("")}function cr(t,e){let n=To(t),o=n.indexOf(`
843
1039
 
844
1040
  ## Design Guide
845
1041
  `);if(o===-1)return[{type:"text",text:n}];let i=n.slice(0,o),r=`## Design Guide
846
- ${Kl()}`,a=[{type:"text",text:i},{type:"text",text:r,cache_control:{type:"ephemeral"}}],l=[];return t?.styleguide&&l.push(`## Brand Style Guide
847
- ${t.styleguide}`),t?.themeContext&&l.push(`## Product Context
848
- ${t.themeContext}`),l.length>0&&a.push({type:"text",text:l.join(`
1042
+ ${Fc()}`,a=[{type:"text",text:i},{type:"text",text:r,cache_control:{type:"ephemeral"}}],l=[];e?.styleguide&&l.push(`## Brand Style Guide
1043
+ ${e.styleguide}`),e?.themeContext&&l.push(`## Product Context
1044
+ ${e.themeContext}`);let c=e?.brandKit&&(e.brandKit.colors?.primary||e.brandKit.colors?.secondary||e.brandKit.colors?.accent||e.brandKit.fonts?.heading||e.brandKit.fonts?.body);if(c){let d=[],u=e.brandKit;u.colors?.primary&&d.push(`- Primary color: ${u.colors.primary}`),u.colors?.secondary&&d.push(`- Secondary color: ${u.colors.secondary}`),u.colors?.accent&&d.push(`- Accent color: ${u.colors.accent}`),u.fonts?.heading&&d.push(`- Heading font: ${u.fonts.heading}`),u.fonts?.body&&d.push(`- Body font: ${u.fonts.body}`),u.logoUrl&&d.push(`- Logo URL: ${u.logoUrl}`),d.length>0&&l.push(`## Brand Kit \u2014 MANDATORY Design Constraints
1045
+ The following brand identity values MUST be used. Do NOT substitute or override them:
1046
+ ${d.join(`
1047
+ `)}`)}return!c&&!e?.styleguide&&l.push(`## No Brand Provided \u2014 Follow the Generation Recipe
1048
+ No brand colors, fonts, or styleguide have been set. You MUST follow these rules to create a unique design:
849
1049
 
850
- `)}),a}function $f(e){let t=[...new Set([...e.matchAll(/\.([a-zA-Z][\w-]*)/g)].map(i=>`.${i[1]}`))],n=[...new Set([...e.matchAll(/(--[\w-]+)\s*:/g)].map(i=>i[1]))],s=[...new Set([...e.matchAll(/@media\s*\([^)]+\)/g)].map(i=>i[0]))],o=[];return n.length>0&&o.push(`CSS Variables: ${n.join(", ")}`),t.length>0&&o.push(`CSS Classes: ${t.join(", ")}`),s.length>0&&o.push(`Breakpoints: ${s.join(", ")}`),o.join(`
851
- `)}function Vl(e,t,n,s){let o=[],i=$f(t);return o.push(`You are the Module Planner for vibeSpot, a HubSpot CMS page builder.
1050
+ ${Oc()}`),l.length>0&&a.push({type:"text",text:l.join(`
1051
+
1052
+ `)}),a}function nh(t){let e=[...new Set([...t.matchAll(/\.([a-zA-Z][\w-]*)/g)].map(i=>`.${i[1]}`))],n=[...new Set([...t.matchAll(/(--[\w-]+)\s*:/g)].map(i=>i[1]))],s=[...new Set([...t.matchAll(/@media\s*\([^)]+\)/g)].map(i=>i[0]))],o=[];return n.length>0&&o.push(`CSS Variables: ${n.join(", ")}`),e.length>0&&o.push(`CSS Classes: ${e.join(", ")}`),s.length>0&&o.push(`Breakpoints: ${s.join(", ")}`),o.join(`
1053
+ `)}function Rc(t,e,n,s){let o=[],i=nh(e);return o.push(`You are the Module Planner for vibeSpot, a HubSpot CMS page builder.
852
1054
 
853
1055
  Your job: plan the modules for a landing page. You define what each module contains (content brief) and how it should be laid out. You do NOT write module code \u2014 downstream Module Developers handle that.
854
1056
 
855
1057
  The Design System has already been created. Your module plans MUST reference the existing CSS classes and variables.
856
1058
 
857
- ## Theme: "${e}"
1059
+ ## Theme: "${t}"
858
1060
 
859
1061
  ## Available CSS Classes & Variables
860
1062
  Reference these in your layoutNotes:
@@ -871,7 +1073,7 @@ ${i}
871
1073
  ### Content & layout
872
1074
  - Content briefs: describe the actual copy/content each module needs (headlines, body text, CTAs, stats)
873
1075
  - Layout notes: describe the visual layout using the available CSS classes above
874
- - Reference specific CSS classes from the shared CSS in your layout notes (e.g., "Use ${e}-grid--3 for card layout, ${e}-section--dark for background")
1076
+ - Reference specific CSS classes from the shared CSS in your layout notes (e.g., "Use ${t}-grid--3 for card layout, ${t}-section--dark for background")
875
1077
 
876
1078
  ### Module order
877
1079
  - \`moduleOrder\`: list **all** modules' names in the order they should appear on the page, including:
@@ -879,7 +1081,7 @@ ${i}
879
1081
  - any "Existing Modules to Keep" the user listed (these are not in \`modules\`, but still belong in \`moduleOrder\`)`),(!s||s.includes("content"))&&o.push(`
880
1082
 
881
1083
  ## Content & Copywriting Guide
882
- ${If()}`),n?.brandvoice&&o.push(`
1084
+ ${sh()}`),n?.brandvoice&&o.push(`
883
1085
 
884
1086
  ## Brand Voice
885
1087
  ${n.brandvoice}`),n?.themeContext&&o.push(`
@@ -888,7 +1090,63 @@ ${n.brandvoice}`),n?.themeContext&&o.push(`
888
1090
  ${n.themeContext}`),n?.humanify!==!1&&s?.includes("humanify")&&o.push(`
889
1091
 
890
1092
  ## Anti-AI Copy Rules
891
- ${Ef()}`),o.join("")}function Kl(){return`### Design Philosophy
1093
+ ${oh()}`),o.join("")}function Oc(){let t=Un(),e=Pc(t,"## 4. Color System","## 5."),n=Pc(t,"### Recommended Font Pairings","### Typography Scale"),s=[];return s.push(`### Step 1: Derive the aesthetic from the content
1094
+ Read the user's request carefully. What industry? What audience? What mood?
1095
+ Map it to ONE of these aesthetic directions \u2014 then commit fully:
1096
+
1097
+ | Business Type | Aesthetic | Color Direction | Font Mood |
1098
+ |--------------|-----------|----------------|-----------|
1099
+ | SaaS / Tech startup | Cool minimal or Bold tech | Blues, teals, electric purples, neon greens \u2014 COOL tones | Geometric sans or monospace |
1100
+ | Restaurant / Food | Warm editorial | Deep greens, burgundy, cream, terracotta \u2014 WARM but rich | Serif display + clean body |
1101
+ | Agency / Consultancy | Bold confident | Black + a single bold accent (red, orange, electric blue) | Strong geometric display |
1102
+ | E-commerce / DTC | Playful or Premium | Depends on product: pastels for beauty, dark for luxury, bright for fun | Varies \u2014 match the product vibe |
1103
+ | Finance / Legal | Dark luxury or Classic | Navy, charcoal, forest green, gold \u2014 DARK and authoritative | Classic serif or refined sans |
1104
+ | Health / Wellness | Soft organic | Sage, lavender, soft sky, warm sand \u2014 MUTED and calming | Rounded sans or warm serif |
1105
+ | Education / Non-profit | Warm and approachable | Warm blues, soft greens, sunny yellows \u2014 FRIENDLY | Humanist sans, readable |
1106
+ | Real estate / Architecture | Minimal luxe | Off-whites, charcoal, muted golds \u2014 MINIMAL | Thin geometric or editorial serif |
1107
+ | Developer tools / Data | Dark mode tech | Near-black bg, neon accent (cyan, lime, pink) \u2014 HIGH CONTRAST | Monospace display + clean sans body |
1108
+ | Creative / Portfolio | Expressive | Unexpected: magenta + teal, black + coral, deep purple + lime \u2014 BOLD | Anything distinctive |
1109
+ | Events / Entertainment | Energetic | Vibrant saturated colors, gradients OK \u2014 HIGH ENERGY | Bold display, fun pairings |
1110
+ | Local service / Trades | Trustworthy practical | Navy, forest green, or deep red with clean white \u2014 SOLID | Clean readable sans |
1111
+
1112
+ ### Step 2: Pick ORIGINAL colors
1113
+ Do NOT copy any palette you've seen before. Generate new hex values by:
1114
+ 1. Pick a background hue that fits the aesthetic (dark? warm white? cool gray? tinted?)
1115
+ 2. Pick a primary that CONTRASTS with the bg and matches the industry mood
1116
+ 3. Pick an accent that complements the primary (analogous, split-complementary, or triadic)
1117
+ 4. Derive surface, text, muted, border colors from these three anchors
1118
+ 5. Verify contrast: body text \u2265 4.5:1, large text \u2265 3:1 against their backgrounds
1119
+
1120
+ **BANNED combinations** (too common, feels like a template):
1121
+ - White bg + blue primary + light blue accent
1122
+ - White bg + purple/violet primary
1123
+ - Cream/beige bg + brown/orange primary + gold accent
1124
+ - Any combination you've generated in the last 10 sessions`),n&&s.push(`### Step 3: Choose fonts from the design guide
1125
+ These are ideal web font pairings. Since HubSpot CMS uses system fonts, pick the CLOSEST system font stack that matches the mood of the ideal pairing:
1126
+
1127
+ ${n}
1128
+
1129
+ **System font mapping** \u2014 use these to approximate the above:
1130
+ - Serif display (Playfair, Cormorant, Fraunces) \u2192 Georgia, Cambria, "Times New Roman", serif
1131
+ - Clean body serif (Source Serif) \u2192 Georgia, "Times New Roman", serif
1132
+ - Geometric sans (Satoshi, Outfit, Cabinet) \u2192 Futura, "Century Gothic", "Trebuchet MS", sans-serif
1133
+ - Modern sans (DM Sans, Plus Jakarta, General Sans) \u2192 system-ui, -apple-system, "Segoe UI", sans-serif
1134
+ - Humanist sans (Libre Franklin, Nunito) \u2192 Optima, Candara, "Noto Sans", sans-serif
1135
+ - Monospace (Space Mono, JetBrains) \u2192 "SF Mono", "Cascadia Code", "Fira Code", monospace
1136
+ - Bold display (Archivo Black, Bebas Neue, Syne) \u2192 Impact, "Arial Black", sans-serif
1137
+ - Classic serif (Book Antiqua) \u2192 "Book Antiqua", Palatino, "Palatino Linotype", serif
1138
+
1139
+ Choose the pairing that matches the MOOD of the content, not the same one every time.`),e&&s.push(`### Reference: Design Guide Color Philosophy
1140
+ ${e}`),s.push(`### Step 4: Verify uniqueness
1141
+ Before finalizing, ask yourself:
1142
+ - Would this palette look DIFFERENT from a page I just designed for a different topic?
1143
+ - Is the primary color something other than blue, brown, or purple?
1144
+ - Would the user be surprised (pleasantly) by this color choice?
1145
+ - Does the font pairing match the industry, not just "safe defaults"?
1146
+
1147
+ If any answer is "no," go bolder. The user wants personality, not safety.`),s.join(`
1148
+
1149
+ `)}function Pc(t,e,n){let s=t.indexOf(e);if(s===-1)return"";let o=t.indexOf(n,s);return o===-1?t.slice(s):t.slice(s,o).trim()}function Fc(){return`### Design Philosophy
892
1150
  You are a senior UI designer. Every page must look professionally designed, not like AI output.
893
1151
  Avoid "AI slop": purple gradients on white, cookie-cutter card grids, no personality.
894
1152
 
@@ -899,12 +1157,12 @@ Before designing, decide on:
899
1157
 
900
1158
  When a user gives a simple prompt like "build me a landing page for a coffee shop," internally expand it:
901
1159
  - Pick an aesthetic (warm, editorial, slightly vintage)
902
- - Pick specific colors (cream bg #faf7f2, espresso #3c1e0e, gold accent #c4956a)
1160
+ - Pick ORIGINAL colors derived from the topic (coffee \u2192 think espresso browns, cream tones, warm gold \u2014 but pick your own unique hex values every time)
903
1161
  - Decide hero style (full-bleed image background, overlaid text)
904
1162
  - Choose layout approach (asymmetric sections, large visual areas)
905
1163
  - Add texture (subtle paper/grain noise overlay)
906
1164
  - Set animations (scroll-triggered reveals)
907
- The user gives the "what," you decide the "how it should look and feel."
1165
+ The user gives the "what," you decide the "how it should look and feel." Every project gets a fresh, unique palette.
908
1166
 
909
1167
  ### Typography Scale
910
1168
  Include these in the CSS custom properties:
@@ -921,14 +1179,18 @@ letter-spacing: -0.02em to -0.04em for large headings (tighter = more premium)
921
1179
  ### Color Palettes
922
1180
  Pick a dominant (70%), secondary (25%), accent (5%). Ensure WCAG AA contrast (4.5:1 body, 3:1 large text).
923
1181
 
924
- \`\`\`
925
- DARK LUXURY: --bg: #0a0a0a; --surface: #141414; --text: #e8e8e8; --primary: #c9a84c; --accent: #e8d5a3
926
- WARM EARTH: --bg: #faf7f2; --surface: #f0ebe3; --text: #2d2418; --primary: #8b5e3c; --accent: #c4956a
927
- COOL MINIMAL: --bg: #fafafa; --surface: #f1f1f1; --text: #1a1a1a; --primary: #0055ff; --accent: #00c4ff
928
- FOREST: --bg: #0f1a0f; --surface: #1a2e1a; --text: #d4e8d0; --primary: #4ade80; --accent: #22c55e
929
- EDITORIAL CREAM:--bg: #fffdf5; --surface: #f5f0e8; --text: #1c1917; --primary: #dc2626; --accent: #f97316
930
- NOIR: --bg: #000000; --surface: #111111; --text: #ffffff; --primary: #ffffff; --accent: #666666
931
- \`\`\`
1182
+ **CRITICAL: Every project MUST have a unique palette derived from its specific content.** The palette should feel inevitable for the topic \u2014 like a designer hand-picked it for this exact business.
1183
+
1184
+ Derive colors from the CONTENT, not from defaults:
1185
+ - Read the topic/industry from the user's request
1186
+ - Think about what colors that industry evokes (coffee \u2192 deep browns; ocean resort \u2192 teals; cybersecurity \u2192 dark + neon)
1187
+ - Pick a bg, primary, and accent that tell that specific story
1188
+ - Never default to warm beige/brown/orange \u2014 that's only right for earthy/organic topics
1189
+
1190
+ **BANNED default combinations** (too commonly generated):
1191
+ - Cream/beige bg (#faf7f2 etc.) + brown primary + gold/orange accent \u2014 unless the topic is explicitly earthy (coffee, bakery, farmhouse)
1192
+ - White bg + blue primary + light blue accent \u2014 unless the topic is explicitly corporate/finance
1193
+ - Any palette with all warm tones (beige + brown + orange + gold) \u2014 mix temperature
932
1194
 
933
1195
  ### Layout Patterns
934
1196
  1. **Split hero**: Content left, visual right (50/50 or 60/40)
@@ -991,7 +1253,7 @@ Include these in shared CSS:
991
1253
  | All animations same speed | Stagger with increasing delays |
992
1254
  | Skip hover/focus states | Every interactive element needs feedback |
993
1255
  | Use \`<br>\` tags for spacing | Use proper margin/padding |
994
- | Put everything in a shadowed card | Vary: full-bleed, contained, floating |`}function If(){return`### Mandatory Page Sections (generate all)
1256
+ | Put everything in a shadowed card | Vary: full-bleed, contained, floating |`}function sh(){return`### Mandatory Page Sections (generate all)
995
1257
  1. **Navigation Bar** \u2014 Logo, 4-5 nav links, CTA button, sticky on scroll
996
1258
  2. **Hero** \u2014 Badge/pill, primary headline, subheadline, primary + secondary CTA, trust signals, visual element
997
1259
  3. **Social Proof Bar** \u2014 Logo strip of 4-6 clients OR stats bar (compact, py-8)
@@ -1079,7 +1341,7 @@ Alternate backgrounds every 2-3 sections to create visual "chapters." Sprinkle t
1079
1341
  - Invent plausible specifics: neighborhood names, "48 hours" not "quickly", "\u20AC49" not "affordable"
1080
1342
  - Keep paragraphs to 2-3 sentences max
1081
1343
  - Aim for 6th-grade reading level
1082
- - Include section labels (UPPERCASE, letter-spacing 0.1em, accent color, 2-3 words) above every headline`}function Ef(){return`### Banned Punctuation
1344
+ - Include section labels (UPPERCASE, letter-spacing 0.1em, accent color, 2-3 words) above every headline`}function oh(){return`### Banned Punctuation
1083
1345
  - **Em dashes (\u2014)**: NEVER use. Biggest AI tell. Replace with periods, commas, or parentheses.
1084
1346
  - **Semicolons**: Feel academic, not conversational. Use periods instead.
1085
1347
  - **Exclamation marks**: One per page maximum. Zero is ideal for B2B.
@@ -1109,38 +1371,387 @@ seamless, cutting-edge, groundbreaking, game-changer, revolutionary, transformat
1109
1371
  - Use plain short words: use > utilize, start > commence, help > facilitate
1110
1372
  - Vary sentence length aggressively: mix 3-word, 12-word, and 25-word sentences
1111
1373
  - Front-load the benefit in the first 5 words
1112
- - Write like you'd explain it in a bar \u2014 if you wouldn't say it holding a beer, rewrite it`}var Wl,zl,Yl=G(()=>{"use strict";g();Wl={type:"object",properties:{cssVariables:{type:"object",description:"CSS custom property name \u2192 value map. Every var() used in sharedCss must be defined here."},sharedCss:{type:"string",description:"Complete shared CSS file. MUST start with :root {} block defining all cssVariables, followed by reset, typography, layout, components, animations, and responsive styles."},sharedJs:{type:"string",description:"Optional shared JS for scroll animations (IntersectionObserver). Wrap in IIFE. Empty string if not needed."},aesthetic:{type:"string",description:"Brief description of the chosen aesthetic direction (e.g., 'dark luxury with warm gold accents')"}},required:["cssVariables","sharedCss","aesthetic"]};zl={type:"object",properties:{modules:{type:"array",items:{type:"object",properties:{name:{type:"string",description:"Module identifier. If this module already exists in the project, use the existing name verbatim. For new modules, use kebab-case (e.g., 'hero', 'pricing-cards')."},description:{type:"string",description:"What this module does"},contentBrief:{type:"string",description:"Specific content: headlines, body copy, stats, CTAs"},layoutNotes:{type:"string",description:"Visual layout approach referencing shared CSS classes"}},required:["name","description","contentBrief","layoutNotes"]}},moduleOrder:{type:"array",items:{type:"string"},description:"Module names in page display order"},narrative:{type:"string",description:"Brief description of the page story/flow"}},required:["modules","moduleOrder","narrative"]}});async function ql(e,t,n,s,o,i,r){r({type:"agent_step",step:"designing",label:"Creating design system..."});let a=s==="anthropic-api"||s==="claude-oauth",l=Li(n.themeName,n.brandAssets),c=a?Gl(n.themeName,n.brandAssets):void 0,d=`## User Request
1113
- ${e}`;n.modules.length>0&&t.designSystemChanges&&(d+=`
1374
+ - Write like you'd explain it in a bar \u2014 if you wouldn't say it holding a beer, rewrite it`}var dr,Nc,jc=R(()=>{"use strict";y();Ue();dr={type:"object",properties:{cssVariables:{type:"object",description:"CSS custom property name \u2192 value map. Every var() used in sharedCss must be defined here."},sharedCss:{type:"string",description:"Complete shared CSS file. MUST start with :root {} block defining all cssVariables, followed by reset, typography, layout, components, animations, and responsive styles."},sharedJs:{type:"string",description:"Optional shared JS for scroll animations (IntersectionObserver). Wrap in IIFE. Empty string if not needed."},aesthetic:{type:"string",description:"Brief description of the chosen aesthetic direction (e.g., 'dark luxury with warm gold accents')"}},required:["cssVariables","sharedCss","aesthetic"]};Nc={type:"object",properties:{modules:{type:"array",items:{type:"object",properties:{name:{type:"string",description:"Module identifier. If this module already exists in the project, use the existing name verbatim. For new modules, use kebab-case (e.g., 'hero', 'pricing-cards')."},description:{type:"string",description:"What this module does"},contentBrief:{type:"string",description:"Specific content: headlines, body copy, stats, CTAs"},layoutNotes:{type:"string",description:"Visual layout approach referencing shared CSS classes"}},required:["name","description","contentBrief","layoutNotes"]}},moduleOrder:{type:"array",items:{type:"string"},description:"Module names in page display order"},narrative:{type:"string",description:"Brief description of the page story/flow"}},required:["modules","moduleOrder","narrative"]}});function ur(t){if(!t)return"";let e=[];return t.colors&&(t.colors.primary&&e.push(`- Primary color: ${t.colors.primary}`),t.colors.secondary&&e.push(`- Secondary color: ${t.colors.secondary}`),t.colors.accent&&e.push(`- Accent color: ${t.colors.accent}`)),t.fonts&&(t.fonts.heading&&e.push(`- Heading font: ${t.fonts.heading}`),t.fonts.body&&e.push(`- Body font: ${t.fonts.body}`)),t.logoUrl&&e.push(`- Logo URL: ${t.logoUrl}`),e.length===0?"":`
1375
+
1376
+ ## Brand Kit \u2014 MANDATORY Design Constraints
1377
+ The following brand identity values MUST be used. Do NOT substitute or override them:
1378
+ ${e.join(`
1379
+ `)}`}function Ao(t,e){let n=[];n.push(`You are the Email Design Token Architect for vibeSpot, a HubSpot email template builder.
1380
+
1381
+ Your job: create a complete set of inline-safe design tokens for an email template. Email clients do NOT support CSS custom properties (var()), external stylesheets, flexbox, grid, or JavaScript. All styling must be inline.
1382
+
1383
+ You produce a token map (colors, fonts, sizes) and a style guide string that downstream email module developers will reference when writing inline styles.
1384
+
1385
+ ## Theme: "${t}"
1386
+
1387
+ ## Output Requirements
1388
+
1389
+ ### cssVariables
1390
+ A flat object mapping token names to literal CSS values. These are NOT CSS custom properties \u2014 they are a reference map for module developers to copy into inline styles. Use descriptive names:
1391
+
1392
+ **Colors** (choose original values that fit the topic \u2014 no default palette):
1393
+ - bg-color: email body background
1394
+ - content-bg: main content area background
1395
+ - text-color: primary text color
1396
+ - text-muted: secondary text color
1397
+ - text-light: light text for footers
1398
+ - heading-color: heading text color
1399
+ - primary-color: primary brand/CTA color
1400
+ - primary-hover: darker primary for button states
1401
+ - accent-color: accent/highlight color
1402
+ - border-color: divider/border color
1403
+ - footer-bg: footer background color
1404
+
1405
+ **Typography** (web-safe stacks only \u2014 pick the pairing that fits the mood):
1406
+ - font-heading: heading font stack
1407
+ - font-body: body font stack
1408
+ - size-h1: main heading size in px (e.g., "28px")
1409
+ - size-h2: section heading size in px (e.g., "22px")
1410
+ - size-h3: subheading size in px (e.g., "18px")
1411
+ - size-body: body text size in px (e.g., "16px")
1412
+ - size-small: small/footer text size in px (e.g., "13px")
1413
+ - line-height: body line height (e.g., "1.5")
1414
+
1415
+ **Spacing** (px only):
1416
+ - content-width: email content width (always "600")
1417
+ - padding-section: vertical section padding (e.g., "40")
1418
+ - padding-cell: cell padding (e.g., "20")
1419
+ - padding-button: button padding (e.g., "14px 32px")
1420
+
1421
+ ### sharedCss
1422
+ For email, this MUST be an empty string "". Email modules use inline styles only.
1423
+
1424
+ ### sharedJs
1425
+ MUST be omitted or empty string. No JavaScript in email.
1426
+
1427
+ ### aesthetic
1428
+ Brief description of the chosen email design direction (e.g., "clean professional with warm coral accents").
1429
+
1430
+ ## Email Design Rules \u2014 CRITICAL
1431
+
1432
+ ### Font Strategy
1433
+ Use ONLY web-safe font stacks. These are the only fonts guaranteed across email clients:
1434
+
1435
+ | Style | Stack |
1436
+ |-------|-------|
1437
+ | Sans-serif | Arial, Helvetica, sans-serif |
1438
+ | Serif | Georgia, "Times New Roman", Times, serif |
1439
+ | Modern sans | Verdana, Geneva, sans-serif |
1440
+ | Compact | Tahoma, Geneva, sans-serif |
1441
+ | Monospace | "Courier New", Courier, monospace |
1442
+
1443
+ Do NOT use: system-ui, -apple-system, Segoe UI, Inter, or any Google Fonts.
1444
+
1445
+ ### Color Rules
1446
+ - Use hex colors only (no rgb(), hsl(), or named colors)
1447
+ - Ensure WCAG AA contrast (4.5:1 for body text, 3:1 for large text)
1448
+ - CTA buttons need high contrast against both email body and content area backgrounds
1449
+ - Consider dark mode: some clients invert colors. Use medium-contrast ratios that work inverted.
1450
+
1451
+ ### Size Rules
1452
+ - All font sizes in px (never rem, em, or clamp())
1453
+ - Line heights as unitless numbers (1.5) or px values
1454
+ - Container width always 600px
1455
+ - Padding/margin in px only
1456
+ - Button padding generous: at least 12px vertical, 28px horizontal
1457
+
1458
+ ### What NOT to generate
1459
+ - No CSS custom properties (var())
1460
+ - No calc(), clamp(), or CSS functions
1461
+ - No @media queries (module developers may add progressive enhancement)
1462
+ - No animation, transition, or transform values
1463
+ - No box-shadow or text-shadow (poor email support)
1464
+ - No flexbox or grid references
1465
+ - No external font imports`),n.push(`
1466
+
1467
+ ## Email Design Guide
1468
+ ${Lc()}`),e?.styleguide&&n.push(`
1469
+
1470
+ ## Brand Style Guide
1471
+ ${e.styleguide}`),e?.themeContext&&n.push(`
1472
+
1473
+ ## Product Context
1474
+ ${e.themeContext}`);let s=ur(e?.brandKit);return s?n.push(s):e?.styleguide||n.push(`
1475
+
1476
+ ## No Brand Provided \u2014 Be Creative
1477
+ No brand colors or fonts have been set. Invent an original color palette that fits the email's topic and audience. Do NOT fall back to generic grays and blues. Choose web-safe font pairings (heading + body) that match the mood \u2014 vary between serif, sans-serif, and other stacks based on what fits.`),n.join("")}function mr(t,e){let n=Ao(t),o=n.indexOf(`
1478
+
1479
+ ## Email Design Guide
1480
+ `);if(o===-1)return[{type:"text",text:n}];let i=n.slice(0,o),r=`## Email Design Guide
1481
+ ${Lc()}`,a=[{type:"text",text:i},{type:"text",text:r,cache_control:{type:"ephemeral"}}],l=[];e?.styleguide&&l.push(`## Brand Style Guide
1482
+ ${e.styleguide}`),e?.themeContext&&l.push(`## Product Context
1483
+ ${e.themeContext}`);let c=ur(e?.brandKit);return c?l.push(c):e?.styleguide||l.push(`## No Brand Provided \u2014 Be Creative
1484
+ No brand colors or fonts have been set. Invent an original color palette that fits the email's topic and audience. Do NOT fall back to generic grays and blues. Choose web-safe font pairings (heading + body) that match the mood \u2014 vary between serif, sans-serif, and other stacks based on what fits.`),l.length>0&&a.push({type:"text",text:l.join(`
1485
+
1486
+ `)}),a}function Dc(t,e,n,s){let o=[],i=Object.entries(e).map(([a,l])=>` ${a}: ${l}`).join(`
1487
+ `);o.push(`You are the Email Module Planner for vibeSpot, a HubSpot email template builder.
1488
+
1489
+ Your job: plan the modules (sections) for an email template. You define what each section contains and how it should look. You do NOT write module code \u2014 downstream Email Module Developers handle that.
1490
+
1491
+ The Design Tokens have already been created. Your module plans MUST reference these tokens for consistent styling.
1492
+
1493
+ ## Theme: "${t}"
1494
+
1495
+ ## Design Tokens
1496
+ These literal values will be used in inline styles by module developers:
1497
+
1498
+ ${i}
1499
+
1500
+ ## Email Structure Rules
1501
+
1502
+ ### Standard Email Sections
1503
+ Plan modules from this list (use what fits the email type):
1504
+
1505
+ 1. **preheader** \u2014 Hidden preview text for inbox (always include)
1506
+ 2. **header** \u2014 Logo, optional nav links (keep simple)
1507
+ 3. **hero** \u2014 Main headline, hero image or illustration, primary CTA
1508
+ 4. **body-content** \u2014 Main message text, product details, or story
1509
+ 5. **features** / **highlights** \u2014 2-3 feature cards or product highlights
1510
+ 6. **cta-block** \u2014 Standalone call-to-action section
1511
+ 7. **testimonial** \u2014 Customer quote or social proof
1512
+ 8. **footer** \u2014 Unsubscribe link, physical address, social links (required by law)
1513
+
1514
+ ### Module Planning Rules
1515
+ - Every email MUST have: preheader, header, at least one content section, footer
1516
+ - Footer MUST include unsubscribe link and physical address (CAN-SPAM/GDPR)
1517
+ - Keep emails focused: 3-6 modules total (shorter emails perform better)
1518
+ - Each module is a self-contained table-based section
1519
+ - Module names: kebab-case identifiers (e.g., "hero", "feature-grid", "cta-block")
1520
+
1521
+ ### Content Briefs
1522
+ - Be specific about copy: write actual headlines, body text, CTA labels
1523
+ - Include placeholder image dimensions (e.g., "hero image 600x300")
1524
+ - Specify button copy with action verbs ("Shop the Collection", "Read the Full Story")
1525
+
1526
+ ### Layout Notes
1527
+ - All layouts are table-based (no flexbox/grid)
1528
+ - Reference design tokens by name (e.g., "Use primary-color for CTA background")
1529
+ - Specify alignment (center, left) and padding values
1530
+ - For multi-column sections: describe as "2-column table layout" or "3-column table layout"
1531
+ - Max content width: 600px (email standard)
1532
+
1533
+ ## Output Rules
1534
+
1535
+ ### modules array
1536
+ Each module needs: name, description, contentBrief, layoutNotes
1537
+
1538
+ ### moduleOrder
1539
+ List all module names in display order (top to bottom)
1540
+
1541
+ ### narrative
1542
+ One sentence describing the email's purpose and flow`),(!s||s.includes("content"))&&o.push(`
1543
+
1544
+ ## Email Content Guide
1545
+ ${ih()}`),n?.brandvoice&&o.push(`
1546
+
1547
+ ## Brand Voice
1548
+ ${n.brandvoice}`),n?.themeContext&&o.push(`
1549
+
1550
+ ## Product Context
1551
+ ${n.themeContext}`),n?.humanify!==!1&&s?.includes("humanify")&&o.push(`
1552
+
1553
+ ## Anti-AI Copy Rules
1554
+ ${rh()}`);let r=ur(n?.brandKit);return r&&o.push(r),o.join("")}function Lc(){return`### Email Design Philosophy
1555
+ Design for the inbox, not the browser. Email templates must look clean and professional in Gmail, Outlook, Apple Mail, and Yahoo Mail simultaneously.
1556
+
1557
+ ### Color Strategy
1558
+ - **Background**: light gray (#f4f4f4 to #eeeeee) for email body, white (#ffffff) for content area
1559
+ - **Text**: dark but not pure black (#333333 body, #1a1a1a headings) \u2014 pure black on white strains eyes
1560
+ - **CTA buttons**: high-saturation brand color, minimum 44px touch target height
1561
+ - **Dividers**: light borders (#e0e0e0 to #dddddd), 1px solid
1562
+
1563
+ ### Typography Strategy
1564
+ - Headings: 24-32px, bold, short line length (max 8 words)
1565
+ - Body: 15-17px (16px is the sweet spot), line-height 1.5-1.6
1566
+ - Small/legal: 12-13px, muted color
1567
+ - Button text: 15-17px, bold, uppercase optional
1568
+
1569
+ ### Layout Strategy
1570
+ - 600px container (fits all clients including Outlook desktop)
1571
+ - Single-column for mobile friendliness (stacks naturally)
1572
+ - 2-column max for feature grids (stack to 1-col on mobile)
1573
+ - Generous padding: 40-60px vertical between sections, 20-30px horizontal
1574
+ - White space is your friend \u2014 cramped emails get deleted
1575
+
1576
+ ### CTA Button Design
1577
+ - Minimum 44px height (touch target)
1578
+ - 14-16px vertical padding, 28-40px horizontal
1579
+ - Rounded corners via border-radius (degrades gracefully in Outlook)
1580
+ - VML fallback for Outlook (module developer handles this)
1581
+ - One primary CTA per email (secondary CTAs as text links)
1582
+
1583
+ ### Image Guidelines
1584
+ - Hero images: 600px wide, 2:1 to 3:1 aspect ratio
1585
+ - Always include alt text (images blocked by default in many clients)
1586
+ - Use display:block to prevent gaps in Outlook
1587
+ - Product images: consistent sizing within a row`}function ih(){return`### Email Types and Structure
1588
+
1589
+ **Welcome / Onboarding Email**
1590
+ - Warm greeting with first-name personalization
1591
+ - 1-2 sentence value reminder (why they signed up)
1592
+ - 3 numbered getting-started steps
1593
+ - Single primary CTA
1594
+ - Tone: friendly, concise, action-oriented
1595
+
1596
+ **Product Announcement**
1597
+ - Bold headline announcing the update
1598
+ - Hero image or product screenshot
1599
+ - 3-4 key benefits (not features \u2014 what it means for them)
1600
+ - Primary CTA to try/see the feature
1601
+ - Tone: excited but not breathless
1602
+
1603
+ **Newsletter / Digest**
1604
+ - Curated 3-5 content pieces with thumbnails
1605
+ - Brief summary (2-3 sentences) per item
1606
+ - "Read more" links per item + one main CTA
1607
+ - Tone: informative, scannable
1608
+
1609
+ **Event Invitation**
1610
+ - Event name, date, time, location (prominent)
1611
+ - 2-3 sentence description of value
1612
+ - Speaker/host info if applicable
1613
+ - Single "Register" / "RSVP" CTA
1614
+ - Tone: professional, creates urgency without hype
1615
+
1616
+ **Re-engagement**
1617
+ - Acknowledge the absence directly ("We miss you")
1618
+ - Highlight what they're missing (new features, content)
1619
+ - Incentive if applicable (discount, free resource)
1620
+ - Single "Come back" CTA
1621
+ - Tone: genuine, no guilt-tripping
1622
+
1623
+ ### Subject Line & Preheader
1624
+ - Subject: 6-10 words, specific benefit or curiosity gap
1625
+ - Preheader: extends the subject line, 40-90 characters
1626
+ - Do NOT repeat the subject line in the preheader
1627
+
1628
+ ### Email Copy Rules
1629
+ - Front-load the key message in the first 2 sentences
1630
+ - One idea per paragraph, 2-3 sentences max
1631
+ - Use "you" more than "we"
1632
+ - Specific > vague: "saves 3 hours/week" beats "saves time"
1633
+ - CTA copy = verb + benefit: "Start Your Trial", "See the Results"`}function rh(){return`### Email-Specific Anti-AI Rules
1634
+ - No em dashes (\u2014) in email copy. Period.
1635
+ - No "I hope this email finds you well"
1636
+ - No "In today's fast-paced world"
1637
+ - No "We're thrilled/excited/delighted to announce"
1638
+ - Open with the point, not a preamble
1639
+ - One exclamation mark per email maximum
1640
+ - Avoid tricolon structures ("Fast, reliable, secure")
1641
+ - Write like a colleague, not a press release
1642
+ - Every sentence must earn its place \u2014 if removing it doesn't hurt, remove it`}var pr,Jc=R(()=>{"use strict";y();pr={type:"object",properties:{cssVariables:{type:"object",description:"Token name \u2192 literal CSS value map. NOT CSS custom properties. These are reference values for inline styles (e.g., 'bg-color': '#f4f4f4', 'font-body': 'Arial, Helvetica, sans-serif')."},sharedCss:{type:"string",description:"MUST be empty string for email templates. Email uses inline styles only."},sharedJs:{type:"string",description:"MUST be empty string for email templates. No JavaScript in email."},aesthetic:{type:"string",description:"Brief description of the chosen email design direction."}},required:["cssVariables","sharedCss","aesthetic"]}});async function Bc(t,e,n,s,o,i,r){let a=e.contentType==="email";r({type:"agent_step",step:"designing",label:a?"Creating email design tokens...":"Creating design system..."});let l=s==="anthropic-api"||s==="claude-oauth",c=a?Ao(n.themeName,n.brandAssets):To(n.themeName,n.brandAssets),d=l?a?mr(n.themeName,n.brandAssets):cr(n.themeName,n.brandAssets):void 0,u=`## User Request
1643
+ ${t}`;n.modules.length>0&&e.designSystemChanges&&(u+=`
1644
+
1645
+ ## Current Shared CSS (update this)
1646
+ \`\`\`css
1647
+ ${n.sharedCss}
1648
+ \`\`\``);let m=Sn(s),h=await _e(s,o,i,{systemPrompt:c,systemBlocks:d,messages:[{role:"user",content:u}],structuredOutput:{schema:a?pr:dr,name:"design_system"},maxTokens:16e3,...m>0?{thinkingBudgetTokens:m}:{}}),f;h.type!=="structured"?(E.warn("page-architect","Design system: did not get structured output, using fallback"),f={cssVariables:{},sharedCss:n.sharedCss||"",sharedJs:n.sharedJs||"",aesthetic:"default"}):(f=h.data,E.info("page-architect","Design system created",{aesthetic:f.aesthetic,varCount:Object.keys(f.cssVariables||{}).length,cssLength:f.sharedCss?.length||0}));let b=a?"":f.sharedCss||"",S=f.cssVariables;!a&&S&&typeof S=="object"&&Object.keys(S).length>0&&(b.includes(":root")||(b=`:root {
1649
+ ${Object.entries(S).map(([F,H])=>` ${F.startsWith("--")?F:`--${F}`}: ${H};`).join(`
1650
+ `)}
1651
+ }
1652
+
1653
+ ${b}`));let x=Object.keys(S||{}).length,w=a?[`Email design tokens: ${f.aesthetic||"created"} | ${x} tokens`]:[`Design system: ${f.aesthetic||"created"} | ${x} variables, ${b.length} chars CSS`];return r({type:"agent_decision",step:"designing",decision:w.join(`
1654
+ `)}),r({type:"design_system_ready",sharedCss:b,sharedJs:f.sharedJs||"",aesthetic:f.aesthetic||""}),{...f,sharedCss:b}}async function Hc(t,e,n,s,o,i,r){let a=e.contentType==="email";r({type:"agent_step",step:"designing",label:a?"Creating email design tokens...":"Creating design system..."});let l=s==="anthropic-api"||s==="claude-oauth",c=a?Ao(n.themeName,n.brandAssets):To(n.themeName,n.brandAssets),d=l?a?mr(n.themeName,n.brandAssets):cr(n.themeName,n.brandAssets):void 0,u=`## User Request
1655
+ ${t}`;n.modules.length>0&&e.designSystemChanges&&(u+=`
1114
1656
 
1115
1657
  ## Current Shared CSS (update this)
1116
1658
  \`\`\`css
1117
1659
  ${n.sharedCss}
1118
- \`\`\``);let u=Ji(s),m=await Re(s,o,i,{systemPrompt:l,systemBlocks:c,messages:[{role:"user",content:d}],structuredOutput:{schema:Wl,name:"design_system"},maxTokens:16e3,...u>0?{thinkingBudgetTokens:u}:{}}),f;m.type!=="structured"?(E.warn("page-architect","Design system: did not get structured output, using fallback"),f={cssVariables:{},sharedCss:n.sharedCss||"",sharedJs:n.sharedJs||"",aesthetic:"default"}):(f=m.data,E.info("page-architect","Design system created",{aesthetic:f.aesthetic,varCount:Object.keys(f.cssVariables||{}).length,cssLength:f.sharedCss?.length||0}));let y=f.sharedCss||"",h=f.cssVariables;h&&typeof h=="object"&&Object.keys(h).length>0&&(y.includes(":root")||(y=`:root {
1119
- ${Object.entries(h).map(([j,k])=>` ${j.startsWith("--")?j:`--${j}`}: ${k};`).join(`
1660
+ \`\`\``);let m=Sn(s),h=await _e(s,o,i,{systemPrompt:c,systemBlocks:d,messages:[{role:"user",content:u}],structuredOutput:{schema:a?pr:dr,name:"design_system"},maxTokens:16e3,...m>0?{thinkingBudgetTokens:m}:{}}),f;h.type!=="structured"?(E.warn("page-architect","Design system: did not get structured output, using fallback"),f={cssVariables:{},sharedCss:n.sharedCss||"",sharedJs:n.sharedJs||"",aesthetic:"default"}):(f=h.data,E.info("page-architect","Design system created",{aesthetic:f.aesthetic,varCount:Object.keys(f.cssVariables||{}).length,cssLength:f.sharedCss?.length||0}));let b=a?"":f.sharedCss||"",S=f.cssVariables;!a&&S&&typeof S=="object"&&Object.keys(S).length>0&&(b.includes(":root")||(b=`:root {
1661
+ ${Object.entries(S).map(([k,K])=>` ${k.startsWith("--")?k:`--${k}`}: ${K};`).join(`
1120
1662
  `)}
1121
1663
  }
1122
1664
 
1123
- ${y}`));let S=[],x=/\b(Montserrat|Inter|Poppins|Raleway|Playfair|Lato|Roboto|Open\s?Sans|Nunito|Merriweather|Oswald|Source\s?Sans|Fira\s?Sans|Work\s?Sans|Manrope|Plus\s?Jakarta)\b/gi,w=[...new Set((e.match(x)||[]).map(_=>_.trim()))];if(w.length>0){let _=w.filter(k=>y.toLowerCase().includes(k.toLowerCase())),j=w.filter(k=>!_.includes(k));j.length>0&&S.push(`Note: ${j.join(", ")} not available \u2014 HubSpot modules use system font stacks (no external font imports allowed)`)}let v=[`Design system: ${f.aesthetic||"created"} | ${Object.keys(h||{}).length} variables, ${y.length} chars CSS`,...S];r({type:"agent_decision",step:"designing",decision:v.join(`
1124
- `)}),r({type:"design_system_ready",sharedCss:y,sharedJs:f.sharedJs||"",aesthetic:f.aesthetic||""}),r({type:"agent_step",step:"designing",label:"Planning modules..."});let N=Vl(n.themeName,y,n.brandAssets,t.guidesNeeded),O=`## User Request
1125
- ${e}`;if(t.newModules.length>0&&(O+=`
1665
+ ${b}`));let x=[],w=/\b(Montserrat|Inter|Poppins|Raleway|Playfair|Lato|Roboto|Open\s?Sans|Nunito|Merriweather|Oswald|Source\s?Sans|Fira\s?Sans|Work\s?Sans|Manrope|Plus\s?Jakarta)\b/gi,P=[...new Set((t.match(w)||[]).map(I=>I.trim()))];if(P.length>0){let I=P.filter(K=>b.toLowerCase().includes(K.toLowerCase())),k=P.filter(K=>!I.includes(K));k.length>0&&x.push(`Note: ${k.join(", ")} not available \u2014 HubSpot modules use system font stacks (no external font imports allowed)`)}let F=Object.keys(S||{}).length,H=a?[`Email design tokens: ${f.aesthetic||"created"} | ${F} tokens`]:[`Design system: ${f.aesthetic||"created"} | ${F} variables, ${b.length} chars CSS`,...x];r({type:"agent_decision",step:"designing",decision:H.join(`
1666
+ `)}),r({type:"design_system_ready",sharedCss:b,sharedJs:f.sharedJs||"",aesthetic:f.aesthetic||""}),r({type:"agent_step",step:"designing",label:"Planning modules..."});let L=a?Dc(n.themeName,S||{},n.brandAssets,e.guidesNeeded):Rc(n.themeName,b,n.brandAssets,e.guidesNeeded),V=`## User Request
1667
+ ${t}`;if(e.newModules.length>0&&(V+=`
1126
1668
 
1127
1669
  ## Planned Modules
1128
- ${t.newModules.map((_,j)=>`${j+1}. **${_.name}** \u2014 ${_.description}`).join(`
1129
- `)}`),n.modules.length>0){let _=new Set(t.affectedModules),j=n.modules.filter(M=>_.has(M.moduleName)),k=n.modules.filter(M=>!_.has(M.moduleName));j.length>0&&(O+=`
1670
+ ${e.newModules.map((I,k)=>`${k+1}. **${I.name}** \u2014 ${I.description}`).join(`
1671
+ `)}`),n.modules.length>0){let I=new Set(e.affectedModules),k=n.modules.filter(oe=>I.has(oe.moduleName)),K=n.modules.filter(oe=>!I.has(oe.moduleName));k.length>0&&(V+=`
1130
1672
 
1131
1673
  ## Existing Modules to Re-plan (PRESERVE THESE EXACT NAMES)
1132
1674
  These already exist and are being regenerated. Your output's module names MUST match these exactly \u2014 do NOT rename, retitle-case, or "improve" them. Their content/layout may change; their identifier must not.
1133
- `+j.map(M=>`- \`${M.moduleName}\``).join(`
1134
- `)),k.length>0&&(O+=`
1675
+ `+k.map(oe=>`- \`${oe.moduleName}\``).join(`
1676
+ `)),K.length>0&&(V+=`
1135
1677
 
1136
1678
  ## Existing Modules to Keep (do not re-plan)
1137
1679
  These stay as-is. Do NOT include them in your output. They will appear in the final \`moduleOrder\` (you can reference them by name when you list it).
1138
- `+k.map(M=>`- \`${M.moduleName}\``).join(`
1139
- `))}let F=await Re(s,o,i,{systemPrompt:N,messages:[{role:"user",content:O}],structuredOutput:{schema:zl,name:"module_plan"},maxTokens:8e3,...u>0?{thinkingBudgetTokens:u}:{}}),U,q={modules:t.newModules.map(_=>({name:_.name,description:_.description,contentBrief:"Generate appropriate content",layoutNotes:"Use responsive layout"})),moduleOrder:t.newModules.map(_=>_.name),narrative:"Page generated from user request"};if(F.type!=="structured")E.warn("page-architect","Module planner: did not get structured output, using fallback"),U=q;else{let _=F.data;Array.isArray(_?.modules)&&_.modules.length>0?(U=_,U.moduleOrder=U.moduleOrder||U.modules.map(j=>j.name),U.narrative=U.narrative||"Page generated from user request"):(E.warn("page-architect","Module planner: structured output missing 'modules' array, using fallback",{keys:_?Object.keys(_):[]}),U=q),E.info("page-architect","Module plan",{moduleCount:U.modules.length})}return r({type:"agent_decision",step:"designing",decision:`Page: ${U.narrative} | ${U.modules.length} modules planned`}),{designSystem:{cssVariables:f.cssVariables||{},sharedCss:y,sharedJs:f.sharedJs},modules:U.modules,moduleOrder:U.moduleOrder,narrative:U.narrative}}var Xl=G(()=>{"use strict";g();nt();Yl();re()});function so(e){let t=0,n=[];return async function(o){t>=e&&await new Promise(i=>n.push(i)),t++;try{return await o()}finally{t--,n.length>0&&n.shift()()}}}var Hi=G(()=>{"use strict";g()});function Bn(e,t,n,s){let o=[];return o.push(`You are a Module Developer for vibeSpot, a HubSpot CMS page builder.
1680
+ `+K.map(oe=>`- \`${oe.moduleName}\``).join(`
1681
+ `))}let B=await _e(s,o,i,{systemPrompt:L,messages:[{role:"user",content:V}],structuredOutput:{schema:Nc,name:"module_plan"},maxTokens:8e3,...m>0?{thinkingBudgetTokens:m}:{}}),N,T={modules:e.newModules.map(I=>({name:I.name,description:I.description,contentBrief:"Generate appropriate content",layoutNotes:"Use responsive layout"})),moduleOrder:e.newModules.map(I=>I.name),narrative:"Page generated from user request"};if(B.type!=="structured")E.warn("page-architect","Module planner: did not get structured output, using fallback"),N=T;else{let I=B.data;Array.isArray(I?.modules)&&I.modules.length>0?(N=I,N.moduleOrder=N.moduleOrder||N.modules.map(k=>k.name),N.narrative=N.narrative||"Page generated from user request"):(E.warn("page-architect","Module planner: structured output missing 'modules' array, using fallback",{keys:I?Object.keys(I):[]}),N=T),E.info("page-architect","Module plan",{moduleCount:N.modules.length})}return r({type:"agent_decision",step:"designing",decision:`Page: ${N.narrative} | ${N.modules.length} modules planned`}),{designSystem:{cssVariables:f.cssVariables||{},sharedCss:b,sharedJs:f.sharedJs},modules:N.modules,moduleOrder:N.moduleOrder,narrative:N.narrative}}var Uc=R(()=>{"use strict";y();nt();jc();Jc();de()});function ah(t){let e=[...new Set([...t.matchAll(/\.([a-zA-Z][\w-]*)/g)].map(i=>`.${i[1]}`))],n=[...new Set([...t.matchAll(/(--[\w-]+)\s*:/g)].map(i=>i[1]))],s=[...new Set([...t.matchAll(/@media\s*\([^)]+\)/g)].map(i=>i[0]))],o=[];return n.length>0&&o.push(`CSS Variables: ${n.join(", ")}`),e.length>0&&o.push(`CSS Classes: ${e.join(", ")}`),s.length>0&&o.push(`Breakpoints: ${s.join(", ")}`),o.join(`
1682
+ `)}function Gc(t,e,n,s,o){let i=ah(s),r=e.map(c=>`- **${c.label}** (${c.pageType}, slug: "${c.slug}"): ${c.purpose}`).join(`
1683
+ `),a=n.map(c=>`- **${c}**`).join(`
1684
+ `),l=[];return l.push(`You are the Site Module Planner for vibeSpot, a HubSpot CMS page builder.
1685
+
1686
+ Your job: plan modules for a MULTI-PAGE website. You plan ALL pages in one pass to ensure cross-page coherence. You also plan shared modules (header, footer, navigation) that appear on every page identically.
1687
+
1688
+ ## Theme: "${t}"
1689
+
1690
+ ## Site Map
1691
+ ${r}
1692
+
1693
+ ## Shared Modules (appear on EVERY page)
1694
+ ${a}
1695
+
1696
+ Plan these shared modules ONCE. They will be automatically added to every page's template.
1697
+
1698
+ ## Available CSS Classes & Variables
1699
+ Reference these in your layoutNotes:
1700
+
1701
+ ${i}
1702
+
1703
+ ## Shared Module Rules
1704
+
1705
+ ### site-header (Navigation)
1706
+ - Logo on the left, nav links center or right, CTA button far right
1707
+ - Nav links: one for each page in the site map. Use relative hrefs matching slugs:
1708
+ ${e.map(c=>` - "${c.label}" \u2192 href="/${c.slug}"`).join(`
1709
+ `)}
1710
+ - Active page link uses CSS class "${t}-nav__link--active"
1711
+ - Sticky with backdrop-blur, transitions on scroll
1712
+ - Mobile: hamburger menu with slide-in nav
1713
+
1714
+ ### site-footer
1715
+ - Consistent across all pages
1716
+ - Brand name, link columns (include page links), contact info, social icons, copyright
1717
+ - Include navigation links matching the header
1718
+
1719
+ ## Per-Page Module Rules
1720
+ For each page, plan modules specific to that page's purpose. Do NOT include shared modules (${n.join(", ")}) in per-page module lists or per-page moduleOrder \u2014 they are automatically prepended/appended.
1721
+
1722
+ Each page should have distinct content appropriate to its purpose. Aim for:
1723
+ - 4-8 unique modules per page (not counting shared modules)
1724
+ - Content appropriate to the page's purpose
1725
+ - Consistent use of design system classes across all pages
1726
+
1727
+ ## Module Naming
1728
+ - Use kebab-case identifiers (e.g., "hero", "team-grid", "contact-form")
1729
+ - Page-specific modules that might conflict across pages should be prefixed with a short page identifier (e.g., "home-hero", "about-hero") unless the content is genuinely different enough that the name alone distinguishes it
1730
+ - Shared modules use the exact names from the shared modules list above
1731
+
1732
+ ## Output Structure
1733
+ Return a JSON object with:
1734
+ - \`sharedModules\`: array of shared module specs (planned once, used everywhere)
1735
+ - \`pages\`: array of per-page blueprints, each with:
1736
+ - \`pageId\`: matching the page ID from the site map
1737
+ - \`modules\`: array of module specs for that page only (excluding shared)
1738
+ - \`moduleOrder\`: ordered list of per-page module names only (excluding shared)
1739
+ - \`narrative\`: brief description of the overall site story/flow`),o?.brandvoice&&l.push(`
1740
+
1741
+ ## Brand Voice
1742
+ ${o.brandvoice}`),o?.themeContext&&l.push(`
1743
+
1744
+ ## Product Context
1745
+ ${o.themeContext}`),l.join("")}var Wc,Kc=R(()=>{"use strict";y();Wc={type:"object",properties:{sharedModules:{type:"array",items:{type:"object",properties:{name:{type:"string",description:"Shared module identifier (e.g., site-header, site-footer)"},description:{type:"string"},contentBrief:{type:"string",description:"Content for this shared module"},layoutNotes:{type:"string",description:"Layout referencing shared CSS classes"}},required:["name","description","contentBrief","layoutNotes"]},description:"Modules shared across all pages (header, footer)"},pages:{type:"array",items:{type:"object",properties:{pageId:{type:"string",description:"Matches the page ID from the site map"},modules:{type:"array",items:{type:"object",properties:{name:{type:"string"},description:{type:"string"},contentBrief:{type:"string"},layoutNotes:{type:"string"}},required:["name","description","contentBrief","layoutNotes"]}},moduleOrder:{type:"array",items:{type:"string"},description:"Per-page module names in display order (excluding shared modules)"}},required:["pageId","modules","moduleOrder"]}},narrative:{type:"string",description:"Brief description of the overall site story and how pages connect"}},required:["sharedModules","pages","narrative"]}});async function zc(t,e,n,s,o,i,r,a){a({type:"agent_step",step:"planning_site",label:`Planning modules for ${e.pages?.length||0} pages...`});let l=e.pages||[],c=e.sharedModules||["site-header","site-footer"],d=Gc(n.themeName,l,c,s,n.brandAssets),u=`## User Request
1746
+ ${t}
1747
+
1748
+ ## Site Map
1749
+ ${l.map(x=>`- ${x.label} (${x.slug}): ${x.purpose}`).join(`
1750
+ `)}`,m=Sn(o),g=await _e(o,i,r,{systemPrompt:d,messages:[{role:"user",content:u}],structuredOutput:{schema:Wc,name:"site_module_plan"},maxTokens:16e3,...m>0?{thinkingBudgetTokens:m}:{}});if(g.type!=="structured")return E.warn("site-planner","Did not get structured output, building fallback"),Vc(e,c,s);let h=g.data;if(!Array.isArray(h?.pages)||!Array.isArray(h?.sharedModules))return E.warn("site-planner","Structured output missing expected fields",{keys:h?Object.keys(h):[]}),Vc(e,c,s);let f=h.sharedModules.map(x=>({name:x.name,description:x.description,contentBrief:x.contentBrief,layoutNotes:x.layoutNotes})),b=h.pages.map(x=>({pageId:x.pageId,modules:(x.modules||[]).map(w=>({name:w.name,description:w.description,contentBrief:w.contentBrief,layoutNotes:w.layoutNotes})),moduleOrder:x.moduleOrder||[]})),S=f.length+b.reduce((x,w)=>x+w.modules.length,0);return E.info("site-planner","Site plan complete",{pages:b.length,sharedModules:f.length,totalModules:S}),a({type:"agent_decision",step:"planning_site",decision:`${b.length} pages planned, ${f.length} shared modules, ${S} total modules`}),a({type:"site_blueprint_ready",pages:b.map(x=>{let w=l.find(P=>P.id===x.pageId);return{pageId:x.pageId,label:w?.label||x.pageId,moduleCount:x.modules.length}}),sharedModuleCount:f.length}),{designSystem:{cssVariables:{},sharedCss:s},pages:b,sharedModules:f,narrative:h.narrative||"Multi-page site generated from user request"}}function Vc(t,e,n){let s=t.pages||[];return{designSystem:{cssVariables:{},sharedCss:n},pages:s.map(o=>({pageId:o.id,modules:[{name:`${o.slug}-hero`,description:`Hero section for ${o.label}`,contentBrief:`Create a hero for the ${o.label} page: ${o.purpose}`,layoutNotes:"Use responsive layout matching the design system"},{name:`${o.slug}-content`,description:`Main content for ${o.label}`,contentBrief:`Create main content for the ${o.label} page: ${o.purpose}`,layoutNotes:"Use responsive layout matching the design system"}],moduleOrder:[`${o.slug}-hero`,`${o.slug}-content`]})),sharedModules:e.map(o=>({name:o,description:`Shared ${o} module`,contentBrief:`Generate ${o} for the site`,layoutNotes:"Use responsive layout matching the design system"})),narrative:"Multi-page site (fallback plan)"}}var Yc=R(()=>{"use strict";y();nt();Kc();de()});function $o(t){let e=0,n=[];return async function(o){e>=t&&await new Promise(i=>n.push(i)),e++;try{return await o()}finally{e--,n.length>0&&n.shift()()}}}var gr=R(()=>{"use strict";y()});function as(t,e,n,s){let o=[];return o.push(`You are a Module Developer for vibeSpot, a HubSpot CMS page builder.
1140
1751
 
1141
1752
  Your job: generate ONE HubSpot CMS module. You receive a module specification and must produce the complete module code.
1142
1753
 
1143
- ## Theme: "${e}"
1754
+ ## Theme: "${t}"
1144
1755
 
1145
1756
  ## Output Rules \u2014 CRITICAL
1146
1757
  You produce a single module with these fields:
@@ -1152,8 +1763,8 @@ You produce a single module with these fields:
1152
1763
  - **moduleJs**: Optional vanilla JS wrapped in IIFE, or null
1153
1764
 
1154
1765
  ## CSS Rules
1155
- - All CSS classes must use prefix "${e}-"
1156
- - Use BEM naming: ${e}-moduleName__element--modifier
1766
+ - All CSS classes must use prefix "${t}-"
1767
+ - Use BEM naming: ${t}-moduleName__element--modifier
1157
1768
  - Reference the theme's CSS custom properties (shown below)
1158
1769
  - No CDN imports (@import url(), external <link> tags)
1159
1770
  - Use system font stacks \u2014 no Google Fonts
@@ -1170,7 +1781,7 @@ You produce a single module with these fields:
1170
1781
  - For repeater groups, use "occurrence": { "min": 0, "max": 100 }
1171
1782
 
1172
1783
  ## Images & Assets
1173
- - Use get_asset_url("${e}/assets/filename.ext") for uploaded assets
1784
+ - Use get_asset_url("${t}/assets/filename.ext") for uploaded assets
1174
1785
  - For placeholder images, use image fields with placehold.co defaults
1175
1786
  - Size placeholders appropriately (hero: 1920x800, cards: 600x400, icons: 200x200)
1176
1787
 
@@ -1180,37 +1791,37 @@ You produce a single module with these fields:
1180
1791
  - Include smooth scroll behavior in nav click handlers
1181
1792
 
1182
1793
  ## metaJson Template
1183
- { "host_template_types": ["PAGE"], "is_available_for_new_content": true }`),t&&o.push(`
1794
+ { "host_template_types": ["PAGE"], "is_available_for_new_content": true }`),e&&o.push(`
1184
1795
 
1185
1796
  ## Theme Shared CSS (use these custom properties)
1186
1797
  \`\`\`css
1187
- ${t}
1798
+ ${e}
1188
1799
  \`\`\``),(!n||n.includes("hubspot_rules"))&&o.push(`
1189
1800
 
1190
1801
  ## HubSpot CMS Rules
1191
- ${He()}`),(!n||n.includes("conversion"))&&o.push(`
1802
+ ${je()}`),(!n||n.includes("conversion"))&&o.push(`
1192
1803
 
1193
1804
  ## Conversion Guide
1194
- ${ge()}`),s?.themeContext&&o.push(`
1805
+ ${fe()}`),s?.themeContext&&o.push(`
1195
1806
 
1196
1807
  ## Product Context
1197
1808
  ${s.themeContext}`),s?.humanify!==!1&&n?.includes("humanify")&&o.push(`
1198
1809
 
1199
1810
  ## Anti-AI Copy Rules
1200
- ${Zl()}`),o.join("")}function oo(e,t,n,s){let o=[],i=Bn(e,"",[],s?{...s,humanify:!1}:void 0);t&&(i+=`
1811
+ ${qc()}`),o.join("")}function _o(t,e,n,s){let o=[],i=as(t,"",[],s?{...s,humanify:!1}:void 0);e&&(i+=`
1201
1812
 
1202
1813
  ## Theme Shared CSS (use these custom properties)
1203
1814
  \`\`\`css
1204
- ${t}
1815
+ ${e}
1205
1816
  \`\`\``),o.push({type:"text",text:i});let r=[];(!n||n.includes("hubspot_rules"))&&r.push(`## HubSpot CMS Rules
1206
- ${He()}`),(!n||n.includes("conversion"))&&r.push(`## Conversion Guide
1207
- ${ge()}`),r.length>0&&o.push({type:"text",text:r.join(`
1817
+ ${je()}`),(!n||n.includes("conversion"))&&r.push(`## Conversion Guide
1818
+ ${fe()}`),r.length>0&&o.push({type:"text",text:r.join(`
1208
1819
 
1209
1820
  `),cache_control:{type:"ephemeral"}});let a=[];return s?.themeContext&&a.push(`## Product Context
1210
1821
  ${s.themeContext}`),s?.humanify!==!1&&n?.includes("humanify")&&a.push(`## Anti-AI Copy Rules
1211
- ${Zl()}`),a.length>0&&o.push({type:"text",text:a.join(`
1822
+ ${qc()}`),a.length>0&&o.push({type:"text",text:a.join(`
1212
1823
 
1213
- `)}),o}function Zl(){return`### Banned Punctuation
1824
+ `)}),o}function qc(){return`### Banned Punctuation
1214
1825
  - **Em dashes (\u2014)**: NEVER use. Replace with periods, commas, or parentheses. Hyphens for compounds fine.
1215
1826
  - **Semicolons**: Use periods instead in marketing copy.
1216
1827
  - **Exclamation marks**: One per page max. Zero ideal for B2B.
@@ -1249,14 +1860,14 @@ Never end with: "The future of [X] is here", "Your journey starts here", "Join t
1249
1860
  - Keep slightly imperfect (fragments OK, mild hedging like "honestly didn't think")
1250
1861
  - Full names, specific roles (not "John D., CEO")
1251
1862
  - Never start with "This product is..." \u2014 start with the person's situation
1252
- - Vary length and voice across testimonials`}function Ql(e,t,n){let s=[];return s.push(`## User Request
1253
- ${e}`),s.push(`
1863
+ - Vary length and voice across testimonials`}function Xc(t,e,n){let s=[];return s.push(`## User Request
1864
+ ${t}`),s.push(`
1254
1865
 
1255
1866
  ## Module Specification
1256
- - **Name**: ${t.name}
1257
- - **Description**: ${t.description}
1258
- - **Content Brief**: ${t.contentBrief}
1259
- - **Layout Notes**: ${t.layoutNotes}`),n&&(s.push(`
1867
+ - **Name**: ${e.name}
1868
+ - **Description**: ${e.description}
1869
+ - **Content Brief**: ${e.contentBrief}
1870
+ - **Layout Notes**: ${e.layoutNotes}`),n&&(s.push(`
1260
1871
 
1261
1872
  ## Existing Module Code (modify this)
1262
1873
  **fields.json:**
@@ -1276,21 +1887,487 @@ ${n.moduleCss}
1276
1887
  **module.js:**
1277
1888
  \`\`\`js
1278
1889
  ${n.moduleJs}
1279
- \`\`\``)),s.join("")}var io,Bi=G(()=>{"use strict";g();ut();io={type:"object",properties:{moduleName:{type:"string"},fieldsJson:{type:"string",description:"Complete fields.json content as a JSON string"},metaJson:{type:"string",description:"Complete meta.json content as a JSON string"},moduleHtml:{type:"string",description:"Complete module.html HubL template content"},moduleCss:{type:"string",description:"Complete module.css vanilla CSS content"},moduleJs:{type:"string",description:"Optional module.js vanilla JS content, or empty string if not needed"}},required:["moduleName","fieldsJson","metaJson","moduleHtml","moduleCss"]}});async function ec(e,t,n,s,o,i,r,a,l,c,d){l({type:"agent_step",step:"developing",label:`Generating ${t.length} module${t.length===1?"":"s"}...`});let u=o==="anthropic-api"||o==="claude-oauth",m=Bn(s,n,c,d),f=u?oo(s,n,c,d):void 0,y=so(a),h=t.length,S=t.map((w,v)=>y(async()=>{l({type:"module_progress",module:w.name,status:"generating",current:v+1,total:h});let N="";for(let O=0;O<2;O++)try{O>0&&(E.warn("module-developer",`${w.name}: retrying after failure (attempt ${O+1})`),l({type:"module_progress",module:w.name,status:"retrying",current:v+1,total:h}));let F=await tc(e,w,m,o,i,r,0,f);return l({type:"module_progress",module:w.name,status:"complete",current:v+1,total:h,moduleFiles:F}),{moduleName:w.name,module:F}}catch(F){N=F instanceof Error?F.message:typeof F=="object"&&F!==null?JSON.stringify(F):String(F),E.error("module-developer",`Failed: ${w.name} (attempt ${O+1})`,{error:N})}return l({type:"module_progress",module:w.name,status:"failed",current:v+1,total:h}),{moduleName:w.name,error:N}}));return(await Promise.allSettled(S)).map(w=>w.status==="fulfilled"?w.value:{moduleName:"unknown",error:w.reason instanceof Error?w.reason.message:String(w.reason)})}async function tc(e,t,n,s,o,i,r=0,a){let l=Ql(e,t,t.existingCode),c=await Re(s,o,i,{systemPrompt:n,systemBlocks:a,messages:[{role:"user",content:l}],structuredOutput:{schema:io,name:"module_output"},maxTokens:16e3});if(c.type!=="structured"){if(r<2)return E.warn("module-developer",`${t.name}: no structured output, retry ${r+1}`),tc(e,t,n,s,o,i,r+1,a);throw new Error(`Module "${t.name}" failed to produce structured output after ${r+1} attempts`)}let d=c.data,u=typeof d.fieldsJson=="string"?d.fieldsJson:JSON.stringify(d.fieldsJson,null,2),m=typeof d.metaJson=="string"?d.metaJson:JSON.stringify(d.metaJson,null,2);return{moduleName:t.name,fieldsJson:u,metaJson:m,moduleHtml:String(d.moduleHtml||""),moduleCss:String(d.moduleCss||""),moduleJs:d.moduleJs?String(d.moduleJs):void 0}}var nc=G(()=>{"use strict";g();nt();Hi();Bi();re()});function ro(e,t,n){return n({type:"agent_step",step:"quality_check",label:"Quality check..."}),e.map(s=>{let o=[],i={...s};i.fieldsJson=sc(i.fieldsJson,i.moduleName,"fieldsJson",o),i.metaJson=sc(i.metaJson,i.moduleName,"metaJson",o),i.fieldsJson=Mf(i.fieldsJson,i.moduleName,o),i.fieldsJson=Rf(i.fieldsJson,i.moduleName,o),i.moduleCss=_f(i.moduleCss,i.moduleName,"moduleCss",o),i.moduleCss=Nf(i.moduleCss,i.moduleName,t,o),i.moduleHtml=Of(i.moduleHtml,i.moduleName,t,o),i.moduleHtml=jf(i.moduleHtml,i.moduleName,o),i.metaJson=Df(i.metaJson,i.moduleName,o);let r=o.every(a=>a.autoFixed);return o.length>0&&E.info("validator",`${i.moduleName}: ${o.length} issues`,{autoFixed:o.filter(a=>a.autoFixed).length,unfixed:o.filter(a=>!a.autoFixed).length}),{module:i,issues:o,valid:r}})}function sc(e,t,n,s){return!e||e.trim()===""?(s.push({module:t,field:n,message:`Empty ${n}`,autoFixed:n==="metaJson"}),n==="metaJson"?JSON.stringify({host_template_types:["PAGE"],is_available_for_new_content:!0}):e):(tt(e)===null&&s.push({module:t,field:n,message:`Invalid JSON in ${n}`,autoFixed:!1}),e)}function Mf(e,t,n){let s=e;return/"name"\s*:\s*"name"/g.test(s)&&(n.push({module:t,field:"fieldsJson",message:'"name" is a reserved field name \u2192 renamed to "item_name"',autoFixed:!0}),s=s.replace(/"name"\s*:\s*"name"/g,'"name": "item_name"')),/"name"\s*:\s*"label"/g.test(s)&&(n.push({module:t,field:"fieldsJson",message:'"label" is a reserved field name \u2192 renamed to "section_label"',autoFixed:!0}),s=s.replace(/"name"\s*:\s*"label"/g,'"name": "section_label"')),s}function Rf(e,t,n){let s=e;return/"type"\s*:\s*"textarea"/g.test(s)&&(n.push({module:t,field:"fieldsJson",message:'"textarea" is deprecated \u2192 changed to "text"',autoFixed:!0}),s=s.replace(/"type"\s*:\s*"textarea"/g,'"type": "text"')),s}function _f(e,t,n,s){if(!e)return e;let o=e,i=/@import\s+url\([^)]*(?:fonts\.googleapis|cdnjs|unpkg|jsdelivr)[^)]*\)\s*;?/gi;return i.test(o)&&(s.push({module:t,field:n,message:"CDN @import removed (external imports not allowed)",autoFixed:!0}),o=o.replace(i,"/* CDN import removed */")),o}function oc(e){return Pf.has(e)||e.startsWith("body-wrapper")||e.startsWith("dnd-")||e.startsWith("row-")||e.startsWith("hs-")||e.startsWith("hs_")}function Nf(e,t,n,s){if(!e)return e;let o=n+"-",i=/\.([a-zA-Z][\w-]*)/g,r=new Set,a;for(;(a=i.exec(e))!==null;){let c=a[1];!c.startsWith(o)&&!oc(c)&&r.add(c)}if(r.size<=3)return e;let l=e;for(let c of r){let d=new RegExp(`\\.${Ff(c)}(?=[\\s,{:+~>\\[\\]])`,"g");l=l.replace(d,`.${o}${c}`)}return l!==e&&s.push({module:t,field:"moduleCss",message:`${r.size} CSS classes auto-prefixed with "${o}"`,autoFixed:!0}),l}function Of(e,t,n,s){if(!e)return e;let o=n+"-",i=/class="([^"]*)"/g,r=!1,a=e.replace(i,(l,c)=>{let d=c.split(/\s+/),u=!1,m=d.map(f=>f&&!f.startsWith(o)&&!oc(f)&&/^[a-zA-Z][\w-]*$/.test(f)?(u=!0,o+f):f);return u?(r=!0,`class="${m.join(" ")}"`):l});return r&&s.push({module:t,field:"moduleHtml",message:`HTML class references auto-prefixed with "${o}"`,autoFixed:!0}),a}function Ff(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function jf(e,t,n){if(!e)return e;let s=e,o=/\{%[-~]?\s*(if|for|block|macro|endif|endfor|endblock|endmacro)\b[^%]*%\}/g,i=[],r;for(;(r=o.exec(s))!==null;){let c=r[1],d=!c.startsWith("end"),u=d?c:c.replace("end","");i.push({tag:c,isOpen:d,baseTag:u,start:r.index,end:r.index+r[0].length})}let a=[],l=[];for(let c=0;c<i.length;c++)if(i[c].isOpen)a.push(c);else{let d=-1;for(let u=a.length-1;u>=0;u--)if(i[a[u]].baseTag===i[c].baseTag){d=u;break}d!==-1?a.splice(d,1):l.push(c)}if(l.length>0){for(let c=l.length-1;c>=0;c--){let d=i[l[c]];s=s.slice(0,d.start)+`<!-- removed orphan {% ${d.tag} %} -->`+s.slice(d.end)}n.push({module:t,field:"moduleHtml",message:`Removed ${l.length} orphan closing tag${l.length===1?"":"s"} with no matching opener`,autoFixed:!0})}if(a.length>0){let c=a.map(u=>i[u].baseTag),d=c.reverse().map(u=>`{% end${u} %}`).join(`
1890
+ \`\`\``)),s.join("")}var ls,fr=R(()=>{"use strict";y();Ue();ls={type:"object",properties:{moduleName:{type:"string"},fieldsJson:{type:"string",description:"Complete fields.json content as a JSON string"},metaJson:{type:"string",description:"Complete meta.json content as a JSON string"},moduleHtml:{type:"string",description:"Complete module.html HubL template content"},moduleCss:{type:"string",description:"Complete module.css vanilla CSS content"},moduleJs:{type:"string",description:"Optional module.js vanilla JS content, or empty string if not needed"}},required:["moduleName","fieldsJson","metaJson","moduleHtml","moduleCss"]}});function hr(t,e){let n=[];if(n.push(`You are an Email Module Developer for vibeSpot, a HubSpot CMS builder.
1891
+
1892
+ Your job: generate ONE HubSpot CMS email module. You receive a module specification and must produce the complete module code optimized for email client rendering.
1893
+
1894
+ ## Theme: "${t}"
1895
+
1896
+ ## CRITICAL: Email vs. Page Differences
1897
+ This is an EMAIL module, not a page module. Email clients (Gmail, Outlook, Apple Mail) have severe rendering limitations:
1898
+ - **NO flexbox, NO grid** \u2014 use HTML tables with role="presentation" for ALL layout
1899
+ - **NO <style> blocks** \u2014 ALL CSS must be inline on every element
1900
+ - **NO CSS custom properties** (var()) \u2014 use literal values
1901
+ - **NO JavaScript** \u2014 module.js must be empty/null
1902
+ - **NO external assets** \u2014 no require_css(), require_js(), get_asset_url(), scope_css
1903
+ - **NO modern CSS** \u2014 no calc(), transform, animation, transition, position, overflow, float
1904
+ - **Container width: 600px** \u2014 the universal email safe width
1905
+
1906
+ ## Output Rules \u2014 CRITICAL
1907
+ You produce a single module with these fields:
1908
+ - **moduleName**: Exact module name (title-case, e.g., "Email Hero")
1909
+ - **fieldsJson**: Valid JSON string \u2014 the module's fields.json content
1910
+ - **metaJson**: Valid JSON string \u2014 must include host_template_types: ["EMAIL"], is_available_for_new_content: true
1911
+ - **moduleHtml**: HubL template using TABLE-BASED layout with ALL CSS inline
1912
+ - **moduleCss**: Empty string (all CSS is inline in moduleHtml)
1913
+ - **moduleJs**: null or empty string (no JS in email)
1914
+
1915
+ ## Layout Rules \u2014 Table-Based Only
1916
+
1917
+ ALL layout MUST use nested tables:
1918
+
1919
+ \`\`\`html
1920
+ <!-- Outer wrapper: centers content -->
1921
+ <table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%">
1922
+ <tr>
1923
+ <td align="center" style="padding: 0;">
1924
+ <!-- Inner container: 600px fixed width -->
1925
+ <table role="presentation" cellpadding="0" cellspacing="0" border="0" width="600" style="max-width: 600px;">
1926
+ <tr>
1927
+ <td style="padding: 40px 30px;">
1928
+ <!-- Module content here -->
1929
+ </td>
1930
+ </tr>
1931
+ </table>
1932
+ </td>
1933
+ </tr>
1934
+ </table>
1935
+ \`\`\`
1936
+
1937
+ For multi-column layouts, use table cells with explicit widths:
1938
+
1939
+ \`\`\`html
1940
+ <table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%">
1941
+ <tr>
1942
+ <td width="50%" valign="top" style="padding-right: 10px;">Left</td>
1943
+ <td width="50%" valign="top" style="padding-left: 10px;">Right</td>
1944
+ </tr>
1945
+ </table>
1946
+ \`\`\`
1947
+
1948
+ ## CSS Rules \u2014 Inline Only
1949
+ - ALL CSS must be inline style attributes on every element
1950
+ - moduleCss must be an empty string \u2014 there are no external stylesheets in email
1951
+ - Use web-safe font stacks: Arial, Helvetica, sans-serif / Georgia, Times New Roman, serif
1952
+ - Font sizes in px only (never rem/em)
1953
+ - Use unitless line-height (1.5) or px (24px)
1954
+ - Repeat font-family on every text element
1955
+ - Set margin: 0 on all headings and paragraphs
1956
+ - No border-radius in Outlook desktop \u2014 include but accept degradation
1957
+
1958
+ ## Inline Style Patterns
1959
+
1960
+ \`\`\`html
1961
+ <!-- Heading -->
1962
+ <h1 style="margin: 0 0 16px 0; font-family: Arial, Helvetica, sans-serif; font-size: 28px; font-weight: bold; line-height: 1.2; color: #1a1a2e;">
1963
+ {{ module.heading }}
1964
+ </h1>
1965
+
1966
+ <!-- Body text -->
1967
+ <p style="margin: 0 0 16px 0; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 1.5; color: #4a4a4a;">
1968
+ {{ module.body_text }}
1969
+ </p>
1970
+
1971
+ <!-- Button (bulletproof) -->
1972
+ <table role="presentation" cellpadding="0" cellspacing="0" border="0">
1973
+ <tr>
1974
+ <td align="center" style="border-radius: 4px; background-color: #e8613a;">
1975
+ <a href="{{ module.cta_link.url.href }}" target="_blank"
1976
+ style="display: inline-block; padding: 14px 32px; font-family: Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; color: #ffffff; text-decoration: none; border-radius: 4px; background-color: #e8613a;">
1977
+ {{ module.cta_text }}
1978
+ </a>
1979
+ </td>
1980
+ </tr>
1981
+ </table>
1982
+
1983
+ <!-- Image -->
1984
+ <img src="{{ module.hero_image.src }}" alt="{{ module.hero_image.alt }}"
1985
+ width="560" height="300"
1986
+ style="display: block; border: 0; outline: none; text-decoration: none; max-width: 100%; height: auto;" />
1987
+ \`\`\`
1988
+
1989
+ ## MSO Conditionals \u2014 Outlook Desktop
1990
+
1991
+ Wrap the outer container with MSO conditionals so Outlook desktop respects the 600px width:
1992
+
1993
+ \`\`\`html
1994
+ <!--[if mso]>
1995
+ <table role="presentation" cellpadding="0" cellspacing="0" border="0" width="600"><tr><td>
1996
+ <![endif]-->
1997
+ <div style="max-width: 600px; margin: 0 auto;">
1998
+ <!-- content -->
1999
+ </div>
2000
+ <!--[if mso]>
2001
+ </td></tr></table>
2002
+ <![endif]-->
2003
+ \`\`\`
2004
+
2005
+ ## Field Rules
2006
+ - Use "type": "text" (NEVER "textarea" \u2014 it's deprecated)
2007
+ - NEVER use "name": "name" (reserved) \u2014 use "item_name" instead
2008
+ - NEVER use "name": "label" (reserved) \u2014 use "section_label" instead
2009
+ - NEVER put literal \\n in field defaults
2010
+ - Color fields: type "color", default { "color": "#hex", "opacity": 100 }
2011
+ - Link fields: type "link", default { "url": { "href": "#", "type": "EXTERNAL" }, "open_in_new_tab": true, "no_follow": false }
2012
+ - Image fields: type "image", default { "src": "https://placehold.co/560x300/1a1a2e/ffffff?text=Replace+in+HubSpot", "alt": "Placeholder", "width": 560, "height": 300 }
2013
+ - For repeater groups, use "occurrence": { "min": 0, "max": 10 }
2014
+
2015
+ ## Images
2016
+ - Use image fields with placehold.co defaults \u2014 no get_asset_url()
2017
+ - Maximum image width: 560px (600px container minus 20px padding each side)
2018
+ - Always set explicit width and height attributes AND style
2019
+ - Always include alt text, display: block, border: 0
2020
+
2021
+ ## HubL for Email \u2014 Safe Subset ONLY
2022
+ Allowed:
2023
+ - {{ module.field_name }} / {{ module.field_name|escape }}
2024
+ - {% if %} / {% endif %}, {% for %} / {% endfor %}
2025
+ - {{ module.color_field.color }}, {{ module.link_field.url.href }}, {{ module.image_field.src }}
2026
+ - {{ unsubscribe_link }}, {{ site_settings.company_name }}, {{ view_as_page_url }}
2027
+
2028
+ NEVER use:
2029
+ - require_css() / require_js()
2030
+ - scope_css
2031
+ - get_asset_url()
2032
+ - now() / local_dt
2033
+ - dnd_area / dnd_section / dnd_module
2034
+
2035
+ ## metaJson Template
2036
+ { "host_template_types": ["EMAIL"], "is_available_for_new_content": true }
2037
+
2038
+ ## Email-Specific Required Elements
2039
+ Modules that serve as email footers MUST include:
2040
+ - Unsubscribe link: <a href="{{ unsubscribe_link }}">Unsubscribe</a>
2041
+ - Physical address: {{ site_settings.company_street_address_1 }}, {{ site_settings.company_city }}, {{ site_settings.company_state }}
2042
+ - Company name: {{ site_settings.company_name }}`),e?.themeContext&&n.push(`
2043
+
2044
+ ## Product Context
2045
+ ${e.themeContext}`),e?.humanify!==!1&&n.push(`
2046
+
2047
+ ## Anti-AI Copy Rules
2048
+ ${Qc()}`),e?.brandKit){let s=[];e.brandKit.colors&&(e.brandKit.colors.primary&&s.push(`- Primary color: ${e.brandKit.colors.primary}`),e.brandKit.colors.secondary&&s.push(`- Secondary color: ${e.brandKit.colors.secondary}`),e.brandKit.colors.accent&&s.push(`- Accent color: ${e.brandKit.colors.accent}`)),e.brandKit.fonts&&(e.brandKit.fonts.heading&&s.push(`- Heading font: ${e.brandKit.fonts.heading}`),e.brandKit.fonts.body&&s.push(`- Body font: ${e.brandKit.fonts.body}`)),e.brandKit.logoUrl&&s.push(`- Logo URL: ${e.brandKit.logoUrl}`),s.length>0&&n.push(`
2049
+
2050
+ ## Brand Kit \u2014 MANDATORY Design Constraints
2051
+ The following brand identity values MUST be used. Do NOT substitute or override them:
2052
+ ${s.join(`
2053
+ `)}`)}return n.join("")}function Zc(t,e){let n=[],s=hr(t,{...e,humanify:!1});n.push({type:"text",text:s});let o;try{o=Pa()}catch{o=""}o&&n.push({type:"text",text:`## Email Template Rules Reference
2054
+ ${o}`,cache_control:{type:"ephemeral"}});let i=[];return e?.themeContext&&i.push(`## Product Context
2055
+ ${e.themeContext}`),e?.humanify!==!1&&i.push(`## Anti-AI Copy Rules
2056
+ ${Qc()}`),i.length>0&&n.push({type:"text",text:i.join(`
2057
+
2058
+ `)}),n}function Qc(){return`### Banned Punctuation
2059
+ - **Em dashes (\u2014)**: NEVER use. Replace with periods, commas, or parentheses.
2060
+ - **Semicolons**: Use periods instead.
2061
+ - **Exclamation marks**: One per email max. Zero ideal for B2B.
2062
+
2063
+ ### Banned Words
2064
+ **HARD BANNED:**
2065
+ delve, tapestry, multifaceted, utilize, harness, bolster, underscore, illuminate, facilitate, fostering, garner, pivotal, commence, endeavor, myriad, plethora, pertinent, aforementioned, beacon, synergy, paradigm, bespoke, holistic, spearhead, embark, reimagine, cultivate, cornerstone
2066
+
2067
+ **SOFT BANNED (rewrite unless truly earned):**
2068
+ seamless, cutting-edge, groundbreaking, game-changer, revolutionary, transformative, innovative, robust, comprehensive, elevate, unlock, streamline, optimize, curated
2069
+
2070
+ ### Banned Openers
2071
+ Never start with: "In today's", "In an era", "Whether you're", "Imagine a world", "Here's the thing", "Say goodbye to", "Gone are the days"
2072
+
2073
+ ### Positive Rules
2074
+ - Be concrete: "42 minutes" not "fast", "\u20AC29/month" not "affordable"
2075
+ - Use plain words: use > utilize, start > commence, help > facilitate
2076
+ - Front-load the benefit in the first 5 words
2077
+ - Email subject lines: specific, benefit-first, under 50 chars`}function ed(t,e,n){let s=[];return s.push(`## User Request
2078
+ ${t}`),s.push(`
2079
+
2080
+ ## Email Module Specification
2081
+ - **Name**: ${e.name}
2082
+ - **Description**: ${e.description}
2083
+ - **Content Brief**: ${e.contentBrief}
2084
+ - **Layout Notes**: ${e.layoutNotes}
2085
+
2086
+ REMEMBER: This is an EMAIL module. ALL layout must use tables. ALL CSS must be inline. NO external stylesheets. NO JavaScript.`),n&&s.push(`
2087
+
2088
+ ## Existing Module Code (modify this)
2089
+ **fields.json:**
2090
+ \`\`\`json
2091
+ ${n.fieldsJson}
2092
+ \`\`\`
2093
+
2094
+ **module.html:**
2095
+ \`\`\`html
2096
+ ${n.moduleHtml}
2097
+ \`\`\``),s.join("")}var td,nd=R(()=>{"use strict";y();Ue();td={type:"object",properties:{moduleName:{type:"string"},fieldsJson:{type:"string",description:"Complete fields.json content as a JSON string"},metaJson:{type:"string",description:'Complete meta.json content \u2014 must include host_template_types: ["EMAIL"]'},moduleHtml:{type:"string",description:"Complete module.html with TABLE-BASED layout and ALL CSS inline. No <style> blocks."},moduleCss:{type:"string",description:"Must be empty string \u2014 all CSS is inline in moduleHtml for email"},moduleJs:{type:"string",description:"Must be empty string \u2014 no JavaScript in email"}},required:["moduleName","fieldsJson","metaJson","moduleHtml"]}});function yr(t,e,n,s){let o=[];o.push(`You are a Blog Module Developer for vibeSpot, a HubSpot CMS builder.
2098
+
2099
+ Your job: generate ONE HubSpot CMS blog module. You receive a module specification and must produce the complete module code optimized for blog templates.
2100
+
2101
+ ## Theme: "${t}"
2102
+
2103
+ ## CRITICAL: Blog Template Context
2104
+ This is a BLOG module. Blog modules are used in HubSpot blog post and blog listing templates. They differ from page modules in these key ways:
2105
+ - **Blog post modules** use HubSpot blog variables (\`{{ content.post_body }}\`, \`{{ content.author }}\`, \`{{ content.tag_list }}\`, etc.)
2106
+ - **Blog listing modules** use \`{% for content in contents %}\` to loop over posts
2107
+ - **Reading-optimized design** \u2014 wider line heights, constrained content width (680-720px), generous spacing
2108
+ - **host_template_types** must be \`["BLOG_POST"]\`, \`["BLOG_LISTING"]\`, or \`["BLOG_POST", "BLOG_LISTING"]\`
2109
+
2110
+ ## Output Rules \u2014 CRITICAL
2111
+ You produce a single module with these fields:
2112
+ - **moduleName**: Exact module name (kebab-case, e.g., "blog-post-header")
2113
+ - **fieldsJson**: Valid JSON string \u2014 the module's fields.json content
2114
+ - **metaJson**: Valid JSON string \u2014 must include the correct host_template_types and is_available_for_new_content: true
2115
+ - **moduleHtml**: HubL template using blog variables where appropriate
2116
+ - **moduleCss**: Vanilla CSS (no Tailwind, no Sass, no CDN imports)
2117
+ - **moduleJs**: Optional vanilla JS wrapped in IIFE, or null
2118
+
2119
+ ## CSS Rules
2120
+ - All CSS classes must use prefix "${t}-"
2121
+ - Use BEM naming: ${t}-moduleName__element--modifier
2122
+ - Reference the theme's CSS custom properties (shown below)
2123
+ - No CDN imports (@import url(), external <link> tags)
2124
+ - Use system font stacks \u2014 no Google Fonts
2125
+
2126
+ ## Reading-Optimized Design Tokens
2127
+ Blog modules should use these design principles:
2128
+ - Body text: 18-20px for long-form readability
2129
+ - Line height: 1.6-1.8 for body copy
2130
+ - Content width: 680-720px max for article body
2131
+ - Generous paragraph spacing: 1.5em between paragraphs
2132
+ - Clear heading hierarchy with adequate spacing
2133
+ - High contrast for body text (WCAG AA minimum)
2134
+
2135
+ ## Shared CSS (use these variables)
2136
+ \`\`\`css
2137
+ ${e||"/* No shared CSS yet \u2014 create appropriate custom properties */"}
2138
+ \`\`\`
2139
+
2140
+ ## HubSpot Blog Variables \u2014 Use These
2141
+
2142
+ ### Blog Post Variables
2143
+ \`\`\`
2144
+ {{ content.name }} \u2014 Post title
2145
+ {{ content.post_body }} \u2014 Full post body HTML
2146
+ {{ content.featured_image }} \u2014 Featured image URL
2147
+ {{ content.featured_image_alt_text }} \u2014 Featured image alt text
2148
+ {{ content.publish_date }} \u2014 Publish date
2149
+ {{ content.blog_post_author }} \u2014 Author name
2150
+ {{ content.author.display_name }} \u2014 Author display name
2151
+ {{ content.author.avatar }} \u2014 Author avatar URL
2152
+ {{ content.author.bio }} \u2014 Author bio
2153
+ {{ content.tag_list }} \u2014 Tags (iterable)
2154
+ {{ content.topic_list }} \u2014 Topics (iterable)
2155
+ {{ content.absolute_url }} \u2014 Canonical URL
2156
+ {{ content.meta_description }} \u2014 Excerpt / meta description
2157
+ \`\`\`
2158
+
2159
+ ### Blog Listing Variables
2160
+ \`\`\`html
2161
+ {% for content in contents %}
2162
+ {{ content.name }} \u2014 Post title
2163
+ {{ content.absolute_url }} \u2014 Post URL
2164
+ {{ content.featured_image }} \u2014 Featured image
2165
+ {{ content.meta_description }} \u2014 Excerpt
2166
+ {{ content.publish_date }} \u2014 Date
2167
+ {{ content.blog_post_author }} \u2014 Author
2168
+ {% endfor %}
2169
+
2170
+ {{ group.public_title }} \u2014 Blog name
2171
+ {{ group.description }} \u2014 Blog description
2172
+ \`\`\`
2173
+
2174
+ ### Date Formatting
2175
+ \`\`\`html
2176
+ {{ content.publish_date|datetimeformat('%B %d, %Y') }}
2177
+ \`\`\`
2178
+
2179
+ ### Pagination (for listing modules)
2180
+ \`\`\`html
2181
+ {% if last_page_num > 1 %}
2182
+ {% if current_page_num > 1 %}
2183
+ <a href="{{ blog_page_link(current_page_num - 1) }}">Previous</a>
2184
+ {% endif %}
2185
+ {% for page_num in range(1, last_page_num + 1) %}
2186
+ {% if page_num == current_page_num %}
2187
+ <span>{{ page_num }}</span>
2188
+ {% else %}
2189
+ <a href="{{ blog_page_link(page_num) }}">{{ page_num }}</a>
2190
+ {% endif %}
2191
+ {% endfor %}
2192
+ {% if current_page_num < last_page_num %}
2193
+ <a href="{{ blog_page_link(current_page_num + 1) }}">Next</a>
2194
+ {% endif %}
2195
+ {% endif %}
2196
+ \`\`\`
2197
+
2198
+ ### Tag Filtering
2199
+ \`\`\`html
2200
+ {% set topics = blog_topics(group.id, 250) %}
2201
+ {% for topic in topics %}
2202
+ <a href="{{ blog_tag_url(group.id, topic.slug) }}">{{ topic.name }}</a>
2203
+ {% endfor %}
2204
+ \`\`\`
2205
+
2206
+ ### Related Posts
2207
+ \`\`\`html
2208
+ {% set recent = blog_recent_posts(group.id, 3) %}
2209
+ {% for post in recent %}
2210
+ {% if post.absolute_url != content.absolute_url %}
2211
+ <a href="{{ post.absolute_url }}">{{ post.name }}</a>
2212
+ {% endif %}
2213
+ {% endfor %}
2214
+ \`\`\`
2215
+
2216
+ ## Field Rules
2217
+ - Use "type": "text" (NEVER "textarea" \u2014 it's deprecated)
2218
+ - NEVER use "name": "name" (reserved) \u2014 use "item_name" instead
2219
+ - NEVER use "name": "label" (reserved) \u2014 use "section_label" instead
2220
+ - NEVER put literal \\n in field defaults
2221
+ - Wrap style fields in a "styles" group with "tab": "STYLE"
2222
+ - Color fields: type "color", default { "color": "#hex", "opacity": 100 }
2223
+ - Link fields: type "link", default { "url": { "href": "#", "type": "EXTERNAL" }, "open_in_new_tab": true, "no_follow": false }
2224
+ - Image fields: type "image", default { "src": "https://placehold.co/800x450/1a1a2e/ffffff?text=Replace+in+HubSpot", "alt": "Placeholder", "width": 800, "height": 450 }
2225
+ - For repeater groups, use "occurrence": { "min": 0, "max": 10 }
2226
+
2227
+ ## metaJson Templates
2228
+
2229
+ For blog post modules:
2230
+ { "host_template_types": ["BLOG_POST"], "is_available_for_new_content": true }
2231
+
2232
+ For blog listing modules:
2233
+ { "host_template_types": ["BLOG_LISTING"], "is_available_for_new_content": true }
2234
+
2235
+ For modules usable in both:
2236
+ { "host_template_types": ["BLOG_POST", "BLOG_LISTING"], "is_available_for_new_content": true }
2237
+
2238
+ ## Module Type Detection
2239
+ Determine the correct host_template_types from the module specification:
2240
+ - Modules with "listing", "grid", "archive", "index", "pagination", "topic-filter", "category" in the name/description \u2192 BLOG_LISTING
2241
+ - Modules with "post-body", "post-header", "author-bio", "related-posts", "comments", "share" in the name/description \u2192 BLOG_POST
2242
+ - Generic modules like "newsletter-signup", "sidebar" \u2192 both ["BLOG_POST", "BLOG_LISTING"]
2243
+
2244
+ ## Key Patterns
2245
+
2246
+ ### Blog Post Body Wrapper
2247
+ The blog post body module wraps \`{{ content.post_body }}\` with reading-optimized styles:
2248
+ \`\`\`html
2249
+ <article class="${t}-post-body">
2250
+ <div class="${t}-post-body__content">
2251
+ {{ content.post_body }}
2252
+ </div>
2253
+ </article>
2254
+ \`\`\`
2255
+
2256
+ ### Post Card (for listing)
2257
+ \`\`\`html
2258
+ {% for content in contents %}
2259
+ <article class="${t}-post-card">
2260
+ {% if content.featured_image %}
2261
+ <img src="{{ content.featured_image }}" alt="{{ content.featured_image_alt_text }}"
2262
+ class="${t}-post-card__image" loading="lazy" />
2263
+ {% endif %}
2264
+ <div class="${t}-post-card__content">
2265
+ <span class="${t}-post-card__date">
2266
+ {{ content.publish_date|datetimeformat('%B %d, %Y') }}
2267
+ </span>
2268
+ <h2 class="${t}-post-card__title">
2269
+ <a href="{{ content.absolute_url }}">{{ content.name }}</a>
2270
+ </h2>
2271
+ <p class="${t}-post-card__excerpt">{{ content.meta_description|truncate(160) }}</p>
2272
+ <span class="${t}-post-card__author">{{ content.blog_post_author }}</span>
2273
+ </div>
2274
+ </article>
2275
+ {% endfor %}
2276
+ \`\`\``),s?.themeContext&&o.push(`
2277
+
2278
+ ## Product Context
2279
+ ${s.themeContext}`),s?.humanify!==!1&&o.push(`
2280
+
2281
+ ## Anti-AI Copy Rules
2282
+ ${od()}`);let i=[];if(n?.includes("conversion"))try{let r=fe();r&&i.push(`## Conversion Guide
2283
+ ${r}`)}catch{}if(n?.includes("hubspot_rules"))try{let r=je();r&&i.push(`## HubSpot Rules
2284
+ ${r}`)}catch{}return i.length>0&&o.push(`
2285
+
2286
+ ${i.join(`
2287
+
2288
+ `)}`),o.join("")}function sd(t,e,n,s){let o=[],i=yr(t,e,void 0,{...s,humanify:!1});o.push({type:"text",text:i});let r;try{r=Ra()}catch{r=""}r&&o.push({type:"text",text:`## Blog Template Rules Reference
2289
+ ${r}`,cache_control:{type:"ephemeral"}});let a=[];if(n?.includes("conversion"))try{let c=fe();c&&a.push(`## Conversion Guide
2290
+ ${c}`)}catch{}if(n?.includes("hubspot_rules"))try{let c=je();c&&a.push(`## HubSpot Rules
2291
+ ${c}`)}catch{}a.length>0&&o.push({type:"text",text:a.join(`
2292
+
2293
+ `),cache_control:{type:"ephemeral"}});let l=[];return s?.themeContext&&l.push(`## Product Context
2294
+ ${s.themeContext}`),s?.humanify!==!1&&l.push(`## Anti-AI Copy Rules
2295
+ ${od()}`),l.length>0&&o.push({type:"text",text:l.join(`
2296
+
2297
+ `)}),o}function od(){return`### Banned Punctuation
2298
+ - **Em dashes (\u2014)**: NEVER use. Replace with periods, commas, or parentheses.
2299
+ - **Semicolons**: Use periods instead.
2300
+ - **Exclamation marks**: Maximum one per page. Zero ideal for B2B.
2301
+
2302
+ ### Banned Words
2303
+ **HARD BANNED:**
2304
+ delve, tapestry, multifaceted, utilize, harness, bolster, underscore, illuminate, facilitate, fostering, garner, pivotal, commence, endeavor, myriad, plethora, pertinent, aforementioned, beacon, synergy, paradigm, bespoke, holistic, spearhead, embark, reimagine, cultivate, cornerstone
2305
+
2306
+ **SOFT BANNED (rewrite unless truly earned):**
2307
+ seamless, cutting-edge, groundbreaking, game-changer, revolutionary, transformative, innovative, robust, comprehensive, elevate, unlock, streamline, optimize, curated
2308
+
2309
+ ### Banned Openers
2310
+ Never start with: "In today's", "In an era", "Whether you're", "Imagine a world", "Here's the thing", "Say goodbye to", "Gone are the days"
2311
+
2312
+ ### Positive Rules
2313
+ - Be concrete: "42 minutes" not "fast", "\u20AC29/month" not "affordable"
2314
+ - Use plain words: use > utilize, start > commence, help > facilitate
2315
+ - Front-load the benefit in the first 5 words
2316
+ - Blog headlines: specific, benefit-first, no clickbait`}function id(t,e,n){let s=[];return s.push(`## User Request
2317
+ ${t}`),s.push(`
2318
+
2319
+ ## Blog Module Specification
2320
+ - **Name**: ${e.name}
2321
+ - **Description**: ${e.description}
2322
+ - **Content Brief**: ${e.contentBrief}
2323
+ - **Layout Notes**: ${e.layoutNotes}
2324
+
2325
+ REMEMBER: This is a BLOG module. Use HubSpot blog variables where appropriate (content.post_body, content.author, content.tag_list, etc.). Set the correct host_template_types in meta.json (BLOG_POST, BLOG_LISTING, or both).`),n&&s.push(`
2326
+
2327
+ ## Existing Module Code (modify this)
2328
+ **fields.json:**
2329
+ \`\`\`json
2330
+ ${n.fieldsJson}
2331
+ \`\`\`
2332
+
2333
+ **module.html:**
2334
+ \`\`\`html
2335
+ ${n.moduleHtml}
2336
+ \`\`\`
2337
+
2338
+ **module.css:**
2339
+ \`\`\`css
2340
+ ${n.moduleCss}
2341
+ \`\`\``),s.join("")}var rd,ad=R(()=>{"use strict";y();Ue();Ue();rd={type:"object",properties:{moduleName:{type:"string"},fieldsJson:{type:"string",description:"Complete fields.json content as a JSON string"},metaJson:{type:"string",description:'Complete meta.json content \u2014 must include host_template_types with "BLOG_POST" and/or "BLOG_LISTING"'},moduleHtml:{type:"string",description:"Complete module.html using HubSpot blog variables where appropriate"},moduleCss:{type:"string",description:"Complete module.css with reading-optimized styles"},moduleJs:{type:"string",description:"Optional module.js (vanilla JS in IIFE) or empty string"}},required:["moduleName","fieldsJson","metaJson","moduleHtml","moduleCss"]}});async function cs(t,e,n,s,o,i,r,a,l,c,d,u){let m=u==="email",g=u==="blog",h=m?"email module":g?"blog module":"module";l({type:"agent_step",step:"developing",label:`Generating ${e.length} ${h}${e.length===1?"":"s"}...`});let f=o==="anthropic-api"||o==="claude-oauth",b=m?hr(s,d):g?yr(s,n,c,d):as(s,n,c,d),S=f?m?Zc(s,d):g?sd(s,n,c,d):_o(s,n,c,d):void 0,x=$o(a),w=e.length,P=m?td:g?rd:ls,F=e.map((L,V)=>x(async()=>{l({type:"module_progress",module:L.name,status:"generating",current:V+1,total:w});let B="";for(let N=0;N<2;N++)try{N>0&&(E.warn("module-developer",`${L.name}: retrying after failure (attempt ${N+1})`),l({type:"module_progress",module:L.name,status:"retrying",current:V+1,total:w}));let T=await ld(t,L,b,o,i,r,0,S,m,P,g);return l({type:"module_progress",module:L.name,status:"complete",current:V+1,total:w,moduleFiles:T}),{moduleName:L.name,module:T}}catch(T){B=T instanceof Error?T.message:typeof T=="object"&&T!==null?JSON.stringify(T):String(T),E.error("module-developer",`Failed: ${L.name} (attempt ${N+1})`,{error:B})}return l({type:"module_progress",module:L.name,status:"failed",current:V+1,total:w}),{moduleName:L.name,error:B}}));return(await Promise.allSettled(F)).map(L=>L.status==="fulfilled"?L.value:{moduleName:"unknown",error:L.reason instanceof Error?L.reason.message:String(L.reason)})}async function ld(t,e,n,s,o,i,r=0,a,l=!1,c=ls,d=!1){let u=l?ed(t,e,e.existingCode):d?id(t,e,e.existingCode):Xc(t,e,e.existingCode),m=await _e(s,o,i,{systemPrompt:n,systemBlocks:a,messages:[{role:"user",content:u}],structuredOutput:{schema:c,name:"module_output"},maxTokens:16e3});if(m.type!=="structured"){if(r<2)return E.warn("module-developer",`${e.name}: no structured output, retry ${r+1}`),ld(t,e,n,s,o,i,r+1,a,l,c,d);throw new Error(`Module "${e.name}" failed to produce structured output after ${r+1} attempts`)}let g=m.data,h=typeof g.fieldsJson=="string"?g.fieldsJson:JSON.stringify(g.fieldsJson,null,2),f=typeof g.metaJson=="string"?g.metaJson:JSON.stringify(g.metaJson,null,2);return{moduleName:e.name,fieldsJson:h,metaJson:f,moduleHtml:String(g.moduleHtml||""),moduleCss:l?"":String(g.moduleCss||""),moduleJs:l?void 0:g.moduleJs?String(g.moduleJs):void 0}}var cd=R(()=>{"use strict";y();nt();gr();fr();nd();ad();de()});function zt(t,e,n,s,o){let i=s==="email",r=s==="blog";return n({type:"agent_step",step:"quality_check",label:i?"Email quality check...":r?"Blog quality check...":"Quality check..."}),t.map(a=>{let l=[],c={...a};c.fieldsJson=dd(c.fieldsJson,c.moduleName,"fieldsJson",l,i),c.metaJson=dd(c.metaJson,c.moduleName,"metaJson",l,i,r),c.fieldsJson=lh(c.fieldsJson,c.moduleName,l),c.fieldsJson=ch(c.fieldsJson,c.moduleName,l),i?c=Sh(c,l):(c.moduleCss=dh(c.moduleCss,c.moduleName,"moduleCss",l),c.moduleCss=mh(c.moduleCss,c.moduleName,e,l),c.moduleHtml=ph(c.moduleHtml,c.moduleName,e,l),r&&(c=xh(c,l))),c.moduleHtml=fh(c.moduleHtml,c.moduleName,l),c.metaJson=hh(c.metaJson,c.moduleName,l,i,r),o&&bh(c,o,l);let d=l.every(u=>u.autoFixed);return l.length>0&&E.info("validator",`${c.moduleName}: ${l.length} issues`,{autoFixed:l.filter(u=>u.autoFixed).length,unfixed:l.filter(u=>!u.autoFixed).length}),{module:c,issues:l,valid:d}})}function dd(t,e,n,s,o=!1,i=!1){return!t||t.trim()===""?(s.push({module:e,field:n,message:`Empty ${n}`,autoFixed:n==="metaJson"}),n==="metaJson"?JSON.stringify({host_template_types:[o?"EMAIL":i?"BLOG_POST":"PAGE"],is_available_for_new_content:!0}):t):ft(t)===null?(s.push({module:e,field:n,message:`Invalid JSON in ${n} \u2014 reset to empty`,autoFixed:!0}),n==="fieldsJson"?"[]":JSON.stringify({host_template_types:[o?"EMAIL":i?"BLOG_POST":"PAGE"],is_available_for_new_content:!0})):t}function lh(t,e,n){let s=t;return/"name"\s*:\s*"name"/g.test(s)&&(n.push({module:e,field:"fieldsJson",message:'"name" is a reserved field name \u2192 renamed to "item_name"',autoFixed:!0}),s=s.replace(/"name"\s*:\s*"name"/g,'"name": "item_name"')),/"name"\s*:\s*"label"/g.test(s)&&(n.push({module:e,field:"fieldsJson",message:'"label" is a reserved field name \u2192 renamed to "section_label"',autoFixed:!0}),s=s.replace(/"name"\s*:\s*"label"/g,'"name": "section_label"')),s}function ch(t,e,n){let s=t;return/"type"\s*:\s*"textarea"/g.test(s)&&(n.push({module:e,field:"fieldsJson",message:'"textarea" is deprecated \u2192 changed to "text"',autoFixed:!0}),s=s.replace(/"type"\s*:\s*"textarea"/g,'"type": "text"')),s}function dh(t,e,n,s){if(!t)return t;let o=t,i=/@import\s+url\([^)]*(?:fonts\.googleapis|cdnjs|unpkg|jsdelivr)[^)]*\)\s*;?/gi;return i.test(o)&&(s.push({module:e,field:n,message:"CDN @import removed (external imports not allowed)",autoFixed:!0}),o=o.replace(i,"/* CDN import removed */")),o}function ud(t){return uh.has(t)||t.startsWith("body-wrapper")||t.startsWith("dnd-")||t.startsWith("row-")||t.startsWith("hs-")||t.startsWith("hs_")}function mh(t,e,n,s){if(!t)return t;let o=n+"-",i=/\.([a-zA-Z][\w-]*)/g,r=new Set,a;for(;(a=i.exec(t))!==null;){let c=a[1];!c.startsWith(o)&&!ud(c)&&r.add(c)}if(r.size<=3)return t;let l=t;for(let c of r){let d=new RegExp(`\\.${gh(c)}(?=[\\s,{:+~>\\[\\]])`,"g");l=l.replace(d,`.${o}${c}`)}return l!==t&&s.push({module:e,field:"moduleCss",message:`${r.size} CSS classes auto-prefixed with "${o}"`,autoFixed:!0}),l}function ph(t,e,n,s){if(!t)return t;let o=n+"-",i=/class="([^"]*)"/g,r=!1,a=t.replace(i,(l,c)=>{let d=/(\{%[-~]?[\s\S]*?[-~]?%\}|\{\{[\s\S]*?\}\})/g,u=c.split(d),m=!1,g=u.map((h,f)=>f%2===1?h:h.split(/(\s+)/).map(b=>/^\s*$/.test(b)?b:b&&!b.startsWith(o)&&!ud(b)&&/^[a-zA-Z][\w-]*$/.test(b)?(m=!0,o+b):b).join("")).join("");return m?(r=!0,`class="${g}"`):l});return r&&s.push({module:e,field:"moduleHtml",message:`HTML class references auto-prefixed with "${o}"`,autoFixed:!0}),a}function gh(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function fh(t,e,n){if(!t)return t;let s=t,i=["if","elif","else","endif","for","endfor","set","do","block","endblock","macro","endmacro","call","endcall","filter","endfilter","raw","endraw","include","import","from","extends","print","unless","endunless","is","not","and","or","in"].join("|"),r=new RegExp(`\\b[a-zA-Z][\\w-]*-(${i})\\b(?!-)`,"g"),a=/(\{%[-~]?[\s\S]*?[-~]?%\})/g,l=!1;s=s.replace(a,h=>h.replace(r,(b,S)=>(l=!0,S))),l&&n.push({module:e,field:"moduleHtml",message:"Stripped CSS-class prefix from HubL keywords inside {% %} tags",autoFixed:!0});let c=/\{%[-~]?\s*(if|for|block|macro|endif|endfor|endblock|endmacro)\b[^%]*%\}/g,d=[],u;for(;(u=c.exec(s))!==null;){let h=u[1],f=!h.startsWith("end"),b=f?h:h.replace("end","");d.push({tag:h,isOpen:f,baseTag:b,start:u.index,end:u.index+u[0].length})}let m=[],g=[];for(let h=0;h<d.length;h++)if(d[h].isOpen)m.push(h);else{let f=-1;for(let b=m.length-1;b>=0;b--)if(d[m[b]].baseTag===d[h].baseTag){f=b;break}f!==-1?m.splice(f,1):g.push(h)}if(g.length>0){for(let h=g.length-1;h>=0;h--){let f=d[g[h]];s=s.slice(0,f.start)+`<!-- removed orphan {% ${f.tag} %} -->`+s.slice(f.end)}n.push({module:e,field:"moduleHtml",message:`Removed ${g.length} orphan closing tag${g.length===1?"":"s"} with no matching opener`,autoFixed:!0})}if(m.length>0){let h=m.map(b=>d[b].baseTag),f=h.reverse().map(b=>`{% end${b} %}`).join(`
1280
2342
  `);s=`${s}
1281
- ${d}`,n.push({module:t,field:"moduleHtml",message:`Added ${c.length} missing closing tag${c.length===1?"":"s"}: ${c.map(u=>`{% end${u} %}`).join(", ")}`,autoFixed:!0})}return/\bnow\(\)/.test(s)&&(s=s.replace(/\bnow\(\)/g,"local_dt"),n.push({module:t,field:"moduleHtml",message:"Replaced now() with local_dt (now() is not valid HubL)",autoFixed:!0})),s}function Df(e,t,n){let s=tt(e);if(!s||typeof s!="object")return e;let o=s,i=!1;return o.host_template_types||(o.host_template_types=["PAGE"],i=!0),o.is_available_for_new_content===void 0&&(o.is_available_for_new_content=!0,i=!0),i?(n.push({module:t,field:"metaJson",message:"Added missing meta.json required fields",autoFixed:!0}),JSON.stringify(o,null,2)):e}var Pf,Ui=G(()=>{"use strict";g();eo();re();Pf=new Set(["visible","active","scroll-animate","hidden","open","closed","fade-in","fade-out","is-active","is-open","is-visible"])});import{execSync as Jf}from"child_process";async function ic(e,t,n,s,o,i,r,a){let l=Date.now(),c=i;if(an(n)){let k={"claude-code":"claude","gemini-cli":"gemini","codex-cli":"codex"}[n];if(k)try{Jf(`command -v ${k}`,{stdio:"ignore"})}catch{throw new Error(`CLI engine "${n}" requires "${k}" to be installed and on your PATH.`)}}let d=await Bl(e,t,n,s,o,r,a);if(d.intent==="question"&&d.answer){let j=Date.now()-l;return r({type:"pipeline_complete",modulesGenerated:0,modulesUnchanged:t.modules.length,durationMs:j,answer:d.answer}),{modules:[...t.modules],moduleOrder:t.moduleOrder,sharedCss:t.sharedCss,sharedJs:t.sharedJs,assistantMessage:d.answer,stats:{modulesGenerated:0,modulesUnchanged:t.modules.length,modulesFailed:0,durationMs:j}}}let u=null,m=t.sharedCss,f=t.sharedJs;(d.intent==="create"||d.designSystemChanges)&&(u=await ql(e,d,t,n,s,o,r),m=u.designSystem.sharedCss||m,f=u.designSystem.sharedJs||f,r({type:"blueprint_ready",moduleOrder:u.moduleOrder,sharedCss:m,sharedJs:f}));let h=[];if(u)for(let j of u.modules)h.push({name:j.name,description:j.description,contentBrief:j.contentBrief,layoutNotes:j.layoutNotes});else{for(let j of d.newModules)h.push({name:j.name,description:j.description,contentBrief:"Generate appropriate content based on the user request",layoutNotes:"Use responsive layout matching the existing design system"});for(let j of d.affectedModules){let k=t.modules.find(M=>M.moduleName===j);k&&h.push({name:j,description:`Modify existing module: ${j}`,contentBrief:"Apply the user's requested changes",layoutNotes:"Preserve existing layout unless changes are requested",existingCode:k})}}let S=[],x=[];if(h.length>0){let j=await ec(e,h,m,t.themeName,n,s,o,c,r,d.guidesNeeded,t.brandAssets);for(let k of j)k.module?S.push(k.module):x.push(k.moduleName)}let w=null;if(S.length>0){w=ro(S,t.themeName,r),S=w.map(k=>k.module);let j=w.reduce((k,M)=>k+M.issues.length,0);if(j>0){let k=w.reduce((te,es)=>te+es.issues.filter(It=>It.autoFixed).length,0);E.info("pipeline",`Quality check: ${j} issues, ${k} auto-fixed`);let M=w.flatMap(te=>te.issues).map(te=>`${te.autoFixed?"\u2713":"\u26A0"} ${te.module}: ${te.message}`).join(`
1282
- `);r({type:"agent_decision",step:"quality_check",decision:`${j} issues found, ${k} auto-fixed
1283
- ${M}`})}else r({type:"agent_decision",step:"quality_check",decision:"All modules passed quality checks"})}let v=Lf(t,d,S,u,a),N=Hf(t,d,u,v);if(u?.moduleOrder?.length){let j=new Set(u.moduleOrder),k=v.filter(M=>!j.has(M.moduleName)).map(M=>M.moduleName);k.length>0&&r({type:"agent_decision",step:"quality_check",decision:`\u26A0 ${k.length} module${k.length===1?"":"s"} missing from page order \u2014 auto-inserted: ${k.join(", ")}`})}let O=Date.now()-l,F=S.length,U=d.unchangedModules.length,q=w?w.flatMap(j=>j.issues):[],_=Bf(d,F,U,x,O,u,q);return x.length>0?r({type:"pipeline_partial",succeeded:S.map(j=>j.moduleName),failed:x,durationMs:O}):r({type:"pipeline_complete",modulesGenerated:F,modulesUnchanged:U,durationMs:O}),{modules:v,moduleOrder:N,sharedCss:m,sharedJs:f,assistantMessage:_,stats:{modulesGenerated:F,modulesUnchanged:U,modulesFailed:x.length,durationMs:O}}}function Lf(e,t,n,s,o){let i=[],r=new Set;for(let a of n)i.push(a),r.add(a.moduleName);for(let a of t.unchangedModules){if(r.has(a))continue;let l=e.modules.find(c=>c.moduleName===a);l&&(i.push(l),r.add(a))}if(t.reuseModules)for(let a of t.reuseModules){if(r.has(a.name))continue;let l=o.find(c=>c.name===a.name&&c.module);l&&l.module&&(i.push(l.module),r.add(a.name))}return i}function Hf(e,t,n,s){if(n?.moduleOrder?.length){let a=[...n.moduleOrder],l=new Set(a);for(let c of s)if(!l.has(c.moduleName)){let d=a.findIndex(u=>u.toLowerCase().includes("footer"));d!==-1?a.splice(d,0,c.moduleName):a.push(c.moduleName),l.add(c.moduleName),E.warn("pipeline",`Module "${c.moduleName}" missing from blueprint order \u2014 inserted`)}return a}if(t.intent==="create")return s.map(a=>a.moduleName);let o=[...e.moduleOrder],i=[...t.newModules.map(a=>({name:a.name,position:a.position})),...(t.reuseModules||[]).map(a=>({name:a.name,position:a.position}))].sort((a,l)=>a.position-l.position);for(let a of i){let l=Math.min(a.position,o.length);o.splice(l,0,a.name)}let r=new Set(s.map(a=>a.moduleName));return o.filter(a=>r.has(a))}function Bf(e,t,n,s,o,i,r){let a=Math.round(o/1e3),l=[];if(e.intent==="create")l.push(`Created ${t} module${t===1?"":"s"} in ${a}s.`);else if(e.intent==="modify"||e.intent==="style_change")l.push(`Updated ${t} module${t===1?"":"s"} in ${a}s.`),n>0&&l.push(`${n} module${n===1?"":"s"} unchanged.`);else if(e.intent==="add"){let u=e.newModules.map(m=>m.name).join(", ");l.push(`Added ${u} in ${a}s.`)}else e.intent==="remove"?l.push(`Removed modules in ${a}s.`):e.intent==="rearrange"&&l.push(`Rearranged modules in ${a}s.`);i?.narrative&&l.push(`
2343
+ ${f}`,n.push({module:e,field:"moduleHtml",message:`Added ${h.length} missing closing tag${h.length===1?"":"s"}: ${h.map(b=>`{% end${b} %}`).join(", ")}`,autoFixed:!0})}return/\bnow\(\)/.test(s)&&(s=s.replace(/\bnow\(\)/g,"local_dt"),n.push({module:e,field:"moduleHtml",message:"Replaced now() with local_dt (now() is not valid HubL)",autoFixed:!0})),s}function hh(t,e,n,s=!1,o=!1){let i=ft(t);if(!i||typeof i!="object")return t;let r=i,a=!1;if(r.host_template_types){if(s)r.host_template_types.includes("EMAIL")||(r.host_template_types=["EMAIL"],a=!0,n.push({module:e,field:"metaJson",message:'Fixed host_template_types to ["EMAIL"] for email module',autoFixed:!0}));else if(o){let l=r.host_template_types;l.includes("BLOG_POST")||l.includes("BLOG_LISTING")||(r.host_template_types=["BLOG_POST"],a=!0,n.push({module:e,field:"metaJson",message:"Fixed host_template_types to include blog type for blog module",autoFixed:!0}))}}else{let l=s?"EMAIL":o?"BLOG_POST":"PAGE";r.host_template_types=[l],a=!0}return r.is_available_for_new_content===void 0&&(r.is_available_for_new_content=!0,a=!0),a?(n.push({module:e,field:"metaJson",message:"Added missing meta.json required fields",autoFixed:!0}),JSON.stringify(r,null,2)):t}function md(t,e){let n=[],s=new Set(e.map(o=>`/${o}`));for(let o of t){if(!o.moduleName.includes("header")&&!o.moduleName.includes("nav")&&!o.moduleName.includes("footer"))continue;let i=/href=["'](\/?[a-z0-9][a-z0-9-]*(?:\/[a-z0-9-]*)*)["']/gi,r,a=[];for(;(r=i.exec(o.moduleHtml))!==null;){let l=r[1];l.startsWith("/")||(l="/"+l),!(l==="/"||l.startsWith("/http")||l.startsWith("/#"))&&a.push(l)}for(let l of a)s.has(l)||n.push({module:o.moduleName,message:`Nav link "${l}" does not match any page slug (valid: ${e.map(c=>"/"+c).join(", ")})`,autoFixed:!1})}return n}function bh(t,e,n){let s=new Set;if(e.colors?.primary&&s.add(e.colors.primary.toLowerCase()),e.colors?.secondary&&s.add(e.colors.secondary.toLowerCase()),e.colors?.accent&&s.add(e.colors.accent.toLowerCase()),s.size===0&&!e.fonts?.heading&&!e.fonts?.body)return;let o=(t.moduleHtml||"")+(t.moduleCss||"");if(s.size>0){let i=new Set;for(let a of o.matchAll(yh))i.add(a[0].toLowerCase());let r=new Set(["#ffffff","#000000","#f4f4f4","#f5f5f5","#fafafa","#eeeeee","#e0e0e0","#dddddd","#cccccc","#999999","#666666","#333333","#1a1a1a","#111111","#222222","#444444","#555555","#777777","#888888","#aaaaaa","#bbbbbb"]);for(let a of i)if(!r.has(a)&&!s.has(a)){n.push({module:t.moduleName,field:"moduleHtml",message:`Off-brand color ${a} (brand colors: ${[...s].join(", ")})`,autoFixed:!1});break}}if(e.fonts?.heading||e.fonts?.body){let i=[];e.fonts.heading&&i.push(e.fonts.heading.toLowerCase()),e.fonts.body&&i.push(e.fonts.body.toLowerCase());let r=/font-family:\s*([^;}"]+)/gi;for(let a of o.matchAll(r)){let l=a[1].toLowerCase().trim();if(!i.some(c=>l.includes(c))){n.push({module:t.moduleName,field:"moduleHtml",message:`Off-brand font "${a[1].trim()}" (brand fonts: ${i.join(", ")})`,autoFixed:!1});break}}}}function Sh(t,e){let n={...t},s=n.moduleHtml;n.moduleCss&&n.moduleCss.trim()&&(e.push({module:t.moduleName,field:"moduleCss",message:"Cleared moduleCss \u2014 email modules must use inline styles only",autoFixed:!0}),n.moduleCss=""),n.moduleJs&&n.moduleJs.trim()&&(e.push({module:t.moduleName,field:"moduleJs",message:"Cleared moduleJs \u2014 email clients do not support JavaScript",autoFixed:!0}),n.moduleJs=void 0),/<style[\s>]/i.test(s)&&(s=s.replace(/<style[^>]*>[\s\S]*?<\/style>/gi,""),e.push({module:t.moduleName,field:"moduleHtml",message:"Removed <style> blocks \u2014 email clients strip them",autoFixed:!0})),/display\s*:\s*flex/i.test(s)&&e.push({module:t.moduleName,field:"moduleHtml",message:"Contains display:flex \u2014 not supported in email clients",autoFixed:!1}),/display\s*:\s*grid/i.test(s)&&e.push({module:t.moduleName,field:"moduleHtml",message:"Contains display:grid \u2014 not supported in email clients",autoFixed:!1}),/var\s*\(/i.test(s)&&e.push({module:t.moduleName,field:"moduleHtml",message:"Contains var() \u2014 CSS custom properties not supported in email",autoFixed:!1});let o=/\{[{%].*?(?:require_css|require_js|scope_css|get_asset_url)\s*\(.*?\}[}%]/g;o.test(s)&&(s=s.replace(o,""),e.push({module:t.moduleName,field:"moduleHtml",message:"Removed banned HubL functions for email (require_css, require_js, scope_css, get_asset_url)",autoFixed:!0}));let i=/<link[^>]*href="https?:\/\/[^"]*(?:fonts\.googleapis|cdnjs|unpkg|jsdelivr)[^"]*"[^>]*\/?>/gi;return i.test(s)&&(s=s.replace(i,""),e.push({module:t.moduleName,field:"moduleHtml",message:"Removed CDN <link> tags \u2014 external resources not supported in email",autoFixed:!0})),n.moduleHtml=s,n}function xh(t,e){let n={...t},s=n.moduleHtml;return/\{\{[\s]*content\.body[\s]*\}\}/g.test(s)&&(s=s.replace(/\{\{[\s]*content\.body[\s]*\}\}/g,"{{ content.post_body }}"),e.push({module:t.moduleName,field:"moduleHtml",message:"Fixed content.body \u2192 content.post_body (correct blog variable)",autoFixed:!0})),/\{\{[\s]*content\.title[\s]*\}\}/g.test(s)&&(s=s.replace(/\{\{[\s]*content\.title[\s]*\}\}/g,"{{ content.name }}"),e.push({module:t.moduleName,field:"moduleHtml",message:"Fixed content.title \u2192 content.name (correct blog variable)",autoFixed:!0})),/\{\{[\s]*content\.author_name[\s]*\}\}/g.test(s)&&(s=s.replace(/\{\{[\s]*content\.author_name[\s]*\}\}/g,"{{ content.blog_post_author }}"),e.push({module:t.moduleName,field:"moduleHtml",message:"Fixed content.author_name \u2192 content.blog_post_author",autoFixed:!0})),/\{\{[\s]*content\.date[\s]*\}\}/g.test(s)&&(s=s.replace(/\{\{[\s]*content\.date[\s]*\}\}/g,"{{ content.publish_date }}"),e.push({module:t.moduleName,field:"moduleHtml",message:"Fixed content.date \u2192 content.publish_date",autoFixed:!0})),/\{\{[\s]*content\.image[\s]*\}\}/g.test(s)&&(s=s.replace(/\{\{[\s]*content\.image[\s]*\}\}/g,"{{ content.featured_image }}"),e.push({module:t.moduleName,field:"moduleHtml",message:"Fixed content.image \u2192 content.featured_image",autoFixed:!0})),/\{%.*dnd_area.*%\}/g.test(s)&&e.push({module:t.moduleName,field:"moduleHtml",message:"Contains dnd_area \u2014 blog templates typically use fixed module positions",autoFixed:!1}),/\{\{[\s]*content\.publish_date[\s]*\}\}/g.test(s)&&e.push({module:t.moduleName,field:"moduleHtml",message:"publish_date used without |datetimeformat filter \u2014 dates may render as raw timestamps",autoFixed:!1}),n.moduleHtml=s,n}var uh,yh,br=R(()=>{"use strict";y();wo();de();uh=new Set(["visible","active","scroll-animate","hidden","open","closed","fade-in","fade-out","is-active","is-open","is-visible"]);yh=/#[0-9a-fA-F]{6}\b/g});import{execSync as vh}from"child_process";async function pd(t,e,n,s,o,i,r,a){let l=Date.now(),c=i;if(xn(n)){let T={"claude-code":"claude","gemini-cli":"gemini","codex-cli":"codex"}[n];if(T)try{vh(`command -v ${T}`,{stdio:"ignore"})}catch{throw new Error(`CLI engine "${n}" requires "${T}" to be installed and on your PATH.`)}}let d=await Ec(t,e,n,s,o,r,a);if(d.intent==="question"&&d.answer){let N=Date.now()-l;return r({type:"pipeline_complete",modulesGenerated:0,modulesUnchanged:e.modules.length,durationMs:N,answer:d.answer}),{modules:[...e.modules],moduleOrder:e.moduleOrder,sharedCss:e.sharedCss,sharedJs:e.sharedJs,assistantMessage:d.answer,stats:{modulesGenerated:0,modulesUnchanged:e.modules.length,modulesFailed:0,durationMs:N}}}if(d.intent==="create_site"&&d.pages&&d.pages.length>0)return wh(t,d,e,n,s,o,i,r,l);let u=null,m=e.sharedCss,g=e.sharedJs;(d.intent==="create"||d.designSystemChanges)&&(u=await Hc(t,d,e,n,s,o,r),d.contentType!=="email"&&(m=u.designSystem.sharedCss||m,g=u.designSystem.sharedJs||g),r({type:"blueprint_ready",moduleOrder:u.moduleOrder,sharedCss:m,sharedJs:g}));let f=[];if(u)for(let N of u.modules)f.push({name:N.name,description:N.description,contentBrief:N.contentBrief,layoutNotes:N.layoutNotes});else{for(let N of d.newModules)f.push({name:N.name,description:N.description,contentBrief:"Generate appropriate content based on the user request",layoutNotes:"Use responsive layout matching the existing design system"});for(let N of d.affectedModules){let T=e.modules.find(I=>I.moduleName===N);T&&f.push({name:N,description:`Modify existing module: ${N}`,contentBrief:"Apply the user's requested changes",layoutNotes:"Preserve existing layout unless changes are requested",existingCode:T})}}let b=[],S=[];if(f.length>0){let N=await cs(t,f,m,e.themeName,n,s,o,c,r,d.guidesNeeded,e.brandAssets,d.contentType);for(let T of N)T.module?b.push(T.module):S.push(T.moduleName)}let x=null;if(b.length>0){x=zt(b,e.themeName,r,d.contentType,e.brandAssets?.brandKit);let N=x.filter(I=>I.issues.some(k=>k.field==="fieldsJson"&&k.message.includes("reset to empty"))).map(I=>I.module.moduleName);if(N.length>0){let I=N.map(k=>f.find(K=>K.name===k)).filter(k=>k!=null);if(I.length>0){E.info("pipeline",`Retrying ${I.length} module(s) with broken fieldsJson: ${I.map(K=>K.name).join(", ")}`),r({type:"agent_decision",step:"quality_check",decision:`Regenerating ${I.length} module(s) with invalid fields JSON...`});let k=await cs(t,I,m,e.themeName,n,s,o,c,r,d.guidesNeeded,e.brandAssets,d.contentType);for(let K of k)if(K.module){let oe=b.findIndex(it=>it.moduleName===K.moduleName);oe>=0&&(b[oe]=K.module)}x=zt(b,e.themeName,r,d.contentType,e.brandAssets?.brandKit)}}b=x.map(I=>I.module);let T=x.reduce((I,k)=>I+k.issues.length,0);if(T>0){let I=x.reduce((K,oe)=>K+oe.issues.filter(it=>it.autoFixed).length,0);E.info("pipeline",`Quality check: ${T} issues, ${I} auto-fixed`);let k=x.flatMap(K=>K.issues).map(K=>`${K.autoFixed?"\u2713":"\u26A0"} ${K.module}: ${K.message}`).join(`
2344
+ `);r({type:"agent_decision",step:"quality_check",decision:`${T} issues found, ${I} auto-fixed
2345
+ ${k}`})}else r({type:"agent_decision",step:"quality_check",decision:"All modules passed quality checks"})}let w=kh(e,d,b,u,a),P=Th(e,d,u,w);if(u?.moduleOrder?.length){let N=new Set(u.moduleOrder),T=w.filter(I=>!N.has(I.moduleName)).map(I=>I.moduleName);T.length>0&&r({type:"agent_decision",step:"quality_check",decision:`\u26A0 ${T.length} module${T.length===1?"":"s"} missing from page order \u2014 auto-inserted: ${T.join(", ")}`})}let F=Date.now()-l,H=b.length,L=d.unchangedModules.length,V=x?x.flatMap(N=>N.issues):[],B=Ah(d,H,L,S,F,u,V);return S.length>0?r({type:"pipeline_partial",succeeded:b.map(N=>N.moduleName),failed:S,durationMs:F}):r({type:"pipeline_complete",modulesGenerated:H,modulesUnchanged:L,durationMs:F,assistantMessage:B}),{modules:w,moduleOrder:P,sharedCss:m,sharedJs:g,assistantMessage:B,contentType:d.contentType,stats:{modulesGenerated:H,modulesUnchanged:L,modulesFailed:S.length,durationMs:F}}}async function wh(t,e,n,s,o,i,r,a,l){let c=e.pages,d=e.sharedModules||["site-header","site-footer"],u=await Bc(t,e,n,s,o,i,a),m=u.sharedCss||n.sharedCss,g=u.sharedJs||n.sharedJs;a({type:"blueprint_ready",moduleOrder:d,sharedCss:m,sharedJs:g});let h=await zc(t,e,n,m,s,o,i,a);a({type:"agent_step",step:"developing",label:`Generating modules for ${c.length} pages...`});let f=[];for(let k of h.sharedModules)f.push({...k});for(let k of h.pages)for(let K of k.modules)f.push({name:K.name,description:K.description,contentBrief:K.contentBrief,layoutNotes:K.layoutNotes});let b=c.map(k=>`- "${k.label}" \u2192 /${k.slug}`).join(`
2346
+ `);for(let k of f)(k.name.includes("header")||k.name.includes("nav"))&&(k.layoutNotes+=`
2347
+
2348
+ ## Site Navigation
2349
+ This is a multi-page site. Include navigation links to all pages:
2350
+ ${b}
2351
+ Use relative href paths. Add CSS class "${n.themeName}-nav__link--active" on the current page's link.`);let S=await cs(t,f,m,n.themeName,s,o,i,r,a,e.guidesNeeded,n.brandAssets,e.contentType),x=[],w=[];for(let k of S)k.module?x.push(k.module):w.push(k.moduleName);let P=x,F=[];if(x.length>0){let k=zt(x,n.themeName,a,e.contentType,n.brandAssets?.brandKit),K=k.filter(ie=>ie.issues.some(ye=>ye.field==="fieldsJson"&&ye.message.includes("reset to empty"))).map(ie=>ie.module.moduleName);if(K.length>0){let ie=K.map(ye=>f.find(le=>le.name===ye)).filter(ye=>ye!=null);if(ie.length>0){E.info("pipeline",`Retrying ${ie.length} module(s) with broken fieldsJson`),a({type:"agent_decision",step:"quality_check",decision:`Regenerating ${ie.length} module(s) with invalid fields JSON...`});let ye=await cs(t,ie,m,n.themeName,s,o,i,r,a,e.guidesNeeded,n.brandAssets,e.contentType);for(let le of ye)if(le.module){let Je=x.findIndex(ws=>ws.moduleName===le.moduleName);Je>=0&&(x[Je]=le.module)}k=zt(x,n.themeName,a,e.contentType,n.brandAssets?.brandKit)}}P=k.map(ie=>ie.module),F=k.flatMap(ie=>ie.issues);let oe=md(P,c.map(ie=>ie.slug));F.push(...oe);let it=F.length;if(it>0){let ie=F.filter(ye=>ye.autoFixed).length;a({type:"agent_decision",step:"quality_check",decision:`${it} issues found, ${ie} auto-fixed`})}else a({type:"agent_decision",step:"quality_check",decision:"All modules passed quality checks"})}let H=new Map(P.map(k=>[k.moduleName,k])),L=h.sharedModules.map(k=>H.get(k.name)).filter(k=>!!k),V=new Map(c.map(k=>[k.id,k])),B=h.pages.map(k=>{let K=k.modules.map(le=>H.get(le.name)).filter(le=>!!le),oe=d.filter(le=>le.includes("header")||le.includes("nav")),it=d.filter(le=>le.includes("footer")),ie=[...oe,...k.moduleOrder,...it],ye=V.get(k.pageId);return{pageId:k.pageId,templateId:k.pageId,label:ye?.label||k.pageId,pageType:ye?.pageType||"website_page",modules:[...L,...K],moduleOrder:ie}}),N=Date.now()-l,T=Ch(c,x.length,w,N,h.narrative,F);return w.length>0?a({type:"pipeline_partial",succeeded:x.map(k=>k.moduleName),failed:w,durationMs:N}):a({type:"pipeline_complete",modulesGenerated:x.length,modulesUnchanged:0,durationMs:N,assistantMessage:T}),{modules:P,moduleOrder:P.map(k=>k.moduleName),sharedCss:m,sharedJs:g||"",assistantMessage:T,stats:{modulesGenerated:x.length,modulesUnchanged:0,modulesFailed:w.length,durationMs:N},multiPage:{pages:B,sharedModules:L,sharedCss:m,sharedJs:g||"",assistantMessage:T,stats:{pagesGenerated:c.length,modulesGenerated:x.length,modulesFailed:w.length,durationMs:N}}}}function Ch(t,e,n,s,o,i){let r=Math.round(s/1e3),a=[];a.push(`Created ${t.length}-page site with ${e} modules in ${r}s.`),a.push(`
2352
+
2353
+ **Pages:** ${t.map(d=>d.label).join(", ")}`),o&&a.push(`
2354
+
2355
+ ${o}`),n.length>0&&a.push(`
2356
+
2357
+ **Failed:** ${n.join(", ")}. You can retry these individually.`);let l=i.filter(d=>!d.autoFixed),c=i.filter(d=>d.autoFixed);if(c.length>0||l.length>0){let d=[];c.length>0&&d.push(`**Auto-fixed:** ${c.map(u=>`${u.module}: ${u.message}`).join(", ")}`),l.length>0&&d.push(`**Warnings:** ${l.map(u=>`${u.module}: ${u.message}`).join(", ")}`),a.push(`
2358
+
2359
+ ${d.join(`
2360
+ `)}`)}return a.join("")}function kh(t,e,n,s,o){let i=[],r=new Set;for(let a of n)i.push(a),r.add(a.moduleName);for(let a of e.unchangedModules){if(r.has(a))continue;let l=t.modules.find(c=>c.moduleName===a);l&&(i.push(l),r.add(a))}if(e.reuseModules)for(let a of e.reuseModules){if(r.has(a.name))continue;let l=o.find(c=>c.name===a.name&&c.module);l&&l.module&&(i.push(l.module),r.add(a.name))}return i}function Th(t,e,n,s){if(n?.moduleOrder?.length){let a=[...n.moduleOrder],l=new Set(a);for(let c of s)if(!l.has(c.moduleName)){let d=a.findIndex(u=>u.toLowerCase().includes("footer"));d!==-1?a.splice(d,0,c.moduleName):a.push(c.moduleName),l.add(c.moduleName),E.warn("pipeline",`Module "${c.moduleName}" missing from blueprint order \u2014 inserted`)}return a}if(e.intent==="create")return s.map(a=>a.moduleName);let o=[...t.moduleOrder],i=[...e.newModules.map(a=>({name:a.name,position:a.position})),...(e.reuseModules||[]).map(a=>({name:a.name,position:a.position}))].sort((a,l)=>a.position-l.position);for(let a of i){let l=Math.min(a.position,o.length);o.splice(l,0,a.name)}let r=new Set(s.map(a=>a.moduleName));return o.filter(a=>r.has(a))}function Ah(t,e,n,s,o,i,r){let a=Math.round(o/1e3),l=[];if(t.intent==="create")l.push(`Created ${e} module${e===1?"":"s"} in ${a}s.`);else if(t.intent==="modify"||t.intent==="style_change")l.push(`Updated ${e} module${e===1?"":"s"} in ${a}s.`),n>0&&l.push(`${n} module${n===1?"":"s"} unchanged.`);else if(t.intent==="add"){let u=t.newModules.map(m=>m.name).join(", ");l.push(`Added ${u} in ${a}s.`)}else t.intent==="remove"?l.push(`Removed modules in ${a}s.`):t.intent==="rearrange"&&l.push(`Rearranged modules in ${a}s.`);i?.narrative&&l.push(`
1284
2361
 
1285
2362
  ${i.narrative}`),s.length>0&&l.push(`
1286
2363
 
1287
2364
  **Failed:** ${s.join(", ")}. You can retry these individually.`);let c=r.filter(u=>!u.autoFixed),d=r.filter(u=>u.autoFixed);if(d.length>0||c.length>0){let u=[];d.length>0&&u.push(`**Auto-fixed:** ${d.map(m=>`${m.module}: ${m.message}`).join(", ")}`),c.length>0&&u.push(`**Warnings:** ${c.map(m=>`${m.module}: ${m.message}`).join(", ")}`),l.push(`
1288
2365
 
1289
2366
  ${u.join(`
1290
- `)}`)}return l.join("")}var rc=G(()=>{"use strict";g();nt();Ul();Xl();nc();Ui();re();nt()});var uc={};_e(uc,{runFigmaConversion:()=>Uf});import{basename as cc}from"path";async function Uf(e,t,n,s,o,i,r,a,l){let c=Date.now();r({type:"agent_step",step:"designing",label:"Building design system from Figma tokens..."});let{sharedCss:d,sharedJs:u}=Gf(e.designTokens,t);r({type:"design_system_ready",sharedCss:d,sharedJs:u,aesthetic:"Figma import"}),r({type:"agent_decision",step:"designing",decision:`Generated CSS variables and utility classes from ${e.designTokens.colors.length} colors, ${e.designTokens.typography.length} typography styles`});let{specs:m,moduleOrder:f}=Vf(e.sections,e.assets,t);r({type:"blueprint_ready",moduleOrder:f,sharedCss:d,sharedJs:u}),r({type:"agent_decision",step:"designing",decision:`Mapped ${m.length} Figma sections to modules: ${f.join(", ")}`}),r({type:"agent_step",step:"developing",label:`Converting ${m.length} modules...`});let y=n==="anthropic-api"||n==="claude-oauth",h=Bn(t,d,["hubspot_rules","conversion"],a),S=y?oo(t,d,["hubspot_rules","conversion"],a):void 0,x=so(i),w=m.length,v=m.map((M,te)=>{let es=e.sections[te];return x(async()=>{r({type:"module_progress",module:M.name,status:"generating",current:te+1,total:w});let It=Yf(es,M,e.assets,t,l!==!1),Fo="";for(let pn=0;pn<2;pn++)try{pn>0&&(E.warn("figma-pipeline",`${M.name}: retrying (attempt ${pn+1})`),r({type:"module_progress",module:M.name,status:"retrying",current:te+1,total:w}));let Bt=await Re(n,s,o,{systemPrompt:h,systemBlocks:S,messages:[{role:"user",content:It}],structuredOutput:{schema:io,name:"module_output"},maxTokens:16e3});if(Bt.type!=="structured")throw new Error("No structured output returned");let ze=Bt.data,Ir={moduleName:M.name,fieldsJson:typeof ze.fieldsJson=="string"?ze.fieldsJson:JSON.stringify(ze.fieldsJson,null,2),metaJson:typeof ze.metaJson=="string"?ze.metaJson:JSON.stringify(ze.metaJson,null,2),moduleHtml:String(ze.moduleHtml||""),moduleCss:String(ze.moduleCss||""),moduleJs:ze.moduleJs?String(ze.moduleJs):void 0};return r({type:"module_progress",module:M.name,status:"complete",current:te+1,total:w,moduleFiles:Ir}),{moduleName:M.name,module:Ir}}catch(Bt){Fo=Bt instanceof Error?Bt.message:String(Bt),E.error("figma-pipeline",`Failed: ${M.name} (attempt ${pn+1}): ${Fo}`)}return r({type:"module_progress",module:M.name,status:"failed",current:te+1,total:w}),{moduleName:M.name,error:Fo}})}),O=(await Promise.allSettled(v)).map(M=>M.status==="fulfilled"?M.value:{moduleName:"unknown",error:String(M.reason)}),F=O.filter(M=>M.module).map(M=>M.module),U=O.filter(M=>M.error).map(M=>M.moduleName),_=ro(F,t,r).map(M=>M.module),j=Date.now()-c,k=Math.round(j/1e3);return U.length>0?r({type:"pipeline_partial",succeeded:_.map(M=>M.moduleName),failed:U,durationMs:j}):r({type:"pipeline_complete",modulesGenerated:_.length,modulesUnchanged:0,durationMs:j}),{modules:_,moduleOrder:f,sharedCss:d,sharedJs:u,assistantMessage:`Imported ${_.length} modules from Figma design "${e.fileName}" in ${k}s.`,stats:{modulesGenerated:_.length,modulesUnchanged:0,modulesFailed:U.length,durationMs:j}}}function ao(e){let t=parseInt(e.slice(1,3),16)/255,n=parseInt(e.slice(3,5),16)/255,s=parseInt(e.slice(5,7),16)/255,o=Math.max(t,n,s),i=Math.min(t,n,s),r=(o+i)/2;if(o===i)return{h:0,s:0,l:r};let a=o-i,l=r>.5?a/(2-o-i):a/(o+i),c=0;return o===t?c=((n-s)/a+(n<s?6:0))/6:o===n?c=((s-t)/a+2)/6:c=((t-n)/a+4)/6,{h:c*360,s:l,l:r}}function Gf(e,t){let n=[],s=t,o=[...e.colors].sort((k,M)=>M.occurrences-k.occurrences),i=o.filter(k=>k.usage==="background"||k.usage==="fill"),r=o.filter(k=>k.usage==="text"),a=i[0]||o[0],l=a?ao(a.hex).l<.4:!1;a&&n.push(` --${s}-color-bg: ${a.hex}`);let c=r[0]||(l?o.find(k=>ao(k.hex).l>.7):o.find(k=>ao(k.hex).l<.3));c&&n.push(` --${s}-color-text: ${c.hex}`);let d=new Set([a?.hex,c?.hex].filter(Boolean)),u=o.filter(k=>!d.has(k.hex));if(u[0]&&(n.push(` --${s}-color-primary: ${u[0].hex}`),d.add(u[0].hex)),u[1]&&(n.push(` --${s}-color-accent: ${u[1].hex}`),d.add(u[1].hex)),u.filter(k=>!d.has(k.hex)).slice(0,6).forEach((k,M)=>n.push(` --${s}-color-${M+1}: ${k.hex}`)),a){let k=ao(a.hex).l;n.push(` --${s}-color-surface: ${l?ac(a.hex,.05):lc(a.hex,.03)}`),n.push(` --${s}-color-border: ${l?ac(a.hex,.15):lc(a.hex,.12)}`)}let f=e.typography.filter(k=>k.role==="heading"||k.role==="subheading"),y=e.typography.filter(k=>k.role==="body"||k.role==="label"||k.role==="caption"),h=f[0]?.fontFamily||y[0]?.fontFamily||"system-ui",S=y[0]?.fontFamily||h;n.push(` --${s}-font-display: "${h}", system-ui, sans-serif`),n.push(` --${s}-font-body: "${S}", system-ui, sans-serif`);let x=f.sort((k,M)=>M.fontSize-k.fontSize);x[0]&&n.push(` --${s}-size-h1: ${x[0].fontSize}px`),x[1]&&n.push(` --${s}-size-h2: ${x[1].fontSize}px`),x[2]&&n.push(` --${s}-size-h3: ${x[2].fontSize}px`);let w=y.sort((k,M)=>M.occurrences-k.occurrences)[0];w&&n.push(` --${s}-size-body: ${w.fontSize}px`);let v=[...new Set(e.spacing.map(k=>k.value))].sort((k,M)=>k-M),N=["xs","sm","md","lg","xl","2xl","section"];v.slice(0,N.length).forEach((k,M)=>{n.push(` --${s}-space-${N[M]}: ${k}px`)});let O=e.effects.filter(k=>k.type==="shadow"),F=e.effects.filter(k=>k.type==="radius");O[0]&&n.push(` --${s}-shadow: ${O[0].cssValue}`),F.sort((k,M)=>parseFloat(k.cssValue)-parseFloat(M.cssValue)),F[0]&&n.push(` --${s}-radius: ${F[0].cssValue}`),F[1]&&n.push(` --${s}-radius-lg: ${F[1].cssValue}`);let U=`:root {
2367
+ `)}`)}return l.join("")}var gd=R(()=>{"use strict";y();nt();Ic();Uc();Yc();cd();br();de();nt()});var Sd={};Be(Sd,{runFigmaConversion:()=>$h});import{basename as yd}from"path";async function $h(t,e,n,s,o,i,r,a,l){let c=Date.now();r({type:"agent_step",step:"designing",label:"Building design system from Figma tokens..."});let{sharedCss:d,sharedJs:u}=_h(t.designTokens,e);r({type:"design_system_ready",sharedCss:d,sharedJs:u,aesthetic:"Figma import"}),r({type:"agent_decision",step:"designing",decision:`Generated CSS variables and utility classes from ${t.designTokens.colors.length} colors, ${t.designTokens.typography.length} typography styles`});let{specs:m,moduleOrder:g}=Eh(t.sections,t.assets,e);r({type:"blueprint_ready",moduleOrder:g,sharedCss:d,sharedJs:u}),r({type:"agent_decision",step:"designing",decision:`Mapped ${m.length} Figma sections to modules: ${g.join(", ")}`}),r({type:"agent_step",step:"developing",label:`Converting ${m.length} modules...`});let h=n==="anthropic-api"||n==="claude-oauth",f=as(e,d,["hubspot_rules","conversion"],a),b=h?_o(e,d,["hubspot_rules","conversion"],a):void 0,S=$o(i),x=m.length,w=m.map((k,K)=>{let oe=t.sections[K];return S(async()=>{r({type:"module_progress",module:k.name,status:"generating",current:K+1,total:x});let it=Rh(oe,k,t.assets,e,l!==!1),ie="";for(let ye=0;ye<2;ye++)try{ye>0&&(E.warn("figma-pipeline",`${k.name}: retrying (attempt ${ye+1})`),r({type:"module_progress",module:k.name,status:"retrying",current:K+1,total:x}));let le=await _e(n,s,o,{systemPrompt:f,systemBlocks:b,messages:[{role:"user",content:it}],structuredOutput:{schema:ls,name:"module_output"},maxTokens:16e3});if(le.type!=="structured")throw new Error("No structured output returned");let Je=le.data,ws={moduleName:k.name,fieldsJson:typeof Je.fieldsJson=="string"?Je.fieldsJson:JSON.stringify(Je.fieldsJson,null,2),metaJson:typeof Je.metaJson=="string"?Je.metaJson:JSON.stringify(Je.metaJson,null,2),moduleHtml:String(Je.moduleHtml||""),moduleCss:String(Je.moduleCss||""),moduleJs:Je.moduleJs?String(Je.moduleJs):void 0};return r({type:"module_progress",module:k.name,status:"complete",current:K+1,total:x,moduleFiles:ws}),{moduleName:k.name,module:ws}}catch(le){ie=le instanceof Error?le.message:String(le),E.error("figma-pipeline",`Failed: ${k.name} (attempt ${ye+1}): ${ie}`)}return r({type:"module_progress",module:k.name,status:"failed",current:K+1,total:x}),{moduleName:k.name,error:ie}})}),F=(await Promise.allSettled(w)).map(k=>k.status==="fulfilled"?k.value:{moduleName:"unknown",error:String(k.reason)}),H=F.filter(k=>k.module).map(k=>k.module),L=F.filter(k=>k.error).map(k=>k.moduleName),B=zt(H,e,r).map(k=>k.module),N=Date.now()-c,T=Math.round(N/1e3),I=`Imported ${B.length} modules from Figma design "${t.fileName}" in ${T}s.`;return L.length>0?r({type:"pipeline_partial",succeeded:B.map(k=>k.moduleName),failed:L,durationMs:N}):r({type:"pipeline_complete",modulesGenerated:B.length,modulesUnchanged:0,durationMs:N,assistantMessage:I}),{modules:B,moduleOrder:g,sharedCss:d,sharedJs:u,assistantMessage:I,stats:{modulesGenerated:B.length,modulesUnchanged:0,modulesFailed:L.length,durationMs:N}}}function Mo(t){let e=parseInt(t.slice(1,3),16)/255,n=parseInt(t.slice(3,5),16)/255,s=parseInt(t.slice(5,7),16)/255,o=Math.max(e,n,s),i=Math.min(e,n,s),r=(o+i)/2;if(o===i)return{h:0,s:0,l:r};let a=o-i,l=r>.5?a/(2-o-i):a/(o+i),c=0;return o===e?c=((n-s)/a+(n<s?6:0))/6:o===n?c=((s-e)/a+2)/6:c=((e-n)/a+4)/6,{h:c*360,s:l,l:r}}function _h(t,e){let n=[],s=e,o=[...t.colors].sort((T,I)=>I.occurrences-T.occurrences),i=o.filter(T=>T.usage==="background"||T.usage==="fill"),r=o.filter(T=>T.usage==="text"),a=i[0]||o[0],l=a?Mo(a.hex).l<.4:!1;a&&n.push(` --${s}-color-bg: ${a.hex}`);let c=r[0]||(l?o.find(T=>Mo(T.hex).l>.7):o.find(T=>Mo(T.hex).l<.3));c&&n.push(` --${s}-color-text: ${c.hex}`);let d=new Set([a?.hex,c?.hex].filter(Boolean)),u=o.filter(T=>!d.has(T.hex));if(u[0]&&(n.push(` --${s}-color-primary: ${u[0].hex}`),d.add(u[0].hex)),u[1]&&(n.push(` --${s}-color-accent: ${u[1].hex}`),d.add(u[1].hex)),u.filter(T=>!d.has(T.hex)).slice(0,6).forEach((T,I)=>n.push(` --${s}-color-${I+1}: ${T.hex}`)),a){let T=Mo(a.hex).l;n.push(` --${s}-color-surface: ${l?fd(a.hex,.05):hd(a.hex,.03)}`),n.push(` --${s}-color-border: ${l?fd(a.hex,.15):hd(a.hex,.12)}`)}let g=t.typography.filter(T=>T.role==="heading"||T.role==="subheading"),h=t.typography.filter(T=>T.role==="body"||T.role==="label"||T.role==="caption"),f=g[0]?.fontFamily||h[0]?.fontFamily||"system-ui",b=h[0]?.fontFamily||f;n.push(` --${s}-font-display: "${f}", system-ui, sans-serif`),n.push(` --${s}-font-body: "${b}", system-ui, sans-serif`);let S=g.sort((T,I)=>I.fontSize-T.fontSize);S[0]&&n.push(` --${s}-size-h1: ${S[0].fontSize}px`),S[1]&&n.push(` --${s}-size-h2: ${S[1].fontSize}px`),S[2]&&n.push(` --${s}-size-h3: ${S[2].fontSize}px`);let x=h.sort((T,I)=>I.occurrences-T.occurrences)[0];x&&n.push(` --${s}-size-body: ${x.fontSize}px`);let w=[...new Set(t.spacing.map(T=>T.value))].sort((T,I)=>T-I),P=["xs","sm","md","lg","xl","2xl","section"];w.slice(0,P.length).forEach((T,I)=>{n.push(` --${s}-space-${P[I]}: ${T}px`)});let F=t.effects.filter(T=>T.type==="shadow"),H=t.effects.filter(T=>T.type==="radius");F[0]&&n.push(` --${s}-shadow: ${F[0].cssValue}`),H.sort((T,I)=>parseFloat(T.cssValue)-parseFloat(I.cssValue)),H[0]&&n.push(` --${s}-radius: ${H[0].cssValue}`),H[1]&&n.push(` --${s}-radius-lg: ${H[1].cssValue}`);let L=`:root {
1291
2368
  ${n.join(`;
1292
2369
  `)};
1293
- }`,q=`
2370
+ }`,V=`
1294
2371
  /* Reset */
1295
2372
  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
1296
2373
 
@@ -1374,8 +2451,8 @@ body {
1374
2451
  h1 { font-size: 2rem; }
1375
2452
  h2 { font-size: 1.5rem; }
1376
2453
  h3 { font-size: 1.25rem; }
1377
- }`;return{sharedCss:U+`
1378
- `+q,sharedJs:`(function() {
2454
+ }`;return{sharedCss:L+`
2455
+ `+V,sharedJs:`(function() {
1379
2456
  var observer = new IntersectionObserver(function(entries) {
1380
2457
  entries.forEach(function(entry) {
1381
2458
  if (entry.isIntersecting) {
@@ -1385,11 +2462,11 @@ body {
1385
2462
  });
1386
2463
  }, { threshold: 0.1 });
1387
2464
  document.querySelectorAll('[data-animate]').forEach(function(el) { observer.observe(el); });
1388
- })();`}}function ac(e,t){return dc(e,t)}function lc(e,t){return dc(e,-t)}function dc(e,t){let n=parseInt(e.slice(1,3),16),s=parseInt(e.slice(3,5),16),o=parseInt(e.slice(5,7),16);return n=Math.min(255,Math.max(0,Math.round(n+255*t))),s=Math.min(255,Math.max(0,Math.round(s+255*t))),o=Math.min(255,Math.max(0,Math.round(o+255*t))),`#${n.toString(16).padStart(2,"0")}${s.toString(16).padStart(2,"0")}${o.toString(16).padStart(2,"0")}`}function Wf(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[^a-zA-Z0-9]+/g,"-").replace(/(^-|-$)/g,"").toLowerCase()}function Vf(e,t,n){let s=new Set,o=[];for(let i of e){let r=Wf(i.name);if(s.has(r)){let d=2;for(;s.has(`${r}-${d}`);)d++;r=`${r}-${d}`}s.add(r);let a=zf(i.textContent),l=Kf(i,t,n),c=`Figma section "${i.name}" \u2014 ${i.width}x${i.height}px, ${i.textContent.length} text elements, ${i.children.length} children`;o.push({name:r,description:c,contentBrief:a,layoutNotes:l})}return{specs:o,moduleOrder:o.map(i=>i.name)}}function zf(e){let t={};for(let o of e){let i=o.role;t[i]||(t[i]=[]),t[i].push(o.text)}let n=[],s=["headline","subheadline","body","cta","label","caption"];for(let o of s)if(t[o])for(let i of t[o])n.push(`**${o}** (use as field default): "${i}"`);return n.join(`
1389
- `)}function Kf(e,t,n){let s=[];if(s.push(`Dimensions: ${e.width}x${e.height}px`),e.backgroundColor&&s.push(`Background: ${e.backgroundColor}`),e.layoutMode&&s.push(`Layout: ${e.layoutMode}`),e.itemSpacing&&s.push(`Gap: ${e.itemSpacing}px`),(e.paddingTop||e.paddingRight||e.paddingBottom||e.paddingLeft)&&s.push(`Padding: ${e.paddingTop||0}px ${e.paddingRight||0}px ${e.paddingBottom||0}px ${e.paddingLeft||0}px`),e.children.length>0){s.push(`
1390
- Children (${e.children.length}):`);for(let o of e.children){let i=` - ${o.type} "${o.name}" (${o.width}x${o.height})`;o.layoutMode&&(i+=` [${o.layoutMode}]`),o.childCount>0&&(i+=` [${o.childCount} children]`),o.characters&&(i+=` text: "${o.characters.slice(0,60)}"`),s.push(i)}}if(t.length>0){s.push(`
1391
- Available image assets:`);for(let o of t){let i=cc(o.localPath);s.push(` - get_asset_url("${n}/assets/${i}") \u2014 ${o.name}`)}}return s.join(`
1392
- `)}function Yf(e,t,n,s,o){let i=[];if(i.push(`## Figma Design Translation
2465
+ })();`}}function fd(t,e){return bd(t,e)}function hd(t,e){return bd(t,-e)}function bd(t,e){let n=parseInt(t.slice(1,3),16),s=parseInt(t.slice(3,5),16),o=parseInt(t.slice(5,7),16);return n=Math.min(255,Math.max(0,Math.round(n+255*e))),s=Math.min(255,Math.max(0,Math.round(s+255*e))),o=Math.min(255,Math.max(0,Math.round(o+255*e))),`#${n.toString(16).padStart(2,"0")}${s.toString(16).padStart(2,"0")}${o.toString(16).padStart(2,"0")}`}function Mh(t){return t.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[^a-zA-Z0-9]+/g,"-").replace(/(^-|-$)/g,"").toLowerCase()}function Eh(t,e,n){let s=new Set,o=[];for(let i of t){let r=Mh(i.name);if(s.has(r)){let d=2;for(;s.has(`${r}-${d}`);)d++;r=`${r}-${d}`}s.add(r);let a=Ih(i.textContent),l=Ph(i,e,n),c=`Figma section "${i.name}" \u2014 ${i.width}x${i.height}px, ${i.textContent.length} text elements, ${i.children.length} children`;o.push({name:r,description:c,contentBrief:a,layoutNotes:l})}return{specs:o,moduleOrder:o.map(i=>i.name)}}function Ih(t){let e={};for(let o of t){let i=o.role;e[i]||(e[i]=[]),e[i].push(o.text)}let n=[],s=["headline","subheadline","body","cta","label","caption"];for(let o of s)if(e[o])for(let i of e[o])n.push(`**${o}** (use as field default): "${i}"`);return n.join(`
2466
+ `)}function Ph(t,e,n){let s=[];if(s.push(`Dimensions: ${t.width}x${t.height}px`),t.backgroundColor&&s.push(`Background: ${t.backgroundColor}`),t.layoutMode&&s.push(`Layout: ${t.layoutMode}`),t.itemSpacing&&s.push(`Gap: ${t.itemSpacing}px`),(t.paddingTop||t.paddingRight||t.paddingBottom||t.paddingLeft)&&s.push(`Padding: ${t.paddingTop||0}px ${t.paddingRight||0}px ${t.paddingBottom||0}px ${t.paddingLeft||0}px`),t.children.length>0){s.push(`
2467
+ Children (${t.children.length}):`);for(let o of t.children){let i=` - ${o.type} "${o.name}" (${o.width}x${o.height})`;o.layoutMode&&(i+=` [${o.layoutMode}]`),o.childCount>0&&(i+=` [${o.childCount} children]`),o.characters&&(i+=` text: "${o.characters.slice(0,60)}"`),s.push(i)}}if(e.length>0){s.push(`
2468
+ Available image assets:`);for(let o of e){let i=yd(o.localPath);s.push(` - get_asset_url("${n}/assets/${i}") \u2014 ${o.name}`)}}return s.join(`
2469
+ `)}function Rh(t,e,n,s,o){let i=[];if(i.push(`## Figma Design Translation
1393
2470
 
1394
2471
  TRANSLATE this Figma section into a HubSpot CMS module. This is a CONVERSION, not creation.
1395
2472
  - Use the EXACT text content from the design as field default values
@@ -1409,17 +2486,17 @@ The Figma design shows the DESKTOP layout. You MUST add responsive CSS:
1409
2486
  - Hide purely decorative elements if they break mobile layout
1410
2487
  - Add a \`@media (max-width: 1023px)\` block for tablet if the layout has 3+ columns
1411
2488
 
1412
- ## Section: "${e.name}" (${e.width}x${e.height}px)`),e.backgroundColor&&i.push(`Background: ${e.backgroundColor}`),(e.layoutMode||e.itemSpacing||e.paddingTop)&&(i.push(`
1413
- ### Layout`),e.layoutMode&&i.push(`Direction: ${e.layoutMode}`),e.itemSpacing&&i.push(`Gap: ${e.itemSpacing}px`),(e.paddingTop||e.paddingRight||e.paddingBottom||e.paddingLeft)&&i.push(`Padding: ${e.paddingTop||0}px ${e.paddingRight||0}px ${e.paddingBottom||0}px ${e.paddingLeft||0}px`)),e.textContent.length>0){i.push(`
1414
- ### Text Content \u2014 USE THESE AS FIELD DEFAULTS`);for(let r of e.textContent)i.push(`- **${r.role}** (${r.fontSize}px, weight ${r.fontWeight}): "${r.text}"`)}if(e.children.length>0){i.push(`
1415
- ### Structure (${e.children.length} children)`);for(let r of e.children){let a=`- ${r.type} "${r.name}" (${r.width}x${r.height})`;r.layoutMode&&(a+=` layout: ${r.layoutMode}`),r.childCount>0&&(a+=`, ${r.childCount} children`),r.characters&&(a+=`
2489
+ ## Section: "${t.name}" (${t.width}x${t.height}px)`),t.backgroundColor&&i.push(`Background: ${t.backgroundColor}`),(t.layoutMode||t.itemSpacing||t.paddingTop)&&(i.push(`
2490
+ ### Layout`),t.layoutMode&&i.push(`Direction: ${t.layoutMode}`),t.itemSpacing&&i.push(`Gap: ${t.itemSpacing}px`),(t.paddingTop||t.paddingRight||t.paddingBottom||t.paddingLeft)&&i.push(`Padding: ${t.paddingTop||0}px ${t.paddingRight||0}px ${t.paddingBottom||0}px ${t.paddingLeft||0}px`)),t.textContent.length>0){i.push(`
2491
+ ### Text Content \u2014 USE THESE AS FIELD DEFAULTS`);for(let r of t.textContent)i.push(`- **${r.role}** (${r.fontSize}px, weight ${r.fontWeight}): "${r.text}"`)}if(t.children.length>0){i.push(`
2492
+ ### Structure (${t.children.length} children)`);for(let r of t.children){let a=`- ${r.type} "${r.name}" (${r.width}x${r.height})`;r.layoutMode&&(a+=` layout: ${r.layoutMode}`),r.childCount>0&&(a+=`, ${r.childCount} children`),r.characters&&(a+=`
1416
2493
  text: "${r.characters.slice(0,100)}"`),i.push(a)}}if(n.length>0)if(o){i.push(`
1417
- ### Available Image Assets \u2014 USE get_asset_url()`),i.push("Images are uploaded as theme assets. Reference them with get_asset_url():");for(let r of n){let a=cc(r.localPath);i.push(`- \`get_asset_url("${s}/assets/${a}")\` \u2014 ${r.name}`)}}else{i.push(`
2494
+ ### Available Image Assets \u2014 USE get_asset_url()`),i.push("Images are uploaded as theme assets. Reference them with get_asset_url():");for(let r of n){let a=yd(r.localPath);i.push(`- \`get_asset_url("${s}/assets/${a}")\` \u2014 ${r.name}`)}}else{i.push(`
1418
2495
  ### Images \u2014 USE IMAGE FIELDS WITH PLACEHOLDERS`),i.push('Do NOT use get_asset_url(). Instead, create "image" type fields in fields.json for each image.'),i.push('Set a descriptive default.src (e.g. "https://placehold.co/600x400?text=Hero+Image") and default.alt text.'),i.push("In the module HTML, use: {{ module.field_name.src }} and {{ module.field_name.alt }}"),i.push("This gives content editors full control to replace images in HubSpot.");for(let r of n)i.push(`- "${r.name}" \u2014 create an image field for this`)}return i.push(`
1419
2496
  ## Module Specification
1420
- - **Name**: ${t.name}
1421
- - **Description**: ${t.description}`),i.join(`
1422
- `)}var mc=G(()=>{"use strict";g();nt();Hi();Bi();Ui();re()});var pc={};_e(pc,{buildPlanModePrompt:()=>qf});function qf(e,t,n,s,o){let i=Xf(o,!!t?.plan),r=[];return r.push(`You are vibeSpot's plan-mode assistant for the theme "${e}".
2497
+ - **Name**: ${e.name}
2498
+ - **Description**: ${e.description}`),i.join(`
2499
+ `)}var xd=R(()=>{"use strict";y();nt();gr();fr();br();de()});var vd={};Be(vd,{buildPlanModePrompt:()=>Nh});function Nh(t,e,n,s,o){let i=Oh(o,!!e?.plan),r=[];return r.push(`You are vibeSpot's plan-mode assistant for the theme "${t}".
1423
2500
 
1424
2501
  Plan mode is a DELIBERATION PHASE. Your job is to help the user articulate what they want to build BEFORE any code is generated. You do NOT write modules, HTML, or CSS in this mode. You ask questions, surface gaps, and maintain a living plan document.
1425
2502
 
@@ -1483,20 +2560,20 @@ Drive toward filling these gaps in priority order:
1483
2560
  4. **Sections / modules** \u2014 high-level page structure (hero, features, testimonials, pricing, FAQ, footer, etc.)
1484
2561
  5. **Content** \u2014 actual copy, value props, social proof, key messages
1485
2562
  6. **Brand voice and visual style** \u2014 formal/casual, palette preferences, reference sites
1486
- 7. **Constraints** \u2014 must-haves, must-avoids, integrations needed`),t?.styleguide&&r.push(`## Available styleguide
2563
+ 7. **Constraints** \u2014 must-haves, must-avoids, integrations needed`),e?.styleguide&&r.push(`## Available styleguide
1487
2564
 
1488
2565
  The theme already has a styleguide. Reference its colors, typography, and tokens in the plan rather than asking about them again.
1489
2566
 
1490
2567
  \`\`\`
1491
- ${Gi(t.styleguide,1500)}
1492
- \`\`\``),t?.brandvoice&&r.push(`## Available brand voice
2568
+ ${Sr(e.styleguide,1500)}
2569
+ \`\`\``),e?.brandvoice&&r.push(`## Available brand voice
1493
2570
 
1494
2571
  \`\`\`
1495
- ${Gi(t.brandvoice,1e3)}
1496
- \`\`\``),t?.themeContext&&r.push(`## Theme context
2572
+ ${Sr(e.brandvoice,1e3)}
2573
+ \`\`\``),e?.themeContext&&r.push(`## Theme context
1497
2574
 
1498
2575
  \`\`\`
1499
- ${Gi(t.themeContext,1e3)}
2576
+ ${Sr(e.themeContext,1e3)}
1500
2577
  \`\`\``),n.length>0&&r.push(`## Existing modules in this theme
1501
2578
 
1502
2579
  These already exist on the page \u2014 you can keep, modify, or remove them in the plan, or reference them as reusable:
@@ -1507,23 +2584,23 @@ ${n.map(a=>`- ${a}`).join(`
1507
2584
  These modules exist in other templates and could be reused here. Reference them by name in the plan if appropriate.
1508
2585
 
1509
2586
  ${s.map(a=>`- **${a.name}** (used in: ${a.usedIn.join(", ")})`).join(`
1510
- `)}`),t?.plan&&r.push(`## Current plan (continue refining)
2587
+ `)}`),e?.plan&&r.push(`## Current plan (continue refining)
1511
2588
 
1512
2589
  The plan in progress so far. Build on it \u2014 preserve what's there, only update sections that are changing based on the user's latest message.
1513
2590
 
1514
2591
  \`\`\`markdown
1515
- ${t.plan}
2592
+ ${e.plan}
1516
2593
  \`\`\``),r.push(`## Phase guidance for this turn
1517
2594
 
1518
2595
  ${i}`),r.join(`
1519
2596
 
1520
- `)}function Xf(e,t){return e===0&&!t?"**Phase 1: UNDERSTAND.** This is the user's first message in plan mode. Acknowledge what they said, then ask 2\u20133 high-leverage questions to surface gaps. The plan block should be a skeleton with TBDs and an **Open questions** section. Do NOT propose specific sections or content yet \u2014 you don't know enough.":e===0&&t?`**Phase 1-T: TEMPLATED START.** The user picked a plan-mode template, so a structured plan already exists. Your job on this turn is to:
2597
+ `)}function Oh(t,e){return t===0&&!e?"**Phase 1: UNDERSTAND.** This is the user's first message in plan mode. Acknowledge what they said, then ask 2\u20133 high-leverage questions to surface gaps. The plan block should be a skeleton with TBDs and an **Open questions** section. Do NOT propose specific sections or content yet \u2014 you don't know enough.":t===0&&e?`**Phase 1-T: TEMPLATED START.** The user picked a plan-mode template, so a structured plan already exists. Your job on this turn is to:
1521
2598
  - Briefly acknowledge the template and that you'll work from this structure (1\u20132 sentences in chat).
1522
2599
  - Pick 2\u20133 of the highest-leverage items from the plan's **Open questions** section and ask the user about them. Prefer questions about: product/page name + one-line pitch, primary CTA, and target audience. Save tone/visual questions for later turns.
1523
2600
  - Do NOT propose new sections or rewrite the existing structure on this turn \u2014 the user explicitly chose this scaffold. Keep the plan block VERBATIM (same headings, same sections, same open-questions list) and only re-emit it.
1524
2601
  - If the user's first message already supplies content (e.g. "It's for Acme, a fintech startup, primary CTA is book a demo"), thread that into the plan's TBDs and check those items off the **Open questions** list before asking your follow-ups.
1525
- - Use \`vibespot-choices\` chips when one of your questions is multiple-choice (e.g. "Primary CTA?", "Cuisine?").`:e<=2&&!t?"**Phase 2: RESEARCH & DRAFT.** Take what the user has shared and produce a real first draft of the plan: goal, audience, primary CTA, and a proposed module list with brief descriptions. Reference existing modules/styleguide where applicable. Ask 1\u20132 narrow follow-ups to fill remaining gaps. Don't be exhaustive \u2014 a directionally-correct draft is better than asking 10 more questions.":`**Phase 3: REFINE.** A plan exists. Update it based on the user's latest message \u2014 change only what they're asking to change, preserve the rest. Confirm what you've updated in your conversational reply ("I changed the hero CTA to 'Get started free' and added a logos bar before the features section."). Ask narrow clarifying questions only when the user's edit creates a new ambiguity.`}function Gi(e,t){return e.length<=t?e:e.slice(0,t)+`
1526
- ... [truncated]`}var fc=G(()=>{"use strict";g()});var Zi={};_e(Zi,{applyPipelineResult:()=>Dt,handleAgenticGenerate:()=>lo,handleFigmaImport:()=>Gn,handleGenerate:()=>Zf,handleGenerateStream:()=>Un,handlePlanModeStream:()=>Yi,isGenerating:()=>kt,isPlanModeActive:()=>qi,resolveAgenticEngine:()=>ln,setParseWarningCallback:()=>zi,shouldUseAgenticMode:()=>Xi});import{execSync as Wi}from"child_process";function zi(e){Vi=e}function kt(){return ht!==null}function jt(e){if(ht){let t=C();if(!t||t.id!==ht){E.warn("ai-handler","Session changed during generation \u2014 discarding AI output");return}}Ge("assistant",e),bl(e,Vi||void 0),J()}async function Un(e,t,n,s){let o=C();if(!o)throw new Error("No active session");ht=o.id;let r=s?.length?to(s):void 0;try{let a=R(),l=a.aiEngine||Ki();switch(l){case"anthropic-api":case"api":{let c=Te("anthropic-api",a);if(!c)throw new Error("Anthropic API key not configured. Open Settings to add one.");await Tl(e,c,o.themeName,a.anthropicApiModel||"claude-sonnet-4-6",t,n,jt,r);break}case"claude-oauth":{await $l(e,o.themeName,a.anthropicApiModel||"claude-sonnet-4-6",t,n,jt,r);break}case"openai-api":{let c=Te("openai-api",a);if(!c)throw new Error("OpenAI API key not configured. Open Settings to add one.");await Il(e,c,o.themeName,a.openaiApiModel||"gpt-4o",t,n,jt,r);break}case"gemini-api":{let c=Te("gemini-api",a);if(!c)throw new Error("Gemini API key not configured. Open Settings to add one.");await El(e,c,o.themeName,t,n,jt,r);break}case"claude-code":await Ml(e,o.themeName,t,n,jt,r);break;case"gemini-cli":await Ri("gemini",e,o.themeName,t,n,jt,r);break;case"codex-cli":await Ri("codex",e,o.themeName,t,n,jt,r);break;default:throw new Error(`Unknown AI engine: ${l}. Open Settings to configure one.`)}}finally{ht=null,Vi=null}}function Ki(){let e=R();if(Ye())return"claude-oauth";if(e.anthropicApiKey||process.env.ANTHROPIC_API_KEY)return"anthropic-api";if(e.openaiApiKey||process.env.OPENAI_API_KEY)return"openai-api";if(e.geminiApiKey||process.env.GEMINI_API_KEY||process.env.GOOGLE_AI_API_KEY)return"gemini-api";try{return Wi("claude --version",{stdio:"pipe"}),"claude-code"}catch{}try{return Wi("gemini --version",{stdio:"pipe"}),"gemini-cli"}catch{}try{return Wi("codex --version",{stdio:"pipe"}),"codex-cli"}catch{}throw new Error("No AI engine available. Open Settings to configure one.")}async function Zf(e){let t="";return await Un(e,n=>{t+=n}),t}function gc(){let e=C(),t=ye(),n=t?[...t.modules]:[...e.modules],s=t?[...t.moduleOrder]:[...e.moduleOrder];return{modules:n,moduleOrder:s,sharedCss:t?.sharedCss||e.sharedCss,sharedJs:t?.sharedJs||e.sharedJs,messages:[...e.messages],themeName:e.themeName,themePath:e.themePath,brandAssets:e.brandAssets?{...e.brandAssets}:void 0}}function ln(e){let t=e.aiEngine||Ki();if(!Hn(t))throw new Error("Agentic pipeline is not available for this engine.");if(an(t)){let o="";return t==="claude-code"&&(o=e.claudeCodeModel||""),{engine:t,apiKey:"",model:o}}let n;if(t==="claude-oauth"){if(!Ye())throw new Error("Claude OAuth session expired. Please re-authenticate in Settings.");n="oauth"}else n=Te(t,e);if(!n)throw new Error(`API key not configured for ${t}. Open Settings to add one.`);let s;switch(t){case"anthropic-api":case"claude-oauth":s=e.anthropicApiModel||"claude-sonnet-4-6";break;case"openai-api":s=e.openaiApiModel||"gpt-5.5";break;case"gemini-api":s=e.geminiApiModel||"gemini-2.5-pro";break;case"claude-code":s=e.claudeCodeModel||"";break;case"codex-cli":s=e.codexCliModel||"";break;case"gemini-cli":s=e.geminiCliModel||"";break;default:s=""}return{engine:t,apiKey:n,model:s}}async function lo(e,t,n){let s=C();if(!s)throw new Error("No active session");let o=s.id;ht=o;try{let i=R(),{engine:r,apiKey:a,model:l}=ln(i),c=i.agenticConcurrency||20,d=gc(),u=d.brandAssets?.plan,m=e;u&&u.trim()&&(m=`## Approved plan
2602
+ - Use \`vibespot-choices\` chips when one of your questions is multiple-choice (e.g. "Primary CTA?", "Cuisine?").`:t<=2&&!e?"**Phase 2: RESEARCH & DRAFT.** Take what the user has shared and produce a real first draft of the plan: goal, audience, primary CTA, and a proposed module list with brief descriptions. Reference existing modules/styleguide where applicable. Ask 1\u20132 narrow follow-ups to fill remaining gaps. Don't be exhaustive \u2014 a directionally-correct draft is better than asking 10 more questions.":`**Phase 3: REFINE.** A plan exists. Update it based on the user's latest message \u2014 change only what they're asking to change, preserve the rest. Confirm what you've updated in your conversational reply ("I changed the hero CTA to 'Get started free' and added a logos bar before the features section."). Ask narrow clarifying questions only when the user's edit creates a new ambiguity.`}function Sr(t,e){return t.length<=e?t:t.slice(0,e)+`
2603
+ ... [truncated]`}var wd=R(()=>{"use strict";y()});var $r={};Be($r,{applyPipelineResult:()=>qt,handleAgenticGenerate:()=>Eo,handleFigmaImport:()=>us,handleGenerate:()=>Fh,handleGenerateStream:()=>ds,handlePlanModeStream:()=>kr,isGenerating:()=>Ft,isPlanModeActive:()=>Tr,resolveAgenticEngine:()=>vn,setParseWarningCallback:()=>wr,shouldUseAgenticMode:()=>Ar});import{execSync as xr}from"child_process";function wr(t){vr=t}function Ft(){return $t!==null}function Yt(t){if($t){let e=C();if(!e||e.id!==$t){E.warn("ai-handler","Session changed during generation \u2014 discarding AI output");return}}tt("assistant",t),rc(t,vr||void 0),D()}async function ds(t,e,n,s){let o=C();if(!o)throw new Error("No active session");$t=o.id;let r=s?.length?Co(s):void 0;try{let a=O(),l=a.aiEngine||Cr();switch(l){case"anthropic-api":case"api":{let c=Oe("anthropic-api",a);if(!c)throw new Error("Anthropic API key not configured. Open Settings to add one.");await gc(t,c,o.themeName,a.anthropicApiModel||"claude-sonnet-4-6",e,n,Yt,r);break}case"claude-oauth":{await fc(t,o.themeName,a.anthropicApiModel||"claude-sonnet-4-6",e,n,Yt,r);break}case"openai-api":{let c=Oe("openai-api",a);if(!c)throw new Error("OpenAI API key not configured. Open Settings to add one.");await hc(t,c,o.themeName,a.openaiApiModel||"gpt-4o",e,n,Yt,r);break}case"gemini-api":{let c=Oe("gemini-api",a);if(!c)throw new Error("Gemini API key not configured. Open Settings to add one.");await yc(t,c,o.themeName,e,n,Yt,r);break}case"claude-code":await bc(t,o.themeName,e,n,Yt,r);break;case"gemini-cli":await tr("gemini",t,o.themeName,e,n,Yt,r);break;case"codex-cli":await tr("codex",t,o.themeName,e,n,Yt,r);break;default:throw new Error(`Unknown AI engine: ${l}. Open Settings to configure one.`)}}finally{$t=null,vr=null}}function Cr(){let t=O();if(lt())return"claude-oauth";if(t.anthropicApiKey||process.env.ANTHROPIC_API_KEY)return"anthropic-api";if(t.openaiApiKey||process.env.OPENAI_API_KEY)return"openai-api";if(t.geminiApiKey||process.env.GEMINI_API_KEY||process.env.GOOGLE_AI_API_KEY)return"gemini-api";try{return xr("claude --version",{stdio:"pipe"}),"claude-code"}catch{}try{return xr("gemini --version",{stdio:"pipe"}),"gemini-cli"}catch{}try{return xr("codex --version",{stdio:"pipe"}),"codex-cli"}catch{}throw new Error("No AI engine available. Open Settings to configure one.")}async function Fh(t){let e="";return await ds(t,n=>{e+=n}),e}function Cd(){let t=C(),e=Ce(),n=e?[...e.modules]:[...t.modules],s=e?[...e.moduleOrder]:[...t.moduleOrder],o={modules:n,moduleOrder:s,sharedCss:e?.sharedCss||t.sharedCss,sharedJs:e?.sharedJs||t.sharedJs,messages:[...t.messages],themeName:t.themeName,themePath:t.themePath,contentMode:e?.contentMode,brandAssets:t.brandAssets?{...t.brandAssets}:void 0};return t.templates.length>1&&(o.activePageLabel=e?.label,o.sitePages=t.templates.map(i=>({id:i.id,label:i.label,pageType:i.pageType,moduleCount:i.modules.length}))),o}function vn(t){let e=t.aiEngine||Cr();if(!rs(e))throw new Error("Agentic pipeline is not available for this engine.");if(xn(e)){let o="";return e==="claude-code"&&(o=t.claudeCodeModel||""),{engine:e,apiKey:"",model:o}}let n;if(e==="claude-oauth"){if(!lt())throw new Error("Claude OAuth session expired. Please re-authenticate in Settings.");n="oauth"}else n=Oe(e,t);if(!n)throw new Error(`API key not configured for ${e}. Open Settings to add one.`);let s;switch(e){case"anthropic-api":case"claude-oauth":s=t.anthropicApiModel||"claude-sonnet-4-6";break;case"openai-api":s=t.openaiApiModel||"gpt-5.5";break;case"gemini-api":s=t.geminiApiModel||"gemini-2.5-pro";break;case"claude-code":s=t.claudeCodeModel||"";break;case"codex-cli":s=t.codexCliModel||"";break;case"gemini-cli":s=t.geminiCliModel||"";break;default:s=""}return{engine:e,apiKey:n,model:s}}async function Eo(t,e,n){let s=C();if(!s)throw new Error("No active session");let o=s.id;$t=o;try{let i=O(),{engine:r,apiKey:a,model:l}=vn(i),c=i.agenticConcurrency||20,d=Cd(),u=d.brandAssets?.plan,m=t;u&&u.trim()&&(m=`## Approved plan
1527
2604
 
1528
2605
  Build the page according to this plan exactly. The user reviewed and approved it; do not deviate from its goal, audience, sections, or content unless the user message below explicitly requests changes.
1529
2606
 
@@ -1533,32 +2610,39 @@ ${u}
1533
2610
 
1534
2611
  ## User message
1535
2612
 
1536
- ${e}`);let f=n?.length?to(n):void 0;if(f?.length)for(let v of f)v.type==="document"&&v.extractedText&&(m+=`
2613
+ ${t}`);let g=n?.length?Co(n):void 0;if(g?.length)for(let w of g)w.type==="document"&&w.extractedText&&(m+=`
1537
2614
 
1538
2615
  ---
1539
- [Attached document: ${v.originalName}]
1540
- ${v.extractedText}`),v.type==="image"&&v.usage==="asset"&&v.assetPath&&(m+=`
2616
+ [Attached document: ${w.originalName}]
2617
+ ${w.extractedText}`),w.type==="image"&&w.usage==="asset"&&w.assetPath&&(m+=`
1541
2618
 
1542
- [Uploaded image: ${v.originalName} \u2192 available as get_asset_url("${v.assetPath}")]`);let y=ft(),h=new Set(d.modules.map(v=>v.moduleName)),S=y.filter(v=>!h.has(v.module.moduleName)).map(v=>({name:v.module.moduleName,usedIn:v.usedIn})),x=await ic(m,d,r,a,l,c,t,S),w=C();if(!w||w.id!==o)throw E.warn("ai-handler","Session changed during agentic generation \u2014 discarding output"),new Error("Session changed during generation");return x}finally{ht=null}}async function Gn(e,t,n,s){let o=C();if(!o)throw new Error("No active session");let i=o.id;ht=i;try{let{runFigmaConversion:r}=await Promise.resolve().then(()=>(mc(),uc)),a=R(),{engine:l,apiKey:c,model:d}=ln(a),u=a.agenticConcurrency||20,m=gc(),f=await r(e,t,l,c,d,u,n,m.brandAssets,s?.useAssets),y=C();if(!y||y.id!==i)throw E.warn("ai-handler","Session changed during Figma import \u2014 discarding output"),new Error("Session changed during generation");return f}finally{ht=null}}function Dt(e,t){Ie({modules:e.modules,sharedCss:e.sharedCss,sharedJs:e.sharedJs}),wt(e.moduleOrder),Ge("assistant",e.assistantMessage,t),J()}async function Yi(e,t,n){let s=C();if(!s)throw new Error("No active session");let o=R(),{engine:i,apiKey:r,model:a}=ln(o),[{buildPlanModePrompt:l},{callAgent:c}]=await Promise.all([Promise.resolve().then(()=>(fc(),pc)),Promise.resolve().then(()=>(nt(),Dl))]),d=s.messages.filter(v=>v.role==="assistant").length,u=s.modules.map(v=>v.moduleName),m=ft(),f=new Set(u),y=m.filter(v=>!f.has(v.module.moduleName)).map(v=>({name:v.module.moduleName,usedIn:v.usedIn})),h=l(s.themeName,s.brandAssets,u,y,d),S=n?.length?to(n):void 0,x=e;if(S?.length)for(let v of S)v.type==="document"&&v.extractedText&&(x+=`
2619
+ [Uploaded image: ${w.originalName} \u2192 available as get_asset_url("${w.assetPath}")]`);let h=At(),f=new Set(d.modules.map(w=>w.moduleName)),b=h.filter(w=>!f.has(w.module.moduleName)).map(w=>({name:w.module.moduleName,usedIn:w.usedIn})),S=await pd(m,d,r,a,l,c,e,b),x=C();if(!x||x.id!==o)throw E.warn("ai-handler","Session changed during agentic generation \u2014 discarding output"),new Error("Session changed during generation");return S}finally{$t=null}}async function us(t,e,n,s){let o=C();if(!o)throw new Error("No active session");let i=o.id;$t=i;try{let{runFigmaConversion:r}=await Promise.resolve().then(()=>(xd(),Sd)),a=O(),{engine:l,apiKey:c,model:d}=vn(a),u=a.agenticConcurrency||20,m=Cd(),g=await r(t,e,l,c,d,u,n,m.brandAssets,s?.useAssets),h=C();if(!h||h.id!==i)throw E.warn("ai-handler","Session changed during Figma import \u2014 discarding output"),new Error("Session changed during generation");return g}finally{$t=null}}function qt(t,e){let n=t.multiPage;if(n&&n.pages.length>0){let s=new Map;for(let o of n.pages)s.set(o.pageId,{label:o.label||o.pageId,pageType:o.pageType||"website_page"});Al({pages:n.pages,sharedModules:n.sharedModules,sharedCss:n.sharedCss,sharedJs:n.sharedJs,pageLabels:s})}else if(De({modules:t.modules,sharedCss:t.sharedCss,sharedJs:t.sharedJs}),Rt(t.moduleOrder),t.contentType==="email"){let o=Ce();o&&!o.contentMode&&(o.contentMode="email")}tt("assistant",t.assistantMessage,e),D()}async function kr(t,e,n){let s=C();if(!s)throw new Error("No active session");let o=O(),{engine:i,apiKey:r,model:a}=vn(o),[{buildPlanModePrompt:l},{callAgent:c}]=await Promise.all([Promise.resolve().then(()=>(wd(),vd)),Promise.resolve().then(()=>(nt(),Ac))]),d=s.messages.filter(w=>w.role==="assistant").length,u=s.modules.map(w=>w.moduleName),m=At(),g=new Set(u),h=m.filter(w=>!g.has(w.module.moduleName)).map(w=>({name:w.module.moduleName,usedIn:w.usedIn})),f=l(s.themeName,s.brandAssets,u,h,d),b=n?.length?Co(n):void 0,S=t;if(b?.length)for(let w of b)w.type==="document"&&w.extractedText&&(S+=`
1543
2620
 
1544
2621
  ---
1545
- [Attached document: ${v.originalName}]
1546
- ${v.extractedText}`);let w=await c(i,r,a,{systemPrompt:h,messages:[{role:"user",content:x}],maxTokens:8e3,onChunk:t,enableWebSearch:!!o.webSearch});return w.type==="text"?w.text:JSON.stringify(w.data)}function qi(){return!!R().planMode}function Xi(){let e=R(),t=e.aiEngine||Ki();return Hn(t)?e.agenticMode===void 0?{useAgentic:!1,needsPrompt:!0}:{useAgentic:e.agenticMode,needsPrompt:!1}:{useAgentic:!1,needsPrompt:!1,reason:"Agentic pipeline is not available for this engine."}}var Vi,ht,cn=G(()=>{"use strict";g();X();me();eo();re();_i();lt();Oi();rc();Vi=null;ht=null});var zn={};_e(zn,{collectThemeFiles:()=>Oc,extractDesignContext:()=>Cg});import{existsSync as go,readdirSync as ho,readFileSync as Sg}from"fs";import{join as st}from"path";import{spawn as xg}from"child_process";async function Nc(){return or||(or=(await import("@anthropic-ai/sdk")).default),or}function Vn(e){try{return Sg(e,"utf-8")}catch{return""}}function Oc(e){let t=[],n=0;function s(a,l){if(!l.trim())return!0;let c=`
2622
+ [Attached document: ${w.originalName}]
2623
+ ${w.extractedText}`);let x=await c(i,r,a,{systemPrompt:f,messages:[{role:"user",content:S}],maxTokens:8e3,onChunk:e,enableWebSearch:!!o.webSearch});return x.type==="text"?x.text:JSON.stringify(x.data)}function Tr(){return!!O().planMode}function Ar(){let t=O(),e=t.aiEngine||Cr();return rs(e)?t.agenticMode===void 0?{useAgentic:!1,needsPrompt:!0}:{useAgentic:t.agenticMode,needsPrompt:!1}:{useAgentic:!1,needsPrompt:!1,reason:"Agentic pipeline is not available for this engine."}}var vr,$t,wn=R(()=>{"use strict";y();Q();we();wo();de();nr();xt();ir();gd();vr=null;$t=null});import{readFileSync as jh,readdirSync as Dh,existsSync as Lh}from"fs";import{dirname as Jh,join as Io}from"path";import{fileURLToPath as Bh}from"url";function Uh(t){let e=t.match(Hh);if(!e)return null;let[,n,s]=e,o={};for(let i of n.split(/\r?\n/)){let r=i.indexOf(":");if(r===-1)continue;let a=i.slice(0,r).trim(),l=i.slice(r+1).trim();(l.startsWith('"')&&l.endsWith('"')||l.startsWith("'")&&l.endsWith("'"))&&(l=l.slice(1,-1)),a&&(o[a]=l)}return{fields:o,body:s.trimStart()}}function Gh(t){let e=Uh(t);if(!e)return null;let{fields:n,body:s}=e,o=n.id,i=n.label,r=n.description??"";if(!o||!i)return null;let a=n.order?Number(n.order):NaN,l=n.contentType==="email"?"email":void 0;return{id:o,label:i,description:r,icon:n.icon||void 0,order:Number.isFinite(a)?a:9999,contentType:l,body:s.trimEnd()+`
2624
+ `}}function Wh(){let t=[Io(kd,"../../assets/plan-templates"),Io(kd,"../assets/plan-templates"),Io(process.cwd(),"assets/plan-templates")];for(let e of t)if(Lh(e))return e;return null}function Td(){if(jt)return jt;let t=Wh();if(!t)return jt=[],jt;let e=[],n=[];try{n=Dh(t)}catch{return jt=[],jt}for(let s of n)if(s.endsWith(".md"))try{let o=jh(Io(t,s),"utf-8"),i=Gh(o);i&&e.push(i)}catch{}return e.sort((s,o)=>s.order!==o.order?s.order-o.order:s.label.localeCompare(o.label)),jt=e,jt}function Ad(t){return Td().find(e=>e.id===t)??null}function $d(){return Td().map(({id:t,label:e,description:n,icon:s,order:o,contentType:i})=>({id:t,label:e,description:n,icon:s,order:o,contentType:i}))}var kd,Hh,jt,_d=R(()=>{"use strict";y();kd=Jh(Bh(import.meta.url)),Hh=/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/;jt=null});import{existsSync as Md,mkdirSync as Kh,writeFileSync as Vh,rmSync as zh}from"fs";import{join as Ed}from"path";function Id(t){return Ed(t,".vibespot",Yh)}function Po(t){let e=C();if(!e)return null;e.brandAssets||(e.brandAssets={}),e.brandAssets.plan=t;let n=Ce();n&&(n.plan=t);try{let s=Ed(e.themePath,".vibespot");Md(s)||Kh(s,{recursive:!0}),Vh(Id(e.themePath),t,"utf-8")}catch(s){E.warn("plan",`Failed to write plan.md: ${s instanceof Error?s.message:String(s)}`)}return D(),t}function _r(){let t=C();if(!t)return;t.brandAssets&&delete t.brandAssets.plan;let e=Ce();e&&delete e.plan;try{let n=Id(t.themePath);Md(n)&&zh(n)}catch(n){E.warn("plan",`Failed to remove plan.md: ${n instanceof Error?n.message:String(n)}`)}D()}function Pd(t,e){Ve(t,e,n=>{if(!C()){p(e,400,{error:"No active session"});return}let o=typeof n.markdown=="string"?n.markdown:"";if(!o.trim()){p(e,400,{error:"Plan content cannot be empty"});return}Po(o),p(e,200,{ok:!0,plan:o})})}function Rd(t,e){Ve(t,e,()=>{_r(),Y({planMode:!1}),p(e,200,{ok:!0})})}function Nd(t,e){p(e,200,{templates:$d()})}function Od(t,e){Ve(t,e,n=>{if(!C()){p(e,400,{error:"No active session"});return}let o=typeof n.templateId=="string"?n.templateId.trim():"";if(!o){p(e,400,{error:"templateId is required"});return}let i=Ad(o);if(!i){p(e,404,{error:`Unknown plan template: ${o}`});return}Po(i.body),Y({planMode:!0}),p(e,200,{ok:!0,templateId:i.id,label:i.label,plan:i.body})})}var Yh,Fd=R(()=>{"use strict";y();ze();we();Nt();Q();de();_d();Yh="plan.md"});function jd(t){let e,n,s;for(Mr.lastIndex=0;(s=Mr.exec(t))!==null;)e=s[1].trim();let o;for(Er.lastIndex=0;(o=Er.exec(t))!==null;)try{let r=JSON.parse(o[1].trim());r&&typeof r.question=="string"&&Array.isArray(r.options)&&r.options.every(a=>typeof a=="string")&&r.options.length>0&&(n={question:r.question,options:r.options})}catch{}return{cleanedContent:t.replace(Mr,"").replace(Er,"").replace(/\n{3,}/g,`
2625
+
2626
+ `).trim(),plan:e,choices:n}}var Mr,Er,Dd=R(()=>{"use strict";y();Mr=/```vibespot-plan\s*\n([\s\S]*?)```/g,Er=/```vibespot-choices\s*\n([\s\S]*?)```/g});import{spawn as Ir}from"child_process";function Ld(t,e,n){t.stdout?.on("data",o=>{e.output+=o.toString()}),t.stderr?.on("data",o=>{e.output+=o.toString()}),t.on("close",o=>{e.status=o===0?"completed":"failed",e.exitCode=o,e.completedAt=Date.now()}),t.on("error",o=>{e.status="failed",e.output+=`
2627
+ Process error: ${o.message}`,e.completedAt=Date.now()}),setTimeout(()=>{e.status==="running"&&(t.kill(),e.status="failed",e.output+=`
2628
+ Process timed out`,e.completedAt=Date.now())},n||3e5)}function ms(t,e,n,s){let o=`job-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`,i={id:o,command:`${t} ${e.join(" ")}`,description:n,status:"running",output:"",exitCode:null,startedAt:Date.now(),completedAt:null};Dt.set(o,i);let r=Ir(t,e,{cwd:s?.cwd,stdio:[s?.stdin?"pipe":"ignore","pipe","pipe"],env:{...process.env,...s?.env},shell:process.platform==="win32"});return s?.stdin&&r.stdin&&(r.stdin.write(s.stdin),r.stdin.end()),Ld(r,i,s?.timeout),o}function Xt(t,e,n){let s=`job-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`,o={id:s,command:t,description:e,status:"running",output:"",exitCode:null,startedAt:Date.now(),completedAt:null};Dt.set(s,o);let i=t.split(" "),r=Ir(i[0],i.slice(1),{cwd:n?.cwd,stdio:["ignore","pipe","pipe"],env:{...process.env,...n?.env},shell:!0});return Ld(r,o,n?.timeout),s}function Ro(t){return Dt.get(t)}function qh(){let t=Date.now()-18e5;for(let[e,n]of Dt)n.completedAt&&n.completedAt<t&&Dt.delete(e)}function No(t,e,n){let s=`job-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`,o={id:s,command:t,description:e,status:"running",output:"",exitCode:null,startedAt:Date.now(),completedAt:null,listeners:new Set};Dt.set(s,o);let i=t.split(" "),r=Ir(i[0],i.slice(1),{cwd:n?.cwd,stdio:["ignore","pipe","pipe"],env:{...process.env,...n?.env},shell:!0}),a=c=>{for(let d of o.listeners)try{d(c)}catch{}};r.stdout?.on("data",c=>{let d=c.toString();o.output+=d,a(d)}),r.stderr?.on("data",c=>{let d=c.toString();o.output+=d,a(d)}),r.on("close",c=>{o.status=c===0?"completed":"failed",o.exitCode=c,o.completedAt=Date.now(),o.listeners.clear()}),r.on("error",c=>{o.status="failed",o.output+=`
2629
+ Process error: ${c.message}`,o.completedAt=Date.now(),o.listeners.clear()});let l=n?.timeout||3e5;return setTimeout(()=>{o.status==="running"&&(r.kill(),o.status="failed",o.output+=`
2630
+ Process timed out`,o.completedAt=Date.now(),o.listeners.clear())},l),s}function Jd(t,e){let n=Dt.get(t);if(!n||!("listeners"in n))return;let s=n;if(s.output)try{e(s.output)}catch{}s.listeners.add(e)}function Bd(t,e){let n=Dt.get(t);!n||!("listeners"in n)||n.listeners.delete(e)}var Dt,Oo=R(()=>{"use strict";y();Dt=new Map;setInterval(qh,600*1e3)});import{readFileSync as Xh,readdirSync as Zh,existsSync as Qh}from"fs";import{dirname as ey,join as Fo}from"path";import{fileURLToPath as ty}from"url";function ny(){let t=[Fo(Hd,"../../starters"),Fo(Hd,"../starters"),Fo(process.cwd(),"starters")];for(let e of t)if(Qh(e))return e;return null}function Ud(){if(Cn!==null)return Cn;let t=ny();if(!t)return Cn=[],Cn;let e=[];for(let n of Zh(t).filter(s=>s.endsWith(".json")).sort())try{let s=JSON.parse(Xh(Fo(t,n),"utf-8"));e.push({id:s.id,name:s.name,description:s.description,category:s.category||"General",contentType:s.contentType==="email"?"email":void 0,modules:s.modules||[],moduleOrder:s.moduleOrder||[],sharedCss:s.sharedCss||"",sharedJs:s.sharedJs||""})}catch{}return Cn=e,Cn}function Gd(){return Ud().map(t=>({id:t.id,name:t.name,description:t.description,category:t.category,contentType:t.contentType,moduleCount:t.modules.length}))}function Pr(t){return Ud().find(e=>e.id===t)||null}var Hd,Cn,Wd=R(()=>{"use strict";y();Hd=ey(ty(import.meta.url)),Cn=null});var gs={};Be(gs,{collectThemeFiles:()=>Vd,extractDesignContext:()=>ay});import{existsSync as jo,readdirSync as Do,readFileSync as sy}from"fs";import{join as ht}from"path";import{spawn as oy}from"child_process";async function Kd(){return Rr||(Rr=(await import("@anthropic-ai/sdk")).default),Rr}function ps(t){try{return sy(t,"utf-8")}catch{return""}}function Vd(t){let e=[],n=0;function s(a,l){if(!l.trim())return!0;let c=`
1547
2631
  ### ${a}
1548
2632
  \`\`\`
1549
2633
  ${l}
1550
2634
  \`\`\`
1551
- `;return n+c.length>vg?!1:(t.push(c),n+=c.length,!0)}let o=Vn(st(e,"theme.json"));o&&s("theme.json",o);let i=st(e,"css");if(go(i)){for(let a of ho(i).filter(l=>l.endsWith(".css")))if(!s(`css/${a}`,Vn(st(i,a))))break}let r=st(e,"modules");if(go(r))for(let a of ho(r).filter(l=>l.endsWith(".module"))){let l=st(r,a),c=Vn(st(l,"module.css"));if(c&&!s(`modules/${a}/module.css`,c))break}if(go(r))for(let a of ho(r).filter(l=>l.endsWith(".module"))){let l=st(r,a),c=Vn(st(l,"module.html"));if(c&&!s(`modules/${a}/module.html`,c))break}if(go(r))for(let a of ho(r).filter(l=>l.endsWith(".module"))){let l=st(r,a),c=Vn(st(l,"fields.json"));if(c&&!s(`modules/${a}/fields.json`,c))break}return t.join("")}function wg(){if(!yo)try{yo=T(ss("extraction-prompt.md"))}catch{yo=""}return yo}function ir(e,t,n){return new Promise((s,o)=>{let i={...process.env};delete i.CLAUDECODE;let r=xg(e,t,{stdio:["pipe","pipe","pipe"],env:i,shell:!0}),a="",l="";r.stdout.on("data",c=>{a+=c.toString()}),r.stderr.on("data",c=>{l+=c.toString()}),r.on("error",c=>o(new Error(`${e} failed to start: ${c.message}`))),r.on("close",c=>{c===0||a.trim()?s(a.trim()):o(new Error(`${e} exited with code ${c}: ${l.trim()}`))}),r.stdin.write(n),r.stdin.end()})}async function Cg(e,t){t?.({status:"Collecting theme files..."});let n=Oc(e);if(!n.trim())throw new Error("No CSS, HTML, or fields.json files found in theme.");let s=wg();if(!s)throw new Error("Extraction prompt not found (assets/extraction-prompt.md).");let o=`Analyze this HubSpot CMS theme and extract the design system:
1552
- ${n}`;t?.({status:"Analyzing design patterns..."});let i=R(),r=i.aiEngine||"anthropic-api",a="";switch(r){case"anthropic-api":case"api":{let l=Te("anthropic-api");if(!l)throw new Error("Anthropic API key not configured. Open Settings to add one.");let c=await Nc();a=(await new c({apiKey:l}).messages.create({model:i.anthropicApiModel||"claude-sonnet-4-6",max_tokens:8e3,system:[{type:"text",text:s,cache_control:{type:"ephemeral"}}],messages:[{role:"user",content:o}]})).content.map(m=>m.type==="text"?m.text:"").join("");break}case"claude-oauth":{let{getValidAccessToken:l,OAUTH_EXTRA_HEADERS:c,OAUTH_SYSTEM_PREFIX:d}=await Promise.resolve().then(()=>(lt(),Uo)),u=await l();if(!u)throw new Error("Claude OAuth session expired. Please re-authenticate in Settings.");let m=await Nc();a=(await new m({authToken:u,defaultHeaders:c}).messages.create({model:i.anthropicApiModel||"claude-sonnet-4-6",max_tokens:8e3,system:[{type:"text",text:d},{type:"text",text:s,cache_control:{type:"ephemeral"}}],messages:[{role:"user",content:o}]})).content.map(h=>h.type==="text"?h.text:"").join("");break}case"openai-api":{let l=Te("openai-api");if(!l)throw new Error("OpenAI API key not configured. Open Settings to add one.");let c=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${l}`},body:JSON.stringify({model:i.openaiApiModel||"gpt-4o",max_tokens:8e3,messages:[{role:"system",content:s},{role:"user",content:o}]})});if(!c.ok)throw new Error(`OpenAI API error: ${c.status} ${await c.text()}`);a=(await c.json()).choices?.[0]?.message?.content||"";break}case"gemini-api":{let l=Te("gemini-api");if(!l)throw new Error("Gemini API key not configured. Open Settings to add one.");let c=i.geminiApiModel||"gemini-2.5-flash",d=await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${c}:generateContent?key=${l}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({system_instruction:{parts:[{text:s}]},contents:[{role:"user",parts:[{text:o}]}],generationConfig:{maxOutputTokens:8e3}})});if(!d.ok)throw new Error(`Gemini API error: ${d.status} ${await d.text()}`);a=(await d.json()).candidates?.[0]?.content?.parts?.map(m=>m.text).join("")||"";break}case"claude-code":{let l=`${s}
2635
+ `;return n+c.length>iy?!1:(e.push(c),n+=c.length,!0)}let o=ps(ht(t,"theme.json"));o&&s("theme.json",o);let i=ht(t,"css");if(jo(i)){for(let a of Do(i).filter(l=>l.endsWith(".css")))if(!s(`css/${a}`,ps(ht(i,a))))break}let r=ht(t,"modules");if(jo(r))for(let a of Do(r).filter(l=>l.endsWith(".module"))){let l=ht(r,a),c=ps(ht(l,"module.css"));if(c&&!s(`modules/${a}/module.css`,c))break}if(jo(r))for(let a of Do(r).filter(l=>l.endsWith(".module"))){let l=ht(r,a),c=ps(ht(l,"module.html"));if(c&&!s(`modules/${a}/module.html`,c))break}if(jo(r))for(let a of Do(r).filter(l=>l.endsWith(".module"))){let l=ht(r,a),c=ps(ht(l,"fields.json"));if(c&&!s(`modules/${a}/fields.json`,c))break}return e.join("")}function ry(){if(!Lo)try{Lo=M(Ts("extraction-prompt.md"))}catch{Lo=""}return Lo}function Nr(t,e,n){return new Promise((s,o)=>{let i={...process.env};delete i.CLAUDECODE;let r=oy(t,e,{stdio:["pipe","pipe","pipe"],env:i,shell:!0}),a="",l="";r.stdout.on("data",c=>{a+=c.toString()}),r.stderr.on("data",c=>{l+=c.toString()}),r.on("error",c=>o(new Error(`${t} failed to start: ${c.message}`))),r.on("close",c=>{c===0||a.trim()?s(a.trim()):o(new Error(`${t} exited with code ${c}: ${l.trim()}`))}),r.stdin.write(n),r.stdin.end()})}async function ay(t,e){e?.({status:"Collecting theme files..."});let n=Vd(t);if(!n.trim())throw new Error("No CSS, HTML, or fields.json files found in theme.");let s=ry();if(!s)throw new Error("Extraction prompt not found (assets/extraction-prompt.md).");let o=`Analyze this HubSpot CMS theme and extract the design system:
2636
+ ${n}`;e?.({status:"Analyzing design patterns..."});let i=O(),r=i.aiEngine||"anthropic-api",a="";switch(r){case"anthropic-api":case"api":{let l=Oe("anthropic-api");if(!l)throw new Error("Anthropic API key not configured. Open Settings to add one.");let c=await Kd();a=(await new c({apiKey:l}).messages.create({model:i.anthropicApiModel||"claude-sonnet-4-6",max_tokens:8e3,system:[{type:"text",text:s,cache_control:{type:"ephemeral"}}],messages:[{role:"user",content:o}]})).content.map(m=>m.type==="text"?m.text:"").join("");break}case"claude-oauth":{let{getValidAccessToken:l,OAUTH_EXTRA_HEADERS:c,OAUTH_SYSTEM_PREFIX:d}=await Promise.resolve().then(()=>(xt(),gi)),u=await l();if(!u)throw new Error("Claude OAuth session expired. Please re-authenticate in Settings.");let m=await Kd();a=(await new m({authToken:u,defaultHeaders:c}).messages.create({model:i.anthropicApiModel||"claude-sonnet-4-6",max_tokens:8e3,system:[{type:"text",text:d},{type:"text",text:s,cache_control:{type:"ephemeral"}}],messages:[{role:"user",content:o}]})).content.map(f=>f.type==="text"?f.text:"").join("");break}case"openai-api":{let l=Oe("openai-api");if(!l)throw new Error("OpenAI API key not configured. Open Settings to add one.");let c=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${l}`},body:JSON.stringify({model:i.openaiApiModel||"gpt-4o",max_tokens:8e3,messages:[{role:"system",content:s},{role:"user",content:o}]})});if(!c.ok)throw new Error(`OpenAI API error: ${c.status} ${await c.text()}`);a=(await c.json()).choices?.[0]?.message?.content||"";break}case"gemini-api":{let l=Oe("gemini-api");if(!l)throw new Error("Gemini API key not configured. Open Settings to add one.");let c=i.geminiApiModel||"gemini-2.5-flash",d=await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${c}:generateContent?key=${l}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({system_instruction:{parts:[{text:s}]},contents:[{role:"user",parts:[{text:o}]}],generationConfig:{maxOutputTokens:8e3}})});if(!d.ok)throw new Error(`Gemini API error: ${d.status} ${await d.text()}`);a=(await d.json()).candidates?.[0]?.content?.parts?.map(m=>m.text).join("")||"";break}case"claude-code":{let l=`${s}
1553
2637
 
1554
2638
  ## User Request
1555
- ${o}`,c=["--print"];i.claudeCodeModel&&c.push("--model",i.claudeCodeModel),a=await ir("claude",c,l);break}case"gemini-cli":{let l=`${s}
2639
+ ${o}`,c=["--print"];i.claudeCodeModel&&c.push("--model",i.claudeCodeModel),a=await Nr("claude",c,l);break}case"gemini-cli":{let l=`${s}
1556
2640
 
1557
2641
  ## User Request
1558
- ${o}`;a=await ir("gemini",[],l);break}case"codex-cli":{let l=`${s}
2642
+ ${o}`;a=await Nr("gemini",[],l);break}case"codex-cli":{let l=`${s}
1559
2643
 
1560
2644
  ## User Request
1561
- ${o}`;a=await ir("codex",[],l);break}default:throw new Error(`Unknown AI engine: ${r}. Open Settings to configure one.`)}if(!a.trim())throw new Error("AI returned empty response.");return t?.({status:"Design extraction complete."}),a}var or,vg,yo,Kn=G(()=>{"use strict";g();Q();X();or=null;vg=8e4;yo=""});var rr={};_e(rr,{extractBrandvoice:()=>kg});async function kg(e,t,n,s){if(!e||e.length<50)return null;let o=`You are a brand strategist. Analyze the rendered landing page HTML below and extract a concise brand voice guide. The HTML contains the actual text content with all template variables resolved to their default values.
2645
+ ${o}`;a=await Nr("codex",[],l);break}default:throw new Error(`Unknown AI engine: ${r}. Open Settings to configure one.`)}if(!a.trim())throw new Error("AI returned empty response.");return e?.({status:"Design extraction complete."}),a}var Rr,iy,Lo,fs=R(()=>{"use strict";y();ne();Q();Rr=null;iy=8e4;Lo=""});var Or={};Be(Or,{extractBrandvoice:()=>ly});async function ly(t,e,n,s){if(!t||t.length<50)return null;let o=`You are a brand strategist. Analyze the rendered landing page HTML below and extract a concise brand voice guide. The HTML contains the actual text content with all template variables resolved to their default values.
1562
2646
 
1563
2647
  Return a markdown document with these sections (skip any section where the content provides no signal):
1564
2648
 
@@ -1578,7 +2662,7 @@ Typical sentence length, structure, use of questions, imperatives, etc.
1578
2662
  ## Dos and Don'ts
1579
2663
  3-4 practical rules for writing in this voice (e.g., "Do: Lead with benefits, not features", "Don't: Use jargon without context").
1580
2664
 
1581
- Keep it actionable \u2014 this guide will be fed to AI to maintain consistent copy across pages.`;try{let i=await Re(t,n,s,{systemPrompt:o,messages:[{role:"user",content:e}],maxTokens:1e3}),r=i.type==="text"?i.text:JSON.stringify(i.data);return!r||r.trim().length<20?null:(E.info("brandvoice-extractor",`Extracted brand voice (${r.length} chars)`),r.trim())}catch(i){let r=i instanceof Error?i.message:String(i);return E.warn("brandvoice-extractor",`Brand voice extraction failed: ${r}`),null}}var ar=G(()=>{"use strict";g();nt();re()});var bo={};_e(bo,{extractThemeContext:()=>Ag});async function Ag(e,t,n,s,o){if(!e||e.length<50)return null;let r=`You are a content analyst. Extract a concise product/company brief from the rendered landing page HTML below. The HTML contains the actual text content (headings, paragraphs, button labels, image alt text, etc.) with all template variables resolved to their default values.
2665
+ Keep it actionable \u2014 this guide will be fed to AI to maintain consistent copy across pages.`;try{let i=await _e(e,n,s,{systemPrompt:o,messages:[{role:"user",content:t}],maxTokens:1e3}),r=i.type==="text"?i.text:JSON.stringify(i.data);return!r||r.trim().length<20?null:(E.info("brandvoice-extractor",`Extracted brand voice (${r.length} chars)`),r.trim())}catch(i){let r=i instanceof Error?i.message:String(i);return E.warn("brandvoice-extractor",`Brand voice extraction failed: ${r}`),null}}var Fr=R(()=>{"use strict";y();nt();de()});var Jo={};Be(Jo,{extractThemeContext:()=>cy});async function cy(t,e,n,s,o){if(!t||t.length<50)return null;let r=`You are a content analyst. Extract a concise product/company brief from the rendered landing page HTML below. The HTML contains the actual text content (headings, paragraphs, button labels, image alt text, etc.) with all template variables resolved to their default values.
1582
2666
 
1583
2667
  Return a markdown document with these sections (skip any section where the content provides no information):
1584
2668
 
@@ -1597,42 +2681,69 @@ Communication style (e.g., professional, casual, technical, friendly).
1597
2681
  ## Key Terminology
1598
2682
  Specific terms, product names, or branded language used consistently.
1599
2683
 
1600
- Keep it concise \u2014 this brief is used as context for AI-generated content on other pages in the same theme.${t?`
2684
+ Keep it concise \u2014 this brief is used as context for AI-generated content on other pages in the same theme.${e?`
1601
2685
 
1602
2686
  Existing product context (update if the new content adds info, keep what's still accurate):
1603
- ${t}`:""}`;try{let a=await Re(n,s,o,{systemPrompt:r,messages:[{role:"user",content:e}],maxTokens:1e3}),l=a.type==="text"?a.text:JSON.stringify(a.data);return!l||l.trim().length<20?null:(E.info("context-extractor",`Extracted theme context (${l.length} chars)`),l.trim())}catch(a){let l=a instanceof Error?a.message:String(a);return E.warn("context-extractor",`Theme context extraction failed: ${l}`),null}}var So=G(()=>{"use strict";g();nt();re()});import{writeFileSync as Qg,mkdirSync as Gd}from"fs";import{join as ko}from"path";import{randomUUID as eh}from"crypto";function Wd(e){let t=e.match(th);if(!t)return null;let n=t[1],s=t[2]?decodeURIComponent(t[2].replace(/-/g," ")):void 0,o;try{let r=new URL(e).searchParams.get("node-id");r&&(o=r.replace(/-/g,":"))}catch{}return{fileKey:n,nodeId:o,fileName:s}}async function To(e,t){let n=await fetch(`${nh}${e}`,{headers:{"X-Figma-Token":t}});if(!n.ok){let s=await n.text().catch(()=>""),o=new Error(`Figma API ${n.status}: ${s.slice(0,200)}`);throw o.status=n.status,o}return n.json()}async function ur(e,t){for(let n=0;;n++)try{return await e()}catch(s){if(!(s.status===429)||n>=Ud.length)throw s;let r=Ud[n];E.warn("figma",`Rate limited (429), attempt ${n+1} \u2014 waiting ${r}s`),t&&t(`Figma rate limited \u2014 retrying in ${r}s...`),await new Promise(a=>setTimeout(a,r*1e3))}}function Ht(e,t,n=0){if(t(e,n),e.children)for(let s of e.children)Ht(s,t,n+1)}function Vd(e,t){if(e.id===t)return e;if(e.children)for(let n of e.children){let s=Vd(n,t);if(s)return s}return null}function sh(e,t){if(t){let s=Vd(e,t);if(!s)return[];if(s.type==="FRAME"||s.type==="COMPONENT"||s.type==="COMPONENT_SET"){let o=(s.children||[]).filter(i=>dr.has(i.type));return o.length>0?o:[s]}return s.children?s.children.filter(o=>dr.has(o.type)):[]}let n=e.children?.[0];return n?.children?n.children.filter(s=>dr.has(s.type)):[]}function Ao(e){let t=Math.round(e.r*255),n=Math.round(e.g*255),s=Math.round(e.b*255);return`#${t.toString(16).padStart(2,"0")}${n.toString(16).padStart(2,"0")}${s.toString(16).padStart(2,"0")}`}function oh(e){let t=new Map;for(let n of e)Ht(n,s=>{if(s.fills){for(let o of s.fills)if(o.type==="SOLID"&&o.color){let i=Ao(o.color),r=t.get(i),a=s.type==="TEXT",l=a?"text":"fill";r?(r.occurrences++,a&&r.usage!=="text"&&(r.usage="text")):t.set(i,{hex:i,opacity:o.opacity??o.color.a,occurrences:1,usage:l})}}if(s.strokes){for(let o of s.strokes)if(o.type==="SOLID"&&o.color){let i=Ao(o.color),r=t.get(i);r?r.occurrences++:t.set(i,{hex:i,opacity:1,occurrences:1,usage:"border"})}}});return[...t.values()].sort((n,s)=>s.occurrences-n.occurrences)}function ih(e){let t=new Map;for(let n of e)Ht(n,s=>{if(s.type!=="TEXT"||!s.style)return;let o=s.style,i=o.fontSize||16,r=o.fontWeight||400,a=o.lineHeightPx?Math.round(o.lineHeightPx/i*100)/100:1.5,l=o.letterSpacing||0,c=o.fontFamily||"sans-serif",d="body";i>=32?d="heading":i>=20?d="subheading":i<=12?d="caption":r>=600&&i<=14&&(d="label");let u=`${c}-${i}-${r}`,m=t.get(u);m?m.occurrences++:t.set(u,{fontFamily:c,fontSize:i,fontWeight:r,lineHeight:a,letterSpacing:l,role:d,occurrences:1})});return[...t.values()].sort((n,s)=>s.fontSize-n.fontSize)}function rh(e){let t=[],n=new Set;for(let s of e)Ht(s,o=>{if(!o.layoutMode||o.layoutMode==="NONE")return;if(o.itemSpacing&&o.itemSpacing>0){let c=`gap-${o.itemSpacing}-${o.name}`;n.has(c)||(n.add(c),t.push({context:`${o.name} gap`,value:o.itemSpacing,type:"gap"}))}let i=o.paddingTop||0,r=o.paddingRight||0,a=o.paddingBottom||0,l=o.paddingLeft||0;if(i>0||r>0||a>0||l>0){let c=`pad-${i}-${r}-${a}-${l}-${o.name}`;if(!n.has(c)){n.add(c);let d=i===a&&l===r&&i===l?i:Math.max(i,r,a,l);t.push({context:`${o.name} padding`,value:d,type:"padding"})}}});return t}function ah(e){let t=[],n=new Set;for(let s of e)Ht(s,o=>{if(o.effects){for(let i of o.effects)if(i.type==="DROP_SHADOW"&&i.color&&i.offset){let{r,g:a,b:l,a:c}=i.color,d=`${i.offset.x}px ${i.offset.y}px ${i.radius||0}px rgba(${Math.round(r*255)},${Math.round(a*255)},${Math.round(l*255)},${Math.round(c*100)/100})`;n.has(d)||(n.add(d),t.push({type:"shadow",cssValue:d,context:o.name}))}}if(o.cornerRadius&&o.cornerRadius>0){let i=`${o.cornerRadius}px`;n.has(`radius-${i}`)||(n.add(`radius-${i}`),t.push({type:"radius",cssValue:i,context:o.name}))}});return t}function lh(e,t){let n=[];return Ht(e,s=>{if(s.type!=="TEXT"||!s.characters?.trim())return;let o=s.style?.fontSize||16,i=s.style?.fontWeight||400,r="body";o>=32?r="headline":o>=20?r="subheadline":o<=12?r="caption":i>=600&&o<=16&&(r="label"),i>=600&&s.characters.length<40&&o>=14&&o<32&&(r="cta"),n.push({text:s.characters,fontSize:o,fontWeight:i,role:r,sectionName:t})}),n}function ch(e){let t=e.absoluteBoundingBox;return{name:e.name,type:e.type,nodeId:e.id,width:t?.width||0,height:t?.height||0,layoutMode:e.layoutMode==="NONE"?void 0:e.layoutMode,childCount:e.children?.length||0,characters:e.type==="TEXT"?e.characters:void 0}}function dh(e){if(e.fills){for(let t of e.fills)if(t.type==="SOLID"&&t.color)return Ao(t.color)}if(e.backgroundColor)return Ao(e.backgroundColor)}function uh(e){return e.map(t=>{let n=t.absoluteBoundingBox;return{name:t.name,nodeId:t.id,width:n?.width||0,height:n?.height||0,textContent:lh(t,t.name),children:(t.children||[]).slice(0,20).map(ch),backgroundColor:dh(t),layoutMode:t.layoutMode==="NONE"?void 0:t.layoutMode,itemSpacing:t.itemSpacing,paddingTop:t.paddingTop,paddingRight:t.paddingRight,paddingBottom:t.paddingBottom,paddingLeft:t.paddingLeft}})}function mh(e){let t=[];for(let n of e)Ht(n,s=>{if(s.fills){for(let o of s.fills)if(o.type==="IMAGE"&&o.imageRef){t.push({nodeId:s.id,name:s.name||"image"});break}}});return t}async function zd(e,t){let n=await fetch(e);if(!n.ok)throw new Error(`Failed to download image: ${n.status}`);let s=Buffer.from(await n.arrayBuffer());Qg(t,s)}async function ph(e,t,n,s,o){if(t.length===0)return new Map;Gd(s,{recursive:!0});let r=t.map(c=>c.id).join(",");o&&o("Exporting frame screenshots...");let a=await ur(()=>To(`/v1/images/${e}?ids=${r}&format=png&scale=2`,n),o),l=new Map;for(let[c,d]of Object.entries(a.images)){if(!d)continue;let u=c.replace(/:/g,"-"),m=ko(s,`frame-${u}.png`);try{await zd(d,m),l.set(c,m),E.info("figma",`Downloaded frame screenshot: ${m}`)}catch(f){E.warn("figma",`Failed to download frame ${c}: ${f}`)}}return l}async function fh(e,t,n,s,o){if(t.length===0)return[];Gd(s,{recursive:!0});let i=50,r=[];for(let a=0;a<t.length;a+=i){let l=t.slice(a,a+i),c=l.map(u=>u.nodeId).join(",");o&&o(`Exporting images (${a+1}-${Math.min(a+i,t.length)} of ${t.length})...`);let d=await ur(()=>To(`/v1/images/${e}?ids=${c}&format=png&scale=2`,n),o);for(let u of l){let m=d.images[u.nodeId];if(!m)continue;let y=`${u.name.replace(/[^a-zA-Z0-9-_]/g,"-").toLowerCase()}-${eh().slice(0,6)}.png`,h=ko(s,y);try{await zd(m,h),r.push({name:u.name,localPath:h,nodeId:u.nodeId,format:"png"}),E.info("figma",`Downloaded asset: ${y}`)}catch(S){E.warn("figma",`Failed to download image ${u.name}: ${S}`)}}}return r}async function Kd(e,t,n,s,o){o&&o("Fetching Figma file...");let i=t?`/v1/files/${e}?ids=${t}&geometry=paths`:`/v1/files/${e}?geometry=paths`,r=await ur(()=>To(i,n),o);E.info("figma",`Fetched file: ${r.name}`);let a=sh(r.document,t);if(a.length===0)throw new Error("No frames found in the Figma file. The file may be empty or structured differently.");E.info("figma",`Found ${a.length} top-level frames`),o&&o(`Found ${a.length} sections. Extracting design tokens...`);let l={colors:oh(a),typography:ih(a),spacing:rh(a),effects:ah(a)};E.info("figma","Design tokens extracted",{colors:l.colors.length,typography:l.typography.length,spacing:l.spacing.length,effects:l.effects.length}),o&&o("Mapping page structure...");let c=uh(a),d=ko(s,".vibespot","figma-frames"),u=await ph(e,a,n,d,o),m=c.map(S=>({...S,frameImagePath:u.get(S.nodeId)||""}));o&&o("Extracting image assets...");let f=mh(a),y=ko(s,"assets"),h=await fh(e,f,n,y,o);return E.info("figma",`Extraction complete: ${m.length} sections, ${h.length} assets`),{fileName:r.name,fileUrl:`https://www.figma.com/design/${e}`,designTokens:l,sections:m,assets:h}}function Yd(e){let t=e.fileName.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"").slice(0,30);return{fileName:e.fileName,fileUrl:e.fileUrl,sectionNames:e.sections.map(n=>n.name),sectionCount:e.sections.length,colorPalette:e.designTokens.colors.slice(0,10).map(n=>n.hex),fontFamilies:[...new Set(e.designTokens.typography.map(n=>n.fontFamily))],textBlockCount:e.sections.reduce((n,s)=>n+s.textContent.length,0),assetCount:e.assets.length,suggestedThemeName:t}}async function qd(e){return await To("/v1/me",e)}var th,nh,Ud,dr,Xd=G(()=>{"use strict";g();re();th=/figma\.com\/(?:design|file|proto)\/([a-zA-Z0-9]+)(?:\/([^?]*))?/;nh="https://api.figma.com",Ud=[10,20,40,60,120];dr=new Set(["FRAME","COMPONENT","COMPONENT_SET","SECTION"])});var su={};_e(su,{getCachedExtraction:()=>nu,handleFigmaExtractRoute:()=>pr,handleFigmaGenerateRoute:()=>fr,handleFigmaTestTokenRoute:()=>mr});import{randomUUID as Zd}from"crypto";import{existsSync as Qd,mkdirSync as eu,writeFileSync as gh,copyFileSync as hh}from"fs";import{join as $o,basename as yh}from"path";function tu(){let e=Date.now();for(let[t,n]of qn)n.expires<e&&qn.delete(t)}function nu(e){tu();let t=qn.get(e);return t?(qn.delete(e),t.extraction):null}function mr(e,t){Oe(e,t,async n=>{let s=n.token||R().figmaToken;if(!s){p(t,400,{ok:!1,error:"No Figma token provided"});return}try{let o=await qd(s);p(t,200,{ok:!0,user:o})}catch(o){let i=o instanceof Error?o.message:String(o);E.warn("figma",`Token test failed: ${i}`),p(t,200,{ok:!1,error:"Invalid or expired Figma token"})}})}function pr(e,t){Oe(e,t,async n=>{let s=n.url;if(!s){p(t,400,{error:"Missing 'url' field"});return}let o=n.token||R().figmaToken;if(!o){p(t,400,{error:"No Figma token configured. Add one in Settings."});return}let i=Wd(s);if(!i){p(t,400,{error:"Not a valid Figma URL. Expected: figma.com/design/<key>/..."});return}let a=C()?.themePath||`/tmp/vibespot-figma-${Zd().slice(0,8)}`;t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let l=c=>{t.write(`data: ${JSON.stringify(c)}
2687
+ ${e}`:""}`;try{let a=await _e(n,s,o,{systemPrompt:r,messages:[{role:"user",content:t}],maxTokens:1e3}),l=a.type==="text"?a.text:JSON.stringify(a.data);return!l||l.trim().length<20?null:(E.info("context-extractor",`Extracted theme context (${l.length} chars)`),l.trim())}catch(a){let l=a instanceof Error?a.message:String(a);return E.warn("context-extractor",`Theme context extraction failed: ${l}`),null}}var Bo=R(()=>{"use strict";y();nt();de()});import{join as zd}from"path";function dy(t){let e=[];return t.brandAssets?.styleguide||e.push("styleguide"),t.brandAssets?.brandvoice||e.push("brandvoice"),t.brandAssets?.themeContext||e.push("themeContext"),e}function uy(t,e,n){t.brandAssets||(t.brandAssets={}),t.brandAssets[e]=n,t.updatedAt=Date.now();let s=e==="themeContext"?"theme-context.md":`${e}.md`,o=zd(t.themePath,".vibespot");Ie(o),J(zd(o,s),n)}async function Yd(t,e){let n=dy(t),s={attempted:[],extracted:[],skipped:[],errors:[]};if(n.length===0)return s;let o=my(e)?e:{...await py(t),...e??{}};n.includes("styleguide")&&await jr(t,"styleguide",s,()=>o.extractStyleguide(t));let i=n.filter(a=>a==="brandvoice"||a==="themeContext");if(i.length===0)return s;let r="";try{r=o.buildPreviewHtml()}catch(a){let l=a instanceof Error?a.message:String(a);for(let c of i)s.skipped.push(c),s.errors.push({asset:c,message:`Could not render preview HTML: ${l}`});return s}if(!r||r.length<50){for(let a of i)s.skipped.push(a);return s}return n.includes("brandvoice")&&await jr(t,"brandvoice",s,()=>o.extractBrandvoice(t,r)),n.includes("themeContext")&&await jr(t,"themeContext",s,()=>o.extractThemeContext(t,r)),s}async function jr(t,e,n,s){n.attempted.push(e);try{let o=await s();if(!o){n.skipped.push(e);return}uy(t,e,o),n.extracted.push(e)}catch(o){let i=o instanceof Error?o.message:String(o);n.skipped.push(e),n.errors.push({asset:e,message:i}),E.warn("brand-enrichment",`${e} enrichment skipped: ${i}`)}}function my(t){return!!t?.extractStyleguide&&!!t.extractBrandvoice&&!!t.extractThemeContext&&!!t.buildPreviewHtml}async function py(t){let{extractDesignContext:e}=await Promise.resolve().then(()=>(fs(),gs)),{buildPreviewHtml:n}=await Promise.resolve().then(()=>(es(),vo)),{resolveAgenticEngine:s}=await Promise.resolve().then(()=>(wn(),$r)),{extractBrandvoice:o}=await Promise.resolve().then(()=>(Fr(),Or)),{extractThemeContext:i}=await Promise.resolve().then(()=>(Bo(),Jo)),r=O();return{extractStyleguide:()=>e(t.themePath),buildPreviewHtml:n,extractBrandvoice:async(a,l)=>{let{engine:c,apiKey:d,model:u}=s(r);return o(l,c,d,u)},extractThemeContext:async(a,l)=>{let{engine:c,apiKey:d,model:u}=s(r);return i(l,a.brandAssets?.themeContext,c,d,u)}}}var qd=R(()=>{"use strict";y();ne();Q();de()});import{existsSync as kn,readdirSync as Xd,rmSync as gy,writeFileSync as Zt,mkdirSync as Ho}from"fs";import{join as Me,basename as fy}from"path";import{homedir as hy}from"os";import{execFileSync as Qd}from"child_process";function Go(){if(Uo&&Date.now()-Uo.ts<yy)return Uo.data;let t=[];if(kn(st))try{for(let e of Xd(st,{withFileTypes:!0}))if(e.isDirectory()){let n=Me(st,e.name,"theme.json");if(kn(n)){let s=0,o=Me(st,e.name,"modules");if(kn(o))try{s=Xd(o,{withFileTypes:!0}).filter(i=>i.isDirectory()).length}catch{}t.push({name:e.name,moduleCount:s})}}}catch{}return Uo={data:t,ts:Date.now()},t}function tu(t){let e=C(),n=Os(),s=!1;try{Qd("hs",["--version"],{encoding:"utf-8",stdio:"pipe",...eu}),s=!0}catch{}let o=gn().sort((r,a)=>a.updatedAt-r.updatedAt),i=Go();p(t,200,{hasActiveSession:!!e,activeSession:e?{id:e.id,themeName:e.themeName,moduleCount:e.modules.length,isImported:!!e.isImported}:null,hsInstalled:s,aiAvailable:n.availableEngines.length>0,availableEngines:n.availableEngines,activeEngine:n.activeEngine,sessions:o,localThemes:i,contentMode:yn()})}function nu(t,e){W(t,n=>{try{if(Ft()){p(e,409,{error:"Cannot switch projects while AI is generating.",generating:!0});return}let{name:s,starterId:o,assetType:i}=JSON.parse(n);if(!s||typeof s!="string"){p(e,400,{error:"Theme name is required"});return}let r=s.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"");if(!r){p(e,400,{error:"Theme name must contain at least one alphanumeric character"});return}let a=Me(st,r);if(Ie(st),kn(a)&&gy(a,{recursive:!0,force:!0}),o&&typeof o=="string"&&!Pr(o)){p(e,400,{error:`Starter template "${o}" not found`});return}Ln(a,r),pn(a,r),o&&typeof o=="string"?(by(a,r,o),ke()):i==="email"&&(Tt("module_only","Email","email"),ln(a,r)),D(),p(e,200,{ok:!0,themeName:r,themePath:a,starterId:o||void 0})}catch(s){p(e,500,{error:s instanceof Error?s.message:String(s)})}})}function by(t,e,n){let s=Pr(n);if(!s)return;let o=C();if(!o)return;let i=s.contentType==="email",r=s.modules.map(u=>({...u})),a=[...s.moduleOrder],l=i?`email-${e}`:`lp-${e}`,c={id:l,label:`${s.name}`,pageType:i?"module_only":"landing_page",contentMode:i?"email":void 0,templateFile:i?"templates/email.html":`templates/${l}.html`,modules:r,moduleOrder:a,sharedCss:s.sharedCss,sharedJs:s.sharedJs,template:"",messages:[]};i&&ln(t,e),o.templates=[c],o.activeTemplateId=l,o.modules=r,o.moduleOrder=a,o.sharedCss=s.sharedCss,o.sharedJs=s.sharedJs;let d=Me(t,"modules");Ho(d,{recursive:!0});for(let u of s.modules){let m=Me(d,`${u.moduleName}.module`);Ho(m,{recursive:!0}),Zt(Me(m,"fields.json"),u.fieldsJson,"utf-8"),Zt(Me(m,"meta.json"),u.metaJson,"utf-8"),Zt(Me(m,"module.html"),u.moduleHtml,"utf-8"),Zt(Me(m,"module.css"),u.moduleCss,"utf-8"),u.moduleJs&&Zt(Me(m,"module.js"),u.moduleJs,"utf-8")}if(s.sharedCss){let u=Me(t,"css");Ho(u,{recursive:!0}),Zt(Me(u,`${e}-theme.css`),s.sharedCss,"utf-8")}if(s.sharedJs){let u=Me(t,"js");Ho(u,{recursive:!0}),Zt(Me(u,`${e}-animations.js`),s.sharedJs,"utf-8")}}function su(t){p(t,200,{starters:Gd()})}function ou(t,e){W(t,n=>{try{if(Ft()){p(e,409,{error:"Cannot switch projects while AI is generating.",generating:!0});return}let{name:s}=JSON.parse(n);if(!s||typeof s!="string"){p(e,400,{error:"Theme name is required"});return}let o=s.replace(/^\/+|\/+$/g,"");if(!o){p(e,400,{error:"Theme name is required"});return}let i=Fe(),r=O(),a=o.includes("/")||o.includes("@")?o.replace(/[@/]/g,"_").replace(/_+/g,"_").replace(/^_|_$/g,""):o,l=Me(st,a);Ie(st),r.hubspotUploadMode==="cli"||!i?(async()=>{Qd("hs",["cms","fetch",o,l],{encoding:"utf-8",stdio:"pipe",...eu});let c=await Zd(l,a);p(e,200,{ok:!0,themeName:a,themePath:l,moduleCount:c.moduleCount,brandEnrichment:c.brandEnrichment})})().catch(c=>{p(e,500,{error:c instanceof Error?c.message:String(c)})}):Bn(i,o,l).then(async()=>{let c=await Zd(l,a);p(e,200,{ok:!0,themeName:a,themePath:l,moduleCount:c.moduleCount,brandEnrichment:c.brandEnrichment})}).catch(c=>{p(e,500,{error:c instanceof Error?c.message:String(c)})})}catch(s){p(e,500,{error:s instanceof Error?s.message:String(s)})}})}async function Zd(t,e){pn(t,e,{isImported:!0}),So(t),D();let n=C(),s={attempted:[],extracted:[],skipped:[],errors:[]};return n&&(s=await Yd(n),D()),{moduleCount:n?.modules.length||0,brandEnrichment:s}}function iu(t,e){W(t,n=>{try{if(Ft()){p(e,409,{error:"Cannot switch projects while AI is generating.",generating:!0});return}let{path:s}=JSON.parse(n);if(!s||typeof s!="string"){p(e,400,{error:"Theme path is required"});return}let o=s;if(kn(o)||(o=Me(st,s)),!kn(o)){p(e,400,{error:`Theme folder not found: ${s}`});return}let i=fy(o);pn(o,i),So(o),D(),p(e,200,{ok:!0,themeName:i,themePath:o,moduleCount:C()?.modules.length||0})}catch(s){p(e,500,{error:s instanceof Error?s.message:String(s)})}})}function ru(t,e){W(t,n=>{try{if(Ft()){p(e,409,{error:"Cannot switch projects while AI is generating.",generating:!0});return}let{sessionId:s}=JSON.parse(n);if(!s||typeof s!="string"){p(e,400,{error:"Session ID is required"});return}let o=po(s);if(!o){p(e,404,{error:"Session not found"});return}p(e,200,{ok:!0,themeName:o.themeName,themePath:o.themePath,moduleCount:o.modules.length,messageCount:o.messages.length})}catch(s){p(e,500,{error:s instanceof Error?s.message:String(s)})}})}function au(t,e){W(t,n=>{try{let{apiKey:s}=JSON.parse(n);if(!s||typeof s!="string"){p(e,400,{error:"API key is required"});return}Y({anthropicApiKey:s}),p(e,200,{ok:!0})}catch(s){p(e,400,{error:s instanceof Error?s.message:String(s)})}})}function lu(t){let e=Fe();if(!e){p(t,200,{themes:[],error:"No HubSpot account connected"});return}(async()=>{let n=await wa(e);if(n.length===0){p(t,200,{themes:[]});return}let s=[],o=n.map(async a=>{let l=a.path||a.name;try{let c=await Ds(e,`${l}/theme.json`);c&&!c.folder&&s.push({name:a.name,path:l})}catch{}});await Promise.all(o),s.sort((a,l)=>a.name.localeCompare(l.name));let i=Go(),r=new Set(i.map(a=>a.name));p(t,200,{themes:s.map(a=>({...a,existsLocally:r.has(a.name)}))})})().catch(n=>{p(t,200,{themes:[],error:n instanceof Error?n.message:String(n)})})}var eu,st,Uo,yy,Wo=R(()=>{"use strict";y();ze();Q();Jn();Hs();Ut();we();Nt();wn();Ht();Q();ne();Wd();ts();qd();eu=process.platform==="win32"?{shell:!0}:{},st=Me(hy(),"vibespot-themes"),Uo=null,yy=5e3});import{existsSync as Sy,readFileSync as xy,appendFileSync as vy}from"fs";import{join as cu}from"path";import{homedir as du}from"os";function ky(t){let e=t.match(/^gpt-(\d+(?:\.\d+)?)(?:-(.+))?$/);if(e){let n=e[1],s=e[2];if(!s)return`GPT-${n}`;let o=s.replace(/-/g," ").replace(/\b\w/g,i=>i.toUpperCase());return`GPT-${n} ${o}`}return t.startsWith("codex-")?`Codex ${t.slice(6).replace(/-/g," ").replace(/\b\w/g,s=>s.toUpperCase())}`:/^o\d/.test(t)?t.replace(/-/g," "):t}async function Ty(t){let e=await fetch("https://api.anthropic.com/v1/models",{headers:{"x-api-key":t,"anthropic-version":"2023-06-01"}});return e.ok?(await e.json()).data.filter(s=>!s.id.startsWith("claude-3-")&&!s.id.startsWith("claude-2")).map(s=>({id:s.id,label:s.display_name})):[]}async function Ay(t){let e=await fetch("https://api.openai.com/v1/models",{headers:{Authorization:`Bearer ${t}`}});return e.ok?(await e.json()).data.map(s=>s.id):[]}function uu(t,e){return t.filter(n=>e.test(n)).sort((n,s)=>n.localeCompare(s)).map(n=>({id:n,label:ky(n)}))}async function $y(t){let e=await fetch(`https://generativelanguage.googleapis.com/v1beta/models?key=${t}`);return e.ok?(await e.json()).models.filter(s=>s.name.includes("gemini-2")).map(s=>({id:s.name.replace("models/",""),label:s.displayName})):[]}async function _y(){if(Date.now()-hs.ts<wy&&Object.keys(hs.data).length>0)return hs.data;let t=O(),e={...mu},n=[],s=Oe("anthropic-api",t);s&&n.push(Ty(s).then(r=>{r.length&&(e["anthropic-api"]=r,e["claude-oauth"]=r)}).catch(()=>{}));let o=Oe("openai-api",t);o&&n.push(Ay(o).then(r=>{if(!r.length)return;let a=uu(r,pu);a.length&&(e["openai-api"]=a);let l=uu(r,Cy);l.length&&(e["codex-cli"]=l)}).catch(()=>{}));let i=Oe("gemini-api",t);return i&&n.push($y(i).then(r=>{r.length&&(e["gemini-api"]=r,e["gemini-cli"]=r)}).catch(()=>{})),await Promise.all(n),hs.data=e,hs.ts=Date.now(),e}function gu(t){let e=Os(),n=O(),s={aiEngine:n.aiEngine||null,claudeCodeModel:n.claudeCodeModel||null,anthropicApiModel:n.anthropicApiModel||null,openaiApiModel:n.openaiApiModel||null,codexCliModel:n.codexCliModel||null,geminiCliModel:n.geminiCliModel||null,geminiApiModel:n.geminiApiModel||null,hubspotUploadMode:n.hubspotUploadMode||"api",hubspotAccounts:(n.hubspotAccounts||[]).map(a=>({portalId:a.portalId,portalName:a.portalName,dataCenter:a.dataCenter})),activeHubSpotAccount:n.activeHubSpotAccount||null,enabledCLITools:n.enabledCLITools||[],agenticMode:n.agenticMode,agenticConcurrency:n.agenticConcurrency,planMode:n.planMode||!1,extendedThinking:n.extendedThinking||!1,extendedThinkingBudget:n.extendedThinkingBudget||"medium",webSearch:n.webSearch||!1,figmaToken:n.figmaToken?"\u2022\u2022\u2022\u2022"+n.figmaToken.slice(-4):null},o=gn().length,i=Go().length,r=sn();_y().then(a=>{p(t,200,{version:r,environment:e,config:s,models:a,sessionCount:o,localThemeCount:i})}).catch(()=>{p(t,200,{version:r,environment:e,config:s,models:mu,sessionCount:o,localThemeCount:i})})}function fu(t,e){W(t,n=>{try{let{engine:s,model:o}=JSON.parse(n);if(!["claude-code","anthropic-api","claude-oauth","openai-api","gemini-cli","gemini-api","codex-cli"].includes(s)){p(e,400,{error:`Invalid engine: ${s}`});return}let r={aiEngine:s};if(o)switch(s){case"claude-code":r.claudeCodeModel=o;break;case"anthropic-api":case"claude-oauth":r.anthropicApiModel=o;break;case"openai-api":r.openaiApiModel=o;break;case"codex-cli":r.codexCliModel=o;break;case"gemini-cli":r.geminiCliModel=o;break;case"gemini-api":r.geminiApiModel=o;break}Y(r),p(e,200,{ok:!0,engine:s})}catch(s){p(e,400,{error:s instanceof Error?s.message:String(s)})}})}function hu(t,e){W(t,n=>{try{let{provider:s,apiKey:o}=JSON.parse(n);if(!s||typeof s!="string"){p(e,400,{error:"provider is required"});return}if(!o){let l={};switch(s){case"anthropic":l.anthropicApiKey="";break;case"openai":l.openaiApiKey="";break;case"gemini":l.geminiApiKey="";break;case"figma":l.figmaToken="";break;default:p(e,400,{error:`Unknown provider: ${s}`});return}Y(l),p(e,200,{ok:!0,provider:s,deleted:!0});return}let i={};switch(s){case"anthropic":i.anthropicApiKey=o;break;case"openai":i.openaiApiKey=o;break;case"gemini":i.geminiApiKey=o;break;case"figma":i.figmaToken=o;break;default:p(e,400,{error:`Unknown provider: ${s}`});return}Y(i);let r=null;if(!O().aiEngine){let c={anthropic:"anthropic-api",openai:"openai-api",gemini:"gemini-api"}[s];c&&(Y({aiEngine:c}),r=c)}p(e,200,{ok:!0,provider:s,autoSelectedEngine:r})}catch(s){p(e,400,{error:s instanceof Error?s.message:String(s)})}})}function yu(t,e){W(t,n=>{try{let{tool:s}=JSON.parse(n),o={hubspot:{cmd:"npm install -g @hubspot/cli",desc:"Installing HubSpot CLI"},claude:{cmd:"npm install -g @anthropic-ai/claude-code",desc:"Installing Claude Code"},gemini:{cmd:"npm install -g @google/gemini-cli",desc:"Installing Gemini CLI"},codex:{cmd:process.platform==="darwin"?"brew install --cask codex":"npm install -g @openai/codex",desc:"Installing OpenAI Codex"},gh:{cmd:process.platform==="darwin"?"brew install gh":"npm install -g @cli/gh",desc:"Installing GitHub CLI"}},i=o[s];if(!i){p(e,400,{error:`Unknown tool: ${s}. Valid: ${Object.keys(o).join(", ")}`});return}let r=Xt(i.cmd,i.desc,{timeout:12e4});p(e,200,{ok:!0,jobId:r})}catch(s){p(e,400,{error:s instanceof Error?s.message:String(s)})}})}function bu(t,e){W(t,n=>{try{let s=JSON.parse(n||"{}"),o=O(),i=o.hubspotUploadMode||"api";if(s.personalAccessKey)if(i==="api"){js(s.personalAccessKey).then(r=>{An(s.personalAccessKey,r.portalId,r.portalName,r.dataCenter),p(e,200,{ok:!0,portalName:r.portalName,portalId:r.portalId,dataCenter:r.dataCenter})}).catch(r=>{p(e,400,{error:r instanceof Error?r.message:String(r)})});return}else{if(!ct().found){p(e,400,{error:"HubSpot CLI not installed",needsInstall:!0});return}let a=ms("hs",["auth",`--pak=${s.personalAccessKey}`],"Authenticating with HubSpot",{timeout:3e4});p(e,200,{ok:!0,jobId:a});return}if(i==="api"){let r=o.hubspotAccounts||[];if(r.length>0&&!s.force){let a=r.find(l=>l.portalId===o.activeHubSpotAccount)||r[0];p(e,200,{ok:!0,alreadyAuthenticated:!0,portalName:a.portalName,portalId:a.portalId});return}}else{if(!ct().found){p(e,400,{error:"HubSpot CLI not installed",needsInstall:!0});return}let a=dt();if(a.authenticated&&!s.force){p(e,200,{ok:!0,alreadyAuthenticated:!0,portalName:a.portalName,portalId:a.portalId});return}}p(e,200,{needsKey:!0,instructions:"Create a personal access key in HubSpot",url:"https://app.hubspot.com/portal-recommend/l?slug=personal-access-key",steps:["Click the link above to open HubSpot","Select your account","Create a Personal Access Key with CMS permissions","Copy the key and paste it below"]})}catch(s){p(e,500,{error:s instanceof Error?s.message:String(s)})}})}function Su(t,e){W(t,n=>{try{let s=JSON.parse(n||"{}");if(!hi().found){p(e,400,{error:"GitHub CLI not installed",needsInstall:!0});return}let i=yi();if(i.authenticated&&!s.force){p(e,200,{ok:!0,alreadyAuthenticated:!0,username:i.username});return}if(s.token){let a=ms("gh",["auth","login","--with-token"],"Authenticating with GitHub",{timeout:3e4,stdin:s.token});p(e,200,{ok:!0,jobId:a});return}let r=Xt("gh auth login --web --git-protocol https","GitHub authentication (check your browser)",{timeout:3e5});p(e,200,{ok:!0,jobId:r,browserAuthRequired:!0})}catch(s){p(e,500,{error:s instanceof Error?s.message:String(s)})}})}function xu(t,e){W(t,n=>{try{let{portalId:s,action:o}=JSON.parse(n);if((O().hubspotUploadMode||"api")==="api"){if(o==="remove"&&s){ci(s),p(e,200,{ok:!0});return}if(s){di(s),p(e,200,{ok:!0});return}}else{if(!ct().found){p(e,400,{error:"HubSpot CLI not installed"});return}let l=String(s).replace(/[^0-9]/g,"");if(!l){p(e,400,{error:"Invalid portalId"});return}if(o==="remove"){let c=ms("hs",["accounts","remove",l],`Removing HubSpot account ${l}`,{timeout:15e3});p(e,200,{ok:!0,jobId:c});return}if(l){let c=ms("hs",["accounts","use",l],`Switching to HubSpot account ${l}`,{timeout:15e3});p(e,200,{ok:!0,jobId:c});return}}p(e,400,{error:"portalId required"})}catch(s){p(e,500,{error:s instanceof Error?s.message:String(s)})}})}function vu(t){let e=Xt("gh auth logout --hostname github.com -y","Logging out of GitHub",{timeout:15e3});p(t,200,{ok:!0,jobId:e})}function wu(t,e){W(t,n=>{try{let{cli:s,apiKey:o}=JSON.parse(n||"{}");switch(s){case"claude":{let i=Xt("CLAUDECODE= claude --print -p 'reply OK'","Authenticating Claude Code (check your browser if prompted)",{timeout:12e4});p(e,200,{ok:!0,jobId:i,hint:"If Claude Code opens a browser window, complete the sign-in there."});break}case"gemini":{let i=Xt("gemini -p 'reply OK'","Authenticating Gemini CLI (check your browser if prompted)",{timeout:12e4});p(e,200,{ok:!0,jobId:i,hint:"If Gemini opens a browser window, complete the sign-in there."});break}case"codex":{if(o&&o.trim()){let i=o.trim();if(process.env.OPENAI_API_KEY=i,Y({openaiApiKey:i}),process.platform!=="win32"){let r=/^[A-Za-z0-9_\-.:]+$/.test(i)?i:"";if(r){let a=`export OPENAI_API_KEY="${r}"`,l=process.env.SHELL?.includes("zsh")?cu(du(),".zshrc"):cu(du(),".bashrc");try{(Sy(l)?xy(l,"utf-8"):"").includes("OPENAI_API_KEY")||vy(l,`
2688
+ # Added by vibeSpot
2689
+ ${a}
2690
+ `)}catch{}}}p(e,200,{ok:!0,message:"API key saved"})}else{let i=Xt("codex login","Authenticating Codex CLI (check your browser if prompted)",{timeout:12e4});p(e,200,{ok:!0,jobId:i,hint:"Complete the sign-in in your browser."})}break}default:p(e,400,{error:`Unknown CLI: ${s}`})}}catch(s){p(e,400,{error:s instanceof Error?s.message:String(s)})}})}function Cu(t,e){W(t,n=>{try{let{mode:s}=JSON.parse(n);if(s!=="api"&&s!=="cli"){p(e,400,{error:`Invalid mode: ${s}. Must be "api" or "cli".`});return}Y({hubspotUploadMode:s}),p(e,200,{ok:!0,mode:s})}catch(s){p(e,400,{error:s instanceof Error?s.message:String(s)})}})}function ku(t,e){W(t,n=>{try{let{toolId:s,enabled:o}=JSON.parse(n);if(!s||typeof o!="boolean"){p(e,400,{error:"toolId (string) and enabled (boolean) required"});return}ui(s,o),p(e,200,{ok:!0,toolId:s,enabled:o})}catch(s){p(e,400,{error:s instanceof Error?s.message:String(s)})}})}function Tu(t,e){W(t,n=>{try{let s=JSON.parse(n),o=["agenticMode","agenticConcurrency","planMode","extendedThinking","extendedThinkingBudget","webSearch"];if(s.extendedThinkingBudget!==void 0&&!["low","medium","high"].includes(s.extendedThinkingBudget)){p(e,400,{error:"extendedThinkingBudget must be 'low' | 'medium' | 'high'"});return}let i={};for(let r of o)r in s&&(i[r]=s[r]);if(Object.keys(i).length===0){p(e,400,{error:"No valid settings fields provided"});return}Y(i),p(e,200,{ok:!0,updated:Object.keys(i)})}catch(s){p(e,400,{error:s instanceof Error?s.message:String(s)})}})}function Au(t,e){let n=t.replace("/api/settings/job/","");if(!n){p(e,400,{error:"Job ID required"});return}let s=Ro(n);if(!s){p(e,404,{error:"Job not found"});return}p(e,200,{id:s.id,status:s.status,description:s.description,output:s.output,exitCode:s.exitCode,startedAt:s.startedAt,completedAt:s.completedAt})}var hs,wy,mu,pu,Cy,$u=R(()=>{"use strict";y();ze();Q();we();Wo();Ht();Ut();ne();Oo();hs={data:{},ts:0},wy=600*1e3,mu={"claude-code":[{id:"claude-opus-4-7",label:"Claude Opus 4.7"},{id:"claude-opus-4-6",label:"Claude Opus 4.6"},{id:"claude-sonnet-4-6",label:"Claude Sonnet 4.6 (default)"},{id:"claude-sonnet-4-5",label:"Claude Sonnet 4.5"},{id:"claude-haiku-4-5",label:"Claude Haiku 4.5"}],"codex-cli":[{id:"gpt-5.5",label:"GPT-5.5 (default)"},{id:"gpt-5.5-pro",label:"GPT-5.5 Pro"},{id:"gpt-5.3-codex",label:"GPT-5.3 Codex"},{id:"gpt-5.2-codex",label:"GPT-5.2 Codex"},{id:"gpt-5.1-codex-max",label:"GPT-5.1 Codex Max"},{id:"gpt-5.1-codex-mini",label:"GPT-5.1 Codex Mini"},{id:"gpt-5.4-mini",label:"GPT-5.4 Mini"},{id:"gpt-5.4-nano",label:"GPT-5.4 Nano"},{id:"codex-mini-latest",label:"Codex Mini (latest)"}],"anthropic-api":[{id:"claude-opus-4-7",label:"Claude Opus 4.7"},{id:"claude-opus-4-6",label:"Claude Opus 4.6"},{id:"claude-sonnet-4-6",label:"Claude Sonnet 4.6 (default)"},{id:"claude-sonnet-4-5",label:"Claude Sonnet 4.5"},{id:"claude-haiku-4-5-20251001",label:"Claude Haiku 4.5"}],"claude-oauth":[{id:"claude-opus-4-7",label:"Claude Opus 4.7"},{id:"claude-opus-4-6",label:"Claude Opus 4.6"},{id:"claude-sonnet-4-6",label:"Claude Sonnet 4.6 (default)"},{id:"claude-sonnet-4-5",label:"Claude Sonnet 4.5"},{id:"claude-haiku-4-5-20251001",label:"Claude Haiku 4.5"}],"openai-api":[{id:"gpt-5.5",label:"GPT-5.5 (default)"},{id:"gpt-5.5-pro",label:"GPT-5.5 Pro"},{id:"gpt-5.4-mini",label:"GPT-5.4 Mini"},{id:"gpt-5.4-nano",label:"GPT-5.4 Nano"},{id:"gpt-5.3-codex",label:"GPT-5.3 Codex"}],"gemini-api":[{id:"gemini-2.5-pro",label:"Gemini 2.5 Pro (default)"},{id:"gemini-2.5-flash",label:"Gemini 2.5 Flash"},{id:"gemini-2.0-flash",label:"Gemini 2.0 Flash"}],"gemini-cli":[{id:"gemini-2.5-pro",label:"Gemini 2.5 Pro (default)"},{id:"gemini-2.5-flash",label:"Gemini 2.5 Flash"},{id:"gemini-2.0-flash",label:"Gemini 2.0 Flash"}]},pu=/^(gpt-[45](\.\d+)?(-[a-z0-9-]+)?|o[1-4](-(mini|pro|nano)(-high)?)?|codex(-[a-z0-9-]+)?)$/,Cy=pu});function _u(t,e){W(t,n=>{try{let{access_token:s,refresh_token:o}=JSON.parse(n);if(!s||typeof s!="string"){p(e,400,{error:"access_token is required"});return}mi(s.trim(),(o||"").trim());let i=O();(!i.aiEngine||i.aiEngine!=="claude-oauth")&&Y({aiEngine:"claude-oauth"}),p(e,200,{ok:!0})}catch(s){p(e,400,{error:s instanceof Error?s.message:String(s)})}})}function Mu(t,e){let n=lt(),s=Mn();p(e,200,{authenticated:n,expiresAt:s?.expiresAt||null})}function Eu(t,e){try{Es(),O().aiEngine==="claude-oauth"&&Y({aiEngine:void 0}),p(e,200,{ok:!0})}catch(n){p(e,500,{error:n instanceof Error?n.message:String(n)})}}var Iu=R(()=>{"use strict";y();ze();Q();xt()});import{existsSync as My,rmSync as Ey}from"fs";import{join as Iy}from"path";function Pu(t,e,n){if(t==="GET"){let s=C(),o=gn().sort((i,r)=>r.updatedAt-i.updatedAt);p(n,200,{activeTheme:s?{id:s.id,themeName:s.themeName,isImported:!!s.isImported}:null,sessions:o});return}if(t==="DELETE"){W(e,s=>{try{let{sessionId:o,deleteFiles:i}=JSON.parse(s);Ol(o,i),p(n,200,{ok:!0})}catch(o){p(n,500,{error:o instanceof Error?o.message:String(o)})}});return}p(n,405,{error:"Method not allowed"})}function Ru(t,e){W(t,n=>{try{let{sessionId:s}=JSON.parse(n),o=po(s);if(!o){p(e,404,{error:"Session not found"});return}p(e,200,{ok:!0,themeName:o.themeName,themePath:o.themePath})}catch(s){p(e,500,{error:s instanceof Error?s.message:String(s)})}})}function Nu(t,e){W(t,n=>{try{let{themeName:s}=JSON.parse(n);if(!s||typeof s!="string"){p(e,400,{error:"Theme name is required"});return}if(/[\/\\]|\.\./.test(s)||s==="."||!s.replace(/[^a-z0-9]/gi,"")){p(e,400,{error:"Invalid theme name"});return}let o=Iy(st,s);if(!My(o)){p(e,404,{error:"Theme not found on disk"});return}Ey(o,{recursive:!0,force:!0}),p(e,200,{ok:!0})}catch(s){p(e,500,{error:s instanceof Error?s.message:String(s)})}})}function Ou(t,e){W(t,n=>{try{let{sessionId:s,newName:o}=JSON.parse(n);if(!s||!o||typeof o!="string"){p(e,400,{error:"sessionId and newName are required"});return}let i=o.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/^-|-$/g,"").replace(/-{2,}/g,"-");if(!i){p(e,400,{error:"Invalid name"});return}let r=Fl(s,i);r.ok?p(e,200,{ok:!0,newName:i}):p(e,400,{error:r.error})}catch(s){p(e,500,{error:s instanceof Error?s.message:String(s)})}})}function Fu(t,e){W(t,n=>{try{let{sessionId:s}=JSON.parse(n);if(!s){p(e,400,{error:"sessionId is required"});return}let o=jl(s);o.ok?p(e,200,{ok:!0,newName:o.newName,newSessionId:o.newSessionId}):p(e,400,{error:o.error})}catch(s){p(e,500,{error:s instanceof Error?s.message:String(s)})}})}var ju=R(()=>{"use strict";y();ze();we();Wo()});import{existsSync as ys,readFileSync as Py,rmSync as Ko}from"fs";import{join as Ne,basename as Ry}from"path";import{execFileSync as Ny}from"child_process";function Bu(t){let e=C();if(!e){p(t,404,{error:"No active session"});return}let n=At();p(t,200,{themeName:e.themeName,themePath:e.themePath,templates:e.templates.map(s=>({id:s.id,label:s.label,pageType:s.contentMode==="email"?"email":s.pageType,moduleCount:s.modules.length,messageCount:s.messages.length})),activeTemplateId:e.activeTemplateId,moduleLibrary:n.map(s=>({moduleName:s.module.moduleName,usedIn:s.usedIn})),brandAssets:{hasStyleguide:!!e.brandAssets?.styleguide,hasBrandvoice:!!e.brandAssets?.brandvoice,hasThemeContext:!!e.brandAssets?.themeContext,humanify:e.brandAssets?.humanify!==!1,hasBrandKit:!!e.brandAssets?.brandKit&&Object.keys(e.brandAssets.brandKit).length>0,brandKit:e.brandAssets?.brandKit||null}})}function Hu(t){let e=C();if(!e){p(t,404,{error:"No active session"});return}let n=e.themePath;if(!ys(n)){p(t,404,{error:"Theme directory not found"});return}let s=e.themeName||"theme",o=Ne(n,".."),i=Ry(n);try{let r=`${s}.zip`,a=Ne(o,r);ys(a)&&Ko(a),Ny("zip",["-r",r,i,"-x",`${i}/.git/*`,`${i}/.vibespot/*`,`${i}/node_modules/*`],{cwd:o,timeout:3e4,...Oy});let l=Py(a);Ko(a),t.writeHead(200,{"Content-Type":"application/zip","Content-Disposition":`attachment; filename="${r}"`,"Content-Length":l.length}),t.end(l)}catch(r){E.error("download-zip","Failed to create zip archive",r),p(t,500,{error:"Failed to create zip archive"})}}function Uu(t,e,n){let s=C();if(!s){p(n,404,{error:"No active session"});return}if(t==="GET"){p(n,200,{templates:s.templates.map(o=>({id:o.id,label:o.label,pageType:o.contentMode==="email"?"email":o.pageType,moduleCount:o.modules.length})),activeTemplateId:s.activeTemplateId});return}if(t==="POST"){W(e,o=>{try{let{pageType:i,label:r}=JSON.parse(o);if(!i||!r){p(n,400,{error:"pageType and label are required"});return}if(!["landing_page","blog_post","website_page","module_only","email"].includes(i)){p(n,400,{error:`Invalid pageType: ${i}`});return}let l=i==="email",d=Tt(l?"module_only":i,r,l?"email":void 0);l&&s.themePath&&ln(s.themePath,s.themeName),D(),p(n,200,{ok:!0,template:{id:d.id,label:d.label,pageType:d.pageType}})}catch(i){p(n,500,{error:i instanceof Error?i.message:String(i)})}});return}if(t==="DELETE"){W(e,o=>{try{let{templateId:i,deleteModules:r}=JSON.parse(o);if(!i){p(n,400,{error:"templateId is required"});return}if(!Il(i,!!r)){p(n,404,{error:"Template not found"});return}D(),p(n,200,{ok:!0})}catch(i){p(n,500,{error:i instanceof Error?i.message:String(i)})}});return}p(n,405,{error:"Method not allowed"})}function Gu(t,e){W(t,n=>{try{let{templateId:s}=JSON.parse(n);if(!s){p(e,400,{error:"templateId is required"});return}if(!Kn(s)){p(e,404,{error:"Template not found"});return}D();let i=C();p(e,200,{ok:!0,modules:Se().map(r=>r.moduleName),messageCount:i?.messages.length||0})}catch(s){p(e,500,{error:s instanceof Error?s.message:String(s)})}})}function Wu(t,e){W(t,n=>{try{let{templateId:s,newLabel:o}=JSON.parse(n);if(!s||!o||typeof o!="string"){p(e,400,{error:"templateId and newLabel are required"});return}if(!El(s,o.trim())){p(e,404,{error:"Template not found"});return}D(),p(e,200,{ok:!0,newLabel:o.trim()})}catch(s){p(e,500,{error:s instanceof Error?s.message:String(s)})}})}function Ku(t,e){W(t,n=>{try{let{templateIds:s}=JSON.parse(n);if(!Array.isArray(s)||s.some(i=>typeof i!="string")){p(e,400,{error:"templateIds must be an array of strings"});return}if(!Ml(s)){p(e,400,{error:"Reorder rejected (length mismatch or no session)"});return}D(),p(e,200,{ok:!0})}catch(s){p(e,500,{error:s instanceof Error?s.message:String(s)})}})}function Vu(t,e){W(t,n=>{try{let{templateId:s,label:o}=JSON.parse(n);if(!s){p(e,400,{error:"templateId is required"});return}let i=_l(s,o);if(!i){p(e,404,{error:"Template not found"});return}D(),p(e,200,{ok:!0,template:{id:i.id,label:i.label,pageType:i.pageType,moduleCount:i.modules.length}})}catch(s){p(e,500,{error:s instanceof Error?s.message:String(s)})}})}function zu(t){let e=At();p(t,200,{modules:e.map(n=>({moduleName:n.module.moduleName,usedIn:n.usedIn,fieldsJson:n.module.fieldsJson}))})}function Yu(t,e,n){let s=C();if(!s){p(n,404,{error:"No active session"});return}W(e,o=>{try{let{moduleName:i}=JSON.parse(o);if(!i){p(n,400,{error:"moduleName is required"});return}let a=At().find(d=>d.module.moduleName===i);if(!a){p(n,404,{error:`Module "${i}" not found in library`});return}let l={...a.module};s.modules.find(d=>d.moduleName===l.moduleName)||(s.modules.push(l),s.moduleOrder.push(l.moduleName),s.updatedAt=Date.now()),D(),p(n,200,{ok:!0})}catch(i){p(n,500,{error:i instanceof Error?i.message:String(i)})}})}function qu(t,e,n){let s=C();if(!s){p(n,404,{error:"No active session"});return}if(t==="GET"){p(n,200,{styleguide:s.brandAssets?.styleguide||null,brandvoice:s.brandAssets?.brandvoice||null,themeContext:s.brandAssets?.themeContext||null});return}if(t==="POST"){W(e,o=>{try{let{type:i,content:r}=JSON.parse(o);if(!i){p(n,400,{error:"type is required"});return}if(s.brandAssets||(s.brandAssets={}),i==="humanify"){s.brandAssets.humanify=r==="on",s.updatedAt=Date.now(),D(),p(n,200,{ok:!0});return}if(!r){p(n,400,{error:"content is required"});return}if(i!=="styleguide"&&i!=="brandvoice"&&i!=="themeContext"){p(n,400,{error:`Invalid type: ${i}. Must be "styleguide", "brandvoice", or "themeContext"`});return}let a=i,l=a==="themeContext"?"theme-context.md":`${a}.md`;s.brandAssets[a]=r,s.updatedAt=Date.now();let c=Ne(s.themePath,".vibespot");Ie(c),J(Ne(c,l),r);let d=null;a==="styleguide"&&(d=Dr(s,r)),D(),p(n,200,{ok:!0,brandKit:d})}catch(i){p(n,500,{error:i instanceof Error?i.message:String(i)})}});return}if(t==="DELETE"){W(e,o=>{try{let{type:i}=JSON.parse(o);if(i!=="styleguide"&&i!=="brandvoice"&&i!=="themeContext"){p(n,400,{error:`Invalid type: ${i}`});return}let r=i;s.brandAssets&&delete s.brandAssets[r],s.updatedAt=Date.now();let a=r==="themeContext"?"theme-context.md":`${r}.md`,l=Ne(s.themePath,".vibespot",a);ys(l)&&Ko(l),D(),p(n,200,{ok:!0})}catch(i){p(n,500,{error:i instanceof Error?i.message:String(i)})}});return}p(n,405,{error:"Method not allowed"})}function Zu(t,e){p(e,200,Xu)}function jy(t){let e=[],n=[],s=t.split(`
2691
+ `),o=!1,i=!1;for(let r of s){let a=r.trim();if(/^##\s+color/i.test(a)){o=!0,i=!1;continue}if(/^##\s+typography/i.test(a)){i=!0,o=!1;continue}if(/^##\s+/.test(a)&&!(/color/i.test(a)||/typography/i.test(a))){o=!1,i=!1;continue}if(o){let l=a.match(Fy);if(l)for(let c of l)e.includes(c.toLowerCase())||e.push(c.toLowerCase())}if(i){let l=Du.exec(a);if(Du.lastIndex=0,l){let c=l[1].trim().replace(/['"`]/g,"").split(",")[0].trim();c&&!n.includes(c)&&n.push(c)}if(/\bheading|body|display|monospace\b/i.test(a)&&!l){let c=a.split(":").slice(1).join(":").trim();if(c){let d=c.replace(/['"`*]/g,"").split(",")[0].trim().split("(")[0].trim();d&&d.length<60&&!/^\d/.test(d)&&!n.includes(d)&&n.push(d)}}}}return{colors:e.slice(0,6),fonts:n.slice(0,4)}}function Dr(t,e){let{colors:n,fonts:s}=jy(e);if(n.length===0&&s.length===0)return null;t.brandAssets||(t.brandAssets={});let o=t.brandAssets.brandKit||{};if(n.length>0&&(o.colors||(o.colors={}),n[0]&&(o.colors.primary=n[0]),n[1]&&(o.colors.secondary=n[1]),n[2]&&(o.colors.accent=n[2])),s.length>0){o.fonts||(o.fonts={});let r=a=>{let l=a.toLowerCase(),c=Xu.find(d=>d.name.toLowerCase()===l);return c?c.stack:a};s[0]&&(o.fonts.heading=r(s[0])),s[1]?o.fonts.body=r(s[1]):s[0]&&(o.fonts.body=r(s[0]))}t.brandAssets.brandKit=o;let i=Ne(t.themePath,".vibespot");return Ie(i),J(Ne(i,"brand-kit.json"),JSON.stringify(o,null,2)),o}function Qu(t,e,n){let s=C();if(!s){p(n,404,{error:"No active session"});return}if(t==="GET"){p(n,200,s.brandAssets?.brandKit||{});return}if(t==="POST"){W(e,o=>{try{let i=JSON.parse(o);s.brandAssets||(s.brandAssets={});let r={};if(i.colors&&typeof i.colors=="object"){let l={};for(let c of["primary","secondary","accent"])typeof i.colors[c]=="string"&&Dy.test(i.colors[c])&&(l[c]=i.colors[c]);Object.keys(l).length>0&&(r.colors=l)}if(i.fonts&&typeof i.fonts=="object"){let l={};for(let c of["heading","body"])typeof i.fonts[c]=="string"&&i.fonts[c].trim()&&(l[c]=i.fonts[c].trim());Object.keys(l).length>0&&(r.fonts=l)}typeof i.logoUrl=="string"&&i.logoUrl.trim()&&(r.logoUrl=i.logoUrl.trim()),s.brandAssets.brandKit=r,s.updatedAt=Date.now();let a=Ne(s.themePath,".vibespot");Ie(a),J(Ne(a,"brand-kit.json"),JSON.stringify(r,null,2)),D(),p(n,200,{ok:!0,brandKit:r})}catch(i){p(n,500,{error:i instanceof Error?i.message:String(i)})}});return}if(t==="DELETE"){s.brandAssets&&delete s.brandAssets.brandKit,s.updatedAt=Date.now();let o=Ne(s.themePath,".vibespot","brand-kit.json");ys(o)&&Ko(o),D(),p(n,200,{ok:!0});return}p(n,405,{error:"Method not allowed"})}function Lu(t,e,n){if(!t)return;t.brandAssets||(t.brandAssets={}),t.brandAssets[e]=n,t.updatedAt=Date.now();let s=e==="themeContext"?"theme-context.md":`${e}.md`,o=Ne(t.themePath,".vibespot");Ie(o),J(Ne(o,s),n)}async function Ju(t,e,n){if(e==="styleguide"){let{extractDesignContext:m}=await Promise.resolve().then(()=>(fs(),gs));return m(n||t.themePath)}let{resolveAgenticEngine:s}=await Promise.resolve().then(()=>(wn(),$r)),{loadConfig:o}=await Promise.resolve().then(()=>(Q(),pa)),i=o(),{engine:r,apiKey:a,model:l}=s(i),{buildPreviewHtml:c}=await Promise.resolve().then(()=>(es(),vo)),d=c();if(!d||d.length<50)return null;if(e==="brandvoice"){let{extractBrandvoice:m}=await Promise.resolve().then(()=>(Fr(),Or));return m(d,r,a,l)}let{extractThemeContext:u}=await Promise.resolve().then(()=>(Bo(),Jo));return u(d,t.brandAssets?.themeContext,r,a,l)}function em(t,e){let n=C();if(!n){p(e,404,{error:"No active session"});return}W(t,s=>{(async()=>{try{let o=s?JSON.parse(s):{},i=o.type||"styleguide",r=o.sourcePath;if(i==="all"){let c=["styleguide","brandvoice","themeContext"],d=await Promise.allSettled(c.map(g=>Ju(n,g,r))),u={};for(let g=0;g<c.length;g++){let h=d[g],f=h.status==="fulfilled"?h.value:null;f&&Lu(n,c[g],f),u[c[g]]=f}let m=null;u.styleguide&&(m=Dr(n,u.styleguide)),D(),p(e,200,{ok:!0,type:"all",extracted:u,brandKit:m});return}if(i!=="styleguide"&&i!=="brandvoice"&&i!=="themeContext"){p(e,400,{error:`Invalid type: ${i}`});return}let a=await Ju(n,i,r);if(!a){p(e,200,{ok:!1,type:i,error:"No content to extract from"});return}Lu(n,i,a);let l=null;i==="styleguide"&&(l=Dr(n,a)),D(),p(e,200,{ok:!0,type:i,content:a,brandKit:l})}catch(o){p(e,500,{error:o instanceof Error?o.message:String(o)})}})()})}function tm(t,e){let n=C();if(!n){p(e,404,{error:"No active session"});return}W(t,s=>{(async()=>{try{let{source:o,themeName:i,localPath:r}=JSON.parse(s),a;if(o==="hubspot"){if(!i){p(e,400,{error:"themeName is required for HubSpot import"});return}let u=Fe();if(!u){p(e,400,{error:"No HubSpot account connected"});return}let m=i.replace(/^\/+|\/+$/g,"");if(!m){p(e,400,{error:"Invalid theme name"});return}let g=m.replace(/[@/]/g,"_").replace(/_+/g,"_"),{homedir:h}=await import("os"),f=Ne(h(),"vibespot-themes",".references",g);Ie(f);let{fetchTheme:b}=await Promise.resolve().then(()=>(Hs(),Ea));await b(u,m,f),a=f}else if(o==="local"){if(!r){p(e,400,{error:"localPath is required for local import"});return}if(!ys(r)){p(e,400,{error:`Path not found: ${r}`});return}a=r}else{p(e,400,{error:"source must be 'hubspot' or 'local'"});return}let{extractDesignContext:l}=await Promise.resolve().then(()=>(fs(),gs)),c=await l(a);n.brandAssets||(n.brandAssets={}),n.brandAssets.styleguide=c,n.updatedAt=Date.now();let d=Ne(n.themePath,".vibespot");Ie(d),J(Ne(d,"styleguide.md"),c),D(),p(e,200,{ok:!0,styleguide:c,source:a})}catch(o){p(e,500,{error:o instanceof Error?o.message:String(o)})}})()})}var Oy,Xu,Fy,Du,Dy,nm=R(()=>{"use strict";y();ze();de();Q();Jn();we();ne();Oy=process.platform==="win32"?{shell:!0}:{};Xu=[{name:"System Default",stack:"system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",category:"system"},{name:"Inter",stack:"Inter, system-ui, sans-serif",category:"sans-serif"},{name:"DM Sans",stack:"'DM Sans', system-ui, sans-serif",category:"sans-serif"},{name:"Open Sans",stack:"'Open Sans', system-ui, sans-serif",category:"sans-serif"},{name:"Roboto",stack:"Roboto, system-ui, sans-serif",category:"sans-serif"},{name:"Lato",stack:"Lato, system-ui, sans-serif",category:"sans-serif"},{name:"Montserrat",stack:"Montserrat, system-ui, sans-serif",category:"sans-serif"},{name:"Poppins",stack:"Poppins, system-ui, sans-serif",category:"sans-serif"},{name:"Nunito",stack:"Nunito, system-ui, sans-serif",category:"sans-serif"},{name:"Raleway",stack:"Raleway, system-ui, sans-serif",category:"sans-serif"},{name:"Work Sans",stack:"'Work Sans', system-ui, sans-serif",category:"sans-serif"},{name:"Source Sans 3",stack:"'Source Sans 3', system-ui, sans-serif",category:"sans-serif"},{name:"Manrope",stack:"Manrope, system-ui, sans-serif",category:"sans-serif"},{name:"Plus Jakarta Sans",stack:"'Plus Jakarta Sans', system-ui, sans-serif",category:"sans-serif"},{name:"Outfit",stack:"Outfit, system-ui, sans-serif",category:"sans-serif"},{name:"Space Grotesk",stack:"'Space Grotesk', system-ui, sans-serif",category:"sans-serif"},{name:"Albert Sans",stack:"'Albert Sans', system-ui, sans-serif",category:"sans-serif"},{name:"Figtree",stack:"Figtree, system-ui, sans-serif",category:"sans-serif"},{name:"Helvetica",stack:"Helvetica, Arial, sans-serif",category:"sans-serif"},{name:"Arial",stack:"Arial, Helvetica, sans-serif",category:"sans-serif"},{name:"Verdana",stack:"Verdana, Geneva, sans-serif",category:"sans-serif"},{name:"Georgia",stack:"Georgia, 'Times New Roman', serif",category:"serif"},{name:"Playfair Display",stack:"'Playfair Display', Georgia, serif",category:"serif"},{name:"Merriweather",stack:"Merriweather, Georgia, serif",category:"serif"},{name:"Lora",stack:"Lora, Georgia, serif",category:"serif"},{name:"PT Serif",stack:"'PT Serif', Georgia, serif",category:"serif"},{name:"Libre Baskerville",stack:"'Libre Baskerville', Georgia, serif",category:"serif"},{name:"Source Serif 4",stack:"'Source Serif 4', Georgia, serif",category:"serif"},{name:"Cormorant Garamond",stack:"'Cormorant Garamond', Garamond, serif",category:"serif"},{name:"Times New Roman",stack:"'Times New Roman', Times, serif",category:"serif"},{name:"Sora",stack:"Sora, system-ui, sans-serif",category:"display"},{name:"Clash Display",stack:"'Clash Display', system-ui, sans-serif",category:"display"},{name:"Cabinet Grotesk",stack:"'Cabinet Grotesk', system-ui, sans-serif",category:"display"},{name:"Satoshi",stack:"Satoshi, system-ui, sans-serif",category:"display"},{name:"General Sans",stack:"'General Sans', system-ui, sans-serif",category:"display"},{name:"JetBrains Mono",stack:"'JetBrains Mono', 'Fira Code', monospace",category:"monospace"},{name:"Fira Code",stack:"'Fira Code', 'Courier New', monospace",category:"monospace"},{name:"Source Code Pro",stack:"'Source Code Pro', monospace",category:"monospace"},{name:"Courier New",stack:"'Courier New', Courier, monospace",category:"monospace"}];Fy=/#[0-9a-fA-F]{6}\b/g,Du=/font[- ]?famil(?:y|ies)\s*[:=]\s*([^\n]+)/gi;Dy=/^#[0-9a-fA-F]{6}$/});import{join as Ly}from"path";function sm(t,e){let n=C();if(!n){p(e,404,{error:"No active session"});return}p(e,200,{id:n.id,themeName:n.themeName,themePath:n.themePath,messageCount:n.messages.length,moduleCount:n.modules.length,moduleOrder:n.moduleOrder})}function om(t,e,n){let s=C();if(!s){p(n,404,{error:"No active session"});return}if(t==="GET"){let o=Se();p(n,200,{modules:o.map(i=>({moduleName:i.moduleName,fieldsJson:i.fieldsJson,moduleHtml:i.moduleHtml,moduleCss:i.moduleCss,moduleJs:i.moduleJs||null})),sharedCss:s.sharedCss,sharedJs:s.sharedJs});return}if(t==="DELETE"){Ve(e,n,o=>{o.deleteEntirely?wl(o.moduleName):Cl(o.moduleName),D(),p(n,200,{ok:!0})});return}p(n,405,{error:"Method not allowed"})}function im(t,e){let n=C();if(!n){p(e,404,{error:"No active session"});return}W(t,s=>{try{let o=JSON.parse(s);if(o.shared){if(o.shared==="css")n.sharedCss=o.content;else if(o.shared==="js")n.sharedJs=o.content;else{p(e,400,{error:"Invalid shared type"});return}let c=Ce();c&&(o.shared==="css"?c.sharedCss=o.content:c.sharedJs=o.content),n.updatedAt=Date.now(),et(),D(),ke(),p(e,200,{ok:!0});return}let{moduleName:i,fileType:r,content:a}=o;if(!i||!r){p(e,400,{error:"moduleName and fileType required"});return}let l=n.modules.find(c=>c.moduleName===i);if(!l){p(e,404,{error:`Module "${i}" not found`});return}switch(r){case"html":l.moduleHtml=a;break;case"css":l.moduleCss=a;break;case"js":l.moduleJs=a||void 0;break;case"fields":try{JSON.parse(a)}catch{p(e,400,{error:"Invalid JSON in fields.json"});return}l.fieldsJson=a;break;default:p(e,400,{error:`Invalid fileType: ${r}`});return}n.updatedAt=Date.now(),et(),D(),ke(),p(e,200,{ok:!0})}catch(o){p(e,400,{error:String(o)})}})}function rm(t,e){Ve(t,e,n=>{Array.isArray(n.order)?(Rt(n.order),D(),p(e,200,{ok:!0})):p(e,400,{error:"order must be an array"})})}async function am(t){let e=C();if(!e){p(t,404,{error:"No active session"});return}try{ke();let n=Qs(e.themePath),s=No(`hs cms upload "${e.themePath}" "${e.themeName}"`,"Uploading to HubSpot",{cwd:Ly(e.themePath,".."),timeout:18e4});p(t,200,{ok:!0,jobId:s,fixes:n})}catch(n){p(t,500,{error:String(n)})}}function lm(t,e){W(t,n=>{try{let{moduleName:s,fieldPath:o,value:i}=JSON.parse(n);kl(s,o,i),D(),p(e,200,{ok:!0})}catch(s){p(e,400,{error:String(s)})}})}function cm(t,e){W(t,n=>{try{let{url:s}=JSON.parse(n);if(!s||typeof s!="string"){p(e,400,{error:"url is required"});return}let o=$a(s),i=o.components.map(a=>`- ${a.name}: ${a.description}`).join(`
2692
+ `),r={sourceDir:o.sourceDir,componentCount:o.components.length,components:o.components.map(a=>({name:a.name,description:a.description})),hasTailwind:o.hasTailwind,cssVarCount:o.cssVarCount,fonts:o.fonts,interactions:o.interactions,conversionPrompt:`Import and convert the React landing page from ${s} to native HubSpot modules.
1604
2693
 
1605
- `)};try{let c=await Kd(i.fileKey,i.nodeId,o,a,m=>l({type:"progress",message:m})),d=Zd();tu(),qn.set(d,{extraction:c,expires:Date.now()+bh});let u=Yd(c);l({type:"complete",ok:!0,extractionId:d,summary:u})}catch(c){let d=c instanceof Error?c.message:String(c);E.error("figma",`Extraction failed: ${d}`);let u=d;d.includes("403")?u="Cannot access this file. Check sharing permissions and your token.":d.includes("404")?u="Figma file not found. Check the URL.":d.includes("429")&&(u="Figma rate limited. Try again in a minute."),l({type:"complete",ok:!1,error:u})}t.end()})}function Sh(e){let{designTokens:t,fileName:n}=e,s=[`# Styleguide \u2014 ${n}`,""];if(t.colors.length>0){s.push("## Colors","");let o=[...t.colors].sort((a,l)=>l.count-a.count),i=o[0],r=o[1];i&&s.push(`- **Primary:** \`${i.hex}\` (${i.name||"dominant color"})`),r&&s.push(`- **Secondary:** \`${r.hex}\` (${r.name||"accent color"})`),s.push(""),s.push("### Full palette","");for(let a of o.slice(0,15)){let l=a.name?`${a.name}`:`${a.count}\xD7 used`;s.push(`- \`${a.hex}\` \u2014 ${l}`)}s.push("")}if(t.typography.length>0){s.push("## Typography","");let o=[...new Set(t.typography.map(r=>r.fontFamily))];s.push(`**Font families:** ${o.join(", ")}`,""),s.push("| Role | Family | Size | Weight |"),s.push("|------|--------|------|--------|");let i=new Set;for(let r of t.typography){let a=`${r.role}-${r.fontSize}-${r.fontWeight}`;i.has(a)||(i.add(a),s.push(`| ${r.role} | ${r.fontFamily} | ${r.fontSize}px | ${r.fontWeight} |`))}s.push("")}if(t.spacing.length>0){s.push("## Spacing","");let o=[...new Set(t.spacing.map(i=>i.value))].sort((i,r)=>i-r);s.push(`**Scale:** ${o.join("px, ")}px`,"");for(let i of t.spacing)s.push(`- **${i.property}** (${i.context}): ${i.value}px`);s.push("")}if(t.effects.length>0){s.push("## Effects","");for(let o of t.effects)o.boxShadow&&s.push(`- **Box shadow:** \`${o.boxShadow}\``),o.borderRadius&&s.push(`- **Border radius:** ${o.borderRadius}px`);s.push("")}return s.join(`
1606
- `)}function fr(e,t){Oe(e,t,async n=>{let s=n.extractionId,o=n.themeName,i=n.useAssets!==!1;if(!s||!o){p(t,400,{error:"Missing extractionId or themeName"});return}let r=nu(s);if(!r){p(t,400,{error:"Extraction expired or not found. Please re-extract."});return}let a=C();if(!a){p(t,400,{error:"No active session. Create a theme first."});return}t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let l=c=>{t.write(`data: ${JSON.stringify(c)}
2694
+ Source analysis found ${o.components.length} components:
2695
+ ${i}
1607
2696
 
1608
- `)};try{l({type:"progress",message:"Generating styleguide from design tokens..."});let c=Sh(r),d=$o(a.themePath,".vibespot");if(Qd(d)||eu(d,{recursive:!0}),gh($o(d,"styleguide.md"),c),a.brandAssets||(a.brandAssets={}),a.brandAssets.styleguide=c,J(),l({type:"progress",message:"Styleguide saved."}),a.templates.length===0)Hs("landing_page","Landing Page");else{a.modules=[],a.moduleOrder=[],a.sharedCss="",a.sharedJs="";let h=a.templates.find(S=>S.id===a.activeTemplateId);h&&(h.modules=[],h.moduleOrder=[],h.sharedCss="",h.sharedJs="")}if(J(),i&&r.assets.length>0){let h=$o(a.themePath,"assets");eu(h,{recursive:!0});let S=0;for(let x of r.assets)if(Qd(x.localPath)){let w=$o(h,yh(x.localPath));try{hh(x.localPath,w),x.localPath=w,S++}catch{}}S>0&&l({type:"progress",message:`Copied ${S} image assets to theme.`})}l({type:"progress",message:"Starting AI conversion..."});let u=[],m=[],f=await Gn(r,o,h=>{if(h.type==="agent_step")u.push({step:h.step,label:h.label}),l({type:"progress",message:`${h.label}...`});else if(h.type==="agent_decision"){let S=u[u.length-1];S&&(S.decisions||(S.decisions=[]),S.decisions.push(h.decision)),l({type:"progress",message:` ${h.decision}`})}else h.type==="design_system_ready"?Ie({sharedCss:h.sharedCss,sharedJs:h.sharedJs}):h.type==="blueprint_ready"?(Ie({sharedCss:h.sharedCss,sharedJs:h.sharedJs}),wt(h.moduleOrder),l({type:"progress",message:`Planned ${h.moduleOrder.length} modules`})):h.type==="module_progress"&&(h.status==="generating"?l({type:"progress",message:`Generating module: ${h.module}`}):h.status==="complete"&&h.moduleFiles?(Ie({modules:[{moduleName:h.module,fieldsJson:h.moduleFiles.fieldsJson,metaJson:h.moduleFiles.metaJson,moduleHtml:h.moduleFiles.moduleHtml,moduleCss:h.moduleFiles.moduleCss,moduleJs:h.moduleFiles.moduleJs}]}),m.push({name:h.module,status:"complete"}),l({type:"progress",message:`Module complete: ${h.module}`})):h.status==="failed"&&(m.push({name:h.module,status:"failed"}),l({type:"progress",message:`Module failed: ${h.module}`})))},{useAssets:i});Dt(f,{steps:u,modules:m,stats:f.stats}),we(),_t(a.themePath,`Figma import: ${r.fileName}`);let y=ce().map(h=>h.moduleName);l({type:"progress",message:`Conversion complete \u2014 ${y.length} modules generated`}),l({type:"complete",ok:!0,modules:y})}catch(c){let d=c instanceof Error?c.message:String(c);E.error("figma",`Generate failed: ${d}`),l({type:"complete",ok:!1,error:d})}t.end()})}var qn,bh,gr=G(()=>{"use strict";g();Fe();X();re();Xd();me();Mn();Si();Zt();cn();Nt();qn=new Map,bh=1800*1e3});g();g();import{Command as Kh}from"commander";g();g();g();import Ut from"chalk";var Ke={accent:"#FF7A59",accentBright:"#FF9A7A",success:"#00BDA5",info:"#0066FF",warn:"#FFB020",error:"#E23D2D",muted:"#8B8D91",vibes:"#00BDD6"},Er=!!process.env.NO_COLOR;function rt(e){return Er?Ut:Ut.hex(e)}var A={accent:rt(Ke.accent),accentBright:rt(Ke.accentBright),success:rt(Ke.success),info:rt(Ke.info),warn:rt(Ke.warn),error:rt(Ke.error),muted:rt(Ke.muted),vibes:rt(Ke.vibes),heading:Er?Ut.bold:Ut.bold.hex(Ke.accent),command:rt(Ke.accentBright),dim:Ut.dim,bold:Ut.bold};Q();function pe(){let e=A.vibes,t=A.accent,n=A.muted,s=[`${e("\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2584\u2584\u2584\u2584\u2584")}${e(" \u224B\u224B\u224B\u224B\u224B\u224B\u224B\u224B ")}${t("\u2584\u2584\u2584\u2584\u2584 \u2588\u2588\u2588\u2588\u2588 \u2584\u2584\u2584\u2584 \u2580\u2580\u2588\u2588\u2580\u2580")}`,`${e("\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 ")}${e(" \u224B\u224B\u224B\u224B\u224B\u224B ")}${t("\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 ")}`,`${e("\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 ")}${e(" \u224B\u224B\u224B\u224B ")}${t("\u2580\u2580\u2580\u2584 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 ")}`,`${e(" \u2588\u2584\u2584\u2588\u2580 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 ")}${e(" \u224B\u224B\u224B\u224B\u224B\u224B ")}${t(" \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 ")}`,`${e(" \u2580\u2580\u2580 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2580\u2580\u2580\u2580\u2580")}${e(" \u224B\u224B\u224B\u224B\u224B\u224B\u224B\u224B ")}${t("\u2580\u2580\u2580\u2580 \u2588\u2588 \u2580\u2580\u2580\u2580 \u2588\u2588 ")}`];console.log();for(let o of s)console.log(` ${o}`);console.log(),console.log(` ${n("AI-powered HubSpot Landing Pages")} ${A.dim(`v${Vt()}`)}`),console.log()}g();g();Et();X();lt();import{join as cs}from"path";import{homedir as ds}from"os";import{readFileSync as Jr,existsSync as us,readdirSync as Hu}from"fs";var Mt=process.platform==="win32"?"where":"which";function bn(){let e=D("node --version");return{name:"Node.js",found:e.success,version:e.stdout.replace(/^v/,""),path:D(`${Mt} node`).stdout}}function Sn(){let e=D("git --version");return{name:"Git",found:e.success,version:e.stdout.replace("git version ",""),path:D(`${Mt} git`).stdout}}function qe(){let e=D("hs --version");return{name:"HubSpot CLI",found:e.success,version:e.stdout,path:D(`${Mt} hs`).stdout}}function xn(){let e=D("claude --version");if(!e.success)return{name:"Claude Code",found:!1,version:"",path:"",authenticated:!1,authDetail:"Not installed"};let t=cs(ds(),".claude"),n=!1,s="Not signed in \u2014 run `claude` to authenticate";try{if(us(t)){let o=Hu(t);(o.some(r=>r.includes("credentials")||r.includes("auth")||r.includes("token")||r===".credentials.json")||o.length>2)&&(n=!0,s="Authenticated")}}catch{}return{name:"Claude Code",found:!0,version:e.stdout,path:D(`${Mt} claude`).stdout,authenticated:n,authDetail:s}}function vn(e){try{let t=cs(ds(),".hscli","config.yml");if(!us(t))return"na1";let n=Jr(t,"utf-8"),s=n.indexOf(`accountId: ${e}`);if(s===-1)return"na1";let o=n.indexOf("personalAccessKey:",s);if(o===-1)return"na1";let r=n.slice(o,o+300).match(/personalAccessKey:[\s>-]*\n\s+(\S+)/);if(!r)return"na1";if(r[1].startsWith("CiRldTE"))return"eu1"}catch{}return"na1"}function Xe(){let e=D("hs accounts list");if(!e.success||!e.stdout)return{authenticated:!1,portalName:"",portalId:"",accounts:[]};let t=[],n="",s="",o=e.stdout.match(/Account:\s*(.+?)\s*\((\d+)\)/);o&&(n=o[1].trim(),s=o[2].trim());let i=e.stdout.split(`
1609
- `);for(let r of i){let a=r.match(/^\s*(.+?)\s+(\d{5,})\s+(.*)/);if(a&&!/Account ID/i.test(r)&&!/^-+$/.test(r.trim())&&!/^Name\s/i.test(r.trim())){let l=a[1].trim(),c=a[2].trim(),d=a[3]?.trim()||"unknown";t.push({name:l,portalId:c,authType:d,isDefault:c===s})}}return o?{authenticated:!0,portalName:n,portalId:s,accounts:t}:t.length>0?{authenticated:!0,portalName:t[0].name,portalId:t[0].portalId,accounts:t}:{authenticated:e.stdout.length>0,portalName:"",portalId:"",accounts:[]}}function wn(){let e=D("gemini --version");if(!e.success)return{name:"Gemini CLI",found:!1,version:"",path:"",authenticated:!1,authDetail:"Not installed"};let t=cs(ds(),".config","gcloud","application_default_credentials.json"),n=us(t),s=!!(process.env.GEMINI_API_KEY||process.env.GOOGLE_API_KEY||process.env.GOOGLE_AI_API_KEY),o=n||s;return{name:"Gemini CLI",found:!0,version:e.stdout,path:D(`${Mt} gemini`).stdout,authenticated:o,authDetail:o?"Authenticated":"Run `gemini` to sign in with Google"}}function Cn(){let e=D("codex --version");if(!e.success)return{name:"OpenAI Codex CLI",found:!1,version:"",path:"",authenticated:!1,authDetail:"Not installed"};let t=!!process.env.OPENAI_API_KEY,n=!1;try{let i=cs(ds(),".codex","auth.json");us(i)&&(n=Jr(i,"utf-8").length>10)}catch{}let s=t||n,o=n?"Authenticated (OAuth)":t?"Authenticated (API key)":"Not authenticated";return{name:"OpenAI Codex CLI",found:!0,version:e.stdout,path:D(`${Mt} codex`).stdout,authenticated:s,authDetail:o}}function Wo(){let e=D("gh --version");return{name:"GitHub CLI",found:e.success,version:e.stdout.split(`
1610
- `)[0]?.replace("gh version ","").split(" ")[0]||"",path:D(`${Mt} gh`).stdout}}function Vo(){let e=D("gh auth status 2>&1");if(!e.success&&!e.stdout)return{authenticated:!1,username:""};let t=e.stdout||e.stderr||"",n=t.match(/Logged in to github\.com.*account\s+(\S+)/);if(n)return{authenticated:!0,username:n[1]};let s=t.match(/account\s+(\S+)/);return s&&t.includes("Logged in")?{authenticated:!0,username:s[1]}:{authenticated:t.includes("Logged in"),username:""}}function Lr(){return!!process.env.ANTHROPIC_API_KEY}function ms(e){return parseInt(e.split(".")[0],10)>=18}function Hr(e){let t=parseInt(e.split(".")[0],10);return!isNaN(t)&&t>=8}function Bu(){let e=R(),t=e.hubspotUploadMode||"api",n=e.hubspotAccounts||[],s=n.map(i=>({name:i.portalName,portalId:i.portalId,authType:"personalaccesskey",isDefault:i.portalId===(e.activeHubSpotAccount||n[0]?.portalId)})),o=xt();return{authenticated:!!o,portalName:o?.portalName||"",portalId:o?.portalId||"",dataCenter:o?o.dataCenter:"na1",accounts:s,uploadMode:t}}var Go={name:"",found:!1,version:"",path:"",authenticated:!1,authDetail:"Disabled"};function ps(){let e=R(),t=bn(),n=Sn(),s=e.hubspotUploadMode||"api",o;if(s==="cli"){let x=qe(),w=x.found?Xe():{authenticated:!1,portalName:"",portalId:"",accounts:[]},v=w.portalId?vn(w.portalId):"na1";o={...x,...w,dataCenter:v,uploadMode:"cli"}}else o={name:"HubSpot API",found:!0,version:"v3",path:"",...Bu()};let i=Wo(),r=i.found?Vo():{authenticated:!1,username:""},a={authenticated:Ye(),expiresAt:yn()?.expiresAt},l=e.enabledCLITools||[],c=gn("claude-code")?xn():{...Go,name:"Claude Code"},d=gn("gemini-cli")?wn():{...Go,name:"Gemini CLI"},u=gn("codex-cli")?Cn():{...Go,name:"OpenAI Codex CLI"};function m(x,...w){if(x)return{configured:!0,masked:is(x),source:"config"};for(let v of w)if(process.env[v])return{configured:!0,masked:is(process.env[v]),source:"env"};return{configured:!1,masked:"",source:null}}let f=m(e.anthropicApiKey,"ANTHROPIC_API_KEY"),y=m(e.openaiApiKey,"OPENAI_API_KEY"),h=m(e.geminiApiKey,"GEMINI_API_KEY","GOOGLE_AI_API_KEY"),S=[];return c.found&&c.authenticated&&S.push("claude-code"),a.authenticated&&S.push("claude-oauth"),f.configured&&S.push("anthropic-api"),y.configured&&S.push("openai-api"),d.found&&d.authenticated&&S.push("gemini-cli"),h.configured&&S.push("gemini-api"),u.found&&u.authenticated&&S.push("codex-cli"),{tools:{node:t,git:n,hubspot:o,github:{...i,...r},claudeCode:c,claudeOAuth:a,geminiCli:d,codexCli:u},apiKeys:{anthropic:f,openai:y,gemini:h},activeEngine:e.aiEngine||null,availableEngines:S,enabledCLITools:l}}lt();Et();X();Rt();g();import*as ee from"@clack/prompts";function Ko(e){ee.isCancel(e)&&(ee.cancel(A.muted("Operation cancelled.")),process.exit(0))}async function se(e){ee.intro(A.heading(e))}async function oe(e){ee.outro(A.success(e))}async function Ze(e,t){ee.note(e,t?A.heading(t):void 0)}async function le(e){let t=await ee.text({message:A.accent(e.message),placeholder:e.placeholder,defaultValue:e.defaultValue,validate:e.validate});return Ko(t),t}async function fe(e){let t=await ee.confirm({message:A.accent(e.message),initialValue:e.initialValue??!0});return Ko(t),t}async function dt(e){let t=await ee.select({message:A.accent(e.message),options:e.options});return Ko(t),t}async function Ce(){let e=ee.spinner();return{start:t=>e.start(A.muted(t)),stop:t=>e.stop(A.success(t)),message:t=>e.message(A.muted(t))}}function P(e){ee.log.info(e)}function H(e){ee.log.success(A.success(e))}function Z(e){ee.log.warn(A.warn(e))}function z(e){ee.log.error(A.error(e))}async function ys(){await se("Checking your environment");let e=bn();e.found||(z("Node.js not found. Install it from https://nodejs.org"),process.exit(1)),ms(e.version)||(z(`Node.js ${e.version} is too old. Version 18+ required. Update at https://nodejs.org`),process.exit(1)),H(`Node.js v${e.version}`);let t=Sn();t.found||(z("Git not found. Install it from https://git-scm.com"),process.exit(1)),H(`Git ${t.version}`);let n=R(),s=n.hubspotUploadMode!=="cli",o="",i="";if(s){let S=$e(),x=xt();if(S)o=x?.portalId||"",i=x?.portalName||"",H(`HubSpot${i?`: ${i}`:""}${o?` (${o})`:""} \u2014 API mode`);else{Z("No HubSpot account connected"),await Ze(`You need a Personal Access Key to deploy themes.
2697
+ Design system: ${o.hasTailwind?"Tailwind CSS":"Custom CSS"}, ${o.cssVarCount} CSS variables
2698
+ Fonts: ${o.fonts.length>0?o.fonts.join(", "):"System fonts"}
2699
+ Interactions: ${o.interactions.join(", ")}
2700
+
2701
+ Read the React source files from ${o.sourceDir} and convert each component to a HubSpot module. Preserve the design, layout, colors, and content. Generate fields.json so marketers can edit all text, images, colors, and links in the HubSpot page editor.`};p(e,200,r)}catch(s){p(e,500,{error:s instanceof Error?s.message:String(s)})}})}function dm(t,e){let n=C();if(!n){p(e,404,{error:"No active session"});return}if(!Qe()){p(e,200,{available:!1,commits:[]});return}let o=new URL(t.url||"/","http://localhost").searchParams.get("templateId"),i=o?hl(n.themePath,o,50):fl(n.themePath,50);p(e,200,{available:!0,commits:i,filtered:!!o})}function um(t,e){W(t,n=>{try{let s=C();if(!s){p(e,404,{error:"No active session"});return}let{hash:o,templateId:i}=JSON.parse(n);if(!o||typeof o!="string"){p(e,400,{error:"Commit hash is required"});return}if(tt("assistant",`Rolled back to version ${o.slice(0,7)}.`),i){let r=s.templates.find(c=>c.id===i);if(!r){p(e,404,{error:"Template not found"});return}let a=r.moduleOrder.map(c=>`modules/${c}.module`);r.templateFile&&a.push(r.templateFile);let l=bl(s.themePath,i,o,a);if(!l.success){p(e,500,{error:l.error||"Rollback failed"});return}zl()}else{let r=yl(s.themePath,o);if(!r.success){p(e,500,{error:r.error||"Rollback failed"});return}Vl()}D(),p(e,200,{ok:!0,modules:Se().map(r=>r.moduleName)})}catch(s){p(e,500,{error:s instanceof Error?s.message:String(s)})}})}var mm=R(()=>{"use strict";y();ze();we();eo();Oo();Bs();dn()});import{writeFileSync as Jy,mkdirSync as gm}from"fs";import{join as Vo}from"path";import{randomUUID as By}from"crypto";function fm(t){let e=t.match(Hy);if(!e)return null;let n=e[1],s=e[2]?decodeURIComponent(e[2].replace(/-/g," ")):void 0,o;try{let r=new URL(t).searchParams.get("node-id");r&&(o=r.replace(/-/g,":"))}catch{}return{fileKey:n,nodeId:o,fileName:s}}async function Yo(t,e){let n=await fetch(`${Uy}${t}`,{headers:{"X-Figma-Token":e}});if(!n.ok){let s=await n.text().catch(()=>""),o=new Error(`Figma API ${n.status}: ${s.slice(0,200)}`);throw o.status=n.status,o}return n.json()}async function Jr(t,e){for(let n=0;;n++)try{return await t()}catch(s){if(!(s.status===429)||n>=pm.length)throw s;let r=pm[n];E.warn("figma",`Rate limited (429), attempt ${n+1} \u2014 waiting ${r}s`),e&&e(`Figma rate limited \u2014 retrying in ${r}s...`),await new Promise(a=>setTimeout(a,r*1e3))}}function Qt(t,e,n=0){if(e(t,n),t.children)for(let s of t.children)Qt(s,e,n+1)}function hm(t,e){if(t.id===e)return t;if(t.children)for(let n of t.children){let s=hm(n,e);if(s)return s}return null}function Gy(t,e){if(e){let s=hm(t,e);if(!s)return[];if(s.type==="FRAME"||s.type==="COMPONENT"||s.type==="COMPONENT_SET"){let o=(s.children||[]).filter(i=>Lr.has(i.type));return o.length>0?o:[s]}return s.children?s.children.filter(o=>Lr.has(o.type)):[]}let n=t.children?.[0];return n?.children?n.children.filter(s=>Lr.has(s.type)):[]}function zo(t){let e=Math.round(t.r*255),n=Math.round(t.g*255),s=Math.round(t.b*255);return`#${e.toString(16).padStart(2,"0")}${n.toString(16).padStart(2,"0")}${s.toString(16).padStart(2,"0")}`}function Wy(t){let e=new Map;for(let n of t)Qt(n,s=>{if(s.fills){for(let o of s.fills)if(o.type==="SOLID"&&o.color){let i=zo(o.color),r=e.get(i),a=s.type==="TEXT",l=a?"text":"fill";r?(r.occurrences++,a&&r.usage!=="text"&&(r.usage="text")):e.set(i,{hex:i,opacity:o.opacity??o.color.a,occurrences:1,usage:l})}}if(s.strokes){for(let o of s.strokes)if(o.type==="SOLID"&&o.color){let i=zo(o.color),r=e.get(i);r?r.occurrences++:e.set(i,{hex:i,opacity:1,occurrences:1,usage:"border"})}}});return[...e.values()].sort((n,s)=>s.occurrences-n.occurrences)}function Ky(t){let e=new Map;for(let n of t)Qt(n,s=>{if(s.type!=="TEXT"||!s.style)return;let o=s.style,i=o.fontSize||16,r=o.fontWeight||400,a=o.lineHeightPx?Math.round(o.lineHeightPx/i*100)/100:1.5,l=o.letterSpacing||0,c=o.fontFamily||"sans-serif",d="body";i>=32?d="heading":i>=20?d="subheading":i<=12?d="caption":r>=600&&i<=14&&(d="label");let u=`${c}-${i}-${r}`,m=e.get(u);m?m.occurrences++:e.set(u,{fontFamily:c,fontSize:i,fontWeight:r,lineHeight:a,letterSpacing:l,role:d,occurrences:1})});return[...e.values()].sort((n,s)=>s.fontSize-n.fontSize)}function Vy(t){let e=[],n=new Set;for(let s of t)Qt(s,o=>{if(!o.layoutMode||o.layoutMode==="NONE")return;if(o.itemSpacing&&o.itemSpacing>0){let c=`gap-${o.itemSpacing}-${o.name}`;n.has(c)||(n.add(c),e.push({context:`${o.name} gap`,value:o.itemSpacing,type:"gap"}))}let i=o.paddingTop||0,r=o.paddingRight||0,a=o.paddingBottom||0,l=o.paddingLeft||0;if(i>0||r>0||a>0||l>0){let c=`pad-${i}-${r}-${a}-${l}-${o.name}`;if(!n.has(c)){n.add(c);let d=i===a&&l===r&&i===l?i:Math.max(i,r,a,l);e.push({context:`${o.name} padding`,value:d,type:"padding"})}}});return e}function zy(t){let e=[],n=new Set;for(let s of t)Qt(s,o=>{if(o.effects){for(let i of o.effects)if(i.type==="DROP_SHADOW"&&i.color&&i.offset){let{r,g:a,b:l,a:c}=i.color,d=`${i.offset.x}px ${i.offset.y}px ${i.radius||0}px rgba(${Math.round(r*255)},${Math.round(a*255)},${Math.round(l*255)},${Math.round(c*100)/100})`;n.has(d)||(n.add(d),e.push({type:"shadow",cssValue:d,context:o.name}))}}if(o.cornerRadius&&o.cornerRadius>0){let i=`${o.cornerRadius}px`;n.has(`radius-${i}`)||(n.add(`radius-${i}`),e.push({type:"radius",cssValue:i,context:o.name}))}});return e}function Yy(t,e){let n=[];return Qt(t,s=>{if(s.type!=="TEXT"||!s.characters?.trim())return;let o=s.style?.fontSize||16,i=s.style?.fontWeight||400,r="body";o>=32?r="headline":o>=20?r="subheadline":o<=12?r="caption":i>=600&&o<=16&&(r="label"),i>=600&&s.characters.length<40&&o>=14&&o<32&&(r="cta"),n.push({text:s.characters,fontSize:o,fontWeight:i,role:r,sectionName:e})}),n}function qy(t){let e=t.absoluteBoundingBox;return{name:t.name,type:t.type,nodeId:t.id,width:e?.width||0,height:e?.height||0,layoutMode:t.layoutMode==="NONE"?void 0:t.layoutMode,childCount:t.children?.length||0,characters:t.type==="TEXT"?t.characters:void 0}}function Xy(t){if(t.fills){for(let e of t.fills)if(e.type==="SOLID"&&e.color)return zo(e.color)}if(t.backgroundColor)return zo(t.backgroundColor)}function Zy(t){return t.map(e=>{let n=e.absoluteBoundingBox;return{name:e.name,nodeId:e.id,width:n?.width||0,height:n?.height||0,textContent:Yy(e,e.name),children:(e.children||[]).slice(0,20).map(qy),backgroundColor:Xy(e),layoutMode:e.layoutMode==="NONE"?void 0:e.layoutMode,itemSpacing:e.itemSpacing,paddingTop:e.paddingTop,paddingRight:e.paddingRight,paddingBottom:e.paddingBottom,paddingLeft:e.paddingLeft}})}function Qy(t){let e=[];for(let n of t)Qt(n,s=>{if(s.fills){for(let o of s.fills)if(o.type==="IMAGE"&&o.imageRef){e.push({nodeId:s.id,name:s.name||"image"});break}}});return e}async function ym(t,e){let n=await fetch(t);if(!n.ok)throw new Error(`Failed to download image: ${n.status}`);let s=Buffer.from(await n.arrayBuffer());Jy(e,s)}async function eb(t,e,n,s,o){if(e.length===0)return new Map;gm(s,{recursive:!0});let r=e.map(c=>c.id).join(",");o&&o("Exporting frame screenshots...");let a=await Jr(()=>Yo(`/v1/images/${t}?ids=${r}&format=png&scale=2`,n),o),l=new Map;for(let[c,d]of Object.entries(a.images)){if(!d)continue;let u=c.replace(/:/g,"-"),m=Vo(s,`frame-${u}.png`);try{await ym(d,m),l.set(c,m),E.info("figma",`Downloaded frame screenshot: ${m}`)}catch(g){E.warn("figma",`Failed to download frame ${c}: ${g}`)}}return l}async function tb(t,e,n,s,o){if(e.length===0)return[];gm(s,{recursive:!0});let i=50,r=[];for(let a=0;a<e.length;a+=i){let l=e.slice(a,a+i),c=l.map(u=>u.nodeId).join(",");o&&o(`Exporting images (${a+1}-${Math.min(a+i,e.length)} of ${e.length})...`);let d=await Jr(()=>Yo(`/v1/images/${t}?ids=${c}&format=png&scale=2`,n),o);for(let u of l){let m=d.images[u.nodeId];if(!m)continue;let h=`${u.name.replace(/[^a-zA-Z0-9-_]/g,"-").toLowerCase()}-${By().slice(0,6)}.png`,f=Vo(s,h);try{await ym(m,f),r.push({name:u.name,localPath:f,nodeId:u.nodeId,format:"png"}),E.info("figma",`Downloaded asset: ${h}`)}catch(b){E.warn("figma",`Failed to download image ${u.name}: ${b}`)}}}return r}async function bm(t,e,n,s,o){o&&o("Fetching Figma file...");let i=e?`/v1/files/${t}?ids=${e}&geometry=paths`:`/v1/files/${t}?geometry=paths`,r=await Jr(()=>Yo(i,n),o);E.info("figma",`Fetched file: ${r.name}`);let a=Gy(r.document,e);if(a.length===0)throw new Error("No frames found in the Figma file. The file may be empty or structured differently.");E.info("figma",`Found ${a.length} top-level frames`),o&&o(`Found ${a.length} sections. Extracting design tokens...`);let l={colors:Wy(a),typography:Ky(a),spacing:Vy(a),effects:zy(a)};E.info("figma","Design tokens extracted",{colors:l.colors.length,typography:l.typography.length,spacing:l.spacing.length,effects:l.effects.length}),o&&o("Mapping page structure...");let c=Zy(a),d=Vo(s,".vibespot","figma-frames"),u=await eb(t,a,n,d,o),m=c.map(b=>({...b,frameImagePath:u.get(b.nodeId)||""}));o&&o("Extracting image assets...");let g=Qy(a),h=Vo(s,"assets"),f=await tb(t,g,n,h,o);return E.info("figma",`Extraction complete: ${m.length} sections, ${f.length} assets`),{fileName:r.name,fileUrl:`https://www.figma.com/design/${t}`,designTokens:l,sections:m,assets:f}}function Sm(t){let e=t.fileName.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"").slice(0,30);return{fileName:t.fileName,fileUrl:t.fileUrl,sectionNames:t.sections.map(n=>n.name),sectionCount:t.sections.length,colorPalette:t.designTokens.colors.slice(0,10).map(n=>n.hex),fontFamilies:[...new Set(t.designTokens.typography.map(n=>n.fontFamily))],textBlockCount:t.sections.reduce((n,s)=>n+s.textContent.length,0),assetCount:t.assets.length,suggestedThemeName:e}}async function xm(t){return await Yo("/v1/me",t)}var Hy,Uy,pm,Lr,vm=R(()=>{"use strict";y();de();Hy=/figma\.com\/(?:design|file|proto)\/([a-zA-Z0-9]+)(?:\/([^?]*))?/;Uy="https://api.figma.com",pm=[10,20,40,60,120];Lr=new Set(["FRAME","COMPONENT","COMPONENT_SET","SECTION"])});var $m={};Be($m,{getCachedExtraction:()=>Am,handleFigmaExtractRoute:()=>Hr,handleFigmaGenerateRoute:()=>Ur,handleFigmaTestTokenRoute:()=>Br});import{randomUUID as wm}from"crypto";import{existsSync as Cm,mkdirSync as km,writeFileSync as nb,copyFileSync as sb}from"fs";import{join as qo,basename as ob}from"path";function Tm(){let t=Date.now();for(let[e,n]of bs)n.expires<t&&bs.delete(e)}function Am(t){Tm();let e=bs.get(t);return e?(bs.delete(t),e.extraction):null}function Br(t,e){Ve(t,e,async n=>{let s=n.token||O().figmaToken;if(!s){p(e,400,{ok:!1,error:"No Figma token provided"});return}try{let o=await xm(s);p(e,200,{ok:!0,user:o})}catch(o){let i=o instanceof Error?o.message:String(o);E.warn("figma",`Token test failed: ${i}`),p(e,200,{ok:!1,error:"Invalid or expired Figma token"})}})}function Hr(t,e){Ve(t,e,async n=>{let s=n.url;if(!s){p(e,400,{error:"Missing 'url' field"});return}let o=n.token||O().figmaToken;if(!o){p(e,400,{error:"No Figma token configured. Add one in Settings."});return}let i=fm(s);if(!i){p(e,400,{error:"Not a valid Figma URL. Expected: figma.com/design/<key>/..."});return}let a=C()?.themePath||`/tmp/vibespot-figma-${wm().slice(0,8)}`;e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let l=c=>{e.write(`data: ${JSON.stringify(c)}
2702
+
2703
+ `)};try{let c=await bm(i.fileKey,i.nodeId,o,a,m=>l({type:"progress",message:m})),d=wm();Tm(),bs.set(d,{extraction:c,expires:Date.now()+ib});let u=Sm(c);l({type:"complete",ok:!0,extractionId:d,summary:u})}catch(c){let d=c instanceof Error?c.message:String(c);E.error("figma",`Extraction failed: ${d}`);let u=d;d.includes("403")?u="Cannot access this file. Check sharing permissions and your token.":d.includes("404")?u="Figma file not found. Check the URL.":d.includes("429")&&(u="Figma rate limited. Try again in a minute."),l({type:"complete",ok:!1,error:u})}e.end()})}function rb(t){let{designTokens:e,fileName:n}=t,s=[`# Styleguide \u2014 ${n}`,""];if(e.colors.length>0){s.push("## Colors","");let o=[...e.colors].sort((a,l)=>l.count-a.count),i=o[0],r=o[1];i&&s.push(`- **Primary:** \`${i.hex}\` (${i.name||"dominant color"})`),r&&s.push(`- **Secondary:** \`${r.hex}\` (${r.name||"accent color"})`),s.push(""),s.push("### Full palette","");for(let a of o.slice(0,15)){let l=a.name?`${a.name}`:`${a.count}\xD7 used`;s.push(`- \`${a.hex}\` \u2014 ${l}`)}s.push("")}if(e.typography.length>0){s.push("## Typography","");let o=[...new Set(e.typography.map(r=>r.fontFamily))];s.push(`**Font families:** ${o.join(", ")}`,""),s.push("| Role | Family | Size | Weight |"),s.push("|------|--------|------|--------|");let i=new Set;for(let r of e.typography){let a=`${r.role}-${r.fontSize}-${r.fontWeight}`;i.has(a)||(i.add(a),s.push(`| ${r.role} | ${r.fontFamily} | ${r.fontSize}px | ${r.fontWeight} |`))}s.push("")}if(e.spacing.length>0){s.push("## Spacing","");let o=[...new Set(e.spacing.map(i=>i.value))].sort((i,r)=>i-r);s.push(`**Scale:** ${o.join("px, ")}px`,"");for(let i of e.spacing)s.push(`- **${i.property}** (${i.context}): ${i.value}px`);s.push("")}if(e.effects.length>0){s.push("## Effects","");for(let o of e.effects)o.boxShadow&&s.push(`- **Box shadow:** \`${o.boxShadow}\``),o.borderRadius&&s.push(`- **Border radius:** ${o.borderRadius}px`);s.push("")}return s.join(`
2704
+ `)}function Ur(t,e){Ve(t,e,async n=>{let s=n.extractionId,o=n.themeName,i=n.useAssets!==!1;if(!s||!o){p(e,400,{error:"Missing extractionId or themeName"});return}let r=Am(s);if(!r){p(e,400,{error:"Extraction expired or not found. Please re-extract."});return}let a=C();if(!a){p(e,400,{error:"No active session. Create a theme first."});return}e.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"});let l=c=>{e.write(`data: ${JSON.stringify(c)}
2705
+
2706
+ `)};try{l({type:"progress",message:"Generating styleguide from design tokens..."});let c=rb(r),d=qo(a.themePath,".vibespot");if(Cm(d)||km(d,{recursive:!0}),nb(qo(d,"styleguide.md"),c),a.brandAssets||(a.brandAssets={}),a.brandAssets.styleguide=c,D(),l({type:"progress",message:"Styleguide saved."}),a.templates.length===0)Tt("landing_page","Landing Page");else{a.modules=[],a.moduleOrder=[],a.sharedCss="",a.sharedJs="";let f=a.templates.find(b=>b.id===a.activeTemplateId);f&&(f.modules=[],f.moduleOrder=[],f.sharedCss="",f.sharedJs="")}if(D(),i&&r.assets.length>0){let f=qo(a.themePath,"assets");km(f,{recursive:!0});let b=0;for(let S of r.assets)if(Cm(S.localPath)){let x=qo(f,ob(S.localPath));try{sb(S.localPath,x),S.localPath=x,b++}catch{}}b>0&&l({type:"progress",message:`Copied ${b} image assets to theme.`})}l({type:"progress",message:"Starting AI conversion..."});let u=[],m=[],g=await us(r,o,f=>{if(f.type==="agent_step")u.push({step:f.step,label:f.label}),l({type:"progress",message:`${f.label}...`});else if(f.type==="agent_decision"){let b=u[u.length-1];b&&(b.decisions||(b.decisions=[]),b.decisions.push(f.decision)),l({type:"progress",message:` ${f.decision}`})}else f.type==="design_system_ready"?De({sharedCss:f.sharedCss,sharedJs:f.sharedJs}):f.type==="blueprint_ready"?(De({sharedCss:f.sharedCss,sharedJs:f.sharedJs}),Rt(f.moduleOrder),l({type:"progress",message:`Planned ${f.moduleOrder.length} modules`})):f.type==="module_progress"&&(f.status==="generating"?l({type:"progress",message:`Generating module: ${f.module}`}):f.status==="complete"&&f.moduleFiles?(De({modules:[{moduleName:f.module,fieldsJson:f.moduleFiles.fieldsJson,metaJson:f.moduleFiles.metaJson,moduleHtml:f.moduleFiles.moduleHtml,moduleCss:f.moduleFiles.moduleCss,moduleJs:f.moduleFiles.moduleJs}]}),m.push({name:f.module,status:"complete"}),l({type:"progress",message:`Module complete: ${f.module}`})):f.status==="failed"&&(m.push({name:f.module,status:"failed"}),l({type:"progress",message:`Module failed: ${f.module}`})))},{useAssets:i});qt(g,{steps:u,modules:m,stats:g.stats}),ke(),Gt(a.themePath,`Figma import: ${r.fileName}`);let h=Se().map(f=>f.moduleName);l({type:"progress",message:`Conversion complete \u2014 ${h.length} modules generated`}),l({type:"complete",ok:!0,modules:h})}catch(c){let d=c instanceof Error?c.message:String(c);E.error("figma",`Generate failed: ${d}`),l({type:"complete",ok:!1,error:d})}e.end()})}var bs,ib,Gr=R(()=>{"use strict";y();ze();Q();de();vm();we();Wn();Ui();dn();wn();Nt();bs=new Map,ib=1800*1e3});import{readdirSync as Vr,statSync as ab}from"fs";import{join as q,relative as lb}from"path";function Tn(t){let e=q(t,_t);if(!v(e))return null;try{return JSON.parse(M(e))}catch{return null}}function Zo(t,e){let n=q(t,_t);J(n,JSON.stringify(e,null,2)+`
2707
+ `)}function Ss(t){let e=[];if(!v(t))return e.push({severity:"error",rule:"theme.path.missing",message:`Theme directory not found: ${t}`}),Wr(t,e,null);let n=Kr(q(t,"theme.json"));if(!n)return e.push({severity:"error",rule:"theme.json.missing",file:"theme.json",message:"theme.json is missing or invalid JSON",fix:"Recreate the theme so theme.json is generated, or restore it from version control."}),Wr(t,e,Tn(t));ub(t,n,e),mb(t,n,e),pb(t,e),fb(t,e),hb(t,e),yb(t,e);let s=Tn(t);return bb(s,e),Wr(t,e,s)}function Wr(t,e,n){let s=e.filter(r=>r.severity==="error").length,o=e.filter(r=>r.severity==="warning").length,i=e.filter(r=>r.severity==="info").length;return{themePath:t,passed:s===0,errorCount:s,warningCount:o,infoCount:i,findings:e,metadata:n}}function ub(t,e,n){let s={documentation_url:'Add a "documentation_url" entry pointing to public docs for the theme.',license:'Add a "license" entry \u2014 an SPDX identifier or URL (e.g. "MIT").',example_url:'Add an "example_url" entry pointing to a public live preview of the theme.'};for(let r of cb)yt(e,r)||n.push({severity:"error",rule:`theme.json.${r}.missing`,file:"theme.json",message:`theme.json is missing required field "${r}"`,fix:s[r]??`Add a "${r}" entry to theme.json.`});for(let r of db)(!(r in e)||typeof e[r]!="boolean")&&n.push({severity:"error",rule:`theme.json.${r}.missing`,file:"theme.json",message:`theme.json must declare boolean "${r}"`,fix:`Add "${r}": true (or false) to theme.json.`});let o=e.author;!o||typeof o!="object"?n.push({severity:"error",rule:"theme.json.author.missing",file:"theme.json",message:'theme.json is missing required "author" block',fix:'Add { "author": { "name": "...", "email": "...", "url": "..." } } to theme.json.'}):(yt(o,"name")||n.push({severity:"error",rule:"theme.json.author.name.missing",file:"theme.json",message:"theme.json author.name is missing",fix:"Provide a publisher name in theme.json author.name."}),yt(o,"email")||n.push({severity:"error",rule:"theme.json.author.email.missing",file:"theme.json",message:"theme.json author.email is missing",fix:"Provide a contact email in theme.json author.email."}),yt(o,"url")||n.push({severity:"error",rule:"theme.json.author.url.missing",file:"theme.json",message:"theme.json author.url is missing",fix:"Add a public URL for the publisher (homepage or support page)."}));let i=e.preview_path;if(typeof i=="string"&&i.length>0){let r=Im(t,i);v(r)||n.push({severity:"error",rule:"theme.json.preview_path.invalid",file:"theme.json",message:`preview_path "${i}" does not point to an existing file`,fix:"Update preview_path to a real template, e.g. ./templates/home.html."})}}function mb(t,e,n){let s=e.screenshot_path;if(typeof s!="string"||s.length===0)return;let o=Im(t,s);if(!v(o)){n.push({severity:"error",rule:"theme.json.screenshot.missing",file:"theme.json",message:`Screenshot not found at ${s}`,fix:"Place a 1500\xD71000 PNG at the screenshot_path declared in theme.json."});return}/\.(png|jpg|jpeg)$/i.test(s)||n.push({severity:"warning",rule:"theme.json.screenshot.format",file:s,message:"Screenshot should be a PNG or JPG",fix:"Re-export the screenshot as PNG (1500\xD71000) or JPG."})}function pb(t,e){let n=q(t,"modules");if(!v(n)){e.push({severity:"warning",rule:"modules.empty",message:"Theme has no modules/ directory",fix:"Generate at least one module before submitting to Marketplace."});return}let s=0,o=[];try{o=Vr(n)}catch{return}for(let i of o){if(!i.endsWith(".module"))continue;s++;let r=q(n,i);gb(t,r,i,e)}s===0&&e.push({severity:"warning",rule:"modules.empty",message:"Theme has no .module directories",fix:"Generate at least one module before submitting to Marketplace."})}function gb(t,e,n,s){let o=Kr(q(e,"meta.json")),i=ot(t,q(e,"meta.json"));o?(yt(o,"label")||s.push({severity:"error",rule:"module.meta.label.missing",file:i,message:`${n}: meta.json is missing "label"`,fix:`Add a "label" entry to the module's meta.json.`,autoFixable:!0}),o.is_available_for_new_content===!1&&s.push({severity:"info",rule:"module.meta.unavailable",file:i,message:`${n}: is_available_for_new_content=false (won\u2019t be selectable in HubSpot UI)`})):s.push({severity:"error",rule:"module.meta.missing",file:i,message:`${n}: meta.json is missing or invalid`,fix:"Recreate the module so meta.json is generated."});let r=q(e,"fields.json"),a=ot(t,r);if(!v(r))s.push({severity:"warning",rule:"module.fields.missing",file:a,message:`${n}: fields.json is missing`,fix:"Add a fields.json (an empty array [] is acceptable for static modules)."});else{let c=Kr(r);Array.isArray(c)?Mm(c,n,a,s):s.push({severity:"warning",rule:"module.fields.invalid",file:a,message:`${n}: fields.json is not a JSON array`})}let l=q(e,"module.html");v(l)||s.push({severity:"error",rule:"module.html.missing",file:ot(t,l),message:`${n}: module.html is missing`,fix:"Recreate the module so module.html is generated."})}function Mm(t,e,n,s){for(let o of t){if(typeof o!="object"||o===null)continue;let i=o,r=typeof i.name=="string"?i.name:"(unnamed)";yt(i,"label")||s.push({severity:"error",rule:"module.field.label.missing",file:n,message:`${e}.${r}: field is missing "label"`,fix:`Add a human-readable "label" to the "${r}" field in fields.json.`,autoFixable:!0}),!yt(i,"help_text")&&i.type!=="group"&&s.push({severity:"info",rule:"module.field.help_text.missing",file:n,message:`${e}.${r}: consider adding "help_text"`,fix:`Add a short "help_text" describing what "${r}" controls.`}),Array.isArray(i.children)&&Mm(i.children,e,n,s)}}function fb(t,e){let n=[],s=q(t,"css");Xo(s,".css").forEach(i=>{_m(i,n,t)});let o=q(t,"modules");if(v(o))for(let i of xs(o)){if(!i.endsWith(".module"))continue;let r=q(o,i);["module.css","module.html"].forEach(a=>{let l=q(r,a);v(l)&&_m(l,n,t)})}for(let i of n)e.push({severity:"error",rule:"asset.cdn-import",file:i.file,message:`External CDN reference found: ${i.match}`,fix:"Remove external @import / <link> URLs and bundle the asset locally.",autoFixable:!0})}function _m(t,e,n){let s;try{s=M(t)}catch{return}let o=s.match(/@import\s+url\(['"]?https?:\/\/[^)\s'"]+['"]?\)/i);o&&e.push({file:ot(n,t),match:o[0]});let i=s.match(/<link[^>]+href=['"]https?:\/\/[^'"]+['"][^>]*>/i);i&&e.push({file:ot(n,t),match:i[0]});let r=s.match(/<script[^>]+src=['"]https?:\/\/[^'"]+['"][^>]*>/i);r&&e.push({file:ot(n,t),match:r[0]})}function hb(t,e){let n=[{rule:"asset.hardcoded.hubfs",re:/https?:\/\/[\w.-]*hubfs[\w.-]*\/(\d+)\//i,message:"Hardcoded portal-specific HubFS URL detected"},{rule:"asset.hardcoded.usercontent",re:/hubspotusercontent[-\w]*\.net\/(\w+\/)?(\d+)\//i,message:"Hardcoded portal-specific HubSpot user-content URL detected"},{rule:"asset.hardcoded.preview",re:/\d+\.hs-sites\.com|hubspotpagebuilder\.com\/\d+/i,message:"Hardcoded portal preview URL detected"}],s=[],o=q(t,"css");Xo(o,".css").forEach(a=>s.push(a));let i=q(t,"js");Xo(i,".js").forEach(a=>s.push(a));let r=q(t,"modules");if(v(r))for(let a of xs(r))a.endsWith(".module")&&["module.html","module.css","module.js"].forEach(l=>{let c=q(r,a,l);v(c)&&s.push(c)});for(let a of s){let l;try{l=M(a)}catch{continue}for(let c of n){let d=l.match(c.re);d&&e.push({severity:"error",rule:c.rule,file:ot(t,a),message:`${c.message}: ${d[0]}`,fix:"Replace portal-specific URLs with theme-relative paths or HubSpot tokens like get_asset_url."})}}}function yb(t,e){let n=q(t,"modules");if(v(n))for(let s of xs(n)){if(!s.endsWith(".module"))continue;let o=q(n,s,"module.html");if(!v(o))continue;let i;try{i=M(o)}catch{continue}let r=/<img\b([^>]*)>/gi,a;for(;a=r.exec(i);){let c=a[1];/\balt\s*=/.test(c)||e.push({severity:"warning",rule:"a11y.img.alt-missing",file:ot(t,o),message:`${s}: <img> without alt attribute`,fix:'Add an alt attribute (alt="" is fine for purely decorative images).'})}/<(section|article|header|footer|main|nav|aside|h[1-6])\b/i.test(i)||e.push({severity:"info",rule:"a11y.semantics.missing",file:ot(t,o),message:`${s}: module.html has no semantic landmarks (section/article/header/etc.)`,fix:"Wrap the module's main content in a <section> with a heading."})}}function bb(t,e){if(!t){e.push({severity:"warning",rule:"marketplace.json.missing",file:_t,message:"marketplace.json sidecar not found",fix:"Run `vibespot marketplace edit` (CLI) or open the Marketplace panel in the editor to fill in listing details."});return}t.category?Lt.includes(t.category)||e.push({severity:"warning",rule:"marketplace.json.category.unknown",file:_t,message:`marketplace.json category "${t.category}" is not a recognized HubSpot Marketplace category`,fix:`Use one of: ${Lt.join(", ")}.`}):e.push({severity:"warning",rule:"marketplace.json.category.missing",file:_t,message:"marketplace.json has no category",fix:`Pick one of: ${Lt.join(", ")}.`}),(!t.description||t.description.trim().length<40)&&e.push({severity:"warning",rule:"marketplace.json.description.short",file:_t,message:"marketplace.json description is missing or short (<40 chars)",fix:"Provide a 1\u20132 sentence description of the theme for the Marketplace listing."}),t.supportUrl||e.push({severity:"warning",rule:"marketplace.json.supportUrl.missing",file:_t,message:"marketplace.json has no supportUrl",fix:"Add a public support URL where buyers can reach the publisher."});let n=t.features?.length??0;n<2?e.push({severity:"warning",rule:"marketplace.json.features.too_few",file:_t,message:`marketplace.json needs at least 2 features (has ${n})`,fix:"Add 2\u20135 short bullet points highlighting what the theme does well."}):n>5&&e.push({severity:"warning",rule:"marketplace.json.features.too_many",file:_t,message:`marketplace.json has ${n} features but HubSpot allows at most 5`,fix:"Trim the features list to 5 or fewer entries."})}function Qo(t){let e=[],n=[],s=q(t,"modules");if(v(s))for(let i of xs(s)){if(!i.endsWith(".module"))continue;let r=q(s,i),a=i.replace(/\.module$/,""),l=q(r,"meta.json");if(v(l))try{let d=JSON.parse(M(l));yt(d,"label")||(d.label=Pm(a),J(l,JSON.stringify(d,null,2)+`
2708
+ `),e.push(`${i}: filled meta.label = "${d.label}"`))}catch{n.push(`${i}: meta.json could not be parsed`)}let c=q(r,"fields.json");if(v(c))try{let d=JSON.parse(M(c));if(Array.isArray(d)){let u=Em(d);u>0&&(J(c,JSON.stringify(d,null,2)+`
2709
+ `),e.push(`${i}: filled ${u} missing field label(s)`))}}catch{n.push(`${i}: fields.json could not be parsed`)}}let o=Sb(t);for(let i of o)e.push(`${i}: stripped external CDN reference(s)`);return{applied:e,skipped:n}}function Sb(t){let e=[],n=/@import\s+url\(['"]?https?:\/\/[^)]+['"]?\)\s*;?/gi,s=/<link[^>]+href=['"]https?:\/\/[^'"]+['"][^>]*>/gi,o=/<script[^>]+src=['"]https?:\/\/[^'"]+['"][^>]*><\/script>/gi,i=/<script[^>]+src=['"]https?:\/\/[^'"]+['"][^>]*\/>/gi;function r(c){let d;try{d=M(c)}catch{return}let u=d.replace(n,"");u!==d&&(J(c,u),e.push(ot(t,c)))}function a(c){let d;try{d=M(c)}catch{return}let u=d.replace(s,"");u=u.replace(o,""),u=u.replace(i,""),u=u.replace(n,""),u!==d&&(J(c,u),e.push(ot(t,c)))}Xo(q(t,"css"),".css").forEach(r);let l=q(t,"modules");if(v(l))for(let c of xs(l)){if(!c.endsWith(".module"))continue;let d=q(l,c),u=q(d,"module.css"),m=q(d,"module.html");v(u)&&r(u),v(m)&&a(m)}return e}function Em(t){let e=0;for(let n of t){if(typeof n!="object"||n===null)continue;let s=n;!yt(s,"label")&&yt(s,"name")&&(s.label=Pm(String(s.name)),e++),Array.isArray(s.children)&&(e+=Em(s.children))}return e}function Kr(t){if(!v(t))return null;try{let e=JSON.parse(M(t));return e&&typeof e=="object"?e:null}catch{return null}}function yt(t,e){let n=t[e];return typeof n=="string"?n.trim().length>0:Array.isArray(n)?n.length>0:n!=null&&n!==""}function Im(t,e){let n=e.replace(/^\.?\//,"");return q(t,n)}function ot(t,e){return lb(t,e).split("\\").join("/")}function xs(t){try{return Vr(t)}catch{return[]}}function Xo(t,e){if(!v(t))return[];try{let n=[];for(let s of Vr(t)){let o=q(t,s);ab(o).isFile()&&s.endsWith(e)&&n.push(o)}return n}catch{return[]}}function Pm(t){return t.replace(/[-_]+/g," ").split(" ").filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(" ")}var Lt,cb,db,_t,zr=R(()=>{"use strict";y();ne();Lt=["Business Services","Education","Events","Health & Wellness","Hospitality","Marketing & SEO","Non-profit","Portfolio","Real Estate","Restaurant & Food","Retail & E-commerce","SaaS & Technology","Travel","Other"],cb=["label","preview_path","screenshot_path","version","documentation_url","license","example_url"],db=["enable_domain_stylesheets","is_available_for_new_content"],_t="marketplace.json"});function Yr(t){let e=C();if(!e)return p(t,400,{error:"No active theme. Open or create a theme first."}),null;try{ke()}catch{}return e.themePath}function Rm(t,e){let n=Yr(e);if(!n)return;let s=Ss(n);p(e,200,{report:s,categories:Lt})}function Nm(t,e){let n=Yr(e);if(!n)return;let s=Qo(n),o=Ss(n);p(e,200,{fix:s,report:o})}function Om(t,e,n){let s=Yr(n);if(s){if(t==="GET"){p(n,200,{metadata:Tn(s),categories:Lt});return}if(t==="POST"){Ve(e,n,o=>{let i={category:typeof o.category=="string"?o.category:void 0,description:typeof o.description=="string"?o.description:void 0,features:Array.isArray(o.features)?o.features.filter(r=>typeof r=="string"&&r.trim().length>0):void 0,supportUrl:typeof o.supportUrl=="string"?o.supportUrl:void 0,documentationUrl:typeof o.documentationUrl=="string"?o.documentationUrl:void 0,pricingTier:o.pricingTier==="free"||o.pricingTier==="paid"?o.pricingTier:void 0,tags:Array.isArray(o.tags)?o.tags.filter(r=>typeof r=="string"):void 0};Zo(s,i),p(n,200,{ok:!0,metadata:i})});return}p(n,405,{error:"Method not allowed"})}}var Fm=R(()=>{"use strict";y();ze();we();zr()});function xb(t){let e=C();if(!e)return p(t,400,{error:"No active theme. Open or fetch a theme first."}),null;try{ke()}catch{}return e.themePath}function jm(t,e){let n=xb(e);if(!n)return;let s=ho(n);p(e,200,{report:s})}function Dm(t,e){let n=C();if(!n){p(e,400,{error:"No active theme. Open or fetch a theme first."});return}let s=fn(n.themePath),o=Yn(s);if(!o){p(e,200,{applied:!1,reason:"No tokens to apply."});return}if(!n.sharedCss||n.sharedCss.trim().length===0){n.sharedCss=o,n.updatedAt=Date.now(),D(),p(e,200,{applied:!0,written:"session.sharedCss",rootBlock:o});return}let i=yo(n.themePath,n.themeName);i?p(e,200,{applied:!0,written:i,rootBlock:o}):p(e,200,{applied:!1,reason:"Theme already has shared CSS."})}var Lm=R(()=>{"use strict";y();ze();we();bo()});import{createServer as vb}from"http";import{readFileSync as Xr,existsSync as vs}from"fs";import{join as Et,extname as Bm}from"path";import{WebSocketServer as wb,WebSocket as Cb}from"ws";function Ee(t){ti&&ti.readyState===Cb.OPEN&&ti.send(JSON.stringify(t))}function ei(t){ni.push(t),Ee(t)}function Mt(){ni=[]}function qr(t,e){return n=>{if(n.type==="module_progress"&&n.moduleFiles){let{moduleFiles:s,...o}=n;ei(o)}else ei(n);if(n.type==="agent_step")t.push({step:n.step,label:n.label});else if(n.type==="agent_decision"){let s=t[t.length-1];s&&(s.decisions||(s.decisions=[]),s.decisions.push(n.decision))}else n.type==="design_system_ready"?De({sharedCss:n.sharedCss,sharedJs:n.sharedJs}):n.type==="blueprint_ready"?(De({sharedCss:n.sharedCss,sharedJs:n.sharedJs}),Rt(n.moduleOrder),ei({type:"modules_updated",modules:Se().map(s=>s.moduleName)})):n.type==="module_progress"&&n.status==="complete"&&n.moduleFiles?(De({modules:[{moduleName:n.module,fieldsJson:n.moduleFiles.fieldsJson,metaJson:n.moduleFiles.metaJson,moduleHtml:n.moduleFiles.moduleHtml,moduleCss:n.moduleFiles.moduleCss,moduleJs:n.moduleFiles.moduleJs}]}),ei({type:"modules_updated",modules:Se().map(s=>s.moduleName)}),e.push({name:n.module,status:"complete"})):n.type==="module_progress"&&n.status==="failed"&&e.push({name:n.module,status:"failed"})}}function yn(){return Um}function si(t){let{port:e,uiDir:n}=t;Um=t.contentMode||"page";let s=vb((i,r)=>kb(i,r,n)),o=new wb({server:s});return o.on("connection",i=>Ab(i)),new Promise((i,r)=>{s.on("error",a=>{a.code==="EADDRINUSE"?s.listen(e+1,"0.0.0.0",()=>{i({port:e+1,close:()=>{s.close(),o.close()}})}):r(a)}),s.listen(e,"0.0.0.0",()=>{i({port:e,close:()=>{s.close(),o.close()}})})})}function kb(t,e,n){let s=new URL(t.url||"/",`http://${t.headers.host}`),o=t.method||"GET";if(e.setHeader("X-Content-Type-Options","nosniff"),e.setHeader("X-Frame-Options","DENY"),e.setHeader("X-XSS-Protection","1; mode=block"),e.setHeader("Referrer-Policy","strict-origin-when-cross-origin"),s.pathname.startsWith("/api/")){Tb(o,s.pathname,t,e);return}if(s.pathname==="/preview"){let i=Vi();e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(i);return}if(s.pathname==="/module-preview"){let i=s.searchParams.get("module")||"",r=zi(i);e.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),e.end(r||"<!-- module not found -->");return}if(s.pathname.startsWith("/theme-assets/")){$b(s.pathname.slice(14),e);return}if(s.pathname==="/docs"){e.writeHead(301,{Location:"/docs/"}),e.end();return}if(s.pathname.startsWith("/docs/")){let i=s.pathname.slice(5)||"/index.html";Jm(i,Et(n,"docs"),t,e);return}Jm(s.pathname,n,t,e)}function Tb(t,e,n,s){let o=n.headers.origin||"";if(/^https?:\/\/(localhost|127\.0\.0\.1|100\.\d+\.\d+\.\d+|192\.168\.\d+\.\d+|10\.\d+\.\d+\.\d+)(:\d+)?$/.test(o)&&s.setHeader("Access-Control-Allow-Origin",o),s.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, OPTIONS"),s.setHeader("Access-Control-Allow-Headers","Content-Type"),t==="OPTIONS"){s.writeHead(204),s.end();return}switch(e){case"/api/session":sm(t,s);break;case"/api/modules":om(t,n,s);break;case"/api/modules/reorder":rm(n,s);break;case"/api/modules/code":im(n,s);break;case"/api/upload":am(s);break;case"/api/upload-files":t==="POST"?wc(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/field":lm(n,s);break;case"/api/import":cm(n,s);break;case"/api/setup":tu(s);break;case"/api/setup/create":nu(n,s);break;case"/api/setup/fetch":ou(n,s);break;case"/api/setup/open":iu(n,s);break;case"/api/setup/resume":ru(n,s);break;case"/api/setup/apikey":au(n,s);break;case"/api/setup/remote-themes":t==="GET"?lu(s):p(s,405,{error:"Method not allowed"});break;case"/api/starters":t==="GET"?su(s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/status":t==="GET"?gu(s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/engine":t==="POST"?fu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/apikey":t==="POST"?hu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/install":t==="POST"?yu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/hs-auth":t==="POST"?bu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/gh-auth":t==="POST"?Su(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/hs-switch":t==="POST"?xu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/gh-logout":t==="POST"?vu(s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/cli-auth":t==="POST"?wu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/hs-mode":t==="POST"?Cu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/cli-toggle":t==="POST"?ku(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/claude-oauth/save":t==="POST"?_u(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/claude-oauth/status":t==="GET"?Mu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/claude-oauth/logout":t==="POST"?Eu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings":t==="POST"?Tu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/changelog":t==="GET"?p(s,200,{changelog:la()}):p(s,405,{error:"Method not allowed"});break;case"/api/themes":Pu(t,n,s);break;case"/api/themes/switch":t==="POST"?Ru(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/themes/delete-local":t==="POST"?Nu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/themes/rename":t==="POST"?Ou(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/themes/duplicate":t==="POST"?Fu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/history":t==="GET"?dm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/rollback":t==="POST"?um(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/dashboard":t==="GET"?Bu(s):p(s,405,{error:"Method not allowed"});break;case"/api/templates":Uu(t,n,s);break;case"/api/templates/activate":t==="POST"?Gu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/templates/rename":t==="POST"?Wu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/templates/clone":t==="POST"?Vu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/templates/reorder":t==="POST"?Ku(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/module-library":t==="GET"?zu(s):p(s,405,{error:"Method not allowed"});break;case"/api/brand-assets":qu(t,n,s);break;case"/api/brand-kit":Qu(t,n,s);break;case"/api/fonts":t==="GET"?Zu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/brand-assets/extract":t==="POST"?em(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/brand-assets/import-reference":t==="POST"?tm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/download-zip":t==="GET"?Hu(s):p(s,405,{error:"Method not allowed"});break;case"/api/figma/test-token":t==="POST"?Br(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/figma/extract":t==="POST"?Hr(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/figma/generate":t==="POST"?Ur(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/edit":t==="POST"?Pd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/discard":t==="POST"?Rd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/templates":t==="GET"?Nd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/template":t==="POST"?Od(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/marketplace/check":t==="GET"?Rm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/marketplace/fix":t==="POST"?Nm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/marketplace/listing":Om(t,n,s);break;case"/api/inverse/analyze":t==="GET"?jm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/inverse/apply-tokens":t==="POST"?Dm(n,s):p(s,405,{error:"Method not allowed"});break;default:e.startsWith("/api/settings/job/")&&t==="GET"?Au(e,s):e.match(/^\/api\/templates\/[^/]+\/add-module$/)&&t==="POST"?Yu(e,n,s):p(s,404,{error:"Not found"})}}function Ab(t){t.on("message",async n=>{let s;try{s=JSON.parse(n.toString())}catch{t.send(JSON.stringify({type:"error",message:"Invalid JSON"}));return}switch(s.type){case"chat":{let o=String(s.message||"");if(!o.trim())return;let i=Array.isArray(s.fileIds)?s.fileIds:void 0;if(Tr()){tt("user",o),D();try{t.send(JSON.stringify({type:"stream_status",content:"Planning..."}));let a="",l=await kr(o,d=>{a+=d,t.send(JSON.stringify({type:"stream",content:d}))},i),c=jd(l||a);c.plan&&(Po(c.plan),t.send(JSON.stringify({type:"plan_updated",plan:c.plan}))),c.choices&&t.send(JSON.stringify({type:"plan_choices",question:c.choices.question,options:c.choices.options})),tt("assistant",c.cleanedContent),D(),t.send(JSON.stringify({type:"plan_complete",cleanedContent:c.cleanedContent})),t.send(JSON.stringify({type:"generation_complete"}))}catch(a){t.send(JSON.stringify({type:"error",message:a instanceof Error?a.message:String(a)}))}break}tt("user",o),D();let r=Ar();r.needsPrompt&&t.send(JSON.stringify({type:"agentic_prompt"}));try{if(r.useAgentic){Mt();let l=[],c=[],d=await Eo(o,qr(l,c),i);qt(d,{steps:l,modules:c,stats:d.stats})}else wr(l=>{Ee({type:"parse_warning",message:l})}),await ds(o,l=>{Ee({type:"stream",content:l})},l=>{Ee({type:"stream_status",content:l})},i);let a=C();if(a){ke();let l=Ce(),c=null;if(l){let d=l.moduleOrder.map(u=>`modules/${u}.module`);l.templateFile&&d.push(l.templateFile),l.sharedCss&&d.push(`css/${a.themeName}-theme.css`),l.sharedJs&&d.push(`js/${a.themeName}-animations.js`),c=_i(a.themePath,l.id,o,d)}else c=Gt(a.themePath,o);c&&Ee({type:"version_created",hash:c})}Ee({type:"generation_complete"});{let l=C();Ee({type:"modules_updated",modules:Se().map(c=>c.moduleName),templateId:l?.activeTemplateId||null,templates:(l?.templates||[]).map(c=>({id:c.id,label:c.label,pageType:c.pageType,moduleCount:c.modules.length}))})}Mt();{let l=C();l&&r.useAgentic&&!l.brandAssets?.styleguide&&!l.brandAssets?.brandvoice&&!l.brandAssets?.themeContext&&Ee({type:"suggest_brand_extraction"})}}catch(a){Mt(),Ee({type:"error",message:a instanceof Error?a.message:String(a)})}break}case"figma_import":{let o=String(s.extractionId||""),i=String(s.themeName||"");if(!o||!i){t.send(JSON.stringify({type:"error",message:"Missing extractionId or themeName"}));break}let{getCachedExtraction:r}=await Promise.resolve().then(()=>(Gr(),$m)),a=r(o);if(!a){t.send(JSON.stringify({type:"error",message:"Extraction expired or not found. Please re-extract."}));break}try{let l=C();if(!l||l.themeName!==i){let{join:m}=await import("path"),{homedir:g}=await import("os"),{existsSync:h}=await import("fs"),{createThemeScaffold:f}=await Promise.resolve().then(()=>(Jn(),_a)),b=m(g(),"vibespot-themes"),S=m(b,i);if(!h(b)){let{mkdirSync:x}=await import("fs");x(b,{recursive:!0})}h(S)||f(S,i),pn(S,i),D()}Ee({type:"figma_import_started",fileName:a.fileName}),Mt();let c=[],d=[],u=await us(a,i,qr(c,d));qt(u,{steps:c,modules:d,stats:u.stats}),ke(),Gt(C().themePath,`Figma import: ${a.fileName}`),Ee({type:"generation_complete"});{let m=C();Ee({type:"modules_updated",modules:Se().map(g=>g.moduleName),templateId:m?.activeTemplateId||null,templates:(m?.templates||[]).map(g=>({id:g.id,label:g.label,pageType:g.pageType,moduleCount:g.modules.length}))})}Mt()}catch(l){Mt(),Ee({type:"error",message:l instanceof Error?l.message:String(l)})}break}case"extract_brand_assets":{let o=C();if(!o){t.send(JSON.stringify({type:"error",message:"No active session"}));break}(async()=>{try{let i=O(),{engine:r,apiKey:a,model:l}=vn(i),{buildPreviewHtml:c}=await Promise.resolve().then(()=>(es(),vo)),d=c();if(!d||d.length<50)return;let{extractThemeContext:u}=await Promise.resolve().then(()=>(Bo(),Jo)),m=await u(d,o.brandAssets?.themeContext,r,a,l),{mkdirSync:g,writeFileSync:h}=await import("fs");if(m){o.brandAssets||(o.brandAssets={}),o.brandAssets.themeContext=m,o.updatedAt=Date.now();let f=Et(o.themePath,".vibespot");vs(f)||g(f,{recursive:!0}),h(Et(f,"theme-context.md"),m),D(),t.send(JSON.stringify({type:"brand_asset_extracted",assetType:"themeContext"}))}if(!o.brandAssets?.styleguide)try{let{extractDesignContext:f}=await Promise.resolve().then(()=>(fs(),gs)),b=await f(o.themePath);if(b){o.brandAssets||(o.brandAssets={}),o.brandAssets.styleguide=b,o.updatedAt=Date.now();let S=Et(o.themePath,".vibespot");vs(S)||g(S,{recursive:!0}),h(Et(S,"styleguide.md"),b),D(),t.send(JSON.stringify({type:"brand_asset_extracted",assetType:"styleguide"}))}}catch{}t.send(JSON.stringify({type:"brand_extraction_complete"}))}catch(i){t.send(JSON.stringify({type:"brand_extraction_error",message:i instanceof Error?i.message:String(i)}))}})();break}case"start_upload":{let o=C();if(!o){t.send(JSON.stringify({type:"error",message:"No active session"}));break}try{ke();let i=Qs(o.themePath);if(i.length>0&&t.send(JSON.stringify({type:"upload_status",phase:"autofix",fixes:i})),(O().hubspotUploadMode||"api")==="api"){let l=Fe();if(!l){t.send(JSON.stringify({type:"upload_failed",output:"No HubSpot account configured. Open Settings \u2192 HubSpot to add one.",errors:[{file:"",message:"No HubSpot account configured",fixable:!1}]}));break}t.send(JSON.stringify({type:"upload_started",jobId:"api-upload"}));let c=await to(l,o.themePath,o.themeName,{onFileStart:d=>{t.send(JSON.stringify({type:"upload_output",chunk:`Uploading ${d}
2710
+ `}))},onFileComplete:d=>{t.send(JSON.stringify({type:"upload_output",chunk:` \u2713 ${d}
2711
+ `}))},onFileError:(d,u)=>{t.send(JSON.stringify({type:"upload_output",chunk:` \u2717 ${d}: ${u.message}
2712
+ `}))},onProgress:(d,u)=>{t.send(JSON.stringify({type:"upload_progress",completed:d,total:u}))}});if(c.success){let d=It();t.send(JSON.stringify({type:"upload_complete",output:`Uploaded ${c.uploaded} files`,portalId:d?.portalId||"",dataCenter:d?.dataCenter||"na1",themeName:o.themeName,contentMode:yn()}))}else{let d=Xs(c.errors);t.send(JSON.stringify({type:"upload_failed",output:c.errors.map(u=>`${u.file}: ${u.message}`).join(`
2713
+ `),errors:d}))}}else{let l=No(`hs cms upload "${o.themePath}" "${o.themeName}"`,"Uploading to HubSpot",{cwd:Et(o.themePath,".."),timeout:18e4});t.send(JSON.stringify({type:"upload_started",jobId:l}));let c=u=>{t.send(JSON.stringify({type:"upload_output",chunk:u}))};Jd(l,c);let d=setInterval(()=>{let u=Ro(l);if(!(!u||u.status==="running"))if(clearInterval(d),Bd(l,c),u.status==="completed"){let m=dt(),g=m.portalId?Rn(m.portalId):"na1";t.send(JSON.stringify({type:"upload_complete",output:u.output,portalId:m.portalId||"",dataCenter:g,themeName:o.themeName,contentMode:yn()}))}else{let m=Zs(u.output);t.send(JSON.stringify({type:"upload_failed",output:u.output,errors:m,exitCode:u.exitCode}))}},500)}}catch(i){t.send(JSON.stringify({type:"error",message:i instanceof Error?i.message:String(i)}))}break}case"upload_fix_with_ai":{let o=String(s.errorContext||"");if(!o.trim()){t.send(JSON.stringify({type:"error",message:"No error context provided"}));break}let i=`The HubSpot upload ("hs cms upload") failed. Below is the upload log output containing the errors.
2714
+
2715
+ IMPORTANT: Be verbose in your response. For each error:
2716
+ 1. State exactly which file has the problem and what the error is
2717
+ 2. Explain WHY this error occurs (e.g. "HubSpot doesn't support textarea field type" or "field name 'name' is reserved in HubSpot modules")
2718
+ 3. Describe the specific fix you're applying (e.g. "Changing field type from textarea to text" or "Renaming field from 'name' to 'item_name'")
2719
+ 4. Apply the fix to the module files
2720
+
2721
+ CRITICAL: After fixing the reported errors, scan ALL other module files in the theme for the same issues. For example, if you fix "name" \u2192 "item_name" in one module, check every other module's fields.json for the same problem. Fix all occurrences, not just the ones in the error log.
2722
+
2723
+ After fixing all errors, summarize the changes you made.
2724
+
2725
+ Upload log:
2726
+ ${o}`;tt("user",i),D(),t.send(JSON.stringify({type:"upload_fix_started"}));try{await ds(i,a=>{t.send(JSON.stringify({type:"stream",content:a})),t.send(JSON.stringify({type:"upload_fix_stream",content:a}))});let r=C();if(r){ke();let a=Gt(r.themePath,"AI fix: upload errors");a&&t.send(JSON.stringify({type:"version_created",hash:a}))}t.send(JSON.stringify({type:"upload_fix_complete"}));{let a=C();t.send(JSON.stringify({type:"modules_updated",modules:Se().map(l=>l.moduleName),templateId:a?.activeTemplateId||null,templates:(a?.templates||[]).map(l=>({id:l.id,label:l.label,pageType:l.pageType,moduleCount:l.modules.length}))}))}}catch(r){t.send(JSON.stringify({type:"upload_failed",output:r instanceof Error?r.message:String(r),errors:[{file:"AI fix",message:r instanceof Error?r.message:String(r),fixable:!1}]}))}break}case"ping":t.send(JSON.stringify({type:"pong"}));break;case"plan_approve":{let o=C();if(!o){t.send(JSON.stringify({type:"error",message:"No active session"}));break}let i=o.brandAssets?.plan;if(!i||!i.trim()){t.send(JSON.stringify({type:"error",message:"No plan to approve. Send a chat message first."}));break}Y({planMode:!1});let r="Implement the approved plan.";tt("user",r),D();try{Mt();let a=[],l=[],c=await Eo(r,qr(a,l));qt(c,{steps:a,modules:l,stats:c.stats});let d=C();if(d){ke();let u=Ce(),m=null;if(u){let g=u.moduleOrder.map(h=>`modules/${h}.module`);u.templateFile&&g.push(u.templateFile),u.sharedCss&&g.push(`css/${d.themeName}-theme.css`),u.sharedJs&&g.push(`js/${d.themeName}-animations.js`),m=_i(d.themePath,u.id,"Approved plan: implementation",g)}else m=Gt(d.themePath,"Approved plan: implementation");m&&Ee({type:"version_created",hash:m})}Ee({type:"generation_complete"});{let u=C();Ee({type:"modules_updated",modules:Se().map(m=>m.moduleName),templateId:u?.activeTemplateId||null,templates:(u?.templates||[]).map(m=>({id:m.id,label:m.label,pageType:m.pageType,moduleCount:m.modules.length}))})}Mt()}catch(a){Mt(),Ee({type:"error",message:a instanceof Error?a.message:String(a)})}break}case"plan_discard":{_r(),Y({planMode:!1}),t.send(JSON.stringify({type:"plan_discarded"}));break}default:t.send(JSON.stringify({type:"error",message:`Unknown type: ${s.type}`}))}}),ti=t;let e=C();if(e){let n=O(),s={"claude-code":"Claude Code","anthropic-api":"Anthropic API","claude-oauth":"Claude (OAuth)","openai-api":"OpenAI API","gemini-cli":"Gemini CLI","gemini-api":"Gemini API","codex-cli":"Codex CLI",api:"Anthropic API"},o=Ft(),i=Ce();if(t.send(JSON.stringify({type:"init",sessionId:e.id,themeName:e.themeName,modules:Se().map(r=>r.moduleName),messageCount:e.messages.length,messages:e.messages,gitAvailable:Qe(),engine:n.aiEngine?s[n.aiEngine]||n.aiEngine:"",updatedAt:e.updatedAt,templateId:i?.id||null,pageType:i?.pageType||null,templates:(e.templates||[]).map(r=>({id:r.id,label:r.label,pageType:r.pageType,moduleCount:r.modules.length})),planMode:!!n.planMode,plan:e.brandAssets?.plan||"",isGenerating:o})),o&&ni.length>0)for(let r of ni)t.send(JSON.stringify(r))}else t.send(JSON.stringify({type:"needs_setup"}))}function $b(t,e){let n=C();if(!n){e.writeHead(404,{"Content-Type":"text/plain"}),e.end("No session");return}let s=Et(n.themePath,"assets",t);if(!vs(s)){e.writeHead(404,{"Content-Type":"text/plain"}),e.end("Asset not found");return}let o=Bm(s),i=Hm[o]||"application/octet-stream",r=Xr(s);e.writeHead(200,{"Content-Type":i,"Cache-Control":"no-cache"}),e.end(r)}function Jm(t,e,n,s){let i=Et(e,t==="/"?"/index.html":t);if(!vs(i)){let c=Et(e,"index.html");if(vs(c)){let d=Xr(c);s.writeHead(200,{"Content-Type":"text/html","Cache-Control":"no-cache"}),s.end(d)}else s.writeHead(404,{"Content-Type":"text/plain"}),s.end("Not found");return}let r=Bm(i),a=Hm[r]||"application/octet-stream",l=r===".html";try{let c=Xr(i);s.writeHead(200,{"Content-Type":a,"Cache-Control":"no-store"}),s.end(c)}catch{s.writeHead(500,{"Content-Type":"text/plain"}),s.end("Internal Server Error")}}var Hm,ti,ni,Um,ts=R(()=>{"use strict";y();we();dn();es();wn();Fd();Dd();Q();Ht();eo();Oo();Ai();ze();ne();Wo();$u();Iu();ju();nm();mm();ir();Gr();Fm();Lm();Hm={".html":"text/html",".css":"text/css",".js":"application/javascript",".json":"application/json",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp",".gif":"image/gif",".ico":"image/x-icon",".woff2":"font/woff2"},ti=null,ni=[];Um="page"});y();y();import{Command as Jb}from"commander";y();y();at();ne();function Te(){let t=_.vibes,e=_.accent,n=_.muted,s=[`${t("\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2584\u2584\u2584\u2584\u2584")}${t(" \u224B\u224B\u224B\u224B\u224B\u224B\u224B\u224B ")}${e("\u2584\u2584\u2584\u2584\u2584 \u2588\u2588\u2588\u2588\u2588 \u2584\u2584\u2584\u2584 \u2580\u2580\u2588\u2588\u2580\u2580")}`,`${t("\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 ")}${t(" \u224B\u224B\u224B\u224B\u224B\u224B ")}${e("\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 ")}`,`${t("\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 ")}${t(" \u224B\u224B\u224B\u224B ")}${e("\u2580\u2580\u2580\u2584 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 ")}`,`${t(" \u2588\u2584\u2584\u2588\u2580 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 ")}${t(" \u224B\u224B\u224B\u224B\u224B\u224B ")}${e(" \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 ")}`,`${t(" \u2580\u2580\u2580 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2580\u2580\u2580\u2580\u2580")}${t(" \u224B\u224B\u224B\u224B\u224B\u224B\u224B\u224B ")}${e("\u2580\u2580\u2580\u2580 \u2588\u2588 \u2580\u2580\u2580\u2580 \u2588\u2588 ")}`];console.log();for(let o of s)console.log(` ${o}`);console.log(),console.log(` ${n("AI-powered HubSpot Landing Pages")} ${_.dim(`v${sn()}`)}`),console.log()}y();Ht();xt();Jt();Q();Ut();Ye();at();async function Ls(){await me("Checking your environment");let t=En();t.found||(z("Node.js not found. Install it from https://nodejs.org"),process.exit(1)),Ns(t.version)||(z(`Node.js ${t.version} is too old. Version 18+ required. Update at https://nodejs.org`),process.exit(1)),G(`Node.js v${t.version}`);let e=In();e.found||(z("Git not found. Install it from https://git-scm.com"),process.exit(1)),G(`Git ${e.version}`);let n=O(),s=n.hubspotUploadMode!=="cli",o="",i="";if(s){let b=Fe(),S=It();if(b)o=S?.portalId||"",i=S?.portalName||"",G(`HubSpot${i?`: ${i}`:""}${o?` (${o})`:""} \u2014 API mode`);else{ee("No HubSpot account connected"),await ut(`You need a Personal Access Key to deploy themes.
1611
2727
  Create one at: https://app.hubspot.com/l/personal-access-key
1612
- Make sure the Content scope is enabled.`,"HubSpot connection required");let w=await le({message:"Paste your Personal Access Key:",placeholder:"pat-na1-...",validate:N=>N.trim()?void 0:"Key is required"}),v=await Ce();v.start("Validating key...");try{let N=await gs(w);fn(w,N.portalId,N.portalName,N.dataCenter),S=w,o=N.portalId,i=N.portalName,v.stop(`Connected to ${N.portalName} (${N.portalId})`)}catch(N){v.stop("Validation failed"),z(`Invalid key: ${N instanceof Error?N.message:String(N)}`),process.exit(1)}}}else{let S=qe();if(S.found)H(`HubSpot CLI v${S.version}`);else{Z("HubSpot CLI not found"),await fe({message:"Install HubSpot CLI globally?"})||(z("HubSpot CLI is required in CLI mode. Install: npm install -g @hubspot/cli"),process.exit(1));let v=await Ce();v.start("Installing HubSpot CLI..."),D("npm install -g @hubspot/cli").success||(v.stop("Failed"),z("Try: npm install -g @hubspot/cli"),process.exit(1)),S=qe(),v.stop(`HubSpot CLI v${S.version} installed`)}let x=Xe();if(x.authenticated)H(`HubSpot portal${x.portalName?`: ${x.portalName}`:""} (ID: ${x.portalId})`);else{Z("HubSpot not authenticated"),await fe({message:"Run `hs init` now?"})||(z("Run `hs init` manually."),process.exit(1));let v=await Ce();v.start("Waiting for HubSpot authentication..."),Nr("hs init")||(v.stop("Authentication failed"),process.exit(1)),x=Xe(),v.stop(`Connected to portal${x.portalName?`: ${x.portalName}`:""} (ID: ${x.portalId})`)}o=x.portalId,i=x.portalName}let r=xn(),a=wn(),l=Cn(),c=Lr(),d={"claude-code":"Claude Code",api:"Anthropic API","anthropic-api":"Anthropic API","claude-oauth":"Claude (OAuth)","openai-api":"OpenAI API","gemini-api":"Gemini API","gemini-cli":"Gemini CLI","codex-cli":"OpenAI Codex"},u=Ye(),m,f=n.aiEngine,y=[];if(r.found&&y.push({value:"claude-code",label:"Claude Code",hint:f==="claude-code"?"last used \u2014 recommended":"uses your existing Claude subscription \u2014 recommended"}),u&&y.push({value:"claude-oauth",label:"Claude (OAuth)",hint:f==="claude-oauth"?"last used":"uses your Claude Pro/Max subscription via OAuth"}),a.found&&y.push({value:"gemini-cli",label:"Gemini CLI",hint:f==="gemini-cli"?"last used":"uses your existing Gemini setup"}),l.found&&y.push({value:"codex-cli",label:"OpenAI Codex",hint:f==="codex-cli"?"last used":"uses your existing OpenAI setup"}),c&&y.push({value:"api",label:"Anthropic API",hint:f==="api"?"last used":"uses your API key"}),f&&y.sort((S,x)=>S.value===f?-1:x.value===f?1:0),y.length===1)m=y[0].value,H(`AI engine: ${d[m]} (auto-detected)`);else if(y.length>1)m=await dt({message:"Choose your AI engine:",options:y});else if(await Ze(`You need an AI coding assistant to power the conversion.
2728
+ Make sure the Content scope is enabled.`,"HubSpot connection required");let x=await be({message:"Paste your Personal Access Key:",placeholder:"pat-na1-...",validate:P=>P.trim()?void 0:"Key is required"}),w=await Pe();w.start("Validating key...");try{let P=await js(x);An(x,P.portalId,P.portalName,P.dataCenter),b=x,o=P.portalId,i=P.portalName,w.stop(`Connected to ${P.portalName} (${P.portalId})`)}catch(P){w.stop("Validation failed"),z(`Invalid key: ${P instanceof Error?P.message:String(P)}`),process.exit(1)}}}else{let b=ct();if(b.found)G(`HubSpot CLI v${b.version}`);else{ee("HubSpot CLI not found"),await Ae({message:"Install HubSpot CLI globally?"})||(z("HubSpot CLI is required in CLI mode. Install: npm install -g @hubspot/cli"),process.exit(1));let w=await Pe();w.start("Installing HubSpot CLI..."),te("npm install -g @hubspot/cli").success||(w.stop("Failed"),z("Try: npm install -g @hubspot/cli"),process.exit(1)),b=ct(),w.stop(`HubSpot CLI v${b.version} installed`)}let S=dt();if(S.authenticated)G(`HubSpot portal${S.portalName?`: ${S.portalName}`:""} (ID: ${S.portalId})`);else{ee("HubSpot not authenticated"),await Ae({message:"Run `hs init` now?"})||(z("Run `hs init` manually."),process.exit(1));let w=await Pe();w.start("Waiting for HubSpot authentication..."),da("hs init")||(w.stop("Authentication failed"),process.exit(1)),S=dt(),w.stop(`Connected to portal${S.portalName?`: ${S.portalName}`:""} (ID: ${S.portalId})`)}o=S.portalId,i=S.portalName}let r=Pn(),a=Nn(),l=On(),c=ha(),d={"claude-code":"Claude Code",api:"Anthropic API","anthropic-api":"Anthropic API","claude-oauth":"Claude (OAuth)","openai-api":"OpenAI API","gemini-api":"Gemini API","gemini-cli":"Gemini CLI","codex-cli":"OpenAI Codex"},u=lt(),m,g=n.aiEngine,h=[];if(r.found&&h.push({value:"claude-code",label:"Claude Code",hint:g==="claude-code"?"last used \u2014 recommended":"uses your existing Claude subscription \u2014 recommended"}),u&&h.push({value:"claude-oauth",label:"Claude (OAuth)",hint:g==="claude-oauth"?"last used":"uses your Claude Pro/Max subscription via OAuth"}),a.found&&h.push({value:"gemini-cli",label:"Gemini CLI",hint:g==="gemini-cli"?"last used":"uses your existing Gemini setup"}),l.found&&h.push({value:"codex-cli",label:"OpenAI Codex",hint:g==="codex-cli"?"last used":"uses your existing OpenAI setup"}),c&&h.push({value:"api",label:"Anthropic API",hint:g==="api"?"last used":"uses your API key"}),g&&h.sort((b,S)=>b.value===g?-1:S.value===g?1:0),h.length===1)m=h[0].value,G(`AI engine: ${d[m]} (auto-detected)`);else if(h.length>1)m=await wt({message:"Choose your AI engine:",options:h});else if(await ut(`You need an AI coding assistant to power the conversion.
1613
2729
 
1614
- ${A.bold("Option 1:")} Install Claude Code ${A.muted("(recommended)")}
2730
+ ${_.bold("Option 1:")} Install Claude Code ${_.muted("(recommended)")}
1615
2731
  https://claude.ai/code
1616
2732
 
1617
- ${A.bold("Option 2:")} Install Gemini CLI
2733
+ ${_.bold("Option 2:")} Install Gemini CLI
1618
2734
  https://github.com/google-gemini/gemini-cli
1619
2735
 
1620
- ${A.bold("Option 3:")} Install OpenAI Codex
2736
+ ${_.bold("Option 3:")} Install OpenAI Codex
1621
2737
  https://github.com/openai/codex
1622
2738
 
1623
- ${A.bold("Option 4:")} Set an Anthropic API key
2739
+ ${_.bold("Option 4:")} Set an Anthropic API key
1624
2740
  export ANTHROPIC_API_KEY=sk-ant-...
1625
- (get one at https://console.anthropic.com)`,"AI engine required"),m=await dt({message:"Which will you set up?",options:[{value:"claude-code",label:"Claude Code",hint:"I'll install it now"},{value:"gemini-cli",label:"Gemini CLI",hint:"I'll install it now"},{value:"codex-cli",label:"OpenAI Codex",hint:"I'll install it now"},{value:"api",label:"Anthropic API",hint:"I'll enter my key"}]}),m==="api"){let S=await le({message:"Enter your Anthropic API key:",placeholder:"sk-ant-api03-...",validate:x=>x.startsWith("sk-ant-")?void 0:"Key should start with sk-ant-"});process.env.ANTHROPIC_API_KEY=S,V({anthropicApiKey:S})}let h;return m==="claude-code"&&(h=await dt({message:"Which model?",options:[{value:"sonnet",label:"Sonnet",hint:"fast, recommended"},{value:"opus",label:"Opus",hint:"most capable"},{value:"haiku",label:"Haiku",hint:"fastest, cheapest"}]})),V({aiEngine:m}),await oe("Environment ready!"),{aiEngine:m,model:h,portalId:o,portalName:i}}g();Et();Q();import{readdirSync as Yo,statSync as qu}from"fs";import{join as ie,basename as qo,extname as Xu}from"path";function zr(e){let t=[],n=[ie(e,"src/components/landing"),ie(e,"src/components/sections"),ie(e,"src/components"),ie(e,"src/pages"),ie(e,"app/components"),ie(e,"components")];for(let s of n)if(b(s))try{let o=Yo(s);for(let i of o){let r=ie(s,i);if(!qu(r).isFile())continue;let l=Xu(i);if(![".tsx",".jsx"].includes(l))continue;let c=qo(i,l);if(c.startsWith("ui")||c==="index")continue;let d=T(r),u=Zu(c,d);t.push({name:c,path:r,description:u})}}catch{}return t}function Zu(e,t){let n=[];return/carousel|slider|swiper|embla/i.test(t)&&n.push("carousel"),/accordion|collapsible|expand/i.test(t)&&n.push("accordion"),/form|submit|input.*email/i.test(t)&&n.push("form"),/nav|navigation|menu/i.test(t)&&n.push("navigation"),/hero|headline|tagline/i.test(t)&&n.push("hero"),/footer|copyright/i.test(t)&&n.push("footer"),/testimonial|quote|review/i.test(t)&&n.push("testimonials"),/pricing|plan|tier/i.test(t)&&n.push("pricing"),/faq|question.*answer/i.test(t)&&n.push("FAQ"),/feature|benefit|advantage/i.test(t)&&n.push("features"),/contact|get.in.touch/i.test(t)&&n.push("contact"),/cta|call.to.action/i.test(t)&&n.push("CTA"),/team|member|bio/i.test(t)&&n.push("team"),n.length===0?e.replace(/Section$/,"").replace(/([A-Z])/g," $1").trim():n.join(", ")}function Kr(e){let t=[ie(e,"src/index.css"),ie(e,"src/globals.css"),ie(e,"src/app/globals.css"),ie(e,"app/globals.css")],n=0,s=[];for(let o of t){if(!b(o))continue;let i=T(o),r=i.match(/--[\w-]+:/g);r&&(n+=r.length);let a=i.match(/font-family:\s*['"]([^'"]+)['"]/g);if(a)for(let c of a){let d=c.match(/['"]([^'"]+)['"]/)?.[1];d&&!s.includes(d)&&s.push(d)}let l=i.match(/@import\s+url\([^)]*fonts\.googleapis\.com[^)]*family=([^&)]+)/g);if(l)for(let c of l){let d=c.match(/family=([^&)]+)/)?.[1]?.replace(/\+/g," ");d&&!s.includes(d)&&s.push(d)}}return{varCount:n,fonts:s}}function Yr(e){let t=[],n=ie(e,"src/hooks");if(b(n))try{let o=Yo(n);for(let i of o)/scroll/i.test(i)&&t.push("Scroll animations"),/intersection/i.test(i)&&t.push("Scroll animations")}catch{}let s=ie(e,"src/components/landing");if(b(s))try{let o=Yo(s);for(let i of o){if(!i.endsWith(".tsx")&&!i.endsWith(".jsx"))continue;let r=T(ie(s,i));/carousel|embla|swiper/i.test(r)&&!t.includes("Carousel")&&t.push("Carousel"),/accordion|collapsible/i.test(r)&&!t.includes("Accordion")&&t.push("Accordion"),/typing|typewriter/i.test(r)&&!t.includes("Typing animation")&&t.push("Typing animation"),/parallax|requestAnimationFrame/i.test(r)&&!t.includes("Parallax")&&t.push("Parallax")}}catch{}return t.length===0&&t.push("Scroll animations"),t}function qr(e){let t,n=!1;if(e.startsWith("http")||e.startsWith("git@")){n=!0;let l=qo(e.replace(/\.git$/,""))||"react-source";if(t=ie(process.cwd(),"workspace",l),!b(t)){let c=D(`git clone --depth 1 "${e}" "${t}"`);if(!c.success)throw new Error(`Failed to clone ${e}: ${c.stderr}`)}}else if(t=e,!b(t))throw new Error(`Directory not found: ${t}`);let s=zr(t),o=b(ie(t,"tailwind.config.ts"))||b(ie(t,"tailwind.config.js")),{varCount:i,fonts:r}=Kr(t),a=Yr(t);return{sourceDir:t,wasCloned:n,components:s,hasTailwind:o,cssVarCount:i,fonts:r,interactions:a}}async function bs(){await se("Source Project");let e=await le({message:"GitHub URL or local path to your React project:",placeholder:"https://github.com/user/my-lovable-page",validate:y=>{if(!y.trim())return"Please enter a URL or path"}}),t,n=!1;if(e.startsWith("http")||e.startsWith("git@")){n=!0;let y=qo(e.replace(/\.git$/,""))||"react-source";if(t=ie(process.cwd(),"workspace",y),b(t))H(`Using existing clone: ${A.dim(t)}`);else{let h=await Ce();h.start("Cloning repository..."),D(`git clone --depth 1 "${e}" "${t}"`).success||(h.stop("Clone failed"),z(`Failed to clone ${e}. Check the URL and your access permissions.`),process.exit(1)),h.stop(`Cloned to ${A.dim(t)}`)}}else t=e,b(t)||(z(`Directory not found: ${t}`),process.exit(1)),H(`Using local source: ${A.dim(t)}`);let s=await Ce();s.start("Analyzing project structure...");let o=zr(t),i=b(ie(t,"tailwind.config.ts"))||b(ie(t,"tailwind.config.js")),{varCount:r,fonts:a}=Kr(t),l=Yr(t);s.stop(`Found ${o.length} landing page components`),o.length===0&&(Z("No components found. Make sure the React source has .tsx/.jsx files in src/components/"),process.exit(1));let c=o.map((y,h)=>` ${A.dim(`${h+1}.`)} ${A.bold(y.name)} ${A.muted(`\u2014 ${y.description}`)}`).join(`
1626
- `),d=i?`Tailwind + custom CSS (${r} variables)`:`Custom CSS (${r} variables)`,u=a.length>0?a.join(", "):"System fonts",m=l.join(", ");return await Ze(`${c}
1627
-
1628
- CSS: ${d}
1629
- JS: ${m}
1630
- Font: ${u}`,`${o.length} components detected`),await fe({message:"Does this look right?"})||(z("Please adjust your source directory and try again."),process.exit(0)),await oe("Source analyzed!"),{sourceDir:t,wasCloned:n,components:o,hasTailwind:i,cssVarCount:r,fonts:a,interactions:l}}g();Et();Q();import{join as In}from"path";X();xs();vs();async function ws(){await se("HubSpot Theme Setup");let e=await dt({message:"Do you have an existing HubSpot theme?",options:[{value:"fetch",label:"Fetch my existing theme from HubSpot",hint:"downloads your current theme"},{value:"create",label:"Start fresh (HubSpot Boilerplate)",hint:"creates a new starter theme"}]}),t,n,s=In(process.cwd(),"workspace");if(Ae(s),e==="fetch"){t=await le({message:"What's your theme name in HubSpot?",placeholder:"My-Company-Theme",validate:u=>u.trim()?void 0:"Theme name is required"}),n=In(s,t);let l=await Ce();l.start("Fetching theme from HubSpot...");let c=R(),d=$e();if(c.hubspotUploadMode==="cli"||!d)D(`hs cms fetch "${t}" "${n}"`).success||(l.stop("Fetch failed"),z(`Could not fetch theme "${t}". Check the name in HubSpot Design Manager.`),process.exit(1));else try{await $n(d,t,n)}catch(u){l.stop("Fetch failed"),z(`Could not fetch theme "${t}": ${u instanceof Error?u.message:String(u)}`),process.exit(1)}l.stop(`Theme fetched: ${A.dim(n)}`)}else{t=await le({message:"Name for your new theme:",placeholder:"my-theme",defaultValue:"my-theme"}),n=In(s,t);let l=await Ce();l.start("Creating theme...");try{Tn(n,t)}catch(c){l.stop("Creation failed"),z(`Could not create theme "${t}": ${c instanceof Error?c.message:String(c)}`),process.exit(1)}l.stop(`Theme created: ${A.dim(n)}`)}await se("Checking theme compatibility");let o=In(n,"templates/layouts/base.html");b(o)||(z(`base.html not found at ${o}. Your theme may have a different structure.`),process.exit(1)),H("base.html found");let i=T(o),r=!1;if(i.includes("template_css"))H("template_css support");else{Z("Missing template_css support in base.html");let l=i.indexOf("theme-overrides.css")!==-1?i.indexOf("{{",i.lastIndexOf(`
2741
+ (get one at https://console.anthropic.com)`,"AI engine required"),m=await wt({message:"Which will you set up?",options:[{value:"claude-code",label:"Claude Code",hint:"I'll install it now"},{value:"gemini-cli",label:"Gemini CLI",hint:"I'll install it now"},{value:"codex-cli",label:"OpenAI Codex",hint:"I'll install it now"},{value:"api",label:"Anthropic API",hint:"I'll enter my key"}]}),m==="api"){let b=await be({message:"Enter your Anthropic API key:",placeholder:"sk-ant-api03-...",validate:S=>S.startsWith("sk-ant-")?void 0:"Key should start with sk-ant-"});process.env.ANTHROPIC_API_KEY=b,Y({anthropicApiKey:b})}let f;return m==="claude-code"&&(f=await wt({message:"Which model?",options:[{value:"sonnet",label:"Sonnet",hint:"fast, recommended"},{value:"opus",label:"Opus",hint:"most capable"},{value:"haiku",label:"Haiku",hint:"fastest, cheapest"}]})),Y({aiEngine:m}),await pe("Environment ready!"),{aiEngine:m,model:f,portalId:o,portalName:i}}Bs();y();Jt();ne();Ye();at();Q();Jn();Hs();import{join as Hn}from"path";async function Us(){await me("HubSpot Theme Setup");let t=await wt({message:"Do you have an existing HubSpot theme?",options:[{value:"fetch",label:"Fetch my existing theme from HubSpot",hint:"downloads your current theme"},{value:"create",label:"Start fresh (HubSpot Boilerplate)",hint:"creates a new starter theme"}]}),e,n,s=Hn(process.cwd(),"workspace");if(Ie(s),t==="fetch"){e=await be({message:"What's your theme name in HubSpot?",placeholder:"My-Company-Theme",validate:u=>u.trim()?void 0:"Theme name is required"}),n=Hn(s,e);let l=await Pe();l.start("Fetching theme from HubSpot...");let c=O(),d=Fe();if(c.hubspotUploadMode==="cli"||!d)te(`hs cms fetch "${e}" "${n}"`).success||(l.stop("Fetch failed"),z(`Could not fetch theme "${e}". Check the name in HubSpot Design Manager.`),process.exit(1));else try{await Bn(d,e,n)}catch(u){l.stop("Fetch failed"),z(`Could not fetch theme "${e}": ${u instanceof Error?u.message:String(u)}`),process.exit(1)}l.stop(`Theme fetched: ${_.dim(n)}`)}else{e=await be({message:"Name for your new theme:",placeholder:"my-theme",defaultValue:"my-theme"}),n=Hn(s,e);let l=await Pe();l.start("Creating theme...");try{Ln(n,e)}catch(c){l.stop("Creation failed"),z(`Could not create theme "${e}": ${c instanceof Error?c.message:String(c)}`),process.exit(1)}l.stop(`Theme created: ${_.dim(n)}`)}await me("Checking theme compatibility");let o=Hn(n,"templates/layouts/base.html");v(o)||(z(`base.html not found at ${o}. Your theme may have a different structure.`),process.exit(1)),G("base.html found");let i=M(o),r=!1;if(i.includes("template_css"))G("template_css support");else{ee("Missing template_css support in base.html");let l=i.indexOf("theme-overrides.css")!==-1?i.indexOf("{{",i.lastIndexOf(`
1631
2742
  `,i.indexOf("theme-overrides.css"))):i.lastIndexOf("require_css");if(l>0){let c=i.lastIndexOf(`
1632
2743
  `,l);i=i.slice(0,c)+`
1633
2744
  {% if template_css %}
1634
2745
  {{ require_css(get_asset_url(template_css)) }}
1635
- {% endif %}`+i.slice(c),r=!0}}if(i.includes("template_js"))H("template_js support");else{Z("Missing template_js support in base.html");let l=i.indexOf("require_js");if(l>0){let c=i.indexOf(`
2746
+ {% endif %}`+i.slice(c),r=!0}}if(i.includes("template_js"))G("template_js support");else{ee("Missing template_js support in base.html");let l=i.indexOf("require_js");if(l>0){let c=i.indexOf(`
1636
2747
  `,l),d=i.indexOf(`
1637
2748
  `,c+1),u=`
1638
2749
  {% if template_js %}
@@ -1640,17 +2751,17 @@ ${A.bold("Option 4:")} Set an Anthropic API key
1640
2751
  {% endif %}`,m=i.indexOf("}}",l)+2+i.slice(i.indexOf("}}",l)+2).indexOf(`
1641
2752
  `)+1;i=i.slice(0,i.indexOf(`
1642
2753
  `,i.indexOf("}}",l)+2))+u+i.slice(i.indexOf(`
1643
- `,i.indexOf("}}",l)+2)),r=!0}}if(r){let l=await Ce();l.start("Patching base.html..."),L(o,i),l.stop("base.html patched with template_css/template_js support")}let a=In(n,".hsignore");if(b(a)){let l=T(a);l.includes("docs/")||(L(a,l+`
2754
+ `,i.indexOf("}}",l)+2)),r=!0}}if(r){let l=await Pe();l.start("Patching base.html..."),J(o,i),l.stop("base.html patched with template_css/template_js support")}let a=Hn(n,".hsignore");if(v(a)){let l=M(a);l.includes("docs/")||(J(a,l+`
1644
2755
  docs/
1645
- `),H("Added docs/ to .hsignore"))}else L(a,`docs/
2756
+ `),G("Added docs/ to .hsignore"))}else J(a,`docs/
1646
2757
  *.md
1647
2758
  node_modules/
1648
2759
  .git
1649
- `),H("Created .hsignore");return await oe("Theme ready!"),{themePath:n,themeName:t}}g();import{join as je}from"path";import{readdirSync as En,rmSync as la}from"fs";g();ut();Q();import{spawn as sm}from"child_process";import{join as Y,basename as om}from"path";import{readdirSync as Qe,statSync as ra,writeFileSync as im}from"fs";var rm=new Set(["about.html","blog-index.html","blog-post.html","contact.html","home.html","hubdb.html","landing-page.html","pricing.html","qa-test.html","base.html"]),Cs=class{model;reported=new Set;moduleCount=0;expectedModules=0;constructor(t){this.model=t}async convert(t){let{sourceDir:n,themePath:s,onProgress:o}=t,i=t.conversionGuide||ge();this.reported.clear(),this.moduleCount=0,this.expectedModules=0;let r=this.countSourceComponents(n),a=this.listModules(s),l=this.listDir(Y(s,"css")),c=this.listDir(Y(s,"js")),d=this.listDir(Y(s,"templates")),u=this.buildFullPrompt(n,s,i);o("convert",`Starting Claude Code (${r} source components found)...`);let m="",f="",y=setInterval(()=>{this.reportProgress(s,a,l,c,d,o)},3e3);try{await new Promise((w,v)=>{let N={...process.env};delete N.CLAUDECODE;let O=["--print","--max-turns","50","--allowedTools","Read,Glob,Grep,Write,Edit,Bash"];this.model&&O.push("--model",this.model);let F=sm("claude",O,{cwd:s,stdio:["pipe","pipe","pipe"],env:N,shell:!0});F.stdout.on("data",U=>{m+=U.toString()}),F.stderr.on("data",U=>{f+=U.toString()}),F.on("error",U=>v(new Error(`Claude Code failed to start: ${U.message}`))),F.on("close",U=>{U!==0?v(new Error(`Claude Code exited with code ${U}.
1650
- `+(f?`Stderr: ${f.slice(0,500)}
1651
- `:"")+(m?`Output: ${m.slice(0,500)}`:"No output"))):w()}),F.stdin.on("error",()=>{}),F.stdin.write(u),F.stdin.end(),setTimeout(()=>{F.kill(),v(new Error("Claude Code timed out after 30 minutes"))},18e5)})}finally{clearInterval(y)}let h=Y(s,"..","vibespot-conversion.log");try{let v=["=== vibeSpot Conversion Log ===",`Timestamp: ${new Date().toISOString()}`,`Source: ${n}`,`Theme: ${s}`,`Model: ${this.model||"default"}`,"","=== PROMPT SENT ===",u.slice(0,500)+`
1652
- ... (truncated, full guide follows)`,"","=== CLAUDE CODE STDOUT ===",m||"(empty)","","=== CLAUDE CODE STDERR ===",f||"(empty)",""].join(`
1653
- `);im(h,v,"utf-8"),o("status",`Log written to ${om(h)}`)}catch{}o("scan","Scanning generated files...");let S=this.scanGeneratedFiles(s);if(S.modules.filter(w=>!a.has(w.moduleName+".module")).length===0){let w=m.slice(0,1500)||"(no output)",v=f.slice(0,500);throw new Error(`Claude Code did not create any new module files.
2760
+ `),G("Created .hsignore");return await pe("Theme ready!"),{themePath:n,themeName:e}}y();import{join as qe}from"path";import{readdirSync as Gn,rmSync as Ba}from"fs";y();Ue();ne();import{spawn as Pp}from"child_process";import{join as Z,basename as Rp}from"path";import{readdirSync as mt,statSync as La,writeFileSync as Np}from"fs";var Op=new Set(["about.html","blog-index.html","blog-post.html","contact.html","home.html","hubdb.html","landing-page.html","pricing.html","qa-test.html","base.html"]),Gs=class{model;reported=new Set;moduleCount=0;expectedModules=0;constructor(e){this.model=e}async convert(e){let{sourceDir:n,themePath:s,onProgress:o}=e,i=e.conversionGuide||fe();this.reported.clear(),this.moduleCount=0,this.expectedModules=0;let r=this.countSourceComponents(n),a=this.listModules(s),l=this.listDir(Z(s,"css")),c=this.listDir(Z(s,"js")),d=this.listDir(Z(s,"templates")),u=this.buildFullPrompt(n,s,i);o("convert",`Starting Claude Code (${r} source components found)...`);let m="",g="",h=setInterval(()=>{this.reportProgress(s,a,l,c,d,o)},3e3);try{await new Promise((x,w)=>{let P={...process.env};delete P.CLAUDECODE;let F=["--print","--max-turns","50","--allowedTools","Read,Glob,Grep,Write,Edit,Bash"];this.model&&F.push("--model",this.model);let H=Pp("claude",F,{cwd:s,stdio:["pipe","pipe","pipe"],env:P,shell:!0});H.stdout.on("data",L=>{m+=L.toString()}),H.stderr.on("data",L=>{g+=L.toString()}),H.on("error",L=>w(new Error(`Claude Code failed to start: ${L.message}`))),H.on("close",L=>{L!==0?w(new Error(`Claude Code exited with code ${L}.
2761
+ `+(g?`Stderr: ${g.slice(0,500)}
2762
+ `:"")+(m?`Output: ${m.slice(0,500)}`:"No output"))):x()}),H.stdin.on("error",()=>{}),H.stdin.write(u),H.stdin.end(),setTimeout(()=>{H.kill(),w(new Error("Claude Code timed out after 30 minutes"))},18e5)})}finally{clearInterval(h)}let f=Z(s,"..","vibespot-conversion.log");try{let w=["=== vibeSpot Conversion Log ===",`Timestamp: ${new Date().toISOString()}`,`Source: ${n}`,`Theme: ${s}`,`Model: ${this.model||"default"}`,"","=== PROMPT SENT ===",u.slice(0,500)+`
2763
+ ... (truncated, full guide follows)`,"","=== CLAUDE CODE STDOUT ===",m||"(empty)","","=== CLAUDE CODE STDERR ===",g||"(empty)",""].join(`
2764
+ `);Np(f,w,"utf-8"),o("status",`Log written to ${Rp(f)}`)}catch{}o("scan","Scanning generated files...");let b=this.scanGeneratedFiles(s);if(b.modules.filter(x=>!a.has(x.moduleName+".module")).length===0){let x=m.slice(0,1500)||"(no output)",w=g.slice(0,500);throw new Error(`Claude Code did not create any new module files.
1654
2765
 
1655
2766
  This usually means the model described the conversion instead of using Write tool to create files.
1656
2767
 
@@ -1659,23 +2770,23 @@ Possible causes:
1659
2770
  - Claude Code hit a rate limit or API error
1660
2771
  - The source directory was not accessible
1661
2772
 
1662
- Source: ${t.sourceDir}
2773
+ Source: ${e.sourceDir}
1663
2774
  Theme: ${s}
1664
- `+(v?`
2775
+ `+(w?`
1665
2776
  Stderr:
1666
- ${v}
2777
+ ${w}
1667
2778
  `:"")+`
1668
2779
  Claude output:
1669
- ${w}`)}return S}reportProgress(t,n,s,o,i,r){let a=0,l=this.listDir(Y(t,"css"));for(let m of l){if(s.has(m)||!m.endsWith(".css"))continue;let f=`css:${m}`;this.reported.has(f)||(this.reported.add(f),r("created",`Shared CSS (${m})`),a++)}let c=this.listDir(Y(t,"js"));for(let m of c){if(o.has(m)||!m.endsWith(".js"))continue;let f=`js:${m}`;this.reported.has(f)||(this.reported.add(f),r("created",`Shared JS (${m})`),a++)}this.expectedModules===0&&(this.expectedModules=this.detectExpectedModules(t,i));let d=this.listModules(t);for(let m of d){if(n.has(m))continue;let f=`module:${m}`;if(!this.reported.has(f)){this.reported.add(f),this.moduleCount++;let y=this.expectedModules>0?`[${this.moduleCount}/${this.expectedModules}]`:`[${this.moduleCount}]`;r("created",`Module ${y}: ${m.replace(".module","")}`),a++}}let u=this.listDir(Y(t,"templates"));for(let m of u){if(i.has(m)||!m.endsWith(".html"))continue;let f=`template:${m}`;this.reported.has(f)||(this.reported.add(f),r("created",`Page template (${m})`),a++)}if(a===0)if(this.moduleCount>0){let m=this.expectedModules>0?`/${this.expectedModules}`:"";r("status",`${this.moduleCount}${m} modules created, conversion continuing...`)}else this.reported.size>0?r("status","Shared assets created, building modules..."):r("status","Claude Code is analyzing source files...")}buildFullPrompt(t,n,s){return`You are converting a React landing page to native HubSpot CMS modules.
2780
+ ${x}`)}return b}reportProgress(e,n,s,o,i,r){let a=0,l=this.listDir(Z(e,"css"));for(let m of l){if(s.has(m)||!m.endsWith(".css"))continue;let g=`css:${m}`;this.reported.has(g)||(this.reported.add(g),r("created",`Shared CSS (${m})`),a++)}let c=this.listDir(Z(e,"js"));for(let m of c){if(o.has(m)||!m.endsWith(".js"))continue;let g=`js:${m}`;this.reported.has(g)||(this.reported.add(g),r("created",`Shared JS (${m})`),a++)}this.expectedModules===0&&(this.expectedModules=this.detectExpectedModules(e,i));let d=this.listModules(e);for(let m of d){if(n.has(m))continue;let g=`module:${m}`;if(!this.reported.has(g)){this.reported.add(g),this.moduleCount++;let h=this.expectedModules>0?`[${this.moduleCount}/${this.expectedModules}]`:`[${this.moduleCount}]`;r("created",`Module ${h}: ${m.replace(".module","")}`),a++}}let u=this.listDir(Z(e,"templates"));for(let m of u){if(i.has(m)||!m.endsWith(".html"))continue;let g=`template:${m}`;this.reported.has(g)||(this.reported.add(g),r("created",`Page template (${m})`),a++)}if(a===0)if(this.moduleCount>0){let m=this.expectedModules>0?`/${this.expectedModules}`:"";r("status",`${this.moduleCount}${m} modules created, conversion continuing...`)}else this.reported.size>0?r("status","Shared assets created, building modules..."):r("status","Claude Code is analyzing source files...")}buildFullPrompt(e,n,s){return`You are converting a React landing page to native HubSpot CMS modules.
1670
2781
 
1671
- SOURCE DIRECTORY: ${t}
2782
+ SOURCE DIRECTORY: ${e}
1672
2783
  THEME DIRECTORY: ${n}
1673
2784
 
1674
2785
  IMPORTANT \u2014 YOU MUST CREATE REAL FILES:
1675
2786
  You have access to Write, Edit, Read, Glob, Grep, and Bash tools. You MUST use the Write tool to create each file. Do NOT just describe or list what files should be created \u2014 actually call the Write tool for every single file. If you do not call Write, no files will be created and the conversion will fail.
1676
2787
 
1677
2788
  STEP-BY-STEP PROCESS:
1678
- 1. Use Glob to find all .tsx/.jsx files in ${t}/src/
2789
+ 1. Use Glob to find all .tsx/.jsx files in ${e}/src/
1679
2790
  2. Use Read to read each component file and understand the page structure
1680
2791
  3. Use Write to create a shared CSS file at ${n}/css/<name>-theme.css
1681
2792
  - Include CSS custom properties, design system variables, utility classes
@@ -1709,16 +2820,16 @@ CSS QUALITY: The converted page must visually match the original React page. Eve
1709
2820
  Do NOT run hs upload \u2014 I will handle that separately.
1710
2821
 
1711
2822
  HUBSPOT CMS RULES:
1712
- ${He()}
2823
+ ${je()}
1713
2824
 
1714
2825
  CONVERSION GUIDE:
1715
- ${s}`}scanGeneratedFiles(t){let n={sharedCss:"",sharedJs:"",template:"",modules:[]},s=Y(t,"css");if(b(s)){for(let a of Qe(s))if(a.endsWith(".css")&&a!=="theme-overrides.css"&&a!=="main.css"&&a!=="style.css"){n.sharedCss=T(Y(s,a));break}}let o=Y(t,"js");if(b(o)){for(let a of Qe(o))if(a.endsWith(".js")&&a!=="main.js"){n.sharedJs=T(Y(o,a));break}}let i=Y(t,"templates");if(b(i)){for(let a of Qe(i))if(a.startsWith("lp-")&&a.endsWith(".html")){n.template=T(Y(i,a));break}if(!n.template){for(let a of Qe(i))if(a.endsWith(".html")&&!rm.has(a)&&!a.startsWith("system")){let l=T(Y(i,a));if(l.includes("dnd_area")){n.template=l;break}}}if(!n.template){for(let a of Qe(i))if(a.endsWith(".html")&&!a.startsWith("system")&&a!=="base.html"){let l=T(Y(i,a));if(l.includes("dnd_area")){n.template=l;break}}}}let r=Y(t,"modules");if(b(r))for(let a of Qe(r)){if(!a.endsWith(".module"))continue;let l=Y(r,a);if(!ra(l).isDirectory())continue;let c={moduleName:a.replace(".module",""),fieldsJson:"",metaJson:"",moduleHtml:"",moduleCss:""},d=Y(l,"fields.json");b(d)&&(c.fieldsJson=T(d));let u=Y(l,"meta.json");b(u)&&(c.metaJson=T(u));let m=Y(l,"module.html");b(m)&&(c.moduleHtml=T(m));let f=Y(l,"module.css");b(f)&&(c.moduleCss=T(f));let y=Y(l,"module.js");b(y)&&(c.moduleJs=T(y)),c.fieldsJson&&c.moduleHtml&&n.modules.push(c)}return n}listModules(t){let n=Y(t,"modules");return b(n)?new Set(Qe(n).filter(s=>s.endsWith(".module"))):new Set}listDir(t){return b(t)?new Set(Qe(t)):new Set}detectExpectedModules(t,n){let s=Y(t,"templates");if(!b(s))return 0;for(let o of Qe(s))if(!n.has(o)&&!(!o.endsWith(".html")||o==="base.html"||o.startsWith("system")))try{let i=T(Y(s,o));if(i.includes("dnd_area")){let r=i.match(/dnd_module/g);return r?r.length:0}}catch{}return 0}countSourceComponents(t){let n=Y(t,"src");return b(n)?this.countComponentsRecursive(n):0}countComponentsRecursive(t){let n=0;for(let s of Qe(t)){let o=Y(t,s);try{ra(o).isDirectory()&&s!=="node_modules"&&s!==".git"?n+=this.countComponentsRecursive(o):/\.(tsx|jsx)$/.test(s)&&!s.includes(".test.")&&!s.includes(".spec.")&&n++}catch{}}return n}};g();ut();Q();import am from"@anthropic-ai/sdk";import{join as ne,basename as lm}from"path";import{readdirSync as aa}from"fs";var ks=class{client;model="claude-sonnet-4-6";constructor(t){this.client=new am({apiKey:t||process.env.ANTHROPIC_API_KEY})}async convert(t){let{sourceDir:n,themePath:s,conversionGuide:o,onProgress:i}=t,r=ta(o),a=lm(n)||"page",l=a.toLowerCase().replace(/[^a-z0-9]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").slice(0,15);i("css","Analyzing design system...");let c=this.findAndReadCSS(n),d=this.findAndReadTailwind(n),u=await this.complete(r,sa(c,d,l)),m=ne(s,"css",`${l}-theme.css`);L(m,u),i("css-done",`Created css/${l}-theme.css`),i("js","Creating shared JavaScript...");let f=this.findAndReadHooks(n),y=this.findInteractiveComponents(n),h=await this.complete(r,oa(f,y,l)),S=ne(s,"js",`${l}-animations.js`);L(S,h),i("js-done",`Created js/${l}-animations.js`),i("modules","Building modules...");let x=this.findComponents(n),w=[];for(let F=0;F<x.length;F++){let U=x[F],q=U.name.replace(/Section$/,"").replace(/([A-Z])/g," $1").trim();i("module",`Building ${q}.module (${F+1}/${x.length})...`);let _=T(U.path),j=await this.complete(r,na(_,q,`See css/${l}-theme.css`));try{let k=JSON.parse(j),M={moduleName:q,fieldsJson:typeof k.fieldsJson=="string"?k.fieldsJson:JSON.stringify(k.fieldsJson,null,2),metaJson:typeof k.metaJson=="string"?k.metaJson:JSON.stringify(k.metaJson,null,2),moduleHtml:k.moduleHtml||"",moduleCss:k.moduleCss||"",moduleJs:k.moduleJs||void 0},te=ne(s,"modules",`${q}.module`);Ae(te),L(ne(te,"fields.json"),M.fieldsJson),L(ne(te,"meta.json"),M.metaJson),L(ne(te,"module.html"),M.moduleHtml),L(ne(te,"module.css"),M.moduleCss),M.moduleJs&&L(ne(te,"module.js"),M.moduleJs),w.push(M),i("module-done",`${q}.module (${this.countFiles(M)} files)`)}catch{i("module-error",`Failed to parse ${q} \u2014 skipping`)}}i("template","Creating page template...");let v=w.map(F=>F.moduleName),N=await this.complete(r,ia(v,a,l)),O=ne(s,"templates",`lp-${l}.html`);return L(O,N),i("template-done",`Created templates/lp-${l}.html`),{sharedCss:u,sharedJs:h,template:N,modules:w}}async complete(t,n){return(await this.client.messages.create({model:this.model,max_tokens:8192,system:[{type:"text",text:t,cache_control:{type:"ephemeral"}}],messages:[{role:"user",content:n}]})).content.find(i=>i.type==="text")?.text||""}findAndReadCSS(t){let n=[ne(t,"src/index.css"),ne(t,"src/globals.css"),ne(t,"src/app/globals.css"),ne(t,"app/globals.css")];for(let s of n)if(b(s))return T(s);return""}findAndReadTailwind(t){let n=[ne(t,"tailwind.config.ts"),ne(t,"tailwind.config.js"),ne(t,"tailwind.config.mjs")];for(let s of n)if(b(s))return T(s);return""}findAndReadHooks(t){let n=ne(t,"src/hooks");if(!b(n))return"";try{return aa(n).filter(s=>s.endsWith(".ts")||s.endsWith(".tsx")).map(s=>`// ${s}
1716
- ${T(ne(n,s))}`).join(`
2826
+ ${s}`}scanGeneratedFiles(e){let n={sharedCss:"",sharedJs:"",template:"",modules:[]},s=Z(e,"css");if(v(s)){for(let a of mt(s))if(a.endsWith(".css")&&a!=="theme-overrides.css"&&a!=="main.css"&&a!=="style.css"){n.sharedCss=M(Z(s,a));break}}let o=Z(e,"js");if(v(o)){for(let a of mt(o))if(a.endsWith(".js")&&a!=="main.js"){n.sharedJs=M(Z(o,a));break}}let i=Z(e,"templates");if(v(i)){for(let a of mt(i))if(a.startsWith("lp-")&&a.endsWith(".html")){n.template=M(Z(i,a));break}if(!n.template){for(let a of mt(i))if(a.endsWith(".html")&&!Op.has(a)&&!a.startsWith("system")){let l=M(Z(i,a));if(l.includes("dnd_area")){n.template=l;break}}}if(!n.template){for(let a of mt(i))if(a.endsWith(".html")&&!a.startsWith("system")&&a!=="base.html"){let l=M(Z(i,a));if(l.includes("dnd_area")){n.template=l;break}}}}let r=Z(e,"modules");if(v(r))for(let a of mt(r)){if(!a.endsWith(".module"))continue;let l=Z(r,a);if(!La(l).isDirectory())continue;let c={moduleName:a.replace(".module",""),fieldsJson:"",metaJson:"",moduleHtml:"",moduleCss:""},d=Z(l,"fields.json");v(d)&&(c.fieldsJson=M(d));let u=Z(l,"meta.json");v(u)&&(c.metaJson=M(u));let m=Z(l,"module.html");v(m)&&(c.moduleHtml=M(m));let g=Z(l,"module.css");v(g)&&(c.moduleCss=M(g));let h=Z(l,"module.js");v(h)&&(c.moduleJs=M(h)),c.fieldsJson&&c.moduleHtml&&n.modules.push(c)}return n}listModules(e){let n=Z(e,"modules");return v(n)?new Set(mt(n).filter(s=>s.endsWith(".module"))):new Set}listDir(e){return v(e)?new Set(mt(e)):new Set}detectExpectedModules(e,n){let s=Z(e,"templates");if(!v(s))return 0;for(let o of mt(s))if(!n.has(o)&&!(!o.endsWith(".html")||o==="base.html"||o.startsWith("system")))try{let i=M(Z(s,o));if(i.includes("dnd_area")){let r=i.match(/dnd_module/g);return r?r.length:0}}catch{}return 0}countSourceComponents(e){let n=Z(e,"src");return v(n)?this.countComponentsRecursive(n):0}countComponentsRecursive(e){let n=0;for(let s of mt(e)){let o=Z(e,s);try{La(o).isDirectory()&&s!=="node_modules"&&s!==".git"?n+=this.countComponentsRecursive(o):/\.(tsx|jsx)$/.test(s)&&!s.includes(".test.")&&!s.includes(".spec.")&&n++}catch{}}return n}};y();Ue();ne();import Fp from"@anthropic-ai/sdk";import{join as re,basename as jp}from"path";import{readdirSync as Ja}from"fs";var Ws=class{client;model="claude-sonnet-4-6";constructor(e){this.client=new Fp({apiKey:e||process.env.ANTHROPIC_API_KEY})}async convert(e){let{sourceDir:n,themePath:s,conversionGuide:o,onProgress:i}=e,r=Na(o),a=jp(n)||"page",l=a.toLowerCase().replace(/[^a-z0-9]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").slice(0,15);i("css","Analyzing design system...");let c=this.findAndReadCSS(n),d=this.findAndReadTailwind(n),u=await this.complete(r,Fa(c,d,l)),m=re(s,"css",`${l}-theme.css`);J(m,u),i("css-done",`Created css/${l}-theme.css`),i("js","Creating shared JavaScript...");let g=this.findAndReadHooks(n),h=this.findInteractiveComponents(n),f=await this.complete(r,ja(g,h,l)),b=re(s,"js",`${l}-animations.js`);J(b,f),i("js-done",`Created js/${l}-animations.js`),i("modules","Building modules...");let S=this.findComponents(n),x=[];for(let H=0;H<S.length;H++){let L=S[H],V=L.name.replace(/Section$/,"").replace(/([A-Z])/g," $1").trim();i("module",`Building ${V}.module (${H+1}/${S.length})...`);let B=M(L.path),N=await this.complete(r,Oa(B,V,`See css/${l}-theme.css`));try{let T=JSON.parse(N),I={moduleName:V,fieldsJson:typeof T.fieldsJson=="string"?T.fieldsJson:JSON.stringify(T.fieldsJson,null,2),metaJson:typeof T.metaJson=="string"?T.metaJson:JSON.stringify(T.metaJson,null,2),moduleHtml:T.moduleHtml||"",moduleCss:T.moduleCss||"",moduleJs:T.moduleJs||void 0},k=re(s,"modules",`${V}.module`);Ie(k),J(re(k,"fields.json"),I.fieldsJson),J(re(k,"meta.json"),I.metaJson),J(re(k,"module.html"),I.moduleHtml),J(re(k,"module.css"),I.moduleCss),I.moduleJs&&J(re(k,"module.js"),I.moduleJs),x.push(I),i("module-done",`${V}.module (${this.countFiles(I)} files)`)}catch{i("module-error",`Failed to parse ${V} \u2014 skipping`)}}i("template","Creating page template...");let w=x.map(H=>H.moduleName),P=await this.complete(r,Da(w,a,l)),F=re(s,"templates",`lp-${l}.html`);return J(F,P),i("template-done",`Created templates/lp-${l}.html`),{sharedCss:u,sharedJs:f,template:P,modules:x}}async complete(e,n){return(await this.client.messages.create({model:this.model,max_tokens:8192,system:[{type:"text",text:e,cache_control:{type:"ephemeral"}}],messages:[{role:"user",content:n}]})).content.find(i=>i.type==="text")?.text||""}findAndReadCSS(e){let n=[re(e,"src/index.css"),re(e,"src/globals.css"),re(e,"src/app/globals.css"),re(e,"app/globals.css")];for(let s of n)if(v(s))return M(s);return""}findAndReadTailwind(e){let n=[re(e,"tailwind.config.ts"),re(e,"tailwind.config.js"),re(e,"tailwind.config.mjs")];for(let s of n)if(v(s))return M(s);return""}findAndReadHooks(e){let n=re(e,"src/hooks");if(!v(n))return"";try{return Ja(n).filter(s=>s.endsWith(".ts")||s.endsWith(".tsx")).map(s=>`// ${s}
2827
+ ${M(re(n,s))}`).join(`
1717
2828
 
1718
- `)}catch{return""}}findInteractiveComponents(t){let n=this.findComponents(t),s=[];for(let o of n){let i=T(o.path);/carousel|accordion|typing|parallax|embla|swiper|collapsible/i.test(i)&&s.push(`// ${o.name}
2829
+ `)}catch{return""}}findInteractiveComponents(e){let n=this.findComponents(e),s=[];for(let o of n){let i=M(o.path);/carousel|accordion|typing|parallax|embla|swiper|collapsible/i.test(i)&&s.push(`// ${o.name}
1719
2830
  ${i}`)}return s.join(`
1720
2831
 
1721
- `)}findComponents(t){let n=[ne(t,"src/components/landing"),ne(t,"src/components/sections"),ne(t,"src/components")];for(let s of n)if(b(s))try{return aa(s).filter(o=>(o.endsWith(".tsx")||o.endsWith(".jsx"))&&!o.startsWith("ui")&&o!=="index.tsx"&&o!=="index.jsx").map(o=>({name:o.replace(/\.(tsx|jsx)$/,""),path:ne(s,o)}))}catch{continue}return[]}countFiles(t){let n=3;return t.moduleCss&&n++,t.moduleJs&&n++,n}};g();ut();Q();import{spawn as cm}from"child_process";import{join as Pe}from"path";import{readdirSync as As,statSync as dm}from"fs";var Ts=class{async convert(t){let{sourceDir:n,themePath:s,onProgress:o}=t,i=t.conversionGuide||ge(),r=this.buildFullPrompt(n,s,i);return o("convert","Running Gemini CLI (this may take a few minutes)..."),await new Promise((a,l)=>{let c=cm("gemini",["-p",r],{cwd:s,stdio:["pipe","pipe","pipe"],env:{...process.env},shell:!0}),d="",u="";c.stdout.on("data",m=>{d+=m.toString()}),c.stderr.on("data",m=>{u+=m.toString()}),c.on("error",m=>l(new Error(`Gemini CLI failed: ${m.message}`))),c.on("close",m=>{m!==0&&u&&!d?l(new Error(`Gemini CLI failed: ${u}`)):a()}),setTimeout(()=>{c.kill(),l(new Error("Gemini CLI timed out after 10 minutes"))},6e5)}),o("scan","Scanning generated files..."),this.scanGeneratedFiles(s)}buildFullPrompt(t,n,s){return`Read the conversion guide below, then convert the React landing page at ${t} into native HubSpot CMS modules for the theme at ${n}.
2832
+ `)}findComponents(e){let n=[re(e,"src/components/landing"),re(e,"src/components/sections"),re(e,"src/components")];for(let s of n)if(v(s))try{return Ja(s).filter(o=>(o.endsWith(".tsx")||o.endsWith(".jsx"))&&!o.startsWith("ui")&&o!=="index.tsx"&&o!=="index.jsx").map(o=>({name:o.replace(/\.(tsx|jsx)$/,""),path:re(s,o)}))}catch{continue}return[]}countFiles(e){let n=3;return e.moduleCss&&n++,e.moduleJs&&n++,n}};y();Ue();ne();import{spawn as Dp}from"child_process";import{join as Ge}from"path";import{readdirSync as Ks,statSync as Lp}from"fs";var Vs=class{async convert(e){let{sourceDir:n,themePath:s,onProgress:o}=e,i=e.conversionGuide||fe(),r=this.buildFullPrompt(n,s,i);return o("convert","Running Gemini CLI (this may take a few minutes)..."),await new Promise((a,l)=>{let c=Dp("gemini",["-p",r],{cwd:s,stdio:["pipe","pipe","pipe"],env:{...process.env},shell:!0}),d="",u="";c.stdout.on("data",m=>{d+=m.toString()}),c.stderr.on("data",m=>{u+=m.toString()}),c.on("error",m=>l(new Error(`Gemini CLI failed: ${m.message}`))),c.on("close",m=>{m!==0&&u&&!d?l(new Error(`Gemini CLI failed: ${u}`)):a()}),setTimeout(()=>{c.kill(),l(new Error("Gemini CLI timed out after 10 minutes"))},6e5)}),o("scan","Scanning generated files..."),this.scanGeneratedFiles(s)}buildFullPrompt(e,n,s){return`Read the conversion guide below, then convert the React landing page at ${e} into native HubSpot CMS modules for the theme at ${n}.
1722
2833
 
1723
2834
  INSTRUCTIONS:
1724
2835
  1. Analyze all .tsx/.jsx components in the React source
@@ -1733,7 +2844,7 @@ CONVERSION GUIDE:
1733
2844
  ${s}
1734
2845
 
1735
2846
  Do NOT run hs upload \u2014 I will handle that separately.
1736
- Create all files directly in the theme directory.`}scanGeneratedFiles(t){let n={sharedCss:"",sharedJs:"",template:"",modules:[]},s=Pe(t,"css");if(b(s)){for(let a of As(s))if((a.includes("theme")||a.includes("page"))&&a.endsWith(".css")&&a!=="theme-overrides.css"&&a!=="main.css"&&a!=="style.css"){n.sharedCss=T(Pe(s,a));break}}let o=Pe(t,"js");if(b(o)){for(let a of As(o))if((a.includes("animation")||a.includes("page"))&&a.endsWith(".js")&&a!=="main.js"){n.sharedJs=T(Pe(o,a));break}}let i=Pe(t,"templates");if(b(i)){for(let a of As(i))if(a.endsWith(".html")&&!a.startsWith("system")&&a!=="base.html"){let l=T(Pe(i,a));if(l.includes("dnd_area")){n.template=l;break}}}let r=Pe(t,"modules");if(b(r))for(let a of As(r)){if(!a.endsWith(".module"))continue;let l=Pe(r,a);if(!dm(l).isDirectory())continue;let c={moduleName:a.replace(".module",""),fieldsJson:"",metaJson:"",moduleHtml:"",moduleCss:""},d=Pe(l,"fields.json");b(d)&&(c.fieldsJson=T(d));let u=Pe(l,"meta.json");b(u)&&(c.metaJson=T(u));let m=Pe(l,"module.html");b(m)&&(c.moduleHtml=T(m));let f=Pe(l,"module.css");b(f)&&(c.moduleCss=T(f));let y=Pe(l,"module.js");b(y)&&(c.moduleJs=T(y)),c.fieldsJson&&c.moduleHtml&&n.modules.push(c)}return n}};g();ut();Q();import{spawn as um}from"child_process";import{join as Ne}from"path";import{readdirSync as $s,statSync as mm}from"fs";var Is=class{async convert(t){let{sourceDir:n,themePath:s,onProgress:o}=t,i=t.conversionGuide||ge(),r=this.buildFullPrompt(n,s,i);return o("convert","Running OpenAI Codex (this may take a few minutes)..."),await new Promise((a,l)=>{let c=um("codex",["exec","--full-auto",r],{cwd:s,stdio:["pipe","pipe","pipe"],env:{...process.env},shell:!0}),d="",u="";c.stdout.on("data",m=>{d+=m.toString()}),c.stderr.on("data",m=>{u+=m.toString()}),c.on("error",m=>l(new Error(`Codex CLI failed: ${m.message}`))),c.on("close",m=>{m!==0&&u&&!d?l(new Error(`Codex CLI failed: ${u}`)):a()}),setTimeout(()=>{c.kill(),l(new Error("Codex CLI timed out after 10 minutes"))},6e5)}),o("scan","Scanning generated files..."),this.scanGeneratedFiles(s)}buildFullPrompt(t,n,s){return`Read the conversion guide below, then convert the React landing page at ${t} into native HubSpot CMS modules for the theme at ${n}.
2847
+ Create all files directly in the theme directory.`}scanGeneratedFiles(e){let n={sharedCss:"",sharedJs:"",template:"",modules:[]},s=Ge(e,"css");if(v(s)){for(let a of Ks(s))if((a.includes("theme")||a.includes("page"))&&a.endsWith(".css")&&a!=="theme-overrides.css"&&a!=="main.css"&&a!=="style.css"){n.sharedCss=M(Ge(s,a));break}}let o=Ge(e,"js");if(v(o)){for(let a of Ks(o))if((a.includes("animation")||a.includes("page"))&&a.endsWith(".js")&&a!=="main.js"){n.sharedJs=M(Ge(o,a));break}}let i=Ge(e,"templates");if(v(i)){for(let a of Ks(i))if(a.endsWith(".html")&&!a.startsWith("system")&&a!=="base.html"){let l=M(Ge(i,a));if(l.includes("dnd_area")){n.template=l;break}}}let r=Ge(e,"modules");if(v(r))for(let a of Ks(r)){if(!a.endsWith(".module"))continue;let l=Ge(r,a);if(!Lp(l).isDirectory())continue;let c={moduleName:a.replace(".module",""),fieldsJson:"",metaJson:"",moduleHtml:"",moduleCss:""},d=Ge(l,"fields.json");v(d)&&(c.fieldsJson=M(d));let u=Ge(l,"meta.json");v(u)&&(c.metaJson=M(u));let m=Ge(l,"module.html");v(m)&&(c.moduleHtml=M(m));let g=Ge(l,"module.css");v(g)&&(c.moduleCss=M(g));let h=Ge(l,"module.js");v(h)&&(c.moduleJs=M(h)),c.fieldsJson&&c.moduleHtml&&n.modules.push(c)}return n}};y();Ue();ne();import{spawn as Jp}from"child_process";import{join as We}from"path";import{readdirSync as zs,statSync as Bp}from"fs";var Ys=class{async convert(e){let{sourceDir:n,themePath:s,onProgress:o}=e,i=e.conversionGuide||fe(),r=this.buildFullPrompt(n,s,i);return o("convert","Running OpenAI Codex (this may take a few minutes)..."),await new Promise((a,l)=>{let c=Jp("codex",["exec","--full-auto",r],{cwd:s,stdio:["pipe","pipe","pipe"],env:{...process.env},shell:!0}),d="",u="";c.stdout.on("data",m=>{d+=m.toString()}),c.stderr.on("data",m=>{u+=m.toString()}),c.on("error",m=>l(new Error(`Codex CLI failed: ${m.message}`))),c.on("close",m=>{m!==0&&u&&!d?l(new Error(`Codex CLI failed: ${u}`)):a()}),setTimeout(()=>{c.kill(),l(new Error("Codex CLI timed out after 10 minutes"))},6e5)}),o("scan","Scanning generated files..."),this.scanGeneratedFiles(s)}buildFullPrompt(e,n,s){return`Read the conversion guide below, then convert the React landing page at ${e} into native HubSpot CMS modules for the theme at ${n}.
1737
2848
 
1738
2849
  INSTRUCTIONS:
1739
2850
  1. Analyze all .tsx/.jsx components in the React source
@@ -1748,15 +2859,15 @@ CONVERSION GUIDE:
1748
2859
  ${s}
1749
2860
 
1750
2861
  Do NOT run hs upload \u2014 I will handle that separately.
1751
- Create all files directly in the theme directory.`}scanGeneratedFiles(t){let n={sharedCss:"",sharedJs:"",template:"",modules:[]},s=Ne(t,"css");if(b(s)){for(let a of $s(s))if((a.includes("theme")||a.includes("page"))&&a.endsWith(".css")&&a!=="theme-overrides.css"&&a!=="main.css"&&a!=="style.css"){n.sharedCss=T(Ne(s,a));break}}let o=Ne(t,"js");if(b(o)){for(let a of $s(o))if((a.includes("animation")||a.includes("page"))&&a.endsWith(".js")&&a!=="main.js"){n.sharedJs=T(Ne(o,a));break}}let i=Ne(t,"templates");if(b(i)){for(let a of $s(i))if(a.endsWith(".html")&&!a.startsWith("system")&&a!=="base.html"){let l=T(Ne(i,a));if(l.includes("dnd_area")){n.template=l;break}}}let r=Ne(t,"modules");if(b(r))for(let a of $s(r)){if(!a.endsWith(".module"))continue;let l=Ne(r,a);if(!mm(l).isDirectory())continue;let c={moduleName:a.replace(".module",""),fieldsJson:"",metaJson:"",moduleHtml:"",moduleCss:""},d=Ne(l,"fields.json");b(d)&&(c.fieldsJson=T(d));let u=Ne(l,"meta.json");b(u)&&(c.metaJson=T(u));let m=Ne(l,"module.html");b(m)&&(c.moduleHtml=T(m));let f=Ne(l,"module.css");b(f)&&(c.moduleCss=T(f));let y=Ne(l,"module.js");b(y)&&(c.moduleJs=T(y)),c.fieldsJson&&c.moduleHtml&&n.modules.push(c)}return n}};ut();Q();function pm(e,t){switch(e){case"claude-code":return new Cs(t);case"gemini-cli":return new Ts;case"codex-cli":return new Is;case"api":return new ks}}async function Es(e){await se("Converting React to HubSpot Modules"),await Ze(`AI will now analyze your React code and create
1752
- HubSpot-native modules. This takes 2-5 minutes.`,"AI Conversion");let t=pm(e.aiEngine,e.model),n=ge(),s=await Ce();s.start("Starting AI conversion...");let o=Date.now(),i=await t.convert({sourceDir:e.sourceDir,themePath:e.themePath,conversionGuide:n,onProgress:(y,h)=>{y==="created"?H(h):s.message(h)}}),r=((Date.now()-o)/1e3).toFixed(0);s.stop(`AI conversion complete (${r}s)`);let a=fm(e.themePath);for(let y of a)H(`Auto-fixed: ${y}`);let l=gm(e.themePath,i),c=[];for(let y of l){let h=y.passed?"\u2705":"\u274C",S=y.passed?"":y.critical?" (CRITICAL)":" (cosmetic)";c.push(`${h} ${y.label}${S}`)}let d=l.filter(y=>y.passed).length;c.push(`
1753
- ${d}/${l.length} checks passed`),await Ze(c.join(`
1754
- `),"Conversion Checklist");let u=l.filter(y=>!y.passed&&y.critical),m=l.filter(y=>!y.passed&&!y.critical);if(u.length>0){if(z(`${u.length} critical issue(s) \u2014 upload will likely fail:
1755
- `+u.map(h=>` - ${h.label}`).join(`
1756
- `)),!await fe({message:"Continue with upload anyway?",initialValue:!1}))throw new Error("Conversion aborted due to critical checklist failures.")}else m.length>0&&Z(`${m.length} non-critical issue(s) \u2014 page will work but may look incomplete:
1757
- `+m.map(y=>` - ${y.label}`).join(`
1758
- `));let f=je(e.themePath,"..","vibespot-conversion.log");return b(f)&&(await fe({message:"Keep conversion log file for debugging?",initialValue:!1})?H(`Log saved: ${f}`):la(f)),await oe("Files ready for upload!"),i}function fm(e){let t=[];hm(e),ym(e);let n=je(e,"modules");if(b(n))for(let o of En(n)){if(!o.endsWith(".module"))continue;let i=je(n,o,"fields.json");if(!b(i))continue;let r=o.replace(".module",""),a=T(i),l=!1;a.includes('"textarea"')&&(a=a.replace(/"textarea"/g,'"text"'),l=!0,t.push(`${r}: "textarea" \u2192 "text"`)),/"name":\s*"name"/.test(a)&&(a=a.replace(/"name":\s*"name"/g,'"name": "item_name"'),l=!0,t.push(`${r}: reserved field name "name" \u2192 "item_name"`));try{let d=JSON.parse(a),u=!1;ca(d)&&(u=!0,t.push(`${r}: fixed choice field format`)),da(d)&&(u=!0,t.push(`${r}: fixed link field default value`)),u&&(a=JSON.stringify(d,null,2)+`
1759
- `,l=!0)}catch{t.push(`${r}: fields.json has invalid JSON \u2014 manual fix needed`)}l&&L(i,a);let c=je(n,o,"module.html");if(b(c)){let d=T(c);d.includes("now()")&&(d=d.replace(/now\(\)/g,"local_dt"),L(c,d),t.push(`${r}: now() \u2192 local_dt`))}}let s=je(e,"templates");if(b(s))for(let o of En(s)){if(!o.endsWith(".html"))continue;let i=je(s,o),r=T(i);(r.includes("hubdb_table")||r.includes("hubdb_table_rows"))&&(la(i),t.push(`Removed ${o} (HubDB requires CMS Hub Pro/Enterprise)`))}return t}function ca(e){let t=!1;for(let n of e){if(typeof n!="object"||n===null)continue;let s=n;s.type==="choice"&&Array.isArray(s.choices)&&s.choices.some(i=>typeof i=="string")&&(s.choices=s.choices.map(i=>{if(typeof i=="string"){let r=i.charAt(0).toUpperCase()+i.slice(1);return[i,r]}return i}),t=!0),Array.isArray(s.children)&&ca(s.children)&&(t=!0)}return t}function da(e){let t=!1;for(let n of e){if(typeof n!="object"||n===null)continue;let s=n;if(s.type==="link"){let o=s.default;if(typeof o=="string"||o===void 0||o===null||typeof o=="object"&&!o.url){let r=typeof o=="string"?o:"";s.default={url:{href:r,type:"EXTERNAL"},open_in_new_tab:!1,no_follow:!1},t=!0}}Array.isArray(s.children)&&da(s.children)&&(t=!0)}return t}function gm(e,t){let n=[],s=t.modules.length;n.push({label:`Modules created (${s})`,passed:s>0,critical:!0});let o=!0;for(let u of t.modules)if(u.fieldsJson.includes('"textarea"')||/"name":\s*"name"/.test(u.fieldsJson)){o=!1;break}n.push({label:"fields.json valid (no textarea, no reserved names)",passed:s>0&&o,critical:!0});let i=t.modules.every(u=>u.moduleHtml.length>0);n.push({label:"module.html created for each module",passed:s>0&&i,critical:!0});let r=t.modules.filter(u=>!u.moduleCss).map(u=>u.moduleName),a=r.length===0;n.push({label:a?"module.css created for each module":`module.css missing for: ${r.join(", ")}`,passed:s>0&&a,critical:!1});let l=t.modules.some(u=>u.fieldsJson.includes('"STYLE"'));n.push({label:"Style tab fields (color pickers)",passed:l,critical:!1}),n.push({label:"Shared CSS with design system variables",passed:t.sharedCss.length>50,critical:!1}),n.push({label:"Shared JS for scroll animations",passed:t.sharedJs.length>50,critical:!1}),n.push({label:"Page template with dnd_area",passed:t.template.length>0&&t.template.includes("dnd_area"),critical:!0});let c=je(e,"templates"),d=!1;if(b(c))for(let u of En(c)){if(!u.endsWith(".html")||u==="base.html"||u.startsWith("system"))continue;let m=T(je(c,u));if(m.includes("dnd_area")&&/templateType\s*:\s*page/i.test(m)){d=!0;break}}return n.push({label:"Template annotations (templateType: page)",passed:d,critical:!0}),n}function hm(e){let t=je(e,"templates");if(b(t))for(let n of En(t)){if(!n.endsWith(".html")||n==="base.html"||n.startsWith("system"))continue;let s=je(t,n),o=T(s);if(!o.includes("dnd_area")&&!o.includes("extends"))continue;let i=/templateType\s*:\s*page/i.test(o),r=/isAvailableForNewContent\s*:\s*true/i.test(o);if(i&&r)continue;let a=n.replace(".html","").replace(/[-_]/g," ").replace(/\b\w/g,l=>l.toUpperCase());if(o.includes("<!--")&&o.indexOf("-->")<200){let l=o.indexOf("-->"),c=o.slice(0,l);i||(c+=`
2862
+ Create all files directly in the theme directory.`}scanGeneratedFiles(e){let n={sharedCss:"",sharedJs:"",template:"",modules:[]},s=We(e,"css");if(v(s)){for(let a of zs(s))if((a.includes("theme")||a.includes("page"))&&a.endsWith(".css")&&a!=="theme-overrides.css"&&a!=="main.css"&&a!=="style.css"){n.sharedCss=M(We(s,a));break}}let o=We(e,"js");if(v(o)){for(let a of zs(o))if((a.includes("animation")||a.includes("page"))&&a.endsWith(".js")&&a!=="main.js"){n.sharedJs=M(We(o,a));break}}let i=We(e,"templates");if(v(i)){for(let a of zs(i))if(a.endsWith(".html")&&!a.startsWith("system")&&a!=="base.html"){let l=M(We(i,a));if(l.includes("dnd_area")){n.template=l;break}}}let r=We(e,"modules");if(v(r))for(let a of zs(r)){if(!a.endsWith(".module"))continue;let l=We(r,a);if(!Bp(l).isDirectory())continue;let c={moduleName:a.replace(".module",""),fieldsJson:"",metaJson:"",moduleHtml:"",moduleCss:""},d=We(l,"fields.json");v(d)&&(c.fieldsJson=M(d));let u=We(l,"meta.json");v(u)&&(c.metaJson=M(u));let m=We(l,"module.html");v(m)&&(c.moduleHtml=M(m));let g=We(l,"module.css");v(g)&&(c.moduleCss=M(g));let h=We(l,"module.js");v(h)&&(c.moduleJs=M(h)),c.fieldsJson&&c.moduleHtml&&n.modules.push(c)}return n}};Ue();ne();Ye();function Hp(t,e){switch(t){case"claude-code":return new Gs(e);case"gemini-cli":return new Vs;case"codex-cli":return new Ys;case"api":return new Ws}}async function qs(t){await me("Converting React to HubSpot Modules"),await ut(`AI will now analyze your React code and create
2863
+ HubSpot-native modules. This takes 2-5 minutes.`,"AI Conversion");let e=Hp(t.aiEngine,t.model),n=fe(),s=await Pe();s.start("Starting AI conversion...");let o=Date.now(),i=await e.convert({sourceDir:t.sourceDir,themePath:t.themePath,conversionGuide:n,onProgress:(h,f)=>{h==="created"?G(f):s.message(f)}}),r=((Date.now()-o)/1e3).toFixed(0);s.stop(`AI conversion complete (${r}s)`);let a=Up(t.themePath);for(let h of a)G(`Auto-fixed: ${h}`);let l=Gp(t.themePath,i),c=[];for(let h of l){let f=h.passed?"\u2705":"\u274C",b=h.passed?"":h.critical?" (CRITICAL)":" (cosmetic)";c.push(`${f} ${h.label}${b}`)}let d=l.filter(h=>h.passed).length;c.push(`
2864
+ ${d}/${l.length} checks passed`),await ut(c.join(`
2865
+ `),"Conversion Checklist");let u=l.filter(h=>!h.passed&&h.critical),m=l.filter(h=>!h.passed&&!h.critical);if(u.length>0){if(z(`${u.length} critical issue(s) \u2014 upload will likely fail:
2866
+ `+u.map(f=>` - ${f.label}`).join(`
2867
+ `)),!await Ae({message:"Continue with upload anyway?",initialValue:!1}))throw new Error("Conversion aborted due to critical checklist failures.")}else m.length>0&&ee(`${m.length} non-critical issue(s) \u2014 page will work but may look incomplete:
2868
+ `+m.map(h=>` - ${h.label}`).join(`
2869
+ `));let g=qe(t.themePath,"..","vibespot-conversion.log");return v(g)&&(await Ae({message:"Keep conversion log file for debugging?",initialValue:!1})?G(`Log saved: ${g}`):Ba(g)),await pe("Files ready for upload!"),i}function Up(t){let e=[];Wp(t),Kp(t);let n=qe(t,"modules");if(v(n))for(let o of Gn(n)){if(!o.endsWith(".module"))continue;let i=qe(n,o,"fields.json");if(!v(i))continue;let r=o.replace(".module",""),a=M(i),l=!1;a.includes('"textarea"')&&(a=a.replace(/"textarea"/g,'"text"'),l=!0,e.push(`${r}: "textarea" \u2192 "text"`)),/"name":\s*"name"/.test(a)&&(a=a.replace(/"name":\s*"name"/g,'"name": "item_name"'),l=!0,e.push(`${r}: reserved field name "name" \u2192 "item_name"`));try{let d=JSON.parse(a),u=!1;Ha(d)&&(u=!0,e.push(`${r}: fixed choice field format`)),Ua(d)&&(u=!0,e.push(`${r}: fixed link field default value`)),u&&(a=JSON.stringify(d,null,2)+`
2870
+ `,l=!0)}catch{e.push(`${r}: fields.json has invalid JSON \u2014 manual fix needed`)}l&&J(i,a);let c=qe(n,o,"module.html");if(v(c)){let d=M(c);d.includes("now()")&&(d=d.replace(/now\(\)/g,"local_dt"),J(c,d),e.push(`${r}: now() \u2192 local_dt`))}}let s=qe(t,"templates");if(v(s))for(let o of Gn(s)){if(!o.endsWith(".html"))continue;let i=qe(s,o),r=M(i);(r.includes("hubdb_table")||r.includes("hubdb_table_rows"))&&(Ba(i),e.push(`Removed ${o} (HubDB requires CMS Hub Pro/Enterprise)`))}return e}function Ha(t){let e=!1;for(let n of t){if(typeof n!="object"||n===null)continue;let s=n;s.type==="choice"&&Array.isArray(s.choices)&&s.choices.some(i=>typeof i=="string")&&(s.choices=s.choices.map(i=>{if(typeof i=="string"){let r=i.charAt(0).toUpperCase()+i.slice(1);return[i,r]}return i}),e=!0),Array.isArray(s.children)&&Ha(s.children)&&(e=!0)}return e}function Ua(t){let e=!1;for(let n of t){if(typeof n!="object"||n===null)continue;let s=n;if(s.type==="link"){let o=s.default;if(typeof o=="string"||o===void 0||o===null||typeof o=="object"&&!o.url){let r=typeof o=="string"?o:"";s.default={url:{href:r,type:"EXTERNAL"},open_in_new_tab:!1,no_follow:!1},e=!0}}Array.isArray(s.children)&&Ua(s.children)&&(e=!0)}return e}function Gp(t,e){let n=[],s=e.modules.length;n.push({label:`Modules created (${s})`,passed:s>0,critical:!0});let o=!0;for(let u of e.modules)if(u.fieldsJson.includes('"textarea"')||/"name":\s*"name"/.test(u.fieldsJson)){o=!1;break}n.push({label:"fields.json valid (no textarea, no reserved names)",passed:s>0&&o,critical:!0});let i=e.modules.every(u=>u.moduleHtml.length>0);n.push({label:"module.html created for each module",passed:s>0&&i,critical:!0});let r=e.modules.filter(u=>!u.moduleCss).map(u=>u.moduleName),a=r.length===0;n.push({label:a?"module.css created for each module":`module.css missing for: ${r.join(", ")}`,passed:s>0&&a,critical:!1});let l=e.modules.some(u=>u.fieldsJson.includes('"STYLE"'));n.push({label:"Style tab fields (color pickers)",passed:l,critical:!1}),n.push({label:"Shared CSS with design system variables",passed:e.sharedCss.length>50,critical:!1}),n.push({label:"Shared JS for scroll animations",passed:e.sharedJs.length>50,critical:!1}),n.push({label:"Page template with dnd_area",passed:e.template.length>0&&e.template.includes("dnd_area"),critical:!0});let c=qe(t,"templates"),d=!1;if(v(c))for(let u of Gn(c)){if(!u.endsWith(".html")||u==="base.html"||u.startsWith("system"))continue;let m=M(qe(c,u));if(m.includes("dnd_area")&&/templateType\s*:\s*page/i.test(m)){d=!0;break}}return n.push({label:"Template annotations (templateType: page)",passed:d,critical:!0}),n}function Wp(t){let e=qe(t,"templates");if(v(e))for(let n of Gn(e)){if(!n.endsWith(".html")||n==="base.html"||n.startsWith("system"))continue;let s=qe(e,n),o=M(s);if(!o.includes("dnd_area")&&!o.includes("extends"))continue;let i=/templateType\s*:\s*page/i.test(o),r=/isAvailableForNewContent\s*:\s*true/i.test(o);if(i&&r)continue;let a=n.replace(".html","").replace(/[-_]/g," ").replace(/\b\w/g,l=>l.toUpperCase());if(o.includes("<!--")&&o.indexOf("-->")<200){let l=o.indexOf("-->"),c=o.slice(0,l);i||(c+=`
1760
2871
  templateType: page`),r||(c+=`
1761
2872
  isAvailableForNewContent: true`),/label\s*:/i.test(c)||(c+=`
1762
2873
  label: ${a}`),o=c+o.slice(l)}else o=`<!--
@@ -1764,69 +2875,31 @@ ${d}/${l.length} checks passed`),await Ze(c.join(`
1764
2875
  isAvailableForNewContent: true
1765
2876
  label: ${a}
1766
2877
  -->
1767
- `+o;L(s,o),H(`Template "${n}" \u2014 annotations verified`)}}function ym(e){let t=je(e,"modules");if(b(t))for(let n of En(t)){if(!n.endsWith(".module"))continue;let s=je(t,n,"meta.json");if(b(s))try{let o=JSON.parse(T(s)),i=!1;(!o.host_template_types||!o.host_template_types.includes("PAGE"))&&(o.host_template_types=["PAGE"],i=!0),o.is_available_for_new_content||(o.is_available_for_new_content=!0,i=!0),i&&L(s,JSON.stringify(o,null,2)+`
1768
- `)}catch{}}}g();Et();import{join as va,basename as $m}from"path";g();Q();import{join as he}from"path";import{readdirSync as mt,rmSync as bm}from"fs";function Ms(e){let t=[];for(let n of e){let s=`${n.message}${n.detail?` \u2014 ${n.detail}`:""}`,o=!1;/textarea|unknown.*field.*type/i.test(s)&&(o=!0),/reserved.*name|missing field name|field null/i.test(s)&&(o=!0),/could not resolve.*now/i.test(s)&&(o=!0),/hubdb|do not have access/i.test(s)&&(o=!0),/invalid default value|link.*invalid|deserializ/i.test(s)&&(o=!0),/color.*invalid/i.test(s)&&(o=!0),t.push({file:n.file||"unknown",message:s,fixable:o})}return t}function Rs(e){let t=[];if(/textarea.*not.*valid|unknown.*field.*type/i.test(e)){let n=e.match(/(?:in|file:?)\s+(\S+fields\.json)/i);t.push({file:n?.[1]||"fields.json",message:'"textarea" is not a valid field type',fixable:!0})}if(/missing field name|field null/i.test(e)){let n=e.match(/(?:in|file:?)\s+(\S+fields\.json)/i);t.push({file:n?.[1]||"fields.json",message:'"name" is a reserved field name',fixable:!0})}if(/could not resolve.*now/i.test(e)&&t.push({file:"module.html",message:"now() is not a valid HubL function",fixable:!0}),/hubdb|do not have access to hubdb/i.test(e)&&t.push({file:"templates",message:"HubDB requires CMS Hub Pro/Enterprise",fixable:!0}),/invalid default value|link.*field.*invalid/i.test(e)){let n=e.match(/field.*?(\w+)\s+has an invalid/i);t.push({file:n?.[1]||"fields.json",message:"Link field has invalid default value",fixable:!0})}if(/failed to deserialize/i.test(e)){let n=e.match(/file '([^']+)'/i);t.push({file:n?.[1]||"fields.json",message:"fields.json deserialization error",fixable:!0})}return/format for the color value is invalid/i.test(e)&&t.push({file:"fields.json",message:"Color field has invalid format (rgba/rgb/named \u2014 must be hex)",fixable:!0}),t}function _s(e){let t=[];return ma(e)&&t.push("textarea \u2192 text"),pa(e)&&t.push("name \u2192 item_name"),fa(e)&&t.push("now() \u2192 local_dt"),ga(e)&&t.push("Removed HubDB templates"),ha(e)&&t.push("Fixed link field defaults"),ya(e)&&t.push("Fixed rgba/invalid color values \u2192 hex"),Sm(e)&&t.push("Stripped CDN @import statements"),t}function ua(e,t){return t.message.includes("textarea")?ma(e):t.message.includes("reserved field name")?pa(e):t.message.includes("now()")?fa(e):t.message.includes("HubDB")?ga(e):t.message.includes("invalid default value")||t.message.includes("deserialization")?ha(e):t.message.includes("invalid format")&&t.message.includes("color")?ya(e):!1}function ma(e){let t=!1,n=he(e,"modules");if(!b(n))return!1;for(let s of mt(n)){if(!s.endsWith(".module"))continue;let o=he(n,s,"fields.json");if(!b(o))continue;let i=T(o);i.includes('"textarea"')&&(i=i.replace(/"textarea"/g,'"text"'),L(o,i),t=!0)}return t}function pa(e){let t=!1,n=he(e,"modules");if(!b(n))return!1;for(let s of mt(n)){if(!s.endsWith(".module"))continue;let o=he(n,s,"fields.json");if(!b(o))continue;let i=T(o);/"name":\s*"name"/g.test(i)&&(i=i.replace(/"name":\s*"name"/g,'"name": "item_name"'),L(o,i),t=!0)}return t}function fa(e){let t=!1,n=he(e,"modules");if(!b(n))return!1;for(let s of mt(n)){if(!s.endsWith(".module"))continue;let o=he(n,s,"module.html");if(!b(o))continue;let i=T(o);i.includes("now()")&&(i=i.replace(/now\(\)/g,"local_dt"),L(o,i),t=!0)}return t}function ga(e){let t=!1,n=he(e,"templates");if(!b(n))return!1;for(let s of mt(n)){if(!s.endsWith(".html"))continue;let o=he(n,s),i=T(o);(i.includes("hubdb_table")||i.includes("hubdb_table_rows"))&&(bm(o),t=!0)}return t}function ha(e){let t=!1,n=he(e,"modules");if(!b(n))return!1;for(let s of mt(n)){if(!s.endsWith(".module"))continue;let o=he(n,s,"fields.json");if(b(o))try{let i=JSON.parse(T(o));Sa(i)&&(L(o,JSON.stringify(i,null,2)+`
1769
- `),t=!0)}catch{}}return t}function Sm(e){let t=!1,n=he(e,"css");if(b(n))for(let o of mt(n)){if(!o.endsWith(".css"))continue;let i=he(n,o),r=T(i),a=r.replace(/@import\s+url\(['"]?https?:\/\/[^)]+['"]?\)\s*;?/gi,"");a!==r&&(L(i,a),t=!0)}let s=he(e,"modules");if(b(s))for(let o of mt(s)){if(!o.endsWith(".module"))continue;let i=he(s,o,"module.css");if(!b(i))continue;let r=T(i),a=r.replace(/@import\s+url\(['"]?https?:\/\/[^)]+['"]?\)\s*;?/gi,"");a!==r&&(L(i,a),t=!0)}if(b(s))for(let o of mt(s)){if(!o.endsWith(".module"))continue;let i=he(s,o,"module.html");if(!b(i))continue;let r=T(i),a=r.replace(/<link[^>]+href=['"]https?:\/\/[^'"]+['"][^>]*>/gi,"");a!==r&&(L(i,a),t=!0)}return t}function ya(e){let t=!1,n=he(e,"modules");if(!b(n))return!1;for(let s of mt(n)){if(!s.endsWith(".module"))continue;let o=he(n,s,"fields.json");if(b(o))try{let i=JSON.parse(T(o));ba(i)&&(L(o,JSON.stringify(i,null,2)+`
1770
- `),t=!0)}catch{}}return t}function ba(e){let t=!1;for(let n of e){if(typeof n!="object"||n===null)continue;let s=n;if(s.type==="color"&&s.default&&typeof s.default=="object"){let o=s.default,i=o.color;if(typeof i=="string"&&!xm(i)){let r=vm(i);r&&(o.color=r.hex,r.opacity!==void 0&&(o.opacity=r.opacity),t=!0)}}Array.isArray(s.children)&&ba(s.children)&&(t=!0)}return t}function xm(e){return/^#[0-9a-fA-F]{6}$/.test(e)}function vm(e){let t=e.match(/^#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])$/);if(t)return{hex:`#${t[1]}${t[1]}${t[2]}${t[2]}${t[3]}${t[3]}`};let n=e.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([\d.]+))?\s*\)/i);if(n){let i=Math.min(255,parseInt(n[1])),r=Math.min(255,parseInt(n[2])),a=Math.min(255,parseInt(n[3])),l=`#${i.toString(16).padStart(2,"0")}${r.toString(16).padStart(2,"0")}${a.toString(16).padStart(2,"0")}`,c=n[4]!==void 0?Math.round(parseFloat(n[4])*100):void 0;return{hex:l,opacity:c}}let s={white:"#ffffff",black:"#000000",red:"#ff0000",green:"#008000",blue:"#0000ff",yellow:"#ffff00",orange:"#ffa500",purple:"#800080",gray:"#808080",grey:"#808080",transparent:"#000000"},o=e.toLowerCase().trim();return s[o]?{hex:s[o],opacity:o==="transparent"?0:void 0}:null}function Sa(e){let t=!1;for(let n of e){if(typeof n!="object"||n===null)continue;let s=n;if(s.type==="link"){let o=s.default;if(typeof o=="string"||o===void 0||o===null||typeof o=="object"&&!o.url){let r=typeof o=="string"?o:"";s.default={url:{href:r,type:"EXTERNAL"},open_in_new_tab:!1,no_follow:!1},t=!0}}Array.isArray(s.children)&&Sa(s.children)&&(t=!0)}return t}X();g();Rt();Rt();import{readdirSync as wm}from"fs";import{join as Cm,relative as km}from"path";var Am=new Set([".git","node_modules",".vibespot",".DS_Store"]);function xa(e){let t=[];for(let n of wm(e,{withFileTypes:!0})){if(Am.has(n.name)||n.name.startsWith(".")&&n.name!==".gitkeep")continue;let s=Cm(e,n.name);n.isDirectory()?t.push(...xa(s)):n.isFile()&&t.push(s)}return t}async function Tm(e,t,n){let s=0;async function o(){for(;s<e.length;){let r=s++;await n(e[r])}}let i=Array.from({length:Math.min(t,e.length)},()=>o());await Promise.all(i)}async function Ps(e,t,n,s={}){let o=s.concurrency??5,i=xa(t),r=i.length,a=0,l=0,c=[];return await Tm(i,o,async d=>{let u=km(t,d).replace(/\\/g,"/"),m=`${n}/${u}`;s.onFileStart?.(u);let f=await Gr(e,m,d);if(f.success)a++,s.onFileComplete?.(u);else{l++;let y={file:u,status:f.error?.status||0,message:f.error?.message||"Unknown error",category:f.error?.category,detail:f.error?.detail};c.push(y),s.onFileError?.(u,y)}s.onProgress?.(a+l,r)}),{success:l===0,uploaded:a,failed:l,total:r,errors:c}}function Im(e){return(e.match(/^Uploaded file /gm)||[]).length}async function Xt(e){await se("Uploading to HubSpot");let t=$m(e)||e,n=R(),s=$e(),o=n.hubspotUploadMode!=="cli"&&!!s,i=await Ce(),r=3;for(let a=1;a<=r;a++){i.start(a===1?"Uploading theme...":`Retrying upload (attempt ${a}/${r})...`);let l=[],c=0,d=!1;if(o){let m=await Ps(s,e,t,{onFileComplete:()=>{c++}});d=m.success,d?c=m.uploaded:l=Ms(m.errors)}else{let m=D(`hs cms upload "${e}" "${t}"`,{cwd:va(e,"..")}),f=[m.stdout,m.stderr].filter(Boolean).join(`
1771
- `);c=Im(f),d=m.success,d||(l=Rs(f))}if(d)return i.stop(`All files uploaded! (${c} files)`),await oe("Upload complete!"),!0;if(c>0?i.stop(`${c} files uploaded, but some errors occurred`):i.stop("Upload failed"),l.length===0){if(z("Upload failed with unknown error."),c>0&&(Z(`Most files uploaded successfully. The theme may already be usable in HubSpot.
1772
- You can check your HubSpot Design Manager to verify.`),await fe({message:"Continue anyway (theme is likely uploaded)?",initialValue:!0})))return!0;if(a<r){if(!await fe({message:"Try uploading again?"}))break;continue}break}let u=!1;for(let m of l)m.fixable?ua(e,m)?(H(`Auto-fixed: ${m.message}`),u=!0):Z(`Could not auto-fix: ${m.message}`):z(m.message);if(!(u&&a<r)){if(c>0&&(Z(`${c} files uploaded successfully despite errors.
1773
- The theme may work \u2014 check HubSpot Design Manager.`),await fe({message:"Continue anyway?",initialValue:!0})))return!0;if(!u){if(i.start("Cleaning up stuck modules..."),o)try{await zo(s,`${t}/modules`)}catch{}else D(`hs cms delete "${t}/modules"`,{cwd:va(e,"..")});i.stop("Cleaned up modules, retrying...")}}}return z("Upload failed after multiple attempts."),!1}g();import{execFileSync as ni}from"child_process";import{rmSync as Em}from"fs";import{basename as wa}from"path";Q();async function Ca(e){let{portalId:t,sourceDir:n,themePath:s,wasCloned:o}=e;await se("You're all set!");let r=vn(t)==="eu1"?"app-eu1.hubspot.com":"app.hubspot.com";if(await Ze(`Your React page has been converted and uploaded to HubSpot.
2878
+ `+o;J(s,o),G(`Template "${n}" \u2014 annotations verified`)}}function Kp(t){let e=qe(t,"modules");if(v(e))for(let n of Gn(e)){if(!n.endsWith(".module"))continue;let s=qe(e,n,"meta.json");if(v(s))try{let o=JSON.parse(M(s)),i=!1;(!o.host_template_types||!o.host_template_types.includes("PAGE"))&&(o.host_template_types=["PAGE"],i=!0),o.is_available_for_new_content||(o.is_available_for_new_content=!0,i=!0),i&&J(s,JSON.stringify(o,null,2)+`
2879
+ `)}catch{}}}y();Jt();Ye();eo();Q();Ai();import{join as nl,basename as ng}from"path";function sg(t){return(t.match(/^Uploaded file /gm)||[]).length}async function cn(t){await me("Uploading to HubSpot");let e=ng(t)||t,n=O(),s=Fe(),o=n.hubspotUploadMode!=="cli"&&!!s,i=await Pe(),r=3;for(let a=1;a<=r;a++){i.start(a===1?"Uploading theme...":`Retrying upload (attempt ${a}/${r})...`);let l=[],c=0,d=!1;if(o){let m=await to(s,t,e,{onFileComplete:()=>{c++}});d=m.success,d?c=m.uploaded:l=Xs(m.errors)}else{let m=te(`hs cms upload "${t}" "${e}"`,{cwd:nl(t,"..")}),g=[m.stdout,m.stderr].filter(Boolean).join(`
2880
+ `);c=sg(g),d=m.success,d||(l=Zs(g))}if(d)return i.stop(`All files uploaded! (${c} files)`),await pe("Upload complete!"),!0;if(c>0?i.stop(`${c} files uploaded, but some errors occurred`):i.stop("Upload failed"),l.length===0){if(z("Upload failed with unknown error."),c>0&&(ee(`Most files uploaded successfully. The theme may already be usable in HubSpot.
2881
+ You can check your HubSpot Design Manager to verify.`),await Ae({message:"Continue anyway (theme is likely uploaded)?",initialValue:!0})))return!0;if(a<r){if(!await Ae({message:"Try uploading again?"}))break;continue}break}let u=!1;for(let m of l)m.fixable?Ga(t,m)?(G(`Auto-fixed: ${m.message}`),u=!0):ee(`Could not auto-fix: ${m.message}`):z(m.message);if(!(u&&a<r)){if(c>0&&(ee(`${c} files uploaded successfully despite errors.
2882
+ The theme may work \u2014 check HubSpot Design Manager.`),await Ae({message:"Continue anyway?",initialValue:!0})))return!0;if(!u){if(i.start("Cleaning up stuck modules..."),o)try{await bi(s,`${e}/modules`)}catch{}else te(`hs cms delete "${e}/modules"`,{cwd:nl(t,"..")});i.stop("Cleaned up modules, retrying...")}}}return z("Upload failed after multiple attempts."),!1}y();Ye();at();Ht();ne();import{execFileSync as $i}from"child_process";import{rmSync as og}from"fs";import{basename as sl}from"path";async function ol(t){let{portalId:e,sourceDir:n,themePath:s,wasCloned:o}=t;await me("You're all set!");let r=Rn(e)==="eu1"?"app-eu1.hubspot.com":"app.hubspot.com";if(await ut(`Your React page has been converted and uploaded to HubSpot.
1774
2883
  The theme and modules are now in your account, but you still
1775
- need to ${A.bold("create a new landing page")} that uses them.
2884
+ need to ${_.bold("create a new landing page")} that uses them.
1776
2885
 
1777
2886
  Next steps:
1778
2887
 
1779
- ${A.bold("1.")} Go to HubSpot ${A.muted("\u2192")} Content ${A.muted("\u2192")} Landing Pages ${A.muted("\u2192")} Create
1780
- ${A.bold("2.")} Choose your uploaded theme from the theme picker
1781
- ${A.bold("3.")} Select the landing page template that was just created
1782
- ${A.bold("4.")} Your converted modules will appear \u2014 drag them onto the page
1783
- ${A.bold("5.")} Click each section to edit text, images, and colors
1784
- ${A.bold("6.")} Upload images via File Manager ${A.muted("(Settings \u2192 Files)")}
1785
- ${A.bold("7.")} Preview and publish!`,"What's next"),await fe({message:"Open HubSpot Landing Pages in your browser?"})){let c=t?`https://${r}/page-ui/${t}/management/pages/landing`:`https://${r}`;try{let d=process.platform;d==="darwin"?ni("open",[c],{stdio:"ignore"}):d==="win32"?ni("cmd",["/c","start","",c],{stdio:"ignore"}):ni("xdg-open",[c],{stdio:"ignore"}),H("Opening HubSpot Landing Pages...")}catch{P(`Open this URL in your browser: ${A.info(c)}`)}}let l=[];if(o&&b(n)&&l.push({path:n,label:`Cloned source (${wa(n)})`}),b(s)&&l.push({path:s,label:`Theme directory (${wa(s)})`}),l.length>0&&await fe({message:"Clean up local working directories?"}))for(let d of l)try{Em(d.path,{recursive:!0,force:!0}),H(`Removed ${d.label}`)}catch{Z(`Could not remove ${d.label} \u2014 delete manually if needed.`)}await oe(`Thanks for using hub${A.vibes("Vibes")}! ${A.vibes("~")}`)}X();async function ka(){pe();let e=await ys(),t=await bs();V({lastSourcePath:t.sourceDir});let n=await ws();V({lastThemePath:n.themePath}),await Es({aiEngine:e.aiEngine,model:e.model,sourceDir:t.sourceDir,themePath:n.themePath}),await Xt(n.themePath),await Ca({portalId:e.portalId,sourceDir:t.sourceDir,themePath:n.themePath,wasCloned:t.wasCloned})}g();async function Aa(){pe(),await ys()}g();X();async function Ta(){pe();let e=R();e.aiEngine||(z("AI engine not configured. Run `vibespot init` first or use the full wizard with `vibespot`."),process.exit(1));let t=await bs(),n=await ws();await Es({aiEngine:e.aiEngine,sourceDir:t.sourceDir,themePath:n.themePath})}g();X();async function $a(){pe();let e=R();if(e.lastThemePath)if(await fe({message:`Upload from ${e.lastThemePath}?`}))await Xt(e.lastThemePath);else{let n=await le({message:"Path to your HubSpot theme directory:",placeholder:"./my-theme"});await Xt(n)}else{let t=await le({message:"Path to your HubSpot theme directory:",placeholder:"./my-theme",validate:n=>n.trim()?void 0:"Path is required"});await Xt(t)}}g();X();async function Ia(){pe(),await se("Environment Diagnostics");let e=0,t=bn();t.found?ms(t.version)?H(`Node.js v${t.version}`):(Z(`Node.js v${t.version} \u2014 too old (need 18+)`),P(" Update at https://nodejs.org"),e++):(z("Node.js \u2014 not installed"),P(" Install from https://nodejs.org"),e++);let n=Sn();n.found?H(`Git ${n.version}`):(z("Git \u2014 not installed"),P(" Install from https://git-scm.com"),e++);let s=qe();if(!s.found)Z("HubSpot CLI \u2014 not installed (only needed for deployment)"),P(" Install: npm install -g @hubspot/cli");else if(!Hr(s.version))Z(`HubSpot CLI v${s.version} \u2014 too old (need v8+)`),P(" Update: npm install -g @hubspot/cli@latest"),e++;else{H(`HubSpot CLI v${s.version}`);let m=Xe();m.authenticated?H(`HubSpot portal${m.portalName?`: ${m.portalName}`:""} (ID: ${m.portalId})`):(Z("HubSpot \u2014 not authenticated"),P(" Run: hs init"))}let o=xn();o.found?H(`Claude Code ${o.version} at ${o.path}`):P(A.muted("Claude Code \u2014 not installed"));let i=wn();i.found?H(`Gemini CLI ${i.version} at ${i.path}`):P(A.muted("Gemini CLI \u2014 not installed"));let r=Cn();r.found?H(`OpenAI Codex ${r.version} at ${r.path}`):P(A.muted("OpenAI Codex \u2014 not installed"));let a=R(),l=!!(a.anthropicApiKey||process.env.ANTHROPIC_API_KEY),c=!!(a.openaiApiKey||process.env.OPENAI_API_KEY),d=!!(a.geminiApiKey||process.env.GEMINI_API_KEY||process.env.GOOGLE_AI_API_KEY);l?H("Anthropic API key configured"):P(A.muted("Anthropic API key \u2014 not set")),c?H("OpenAI API key configured"):P(A.muted("OpenAI API key \u2014 not set")),d?H("Google AI API key configured"):P(A.muted("Google AI API key \u2014 not set"));let u={"claude-code":"Claude Code",api:"Anthropic API","anthropic-api":"Anthropic API","claude-oauth":"Claude (OAuth)","openai-api":"OpenAI API","gemini-api":"Gemini API","gemini-cli":"Gemini CLI","codex-cli":"OpenAI Codex"};a.aiEngine&&H(`AI engine: ${u[a.aiEngine]||a.aiEngine}`),a.lastThemePath&&P(A.muted(`Last theme: ${a.lastThemePath}`)),!o.found&&!i.found&&!r.found&&!l&&!c&&!d&&(Z("No AI engine available"),P(" Fastest: Set an API key (ANTHROPIC_API_KEY, OPENAI_API_KEY, or GEMINI_API_KEY)"),P(" Or install: Claude Code \u2014 https://claude.ai/code"),P(" Gemini CLI \u2014 https://github.com/google-gemini/gemini-cli"),P(" Codex CLI \u2014 https://github.com/openai/codex"),e++),console.log(),e===0?await oe("Everything looks good!"):await oe(A.warn(`${e} issue${e>1?"s":""} found \u2014 see above`))}g();import{dirname as Hh,join as No}from"path";import{existsSync as Bh}from"fs";import{fileURLToPath as Uh}from"url";import{execFileSync as wr}from"child_process";import Oo from"chalk";g();me();Zt();Fn();cn();import{createServer as Nh}from"http";import{readFileSync as vr,existsSync as Qn}from"fs";import{join as St,extname as gu}from"path";import{WebSocketServer as Oh,WebSocket as Fh}from"ws";g();Fe();me();Nt();X();re();import{existsSync as xc,mkdirSync as lg,writeFileSync as cg,rmSync as dg}from"fs";import{join as vc}from"path";g();import{readFileSync as Qf,readdirSync as eg,existsSync as tg}from"fs";import{dirname as ng,join as co}from"path";import{fileURLToPath as sg}from"url";var hc=ng(sg(import.meta.url)),og=/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/;function ig(e){let t=e.match(og);if(!t)return null;let[,n,s]=t,o={};for(let i of n.split(/\r?\n/)){let r=i.indexOf(":");if(r===-1)continue;let a=i.slice(0,r).trim(),l=i.slice(r+1).trim();(l.startsWith('"')&&l.endsWith('"')||l.startsWith("'")&&l.endsWith("'"))&&(l=l.slice(1,-1)),a&&(o[a]=l)}return{fields:o,body:s.trimStart()}}function rg(e){let t=ig(e);if(!t)return null;let{fields:n,body:s}=t,o=n.id,i=n.label,r=n.description??"";if(!o||!i)return null;let a=n.order?Number(n.order):NaN;return{id:o,label:i,description:r,icon:n.icon||void 0,order:Number.isFinite(a)?a:9999,body:s.trimEnd()+`
1786
- `}}var At=null;function ag(){let e=[co(hc,"../../assets/plan-templates"),co(hc,"../assets/plan-templates"),co(process.cwd(),"assets/plan-templates")];for(let t of e)if(tg(t))return t;return null}function yc(){if(At)return At;let e=ag();if(!e)return At=[],At;let t=[],n=[];try{n=eg(e)}catch{return At=[],At}for(let s of n)if(s.endsWith(".md"))try{let o=Qf(co(e,s),"utf-8"),i=rg(o);i&&t.push(i)}catch{}return t.sort((s,o)=>s.order!==o.order?s.order-o.order:s.label.localeCompare(o.label)),At=t,At}function bc(e){return yc().find(t=>t.id===e)??null}function Sc(){return yc().map(({id:e,label:t,description:n,icon:s,order:o})=>({id:e,label:t,description:n,icon:s,order:o}))}var ug="plan.md";function wc(e){return vc(e,".vibespot",ug)}function uo(e){let t=C();if(!t)return null;t.brandAssets||(t.brandAssets={}),t.brandAssets.plan=e;let n=ye();n&&(n.plan=e);try{let s=vc(t.themePath,".vibespot");xc(s)||lg(s,{recursive:!0}),cg(wc(t.themePath),e,"utf-8")}catch(s){E.warn("plan",`Failed to write plan.md: ${s instanceof Error?s.message:String(s)}`)}return J(),e}function Qi(){let e=C();if(!e)return;e.brandAssets&&delete e.brandAssets.plan;let t=ye();t&&delete t.plan;try{let n=wc(e.themePath);xc(n)&&dg(n)}catch(n){E.warn("plan",`Failed to remove plan.md: ${n instanceof Error?n.message:String(n)}`)}J()}function Cc(e,t){Oe(e,t,n=>{if(!C()){p(t,400,{error:"No active session"});return}let o=typeof n.markdown=="string"?n.markdown:"";if(!o.trim()){p(t,400,{error:"Plan content cannot be empty"});return}uo(o),p(t,200,{ok:!0,plan:o})})}function kc(e,t){Oe(e,t,()=>{Qi(),V({planMode:!1}),p(t,200,{ok:!0})})}function Ac(e,t){p(t,200,{templates:Sc()})}function Tc(e,t){Oe(e,t,n=>{if(!C()){p(t,400,{error:"No active session"});return}let o=typeof n.templateId=="string"?n.templateId.trim():"";if(!o){p(t,400,{error:"templateId is required"});return}let i=bc(o);if(!i){p(t,404,{error:`Unknown plan template: ${o}`});return}uo(i.body),V({planMode:!0}),p(t,200,{ok:!0,templateId:i.id,label:i.label,plan:i.body})})}g();var er=/```vibespot-plan\s*\n([\s\S]*?)```/g,tr=/```vibespot-choices\s*\n([\s\S]*?)```/g;function $c(e){let t,n,s;for(er.lastIndex=0;(s=er.exec(e))!==null;)t=s[1].trim();let o;for(tr.lastIndex=0;(o=tr.exec(e))!==null;)try{let r=JSON.parse(o[1].trim());r&&typeof r.question=="string"&&Array.isArray(r.options)&&r.options.every(a=>typeof a=="string")&&r.options.length>0&&(n={question:r.question,options:r.options})}catch{}return{cleanedContent:e.replace(er,"").replace(tr,"").replace(/\n{3,}/g,`
1787
-
1788
- `).trim(),plan:t,choices:n}}X();g();import{spawn as nr}from"child_process";var Tt=new Map;function Ic(e,t,n){e.stdout?.on("data",o=>{t.output+=o.toString()}),e.stderr?.on("data",o=>{t.output+=o.toString()}),e.on("close",o=>{t.status=o===0?"completed":"failed",t.exitCode=o,t.completedAt=Date.now()}),e.on("error",o=>{t.status="failed",t.output+=`
1789
- Process error: ${o.message}`,t.completedAt=Date.now()}),setTimeout(()=>{t.status==="running"&&(e.kill(),t.status="failed",t.output+=`
1790
- Process timed out`,t.completedAt=Date.now())},n||3e5)}function Wn(e,t,n,s){let o=`job-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`,i={id:o,command:`${e} ${t.join(" ")}`,description:n,status:"running",output:"",exitCode:null,startedAt:Date.now(),completedAt:null};Tt.set(o,i);let r=nr(e,t,{cwd:s?.cwd,stdio:[s?.stdin?"pipe":"ignore","pipe","pipe"],env:{...process.env,...s?.env},shell:process.platform==="win32"});return s?.stdin&&r.stdin&&(r.stdin.write(s.stdin),r.stdin.end()),Ic(r,i,s?.timeout),o}function Jt(e,t,n){let s=`job-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`,o={id:s,command:e,description:t,status:"running",output:"",exitCode:null,startedAt:Date.now(),completedAt:null};Tt.set(s,o);let i=e.split(" "),r=nr(i[0],i.slice(1),{cwd:n?.cwd,stdio:["ignore","pipe","pipe"],env:{...process.env,...n?.env},shell:!0});return Ic(r,o,n?.timeout),s}function mo(e){return Tt.get(e)}function mg(){let e=Date.now()-18e5;for(let[t,n]of Tt)n.completedAt&&n.completedAt<e&&Tt.delete(t)}setInterval(mg,600*1e3);function po(e,t,n){let s=`job-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`,o={id:s,command:e,description:t,status:"running",output:"",exitCode:null,startedAt:Date.now(),completedAt:null,listeners:new Set};Tt.set(s,o);let i=e.split(" "),r=nr(i[0],i.slice(1),{cwd:n?.cwd,stdio:["ignore","pipe","pipe"],env:{...process.env,...n?.env},shell:!0}),a=c=>{for(let d of o.listeners)try{d(c)}catch{}};r.stdout?.on("data",c=>{let d=c.toString();o.output+=d,a(d)}),r.stderr?.on("data",c=>{let d=c.toString();o.output+=d,a(d)}),r.on("close",c=>{o.status=c===0?"completed":"failed",o.exitCode=c,o.completedAt=Date.now(),o.listeners.clear()}),r.on("error",c=>{o.status="failed",o.output+=`
1791
- Process error: ${c.message}`,o.completedAt=Date.now(),o.listeners.clear()});let l=n?.timeout||3e5;return setTimeout(()=>{o.status==="running"&&(r.kill(),o.status="failed",o.output+=`
1792
- Process timed out`,o.completedAt=Date.now(),o.listeners.clear())},l),s}function Ec(e,t){let n=Tt.get(e);if(!n||!("listeners"in n))return;let s=n;if(s.output)try{t(s.output)}catch{}s.listeners.add(t)}function Mc(e,t){let n=Tt.get(e);!n||!("listeners"in n)||n.listeners.delete(t)}Fe();Q();g();Fe();X();xs();vs();Rt();me();cn();import{existsSync as un,readdirSync as Dc,rmSync as Mg,writeFileSync as Lt,mkdirSync as xo}from"fs";import{join as xe,basename as Rg}from"path";import{homedir as _g}from"os";import{execFileSync as Lc}from"child_process";X();Q();g();import{readFileSync as pg,readdirSync as fg,existsSync as gg}from"fs";import{dirname as hg,join as fo}from"path";import{fileURLToPath as yg}from"url";var Rc=hg(yg(import.meta.url)),dn=null;function bg(){let e=[fo(Rc,"../../starters"),fo(Rc,"../starters"),fo(process.cwd(),"starters")];for(let t of e)if(gg(t))return t;return null}function _c(){if(dn!==null)return dn;let e=bg();if(!e)return dn=[],dn;let t=[];for(let n of fg(e).filter(s=>s.endsWith(".json")).sort())try{let s=JSON.parse(pg(fo(e,n),"utf-8"));t.push({id:s.id,name:s.name,description:s.description,category:s.category||"General",modules:s.modules||[],moduleOrder:s.moduleOrder||[],sharedCss:s.sharedCss||"",sharedJs:s.sharedJs||""})}catch{}return dn=t,dn}function Pc(){return _c().map(e=>({id:e.id,name:e.name,description:e.description,category:e.category,moduleCount:e.modules.length}))}function sr(e){return _c().find(t=>t.id===e)||null}g();Q();X();re();import{join as Fc}from"path";function Tg(e){let t=[];return e.brandAssets?.styleguide||t.push("styleguide"),e.brandAssets?.brandvoice||t.push("brandvoice"),e.brandAssets?.themeContext||t.push("themeContext"),t}function $g(e,t,n){e.brandAssets||(e.brandAssets={}),e.brandAssets[t]=n,e.updatedAt=Date.now();let s=t==="themeContext"?"theme-context.md":`${t}.md`,o=Fc(e.themePath,".vibespot");Ae(o),L(Fc(o,s),n)}async function jc(e,t){let n=Tg(e),s={attempted:[],extracted:[],skipped:[],errors:[]};if(n.length===0)return s;let o=Ig(t)?t:{...await Eg(e),...t??{}};n.includes("styleguide")&&await lr(e,"styleguide",s,()=>o.extractStyleguide(e));let i=n.filter(a=>a==="brandvoice"||a==="themeContext");if(i.length===0)return s;let r="";try{r=o.buildPreviewHtml()}catch(a){let l=a instanceof Error?a.message:String(a);for(let c of i)s.skipped.push(c),s.errors.push({asset:c,message:`Could not render preview HTML: ${l}`});return s}if(!r||r.length<50){for(let a of i)s.skipped.push(a);return s}return n.includes("brandvoice")&&await lr(e,"brandvoice",s,()=>o.extractBrandvoice(e,r)),n.includes("themeContext")&&await lr(e,"themeContext",s,()=>o.extractThemeContext(e,r)),s}async function lr(e,t,n,s){n.attempted.push(t);try{let o=await s();if(!o){n.skipped.push(t);return}$g(e,t,o),n.extracted.push(t)}catch(o){let i=o instanceof Error?o.message:String(o);n.skipped.push(t),n.errors.push({asset:t,message:i}),E.warn("brand-enrichment",`${t} enrichment skipped: ${i}`)}}function Ig(e){return!!e?.extractStyleguide&&!!e.extractBrandvoice&&!!e.extractThemeContext&&!!e.buildPreviewHtml}async function Eg(e){let{extractDesignContext:t}=await Promise.resolve().then(()=>(Kn(),zn)),{buildPreviewHtml:n}=await Promise.resolve().then(()=>(Fn(),Qs)),{resolveAgenticEngine:s}=await Promise.resolve().then(()=>(cn(),Zi)),{extractBrandvoice:o}=await Promise.resolve().then(()=>(ar(),rr)),{extractThemeContext:i}=await Promise.resolve().then(()=>(So(),bo)),r=R();return{extractStyleguide:()=>t(e.themePath),buildPreviewHtml:n,extractBrandvoice:async(a,l)=>{let{engine:c,apiKey:d,model:u}=s(r);return o(l,c,d,u)},extractThemeContext:async(a,l)=>{let{engine:c,apiKey:d,model:u}=s(r);return i(l,a.brandAssets?.themeContext,c,d,u)}}}var Hc=process.platform==="win32"?{shell:!0}:{},We=xe(_g(),"vibespot-themes"),vo=null,Pg=5e3;function wo(){if(vo&&Date.now()-vo.ts<Pg)return vo.data;let e=[];if(un(We))try{for(let t of Dc(We,{withFileTypes:!0}))if(t.isDirectory()){let n=xe(We,t.name,"theme.json");if(un(n)){let s=0,o=xe(We,t.name,"modules");if(un(o))try{s=Dc(o,{withFileTypes:!0}).filter(i=>i.isDirectory()).length}catch{}e.push({name:t.name,moduleCount:s})}}}catch{}return vo={data:e,ts:Date.now()},e}function Bc(e){let t=C(),n=ps(),s=!1;try{Lc("hs",["--version"],{encoding:"utf-8",stdio:"pipe",...Hc}),s=!0}catch{}let o=nn().sort((r,a)=>a.updatedAt-r.updatedAt).slice(0,10),i=wo();p(e,200,{hasActiveSession:!!t,activeSession:t?{id:t.id,themeName:t.themeName,moduleCount:t.modules.length,isImported:!!t.isImported}:null,hsInstalled:s,aiAvailable:n.availableEngines.length>0,availableEngines:n.availableEngines,activeEngine:n.activeEngine,sessions:o,localThemes:i})}function Uc(e,t){W(e,n=>{try{if(kt()){p(t,409,{error:"Cannot switch projects while AI is generating.",generating:!0});return}let{name:s,starterId:o}=JSON.parse(n);if(!s||typeof s!="string"){p(t,400,{error:"Theme name is required"});return}let i=s.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,""),r=xe(We,i);if(Ae(We),un(r)&&Mg(r,{recursive:!0,force:!0}),o&&typeof o=="string"&&!sr(o)){p(t,400,{error:`Starter template "${o}" not found`});return}Tn(r,i),tn(r,i),o&&typeof o=="string"&&Ng(r,i,o),J(),p(t,200,{ok:!0,themeName:i,themePath:r,starterId:o||void 0})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function Ng(e,t,n){let s=sr(n);if(!s)return;let o=C();if(!o)return;let i=s.modules.map(d=>({...d})),r=[...s.moduleOrder],a=`lp-${t}`,l={id:a,label:`${s.name}`,pageType:"landing_page",templateFile:`templates/${a}.html`,modules:i,moduleOrder:r,sharedCss:s.sharedCss,sharedJs:s.sharedJs,template:"",messages:[]};o.templates=[l],o.activeTemplateId=a,o.modules=i,o.moduleOrder=r,o.sharedCss=s.sharedCss,o.sharedJs=s.sharedJs;let c=xe(e,"modules");xo(c,{recursive:!0});for(let d of s.modules){let u=xe(c,`${d.moduleName}.module`);xo(u,{recursive:!0}),Lt(xe(u,"fields.json"),d.fieldsJson,"utf-8"),Lt(xe(u,"meta.json"),d.metaJson,"utf-8"),Lt(xe(u,"module.html"),d.moduleHtml,"utf-8"),Lt(xe(u,"module.css"),d.moduleCss,"utf-8"),d.moduleJs&&Lt(xe(u,"module.js"),d.moduleJs,"utf-8")}if(s.sharedCss){let d=xe(e,"css");xo(d,{recursive:!0}),Lt(xe(d,`${t}-theme.css`),s.sharedCss,"utf-8")}if(s.sharedJs){let d=xe(e,"js");xo(d,{recursive:!0}),Lt(xe(d,`${t}-animations.js`),s.sharedJs,"utf-8")}}function Gc(e){p(e,200,{starters:Pc()})}function Wc(e,t){W(e,n=>{try{if(kt()){p(t,409,{error:"Cannot switch projects while AI is generating.",generating:!0});return}let{name:s}=JSON.parse(n);if(!s||typeof s!="string"){p(t,400,{error:"Theme name is required"});return}let o=s.replace(/^\/+|\/+$/g,"");if(!o){p(t,400,{error:"Theme name is required"});return}let i=$e(),r=R(),a=o.includes("/")||o.includes("@")?o.replace(/[@/]/g,"_").replace(/_+/g,"_").replace(/^_|_$/g,""):o,l=xe(We,a);Ae(We),r.hubspotUploadMode==="cli"||!i?(async()=>{Lc("hs",["cms","fetch",o,l],{encoding:"utf-8",stdio:"pipe",...Hc});let c=await Jc(l,a);p(t,200,{ok:!0,themeName:a,themePath:l,moduleCount:c.moduleCount,brandEnrichment:c.brandEnrichment})})().catch(c=>{p(t,500,{error:c instanceof Error?c.message:String(c)})}):$n(i,o,l).then(async()=>{let c=await Jc(l,a);p(t,200,{ok:!0,themeName:a,themePath:l,moduleCount:c.moduleCount,brandEnrichment:c.brandEnrichment})}).catch(c=>{p(t,500,{error:c instanceof Error?c.message:String(c)})})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}async function Jc(e,t){tn(e,t,{isImported:!0}),Xs(e),J();let n=C(),s={attempted:[],extracted:[],skipped:[],errors:[]};return n&&(s=await jc(n),J()),{moduleCount:n?.modules.length||0,brandEnrichment:s}}function Vc(e,t){W(e,n=>{try{if(kt()){p(t,409,{error:"Cannot switch projects while AI is generating.",generating:!0});return}let{path:s}=JSON.parse(n);if(!s||typeof s!="string"){p(t,400,{error:"Theme path is required"});return}let o=s;if(un(o)||(o=xe(We,s)),!un(o)){p(t,400,{error:`Theme folder not found: ${s}`});return}let i=Rg(o);tn(o,i),Xs(o),J(),p(t,200,{ok:!0,themeName:i,themePath:o,moduleCount:C()?.modules.length||0})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function zc(e,t){W(e,n=>{try{if(kt()){p(t,409,{error:"Cannot switch projects while AI is generating.",generating:!0});return}let{sessionId:s}=JSON.parse(n);if(!s||typeof s!="string"){p(t,400,{error:"Session ID is required"});return}let o=Ws(s);if(!o){p(t,404,{error:"Session not found"});return}p(t,200,{ok:!0,themeName:o.themeName,themePath:o.themePath,moduleCount:o.modules.length,messageCount:o.messages.length})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function Kc(e,t){W(e,n=>{try{let{apiKey:s}=JSON.parse(n);if(!s||typeof s!="string"){p(t,400,{error:"API key is required"});return}V({anthropicApiKey:s}),p(t,200,{ok:!0})}catch(s){p(t,400,{error:s instanceof Error?s.message:String(s)})}})}function Yc(e){let t=$e();if(!t){p(e,200,{themes:[],error:"No HubSpot account connected"});return}(async()=>{let n=await Vr(t);if(n.length===0){p(e,200,{themes:[]});return}let s=[],o=n.map(async a=>{let l=a.path||a.name;try{let c=await hs(t,`${l}/theme.json`);c&&!c.folder&&s.push({name:a.name,path:l})}catch{}});await Promise.all(o),s.sort((a,l)=>a.name.localeCompare(l.name));let i=wo(),r=new Set(i.map(a=>a.name));p(e,200,{themes:s.map(a=>({...a,existsLocally:r.has(a.name)}))})})().catch(n=>{p(e,200,{themes:[],error:n instanceof Error?n.message:String(n)})})}g();Fe();X();me();import{existsSync as Og,readFileSync as Fg,appendFileSync as jg}from"fs";import{join as qc}from"path";import{homedir as Xc}from"os";Rt();Q();var Yn={data:{},ts:0},Dg=600*1e3,Qc={"claude-code":[{id:"claude-opus-4-7",label:"Claude Opus 4.7"},{id:"claude-opus-4-6",label:"Claude Opus 4.6"},{id:"claude-sonnet-4-6",label:"Claude Sonnet 4.6 (default)"},{id:"claude-sonnet-4-5",label:"Claude Sonnet 4.5"},{id:"claude-haiku-4-5",label:"Claude Haiku 4.5"}],"codex-cli":[{id:"gpt-5.5",label:"GPT-5.5 (default)"},{id:"gpt-5.5-pro",label:"GPT-5.5 Pro"},{id:"gpt-5.3-codex",label:"GPT-5.3 Codex"},{id:"gpt-5.2-codex",label:"GPT-5.2 Codex"},{id:"gpt-5.1-codex-max",label:"GPT-5.1 Codex Max"},{id:"gpt-5.1-codex-mini",label:"GPT-5.1 Codex Mini"},{id:"gpt-5.4-mini",label:"GPT-5.4 Mini"},{id:"gpt-5.4-nano",label:"GPT-5.4 Nano"},{id:"codex-mini-latest",label:"Codex Mini (latest)"}],"anthropic-api":[{id:"claude-opus-4-7",label:"Claude Opus 4.7"},{id:"claude-opus-4-6",label:"Claude Opus 4.6"},{id:"claude-sonnet-4-6",label:"Claude Sonnet 4.6 (default)"},{id:"claude-sonnet-4-5",label:"Claude Sonnet 4.5"},{id:"claude-haiku-4-5-20251001",label:"Claude Haiku 4.5"}],"claude-oauth":[{id:"claude-opus-4-7",label:"Claude Opus 4.7"},{id:"claude-opus-4-6",label:"Claude Opus 4.6"},{id:"claude-sonnet-4-6",label:"Claude Sonnet 4.6 (default)"},{id:"claude-sonnet-4-5",label:"Claude Sonnet 4.5"},{id:"claude-haiku-4-5-20251001",label:"Claude Haiku 4.5"}],"openai-api":[{id:"gpt-5.5",label:"GPT-5.5 (default)"},{id:"gpt-5.5-pro",label:"GPT-5.5 Pro"},{id:"gpt-5.4-mini",label:"GPT-5.4 Mini"},{id:"gpt-5.4-nano",label:"GPT-5.4 Nano"},{id:"gpt-5.3-codex",label:"GPT-5.3 Codex"}],"gemini-api":[{id:"gemini-2.5-pro",label:"Gemini 2.5 Pro (default)"},{id:"gemini-2.5-flash",label:"Gemini 2.5 Flash"},{id:"gemini-2.0-flash",label:"Gemini 2.0 Flash"}],"gemini-cli":[{id:"gemini-2.5-pro",label:"Gemini 2.5 Pro (default)"},{id:"gemini-2.5-flash",label:"Gemini 2.5 Flash"},{id:"gemini-2.0-flash",label:"Gemini 2.0 Flash"}]},ed=/^(gpt-[45](\.\d+)?(-[a-z0-9-]+)?|o[1-4](-(mini|pro|nano)(-high)?)?|codex(-[a-z0-9-]+)?)$/,Jg=ed;function Lg(e){let t=e.match(/^gpt-(\d+(?:\.\d+)?)(?:-(.+))?$/);if(t){let n=t[1],s=t[2];if(!s)return`GPT-${n}`;let o=s.replace(/-/g," ").replace(/\b\w/g,i=>i.toUpperCase());return`GPT-${n} ${o}`}return e.startsWith("codex-")?`Codex ${e.slice(6).replace(/-/g," ").replace(/\b\w/g,s=>s.toUpperCase())}`:/^o\d/.test(e)?e.replace(/-/g," "):e}async function Hg(e){let t=await fetch("https://api.anthropic.com/v1/models",{headers:{"x-api-key":e,"anthropic-version":"2023-06-01"}});return t.ok?(await t.json()).data.filter(s=>!s.id.startsWith("claude-3-")&&!s.id.startsWith("claude-2")).map(s=>({id:s.id,label:s.display_name})):[]}async function Bg(e){let t=await fetch("https://api.openai.com/v1/models",{headers:{Authorization:`Bearer ${e}`}});return t.ok?(await t.json()).data.map(s=>s.id):[]}function Zc(e,t){return e.filter(n=>t.test(n)).sort((n,s)=>n.localeCompare(s)).map(n=>({id:n,label:Lg(n)}))}async function Ug(e){let t=await fetch(`https://generativelanguage.googleapis.com/v1beta/models?key=${e}`);return t.ok?(await t.json()).models.filter(s=>s.name.includes("gemini-2")).map(s=>({id:s.name.replace("models/",""),label:s.displayName})):[]}async function Gg(){if(Date.now()-Yn.ts<Dg&&Object.keys(Yn.data).length>0)return Yn.data;let e=R(),t={...Qc},n=[],s=Te("anthropic-api",e);s&&n.push(Hg(s).then(r=>{r.length&&(t["anthropic-api"]=r,t["claude-oauth"]=r)}).catch(()=>{}));let o=Te("openai-api",e);o&&n.push(Bg(o).then(r=>{if(!r.length)return;let a=Zc(r,ed);a.length&&(t["openai-api"]=a);let l=Zc(r,Jg);l.length&&(t["codex-cli"]=l)}).catch(()=>{}));let i=Te("gemini-api",e);return i&&n.push(Ug(i).then(r=>{r.length&&(t["gemini-api"]=r,t["gemini-cli"]=r)}).catch(()=>{})),await Promise.all(n),Yn.data=t,Yn.ts=Date.now(),t}function td(e){let t=ps(),n=R(),s={aiEngine:n.aiEngine||null,claudeCodeModel:n.claudeCodeModel||null,anthropicApiModel:n.anthropicApiModel||null,openaiApiModel:n.openaiApiModel||null,codexCliModel:n.codexCliModel||null,geminiCliModel:n.geminiCliModel||null,geminiApiModel:n.geminiApiModel||null,hubspotUploadMode:n.hubspotUploadMode||"api",hubspotAccounts:(n.hubspotAccounts||[]).map(a=>({portalId:a.portalId,portalName:a.portalName,dataCenter:a.dataCenter})),activeHubSpotAccount:n.activeHubSpotAccount||null,enabledCLITools:n.enabledCLITools||[],agenticMode:n.agenticMode,agenticConcurrency:n.agenticConcurrency,planMode:n.planMode||!1,extendedThinking:n.extendedThinking||!1,extendedThinkingBudget:n.extendedThinkingBudget||"medium",webSearch:n.webSearch||!1,figmaToken:n.figmaToken?"\u2022\u2022\u2022\u2022"+n.figmaToken.slice(-4):null},o=nn().length,i=wo().length,r=Vt();Gg().then(a=>{p(e,200,{version:r,environment:t,config:s,models:a,sessionCount:o,localThemeCount:i})}).catch(()=>{p(e,200,{version:r,environment:t,config:s,models:Qc,sessionCount:o,localThemeCount:i})})}function nd(e,t){W(e,n=>{try{let{engine:s,model:o}=JSON.parse(n);if(!["claude-code","anthropic-api","claude-oauth","openai-api","gemini-cli","gemini-api","codex-cli"].includes(s)){p(t,400,{error:`Invalid engine: ${s}`});return}let r={aiEngine:s};if(o)switch(s){case"claude-code":r.claudeCodeModel=o;break;case"anthropic-api":case"claude-oauth":r.anthropicApiModel=o;break;case"openai-api":r.openaiApiModel=o;break;case"codex-cli":r.codexCliModel=o;break;case"gemini-cli":r.geminiCliModel=o;break;case"gemini-api":r.geminiApiModel=o;break}V(r),p(t,200,{ok:!0,engine:s})}catch(s){p(t,400,{error:s instanceof Error?s.message:String(s)})}})}function sd(e,t){W(e,n=>{try{let{provider:s,apiKey:o}=JSON.parse(n);if(!s||typeof s!="string"){p(t,400,{error:"provider is required"});return}if(!o){let l={};switch(s){case"anthropic":l.anthropicApiKey="";break;case"openai":l.openaiApiKey="";break;case"gemini":l.geminiApiKey="";break;case"figma":l.figmaToken="";break;default:p(t,400,{error:`Unknown provider: ${s}`});return}V(l),p(t,200,{ok:!0,provider:s,deleted:!0});return}let i={};switch(s){case"anthropic":i.anthropicApiKey=o;break;case"openai":i.openaiApiKey=o;break;case"gemini":i.geminiApiKey=o;break;case"figma":i.figmaToken=o;break;default:p(t,400,{error:`Unknown provider: ${s}`});return}V(i);let r=null;if(!R().aiEngine){let c={anthropic:"anthropic-api",openai:"openai-api",gemini:"gemini-api"}[s];c&&(V({aiEngine:c}),r=c)}p(t,200,{ok:!0,provider:s,autoSelectedEngine:r})}catch(s){p(t,400,{error:s instanceof Error?s.message:String(s)})}})}function od(e,t){W(e,n=>{try{let{tool:s}=JSON.parse(n),o={hubspot:{cmd:"npm install -g @hubspot/cli",desc:"Installing HubSpot CLI"},claude:{cmd:"npm install -g @anthropic-ai/claude-code",desc:"Installing Claude Code"},gemini:{cmd:"npm install -g @google/gemini-cli",desc:"Installing Gemini CLI"},codex:{cmd:process.platform==="darwin"?"brew install --cask codex":"npm install -g @openai/codex",desc:"Installing OpenAI Codex"},gh:{cmd:process.platform==="darwin"?"brew install gh":"npm install -g @cli/gh",desc:"Installing GitHub CLI"}},i=o[s];if(!i){p(t,400,{error:`Unknown tool: ${s}. Valid: ${Object.keys(o).join(", ")}`});return}let r=Jt(i.cmd,i.desc,{timeout:12e4});p(t,200,{ok:!0,jobId:r})}catch(s){p(t,400,{error:s instanceof Error?s.message:String(s)})}})}function id(e,t){W(e,n=>{try{let s=JSON.parse(n||"{}"),o=R(),i=o.hubspotUploadMode||"api";if(s.personalAccessKey)if(i==="api"){gs(s.personalAccessKey).then(r=>{fn(s.personalAccessKey,r.portalId,r.portalName,r.dataCenter),p(t,200,{ok:!0,portalName:r.portalName,portalId:r.portalId,dataCenter:r.dataCenter})}).catch(r=>{p(t,400,{error:r instanceof Error?r.message:String(r)})});return}else{if(!qe().found){p(t,400,{error:"HubSpot CLI not installed",needsInstall:!0});return}let a=Wn("hs",["auth",`--pak=${s.personalAccessKey}`],"Authenticating with HubSpot",{timeout:3e4});p(t,200,{ok:!0,jobId:a});return}if(i==="api"){let r=o.hubspotAccounts||[];if(r.length>0&&!s.force){let a=r.find(l=>l.portalId===o.activeHubSpotAccount)||r[0];p(t,200,{ok:!0,alreadyAuthenticated:!0,portalName:a.portalName,portalId:a.portalId});return}}else{if(!qe().found){p(t,400,{error:"HubSpot CLI not installed",needsInstall:!0});return}let a=Xe();if(a.authenticated&&!s.force){p(t,200,{ok:!0,alreadyAuthenticated:!0,portalName:a.portalName,portalId:a.portalId});return}}p(t,200,{needsKey:!0,instructions:"Create a personal access key in HubSpot",url:"https://app.hubspot.com/portal-recommend/l?slug=personal-access-key",steps:["Click the link above to open HubSpot","Select your account","Create a Personal Access Key with CMS permissions","Copy the key and paste it below"]})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function rd(e,t){W(e,n=>{try{let s=JSON.parse(n||"{}");if(!Wo().found){p(t,400,{error:"GitHub CLI not installed",needsInstall:!0});return}let i=Vo();if(i.authenticated&&!s.force){p(t,200,{ok:!0,alreadyAuthenticated:!0,username:i.username});return}if(s.token){let a=Wn("gh",["auth","login","--with-token"],"Authenticating with GitHub",{timeout:3e4,stdin:s.token});p(t,200,{ok:!0,jobId:a});return}let r=Jt("gh auth login --web --git-protocol https","GitHub authentication (check your browser)",{timeout:3e5});p(t,200,{ok:!0,jobId:r,browserAuthRequired:!0})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function ad(e,t){W(e,n=>{try{let{portalId:s,action:o}=JSON.parse(n);if((R().hubspotUploadMode||"api")==="api"){if(o==="remove"&&s){Do(s),p(t,200,{ok:!0});return}if(s){Jo(s),p(t,200,{ok:!0});return}}else{if(!qe().found){p(t,400,{error:"HubSpot CLI not installed"});return}let l=String(s).replace(/[^0-9]/g,"");if(!l){p(t,400,{error:"Invalid portalId"});return}if(o==="remove"){let c=Wn("hs",["accounts","remove",l],`Removing HubSpot account ${l}`,{timeout:15e3});p(t,200,{ok:!0,jobId:c});return}if(l){let c=Wn("hs",["accounts","use",l],`Switching to HubSpot account ${l}`,{timeout:15e3});p(t,200,{ok:!0,jobId:c});return}}p(t,400,{error:"portalId required"})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function ld(e){let t=Jt("gh auth logout --hostname github.com -y","Logging out of GitHub",{timeout:15e3});p(e,200,{ok:!0,jobId:t})}function cd(e,t){W(e,n=>{try{let{cli:s,apiKey:o}=JSON.parse(n||"{}");switch(s){case"claude":{let i=Jt("CLAUDECODE= claude --print -p 'reply OK'","Authenticating Claude Code (check your browser if prompted)",{timeout:12e4});p(t,200,{ok:!0,jobId:i,hint:"If Claude Code opens a browser window, complete the sign-in there."});break}case"gemini":{let i=Jt("gemini -p 'reply OK'","Authenticating Gemini CLI (check your browser if prompted)",{timeout:12e4});p(t,200,{ok:!0,jobId:i,hint:"If Gemini opens a browser window, complete the sign-in there."});break}case"codex":{if(o&&o.trim()){let i=o.trim();if(process.env.OPENAI_API_KEY=i,V({openaiApiKey:i}),process.platform!=="win32"){let r=/^[A-Za-z0-9_\-.:]+$/.test(i)?i:"";if(r){let a=`export OPENAI_API_KEY="${r}"`,l=process.env.SHELL?.includes("zsh")?qc(Xc(),".zshrc"):qc(Xc(),".bashrc");try{(Og(l)?Fg(l,"utf-8"):"").includes("OPENAI_API_KEY")||jg(l,`
1793
- # Added by vibeSpot
1794
- ${a}
1795
- `)}catch{}}}p(t,200,{ok:!0,message:"API key saved"})}else{let i=Jt("codex login","Authenticating Codex CLI (check your browser if prompted)",{timeout:12e4});p(t,200,{ok:!0,jobId:i,hint:"Complete the sign-in in your browser."})}break}default:p(t,400,{error:`Unknown CLI: ${s}`})}}catch(s){p(t,400,{error:s instanceof Error?s.message:String(s)})}})}function dd(e,t){W(e,n=>{try{let{mode:s}=JSON.parse(n);if(s!=="api"&&s!=="cli"){p(t,400,{error:`Invalid mode: ${s}. Must be "api" or "cli".`});return}V({hubspotUploadMode:s}),p(t,200,{ok:!0,mode:s})}catch(s){p(t,400,{error:s instanceof Error?s.message:String(s)})}})}function ud(e,t){W(e,n=>{try{let{toolId:s,enabled:o}=JSON.parse(n);if(!s||typeof o!="boolean"){p(t,400,{error:"toolId (string) and enabled (boolean) required"});return}Lo(s,o),p(t,200,{ok:!0,toolId:s,enabled:o})}catch(s){p(t,400,{error:s instanceof Error?s.message:String(s)})}})}function md(e,t){W(e,n=>{try{let s=JSON.parse(n),o=["agenticMode","agenticConcurrency","planMode","extendedThinking","extendedThinkingBudget","webSearch"];if(s.extendedThinkingBudget!==void 0&&!["low","medium","high"].includes(s.extendedThinkingBudget)){p(t,400,{error:"extendedThinkingBudget must be 'low' | 'medium' | 'high'"});return}let i={};for(let r of o)r in s&&(i[r]=s[r]);if(Object.keys(i).length===0){p(t,400,{error:"No valid settings fields provided"});return}V(i),p(t,200,{ok:!0,updated:Object.keys(i)})}catch(s){p(t,400,{error:s instanceof Error?s.message:String(s)})}})}function pd(e,t){let n=e.replace("/api/settings/job/","");if(!n){p(t,400,{error:"Job ID required"});return}let s=mo(n);if(!s){p(t,404,{error:"Job not found"});return}p(t,200,{id:s.id,status:s.status,description:s.description,output:s.output,exitCode:s.exitCode,startedAt:s.startedAt,completedAt:s.completedAt})}g();Fe();X();lt();function fd(e,t){W(e,n=>{try{let{access_token:s,refresh_token:o}=JSON.parse(n);if(!s||typeof s!="string"){p(t,400,{error:"access_token is required"});return}Ho(s.trim(),(o||"").trim());let i=R();(!i.aiEngine||i.aiEngine!=="claude-oauth")&&V({aiEngine:"claude-oauth"}),p(t,200,{ok:!0})}catch(s){p(t,400,{error:s instanceof Error?s.message:String(s)})}})}function gd(e,t){let n=Ye(),s=yn();p(t,200,{authenticated:n,expiresAt:s?.expiresAt||null})}function hd(e,t){try{ls(),R().aiEngine==="claude-oauth"&&V({aiEngine:void 0}),p(t,200,{ok:!0})}catch(n){p(t,500,{error:n instanceof Error?n.message:String(n)})}}g();Fe();me();import{existsSync as Wg,rmSync as Vg}from"fs";import{join as zg}from"path";function yd(e,t,n){if(e==="GET"){let s=C(),o=nn().sort((i,r)=>r.updatedAt-i.updatedAt);p(n,200,{activeTheme:s?{id:s.id,themeName:s.themeName,isImported:!!s.isImported}:null,sessions:o});return}if(e==="DELETE"){W(t,s=>{try{let{sessionId:o,deleteFiles:i}=JSON.parse(s);Ya(o,i),p(n,200,{ok:!0})}catch(o){p(n,500,{error:o instanceof Error?o.message:String(o)})}});return}p(n,405,{error:"Method not allowed"})}function bd(e,t){W(e,n=>{try{let{sessionId:s}=JSON.parse(n),o=Ws(s);if(!o){p(t,404,{error:"Session not found"});return}p(t,200,{ok:!0,themeName:o.themeName,themePath:o.themePath})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function Sd(e,t){W(e,n=>{try{let{themeName:s}=JSON.parse(n);if(!s||typeof s!="string"){p(t,400,{error:"Theme name is required"});return}let o=zg(We,s);if(!Wg(o)){p(t,404,{error:"Theme not found on disk"});return}Vg(o,{recursive:!0,force:!0}),p(t,200,{ok:!0})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function xd(e,t){W(e,n=>{try{let{sessionId:s,newName:o}=JSON.parse(n);if(!s||!o||typeof o!="string"){p(t,400,{error:"sessionId and newName are required"});return}let i=o.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/^-|-$/g,"").replace(/-{2,}/g,"-");if(!i){p(t,400,{error:"Invalid name"});return}let r=qa(s,i);r.ok?p(t,200,{ok:!0,newName:i}):p(t,400,{error:r.error})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}g();Fe();re();X();me();Q();import{existsSync as Co,readFileSync as Kg,rmSync as cr}from"fs";import{join as ot,basename as Yg}from"path";import{execFileSync as qg}from"child_process";var Xg=process.platform==="win32"?{shell:!0}:{};function Cd(e){let t=C();if(!t){p(e,404,{error:"No active session"});return}let n=ft();p(e,200,{themeName:t.themeName,themePath:t.themePath,templates:t.templates.map(s=>({id:s.id,label:s.label,pageType:s.pageType,moduleCount:s.modules.length,messageCount:s.messages.length})),activeTemplateId:t.activeTemplateId,moduleLibrary:n.map(s=>({moduleName:s.module.moduleName,usedIn:s.usedIn})),brandAssets:{hasStyleguide:!!t.brandAssets?.styleguide,hasBrandvoice:!!t.brandAssets?.brandvoice,hasThemeContext:!!t.brandAssets?.themeContext,humanify:t.brandAssets?.humanify!==!1}})}function kd(e){let t=C();if(!t){p(e,404,{error:"No active session"});return}let n=t.themePath;if(!Co(n)){p(e,404,{error:"Theme directory not found"});return}let s=t.themeName||"theme",o=ot(n,".."),i=Yg(n);try{let r=`${s}.zip`,a=ot(o,r);Co(a)&&cr(a),qg("zip",["-r",r,i,"-x",`${i}/.git/*`,`${i}/.vibespot/*`,`${i}/node_modules/*`],{cwd:o,timeout:3e4,...Xg});let l=Kg(a);cr(a),e.writeHead(200,{"Content-Type":"application/zip","Content-Disposition":`attachment; filename="${r}"`,"Content-Length":l.length}),e.end(l)}catch(r){E.error("download-zip","Failed to create zip archive",r),p(e,500,{error:"Failed to create zip archive"})}}function Ad(e,t,n){let s=C();if(!s){p(n,404,{error:"No active session"});return}if(e==="GET"){p(n,200,{templates:s.templates.map(o=>({id:o.id,label:o.label,pageType:o.pageType,moduleCount:o.modules.length})),activeTemplateId:s.activeTemplateId});return}if(e==="POST"){W(t,o=>{try{let{pageType:i,label:r}=JSON.parse(o);if(!i||!r){p(n,400,{error:"pageType and label are required"});return}if(!["landing_page","blog_post","website_page","module_only"].includes(i)){p(n,400,{error:`Invalid pageType: ${i}`});return}let l=Hs(i,r);J(),p(n,200,{ok:!0,template:{id:l.id,label:l.label,pageType:l.pageType}})}catch(i){p(n,500,{error:i instanceof Error?i.message:String(i)})}});return}if(e==="DELETE"){W(t,o=>{try{let{templateId:i,deleteModules:r}=JSON.parse(o);if(!i){p(n,400,{error:"templateId is required"});return}if(!za(i,!!r)){p(n,404,{error:"Template not found"});return}J(),p(n,200,{ok:!0})}catch(i){p(n,500,{error:i instanceof Error?i.message:String(i)})}});return}p(n,405,{error:"Method not allowed"})}function Td(e,t){W(e,n=>{try{let{templateId:s}=JSON.parse(n);if(!s){p(t,400,{error:"templateId is required"});return}if(!li(s)){p(t,404,{error:"Template not found"});return}J();let i=C();p(t,200,{ok:!0,modules:ce().map(r=>r.moduleName),messageCount:i?.messages.length||0})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function $d(e,t){W(e,n=>{try{let{templateId:s,newLabel:o}=JSON.parse(n);if(!s||!o||typeof o!="string"){p(t,400,{error:"templateId and newLabel are required"});return}if(!Va(s,o.trim())){p(t,404,{error:"Template not found"});return}J(),p(t,200,{ok:!0,newLabel:o.trim()})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function Id(e,t){W(e,n=>{try{let{templateId:s,label:o}=JSON.parse(n);if(!s){p(t,400,{error:"templateId is required"});return}let i=Wa(s,o);if(!i){p(t,404,{error:"Template not found"});return}J(),p(t,200,{ok:!0,template:{id:i.id,label:i.label,pageType:i.pageType,moduleCount:i.modules.length}})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function Ed(e){let t=ft();p(e,200,{modules:t.map(n=>({moduleName:n.module.moduleName,usedIn:n.usedIn,fieldsJson:n.module.fieldsJson}))})}function Md(e,t,n){let s=C();if(!s){p(n,404,{error:"No active session"});return}W(t,o=>{try{let{moduleName:i}=JSON.parse(o);if(!i){p(n,400,{error:"moduleName is required"});return}let a=ft().find(d=>d.module.moduleName===i);if(!a){p(n,404,{error:`Module "${i}" not found in library`});return}let l={...a.module};s.modules.find(d=>d.moduleName===l.moduleName)||(s.modules.push(l),s.moduleOrder.push(l.moduleName),s.updatedAt=Date.now()),J(),p(n,200,{ok:!0})}catch(i){p(n,500,{error:i instanceof Error?i.message:String(i)})}})}function Rd(e,t,n){let s=C();if(!s){p(n,404,{error:"No active session"});return}if(e==="GET"){p(n,200,{styleguide:s.brandAssets?.styleguide||null,brandvoice:s.brandAssets?.brandvoice||null,themeContext:s.brandAssets?.themeContext||null});return}if(e==="POST"){W(t,o=>{try{let{type:i,content:r}=JSON.parse(o);if(!i){p(n,400,{error:"type is required"});return}if(s.brandAssets||(s.brandAssets={}),i==="humanify"){s.brandAssets.humanify=r==="on",s.updatedAt=Date.now(),J(),p(n,200,{ok:!0});return}if(!r){p(n,400,{error:"content is required"});return}if(i!=="styleguide"&&i!=="brandvoice"&&i!=="themeContext"){p(n,400,{error:`Invalid type: ${i}. Must be "styleguide", "brandvoice", or "themeContext"`});return}let a=i,l=a==="themeContext"?"theme-context.md":`${a}.md`;s.brandAssets[a]=r,s.updatedAt=Date.now();let c=ot(s.themePath,".vibespot");Ae(c),L(ot(c,l),r),J(),p(n,200,{ok:!0})}catch(i){p(n,500,{error:i instanceof Error?i.message:String(i)})}});return}if(e==="DELETE"){W(t,o=>{try{let{type:i}=JSON.parse(o);if(i!=="styleguide"&&i!=="brandvoice"&&i!=="themeContext"){p(n,400,{error:`Invalid type: ${i}`});return}let r=i;s.brandAssets&&delete s.brandAssets[r],s.updatedAt=Date.now();let a=r==="themeContext"?"theme-context.md":`${r}.md`,l=ot(s.themePath,".vibespot",a);Co(l)&&cr(l),J(),p(n,200,{ok:!0})}catch(i){p(n,500,{error:i instanceof Error?i.message:String(i)})}});return}p(n,405,{error:"Method not allowed"})}function vd(e,t,n){if(!e)return;e.brandAssets||(e.brandAssets={}),e.brandAssets[t]=n,e.updatedAt=Date.now();let s=t==="themeContext"?"theme-context.md":`${t}.md`,o=ot(e.themePath,".vibespot");Ae(o),L(ot(o,s),n)}async function wd(e,t,n){if(t==="styleguide"){let{extractDesignContext:m}=await Promise.resolve().then(()=>(Kn(),zn));return m(n||e.themePath)}let{resolveAgenticEngine:s}=await Promise.resolve().then(()=>(cn(),Zi)),{loadConfig:o}=await Promise.resolve().then(()=>(X(),jr)),i=o(),{engine:r,apiKey:a,model:l}=s(i),{buildPreviewHtml:c}=await Promise.resolve().then(()=>(Fn(),Qs)),d=c();if(!d||d.length<50)return null;if(t==="brandvoice"){let{extractBrandvoice:m}=await Promise.resolve().then(()=>(ar(),rr));return m(d,r,a,l)}let{extractThemeContext:u}=await Promise.resolve().then(()=>(So(),bo));return u(d,e.brandAssets?.themeContext,r,a,l)}function _d(e,t){let n=C();if(!n){p(t,404,{error:"No active session"});return}W(e,s=>{(async()=>{try{let o=s?JSON.parse(s):{},i=o.type||"styleguide",r=o.sourcePath;if(i==="all"){let l=["styleguide","brandvoice","themeContext"],c=await Promise.allSettled(l.map(u=>wd(n,u,r))),d={};for(let u=0;u<l.length;u++){let m=c[u],f=m.status==="fulfilled"?m.value:null;f&&vd(n,l[u],f),d[l[u]]=f}J(),p(t,200,{ok:!0,type:"all",extracted:d});return}if(i!=="styleguide"&&i!=="brandvoice"&&i!=="themeContext"){p(t,400,{error:`Invalid type: ${i}`});return}let a=await wd(n,i,r);if(!a){p(t,200,{ok:!1,type:i,error:"No content to extract from"});return}vd(n,i,a),J(),p(t,200,{ok:!0,type:i,content:a})}catch(o){p(t,500,{error:o instanceof Error?o.message:String(o)})}})()})}function Pd(e,t){let n=C();if(!n){p(t,404,{error:"No active session"});return}W(e,s=>{(async()=>{try{let{source:o,themeName:i,localPath:r}=JSON.parse(s),a;if(o==="hubspot"){if(!i){p(t,400,{error:"themeName is required for HubSpot import"});return}let u=$e();if(!u){p(t,400,{error:"No HubSpot account connected"});return}let m=i.replace(/^\/+|\/+$/g,"");if(!m){p(t,400,{error:"Invalid theme name"});return}let f=m.replace(/[@/]/g,"_").replace(/_+/g,"_"),{homedir:y}=await import("os"),h=ot(y(),"vibespot-themes",".references",f);Ae(h);let{fetchTheme:S}=await Promise.resolve().then(()=>(vs(),Qr));await S(u,m,h),a=h}else if(o==="local"){if(!r){p(t,400,{error:"localPath is required for local import"});return}if(!Co(r)){p(t,400,{error:`Path not found: ${r}`});return}a=r}else{p(t,400,{error:"source must be 'hubspot' or 'local'"});return}let{extractDesignContext:l}=await Promise.resolve().then(()=>(Kn(),zn)),c=await l(a);n.brandAssets||(n.brandAssets={}),n.brandAssets.styleguide=c,n.updatedAt=Date.now();let d=ot(n.themePath,".vibespot");Ae(d),L(ot(d,"styleguide.md"),c),J(),p(t,200,{ok:!0,styleguide:c,source:a})}catch(o){p(t,500,{error:o instanceof Error?o.message:String(o)})}})()})}g();Fe();me();import{join as Zg}from"path";Zt();function Nd(e,t){let n=C();if(!n){p(t,404,{error:"No active session"});return}p(t,200,{id:n.id,themeName:n.themeName,themePath:n.themePath,messageCount:n.messages.length,moduleCount:n.modules.length,moduleOrder:n.moduleOrder})}function Od(e,t,n){let s=C();if(!s){p(n,404,{error:"No active session"});return}if(e==="GET"){let o=ce();p(n,200,{modules:o.map(i=>({moduleName:i.moduleName,fieldsJson:i.fieldsJson,moduleHtml:i.moduleHtml,moduleCss:i.moduleCss,moduleJs:i.moduleJs||null})),sharedCss:s.sharedCss,sharedJs:s.sharedJs});return}if(e==="DELETE"){Oe(t,n,o=>{o.deleteEntirely?La(o.moduleName):Ha(o.moduleName),J(),p(n,200,{ok:!0})});return}p(n,405,{error:"Method not allowed"})}function Fd(e,t){let n=C();if(!n){p(t,404,{error:"No active session"});return}W(e,s=>{try{let o=JSON.parse(s);if(o.shared){if(o.shared==="css")n.sharedCss=o.content;else if(o.shared==="js")n.sharedJs=o.content;else{p(t,400,{error:"Invalid shared type"});return}let c=ye();c&&(o.shared==="css"?c.sharedCss=o.content:c.sharedJs=o.content),n.updatedAt=Date.now(),Ue(),J(),we(),p(t,200,{ok:!0});return}let{moduleName:i,fileType:r,content:a}=o;if(!i||!r){p(t,400,{error:"moduleName and fileType required"});return}let l=n.modules.find(c=>c.moduleName===i);if(!l){p(t,404,{error:`Module "${i}" not found`});return}switch(r){case"html":l.moduleHtml=a;break;case"css":l.moduleCss=a;break;case"js":l.moduleJs=a||void 0;break;case"fields":try{JSON.parse(a)}catch{p(t,400,{error:"Invalid JSON in fields.json"});return}l.fieldsJson=a;break;default:p(t,400,{error:`Invalid fileType: ${r}`});return}n.updatedAt=Date.now(),Ue(),J(),we(),p(t,200,{ok:!0})}catch(o){p(t,400,{error:String(o)})}})}function jd(e,t){Oe(e,t,n=>{Array.isArray(n.order)?(wt(n.order),J(),p(t,200,{ok:!0})):p(t,400,{error:"order must be an array"})})}async function Dd(e){let t=C();if(!t){p(e,404,{error:"No active session"});return}try{we();let n=_s(t.themePath),s=po(`hs cms upload "${t.themePath}" "${t.themeName}"`,"Uploading to HubSpot",{cwd:Zg(t.themePath,".."),timeout:18e4});p(e,200,{ok:!0,jobId:s,fixes:n})}catch(n){p(e,500,{error:String(n)})}}function Jd(e,t){W(e,n=>{try{let{moduleName:s,fieldPath:o,value:i}=JSON.parse(n);Ba(s,o,i),J(),p(t,200,{ok:!0})}catch(s){p(t,400,{error:String(s)})}})}function Ld(e,t){W(e,n=>{try{let{url:s}=JSON.parse(n);if(!s||typeof s!="string"){p(t,400,{error:"url is required"});return}let o=qr(s),i=o.components.map(a=>`- ${a.name}: ${a.description}`).join(`
1796
- `),r={sourceDir:o.sourceDir,componentCount:o.components.length,components:o.components.map(a=>({name:a.name,description:a.description})),hasTailwind:o.hasTailwind,cssVarCount:o.cssVarCount,fonts:o.fonts,interactions:o.interactions,conversionPrompt:`Import and convert the React landing page from ${s} to native HubSpot modules.
1797
-
1798
- Source analysis found ${o.components.length} components:
1799
- ${i}
1800
-
1801
- Design system: ${o.hasTailwind?"Tailwind CSS":"Custom CSS"}, ${o.cssVarCount} CSS variables
1802
- Fonts: ${o.fonts.length>0?o.fonts.join(", "):"System fonts"}
1803
- Interactions: ${o.interactions.join(", ")}
1804
-
1805
- Read the React source files from ${o.sourceDir} and convert each component to a HubSpot module. Preserve the design, layout, colors, and content. Generate fields.json so marketers can edit all text, images, colors, and links in the HubSpot page editor.`};p(t,200,r)}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function Hd(e,t){let n=C();if(!n){p(t,404,{error:"No active session"});return}if(!Be()){p(t,200,{available:!1,commits:[]});return}let o=new URL(e.url||"/","http://localhost").searchParams.get("templateId"),i=o?Na(n.themePath,o,50):Pa(n.themePath,50);p(t,200,{available:!0,commits:i,filtered:!!o})}function Bd(e,t){W(e,n=>{try{let s=C();if(!s){p(t,404,{error:"No active session"});return}let{hash:o,templateId:i}=JSON.parse(n);if(!o||typeof o!="string"){p(t,400,{error:"Commit hash is required"});return}if(Ge("assistant",`Rolled back to version ${o.slice(0,7)}.`),i){let r=s.templates.find(c=>c.id===i);if(!r){p(t,404,{error:"Template not found"});return}let a=r.moduleOrder.map(c=>`modules/${c}.module`);r.templateFile&&a.push(r.templateFile);let l=Fa(s.themePath,i,o,a);if(!l.success){p(t,500,{error:l.error||"Rollback failed"});return}rl()}else{let r=Oa(s.themePath,o);if(!r.success){p(t,500,{error:r.error||"Rollback failed"});return}il()}J(),p(t,200,{ok:!0,modules:ce().map(r=>r.moduleName)})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}Oi();gr();g();Fe();me();g();Q();import{readdirSync as br,statSync as xh}from"fs";import{join as K,relative as vh}from"path";var $t=["Business Services","Education","Events","Health & Wellness","Hospitality","Marketing & SEO","Non-profit","Portfolio","Real Estate","Restaurant & Food","Retail & E-commerce","SaaS & Technology","Travel","Other"],wh=["label","preview_path","screenshot_path","version","documentation_url","license","example_url"],Ch=["enable_domain_stylesheets","is_available_for_new_content"],yt="marketplace.json";function mn(e){let t=K(e,yt);if(!b(t))return null;try{return JSON.parse(T(t))}catch{return null}}function Eo(e,t){let n=K(e,yt);L(n,JSON.stringify(t,null,2)+`
1806
- `)}function Xn(e){let t=[];if(!b(e))return t.push({severity:"error",rule:"theme.path.missing",message:`Theme directory not found: ${e}`}),hr(e,t,null);let n=yr(K(e,"theme.json"));if(!n)return t.push({severity:"error",rule:"theme.json.missing",file:"theme.json",message:"theme.json is missing or invalid JSON",fix:"Recreate the theme so theme.json is generated, or restore it from version control."}),hr(e,t,mn(e));kh(e,n,t),Ah(e,n,t),Th(e,t),Ih(e,t),Eh(e,t),Mh(e,t);let s=mn(e);return Rh(s,t),hr(e,t,s)}function hr(e,t,n){let s=t.filter(r=>r.severity==="error").length,o=t.filter(r=>r.severity==="warning").length,i=t.filter(r=>r.severity==="info").length;return{themePath:e,passed:s===0,errorCount:s,warningCount:o,infoCount:i,findings:t,metadata:n}}function kh(e,t,n){let s={documentation_url:'Add a "documentation_url" entry pointing to public docs for the theme.',license:'Add a "license" entry \u2014 an SPDX identifier or URL (e.g. "MIT").',example_url:'Add an "example_url" entry pointing to a public live preview of the theme.'};for(let r of wh)it(t,r)||n.push({severity:"error",rule:`theme.json.${r}.missing`,file:"theme.json",message:`theme.json is missing required field "${r}"`,fix:s[r]??`Add a "${r}" entry to theme.json.`});for(let r of Ch)(!(r in t)||typeof t[r]!="boolean")&&n.push({severity:"error",rule:`theme.json.${r}.missing`,file:"theme.json",message:`theme.json must declare boolean "${r}"`,fix:`Add "${r}": true (or false) to theme.json.`});let o=t.author;!o||typeof o!="object"?n.push({severity:"error",rule:"theme.json.author.missing",file:"theme.json",message:'theme.json is missing required "author" block',fix:'Add { "author": { "name": "...", "email": "...", "url": "..." } } to theme.json.'}):(it(o,"name")||n.push({severity:"error",rule:"theme.json.author.name.missing",file:"theme.json",message:"theme.json author.name is missing",fix:"Provide a publisher name in theme.json author.name."}),it(o,"email")||n.push({severity:"error",rule:"theme.json.author.email.missing",file:"theme.json",message:"theme.json author.email is missing",fix:"Provide a contact email in theme.json author.email."}),it(o,"url")||n.push({severity:"error",rule:"theme.json.author.url.missing",file:"theme.json",message:"theme.json author.url is missing",fix:"Add a public URL for the publisher (homepage or support page)."}));let i=t.preview_path;if(typeof i=="string"&&i.length>0){let r=au(e,i);b(r)||n.push({severity:"error",rule:"theme.json.preview_path.invalid",file:"theme.json",message:`preview_path "${i}" does not point to an existing file`,fix:"Update preview_path to a real template, e.g. ./templates/home.html."})}}function Ah(e,t,n){let s=t.screenshot_path;if(typeof s!="string"||s.length===0)return;let o=au(e,s);if(!b(o)){n.push({severity:"error",rule:"theme.json.screenshot.missing",file:"theme.json",message:`Screenshot not found at ${s}`,fix:"Place a 1500\xD71000 PNG at the screenshot_path declared in theme.json."});return}/\.(png|jpg|jpeg)$/i.test(s)||n.push({severity:"warning",rule:"theme.json.screenshot.format",file:s,message:"Screenshot should be a PNG or JPG",fix:"Re-export the screenshot as PNG (1500\xD71000) or JPG."})}function Th(e,t){let n=K(e,"modules");if(!b(n)){t.push({severity:"warning",rule:"modules.empty",message:"Theme has no modules/ directory",fix:"Generate at least one module before submitting to Marketplace."});return}let s=0,o=[];try{o=br(n)}catch{return}for(let i of o){if(!i.endsWith(".module"))continue;s++;let r=K(n,i);$h(e,r,i,t)}s===0&&t.push({severity:"warning",rule:"modules.empty",message:"Theme has no .module directories",fix:"Generate at least one module before submitting to Marketplace."})}function $h(e,t,n,s){let o=yr(K(t,"meta.json")),i=Ve(e,K(t,"meta.json"));o?(it(o,"label")||s.push({severity:"error",rule:"module.meta.label.missing",file:i,message:`${n}: meta.json is missing "label"`,fix:`Add a "label" entry to the module's meta.json.`,autoFixable:!0}),o.is_available_for_new_content===!1&&s.push({severity:"info",rule:"module.meta.unavailable",file:i,message:`${n}: is_available_for_new_content=false (won\u2019t be selectable in HubSpot UI)`})):s.push({severity:"error",rule:"module.meta.missing",file:i,message:`${n}: meta.json is missing or invalid`,fix:"Recreate the module so meta.json is generated."});let r=K(t,"fields.json"),a=Ve(e,r);if(!b(r))s.push({severity:"warning",rule:"module.fields.missing",file:a,message:`${n}: fields.json is missing`,fix:"Add a fields.json (an empty array [] is acceptable for static modules)."});else{let c=yr(r);Array.isArray(c)?iu(c,n,a,s):s.push({severity:"warning",rule:"module.fields.invalid",file:a,message:`${n}: fields.json is not a JSON array`})}let l=K(t,"module.html");b(l)||s.push({severity:"error",rule:"module.html.missing",file:Ve(e,l),message:`${n}: module.html is missing`,fix:"Recreate the module so module.html is generated."})}function iu(e,t,n,s){for(let o of e){if(typeof o!="object"||o===null)continue;let i=o,r=typeof i.name=="string"?i.name:"(unnamed)";it(i,"label")||s.push({severity:"error",rule:"module.field.label.missing",file:n,message:`${t}.${r}: field is missing "label"`,fix:`Add a human-readable "label" to the "${r}" field in fields.json.`,autoFixable:!0}),!it(i,"help_text")&&i.type!=="group"&&s.push({severity:"info",rule:"module.field.help_text.missing",file:n,message:`${t}.${r}: consider adding "help_text"`,fix:`Add a short "help_text" describing what "${r}" controls.`}),Array.isArray(i.children)&&iu(i.children,t,n,s)}}function Ih(e,t){let n=[],s=K(e,"css");Io(s,".css").forEach(i=>{ou(i,n,e)});let o=K(e,"modules");if(b(o))for(let i of Zn(o)){if(!i.endsWith(".module"))continue;let r=K(o,i);["module.css","module.html"].forEach(a=>{let l=K(r,a);b(l)&&ou(l,n,e)})}for(let i of n)t.push({severity:"error",rule:"asset.cdn-import",file:i.file,message:`External CDN reference found: ${i.match}`,fix:"Remove external @import / <link> URLs and bundle the asset locally.",autoFixable:!0})}function ou(e,t,n){let s;try{s=T(e)}catch{return}let o=s.match(/@import\s+url\(['"]?https?:\/\/[^)\s'"]+['"]?\)/i);o&&t.push({file:Ve(n,e),match:o[0]});let i=s.match(/<link[^>]+href=['"]https?:\/\/[^'"]+['"][^>]*>/i);i&&t.push({file:Ve(n,e),match:i[0]});let r=s.match(/<script[^>]+src=['"]https?:\/\/[^'"]+['"][^>]*>/i);r&&t.push({file:Ve(n,e),match:r[0]})}function Eh(e,t){let n=[{rule:"asset.hardcoded.hubfs",re:/https?:\/\/[\w.-]*hubfs[\w.-]*\/(\d+)\//i,message:"Hardcoded portal-specific HubFS URL detected"},{rule:"asset.hardcoded.usercontent",re:/hubspotusercontent[-\w]*\.net\/(\w+\/)?(\d+)\//i,message:"Hardcoded portal-specific HubSpot user-content URL detected"},{rule:"asset.hardcoded.preview",re:/\d+\.hs-sites\.com|hubspotpagebuilder\.com\/\d+/i,message:"Hardcoded portal preview URL detected"}],s=[],o=K(e,"css");Io(o,".css").forEach(a=>s.push(a));let i=K(e,"js");Io(i,".js").forEach(a=>s.push(a));let r=K(e,"modules");if(b(r))for(let a of Zn(r))a.endsWith(".module")&&["module.html","module.css","module.js"].forEach(l=>{let c=K(r,a,l);b(c)&&s.push(c)});for(let a of s){let l;try{l=T(a)}catch{continue}for(let c of n){let d=l.match(c.re);d&&t.push({severity:"error",rule:c.rule,file:Ve(e,a),message:`${c.message}: ${d[0]}`,fix:"Replace portal-specific URLs with theme-relative paths or HubSpot tokens like get_asset_url."})}}}function Mh(e,t){let n=K(e,"modules");if(b(n))for(let s of Zn(n)){if(!s.endsWith(".module"))continue;let o=K(n,s,"module.html");if(!b(o))continue;let i;try{i=T(o)}catch{continue}let r=/<img\b([^>]*)>/gi,a;for(;a=r.exec(i);){let c=a[1];/\balt\s*=/.test(c)||t.push({severity:"warning",rule:"a11y.img.alt-missing",file:Ve(e,o),message:`${s}: <img> without alt attribute`,fix:'Add an alt attribute (alt="" is fine for purely decorative images).'})}/<(section|article|header|footer|main|nav|aside|h[1-6])\b/i.test(i)||t.push({severity:"info",rule:"a11y.semantics.missing",file:Ve(e,o),message:`${s}: module.html has no semantic landmarks (section/article/header/etc.)`,fix:"Wrap the module's main content in a <section> with a heading."})}}function Rh(e,t){if(!e){t.push({severity:"warning",rule:"marketplace.json.missing",file:yt,message:"marketplace.json sidecar not found",fix:"Run `vibespot marketplace edit` (CLI) or open the Marketplace panel in the editor to fill in listing details."});return}e.category?$t.includes(e.category)||t.push({severity:"warning",rule:"marketplace.json.category.unknown",file:yt,message:`marketplace.json category "${e.category}" is not a recognized HubSpot Marketplace category`,fix:`Use one of: ${$t.join(", ")}.`}):t.push({severity:"warning",rule:"marketplace.json.category.missing",file:yt,message:"marketplace.json has no category",fix:`Pick one of: ${$t.join(", ")}.`}),(!e.description||e.description.trim().length<40)&&t.push({severity:"warning",rule:"marketplace.json.description.short",file:yt,message:"marketplace.json description is missing or short (<40 chars)",fix:"Provide a 1\u20132 sentence description of the theme for the Marketplace listing."}),e.supportUrl||t.push({severity:"warning",rule:"marketplace.json.supportUrl.missing",file:yt,message:"marketplace.json has no supportUrl",fix:"Add a public support URL where buyers can reach the publisher."});let n=e.features?.length??0;n<2?t.push({severity:"warning",rule:"marketplace.json.features.too_few",file:yt,message:`marketplace.json needs at least 2 features (has ${n})`,fix:"Add 2\u20135 short bullet points highlighting what the theme does well."}):n>5&&t.push({severity:"warning",rule:"marketplace.json.features.too_many",file:yt,message:`marketplace.json has ${n} features but HubSpot allows at most 5`,fix:"Trim the features list to 5 or fewer entries."})}function Mo(e){let t=[],n=[],s=K(e,"modules");if(b(s))for(let i of Zn(s)){if(!i.endsWith(".module"))continue;let r=K(s,i),a=i.replace(/\.module$/,""),l=K(r,"meta.json");if(b(l))try{let d=JSON.parse(T(l));it(d,"label")||(d.label=lu(a),L(l,JSON.stringify(d,null,2)+`
1807
- `),t.push(`${i}: filled meta.label = "${d.label}"`))}catch{n.push(`${i}: meta.json could not be parsed`)}let c=K(r,"fields.json");if(b(c))try{let d=JSON.parse(T(c));if(Array.isArray(d)){let u=ru(d);u>0&&(L(c,JSON.stringify(d,null,2)+`
1808
- `),t.push(`${i}: filled ${u} missing field label(s)`))}}catch{n.push(`${i}: fields.json could not be parsed`)}}let o=_h(e);for(let i of o)t.push(`${i}: stripped external CDN reference(s)`);return{applied:t,skipped:n}}function _h(e){let t=[],n=/@import\s+url\(['"]?https?:\/\/[^)]+['"]?\)\s*;?/gi,s=/<link[^>]+href=['"]https?:\/\/[^'"]+['"][^>]*>/gi,o=/<script[^>]+src=['"]https?:\/\/[^'"]+['"][^>]*><\/script>/gi,i=/<script[^>]+src=['"]https?:\/\/[^'"]+['"][^>]*\/>/gi;function r(c){let d;try{d=T(c)}catch{return}let u=d.replace(n,"");u!==d&&(L(c,u),t.push(Ve(e,c)))}function a(c){let d;try{d=T(c)}catch{return}let u=d.replace(s,"");u=u.replace(o,""),u=u.replace(i,""),u=u.replace(n,""),u!==d&&(L(c,u),t.push(Ve(e,c)))}Io(K(e,"css"),".css").forEach(r);let l=K(e,"modules");if(b(l))for(let c of Zn(l)){if(!c.endsWith(".module"))continue;let d=K(l,c),u=K(d,"module.css"),m=K(d,"module.html");b(u)&&r(u),b(m)&&a(m)}return t}function ru(e){let t=0;for(let n of e){if(typeof n!="object"||n===null)continue;let s=n;!it(s,"label")&&it(s,"name")&&(s.label=lu(String(s.name)),t++),Array.isArray(s.children)&&(t+=ru(s.children))}return t}function yr(e){if(!b(e))return null;try{let t=JSON.parse(T(e));return t&&typeof t=="object"?t:null}catch{return null}}function it(e,t){let n=e[t];return typeof n=="string"?n.trim().length>0:Array.isArray(n)?n.length>0:n!=null&&n!==""}function au(e,t){let n=t.replace(/^\.?\//,"");return K(e,n)}function Ve(e,t){return vh(e,t).split("\\").join("/")}function Zn(e){try{return br(e)}catch{return[]}}function Io(e,t){if(!b(e))return[];try{let n=[];for(let s of br(e)){let o=K(e,s);xh(o).isFile()&&s.endsWith(t)&&n.push(o)}return n}catch{return[]}}function lu(e){return e.replace(/[-_]+/g," ").split(" ").filter(Boolean).map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" ")}function Sr(e){let t=C();if(!t)return p(e,400,{error:"No active theme. Open or create a theme first."}),null;try{we()}catch{}return t.themePath}function cu(e,t){let n=Sr(t);if(!n)return;let s=Xn(n);p(t,200,{report:s,categories:$t})}function du(e,t){let n=Sr(t);if(!n)return;let s=Mo(n),o=Xn(n);p(t,200,{fix:s,report:o})}function uu(e,t,n){let s=Sr(n);if(s){if(e==="GET"){p(n,200,{metadata:mn(s),categories:$t});return}if(e==="POST"){Oe(t,n,o=>{let i={category:typeof o.category=="string"?o.category:void 0,description:typeof o.description=="string"?o.description:void 0,features:Array.isArray(o.features)?o.features.filter(r=>typeof r=="string"&&r.trim().length>0):void 0,supportUrl:typeof o.supportUrl=="string"?o.supportUrl:void 0,documentationUrl:typeof o.documentationUrl=="string"?o.documentationUrl:void 0,pricingTier:o.pricingTier==="free"||o.pricingTier==="paid"?o.pricingTier:void 0,tags:Array.isArray(o.tags)?o.tags.filter(r=>typeof r=="string"):void 0};Eo(s,i),p(n,200,{ok:!0,metadata:i})});return}p(n,405,{error:"Method not allowed"})}}g();Fe();me();qs();function Ph(e){let t=C();if(!t)return p(e,400,{error:"No active theme. Open or fetch a theme first."}),null;try{we()}catch{}return t.themePath}function mu(e,t){let n=Ph(t);if(!n)return;let s=Ks(n);p(t,200,{report:s})}function pu(e,t){let n=C();if(!n){p(t,400,{error:"No active theme. Open or fetch a theme first."});return}let s=sn(n.themePath),o=_n(s);if(!o){p(t,200,{applied:!1,reason:"No tokens to apply."});return}if(!n.sharedCss||n.sharedCss.trim().length===0){n.sharedCss=o,n.updatedAt=Date.now(),J(),p(t,200,{applied:!0,written:"session.sharedCss",rootBlock:o});return}let i=Ys(n.themePath,n.themeName);i?p(t,200,{applied:!0,written:i,rootBlock:o}):p(t,200,{applied:!1,reason:"Theme already has shared CSS."})}var hu={".html":"text/html",".css":"text/css",".js":"application/javascript",".json":"application/json",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp",".gif":"image/gif",".ico":"image/x-icon",".woff2":"font/woff2"},_o=null,Po=[];function ve(e){_o&&_o.readyState===Fh.OPEN&&_o.send(JSON.stringify(e))}function Ro(e){Po.push(e),ve(e)}function bt(){Po=[]}function xr(e,t){return n=>{if(n.type==="module_progress"&&n.moduleFiles){let{moduleFiles:s,...o}=n;Ro(o)}else Ro(n);if(n.type==="agent_step")e.push({step:n.step,label:n.label});else if(n.type==="agent_decision"){let s=e[e.length-1];s&&(s.decisions||(s.decisions=[]),s.decisions.push(n.decision))}else n.type==="design_system_ready"?Ie({sharedCss:n.sharedCss,sharedJs:n.sharedJs}):n.type==="blueprint_ready"?(Ie({sharedCss:n.sharedCss,sharedJs:n.sharedJs}),wt(n.moduleOrder),Ro({type:"modules_updated",modules:ce().map(s=>s.moduleName)})):n.type==="module_progress"&&n.status==="complete"&&n.moduleFiles?(Ie({modules:[{moduleName:n.module,fieldsJson:n.moduleFiles.fieldsJson,metaJson:n.moduleFiles.metaJson,moduleHtml:n.moduleFiles.moduleHtml,moduleCss:n.moduleFiles.moduleCss,moduleJs:n.moduleFiles.moduleJs}]}),Ro({type:"modules_updated",modules:ce().map(s=>s.moduleName)}),t.push({name:n.module,status:"complete"})):n.type==="module_progress"&&n.status==="failed"&&t.push({name:n.module,status:"failed"})}}function yu(e){let{port:t,uiDir:n}=e,s=Nh((i,r)=>jh(i,r,n)),o=new Oh({server:s});return o.on("connection",i=>Jh(i)),new Promise((i,r)=>{s.on("error",a=>{a.code==="EADDRINUSE"?s.listen(t+1,()=>{i({port:t+1,close:()=>{s.close(),o.close()}})}):r(a)}),s.listen(t,()=>{i({port:t,close:()=>{s.close(),o.close()}})})})}function jh(e,t,n){let s=new URL(e.url||"/",`http://${e.headers.host}`),o=e.method||"GET";if(t.setHeader("X-Content-Type-Options","nosniff"),t.setHeader("X-Frame-Options","DENY"),t.setHeader("X-XSS-Protection","1; mode=block"),t.setHeader("Referrer-Policy","strict-origin-when-cross-origin"),s.pathname.startsWith("/api/")){Dh(o,s.pathname,e,t);return}if(s.pathname==="/preview"){let i=Ci();t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(i);return}if(s.pathname==="/module-preview"){let i=s.searchParams.get("module")||"",r=ki(i);t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(r||"<!-- module not found -->");return}if(s.pathname.startsWith("/theme-assets/")){Lh(s.pathname.slice(14),t);return}if(s.pathname==="/docs"){t.writeHead(301,{Location:"/docs/"}),t.end();return}if(s.pathname.startsWith("/docs/")){let i=s.pathname.slice(5)||"/index.html";fu(i,St(n,"docs"),e,t);return}fu(s.pathname,n,e,t)}function Dh(e,t,n,s){let o=n.headers.origin||"";if(/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/.test(o)&&s.setHeader("Access-Control-Allow-Origin",o),s.setHeader("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, OPTIONS"),s.setHeader("Access-Control-Allow-Headers","Content-Type"),e==="OPTIONS"){s.writeHead(204),s.end();return}switch(t){case"/api/session":Nd(e,s);break;case"/api/modules":Od(e,n,s);break;case"/api/modules/reorder":jd(n,s);break;case"/api/modules/code":Fd(n,s);break;case"/api/upload":Dd(s);break;case"/api/upload-files":e==="POST"?Nl(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/field":Jd(n,s);break;case"/api/import":Ld(n,s);break;case"/api/setup":Bc(s);break;case"/api/setup/create":Uc(n,s);break;case"/api/setup/fetch":Wc(n,s);break;case"/api/setup/open":Vc(n,s);break;case"/api/setup/resume":zc(n,s);break;case"/api/setup/apikey":Kc(n,s);break;case"/api/setup/remote-themes":e==="GET"?Yc(s):p(s,405,{error:"Method not allowed"});break;case"/api/starters":e==="GET"?Gc(s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/status":e==="GET"?td(s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/engine":e==="POST"?nd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/apikey":e==="POST"?sd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/install":e==="POST"?od(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/hs-auth":e==="POST"?id(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/gh-auth":e==="POST"?rd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/hs-switch":e==="POST"?ad(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/gh-logout":e==="POST"?ld(s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/cli-auth":e==="POST"?cd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/hs-mode":e==="POST"?dd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/cli-toggle":e==="POST"?ud(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/claude-oauth/save":e==="POST"?fd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/claude-oauth/status":e==="GET"?gd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/claude-oauth/logout":e==="POST"?hd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings":e==="POST"?md(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/changelog":e==="GET"?p(s,200,{changelog:_r()}):p(s,405,{error:"Method not allowed"});break;case"/api/themes":yd(e,n,s);break;case"/api/themes/switch":e==="POST"?bd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/themes/delete-local":e==="POST"?Sd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/themes/rename":e==="POST"?xd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/history":e==="GET"?Hd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/rollback":e==="POST"?Bd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/dashboard":e==="GET"?Cd(s):p(s,405,{error:"Method not allowed"});break;case"/api/templates":Ad(e,n,s);break;case"/api/templates/activate":e==="POST"?Td(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/templates/rename":e==="POST"?$d(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/templates/clone":e==="POST"?Id(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/module-library":e==="GET"?Ed(s):p(s,405,{error:"Method not allowed"});break;case"/api/brand-assets":Rd(e,n,s);break;case"/api/brand-assets/extract":e==="POST"?_d(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/brand-assets/import-reference":e==="POST"?Pd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/download-zip":e==="GET"?kd(s):p(s,405,{error:"Method not allowed"});break;case"/api/figma/test-token":e==="POST"?mr(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/figma/extract":e==="POST"?pr(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/figma/generate":e==="POST"?fr(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/edit":e==="POST"?Cc(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/discard":e==="POST"?kc(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/templates":e==="GET"?Ac(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/template":e==="POST"?Tc(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/marketplace/check":e==="GET"?cu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/marketplace/fix":e==="POST"?du(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/marketplace/listing":uu(e,n,s);break;case"/api/inverse/analyze":e==="GET"?mu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/inverse/apply-tokens":e==="POST"?pu(n,s):p(s,405,{error:"Method not allowed"});break;default:t.startsWith("/api/settings/job/")&&e==="GET"?pd(t,s):t.match(/^\/api\/templates\/[^/]+\/add-module$/)&&e==="POST"?Md(t,n,s):p(s,404,{error:"Not found"})}}function Jh(e){e.on("message",async n=>{let s;try{s=JSON.parse(n.toString())}catch{e.send(JSON.stringify({type:"error",message:"Invalid JSON"}));return}switch(s.type){case"chat":{let o=String(s.message||"");if(!o.trim())return;let i=Array.isArray(s.fileIds)?s.fileIds:void 0;if(qi()){Ge("user",o),J();try{e.send(JSON.stringify({type:"stream_status",content:"Planning..."}));let a="",l=await Yi(o,d=>{a+=d,e.send(JSON.stringify({type:"stream",content:d}))},i),c=$c(l||a);c.plan&&(uo(c.plan),e.send(JSON.stringify({type:"plan_updated",plan:c.plan}))),c.choices&&e.send(JSON.stringify({type:"plan_choices",question:c.choices.question,options:c.choices.options})),Ge("assistant",c.cleanedContent),J(),e.send(JSON.stringify({type:"plan_complete",cleanedContent:c.cleanedContent})),e.send(JSON.stringify({type:"generation_complete"}))}catch(a){e.send(JSON.stringify({type:"error",message:a instanceof Error?a.message:String(a)}))}break}Ge("user",o),J();let r=Xi();r.needsPrompt&&e.send(JSON.stringify({type:"agentic_prompt"}));try{if(r.useAgentic){bt();let l=[],c=[],d=await lo(o,xr(l,c),i);Dt(d,{steps:l,modules:c,stats:d.stats})}else zi(l=>{ve({type:"parse_warning",message:l})}),await Un(o,l=>{ve({type:"stream",content:l})},l=>{ve({type:"stream_status",content:l})},i);let a=C();if(a){we();let l=ye(),c=null;if(l){let d=l.moduleOrder.map(u=>`modules/${u}.module`);l.templateFile&&d.push(l.templateFile),l.sharedCss&&d.push(`css/${a.themeName}-theme.css`),l.sharedJs&&d.push(`js/${a.themeName}-animations.js`),c=si(a.themePath,l.id,o,d)}else c=_t(a.themePath,o);c&&ve({type:"version_created",hash:c})}ve({type:"generation_complete"}),ve({type:"modules_updated",modules:ce().map(l=>l.moduleName)}),bt();{let l=C();l&&r.useAgentic&&!l.brandAssets?.styleguide&&!l.brandAssets?.brandvoice&&!l.brandAssets?.themeContext&&ve({type:"suggest_brand_extraction"})}}catch(a){bt(),ve({type:"error",message:a instanceof Error?a.message:String(a)})}break}case"figma_import":{let o=String(s.extractionId||""),i=String(s.themeName||"");if(!o||!i){e.send(JSON.stringify({type:"error",message:"Missing extractionId or themeName"}));break}let{getCachedExtraction:r}=await Promise.resolve().then(()=>(gr(),su)),a=r(o);if(!a){e.send(JSON.stringify({type:"error",message:"Extraction expired or not found. Please re-extract."}));break}try{let l=C();if(!l||l.themeName!==i){let{join:m}=await import("path"),{homedir:f}=await import("os"),{existsSync:y}=await import("fs"),{createThemeScaffold:h}=await Promise.resolve().then(()=>(xs(),Xr)),S=m(f(),"vibespot-themes"),x=m(S,i);if(!y(S)){let{mkdirSync:w}=await import("fs");w(S,{recursive:!0})}y(x)||h(x,i),tn(x,i),J()}ve({type:"figma_import_started",fileName:a.fileName}),bt();let c=[],d=[],u=await Gn(a,i,xr(c,d));Dt(u,{steps:c,modules:d,stats:u.stats}),we(),_t(C().themePath,`Figma import: ${a.fileName}`),ve({type:"generation_complete"}),ve({type:"modules_updated",modules:ce().map(m=>m.moduleName)}),bt()}catch(l){bt(),ve({type:"error",message:l instanceof Error?l.message:String(l)})}break}case"extract_brand_assets":{let o=C();if(!o){e.send(JSON.stringify({type:"error",message:"No active session"}));break}(async()=>{try{let i=R(),{engine:r,apiKey:a,model:l}=ln(i),{buildPreviewHtml:c}=await Promise.resolve().then(()=>(Fn(),Qs)),d=c();if(!d||d.length<50)return;let{extractThemeContext:u}=await Promise.resolve().then(()=>(So(),bo)),m=await u(d,o.brandAssets?.themeContext,r,a,l),{mkdirSync:f,writeFileSync:y}=await import("fs");if(m){o.brandAssets||(o.brandAssets={}),o.brandAssets.themeContext=m,o.updatedAt=Date.now();let h=St(o.themePath,".vibespot");Qn(h)||f(h,{recursive:!0}),y(St(h,"theme-context.md"),m),J(),e.send(JSON.stringify({type:"brand_asset_extracted",assetType:"themeContext"}))}if(!o.brandAssets?.styleguide)try{let{extractDesignContext:h}=await Promise.resolve().then(()=>(Kn(),zn)),S=await h(o.themePath);if(S){o.brandAssets||(o.brandAssets={}),o.brandAssets.styleguide=S,o.updatedAt=Date.now();let x=St(o.themePath,".vibespot");Qn(x)||f(x,{recursive:!0}),y(St(x,"styleguide.md"),S),J(),e.send(JSON.stringify({type:"brand_asset_extracted",assetType:"styleguide"}))}}catch{}e.send(JSON.stringify({type:"brand_extraction_complete"}))}catch(i){e.send(JSON.stringify({type:"brand_extraction_error",message:i instanceof Error?i.message:String(i)}))}})();break}case"start_upload":{let o=C();if(!o){e.send(JSON.stringify({type:"error",message:"No active session"}));break}try{we();let i=_s(o.themePath);if(i.length>0&&e.send(JSON.stringify({type:"upload_status",phase:"autofix",fixes:i})),(R().hubspotUploadMode||"api")==="api"){let l=$e();if(!l){e.send(JSON.stringify({type:"upload_failed",output:"No HubSpot account configured. Open Settings \u2192 HubSpot to add one.",errors:[{file:"",message:"No HubSpot account configured",fixable:!1}]}));break}e.send(JSON.stringify({type:"upload_started",jobId:"api-upload"}));let c=await Ps(l,o.themePath,o.themeName,{onFileStart:d=>{e.send(JSON.stringify({type:"upload_output",chunk:`Uploading ${d}
1809
- `}))},onFileComplete:d=>{e.send(JSON.stringify({type:"upload_output",chunk:` \u2713 ${d}
1810
- `}))},onFileError:(d,u)=>{e.send(JSON.stringify({type:"upload_output",chunk:` \u2717 ${d}: ${u.message}
1811
- `}))},onProgress:(d,u)=>{e.send(JSON.stringify({type:"upload_progress",completed:d,total:u}))}});if(c.success){let d=xt();e.send(JSON.stringify({type:"upload_complete",output:`Uploaded ${c.uploaded} files`,portalId:d?.portalId||"",dataCenter:d?.dataCenter||"na1",themeName:o.themeName}))}else{let d=Ms(c.errors);e.send(JSON.stringify({type:"upload_failed",output:c.errors.map(u=>`${u.file}: ${u.message}`).join(`
1812
- `),errors:d}))}}else{let l=po(`hs cms upload "${o.themePath}" "${o.themeName}"`,"Uploading to HubSpot",{cwd:St(o.themePath,".."),timeout:18e4});e.send(JSON.stringify({type:"upload_started",jobId:l}));let c=u=>{e.send(JSON.stringify({type:"upload_output",chunk:u}))};Ec(l,c);let d=setInterval(()=>{let u=mo(l);if(!(!u||u.status==="running"))if(clearInterval(d),Mc(l,c),u.status==="completed"){let m=Xe(),f=m.portalId?vn(m.portalId):"na1";e.send(JSON.stringify({type:"upload_complete",output:u.output,portalId:m.portalId||"",dataCenter:f,themeName:o.themeName}))}else{let m=Rs(u.output);e.send(JSON.stringify({type:"upload_failed",output:u.output,errors:m,exitCode:u.exitCode}))}},500)}}catch(i){e.send(JSON.stringify({type:"error",message:i instanceof Error?i.message:String(i)}))}break}case"upload_fix_with_ai":{let o=String(s.errorContext||"");if(!o.trim()){e.send(JSON.stringify({type:"error",message:"No error context provided"}));break}let i=`The HubSpot upload ("hs cms upload") failed. Below is the upload log output containing the errors.
1813
-
1814
- IMPORTANT: Be verbose in your response. For each error:
1815
- 1. State exactly which file has the problem and what the error is
1816
- 2. Explain WHY this error occurs (e.g. "HubSpot doesn't support textarea field type" or "field name 'name' is reserved in HubSpot modules")
1817
- 3. Describe the specific fix you're applying (e.g. "Changing field type from textarea to text" or "Renaming field from 'name' to 'item_name'")
1818
- 4. Apply the fix to the module files
1819
-
1820
- CRITICAL: After fixing the reported errors, scan ALL other module files in the theme for the same issues. For example, if you fix "name" \u2192 "item_name" in one module, check every other module's fields.json for the same problem. Fix all occurrences, not just the ones in the error log.
1821
-
1822
- After fixing all errors, summarize the changes you made.
1823
-
1824
- Upload log:
1825
- ${o}`;Ge("user",i),J(),e.send(JSON.stringify({type:"upload_fix_started"}));try{await Un(i,a=>{e.send(JSON.stringify({type:"stream",content:a})),e.send(JSON.stringify({type:"upload_fix_stream",content:a}))});let r=C();if(r){we();let a=_t(r.themePath,"AI fix: upload errors");a&&e.send(JSON.stringify({type:"version_created",hash:a}))}e.send(JSON.stringify({type:"upload_fix_complete"})),e.send(JSON.stringify({type:"modules_updated",modules:ce().map(a=>a.moduleName)}))}catch(r){e.send(JSON.stringify({type:"upload_failed",output:r instanceof Error?r.message:String(r),errors:[{file:"AI fix",message:r instanceof Error?r.message:String(r),fixable:!1}]}))}break}case"ping":e.send(JSON.stringify({type:"pong"}));break;case"plan_approve":{let o=C();if(!o){e.send(JSON.stringify({type:"error",message:"No active session"}));break}let i=o.brandAssets?.plan;if(!i||!i.trim()){e.send(JSON.stringify({type:"error",message:"No plan to approve. Send a chat message first."}));break}V({planMode:!1});let r="Implement the approved plan.";Ge("user",r),J();try{bt();let a=[],l=[],c=await lo(r,xr(a,l));Dt(c,{steps:a,modules:l,stats:c.stats});let d=C();if(d){we();let u=ye(),m=null;if(u){let f=u.moduleOrder.map(y=>`modules/${y}.module`);u.templateFile&&f.push(u.templateFile),u.sharedCss&&f.push(`css/${d.themeName}-theme.css`),u.sharedJs&&f.push(`js/${d.themeName}-animations.js`),m=si(d.themePath,u.id,"Approved plan: implementation",f)}else m=_t(d.themePath,"Approved plan: implementation");m&&ve({type:"version_created",hash:m})}ve({type:"generation_complete"}),ve({type:"modules_updated",modules:ce().map(u=>u.moduleName)}),bt()}catch(a){bt(),ve({type:"error",message:a instanceof Error?a.message:String(a)})}break}case"plan_discard":{Qi(),V({planMode:!1}),e.send(JSON.stringify({type:"plan_discarded"}));break}default:e.send(JSON.stringify({type:"error",message:`Unknown type: ${s.type}`}))}}),_o=e;let t=C();if(t){let n=R(),s={"claude-code":"Claude Code","anthropic-api":"Anthropic API","claude-oauth":"Claude (OAuth)","openai-api":"OpenAI API","gemini-cli":"Gemini CLI","gemini-api":"Gemini API","codex-cli":"Codex CLI",api:"Anthropic API"},o=kt(),i=ye();if(e.send(JSON.stringify({type:"init",sessionId:t.id,themeName:t.themeName,modules:ce().map(r=>r.moduleName),messageCount:t.messages.length,messages:t.messages,gitAvailable:Be(),engine:n.aiEngine?s[n.aiEngine]||n.aiEngine:"",templateId:i?.id||null,pageType:i?.pageType||null,templates:(t.templates||[]).map(r=>({id:r.id,label:r.label,pageType:r.pageType,moduleCount:r.modules.length})),planMode:!!n.planMode,plan:t.brandAssets?.plan||"",isGenerating:o})),o&&Po.length>0)for(let r of Po)e.send(JSON.stringify(r))}else e.send(JSON.stringify({type:"needs_setup"}))}function Lh(e,t){let n=C();if(!n){t.writeHead(404,{"Content-Type":"text/plain"}),t.end("No session");return}let s=St(n.themePath,"assets",e);if(!Qn(s)){t.writeHead(404,{"Content-Type":"text/plain"}),t.end("Asset not found");return}let o=gu(s),i=hu[o]||"application/octet-stream",r=vr(s);t.writeHead(200,{"Content-Type":i,"Cache-Control":"no-cache"}),t.end(r)}function fu(e,t,n,s){let i=St(t,e==="/"?"/index.html":e);if(!Qn(i)){let c=St(t,"index.html");if(Qn(c)){let d=vr(c);s.writeHead(200,{"Content-Type":"text/html","Cache-Control":"no-cache"}),s.end(d)}else s.writeHead(404,{"Content-Type":"text/plain"}),s.end("Not found");return}let r=gu(i),a=hu[r]||"application/octet-stream",l=r===".html";try{let c=vr(i);s.writeHead(200,{"Content-Type":a,"Cache-Control":"no-store"}),s.end(c)}catch{s.writeHead(500,{"Content-Type":"text/plain"}),s.end("Internal Server Error")}}me();var bu=Hh(Uh(import.meta.url)),Gh=4200;async function Su(){let e=Oo.hex("#e8613a"),t=Oo.dim;console.log(""),console.log(e(" v vibeSpot")),console.log(t(` Starting...
1826
- `));let n=Wh();n||(console.error(Oo.red(" Could not find UI assets. Is the package installed correctly?")),process.exit(1));try{let{port:s,close:o}=await yu({port:Gh,uiDir:n}),i=`http://localhost:${s}`;console.log(e(` v ${i}`)),console.log(t(` Press Ctrl+C to stop
1827
- `));try{process.platform==="darwin"?wr("open",[i],{stdio:"ignore"}):process.platform==="win32"?wr("cmd",["/c","start","",i],{stdio:"ignore"}):wr("xdg-open",[i],{stdio:"ignore"})}catch{}await new Promise(r=>{process.on("SIGINT",()=>{console.log(t(`
1828
- Saving session...`)),J(),o(),console.log(t(` Goodbye!
1829
- `)),r(),setTimeout(()=>process.exit(0),500)})})}catch(s){console.error(Oo.red(` Failed to start: ${s instanceof Error?s.message:String(s)}`)),process.exit(1)}}function Wh(){let e=[No(bu,"../../ui"),No(bu,"../ui"),No(process.cwd(),"ui")];for(let t of e)if(Bh(No(t,"index.html")))return t;return null}g();import{resolve as xu}from"path";import{existsSync as Cr}from"fs";X();async function vu(e={}){let t=await Cu(e.path);if(e.fix){let o=Mo(t);if(o.applied.length>0){H(`Applied ${o.applied.length} auto-fix${o.applied.length===1?"":"es"}:`);for(let i of o.applied)P(` ${i}`)}else P(A.muted("No auto-fixable issues found."));if(o.skipped.length>0)for(let i of o.skipped)Z(i)}let n=Xn(t);if(e.json){process.stdout.write(JSON.stringify(n,null,2)+`
1830
- `),n.passed||process.exit(1);return}pe(),await se("Marketplace check");let s=`${n.errorCount} error${Ar(n.errorCount)}, ${n.warningCount} warning${Ar(n.warningCount)}, ${n.infoCount} note${Ar(n.infoCount)}`;n.passed?H(`Theme passes Marketplace checks (${s}).`):z(`Theme is not yet ready: ${s}.`),kr("Errors",n.findings.filter(o=>o.severity==="error")),kr("Warnings",n.findings.filter(o=>o.severity==="warning")),kr("Notes",n.findings.filter(o=>o.severity==="info")),n.passed||(P(""),P(`Tip: run ${A.accent("vibespot marketplace check --fix")} to apply auto-fixable issues, then re-check.`),process.exit(1)),await oe("Looks good! Submit the theme via your HubSpot Marketplace dashboard.")}async function wu(e={}){let t=await Cu(e.path);pe(),await se("Marketplace listing details");let n=mn(t)??{},s=await dt({message:"Category",options:$t.map(u=>({value:u,label:u}))}),o=await le({message:"Description (1\u20132 sentences shown on the listing)",placeholder:"A clean, fast SaaS landing page theme...",defaultValue:n.description??"",validate:u=>u.trim().length<40?"Aim for at least 40 characters.":void 0}),r=(await le({message:"Key features (comma-separated, 2\u20135 items)",placeholder:"Hero, Pricing, Testimonials, Footer",defaultValue:(n.features??[]).join(", "),validate:u=>{let m=u.split(",").map(f=>f.trim()).filter(Boolean).length;if(m<2)return"Provide at least 2 features.";if(m>5)return"Provide at most 5 features."}})).split(",").map(u=>u.trim()).filter(Boolean),a=await le({message:"Public support URL",placeholder:"https://example.com/support",defaultValue:n.supportUrl??"",validate:u=>u&&!/^https?:\/\//i.test(u)?"Must start with http(s)://":void 0}),l=await le({message:"Documentation URL (optional)",placeholder:"https://example.com/docs",defaultValue:n.documentationUrl??"",validate:u=>u&&!/^https?:\/\//i.test(u)?"Must start with http(s)://":void 0}),c=await dt({message:"Pricing tier",options:[{value:"free",label:"Free"},{value:"paid",label:"Paid"}]}),d={category:s,description:o.trim(),features:r,supportUrl:a.trim()||void 0,documentationUrl:l.trim()||void 0,pricingTier:c,tags:n.tags};Eo(t,d),H("Saved marketplace.json"),await oe(`Run ${A.accent("vibespot marketplace check")} to confirm the theme is ready to submit.`)}async function Cu(e){if(e){let o=xu(e);if(!Cr(o))throw new Error(`Theme not found: ${o}`);return o}let t=R();if(t.lastThemePath&&Cr(t.lastThemePath))return t.lastThemePath;pe();let n=await le({message:"Path to your HubSpot theme directory:",placeholder:"./my-theme",validate:o=>o.trim()?void 0:"Path is required"}),s=xu(n);if(!Cr(s))throw new Error(`Theme not found: ${s}`);return s}function kr(e,t){if(t.length!==0){P(""),P(A.heading(e));for(let n of t){let s=n.file?A.muted(`[${n.file}] `):"",o=n.severity==="error"?A.error("\u2717"):n.severity==="warning"?A.warn("!"):A.muted("\xB7");P(` ${o} ${s}${n.message}`),n.fix&&P(` ${A.muted("\u2192 "+n.fix)}`)}}}function Ar(e){return e===1?"":"s"}g();import{resolve as ku}from"path";import{existsSync as Tr}from"fs";import{basename as Vh}from"path";X();qs();async function Au(e={}){let t=await zh(e.path),n=Vh(t);if(e.applyTokens){let i=Ys(t,n);i?H(`Wrote design tokens to ${i}`):P(A.muted("Skipped: theme already has shared CSS or no tokens were inferred."))}if(e.snapshot){let i=gi(t);e.json||H(`Wrote imported theme snapshot to ${i}`)}let s=Ks(t);e.json&&(process.stdout.write(JSON.stringify(s,null,2)+`
1831
- `),process.exit(0)),pe(),await se("Inverse pipeline analyzer");let o=s.summary;if(P(`${A.heading("Summary")} ${o.moduleCount} module(s), ${o.templateCount} template(s), ${o.orphanCount} orphan, ${o.paletteSize} colour(s), ${o.cssVarCount} CSS var(s), ${o.customMacroCount} macro(s)`),s.designTokens.palette.length>0){P(""),P(A.heading("Palette (top by frequency)"));for(let i of s.designTokens.palette.slice(0,6)){let r=i.varName?A.muted(` (${i.varName})`):"";P(` ${i.value} ${A.muted(`\xD7${i.count}`)}${r}`)}}if(s.designTokens.fontFamilies.length>0){P(""),P(A.heading("Typography"));for(let i of s.designTokens.fontFamilies.slice(0,4))P(` ${i}`)}if(s.graph.templates.length>0){P(""),P(A.heading("Template \u2192 modules"));for(let i of s.graph.templates)P(` ${i.id}: ${i.modules.length===0?A.muted("(empty)"):i.modules.join(", ")}`)}if(s.graph.orphanModules.length>0){P(""),P(A.heading("Orphan modules"));for(let i of s.graph.orphanModules)P(` ${i}`)}if(s.roundTripDiff.hasSnapshot){P(""),P(A.heading("Round-trip diff"));let i=s.roundTripDiff;if(i.filesChanged===0)P(` ${A.muted("No changes from imported snapshot.")}`);else{P(` ${i.filesChanged} changed file(s): ${i.added} added, ${i.modified} modified, ${i.deleted} deleted`);for(let r of i.files.slice(0,12))P(` ${r.status.padEnd(8)} ${r.file}`);i.files.length>12&&P(` ${A.muted(`...and ${i.files.length-12} more`)}`)}}$r("Errors",s.findings.filter(i=>i.severity==="error")),$r("Warnings",s.findings.filter(i=>i.severity==="warning")),$r("Notes",s.findings.filter(i=>i.severity==="info")),!e.applyTokens&&s.summary.cssVarCount===0&&s.designTokens.palette.length>0&&(P(""),P(`Tip: run ${A.accent("vibespot inverse --apply-tokens")} to seed a :root block from the inferred palette.`)),await oe("Analysis complete."),process.exit(0)}async function zh(e){if(e){let o=ku(e);if(!Tr(o))throw new Error(`Theme not found: ${o}`);return o}let t=R();if(t.lastThemePath&&Tr(t.lastThemePath))return t.lastThemePath;pe();let n=await le({message:"Path to the imported HubSpot theme directory:",placeholder:"./my-theme",validate:o=>o.trim()?void 0:"Path is required"}),s=ku(n);if(!Tr(s))throw new Error(`Theme not found: ${s}`);return s}function $r(e,t){if(t.length!==0){P(""),P(A.heading(e));for(let n of t){let s=n.file?A.muted(`[${n.file}] `):"",o=n.severity==="error"?A.error("\u2717"):n.severity==="warning"?A.warn("!"):A.muted("\xB7");P(` ${o} ${s}${n.message}`),n.fix&&P(` ${A.muted("\u2192 "+n.fix)}`)}}}Q();function Tu(){let e=new Kh;e.name("vibespot").description("AI-powered HubSpot CMS landing page builder").version(Vt()).action(Su),e.command("wizard").description("Classic CLI wizard \u2014 step-by-step conversion flow").action(ka),e.command("init").description("Check and install required tools").action(Aa),e.command("convert").description("Convert a React project to HubSpot modules").action(Ta),e.command("upload").description("Upload theme to HubSpot").action($a),e.command("doctor").description("Diagnose environment issues").action(Ia);let t=e.command("marketplace").description("Prepare a theme for HubSpot Marketplace submission");return t.command("check").description("Audit the theme against Marketplace requirements").option("-p, --path <path>","Path to the theme directory").option("--json","Emit machine-readable JSON instead of formatted output").option("--fix","Apply auto-fixable findings before checking").action(n=>vu(n)),t.command("edit").description("Edit Marketplace listing metadata (marketplace.json)").option("-p, --path <path>","Path to the theme directory").action(n=>wu(n)),e.command("inverse").description("Analyze an imported HubSpot theme: design tokens, module graph, field flags, round-trip risks").option("-p, --path <path>","Path to the theme directory").option("--json","Emit machine-readable JSON instead of formatted output").option("--apply-tokens","Seed css/<theme>-theme.css with the inferred :root block when missing").option("--snapshot","Capture the current theme as the imported round-trip baseline before analysis").action(n=>Au(n)),e}var Yh=Tu();Yh.parseAsync(process.argv).catch(e=>{console.error(e),process.exit(1)});
2888
+ ${_.bold("1.")} Go to HubSpot ${_.muted("\u2192")} Content ${_.muted("\u2192")} Landing Pages ${_.muted("\u2192")} Create
2889
+ ${_.bold("2.")} Choose your uploaded theme from the theme picker
2890
+ ${_.bold("3.")} Select the landing page template that was just created
2891
+ ${_.bold("4.")} Your converted modules will appear \u2014 drag them onto the page
2892
+ ${_.bold("5.")} Click each section to edit text, images, and colors
2893
+ ${_.bold("6.")} Upload images via File Manager ${_.muted("(Settings \u2192 Files)")}
2894
+ ${_.bold("7.")} Preview and publish!`,"What's next"),await Ae({message:"Open HubSpot Landing Pages in your browser?"})){let c=e?`https://${r}/page-ui/${e}/management/pages/landing`:`https://${r}`;try{let d=process.platform;d==="darwin"?$i("open",[c],{stdio:"ignore"}):d==="win32"?$i("cmd",["/c","start","",c],{stdio:"ignore"}):$i("xdg-open",[c],{stdio:"ignore"}),G("Opening HubSpot Landing Pages...")}catch{j(`Open this URL in your browser: ${_.info(c)}`)}}let l=[];if(o&&v(n)&&l.push({path:n,label:`Cloned source (${sl(n)})`}),v(s)&&l.push({path:s,label:`Theme directory (${sl(s)})`}),l.length>0&&await Ae({message:"Clean up local working directories?"}))for(let d of l)try{og(d.path,{recursive:!0,force:!0}),G(`Removed ${d.label}`)}catch{ee(`Could not remove ${d.label} \u2014 delete manually if needed.`)}await pe(`Thanks for using hub${_.vibes("Vibes")}! ${_.vibes("~")}`)}Q();async function il(){Te();let t=await Ls(),e=await Js();Y({lastSourcePath:e.sourceDir});let n=await Us();Y({lastThemePath:n.themePath}),await qs({aiEngine:t.aiEngine,model:t.model,sourceDir:e.sourceDir,themePath:n.themePath}),await cn(n.themePath),await ol({portalId:t.portalId,sourceDir:e.sourceDir,themePath:n.themePath,wasCloned:e.wasCloned})}y();async function rl(){Te(),await Ls()}y();Bs();Q();Ye();async function al(){Te();let t=O();t.aiEngine||(z("AI engine not configured. Run `vibespot init` first or use the full wizard with `vibespot`."),process.exit(1));let e=await Js(),n=await Us();await qs({aiEngine:t.aiEngine,sourceDir:e.sourceDir,themePath:n.themePath})}y();Q();Ye();async function ll(){Te();let t=O();if(t.lastThemePath)if(await Ae({message:`Upload from ${t.lastThemePath}?`}))await cn(t.lastThemePath);else{let n=await be({message:"Path to your HubSpot theme directory:",placeholder:"./my-theme"});await cn(n)}else{let e=await be({message:"Path to your HubSpot theme directory:",placeholder:"./my-theme",validate:n=>n.trim()?void 0:"Path is required"});await cn(e)}}y();Ht();Q();Ye();at();async function cl(){Te(),await me("Environment Diagnostics");let t=0,e=En();e.found?Ns(e.version)?G(`Node.js v${e.version}`):(ee(`Node.js v${e.version} \u2014 too old (need 18+)`),j(" Update at https://nodejs.org"),t++):(z("Node.js \u2014 not installed"),j(" Install from https://nodejs.org"),t++);let n=In();n.found?G(`Git ${n.version}`):(z("Git \u2014 not installed"),j(" Install from https://git-scm.com"),t++);let s=ct();if(!s.found)ee("HubSpot CLI \u2014 not installed (only needed for deployment)"),j(" Install: npm install -g @hubspot/cli");else if(!ya(s.version))ee(`HubSpot CLI v${s.version} \u2014 too old (need v8+)`),j(" Update: npm install -g @hubspot/cli@latest"),t++;else{G(`HubSpot CLI v${s.version}`);let m=dt();m.authenticated?G(`HubSpot portal${m.portalName?`: ${m.portalName}`:""} (ID: ${m.portalId})`):(ee("HubSpot \u2014 not authenticated"),j(" Run: hs init"))}let o=Pn();o.found?G(`Claude Code ${o.version} at ${o.path}`):j(_.muted("Claude Code \u2014 not installed"));let i=Nn();i.found?G(`Gemini CLI ${i.version} at ${i.path}`):j(_.muted("Gemini CLI \u2014 not installed"));let r=On();r.found?G(`OpenAI Codex ${r.version} at ${r.path}`):j(_.muted("OpenAI Codex \u2014 not installed"));let a=O(),l=!!(a.anthropicApiKey||process.env.ANTHROPIC_API_KEY),c=!!(a.openaiApiKey||process.env.OPENAI_API_KEY),d=!!(a.geminiApiKey||process.env.GEMINI_API_KEY||process.env.GOOGLE_AI_API_KEY);l?G("Anthropic API key configured"):j(_.muted("Anthropic API key \u2014 not set")),c?G("OpenAI API key configured"):j(_.muted("OpenAI API key \u2014 not set")),d?G("Google AI API key configured"):j(_.muted("Google AI API key \u2014 not set"));let u={"claude-code":"Claude Code",api:"Anthropic API","anthropic-api":"Anthropic API","claude-oauth":"Claude (OAuth)","openai-api":"OpenAI API","gemini-api":"Gemini API","gemini-cli":"Gemini CLI","codex-cli":"OpenAI Codex"};a.aiEngine&&G(`AI engine: ${u[a.aiEngine]||a.aiEngine}`),a.lastThemePath&&j(_.muted(`Last theme: ${a.lastThemePath}`)),!o.found&&!i.found&&!r.found&&!l&&!c&&!d&&(ee("No AI engine available"),j(" Fastest: Set an API key (ANTHROPIC_API_KEY, OPENAI_API_KEY, or GEMINI_API_KEY)"),j(" Or install: Claude Code \u2014 https://claude.ai/code"),j(" Gemini CLI \u2014 https://github.com/google-gemini/gemini-cli"),j(" Codex CLI \u2014 https://github.com/openai/codex"),t++),console.log(),t===0?await pe("Everything looks good!"):await pe(_.warn(`${t} issue${t>1?"s":""} found \u2014 see above`))}y();ts();we();import{dirname as _b,join as oi}from"path";import{existsSync as Mb}from"fs";import{fileURLToPath as Eb}from"url";import{execFileSync as Zr}from"child_process";import ii from"chalk";var Gm=_b(Eb(import.meta.url)),Ib=4200;async function Wm(){let t=ii.hex("#e8613a"),e=ii.dim;console.log(""),console.log(t(" v vibeSpot")),console.log(e(` Starting...
2895
+ `));let n=Pb();n||(console.error(ii.red(" Could not find UI assets. Is the package installed correctly?")),process.exit(1));try{let{port:s,close:o}=await si({port:Ib,uiDir:n}),i=`http://localhost:${s}`;console.log(t(` v ${i}`)),console.log(e(` Press Ctrl+C to stop
2896
+ `));try{process.platform==="darwin"?Zr("open",[i],{stdio:"ignore"}):process.platform==="win32"?Zr("cmd",["/c","start","",i],{stdio:"ignore"}):Zr("xdg-open",[i],{stdio:"ignore"})}catch{}await new Promise(r=>{process.on("SIGINT",()=>{console.log(e(`
2897
+ Saving session...`)),D(),o(),console.log(e(` Goodbye!
2898
+ `)),r(),setTimeout(()=>process.exit(0),500)})})}catch(s){console.error(ii.red(` Failed to start: ${s instanceof Error?s.message:String(s)}`)),process.exit(1)}}function Pb(){let t=[oi(Gm,"../../ui"),oi(Gm,"../ui"),oi(process.cwd(),"ui")];for(let e of t)if(Mb(oi(e,"index.html")))return e;return null}y();import{resolve as Km}from"path";import{existsSync as Qr}from"fs";at();Ye();Q();zr();async function Vm(t={}){let e=await Ym(t.path);if(t.fix){let o=Qo(e);if(o.applied.length>0){G(`Applied ${o.applied.length} auto-fix${o.applied.length===1?"":"es"}:`);for(let i of o.applied)j(` ${i}`)}else j(_.muted("No auto-fixable issues found."));if(o.skipped.length>0)for(let i of o.skipped)ee(i)}let n=Ss(e);if(t.json){process.stdout.write(JSON.stringify(n,null,2)+`
2899
+ `),n.passed||process.exit(1);return}Te(),await me("Marketplace check");let s=`${n.errorCount} error${ta(n.errorCount)}, ${n.warningCount} warning${ta(n.warningCount)}, ${n.infoCount} note${ta(n.infoCount)}`;n.passed?G(`Theme passes Marketplace checks (${s}).`):z(`Theme is not yet ready: ${s}.`),ea("Errors",n.findings.filter(o=>o.severity==="error")),ea("Warnings",n.findings.filter(o=>o.severity==="warning")),ea("Notes",n.findings.filter(o=>o.severity==="info")),n.passed||(j(""),j(`Tip: run ${_.accent("vibespot marketplace check --fix")} to apply auto-fixable issues, then re-check.`),process.exit(1)),await pe("Looks good! Submit the theme via your HubSpot Marketplace dashboard.")}async function zm(t={}){let e=await Ym(t.path);Te(),await me("Marketplace listing details");let n=Tn(e)??{},s=await wt({message:"Category",options:Lt.map(u=>({value:u,label:u}))}),o=await be({message:"Description (1\u20132 sentences shown on the listing)",placeholder:"A clean, fast SaaS landing page theme...",defaultValue:n.description??"",validate:u=>u.trim().length<40?"Aim for at least 40 characters.":void 0}),r=(await be({message:"Key features (comma-separated, 2\u20135 items)",placeholder:"Hero, Pricing, Testimonials, Footer",defaultValue:(n.features??[]).join(", "),validate:u=>{let m=u.split(",").map(g=>g.trim()).filter(Boolean).length;if(m<2)return"Provide at least 2 features.";if(m>5)return"Provide at most 5 features."}})).split(",").map(u=>u.trim()).filter(Boolean),a=await be({message:"Public support URL",placeholder:"https://example.com/support",defaultValue:n.supportUrl??"",validate:u=>u&&!/^https?:\/\//i.test(u)?"Must start with http(s)://":void 0}),l=await be({message:"Documentation URL (optional)",placeholder:"https://example.com/docs",defaultValue:n.documentationUrl??"",validate:u=>u&&!/^https?:\/\//i.test(u)?"Must start with http(s)://":void 0}),c=await wt({message:"Pricing tier",options:[{value:"free",label:"Free"},{value:"paid",label:"Paid"}]}),d={category:s,description:o.trim(),features:r,supportUrl:a.trim()||void 0,documentationUrl:l.trim()||void 0,pricingTier:c,tags:n.tags};Zo(e,d),G("Saved marketplace.json"),await pe(`Run ${_.accent("vibespot marketplace check")} to confirm the theme is ready to submit.`)}async function Ym(t){if(t){let o=Km(t);if(!Qr(o))throw new Error(`Theme not found: ${o}`);return o}let e=O();if(e.lastThemePath&&Qr(e.lastThemePath))return e.lastThemePath;Te();let n=await be({message:"Path to your HubSpot theme directory:",placeholder:"./my-theme",validate:o=>o.trim()?void 0:"Path is required"}),s=Km(n);if(!Qr(s))throw new Error(`Theme not found: ${s}`);return s}function ea(t,e){if(e.length!==0){j(""),j(_.heading(t));for(let n of e){let s=n.file?_.muted(`[${n.file}] `):"",o=n.severity==="error"?_.error("\u2717"):n.severity==="warning"?_.warn("!"):_.muted("\xB7");j(` ${o} ${s}${n.message}`),n.fix&&j(` ${_.muted("\u2192 "+n.fix)}`)}}}function ta(t){return t===1?"":"s"}y();import{resolve as qm}from"path";import{existsSync as na}from"fs";import{basename as Rb}from"path";at();Ye();Q();bo();async function Xm(t={}){let e=await Nb(t.path),n=Rb(e);if(t.applyTokens){let i=yo(e,n);i?G(`Wrote design tokens to ${i}`):j(_.muted("Skipped: theme already has shared CSS or no tokens were inferred."))}if(t.snapshot){let i=Li(e);t.json||G(`Wrote imported theme snapshot to ${i}`)}let s=ho(e);t.json&&(process.stdout.write(JSON.stringify(s,null,2)+`
2900
+ `),process.exit(0)),Te(),await me("Inverse pipeline analyzer");let o=s.summary;if(j(`${_.heading("Summary")} ${o.moduleCount} module(s), ${o.templateCount} template(s), ${o.orphanCount} orphan, ${o.paletteSize} colour(s), ${o.cssVarCount} CSS var(s), ${o.customMacroCount} macro(s)`),s.designTokens.palette.length>0){j(""),j(_.heading("Palette (top by frequency)"));for(let i of s.designTokens.palette.slice(0,6)){let r=i.varName?_.muted(` (${i.varName})`):"";j(` ${i.value} ${_.muted(`\xD7${i.count}`)}${r}`)}}if(s.designTokens.fontFamilies.length>0){j(""),j(_.heading("Typography"));for(let i of s.designTokens.fontFamilies.slice(0,4))j(` ${i}`)}if(s.graph.templates.length>0){j(""),j(_.heading("Template \u2192 modules"));for(let i of s.graph.templates)j(` ${i.id}: ${i.modules.length===0?_.muted("(empty)"):i.modules.join(", ")}`)}if(s.graph.orphanModules.length>0){j(""),j(_.heading("Orphan modules"));for(let i of s.graph.orphanModules)j(` ${i}`)}if(s.roundTripDiff.hasSnapshot){j(""),j(_.heading("Round-trip diff"));let i=s.roundTripDiff;if(i.filesChanged===0)j(` ${_.muted("No changes from imported snapshot.")}`);else{j(` ${i.filesChanged} changed file(s): ${i.added} added, ${i.modified} modified, ${i.deleted} deleted`);for(let r of i.files.slice(0,12))j(` ${r.status.padEnd(8)} ${r.file}`);i.files.length>12&&j(` ${_.muted(`...and ${i.files.length-12} more`)}`)}}sa("Errors",s.findings.filter(i=>i.severity==="error")),sa("Warnings",s.findings.filter(i=>i.severity==="warning")),sa("Notes",s.findings.filter(i=>i.severity==="info")),!t.applyTokens&&s.summary.cssVarCount===0&&s.designTokens.palette.length>0&&(j(""),j(`Tip: run ${_.accent("vibespot inverse --apply-tokens")} to seed a :root block from the inferred palette.`)),await pe("Analysis complete."),process.exit(0)}async function Nb(t){if(t){let o=qm(t);if(!na(o))throw new Error(`Theme not found: ${o}`);return o}let e=O();if(e.lastThemePath&&na(e.lastThemePath))return e.lastThemePath;Te();let n=await be({message:"Path to the imported HubSpot theme directory:",placeholder:"./my-theme",validate:o=>o.trim()?void 0:"Path is required"}),s=qm(n);if(!na(s))throw new Error(`Theme not found: ${s}`);return s}function sa(t,e){if(e.length!==0){j(""),j(_.heading(t));for(let n of e){let s=n.file?_.muted(`[${n.file}] `):"",o=n.severity==="error"?_.error("\u2717"):n.severity==="warning"?_.warn("!"):_.muted("\xB7");j(` ${o} ${s}${n.message}`),n.fix&&j(` ${_.muted("\u2192 "+n.fix)}`)}}}y();ts();we();import{dirname as Ob,join as ri}from"path";import{existsSync as Fb}from"fs";import{fileURLToPath as jb}from"url";import{execFileSync as oa}from"child_process";import ai from"chalk";var Zm=Ob(jb(import.meta.url)),Db=4200;async function Qm(){let t=ai.hex("#e8613a"),e=ai.dim;console.log(""),console.log(t(" v vibeSpot \u2014 Email Mode")),console.log(e(` Starting...
2901
+ `));let n=Lb();n||(console.error(ai.red(" Could not find UI assets. Is the package installed correctly?")),process.exit(1));try{let{port:s,close:o}=await si({port:Db,uiDir:n,contentMode:"email"}),i=`http://localhost:${s}`;console.log(t(` v ${i}`)),console.log(e(` Email template mode \u2014 Press Ctrl+C to stop
2902
+ `));try{process.platform==="darwin"?oa("open",[i],{stdio:"ignore"}):process.platform==="win32"?oa("cmd",["/c","start","",i],{stdio:"ignore"}):oa("xdg-open",[i],{stdio:"ignore"})}catch{}await new Promise(r=>{process.on("SIGINT",()=>{console.log(e(`
2903
+ Saving session...`)),D(),o(),console.log(e(` Goodbye!
2904
+ `)),r(),setTimeout(()=>process.exit(0),500)})})}catch(s){console.error(ai.red(` Failed to start: ${s instanceof Error?s.message:String(s)}`)),process.exit(1)}}function Lb(){let t=[ri(Zm,"../../ui"),ri(Zm,"../ui"),ri(process.cwd(),"ui")];for(let e of t)if(Fb(ri(e,"index.html")))return e;return null}ne();function ep(){let t=new Jb;t.name("vibespot").description("AI-powered HubSpot CMS landing page builder").version(sn()).action(Wm),t.command("wizard").description("Classic CLI wizard \u2014 step-by-step conversion flow").action(il),t.command("init").description("Check and install required tools").action(rl),t.command("convert").description("Convert a React project to HubSpot modules").action(al),t.command("upload").description("Upload theme to HubSpot").action(ll),t.command("doctor").description("Diagnose environment issues").action(cl);let e=t.command("marketplace").description("Prepare a theme for HubSpot Marketplace submission");return e.command("check").description("Audit the theme against Marketplace requirements").option("-p, --path <path>","Path to the theme directory").option("--json","Emit machine-readable JSON instead of formatted output").option("--fix","Apply auto-fixable findings before checking").action(n=>Vm(n)),e.command("edit").description("Edit Marketplace listing metadata (marketplace.json)").option("-p, --path <path>","Path to the theme directory").action(n=>zm(n)),t.command("email").description("Launch email template generation mode").action(Qm),t.command("inverse").description("Analyze an imported HubSpot theme: design tokens, module graph, field flags, round-trip risks").option("-p, --path <path>","Path to the theme directory").option("--json","Emit machine-readable JSON instead of formatted output").option("--apply-tokens","Seed css/<theme>-theme.css with the inferred :root block when missing").option("--snapshot","Capture the current theme as the imported round-trip baseline before analysis").action(n=>Xm(n)),t}var Bb=ep();Bb.parseAsync(process.argv).catch(t=>{console.error(t),process.exit(1)});
1832
2905
  //# sourceMappingURL=index.js.map