vibespot 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -271
- package/assets/prompts.bundle.json +53 -0
- package/assets/readme/00-hero-banner.png +0 -0
- package/assets/readme/00-hero-banner.svg +59 -0
- package/assets/readme/01-vibe-coding-hero.png +0 -0
- package/assets/readme/02-plan-mode.png +0 -0
- package/assets/readme/03-figma-import.png +0 -0
- package/assets/readme/04-multi-page-sites.png +0 -0
- package/assets/readme/05-inline-wysiwyg.png +0 -0
- package/assets/readme/06-hubspot-upload.png +0 -0
- package/dist/index.js +420 -420
- package/dist/index.js.map +1 -1
- package/package.json +10 -3
- package/ui/chat.js +106 -0
- package/ui/docs/index.html +55 -16
- package/ui/docs/screenshots.zip +0 -0
- package/ui/index.html +1 -0
- package/ui/settings.js +339 -17
- package/ui/styles.css +22 -0
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
var
|
|
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";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
|
|
3
|
-
`)[0]?.replace("gh version ","").split(" ")[0]||"",path:te(`${Bt} gh`).stdout}}function yi(){let e=te("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 ha(){return!!process.env.ANTHROPIC_API_KEY}function Ns(e){return parseInt(e.split(".")[0],10)>=18}function ya(e){let t=parseInt(e.split(".")[0],10);return!isNaN(t)&&t>=8}function bp(){let e=O(),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=It();return{authenticated:!!o,portalName:o?.portalName||"",portalId:o?.portalId||"",dataCenter:o?o.dataCenter:"na1",accounts:s,uploadMode:t}}function Os(){let e=O(),t=Mn(),n=In(),s=e.hubspotUploadMode||"api",o;if(s==="cli"){let x=ct(),v=x.found?dt():{authenticated:!1,portalName:"",portalId:"",accounts:[]},I=v.portalId?Rn(v.portalId):"na1";o={...x,...v,dataCenter:I,uploadMode:"cli"}}else o={name:"HubSpot API",found:!0,version:"v3",path:"",...bp()};let i=hi(),r=i.found?yi():{authenticated:!1,username:""},a={authenticated:lt(),expiresAt:En()?.expiresAt},l=e.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(x,...v){if(x)return{configured:!0,masked:$s(x),source:"config"};for(let I of v)if(process.env[I])return{configured:!0,masked:$s(process.env[I]),source:"env"};return{configured:!1,masked:"",source:null}}let g=m(e.anthropicApiKey,"ANTHROPIC_API_KEY"),h=m(e.openaiApiKey,"OPENAI_API_KEY"),f=m(e.geminiApiKey,"GEMINI_API_KEY","GOOGLE_AI_API_KEY"),b=m(e.langdockApiKey,"LANGDOCK_API_KEY"),S=[];return c.found&&c.authenticated&&S.push("claude-code"),a.authenticated&&S.push("claude-oauth"),g.configured&&S.push("anthropic-api"),h.configured&&S.push("openai-api"),d.found&&d.authenticated&&S.push("gemini-cli"),f.configured&&S.push("gemini-api"),u.found&&u.authenticated&&S.push("codex-cli"),b.configured&&S.push("langdock-api"),{tools:{node:t,git:n,hubspot:o,github:{...i,...r},claudeCode:c,claudeOAuth:a,geminiCli:d,codexCli:u},apiKeys:{anthropic:g,openai:h,gemini:f,langdock:b},activeEngine:e.aiEngine||null,availableEngines:S,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 Sp}from"fs";import{basename as xp}from"path";async function Sa(e){let t=ba.get(e);if(t&&t.expiresAt-Date.now()>Cp)return t;let n=await fetch(`${vt}/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 ba.set(e,o),o}async function an(e){let{accessToken:t}=await Sa(e);return{Authorization:`Bearer ${t}`}}function Fs(e){return e.replace(/^\/+/,"").split("/").filter(Boolean).map(encodeURIComponent).join("/")}function kp(e){return e.startsWith("pat-eu1-")?"eu1":e.startsWith("pat-na1-")?"na1":e.startsWith("CiRldTE")?"eu1":"na1"}function Tp(e){return new Promise(t=>setTimeout(t,e))}async function Fn(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 jn(e,t,n=vp){for(let s=0;s<=n;s++){let o=await fetch(e,t);if(o.status===429||o.status>=500&&s<n){let i=wp*Math.pow(2,s);await Tp(i);continue}return o}return fetch(e,t)}async function js(e){let t=await Sa(e),n=`${vt}/account-info/v3/details`,s=await jn(n,{headers:await an(e)});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||t.hubId||""),r=t.hubName||o.uiDomain||i;return{portalId:i,portalName:r,dataCenter:kp(e)}}async function xa(e,t,n){let s=Sp(n),o=xp(n),i=new FormData,r=new Blob([s]);i.append("file",r,o);let a=`${vt}/cms/v3/source-code/published/content/${Fs(t)}`,l=await jn(a,{method:"PUT",headers:await an(e),body:i});if(!l.ok){let c=await Fn(l,t);return{success:!1,path:t,error:c}}return{success:!0,path:t}}async function bi(e,t){let n=`${vt}/cms/v3/source-code/published/content/${Fs(t)}`,s=await jn(n,{method:"DELETE",headers:await an(e)});if(!s.ok&&s.status!==404){let o=await Fn(s,t);throw new Error(`Failed to delete ${t}: ${o.message}`)}}async function va(e,t){let n=`${vt}/cms/v3/source-code/published/content/${Fs(t)}`,s=await jn(n,{method:"GET",headers:await an(e)});if(!s.ok){let i=await Fn(s,t);throw new Error(`Failed to download ${t}: ${i.message}`)}let o=await s.arrayBuffer();return Buffer.from(o)}async function Ds(e,t){let n=`${vt}/cms/v3/source-code/published/metadata/${Fs(t)}`,s=await jn(n,{method:"GET",headers:await an(e)});if(s.status===404)return null;if(!s.ok){let o=await Fn(s,t);throw new Error(`Failed to get metadata for ${t}: ${o.message}`)}return await s.json()}async function wa(e){let t=await an(e),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: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 vt,vp,wp,Cp,ba,Gt=R(()=>{"use strict";y();vt="https://api.hubapi.com",vp=3,wp=1e3,Cp=300*1e3,ba=new Map});import*as se from"@clack/prompts";function Si(e){se.isCancel(e)&&(se.cancel(_.muted("Operation cancelled.")),process.exit(0))}async function me(e){se.intro(_.heading(e))}async function pe(e){se.outro(_.success(e))}async function ut(e,t){se.note(e,t?_.heading(t):void 0)}async function be(e){let t=await se.text({message:_.accent(e.message),placeholder:e.placeholder,defaultValue:e.defaultValue,validate:e.validate});return Si(t),t}async function Ae(e){let t=await se.confirm({message:_.accent(e.message),initialValue:e.initialValue??!0});return Si(t),t}async function wt(e){let t=await se.select({message:_.accent(e.message),options:e.options});return Si(t),t}async function Pe(){let e=se.spinner();return{start:t=>e.start(_.muted(t)),stop:t=>e.stop(_.success(t)),message:t=>e.message(_.muted(t))}}function j(e){se.log.info(e)}function U(e){se.log.success(_.success(e))}function ee(e){se.log.warn(_.warn(e))}function z(e){se.log.error(_.error(e))}var Ye=R(()=>{"use strict";y();at()});import{readdirSync as xi,statSync as Ap}from"fs";import{join as ge,basename as vi,extname as $p}from"path";function Ca(e){return typeof e!="string"||e.length===0||e.length>2048||/[\s;&|`$()<>\\]/.test(e)?!1:!!(/^https?:\/\/[^\s]+$/.test(e)||/^git@[\w.-]+:[\w./~+-]+$/.test(e))}function ka(e){let t=[],n=[ge(e,"src/components/landing"),ge(e,"src/components/sections"),ge(e,"src/components"),ge(e,"src/pages"),ge(e,"app/components"),ge(e,"components")];for(let s of n)if(w(s))try{let o=xi(s);for(let i of o){let r=ge(s,i);if(!Ap(r).isFile())continue;let l=$p(i);if(![".tsx",".jsx"].includes(l))continue;let c=vi(i,l);if(c.startsWith("ui")||c==="index")continue;let d=E(r),u=_p(c,d);t.push({name:c,path:r,description:u})}}catch{}return t}function _p(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 Ta(e){let t=[ge(e,"src/index.css"),ge(e,"src/globals.css"),ge(e,"src/app/globals.css"),ge(e,"app/globals.css")],n=0,s=[];for(let o of t){if(!w(o))continue;let i=E(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(e){let t=[],n=ge(e,"src/hooks");if(w(n))try{let o=xi(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=ge(e,"src/components/landing");if(w(s))try{let o=xi(s);for(let i of o){if(!i.endsWith(".tsx")&&!i.endsWith(".jsx"))continue;let r=E(ge(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 $a(e){let t,n=!1;if(e.startsWith("http")||e.startsWith("git@")){if(!Ca(e))throw new Error(`Refusing to clone unsafe source URL: ${e}. Only http(s):// and git@host:path URLs without shell metacharacters are allowed.`);n=!0;let l=vi(e.replace(/\.git$/,""))||"react-source";if(t=ge(process.cwd(),"workspace",l),!w(t)){let c=X(["clone","--depth","1","--",e,t]);if(!c.success)throw new Error(`Failed to clone ${e}: ${c.stderr}`)}}else if(t=e,!w(t))throw new Error(`Directory not found: ${t}`);let s=ka(t),o=w(ge(t,"tailwind.config.ts"))||w(ge(t,"tailwind.config.js")),{varCount:i,fonts:r}=Ta(t),a=Aa(t);return{sourceDir:t,wasCloned:n,components:s,hasTailwind:o,cssVarCount:i,fonts:r,interactions:a}}async function Js(){await me("Source Project");let e=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"}}),t,n=!1;if(e.startsWith("http")||e.startsWith("git@")){Ca(e)||(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(e.replace(/\.git$/,""))||"react-source";if(t=ge(process.cwd(),"workspace",h),w(t))U(`Using existing clone: ${_.dim(t)}`);else{let f=await Pe();f.start("Cloning repository..."),X(["clone","--depth","1","--",e,t]).success||(f.stop("Clone failed"),z(`Failed to clone ${e}. Check the URL and your access permissions.`),process.exit(1)),f.stop(`Cloned to ${_.dim(t)}`)}}else t=e,w(t)||(z(`Directory not found: ${t}`),process.exit(1)),U(`Using local source: ${_.dim(t)}`);let s=await Pe();s.start("Analyzing project structure...");let o=ka(t),i=w(ge(t,"tailwind.config.ts"))||w(ge(t,"tailwind.config.js")),{varCount:r,fonts:a}=Ta(t),l=Aa(t);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
|
|
1
|
+
var Zp=Object.defineProperty;var N=(e,t)=>()=>(e&&(t=e(e=0)),t);var Ge=(e,t)=>{for(var n in t)Zp(e,n,{get:t[n],enumerable:!0})};import nv from"path";import{fileURLToPath as ov}from"url";var y=N(()=>{"use strict"});import mn from"chalk";function Tt(e){return Da?mn:mn.hex(e)}var mt,Da,I,pt=N(()=>{"use strict";y();mt={accent:"#FF7A59",accentBright:"#FF9A7A",success:"#00BDA5",info:"#0066FF",warn:"#FFB020",error:"#E23D2D",muted:"#8B8D91",vibes:"#00BDD6"},Da=!!process.env.NO_COLOR;I={accent:Tt(mt.accent),accentBright:Tt(mt.accentBright),success:Tt(mt.success),info:Tt(mt.info),warn:Tt(mt.warn),error:Tt(mt.error),muted:Tt(mt.muted),vibes:Tt(mt.vibes),heading:Da?mn.bold:mn.bold.hex(mt.accent),command:Tt(mt.accentBright),dim:mn.dim,bold:mn.bold}});import{readFileSync as Mi,writeFileSync as Qp,mkdirSync as ja,existsSync as Us}from"fs";import{dirname as La,join as At}from"path";import{fileURLToPath as eg}from"url";function P(e){return Mi(e,"utf-8")}function J(e,t){ja(La(e),{recursive:!0}),Qp(e,t,"utf-8")}function x(e){return Us(e)}function Re(e){ja(e,{recursive:!0})}function fn(e){let t=[At(gn,"../../assets",e),At(gn,"../assets",e),At(process.cwd(),"assets",e)];for(let n of t)if(Us(n))return n;throw new Error(`Asset not found: ${e}`)}function hn(){if(pn)return pn;let e=[At(gn,"../../package.json"),At(gn,"../package.json"),At(process.cwd(),"package.json")];for(let t of e)if(Us(t))try{let n=JSON.parse(Mi(t,"utf-8"));if(n.name==="vibespot"&&n.version)return pn=n.version,pn}catch{}return pn="dev",pn}function Ja(){if(Hs)return Hs;let e=[At(gn,"../../CHANGELOG.md"),At(gn,"../CHANGELOG.md"),At(process.cwd(),"CHANGELOG.md")];for(let t of e)if(Us(t))try{return Hs=Mi(t,"utf-8"),Hs}catch{}return""}var gn,pn,Hs,oe=N(()=>{"use strict";y();gn=La(eg(import.meta.url));pn="";Hs=""});import{execSync as Ba,execFileSync as tg}from"child_process";function ie(e,t={}){try{return{stdout:Ba(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 Z(e,t={}){try{return{stdout:tg("git",e,{encoding:"utf-8",stdio:["pipe","pipe","pipe"],timeout:12e4,...t}).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 Ha(e,t={}){try{return Ba(e,{stdio:"inherit",timeout:3e5,...t}),!0}catch{return!1}}var Yt=N(()=>{"use strict";y()});var Wa={};Ge(Wa,{addHubSpotAccount:()=>Vn,getActiveHubSpotAccount:()=>Lt,getApiKeyForEngine:()=>Oe,getConfigDir:()=>og,getHubSpotPak:()=>Le,isCliToolEnabled:()=>st,loadConfig:()=>R,maskApiKey:()=>Ws,removeHubSpotAccount:()=>Ii,saveConfig:()=>Y,setActiveHubSpotAccount:()=>Pi,setCliToolEnabled:()=>Ni});import{join as Ua}from"path";import{homedir as ng}from"os";import{chmodSync as sg}from"fs";function R(){let e={};if(x(Gs))try{e=JSON.parse(P(Gs)),e.aiEngine==="api"&&(e.aiEngine="anthropic-api")}catch{e={}}return process.env.VIBESPOT_AI_ENGINE&&!e.aiEngine&&(e.aiEngine=process.env.VIBESPOT_AI_ENGINE),process.env.ANTHROPIC_API_KEY&&!e.anthropicApiKey&&(e.anthropicApiKey=process.env.ANTHROPIC_API_KEY),process.env.OPENAI_API_KEY&&!e.openaiApiKey&&(e.openaiApiKey=process.env.OPENAI_API_KEY),(process.env.GEMINI_API_KEY||process.env.GOOGLE_AI_API_KEY)&&!e.geminiApiKey&&(e.geminiApiKey=process.env.GEMINI_API_KEY||process.env.GOOGLE_AI_API_KEY),process.env.LANGDOCK_API_KEY&&!e.langdockApiKey&&(e.langdockApiKey=process.env.LANGDOCK_API_KEY),process.env.LANGDOCK_BASE_URL&&!e.langdockBaseUrl&&(e.langdockBaseUrl=process.env.LANGDOCK_BASE_URL),process.env.LANGDOCK_PROVIDER&&!e.langdockProvider&&(e.langdockProvider=process.env.LANGDOCK_PROVIDER),process.env.FIGMA_TOKEN&&!e.figmaToken&&(e.figmaToken=process.env.FIGMA_TOKEN),process.env.VIBESPOT_AGENTIC_MODE!==void 0&&e.agenticMode===void 0&&(e.agenticMode=process.env.VIBESPOT_AGENTIC_MODE==="true"),process.env.LANGFUSE_PUBLIC_KEY&&!e.langfusePublicKey&&(e.langfusePublicKey=process.env.LANGFUSE_PUBLIC_KEY),process.env.LANGFUSE_SECRET_KEY&&!e.langfuseSecretKey&&(e.langfuseSecretKey=process.env.LANGFUSE_SECRET_KEY),process.env.LANGFUSE_BASE_URL&&!e.langfuseBaseUrl&&(e.langfuseBaseUrl=process.env.LANGFUSE_BASE_URL),process.env.LANGFUSE_ENABLED!==void 0&&e.langfuseEnabled===void 0&&(e.langfuseEnabled=process.env.LANGFUSE_ENABLED==="true"),e}function Oe(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;case"langdock-api":return n.langdockApiKey||process.env.LANGDOCK_API_KEY;default:return}}function Ws(e){return e.length<=12?"***":e.slice(0,7)+"..."+e.slice(-4)}function Y(e){let n={...R(),...e};if(J(Gs,JSON.stringify(n,null,2)),process.platform!=="win32")try{sg(Gs,384)}catch{}}function og(){return Ga}function Lt(){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 Vn(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),Y({hubspotAccounts:i,activeHubSpotAccount:t})}function Ii(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),Y(s)}function Pi(e){Y({activeHubSpotAccount:e})}function Le(){return Lt()?.personalAccessKey||process.env.HUBSPOT_PERSONAL_ACCESS_KEY||null}function st(e){return R().enabledCLITools?.includes(e)??!1}function Ni(e,t){let n=R(),s=new Set(n.enabledCLITools||[]);t?s.add(e):s.delete(e),Y({enabledCLITools:[...s]})}var Ga,Gs,ee=N(()=>{"use strict";y();oe();Ga=Ua(ng(),".vibespot"),Gs=Ua(Ga,"config.json")});var Fi={};Ge(Fi,{OAUTH_EXTRA_HEADERS:()=>zn,OAUTH_SYSTEM_PREFIX:()=>bn,clearOAuthTokens:()=>zs,getOAuthTokenInfo:()=>qt,getValidAccessToken:()=>Oi,hasValidOAuthToken:()=>Ze,saveInitialToken:()=>Ri});import{join as ig}from"path";import{homedir as rg}from"os";import{chmodSync as ag,unlinkSync as lg}from"fs";function Vs(){if(!x(yn))return null;try{return JSON.parse(P(yn))}catch{return null}}function Ka(e){if(J(yn,JSON.stringify(e,null,2)),process.platform!=="win32")try{ag(yn,384)}catch{}}async function mg(e){let t=await fetch(dg,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({grant_type:"refresh_token",refresh_token:e,client_id:cg})});if(!t.ok)throw zs(),new Error("Claude OAuth session expired. Please re-authenticate in Settings.");let n=await t.json();Ka({access_token:n.access_token,refresh_token:n.refresh_token||e,expires_at:Date.now()+(n.expires_in||28800)*1e3})}function Ri(e,t=""){Ka({access_token:e,refresh_token:t,expires_at:Date.now()+28800*1e3})}function Ze(){let e=Vs();return e?e.expires_at>Date.now():!1}async function Oi(){let e=Vs();if(!e)return null;if(e.expires_at-Date.now()>ug)return e.access_token;if(e.refresh_token){Ks||(Ks=mg(e.refresh_token).finally(()=>{Ks=null}));try{await Ks}catch{return null}return Vs()?.access_token??null}return e.access_token}function qt(){let e=Vs();return e?{expiresAt:new Date(e.expires_at).toISOString()}:null}function zs(){if(x(yn))try{lg(yn)}catch{}}var cg,dg,yn,ug,zn,bn,Ks,_t=N(()=>{"use strict";y();oe();cg="9d1c250a-e61b-44d9-88ed-5944d1962f5e",dg="https://console.anthropic.com/v1/oauth/token",yn=ig(rg(),".vibespot","claude-oauth.json"),ug=300*1e3,zn={"user-agent":"claude-cli/2.1.75","x-app":"cli","anthropic-beta":"oauth-2025-04-20"},bn="You are Claude Code, Anthropic's official CLI for Claude.";Ks=null});import{join as Ys}from"path";import{homedir as qs}from"os";import{readFileSync as Va,existsSync as Xs,readdirSync as pg}from"fs";function Yn(){let e=ie("node --version");return{name:"Node.js",found:e.success,version:e.stdout.replace(/^v/,""),path:ie(`${Xt} node`).stdout}}function qn(){let e=ie("git --version");return{name:"Git",found:e.success,version:e.stdout.replace("git version ",""),path:ie(`${Xt} git`).stdout}}function gt(){let e=ie("hs --version");return{name:"HubSpot CLI",found:e.success,version:e.stdout,path:ie(`${Xt} hs`).stdout}}function xn(){let e=ie("claude --version");if(!e.success)return{name:"Claude Code",found:!1,version:"",path:"",authenticated:!1,authDetail:"Not installed"};let t=Ys(qs(),".claude"),n=!1,s="Not signed in \u2014 run `claude` to authenticate";try{if(Xs(t)){let o=pg(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:ie(`${Xt} claude`).stdout,authenticated:n,authDetail:s}}function Xn(e){try{let t=Ys(qs(),".hscli","config.yml");if(!Xs(t))return"na1";let n=Va(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 ft(){let e=ie("hs accounts list",{timeout:za});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(`
|
|
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";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=ie("gemini --version");if(!e.success)return{name:"Gemini CLI",found:!1,version:"",path:"",authenticated:!1,authDetail:"Not installed"};let t=Ys(qs(),".config","gcloud","application_default_credentials.json"),n=Xs(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:ie(`${Xt} gemini`).stdout,authenticated:o,authDetail:o?"Authenticated":"Run `gemini` to sign in with Google"}}function Cn(){let e=ie("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=Ys(qs(),".codex","auth.json");Xs(i)&&(n=Va(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:ie(`${Xt} codex`).stdout,authenticated:s,authDetail:o}}function Zs(){let e=ie("gh --version");return{name:"GitHub CLI",found:e.success,version:e.stdout.split(`
|
|
3
|
+
`)[0]?.replace("gh version ","").split(" ")[0]||"",path:ie(`${Xt} gh`).stdout}}function Qs(){let e=ie("gh auth status 2>&1",{timeout:za});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 Ya(){return!!process.env.ANTHROPIC_API_KEY}function eo(e){return parseInt(e.split(".")[0],10)>=18}function qa(e){let t=parseInt(e.split(".")[0],10);return!isNaN(t)&&t>=8}function gg(){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=Lt();return{authenticated:!!o,portalName:o?.portalName||"",portalId:o?.portalId||"",dataCenter:o?o.dataCenter:"na1",accounts:s,uploadMode:t}}function Sn(e,...t){if(e)return{configured:!0,masked:Ws(e),source:"config"};for(let n of t)if(process.env[n])return{configured:!0,masked:Ws(process.env[n]),source:"env"};return{configured:!1,masked:"",source:null}}function Di(e){return{anthropic:Sn(e.anthropicApiKey,"ANTHROPIC_API_KEY"),openai:Sn(e.openaiApiKey,"OPENAI_API_KEY"),gemini:Sn(e.geminiApiKey,"GEMINI_API_KEY","GOOGLE_AI_API_KEY"),langdock:Sn(e.langdockApiKey,"LANGDOCK_API_KEY"),langfusePublic:Sn(e.langfusePublicKey,"LANGFUSE_PUBLIC_KEY"),langfuseSecret:Sn(e.langfuseSecretKey,"LANGFUSE_SECRET_KEY")}}function ji(e){let t=[];return e.claudeCode&&t.push("claude-code"),e.claudeOAuth&&t.push("claude-oauth"),e.apiKeys.anthropic.configured&&t.push("anthropic-api"),e.apiKeys.openai.configured&&t.push("openai-api"),e.geminiCli&&t.push("gemini-cli"),e.apiKeys.gemini.configured&&t.push("gemini-api"),e.codexCli&&t.push("codex-cli"),e.apiKeys.langdock.configured&&t.push("langdock-api"),t}function Li(e,t){if(e==="cli"){if(!t)return{name:"HubSpot CLI",found:!1,version:"",path:"",authenticated:!1,portalName:"",portalId:"",dataCenter:"na1",accounts:[],uploadMode:"cli"};let n=gt(),s=n.found?ft():{authenticated:!1,portalName:"",portalId:"",accounts:[]},o=s.portalId?Xn(s.portalId):"na1";return{...n,...s,dataCenter:o,uploadMode:"cli"}}return{name:"HubSpot API",found:!0,version:"v3",path:"",...gg()}}function Xa(){let e=R(),t=e.hubspotUploadMode||"api",n=Di(e),s={authenticated:Ze(),expiresAt:qt()?.expiresAt},o=r=>({name:r,found:!1,version:"",path:"",authenticated:!1,authDetail:"Not scanned"}),i=r=>({name:r,found:!1,version:"",path:""});return{tools:{node:i("Node.js"),git:i("Git"),hubspot:Li(t,!1),github:{...i("GitHub CLI"),authenticated:!1,username:""},claudeCode:o("Claude Code"),claudeOAuth:s,geminiCli:o("Gemini CLI"),codexCli:o("OpenAI Codex CLI")},apiKeys:n,activeEngine:e.aiEngine||null,availableEngines:ji({apiKeys:n,claudeOAuth:s.authenticated,claudeCode:st("claude-code"),geminiCli:st("gemini-cli"),codexCli:st("codex-cli")}),enabledCLITools:e.enabledCLITools||[],scanned:!1}}function Za(){let e=R(),t=Di(e),n={authenticated:Ze(),expiresAt:qt()?.expiresAt},s=st("claude-code")?xn():{...vn,name:"Claude Code"},o=st("gemini-cli")?wn():{...vn,name:"Gemini CLI"},i=st("codex-cli")?Cn():{...vn,name:"OpenAI Codex CLI"};return{claudeCode:s,geminiCli:o,codexCli:i,claudeOAuth:n,availableEngines:ji({apiKeys:t,claudeOAuth:n.authenticated,claudeCode:s.found&&s.authenticated,geminiCli:o.found&&o.authenticated,codexCli:i.found&&i.authenticated})}}function Qa(){let t=R().hubspotUploadMode||"api",n=Zs(),s=n.found?Qs():{authenticated:!1,username:""};return{github:{...n,...s},hubspot:Li(t,!0)}}function to(){let e=R(),t=e.hubspotUploadMode||"api",n=Yn(),s=qn(),o=Li(t,!0),i=Zs(),r=i.found?Qs():{authenticated:!1,username:""},a={authenticated:Ze(),expiresAt:qt()?.expiresAt},l=st("claude-code")?xn():{...vn,name:"Claude Code"},c=st("gemini-cli")?wn():{...vn,name:"Gemini CLI"},d=st("codex-cli")?Cn():{...vn,name:"OpenAI Codex CLI"},u=Di(e);return{tools:{node:n,git:s,hubspot:o,github:{...i,...r},claudeCode:l,claudeOAuth:a,geminiCli:c,codexCli:d},apiKeys:u,activeEngine:e.aiEngine||null,availableEngines:ji({apiKeys:u,claudeOAuth:a.authenticated,claudeCode:l.found&&l.authenticated,geminiCli:c.found&&c.authenticated,codexCli:d.found&&d.authenticated}),enabledCLITools:e.enabledCLITools||[],scanned:!0}}var Xt,za,vn,Zt=N(()=>{"use strict";y();Yt();ee();_t();Xt=process.platform==="win32"?"where":"which",za=4e3;vn={name:"",found:!1,version:"",path:"",authenticated:!1,authDetail:"Disabled"}});import{readFileSync as fg}from"fs";import{basename as hg}from"path";async function tl(e){let t=el.get(e);if(t&&t.expiresAt-Date.now()>Sg)return t;let n=await fetch(`${$t}/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 el.set(e,o),o}async function kn(e){let{accessToken:t}=await tl(e);return{Authorization:`Bearer ${t}`}}function no(e){return e.replace(/^\/+/,"").split("/").filter(Boolean).map(encodeURIComponent).join("/")}function vg(e){return e.startsWith("pat-eu1-")?"eu1":e.startsWith("pat-na1-")?"na1":e.startsWith("CiRldTE")?"eu1":"na1"}function xg(e){return new Promise(t=>setTimeout(t,e))}async function Zn(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 Qn(e,t,n=yg){for(let s=0;s<=n;s++){let o=await fetch(e,t);if(o.status===429||o.status>=500&&s<n){let i=bg*Math.pow(2,s);await xg(i);continue}return o}return fetch(e,t)}async function so(e){let t=await tl(e),n=`${$t}/account-info/v3/details`,s=await Qn(n,{headers:await kn(e)});if(!s.ok){let a=await Zn(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:vg(e)}}async function nl(e,t,n){let s=fg(n),o=hg(n),i=new FormData,r=new Blob([s]);i.append("file",r,o);let a=`${$t}/cms/v3/source-code/published/content/${no(t)}`,l=await Qn(a,{method:"PUT",headers:await kn(e),body:i});if(!l.ok){let c=await Zn(l,t);return{success:!1,path:t,error:c}}return{success:!0,path:t}}async function Ji(e,t){let n=`${$t}/cms/v3/source-code/published/content/${no(t)}`,s=await Qn(n,{method:"DELETE",headers:await kn(e)});if(!s.ok&&s.status!==404){let o=await Zn(s,t);throw new Error(`Failed to delete ${t}: ${o.message}`)}}async function sl(e,t){let n=`${$t}/cms/v3/source-code/published/content/${no(t)}`,s=await Qn(n,{method:"GET",headers:await kn(e)});if(!s.ok){let i=await Zn(s,t);throw new Error(`Failed to download ${t}: ${i.message}`)}let o=await s.arrayBuffer();return Buffer.from(o)}async function oo(e,t){let n=`${$t}/cms/v3/source-code/published/metadata/${no(t)}`,s=await Qn(n,{method:"GET",headers:await kn(e)});if(s.status===404)return null;if(!s.ok){let o=await Zn(s,t);throw new Error(`Failed to get metadata for ${t}: ${o.message}`)}return await s.json()}async function ol(e){let t=await kn(e),n=[`${$t}/cms/v3/source-code/published/metadata`,`${$t}/cms/v3/source-code/published/metadata/`,`${$t}/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 $t,yg,bg,Sg,el,Qt=N(()=>{"use strict";y();$t="https://api.hubapi.com",yg=3,bg=1e3,Sg=300*1e3,el=new Map});import*as ae from"@clack/prompts";function Bi(e){ae.isCancel(e)&&(ae.cancel(I.muted("Operation cancelled.")),process.exit(0))}async function ge(e){ae.intro(I.heading(e))}async function fe(e){ae.outro(I.success(e))}async function ht(e,t){ae.note(e,t?I.heading(t):void 0)}async function Se(e){let t=await ae.text({message:I.accent(e.message),placeholder:e.placeholder,defaultValue:e.defaultValue,validate:e.validate});return Bi(t),t}async function Me(e){let t=await ae.confirm({message:I.accent(e.message),initialValue:e.initialValue??!0});return Bi(t),t}async function Et(e){let t=await ae.select({message:I.accent(e.message),options:e.options});return Bi(t),t}async function Fe(){let e=ae.spinner();return{start:t=>e.start(I.muted(t)),stop:t=>e.stop(I.success(t)),message:t=>e.message(I.muted(t))}}function D(e){ae.log.info(e)}function G(e){ae.log.success(I.success(e))}function se(e){ae.log.warn(I.warn(e))}function V(e){ae.log.error(I.error(e))}var Qe=N(()=>{"use strict";y();pt()});import{readdirSync as Hi,statSync as wg}from"fs";import{join as he,basename as Ui,extname as Cg}from"path";function il(e){return typeof e!="string"||e.length===0||e.length>2048||/[\s;&|`$()<>\\]/.test(e)?!1:!!(/^https?:\/\/[^\s]+$/.test(e)||/^git@[\w.-]+:[\w./~+-]+$/.test(e))}function rl(e){let t=[],n=[he(e,"src/components/landing"),he(e,"src/components/sections"),he(e,"src/components"),he(e,"src/pages"),he(e,"app/components"),he(e,"components")];for(let s of n)if(x(s))try{let o=Hi(s);for(let i of o){let r=he(s,i);if(!wg(r).isFile())continue;let l=Cg(i);if(![".tsx",".jsx"].includes(l))continue;let c=Ui(i,l);if(c.startsWith("ui")||c==="index")continue;let d=P(r),u=kg(c,d);t.push({name:c,path:r,description:u})}}catch{}return t}function kg(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 al(e){let t=[he(e,"src/index.css"),he(e,"src/globals.css"),he(e,"src/app/globals.css"),he(e,"app/globals.css")],n=0,s=[];for(let o of t){if(!x(o))continue;let i=P(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 ll(e){let t=[],n=he(e,"src/hooks");if(x(n))try{let o=Hi(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=he(e,"src/components/landing");if(x(s))try{let o=Hi(s);for(let i of o){if(!i.endsWith(".tsx")&&!i.endsWith(".jsx"))continue;let r=P(he(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 cl(e){let t,n=!1;if(e.startsWith("http")||e.startsWith("git@")){if(!il(e))throw new Error(`Refusing to clone unsafe source URL: ${e}. Only http(s):// and git@host:path URLs without shell metacharacters are allowed.`);n=!0;let l=Ui(e.replace(/\.git$/,""))||"react-source";if(t=he(process.cwd(),"workspace",l),!x(t)){let c=Z(["clone","--depth","1","--",e,t]);if(!c.success)throw new Error(`Failed to clone ${e}: ${c.stderr}`)}}else if(t=e,!x(t))throw new Error(`Directory not found: ${t}`);let s=rl(t),o=x(he(t,"tailwind.config.ts"))||x(he(t,"tailwind.config.js")),{varCount:i,fonts:r}=al(t),a=ll(t);return{sourceDir:t,wasCloned:n,components:s,hasTailwind:o,cssVarCount:i,fonts:r,interactions:a}}async function ro(){await ge("Source Project");let e=await Se({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"}}),t,n=!1;if(e.startsWith("http")||e.startsWith("git@")){il(e)||(V("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=Ui(e.replace(/\.git$/,""))||"react-source";if(t=he(process.cwd(),"workspace",h),x(t))G(`Using existing clone: ${I.dim(t)}`);else{let f=await Fe();f.start("Cloning repository..."),Z(["clone","--depth","1","--",e,t]).success||(f.stop("Clone failed"),V(`Failed to clone ${e}. Check the URL and your access permissions.`),process.exit(1)),f.stop(`Cloned to ${I.dim(t)}`)}}else t=e,x(t)||(V(`Directory not found: ${t}`),process.exit(1)),G(`Using local source: ${I.dim(t)}`);let s=await Fe();s.start("Analyzing project structure...");let o=rl(t),i=x(he(t,"tailwind.config.ts"))||x(he(t,"tailwind.config.js")),{varCount:r,fonts:a}=al(t),l=ll(t);s.stop(`Found ${o.length} landing page components`),o.length===0&&(se("No components found. Make sure the React source has .tsx/.jsx files in src/components/"),process.exit(1));let c=o.map((h,f)=>` ${I.dim(`${f+1}.`)} ${I.bold(h.name)} ${I.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 ht(`${c}
|
|
5
5
|
|
|
6
6
|
CSS: ${d}
|
|
7
7
|
JS: ${m}
|
|
8
|
-
Font: ${u}`,`${o.length} components detected`),await
|
|
9
|
-
`),
|
|
8
|
+
Font: ${u}`,`${o.length} components detected`),await Me({message:"Does this look right?"})||(V("Please adjust your source directory and try again."),process.exit(0)),await fe("Source analyzed!"),{sourceDir:t,wasCloned:n,components:o,hasTailwind:i,cssVarCount:r,fonts:a,interactions:l}}var ao=N(()=>{"use strict";y();Yt();oe();Qe();pt()});var dl={};Ge(dl,{addEmailTemplateToTheme:()=>Tn,createThemeScaffold:()=>ts});import{mkdirSync as Mt,writeFileSync as es}from"fs";import{join as We}from"path";function ts(e,t){Mt(e,{recursive:!0}),Mt(We(e,"templates"),{recursive:!0}),Mt(We(e,"modules"),{recursive:!0}),Mt(We(e,"css"),{recursive:!0}),Mt(We(e,"js"),{recursive:!0}),Mt(We(e,"images"),{recursive:!0}),Mt(We(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"}};es(We(e,"theme.json"),JSON.stringify(n,null,2)+`
|
|
9
|
+
`),es(We(e,"fields.json"),`[]
|
|
10
10
|
`);let s=`<!--
|
|
11
11
|
templateType: page
|
|
12
12
|
isAvailableForNewContent: false
|
|
@@ -22,7 +22,7 @@ var np=Object.defineProperty;var R=(e,t)=>()=>(e&&(t=e(e=0)),t);var Be=(e,t)=>{f
|
|
|
22
22
|
%}
|
|
23
23
|
{% end_dnd_area %}
|
|
24
24
|
{% endblock body %}
|
|
25
|
-
`;
|
|
25
|
+
`;es(We(e,"templates","home.html"),s);let o=`<!--
|
|
26
26
|
templateType: none
|
|
27
27
|
isAvailableForNewContent: false
|
|
28
28
|
label: Base Layout
|
|
@@ -45,7 +45,7 @@ var np=Object.defineProperty;var R=(e,t)=>()=>(e&&(t=e(e=0)),t);var Be=(e,t)=>{f
|
|
|
45
45
|
{{ standard_footer_includes }}
|
|
46
46
|
</body>
|
|
47
47
|
</html>
|
|
48
|
-
`;
|
|
48
|
+
`;Mt(We(e,"templates","layouts"),{recursive:!0}),es(We(e,"templates","layouts","base.html"),o)}function Tn(e,t){let n=`<!--
|
|
49
49
|
templateType: email
|
|
50
50
|
isAvailableForNewContent: true
|
|
51
51
|
label: ${t} Email Template
|
|
@@ -84,8 +84,8 @@ var np=Object.defineProperty;var R=(e,t)=>()=>(e&&(t=e(e=0)),t);var Be=(e,t)=>{f
|
|
|
84
84
|
{{ standard_footer_includes }}
|
|
85
85
|
</body>
|
|
86
86
|
</html>
|
|
87
|
-
`;
|
|
88
|
-
## `,o+s.length);return i>=0?t.slice(o,i).trim():t.slice(o).trim()}function
|
|
87
|
+
`;Mt(We(e,"templates"),{recursive:!0}),es(We(e,"templates","email.html"),n)}var ns=N(()=>{"use strict";y()});var ml={};Ge(ml,{fetchTheme:()=>ss});import{mkdirSync as ul,writeFileSync as Tg}from"fs";import{join as Ag,dirname as _g}from"path";async function Gi(e,t){let n=await oo(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 Gi(e,a));else{let l=i;l.folder?s.push(...await Gi(e,l.path||a)):s.push(l.path||a)}}return s}async function $g(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 ss(e,t,n,s={}){let o=s.concurrency??5,i=await Gi(e,t);if(i.length===0)throw new Error(`Theme "${t}" not found on HubSpot or is empty`);ul(n,{recursive:!0}),await $g(i,o,async r=>{let a=r.startsWith(t+"/")?r.slice(t.length+1):r,l=Ag(n,a);ul(_g(l),{recursive:!0});let c=await sl(e,r);Tg(l,c),s.onFile?.(a)})}var lo=N(()=>{"use strict";y();Qt()});function Jt(e){let t=pl.get(e);if(t!==void 0)return t;try{t=P(fn(e))}catch{t=""}return pl.set(e,t),t}function ye(){return Jt("conversion-guide.md")||"Conversion guide not found. Using built-in rules."}function is(){return Jt("design-guide.md")}function Wi(){return Jt("content-guide.md")}function Je(){return Jt("hubspot-rules.md")}function Ki(){return Jt("humanify-guide.md")}function gl(){return Jt("email-rules.md")}function fl(){return Jt("blog-rules.md")}function Vi(e){let t=Jt("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(`
|
|
88
|
+
## `,o+s.length);return i>=0?t.slice(o,i).trim():t.slice(o).trim()}function hl(e){return`You are a HubSpot CMS expert converting React/Tailwind pages to native HubSpot modules.
|
|
89
89
|
|
|
90
90
|
## Rules
|
|
91
91
|
Follow the conversion guide below EXACTLY. Key rules:
|
|
@@ -102,10 +102,10 @@ Follow the conversion guide below EXACTLY. Key rules:
|
|
|
102
102
|
- Convert React hooks to vanilla JS (no React, no npm packages)
|
|
103
103
|
|
|
104
104
|
## HubSpot CMS Rules
|
|
105
|
-
${
|
|
105
|
+
${Je()}
|
|
106
106
|
|
|
107
107
|
## Conversion Guide
|
|
108
|
-
${e}`}function
|
|
108
|
+
${e}`}function yl(e,t,n){return`Convert this React component to a HubSpot module named "${t}".
|
|
109
109
|
|
|
110
110
|
Return a JSON object with these keys:
|
|
111
111
|
- fieldsJson: complete fields.json content (as JSON string)
|
|
@@ -120,7 +120,7 @@ ${n}
|
|
|
120
120
|
React component source:
|
|
121
121
|
${e}
|
|
122
122
|
|
|
123
|
-
Return ONLY valid JSON, no markdown fences.`}function
|
|
123
|
+
Return ONLY valid JSON, no markdown fences.`}function bl(e,t,n){return`Create a shared CSS file for a HubSpot CMS landing page.
|
|
124
124
|
|
|
125
125
|
Extract the design system from the source CSS and Tailwind config below.
|
|
126
126
|
Use the class prefix ".${n}-" for all custom classes.
|
|
@@ -144,7 +144,7 @@ ${e}
|
|
|
144
144
|
Tailwind config:
|
|
145
145
|
${t}
|
|
146
146
|
|
|
147
|
-
Return ONLY the CSS content, no markdown fences.`}function
|
|
147
|
+
Return ONLY the CSS content, no markdown fences.`}function Sl(e,t,n){return`Create a shared vanilla JS file for a HubSpot CMS landing page.
|
|
148
148
|
|
|
149
149
|
Convert the React hooks and interactive components below to plain JavaScript.
|
|
150
150
|
Use the class prefix "${n}-" to match the CSS.
|
|
@@ -162,7 +162,7 @@ ${e}
|
|
|
162
162
|
Interactive component sources:
|
|
163
163
|
${t}
|
|
164
164
|
|
|
165
|
-
Return ONLY the JavaScript content, no markdown fences.`}function
|
|
165
|
+
Return ONLY the JavaScript content, no markdown fences.`}function vl(e,t,n){return`Create a HubSpot page template that assembles these modules:
|
|
166
166
|
|
|
167
167
|
${e.map((s,o)=>`${o+1}. ${s}.module`).join(`
|
|
168
168
|
`)}
|
|
@@ -177,29 +177,29 @@ Template requirements:
|
|
|
177
177
|
- Each module in its own dnd_section with padding zeroed and full_width=true
|
|
178
178
|
- dnd_area label: "${t} Landing Page"
|
|
179
179
|
|
|
180
|
-
Return ONLY the template HTML content, no markdown fences.`}var
|
|
181
|
-
`),t=!0)}catch{}}return t}function Yp(e){let t=!1,n=ce(e,"css");if(w(n))for(let o of Ze(n)){if(!o.endsWith(".css"))continue;let i=ce(n,o),r=E(i),a=r.replace(/@import\s+url\(['"]?https?:\/\/[^)]+['"]?\)\s*;?/gi,"");a!==r&&(J(i,a),t=!0)}let s=ce(e,"modules");if(w(s))for(let o of Ze(s)){if(!o.endsWith(".module"))continue;let i=ce(s,o,"module.css");if(!w(i))continue;let r=E(i),a=r.replace(/@import\s+url\(['"]?https?:\/\/[^)]+['"]?\)\s*;?/gi,"");a!==r&&(J(i,a),t=!0)}if(w(s))for(let o of Ze(s)){if(!o.endsWith(".module"))continue;let i=ce(s,o,"module.html");if(!w(i))continue;let r=E(i),a=r.replace(/<link[^>]+href=['"]https?:\/\/[^'"]+['"][^>]*>/gi,"");a!==r&&(J(i,a),t=!0)}return t}function qa(e){let t=!1,n=ce(e,"modules");if(!w(n))return!1;for(let s of Ze(n)){if(!s.endsWith(".module"))continue;let o=ce(n,s,"fields.json");if(w(o))try{let i=JSON.parse(E(o));Xa(i)&&(J(o,JSON.stringify(i,null,2)+`
|
|
182
|
-
`),t=!0)}catch{}}return t}function
|
|
183
|
-
|
|
184
|
-
`),
|
|
185
|
-
`)
|
|
186
|
-
`)}catch{}}}var oo,gg,Mi,Ii,M,de=R(()=>{"use strict";y();oo=Pi(pg(),".vibespot","logs"),gg=7,Mi=!1,Ii=!1;M={info(e,t,n){let s=n?`[${e}] ${t} ${JSON.stringify(n)}`:`[${e}] ${t}`;console.log(s),Ei("INFO",s)},warn(e,t,n){let s=n?`[${e}] ${t} ${JSON.stringify(n)}`:`[${e}] ${t}`;console.warn(s),Ei("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),Ei("ERROR",o)}}});import{readFileSync as Sg,existsSync as xl,writeFileSync as xg,mkdirSync as vg,rmSync as wg}from"fs";import{join as io}from"path";function Wt(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 et(){let e=C();if(!e)return;let t=Ce();if(!t){if(e.modules.length===0)return;let n={modules:e.modules,moduleOrder:e.moduleOrder,sharedCss:e.sharedCss,sharedJs:e.sharedJs,template:e.template,messages:e.messages,plan:e.brandAssets?.plan};t=Tt("landing_page",`${e.themeName} Landing Page`),e.activeTemplateId=t.id,e.modules=n.modules,e.moduleOrder=n.moduleOrder,e.sharedCss=n.sharedCss,e.sharedJs=n.sharedJs,e.template=n.template,e.messages=n.messages,e.brandAssets&&(e.brandAssets.plan=n.plan)}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 tt(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(),et(),kg()}function vl(e){let t=C();t&&(t.assets||(t.assets=[]),t.assets.push(e),t.updatedAt=Date.now(),D())}function Sl(e){return e.toLowerCase().replace(/[\s\-_]+/g,"")}function Cg(e,t){let n=Sl(e),s=Sl(t);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(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=>Cg(r.moduleName,n.moduleName));i&&M.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(),et()}}function Rt(e){let t=C();t&&(t.moduleOrder=e,t.updatedAt=Date.now(),et())}function wl(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=io(t.themePath,"modules",`${e}.module`);xl(n)&&wg(n,{recursive:!0,force:!0})}t.updatedAt=Date.now(),et()}}function Cl(e){let t=C();t&&(t.moduleOrder=t.moduleOrder.filter(n=>n!==e),t.updatedAt=Date.now(),et())}function kl(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);$l(i,t,n),o.fieldsJson=JSON.stringify(i,null,2),s.updatedAt=Date.now(),et()}catch{}}function Se(){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 kg(){let e=C();if(e)try{let t=io(e.themePath,".vibespot");vg(t,{recursive:!0});let n={sessionId:e.id,themeName:e.themeName,messages:e.messages,updatedAt:Date.now()};xg(io(t,"chat.json"),JSON.stringify(n,null,2),"utf-8")}catch{}}function Tl(e){let t=io(e,".vibespot","chat.json");if(!xl(t))return[];try{let n=JSON.parse(Sg(t,"utf-8"));return Array.isArray(n.messages)?n.messages:[]}catch{return[]}}function Al(e){let t=C();if(t){for(let n of t.templates)n.sharedCss=e.sharedCss,n.sharedJs=e.sharedJs;t.sharedCss=e.sharedCss,t.sharedJs=e.sharedJs;for(let n of e.pages){let s=e.pageLabels.get(n.pageId),o=s?.label||n.pageId,i=s?.pageType||"website_page",r=t.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=e.sharedCss,r.sharedJs=e.sharedJs}e.pages.length>0&&Kn(e.pages[0].templateId),t.updatedAt=Date.now()}}function $l(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&&$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(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 Ce(){let e=C();return!e||!e.activeTemplateId||!e.templates?.length?null:e.templates.find(t=>t.id===e.activeTemplateId)||null}function Kn(e){let t=C();if(!t)return!1;let n=t.templates.find(s=>s.id===e);return n?(t.activeTemplateId=e,Wt(n),t.updatedAt=Date.now(),!0):!1}function Tt(e,t,n){let s=C();if(!s)throw new Error("No active session");let o=t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,""),i=n==="email",a=`${i?"email":e==="blog_post"?"bp":e==="website_page"?"wp":e==="module_only"?"mo":"lp"}-${o}`,l={id:a,label:t,pageType:e,contentMode:n,templateFile:i?"templates/email.html":e==="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(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,Wt(l),n.updatedAt=Date.now(),l}function El(e){let t=C();if(!t||!Array.isArray(e)||e.length===0)return!1;let n=new Map(t.templates.map(i=>[i.id,i])),s=new Set,o=[];for(let i of e){let r=n.get(i);!r||s.has(i)||(o.push(r),s.add(i))}for(let i of t.templates)s.has(i.id)||o.push(i);return o.length!==t.templates.length?!1:(t.templates=o,t.updatedAt=Date.now(),!0)}function Ml(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 Il(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=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(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=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===e&&(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 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]})}for(let n of e.modules)t.has(n.moduleName)||t.set(n.moduleName,{module:n,usedIn:[]});return Array.from(t.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 Tg}from"fs";import{join as ue,dirname as Pl}from"path";import{homedir as Ag}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(e){mn=e;try{co(ae,{recursive:!0}),zn(Oi,JSON.stringify(e),"utf-8")}catch{}}function Fi(){if(!$e(ae))return[];let e=[];for(let t of ji(ae).filter(n=>n.endsWith(".json")&&n!=="_index.json"))try{let n=JSON.parse(gt(ue(ae,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,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=e,mo(e),e}function Rl(e){let t=uo(),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,pageCount:n.filter(i=>i.contentMode!=="email").length,emailCount:n.filter(i=>i.contentMode==="email").length,hasBrandAssets:!!(e.brandAssets&&(e.brandAssets.styleguide||e.brandAssets.brandvoice||e.brandAssets.brandKit)),isImported:!!e.isImported},o=t.findIndex(i=>i.id===e.id);o>=0?t[o]=s:t.push(s),mo(t)}function $g(e){let t=uo().filter(n=>n.id!==e);mo(t)}function _g(e){let t=uo().filter(n=>n.themeName!==e);mo(t)}function C(){return Le}function Nl(){return`vibe-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`}function pn(e,t,n={}){let s={id:Nl(),themePath:e,themeName:t,isImported:!!n.isImported,templates:[],activeTemplateId:"",messages:[],modules:[],sharedCss:"",sharedJs:"",template:"",moduleOrder:[],createdAt:Date.now(),updatedAt:Date.now()};return Le=s,so(e),s}function D(){if(!Le)return;co(ae,{recursive:!0});let e=ue(ae,`${Le.id}.json`);zn(e,JSON.stringify(Le,null,2),"utf-8"),Rl(Le)}function po(e){let t=ue(ae,e+".json");if(!$e(t))return null;try{let n=JSON.parse(gt(t,"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(e,t=!1){let n=ue(ae,e+".json"),s="";if(t)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 $g(e);Le?.id===e&&(Le=null)}function Fl(e,t){let n=ue(ae,e+".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===t)return{ok:!0};let i=s.themePath,r=ue(Pl(i),t);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",`${t}-theme.css`);if($e(a))try{Ni(a,l)}catch{}let c=ue(r,"js",`${o}-animations.js`),d=ue(r,"js",`${t}-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=t,m.name=t,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=t,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=t,Le.themePath=r,Le.updatedAt=Date.now()),Fi(),{ok:!0}}function jl(e){let t=ue(ae,e+".json");if(!$e(t))return{ok:!1,error:"Session not found"};let n;try{n=JSON.parse(gt(t,"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{Tg(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(Ag(),".vibespot","sessions"),Oi=ue(ae,"_index.json"),mn=null;Le=null});import{readFileSync as Eg,readdirSync as Jl,statSync as Di}from"fs";import{createHash as Mg}from"crypto";import{join as he,relative as Ig}from"path";function ho(e){let t=[];if(!w(e))return nf(e,[{severity:"error",rule:"theme.path.missing",message:`Theme directory not found: ${e}`}]);let n=fn(e),s=Zg(e),o=ef(e),i=tf(e),r=Fg(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 Yn(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 {
|
|
180
|
+
Return ONLY the template HTML content, no markdown fences.`}var pl,Ke=N(()=>{"use strict";y();oe();pl=new Map});import{appendFileSync as Ng,mkdirSync as Rg,readdirSync as Og,unlinkSync as Fg}from"fs";import{join as Xi}from"path";import{homedir as Dg}from"os";function Lg(){if(!Yi)try{Rg(mo,{recursive:!0}),Yi=!0}catch{}}function Jg(){if(!qi){qi=!0;try{let e=Date.now()-jg*864e5;for(let t of Og(mo)){if(!t.startsWith("vibespot-")||!t.endsWith(".log"))continue;let n=t.slice(9,19),s=new Date(n).getTime();if(s&&s<e)try{Fg(Xi(mo,t))}catch{}}}catch{}}}function Bg(){let t=new Date().toISOString().slice(0,10);return Xi(mo,`vibespot-${t}.log`)}function Hg(){return new Date().toISOString().slice(11,23)}function zi(e,t){if(Lg(),!!Yi){qi||Jg();try{Ng(Bg(),`${Hg()} ${e} ${t}
|
|
181
|
+
`)}catch{}}}var mo,jg,Yi,qi,E,le=N(()=>{"use strict";y();mo=Xi(Dg(),".vibespot","logs"),jg=7,Yi=!1,qi=!1;E={info(e,t,n){let s=n?`[${e}] ${t} ${JSON.stringify(n)}`:`[${e}] ${t}`;console.log(s),zi("INFO",s)},warn(e,t,n){let s=n?`[${e}] ${t} ${JSON.stringify(n)}`:`[${e}] ${t}`;console.warn(s),zi("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),zi("ERROR",o)}}});function Gg(e){let t=(e||"").toLowerCase();return Ug.find(n=>t.includes(n.match))}function rs(e,t){let n=Gg(e);if(!n)return;let s=n.cacheReadPerM??n.inputPerM*.1,o=n.cacheWritePerM??n.inputPerM*1.25,i=(t.inputTokens??0)*n.inputPerM,r=(t.outputTokens??0)*n.outputPerM,a=(t.cacheReadTokens??0)*s,l=(t.cacheCreationTokens??0)*o,c={total:(i+r+a+l)/1e6};return t.inputTokens!=null&&(c.input=i/1e6),t.outputTokens!=null&&(c.output=r/1e6),t.cacheReadTokens&&(c.cache_read_input_tokens=a/1e6),t.cacheCreationTokens&&(c.cache_creation_input_tokens=l/1e6),c}function et(e){if(e)return{inputTokens:e.input_tokens,outputTokens:e.output_tokens,cacheReadTokens:e.cache_read_input_tokens??void 0,cacheCreationTokens:e.cache_creation_input_tokens??void 0}}function An(e){if(!e)return;let t=e.prompt_tokens_details?.cached_tokens??0,n=e.prompt_tokens;return{inputTokens:n!=null?Math.max(0,n-t):void 0,outputTokens:e.completion_tokens,totalTokens:e.total_tokens,cacheReadTokens:t||void 0}}function _n(e){if(!e)return;let t=e.cachedContentTokenCount??0,n=e.promptTokenCount;return{inputTokens:n!=null?Math.max(0,n-t):void 0,outputTokens:e.candidatesTokenCount,totalTokens:e.totalTokenCount,cacheReadTokens:t||void 0}}function wl(e){let t={};return e.inputTokens!=null&&(t.input=e.inputTokens),e.outputTokens!=null&&(t.output=e.outputTokens),e.cacheReadTokens&&(t.cache_read_input_tokens=e.cacheReadTokens),e.cacheCreationTokens&&(t.cache_creation_input_tokens=e.cacheCreationTokens),e.totalTokens!=null&&(t.total=e.totalTokens),t}var Ug,en=N(()=>{"use strict";y();Ug=[{match:"claude-opus-4",inputPerM:15,outputPerM:75},{match:"claude-sonnet-4",inputPerM:3,outputPerM:15},{match:"claude-haiku-4",inputPerM:1,outputPerM:5},{match:"claude-3-7-sonnet",inputPerM:3,outputPerM:15},{match:"claude-3-5-sonnet",inputPerM:3,outputPerM:15},{match:"claude-3-5-haiku",inputPerM:.8,outputPerM:4},{match:"claude-3-opus",inputPerM:15,outputPerM:75},{match:"gpt-5.5",inputPerM:5,outputPerM:30},{match:"gpt-5.4",inputPerM:2.5,outputPerM:15},{match:"gpt-5.3",inputPerM:1.75,outputPerM:14},{match:"gpt-4o-mini",inputPerM:.15,outputPerM:.6},{match:"gpt-4o",inputPerM:2.5,outputPerM:10},{match:"gpt-4.1-nano",inputPerM:.1,outputPerM:.4},{match:"gpt-4.1-mini",inputPerM:.4,outputPerM:1.6},{match:"gpt-4.1",inputPerM:2,outputPerM:8},{match:"gemini-2.5-pro",inputPerM:1.25,outputPerM:10},{match:"gemini-2.5-flash",inputPerM:.3,outputPerM:2.5},{match:"gemini-2.0-flash",inputPerM:.1,outputPerM:.4},{match:"gemini-1.5-pro",inputPerM:1.25,outputPerM:5},{match:"gemini-1.5-flash",inputPerM:.075,outputPerM:.3}]});import{AsyncLocalStorage as Wg}from"async_hooks";function Kg(){return{inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheCreationTokens:0,costUsd:0,calls:0,unpricedCalls:0}}function Vg(e){return{inputTokens:e.inputTokens,outputTokens:e.outputTokens,cacheReadTokens:e.cacheReadTokens,cacheCreationTokens:e.cacheCreationTokens,totalTokens:e.inputTokens+e.outputTokens+e.cacheReadTokens+e.cacheCreationTokens,costUsd:e.costUsd,calls:e.calls,costComplete:e.unpricedCalls===0}}async function Zi(e){let t=Kg();return{result:await Cl.run(t,e),cost:Vg(t)}}function kl(e,t){if(!t)return;let n=Cl.getStore();if(!n)return;n.inputTokens+=t.inputTokens??0,n.outputTokens+=t.outputTokens??0,n.cacheReadTokens+=t.cacheReadTokens??0,n.cacheCreationTokens+=t.cacheCreationTokens??0,n.calls+=1;let s=rs(e,t);s?n.costUsd+=s.total:n.unpricedCalls+=1}var Cl,Qi=N(()=>{"use strict";y();en();Cl=new Wg});import{randomUUID as Bt}from"crypto";import{AsyncLocalStorage as zg}from"async_hooks";function Al(){let e=R(),t=e.langfusePublicKey||process.env.LANGFUSE_PUBLIC_KEY,n=e.langfuseSecretKey||process.env.LANGFUSE_SECRET_KEY;if(!(e.langfuseEnabled===!0||process.env.LANGFUSE_ENABLED==="true")||!t||!n)return null;let o=(e.langfuseBaseUrl||process.env.LANGFUSE_BASE_URL||Yg).replace(/\/+$/,"");return{publicKey:t,secretKey:n,baseUrl:o}}function er(){return Al()!==null}function go(e){if(typeof e=="string")return e.length>$n?e.slice(0,$n)+`\u2026[+${e.length-$n} chars]`:e;try{let t=JSON.stringify(e);if(t&&t.length>$n)return t.slice(0,$n)+`\u2026[+${t.length-$n} chars]`}catch{return"[unserializable]"}return e}async function tt(e,t){if(!er())return t();let n=Bt();tn.push({id:Bt(),type:"trace-create",timestamp:new Date().toISOString(),body:{id:n,name:e.name,timestamp:new Date().toISOString(),...e.sessionId?{sessionId:e.sessionId}:{},...e.userId?{userId:e.userId}:{},...e.input!==void 0?{input:go(e.input)}:{},...e.metadata?{metadata:e.metadata}:{},...e.tags?{tags:e.tags}:{}}});try{return await po.run({traceId:n,sessionId:e.sessionId},t)}finally{await _l()}}async function te(e,t,n){let s=po.getStore();if(!er()||!s?.traceId)return t();let o=Bt(),i=s.spanId,r=new Date,a,l;try{return await po.run({...s,spanId:o},t)}catch(c){throw a="ERROR",l=c?.message,c}finally{tn.push({id:Bt(),type:"span-create",timestamp:new Date().toISOString(),body:{id:o,traceId:s.traceId,name:e,startTime:r.toISOString(),endTime:new Date().toISOString(),...i?{parentObservationId:i}:{},...n?.input!==void 0?{input:go(n.input)}:{},...n?.metadata?{metadata:n.metadata}:{},...a?{level:a}:{},...l?{statusMessage:l}:{}}})}}async function qg(e){if(er())try{let t=po.getStore(),n=t?.traceId,s=n?t?.spanId:void 0,o=!1;n||(n=Bt(),o=!0,tn.push({id:Bt(),type:"trace-create",timestamp:new Date().toISOString(),body:{id:n,name:e.name,timestamp:new Date().toISOString()}}));let i=e.usage?wl(e.usage):void 0,r=e.usage?rs(e.model,e.usage):void 0;tn.push({id:Bt(),type:"generation-create",timestamp:new Date().toISOString(),body:{id:Bt(),traceId:n,...s?{parentObservationId:s}:{},name:e.name,model:e.model,startTime:(e.startTime??new Date).toISOString(),endTime:(e.endTime??new Date).toISOString(),...e.input!==void 0?{input:go(e.input)}:{},...e.output!==void 0?{output:go(e.output)}:{},...i?{usageDetails:i}:{},...r?{costDetails:r}:{},...e.level?{level:e.level}:{},...e.statusMessage?{statusMessage:e.statusMessage}:{},metadata:{...e.engine?{engine:e.engine}:{},...e.metadata??{}}}}),o&&await _l()}catch(t){E.warn("langfuse",`recordGeneration failed: ${t.message}`)}}function bt(e){let{engine:t,model:n,name:s,usage:o,startTime:i,endTime:r}=e,a=r.getTime()-i.getTime(),l=o?rs(n,o):void 0;if(o&&E.info("agent-usage",`${t} ${s}`,{model:n,inputTokens:o.inputTokens,outputTokens:o.outputTokens,cacheReadTokens:o.cacheReadTokens,costUsd:l?.total,durationMs:a}),Tl.size>0){let c={engine:t,model:n,name:s,usage:o,cost:l,startTime:i,endTime:r,durationMs:a};for(let d of Tl)try{d(c)}catch{}}kl(n,o),qg({name:s,model:n,engine:t,input:e.input,output:e.output,usage:o,startTime:i,endTime:r,level:e.level,statusMessage:e.statusMessage,metadata:e.metadata})}async function _l(){let e=Al();if(!e||tn.length===0)return;let t=tn;tn=[];try{let n=Buffer.from(`${e.publicKey}:${e.secretKey}`).toString("base64"),s=await fetch(`${e.baseUrl}/api/public/ingestion`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Basic ${n}`},body:JSON.stringify({batch:t})});if(!s.ok&&s.status!==207){let o=await s.text().catch(()=>"");E.warn("langfuse",`ingestion HTTP ${s.status}: ${o.slice(0,300)}`)}else E.info("langfuse",`flushed ${t.length} event(s)`)}catch(n){E.warn("langfuse",`ingestion failed: ${n.message}`)}}var Yg,$n,po,tn,Tl,Be=N(()=>{"use strict";y();ee();le();en();Qi();Yg="https://cloud.langfuse.com",$n=24e3,po=new zg,tn=[],Tl=new Set});import{join as me}from"path";import{readdirSync as it,rmSync as cf}from"fs";function xo(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),/dnd.area.*only.*have.*name.*main/i.test(s)&&(o=!0),t.push({file:n.file||"unknown",message:s,fixable:o})}return t}function wo(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}),/dnd.area.*only.*have.*name.*main/i.test(e)&&t.push({file:"templates/email.html",message:'Dnd area can only have name "main"',fixable:!0}),t}function Co(e){let t=[];return Nl(e)&&t.push("textarea \u2192 text"),Rl(e)&&t.push("name \u2192 item_name"),Ol(e)&&t.push("now() \u2192 local_dt"),Fl(e)&&t.push("Removed HubDB templates"),Dl(e)&&t.push("Fixed link field defaults"),jl(e)&&t.push("Fixed rgba/invalid color values \u2192 hex"),df(e)&&t.push("Stripped CDN @import statements"),Jl(e)&&t.push('dnd_area \u2192 "main" in email templates'),Bl(e)&&t.push("Added {{ dnd_area_stylesheet }} to email templates"),t}function Pl(e,t){return t.message.includes("textarea")?Nl(e):t.message.includes("reserved field name")?Rl(e):t.message.includes("now()")?Ol(e):t.message.includes("HubDB")?Fl(e):t.message.includes("invalid default value")||t.message.includes("deserialization")?Dl(e):t.message.includes("invalid format")&&t.message.includes("color")?jl(e):t.message.includes("dnd")||t.message.includes("Dnd area")?Jl(e):t.message.includes("dnd_area_stylesheet")?Bl(e):!1}function Nl(e){let t=!1,n=me(e,"modules");if(!x(n))return!1;for(let s of it(n)){if(!s.endsWith(".module"))continue;let o=me(n,s,"fields.json");if(!x(o))continue;let i=P(o);i.includes('"textarea"')&&(i=i.replace(/"textarea"/g,'"text"'),J(o,i),t=!0)}return t}function Rl(e){let t=!1,n=me(e,"modules");if(!x(n))return!1;for(let s of it(n)){if(!s.endsWith(".module"))continue;let o=me(n,s,"fields.json");if(!x(o))continue;let i=P(o);/"name":\s*"name"/g.test(i)&&(i=i.replace(/"name":\s*"name"/g,'"name": "item_name"'),J(o,i),t=!0)}return t}function Ol(e){let t=!1,n=me(e,"modules");if(!x(n))return!1;for(let s of it(n)){if(!s.endsWith(".module"))continue;let o=me(n,s,"module.html");if(!x(o))continue;let i=P(o);i.includes("now()")&&(i=i.replace(/now\(\)/g,"local_dt"),J(o,i),t=!0)}return t}function Fl(e){let t=!1,n=me(e,"templates");if(!x(n))return!1;for(let s of it(n)){if(!s.endsWith(".html"))continue;let o=me(n,s),i=P(o);(i.includes("hubdb_table")||i.includes("hubdb_table_rows"))&&(cf(o),t=!0)}return t}function Dl(e){let t=!1,n=me(e,"modules");if(!x(n))return!1;for(let s of it(n)){if(!s.endsWith(".module"))continue;let o=me(n,s,"fields.json");if(x(o))try{let i=JSON.parse(P(o));Hl(i)&&(J(o,JSON.stringify(i,null,2)+`
|
|
182
|
+
`),t=!0)}catch{}}return t}function df(e){let t=!1,n=me(e,"css");if(x(n))for(let o of it(n)){if(!o.endsWith(".css"))continue;let i=me(n,o),r=P(i),a=r.replace(/@import\s+url\(['"]?https?:\/\/[^)]+['"]?\)\s*;?/gi,"");a!==r&&(J(i,a),t=!0)}let s=me(e,"modules");if(x(s))for(let o of it(s)){if(!o.endsWith(".module"))continue;let i=me(s,o,"module.css");if(!x(i))continue;let r=P(i),a=r.replace(/@import\s+url\(['"]?https?:\/\/[^)]+['"]?\)\s*;?/gi,"");a!==r&&(J(i,a),t=!0)}if(x(s))for(let o of it(s)){if(!o.endsWith(".module"))continue;let i=me(s,o,"module.html");if(!x(i))continue;let r=P(i),a=r.replace(/<link[^>]+href=['"]https?:\/\/[^'"]+['"][^>]*>/gi,"");a!==r&&(J(i,a),t=!0)}return t}function jl(e){let t=!1,n=me(e,"modules");if(!x(n))return!1;for(let s of it(n)){if(!s.endsWith(".module"))continue;let o=me(n,s,"fields.json");if(x(o))try{let i=JSON.parse(P(o));Ll(i)&&(J(o,JSON.stringify(i,null,2)+`
|
|
183
|
+
`),t=!0)}catch{}}return t}function Ll(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"&&!uf(i)){let r=mf(i);r&&(o.color=r.hex,r.opacity!==void 0&&(o.opacity=r.opacity),t=!0)}}Array.isArray(s.children)&&Ll(s.children)&&(t=!0)}return t}function uf(e){return/^#[0-9a-fA-F]{6}$/.test(e)}function mf(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 Jl(e){let t=!1,n=me(e,"templates");if(!x(n))return!1;for(let s of it(n)){if(!s.endsWith(".html"))continue;let o=me(n,s),i=P(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),t=!0)}return t}function Bl(e){let t=!1,n=me(e,"templates");if(!x(n))return!1;for(let s of it(n)){if(!s.endsWith(".html"))continue;let o=me(n,s),i=P(o);if(!/templateType:\s*email/i.test(i)||i.includes("dnd_area_stylesheet"))continue;let r=i.replace(/(\{\{\s*standard_header_includes\s*\}\})/,`$1
|
|
184
|
+
{{ dnd_area_stylesheet }}`);r!==i&&(J(o,r),t=!0)}return t}function Hl(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)&&Hl(s.children)&&(t=!0)}return t}var ko=N(()=>{"use strict";y();oe()});import{readdirSync as pf}from"fs";import{join as gf,relative as ff}from"path";function Ul(e){let t=[];for(let n of pf(e,{withFileTypes:!0})){if(hf.has(n.name)||n.name.startsWith(".")&&n.name!==".gitkeep")continue;let s=gf(e,n.name);n.isDirectory()?t.push(...Ul(s)):n.isFile()&&t.push(s)}return t}async function yf(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 To(e,t,n,s={}){let o=s.concurrency??5,i=Ul(t),r=i.length,a=0,l=0,c=[];return await yf(i,o,async d=>{let u=ff(t,d).replace(/\\/g,"/"),m=`${n}/${u}`;s.onFileStart?.(u);let g=await nl(e,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 hf,tr=N(()=>{"use strict";y();Qt();Qt();hf=new Set([".git","node_modules",".vibespot",".DS_Store"])});var Zl=N(()=>{"use strict";y()});import{existsSync as It,writeFileSync as xf,mkdirSync as wf}from"fs";import{join as St}from"path";function ec(e){return/^[0-9a-f]{4,40}$/i.test(e)}function tc(e){return Number.isInteger(e)&&e>0&&e<1e3}function rt(){return Ao!==null||(Ao=Z(["--version"]).success),Ao}function _o(e){if(!rt())return!1;if(It(St(e,".git")))return Ql(e),!0;let t=Z(["init"],{cwd:e});return t.success?(Cf(e),Ql(e),Z(["add","-A"],{cwd:e}),Z(["commit","-m","Initial theme"],{cwd:e}),!0):(console.warn(`[project-git] git init failed in ${e}: ${t.stderr}`),!1)}function Ql(e){let t=St(e,".vibespot");It(t)||wf(t,{recursive:!0})}function Cf(e){let t=St(e,".gitignore");xf(t,[".vibespot/","node_modules/",""].join(`
|
|
185
|
+
`),"utf-8")}function nn(e,t){if(!rt()||!It(St(e,".git"))||(Z(["add","-A"],{cwd:e}),Z(["diff","--cached","--quiet"],{cwd:e}).success))return null;let s=t.length>72?t.slice(0,69)+"...":t,o=Z(["commit","-m",s],{cwd:e});if(!o.success)return console.warn(`[project-git] commit failed: ${o.stderr}`),null;let i=Z(["rev-parse","--short","HEAD"],{cwd:e});return i.success?i.stdout:null}function sr(e,t,n,s){if(!rt()||!It(St(e,".git")))return null;for(let u of s){let m=St(e,u);It(m)&&Z(["add","--",u],{cwd:e})}if(Z(["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=Z(["commit","-m",l],{cwd:e});if(!c.success)return console.warn(`[project-git] template commit failed: ${c.stderr}`),null;let d=Z(["rev-parse","--short","HEAD"],{cwd:e});return d.success?d.stdout:null}function nc(e){let t=[],n=null;for(let s of e.split(`
|
|
186
|
+
`)){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 sc(e,t=50){if(!rt())return[];if(!It(St(e,".git")))return[];if(!tc(t))return[];let n=Z(["log","--name-only","--pretty=format:COMMIT|%h|%H|%s|%at","-n",String(t)],{cwd:e});return!n.success||!n.stdout.trim()?[]:nc(n.stdout)}function oc(e,t,n=50){if(!rt())return[];if(!It(St(e,".git")))return[];if(!tc(n))return[];let s=t.replace(/[\\.*+?^${}()|[\]/]/g,"\\$&"),o=Z(["log",`--grep=\\[${s}\\]`,"--name-only","--pretty=format:COMMIT|%h|%H|%s|%at","-n",String(n)],{cwd:e});return!o.success||!o.stdout.trim()?[]:nc(o.stdout)}function ic(e,t){if(!rt())return{success:!1,error:"Git not available"};if(!It(St(e,".git")))return{success:!1,error:"Not a git repo"};if(!ec(t))return{success:!1,error:"Invalid commit hash"};let n=Z(["cat-file","-t",t],{cwd:e});if(!n.success||n.stdout.trim()!=="commit")return{success:!1,error:`Commit ${t} not found`};let s=Z(["log","--format=%s","-1",t],{cwd:e}),o=s.success?s.stdout:t,i=Z(["checkout",t,"--","."],{cwd:e});if(!i.success)return{success:!1,error:`Checkout failed: ${i.stderr}`};let r=`Rollback to: ${o}`.slice(0,72);return Z(["commit","-m",r],{cwd:e}),{success:!0}}function rc(e,t,n,s){if(!rt())return{success:!1,error:"Git not available"};if(!It(St(e,".git")))return{success:!1,error:"Not a git repo"};if(!ec(n))return{success:!1,error:"Invalid commit hash"};let o=Z(["cat-file","-t",n],{cwd:e});if(!o.success||o.stdout.trim()!=="commit")return{success:!1,error:`Commit ${n} not found`};let i=Z(["log","--format=%s","-1",n],{cwd:e}),r=i.success?i.stdout:n,a=0;for(let d of s)Z(["checkout",n,"--",d],{cwd:e}).success&&a++;if(a===0)return{success:!1,error:"No files could be restored from that commit"};Z(["add","-A"],{cwd:e});let c=`${`[${t}] `}Rollback to: ${r}`.slice(0,72);return Z(["commit","-m",c],{cwd:e}),{success:!0}}var Ao,Mn=N(()=>{"use strict";y();Yt();Ao=null});import{readFileSync as kf,existsSync as lc,writeFileSync as Tf,mkdirSync as Af,rmSync as _f}from"fs";import{join as $o}from"path";function sn(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 at(){let e=C();if(!e)return;let t=ke();if(!t){if(e.modules.length===0)return;let n={modules:e.modules,moduleOrder:e.moduleOrder,sharedCss:e.sharedCss,sharedJs:e.sharedJs,template:e.template,messages:e.messages,plan:e.brandAssets?.plan};t=Pt("landing_page",`${e.themeName} Landing Page`),e.activeTemplateId=t.id,e.modules=n.modules,e.moduleOrder=n.moduleOrder,e.sharedCss=n.sharedCss,e.sharedJs=n.sharedJs,e.template=n.template,e.messages=n.messages,e.brandAssets&&(e.brandAssets.plan=n.plan)}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 lt(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(),at(),Ef()}function cc(e){let t=C();t&&(t.assets||(t.assets=[]),t.assets.push(e),t.updatedAt=Date.now(),j())}function dc(e){let t=C();if(!t)return;if(e.calls===0)return t.costTotal;let n=t.costTotal??{costUsd:0,totalTokens:0,generations:0,costComplete:!0},s={costUsd:n.costUsd+e.costUsd,totalTokens:n.totalTokens+e.totalTokens,generations:n.generations+1,costComplete:n.costComplete&&e.costComplete};return t.costTotal=s,t.updatedAt=Date.now(),s}function ac(e){return e.toLowerCase().replace(/[\s\-_]+/g,"")}function $f(e,t){let n=ac(e),s=ac(t);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 He(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=>$f(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(),at()}}function Ht(e){let t=C();t&&(t.moduleOrder=e,t.updatedAt=Date.now(),at())}function uc(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=$o(t.themePath,"modules",`${e}.module`);lc(n)&&_f(n,{recursive:!0,force:!0})}t.updatedAt=Date.now(),at()}}function mc(e){let t=C();t&&(t.moduleOrder=t.moduleOrder.filter(n=>n!==e),t.updatedAt=Date.now(),at())}function pc(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);hc(i,t,n),o.fieldsJson=JSON.stringify(i,null,2),s.updatedAt=Date.now(),at()}catch{}}function ve(){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 Ef(){let e=C();if(e)try{let t=$o(e.themePath,".vibespot");Af(t,{recursive:!0});let n={sessionId:e.id,themeName:e.themeName,messages:e.messages,updatedAt:Date.now()};Tf($o(t,"chat.json"),JSON.stringify(n,null,2),"utf-8")}catch{}}function gc(e){let t=$o(e,".vibespot","chat.json");if(!lc(t))return[];try{let n=JSON.parse(kf(t,"utf-8"));return Array.isArray(n.messages)?n.messages:[]}catch{return[]}}function fc(e){let t=C();if(t){for(let n of t.templates)n.sharedCss=e.sharedCss,n.sharedJs=e.sharedJs;t.sharedCss=e.sharedCss,t.sharedJs=e.sharedJs;for(let n of e.pages){let s=e.pageLabels.get(n.pageId),o=s?.label||n.pageId,i=s?.pageType||"website_page",r=t.templates.find(a=>a.id===n.templateId);r||(r=Pt(i,o),r.id=n.templateId,r.templateFile=`templates/${n.templateId}.html`),r.modules=n.modules,r.moduleOrder=n.moduleOrder,r.sharedCss=e.sharedCss,r.sharedJs=e.sharedJs}e.pages.length>0&&cs(e.pages[0].templateId),t.updatedAt=Date.now()}}function hc(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&&hc(i.children,s.slice(1).join("."),n))}var ls=N(()=>{"use strict";y();ds();Ut();le()});import{existsSync as Eo,rmSync as Mo}from"fs";import{join as In}from"path";function Io(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 ke(){let e=C();return!e||!e.activeTemplateId||!e.templates?.length?null:e.templates.find(t=>t.id===e.activeTemplateId)||null}function cs(e){let t=C();if(!t)return!1;let n=t.templates.find(s=>s.id===e);return n?(t.activeTemplateId=e,sn(n),t.updatedAt=Date.now(),!0):!1}function Pt(e,t,n){let s=C();if(!s)throw new Error("No active session");let o=t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,""),i=n==="email",a=`${i?"email":e==="blog_post"?"bp":e==="website_page"?"wp":e==="module_only"?"mo":"lp"}-${o}`,l={id:a,label:t,pageType:e,contentMode:n,templateFile:i?"templates/email.html":e==="module_only"?"":`templates/${a}.html`,modules:[],moduleOrder:[],sharedCss:"",sharedJs:"",template:"",messages:[]};return s.templates.push(l),s.activeTemplateId=a,sn(l),s.updatedAt=Date.now(),l}function yc(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,sn(l),n.updatedAt=Date.now(),l}function bc(e){let t=C();if(!t||!Array.isArray(e)||e.length===0)return!1;let n=new Map(t.templates.map(i=>[i.id,i])),s=new Set,o=[];for(let i of e){let r=n.get(i);!r||s.has(i)||(o.push(r),s.add(i))}for(let i of t.templates)s.has(i.id)||o.push(i);return o.length!==t.templates.length?!1:(t.templates=o,t.updatedAt=Date.now(),!0)}function Sc(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 vc(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=In(n.themePath,"templates"),r=`${o.id}.html`,a=In(i,r);if(Eo(a)&&Mo(a,{force:!0}),o.pageType==="blog_post"){let l=In(i,`${o.id}-listing.html`);Eo(l)&&Mo(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=In(n.themePath,"modules");for(let l of r){let c=In(a,`${l}.module`);Eo(c)&&Mo(c,{recursive:!0,force:!0})}}}if(n.activeTemplateId===e&&(n.templates.length>0?cs(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=In(n.themePath,".vibespot","plan.md");Eo(r)&&Mo(r,{force:!0})}return n.updatedAt=Date.now(),!0}function Nt(){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]})}for(let n of e.modules)t.has(n.moduleName)||t.set(n.moduleName,{module:n,usedIn:[]});return Array.from(t.values())}var Ut=N(()=>{"use strict";y();ds();ls()});import{readFileSync as vt,readdirSync as lr,existsSync as Ie,writeFileSync as us,mkdirSync as Po,rmSync as or,renameSync as ir,cpSync as Mf}from"fs";import{join as pe,dirname as xc}from"path";import{homedir as If}from"os";function No(){if(Pn)return Pn;try{return Ie(rr)?(Pn=JSON.parse(vt(rr,"utf-8")),Pn):ar()}catch{return ar()}}function Ro(e){Pn=e;try{Po(de,{recursive:!0}),us(rr,JSON.stringify(e),"utf-8")}catch{}}function ar(){if(!Ie(de))return[];let e=[];for(let t of lr(de).filter(n=>n.endsWith(".json")&&n!=="_index.json"))try{let n=JSON.parse(vt(pe(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,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 Pn=e,Ro(e),e}function wc(e){let t=No(),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,pageCount:n.filter(i=>i.contentMode!=="email").length,emailCount:n.filter(i=>i.contentMode==="email").length,hasBrandAssets:!!(e.brandAssets&&(e.brandAssets.styleguide||e.brandAssets.brandvoice||e.brandAssets.brandKit)),isImported:!!e.isImported},o=t.findIndex(i=>i.id===e.id);o>=0?t[o]=s:t.push(s),Ro(t)}function Pf(e){let t=No().filter(n=>n.id!==e);Ro(t)}function Nf(e){let t=No().filter(n=>n.themeName!==e);Ro(t)}function C(){return Ue}function Cc(){return`vibe-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`}function Nn(e,t,n={}){let s={id:Cc(),themePath:e,themeName:t,isImported:!!n.isImported,templates:[],activeTemplateId:"",messages:[],modules:[],sharedCss:"",sharedJs:"",template:"",moduleOrder:[],createdAt:Date.now(),updatedAt:Date.now()};return Ue=s,_o(e),s}function j(){if(!Ue)return;Po(de,{recursive:!0});let e=pe(de,`${Ue.id}.json`);us(e,JSON.stringify(Ue,null,2),"utf-8"),wc(Ue)}function Oo(e){let t=pe(de,e+".json");if(!Ie(t))return null;try{let n=JSON.parse(vt(t,"utf-8"));if(n.templates||(n.templates=[]),n.activeTemplateId||(n.activeTemplateId=""),Io(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 Ue=n,n}catch{return null}}function Rn(){return Ie(de)?No():[]}function kc(e,t=!1){let n=pe(de,e+".json"),s="";if(t)try{let o=JSON.parse(vt(n,"utf-8"));s=o.themeName||"",o.themePath&&Ie(o.themePath)&&or(o.themePath,{recursive:!0,force:!0})}catch{}else try{s=JSON.parse(vt(n,"utf-8")).themeName||""}catch{}try{Ie(n)&&or(n)}catch{}if(s&&Ie(de)){for(let o of lr(de).filter(i=>i.endsWith(".json")&&i!=="_index.json"))try{JSON.parse(vt(pe(de,o),"utf-8")).themeName===s&&or(pe(de,o))}catch{}Nf(s)}else Pf(e);Ue?.id===e&&(Ue=null)}function Tc(e,t){let n=pe(de,e+".json");if(!Ie(n))return{ok:!1,error:"Session not found"};let s;try{s=JSON.parse(vt(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=pe(xc(i),t);if(Ie(i)){if(Ie(r))return{ok:!1,error:"A project with that name already exists"};try{ir(i,r)}catch(m){return{ok:!1,error:`Failed to rename folder: ${m instanceof Error?m.message:String(m)}`}}let a=pe(r,"css",`${o}-theme.css`),l=pe(r,"css",`${t}-theme.css`);if(Ie(a))try{ir(a,l)}catch{}let c=pe(r,"js",`${o}-animations.js`),d=pe(r,"js",`${t}-animations.js`);if(Ie(c))try{ir(c,d)}catch{}let u=pe(r,"theme.json");if(Ie(u))try{let m=JSON.parse(vt(u,"utf-8"));m.label=t,m.name=t,us(u,JSON.stringify(m,null,2),"utf-8")}catch{}}if(Ie(de))for(let a of lr(de).filter(l=>l.endsWith(".json")&&l!=="_index.json"))try{let l=JSON.parse(vt(pe(de,a),"utf-8"));l.themeName===o&&(l.themeName=t,l.themePath=r,l.updatedAt=Date.now(),us(pe(de,a),JSON.stringify(l,null,2),"utf-8"))}catch{}return Ue&&Ue.themeName===o&&(Ue.themeName=t,Ue.themePath=r,Ue.updatedAt=Date.now()),ar(),{ok:!0}}function Ac(e){let t=pe(de,e+".json");if(!Ie(t))return{ok:!1,error:"Session not found"};let n;try{n=JSON.parse(vt(t,"utf-8"))}catch{return{ok:!1,error:"Failed to read session"}}let s=n.themeName.replace(/-copy(-\d+)?$/,""),o=xc(n.themePath),i=`${s}-copy`,r=1;for(;Ie(pe(o,i));)r++,i=`${s}-copy-${r}`;let a=pe(o,i);if(Ie(n.themePath))try{Mf(n.themePath,a,{recursive:!0})}catch(d){return{ok:!1,error:`Failed to copy files: ${d instanceof Error?d.message:String(d)}`}}else Po(a,{recursive:!0});let l=Cc(),c={...JSON.parse(JSON.stringify(n)),id:l,themeName:i,themePath:a,createdAt:Date.now(),updatedAt:Date.now(),messages:[]};return Po(de,{recursive:!0}),us(pe(de,`${l}.json`),JSON.stringify(c,null,2),"utf-8"),wc(c),{ok:!0,newName:i,newSessionId:l}}var de,rr,Pn,Ue,ds=N(()=>{"use strict";y();Mn();Ut();de=pe(If(),".vibespot","sessions"),rr=pe(de,"_index.json"),Pn=null;Ue=null});import{readFileSync as Rf,readdirSync as Ec,statSync as cr}from"fs";import{createHash as Of}from"crypto";import{join as be,relative as Ff}from"path";function jo(e){let t=[];if(!x(e))return ah(e,[{severity:"error",rule:"theme.path.missing",message:`Theme directory not found: ${e}`}]);let n=On(e),s=sh(e),o=ih(e),i=rh(e),r=Bf(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 ms(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 {
|
|
187
187
|
${t.join(`
|
|
188
188
|
`)}
|
|
189
189
|
}
|
|
190
|
-
`}function
|
|
191
|
-
`),s}function Bl(e){let t=qn(e);return w(t)?null:Li(e)}function Og(e){let t=qn(e);if(!w(t))return null;try{let n=JSON.parse(E(t));return of(n)?n:null}catch{return null}}function Fg(e){let t=qn(e),n=Og(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=Gl(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: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:t,filesChanged:r.length,added:a,modified:l,deleted:c,files:r}}function fn(e){let t=Xg(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=E(u)}catch{continue}let g,h=new RegExp(Wg.source,"g");for(;(g=h.exec(m))!==null;){let f=g[1],b=new RegExp(Kg.source,"g"),S;for(;(S=b.exec(f))!==null;){let x=S[1].trim(),v=S[2].trim();n[x]||(n[x]=v);let I=v.match(/#[0-9a-fA-F]{3,8}\b|rgba?\([^)]+\)|hsla?\([^)]+\)/);if(I){let F=Dl(I[0]);o.set(F,x)}}}for(let f of[jg,Dg,Lg]){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,Jg,i,zg),go(m,Bg,r,f=>f.trim()),Vg(m,a),go(m,Gg,l,f=>f.trim()),go(m,Ug,c,f=>f.trim())}let d=[...s.entries()].filter(([u])=>!qg(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(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 Vg(e,t){let n=new RegExp(Hg.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 zg(e){return e.split(",")[0].trim().replace(/^["']|["']$/g,"")}function Dl(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 qg(e){return Yg.has(e)}function Xg(e){let t=[],n=he(e,"css");if(w(n))for(let o of Ot(n))o.endsWith(".css")&&t.push(he(n,o));let s=he(e,"modules");if(w(s))for(let o of Ot(s)){if(!o.endsWith(".module"))continue;let i=he(s,o,"module.css");w(i)&&t.push(i)}return t}function Zg(e){let t=he(e,"modules"),n=he(e,"templates"),s=new Set,o=new Map;if(w(t))for(let c of Ot(t)){if(!c.endsWith(".module"))continue;let d=c.replace(/\.module$/,"");s.add(d),o.set(d,w(he(t,c,"module.js")))}let i=[],r=new Map;if(w(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=E(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:rf(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(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 ef(e){let t=[],n=he(e,"modules");if(!w(n))return t;for(let s of Ot(n)){if(!s.endsWith(".module"))continue;let o=s.replace(/\.module$/,""),i=he(n,s,"fields.json");if(!w(i))continue;let r;try{r=JSON.parse(E(i))}catch{continue}Array.isArray(r)&&Hl(r,o,t,0)}return t}function Hl(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&&!Qg.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)&&Hl(i.children,t,n,s+1)}}function tf(e){let t=[],n=he(e,"modules");if(w(n))for(let i of Ot(n)){if(!i.endsWith(".module"))continue;let r=i.replace(/\.module$/,""),a=he(n,i,"module.html");w(a)&&Ll(a,e,r,t);let l=he(n,i,"module.js");if(w(l))try{E(l).trim().length>0&&t.push({file:Bi(e,l),pattern:"module.js.custom",detail:`${r}: module ships custom JS \u2014 preserve verbatim`})}catch{}}let s=he(e,"templates");if(w(s))for(let i of Ot(s)){if(!i.endsWith(".html"))continue;let r=he(s,i);if(!w(r))continue;let a;try{a=Di(r)}catch{continue}a.isFile()&&Ll(r,e,i,t)}let o=he(e,"import_modules.json");return w(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 Ll(e,t,n,s){let o;try{o=E(e)}catch{return}let i=Bi(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 nf(e,t){let n={hasSnapshot:!1,snapshotPath:qn(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 Gl(e){let t=[];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(e,i),l=Eg(i),c={path:a,sha256:Mg("sha256").update(l).digest("hex"),size:l.length};sf(a)&&(c.text=l.toString("utf8")),t.push(c)}}return n(e),t.sort((s,o)=>s.path.localeCompare(o.path))}function sf(e){let t=e.lastIndexOf(".");return t<0?!1:Rg.has(e.slice(t).toLowerCase())}function of(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 fo(e){if(e!==void 0)return e.length===0?0:e.split(/\r\n|\r|\n/).length}function Ot(e){try{return Jl(e)}catch{return[]}}function Bi(e,t){return Ig(e,t).split("\\").join("/")}function rf(e){return[...new Set(e)]}var Pg,Rg,jg,Dg,Lg,Jg,Bg,Hg,Gg,Ug,Wg,Kg,Yg,Qg,bo=R(()=>{"use strict";y();ne();Pg=".vibespot/import-snapshot.json",Rg=new Set([".css",".html",".htm",".js",".json",".md",".txt",".svg",".yml",".yaml"]);jg=/#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})\b/g,Dg=/\brgba?\([^)]+\)/g,Lg=/\bhsla?\([^)]+\)/g,Jg=/font-family\s*:\s*([^;}\n]+)/g,Bg=/font-size\s*:\s*([^;}\n]+)/g,Hg=/(?:padding|margin|gap)(?:-(?:top|right|bottom|left))?\s*:\s*([^;}\n]+)/g,Gg=/border-radius\s*:\s*([^;}\n]+)/g,Ug=/box-shadow\s*:\s*([^;}\n]+)/g,Wg=/:root\s*\{([\s\S]*?)\}/g,Kg=/(--[\w-]+)\s*:\s*([^;}\n]+)/g;Yg=new Set(["#000000","#ffffff","transparent","currentcolor","inherit","initial"]);Qg=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 Ul}from"fs";import{join as G}from"path";function ve(e){try{return Hi(e,"utf-8")}catch{return""}}function Kl(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 af(e,t){let n=ve(e);if(!n||t==="home.html"||t.endsWith("-listing.html"))return null;let s=t.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:t}}function lf(e,t,n,s,o){if(!xe(e))return[];let i=[],r=Zn(e).filter(a=>a.endsWith(".html")&&a!=="home.html");for(let a of r){let l=G(e,a),c=af(l,a);if(!c||c.moduleNames.length===0&&i.length>0)continue;let d=[],u=[];for(let m of c.moduleNames){let g=t.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(e){let t=C();if(!t)return;let n=Tl(e);n.length>0&&t.messages.length===0&&(t.messages=n),so(e),Bl(e);let s=G(e,"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=G(s,S.name),v=S.name.replace(/\.module$/,""),I={moduleName:v,fieldsJson:ve(G(x,"fields.json")),metaJson:ve(G(x,"meta.json")),moduleHtml:ve(G(x,"module.html")),moduleCss:ve(G(x,"module.css")),moduleJs:ve(G(x,"module.js"))||void 0};I.fieldsJson&&I.moduleHtml&&(t.modules.push(I),t.moduleOrder.push(v))}let i=G(e,"css"),r=G(e,"js"),a="",l="";if(xe(i)){let S=Zn(i).filter(x=>x.endsWith("-theme.css"));S.length>0&&(a=ve(G(i,S[0])),t.sharedCss=a)}if(xe(r)){let S=Zn(r).filter(x=>x.endsWith("-animations.js"));S.length>0&&(l=ve(G(r,S[0])),t.sharedJs=l)}if(!a&&t.modules.length>0){let S=fn(e),x=Yn(S);x&&(t.sharedCss=x,a=x)}let c=G(e,".vibespot","styleguide.md"),d=G(e,".vibespot","brandvoice.md"),u=G(e,".vibespot","theme-context.md"),m=G(e,".vibespot","plan.md"),g=G(e,".vibespot","brand-kit.json");if((xe(c)||xe(d)||xe(u)||xe(m)||xe(g))&&(t.brandAssets||(t.brandAssets={}),xe(c)&&(t.brandAssets.styleguide=ve(c)),xe(d)&&(t.brandAssets.brandvoice=ve(d)),xe(u)&&(t.brandAssets.themeContext=ve(u)),xe(m)&&(t.brandAssets.plan=ve(m)),xe(g)))try{t.brandAssets.brandKit=JSON.parse(ve(g))}catch{}let h=G(e,"templates"),f=new Map(t.modules.map(S=>[S.moduleName,S])),b=lf(h,f,a,l,t.messages);if(b.length>0){t.templates=b,t.activeTemplateId=b[0].id,t.brandAssets?.plan&&!b[0].plan&&(b[0].plan=t.brandAssets.plan);let S=b[0].moduleOrder;if(S.length>0){let x=new Set(t.moduleOrder),v=S.filter(I=>x.has(I));for(let I of t.moduleOrder)v.includes(I)||v.push(I);t.moduleOrder=v}Wt(b[0])}else t.templates||(t.templates=[]),t.activeTemplateId||(t.activeTemplateId=""),lo(t)}function ke(){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=G(t,"modules");Xn(s,{recursive:!0});for(let l of n.values())Xn(G(s,`${l.moduleName}.module`),{recursive:!0});for(let l of n.values()){let c=G(s,`${l.moduleName}.module`);Ke(G(c,"fields.json"),l.fieldsJson,"utf-8"),Ke(G(c,"meta.json"),l.metaJson,"utf-8"),Ke(G(c,"module.html"),l.moduleHtml,"utf-8"),Ke(G(c,"module.css"),l.moduleCss,"utf-8"),l.moduleJs&&Ke(G(c,"module.js"),l.moduleJs,"utf-8")}if(e.sharedCss){let l=G(t,"css");Xn(l,{recursive:!0}),Ke(G(l,`${e.themeName}-theme.css`),e.sharedCss,"utf-8")}if(e.sharedJs){let l=G(t,"js");Xn(l,{recursive:!0}),Ke(G(l,`${e.themeName}-animations.js`),e.sharedJs,"utf-8")}let o=G(t,"templates");Xn(o,{recursive:!0});let i=G(o,"home.html");(e.templates.length>0||e.modules.length>0)&&xe(i)&&Ul(i,{force:!0});let a=new Set;if(e.templates.length>0)for(let l of e.templates){if(l.contentMode==="email"){if(l.modules.length===0)continue;let m=mf(l),g=l.templateFile?l.templateFile.replace("templates/",""):"email.html";Ke(G(o,g),m,"utf-8"),a.add(g);continue}if(l.pageType==="module_only"||l.modules.length===0)continue;let c=l.template||uf(l),d=Wl(c,l.label,l.pageType),u=`${l.id}.html`;Ke(G(o,u),d,"utf-8"),a.add(u),l.pageType==="blog_post"&&(pf(o,l),a.add(`${l.id}-listing.html`))}else if(e.modules.length>0){let l=e.template||gf(),c=Wl(l,`${e.themeName} Landing Page`),d=`lp-${e.themeName}.html`;Ke(G(o,d),c,"utf-8"),a.add(d)}try{for(let l of Zn(o))l.startsWith("lp-")&&l.endsWith(".html")&&!a.has(l)&&Ul(G(o,l),{force:!0})}catch{}cf(),df()}function Vl(){let e=C();e&&(e.modules=[],e.moduleOrder=[],e.sharedCss="",e.sharedJs="",e.template="",So(e.themePath),e.updatedAt=Date.now(),et())}function zl(){let e=C();if(!e)return;let t=Ce();if(!t)return;let n=e.themePath,s=G(n,"modules");t.modules=[];for(let o of t.moduleOrder){let i=G(s,`${o}.module`);if(!xe(i))continue;let r={moduleName:o,fieldsJson:ve(G(i,"fields.json")),metaJson:ve(G(i,"meta.json")),moduleHtml:ve(G(i,"module.html")),moduleCss:ve(G(i,"module.css")),moduleJs:ve(G(i,"module.js"))||void 0};r.fieldsJson&&r.moduleHtml&&t.modules.push(r)}if(t.templateFile){let o=G(n,t.templateFile);xe(o)&&(t.template=ve(o))}Wt(t),e.updatedAt=Date.now()}function cf(){let e=C();if(!e)return;let t=G(e.themePath,"templates","layouts","base.html");if(xe(t))try{let n=Hi(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 Lo(e,t){let n=be(e,"css");if(x(n))try{for(let r of Ec(n))if(r.endsWith("-theme.css"))return null}catch{}let s=On(e),o=ms(s);if(!o)return null;let i=be(n,`${t}-theme.css`);return J(i,o),i}function ps(e){return be(e,Df)}function Lf(e,t=new Date().toISOString()){return{version:1,createdAt:t,files:Pc(e)}}function dr(e,t){let n=Lf(e,t),s=ps(e);return J(s,JSON.stringify(n,null,2)+`
|
|
191
|
+
`),s}function Mc(e){let t=ps(e);return x(t)?null:dr(e)}function Jf(e){let t=ps(e);if(!x(t))return null;try{let n=JSON.parse(P(t));return ch(n)?n:null}catch{return null}}function Bf(e){let t=ps(e),n=Jf(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=Pc(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:Do(d.text),afterLines:Do(u.text)}):r.push({file:d.path,status:"deleted",beforeSha256:d.sha256,beforeSize:d.size,beforeLines:Do(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:Do(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 On(e){let t=nh(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=P(u)}catch{continue}let g,h=new RegExp(qf.source,"g");for(;(g=h.exec(m))!==null;){let f=g[1],b=new RegExp(Xf.source,"g"),S;for(;(S=b.exec(f))!==null;){let v=S[1].trim(),w=S[2].trim();n[v]||(n[v]=w);let M=w.match(/#[0-9a-fA-F]{3,8}\b|rgba?\([^)]+\)|hsla?\([^)]+\)/);if(M){let L=_c(M[0]);o.set(L,v)}}}for(let f of[Hf,Uf,Gf]){let b=new RegExp(f.source,"g"),S;for(;(S=b.exec(m))!==null;){let v=_c(S[0]);v&&s.set(v,(s.get(v)??0)+1)}}Fo(m,Wf,i,Qf),Fo(m,Kf,r,f=>f.trim()),Zf(m,a),Fo(m,zf,l,f=>f.trim()),Fo(m,Yf,c,f=>f.trim())}let d=[...s.entries()].filter(([u])=>!th(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 Fo(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 Zf(e,t){let n=new RegExp(Vf.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 Qf(e){return e.split(",")[0].trim().replace(/^["']|["']$/g,"")}function _c(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 th(e){return eh.has(e)}function nh(e){let t=[],n=be(e,"css");if(x(n))for(let o of Gt(n))o.endsWith(".css")&&t.push(be(n,o));let s=be(e,"modules");if(x(s))for(let o of Gt(s)){if(!o.endsWith(".module"))continue;let i=be(s,o,"module.css");x(i)&&t.push(i)}return t}function sh(e){let t=be(e,"modules"),n=be(e,"templates"),s=new Set,o=new Map;if(x(t))for(let c of Gt(t)){if(!c.endsWith(".module"))continue;let d=c.replace(/\.module$/,"");s.add(d),o.set(d,x(be(t,c,"module.js")))}let i=[],r=new Map;if(x(n))for(let c of Gt(n)){if(!c.endsWith(".html")||c==="home.html")continue;let d=be(n,c),u;try{u=cr(d)}catch{continue}if(!u.isFile())continue;let m;try{m=P(d)}catch{continue}let g=ur(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:dh(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 ur(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 ih(e){let t=[],n=be(e,"modules");if(!x(n))return t;for(let s of Gt(n)){if(!s.endsWith(".module"))continue;let o=s.replace(/\.module$/,""),i=be(n,s,"fields.json");if(!x(i))continue;let r;try{r=JSON.parse(P(i))}catch{continue}Array.isArray(r)&&Ic(r,o,t,0)}return t}function Ic(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&&!oh.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)&&Ic(i.children,t,n,s+1)}}function rh(e){let t=[],n=be(e,"modules");if(x(n))for(let i of Gt(n)){if(!i.endsWith(".module"))continue;let r=i.replace(/\.module$/,""),a=be(n,i,"module.html");x(a)&&$c(a,e,r,t);let l=be(n,i,"module.js");if(x(l))try{P(l).trim().length>0&&t.push({file:mr(e,l),pattern:"module.js.custom",detail:`${r}: module ships custom JS \u2014 preserve verbatim`})}catch{}}let s=be(e,"templates");if(x(s))for(let i of Gt(s)){if(!i.endsWith(".html"))continue;let r=be(s,i);if(!x(r))continue;let a;try{a=cr(r)}catch{continue}a.isFile()&&$c(r,e,i,t)}let o=be(e,"import_modules.json");return x(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 $c(e,t,n,s){let o;try{o=P(e)}catch{return}let i=mr(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 ah(e,t){let n={hasSnapshot:!1,snapshotPath:ps(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 Pc(e){let t=[];function n(s){for(let o of Gt(s)){if(o===".git"||o===".vibespot"||o==="node_modules")continue;let i=be(s,o),r;try{r=cr(i)}catch{continue}if(r.isDirectory()){n(i);continue}if(!r.isFile())continue;let a=mr(e,i),l=Rf(i),c={path:a,sha256:Of("sha256").update(l).digest("hex"),size:l.length};lh(a)&&(c.text=l.toString("utf8")),t.push(c)}}return n(e),t.sort((s,o)=>s.path.localeCompare(o.path))}function lh(e){let t=e.lastIndexOf(".");return t<0?!1:jf.has(e.slice(t).toLowerCase())}function ch(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 Do(e){if(e!==void 0)return e.length===0?0:e.split(/\r\n|\r|\n/).length}function Gt(e){try{return Ec(e)}catch{return[]}}function mr(e,t){return Ff(e,t).split("\\").join("/")}function dh(e){return[...new Set(e)]}var Df,jf,Hf,Uf,Gf,Wf,Kf,Vf,zf,Yf,qf,Xf,eh,oh,Jo=N(()=>{"use strict";y();oe();Df=".vibespot/import-snapshot.json",jf=new Set([".css",".html",".htm",".js",".json",".md",".txt",".svg",".yml",".yaml"]);Hf=/#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})\b/g,Uf=/\brgba?\([^)]+\)/g,Gf=/\bhsla?\([^)]+\)/g,Wf=/font-family\s*:\s*([^;}\n]+)/g,Kf=/font-size\s*:\s*([^;}\n]+)/g,Vf=/(?:padding|margin|gap)(?:-(?:top|right|bottom|left))?\s*:\s*([^;}\n]+)/g,zf=/border-radius\s*:\s*([^;}\n]+)/g,Yf=/box-shadow\s*:\s*([^;}\n]+)/g,qf=/:root\s*\{([\s\S]*?)\}/g,Xf=/(--[\w-]+)\s*:\s*([^;}\n]+)/g;eh=new Set(["#000000","#ffffff","transparent","currentcolor","inherit","initial"]);oh=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 pr,readdirSync as fs,existsSync as xe,writeFileSync as Ye,mkdirSync as gs,rmSync as Nc}from"fs";import{join as U}from"path";function we(e){try{return pr(e,"utf-8")}catch{return""}}function Oc(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 uh(e,t){let n=we(e);if(!n||t==="home.html"||t.endsWith("-listing.html"))return null;let s=t.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=ur(n);return{id:s,label:a,pageType:i,contentMode:r,moduleNames:c,templateContent:n,filename:t}}function mh(e,t,n,s,o){if(!xe(e))return[];let i=[],r=fs(e).filter(a=>a.endsWith(".html")&&a!=="home.html");for(let a of r){let l=U(e,a),c=uh(l,a);if(!c||c.moduleNames.length===0&&i.length>0)continue;let d=[],u=[];for(let m of c.moduleNames){let g=t.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 Bo(e){let t=C();if(!t)return;let n=gc(e);n.length>0&&t.messages.length===0&&(t.messages=n),_o(e),Mc(e);let s=U(e,"modules");if(!xe(s))return;let o=fs(s,{withFileTypes:!0});for(let S of o){if(!S.isDirectory()||!S.name.endsWith(".module"))continue;let v=U(s,S.name),w=S.name.replace(/\.module$/,""),M={moduleName:w,fieldsJson:we(U(v,"fields.json")),metaJson:we(U(v,"meta.json")),moduleHtml:we(U(v,"module.html")),moduleCss:we(U(v,"module.css")),moduleJs:we(U(v,"module.js"))||void 0};M.fieldsJson&&M.moduleHtml&&(t.modules.push(M),t.moduleOrder.push(w))}let i=U(e,"css"),r=U(e,"js"),a="",l="";if(xe(i)){let S=fs(i).filter(v=>v.endsWith("-theme.css"));S.length>0&&(a=we(U(i,S[0])),t.sharedCss=a)}if(xe(r)){let S=fs(r).filter(v=>v.endsWith("-animations.js"));S.length>0&&(l=we(U(r,S[0])),t.sharedJs=l)}if(!a&&t.modules.length>0){let S=On(e),v=ms(S);v&&(t.sharedCss=v,a=v)}let c=U(e,".vibespot","styleguide.md"),d=U(e,".vibespot","brandvoice.md"),u=U(e,".vibespot","theme-context.md"),m=U(e,".vibespot","plan.md"),g=U(e,".vibespot","brand-kit.json");if((xe(c)||xe(d)||xe(u)||xe(m)||xe(g))&&(t.brandAssets||(t.brandAssets={}),xe(c)&&(t.brandAssets.styleguide=we(c)),xe(d)&&(t.brandAssets.brandvoice=we(d)),xe(u)&&(t.brandAssets.themeContext=we(u)),xe(m)&&(t.brandAssets.plan=we(m)),xe(g)))try{t.brandAssets.brandKit=JSON.parse(we(g))}catch{}let h=U(e,"templates"),f=new Map(t.modules.map(S=>[S.moduleName,S])),b=mh(h,f,a,l,t.messages);if(b.length>0){t.templates=b,t.activeTemplateId=b[0].id,t.brandAssets?.plan&&!b[0].plan&&(b[0].plan=t.brandAssets.plan);let S=b[0].moduleOrder;if(S.length>0){let v=new Set(t.moduleOrder),w=S.filter(M=>v.has(M));for(let M of t.moduleOrder)w.includes(M)||w.push(M);t.moduleOrder=w}sn(b[0])}else t.templates||(t.templates=[]),t.activeTemplateId||(t.activeTemplateId=""),Io(t)}function Te(){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=U(t,"modules");gs(s,{recursive:!0});for(let l of n.values())gs(U(s,`${l.moduleName}.module`),{recursive:!0});for(let l of n.values()){let c=U(s,`${l.moduleName}.module`);Ye(U(c,"fields.json"),l.fieldsJson,"utf-8"),Ye(U(c,"meta.json"),l.metaJson,"utf-8"),Ye(U(c,"module.html"),l.moduleHtml,"utf-8"),Ye(U(c,"module.css"),l.moduleCss,"utf-8"),l.moduleJs&&Ye(U(c,"module.js"),l.moduleJs,"utf-8")}if(e.sharedCss){let l=U(t,"css");gs(l,{recursive:!0}),Ye(U(l,`${e.themeName}-theme.css`),e.sharedCss,"utf-8")}if(e.sharedJs){let l=U(t,"js");gs(l,{recursive:!0}),Ye(U(l,`${e.themeName}-animations.js`),e.sharedJs,"utf-8")}let o=U(t,"templates");gs(o,{recursive:!0});let i=U(o,"home.html");(e.templates.length>0||e.modules.length>0)&&xe(i)&&Nc(i,{force:!0});let a=new Set;if(e.templates.length>0)for(let l of e.templates){if(l.contentMode==="email"){if(l.modules.length===0)continue;let m=hh(l),g=l.templateFile?l.templateFile.replace("templates/",""):"email.html";Ye(U(o,g),m,"utf-8"),a.add(g);continue}if(l.pageType==="module_only"||l.modules.length===0)continue;let c=l.template||fh(l),d=Rc(c,l.label,l.pageType),u=`${l.id}.html`;Ye(U(o,u),d,"utf-8"),a.add(u),l.pageType==="blog_post"&&(yh(o,l),a.add(`${l.id}-listing.html`))}else if(e.modules.length>0){let l=e.template||bh(),c=Rc(l,`${e.themeName} Landing Page`),d=`lp-${e.themeName}.html`;Ye(U(o,d),c,"utf-8"),a.add(d)}try{for(let l of fs(o))l.startsWith("lp-")&&l.endsWith(".html")&&!a.has(l)&&Nc(U(o,l),{force:!0})}catch{}ph(),gh()}function Fc(){let e=C();e&&(e.modules=[],e.moduleOrder=[],e.sharedCss="",e.sharedJs="",e.template="",Bo(e.themePath),e.updatedAt=Date.now(),at())}function Dc(){let e=C();if(!e)return;let t=ke();if(!t)return;let n=e.themePath,s=U(n,"modules");t.modules=[];for(let o of t.moduleOrder){let i=U(s,`${o}.module`);if(!xe(i))continue;let r={moduleName:o,fieldsJson:we(U(i,"fields.json")),metaJson:we(U(i,"meta.json")),moduleHtml:we(U(i,"module.html")),moduleCss:we(U(i,"module.css")),moduleJs:we(U(i,"module.js"))||void 0};r.fieldsJson&&r.moduleHtml&&t.modules.push(r)}if(t.templateFile){let o=U(n,t.templateFile);xe(o)&&(t.template=we(o))}sn(t),e.updatedAt=Date.now()}function ph(){let e=C();if(!e)return;let t=U(e.themePath,"templates","layouts","base.html");if(xe(t))try{let n=pr(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+`
|
|
192
192
|
{% if template_js %}
|
|
193
193
|
{{ require_js(get_asset_url(template_js)) }}
|
|
194
194
|
{% endif %}`):n=n.replace("{{ standard_footer_includes }}",`{% if template_js %}
|
|
195
195
|
{{ require_js(get_asset_url(template_js)) }}
|
|
196
196
|
{% endif %}
|
|
197
|
-
{{ standard_footer_includes }}`),
|
|
197
|
+
{{ standard_footer_includes }}`),Ye(t,n,"utf-8")}catch{}}function gh(){let e=C();if(!e)return;let t=U(e.themePath,"theme.json");if(xe(t))try{let n=JSON.parse(pr(t,"utf-8"));n.label=e.themeName,n.name=e.themeName,Ye(t,JSON.stringify(n,null,2),"utf-8")}catch{}}function Rc(e,t,n="landing_page"){return e.includes("templateType")?e:`<!--
|
|
198
198
|
templateType: ${n==="blog_post"?"blog_post":"page"}
|
|
199
199
|
isAvailableForNewContent: true
|
|
200
200
|
label: "${t}"
|
|
201
201
|
-->
|
|
202
|
-
`+e}function
|
|
202
|
+
`+e}function fh(e){if(e.modules.length===0)return"";let n=C().themeName,o=Oc(e).map(r=>` {% dnd_section padding={"top":"0","bottom":"0","left":"0","right":"0"}, full_width=true %}
|
|
203
203
|
{% dnd_module path="../modules/${r.moduleName}.module" %}
|
|
204
204
|
{% end_dnd_module %}
|
|
205
205
|
{% end_dnd_section %}`).join(`
|
|
@@ -230,7 +230,7 @@ ${o}
|
|
|
230
230
|
|
|
231
231
|
{% block footer %}
|
|
232
232
|
{% endblock footer %}
|
|
233
|
-
`}function
|
|
233
|
+
`}function hh(e){let n=Oc(e).map(s=>` {% dnd_section %}
|
|
234
234
|
{% dnd_module path="../modules/${s.moduleName}.module" %}
|
|
235
235
|
{% end_dnd_module %}
|
|
236
236
|
{% end_dnd_section %}`).join(`
|
|
@@ -277,7 +277,7 @@ ${n}
|
|
|
277
277
|
{{ standard_footer_includes }}
|
|
278
278
|
</body>
|
|
279
279
|
</html>
|
|
280
|
-
`}function
|
|
280
|
+
`}function yh(e,t){let n=`<!--
|
|
281
281
|
templateType: blog_listing
|
|
282
282
|
isAvailableForNewContent: true
|
|
283
283
|
label: "${t.label} - Listing"
|
|
@@ -302,7 +302,7 @@ ${n}
|
|
|
302
302
|
{% endif %}
|
|
303
303
|
</div>
|
|
304
304
|
{% endblock body %}
|
|
305
|
-
`;
|
|
305
|
+
`;Ye(U(e,`${t.id}-listing.html`),n,"utf-8")}function bh(){let e=C();if(!e||e.modules.length===0)return"";let t=e.themeName,s=ve().map(o=>` {% dnd_section padding={"top":"0","bottom":"0","left":"0","right":"0"}, full_width=true %}
|
|
306
306
|
{% dnd_module path="../modules/${o.moduleName}.module" %}
|
|
307
307
|
{% end_dnd_module %}
|
|
308
308
|
{% end_dnd_section %}`).join(`
|
|
@@ -333,7 +333,7 @@ ${s}
|
|
|
333
333
|
|
|
334
334
|
{% block footer %}
|
|
335
335
|
{% endblock footer %}
|
|
336
|
-
`}var
|
|
336
|
+
`}var gr=N(()=>{"use strict";y();ds();ls();Ut();Mn();Jo()});var jc=N(()=>{"use strict";y();Zl();ds();ls();gr();Ut()});var Ce=N(()=>{"use strict";y();jc()});function hs(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]=hs(n.children):t[n.name]=n.default??"";return t}function Ho(e,t){let n=e;return n=_h(n),n=Hc(n,t),n=Uc(n,t),n=Gc(n,t),n=Eh(n),n}function hr(e){let t=[e.sharedCss||"",...e.moduleCssArray].filter(Boolean).map(o=>`<style>${o}</style>`).join(`
|
|
337
337
|
`),n=[e.sharedJs||"",...e.moduleJsArray].filter(Boolean).map(o=>`<script>${o}</script>`).join(`
|
|
338
338
|
`),s=e.renderedModules.join(`
|
|
339
339
|
`);return`<!DOCTYPE html>
|
|
@@ -380,11 +380,11 @@ document.querySelectorAll('img').forEach(function(img){
|
|
|
380
380
|
});
|
|
381
381
|
</script>
|
|
382
382
|
</body>
|
|
383
|
-
</html>`}function
|
|
383
|
+
</html>`}function _h(e){return e=e.replace(Sh,""),e=e.replace(vh,""),e=e.replace(xh,""),Lc.lastIndex=0,e=e.replace(Lc,(t,n)=>`/theme-assets/${n}`),Jc.lastIndex=0,e=e.replace(Jc,""),e=e.replace(wh,""),e=e.replace(Ch,""),e=e.replace(kh,""),e=e.replace(Th,""),e=e.replace(Ah,""),e}function Hc(e,t){let n=e,s=0;for(;s<30;){s++;let o=$h(n);if(!o)break;let{varName:i,iterExpr:r,body:a,start:l,end:c}=o,d=Mh(r,t),u="";Array.isArray(d)&&(u=d.map((m,g)=>{let h={...t,[i]:m,loop:{index:g+1,index0:g,first:g===0,last:g===d.length-1,length:d.length}},f=Hc(a,h);return f=Uc(f,h),f=Gc(f,h),f}).join("")),n=n.slice(0,l)+u+n.slice(c)}return n}function $h(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 Uc(e,t){let n=e,s=0;for(;fr.test(n)&&s<50;)s++,n=n.replace(fr,(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(Fn(i,t))return d[0];for(let u=1;u<d.length;u+=2){let m=d[u],g=d[u+1]||"";if(Fn(m,t))return g}return c}return Fn(i,t)?l:c}),fr.lastIndex=0;return n}function Gc(e,t){return e.replace(/\{\{[-\s]*(.*?)[-\s]*\}\}/g,(n,s)=>{let i=s.trim().split("|"),r=i[0].trim(),a=on(t,r);for(let c=1;c<i.length;c++)a=Kc(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 Eh(e){return e=e.replace(/\{%.*?%\}/gs,""),e=e.replace(/\{\{.*?\}\}/gs,""),e}function Mh(e,t){let n=e.match(/^range\(\s*(.+?)\s*,\s*(.+?)\s*\)$/);if(n){let o=Bc(n[1],t),i=Bc(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=on(t,s[1].trim());return typeof o=="string"?o.split(s[2]):[]}return on(t,e)}function Bc(e,t){let s=e.trim().split("|"),o=s[0].trim();if(!isNaN(Number(o)))return Number(o);let i=on(t,o);for(let r=1;r<s.length;r++)i=Kc(i,s[r].trim());return Number(i)||0}function on(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 Fn(e,t){let n=e.trim();if(n.startsWith("not "))return!Fn(n.slice(4),t);if(n.includes(" and "))return n.split(" and ").every(i=>Fn(i,t));if(n.includes(" or "))return n.split(" or ").some(i=>Fn(i,t));let s=n.match(/^(.+?)\s*(==|!=|>=|<=|>|<)\s*(.+)$/);if(s){let i=on(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=on(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=on(t,n);return Wc(o)}function Wc(e){return!(e==null||e===""||e===0||e===!1||Array.isArray(e)&&e.length===0)}function Kc(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,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""");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 Wc(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 Sh,vh,xh,Lc,Jc,wh,Ch,kh,Th,Ah,fr,Vc=N(()=>{"use strict";y();Sh=/\{%[-\s]*require_(css|js)\b.*?%\}/gs,vh=/\{%[-\s]*end_require_(css|js)\s*%\}/gs,xh=/\{\{[-\s]*require_(css|js)\(.*?\)\s*\}\}/gs,Lc=/\{\{[-\s]*get_asset_url\(["'](?:[^"'\/]+\/)?assets\/(.*?)["']\)\s*\}\}/gs,Jc=/\{\{[-\s]*get_asset_url\(.*?\)\s*\}\}/gs,wh=/\{%[-\s]*(end_)?(dnd_area|dnd_section|dnd_column|dnd_row|dnd_module)\b.*?%\}/gs,Ch=/\{%[-\s]*module\b.*?%\}/gs,kh=/\{%[-\s]*(extends|block|endblock|set)\b.*?%\}/gs,Th=/\{#.*?#\}/gs,Ah=/\{\{[-\s]*content\.\w+.*?\}\}/gs,fr=/\{%[-\s]*if\s+(.*?)\s*-?%\}((?:(?!\{%[-\s]*if\s)[\s\S])*?)\{%[-\s]*endif\s*-?%\}/g});var Uo={};Ge(Uo,{buildModulePreviewHtml:()=>Sr,buildPreviewHtml:()=>br});function Ih(e){if(Dn()==="email")return!0;for(let t of e)try{let n=JSON.parse(t.metaJson);if(Array.isArray(n.host_template_types)&&n.host_template_types.includes("EMAIL"))return!0}catch{}return!1}function Ph(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 yr(e,t){if(!Array.isArray(t))return e;let n=new Map;for(let o of t)n.set(o.name,o.type);let s=e;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 br(){let e=C();if(!e)return zc();let t=ve(),n=e.moduleOrder||[];if(t.length===0&&n.length===0)return zc();if(Ih(t))return Nh(t,n);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,u=[];try{let f=JSON.parse(c.fieldsJson);u=Array.isArray(f)?f:[],d={module:hs(u)}}catch{d={module:{}}}let m=yr(c.moduleHtml,u),g=Ho(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=Ph(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}">
|
|
384
384
|
<div class="vibespot-placeholder">
|
|
385
385
|
<div class="vibespot-placeholder__name">${c}</div>
|
|
386
386
|
</div>
|
|
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
|
|
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 hr({renderedModules:s,sharedCss:e.sharedCss,moduleCssArray:[l,...o],sharedJs:e.sharedJs,moduleJsArray:i})}function zc(){return`<!DOCTYPE html>
|
|
388
388
|
<html lang="en">
|
|
389
389
|
<head>
|
|
390
390
|
<meta charset="utf-8">
|
|
@@ -435,7 +435,7 @@ document.querySelectorAll('img').forEach(function(img){
|
|
|
435
435
|
<div class="welcome__sub">Build Something Great</div>
|
|
436
436
|
</div>
|
|
437
437
|
</body>
|
|
438
|
-
</html>`}function
|
|
438
|
+
</html>`}function Sr(e){let t=C();if(!t)return"";let n;for(let a of t.templates)if(n=a.modules.find(l=>l.moduleName===e),n)break;if(n||(n=t.modules.find(a=>a.moduleName===e)),!n)return"";let s,o=[];try{let a=JSON.parse(n.fieldsJson);o=Array.isArray(a)?a:[],s={module:hs(o)}}catch{s={module:{}}}let i=yr(n.moduleHtml,o),r=Ho(i,s);return hr({renderedModules:[`<div class="vibespot-module" data-module="${n.moduleName}">${r}</div>`],sharedCss:t.sharedCss,moduleCssArray:n.moduleCss?[n.moduleCss]:[],sharedJs:t.sharedJs,moduleJsArray:n.moduleJs?[n.moduleJs]:[]})}function Nh(e,t){let n=[],s=new Set;for(let i of e){let r,a=[];try{let u=JSON.parse(i.fieldsJson);a=Array.isArray(u)?u:[],r={module:hs(a)}}catch{r={module:{}}}let l=yr(i.moduleHtml,a),c=Ho(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 t)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
439
|
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="max-width:600px;margin:0 auto;">
|
|
440
440
|
<tr><td style="padding:40px 30px;text-align:center;background-color:#ffffff;border:1px dashed #ddd;">
|
|
441
441
|
<p style="font-family:Arial,Helvetica,sans-serif;font-size:14px;color:#999;">${i}</p>
|
|
@@ -485,8 +485,8 @@ document.addEventListener('click', function(e) {
|
|
|
485
485
|
});
|
|
486
486
|
</script>
|
|
487
487
|
</body>
|
|
488
|
-
</html>`}var
|
|
489
|
-
${
|
|
488
|
+
</html>`}var ys=N(()=>{"use strict";y();Vc();Ce();bs()});function xt(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 Ss(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 xt(c)}function vr(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 Yc(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=xt(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)&&(He({modules:r.modules.map(a=>vr(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=xt(s[1]);if(!r||typeof r!="object")throw new Error("Invalid JSON after repair");let a=r;a.modules&&Array.isArray(a.modules)&&(He({modules:a.modules.map(l=>vr(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=Ss(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}),He({modules:c.modules.map(d=>vr(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 Go=N(()=>{"use strict";y();Ce();le()});function jn(){let e=C();return e?{pageType:ke()?.pageType,brandAssets:e.brandAssets}:{}}function qc(e,t,n=!1,s,o){let r=[{type:"text",text:Oh(t,n)}];if(n){let l=`## HubSpot CMS Rules
|
|
489
|
+
${Je()}
|
|
490
490
|
|
|
491
491
|
## Conversion Guide Reference
|
|
492
492
|
${e}`;r.push({type:"text",text:l,cache_control:{type:"ephemeral"}})}else{let l=`## Design Quality
|
|
@@ -512,22 +512,22 @@ When using scroll-animate classes (opacity: 0 \u2192 visible), you MUST include
|
|
|
512
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.
|
|
513
513
|
|
|
514
514
|
## Design Guide
|
|
515
|
-
${
|
|
515
|
+
${is()}
|
|
516
516
|
|
|
517
517
|
## Content & Copywriting Guide
|
|
518
|
-
${
|
|
518
|
+
${Wi()}
|
|
519
519
|
|
|
520
520
|
## HubSpot CMS Rules
|
|
521
|
-
${
|
|
521
|
+
${Je()}
|
|
522
522
|
|
|
523
523
|
## Conversion Guide Reference
|
|
524
|
-
${e}`;r.push({type:"text",text:l,cache_control:{type:"ephemeral"}})}let a=
|
|
524
|
+
${e}`;r.push({type:"text",text:l,cache_control:{type:"ephemeral"}})}let a=Rh(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 Rh(e,t){let n=[];if(e){let s=Vi(e);s&&n.push(`## Page Type Context
|
|
525
525
|
${s}`)}if(t?.styleguide&&n.push(`## Brand Style Guide
|
|
526
526
|
${t.styleguide}`),t?.brandvoice&&n.push(`## Brand Voice
|
|
527
|
-
${t.brandvoice}`),t?.humanify!==!1){let s=
|
|
527
|
+
${t.brandvoice}`),t?.humanify!==!1){let s=Ki();s&&n.push(`## Anti-AI Copy Rules (Humanify)
|
|
528
528
|
${s}`)}return n.join(`
|
|
529
529
|
|
|
530
|
-
`)}function
|
|
530
|
+
`)}function Oh(e,t){return`You are vibeSpot, an AI that builds HubSpot CMS landing pages from natural language descriptions.
|
|
531
531
|
|
|
532
532
|
## Your Role
|
|
533
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.
|
|
@@ -606,7 +606,7 @@ The current template's modules are listed in page order in the user message. Thi
|
|
|
606
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.
|
|
607
607
|
- **Remove**: When the user asks to remove a section, omit it from the output.
|
|
608
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.
|
|
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
|
|
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 vs(e,t,n=!1,s,o){let i=`You are vibeSpot, an AI that builds HubSpot CMS landing pages from natural language descriptions.
|
|
610
610
|
|
|
611
611
|
## Your Role
|
|
612
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.
|
|
@@ -685,7 +685,7 @@ The current template's modules are listed in page order in the user message. Thi
|
|
|
685
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.
|
|
686
686
|
- **Remove**: When the user asks to remove a section, omit it from the output.
|
|
687
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.
|
|
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?
|
|
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?Vi(s):"",a=r?`
|
|
689
689
|
|
|
690
690
|
## Page Type Context
|
|
691
691
|
${r}`:"",l="";if(o?.styleguide&&(l+=`
|
|
@@ -694,13 +694,13 @@ ${r}`:"",l="";if(o?.styleguide&&(l+=`
|
|
|
694
694
|
${o.styleguide}`),o?.brandvoice&&(l+=`
|
|
695
695
|
|
|
696
696
|
## Brand Voice
|
|
697
|
-
${o.brandvoice}`),o?.humanify!==!1){let d=
|
|
697
|
+
${o.brandvoice}`),o?.humanify!==!1){let d=Ki();d&&(l+=`
|
|
698
698
|
|
|
699
699
|
## Anti-AI Copy Rules (Humanify)
|
|
700
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+`
|
|
701
701
|
|
|
702
702
|
## HubSpot CMS Rules
|
|
703
|
-
${
|
|
703
|
+
${Je()}
|
|
704
704
|
|
|
705
705
|
## Conversion Guide Reference
|
|
706
706
|
${e}`+c:i+a+l+`
|
|
@@ -728,16 +728,16 @@ When using scroll-animate classes (opacity: 0 \u2192 visible), you MUST include
|
|
|
728
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.
|
|
729
729
|
|
|
730
730
|
## Design Guide
|
|
731
|
-
${
|
|
731
|
+
${is()}
|
|
732
732
|
|
|
733
733
|
## Content & Copywriting Guide
|
|
734
|
-
${
|
|
734
|
+
${Wi()}
|
|
735
735
|
|
|
736
736
|
## HubSpot CMS Rules
|
|
737
|
-
${
|
|
737
|
+
${Je()}
|
|
738
738
|
|
|
739
739
|
## Conversion Guide Reference
|
|
740
|
-
${e}`+c}function
|
|
740
|
+
${e}`+c}function xs(){let e=C(),t=[],n=e.modules,s=n.length;if(s>0){t.push(`
|
|
741
741
|
|
|
742
742
|
## Page Narrative (module sequence)
|
|
743
743
|
`),t.push(`This template has ${s} module${s===1?"":"s"} in this order:
|
|
@@ -774,13 +774,13 @@ ${e.sharedCss}
|
|
|
774
774
|
\`\`\`js
|
|
775
775
|
${e.sharedJs}
|
|
776
776
|
\`\`\`
|
|
777
|
-
`)}let o=
|
|
777
|
+
`)}let o=Nt(),i=new Set(e.modules.map(a=>a.moduleName)),r=o.filter(a=>!i.has(a.module.moduleName));if(r.length>0){t.push(`
|
|
778
778
|
|
|
779
779
|
## Available modules in this theme (reusable)
|
|
780
780
|
`);for(let a of r)t.push(`- ${a.module.moduleName} (used in: ${a.usedIn.join(", ")})
|
|
781
781
|
`);t.push(`
|
|
782
782
|
The user can ask to reuse any of these modules by name.
|
|
783
|
-
`)}return t.join("")}function
|
|
783
|
+
`)}return t.join("")}function xr(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=xs(),r="";if(n.assets?.length){let d=n.assets.filter(u=>u.type==="image"&&u.usage==="asset");d.length>0&&(r=`
|
|
784
784
|
|
|
785
785
|
## Available Theme Assets
|
|
786
786
|
These images are in the theme's assets/ folder. Reference them with get_asset_url("${n.themeName}/assets/filename"):
|
|
@@ -794,72 +794,55 @@ ${i}`),r&&(a+=r),a+="\n\n---\nRemember: respond with a ```vibespot-modules JSON
|
|
|
794
794
|
[Attached document: ${d.originalName}]
|
|
795
795
|
${d.extractedText}`),d.type==="image"&&d.usage==="asset"&&d.assetPath&&(a+=`
|
|
796
796
|
|
|
797
|
-
[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
|
|
797
|
+
[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 Xc=N(()=>{"use strict";y();Ke();Ce()});import{spawn as Zc}from"child_process";async function Qc(){return wr||(wr=(await import("@anthropic-ai/sdk")).default),wr}function ed(e){if(!e?.length)return"";let t=[];for(let n of e)n.type==="image"&&n.usage==="asset"&&n.assetPath&&t.push(`
|
|
798
798
|
[Uploaded image: ${n.originalName} \u2192 use get_asset_url("${n.assetPath}")]`),n.type==="document"&&n.extractedText&&t.push(`
|
|
799
799
|
|
|
800
800
|
---
|
|
801
801
|
[Attached document: ${n.originalName}]
|
|
802
|
-
${n.extractedText}`);return t.join("")}async function
|
|
803
|
-
`);
|
|
802
|
+
${n.extractedText}`);return t.join("")}async function td(e,t,n,s,o,i,r,a="anthropic-api"){for(let l=0;;l++){let c=new Date;try{let d="",u=0,m=i||(()=>{});m(De[0]);let g=setInterval(()=>{u++,m(De[Math.min(u,De.length-1)])},6e3),h=e.messages.stream({model:s,max_tokens:48e3,system:t,messages:n});try{for await(let b of h)if(b.type==="content_block_delta"&&b.delta.type==="text_delta"){let S=b.delta.text;d+=S,o(S)}}finally{clearInterval(g)}let f;try{f=et((await h.finalMessage()).usage)}catch{}bt({engine:a,model:s,name:"vibe-chat",input:{system:t,messages:n},output:d,usage:f,startTime:c,endTime:new Date}),r&&r(d);return}catch(d){let u=d.status,m=d.error?.type;if(!(u===429||m==="rate_limit_error"||d instanceof Error&&d.message.includes("429"))||l>=Cr.length)throw d;let h=Cr[l];E.warn("ai-engine",`Rate limited (429), attempt ${l+1}/${Cr.length} \u2014 waiting ${h}s`),i&&i(`Rate limited by Anthropic API \u2014 retrying in ${h}s...`),await new Promise(f=>setTimeout(f,h*1e3)),i&&i("Retrying...")}}}function nd(e,t,n){let s=ye(),i=C().modules.length>0,r=xr(e,n),a=jn(),l=qc(s,t,i,a.pageType,a.brandAssets);return{messages:r,systemBlocks:l,conversionGuide:s,editMode:i}}async function kr(e,t,n,s,o,i,r,a,l){let c=await Qc(),d=new c({apiKey:t,...l?{baseURL:l}:{}}),{messages:u,systemBlocks:m}=nd(e,n,a);E.info("anthropic","API call",{model:s,systemBlockCount:m.length,cachedBlocks:m.filter(g=>g.cache_control).length,messageCount:u.length}),await td(d,m,u,s,o,i,r)}async function sd(e,t,n,s,o,i,r){let a=await Oi();if(!a)throw new Error("Claude OAuth session expired. Please re-authenticate in Settings.");let l=await Qc(),c=new l({authToken:a,defaultHeaders:zn}),{messages:d,systemBlocks:u}=nd(e,t,r),m=[{type:"text",text:bn},...u];E.info("anthropic-oauth","API call",{model:n,systemBlockCount:m.length,cachedBlocks:m.filter(g=>g.cache_control).length,messageCount:d.length}),await td(c,m,d,n,s,o,i,"claude-oauth")}async function Tr(e,t,n,s,o,i,r,a,l){let c=ye(),d=C().modules.length>0,u=xr(e,a),m=jn(),g=u.map(k=>typeof k.content=="string"?k:{role:k.role,content:k.content.map(T=>T.type==="text"?{type:"text",text:T.text}:{type:"image_url",image_url:{url:`data:${T.source.media_type};base64,${T.source.data}`}})}),h=vs(c,n,d,m.pageType,m.brandAssets),f=l||"https://api.openai.com/v1/chat/completions",b=!/\/mistral(\/|$|\?)/.test(f),S=new Date,v=await fetch(f,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify({model:s,max_tokens:48e3,stream:!0,...b?{stream_options:{include_usage:!0}}:{},messages:[{role:"system",content:h},...g]})});if(!v.ok){let k=await v.text();throw new Error(`API error (${v.status}): ${k}`)}let w=0,M=i||(()=>{});M(De[0]);let L=setInterval(()=>{w++,M(De[Math.min(w,De.length-1)])},6e3),H="",B,K=v.body.getReader(),X=new TextDecoder,O="";try{for(;;){let{done:k,value:T}=await K.read();if(k)break;O+=X.decode(T,{stream:!0});let $=O.split(`
|
|
803
|
+
`);O=$.pop()||"";for(let F of $){if(!F.startsWith("data: "))continue;let re=F.slice(6).trim();if(re==="[DONE]")break;try{let _e=JSON.parse(re),z=_e.choices?.[0]?.delta?.content;z&&(H+=z,o(z)),_e.usage&&(B=_e.usage)}catch{}}}}finally{clearInterval(L)}bt({engine:"openai-api",model:s,name:"vibe-chat",input:{system:h,messages:g},output:H,usage:An(B),startTime:S,endTime:new Date}),r&&r(H)}async function Ar(e,t,n,s,o,i,r,a,l){let c=ye(),d=C(),u=d.modules.length>0,m=xs(),g=jn(),h=[];for(let F of d.messages.slice(-20))h.push({role:F.role==="assistant"?"model":"user",parts:[{text:F.content}]});let f=m?`${e}
|
|
804
804
|
|
|
805
805
|
---
|
|
806
|
-
${
|
|
806
|
+
${m}`:e;if(r?.length)for(let F of r)F.type==="document"&&F.extractedText&&(f+=`
|
|
807
807
|
|
|
808
808
|
---
|
|
809
|
-
[Attached document: ${
|
|
810
|
-
${
|
|
809
|
+
[Attached document: ${F.originalName}]
|
|
810
|
+
${F.extractedText}`),F.type==="image"&&F.usage==="asset"&&F.assetPath&&(f+=`
|
|
811
811
|
|
|
812
|
-
[Uploaded image: ${
|
|
813
|
-
`)
|
|
814
|
-
`))>=0;){let
|
|
812
|
+
[Uploaded image: ${F.originalName} \u2192 available as get_asset_url("${F.assetPath}")]`);let b=[];if(r?.length)for(let F of r)F.type==="image"&&F.base64&&b.push({inlineData:{mimeType:F.mimeType,data:F.base64}});b.push({text:f}),h.push({role:"user",parts:b});let S=l||"gemini-2.5-flash",v=a||`https://generativelanguage.googleapis.com/v1beta/models/${S}:streamGenerateContent?alt=sse&key=${t}`,w=vs(c,n,u,g.pageType,g.brandAssets),M=new Date,L=await fetch(v,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({systemInstruction:{parts:[{text:w}]},contents:h,generationConfig:{maxOutputTokens:48e3}})});if(!L.ok){let F=await L.text();throw new Error(`Gemini API error (${L.status}): ${F}`)}let H=0,B=o||(()=>{});B(De[0]);let K=setInterval(()=>{H++,B(De[Math.min(H,De.length-1)])},6e3),X="",O,k=L.body.getReader(),T=new TextDecoder,$="";try{for(;;){let{done:F,value:re}=await k.read();if(F)break;$+=T.decode(re,{stream:!0});let _e=$.split(`
|
|
813
|
+
`);$=_e.pop()||"";for(let z of _e){if(!z.startsWith("data: "))continue;let ue=z.slice(6).trim();try{let ne=JSON.parse(ue),$e=ne.candidates?.[0]?.content?.parts?.[0]?.text;$e&&(X+=$e,s($e)),ne.usageMetadata&&(O=ne.usageMetadata)}catch{}}}}finally{clearInterval(K)}bt({engine:"gemini-api",model:S,name:"vibe-chat",input:{system:w,contents:h},output:X,usage:_n(O),startTime:M,endTime:new Date}),i&&i(X)}function _r(e,t,n={},s){return new Promise((o,i)=>{let r={...process.env};delete r.CLAUDECODE;let a=Zc("claude",e,{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 M of w.message.content)if(M.type==="text"&&typeof M.text=="string"){let L=M.text;l+=L,n.onChunk&&n.onChunk(L)}else if(M.type==="tool_use"){let L=M;L.name&&n.onToolUse&&n.onToolUse(L.name,L.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 M;for(;(M=d.indexOf(`
|
|
814
|
+
`))>=0;){let L=d.slice(0,M).trim();if(d=d.slice(M+1),!!L)try{h(JSON.parse(L))}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}.
|
|
815
815
|
`+(c?`Stderr: ${c.slice(0,500)}
|
|
816
|
-
`:"")+(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 b=s||6e5,S=Math.round(b/6e4),
|
|
816
|
+
`:"")+(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 b=s||6e5,S=Math.round(b/6e4),v=setTimeout(()=>{a.kill(),g(()=>i(new Error(`claude (stream-json) timed out after ${S} minutes.
|
|
817
817
|
`+(c?`Stderr: ${c.slice(0,500)}
|
|
818
|
-
`:"")+`Partial output (${l.length} chars): ${l.slice(0,500)}`)))},b);a.on("close",()=>clearTimeout(
|
|
818
|
+
`:"")+`Partial output (${l.length} chars): ${l.slice(0,500)}`)))},b);a.on("close",()=>clearTimeout(v))})}function $r(e,t,n,s,o){return new Promise((i,r)=>{let a={...process.env};delete a.CLAUDECODE;let l=Zc(e,t,{stdio:["pipe","pipe","pipe"],env:a}),c="",d="",u=!1,m=S=>{u||(u=!0,S())};l.stdout.on("data",S=>{let v=S.toString();c+=v,s&&s(v)}),l.stderr.on("data",S=>{d+=S.toString()}),l.on("error",S=>m(()=>r(new Error(`${e} failed to start: ${S.message}`)))),l.on("close",S=>{m(()=>{S!==0?r(new Error(`${e} exited with code ${S}.
|
|
819
819
|
`+(d?`Stderr: ${d.slice(0,500)}
|
|
820
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(`${e} timed out after ${f} minutes.
|
|
821
821
|
`+(d?`Stderr: ${d.slice(0,500)}
|
|
822
|
-
`:"")+`Partial output (${c.length} chars): ${c.slice(0,500)}`)))},h);l.on("close",()=>clearTimeout(b))})}async function
|
|
822
|
+
`:"")+`Partial output (${c.length} chars): ${c.slice(0,500)}`)))},h);l.on("close",()=>clearTimeout(b))})}async function od(e,t,n,s,o,i){let r=ye(),a=R(),l=C().modules.length>0,c=jn(),d=vs(r,t,l,c.pageType,c.brandAssets);d+=`
|
|
823
823
|
|
|
824
824
|
## User Request
|
|
825
|
-
`+e,d+=
|
|
825
|
+
`+e,d+=xs(),d+=ed(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(De[0]);let h=setInterval(()=>{m++;let f=De[Math.min(m,De.length-1)];g(f)},6e3);try{let f=await _r(u,d,{onChunk:b=>n(b),onToolUse:(b,S)=>{g(Fh(b,S))}});o&&o(f)}finally{clearInterval(h)}}function Fh(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 Er(e,t,n,s,o,i,r){let a=ye(),l=C().modules.length>0,c=jn(),d=vs(a,n,l,c.pageType,c.brandAssets);d+=`
|
|
826
826
|
|
|
827
827
|
## User Request
|
|
828
|
-
`+t,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;e==="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();Ge();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(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 Ve(e,t,n){W(e,s=>{try{n(JSON.parse(s||"{}"))}catch{p(t,400,{error:"Invalid JSON in request body"})}})}var ze=R(()=>{"use strict";y()});import{createWriteStream as Rf,mkdirSync as Sc,existsSync as sr,readFileSync as or}from"fs";import{join as Vt,extname as Nf}from"path";import{randomUUID as Of}from"crypto";import Ff from"busboy";function Jf(e,t){if(vc.has(t))return t;let n=e.slice(e.lastIndexOf(".")).toLowerCase();return Lf[n]??t}function Bf(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_").replace(/_{2,}/g,"_").replace(/^_+|_+$/g,"").toLowerCase()}function Hf(e,t){if(!sr(Vt(e,t)))return t;let n=Nf(t),s=t.slice(0,-n.length||void 0),o=1;for(;sr(Vt(e,`${s}-${o}${n}`));)o++;return`${s}-${o}${n}`}async function Gf(e){let t=(await import("pdf-parse")).default,n=or(e);return(await t(n)).text}async function Uf(e){return(await(await import("mammoth")).extractRawText({path:e})).value}function Wf(e){return or(e,"utf-8")}function wc(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=Ff({headers:e.headers,limits:{fileSize:jf,files:10}});l.on("file",(c,d,u)=>{let{filename:m,mimeType:g}=u;r++;let h=Jf(m,g);if(!vc.has(h)){i.push(`Unsupported file type: ${m} (${g})`),d.resume();return}let f=xc.has(h),b=Bf(m),S=Of(),x,v;f?(x=Vt(n.themePath,"assets"),Sc(x,{recursive:!0}),v=Hf(x,b)):(x=Vt(n.themePath,".vibespot","uploads"),Sc(x,{recursive:!0}),v=`${S}-${b}`);let I=Vt(x,v),F=Rf(I),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:v,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 Gf(d):c.mimeType==="application/vnd.openxmlformats-officedocument.wordprocessingml.document"?c.extractedText=await Uf(d):c.extractedText=Wf(d),M.info("upload",`Extracted text from ${c.originalName} (${c.extractedText.length} chars)`)}catch(u){M.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=>{M.error("upload",`Busboy error: ${c}`),p(t,500,{error:"Upload failed"})}),e.pipe(l)}function Co(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=Vt(t.themePath,"assets",s.filename);sr(i)&&(o.base64=or(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 jf,xc,Df,vc,Lf,ir=R(()=>{"use strict";y();ze();we();de();jf=10*1024*1024,xc=new Set(["image/png","image/jpeg","image/jpg","image/svg+xml","image/webp","image/gif"]),Df=new Set(["application/pdf","application/vnd.openxmlformats-officedocument.wordprocessingml.document","text/markdown","text/plain"]),vc=new Set([...xc,...Df]),Lf={".md":"text/markdown",".txt":"text/plain",".markdown":"text/markdown"}});var $c={};Be($c,{callAgent:()=>_e,callAgentAPI:()=>Ac,isAgenticCapable:()=>rs,isCLIEngine:()=>xn,resolveThinkingBudget:()=>Sn});async function ko(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>=rr.length)throw s;let a=rr[n];M.warn("agent-adapter",`Rate limited (429), attempt ${n+1}/${rr.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 is(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 kc(){return ar||(ar=(await import("@anthropic-ai/sdk")).default),ar}async function Cc(e,t,n,s,o,i){let r=await kc(),a=new r({apiKey:e,...s?{defaultHeaders:s}:{},...i?{baseURL:i}:{}}),l=n.messages,c=n.systemPrompt;if(n.systemBlocks?c=o?[{type:"text",text:o},...n.systemBlocks]:n.systemBlocks:o&&(c=[{type:"text",text:o},{type:"text",text:n.systemPrompt}]),n.structuredOutput){let d={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 u=await a.messages.create({model:t,max_tokens:n.maxTokens||16e3,system:c,messages:l,tools:[d],tool_choice:{type:"tool",name:n.structuredOutput.name},...n.thinkingBudgetTokens?{thinking:{type:"enabled",budget_tokens:n.thinkingBudgetTokens}}:{}});for(let g of u.content)if(g.type==="tool_use")return{type:"structured",data:is(g.input)};return{type:"text",text:u.content.filter(g=>g.type==="text").map(g=>g.text).join("")}},n.onStatus)}return ko(async()=>{let d="",u=a.messages.stream({model:t,max_tokens:n.maxTokens||16e3,system:c,messages:l,...n.enableWebSearch?{tools:[{type:"web_search_20250305",name:"web_search"}]}:{},...n.thinkingBudgetTokens?{thinking:{type:"enabled",budget_tokens:n.thinkingBudgetTokens}}:{}});for await(let m of u)m.type==="content_block_delta"&&m.delta.type==="text_delta"&&(d+=m.delta.text,n.onChunk&&n.onChunk(m.delta.text));return{type:"text",text:d}},n.onStatus)}async function Vf(e,t,n){let s=await kc(),o=new s({authToken:e,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: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: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: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 lr(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"?lr(o):o;t.properties=n}return t.items&&typeof t.items=="object"&&(t.items=lr(t.items)),t}async function zf(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:lr(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:is(JSON.parse(a))}}catch{return M.warn("agent-adapter","OpenAI structured output parse failed, returning raw text"),{type:"text",text:a}}return{type:"text",text:a}}async function Yf(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:is(JSON.parse(c))}}catch{return M.warn("agent-adapter","Gemini structured output parse failed, returning raw text"),{type:"text",text:c}}return{type:"text",text:c}}function qf(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 Xf(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(`
|
|
828
|
+
`+t,d+=xs(),d+=ed(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 g=0,h=o||(()=>{});h(De[0]);let f=setInterval(()=>{g++;let b=De[Math.min(g,De.length-1)];h(b)},6e3);try{let b=await $r(u,m,d,S=>{s(S)});i&&i(b)}finally{clearInterval(f)}}var wr,De,Cr,Mr=N(()=>{"use strict";y();Ke();ee();_t();Ce();Xc();le();Be();en();wr=null;De=["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..."],Cr=[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 qe(e,t,n){W(e,s=>{try{n(JSON.parse(s||"{}"))}catch{p(t,400,{error:"Invalid JSON in request body"})}})}var Xe=N(()=>{"use strict";y()});import{createWriteStream as Dh,mkdirSync as id,existsSync as Ir,readFileSync as Pr}from"fs";import{join as rn,extname as jh}from"path";import{randomUUID as Lh}from"crypto";import Jh from"busboy";function Gh(e,t){if(ad.has(t))return t;let n=e.slice(e.lastIndexOf(".")).toLowerCase();return Uh[n]??t}function Wh(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_").replace(/_{2,}/g,"_").replace(/^_+|_+$/g,"").toLowerCase()}function Kh(e,t){if(!Ir(rn(e,t)))return t;let n=jh(t),s=t.slice(0,-n.length||void 0),o=1;for(;Ir(rn(e,`${s}-${o}${n}`));)o++;return`${s}-${o}${n}`}async function Vh(e){let t=(await import("pdf-parse")).default,n=Pr(e);return(await t(n)).text}async function zh(e){return(await(await import("mammoth")).extractRawText({path:e})).value}function Yh(e){return Pr(e,"utf-8")}function ld(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=Jh({headers:e.headers,limits:{fileSize:Bh,files:10}});l.on("file",(c,d,u)=>{let{filename:m,mimeType:g}=u;r++;let h=Gh(m,g);if(!ad.has(h)){i.push(`Unsupported file type: ${m} (${g})`),d.resume();return}let f=rd.has(h),b=Wh(m),S=Lh(),v,w;f?(v=rn(n.themePath,"assets"),id(v,{recursive:!0}),w=Kh(v,b)):(v=rn(n.themePath,".vibespot","uploads"),id(v,{recursive:!0}),w=`${S}-${b}`);let M=rn(v,w),L=Dh(M),H=0,B=!1;d.on("data",K=>{H+=K.length}),d.on("limit",()=>{B=!0,i.push(`File too large (>10MB): ${m}`)}),d.pipe(L),a.push(new Promise(K=>{L.on("finish",()=>{if(!B){let X={id:S,filename:w,originalName:m,type:f?"image":"document",usage:f?"asset":"context",mimeType:h,size:H,addedAt:new Date().toISOString()};o.push(X),cc(X)}K()}),L.on("error",()=>{i.push(`Failed to write: ${m}`),K()})}))}),l.on("finish",async()=>{await Promise.all(a);for(let c of o)if(c.type==="document"){let d=rn(n.themePath,".vibespot","uploads",c.filename);try{c.mimeType==="application/pdf"?c.extractedText=await Vh(d):c.mimeType==="application/vnd.openxmlformats-officedocument.wordprocessingml.document"?c.extractedText=await zh(d):c.extractedText=Yh(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 Wo(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=rn(t.themePath,"assets",s.filename);Ir(i)&&(o.base64=Pr(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 Bh,rd,Hh,ad,Uh,Nr=N(()=>{"use strict";y();Xe();Ce();le();Bh=10*1024*1024,rd=new Set(["image/png","image/jpeg","image/jpg","image/svg+xml","image/webp","image/gif"]),Hh=new Set(["application/pdf","application/vnd.openxmlformats-officedocument.wordprocessingml.document","text/markdown","text/plain"]),ad=new Set([...rd,...Hh]),Uh={".md":"text/markdown",".txt":"text/plain",".markdown":"text/markdown"}});var fd={};Ge(fd,{LANGDOCK_BASE_URLS:()=>ws,callAgent:()=>Pe,callAgentAPI:()=>gd,isAgenticCapable:()=>ks,isCLIEngine:()=>Jn,resolveThinkingBudget:()=>Ln});async function Ko(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>=Rr.length)throw s;let a=Rr[n];E.warn("agent-adapter",`Rate limited (429), attempt ${n+1}/${Rr.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 Cs(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 md(){return Or||(Or=(await import("@anthropic-ai/sdk")).default),Or}async function cd(e,t,n,s,o,i){let r=await md(),a=new r({apiKey:e,...s?{defaultHeaders:s}:{},...i?{baseURL:i}:{}}),l=n.messages,c=n.systemPrompt;if(n.systemBlocks?c=o?[{type:"text",text:o},...n.systemBlocks]:n.systemBlocks:o&&(c=[{type:"text",text:o},{type:"text",text:n.systemPrompt}]),n.structuredOutput){let d={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 u=await a.messages.create({model:t,max_tokens:n.maxTokens||16e3,system:c,messages:l,tools:[d],tool_choice:{type:"tool",name:n.structuredOutput.name},...n.thinkingBudgetTokens?{thinking:{type:"enabled",budget_tokens:n.thinkingBudgetTokens}}:{}}),m=et(u.usage);for(let h of u.content)if(h.type==="tool_use")return{type:"structured",data:Cs(h.input),usage:m};return{type:"text",text:u.content.filter(h=>h.type==="text").map(h=>h.text).join(""),usage:m}},n.onStatus)}return Ko(async()=>{let d="",u=a.messages.stream({model:t,max_tokens:n.maxTokens||16e3,system:c,messages:l,...n.enableWebSearch?{tools:[{type:"web_search_20250305",name:"web_search"}]}:{},...n.thinkingBudgetTokens?{thinking:{type:"enabled",budget_tokens:n.thinkingBudgetTokens}}:{}});for await(let g of u)g.type==="content_block_delta"&&g.delta.type==="text_delta"&&(d+=g.delta.text,n.onChunk&&n.onChunk(g.delta.text));let m;try{m=et((await u.finalMessage()).usage)}catch{}return{type:"text",text:d,usage:m}},n.onStatus)}async function qh(e,t,n){let s=await md(),o=new s({authToken:e,defaultHeaders:zn}),i=n.messages,r;if(n.systemBlocks?r=[{type:"text",text:bn},...n.systemBlocks]:r=[{type:"text",text:bn},{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: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}}:{}}),c=et(l.usage);for(let u of l.content)if(u.type==="tool_use")return{type:"structured",data:Cs(u.input),usage:c};return{type:"text",text:l.content.filter(u=>u.type==="text").map(u=>u.text).join(""),usage:c}},n.onStatus)}return Ko(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 d of l)d.type==="content_block_delta"&&d.delta.type==="text_delta"&&(a+=d.delta.text,n.onChunk&&n.onChunk(d.delta.text));let c;try{c=et((await l.finalMessage()).usage)}catch{}return{type:"text",text:a,usage:c}},n.onStatus)}function Fr(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"?Fr(o):o;t.properties=n}return t.items&&typeof t.items=="object"&&(t.items=Fr(t.items)),t}async function dd(e,t,n,s){let o=[{role:"system",content:n.systemPrompt},...n.messages.map(u=>({role:u.role,content:typeof u.content=="string"?u.content:u.content.map(m=>({type:"text",text:m.text}))}))],i={model:t,max_completion_tokens:n.maxTokens||16e3,messages:o};n.structuredOutput&&(i.response_format={type:"json_schema",json_schema:{name:n.structuredOutput.name,strict:!1,schema:Fr(n.structuredOutput.schema)}});let a=await fetch(s||"https://api.openai.com/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(i)});if(!a.ok){let u=await a.text(),m=a.status;if(m===429){let g=new Error(`OpenAI rate limit: ${u}`);throw g.status=429,g}throw new Error(`OpenAI API error (${m}): ${u}`)}let l=await a.json(),c=l.choices?.[0]?.message?.content||"",d=An(l.usage);if(n.structuredOutput)try{return{type:"structured",data:Cs(JSON.parse(c)),usage:d}}catch{return E.warn("agent-adapter","OpenAI structured output parse failed, returning raw text"),{type:"text",text:c,usage:d}}return{type:"text",text:c,usage:d}}async function ud(e,t,n,s){let o=t||"gemini-2.5-flash",i=n.messages.map(m=>({role:m.role==="assistant"?"model":"user",parts:typeof m.content=="string"?[{text:m.content}]:m.content.map(g=>({text:g.text}))})),r={systemInstruction:{parts:[{text:n.systemPrompt}]},contents:i,generationConfig:{maxOutputTokens:n.maxTokens||16e3,...n.structuredOutput?{responseMimeType:"application/json",responseSchema:n.structuredOutput.schema}:{}}},a=s||`https://generativelanguage.googleapis.com/v1beta/models/${o}:generateContent?key=${e}`,l=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)});if(!l.ok){let m=await l.text(),g=l.status;if(g===429){let h=new Error(`Gemini rate limit: ${m}`);throw h.status=429,h}throw new Error(`Gemini API error (${g}): ${m}`)}let c=await l.json(),d=c.candidates?.[0]?.content?.parts?.[0]?.text||"",u=_n(c.usageMetadata);if(n.structuredOutput)try{return{type:"structured",data:Cs(JSON.parse(d)),usage:u}}catch{return E.warn("agent-adapter","Gemini structured output parse failed, returning raw text"),{type:"text",text:d,usage:u}}return{type:"text",text:d,usage:u}}function Xh(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 Zh(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(`
|
|
829
829
|
`);t.push(`
|
|
830
830
|
|
|
831
831
|
## ${s}
|
|
832
|
-
${o}`)}if(e.structuredOutput){let n=
|
|
832
|
+
${o}`)}if(e.structuredOutput){let n=pd(e.structuredOutput.schema);t.push(`
|
|
833
833
|
|
|
834
834
|
## Output Format \u2014 CRITICAL
|
|
835
835
|
Respond with a JSON code block. Wrap your JSON in \`\`\`json fences. No prose or explanation before or after the code block.
|
|
836
836
|
|
|
837
837
|
The JSON must match this structure:
|
|
838
|
-
${n}`)}return t.join("")}function
|
|
839
|
-
`)}function
|
|
840
|
-
${t.map((c,d)=>`${d+1}. ${c}`).join(`
|
|
841
|
-
`)}`:"No modules yet (new page).",r=n.length>0?`
|
|
842
|
-
|
|
843
|
-
Module library (reusable from other templates):
|
|
844
|
-
${n.map(c=>`- ${c.name} (used in: ${c.usedIn.join(", ")})`).join(`
|
|
845
|
-
`)}`:"",a=s?`
|
|
846
|
-
|
|
847
|
-
## Product Context
|
|
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.
|
|
838
|
+
${n}`)}return t.join("")}function pd(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}": ${pd(a,t+1)}${l}${d}`):i.push(`${n} "${r}": ${c}${l}${d}${u}`)}return i.push(`${n}}`),i.join(`
|
|
839
|
+
`)}function Qh(e){let t=e.trim(),n=xt(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=xt(a);if(l&&typeof l=="object")return l;let c=Ss(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=xt(a);if(l&&typeof l=="object")return l;let c=Ss(a);if(c&&typeof c=="object")return c}let r=Ss(t);return r&&typeof r=="object"?r:null}async function ey(e,t,n){let{bin:s,args:o}=Xh(e,t,n),i=Zh(n),r;if(e==="claude-code"){let l=[...o,"--output-format","stream-json","--include-partial-messages","--verbose"];r=await _r(l,i,{onChunk:n.onChunk,onToolUse:(c,d)=>{if(!n.onStatus)return;let u=ty(c,d);n.onStatus(u)}})}else r=await $r(s,o,i,n.onChunk);if(!n.structuredOutput)return{type:"text",text:r};let a=Qh(r);return a?{type:"structured",data:Cs(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 ty(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 gd(e,t,n,s){E.info("agent-adapter",`${e} API call`,{model:n,structured:!!s.structuredOutput,schemaName:s.structuredOutput?.name,systemPromptLength:s.systemPrompt.length,messageCount:s.messages.length});let o=new Date,i=await(async()=>{switch(e){case"anthropic-api":return cd(t,n,s);case"claude-oauth":{let{getValidAccessToken:r}=await Promise.resolve().then(()=>(_t(),Fi)),a=await r();if(!a)throw new Error("Claude OAuth session expired. Please re-authenticate in Settings.");return qh(a,n,s)}case"openai-api":return dd(t,n,s);case"gemini-api":return ud(t,n,s);case"langdock-api":{let r=R(),a=r.langdockProvider||"anthropic",l=r.langdockBaseUrl;switch(a){case"openai":case"mistral":{let c=l||ws[a];return dd(t,n,s,`${c}/v1/chat/completions`)}case"google":{let c=l||ws.google;return ud(t,n,s,`${c}/v1beta/models/${n}:generateContent`)}default:{let c=l||ws.anthropic;return cd(t,n,s,void 0,void 0,c)}}}default:throw new Error(`Unsupported API engine: ${e}`)}})();return sy(e,n,s,i,o,new Date),i}function sy(e,t,n,s,o,i){bt({engine:e,model:t,name:n.structuredOutput?.name||"generation",input:{system:n.systemPrompt,messages:n.messages},output:s.type==="structured"?s.data:s.text,usage:s.usage,startTime:o,endTime:i,metadata:{structured:!!n.structuredOutput,systemPromptLength:n.systemPrompt.length}})}async function Pe(e,t,n,s){return ny.has(e)?gd(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}),ey(e,n,s))}function Ln(e){if(e==="langdock-api"){if((R().langdockProvider||"anthropic")!=="anthropic")return 0}else 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 ks(e){return e==="anthropic-api"||e==="claude-oauth"||e==="openai-api"||e==="gemini-api"||e==="langdock-api"||e==="claude-code"||e==="gemini-cli"||e==="codex-cli"}function Jn(e){return e==="claude-code"||e==="gemini-cli"||e==="codex-cli"}var ws,kk,Rr,Or,ny,ct=N(()=>{"use strict";y();Mr();Go();ee();_t();le();en();Be();ws={anthropic:"https://api.langdock.com/anthropic",openai:"https://api.langdock.com/openai",google:"https://api.langdock.com/google",mistral:"https://api.langdock.com/mistral"},kk=ws.anthropic,Rr=[10,20,40,60,120];Or=null;ny=new Set(["anthropic-api","claude-oauth","openai-api","gemini-api","langdock-api"])});var Dr,hd=N(()=>{"use strict";y();Dr={"intent-analyzer":{version:1,placeholders:["themeName","contextData"],template:`You are the Intent Analyzer for vibeSpot, a HubSpot CMS builder that generates pages, email templates, and blog templates.
|
|
857
840
|
|
|
858
841
|
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
842
|
|
|
860
|
-
## Theme: "
|
|
843
|
+
## Theme: "{{themeName}}"
|
|
861
844
|
|
|
862
|
-
|
|
845
|
+
{{contextData}}
|
|
863
846
|
|
|
864
847
|
## Content Type Detection
|
|
865
848
|
|
|
@@ -929,11 +912,11 @@ If the user asks for multiple things (e.g., "make hero taller AND add testimonia
|
|
|
929
912
|
|
|
930
913
|
## Content Type Detection
|
|
931
914
|
|
|
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.`}
|
|
915
|
+
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.`},"design-system":{version:1,placeholders:["themeName"],template:`You are the Design System Architect for vibeSpot, a HubSpot CMS page builder.
|
|
933
916
|
|
|
934
917
|
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.
|
|
935
918
|
|
|
936
|
-
## Theme: "
|
|
919
|
+
## Theme: "{{themeName}}"
|
|
937
920
|
|
|
938
921
|
## Output Requirements
|
|
939
922
|
|
|
@@ -941,36 +924,36 @@ Your job: create a complete, production-ready CSS design system for a landing pa
|
|
|
941
924
|
A flat object mapping CSS custom property names to values. Every variable your CSS references MUST be defined here. Include ALL of these categories:
|
|
942
925
|
|
|
943
926
|
**Colors** (at minimum):
|
|
944
|
-
-
|
|
945
|
-
-
|
|
946
|
-
-
|
|
947
|
-
-
|
|
948
|
-
-
|
|
949
|
-
-
|
|
950
|
-
-
|
|
951
|
-
-
|
|
952
|
-
-
|
|
953
|
-
-
|
|
954
|
-
-
|
|
955
|
-
-
|
|
956
|
-
-
|
|
927
|
+
- --{{themeName}}-color-bg: page background
|
|
928
|
+
- --{{themeName}}-color-surface: card/section background
|
|
929
|
+
- --{{themeName}}-color-dark: dark section background
|
|
930
|
+
- --{{themeName}}-color-dark-surface: card bg inside dark sections
|
|
931
|
+
- --{{themeName}}-color-text: primary text color
|
|
932
|
+
- --{{themeName}}-color-text-inverse: text on dark backgrounds
|
|
933
|
+
- --{{themeName}}-color-text-muted: secondary/muted text
|
|
934
|
+
- --{{themeName}}-color-primary: primary brand color
|
|
935
|
+
- --{{themeName}}-color-primary-dark: darker variant for hover states
|
|
936
|
+
- --{{themeName}}-color-accent: accent/highlight color
|
|
937
|
+
- --{{themeName}}-color-accent-light: light tint for pill/badge backgrounds
|
|
938
|
+
- --{{themeName}}-color-border: default border color
|
|
939
|
+
- --{{themeName}}-color-border-hover: border on hover
|
|
957
940
|
|
|
958
941
|
**Typography**:
|
|
959
|
-
-
|
|
960
|
-
-
|
|
961
|
-
-
|
|
962
|
-
-
|
|
963
|
-
-
|
|
964
|
-
-
|
|
942
|
+
- --{{themeName}}-font-display: display/heading font stack (system fonts only)
|
|
943
|
+
- --{{themeName}}-font-body: body text font stack (system fonts only)
|
|
944
|
+
- --{{themeName}}-size-h1 through --{{themeName}}-size-h3: heading sizes using clamp()
|
|
945
|
+
- --{{themeName}}-size-body, --{{themeName}}-size-lg, --{{themeName}}-size-small, --{{themeName}}-size-label
|
|
946
|
+
- --{{themeName}}-leading-tight, --{{themeName}}-leading-snug, --{{themeName}}-leading-body: line heights
|
|
947
|
+
- --{{themeName}}-tracking-tight, --{{themeName}}-tracking-wide: letter spacing
|
|
965
948
|
|
|
966
949
|
**Spacing**:
|
|
967
|
-
-
|
|
968
|
-
-
|
|
950
|
+
- --{{themeName}}-space-xs through --{{themeName}}-space-xl, --{{themeName}}-space-section
|
|
951
|
+
- --{{themeName}}-max-width: content max-width (1152-1280px)
|
|
969
952
|
|
|
970
953
|
**Effects**:
|
|
971
|
-
-
|
|
972
|
-
-
|
|
973
|
-
-
|
|
954
|
+
- --{{themeName}}-radius-sm, --{{themeName}}-radius-md, --{{themeName}}-radius-lg, --{{themeName}}-radius-full
|
|
955
|
+
- --{{themeName}}-shadow-card-hover, --{{themeName}}-shadow-button
|
|
956
|
+
- --{{themeName}}-transition-fast, --{{themeName}}-transition-base, --{{themeName}}-transition-slow
|
|
974
957
|
|
|
975
958
|
### sharedCss
|
|
976
959
|
Complete CSS file content. MUST include:
|
|
@@ -978,15 +961,15 @@ Complete CSS file content. MUST include:
|
|
|
978
961
|
2. Reset (box-sizing, margin, padding)
|
|
979
962
|
3. Body styles referencing your variables
|
|
980
963
|
4. Typography rules (h1-h6, p)
|
|
981
|
-
5. Layout utilities (
|
|
982
|
-
6. Grid system (
|
|
983
|
-
7. Card component (
|
|
984
|
-
8. Button component (
|
|
964
|
+
5. Layout utilities (.{{themeName}}-container, .{{themeName}}-section, .{{themeName}}-section--dark)
|
|
965
|
+
6. Grid system (.{{themeName}}-grid, .{{themeName}}-grid--2/3/4 with responsive breakpoints)
|
|
966
|
+
7. Card component (.{{themeName}}-card with hover lift)
|
|
967
|
+
8. Button component (.{{themeName}}-btn, .{{themeName}}-btn--primary, .{{themeName}}-btn--secondary)
|
|
985
968
|
CRITICAL: Re-declare color, text-decoration:none, and font-family on :hover/:focus \u2014 HubSpot overrides link hover styles
|
|
986
|
-
9. Pill/badge (
|
|
969
|
+
9. Pill/badge (.{{themeName}}-pill)
|
|
987
970
|
10. Decorative elements (at least one background treatment: grid pattern, noise, gradient orb)
|
|
988
971
|
11. Scroll animation CSS ([data-animate], [data-animate-stagger]) with 3s CSS-only fallback
|
|
989
|
-
12. Section label (
|
|
972
|
+
12. Section label (.{{themeName}}-label) \u2014 uppercase, letter-spacing, accent color
|
|
990
973
|
13. Stat number styling
|
|
991
974
|
14. Responsive mobile styles (@media max-width: 767px)
|
|
992
975
|
|
|
@@ -994,8 +977,8 @@ Complete CSS file content. MUST include:
|
|
|
994
977
|
IntersectionObserver-based scroll animation JS. Wrap in IIFE.
|
|
995
978
|
|
|
996
979
|
## CSS Rules \u2014 CRITICAL
|
|
997
|
-
- All classes MUST use prefix "
|
|
998
|
-
- Use BEM naming:
|
|
980
|
+
- All classes MUST use prefix "{{themeName}}-"
|
|
981
|
+
- Use BEM naming: {{themeName}}-module__element--modifier
|
|
999
982
|
- Use system font stacks ONLY (no Google Fonts @import, no external CDN)
|
|
1000
983
|
- Every var() reference in CSS must have a matching declaration in :root
|
|
1001
984
|
- No Tailwind, no Sass, no PostCSS
|
|
@@ -1016,10 +999,153 @@ Use system font stacks that approximate the desired aesthetic. Pick TWO stacks:
|
|
|
1016
999
|
| Geometric | Futura, "Century Gothic", "Trebuchet MS", sans-serif | system-ui, sans-serif | Architecture, design, fashion |
|
|
1017
1000
|
| Classic | "Book Antiqua", Palatino, "Palatino Linotype", serif | Georgia, "Times New Roman", serif | Law, finance, heritage |
|
|
1018
1001
|
| 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 |`
|
|
1002
|
+
| Contrast pair | Georgia, serif (display) | system-ui, sans-serif (body) | When you want serif/sans tension |`},"module-planner":{version:1,placeholders:["themeName","cssSummary"],template:`You are the Module Planner for vibeSpot, a HubSpot CMS page builder.
|
|
1003
|
+
|
|
1004
|
+
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.
|
|
1005
|
+
|
|
1006
|
+
The Design System has already been created. Your module plans MUST reference the existing CSS classes and variables.
|
|
1007
|
+
|
|
1008
|
+
## Theme: "{{themeName}}"
|
|
1009
|
+
|
|
1010
|
+
## Available CSS Classes & Variables
|
|
1011
|
+
Reference these in your layoutNotes:
|
|
1012
|
+
|
|
1013
|
+
{{cssSummary}}
|
|
1014
|
+
|
|
1015
|
+
## Output Rules
|
|
1016
|
+
|
|
1017
|
+
### Module names \u2014 CRITICAL
|
|
1018
|
+
- **If the user message lists "Existing Modules to Re-plan", you MUST use those exact names verbatim** in \`modules[].name\` and in \`moduleOrder\`. Do not rename them. Do not retitle-case them. Do not "improve" them. The names are identifiers, not labels. Mismatched names create duplicate modules instead of regenerating existing ones.
|
|
1019
|
+
- **For genuinely new modules** (not in any existing-modules list): use kebab-case identifiers (e.g., \`hero\`, \`pricing-cards\`, \`final-cta\`). This matches the convention used by Plan Mode and Figma Import.
|
|
1020
|
+
- The \`description\` and \`contentBrief\` fields can be any text \u2014 they describe the module to humans, while \`name\` is the canonical identifier.
|
|
1021
|
+
|
|
1022
|
+
### Content & layout
|
|
1023
|
+
- Content briefs: describe the actual copy/content each module needs (headlines, body text, CTAs, stats)
|
|
1024
|
+
- Layout notes: describe the visual layout using the available CSS classes above
|
|
1025
|
+
- Reference specific CSS classes from the shared CSS in your layout notes (e.g., "Use {{themeName}}-grid--3 for card layout, {{themeName}}-section--dark for background")
|
|
1026
|
+
|
|
1027
|
+
### Module order
|
|
1028
|
+
- \`moduleOrder\`: list **all** modules' names in the order they should appear on the page, including:
|
|
1029
|
+
- the ones you just planned (in \`modules\`)
|
|
1030
|
+
- any "Existing Modules to Keep" the user listed (these are not in \`modules\`, but still belong in \`moduleOrder\`)`},"site-module-planner":{version:1,placeholders:["themeName","siteMap","sharedList","cssSummary","navHrefs","sharedModuleNamesCsv"],template:`You are the Site Module Planner for vibeSpot, a HubSpot CMS page builder.
|
|
1031
|
+
|
|
1032
|
+
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.
|
|
1033
|
+
|
|
1034
|
+
## Theme: "{{themeName}}"
|
|
1035
|
+
|
|
1036
|
+
## Site Map
|
|
1037
|
+
{{siteMap}}
|
|
1038
|
+
|
|
1039
|
+
## Shared Modules (appear on EVERY page)
|
|
1040
|
+
{{sharedList}}
|
|
1041
|
+
|
|
1042
|
+
Plan these shared modules ONCE. They will be automatically added to every page's template.
|
|
1043
|
+
|
|
1044
|
+
## Available CSS Classes & Variables
|
|
1045
|
+
Reference these in your layoutNotes:
|
|
1046
|
+
|
|
1047
|
+
{{cssSummary}}
|
|
1048
|
+
|
|
1049
|
+
## Shared Module Rules
|
|
1050
|
+
|
|
1051
|
+
### site-header (Navigation)
|
|
1052
|
+
- Logo on the left, nav links center or right, CTA button far right
|
|
1053
|
+
- Nav links: one for each page in the site map. Use relative hrefs matching slugs:
|
|
1054
|
+
{{navHrefs}}
|
|
1055
|
+
- Active page link uses CSS class "{{themeName}}-nav__link--active"
|
|
1056
|
+
- Sticky with backdrop-blur, transitions on scroll
|
|
1057
|
+
- Mobile: hamburger menu with slide-in nav
|
|
1058
|
+
|
|
1059
|
+
### site-footer
|
|
1060
|
+
- Consistent across all pages
|
|
1061
|
+
- Brand name, link columns (include page links), contact info, social icons, copyright
|
|
1062
|
+
- Include navigation links matching the header
|
|
1063
|
+
|
|
1064
|
+
## Per-Page Module Rules
|
|
1065
|
+
For each page, plan modules specific to that page's purpose. Do NOT include shared modules ({{sharedModuleNamesCsv}}) in per-page module lists or per-page moduleOrder \u2014 they are automatically prepended/appended.
|
|
1066
|
+
|
|
1067
|
+
Each page should have distinct content appropriate to its purpose. Aim for:
|
|
1068
|
+
- 4-8 unique modules per page (not counting shared modules)
|
|
1069
|
+
- Content appropriate to the page's purpose
|
|
1070
|
+
- Consistent use of design system classes across all pages
|
|
1071
|
+
|
|
1072
|
+
## Module Naming
|
|
1073
|
+
- Use kebab-case identifiers (e.g., "hero", "team-grid", "contact-form")
|
|
1074
|
+
- 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
|
|
1075
|
+
- Shared modules use the exact names from the shared modules list above
|
|
1076
|
+
|
|
1077
|
+
## Output Structure
|
|
1078
|
+
Return a JSON object with:
|
|
1079
|
+
- \`sharedModules\`: array of shared module specs (planned once, used everywhere)
|
|
1080
|
+
- \`pages\`: array of per-page blueprints, each with:
|
|
1081
|
+
- \`pageId\`: matching the page ID from the site map
|
|
1082
|
+
- \`modules\`: array of module specs for that page only (excluding shared)
|
|
1083
|
+
- \`moduleOrder\`: ordered list of per-page module names only (excluding shared)
|
|
1084
|
+
- \`narrative\`: brief description of the overall site story/flow`},"module-developer":{version:1,placeholders:["themeName"],template:`You are a Module Developer for vibeSpot, a HubSpot CMS page builder.
|
|
1085
|
+
|
|
1086
|
+
Your job: generate ONE HubSpot CMS module. You receive a module specification and must produce the complete module code.
|
|
1087
|
+
|
|
1088
|
+
## Theme: "{{themeName}}"
|
|
1089
|
+
|
|
1090
|
+
## Output Rules \u2014 CRITICAL
|
|
1091
|
+
You produce a single module with these fields:
|
|
1092
|
+
- **moduleName**: Exact module name (title-case, e.g., "Hero Banner")
|
|
1093
|
+
- **fieldsJson**: Valid JSON string \u2014 the module's fields.json content
|
|
1094
|
+
- **metaJson**: Valid JSON string \u2014 must include host_template_types: ["PAGE"], is_available_for_new_content: true
|
|
1095
|
+
- **moduleHtml**: HubL template ({{ module.field_name }} syntax)
|
|
1096
|
+
- **moduleCss**: Vanilla CSS (no Tailwind, no Sass, no CDN imports)
|
|
1097
|
+
- **moduleJs**: Optional vanilla JS wrapped in IIFE, or null
|
|
1098
|
+
|
|
1099
|
+
## CSS Rules
|
|
1100
|
+
- All CSS classes must use prefix "{{themeName}}-"
|
|
1101
|
+
- Use BEM naming: {{themeName}}-moduleName__element--modifier
|
|
1102
|
+
- Reference the theme's CSS custom properties (shown below)
|
|
1103
|
+
- No CDN imports (@import url(), external <link> tags)
|
|
1104
|
+
- Use system font stacks \u2014 no Google Fonts
|
|
1105
|
+
|
|
1106
|
+
## Field Rules
|
|
1107
|
+
- Use "type": "text" (NEVER "textarea" \u2014 it's deprecated)
|
|
1108
|
+
- NEVER use "name": "name" (reserved) \u2014 use "item_name" instead
|
|
1109
|
+
- NEVER use "name": "label" (reserved) \u2014 use "section_label" instead
|
|
1110
|
+
- NEVER put literal \\n in field defaults
|
|
1111
|
+
- Wrap style fields in a "styles" group with "tab": "STYLE"
|
|
1112
|
+
- Color fields: type "color", default { "color": "#hex", "opacity": 100 }
|
|
1113
|
+
- Link fields: type "link", default { "url": { "href": "#", "type": "EXTERNAL" }, "open_in_new_tab": false, "no_follow": false }
|
|
1114
|
+
- Image fields: type "image", default { "src": "https://placehold.co/800x600/1a1a2e/ffffff?text=Replace+in+HubSpot", "alt": "Placeholder", "width": 800, "height": 600 }
|
|
1115
|
+
- For repeater groups, use "occurrence": { "min": 0, "max": 100 }
|
|
1116
|
+
|
|
1117
|
+
## Images & Assets
|
|
1118
|
+
- Use get_asset_url("{{themeName}}/assets/filename.ext") for uploaded assets
|
|
1119
|
+
- For placeholder images, use image fields with placehold.co defaults
|
|
1120
|
+
- Size placeholders appropriately (hero: 1920x800, cards: 600x400, icons: 200x200)
|
|
1121
|
+
|
|
1122
|
+
## Navigation & Anchors
|
|
1123
|
+
- Add id attribute on module root element: id="module-name-lowercased"
|
|
1124
|
+
- For nav modules, use anchor links (#features, #pricing, etc.)
|
|
1125
|
+
- Include smooth scroll behavior in nav click handlers
|
|
1126
|
+
|
|
1127
|
+
## metaJson Template
|
|
1128
|
+
{ "host_template_types": ["PAGE"], "is_available_for_new_content": true }`}}});function iy(){if(yd!==void 0)return yd;if(Ts!==void 0)return Ts;try{let e=JSON.parse(P(fn(oy)));Ts=e&&typeof e=="object"&&e.prompts?e:null}catch{Ts=null}return Ts}function ry(e){let t=new Set;for(let n of e.matchAll(bd))t.add(n[1]);return[...t]}function ay(e){let t=Dr[e],n=iy()?.prompts?.[e];if(n&&n.version===t.version&&typeof n.template=="string"){let s=new Set(t.placeholders);if(ry(n.template).every(o=>s.has(o)))return{id:e,version:n.version,source:"langfuse-bundled",template:n.template}}return{id:e,version:t.version,source:"local-fallback",template:t.template}}function ly(e,t,n){let s=new Set(Dr[e].placeholders);return t.replace(bd,(o,i)=>s.has(i)?n[i]??"":o)}function Rt(e,t){return ly(e,ay(e).template,t)}var oy,bd,Ts,yd,As=N(()=>{"use strict";y();oe();hd();oy="prompts.bundle.json",bd=/\{\{\s*([a-zA-Z][\w]*)\s*\}\}/g});function Sd(e,t,n,s,o){let i=t.length>0?`Current template modules (in page order):
|
|
1129
|
+
${t.map((d,u)=>`${u+1}. ${d}`).join(`
|
|
1130
|
+
`)}`:"No modules yet (new page).",r=n.length>0?`
|
|
1131
|
+
|
|
1132
|
+
Module library (reusable from other templates):
|
|
1133
|
+
${n.map(d=>`- ${d.name} (used in: ${d.usedIn.join(", ")})`).join(`
|
|
1134
|
+
`)}`:"",a=s?`
|
|
1135
|
+
|
|
1136
|
+
## Product Context
|
|
1137
|
+
${s}`:"",l=o?.pages&&o.pages.length>1?`
|
|
1138
|
+
|
|
1139
|
+
## Multi-Page Site Context
|
|
1140
|
+
This is a multi-page site. Currently editing: **${o.activePageLabel||"unknown"}**
|
|
1141
|
+
All pages:
|
|
1142
|
+
${o.pages.map(d=>`- ${d.label} (${d.id}, ${d.moduleCount} modules)`).join(`
|
|
1143
|
+
`)}
|
|
1144
|
+
|
|
1145
|
+
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".`:"",c=`${i}${r}${a}${l}`;return Rt("intent-analyzer",{themeName:e,contextData:c})}var vd,xd=N(()=>{"use strict";y();As();vd={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 wd(e,t,n,s,o,i,r){i({type:"agent_step",step:"analyzing",label:"Analyzing your request..."});let a=t.modules.map(g=>g.moduleName),l=Sd(t.themeName,a,r,t.brandAssets?.themeContext,t.sitePages?{activePageLabel:t.activePageLabel,pages:t.sitePages}:void 0),c=[],d=t.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:e});let u=await te("intent-analyzer",()=>Pe(n,s,o,{systemPrompt:l,messages:c,structuredOutput:{schema:vd,name:"pipeline_plan"},maxTokens:2e3}));if(u.type!=="structured"){E.warn("intent-analyzer","Did not get structured output, falling back");let g=t.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||[],t.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:cy(m)}),m}function cy(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 Cd=N(()=>{"use strict";y();ct();xd();le();Be()});function Vo(e,t){let n=[];n.push(Rt("design-system",{themeName:e})),n.push(`
|
|
1020
1146
|
|
|
1021
1147
|
## Design Guide
|
|
1022
|
-
${
|
|
1148
|
+
${$d()}`),t?.styleguide&&n.push(`
|
|
1023
1149
|
|
|
1024
1150
|
## Brand Style Guide
|
|
1025
1151
|
${t.styleguide}`),t?.themeContext&&n.push(`
|
|
@@ -1035,11 +1161,11 @@ ${o.join(`
|
|
|
1035
1161
|
## No Brand Provided \u2014 Follow the Generation Recipe
|
|
1036
1162
|
No brand colors, fonts, or styleguide have been set. You MUST follow these rules to create a unique design:
|
|
1037
1163
|
|
|
1038
|
-
${
|
|
1164
|
+
${_d()}`),n.join("")}function jr(e,t){let n=Vo(e),o=n.indexOf(`
|
|
1039
1165
|
|
|
1040
1166
|
## Design Guide
|
|
1041
1167
|
`);if(o===-1)return[{type:"text",text:n}];let i=n.slice(0,o),r=`## Design Guide
|
|
1042
|
-
${
|
|
1168
|
+
${$d()}`,a=[{type:"text",text:i},{type:"text",text:r,cache_control:{type:"ephemeral"}}],l=[];t?.styleguide&&l.push(`## Brand Style Guide
|
|
1043
1169
|
${t.styleguide}`),t?.themeContext&&l.push(`## Product Context
|
|
1044
1170
|
${t.themeContext}`);let c=t?.brandKit&&(t.brandKit.colors?.primary||t.brandKit.colors?.secondary||t.brandKit.colors?.accent||t.brandKit.fonts?.heading||t.brandKit.fonts?.body);if(c){let d=[],u=t.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
1171
|
The following brand identity values MUST be used. Do NOT substitute or override them:
|
|
@@ -1047,41 +1173,13 @@ ${d.join(`
|
|
|
1047
1173
|
`)}`)}return!c&&!t?.styleguide&&l.push(`## No Brand Provided \u2014 Follow the Generation Recipe
|
|
1048
1174
|
No brand colors, fonts, or styleguide have been set. You MUST follow these rules to create a unique design:
|
|
1049
1175
|
|
|
1050
|
-
${
|
|
1051
|
-
|
|
1052
|
-
`)}),a}function sh(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(`
|
|
1053
|
-
`)}function Nc(e,t,n,s){let o=[],i=sh(t);return o.push(`You are the Module Planner for vibeSpot, a HubSpot CMS page builder.
|
|
1054
|
-
|
|
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.
|
|
1056
|
-
|
|
1057
|
-
The Design System has already been created. Your module plans MUST reference the existing CSS classes and variables.
|
|
1058
|
-
|
|
1059
|
-
## Theme: "${e}"
|
|
1060
|
-
|
|
1061
|
-
## Available CSS Classes & Variables
|
|
1062
|
-
Reference these in your layoutNotes:
|
|
1063
|
-
|
|
1064
|
-
${i}
|
|
1065
|
-
|
|
1066
|
-
## Output Rules
|
|
1067
|
-
|
|
1068
|
-
### Module names \u2014 CRITICAL
|
|
1069
|
-
- **If the user message lists "Existing Modules to Re-plan", you MUST use those exact names verbatim** in \`modules[].name\` and in \`moduleOrder\`. Do not rename them. Do not retitle-case them. Do not "improve" them. The names are identifiers, not labels. Mismatched names create duplicate modules instead of regenerating existing ones.
|
|
1070
|
-
- **For genuinely new modules** (not in any existing-modules list): use kebab-case identifiers (e.g., \`hero\`, \`pricing-cards\`, \`final-cta\`). This matches the convention used by Plan Mode and Figma Import.
|
|
1071
|
-
- The \`description\` and \`contentBrief\` fields can be any text \u2014 they describe the module to humans, while \`name\` is the canonical identifier.
|
|
1072
|
-
|
|
1073
|
-
### Content & layout
|
|
1074
|
-
- Content briefs: describe the actual copy/content each module needs (headlines, body text, CTAs, stats)
|
|
1075
|
-
- Layout notes: describe the visual layout using the available CSS classes above
|
|
1076
|
-
- 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")
|
|
1176
|
+
${_d()}`),l.length>0&&a.push({type:"text",text:l.join(`
|
|
1077
1177
|
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
- the ones you just planned (in \`modules\`)
|
|
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(`
|
|
1178
|
+
`)}),a}function dy(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(`
|
|
1179
|
+
`)}function Td(e,t,n,s){let o=[],i=dy(t);return o.push(Rt("module-planner",{themeName:e,cssSummary:i})),(!s||s.includes("content"))&&o.push(`
|
|
1082
1180
|
|
|
1083
1181
|
## Content & Copywriting Guide
|
|
1084
|
-
${
|
|
1182
|
+
${uy()}`),n?.brandvoice&&o.push(`
|
|
1085
1183
|
|
|
1086
1184
|
## Brand Voice
|
|
1087
1185
|
${n.brandvoice}`),n?.themeContext&&o.push(`
|
|
@@ -1090,7 +1188,7 @@ ${n.brandvoice}`),n?.themeContext&&o.push(`
|
|
|
1090
1188
|
${n.themeContext}`),n?.humanify!==!1&&s?.includes("humanify")&&o.push(`
|
|
1091
1189
|
|
|
1092
1190
|
## Anti-AI Copy Rules
|
|
1093
|
-
${
|
|
1191
|
+
${my()}`),o.join("")}function _d(){let e=is(),t=kd(e,"## 4. Color System","## 5."),n=kd(e,"### Recommended Font Pairings","### Typography Scale"),s=[];return s.push(`### Step 1: Derive the aesthetic from the content
|
|
1094
1192
|
Read the user's request carefully. What industry? What audience? What mood?
|
|
1095
1193
|
Map it to ONE of these aesthetic directions \u2014 then commit fully:
|
|
1096
1194
|
|
|
@@ -1146,7 +1244,7 @@ Before finalizing, ask yourself:
|
|
|
1146
1244
|
|
|
1147
1245
|
If any answer is "no," go bolder. The user wants personality, not safety.`),s.join(`
|
|
1148
1246
|
|
|
1149
|
-
`)}function
|
|
1247
|
+
`)}function kd(e,t,n){let s=e.indexOf(t);if(s===-1)return"";let o=e.indexOf(n,s);return o===-1?e.slice(s):e.slice(s,o).trim()}function $d(){return`### Design Philosophy
|
|
1150
1248
|
You are a senior UI designer. Every page must look professionally designed, not like AI output.
|
|
1151
1249
|
Avoid "AI slop": purple gradients on white, cookie-cutter card grids, no personality.
|
|
1152
1250
|
|
|
@@ -1253,7 +1351,7 @@ Include these in shared CSS:
|
|
|
1253
1351
|
| All animations same speed | Stagger with increasing delays |
|
|
1254
1352
|
| Skip hover/focus states | Every interactive element needs feedback |
|
|
1255
1353
|
| Use \`<br>\` tags for spacing | Use proper margin/padding |
|
|
1256
|
-
| Put everything in a shadowed card | Vary: full-bleed, contained, floating |`}function
|
|
1354
|
+
| Put everything in a shadowed card | Vary: full-bleed, contained, floating |`}function uy(){return`### Mandatory Page Sections (generate all)
|
|
1257
1355
|
1. **Navigation Bar** \u2014 Logo, 4-5 nav links, CTA button, sticky on scroll
|
|
1258
1356
|
2. **Hero** \u2014 Badge/pill, primary headline, subheadline, primary + secondary CTA, trust signals, visual element
|
|
1259
1357
|
3. **Social Proof Bar** \u2014 Logo strip of 4-6 clients OR stats bar (compact, py-8)
|
|
@@ -1341,7 +1439,7 @@ Alternate backgrounds every 2-3 sections to create visual "chapters." Sprinkle t
|
|
|
1341
1439
|
- Invent plausible specifics: neighborhood names, "48 hours" not "quickly", "\u20AC49" not "affordable"
|
|
1342
1440
|
- Keep paragraphs to 2-3 sentences max
|
|
1343
1441
|
- Aim for 6th-grade reading level
|
|
1344
|
-
- Include section labels (UPPERCASE, letter-spacing 0.1em, accent color, 2-3 words) above every headline`}function
|
|
1442
|
+
- Include section labels (UPPERCASE, letter-spacing 0.1em, accent color, 2-3 words) above every headline`}function my(){return`### Banned Punctuation
|
|
1345
1443
|
- **Em dashes (\u2014)**: NEVER use. Biggest AI tell. Replace with periods, commas, or parentheses.
|
|
1346
1444
|
- **Semicolons**: Feel academic, not conversational. Use periods instead.
|
|
1347
1445
|
- **Exclamation marks**: One per page maximum. Zero is ideal for B2B.
|
|
@@ -1371,12 +1469,12 @@ seamless, cutting-edge, groundbreaking, game-changer, revolutionary, transformat
|
|
|
1371
1469
|
- Use plain short words: use > utilize, start > commence, help > facilitate
|
|
1372
1470
|
- Vary sentence length aggressively: mix 3-word, 12-word, and 25-word sentences
|
|
1373
1471
|
- Front-load the benefit in the first 5 words
|
|
1374
|
-
- Write like you'd explain it in a bar \u2014 if you wouldn't say it holding a beer, rewrite it`}var
|
|
1472
|
+
- Write like you'd explain it in a bar \u2014 if you wouldn't say it holding a beer, rewrite it`}var Lr,Ad,Ed=N(()=>{"use strict";y();Ke();As();Lr={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"]};Ad={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 Jr(e){if(!e)return"";let t=[];return e.colors&&(e.colors.primary&&t.push(`- Primary color: ${e.colors.primary}`),e.colors.secondary&&t.push(`- Secondary color: ${e.colors.secondary}`),e.colors.accent&&t.push(`- Accent color: ${e.colors.accent}`)),e.fonts&&(e.fonts.heading&&t.push(`- Heading font: ${e.fonts.heading}`),e.fonts.body&&t.push(`- Body font: ${e.fonts.body}`)),e.logoUrl&&t.push(`- Logo URL: ${e.logoUrl}`),t.length===0?"":`
|
|
1375
1473
|
|
|
1376
1474
|
## Brand Kit \u2014 MANDATORY Design Constraints
|
|
1377
1475
|
The following brand identity values MUST be used. Do NOT substitute or override them:
|
|
1378
1476
|
${t.join(`
|
|
1379
|
-
`)}`}function
|
|
1477
|
+
`)}`}function zo(e,t){let n=[];n.push(`You are the Email Design Token Architect for vibeSpot, a HubSpot email template builder.
|
|
1380
1478
|
|
|
1381
1479
|
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
1480
|
|
|
@@ -1465,25 +1563,25 @@ Do NOT use: system-ui, -apple-system, Segoe UI, Inter, or any Google Fonts.
|
|
|
1465
1563
|
- No external font imports`),n.push(`
|
|
1466
1564
|
|
|
1467
1565
|
## Email Design Guide
|
|
1468
|
-
${
|
|
1566
|
+
${Id()}`),t?.styleguide&&n.push(`
|
|
1469
1567
|
|
|
1470
1568
|
## Brand Style Guide
|
|
1471
1569
|
${t.styleguide}`),t?.themeContext&&n.push(`
|
|
1472
1570
|
|
|
1473
1571
|
## Product Context
|
|
1474
|
-
${t.themeContext}`);let s=
|
|
1572
|
+
${t.themeContext}`);let s=Jr(t?.brandKit);return s?n.push(s):t?.styleguide||n.push(`
|
|
1475
1573
|
|
|
1476
1574
|
## 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
|
|
1575
|
+
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 Br(e,t){let n=zo(e),o=n.indexOf(`
|
|
1478
1576
|
|
|
1479
1577
|
## Email Design Guide
|
|
1480
1578
|
`);if(o===-1)return[{type:"text",text:n}];let i=n.slice(0,o),r=`## Email Design Guide
|
|
1481
|
-
${
|
|
1579
|
+
${Id()}`,a=[{type:"text",text:i},{type:"text",text:r,cache_control:{type:"ephemeral"}}],l=[];t?.styleguide&&l.push(`## Brand Style Guide
|
|
1482
1580
|
${t.styleguide}`),t?.themeContext&&l.push(`## Product Context
|
|
1483
|
-
${t.themeContext}`);let c=
|
|
1581
|
+
${t.themeContext}`);let c=Jr(t?.brandKit);return c?l.push(c):t?.styleguide||l.push(`## No Brand Provided \u2014 Be Creative
|
|
1484
1582
|
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
1583
|
|
|
1486
|
-
`)}),a}function
|
|
1584
|
+
`)}),a}function Md(e,t,n,s){let o=[],i=Object.entries(t).map(([a,l])=>` ${a}: ${l}`).join(`
|
|
1487
1585
|
`);o.push(`You are the Email Module Planner for vibeSpot, a HubSpot email template builder.
|
|
1488
1586
|
|
|
1489
1587
|
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.
|
|
@@ -1542,7 +1640,7 @@ List all module names in display order (top to bottom)
|
|
|
1542
1640
|
One sentence describing the email's purpose and flow`),(!s||s.includes("content"))&&o.push(`
|
|
1543
1641
|
|
|
1544
1642
|
## Email Content Guide
|
|
1545
|
-
${
|
|
1643
|
+
${py()}`),n?.brandvoice&&o.push(`
|
|
1546
1644
|
|
|
1547
1645
|
## Brand Voice
|
|
1548
1646
|
${n.brandvoice}`),n?.themeContext&&o.push(`
|
|
@@ -1551,7 +1649,7 @@ ${n.brandvoice}`),n?.themeContext&&o.push(`
|
|
|
1551
1649
|
${n.themeContext}`),n?.humanify!==!1&&s?.includes("humanify")&&o.push(`
|
|
1552
1650
|
|
|
1553
1651
|
## Anti-AI Copy Rules
|
|
1554
|
-
${
|
|
1652
|
+
${gy()}`);let r=Jr(n?.brandKit);return r&&o.push(r),o.join("")}function Id(){return`### Email Design Philosophy
|
|
1555
1653
|
Design for the inbox, not the browser. Email templates must look clean and professional in Gmail, Outlook, Apple Mail, and Yahoo Mail simultaneously.
|
|
1556
1654
|
|
|
1557
1655
|
### Color Strategy
|
|
@@ -1584,7 +1682,7 @@ Design for the inbox, not the browser. Email templates must look clean and profe
|
|
|
1584
1682
|
- Hero images: 600px wide, 2:1 to 3:1 aspect ratio
|
|
1585
1683
|
- Always include alt text (images blocked by default in many clients)
|
|
1586
1684
|
- Use display:block to prevent gaps in Outlook
|
|
1587
|
-
- Product images: consistent sizing within a row`}function
|
|
1685
|
+
- Product images: consistent sizing within a row`}function py(){return`### Email Types and Structure
|
|
1588
1686
|
|
|
1589
1687
|
**Welcome / Onboarding Email**
|
|
1590
1688
|
- Warm greeting with first-name personalization
|
|
@@ -1630,7 +1728,7 @@ Design for the inbox, not the browser. Email templates must look clean and profe
|
|
|
1630
1728
|
- One idea per paragraph, 2-3 sentences max
|
|
1631
1729
|
- Use "you" more than "we"
|
|
1632
1730
|
- Specific > vague: "saves 3 hours/week" beats "saves time"
|
|
1633
|
-
- CTA copy = verb + benefit: "Start Your Trial", "See the Results"`}function
|
|
1731
|
+
- CTA copy = verb + benefit: "Start Your Trial", "See the Results"`}function gy(){return`### Email-Specific Anti-AI Rules
|
|
1634
1732
|
- No em dashes (\u2014) in email copy. Period.
|
|
1635
1733
|
- No "I hope this email finds you well"
|
|
1636
1734
|
- No "In today's fast-paced world"
|
|
@@ -1639,159 +1737,61 @@ Design for the inbox, not the browser. Email templates must look clean and profe
|
|
|
1639
1737
|
- One exclamation mark per email maximum
|
|
1640
1738
|
- Avoid tricolon structures ("Fast, reliable, secure")
|
|
1641
1739
|
- 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
|
|
1740
|
+
- Every sentence must earn its place \u2014 if removing it doesn't hurt, remove it`}var Hr,Pd=N(()=>{"use strict";y();Hr={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 Nd(e,t,n,s,o,i,r){let a=t.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?zo(n.themeName,n.brandAssets):Vo(n.themeName,n.brandAssets),d=l?a?Br(n.themeName,n.brandAssets):jr(n.themeName,n.brandAssets):void 0,u=`## User Request
|
|
1643
1741
|
${e}`;n.modules.length>0&&t.designSystemChanges&&(u+=`
|
|
1644
1742
|
|
|
1645
1743
|
## Current Shared CSS (update this)
|
|
1646
1744
|
\`\`\`css
|
|
1647
1745
|
${n.sharedCss}
|
|
1648
|
-
\`\`\``);let m=
|
|
1649
|
-
${Object.entries(S).map(([
|
|
1746
|
+
\`\`\``);let m=Ln(s),g=a?Hr:Lr,h=await te("design-system",()=>Pe(s,o,i,{systemPrompt:c,systemBlocks:d,messages:[{role:"user",content:u}],structuredOutput:{schema:g,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 {
|
|
1747
|
+
${Object.entries(S).map(([L,H])=>` ${L.startsWith("--")?L:`--${L}`}: ${H};`).join(`
|
|
1650
1748
|
`)}
|
|
1651
1749
|
}
|
|
1652
1750
|
|
|
1653
|
-
${b}`));let
|
|
1654
|
-
`)}),r({type:"design_system_ready",sharedCss:b,sharedJs:f.sharedJs||"",aesthetic:f.aesthetic||""}),{...f,sharedCss:b}}async function
|
|
1751
|
+
${b}`));let v=Object.keys(S||{}).length,w=a?[`Email design tokens: ${f.aesthetic||"created"} | ${v} tokens`]:[`Design system: ${f.aesthetic||"created"} | ${v} variables, ${b.length} chars CSS`];return r({type:"agent_decision",step:"designing",decision:w.join(`
|
|
1752
|
+
`)}),r({type:"design_system_ready",sharedCss:b,sharedJs:f.sharedJs||"",aesthetic:f.aesthetic||""}),{...f,sharedCss:b}}async function Rd(e,t,n,s,o,i,r){let a=t.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?zo(n.themeName,n.brandAssets):Vo(n.themeName,n.brandAssets),d=l?a?Br(n.themeName,n.brandAssets):jr(n.themeName,n.brandAssets):void 0,u=`## User Request
|
|
1655
1753
|
${e}`;n.modules.length>0&&t.designSystemChanges&&(u+=`
|
|
1656
1754
|
|
|
1657
1755
|
## Current Shared CSS (update this)
|
|
1658
1756
|
\`\`\`css
|
|
1659
1757
|
${n.sharedCss}
|
|
1660
|
-
\`\`\``);let m=
|
|
1661
|
-
${Object.entries(S).map(([
|
|
1758
|
+
\`\`\``);let m=Ln(s),g=a?Hr:Lr,h=await te("design-system",()=>Pe(s,o,i,{systemPrompt:c,systemBlocks:d,messages:[{role:"user",content:u}],structuredOutput:{schema:g,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 {
|
|
1759
|
+
${Object.entries(S).map(([$,F])=>` ${$.startsWith("--")?$:`--${$}`}: ${F};`).join(`
|
|
1662
1760
|
`)}
|
|
1663
1761
|
}
|
|
1664
1762
|
|
|
1665
|
-
${b}`));let
|
|
1666
|
-
`)}),r({type:"design_system_ready",sharedCss:b,sharedJs:f.sharedJs||"",aesthetic:f.aesthetic||""}),r({type:"agent_step",step:"designing",label:"Planning modules..."});let
|
|
1667
|
-
${e}`;if(t.newModules.length>0&&(
|
|
1763
|
+
${b}`));let v=[],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,M=[...new Set((e.match(w)||[]).map(T=>T.trim()))];if(M.length>0){let T=M.filter(F=>b.toLowerCase().includes(F.toLowerCase())),$=M.filter(F=>!T.includes(F));$.length>0&&v.push(`Note: ${$.join(", ")} not available \u2014 HubSpot modules use system font stacks (no external font imports allowed)`)}let L=Object.keys(S||{}).length,H=a?[`Email design tokens: ${f.aesthetic||"created"} | ${L} tokens`]:[`Design system: ${f.aesthetic||"created"} | ${L} variables, ${b.length} chars CSS`,...v];r({type:"agent_decision",step:"designing",decision:H.join(`
|
|
1764
|
+
`)}),r({type:"design_system_ready",sharedCss:b,sharedJs:f.sharedJs||"",aesthetic:f.aesthetic||""}),r({type:"agent_step",step:"designing",label:"Planning modules..."});let B=a?Md(n.themeName,S||{},n.brandAssets,t.guidesNeeded):Td(n.themeName,b,n.brandAssets,t.guidesNeeded),K=`## User Request
|
|
1765
|
+
${e}`;if(t.newModules.length>0&&(K+=`
|
|
1668
1766
|
|
|
1669
1767
|
## Planned Modules
|
|
1670
|
-
${t.newModules.map((
|
|
1671
|
-
`)}`),n.modules.length>0){let
|
|
1768
|
+
${t.newModules.map((T,$)=>`${$+1}. **${T.name}** \u2014 ${T.description}`).join(`
|
|
1769
|
+
`)}`),n.modules.length>0){let T=new Set(t.affectedModules),$=n.modules.filter(re=>T.has(re.moduleName)),F=n.modules.filter(re=>!T.has(re.moduleName));$.length>0&&(K+=`
|
|
1672
1770
|
|
|
1673
1771
|
## Existing Modules to Re-plan (PRESERVE THESE EXACT NAMES)
|
|
1674
1772
|
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.
|
|
1675
|
-
|
|
1676
|
-
`)),
|
|
1773
|
+
`+$.map(re=>`- \`${re.moduleName}\``).join(`
|
|
1774
|
+
`)),F.length>0&&(K+=`
|
|
1677
1775
|
|
|
1678
1776
|
## Existing Modules to Keep (do not re-plan)
|
|
1679
1777
|
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).
|
|
1680
|
-
`+
|
|
1681
|
-
`))}let
|
|
1682
|
-
`)}function
|
|
1683
|
-
`),a=n.map(
|
|
1684
|
-
`),l=[]
|
|
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: "${e}"
|
|
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
|
-
${t.map(c=>` - "${c.label}" \u2192 href="/${c.slug}"`).join(`
|
|
1709
|
-
`)}
|
|
1710
|
-
- Active page link uses CSS class "${e}-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(`
|
|
1778
|
+
`+F.map(re=>`- \`${re.moduleName}\``).join(`
|
|
1779
|
+
`))}let X=await te("module-planner",()=>Pe(s,o,i,{systemPrompt:B,messages:[{role:"user",content:K}],structuredOutput:{schema:Ad,name:"module_plan"},maxTokens:8e3,...m>0?{thinkingBudgetTokens:m}:{}})),O,k={modules:t.newModules.map(T=>({name:T.name,description:T.description,contentBrief:"Generate appropriate content",layoutNotes:"Use responsive layout"})),moduleOrder:t.newModules.map(T=>T.name),narrative:"Page generated from user request"};if(X.type!=="structured")E.warn("page-architect","Module planner: did not get structured output, using fallback"),O=k;else{let T=X.data;Array.isArray(T?.modules)&&T.modules.length>0?(O=T,O.moduleOrder=O.moduleOrder||O.modules.map($=>$.name),O.narrative=O.narrative||"Page generated from user request"):(E.warn("page-architect","Module planner: structured output missing 'modules' array, using fallback",{keys:T?Object.keys(T):[]}),O=k),E.info("page-architect","Module plan",{moduleCount:O.modules.length})}return r({type:"agent_decision",step:"designing",decision:`Page: ${O.narrative} | ${O.modules.length} modules planned`}),{designSystem:{cssVariables:f.cssVariables||{},sharedCss:b,sharedJs:f.sharedJs},modules:O.modules,moduleOrder:O.moduleOrder,narrative:O.narrative}}var Od=N(()=>{"use strict";y();ct();Ed();Pd();le();Be()});function fy(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(`
|
|
1780
|
+
`)}function Fd(e,t,n,s,o){let i=fy(s),r=t.map(d=>`- **${d.label}** (${d.pageType}, slug: "${d.slug}"): ${d.purpose}`).join(`
|
|
1781
|
+
`),a=n.map(d=>`- **${d}**`).join(`
|
|
1782
|
+
`),l=[],c=t.map(d=>` - "${d.label}" \u2192 href="/${d.slug}"`).join(`
|
|
1783
|
+
`);return l.push(Rt("site-module-planner",{themeName:e,siteMap:r,sharedList:a,cssSummary:i,navHrefs:c,sharedModuleNamesCsv:n.join(", ")})),o?.brandvoice&&l.push(`
|
|
1740
1784
|
|
|
1741
1785
|
## Brand Voice
|
|
1742
1786
|
${o.brandvoice}`),o?.themeContext&&l.push(`
|
|
1743
1787
|
|
|
1744
1788
|
## Product Context
|
|
1745
|
-
${o.themeContext}`),l.join("")}var
|
|
1789
|
+
${o.themeContext}`),l.join("")}var Dd,jd=N(()=>{"use strict";y();As();Dd={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 Jd(e,t,n,s,o,i,r,a){a({type:"agent_step",step:"planning_site",label:`Planning modules for ${t.pages?.length||0} pages...`});let l=t.pages||[],c=t.sharedModules||["site-header","site-footer"],d=Fd(n.themeName,l,c,s,n.brandAssets),u=`## User Request
|
|
1746
1790
|
${e}
|
|
1747
1791
|
|
|
1748
1792
|
## Site Map
|
|
1749
|
-
${l.map(
|
|
1750
|
-
`)}`,m=
|
|
1751
|
-
|
|
1752
|
-
Your job: generate ONE HubSpot CMS module. You receive a module specification and must produce the complete module code.
|
|
1753
|
-
|
|
1754
|
-
## Theme: "${e}"
|
|
1755
|
-
|
|
1756
|
-
## Output Rules \u2014 CRITICAL
|
|
1757
|
-
You produce a single module with these fields:
|
|
1758
|
-
- **moduleName**: Exact module name (title-case, e.g., "Hero Banner")
|
|
1759
|
-
- **fieldsJson**: Valid JSON string \u2014 the module's fields.json content
|
|
1760
|
-
- **metaJson**: Valid JSON string \u2014 must include host_template_types: ["PAGE"], is_available_for_new_content: true
|
|
1761
|
-
- **moduleHtml**: HubL template ({{ module.field_name }} syntax)
|
|
1762
|
-
- **moduleCss**: Vanilla CSS (no Tailwind, no Sass, no CDN imports)
|
|
1763
|
-
- **moduleJs**: Optional vanilla JS wrapped in IIFE, or null
|
|
1764
|
-
|
|
1765
|
-
## CSS Rules
|
|
1766
|
-
- All CSS classes must use prefix "${e}-"
|
|
1767
|
-
- Use BEM naming: ${e}-moduleName__element--modifier
|
|
1768
|
-
- Reference the theme's CSS custom properties (shown below)
|
|
1769
|
-
- No CDN imports (@import url(), external <link> tags)
|
|
1770
|
-
- Use system font stacks \u2014 no Google Fonts
|
|
1771
|
-
|
|
1772
|
-
## Field Rules
|
|
1773
|
-
- Use "type": "text" (NEVER "textarea" \u2014 it's deprecated)
|
|
1774
|
-
- NEVER use "name": "name" (reserved) \u2014 use "item_name" instead
|
|
1775
|
-
- NEVER use "name": "label" (reserved) \u2014 use "section_label" instead
|
|
1776
|
-
- NEVER put literal \\n in field defaults
|
|
1777
|
-
- Wrap style fields in a "styles" group with "tab": "STYLE"
|
|
1778
|
-
- Color fields: type "color", default { "color": "#hex", "opacity": 100 }
|
|
1779
|
-
- Link fields: type "link", default { "url": { "href": "#", "type": "EXTERNAL" }, "open_in_new_tab": false, "no_follow": false }
|
|
1780
|
-
- Image fields: type "image", default { "src": "https://placehold.co/800x600/1a1a2e/ffffff?text=Replace+in+HubSpot", "alt": "Placeholder", "width": 800, "height": 600 }
|
|
1781
|
-
- For repeater groups, use "occurrence": { "min": 0, "max": 100 }
|
|
1782
|
-
|
|
1783
|
-
## Images & Assets
|
|
1784
|
-
- Use get_asset_url("${e}/assets/filename.ext") for uploaded assets
|
|
1785
|
-
- For placeholder images, use image fields with placehold.co defaults
|
|
1786
|
-
- Size placeholders appropriately (hero: 1920x800, cards: 600x400, icons: 200x200)
|
|
1787
|
-
|
|
1788
|
-
## Navigation & Anchors
|
|
1789
|
-
- Add id attribute on module root element: id="module-name-lowercased"
|
|
1790
|
-
- For nav modules, use anchor links (#features, #pricing, etc.)
|
|
1791
|
-
- Include smooth scroll behavior in nav click handlers
|
|
1792
|
-
|
|
1793
|
-
## metaJson Template
|
|
1794
|
-
{ "host_template_types": ["PAGE"], "is_available_for_new_content": true }`),t&&o.push(`
|
|
1793
|
+
${l.map(v=>`- ${v.label} (${v.slug}): ${v.purpose}`).join(`
|
|
1794
|
+
`)}`,m=Ln(o),g=await te("site-module-planner",()=>Pe(o,i,r,{systemPrompt:d,messages:[{role:"user",content:u}],structuredOutput:{schema:Dd,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"),Ld(t,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):[]}),Ld(t,c,s);let f=h.sharedModules.map(v=>({name:v.name,description:v.description,contentBrief:v.contentBrief,layoutNotes:v.layoutNotes})),b=h.pages.map(v=>({pageId:v.pageId,modules:(v.modules||[]).map(w=>({name:w.name,description:w.description,contentBrief:w.contentBrief,layoutNotes:w.layoutNotes})),moduleOrder:v.moduleOrder||[]})),S=f.length+b.reduce((v,w)=>v+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(v=>{let w=l.find(M=>M.id===v.pageId);return{pageId:v.pageId,label:w?.label||v.pageId,moduleCount:v.modules.length}}),sharedModuleCount:f.length}),{designSystem:{cssVariables:{},sharedCss:s},pages:b,sharedModules:f,narrative:h.narrative||"Multi-page site generated from user request"}}function Ld(e,t,n){let s=e.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:t.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 Bd=N(()=>{"use strict";y();ct();jd();le();Be()});function Yo(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 Ur=N(()=>{"use strict";y()});function _s(e,t,n,s){let o=[];return o.push(Rt("module-developer",{themeName:e})),t&&o.push(`
|
|
1795
1795
|
|
|
1796
1796
|
## Theme Shared CSS (use these custom properties)
|
|
1797
1797
|
\`\`\`css
|
|
@@ -1799,29 +1799,29 @@ ${t}
|
|
|
1799
1799
|
\`\`\``),(!n||n.includes("hubspot_rules"))&&o.push(`
|
|
1800
1800
|
|
|
1801
1801
|
## HubSpot CMS Rules
|
|
1802
|
-
${
|
|
1802
|
+
${Je()}`),(!n||n.includes("conversion"))&&o.push(`
|
|
1803
1803
|
|
|
1804
1804
|
## Conversion Guide
|
|
1805
|
-
${
|
|
1805
|
+
${ye()}`),s?.themeContext&&o.push(`
|
|
1806
1806
|
|
|
1807
1807
|
## Product Context
|
|
1808
1808
|
${s.themeContext}`),s?.humanify!==!1&&n?.includes("humanify")&&o.push(`
|
|
1809
1809
|
|
|
1810
1810
|
## Anti-AI Copy Rules
|
|
1811
|
-
${
|
|
1811
|
+
${Hd()}`),o.join("")}function qo(e,t,n,s){let o=[],i=_s(e,"",[],s?{...s,humanify:!1}:void 0);t&&(i+=`
|
|
1812
1812
|
|
|
1813
1813
|
## Theme Shared CSS (use these custom properties)
|
|
1814
1814
|
\`\`\`css
|
|
1815
1815
|
${t}
|
|
1816
1816
|
\`\`\``),o.push({type:"text",text:i});let r=[];(!n||n.includes("hubspot_rules"))&&r.push(`## HubSpot CMS Rules
|
|
1817
|
-
${
|
|
1818
|
-
${
|
|
1817
|
+
${Je()}`),(!n||n.includes("conversion"))&&r.push(`## Conversion Guide
|
|
1818
|
+
${ye()}`),r.length>0&&o.push({type:"text",text:r.join(`
|
|
1819
1819
|
|
|
1820
1820
|
`),cache_control:{type:"ephemeral"}});let a=[];return s?.themeContext&&a.push(`## Product Context
|
|
1821
1821
|
${s.themeContext}`),s?.humanify!==!1&&n?.includes("humanify")&&a.push(`## Anti-AI Copy Rules
|
|
1822
|
-
${
|
|
1822
|
+
${Hd()}`),a.length>0&&o.push({type:"text",text:a.join(`
|
|
1823
1823
|
|
|
1824
|
-
`)}),o}function
|
|
1824
|
+
`)}),o}function Hd(){return`### Banned Punctuation
|
|
1825
1825
|
- **Em dashes (\u2014)**: NEVER use. Replace with periods, commas, or parentheses. Hyphens for compounds fine.
|
|
1826
1826
|
- **Semicolons**: Use periods instead in marketing copy.
|
|
1827
1827
|
- **Exclamation marks**: One per page max. Zero ideal for B2B.
|
|
@@ -1860,7 +1860,7 @@ Never end with: "The future of [X] is here", "Your journey starts here", "Join t
|
|
|
1860
1860
|
- Keep slightly imperfect (fragments OK, mild hedging like "honestly didn't think")
|
|
1861
1861
|
- Full names, specific roles (not "John D., CEO")
|
|
1862
1862
|
- Never start with "This product is..." \u2014 start with the person's situation
|
|
1863
|
-
- Vary length and voice across testimonials`}function
|
|
1863
|
+
- Vary length and voice across testimonials`}function Ud(e,t,n){let s=[];return s.push(`## User Request
|
|
1864
1864
|
${e}`),s.push(`
|
|
1865
1865
|
|
|
1866
1866
|
## Module Specification
|
|
@@ -1887,7 +1887,7 @@ ${n.moduleCss}
|
|
|
1887
1887
|
**module.js:**
|
|
1888
1888
|
\`\`\`js
|
|
1889
1889
|
${n.moduleJs}
|
|
1890
|
-
\`\`\``)),s.join("")}var
|
|
1890
|
+
\`\`\``)),s.join("")}var $s,Gr=N(()=>{"use strict";y();Ke();As();$s={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 Wr(e,t){let n=[];if(n.push(`You are an Email Module Developer for vibeSpot, a HubSpot CMS builder.
|
|
1891
1891
|
|
|
1892
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
1893
|
|
|
@@ -2045,17 +2045,17 @@ Modules that serve as email footers MUST include:
|
|
|
2045
2045
|
${t.themeContext}`),t?.humanify!==!1&&n.push(`
|
|
2046
2046
|
|
|
2047
2047
|
## Anti-AI Copy Rules
|
|
2048
|
-
${
|
|
2048
|
+
${Wd()}`),t?.brandKit){let s=[];t.brandKit.colors&&(t.brandKit.colors.primary&&s.push(`- Primary color: ${t.brandKit.colors.primary}`),t.brandKit.colors.secondary&&s.push(`- Secondary color: ${t.brandKit.colors.secondary}`),t.brandKit.colors.accent&&s.push(`- Accent color: ${t.brandKit.colors.accent}`)),t.brandKit.fonts&&(t.brandKit.fonts.heading&&s.push(`- Heading font: ${t.brandKit.fonts.heading}`),t.brandKit.fonts.body&&s.push(`- Body font: ${t.brandKit.fonts.body}`)),t.brandKit.logoUrl&&s.push(`- Logo URL: ${t.brandKit.logoUrl}`),s.length>0&&n.push(`
|
|
2049
2049
|
|
|
2050
2050
|
## Brand Kit \u2014 MANDATORY Design Constraints
|
|
2051
2051
|
The following brand identity values MUST be used. Do NOT substitute or override them:
|
|
2052
2052
|
${s.join(`
|
|
2053
|
-
`)}`)}return n.join("")}function
|
|
2053
|
+
`)}`)}return n.join("")}function Gd(e,t){let n=[],s=Wr(e,{...t,humanify:!1});n.push({type:"text",text:s});let o;try{o=gl()}catch{o=""}o&&n.push({type:"text",text:`## Email Template Rules Reference
|
|
2054
2054
|
${o}`,cache_control:{type:"ephemeral"}});let i=[];return t?.themeContext&&i.push(`## Product Context
|
|
2055
2055
|
${t.themeContext}`),t?.humanify!==!1&&i.push(`## Anti-AI Copy Rules
|
|
2056
|
-
${
|
|
2056
|
+
${Wd()}`),i.length>0&&n.push({type:"text",text:i.join(`
|
|
2057
2057
|
|
|
2058
|
-
`)}),n}function
|
|
2058
|
+
`)}),n}function Wd(){return`### Banned Punctuation
|
|
2059
2059
|
- **Em dashes (\u2014)**: NEVER use. Replace with periods, commas, or parentheses.
|
|
2060
2060
|
- **Semicolons**: Use periods instead.
|
|
2061
2061
|
- **Exclamation marks**: One per email max. Zero ideal for B2B.
|
|
@@ -2074,7 +2074,7 @@ Never start with: "In today's", "In an era", "Whether you're", "Imagine a world"
|
|
|
2074
2074
|
- Be concrete: "42 minutes" not "fast", "\u20AC29/month" not "affordable"
|
|
2075
2075
|
- Use plain words: use > utilize, start > commence, help > facilitate
|
|
2076
2076
|
- Front-load the benefit in the first 5 words
|
|
2077
|
-
- Email subject lines: specific, benefit-first, under 50 chars`}function
|
|
2077
|
+
- Email subject lines: specific, benefit-first, under 50 chars`}function Kd(e,t,n){let s=[];return s.push(`## User Request
|
|
2078
2078
|
${e}`),s.push(`
|
|
2079
2079
|
|
|
2080
2080
|
## Email Module Specification
|
|
@@ -2094,7 +2094,7 @@ ${n.fieldsJson}
|
|
|
2094
2094
|
**module.html:**
|
|
2095
2095
|
\`\`\`html
|
|
2096
2096
|
${n.moduleHtml}
|
|
2097
|
-
\`\`\``),s.join("")}var
|
|
2097
|
+
\`\`\``),s.join("")}var Vd,zd=N(()=>{"use strict";y();Ke();Vd={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 Kr(e,t,n,s){let o=[];o.push(`You are a Blog Module Developer for vibeSpot, a HubSpot CMS builder.
|
|
2098
2098
|
|
|
2099
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
2100
|
|
|
@@ -2279,22 +2279,22 @@ The blog post body module wraps \`{{ content.post_body }}\` with reading-optimiz
|
|
|
2279
2279
|
${s.themeContext}`),s?.humanify!==!1&&o.push(`
|
|
2280
2280
|
|
|
2281
2281
|
## Anti-AI Copy Rules
|
|
2282
|
-
${
|
|
2283
|
-
${r}`)}catch{}if(n?.includes("hubspot_rules"))try{let r=
|
|
2282
|
+
${qd()}`);let i=[];if(n?.includes("conversion"))try{let r=ye();r&&i.push(`## Conversion Guide
|
|
2283
|
+
${r}`)}catch{}if(n?.includes("hubspot_rules"))try{let r=Je();r&&i.push(`## HubSpot Rules
|
|
2284
2284
|
${r}`)}catch{}return i.length>0&&o.push(`
|
|
2285
2285
|
|
|
2286
2286
|
${i.join(`
|
|
2287
2287
|
|
|
2288
|
-
`)}`),o.join("")}function
|
|
2289
|
-
${r}`,cache_control:{type:"ephemeral"}});let a=[];if(n?.includes("conversion"))try{let c=
|
|
2290
|
-
${c}`)}catch{}if(n?.includes("hubspot_rules"))try{let c=
|
|
2288
|
+
`)}`),o.join("")}function Yd(e,t,n,s){let o=[],i=Kr(e,t,void 0,{...s,humanify:!1});o.push({type:"text",text:i});let r;try{r=fl()}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=ye();c&&a.push(`## Conversion Guide
|
|
2290
|
+
${c}`)}catch{}if(n?.includes("hubspot_rules"))try{let c=Je();c&&a.push(`## HubSpot Rules
|
|
2291
2291
|
${c}`)}catch{}a.length>0&&o.push({type:"text",text:a.join(`
|
|
2292
2292
|
|
|
2293
2293
|
`),cache_control:{type:"ephemeral"}});let l=[];return s?.themeContext&&l.push(`## Product Context
|
|
2294
2294
|
${s.themeContext}`),s?.humanify!==!1&&l.push(`## Anti-AI Copy Rules
|
|
2295
|
-
${
|
|
2295
|
+
${qd()}`),l.length>0&&o.push({type:"text",text:l.join(`
|
|
2296
2296
|
|
|
2297
|
-
`)}),o}function
|
|
2297
|
+
`)}),o}function qd(){return`### Banned Punctuation
|
|
2298
2298
|
- **Em dashes (\u2014)**: NEVER use. Replace with periods, commas, or parentheses.
|
|
2299
2299
|
- **Semicolons**: Use periods instead.
|
|
2300
2300
|
- **Exclamation marks**: Maximum one per page. Zero ideal for B2B.
|
|
@@ -2313,7 +2313,7 @@ Never start with: "In today's", "In an era", "Whether you're", "Imagine a world"
|
|
|
2313
2313
|
- Be concrete: "42 minutes" not "fast", "\u20AC29/month" not "affordable"
|
|
2314
2314
|
- Use plain words: use > utilize, start > commence, help > facilitate
|
|
2315
2315
|
- Front-load the benefit in the first 5 words
|
|
2316
|
-
- Blog headlines: specific, benefit-first, no clickbait`}function
|
|
2316
|
+
- Blog headlines: specific, benefit-first, no clickbait`}function Xd(e,t,n){let s=[];return s.push(`## User Request
|
|
2317
2317
|
${e}`),s.push(`
|
|
2318
2318
|
|
|
2319
2319
|
## Blog Module Specification
|
|
@@ -2338,17 +2338,17 @@ ${n.moduleHtml}
|
|
|
2338
2338
|
**module.css:**
|
|
2339
2339
|
\`\`\`css
|
|
2340
2340
|
${n.moduleCss}
|
|
2341
|
-
\`\`\``),s.join("")}var
|
|
2341
|
+
\`\`\``),s.join("")}var Zd,Qd=N(()=>{"use strict";y();Ke();Ke();Zd={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 Es(e,t,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 ${t.length} ${h}${t.length===1?"":"s"}...`});let f=o==="anthropic-api"||o==="claude-oauth",b=m?Wr(s,d):g?Kr(s,n,c,d):_s(s,n,c,d),S=f?m?Gd(s,d):g?Yd(s,n,c,d):qo(s,n,c,d):void 0,v=Yo(a),w=t.length,M=m?Vd:g?Zd:$s,L=t.map((B,K)=>v(async()=>{l({type:"module_progress",module:B.name,status:"generating",current:K+1,total:w});let X="";for(let O=0;O<2;O++)try{O>0&&(E.warn("module-developer",`${B.name}: retrying after failure (attempt ${O+1})`),l({type:"module_progress",module:B.name,status:"retrying",current:K+1,total:w}));let k=await eu(e,B,b,o,i,r,0,S,m,M,g);return l({type:"module_progress",module:B.name,status:"complete",current:K+1,total:w,moduleFiles:k}),{moduleName:B.name,module:k}}catch(k){X=k instanceof Error?k.message:typeof k=="object"&&k!==null?JSON.stringify(k):String(k),E.error("module-developer",`Failed: ${B.name} (attempt ${O+1})`,{error:X})}return l({type:"module_progress",module:B.name,status:"failed",current:K+1,total:w}),{moduleName:B.name,error:X}}));return(await Promise.allSettled(L)).map(B=>B.status==="fulfilled"?B.value:{moduleName:"unknown",error:B.reason instanceof Error?B.reason.message:String(B.reason)})}async function eu(e,t,n,s,o,i,r=0,a,l=!1,c=$s,d=!1){let u=l?Kd(e,t,t.existingCode):d?Xd(e,t,t.existingCode):Ud(e,t,t.existingCode),m=await Pe(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",`${t.name}: no structured output, retry ${r+1}`),eu(e,t,n,s,o,i,r+1,a,l,c,d);throw new Error(`Module "${t.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:t.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 tu=N(()=>{"use strict";y();ct();Ur();Gr();zd();Qd();le()});function an(e,t,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..."}),e.map(a=>{let l=[],c={...a};c.fieldsJson=nu(c.fieldsJson,c.moduleName,"fieldsJson",l,i),c.metaJson=nu(c.metaJson,c.moduleName,"metaJson",l,i,r);let d={};c.fieldsJson=yy(c.fieldsJson,c.moduleName,l,d),c.moduleHtml=by(c.moduleHtml,d),c.fieldsJson=Sy(c.fieldsJson,c.moduleName,l),i?c=Ey(c,l):(c.moduleCss=vy(c.moduleCss,c.moduleName,"moduleCss",l),c.moduleCss=wy(c.moduleCss,c.moduleName,t,l),c.moduleHtml=Cy(c.moduleHtml,c.moduleName,t,l),r&&(c=My(c,l))),c.moduleHtml=Ty(c.moduleHtml,c.moduleName,l),c.metaJson=Ay(c.metaJson,c.moduleName,l,i,r),o&&$y(c,o,l);let u=l.every(m=>m.autoFixed);return l.length>0&&E.info("validator",`${c.moduleName}: ${l.length} issues`,{autoFixed:l.filter(m=>m.autoFixed).length,unfixed:l.filter(m=>!m.autoFixed).length}),{module:c,issues:l,valid:u}})}function nu(e,t,n,s,o=!1,i=!1){return!e||e.trim()===""?(s.push({module:t,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}):e):xt(e)===null?(s.push({module:t,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})):e}function yy(e,t,n,s){let o=e;for(let[i,r]of hy)new RegExp(`"name"\\s*:\\s*"${i}"`,"g").test(o)&&(n.push({module:t,field:"fieldsJson",message:`"${i}" is a reserved field name \u2192 renamed to "${r}"`,autoFixed:!0}),o=o.replace(new RegExp(`"name"\\s*:\\s*"${i}"`,"g"),`"name": "${r}"`),s[i]=r);return o}function by(e,t){let n=e;for(let[s,o]of Object.entries(t))n=n.replace(new RegExp(`module\\.${s}\\b`,"g"),`module.${o}`);return n}function Sy(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 vy(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 su(e){return xy.has(e)||e.startsWith("body-wrapper")||e.startsWith("dnd-")||e.startsWith("row-")||e.startsWith("hs-")||e.startsWith("hs_")}function wy(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)&&!su(c)&&r.add(c)}if(r.size<=3)return e;let l=e;for(let c of r){let d=new RegExp(`\\.${ky(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 Cy(e,t,n,s){if(!e)return e;let o=n+"-",i=/class="([^"]*)"/g,r=!1,a=e.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)&&!su(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:t,field:"moduleHtml",message:`HTML class references auto-prefixed with "${o}"`,autoFixed:!0}),a}function ky(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Ty(e,t,n){if(!e)return e;let s=e,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:t,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:t,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(`
|
|
2342
2342
|
`);s=`${s}
|
|
2343
|
-
${f}`,n.push({module:t,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:t,field:"moduleHtml",message:"Replaced now() with local_dt (now() is not valid HubL)",autoFixed:!0})),s}function
|
|
2344
|
-
`);r({type:"agent_decision",step:"quality_check",decision:`${
|
|
2345
|
-
${
|
|
2346
|
-
`);for(let
|
|
2343
|
+
${f}`,n.push({module:t,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:t,field:"moduleHtml",message:"Replaced now() with local_dt (now() is not valid HubL)",autoFixed:!0})),s}function Ay(e,t,n,s=!1,o=!1){let i=xt(e);if(!i||typeof i!="object")return e;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:t,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:t,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:t,field:"metaJson",message:"Added missing meta.json required fields",autoFixed:!0}),JSON.stringify(r,null,2)):e}function ou(e,t){let n=[],s=new Set(t.map(o=>`/${o}`));for(let o of e){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: ${t.map(c=>"/"+c).join(", ")})`,autoFixed:!1})}return n}function $y(e,t,n){let s=new Set;if(t.colors?.primary&&s.add(t.colors.primary.toLowerCase()),t.colors?.secondary&&s.add(t.colors.secondary.toLowerCase()),t.colors?.accent&&s.add(t.colors.accent.toLowerCase()),s.size===0&&!t.fonts?.heading&&!t.fonts?.body)return;let o=(e.moduleHtml||"")+(e.moduleCss||"");if(s.size>0){let i=new Set;for(let a of o.matchAll(_y))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:e.moduleName,field:"moduleHtml",message:`Off-brand color ${a} (brand colors: ${[...s].join(", ")})`,autoFixed:!1});break}}if(t.fonts?.heading||t.fonts?.body){let i=[];t.fonts.heading&&i.push(t.fonts.heading.toLowerCase()),t.fonts.body&&i.push(t.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:e.moduleName,field:"moduleHtml",message:`Off-brand font "${a[1].trim()}" (brand fonts: ${i.join(", ")})`,autoFixed:!1});break}}}}function Ey(e,t){let n={...e},s=n.moduleHtml;n.moduleCss&&n.moduleCss.trim()&&(t.push({module:e.moduleName,field:"moduleCss",message:"Cleared moduleCss \u2014 email modules must use inline styles only",autoFixed:!0}),n.moduleCss=""),n.moduleJs&&n.moduleJs.trim()&&(t.push({module:e.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,""),t.push({module:e.moduleName,field:"moduleHtml",message:"Removed <style> blocks \u2014 email clients strip them",autoFixed:!0})),/display\s*:\s*flex/i.test(s)&&t.push({module:e.moduleName,field:"moduleHtml",message:"Contains display:flex \u2014 not supported in email clients",autoFixed:!1}),/display\s*:\s*grid/i.test(s)&&t.push({module:e.moduleName,field:"moduleHtml",message:"Contains display:grid \u2014 not supported in email clients",autoFixed:!1}),/var\s*\(/i.test(s)&&t.push({module:e.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,""),t.push({module:e.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,""),t.push({module:e.moduleName,field:"moduleHtml",message:"Removed CDN <link> tags \u2014 external resources not supported in email",autoFixed:!0})),n.moduleHtml=s,n}function My(e,t){let n={...e},s=n.moduleHtml;return/\{\{[\s]*content\.body[\s]*\}\}/g.test(s)&&(s=s.replace(/\{\{[\s]*content\.body[\s]*\}\}/g,"{{ content.post_body }}"),t.push({module:e.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 }}"),t.push({module:e.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 }}"),t.push({module:e.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 }}"),t.push({module:e.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 }}"),t.push({module:e.moduleName,field:"moduleHtml",message:"Fixed content.image \u2192 content.featured_image",autoFixed:!0})),/\{%.*dnd_area.*%\}/g.test(s)&&t.push({module:e.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)&&t.push({module:e.moduleName,field:"moduleHtml",message:"publish_date used without |datetimeformat filter \u2014 dates may render as raw timestamps",autoFixed:!1}),n.moduleHtml=s,n}var hy,xy,_y,Vr=N(()=>{"use strict";y();Go();le();hy=[["name","item_name"],["label","section_label"],["body","body_text"]];xy=new Set(["visible","active","scroll-animate","hidden","open","closed","fade-in","fade-out","is-active","is-open","is-visible"]);_y=/#[0-9a-fA-F]{6}\b/g});import{execSync as Iy}from"child_process";async function iu(e,t,n,s,o,i,r,a){let l=Date.now(),c=i;if(Jn(n)){let k={"claude-code":"claude","gemini-cli":"gemini","codex-cli":"codex"}[n];if(k)try{Iy(`command -v ${k}`,{stdio:"ignore"})}catch{throw new Error(`CLI engine "${n}" requires "${k}" to be installed and on your PATH.`)}}let d=await wd(e,t,n,s,o,r,a);if(d.intent==="question"&&d.answer){let O=Date.now()-l;return r({type:"pipeline_complete",modulesGenerated:0,modulesUnchanged:t.modules.length,durationMs:O,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:O}}}if(d.intent==="create_site"&&d.pages&&d.pages.length>0)return Py(e,d,t,n,s,o,i,r,l);let u=null,m=t.sharedCss,g=t.sharedJs;(d.intent==="create"||d.designSystemChanges)&&(u=await Rd(e,d,t,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 O of u.modules)f.push({name:O.name,description:O.description,contentBrief:O.contentBrief,layoutNotes:O.layoutNotes});else{for(let O of d.newModules)f.push({name:O.name,description:O.description,contentBrief:"Generate appropriate content based on the user request",layoutNotes:"Use responsive layout matching the existing design system"});for(let O of d.affectedModules){let k=t.modules.find(T=>T.moduleName===O);k&&f.push({name:O,description:`Modify existing module: ${O}`,contentBrief:"Apply the user's requested changes",layoutNotes:"Preserve existing layout unless changes are requested",existingCode:k})}}let b=[],S=[];if(f.length>0){let O=await te("module-development",()=>Es(e,f,m,t.themeName,n,s,o,c,r,d.guidesNeeded,t.brandAssets,d.contentType),{metadata:{moduleCount:f.length}});for(let k of O)k.module?b.push(k.module):S.push(k.moduleName)}let v=null;if(b.length>0){v=an(b,t.themeName,r,d.contentType,t.brandAssets?.brandKit);let O=v.filter(T=>T.issues.some($=>$.field==="fieldsJson"&&$.message.includes("reset to empty"))).map(T=>T.module.moduleName);if(O.length>0){let T=O.map($=>f.find(F=>F.name===$)).filter($=>$!=null);if(T.length>0){E.info("pipeline",`Retrying ${T.length} module(s) with broken fieldsJson: ${T.map(F=>F.name).join(", ")}`),r({type:"agent_decision",step:"quality_check",decision:`Regenerating ${T.length} module(s) with invalid fields JSON...`});let $=await te("module-development-retry",()=>Es(e,T,m,t.themeName,n,s,o,c,r,d.guidesNeeded,t.brandAssets,d.contentType),{metadata:{moduleCount:T.length}});for(let F of $)if(F.module){let re=b.findIndex(_e=>_e.moduleName===F.moduleName);re>=0&&(b[re]=F.module)}v=an(b,t.themeName,r,d.contentType,t.brandAssets?.brandKit)}}b=v.map(T=>T.module);let k=v.reduce((T,$)=>T+$.issues.length,0);if(k>0){let T=v.reduce((F,re)=>F+re.issues.filter(_e=>_e.autoFixed).length,0);E.info("pipeline",`Quality check: ${k} issues, ${T} auto-fixed`);let $=v.flatMap(F=>F.issues).map(F=>`${F.autoFixed?"\u2713":"\u26A0"} ${F.module}: ${F.message}`).join(`
|
|
2344
|
+
`);r({type:"agent_decision",step:"quality_check",decision:`${k} issues found, ${T} auto-fixed
|
|
2345
|
+
${$}`})}else r({type:"agent_decision",step:"quality_check",decision:"All modules passed quality checks"})}let w=Ry(t,d,b,u,a),M=Oy(t,d,u,w);if(u?.moduleOrder?.length){let O=new Set(u.moduleOrder),k=w.filter(T=>!O.has(T.moduleName)).map(T=>T.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 L=Date.now()-l,H=b.length,B=d.unchangedModules.length,K=v?v.flatMap(O=>O.issues):[],X=Fy(d,H,B,S,L,u,K);return S.length>0?r({type:"pipeline_partial",succeeded:b.map(O=>O.moduleName),failed:S,durationMs:L}):r({type:"pipeline_complete",modulesGenerated:H,modulesUnchanged:B,durationMs:L,assistantMessage:X}),{modules:w,moduleOrder:M,sharedCss:m,sharedJs:g,assistantMessage:X,contentType:d.contentType,stats:{modulesGenerated:H,modulesUnchanged:B,modulesFailed:S.length,durationMs:L}}}async function Py(e,t,n,s,o,i,r,a,l){let c=t.pages,d=t.sharedModules||["site-header","site-footer"],u=await Nd(e,t,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 Jd(e,t,n,m,s,o,i,a);a({type:"agent_step",step:"developing",label:`Generating modules for ${c.length} pages...`});let f=[];for(let $ of h.sharedModules)f.push({...$});for(let $ of h.pages)for(let F of $.modules)f.push({name:F.name,description:F.description,contentBrief:F.contentBrief,layoutNotes:F.layoutNotes});let b=c.map($=>`- "${$.label}" \u2192 /${$.slug}`).join(`
|
|
2346
|
+
`);for(let $ of f)($.name.includes("header")||$.name.includes("nav"))&&($.layoutNotes+=`
|
|
2347
2347
|
|
|
2348
2348
|
## Site Navigation
|
|
2349
2349
|
This is a multi-page site. Include navigation links to all pages:
|
|
2350
2350
|
${b}
|
|
2351
|
-
Use relative href paths. Add CSS class "${n.themeName}-nav__link--active" on the current page's link.`);let S=await
|
|
2351
|
+
Use relative href paths. Add CSS class "${n.themeName}-nav__link--active" on the current page's link.`);let S=await te("module-development",()=>Es(e,f,m,n.themeName,s,o,i,r,a,t.guidesNeeded,n.brandAssets,t.contentType),{metadata:{moduleCount:f.length}}),v=[],w=[];for(let $ of S)$.module?v.push($.module):w.push($.moduleName);let M=v,L=[];if(v.length>0){let $=an(v,n.themeName,a,t.contentType,n.brandAssets?.brandKit),F=$.filter(z=>z.issues.some(ue=>ue.field==="fieldsJson"&&ue.message.includes("reset to empty"))).map(z=>z.module.moduleName);if(F.length>0){let z=F.map(ue=>f.find(ne=>ne.name===ue)).filter(ue=>ue!=null);if(z.length>0){E.info("pipeline",`Retrying ${z.length} module(s) with broken fieldsJson`),a({type:"agent_decision",step:"quality_check",decision:`Regenerating ${z.length} module(s) with invalid fields JSON...`});let ue=await te("module-development-retry",()=>Es(e,z,m,n.themeName,s,o,i,r,a,t.guidesNeeded,n.brandAssets,t.contentType),{metadata:{moduleCount:z.length}});for(let ne of ue)if(ne.module){let $e=v.findIndex(Bs=>Bs.moduleName===ne.moduleName);$e>=0&&(v[$e]=ne.module)}$=an(v,n.themeName,a,t.contentType,n.brandAssets?.brandKit)}}M=$.map(z=>z.module),L=$.flatMap(z=>z.issues);let re=ou(M,c.map(z=>z.slug));L.push(...re);let _e=L.length;if(_e>0){let z=L.filter(ue=>ue.autoFixed).length;a({type:"agent_decision",step:"quality_check",decision:`${_e} issues found, ${z} auto-fixed`})}else a({type:"agent_decision",step:"quality_check",decision:"All modules passed quality checks"})}let H=new Map(M.map($=>[$.moduleName,$])),B=h.sharedModules.map($=>H.get($.name)).filter($=>!!$),K=new Map(c.map($=>[$.id,$])),X=h.pages.map($=>{let F=$.modules.map(ne=>H.get(ne.name)).filter(ne=>!!ne),re=d.filter(ne=>ne.includes("header")||ne.includes("nav")),_e=d.filter(ne=>ne.includes("footer")),z=[...re,...$.moduleOrder,..._e],ue=K.get($.pageId);return{pageId:$.pageId,templateId:$.pageId,label:ue?.label||$.pageId,pageType:ue?.pageType||"website_page",modules:[...B,...F],moduleOrder:z}}),O=Date.now()-l,k=Ny(c,v.length,w,O,h.narrative,L);return w.length>0?a({type:"pipeline_partial",succeeded:v.map($=>$.moduleName),failed:w,durationMs:O}):a({type:"pipeline_complete",modulesGenerated:v.length,modulesUnchanged:0,durationMs:O,assistantMessage:k}),{modules:M,moduleOrder:M.map($=>$.moduleName),sharedCss:m,sharedJs:g||"",assistantMessage:k,stats:{modulesGenerated:v.length,modulesUnchanged:0,modulesFailed:w.length,durationMs:O},multiPage:{pages:X,sharedModules:B,sharedCss:m,sharedJs:g||"",assistantMessage:k,stats:{pagesGenerated:c.length,modulesGenerated:v.length,modulesFailed:w.length,durationMs:O}}}}function Ny(e,t,n,s,o,i){let r=Math.round(s/1e3),a=[];a.push(`Created ${e.length}-page site with ${t} modules in ${r}s.`),a.push(`
|
|
2352
2352
|
|
|
2353
2353
|
**Pages:** ${e.map(d=>d.label).join(", ")}`),o&&a.push(`
|
|
2354
2354
|
|
|
@@ -2357,17 +2357,17 @@ ${o}`),n.length>0&&a.push(`
|
|
|
2357
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
2358
|
|
|
2359
2359
|
${d.join(`
|
|
2360
|
-
`)}`)}return a.join("")}function
|
|
2360
|
+
`)}`)}return a.join("")}function Ry(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 Oy(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 Fy(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(`
|
|
2361
2361
|
|
|
2362
2362
|
${i.narrative}`),s.length>0&&l.push(`
|
|
2363
2363
|
|
|
2364
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(`
|
|
2365
2365
|
|
|
2366
2366
|
${u.join(`
|
|
2367
|
-
`)}`)}return l.join("")}var
|
|
2367
|
+
`)}`)}return l.join("")}var ru=N(()=>{"use strict";y();ct();Cd();Od();Bd();tu();Vr();le();Be();ct()});var uu={};Ge(uu,{runFigmaConversion:()=>Dy});import{basename as cu}from"path";async function Dy(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}=jy(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:g}=Jy(e.sections,e.assets,t);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=_s(t,d,["hubspot_rules","conversion"],a),b=h?qo(t,d,["hubspot_rules","conversion"],a):void 0,S=Yo(i),v=m.length,M=(await te("module-development",()=>{let T=m.map(($,F)=>{let re=e.sections[F];return S(async()=>{r({type:"module_progress",module:$.name,status:"generating",current:F+1,total:v});let _e=Uy(re,$,e.assets,t,l!==!1),z="";for(let ue=0;ue<2;ue++)try{ue>0&&(E.warn("figma-pipeline",`${$.name}: retrying (attempt ${ue+1})`),r({type:"module_progress",module:$.name,status:"retrying",current:F+1,total:v}));let ne=await Pe(n,s,o,{systemPrompt:f,systemBlocks:b,messages:[{role:"user",content:_e}],structuredOutput:{schema:$s,name:"module_output"},maxTokens:16e3});if(ne.type!=="structured")throw new Error("No structured output returned");let $e=ne.data,Bs={moduleName:$.name,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};return r({type:"module_progress",module:$.name,status:"complete",current:F+1,total:v,moduleFiles:Bs}),{moduleName:$.name,module:Bs}}catch(ne){z=ne instanceof Error?ne.message:String(ne),E.error("figma-pipeline",`Failed: ${$.name} (attempt ${ue+1}): ${z}`)}return r({type:"module_progress",module:$.name,status:"failed",current:F+1,total:v}),{moduleName:$.name,error:z}})});return Promise.allSettled(T)},{metadata:{moduleCount:v}})).map(T=>T.status==="fulfilled"?T.value:{moduleName:"unknown",error:String(T.reason)}),L=M.filter(T=>T.module).map(T=>T.module),H=M.filter(T=>T.error).map(T=>T.moduleName),K=an(L,t,r).map(T=>T.module),X=Date.now()-c,O=Math.round(X/1e3),k=`Imported ${K.length} modules from Figma design "${e.fileName}" in ${O}s.`;return H.length>0?r({type:"pipeline_partial",succeeded:K.map(T=>T.moduleName),failed:H,durationMs:X}):r({type:"pipeline_complete",modulesGenerated:K.length,modulesUnchanged:0,durationMs:X,assistantMessage:k}),{modules:K,moduleOrder:g,sharedCss:d,sharedJs:u,assistantMessage:k,stats:{modulesGenerated:K.length,modulesUnchanged:0,modulesFailed:H.length,durationMs:X}}}function Xo(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 jy(e,t){let n=[],s=t,o=[...e.colors].sort((k,T)=>T.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?Xo(a.hex).l<.4:!1;a&&n.push(` --${s}-color-bg: ${a.hex}`);let c=r[0]||(l?o.find(k=>Xo(k.hex).l>.7):o.find(k=>Xo(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,T)=>n.push(` --${s}-color-${T+1}: ${k.hex}`)),a){let k=Xo(a.hex).l;n.push(` --${s}-color-surface: ${l?au(a.hex,.05):lu(a.hex,.03)}`),n.push(` --${s}-color-border: ${l?au(a.hex,.15):lu(a.hex,.12)}`)}let g=e.typography.filter(k=>k.role==="heading"||k.role==="subheading"),h=e.typography.filter(k=>k.role==="body"||k.role==="label"||k.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((k,T)=>T.fontSize-k.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 v=h.sort((k,T)=>T.occurrences-k.occurrences)[0];v&&n.push(` --${s}-size-body: ${v.fontSize}px`);let w=[...new Set(e.spacing.map(k=>k.value))].sort((k,T)=>k-T),M=["xs","sm","md","lg","xl","2xl","section"];w.slice(0,M.length).forEach((k,T)=>{n.push(` --${s}-space-${M[T]}: ${k}px`)});let L=e.effects.filter(k=>k.type==="shadow"),H=e.effects.filter(k=>k.type==="radius");L[0]&&n.push(` --${s}-shadow: ${L[0].cssValue}`),H.sort((k,T)=>parseFloat(k.cssValue)-parseFloat(T.cssValue)),H[0]&&n.push(` --${s}-radius: ${H[0].cssValue}`),H[1]&&n.push(` --${s}-radius-lg: ${H[1].cssValue}`);let B=`:root {
|
|
2368
2368
|
${n.join(`;
|
|
2369
2369
|
`)};
|
|
2370
|
-
}`,
|
|
2370
|
+
}`,K=`
|
|
2371
2371
|
/* Reset */
|
|
2372
2372
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
2373
2373
|
|
|
@@ -2451,8 +2451,8 @@ body {
|
|
|
2451
2451
|
h1 { font-size: 2rem; }
|
|
2452
2452
|
h2 { font-size: 1.5rem; }
|
|
2453
2453
|
h3 { font-size: 1.25rem; }
|
|
2454
|
-
}`;return{sharedCss:
|
|
2455
|
-
`+
|
|
2454
|
+
}`;return{sharedCss:B+`
|
|
2455
|
+
`+K,sharedJs:`(function() {
|
|
2456
2456
|
var observer = new IntersectionObserver(function(entries) {
|
|
2457
2457
|
entries.forEach(function(entry) {
|
|
2458
2458
|
if (entry.isIntersecting) {
|
|
@@ -2462,11 +2462,11 @@ body {
|
|
|
2462
2462
|
});
|
|
2463
2463
|
}, { threshold: 0.1 });
|
|
2464
2464
|
document.querySelectorAll('[data-animate]').forEach(function(el) { observer.observe(el); });
|
|
2465
|
-
})();`}}function
|
|
2466
|
-
`)}function
|
|
2465
|
+
})();`}}function au(e,t){return du(e,t)}function lu(e,t){return du(e,-t)}function du(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 Ly(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[^a-zA-Z0-9]+/g,"-").replace(/(^-|-$)/g,"").toLowerCase()}function Jy(e,t,n){let s=new Set,o=[];for(let i of e){let r=Ly(i.name);if(s.has(r)){let d=2;for(;s.has(`${r}-${d}`);)d++;r=`${r}-${d}`}s.add(r);let a=By(i.textContent),l=Hy(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 By(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(`
|
|
2466
|
+
`)}function Hy(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(`
|
|
2467
2467
|
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(`
|
|
2468
|
-
Available image assets:`);for(let o of t){let i=
|
|
2469
|
-
`)}function
|
|
2468
|
+
Available image assets:`);for(let o of t){let i=cu(o.localPath);s.push(` - get_asset_url("${n}/assets/${i}") \u2014 ${o.name}`)}}return s.join(`
|
|
2469
|
+
`)}function Uy(e,t,n,s,o){let i=[];if(i.push(`## Figma Design Translation
|
|
2470
2470
|
|
|
2471
2471
|
TRANSLATE this Figma section into a HubSpot CMS module. This is a CONVERSION, not creation.
|
|
2472
2472
|
- Use the EXACT text content from the design as field default values
|
|
@@ -2491,12 +2491,12 @@ The Figma design shows the DESKTOP layout. You MUST add responsive CSS:
|
|
|
2491
2491
|
### 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(`
|
|
2492
2492
|
### 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+=`
|
|
2493
2493
|
text: "${r.characters.slice(0,100)}"`),i.push(a)}}if(n.length>0)if(o){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=
|
|
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=cu(r.localPath);i.push(`- \`get_asset_url("${s}/assets/${a}")\` \u2014 ${r.name}`)}}else{i.push(`
|
|
2495
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(`
|
|
2496
2496
|
## Module Specification
|
|
2497
2497
|
- **Name**: ${t.name}
|
|
2498
2498
|
- **Description**: ${t.description}`),i.join(`
|
|
2499
|
-
`)}var
|
|
2499
|
+
`)}var mu=N(()=>{"use strict";y();ct();Ur();Gr();Vr();le();Be()});var pu={};Ge(pu,{buildPlanModePrompt:()=>Gy});function Gy(e,t,n,s,o){let i=Wy(o,!!t?.plan),r=[];return r.push(`You are vibeSpot's plan-mode assistant for the theme "${e}".
|
|
2500
2500
|
|
|
2501
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.
|
|
2502
2502
|
|
|
@@ -2565,15 +2565,15 @@ Drive toward filling these gaps in priority order:
|
|
|
2565
2565
|
The theme already has a styleguide. Reference its colors, typography, and tokens in the plan rather than asking about them again.
|
|
2566
2566
|
|
|
2567
2567
|
\`\`\`
|
|
2568
|
-
${
|
|
2568
|
+
${zr(t.styleguide,1500)}
|
|
2569
2569
|
\`\`\``),t?.brandvoice&&r.push(`## Available brand voice
|
|
2570
2570
|
|
|
2571
2571
|
\`\`\`
|
|
2572
|
-
${
|
|
2572
|
+
${zr(t.brandvoice,1e3)}
|
|
2573
2573
|
\`\`\``),t?.themeContext&&r.push(`## Theme context
|
|
2574
2574
|
|
|
2575
2575
|
\`\`\`
|
|
2576
|
-
${
|
|
2576
|
+
${zr(t.themeContext,1e3)}
|
|
2577
2577
|
\`\`\``),n.length>0&&r.push(`## Existing modules in this theme
|
|
2578
2578
|
|
|
2579
2579
|
These already exist on the page \u2014 you can keep, modify, or remove them in the plan, or reference them as reusable:
|
|
@@ -2594,13 +2594,13 @@ ${t.plan}
|
|
|
2594
2594
|
|
|
2595
2595
|
${i}`),r.join(`
|
|
2596
2596
|
|
|
2597
|
-
`)}function
|
|
2597
|
+
`)}function Wy(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:
|
|
2598
2598
|
- Briefly acknowledge the template and that you'll work from this structure (1\u20132 sentences in chat).
|
|
2599
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.
|
|
2600
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.
|
|
2601
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.
|
|
2602
|
-
- 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
|
|
2603
|
-
... [truncated]`}var
|
|
2602
|
+
- 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 zr(e,t){return e.length<=t?e:e.slice(0,t)+`
|
|
2603
|
+
... [truncated]`}var gu=N(()=>{"use strict";y()});var na={};Ge(na,{applyPipelineResult:()=>ln,handleAgenticGenerate:()=>Zo,handleFigmaImport:()=>Is,handleGenerate:()=>Ky,handleGenerateStream:()=>Ms,handlePlanModeStream:()=>Qr,isGenerating:()=>Wt,isPlanModeActive:()=>ea,resolveAgenticEngine:()=>Bn,setParseWarningCallback:()=>Xr,shouldUseAgenticMode:()=>ta});import{execSync as Yr}from"child_process";function Xr(e){qr=e}function Wt(){return Ot!==null}function wt(e){if(Ot){let t=C();if(!t||t.id!==Ot){E.warn("ai-handler","Session changed during generation \u2014 discarding AI output");return}}lt("assistant",e),Yc(e,qr||void 0),j()}async function Ms(e,t,n,s){let o=C();if(!o)throw new Error("No active session");Ot=o.id;let r=s?.length?Wo(s):void 0;try{let a=R(),l=a.aiEngine||Zr();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 kr(e,c,o.themeName,a.anthropicApiModel||"claude-sonnet-4-6",t,n,wt,r);break}case"claude-oauth":{await sd(e,o.themeName,a.anthropicApiModel||"claude-sonnet-4-6",t,n,wt,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 Tr(e,c,o.themeName,a.openaiApiModel||"gpt-4o",t,n,wt,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 Ar(e,c,o.themeName,t,n,wt,r);break}case"claude-code":await od(e,o.themeName,t,n,wt,r);break;case"gemini-cli":await Er("gemini",e,o.themeName,t,n,wt,r);break;case"codex-cli":await Er("codex",e,o.themeName,t,n,wt,r);break;case"langdock-api":{let c=Oe("langdock-api",a);if(!c)throw new Error("Langdock API key not configured. Open Settings to add one.");let d=a.langdockProvider||"anthropic",u={anthropic:"https://api.langdock.com/anthropic",openai:"https://api.langdock.com/openai",google:"https://api.langdock.com/google",mistral:"https://api.langdock.com/mistral"},m=a.langdockBaseUrl||u[d],g=a.langdockApiModel;switch(d){case"openai":case"mistral":await Tr(e,c,o.themeName,g||"gpt-4.1",t,n,wt,r,`${m}/v1/chat/completions`);break;case"google":await Ar(e,c,o.themeName,t,n,wt,r,`${m}/v1beta/models/${g||"gemini-2.5-flash"}:streamGenerateContent?alt=sse`,g);break;default:await kr(e,c,o.themeName,g||"claude-sonnet-4-6",t,n,wt,r,m);break}break}default:throw new Error(`Unknown AI engine: ${l}. Open Settings to configure one.`)}}finally{Ot=null,qr=null}}function Zr(){let e=R();if(Ze())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 Yr("claude --version",{stdio:"pipe"}),"claude-code"}catch{}try{return Yr("gemini --version",{stdio:"pipe"}),"gemini-cli"}catch{}try{return Yr("codex --version",{stdio:"pipe"}),"codex-cli"}catch{}throw new Error("No AI engine available. Open Settings to configure one.")}async function Ky(e){let t="";return await Ms(e,n=>{t+=n}),t}function fu(){let e=C(),t=ke(),n=t?[...t.modules]:[...e.modules],s=t?[...t.moduleOrder]:[...e.moduleOrder],o={modules:n,moduleOrder:s,sharedCss:t?.sharedCss||e.sharedCss,sharedJs:t?.sharedJs||e.sharedJs,messages:[...e.messages],themeName:e.themeName,themePath:e.themePath,contentMode:t?.contentMode,brandAssets:e.brandAssets?{...e.brandAssets}:void 0};return e.templates.length>1&&(o.activePageLabel=t?.label,o.sitePages=e.templates.map(i=>({id:i.id,label:i.label,pageType:i.pageType,moduleCount:i.modules.length}))),o}function Bn(e){let t=e.aiEngine||Zr();if(!ks(t))throw new Error("Agentic pipeline is not available for this engine.");if(Jn(t)){let o="";return t==="claude-code"&&(o=e.claudeCodeModel||""),{engine:t,apiKey:"",model:o}}let n;if(t==="claude-oauth"){if(!Ze())throw new Error("Claude OAuth session expired. Please re-authenticate in Settings.");n="oauth"}else n=Oe(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"langdock-api":{let o={anthropic:"claude-sonnet-4-6",openai:"gpt-4.1",google:"gemini-2.5-flash",mistral:"mistral-large-latest"};s=e.langdockApiModel||o[e.langdockProvider||"anthropic"];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 Zo(e,t,n){let s=C();if(!s)throw new Error("No active session");let o=s.id;Ot=o;try{let i=R(),{engine:r,apiKey:a,model:l}=Bn(i),c=i.agenticConcurrency||20,d=fu(),u=d.brandAssets?.plan,m=e;u&&u.trim()&&(m=`## Approved plan
|
|
2604
2604
|
|
|
2605
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.
|
|
2606
2606
|
|
|
@@ -2610,39 +2610,39 @@ ${u}
|
|
|
2610
2610
|
|
|
2611
2611
|
## User message
|
|
2612
2612
|
|
|
2613
|
-
${e}`);let g=n?.length?
|
|
2613
|
+
${e}`);let g=n?.length?Wo(n):void 0;if(g?.length)for(let M of g)M.type==="document"&&M.extractedText&&(m+=`
|
|
2614
2614
|
|
|
2615
2615
|
---
|
|
2616
|
-
[Attached document: ${
|
|
2617
|
-
${
|
|
2616
|
+
[Attached document: ${M.originalName}]
|
|
2617
|
+
${M.extractedText}`),M.type==="image"&&M.usage==="asset"&&M.assetPath&&(m+=`
|
|
2618
2618
|
|
|
2619
|
-
[Uploaded image: ${
|
|
2619
|
+
[Uploaded image: ${M.originalName} \u2192 available as get_asset_url("${M.assetPath}")]`);let h=Nt(),f=new Set(d.modules.map(M=>M.moduleName)),b=h.filter(M=>!f.has(M.module.moduleName)).map(M=>({name:M.module.moduleName,usedIn:M.usedIn})),{result:S,cost:v}=await Zi(()=>tt({name:"agent_pipeline",sessionId:d.themeName,input:e,metadata:{engine:r,model:l,concurrency:c},tags:["vibespot","agentic-pipeline"]},()=>iu(m,d,r,a,l,c,t,b)));S.cost=v;let 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 S}finally{Ot=null}}async function Is(e,t,n,s){let o=C();if(!o)throw new Error("No active session");let i=o.id;Ot=i;try{let{runFigmaConversion:r}=await Promise.resolve().then(()=>(mu(),uu)),a=R(),{engine:l,apiKey:c,model:d}=Bn(a),u=a.agenticConcurrency||20,m=fu(),{result:g,cost:h}=await Zi(()=>tt({name:"figma_import",sessionId:t,input:{fileName:e.fileName,sections:e.sections.length},metadata:{engine:l,model:d,concurrency:u},tags:["vibespot","figma-import"]},()=>r(e,t,l,c,d,u,n,m.brandAssets,s?.useAssets)));g.cost=h;let f=C();if(!f||f.id!==i)throw E.warn("ai-handler","Session changed during Figma import \u2014 discarding output"),new Error("Session changed during generation");return g}finally{Ot=null}}function ln(e,t){let n=e.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"});fc({pages:n.pages,sharedModules:n.sharedModules,sharedCss:n.sharedCss,sharedJs:n.sharedJs,pageLabels:s})}else if(He({modules:e.modules,sharedCss:e.sharedCss,sharedJs:e.sharedJs}),Ht(e.moduleOrder),e.contentType==="email"){let o=ke();o&&!o.contentMode&&(o.contentMode="email")}t?.cost&&dc(t.cost),lt("assistant",e.assistantMessage,t),j()}async function Qr(e,t,n){let s=C();if(!s)throw new Error("No active session");let o=R(),{engine:i,apiKey:r,model:a}=Bn(o),[{buildPlanModePrompt:l},{callAgent:c}]=await Promise.all([Promise.resolve().then(()=>(gu(),pu)),Promise.resolve().then(()=>(ct(),fd))]),d=s.messages.filter(w=>w.role==="assistant").length,u=s.modules.map(w=>w.moduleName),m=Nt(),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?Wo(n):void 0,S=e;if(b?.length)for(let w of b)w.type==="document"&&w.extractedText&&(S+=`
|
|
2620
2620
|
|
|
2621
2621
|
---
|
|
2622
|
-
[Attached document: ${
|
|
2623
|
-
${
|
|
2624
|
-
`}}function
|
|
2622
|
+
[Attached document: ${w.originalName}]
|
|
2623
|
+
${w.extractedText}`);let v=await c(i,r,a,{systemPrompt:f,messages:[{role:"user",content:S}],maxTokens:8e3,onChunk:t,enableWebSearch:!!o.webSearch});return v.type==="text"?v.text:JSON.stringify(v.data)}function ea(){return!!R().planMode}function ta(){let e=R(),t=e.aiEngine||Zr();return ks(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 qr,Ot,Hn=N(()=>{"use strict";y();ee();Ce();Go();le();Qi();Mr();_t();Nr();ru();Be();qr=null;Ot=null});import{readFileSync as Vy,readdirSync as zy,existsSync as Yy}from"fs";import{dirname as qy,join as Qo}from"path";import{fileURLToPath as Xy}from"url";function Qy(e){let t=e.match(Zy);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 eb(e){let t=Qy(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,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 tb(){let e=[Qo(hu,"../../assets/plan-templates"),Qo(hu,"../assets/plan-templates"),Qo(process.cwd(),"assets/plan-templates")];for(let t of e)if(Yy(t))return t;return null}function yu(){if(Kt)return Kt;let e=tb();if(!e)return Kt=[],Kt;let t=[],n=[];try{n=zy(e)}catch{return Kt=[],Kt}for(let s of n)if(s.endsWith(".md"))try{let o=Vy(Qo(e,s),"utf-8"),i=eb(o);i&&t.push(i)}catch{}return t.sort((s,o)=>s.order!==o.order?s.order-o.order:s.label.localeCompare(o.label)),Kt=t,Kt}function bu(e){return yu().find(t=>t.id===e)??null}function Su(){return yu().map(({id:e,label:t,description:n,icon:s,order:o,contentType:i})=>({id:e,label:t,description:n,icon:s,order:o,contentType:i}))}var hu,Zy,Kt,vu=N(()=>{"use strict";y();hu=qy(Xy(import.meta.url)),Zy=/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/;Kt=null});import{existsSync as xu,mkdirSync as nb,writeFileSync as sb,rmSync as ob}from"fs";import{join as wu}from"path";function Cu(e){return wu(e,".vibespot",ib)}function ei(e){let t=C();if(!t)return null;t.brandAssets||(t.brandAssets={}),t.brandAssets.plan=e;let n=ke();n&&(n.plan=e);try{let s=wu(t.themePath,".vibespot");xu(s)||nb(s,{recursive:!0}),sb(Cu(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 sa(){let e=C();if(!e)return;e.brandAssets&&delete e.brandAssets.plan;let t=ke();t&&delete t.plan;try{let n=Cu(e.themePath);xu(n)&&ob(n)}catch(n){E.warn("plan",`Failed to remove plan.md: ${n instanceof Error?n.message:String(n)}`)}j()}function ku(e,t){qe(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}ei(o),p(t,200,{ok:!0,plan:o})})}function Tu(e,t){qe(e,t,()=>{sa(),Y({planMode:!1}),p(t,200,{ok:!0})})}function Au(e,t){p(t,200,{templates:Su()})}function _u(e,t){qe(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=bu(o);if(!i){p(t,404,{error:`Unknown plan template: ${o}`});return}ei(i.body),Y({planMode:!0}),p(t,200,{ok:!0,templateId:i.id,label:i.label,plan:i.body})})}var ib,$u=N(()=>{"use strict";y();Xe();Ce();Ut();ee();le();vu();ib="plan.md"});function Eu(e){let t,n,s;for(oa.lastIndex=0;(s=oa.exec(e))!==null;)t=s[1].trim();let o;for(ia.lastIndex=0;(o=ia.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(oa,"").replace(ia,"").replace(/\n{3,}/g,`
|
|
2625
2625
|
|
|
2626
|
-
`).trim(),plan:t,choices:n}}var
|
|
2626
|
+
`).trim(),plan:t,choices:n}}var oa,ia,Mu=N(()=>{"use strict";y();oa=/```vibespot-plan\s*\n([\s\S]*?)```/g,ia=/```vibespot-choices\s*\n([\s\S]*?)```/g});import{spawn as ra}from"child_process";function Iu(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+=`
|
|
2627
2627
|
Process error: ${o.message}`,t.completedAt=Date.now()}),setTimeout(()=>{t.status==="running"&&(e.kill(),t.status="failed",t.output+=`
|
|
2628
|
-
Process timed out`,t.completedAt=Date.now())},n||3e5)}function
|
|
2628
|
+
Process timed out`,t.completedAt=Date.now())},n||3e5)}function Ps(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};Vt.set(o,i);let r=ra(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()),Iu(r,i,s?.timeout),o}function cn(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};Vt.set(s,o);let i=e.split(" "),r=ra(i[0],i.slice(1),{cwd:n?.cwd,stdio:["ignore","pipe","pipe"],env:{...process.env,...n?.env},shell:!0});return Iu(r,o,n?.timeout),s}function ti(e){return Vt.get(e)}function rb(){let e=Date.now()-18e5;for(let[t,n]of Vt)n.completedAt&&n.completedAt<e&&Vt.delete(t)}function ni(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};Vt.set(s,o);let i=e.split(" "),r=ra(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
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
|
|
2630
|
+
Process timed out`,o.completedAt=Date.now(),o.listeners.clear())},l),s}function Pu(e,t){let n=Vt.get(e);if(!n||!("listeners"in n))return;let s=n;if(s.output)try{t(s.output)}catch{}s.listeners.add(t)}function Nu(e,t){let n=Vt.get(e);!n||!("listeners"in n)||n.listeners.delete(t)}var Vt,si=N(()=>{"use strict";y();Vt=new Map;setInterval(rb,600*1e3)});import{readFileSync as ab,readdirSync as lb,existsSync as cb}from"fs";import{dirname as db,join as oi}from"path";import{fileURLToPath as ub}from"url";function mb(){let e=[oi(Ru,"../../starters"),oi(Ru,"../starters"),oi(process.cwd(),"starters")];for(let t of e)if(cb(t))return t;return null}function Ou(){if(Un!==null)return Un;let e=mb();if(!e)return Un=[],Un;let t=[];for(let n of lb(e).filter(s=>s.endsWith(".json")).sort())try{let s=JSON.parse(ab(oi(e,n),"utf-8"));t.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 Un=t,Un}function Fu(){return Ou().map(e=>({id:e.id,name:e.name,description:e.description,category:e.category,contentType:e.contentType,moduleCount:e.modules.length}))}function aa(e){return Ou().find(t=>t.id===e)||null}var Ru,Un,Du=N(()=>{"use strict";y();Ru=db(ub(import.meta.url)),Un=null});var Rs={};Ge(Rs,{collectThemeFiles:()=>Lu,extractDesignContext:()=>yb});import{existsSync as ii,readdirSync as ri,readFileSync as pb}from"fs";import{join as Ct}from"path";import{spawn as gb}from"child_process";async function ju(){return la||(la=(await import("@anthropic-ai/sdk")).default),la}function Ns(e){try{return pb(e,"utf-8")}catch{return""}}function Lu(e){let t=[],n=0;function s(a,l){if(!l.trim())return!0;let c=`
|
|
2631
2631
|
### ${a}
|
|
2632
2632
|
\`\`\`
|
|
2633
2633
|
${l}
|
|
2634
2634
|
\`\`\`
|
|
2635
|
-
`;return n+c.length>
|
|
2636
|
-
${n}`;t?.({status:"Analyzing design patterns..."});let i=
|
|
2635
|
+
`;return n+c.length>fb?!1:(t.push(c),n+=c.length,!0)}let o=Ns(Ct(e,"theme.json"));o&&s("theme.json",o);let i=Ct(e,"css");if(ii(i)){for(let a of ri(i).filter(l=>l.endsWith(".css")))if(!s(`css/${a}`,Ns(Ct(i,a))))break}let r=Ct(e,"modules");if(ii(r))for(let a of ri(r).filter(l=>l.endsWith(".module"))){let l=Ct(r,a),c=Ns(Ct(l,"module.css"));if(c&&!s(`modules/${a}/module.css`,c))break}if(ii(r))for(let a of ri(r).filter(l=>l.endsWith(".module"))){let l=Ct(r,a),c=Ns(Ct(l,"module.html"));if(c&&!s(`modules/${a}/module.html`,c))break}if(ii(r))for(let a of ri(r).filter(l=>l.endsWith(".module"))){let l=Ct(r,a),c=Ns(Ct(l,"fields.json"));if(c&&!s(`modules/${a}/fields.json`,c))break}return t.join("")}function hb(){if(!ai)try{ai=P(fn("extraction-prompt.md"))}catch{ai=""}return ai}function ca(e,t,n){return new Promise((s,o)=>{let i={...process.env};delete i.CLAUDECODE;let r=gb(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 yb(e,t){t?.({status:"Collecting theme files..."});let n=Lu(e);if(!n.trim())throw new Error("No CSS, HTML, or fields.json files found in theme.");let s=hb();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}`;t?.({status:"Analyzing design patterns..."});let i=R(),r=i.aiEngine||"anthropic-api",a="",l=new Date,c,d="";switch(r){case"anthropic-api":case"api":{let u=Oe("anthropic-api");if(!u)throw new Error("Anthropic API key not configured. Open Settings to add one.");let m=await ju(),g=new m({apiKey:u});d=i.anthropicApiModel||"claude-sonnet-4-6";let h=await g.messages.create({model:d,max_tokens:8e3,system:[{type:"text",text:s,cache_control:{type:"ephemeral"}}],messages:[{role:"user",content:o}]});a=h.content.map(f=>f.type==="text"?f.text:"").join(""),c=et(h.usage);break}case"claude-oauth":{let{getValidAccessToken:u,OAUTH_EXTRA_HEADERS:m,OAUTH_SYSTEM_PREFIX:g}=await Promise.resolve().then(()=>(_t(),Fi)),h=await u();if(!h)throw new Error("Claude OAuth session expired. Please re-authenticate in Settings.");let f=await ju(),b=new f({authToken:h,defaultHeaders:m});d=i.anthropicApiModel||"claude-sonnet-4-6";let S=await b.messages.create({model:d,max_tokens:8e3,system:[{type:"text",text:g},{type:"text",text:s,cache_control:{type:"ephemeral"}}],messages:[{role:"user",content:o}]});a=S.content.map(v=>v.type==="text"?v.text:"").join(""),c=et(S.usage);break}case"openai-api":{let u=Oe("openai-api");if(!u)throw new Error("OpenAI API key not configured. Open Settings to add one.");d=i.openaiApiModel||"gpt-4o";let m=await fetch("https://api.openai.com/v1/chat/completions",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${u}`},body:JSON.stringify({model:d,max_tokens:8e3,messages:[{role:"system",content:s},{role:"user",content:o}]})});if(!m.ok)throw new Error(`OpenAI API error: ${m.status} ${await m.text()}`);let g=await m.json();a=g.choices?.[0]?.message?.content||"",c=An(g.usage);break}case"gemini-api":{let u=Oe("gemini-api");if(!u)throw new Error("Gemini API key not configured. Open Settings to add one.");d=i.geminiApiModel||"gemini-2.5-flash";let m=await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${d}:generateContent?key=${u}`,{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(!m.ok)throw new Error(`Gemini API error: ${m.status} ${await m.text()}`);let g=await m.json();a=g.candidates?.[0]?.content?.parts?.map(h=>h.text).join("")||"",c=_n(g.usageMetadata);break}case"claude-code":{let u=`${s}
|
|
2637
2637
|
|
|
2638
2638
|
## User Request
|
|
2639
|
-
${o}`,
|
|
2639
|
+
${o}`,m=["--print"];i.claudeCodeModel&&m.push("--model",i.claudeCodeModel),a=await ca("claude",m,u);break}case"gemini-cli":{let u=`${s}
|
|
2640
2640
|
|
|
2641
2641
|
## User Request
|
|
2642
|
-
${o}`;a=await
|
|
2642
|
+
${o}`;a=await ca("gemini",[],u);break}case"codex-cli":{let u=`${s}
|
|
2643
2643
|
|
|
2644
2644
|
## User Request
|
|
2645
|
-
${o}`;a=await
|
|
2645
|
+
${o}`;a=await ca("codex",[],u);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 d&&bt({engine:r,model:d,name:"styleguide-extraction",input:{system:s,messages:[{role:"user",content:o}]},output:a,usage:c,startTime:l,endTime:new Date}),t?.({status:"Design extraction complete."}),a}var la,fb,ai,Os=N(()=>{"use strict";y();oe();ee();Be();en();la=null;fb=8e4;ai=""});var da={};Ge(da,{extractBrandvoice:()=>bb});async function bb(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.
|
|
2646
2646
|
|
|
2647
2647
|
Return a markdown document with these sections (skip any section where the content provides no signal):
|
|
2648
2648
|
|
|
@@ -2662,7 +2662,7 @@ Typical sentence length, structure, use of questions, imperatives, etc.
|
|
|
2662
2662
|
## Dos and Don'ts
|
|
2663
2663
|
3-4 practical rules for writing in this voice (e.g., "Do: Lead with benefits, not features", "Don't: Use jargon without context").
|
|
2664
2664
|
|
|
2665
|
-
Keep it actionable \u2014 this guide will be fed to AI to maintain consistent copy across pages.`;try{let i=await
|
|
2665
|
+
Keep it actionable \u2014 this guide will be fed to AI to maintain consistent copy across pages.`;try{let i=await Pe(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 ua=N(()=>{"use strict";y();ct();le()});var li={};Ge(li,{extractThemeContext:()=>Sb});async function Sb(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.
|
|
2666
2666
|
|
|
2667
2667
|
Return a markdown document with these sections (skip any section where the content provides no information):
|
|
2668
2668
|
|
|
@@ -2684,11 +2684,11 @@ Specific terms, product names, or branded language used consistently.
|
|
|
2684
2684
|
Keep it concise \u2014 this brief is used as context for AI-generated content on other pages in the same theme.${t?`
|
|
2685
2685
|
|
|
2686
2686
|
Existing product context (update if the new content adds info, keep what's still accurate):
|
|
2687
|
-
${t}`:""}`;try{let a=await _e(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:(M.info("context-extractor",`Extracted theme context (${l.length} chars)`),l.trim())}catch(a){let l=a instanceof Error?a.message:String(a);return M.warn("context-extractor",`Theme context extraction failed: ${l}`),null}}var Bo=R(()=>{"use strict";y();nt();de()});import{join as Yd}from"path";function uy(e){let t=[];return e.brandAssets?.styleguide||t.push("styleguide"),e.brandAssets?.brandvoice||t.push("brandvoice"),e.brandAssets?.themeContext||t.push("themeContext"),t}function my(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=Yd(e.themePath,".vibespot");Ie(o),J(Yd(o,s),n)}async function qd(e,t){let n=uy(e),s={attempted:[],extracted:[],skipped:[],errors:[]};if(n.length===0)return s;let o=py(t)?t:{...await gy(e),...t??{}};n.includes("styleguide")&&await jr(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 jr(e,"brandvoice",s,()=>o.extractBrandvoice(e,r)),n.includes("themeContext")&&await jr(e,"themeContext",s,()=>o.extractThemeContext(e,r)),s}async function jr(e,t,n,s){n.attempted.push(t);try{let o=await s();if(!o){n.skipped.push(t);return}my(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}),M.warn("brand-enrichment",`${t} enrichment skipped: ${i}`)}}function py(e){return!!e?.extractStyleguide&&!!e.extractBrandvoice&&!!e.extractThemeContext&&!!e.buildPreviewHtml}async function gy(e){let{extractDesignContext:t}=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:()=>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 Xd=R(()=>{"use strict";y();ne();Q();de()});import{existsSync as kn,readdirSync as Zd,rmSync as fy,writeFileSync as Zt,mkdirSync as Ho}from"fs";import{join as Ee,basename as hy}from"path";import{homedir as yy}from"os";import{execFileSync as eu}from"child_process";function Uo(){if(Go&&Date.now()-Go.ts<by)return Go.data;let e=[];if(kn(st))try{for(let t of Zd(st,{withFileTypes:!0}))if(t.isDirectory()){let n=Ee(st,t.name,"theme.json");if(kn(n)){let s=0,o=Ee(st,t.name,"modules");if(kn(o))try{s=Zd(o,{withFileTypes:!0}).filter(i=>i.isDirectory()).length}catch{}e.push({name:t.name,moduleCount:s})}}}catch{}return Go={data:e,ts:Date.now()},e}function nu(e){let t=C(),n=Os(),s=!1;try{eu("hs",["--version"],{encoding:"utf-8",stdio:"pipe",...tu}),s=!0}catch{}let o=gn().sort((r,a)=>a.updatedAt-r.updatedAt),i=Uo();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,contentMode:yn()})}function su(e,t){W(e,n=>{try{if(Ft()){p(t,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(t,400,{error:"Theme name is required"});return}let r=s.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"");if(!r){p(t,400,{error:"Theme name must contain at least one alphanumeric character"});return}let a=Ee(st,r);if(Ie(st),kn(a)&&fy(a,{recursive:!0,force:!0}),o&&typeof o=="string"&&!Pr(o)){p(t,400,{error:`Starter template "${o}" not found`});return}Ln(a,r),pn(a,r),o&&typeof o=="string"?(Sy(a,r,o),ke()):i==="email"&&(Tt("module_only","Email","email"),ln(a,r)),D(),p(t,200,{ok:!0,themeName:r,themePath:a,starterId:o||void 0})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function Sy(e,t,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-${t}`:`lp-${t}`,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(e,t),o.templates=[c],o.activeTemplateId=l,o.modules=r,o.moduleOrder=a,o.sharedCss=s.sharedCss,o.sharedJs=s.sharedJs;let d=Ee(e,"modules");Ho(d,{recursive:!0});for(let u of s.modules){let m=Ee(d,`${u.moduleName}.module`);Ho(m,{recursive:!0}),Zt(Ee(m,"fields.json"),u.fieldsJson,"utf-8"),Zt(Ee(m,"meta.json"),u.metaJson,"utf-8"),Zt(Ee(m,"module.html"),u.moduleHtml,"utf-8"),Zt(Ee(m,"module.css"),u.moduleCss,"utf-8"),u.moduleJs&&Zt(Ee(m,"module.js"),u.moduleJs,"utf-8")}if(s.sharedCss){let u=Ee(e,"css");Ho(u,{recursive:!0}),Zt(Ee(u,`${t}-theme.css`),s.sharedCss,"utf-8")}if(s.sharedJs){let u=Ee(e,"js");Ho(u,{recursive:!0}),Zt(Ee(u,`${t}-animations.js`),s.sharedJs,"utf-8")}}function ou(e){p(e,200,{starters:Wd()})}function iu(e,t){W(e,n=>{try{if(Ft()){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=Fe(),r=O(),a=o.includes("/")||o.includes("@")?o.replace(/[@/]/g,"_").replace(/_+/g,"_").replace(/^_|_$/g,""):o,l=Ee(st,a);Ie(st),r.hubspotUploadMode==="cli"||!i?(async()=>{eu("hs",["cms","fetch",o,l],{encoding:"utf-8",stdio:"pipe",...tu});let c=await Qd(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)})}):Bn(i,o,l).then(async()=>{let c=await Qd(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 Qd(e,t){pn(e,t,{isImported:!0}),So(e),D();let n=C(),s={attempted:[],extracted:[],skipped:[],errors:[]};return n&&(s=await qd(n),D()),{moduleCount:n?.modules.length||0,brandEnrichment:s}}function ru(e,t){W(e,n=>{try{if(Ft()){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(kn(o)||(o=Ee(st,s)),!kn(o)){p(t,400,{error:`Theme folder not found: ${s}`});return}let i=hy(o);pn(o,i),So(o),D(),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 au(e,t){W(e,n=>{try{if(Ft()){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=po(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 lu(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}Y({anthropicApiKey:s}),p(t,200,{ok:!0})}catch(s){p(t,400,{error:s instanceof Error?s.message:String(s)})}})}function cu(e){let t=Fe();if(!t){p(e,200,{themes:[],error:"No HubSpot account connected"});return}(async()=>{let n=await wa(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 Ds(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=Uo(),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)})})}var tu,st,Go,by,Wo=R(()=>{"use strict";y();ze();Q();Jn();Hs();Gt();we();Nt();wn();Ht();Q();ne();Kd();ts();Xd();tu=process.platform==="win32"?{shell:!0}:{},st=Ee(yy(),"vibespot-themes"),Go=null,by=5e3});import{existsSync as xy,readFileSync as vy,appendFileSync as wy}from"fs";import{join as du}from"path";import{homedir as uu}from"os";function Ty(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 Ay(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 $y(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 mu(e,t){return e.filter(n=>t.test(n)).sort((n,s)=>n.localeCompare(s)).map(n=>({id:n,label:Ty(n)}))}async function _y(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 Ey(){if(Date.now()-hs.ts<Cy&&Object.keys(hs.data).length>0)return hs.data;let e=O(),t={...pu},n=[],s=Oe("anthropic-api",e);s&&n.push(Ay(s).then(r=>{r.length&&(t["anthropic-api"]=r,t["claude-oauth"]=r)}).catch(()=>{}));let o=Oe("openai-api",e);o&&n.push($y(o).then(r=>{if(!r.length)return;let a=mu(r,gu);a.length&&(t["openai-api"]=a);let l=mu(r,ky);l.length&&(t["codex-cli"]=l)}).catch(()=>{}));let i=Oe("gemini-api",e);return i&&n.push(_y(i).then(r=>{r.length&&(t["gemini-api"]=r,t["gemini-cli"]=r)}).catch(()=>{})),await Promise.all(n),hs.data=t,hs.ts=Date.now(),t}function fu(e){let t=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,langdockApiModel:n.langdockApiModel||null,langdockBaseUrl:n.langdockBaseUrl||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=Uo().length,r=sn();Ey().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:pu,sessionCount:o,localThemeCount:i})})}function hu(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","langdock-api"].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;case"langdock-api":r.langdockApiModel=o;break}Y(r),p(t,200,{ok:!0,engine:s})}catch(s){p(t,400,{error:s instanceof Error?s.message:String(s)})}})}function yu(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"langdock":l.langdockApiKey="";break;case"figma":l.figmaToken="";break;default:p(t,400,{error:`Unknown provider: ${s}`});return}Y(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"langdock":i.langdockApiKey=o;break;case"figma":i.figmaToken=o;break;default:p(t,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",langdock:"langdock-api"}[s];c&&(Y({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 bu(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=Xt(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 Su(e,t){W(e,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(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(!ct().found){p(t,400,{error:"HubSpot CLI not installed",needsInstall:!0});return}let a=ms("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(!ct().found){p(t,400,{error:"HubSpot CLI not installed",needsInstall:!0});return}let a=dt();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 xu(e,t){W(e,n=>{try{let s=JSON.parse(n||"{}");if(!hi().found){p(t,400,{error:"GitHub CLI not installed",needsInstall:!0});return}let i=yi();if(i.authenticated&&!s.force){p(t,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(t,200,{ok:!0,jobId:a});return}let r=Xt("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 vu(e,t){W(e,n=>{try{let{portalId:s,action:o}=JSON.parse(n);if((O().hubspotUploadMode||"api")==="api"){if(o==="remove"&&s){ci(s),p(t,200,{ok:!0});return}if(s){di(s),p(t,200,{ok:!0});return}}else{if(!ct().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=ms("hs",["accounts","remove",l],`Removing HubSpot account ${l}`,{timeout:15e3});p(t,200,{ok:!0,jobId:c});return}if(l){let c=ms("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 wu(e){let t=Xt("gh auth logout --hostname github.com -y","Logging out of GitHub",{timeout:15e3});p(e,200,{ok:!0,jobId:t})}function Cu(e,t){W(e,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(t,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(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,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")?du(uu(),".zshrc"):du(uu(),".bashrc");try{(xy(l)?vy(l,"utf-8"):"").includes("OPENAI_API_KEY")||wy(l,`
|
|
2687
|
+
${t}`:""}`;try{let a=await Pe(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 ci=N(()=>{"use strict";y();ct();le()});import{join as Ju}from"path";function vb(e){let t=[];return e.brandAssets?.styleguide||t.push("styleguide"),e.brandAssets?.brandvoice||t.push("brandvoice"),e.brandAssets?.themeContext||t.push("themeContext"),t}function xb(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=Ju(e.themePath,".vibespot");Re(o),J(Ju(o,s),n)}async function Bu(e,t){let n=vb(e),s={attempted:[],extracted:[],skipped:[],errors:[]};return n.length===0?s:tt({name:"brand_enrichment",sessionId:e.themeName,metadata:{missing:n},tags:["vibespot","brand-enrichment"]},()=>wb(e,t,n,s))}async function wb(e,t,n,s){let o=Cb(t)?t:{...await kb(e),...t??{}};n.includes("styleguide")&&await ma(e,"styleguide",s,()=>te("extract-styleguide",()=>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 ma(e,"brandvoice",s,()=>te("extract-brandvoice",()=>o.extractBrandvoice(e,r))),n.includes("themeContext")&&await ma(e,"themeContext",s,()=>te("extract-theme-context",()=>o.extractThemeContext(e,r))),s}async function ma(e,t,n,s){n.attempted.push(t);try{let o=await s();if(!o){n.skipped.push(t);return}xb(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 Cb(e){return!!e?.extractStyleguide&&!!e.extractBrandvoice&&!!e.extractThemeContext&&!!e.buildPreviewHtml}async function kb(e){let{extractDesignContext:t}=await Promise.resolve().then(()=>(Os(),Rs)),{buildPreviewHtml:n}=await Promise.resolve().then(()=>(ys(),Uo)),{resolveAgenticEngine:s}=await Promise.resolve().then(()=>(Hn(),na)),{extractBrandvoice:o}=await Promise.resolve().then(()=>(ua(),da)),{extractThemeContext:i}=await Promise.resolve().then(()=>(ci(),li)),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 Hu=N(()=>{"use strict";y();oe();ee();le();Be()});import{existsSync as Gn,readdirSync as Uu,rmSync as Tb,writeFileSync as dn,mkdirSync as di}from"fs";import{join as Ne,basename as Ab}from"path";import{homedir as _b}from"os";import{execFileSync as Wu}from"child_process";function mi(){if(ui&&Date.now()-ui.ts<$b)return ui.data;let e=[];if(Gn(dt))try{for(let t of Uu(dt,{withFileTypes:!0}))if(t.isDirectory()){let n=Ne(dt,t.name,"theme.json");if(Gn(n)){let s=0,o=Ne(dt,t.name,"modules");if(Gn(o))try{s=Uu(o,{withFileTypes:!0}).filter(i=>i.isDirectory()).length}catch{}e.push({name:t.name,moduleCount:s})}}}catch{}return ui={data:e,ts:Date.now()},e}function Vu(e){let t=C(),n=to(),s=!1;try{Wu("hs",["--version"],{encoding:"utf-8",stdio:"pipe",...Ku}),s=!0}catch{}let o=Rn().sort((r,a)=>a.updatedAt-r.updatedAt),i=mi();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,contentMode:Dn()})}function zu(e,t){W(e,n=>{try{if(Wt()){p(t,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(t,400,{error:"Theme name is required"});return}let r=s.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"");if(!r){p(t,400,{error:"Theme name must contain at least one alphanumeric character"});return}let a=Ne(dt,r);if(Re(dt),Gn(a)&&Tb(a,{recursive:!0,force:!0}),o&&typeof o=="string"&&!aa(o)){p(t,400,{error:`Starter template "${o}" not found`});return}ts(a,r),Nn(a,r),o&&typeof o=="string"?(Eb(a,r,o),Te()):i==="email"&&(Pt("module_only","Email","email"),Tn(a,r)),j(),p(t,200,{ok:!0,themeName:r,themePath:a,starterId:o||void 0})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function Eb(e,t,n){let s=aa(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-${t}`:`lp-${t}`,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&&Tn(e,t),o.templates=[c],o.activeTemplateId=l,o.modules=r,o.moduleOrder=a,o.sharedCss=s.sharedCss,o.sharedJs=s.sharedJs;let d=Ne(e,"modules");di(d,{recursive:!0});for(let u of s.modules){let m=Ne(d,`${u.moduleName}.module`);di(m,{recursive:!0}),dn(Ne(m,"fields.json"),u.fieldsJson,"utf-8"),dn(Ne(m,"meta.json"),u.metaJson,"utf-8"),dn(Ne(m,"module.html"),u.moduleHtml,"utf-8"),dn(Ne(m,"module.css"),u.moduleCss,"utf-8"),u.moduleJs&&dn(Ne(m,"module.js"),u.moduleJs,"utf-8")}if(s.sharedCss){let u=Ne(e,"css");di(u,{recursive:!0}),dn(Ne(u,`${t}-theme.css`),s.sharedCss,"utf-8")}if(s.sharedJs){let u=Ne(e,"js");di(u,{recursive:!0}),dn(Ne(u,`${t}-animations.js`),s.sharedJs,"utf-8")}}function Yu(e){p(e,200,{starters:Fu()})}function qu(e,t){W(e,n=>{try{if(Wt()){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=Le(),r=R(),a=o.includes("/")||o.includes("@")?o.replace(/[@/]/g,"_").replace(/_+/g,"_").replace(/^_|_$/g,""):o,l=Ne(dt,a);Re(dt),r.hubspotUploadMode==="cli"||!i?(async()=>{Wu("hs",["cms","fetch",o,l],{encoding:"utf-8",stdio:"pipe",...Ku});let c=await Gu(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)})}):ss(i,o,l).then(async()=>{let c=await Gu(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 Gu(e,t){Nn(e,t,{isImported:!0}),Bo(e),j();let n=C(),s={attempted:[],extracted:[],skipped:[],errors:[]};return n&&(s=await Bu(n),j()),{moduleCount:n?.modules.length||0,brandEnrichment:s}}function Xu(e,t){W(e,n=>{try{if(Wt()){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(Gn(o)||(o=Ne(dt,s)),!Gn(o)){p(t,400,{error:`Theme folder not found: ${s}`});return}let i=Ab(o);Nn(o,i),Bo(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 Zu(e,t){W(e,n=>{try{if(Wt()){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=Oo(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 Qu(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}Y({anthropicApiKey:s}),p(t,200,{ok:!0})}catch(s){p(t,400,{error:s instanceof Error?s.message:String(s)})}})}function em(e){let t=Le();if(!t){p(e,200,{themes:[],error:"No HubSpot account connected"});return}(async()=>{let n=await ol(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 oo(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=mi(),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)})})}var Ku,dt,ui,$b,pi=N(()=>{"use strict";y();Xe();ee();ns();lo();Qt();Ce();Ut();Hn();Zt();ee();oe();Du();bs();Hu();Ku=process.platform==="win32"?{shell:!0}:{},dt=Ne(_b(),"vibespot-themes"),ui=null,$b=5e3});import{existsSync as Mb,readFileSync as Ib,appendFileSync as Pb}from"fs";import{join as tm}from"path";import{homedir as nm}from"os";function Ob(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 ga(e,t={},n=am){let s=new AbortController,o=setTimeout(()=>s.abort(),n);try{return await fetch(e,{...t,signal:s.signal})}finally{clearTimeout(o)}}async function Fb(e){let t=await ga("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 Db(e){let t=await ga("https://api.openai.com/v1/models",{headers:{Authorization:`Bearer ${e}`}});return t.ok?(await t.json()).data.map(s=>s.id):[]}function om(e,t){return e.filter(n=>t.test(n)).sort((n,s)=>n.localeCompare(s)).map(n=>({id:n,label:Ob(n)}))}async function jb(e){let t=await ga(`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 Lb(e=!1){if(!e&&Date.now()-Wn.ts<Nb&&Object.keys(Wn.data).length>0)return Wn.data;let t=R(),n={...pa},s=[],o=Oe("anthropic-api",t);o&&s.push(Fb(o).then(c=>{c.length&&(n["anthropic-api"]=c,n["claude-oauth"]=c)}).catch(()=>{}));let i=Oe("openai-api",t);i&&s.push(Db(i).then(c=>{if(!c.length)return;let d=om(c,rm);d.length&&(n["openai-api"]=d);let u=om(c,Rb);u.length&&(n["codex-cli"]=u)}).catch(()=>{}));let r=Oe("gemini-api",t);r&&s.push(jb(r).then(c=>{c.length&&(n["gemini-api"]=c,n["gemini-cli"]=c)}).catch(()=>{}));let a=!1;await Promise.race([Promise.all(s).then(()=>{a=!0}),new Promise(c=>setTimeout(c,am+500))]);let l=t.langdockProvider||"anthropic";return n["langdock-api"]=sm[l]||sm.anthropic,a&&(Wn.data=n,Wn.ts=Date.now()),n}function lm(e){let t=Xa(),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,langdockApiModel:n.langdockApiModel||null,langdockBaseUrl:n.langdockBaseUrl||null,langdockProvider:n.langdockProvider||"anthropic",hubspotUploadMode:n.hubspotUploadMode||"api",hubspotAccounts:(n.hubspotAccounts||[]).map(o=>({portalId:o.portalId,portalName:o.portalName,dataCenter:o.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,langfuseEnabled:n.langfuseEnabled,langfuseBaseUrl:n.langfuseBaseUrl||null};p(e,200,{version:hn(),environment:t,config:s,models:pa,sessionCount:Rn().length,localThemeCount:mi().length})}function cm(e,t){let n=/[?&]refresh=1\b/.test(e.url||"");Lb(n).then(s=>p(t,200,{models:s})).catch(()=>p(t,200,{models:pa}))}function dm(e,t){let n=new URL(e.url||"/","http://localhost"),s=n.searchParams.get("group")||"all",o=s==="ai"||s==="platform"?s:"all",i=n.searchParams.get("refresh")==="1",r=im[o];if(!i&&Date.now()-r.ts<Jb&&Object.keys(r.data).length>0){p(t,200,{...r.data,group:o,cached:!0});return}let a;if(o==="ai"){let l=Za();a={tools:{claudeCode:l.claudeCode,geminiCli:l.geminiCli,codexCli:l.codexCli,claudeOAuth:l.claudeOAuth},availableEngines:l.availableEngines}}else if(o==="platform")a={tools:Qa()};else{let l=to();a={tools:l.tools,availableEngines:l.availableEngines}}im[o]={data:a,ts:Date.now()},p(t,200,{...a,group:o,cached:!1})}function um(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","langdock-api"].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;case"langdock-api":r.langdockApiModel=o;break}Y(r),p(t,200,{ok:!0,engine:s})}catch(s){p(t,400,{error:s instanceof Error?s.message:String(s)})}})}function mm(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"langdock":l.langdockApiKey="";break;case"figma":l.figmaToken="";break;case"langfuse-public":l.langfusePublicKey="";break;case"langfuse-secret":l.langfuseSecretKey="";break;default:p(t,400,{error:`Unknown provider: ${s}`});return}Y(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"langdock":i.langdockApiKey=o;break;case"figma":i.figmaToken=o;break;case"langfuse-public":i.langfusePublicKey=o;break;case"langfuse-secret":i.langfuseSecretKey=o;break;default:p(t,400,{error:`Unknown provider: ${s}`});return}Y(i);let r=null;if(!R().aiEngine){let c={anthropic:"anthropic-api",openai:"openai-api",gemini:"gemini-api",langdock:"langdock-api"}[s];c&&(Y({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 pm(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=cn(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 gm(e,t){W(e,n=>{try{let s=JSON.parse(n||"{}"),o=R(),i=o.hubspotUploadMode||"api";if(s.personalAccessKey)if(i==="api"){so(s.personalAccessKey).then(r=>{Vn(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(!gt().found){p(t,400,{error:"HubSpot CLI not installed",needsInstall:!0});return}let a=Ps("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(!gt().found){p(t,400,{error:"HubSpot CLI not installed",needsInstall:!0});return}let a=ft();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 fm(e,t){W(e,n=>{try{let s=JSON.parse(n||"{}");if(!Zs().found){p(t,400,{error:"GitHub CLI not installed",needsInstall:!0});return}let i=Qs();if(i.authenticated&&!s.force){p(t,200,{ok:!0,alreadyAuthenticated:!0,username:i.username});return}if(s.token){let a=Ps("gh",["auth","login","--with-token"],"Authenticating with GitHub",{timeout:3e4,stdin:s.token});p(t,200,{ok:!0,jobId:a});return}let r=cn("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 hm(e,t){W(e,n=>{try{let{portalId:s,action:o}=JSON.parse(n);if((R().hubspotUploadMode||"api")==="api"){if(o==="remove"&&s){Ii(s),p(t,200,{ok:!0});return}if(s){Pi(s),p(t,200,{ok:!0});return}}else{if(!gt().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=Ps("hs",["accounts","remove",l],`Removing HubSpot account ${l}`,{timeout:15e3});p(t,200,{ok:!0,jobId:c});return}if(l){let c=Ps("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 ym(e){let t=cn("gh auth logout --hostname github.com -y","Logging out of GitHub",{timeout:15e3});p(e,200,{ok:!0,jobId:t})}function bm(e,t){W(e,n=>{try{let{cli:s,apiKey:o}=JSON.parse(n||"{}");switch(s){case"claude":{let i=cn("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=cn("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,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")?tm(nm(),".zshrc"):tm(nm(),".bashrc");try{(Mb(l)?Ib(l,"utf-8"):"").includes("OPENAI_API_KEY")||Pb(l,`
|
|
2688
2688
|
# Added by vibeSpot
|
|
2689
2689
|
${a}
|
|
2690
|
-
`)}catch{}}}p(t,200,{ok:!0,message:"API key saved"})}else{let i=Xt("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 ku(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}Y({hubspotUploadMode:s}),p(t,200,{ok:!0,mode:s})}catch(s){p(t,400,{error:s instanceof Error?s.message:String(s)})}})}function Tu(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}ui(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 Au(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}Y(i),p(t,200,{ok:!0,updated:Object.keys(i)})}catch(s){p(t,400,{error:s instanceof Error?s.message:String(s)})}})}function $u(e,t){let n=e.replace("/api/settings/job/","");if(!n){p(t,400,{error:"Job ID required"});return}let s=Ro(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})}var hs,Cy,pu,gu,ky,_u=R(()=>{"use strict";y();ze();Q();we();Wo();Ht();Gt();ne();Oo();hs={data:{},ts:0},Cy=600*1e3,pu={"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"}]},gu=/^(gpt-[45](\.\d+)?(-[a-z0-9-]+)?|o[1-4](-(mini|pro|nano)(-high)?)?|codex(-[a-z0-9-]+)?)$/,ky=gu});function Eu(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}mi(s.trim(),(o||"").trim());let i=O();(!i.aiEngine||i.aiEngine!=="claude-oauth")&&Y({aiEngine:"claude-oauth"}),p(t,200,{ok:!0})}catch(s){p(t,400,{error:s instanceof Error?s.message:String(s)})}})}function Mu(e,t){let n=lt(),s=En();p(t,200,{authenticated:n,expiresAt:s?.expiresAt||null})}function Iu(e,t){try{Ms(),O().aiEngine==="claude-oauth"&&Y({aiEngine:void 0}),p(t,200,{ok:!0})}catch(n){p(t,500,{error:n instanceof Error?n.message:String(n)})}}var Pu=R(()=>{"use strict";y();ze();Q();xt()});import{existsSync as My,rmSync as Iy}from"fs";import{join as Py}from"path";function Ru(e,t,n){if(e==="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(e==="DELETE"){W(t,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 Nu(e,t){W(e,n=>{try{let{sessionId:s}=JSON.parse(n),o=po(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 Ou(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}if(/[\/\\]|\.\./.test(s)||s==="."||!s.replace(/[^a-z0-9]/gi,"")){p(t,400,{error:"Invalid theme name"});return}let o=Py(st,s);if(!My(o)){p(t,404,{error:"Theme not found on disk"});return}Iy(o,{recursive:!0,force:!0}),p(t,200,{ok:!0})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function Fu(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=Fl(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)})}})}function ju(e,t){W(e,n=>{try{let{sessionId:s}=JSON.parse(n);if(!s){p(t,400,{error:"sessionId is required"});return}let o=jl(s);o.ok?p(t,200,{ok:!0,newName:o.newName,newSessionId:o.newSessionId}):p(t,400,{error:o.error})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}var Du=R(()=>{"use strict";y();ze();we();Wo()});import{existsSync as ys,readFileSync as Ry,rmSync as Ko}from"fs";import{join as Ne,basename as Ny}from"path";import{execFileSync as Oy}from"child_process";function Hu(e){let t=C();if(!t){p(e,404,{error:"No active session"});return}let n=At();p(e,200,{themeName:t.themeName,themePath:t.themePath,templates:t.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: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,hasBrandKit:!!t.brandAssets?.brandKit&&Object.keys(t.brandAssets.brandKit).length>0,brandKit:t.brandAssets?.brandKit||null}})}function Gu(e){let t=C();if(!t){p(e,404,{error:"No active session"});return}let n=t.themePath;if(!ys(n)){p(e,404,{error:"Theme directory not found"});return}let s=t.themeName||"theme",o=Ne(n,".."),i=Ny(n);try{let r=`${s}.zip`,a=Ne(o,r);ys(a)&&Ko(a),Oy("zip",["-r",r,i,"-x",`${i}/.git/*`,`${i}/.vibespot/*`,`${i}/node_modules/*`],{cwd:o,timeout:3e4,...Fy});let l=Ry(a);Ko(a),e.writeHead(200,{"Content-Type":"application/zip","Content-Disposition":`attachment; filename="${r}"`,"Content-Length":l.length}),e.end(l)}catch(r){M.error("download-zip","Failed to create zip archive",r),p(e,500,{error:"Failed to create zip archive"})}}function Uu(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.contentMode==="email"?"email":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","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(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(!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 Wu(e,t){W(e,n=>{try{let{templateId:s}=JSON.parse(n);if(!s){p(t,400,{error:"templateId is required"});return}if(!Kn(s)){p(t,404,{error:"Template not found"});return}D();let i=C();p(t,200,{ok:!0,modules:Se().map(r=>r.moduleName),messageCount:i?.messages.length||0})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function Ku(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(!Ml(s,o.trim())){p(t,404,{error:"Template not found"});return}D(),p(t,200,{ok:!0,newLabel:o.trim()})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function Vu(e,t){W(e,n=>{try{let{templateIds:s}=JSON.parse(n);if(!Array.isArray(s)||s.some(i=>typeof i!="string")){p(t,400,{error:"templateIds must be an array of strings"});return}if(!El(s)){p(t,400,{error:"Reorder rejected (length mismatch or no session)"});return}D(),p(t,200,{ok:!0})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function zu(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=_l(s,o);if(!i){p(t,404,{error:"Template not found"});return}D(),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 Yu(e){let t=At();p(e,200,{modules:t.map(n=>({moduleName:n.module.moduleName,usedIn:n.usedIn,fieldsJson:n.module.fieldsJson}))})}function qu(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=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 Xu(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(),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(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=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 Qu(e,t){p(t,200,Zu)}function Dy(e){let t=[],n=[],s=e.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(jy);if(l)for(let c of l)t.includes(c.toLowerCase())||t.push(c.toLowerCase())}if(i){let l=Lu.exec(a);if(Lu.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:t.slice(0,6),fonts:n.slice(0,4)}}function Dr(e,t){let{colors:n,fonts:s}=Dy(t);if(n.length===0&&s.length===0)return null;e.brandAssets||(e.brandAssets={});let o=e.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=Zu.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]))}e.brandAssets.brandKit=o;let i=Ne(e.themePath,".vibespot");return Ie(i),J(Ne(i,"brand-kit.json"),JSON.stringify(o,null,2)),o}function em(e,t,n){let s=C();if(!s){p(n,404,{error:"No active session"});return}if(e==="GET"){p(n,200,s.brandAssets?.brandKit||{});return}if(e==="POST"){W(t,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"&&Ly.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(e==="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 Ju(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=Ne(e.themePath,".vibespot");Ie(o),J(Ne(o,s),n)}async function Bu(e,t,n){if(t==="styleguide"){let{extractDesignContext:m}=await Promise.resolve().then(()=>(fs(),gs));return m(n||e.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(t==="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,e.brandAssets?.themeContext,r,a,l)}function tm(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 c=["styleguide","brandvoice","themeContext"],d=await Promise.allSettled(c.map(g=>Bu(n,g,r))),u={};for(let g=0;g<c.length;g++){let h=d[g],f=h.status==="fulfilled"?h.value:null;f&&Ju(n,c[g],f),u[c[g]]=f}let m=null;u.styleguide&&(m=Dr(n,u.styleguide)),D(),p(t,200,{ok:!0,type:"all",extracted:u,brandKit:m});return}if(i!=="styleguide"&&i!=="brandvoice"&&i!=="themeContext"){p(t,400,{error:`Invalid type: ${i}`});return}let a=await Bu(n,i,r);if(!a){p(t,200,{ok:!1,type:i,error:"No content to extract from"});return}Ju(n,i,a);let l=null;i==="styleguide"&&(l=Dr(n,a)),D(),p(t,200,{ok:!0,type:i,content:a,brandKit:l})}catch(o){p(t,500,{error:o instanceof Error?o.message:String(o)})}})()})}function nm(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=Fe();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 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(),Ma));await b(u,m,f),a=f}else if(o==="local"){if(!r){p(t,400,{error:"localPath is required for local import"});return}if(!ys(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(()=>(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(t,200,{ok:!0,styleguide:c,source:a})}catch(o){p(t,500,{error:o instanceof Error?o.message:String(o)})}})()})}var Fy,Zu,jy,Lu,Ly,sm=R(()=>{"use strict";y();ze();de();Q();Jn();we();ne();Fy=process.platform==="win32"?{shell:!0}:{};Zu=[{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"}];jy=/#[0-9a-fA-F]{6}\b/g,Lu=/font[- ]?famil(?:y|ies)\s*[:=]\s*([^\n]+)/gi;Ly=/^#[0-9a-fA-F]{6}$/});import{join as Jy}from"path";function om(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 im(e,t,n){let s=C();if(!s){p(n,404,{error:"No active session"});return}if(e==="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(e==="DELETE"){Ve(t,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 rm(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=Ce();c&&(o.shared==="css"?c.sharedCss=o.content:c.sharedJs=o.content),n.updatedAt=Date.now(),et(),D(),ke(),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(),et(),D(),ke(),p(t,200,{ok:!0})}catch(o){p(t,400,{error:String(o)})}})}function am(e,t){Ve(e,t,n=>{Array.isArray(n.order)?(Rt(n.order),D(),p(t,200,{ok:!0})):p(t,400,{error:"order must be an array"})})}async function lm(e){let t=C();if(!t){p(e,404,{error:"No active session"});return}try{ke();let n=Qs(t.themePath),s=No(`hs cms upload "${t.themePath}" "${t.themeName}"`,"Uploading to HubSpot",{cwd:Jy(t.themePath,".."),timeout:18e4});p(e,200,{ok:!0,jobId:s,fixes:n})}catch(n){p(e,500,{error:String(n)})}}function cm(e,t){W(e,n=>{try{let{moduleName:s,fieldPath:o,value:i}=JSON.parse(n);kl(s,o,i),D(),p(t,200,{ok:!0})}catch(s){p(t,400,{error:String(s)})}})}function dm(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=$a(s),i=o.components.map(a=>`- ${a.name}: ${a.description}`).join(`
|
|
2690
|
+
`)}catch{}}}p(t,200,{ok:!0,message:"API key saved"})}else{let i=cn("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 Sm(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}Y({hubspotUploadMode:s}),p(t,200,{ok:!0,mode:s})}catch(s){p(t,400,{error:s instanceof Error?s.message:String(s)})}})}function vm(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}Ni(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 xm(e,t){W(e,n=>{try{let s=JSON.parse(n),o=["agenticMode","agenticConcurrency","planMode","extendedThinking","extendedThinkingBudget","webSearch","langdockProvider","langfuseEnabled","langfuseBaseUrl"];if(s.extendedThinkingBudget!==void 0&&!["low","medium","high"].includes(s.extendedThinkingBudget)){p(t,400,{error:"extendedThinkingBudget must be 'low' | 'medium' | 'high'"});return}if(s.langfuseEnabled!==void 0&&typeof s.langfuseEnabled!="boolean"){p(t,400,{error:"langfuseEnabled must be a boolean"});return}if(s.langfuseBaseUrl!==void 0&&typeof s.langfuseBaseUrl!="string"){p(t,400,{error:"langfuseBaseUrl must be a string"});return}if(s.langdockProvider!==void 0&&!["anthropic","openai","google","mistral"].includes(s.langdockProvider)){p(t,400,{error:"langdockProvider must be 'anthropic' | 'openai' | 'google' | 'mistral'"});return}let i={};for(let r of o)r in s&&(i[r]=s[r]);if(i.langdockProvider){let r={anthropic:"claude-sonnet-4-6",openai:"gpt-4.1",google:"gemini-2.5-pro",mistral:"mistral-large-latest"};i.langdockApiModel=r[i.langdockProvider]||"",Wn.ts=0}if(Object.keys(i).length===0){p(t,400,{error:"No valid settings fields provided"});return}Y(i),p(t,200,{ok:!0,updated:Object.keys(i)})}catch(s){p(t,400,{error:s instanceof Error?s.message:String(s)})}})}function wm(e,t){let n=e.replace("/api/settings/job/","");if(!n){p(t,400,{error:"Job ID required"});return}let s=ti(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})}var Wn,Nb,pa,sm,rm,Rb,am,Jb,im,Cm=N(()=>{"use strict";y();Xe();ee();Ce();pi();Zt();Qt();oe();si();Wn={data:{},ts:0},Nb=600*1e3,pa={"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"}]},sm={anthropic:[{id:"claude-sonnet-4-6",label:"Claude Sonnet 4.6 (default)"},{id:"claude-opus-4-7",label:"Claude Opus 4.7"},{id:"claude-opus-4-6",label:"Claude Opus 4.6"},{id:"claude-sonnet-4-5",label:"Claude Sonnet 4.5"},{id:"claude-haiku-4-5-20251001",label:"Claude Haiku 4.5"}],openai:[{id:"gpt-4.1",label:"GPT-4.1 (default)"},{id:"gpt-4.1-mini",label:"GPT-4.1 Mini"},{id:"gpt-4.1-nano",label:"GPT-4.1 Nano"},{id:"gpt-4o",label:"GPT-4o"},{id:"o3-mini",label:"o3 Mini"}],google:[{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"}],mistral:[{id:"mistral-large-latest",label:"Mistral Large (default)"},{id:"mistral-medium-latest",label:"Mistral Medium"},{id:"mistral-small-latest",label:"Mistral Small"},{id:"codestral-latest",label:"Codestral"},{id:"pixtral-large-latest",label:"Pixtral Large"}]},rm=/^(gpt-[45](\.\d+)?(-[a-z0-9-]+)?|o[1-4](-(mini|pro|nano)(-high)?)?|codex(-[a-z0-9-]+)?)$/,Rb=rm;am=2500;Jb=60*1e3,im={ai:{data:{},ts:0},platform:{data:{},ts:0},all:{data:{},ts:0}}});function km(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}Ri(s.trim(),(o||"").trim());let i=R();(!i.aiEngine||i.aiEngine!=="claude-oauth")&&Y({aiEngine:"claude-oauth"}),p(t,200,{ok:!0})}catch(s){p(t,400,{error:s instanceof Error?s.message:String(s)})}})}function Tm(e,t){let n=Ze(),s=qt();p(t,200,{authenticated:n,expiresAt:s?.expiresAt||null})}function Am(e,t){try{zs(),R().aiEngine==="claude-oauth"&&Y({aiEngine:void 0}),p(t,200,{ok:!0})}catch(n){p(t,500,{error:n instanceof Error?n.message:String(n)})}}var _m=N(()=>{"use strict";y();Xe();ee();_t()});import{existsSync as Bb,rmSync as Hb}from"fs";import{join as Ub}from"path";function $m(e,t,n){if(e==="GET"){let s=C(),o=Rn().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);kc(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 Em(e,t){W(e,n=>{try{let{sessionId:s}=JSON.parse(n),o=Oo(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 Mm(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}if(/[\/\\]|\.\./.test(s)||s==="."||!s.replace(/[^a-z0-9]/gi,"")){p(t,400,{error:"Invalid theme name"});return}let o=Ub(dt,s);if(!Bb(o)){p(t,404,{error:"Theme not found on disk"});return}Hb(o,{recursive:!0,force:!0}),p(t,200,{ok:!0})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function Im(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=Tc(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)})}})}function Pm(e,t){W(e,n=>{try{let{sessionId:s}=JSON.parse(n);if(!s){p(t,400,{error:"sessionId is required"});return}let o=Ac(s);o.ok?p(t,200,{ok:!0,newName:o.newName,newSessionId:o.newSessionId}):p(t,400,{error:o.error})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}var Nm=N(()=>{"use strict";y();Xe();Ce();pi()});import{existsSync as Fs,readFileSync as Gb,rmSync as gi}from"fs";import{join as je,basename as Wb}from"path";import{execFileSync as Kb}from"child_process";function jm(e){let t=C();if(!t){p(e,404,{error:"No active session"});return}let n=Nt();p(e,200,{themeName:t.themeName,themePath:t.themePath,templates:t.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: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,hasBrandKit:!!t.brandAssets?.brandKit&&Object.keys(t.brandAssets.brandKit).length>0,brandKit:t.brandAssets?.brandKit||null}})}function Lm(e){let t=C();if(!t){p(e,404,{error:"No active session"});return}let n=t.themePath;if(!Fs(n)){p(e,404,{error:"Theme directory not found"});return}let s=t.themeName||"theme",o=je(n,".."),i=Wb(n);try{let r=`${s}.zip`,a=je(o,r);Fs(a)&&gi(a),Kb("zip",["-r",r,i,"-x",`${i}/.git/*`,`${i}/.vibespot/*`,`${i}/node_modules/*`],{cwd:o,timeout:3e4,...Vb});let l=Gb(a);gi(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 Jm(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.contentMode==="email"?"email":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","email"].includes(i)){p(n,400,{error:`Invalid pageType: ${i}`});return}let l=i==="email",d=Pt(l?"module_only":i,r,l?"email":void 0);l&&s.themePath&&Tn(s.themePath,s.themeName),j(),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(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(!vc(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 Bm(e,t){W(e,n=>{try{let{templateId:s}=JSON.parse(n);if(!s){p(t,400,{error:"templateId is required"});return}if(!cs(s)){p(t,404,{error:"Template not found"});return}j();let i=C();p(t,200,{ok:!0,modules:ve().map(r=>r.moduleName),messageCount:i?.messages.length||0})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function Hm(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(!Sc(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 Um(e,t){W(e,n=>{try{let{templateIds:s}=JSON.parse(n);if(!Array.isArray(s)||s.some(i=>typeof i!="string")){p(t,400,{error:"templateIds must be an array of strings"});return}if(!bc(s)){p(t,400,{error:"Reorder rejected (length mismatch or no session)"});return}j(),p(t,200,{ok:!0})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function Gm(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=yc(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 Wm(e){let t=Nt();p(e,200,{modules:t.map(n=>({moduleName:n.module.moduleName,usedIn:n.usedIn,fieldsJson:n.module.fieldsJson}))})}function Km(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=Nt().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 Vm(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=je(s.themePath,".vibespot");Re(c),J(je(c,l),r);let d=null;a==="styleguide"&&(d=fa(s,r)),j(),p(n,200,{ok:!0,brandKit:d})}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=je(s.themePath,".vibespot",a);Fs(l)&&gi(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 Ym(e,t){p(t,200,zm)}function Yb(e){let t=[],n=[],s=e.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(zb);if(l)for(let c of l)t.includes(c.toLowerCase())||t.push(c.toLowerCase())}if(i){let l=Rm.exec(a);if(Rm.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:t.slice(0,6),fonts:n.slice(0,4)}}function fa(e,t){let{colors:n,fonts:s}=Yb(t);if(n.length===0&&s.length===0)return null;e.brandAssets||(e.brandAssets={});let o=e.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=zm.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]))}e.brandAssets.brandKit=o;let i=je(e.themePath,".vibespot");return Re(i),J(je(i,"brand-kit.json"),JSON.stringify(o,null,2)),o}function qm(e,t,n){let s=C();if(!s){p(n,404,{error:"No active session"});return}if(e==="GET"){p(n,200,s.brandAssets?.brandKit||{});return}if(e==="POST"){W(t,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"&&qb.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=je(s.themePath,".vibespot");Re(a),J(je(a,"brand-kit.json"),JSON.stringify(r,null,2)),j(),p(n,200,{ok:!0,brandKit:r})}catch(i){p(n,500,{error:i instanceof Error?i.message:String(i)})}});return}if(e==="DELETE"){s.brandAssets&&delete s.brandAssets.brandKit,s.updatedAt=Date.now();let o=je(s.themePath,".vibespot","brand-kit.json");Fs(o)&&gi(o),j(),p(n,200,{ok:!0});return}p(n,405,{error:"Method not allowed"})}function Om(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=je(e.themePath,".vibespot");Re(o),J(je(o,s),n)}function Fm(e){return e==="themeContext"?"extract-theme-context":`extract-${e}`}async function Dm(e,t,n){if(t==="styleguide"){let{extractDesignContext:m}=await Promise.resolve().then(()=>(Os(),Rs));return m(n||e.themePath)}let{resolveAgenticEngine:s}=await Promise.resolve().then(()=>(Hn(),na)),{loadConfig:o}=await Promise.resolve().then(()=>(ee(),Wa)),i=o(),{engine:r,apiKey:a,model:l}=s(i),{buildPreviewHtml:c}=await Promise.resolve().then(()=>(ys(),Uo)),d=c();if(!d||d.length<50)return null;if(t==="brandvoice"){let{extractBrandvoice:m}=await Promise.resolve().then(()=>(ua(),da));return m(d,r,a,l)}let{extractThemeContext:u}=await Promise.resolve().then(()=>(ci(),li));return u(d,e.brandAssets?.themeContext,r,a,l)}function Xm(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 c=["styleguide","brandvoice","themeContext"],d=await tt({name:"brand_extract",sessionId:n.themeName,metadata:{type:"all"},tags:["vibespot","brand-extract"]},()=>Promise.allSettled(c.map(g=>te(Fm(g),()=>Dm(n,g,r))))),u={};for(let g=0;g<c.length;g++){let h=d[g],f=h.status==="fulfilled"?h.value:null;f&&Om(n,c[g],f),u[c[g]]=f}let m=null;u.styleguide&&(m=fa(n,u.styleguide)),j(),p(t,200,{ok:!0,type:"all",extracted:u,brandKit:m});return}if(i!=="styleguide"&&i!=="brandvoice"&&i!=="themeContext"){p(t,400,{error:`Invalid type: ${i}`});return}let a=await tt({name:"brand_extract",sessionId:n.themeName,metadata:{type:i},tags:["vibespot","brand-extract"]},()=>te(Fm(i),()=>Dm(n,i,r)));if(!a){p(t,200,{ok:!1,type:i,error:"No content to extract from"});return}Om(n,i,a);let l=null;i==="styleguide"&&(l=fa(n,a)),j(),p(t,200,{ok:!0,type:i,content:a,brandKit:l})}catch(o){p(t,500,{error:o instanceof Error?o.message:String(o)})}})()})}function Zm(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=Le();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 g=m.replace(/[@/]/g,"_").replace(/_+/g,"_"),{homedir:h}=await import("os"),f=je(h(),"vibespot-themes",".references",g);Re(f);let{fetchTheme:b}=await Promise.resolve().then(()=>(lo(),ml));await b(u,m,f),a=f}else if(o==="local"){if(!r){p(t,400,{error:"localPath is required for local import"});return}if(!Fs(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(()=>(Os(),Rs)),c=await tt({name:"brand_extract",sessionId:n.themeName,metadata:{type:"styleguide",source:o},tags:["vibespot","brand-extract"]},()=>te("extract-styleguide",()=>l(a)));n.brandAssets||(n.brandAssets={}),n.brandAssets.styleguide=c,n.updatedAt=Date.now();let d=je(n.themePath,".vibespot");Re(d),J(je(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)})}})()})}var Vb,zm,zb,Rm,qb,Qm=N(()=>{"use strict";y();Xe();le();Be();ee();ns();Ce();oe();Vb=process.platform==="win32"?{shell:!0}:{};zm=[{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"}];zb=/#[0-9a-fA-F]{6}\b/g,Rm=/font[- ]?famil(?:y|ies)\s*[:=]\s*([^\n]+)/gi;qb=/^#[0-9a-fA-F]{6}$/});import{join as Xb}from"path";function ep(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 tp(e,t,n){let s=C();if(!s){p(n,404,{error:"No active session"});return}if(e==="GET"){let o=ve();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"){qe(t,n,o=>{o.deleteEntirely?uc(o.moduleName):mc(o.moduleName),j(),p(n,200,{ok:!0})});return}p(n,405,{error:"Method not allowed"})}function np(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=ke();c&&(o.shared==="css"?c.sharedCss=o.content:c.sharedJs=o.content),n.updatedAt=Date.now(),at(),j(),Te(),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(),at(),j(),Te(),p(t,200,{ok:!0})}catch(o){p(t,400,{error:String(o)})}})}function sp(e,t){qe(e,t,n=>{Array.isArray(n.order)?(Ht(n.order),j(),p(t,200,{ok:!0})):p(t,400,{error:"order must be an array"})})}async function op(e){let t=C();if(!t){p(e,404,{error:"No active session"});return}try{Te();let n=Co(t.themePath),s=ni(`hs cms upload "${t.themePath}" "${t.themeName}"`,"Uploading to HubSpot",{cwd:Xb(t.themePath,".."),timeout:18e4});p(e,200,{ok:!0,jobId:s,fixes:n})}catch(n){p(e,500,{error:String(n)})}}function ip(e,t){W(e,n=>{try{let{moduleName:s,fieldPath:o,value:i}=JSON.parse(n);pc(s,o,i),j(),p(t,200,{ok:!0})}catch(s){p(t,400,{error:String(s)})}})}function rp(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=cl(s),i=o.components.map(a=>`- ${a.name}: ${a.description}`).join(`
|
|
2692
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.
|
|
2693
2693
|
|
|
2694
2694
|
Source analysis found ${o.components.length} components:
|
|
@@ -2698,19 +2698,19 @@ Design system: ${o.hasTailwind?"Tailwind CSS":"Custom CSS"}, ${o.cssVarCount} CS
|
|
|
2698
2698
|
Fonts: ${o.fonts.length>0?o.fonts.join(", "):"System fonts"}
|
|
2699
2699
|
Interactions: ${o.interactions.join(", ")}
|
|
2700
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(t,200,r)}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function um(e,t){let n=C();if(!n){p(t,404,{error:"No active session"});return}if(!Qe()){p(t,200,{available:!1,commits:[]});return}let o=new URL(e.url||"/","http://localhost").searchParams.get("templateId"),i=o?hl(n.themePath,o,50):fl(n.themePath,50);p(t,200,{available:!0,commits:i,filtered:!!o})}function mm(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(tt("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=bl(s.themePath,i,o,a);if(!l.success){p(t,500,{error:l.error||"Rollback failed"});return}zl()}else{let r=yl(s.themePath,o);if(!r.success){p(t,500,{error:r.error||"Rollback failed"});return}Vl()}D(),p(t,200,{ok:!0,modules:Se().map(r=>r.moduleName)})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}var pm=R(()=>{"use strict";y();ze();we();eo();Oo();Bs();dn()});import{writeFileSync as By,mkdirSync as fm}from"fs";import{join as Vo}from"path";import{randomUUID as Hy}from"crypto";function hm(e){let t=e.match(Gy);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 Yo(e,t){let n=await fetch(`${Uy}${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 Jr(e,t){for(let n=0;;n++)try{return await e()}catch(s){if(!(s.status===429)||n>=gm.length)throw s;let r=gm[n];M.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 Qt(e,t,n=0){if(t(e,n),e.children)for(let s of e.children)Qt(s,t,n+1)}function ym(e,t){if(e.id===t)return e;if(e.children)for(let n of e.children){let s=ym(n,t);if(s)return s}return null}function Wy(e,t){if(t){let s=ym(e,t);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=e.children?.[0];return n?.children?n.children.filter(s=>Lr.has(s.type)):[]}function zo(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 Ky(e){let t=new Map;for(let n of e)Qt(n,s=>{if(s.fills){for(let o of s.fills)if(o.type==="SOLID"&&o.color){let i=zo(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=zo(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 Vy(e){let t=new Map;for(let n of e)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=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 zy(e){let t=[],n=new Set;for(let s of e)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),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 Yy(e){let t=[],n=new Set;for(let s of e)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),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 qy(e,t){let n=[];return Qt(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 Xy(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 Zy(e){if(e.fills){for(let t of e.fills)if(t.type==="SOLID"&&t.color)return zo(t.color)}if(e.backgroundColor)return zo(e.backgroundColor)}function Qy(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:qy(t,t.name),children:(t.children||[]).slice(0,20).map(Xy),backgroundColor:Zy(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 eb(e){let t=[];for(let n of e)Qt(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 bm(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());By(t,s)}async function tb(e,t,n,s,o){if(t.length===0)return new Map;fm(s,{recursive:!0});let r=t.map(c=>c.id).join(",");o&&o("Exporting frame screenshots...");let a=await Jr(()=>Yo(`/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=Vo(s,`frame-${u}.png`);try{await bm(d,m),l.set(c,m),M.info("figma",`Downloaded frame screenshot: ${m}`)}catch(g){M.warn("figma",`Failed to download frame ${c}: ${g}`)}}return l}async function nb(e,t,n,s,o){if(t.length===0)return[];fm(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 Jr(()=>Yo(`/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 h=`${u.name.replace(/[^a-zA-Z0-9-_]/g,"-").toLowerCase()}-${Hy().slice(0,6)}.png`,f=Vo(s,h);try{await bm(m,f),r.push({name:u.name,localPath:f,nodeId:u.nodeId,format:"png"}),M.info("figma",`Downloaded asset: ${h}`)}catch(b){M.warn("figma",`Failed to download image ${u.name}: ${b}`)}}}return r}async function Sm(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 Jr(()=>Yo(i,n),o);M.info("figma",`Fetched file: ${r.name}`);let a=Wy(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.");M.info("figma",`Found ${a.length} top-level frames`),o&&o(`Found ${a.length} sections. Extracting design tokens...`);let l={colors:Ky(a),typography:Vy(a),spacing:zy(a),effects:Yy(a)};M.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=Qy(a),d=Vo(s,".vibespot","figma-frames"),u=await tb(e,a,n,d,o),m=c.map(b=>({...b,frameImagePath:u.get(b.nodeId)||""}));o&&o("Extracting image assets...");let g=eb(a),h=Vo(s,"assets"),f=await nb(e,g,n,h,o);return M.info("figma",`Extraction complete: ${m.length} sections, ${f.length} assets`),{fileName:r.name,fileUrl:`https://www.figma.com/design/${e}`,designTokens:l,sections:m,assets:f}}function xm(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 vm(e){return await Yo("/v1/me",e)}var Gy,Uy,gm,Lr,wm=R(()=>{"use strict";y();de();Gy=/figma\.com\/(?:design|file|proto)\/([a-zA-Z0-9]+)(?:\/([^?]*))?/;Uy="https://api.figma.com",gm=[10,20,40,60,120];Lr=new Set(["FRAME","COMPONENT","COMPONENT_SET","SECTION"])});var _m={};Be(_m,{getCachedExtraction:()=>$m,handleFigmaExtractRoute:()=>Hr,handleFigmaGenerateRoute:()=>Gr,handleFigmaTestTokenRoute:()=>Br});import{randomUUID as Cm}from"crypto";import{existsSync as km,mkdirSync as Tm,writeFileSync as sb,copyFileSync as ob}from"fs";import{join as qo,basename as ib}from"path";function Am(){let e=Date.now();for(let[t,n]of bs)n.expires<e&&bs.delete(t)}function $m(e){Am();let t=bs.get(e);return t?(bs.delete(e),t.extraction):null}function Br(e,t){Ve(e,t,async n=>{let s=n.token||O().figmaToken;if(!s){p(t,400,{ok:!1,error:"No Figma token provided"});return}try{let o=await vm(s);p(t,200,{ok:!0,user:o})}catch(o){let i=o instanceof Error?o.message:String(o);M.warn("figma",`Token test failed: ${i}`),p(t,200,{ok:!1,error:"Invalid or expired Figma token"})}})}function Hr(e,t){Ve(e,t,async n=>{let s=n.url;if(!s){p(t,400,{error:"Missing 'url' field"});return}let o=n.token||O().figmaToken;if(!o){p(t,400,{error:"No Figma token configured. Add one in Settings."});return}let i=hm(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-${Cm().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)}
|
|
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(t,200,r)}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function ap(e,t){let n=C();if(!n){p(t,404,{error:"No active session"});return}if(!rt()){p(t,200,{available:!1,commits:[]});return}let o=new URL(e.url||"/","http://localhost").searchParams.get("templateId"),i=o?oc(n.themePath,o,50):sc(n.themePath,50);p(t,200,{available:!0,commits:i,filtered:!!o})}function lp(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(lt("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=rc(s.themePath,i,o,a);if(!l.success){p(t,500,{error:l.error||"Rollback failed"});return}Dc()}else{let r=ic(s.themePath,o);if(!r.success){p(t,500,{error:r.error||"Rollback failed"});return}Fc()}j(),p(t,200,{ok:!0,modules:ve().map(r=>r.moduleName)})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}var cp=N(()=>{"use strict";y();Xe();Ce();ko();si();ao();Mn()});import{writeFileSync as Zb,mkdirSync as up}from"fs";import{join as fi}from"path";import{randomUUID as Qb}from"crypto";function mp(e){let t=e.match(eS);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 yi(e,t){let n=await fetch(`${tS}${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 ya(e,t){for(let n=0;;n++)try{return await e()}catch(s){if(!(s.status===429)||n>=dp.length)throw s;let r=dp[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 un(e,t,n=0){if(t(e,n),e.children)for(let s of e.children)un(s,t,n+1)}function pp(e,t){if(e.id===t)return e;if(e.children)for(let n of e.children){let s=pp(n,t);if(s)return s}return null}function nS(e,t){if(t){let s=pp(e,t);if(!s)return[];if(s.type==="FRAME"||s.type==="COMPONENT"||s.type==="COMPONENT_SET"){let o=(s.children||[]).filter(i=>ha.has(i.type));return o.length>0?o:[s]}return s.children?s.children.filter(o=>ha.has(o.type)):[]}let n=e.children?.[0];return n?.children?n.children.filter(s=>ha.has(s.type)):[]}function hi(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 sS(e){let t=new Map;for(let n of e)un(n,s=>{if(s.fills){for(let o of s.fills)if(o.type==="SOLID"&&o.color){let i=hi(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=hi(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 oS(e){let t=new Map;for(let n of e)un(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 iS(e){let t=[],n=new Set;for(let s of e)un(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 rS(e){let t=[],n=new Set;for(let s of e)un(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 aS(e,t){let n=[];return un(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 lS(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 cS(e){if(e.fills){for(let t of e.fills)if(t.type==="SOLID"&&t.color)return hi(t.color)}if(e.backgroundColor)return hi(e.backgroundColor)}function dS(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:aS(t,t.name),children:(t.children||[]).slice(0,20).map(lS),backgroundColor:cS(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 uS(e){let t=[];for(let n of e)un(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 gp(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());Zb(t,s)}async function mS(e,t,n,s,o){if(t.length===0)return new Map;up(s,{recursive:!0});let r=t.map(c=>c.id).join(",");o&&o("Exporting frame screenshots...");let a=await ya(()=>yi(`/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=fi(s,`frame-${u}.png`);try{await gp(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 pS(e,t,n,s,o){if(t.length===0)return[];up(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 ya(()=>yi(`/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 h=`${u.name.replace(/[^a-zA-Z0-9-_]/g,"-").toLowerCase()}-${Qb().slice(0,6)}.png`,f=fi(s,h);try{await gp(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 fp(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 ya(()=>yi(i,n),o);E.info("figma",`Fetched file: ${r.name}`);let a=nS(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:sS(a),typography:oS(a),spacing:iS(a),effects:rS(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=dS(a),d=fi(s,".vibespot","figma-frames"),u=await mS(e,a,n,d,o),m=c.map(b=>({...b,frameImagePath:u.get(b.nodeId)||""}));o&&o("Extracting image assets...");let g=uS(a),h=fi(s,"assets"),f=await pS(e,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/${e}`,designTokens:l,sections:m,assets:f}}function hp(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 yp(e){return await yi("/v1/me",e)}var eS,tS,dp,ha,bp=N(()=>{"use strict";y();le();eS=/figma\.com\/(?:design|file|proto)\/([a-zA-Z0-9]+)(?:\/([^?]*))?/;tS="https://api.figma.com",dp=[10,20,40,60,120];ha=new Set(["FRAME","COMPONENT","COMPONENT_SET","SECTION"])});var kp={};Ge(kp,{getCachedExtraction:()=>Cp,handleFigmaExtractRoute:()=>Sa,handleFigmaGenerateRoute:()=>va,handleFigmaTestTokenRoute:()=>ba});import{randomUUID as Sp}from"crypto";import{existsSync as vp,mkdirSync as xp,writeFileSync as gS,copyFileSync as fS}from"fs";import{join as bi,basename as hS}from"path";function wp(){let e=Date.now();for(let[t,n]of Ds)n.expires<e&&Ds.delete(t)}function Cp(e){wp();let t=Ds.get(e);return t?(Ds.delete(e),t.extraction):null}function ba(e,t){qe(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 yp(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 Sa(e,t){qe(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=mp(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-${Sp().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)}
|
|
2702
2702
|
|
|
2703
|
-
`)};try{let c=await
|
|
2704
|
-
`)}function
|
|
2703
|
+
`)};try{let c=await fp(i.fileKey,i.nodeId,o,a,m=>l({type:"progress",message:m})),d=Sp();wp(),Ds.set(d,{extraction:c,expires:Date.now()+yS});let u=hp(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 bS(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(`
|
|
2704
|
+
`)}function va(e,t){qe(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=Cp(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)}
|
|
2705
2705
|
|
|
2706
|
-
`)};try{l({type:"progress",message:"Generating styleguide from design tokens..."});let c=
|
|
2707
|
-
`)}function
|
|
2708
|
-
`),t.push(`${i}: filled meta.label = "${d.label}"`))}catch{n.push(`${i}: meta.json could not be parsed`)}let c=q(r,"fields.json");if(
|
|
2709
|
-
`),t.push(`${i}: filled ${u} missing field label(s)`))}}catch{n.push(`${i}: fields.json could not be parsed`)}}let o=xb(e);for(let i of o)t.push(`${i}: stripped external CDN reference(s)`);return{applied:t,skipped:n}}function xb(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=E(c)}catch{return}let u=d.replace(n,"");u!==d&&(J(c,u),t.push(ot(e,c)))}function a(c){let d;try{d=E(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),t.push(ot(e,c)))}Xo(q(e,"css"),".css").forEach(r);let l=q(e,"modules");if(w(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");w(u)&&r(u),w(m)&&a(m)}return t}function Im(e){let t=0;for(let n of e){if(typeof n!="object"||n===null)continue;let s=n;!yt(s,"label")&&yt(s,"name")&&(s.label=Rm(String(s.name)),t++),Array.isArray(s.children)&&(t+=Im(s.children))}return t}function Kr(e){if(!w(e))return null;try{let t=JSON.parse(E(e));return t&&typeof t=="object"?t:null}catch{return null}}function yt(e,t){let n=e[t];return typeof n=="string"?n.trim().length>0:Array.isArray(n)?n.length>0:n!=null&&n!==""}function Pm(e,t){let n=t.replace(/^\.?\//,"");return q(e,n)}function ot(e,t){return cb(e,t).split("\\").join("/")}function xs(e){try{return Vr(e)}catch{return[]}}function Xo(e,t){if(!w(e))return[];try{let n=[];for(let s of Vr(e)){let o=q(e,s);lb(o).isFile()&&s.endsWith(t)&&n.push(o)}return n}catch{return[]}}function Rm(e){return e.replace(/[-_]+/g," ").split(" ").filter(Boolean).map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" ")}var Lt,db,ub,_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"],db=["label","preview_path","screenshot_path","version","documentation_url","license","example_url"],ub=["enable_domain_stylesheets","is_available_for_new_content"],_t="marketplace.json"});function Yr(e){let t=C();if(!t)return p(e,400,{error:"No active theme. Open or create a theme first."}),null;try{ke()}catch{}return t.themePath}function Nm(e,t){let n=Yr(t);if(!n)return;let s=Ss(n);p(t,200,{report:s,categories:Lt})}function Om(e,t){let n=Yr(t);if(!n)return;let s=Qo(n),o=Ss(n);p(t,200,{fix:s,report:o})}function Fm(e,t,n){let s=Yr(n);if(s){if(e==="GET"){p(n,200,{metadata:Tn(s),categories:Lt});return}if(e==="POST"){Ve(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};Zo(s,i),p(n,200,{ok:!0,metadata:i})});return}p(n,405,{error:"Method not allowed"})}}var jm=R(()=>{"use strict";y();ze();we();zr()});function vb(e){let t=C();if(!t)return p(e,400,{error:"No active theme. Open or fetch a theme first."}),null;try{ke()}catch{}return t.themePath}function Dm(e,t){let n=vb(t);if(!n)return;let s=ho(n);p(t,200,{report:s})}function Lm(e,t){let n=C();if(!n){p(t,400,{error:"No active theme. Open or fetch a theme first."});return}let s=fn(n.themePath),o=Yn(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(),D(),p(t,200,{applied:!0,written:"session.sharedCss",rootBlock:o});return}let i=yo(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 Jm=R(()=>{"use strict";y();ze();we();bo()});import{createServer as wb}from"http";import{readFileSync as Xr,existsSync as vs}from"fs";import{join as Mt,extname as Hm}from"path";import{WebSocketServer as Cb,WebSocket as kb}from"ws";function Me(e){ti&&ti.readyState===kb.OPEN&&ti.send(JSON.stringify(e))}function ei(e){ni.push(e),Me(e)}function Et(){ni=[]}function qr(e,t){return n=>{if(n.type==="module_progress"&&n.moduleFiles){let{moduleFiles:s,...o}=n;ei(o)}else ei(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"?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)}),t.push({name:n.module,status:"complete"})):n.type==="module_progress"&&n.status==="failed"&&t.push({name:n.module,status:"failed"})}}function yn(){return Um}function si(e){let{port:t,uiDir:n}=e;Um=e.contentMode||"page";let s=wb((i,r)=>Tb(i,r,n)),o=new Cb({server:s});return o.on("connection",i=>$b(i)),new Promise((i,r)=>{s.on("error",a=>{a.code==="EADDRINUSE"?s.listen(t+1,"0.0.0.0",()=>{i({port:t+1,close:()=>{s.close(),o.close()}})}):r(a)}),s.listen(t,"0.0.0.0",()=>{i({port:t,close:()=>{s.close(),o.close()}})})})}function Tb(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==="/healthz"){t.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify({status:"ok"}));return}if(s.pathname.startsWith("/api/")){Ab(o,s.pathname,e,t);return}if(s.pathname==="/preview"){let i=Vi();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=zi(i);t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(r||"<!-- module not found -->");return}if(s.pathname.startsWith("/theme-assets/")){_b(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";Bm(i,Mt(n,"docs"),e,t);return}Bm(s.pathname,n,e,t)}function Ab(e,t,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"),e==="OPTIONS"){s.writeHead(204),s.end();return}switch(t){case"/api/session":om(e,s);break;case"/api/modules":im(e,n,s);break;case"/api/modules/reorder":am(n,s);break;case"/api/modules/code":rm(n,s);break;case"/api/upload":lm(s);break;case"/api/upload-files":e==="POST"?wc(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/field":cm(n,s);break;case"/api/import":dm(n,s);break;case"/api/setup":nu(s);break;case"/api/setup/create":su(n,s);break;case"/api/setup/fetch":iu(n,s);break;case"/api/setup/open":ru(n,s);break;case"/api/setup/resume":au(n,s);break;case"/api/setup/apikey":lu(n,s);break;case"/api/setup/remote-themes":e==="GET"?cu(s):p(s,405,{error:"Method not allowed"});break;case"/api/starters":e==="GET"?ou(s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/status":e==="GET"?fu(s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/engine":e==="POST"?hu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/apikey":e==="POST"?yu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/install":e==="POST"?bu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/hs-auth":e==="POST"?Su(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/gh-auth":e==="POST"?xu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/hs-switch":e==="POST"?vu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/gh-logout":e==="POST"?wu(s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/cli-auth":e==="POST"?Cu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/hs-mode":e==="POST"?ku(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/cli-toggle":e==="POST"?Tu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/claude-oauth/save":e==="POST"?Eu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/claude-oauth/status":e==="GET"?Mu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/claude-oauth/logout":e==="POST"?Iu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings":e==="POST"?Au(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/changelog":e==="GET"?p(s,200,{changelog:la()}):p(s,405,{error:"Method not allowed"});break;case"/api/themes":Ru(e,n,s);break;case"/api/themes/switch":e==="POST"?Nu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/themes/delete-local":e==="POST"?Ou(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/themes/rename":e==="POST"?Fu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/themes/duplicate":e==="POST"?ju(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/history":e==="GET"?um(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/rollback":e==="POST"?mm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/dashboard":e==="GET"?Hu(s):p(s,405,{error:"Method not allowed"});break;case"/api/templates":Uu(e,n,s);break;case"/api/templates/activate":e==="POST"?Wu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/templates/rename":e==="POST"?Ku(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/templates/clone":e==="POST"?zu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/templates/reorder":e==="POST"?Vu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/module-library":e==="GET"?Yu(s):p(s,405,{error:"Method not allowed"});break;case"/api/brand-assets":Xu(e,n,s);break;case"/api/brand-kit":em(e,n,s);break;case"/api/fonts":e==="GET"?Qu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/brand-assets/extract":e==="POST"?tm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/brand-assets/import-reference":e==="POST"?nm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/download-zip":e==="GET"?Gu(s):p(s,405,{error:"Method not allowed"});break;case"/api/figma/test-token":e==="POST"?Br(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/figma/extract":e==="POST"?Hr(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/figma/generate":e==="POST"?Gr(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/edit":e==="POST"?Rd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/discard":e==="POST"?Nd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/templates":e==="GET"?Od(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/template":e==="POST"?Fd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/marketplace/check":e==="GET"?Nm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/marketplace/fix":e==="POST"?Om(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/marketplace/listing":Fm(e,n,s);break;case"/api/inverse/analyze":e==="GET"?Dm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/inverse/apply-tokens":e==="POST"?Lm(n,s):p(s,405,{error:"Method not allowed"});break;default:t.startsWith("/api/settings/job/")&&e==="GET"?$u(t,s):t.match(/^\/api\/templates\/[^/]+\/add-module$/)&&e==="POST"?qu(t,n,s):p(s,404,{error:"Not found"})}}function $b(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(Tr()){tt("user",o),D();try{e.send(JSON.stringify({type:"stream_status",content:"Planning..."}));let a="",l=await kr(o,d=>{a+=d,e.send(JSON.stringify({type:"stream",content:d}))},i),c=Dd(l||a);c.plan&&(Po(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})),tt("assistant",c.cleanedContent),D(),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}tt("user",o),D();let r=Ar();r.needsPrompt&&e.send(JSON.stringify({type:"agentic_prompt"}));try{if(r.useAgentic){Et();let l=[],c=[],d=await Mo(o,qr(l,c),i);qt(d,{steps:l,modules:c,stats:d.stats})}else wr(l=>{Me({type:"parse_warning",message:l})}),await ds(o,l=>{Me({type:"stream",content:l})},l=>{Me({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=Ut(a.themePath,o);c&&Me({type:"version_created",hash:c})}Me({type:"generation_complete"});{let l=C();Me({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}))})}Et();{let l=C();l&&r.useAgentic&&!l.brandAssets?.styleguide&&!l.brandAssets?.brandvoice&&!l.brandAssets?.themeContext&&Me({type:"suggest_brand_extraction"})}}catch(a){Et(),Me({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(()=>(Ur(),_m)),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: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()}Me({type:"figma_import_started",fileName:a.fileName}),Et();let c=[],d=[],u=await us(a,i,qr(c,d));qt(u,{steps:c,modules:d,stats:u.stats}),ke(),Ut(C().themePath,`Figma import: ${a.fileName}`),Me({type:"generation_complete"});{let m=C();Me({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}))})}Et()}catch(l){Et(),Me({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=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=Mt(o.themePath,".vibespot");vs(f)||g(f,{recursive:!0}),h(Mt(f,"theme-context.md"),m),D(),e.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=Mt(o.themePath,".vibespot");vs(S)||g(S,{recursive:!0}),h(Mt(S,"styleguide.md"),b),D(),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{ke();let i=Qs(o.themePath);if(i.length>0&&e.send(JSON.stringify({type:"upload_status",phase:"autofix",fixes:i})),(O().hubspotUploadMode||"api")==="api"){let l=Fe();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 to(l,o.themePath,o.themeName,{onFileStart:d=>{e.send(JSON.stringify({type:"upload_output",chunk:`Uploading ${d}
|
|
2706
|
+
`)};try{l({type:"progress",message:"Generating styleguide from design tokens..."});let c=bS(r),d=bi(a.themePath,".vibespot");if(vp(d)||xp(d,{recursive:!0}),gS(bi(d,"styleguide.md"),c),a.brandAssets||(a.brandAssets={}),a.brandAssets.styleguide=c,j(),l({type:"progress",message:"Styleguide saved."}),a.templates.length===0)Pt("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(j(),i&&r.assets.length>0){let f=bi(a.themePath,"assets");xp(f,{recursive:!0});let b=0;for(let S of r.assets)if(vp(S.localPath)){let v=bi(f,hS(S.localPath));try{fS(S.localPath,v),S.localPath=v,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 Is(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"?He({sharedCss:f.sharedCss,sharedJs:f.sharedJs}):f.type==="blueprint_ready"?(He({sharedCss:f.sharedCss,sharedJs:f.sharedJs}),Ht(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?(He({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});ln(g,{steps:u,modules:m,stats:g.stats}),Te(),nn(a.themePath,`Figma import: ${r.fileName}`);let h=ve().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})}t.end()})}var Ds,yS,xa=N(()=>{"use strict";y();Xe();ee();le();bp();Ce();ls();gr();Mn();Hn();Ut();Ds=new Map,yS=1800*1e3});import{readdirSync as ka,statSync as SS}from"fs";import{join as q,relative as vS}from"path";function Kn(e){let t=q(e,Ft);if(!x(t))return null;try{return JSON.parse(P(t))}catch{return null}}function vi(e,t){let n=q(e,Ft);J(n,JSON.stringify(t,null,2)+`
|
|
2707
|
+
`)}function js(e){let t=[];if(!x(e))return t.push({severity:"error",rule:"theme.path.missing",message:`Theme directory not found: ${e}`}),wa(e,t,null);let n=Ca(q(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."}),wa(e,t,Kn(e));CS(e,n,t),kS(e,n,t),TS(e,t),_S(e,t),$S(e,t),ES(e,t);let s=Kn(e);return MS(s,t),wa(e,t,s)}function wa(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 CS(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 xS)kt(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 wS)(!(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.'}):(kt(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."}),kt(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."}),kt(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=$p(e,i);x(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 kS(e,t,n){let s=t.screenshot_path;if(typeof s!="string"||s.length===0)return;let o=$p(e,s);if(!x(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 TS(e,t){let n=q(e,"modules");if(!x(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=ka(n)}catch{return}for(let i of o){if(!i.endsWith(".module"))continue;s++;let r=q(n,i);AS(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 AS(e,t,n,s){let o=Ca(q(t,"meta.json")),i=ut(e,q(t,"meta.json"));o?(kt(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(t,"fields.json"),a=ut(e,r);if(!x(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=Ca(r);Array.isArray(c)?Ap(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(t,"module.html");x(l)||s.push({severity:"error",rule:"module.html.missing",file:ut(e,l),message:`${n}: module.html is missing`,fix:"Recreate the module so module.html is generated."})}function Ap(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)";kt(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}),!kt(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)&&Ap(i.children,t,n,s)}}function _S(e,t){let n=[],s=q(e,"css");Si(s,".css").forEach(i=>{Tp(i,n,e)});let o=q(e,"modules");if(x(o))for(let i of Ls(o)){if(!i.endsWith(".module"))continue;let r=q(o,i);["module.css","module.html"].forEach(a=>{let l=q(r,a);x(l)&&Tp(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 Tp(e,t,n){let s;try{s=P(e)}catch{return}let o=s.match(/@import\s+url\(['"]?https?:\/\/[^)\s'"]+['"]?\)/i);o&&t.push({file:ut(n,e),match:o[0]});let i=s.match(/<link[^>]+href=['"]https?:\/\/[^'"]+['"][^>]*>/i);i&&t.push({file:ut(n,e),match:i[0]});let r=s.match(/<script[^>]+src=['"]https?:\/\/[^'"]+['"][^>]*>/i);r&&t.push({file:ut(n,e),match:r[0]})}function $S(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=q(e,"css");Si(o,".css").forEach(a=>s.push(a));let i=q(e,"js");Si(i,".js").forEach(a=>s.push(a));let r=q(e,"modules");if(x(r))for(let a of Ls(r))a.endsWith(".module")&&["module.html","module.css","module.js"].forEach(l=>{let c=q(r,a,l);x(c)&&s.push(c)});for(let a of s){let l;try{l=P(a)}catch{continue}for(let c of n){let d=l.match(c.re);d&&t.push({severity:"error",rule:c.rule,file:ut(e,a),message:`${c.message}: ${d[0]}`,fix:"Replace portal-specific URLs with theme-relative paths or HubSpot tokens like get_asset_url."})}}}function ES(e,t){let n=q(e,"modules");if(x(n))for(let s of Ls(n)){if(!s.endsWith(".module"))continue;let o=q(n,s,"module.html");if(!x(o))continue;let i;try{i=P(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:ut(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:ut(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 MS(e,t){if(!e){t.push({severity:"warning",rule:"marketplace.json.missing",file:Ft,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?zt.includes(e.category)||t.push({severity:"warning",rule:"marketplace.json.category.unknown",file:Ft,message:`marketplace.json category "${e.category}" is not a recognized HubSpot Marketplace category`,fix:`Use one of: ${zt.join(", ")}.`}):t.push({severity:"warning",rule:"marketplace.json.category.missing",file:Ft,message:"marketplace.json has no category",fix:`Pick one of: ${zt.join(", ")}.`}),(!e.description||e.description.trim().length<40)&&t.push({severity:"warning",rule:"marketplace.json.description.short",file:Ft,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:Ft,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:Ft,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:Ft,message:`marketplace.json has ${n} features but HubSpot allows at most 5`,fix:"Trim the features list to 5 or fewer entries."})}function xi(e){let t=[],n=[],s=q(e,"modules");if(x(s))for(let i of Ls(s)){if(!i.endsWith(".module"))continue;let r=q(s,i),a=i.replace(/\.module$/,""),l=q(r,"meta.json");if(x(l))try{let d=JSON.parse(P(l));kt(d,"label")||(d.label=Ep(a),J(l,JSON.stringify(d,null,2)+`
|
|
2708
|
+
`),t.push(`${i}: filled meta.label = "${d.label}"`))}catch{n.push(`${i}: meta.json could not be parsed`)}let c=q(r,"fields.json");if(x(c))try{let d=JSON.parse(P(c));if(Array.isArray(d)){let u=_p(d);u>0&&(J(c,JSON.stringify(d,null,2)+`
|
|
2709
|
+
`),t.push(`${i}: filled ${u} missing field label(s)`))}}catch{n.push(`${i}: fields.json could not be parsed`)}}let o=IS(e);for(let i of o)t.push(`${i}: stripped external CDN reference(s)`);return{applied:t,skipped:n}}function IS(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=P(c)}catch{return}let u=d.replace(n,"");u!==d&&(J(c,u),t.push(ut(e,c)))}function a(c){let d;try{d=P(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),t.push(ut(e,c)))}Si(q(e,"css"),".css").forEach(r);let l=q(e,"modules");if(x(l))for(let c of Ls(l)){if(!c.endsWith(".module"))continue;let d=q(l,c),u=q(d,"module.css"),m=q(d,"module.html");x(u)&&r(u),x(m)&&a(m)}return t}function _p(e){let t=0;for(let n of e){if(typeof n!="object"||n===null)continue;let s=n;!kt(s,"label")&&kt(s,"name")&&(s.label=Ep(String(s.name)),t++),Array.isArray(s.children)&&(t+=_p(s.children))}return t}function Ca(e){if(!x(e))return null;try{let t=JSON.parse(P(e));return t&&typeof t=="object"?t:null}catch{return null}}function kt(e,t){let n=e[t];return typeof n=="string"?n.trim().length>0:Array.isArray(n)?n.length>0:n!=null&&n!==""}function $p(e,t){let n=t.replace(/^\.?\//,"");return q(e,n)}function ut(e,t){return vS(e,t).split("\\").join("/")}function Ls(e){try{return ka(e)}catch{return[]}}function Si(e,t){if(!x(e))return[];try{let n=[];for(let s of ka(e)){let o=q(e,s);SS(o).isFile()&&s.endsWith(t)&&n.push(o)}return n}catch{return[]}}function Ep(e){return e.replace(/[-_]+/g," ").split(" ").filter(Boolean).map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" ")}var zt,xS,wS,Ft,Ta=N(()=>{"use strict";y();oe();zt=["Business Services","Education","Events","Health & Wellness","Hospitality","Marketing & SEO","Non-profit","Portfolio","Real Estate","Restaurant & Food","Retail & E-commerce","SaaS & Technology","Travel","Other"],xS=["label","preview_path","screenshot_path","version","documentation_url","license","example_url"],wS=["enable_domain_stylesheets","is_available_for_new_content"],Ft="marketplace.json"});function Aa(e){let t=C();if(!t)return p(e,400,{error:"No active theme. Open or create a theme first."}),null;try{Te()}catch{}return t.themePath}function Mp(e,t){let n=Aa(t);if(!n)return;let s=js(n);p(t,200,{report:s,categories:zt})}function Ip(e,t){let n=Aa(t);if(!n)return;let s=xi(n),o=js(n);p(t,200,{fix:s,report:o})}function Pp(e,t,n){let s=Aa(n);if(s){if(e==="GET"){p(n,200,{metadata:Kn(s),categories:zt});return}if(e==="POST"){qe(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};vi(s,i),p(n,200,{ok:!0,metadata:i})});return}p(n,405,{error:"Method not allowed"})}}var Np=N(()=>{"use strict";y();Xe();Ce();Ta()});function PS(e){let t=C();if(!t)return p(e,400,{error:"No active theme. Open or fetch a theme first."}),null;try{Te()}catch{}return t.themePath}function Rp(e,t){let n=PS(t);if(!n)return;let s=jo(n);p(t,200,{report:s})}function Op(e,t){let n=C();if(!n){p(t,400,{error:"No active theme. Open or fetch a theme first."});return}let s=On(n.themePath),o=ms(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=Lo(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 Fp=N(()=>{"use strict";y();Xe();Ce();Jo()});import{createServer as NS}from"http";import{readFileSync as Ea,existsSync as Js}from"fs";import{join as jt,extname as jp}from"path";import{WebSocketServer as RS,WebSocket as OS}from"ws";function Ae(e){Ci&&Ci.readyState===OS.OPEN&&Ci.send(JSON.stringify(e))}function wi(e){ki.push(e),Ae(e)}function Dt(){ki=[]}function _a(e,t){return n=>{if(n.type==="module_progress"&&n.moduleFiles){let{moduleFiles:s,...o}=n;wi(o)}else wi(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"?He({sharedCss:n.sharedCss,sharedJs:n.sharedJs}):n.type==="blueprint_ready"?(He({sharedCss:n.sharedCss,sharedJs:n.sharedJs}),Ht(n.moduleOrder),wi({type:"modules_updated",modules:ve().map(s=>s.moduleName)})):n.type==="module_progress"&&n.status==="complete"&&n.moduleFiles?(He({modules:[{moduleName:n.module,fieldsJson:n.moduleFiles.fieldsJson,metaJson:n.moduleFiles.metaJson,moduleHtml:n.moduleFiles.moduleHtml,moduleCss:n.moduleFiles.moduleCss,moduleJs:n.moduleFiles.moduleJs}]}),wi({type:"modules_updated",modules:ve().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 $a(e){let t=e.cost;if(!t||t.calls===0)return;let n=C();Ae({type:"generation_cost",cost:t,projectTotal:n?.costTotal})}function Dn(){return Jp}function Ti(e){let{port:t,uiDir:n}=e;Jp=e.contentMode||"page";let s=NS((i,r)=>FS(i,r,n)),o=new RS({server:s});return o.on("connection",i=>jS(i)),new Promise((i,r)=>{s.on("error",a=>{a.code==="EADDRINUSE"?s.listen(t+1,"0.0.0.0",()=>{i({port:t+1,close:()=>{s.close(),o.close()}})}):r(a)}),s.listen(t,"0.0.0.0",()=>{i({port:t,close:()=>{s.close(),o.close()}})})})}function FS(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==="/healthz"){t.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),t.end(JSON.stringify({status:"ok"}));return}if(s.pathname.startsWith("/api/")){DS(o,s.pathname,e,t);return}if(s.pathname==="/preview"){let i=br();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=Sr(i);t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(r||"<!-- module not found -->");return}if(s.pathname.startsWith("/theme-assets/")){LS(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";Dp(i,jt(n,"docs"),e,t);return}Dp(s.pathname,n,e,t)}function DS(e,t,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"),e==="OPTIONS"){s.writeHead(204),s.end();return}switch(t){case"/api/session":ep(e,s);break;case"/api/modules":tp(e,n,s);break;case"/api/modules/reorder":sp(n,s);break;case"/api/modules/code":np(n,s);break;case"/api/upload":op(s);break;case"/api/upload-files":e==="POST"?ld(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/field":ip(n,s);break;case"/api/import":rp(n,s);break;case"/api/setup":Vu(s);break;case"/api/setup/create":zu(n,s);break;case"/api/setup/fetch":qu(n,s);break;case"/api/setup/open":Xu(n,s);break;case"/api/setup/resume":Zu(n,s);break;case"/api/setup/apikey":Qu(n,s);break;case"/api/setup/remote-themes":e==="GET"?em(s):p(s,405,{error:"Method not allowed"});break;case"/api/starters":e==="GET"?Yu(s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/status":e==="GET"?lm(s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/models":e==="GET"?cm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/tools":e==="GET"?dm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/engine":e==="POST"?um(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/apikey":e==="POST"?mm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/install":e==="POST"?pm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/hs-auth":e==="POST"?gm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/gh-auth":e==="POST"?fm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/hs-switch":e==="POST"?hm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/gh-logout":e==="POST"?ym(s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/cli-auth":e==="POST"?bm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/hs-mode":e==="POST"?Sm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/cli-toggle":e==="POST"?vm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/claude-oauth/save":e==="POST"?km(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/claude-oauth/status":e==="GET"?Tm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/claude-oauth/logout":e==="POST"?Am(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings":e==="POST"?xm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/changelog":e==="GET"?p(s,200,{changelog:Ja()}):p(s,405,{error:"Method not allowed"});break;case"/api/themes":$m(e,n,s);break;case"/api/themes/switch":e==="POST"?Em(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/themes/delete-local":e==="POST"?Mm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/themes/rename":e==="POST"?Im(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/themes/duplicate":e==="POST"?Pm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/history":e==="GET"?ap(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/rollback":e==="POST"?lp(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/dashboard":e==="GET"?jm(s):p(s,405,{error:"Method not allowed"});break;case"/api/templates":Jm(e,n,s);break;case"/api/templates/activate":e==="POST"?Bm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/templates/rename":e==="POST"?Hm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/templates/clone":e==="POST"?Gm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/templates/reorder":e==="POST"?Um(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/module-library":e==="GET"?Wm(s):p(s,405,{error:"Method not allowed"});break;case"/api/brand-assets":Vm(e,n,s);break;case"/api/brand-kit":qm(e,n,s);break;case"/api/fonts":e==="GET"?Ym(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/brand-assets/extract":e==="POST"?Xm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/brand-assets/import-reference":e==="POST"?Zm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/download-zip":e==="GET"?Lm(s):p(s,405,{error:"Method not allowed"});break;case"/api/figma/test-token":e==="POST"?ba(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/figma/extract":e==="POST"?Sa(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/figma/generate":e==="POST"?va(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/edit":e==="POST"?ku(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/discard":e==="POST"?Tu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/templates":e==="GET"?Au(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/template":e==="POST"?_u(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/marketplace/check":e==="GET"?Mp(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/marketplace/fix":e==="POST"?Ip(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/marketplace/listing":Pp(e,n,s);break;case"/api/inverse/analyze":e==="GET"?Rp(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/inverse/apply-tokens":e==="POST"?Op(n,s):p(s,405,{error:"Method not allowed"});break;default:t.startsWith("/api/settings/job/")&&e==="GET"?wm(t,s):t.match(/^\/api\/templates\/[^/]+\/add-module$/)&&e==="POST"?Km(t,n,s):p(s,404,{error:"Not found"})}}function jS(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(ea()){lt("user",o),j();try{e.send(JSON.stringify({type:"stream_status",content:"Planning..."}));let a="",l=await Qr(o,d=>{a+=d,e.send(JSON.stringify({type:"stream",content:d}))},i),c=Eu(l||a);c.plan&&(ei(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})),lt("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}lt("user",o),j();let r=ta();r.needsPrompt&&e.send(JSON.stringify({type:"agentic_prompt"}));try{if(r.useAgentic){Dt();let l=[],c=[],d=await Zo(o,_a(l,c),i);ln(d,{steps:l,modules:c,stats:d.stats,cost:d.cost}),$a(d)}else Xr(l=>{Ae({type:"parse_warning",message:l})}),await Ms(o,l=>{Ae({type:"stream",content:l})},l=>{Ae({type:"stream_status",content:l})},i);let a=C();if(a){Te();let l=ke(),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=sr(a.themePath,l.id,o,d)}else c=nn(a.themePath,o);c&&Ae({type:"version_created",hash:c})}Ae({type:"generation_complete"});{let l=C();Ae({type:"modules_updated",modules:ve().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}))})}Dt();{let l=C();l&&r.useAgentic&&!l.brandAssets?.styleguide&&!l.brandAssets?.brandvoice&&!l.brandAssets?.themeContext&&Ae({type:"suggest_brand_extraction"})}}catch(a){Dt(),Ae({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(()=>(xa(),kp)),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:g}=await import("os"),{existsSync:h}=await import("fs"),{createThemeScaffold:f}=await Promise.resolve().then(()=>(ns(),dl)),b=m(g(),"vibespot-themes"),S=m(b,i);if(!h(b)){let{mkdirSync:v}=await import("fs");v(b,{recursive:!0})}h(S)||f(S,i),Nn(S,i),j()}Ae({type:"figma_import_started",fileName:a.fileName}),Dt();let c=[],d=[],u=await Is(a,i,_a(c,d));ln(u,{steps:c,modules:d,stats:u.stats,cost:u.cost}),$a(u),Te(),nn(C().themePath,`Figma import: ${a.fileName}`),Ae({type:"generation_complete"});{let m=C();Ae({type:"modules_updated",modules:ve().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}))})}Dt()}catch(l){Dt(),Ae({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}=Bn(i),{buildPreviewHtml:c}=await Promise.resolve().then(()=>(ys(),Uo)),d=c();if(!d||d.length<50)return;let{extractThemeContext:u}=await Promise.resolve().then(()=>(ci(),li)),m=await tt({name:"brand_extract",sessionId:o.themeName,metadata:{type:"themeContext"},tags:["vibespot","brand-extract"]},()=>te("extract-theme-context",()=>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=jt(o.themePath,".vibespot");Js(f)||g(f,{recursive:!0}),h(jt(f,"theme-context.md"),m),j(),e.send(JSON.stringify({type:"brand_asset_extracted",assetType:"themeContext"}))}if(!o.brandAssets?.styleguide)try{let{extractDesignContext:f}=await Promise.resolve().then(()=>(Os(),Rs)),b=await tt({name:"brand_extract",sessionId:o.themeName,metadata:{type:"styleguide"},tags:["vibespot","brand-extract"]},()=>te("extract-styleguide",()=>f(o.themePath)));if(b){o.brandAssets||(o.brandAssets={}),o.brandAssets.styleguide=b,o.updatedAt=Date.now();let S=jt(o.themePath,".vibespot");Js(S)||g(S,{recursive:!0}),h(jt(S,"styleguide.md"),b),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{Te();let i=Co(o.themePath);if(i.length>0&&e.send(JSON.stringify({type:"upload_status",phase:"autofix",fixes:i})),(R().hubspotUploadMode||"api")==="api"){let l=Le();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 To(l,o.themePath,o.themeName,{onFileStart:d=>{e.send(JSON.stringify({type:"upload_output",chunk:`Uploading ${d}
|
|
2710
2710
|
`}))},onFileComplete:d=>{e.send(JSON.stringify({type:"upload_output",chunk:` \u2713 ${d}
|
|
2711
2711
|
`}))},onFileError:(d,u)=>{e.send(JSON.stringify({type:"upload_output",chunk:` \u2717 ${d}: ${u.message}
|
|
2712
|
-
`}))},onProgress:(d,u)=>{e.send(JSON.stringify({type:"upload_progress",completed:d,total:u}))}});if(c.success){let d=
|
|
2713
|
-
`),errors:d}))}}else{let l=
|
|
2712
|
+
`}))},onProgress:(d,u)=>{e.send(JSON.stringify({type:"upload_progress",completed:d,total:u}))}});if(c.success){let d=Lt();e.send(JSON.stringify({type:"upload_complete",output:`Uploaded ${c.uploaded} files`,portalId:d?.portalId||"",dataCenter:d?.dataCenter||"na1",themeName:o.themeName,contentMode:Dn()}))}else{let d=xo(c.errors);e.send(JSON.stringify({type:"upload_failed",output:c.errors.map(u=>`${u.file}: ${u.message}`).join(`
|
|
2713
|
+
`),errors:d}))}}else{let l=ni(`hs cms upload "${o.themePath}" "${o.themeName}"`,"Uploading to HubSpot",{cwd:jt(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}))};Pu(l,c);let d=setInterval(()=>{let u=ti(l);if(!(!u||u.status==="running"))if(clearInterval(d),Nu(l,c),u.status==="completed"){let m=ft(),g=m.portalId?Xn(m.portalId):"na1";e.send(JSON.stringify({type:"upload_complete",output:u.output,portalId:m.portalId||"",dataCenter:g,themeName:o.themeName,contentMode:Dn()}))}else{let m=wo(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.
|
|
2714
2714
|
|
|
2715
2715
|
IMPORTANT: Be verbose in your response. For each error:
|
|
2716
2716
|
1. State exactly which file has the problem and what the error is
|
|
@@ -2723,27 +2723,27 @@ CRITICAL: After fixing the reported errors, scan ALL other module files in the t
|
|
|
2723
2723
|
After fixing all errors, summarize the changes you made.
|
|
2724
2724
|
|
|
2725
2725
|
Upload log:
|
|
2726
|
-
${o}`;
|
|
2726
|
+
${o}`;lt("user",i),j(),e.send(JSON.stringify({type:"upload_fix_started"}));try{await Ms(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){Te();let a=nn(r.themePath,"AI fix: upload errors");a&&e.send(JSON.stringify({type:"version_created",hash:a}))}e.send(JSON.stringify({type:"upload_fix_complete"}));{let a=C();e.send(JSON.stringify({type:"modules_updated",modules:ve().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){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}Y({planMode:!1});let r="Implement the approved plan.";lt("user",r),j();try{Dt();let a=[],l=[],c=await Zo(r,_a(a,l));ln(c,{steps:a,modules:l,stats:c.stats,cost:c.cost}),$a(c);let d=C();if(d){Te();let u=ke(),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=sr(d.themePath,u.id,"Approved plan: implementation",g)}else m=nn(d.themePath,"Approved plan: implementation");m&&Ae({type:"version_created",hash:m})}Ae({type:"generation_complete"});{let u=C();Ae({type:"modules_updated",modules:ve().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}))})}Dt()}catch(a){Dt(),Ae({type:"error",message:a instanceof Error?a.message:String(a)})}break}case"plan_discard":{sa(),Y({planMode:!1}),e.send(JSON.stringify({type:"plan_discarded"}));break}default:e.send(JSON.stringify({type:"error",message:`Unknown type: ${s.type}`}))}}),Ci=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=Wt(),i=ke();if(e.send(JSON.stringify({type:"init",sessionId:t.id,themeName:t.themeName,modules:ve().map(r=>r.moduleName),messageCount:t.messages.length,messages:t.messages,gitAvailable:rt(),engine:n.aiEngine?s[n.aiEngine]||n.aiEngine:"",updatedAt:t.updatedAt,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,costTotal:t.costTotal||null})),o&&ki.length>0)for(let r of ki)e.send(JSON.stringify(r))}else e.send(JSON.stringify({type:"needs_setup"}))}function LS(e,t){let n=C();if(!n){t.writeHead(404,{"Content-Type":"text/plain"}),t.end("No session");return}let s=jt(n.themePath,"assets",e);if(!Js(s)){t.writeHead(404,{"Content-Type":"text/plain"}),t.end("Asset not found");return}let o=jp(s),i=Lp[o]||"application/octet-stream",r=Ea(s);t.writeHead(200,{"Content-Type":i,"Cache-Control":"no-cache"}),t.end(r)}function Dp(e,t,n,s){let i=jt(t,e==="/"?"/index.html":e);if(!Js(i)){let c=jt(t,"index.html");if(Js(c)){let d=Ea(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=jp(i),a=Lp[r]||"application/octet-stream",l=r===".html";try{let c=Ea(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 Lp,Ci,ki,Jp,bs=N(()=>{"use strict";y();Ce();Mn();ys();Hn();$u();Mu();ee();Zt();ko();si();tr();Xe();oe();Be();pi();Cm();_m();Nm();Qm();cp();Nr();xa();Np();Fp();Lp={".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"},Ci=null,ki=[];Jp="page"});y();y();import{Command as ZS}from"commander";y();y();pt();oe();function Ee(){let e=I.vibes,t=I.accent,n=I.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")} ${I.dim(`v${hn()}`)}`),console.log()}y();Zt();_t();Yt();ee();Qt();Qe();pt();async function io(){await ge("Checking your environment");let e=Yn();e.found||(V("Node.js not found. Install it from https://nodejs.org"),process.exit(1)),eo(e.version)||(V(`Node.js ${e.version} is too old. Version 18+ required. Update at https://nodejs.org`),process.exit(1)),G(`Node.js v${e.version}`);let t=qn();t.found||(V("Git not found. Install it from https://git-scm.com"),process.exit(1)),G(`Git ${t.version}`);let n=R(),s=n.hubspotUploadMode!=="cli",o="",i="";if(s){let b=Le(),S=Lt();if(b)o=S?.portalId||"",i=S?.portalName||"",G(`HubSpot${i?`: ${i}`:""}${o?` (${o})`:""} \u2014 API mode`);else{se("No HubSpot account connected"),await ht(`You need a Personal Access Key to deploy themes.
|
|
2727
2727
|
Create one at: https://app.hubspot.com/l/personal-access-key
|
|
2728
|
-
Make sure the Content scope is enabled.`,"HubSpot connection required");let
|
|
2728
|
+
Make sure the Content scope is enabled.`,"HubSpot connection required");let v=await Se({message:"Paste your Personal Access Key:",placeholder:"pat-na1-...",validate:M=>M.trim()?void 0:"Key is required"}),w=await Fe();w.start("Validating key...");try{let M=await so(v);Vn(v,M.portalId,M.portalName,M.dataCenter),b=v,o=M.portalId,i=M.portalName,w.stop(`Connected to ${M.portalName} (${M.portalId})`)}catch(M){w.stop("Validation failed"),V(`Invalid key: ${M instanceof Error?M.message:String(M)}`),process.exit(1)}}}else{let b=gt();if(b.found)G(`HubSpot CLI v${b.version}`);else{se("HubSpot CLI not found"),await Me({message:"Install HubSpot CLI globally?"})||(V("HubSpot CLI is required in CLI mode. Install: npm install -g @hubspot/cli"),process.exit(1));let w=await Fe();w.start("Installing HubSpot CLI..."),ie("npm install -g @hubspot/cli").success||(w.stop("Failed"),V("Try: npm install -g @hubspot/cli"),process.exit(1)),b=gt(),w.stop(`HubSpot CLI v${b.version} installed`)}let S=ft();if(S.authenticated)G(`HubSpot portal${S.portalName?`: ${S.portalName}`:""} (ID: ${S.portalId})`);else{se("HubSpot not authenticated"),await Me({message:"Run `hs init` now?"})||(V("Run `hs init` manually."),process.exit(1));let w=await Fe();w.start("Waiting for HubSpot authentication..."),Ha("hs init")||(w.stop("Authentication failed"),process.exit(1)),S=ft(),w.stop(`Connected to portal${S.portalName?`: ${S.portalName}`:""} (ID: ${S.portalId})`)}o=S.portalId,i=S.portalName}let r=xn(),a=wn(),l=Cn(),c=Ya(),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","langdock-api":"Langdock (EU)"},u=Ze(),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 Et({message:"Choose your AI engine:",options:h});else if(await ht(`You need an AI coding assistant to power the conversion.
|
|
2729
2729
|
|
|
2730
|
-
${
|
|
2730
|
+
${I.bold("Option 1:")} Install Claude Code ${I.muted("(recommended)")}
|
|
2731
2731
|
https://claude.ai/code
|
|
2732
2732
|
|
|
2733
|
-
${
|
|
2733
|
+
${I.bold("Option 2:")} Install Gemini CLI
|
|
2734
2734
|
https://github.com/google-gemini/gemini-cli
|
|
2735
2735
|
|
|
2736
|
-
${
|
|
2736
|
+
${I.bold("Option 3:")} Install OpenAI Codex
|
|
2737
2737
|
https://github.com/openai/codex
|
|
2738
2738
|
|
|
2739
|
-
${
|
|
2739
|
+
${I.bold("Option 4:")} Set an Anthropic API key
|
|
2740
2740
|
export ANTHROPIC_API_KEY=sk-ant-...
|
|
2741
|
-
(get one at https://console.anthropic.com)`,"AI engine required"),m=await
|
|
2741
|
+
(get one at https://console.anthropic.com)`,"AI engine required"),m=await Et({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 Se({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 Et({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 fe("Environment ready!"),{aiEngine:m,model:f,portalId:o,portalName:i}}ao();y();Yt();oe();Qe();pt();ee();ns();lo();import{join as os}from"path";async function co(){await ge("HubSpot Theme Setup");let e=await Et({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=os(process.cwd(),"workspace");if(Re(s),e==="fetch"){t=await Se({message:"What's your theme name in HubSpot?",placeholder:"My-Company-Theme",validate:u=>u.trim()?void 0:"Theme name is required"}),n=os(s,t);let l=await Fe();l.start("Fetching theme from HubSpot...");let c=R(),d=Le();if(c.hubspotUploadMode==="cli"||!d)ie(`hs cms fetch "${t}" "${n}"`).success||(l.stop("Fetch failed"),V(`Could not fetch theme "${t}". Check the name in HubSpot Design Manager.`),process.exit(1));else try{await ss(d,t,n)}catch(u){l.stop("Fetch failed"),V(`Could not fetch theme "${t}": ${u instanceof Error?u.message:String(u)}`),process.exit(1)}l.stop(`Theme fetched: ${I.dim(n)}`)}else{t=await Se({message:"Name for your new theme:",placeholder:"my-theme",defaultValue:"my-theme"}),n=os(s,t);let l=await Fe();l.start("Creating theme...");try{ts(n,t)}catch(c){l.stop("Creation failed"),V(`Could not create theme "${t}": ${c instanceof Error?c.message:String(c)}`),process.exit(1)}l.stop(`Theme created: ${I.dim(n)}`)}await ge("Checking theme compatibility");let o=os(n,"templates/layouts/base.html");x(o)||(V(`base.html not found at ${o}. Your theme may have a different structure.`),process.exit(1)),G("base.html found");let i=P(o),r=!1;if(i.includes("template_css"))G("template_css support");else{se("Missing template_css support in base.html");let l=i.indexOf("theme-overrides.css")!==-1?i.indexOf("{{",i.lastIndexOf(`
|
|
2742
2742
|
`,i.indexOf("theme-overrides.css"))):i.lastIndexOf("require_css");if(l>0){let c=i.lastIndexOf(`
|
|
2743
2743
|
`,l);i=i.slice(0,c)+`
|
|
2744
2744
|
{% if template_css %}
|
|
2745
2745
|
{{ require_css(get_asset_url(template_css)) }}
|
|
2746
|
-
{% endif %}`+i.slice(c),r=!0}}if(i.includes("template_js"))
|
|
2746
|
+
{% endif %}`+i.slice(c),r=!0}}if(i.includes("template_js"))G("template_js support");else{se("Missing template_js support in base.html");let l=i.indexOf("require_js");if(l>0){let c=i.indexOf(`
|
|
2747
2747
|
`,l),d=i.indexOf(`
|
|
2748
2748
|
`,c+1),u=`
|
|
2749
2749
|
{% if template_js %}
|
|
@@ -2751,17 +2751,17 @@ ${_.bold("Option 4:")} Set an Anthropic API key
|
|
|
2751
2751
|
{% endif %}`,m=i.indexOf("}}",l)+2+i.slice(i.indexOf("}}",l)+2).indexOf(`
|
|
2752
2752
|
`)+1;i=i.slice(0,i.indexOf(`
|
|
2753
2753
|
`,i.indexOf("}}",l)+2))+u+i.slice(i.indexOf(`
|
|
2754
|
-
`,i.indexOf("}}",l)+2)),r=!0}}if(r){let l=await
|
|
2754
|
+
`,i.indexOf("}}",l)+2)),r=!0}}if(r){let l=await Fe();l.start("Patching base.html..."),J(o,i),l.stop("base.html patched with template_css/template_js support")}let a=os(n,".hsignore");if(x(a)){let l=P(a);l.includes("docs/")||(J(a,l+`
|
|
2755
2755
|
docs/
|
|
2756
|
-
`),
|
|
2756
|
+
`),G("Added docs/ to .hsignore"))}else J(a,`docs/
|
|
2757
2757
|
*.md
|
|
2758
2758
|
node_modules/
|
|
2759
2759
|
.git
|
|
2760
|
-
`),
|
|
2760
|
+
`),G("Created .hsignore");return await fe("Theme ready!"),{themePath:n,themeName:t}}y();import{join as nt}from"path";import{readdirSync as as,rmSync as El}from"fs";y();Ke();oe();import{spawn as Eg}from"child_process";import{join as Q,basename as Mg}from"path";import{readdirSync as yt,statSync as xl,writeFileSync as Ig}from"fs";var Pg=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"]),uo=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||ye();this.reported.clear(),this.moduleCount=0,this.expectedModules=0;let r=this.countSourceComponents(n),a=this.listModules(s),l=this.listDir(Q(s,"css")),c=this.listDir(Q(s,"js")),d=this.listDir(Q(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((v,w)=>{let M={...process.env};delete M.CLAUDECODE;let L=["--print","--max-turns","50","--allowedTools","Read,Glob,Grep,Write,Edit,Bash"];this.model&&L.push("--model",this.model);let H=Eg("claude",L,{cwd:s,stdio:["pipe","pipe","pipe"],env:M,shell:!0});H.stdout.on("data",B=>{m+=B.toString()}),H.stderr.on("data",B=>{g+=B.toString()}),H.on("error",B=>w(new Error(`Claude Code failed to start: ${B.message}`))),H.on("close",B=>{B!==0?w(new Error(`Claude Code exited with code ${B}.
|
|
2761
2761
|
`+(g?`Stderr: ${g.slice(0,500)}
|
|
2762
|
-
`:"")+(m?`Output: ${m.slice(0,500)}`:"No output"))):
|
|
2762
|
+
`:"")+(m?`Output: ${m.slice(0,500)}`:"No output"))):v()}),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=Q(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
2763
|
... (truncated, full guide follows)`,"","=== CLAUDE CODE STDOUT ===",m||"(empty)","","=== CLAUDE CODE STDERR ===",g||"(empty)",""].join(`
|
|
2764
|
-
`);
|
|
2764
|
+
`);Ig(f,w,"utf-8"),o("status",`Log written to ${Mg(f)}`)}catch{}o("scan","Scanning generated files...");let b=this.scanGeneratedFiles(s);if(b.modules.filter(v=>!a.has(v.moduleName+".module")).length===0){let v=m.slice(0,1500)||"(no output)",w=g.slice(0,500);throw new Error(`Claude Code did not create any new module files.
|
|
2765
2765
|
|
|
2766
2766
|
This usually means the model described the conversion instead of using Write tool to create files.
|
|
2767
2767
|
|
|
@@ -2772,12 +2772,12 @@ Possible causes:
|
|
|
2772
2772
|
|
|
2773
2773
|
Source: ${t.sourceDir}
|
|
2774
2774
|
Theme: ${s}
|
|
2775
|
-
`+(
|
|
2775
|
+
`+(w?`
|
|
2776
2776
|
Stderr:
|
|
2777
|
-
${
|
|
2777
|
+
${w}
|
|
2778
2778
|
`:"")+`
|
|
2779
2779
|
Claude output:
|
|
2780
|
-
${
|
|
2780
|
+
${v}`)}return b}reportProgress(t,n,s,o,i,r){let a=0,l=this.listDir(Q(t,"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(Q(t,"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(t,i));let d=this.listModules(t);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(Q(t,"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(t,n,s){return`You are converting a React landing page to native HubSpot CMS modules.
|
|
2781
2781
|
|
|
2782
2782
|
SOURCE DIRECTORY: ${t}
|
|
2783
2783
|
THEME DIRECTORY: ${n}
|
|
@@ -2820,16 +2820,16 @@ CSS QUALITY: The converted page must visually match the original React page. Eve
|
|
|
2820
2820
|
Do NOT run hs upload \u2014 I will handle that separately.
|
|
2821
2821
|
|
|
2822
2822
|
HUBSPOT CMS RULES:
|
|
2823
|
-
${
|
|
2823
|
+
${Je()}
|
|
2824
2824
|
|
|
2825
2825
|
CONVERSION GUIDE:
|
|
2826
|
-
${s}`}scanGeneratedFiles(t){let n={sharedCss:"",sharedJs:"",template:"",modules:[]},s=
|
|
2827
|
-
${
|
|
2826
|
+
${s}`}scanGeneratedFiles(t){let n={sharedCss:"",sharedJs:"",template:"",modules:[]},s=Q(t,"css");if(x(s)){for(let a of yt(s))if(a.endsWith(".css")&&a!=="theme-overrides.css"&&a!=="main.css"&&a!=="style.css"){n.sharedCss=P(Q(s,a));break}}let o=Q(t,"js");if(x(o)){for(let a of yt(o))if(a.endsWith(".js")&&a!=="main.js"){n.sharedJs=P(Q(o,a));break}}let i=Q(t,"templates");if(x(i)){for(let a of yt(i))if(a.startsWith("lp-")&&a.endsWith(".html")){n.template=P(Q(i,a));break}if(!n.template){for(let a of yt(i))if(a.endsWith(".html")&&!Pg.has(a)&&!a.startsWith("system")){let l=P(Q(i,a));if(l.includes("dnd_area")){n.template=l;break}}}if(!n.template){for(let a of yt(i))if(a.endsWith(".html")&&!a.startsWith("system")&&a!=="base.html"){let l=P(Q(i,a));if(l.includes("dnd_area")){n.template=l;break}}}}let r=Q(t,"modules");if(x(r))for(let a of yt(r)){if(!a.endsWith(".module"))continue;let l=Q(r,a);if(!xl(l).isDirectory())continue;let c={moduleName:a.replace(".module",""),fieldsJson:"",metaJson:"",moduleHtml:"",moduleCss:""},d=Q(l,"fields.json");x(d)&&(c.fieldsJson=P(d));let u=Q(l,"meta.json");x(u)&&(c.metaJson=P(u));let m=Q(l,"module.html");x(m)&&(c.moduleHtml=P(m));let g=Q(l,"module.css");x(g)&&(c.moduleCss=P(g));let h=Q(l,"module.js");x(h)&&(c.moduleJs=P(h)),c.fieldsJson&&c.moduleHtml&&n.modules.push(c)}return n}listModules(t){let n=Q(t,"modules");return x(n)?new Set(yt(n).filter(s=>s.endsWith(".module"))):new Set}listDir(t){return x(t)?new Set(yt(t)):new Set}detectExpectedModules(t,n){let s=Q(t,"templates");if(!x(s))return 0;for(let o of yt(s))if(!n.has(o)&&!(!o.endsWith(".html")||o==="base.html"||o.startsWith("system")))try{let i=P(Q(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=Q(t,"src");return x(n)?this.countComponentsRecursive(n):0}countComponentsRecursive(t){let n=0;for(let s of yt(t)){let o=Q(t,s);try{xl(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();Ke();oe();Be();en();import Xg from"@anthropic-ai/sdk";import{join as ce,basename as Zg}from"path";import{readdirSync as $l}from"fs";var fo=class{client;model="claude-sonnet-4-6";constructor(t){this.client=new Xg({apiKey:t||process.env.ANTHROPIC_API_KEY})}async convert(t){let{sourceDir:n,themePath:s,conversionGuide:o,onProgress:i}=t,r=hl(o),a=Zg(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,bl(c,d,l)),m=ce(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,Sl(g,h,l)),b=ce(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),v=[];for(let H=0;H<S.length;H++){let B=S[H],K=B.name.replace(/Section$/,"").replace(/([A-Z])/g," $1").trim();i("module",`Building ${K}.module (${H+1}/${S.length})...`);let X=P(B.path),O=await this.complete(r,yl(X,K,`See css/${l}-theme.css`));try{let k=JSON.parse(O),T={moduleName:K,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},$=ce(s,"modules",`${K}.module`);Re($),J(ce($,"fields.json"),T.fieldsJson),J(ce($,"meta.json"),T.metaJson),J(ce($,"module.html"),T.moduleHtml),J(ce($,"module.css"),T.moduleCss),T.moduleJs&&J(ce($,"module.js"),T.moduleJs),v.push(T),i("module-done",`${K}.module (${this.countFiles(T)} files)`)}catch{i("module-error",`Failed to parse ${K} \u2014 skipping`)}}i("template","Creating page template...");let w=v.map(H=>H.moduleName),M=await this.complete(r,vl(w,a,l)),L=ce(s,"templates",`lp-${l}.html`);return J(L,M),i("template-done",`Created templates/lp-${l}.html`),{sharedCss:u,sharedJs:f,template:M,modules:v}}async complete(t,n){let s=new Date,o=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}]}),r=o.content.find(a=>a.type==="text")?.text||"";return bt({engine:"anthropic-api",model:this.model,name:"react-conversion",input:{system:t,messages:[{role:"user",content:n}]},output:r,usage:et(o.usage),startTime:s,endTime:new Date}),r}findAndReadCSS(t){let n=[ce(t,"src/index.css"),ce(t,"src/globals.css"),ce(t,"src/app/globals.css"),ce(t,"app/globals.css")];for(let s of n)if(x(s))return P(s);return""}findAndReadTailwind(t){let n=[ce(t,"tailwind.config.ts"),ce(t,"tailwind.config.js"),ce(t,"tailwind.config.mjs")];for(let s of n)if(x(s))return P(s);return""}findAndReadHooks(t){let n=ce(t,"src/hooks");if(!x(n))return"";try{return $l(n).filter(s=>s.endsWith(".ts")||s.endsWith(".tsx")).map(s=>`// ${s}
|
|
2827
|
+
${P(ce(n,s))}`).join(`
|
|
2828
2828
|
|
|
2829
|
-
`)}catch{return""}}findInteractiveComponents(t){let n=this.findComponents(t),s=[];for(let o of n){let i=
|
|
2829
|
+
`)}catch{return""}}findInteractiveComponents(t){let n=this.findComponents(t),s=[];for(let o of n){let i=P(o.path);/carousel|accordion|typing|parallax|embla|swiper|collapsible/i.test(i)&&s.push(`// ${o.name}
|
|
2830
2830
|
${i}`)}return s.join(`
|
|
2831
2831
|
|
|
2832
|
-
`)}findComponents(t){let n=[
|
|
2832
|
+
`)}findComponents(t){let n=[ce(t,"src/components/landing"),ce(t,"src/components/sections"),ce(t,"src/components")];for(let s of n)if(x(s))try{return $l(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:ce(s,o)}))}catch{continue}return[]}countFiles(t){let n=3;return t.moduleCss&&n++,t.moduleJs&&n++,n}};y();Ke();oe();import{spawn as Qg}from"child_process";import{join as Ve}from"path";import{readdirSync as ho,statSync as ef}from"fs";var yo=class{async convert(t){let{sourceDir:n,themePath:s,onProgress:o}=t,i=t.conversionGuide||ye(),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=Qg("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}.
|
|
2833
2833
|
|
|
2834
2834
|
INSTRUCTIONS:
|
|
2835
2835
|
1. Analyze all .tsx/.jsx components in the React source
|
|
@@ -2844,7 +2844,7 @@ CONVERSION GUIDE:
|
|
|
2844
2844
|
${s}
|
|
2845
2845
|
|
|
2846
2846
|
Do NOT run hs upload \u2014 I will handle that separately.
|
|
2847
|
-
Create all files directly in the theme directory.`}scanGeneratedFiles(t){let n={sharedCss:"",sharedJs:"",template:"",modules:[]},s=
|
|
2847
|
+
Create all files directly in the theme directory.`}scanGeneratedFiles(t){let n={sharedCss:"",sharedJs:"",template:"",modules:[]},s=Ve(t,"css");if(x(s)){for(let a of ho(s))if((a.includes("theme")||a.includes("page"))&&a.endsWith(".css")&&a!=="theme-overrides.css"&&a!=="main.css"&&a!=="style.css"){n.sharedCss=P(Ve(s,a));break}}let o=Ve(t,"js");if(x(o)){for(let a of ho(o))if((a.includes("animation")||a.includes("page"))&&a.endsWith(".js")&&a!=="main.js"){n.sharedJs=P(Ve(o,a));break}}let i=Ve(t,"templates");if(x(i)){for(let a of ho(i))if(a.endsWith(".html")&&!a.startsWith("system")&&a!=="base.html"){let l=P(Ve(i,a));if(l.includes("dnd_area")){n.template=l;break}}}let r=Ve(t,"modules");if(x(r))for(let a of ho(r)){if(!a.endsWith(".module"))continue;let l=Ve(r,a);if(!ef(l).isDirectory())continue;let c={moduleName:a.replace(".module",""),fieldsJson:"",metaJson:"",moduleHtml:"",moduleCss:""},d=Ve(l,"fields.json");x(d)&&(c.fieldsJson=P(d));let u=Ve(l,"meta.json");x(u)&&(c.metaJson=P(u));let m=Ve(l,"module.html");x(m)&&(c.moduleHtml=P(m));let g=Ve(l,"module.css");x(g)&&(c.moduleCss=P(g));let h=Ve(l,"module.js");x(h)&&(c.moduleJs=P(h)),c.fieldsJson&&c.moduleHtml&&n.modules.push(c)}return n}};y();Ke();oe();import{spawn as tf}from"child_process";import{join as ze}from"path";import{readdirSync as bo,statSync as nf}from"fs";var So=class{async convert(t){let{sourceDir:n,themePath:s,onProgress:o}=t,i=t.conversionGuide||ye(),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=tf("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}.
|
|
2848
2848
|
|
|
2849
2849
|
INSTRUCTIONS:
|
|
2850
2850
|
1. Analyze all .tsx/.jsx components in the React source
|
|
@@ -2859,15 +2859,15 @@ CONVERSION GUIDE:
|
|
|
2859
2859
|
${s}
|
|
2860
2860
|
|
|
2861
2861
|
Do NOT run hs upload \u2014 I will handle that separately.
|
|
2862
|
-
Create all files directly in the theme directory.`}scanGeneratedFiles(t){let n={sharedCss:"",sharedJs:"",template:"",modules:[]},s=
|
|
2863
|
-
HubSpot-native modules. This takes 2-5 minutes.`,"AI Conversion");let t=
|
|
2864
|
-
${d}/${l.length} checks passed`),await
|
|
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(
|
|
2862
|
+
Create all files directly in the theme directory.`}scanGeneratedFiles(t){let n={sharedCss:"",sharedJs:"",template:"",modules:[]},s=ze(t,"css");if(x(s)){for(let a of bo(s))if((a.includes("theme")||a.includes("page"))&&a.endsWith(".css")&&a!=="theme-overrides.css"&&a!=="main.css"&&a!=="style.css"){n.sharedCss=P(ze(s,a));break}}let o=ze(t,"js");if(x(o)){for(let a of bo(o))if((a.includes("animation")||a.includes("page"))&&a.endsWith(".js")&&a!=="main.js"){n.sharedJs=P(ze(o,a));break}}let i=ze(t,"templates");if(x(i)){for(let a of bo(i))if(a.endsWith(".html")&&!a.startsWith("system")&&a!=="base.html"){let l=P(ze(i,a));if(l.includes("dnd_area")){n.template=l;break}}}let r=ze(t,"modules");if(x(r))for(let a of bo(r)){if(!a.endsWith(".module"))continue;let l=ze(r,a);if(!nf(l).isDirectory())continue;let c={moduleName:a.replace(".module",""),fieldsJson:"",metaJson:"",moduleHtml:"",moduleCss:""},d=ze(l,"fields.json");x(d)&&(c.fieldsJson=P(d));let u=ze(l,"meta.json");x(u)&&(c.metaJson=P(u));let m=ze(l,"module.html");x(m)&&(c.moduleHtml=P(m));let g=ze(l,"module.css");x(g)&&(c.moduleCss=P(g));let h=ze(l,"module.js");x(h)&&(c.moduleJs=P(h)),c.fieldsJson&&c.moduleHtml&&n.modules.push(c)}return n}};Ke();oe();Qe();function sf(e,t){switch(e){case"claude-code":return new uo(t);case"gemini-cli":return new yo;case"codex-cli":return new So;case"api":return new fo}}async function vo(e){await ge("Converting React to HubSpot Modules"),await ht(`AI will now analyze your React code and create
|
|
2863
|
+
HubSpot-native modules. This takes 2-5 minutes.`,"AI Conversion");let t=sf(e.aiEngine,e.model),n=ye(),s=await Fe();s.start("Starting AI conversion...");let o=Date.now(),i=await t.convert({sourceDir:e.sourceDir,themePath:e.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=of(e.themePath);for(let h of a)G(`Auto-fixed: ${h}`);let l=rf(e.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 ht(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(V(`${u.length} critical issue(s) \u2014 upload will likely fail:
|
|
2866
2866
|
`+u.map(f=>` - ${f.label}`).join(`
|
|
2867
|
-
`)),!await
|
|
2867
|
+
`)),!await Me({message:"Continue with upload anyway?",initialValue:!1}))throw new Error("Conversion aborted due to critical checklist failures.")}else m.length>0&&se(`${m.length} non-critical issue(s) \u2014 page will work but may look incomplete:
|
|
2868
2868
|
`+m.map(h=>` - ${h.label}`).join(`
|
|
2869
|
-
`));let g=
|
|
2870
|
-
`,l=!0)}catch{t.push(`${r}: fields.json has invalid JSON \u2014 manual fix needed`)}l&&J(i,a);let c=
|
|
2869
|
+
`));let g=nt(e.themePath,"..","vibespot-conversion.log");return x(g)&&(await Me({message:"Keep conversion log file for debugging?",initialValue:!1})?G(`Log saved: ${g}`):El(g)),await fe("Files ready for upload!"),i}function of(e){let t=[];af(e),lf(e);let n=nt(e,"modules");if(x(n))for(let o of as(n)){if(!o.endsWith(".module"))continue;let i=nt(n,o,"fields.json");if(!x(i))continue;let r=o.replace(".module",""),a=P(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;Ml(d)&&(u=!0,t.push(`${r}: fixed choice field format`)),Il(d)&&(u=!0,t.push(`${r}: fixed link field default value`)),u&&(a=JSON.stringify(d,null,2)+`
|
|
2870
|
+
`,l=!0)}catch{t.push(`${r}: fields.json has invalid JSON \u2014 manual fix needed`)}l&&J(i,a);let c=nt(n,o,"module.html");if(x(c)){let d=P(c);d.includes("now()")&&(d=d.replace(/now\(\)/g,"local_dt"),J(c,d),t.push(`${r}: now() \u2192 local_dt`))}}let s=nt(e,"templates");if(x(s))for(let o of as(s)){if(!o.endsWith(".html"))continue;let i=nt(s,o),r=P(i);(r.includes("hubdb_table")||r.includes("hubdb_table_rows"))&&(El(i),t.push(`Removed ${o} (HubDB requires CMS Hub Pro/Enterprise)`))}return t}function Ml(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)&&Ml(s.children)&&(t=!0)}return t}function Il(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)&&Il(s.children)&&(t=!0)}return t}function rf(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=nt(e,"templates"),d=!1;if(x(c))for(let u of as(c)){if(!u.endsWith(".html")||u==="base.html"||u.startsWith("system"))continue;let m=P(nt(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 af(e){let t=nt(e,"templates");if(x(t))for(let n of as(t)){if(!n.endsWith(".html")||n==="base.html"||n.startsWith("system"))continue;let s=nt(t,n),o=P(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+=`
|
|
2871
2871
|
templateType: page`),r||(c+=`
|
|
2872
2872
|
isAvailableForNewContent: true`),/label\s*:/i.test(c)||(c+=`
|
|
2873
2873
|
label: ${a}`),o=c+o.slice(l)}else o=`<!--
|
|
@@ -2875,31 +2875,31 @@ ${d}/${l.length} checks passed`),await ut(c.join(`
|
|
|
2875
2875
|
isAvailableForNewContent: true
|
|
2876
2876
|
label: ${a}
|
|
2877
2877
|
-->
|
|
2878
|
-
`+o;J(s,o),
|
|
2879
|
-
`)}catch{}}}y();
|
|
2880
|
-
`);c=
|
|
2881
|
-
You can check your HubSpot Design Manager to verify.`),await
|
|
2882
|
-
The theme may work \u2014 check HubSpot Design Manager.`),await
|
|
2878
|
+
`+o;J(s,o),G(`Template "${n}" \u2014 annotations verified`)}}function lf(e){let t=nt(e,"modules");if(x(t))for(let n of as(t)){if(!n.endsWith(".module"))continue;let s=nt(t,n,"meta.json");if(x(s))try{let o=JSON.parse(P(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();Yt();Qe();ko();ee();tr();import{join as Gl,basename as bf}from"path";function Sf(e){return(e.match(/^Uploaded file /gm)||[]).length}async function En(e){await ge("Uploading to HubSpot");let t=bf(e)||e,n=R(),s=Le(),o=n.hubspotUploadMode!=="cli"&&!!s,i=await Fe(),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,e,t,{onFileComplete:()=>{c++}});d=m.success,d?c=m.uploaded:l=xo(m.errors)}else{let m=ie(`hs cms upload "${e}" "${t}"`,{cwd:Gl(e,"..")}),g=[m.stdout,m.stderr].filter(Boolean).join(`
|
|
2880
|
+
`);c=Sf(g),d=m.success,d||(l=wo(g))}if(d)return i.stop(`All files uploaded! (${c} files)`),await fe("Upload complete!"),!0;if(c>0?i.stop(`${c} files uploaded, but some errors occurred`):i.stop("Upload failed"),l.length===0){if(V("Upload failed with unknown error."),c>0&&(se(`Most files uploaded successfully. The theme may already be usable in HubSpot.
|
|
2881
|
+
You can check your HubSpot Design Manager to verify.`),await Me({message:"Continue anyway (theme is likely uploaded)?",initialValue:!0})))return!0;if(a<r){if(!await Me({message:"Try uploading again?"}))break;continue}break}let u=!1;for(let m of l)m.fixable?Pl(e,m)?(G(`Auto-fixed: ${m.message}`),u=!0):se(`Could not auto-fix: ${m.message}`):V(m.message);if(!(u&&a<r)){if(c>0&&(se(`${c} files uploaded successfully despite errors.
|
|
2882
|
+
The theme may work \u2014 check HubSpot Design Manager.`),await Me({message:"Continue anyway?",initialValue:!0})))return!0;if(!u){if(i.start("Cleaning up stuck modules..."),o)try{await Ji(s,`${t}/modules`)}catch{}else ie(`hs cms delete "${t}/modules"`,{cwd:Gl(e,"..")});i.stop("Cleaned up modules, retrying...")}}}return V("Upload failed after multiple attempts."),!1}y();Qe();pt();Zt();oe();import{execFileSync as nr}from"child_process";import{rmSync as vf}from"fs";import{basename as Wl}from"path";async function Kl(e){let{portalId:t,sourceDir:n,themePath:s,wasCloned:o}=e;await ge("You're all set!");let r=Xn(t)==="eu1"?"app-eu1.hubspot.com":"app.hubspot.com";if(await ht(`Your React page has been converted and uploaded to HubSpot.
|
|
2883
2883
|
The theme and modules are now in your account, but you still
|
|
2884
|
-
need to ${
|
|
2884
|
+
need to ${I.bold("create a new landing page")} that uses them.
|
|
2885
2885
|
|
|
2886
2886
|
Next steps:
|
|
2887
2887
|
|
|
2888
|
-
${
|
|
2889
|
-
${
|
|
2890
|
-
${
|
|
2891
|
-
${
|
|
2892
|
-
${
|
|
2893
|
-
${
|
|
2894
|
-
${
|
|
2895
|
-
`));let n=
|
|
2896
|
-
`)),!process.env.VIBESPOT_NO_OPEN)try{process.platform==="darwin"?
|
|
2897
|
-
Saving session...`)),
|
|
2898
|
-
`)),a(),setTimeout(()=>process.exit(0),500)})})}catch(o){console.error(
|
|
2899
|
-
`),n.passed||process.exit(1);return}
|
|
2900
|
-
`),process.exit(0)),
|
|
2901
|
-
`));let n=
|
|
2902
|
-
`));try{process.platform==="darwin"?
|
|
2903
|
-
Saving session...`)),
|
|
2904
|
-
`)),r(),setTimeout(()=>process.exit(0),500)})})}catch(s){console.error(
|
|
2888
|
+
${I.bold("1.")} Go to HubSpot ${I.muted("\u2192")} Content ${I.muted("\u2192")} Landing Pages ${I.muted("\u2192")} Create
|
|
2889
|
+
${I.bold("2.")} Choose your uploaded theme from the theme picker
|
|
2890
|
+
${I.bold("3.")} Select the landing page template that was just created
|
|
2891
|
+
${I.bold("4.")} Your converted modules will appear \u2014 drag them onto the page
|
|
2892
|
+
${I.bold("5.")} Click each section to edit text, images, and colors
|
|
2893
|
+
${I.bold("6.")} Upload images via File Manager ${I.muted("(Settings \u2192 Files)")}
|
|
2894
|
+
${I.bold("7.")} Preview and publish!`,"What's next"),await Me({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"?nr("open",[c],{stdio:"ignore"}):d==="win32"?nr("cmd",["/c","start","",c],{stdio:"ignore"}):nr("xdg-open",[c],{stdio:"ignore"}),G("Opening HubSpot Landing Pages...")}catch{D(`Open this URL in your browser: ${I.info(c)}`)}}let l=[];if(o&&x(n)&&l.push({path:n,label:`Cloned source (${Wl(n)})`}),x(s)&&l.push({path:s,label:`Theme directory (${Wl(s)})`}),l.length>0&&await Me({message:"Clean up local working directories?"}))for(let d of l)try{vf(d.path,{recursive:!0,force:!0}),G(`Removed ${d.label}`)}catch{se(`Could not remove ${d.label} \u2014 delete manually if needed.`)}await fe(`Thanks for using hub${I.vibes("Vibes")}! ${I.vibes("~")}`)}ee();async function Vl(){Ee();let e=await io(),t=await ro();Y({lastSourcePath:t.sourceDir});let n=await co();Y({lastThemePath:n.themePath}),await vo({aiEngine:e.aiEngine,model:e.model,sourceDir:t.sourceDir,themePath:n.themePath}),await En(n.themePath),await Kl({portalId:e.portalId,sourceDir:t.sourceDir,themePath:n.themePath,wasCloned:t.wasCloned})}y();async function zl(){Ee(),await io()}y();ao();ee();Qe();async function Yl(){Ee();let e=R();e.aiEngine||(V("AI engine not configured. Run `vibespot init` first or use the full wizard with `vibespot`."),process.exit(1));let t=await ro(),n=await co();await vo({aiEngine:e.aiEngine,sourceDir:t.sourceDir,themePath:n.themePath})}y();ee();Qe();async function ql(){Ee();let e=R();if(e.lastThemePath)if(await Me({message:`Upload from ${e.lastThemePath}?`}))await En(e.lastThemePath);else{let n=await Se({message:"Path to your HubSpot theme directory:",placeholder:"./my-theme"});await En(n)}else{let t=await Se({message:"Path to your HubSpot theme directory:",placeholder:"./my-theme",validate:n=>n.trim()?void 0:"Path is required"});await En(t)}}y();Zt();ee();Qe();pt();async function Xl(){Ee(),await ge("Environment Diagnostics");let e=0,t=Yn();t.found?eo(t.version)?G(`Node.js v${t.version}`):(se(`Node.js v${t.version} \u2014 too old (need 18+)`),D(" Update at https://nodejs.org"),e++):(V("Node.js \u2014 not installed"),D(" Install from https://nodejs.org"),e++);let n=qn();n.found?G(`Git ${n.version}`):(V("Git \u2014 not installed"),D(" Install from https://git-scm.com"),e++);let s=gt();if(!s.found)se("HubSpot CLI \u2014 not installed (only needed for deployment)"),D(" Install: npm install -g @hubspot/cli");else if(!qa(s.version))se(`HubSpot CLI v${s.version} \u2014 too old (need v8+)`),D(" Update: npm install -g @hubspot/cli@latest"),e++;else{G(`HubSpot CLI v${s.version}`);let m=ft();m.authenticated?G(`HubSpot portal${m.portalName?`: ${m.portalName}`:""} (ID: ${m.portalId})`):(se("HubSpot \u2014 not authenticated"),D(" Run: hs init"))}let o=xn();o.found?G(`Claude Code ${o.version} at ${o.path}`):D(I.muted("Claude Code \u2014 not installed"));let i=wn();i.found?G(`Gemini CLI ${i.version} at ${i.path}`):D(I.muted("Gemini CLI \u2014 not installed"));let r=Cn();r.found?G(`OpenAI Codex ${r.version} at ${r.path}`):D(I.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?G("Anthropic API key configured"):D(I.muted("Anthropic API key \u2014 not set")),c?G("OpenAI API key configured"):D(I.muted("OpenAI API key \u2014 not set")),d?G("Google AI API key configured"):D(I.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&&D(I.muted(`Last theme: ${a.lastThemePath}`)),!o.found&&!i.found&&!r.found&&!l&&!c&&!d&&(se("No AI engine available"),D(" Fastest: Set an API key (ANTHROPIC_API_KEY, OPENAI_API_KEY, or GEMINI_API_KEY)"),D(" Or install: Claude Code \u2014 https://claude.ai/code"),D(" Gemini CLI \u2014 https://github.com/google-gemini/gemini-cli"),D(" Codex CLI \u2014 https://github.com/openai/codex"),e++),console.log(),e===0?await fe("Everything looks good!"):await fe(I.warn(`${e} issue${e>1?"s":""} found \u2014 see above`))}y();bs();Ce();import{dirname as JS,join as Ai}from"path";import{existsSync as BS}from"fs";import{fileURLToPath as HS}from"url";import{execFileSync as Ma}from"child_process";import _i from"chalk";var Bp=JS(HS(import.meta.url)),US=4200;async function Hp(){let e=_i.hex("#e8613a"),t=_i.dim;console.log(""),console.log(e(" v vibeSpot")),console.log(t(` Starting...
|
|
2895
|
+
`));let n=GS();n||(console.error(_i.red(" Could not find UI assets. Is the package installed correctly?")),process.exit(1));let s=parseInt(process.env.VIBESPOT_PORT||"",10)||US;try{let{port:o,close:i}=await Ti({port:s,uiDir:n}),r=`http://localhost:${o}`;if(console.log(e(` v ${r}`)),console.log(t(` Press Ctrl+C to stop
|
|
2896
|
+
`)),!process.env.VIBESPOT_NO_OPEN)try{process.platform==="darwin"?Ma("open",[r],{stdio:"ignore"}):process.platform==="win32"?Ma("cmd",["/c","start","",r],{stdio:"ignore"}):Ma("xdg-open",[r],{stdio:"ignore"})}catch{}await new Promise(a=>{process.on("SIGINT",()=>{console.log(t(`
|
|
2897
|
+
Saving session...`)),j(),i(),console.log(t(` Goodbye!
|
|
2898
|
+
`)),a(),setTimeout(()=>process.exit(0),500)})})}catch(o){console.error(_i.red(` Failed to start: ${o instanceof Error?o.message:String(o)}`)),process.exit(1)}}function GS(){let e=[Ai(Bp,"../../ui"),Ai(Bp,"../ui"),Ai(process.cwd(),"ui")];for(let t of e)if(BS(Ai(t,"index.html")))return t;return null}y();import{resolve as Up}from"path";import{existsSync as Ia}from"fs";pt();Qe();ee();Ta();async function Gp(e={}){let t=await Kp(e.path);if(e.fix){let o=xi(t);if(o.applied.length>0){G(`Applied ${o.applied.length} auto-fix${o.applied.length===1?"":"es"}:`);for(let i of o.applied)D(` ${i}`)}else D(I.muted("No auto-fixable issues found."));if(o.skipped.length>0)for(let i of o.skipped)se(i)}let n=js(t);if(e.json){process.stdout.write(JSON.stringify(n,null,2)+`
|
|
2899
|
+
`),n.passed||process.exit(1);return}Ee(),await ge("Marketplace check");let s=`${n.errorCount} error${Na(n.errorCount)}, ${n.warningCount} warning${Na(n.warningCount)}, ${n.infoCount} note${Na(n.infoCount)}`;n.passed?G(`Theme passes Marketplace checks (${s}).`):V(`Theme is not yet ready: ${s}.`),Pa("Errors",n.findings.filter(o=>o.severity==="error")),Pa("Warnings",n.findings.filter(o=>o.severity==="warning")),Pa("Notes",n.findings.filter(o=>o.severity==="info")),n.passed||(D(""),D(`Tip: run ${I.accent("vibespot marketplace check --fix")} to apply auto-fixable issues, then re-check.`),process.exit(1)),await fe("Looks good! Submit the theme via your HubSpot Marketplace dashboard.")}async function Wp(e={}){let t=await Kp(e.path);Ee(),await ge("Marketplace listing details");let n=Kn(t)??{},s=await Et({message:"Category",options:zt.map(u=>({value:u,label:u}))}),o=await Se({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 Se({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 Se({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 Se({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 Et({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};vi(t,d),G("Saved marketplace.json"),await fe(`Run ${I.accent("vibespot marketplace check")} to confirm the theme is ready to submit.`)}async function Kp(e){if(e){let o=Up(e);if(!Ia(o))throw new Error(`Theme not found: ${o}`);return o}let t=R();if(t.lastThemePath&&Ia(t.lastThemePath))return t.lastThemePath;Ee();let n=await Se({message:"Path to your HubSpot theme directory:",placeholder:"./my-theme",validate:o=>o.trim()?void 0:"Path is required"}),s=Up(n);if(!Ia(s))throw new Error(`Theme not found: ${s}`);return s}function Pa(e,t){if(t.length!==0){D(""),D(I.heading(e));for(let n of t){let s=n.file?I.muted(`[${n.file}] `):"",o=n.severity==="error"?I.error("\u2717"):n.severity==="warning"?I.warn("!"):I.muted("\xB7");D(` ${o} ${s}${n.message}`),n.fix&&D(` ${I.muted("\u2192 "+n.fix)}`)}}}function Na(e){return e===1?"":"s"}y();import{resolve as Vp}from"path";import{existsSync as Ra}from"fs";import{basename as WS}from"path";pt();Qe();ee();Jo();async function zp(e={}){let t=await KS(e.path),n=WS(t);if(e.applyTokens){let i=Lo(t,n);i?G(`Wrote design tokens to ${i}`):D(I.muted("Skipped: theme already has shared CSS or no tokens were inferred."))}if(e.snapshot){let i=dr(t);e.json||G(`Wrote imported theme snapshot to ${i}`)}let s=jo(t);e.json&&(process.stdout.write(JSON.stringify(s,null,2)+`
|
|
2900
|
+
`),process.exit(0)),Ee(),await ge("Inverse pipeline analyzer");let o=s.summary;if(D(`${I.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){D(""),D(I.heading("Palette (top by frequency)"));for(let i of s.designTokens.palette.slice(0,6)){let r=i.varName?I.muted(` (${i.varName})`):"";D(` ${i.value} ${I.muted(`\xD7${i.count}`)}${r}`)}}if(s.designTokens.fontFamilies.length>0){D(""),D(I.heading("Typography"));for(let i of s.designTokens.fontFamilies.slice(0,4))D(` ${i}`)}if(s.graph.templates.length>0){D(""),D(I.heading("Template \u2192 modules"));for(let i of s.graph.templates)D(` ${i.id}: ${i.modules.length===0?I.muted("(empty)"):i.modules.join(", ")}`)}if(s.graph.orphanModules.length>0){D(""),D(I.heading("Orphan modules"));for(let i of s.graph.orphanModules)D(` ${i}`)}if(s.roundTripDiff.hasSnapshot){D(""),D(I.heading("Round-trip diff"));let i=s.roundTripDiff;if(i.filesChanged===0)D(` ${I.muted("No changes from imported snapshot.")}`);else{D(` ${i.filesChanged} changed file(s): ${i.added} added, ${i.modified} modified, ${i.deleted} deleted`);for(let r of i.files.slice(0,12))D(` ${r.status.padEnd(8)} ${r.file}`);i.files.length>12&&D(` ${I.muted(`...and ${i.files.length-12} more`)}`)}}Oa("Errors",s.findings.filter(i=>i.severity==="error")),Oa("Warnings",s.findings.filter(i=>i.severity==="warning")),Oa("Notes",s.findings.filter(i=>i.severity==="info")),!e.applyTokens&&s.summary.cssVarCount===0&&s.designTokens.palette.length>0&&(D(""),D(`Tip: run ${I.accent("vibespot inverse --apply-tokens")} to seed a :root block from the inferred palette.`)),await fe("Analysis complete."),process.exit(0)}async function KS(e){if(e){let o=Vp(e);if(!Ra(o))throw new Error(`Theme not found: ${o}`);return o}let t=R();if(t.lastThemePath&&Ra(t.lastThemePath))return t.lastThemePath;Ee();let n=await Se({message:"Path to the imported HubSpot theme directory:",placeholder:"./my-theme",validate:o=>o.trim()?void 0:"Path is required"}),s=Vp(n);if(!Ra(s))throw new Error(`Theme not found: ${s}`);return s}function Oa(e,t){if(t.length!==0){D(""),D(I.heading(e));for(let n of t){let s=n.file?I.muted(`[${n.file}] `):"",o=n.severity==="error"?I.error("\u2717"):n.severity==="warning"?I.warn("!"):I.muted("\xB7");D(` ${o} ${s}${n.message}`),n.fix&&D(` ${I.muted("\u2192 "+n.fix)}`)}}}y();bs();Ce();import{dirname as VS,join as $i}from"path";import{existsSync as zS}from"fs";import{fileURLToPath as YS}from"url";import{execFileSync as Fa}from"child_process";import Ei from"chalk";var Yp=VS(YS(import.meta.url)),qS=4200;async function qp(){let e=Ei.hex("#e8613a"),t=Ei.dim;console.log(""),console.log(e(" v vibeSpot \u2014 Email Mode")),console.log(t(` Starting...
|
|
2901
|
+
`));let n=XS();n||(console.error(Ei.red(" Could not find UI assets. Is the package installed correctly?")),process.exit(1));try{let{port:s,close:o}=await Ti({port:qS,uiDir:n,contentMode:"email"}),i=`http://localhost:${s}`;console.log(e(` v ${i}`)),console.log(t(` Email template mode \u2014 Press Ctrl+C to stop
|
|
2902
|
+
`));try{process.platform==="darwin"?Fa("open",[i],{stdio:"ignore"}):process.platform==="win32"?Fa("cmd",["/c","start","",i],{stdio:"ignore"}):Fa("xdg-open",[i],{stdio:"ignore"})}catch{}await new Promise(r=>{process.on("SIGINT",()=>{console.log(t(`
|
|
2903
|
+
Saving session...`)),j(),o(),console.log(t(` Goodbye!
|
|
2904
|
+
`)),r(),setTimeout(()=>process.exit(0),500)})})}catch(s){console.error(Ei.red(` Failed to start: ${s instanceof Error?s.message:String(s)}`)),process.exit(1)}}function XS(){let e=[$i(Yp,"../../ui"),$i(Yp,"../ui"),$i(process.cwd(),"ui")];for(let t of e)if(zS($i(t,"index.html")))return t;return null}oe();function Xp(){let e=new ZS;e.name("vibespot").description("AI-powered HubSpot CMS landing page builder").version(hn()).action(Hp),e.command("wizard").description("Classic CLI wizard \u2014 step-by-step conversion flow").action(Vl),e.command("init").description("Check and install required tools").action(zl),e.command("convert").description("Convert a React project to HubSpot modules").action(Yl),e.command("upload").description("Upload theme to HubSpot").action(ql),e.command("doctor").description("Diagnose environment issues").action(Xl);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=>Gp(n)),t.command("edit").description("Edit Marketplace listing metadata (marketplace.json)").option("-p, --path <path>","Path to the theme directory").action(n=>Wp(n)),e.command("email").description("Launch email template generation mode").action(qp),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=>zp(n)),e}var QS=Xp();QS.parseAsync(process.argv).catch(e=>{console.error(e),process.exit(1)});
|
|
2905
2905
|
//# sourceMappingURL=index.js.map
|