vibespot 1.6.0 → 1.6.3
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 +3 -2
- package/assets/prompts.bundle.json +11 -11
- package/dist/index.js +303 -252
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
- package/ui/chat.js +17 -0
- package/ui/docs/index.html +102 -1
- package/ui/index.html +4 -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: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
|
|
1
|
+
var rg=Object.defineProperty;var N=(e,t)=>()=>(e&&(t=e(e=0)),t);var Ge=(e,t)=>{for(var n in t)rg(e,n,{get:t[n],enumerable:!0})};import xv from"path";import{fileURLToPath as Cv}from"url";var y=N(()=>{"use strict"});import pn from"chalk";function Tt(e){return Ba?pn:pn.hex(e)}var pt,Ba,I,gt=N(()=>{"use strict";y();pt={accent:"#FF7A59",accentBright:"#FF9A7A",success:"#00BDA5",info:"#0066FF",warn:"#FFB020",error:"#E23D2D",muted:"#8B8D91",vibes:"#00BDD6"},Ba=!!process.env.NO_COLOR;I={accent:Tt(pt.accent),accentBright:Tt(pt.accentBright),success:Tt(pt.success),info:Tt(pt.info),warn:Tt(pt.warn),error:Tt(pt.error),muted:Tt(pt.muted),vibes:Tt(pt.vibes),heading:Ba?pn.bold:pn.bold.hex(pt.accent),command:Tt(pt.accentBright),dim:pn.dim,bold:pn.bold}});import{readFileSync as Ii,writeFileSync as ag,mkdirSync as Ha,existsSync as Ws}from"fs";import{dirname as Ua,join as At}from"path";import{fileURLToPath as lg}from"url";function P(e){return Ii(e,"utf-8")}function B(e,t){Ha(Ua(e),{recursive:!0}),ag(e,t,"utf-8")}function x(e){return Ws(e)}function Re(e){Ha(e,{recursive:!0})}function hn(e){let t=[At(fn,"../../assets",e),At(fn,"../assets",e),At(process.cwd(),"assets",e)];for(let n of t)if(Ws(n))return n;throw new Error(`Asset not found: ${e}`)}function yn(){if(gn)return gn;let e=[At(fn,"../../package.json"),At(fn,"../package.json"),At(process.cwd(),"package.json")];for(let t of e)if(Ws(t))try{let n=JSON.parse(Ii(t,"utf-8"));if(n.name==="vibespot"&&n.version)return gn=n.version,gn}catch{}return gn="dev",gn}function Ga(){if(Gs)return Gs;let e=[At(fn,"../../CHANGELOG.md"),At(fn,"../CHANGELOG.md"),At(process.cwd(),"CHANGELOG.md")];for(let t of e)if(Ws(t))try{return Gs=Ii(t,"utf-8"),Gs}catch{}return""}var fn,gn,Gs,oe=N(()=>{"use strict";y();fn=Ua(lg(import.meta.url));gn="";Gs=""});import{execSync as Wa,execFileSync as cg}from"child_process";function ie(e,t={}){try{return{stdout:Wa(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:cg("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 Ka(e,t={}){try{return Wa(e,{stdio:"inherit",timeout:3e5,...t}),!0}catch{return!1}}var qt=N(()=>{"use strict";y()});var Ya={};Ge(Ya,{addHubSpotAccount:()=>qn,getActiveHubSpotAccount:()=>Lt,getApiKeyForEngine:()=>Fe,getConfigDir:()=>mg,getHubSpotPak:()=>Le,isCliToolEnabled:()=>st,loadConfig:()=>R,maskApiKey:()=>Vs,removeHubSpotAccount:()=>Pi,saveConfig:()=>Y,setActiveHubSpotAccount:()=>Ni,setCliToolEnabled:()=>Ri});import{join as Va}from"path";import{homedir as dg}from"os";import{chmodSync as ug}from"fs";function R(){let e={};if(x(Ks))try{e=JSON.parse(P(Ks)),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 Fe(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 Vs(e){return e.length<=12?"***":e.slice(0,7)+"..."+e.slice(-4)}function Y(e){let n={...R(),...e};if(B(Ks,JSON.stringify(n,null,2)),process.platform!=="win32")try{ug(Ks,384)}catch{}}function mg(){return za}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 qn(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 Pi(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 Ni(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 Ri(e,t){let n=R(),s=new Set(n.enabledCLITools||[]);t?s.add(e):s.delete(e),Y({enabledCLITools:[...s]})}var za,Ks,ee=N(()=>{"use strict";y();oe();za=Va(dg(),".vibespot"),Ks=Va(za,"config.json")});var Di={};Ge(Di,{OAUTH_EXTRA_HEADERS:()=>Xn,OAUTH_SYSTEM_PREFIX:()=>Sn,clearOAuthTokens:()=>qs,getOAuthTokenInfo:()=>Xt,getValidAccessToken:()=>Fi,hasValidOAuthToken:()=>Ze,saveInitialToken:()=>Oi});import{join as pg}from"path";import{homedir as gg}from"os";import{chmodSync as fg,unlinkSync as hg}from"fs";function Ys(){if(!x(bn))return null;try{return JSON.parse(P(bn))}catch{return null}}function qa(e){if(B(bn,JSON.stringify(e,null,2)),process.platform!=="win32")try{fg(bn,384)}catch{}}async function vg(e){let t=await fetch(bg,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({grant_type:"refresh_token",refresh_token:e,client_id:yg})});if(!t.ok)throw qs(),new Error("Claude OAuth session expired. Please re-authenticate in Settings.");let n=await t.json();qa({access_token:n.access_token,refresh_token:n.refresh_token||e,expires_at:Date.now()+(n.expires_in||28800)*1e3})}function Oi(e,t=""){qa({access_token:e,refresh_token:t,expires_at:Date.now()+28800*1e3})}function Ze(){let e=Ys();return e?e.expires_at>Date.now():!1}async function Fi(){let e=Ys();if(!e)return null;if(e.expires_at-Date.now()>Sg)return e.access_token;if(e.refresh_token){zs||(zs=vg(e.refresh_token).finally(()=>{zs=null}));try{await zs}catch{return null}return Ys()?.access_token??null}return e.access_token}function Xt(){let e=Ys();return e?{expiresAt:new Date(e.expires_at).toISOString()}:null}function qs(){if(x(bn))try{hg(bn)}catch{}}var yg,bg,bn,Sg,Xn,Sn,zs,_t=N(()=>{"use strict";y();oe();yg="9d1c250a-e61b-44d9-88ed-5944d1962f5e",bg="https://console.anthropic.com/v1/oauth/token",bn=pg(gg(),".vibespot","claude-oauth.json"),Sg=300*1e3,Xn={"user-agent":"claude-cli/2.1.75","x-app":"cli","anthropic-beta":"oauth-2025-04-20"},Sn="You are Claude Code, Anthropic's official CLI for Claude.";zs=null});import{join as Xs}from"path";import{homedir as Zs}from"os";import{readFileSync as Xa,existsSync as Qs,readdirSync as xg}from"fs";function Zn(){let e=ie("node --version");return{name:"Node.js",found:e.success,version:e.stdout.replace(/^v/,""),path:ie(`${Zt} node`).stdout}}function Qn(){let e=ie("git --version");return{name:"Git",found:e.success,version:e.stdout.replace("git version ",""),path:ie(`${Zt} git`).stdout}}function ft(){let e=ie("hs --version");return{name:"HubSpot CLI",found:e.success,version:e.stdout,path:ie(`${Zt} hs`).stdout}}function wn(){let e=ie("claude --version");if(!e.success)return{name:"Claude Code",found:!1,version:"",path:"",authenticated:!1,authDetail:"Not installed"};let t=Xs(Zs(),".claude"),n=!1,s="Not signed in \u2014 run `claude` to authenticate";try{if(Qs(t)){let o=xg(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(`${Zt} claude`).stdout,authenticated:n,authDetail:s}}function es(e){try{let t=Xs(Zs(),".hscli","config.yml");if(!Qs(t))return"na1";let n=Xa(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 ht(){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 Cn(){let e=ie("gemini --version");if(!e.success)return{name:"Gemini CLI",found:!1,version:"",path:"",authenticated:!1,authDetail:"Not installed"};let t=Xs(Zs(),".config","gcloud","application_default_credentials.json"),n=Qs(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(`${Zt} gemini`).stdout,authenticated:o,authDetail:o?"Authenticated":"Run `gemini` to sign in with Google"}}function kn(){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=Xs(Zs(),".codex","auth.json");Qs(i)&&(n=Xa(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(`${Zt} codex`).stdout,authenticated:s,authDetail:o}}function eo(){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(`${Zt} gh`).stdout}}function to(){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 Qa(){return!!process.env.ANTHROPIC_API_KEY}function no(e){return parseInt(e.split(".")[0],10)>=18}function el(e){let t=parseInt(e.split(".")[0],10);return!isNaN(t)&&t>=8}function wg(){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 vn(e,...t){if(e)return{configured:!0,masked:Vs(e),source:"config"};for(let n of t)if(process.env[n])return{configured:!0,masked:Vs(process.env[n]),source:"env"};return{configured:!1,masked:"",source:null}}function ji(e){return{anthropic:vn(e.anthropicApiKey,"ANTHROPIC_API_KEY"),openai:vn(e.openaiApiKey,"OPENAI_API_KEY"),gemini:vn(e.geminiApiKey,"GEMINI_API_KEY","GOOGLE_AI_API_KEY"),langdock:vn(e.langdockApiKey,"LANGDOCK_API_KEY"),langfusePublic:vn(e.langfusePublicKey,"LANGFUSE_PUBLIC_KEY"),langfuseSecret:vn(e.langfuseSecretKey,"LANGFUSE_SECRET_KEY")}}function Li(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 Ji(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=ft(),s=n.found?ht():{authenticated:!1,portalName:"",portalId:"",accounts:[]},o=s.portalId?es(s.portalId):"na1";return{...n,...s,dataCenter:o,uploadMode:"cli"}}return{name:"HubSpot API",found:!0,version:"v3",path:"",...wg()}}function tl(){let e=R(),t=e.hubspotUploadMode||"api",n=ji(e),s={authenticated:Ze(),expiresAt:Xt()?.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:Ji(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:Li({apiKeys:n,claudeOAuth:s.authenticated,claudeCode:st("claude-code"),geminiCli:st("gemini-cli"),codexCli:st("codex-cli")}),enabledCLITools:e.enabledCLITools||[],scanned:!1}}function nl(){let e=R(),t=ji(e),n={authenticated:Ze(),expiresAt:Xt()?.expiresAt},s=st("claude-code")?wn():{...xn,name:"Claude Code"},o=st("gemini-cli")?Cn():{...xn,name:"Gemini CLI"},i=st("codex-cli")?kn():{...xn,name:"OpenAI Codex CLI"};return{claudeCode:s,geminiCli:o,codexCli:i,claudeOAuth:n,availableEngines:Li({apiKeys:t,claudeOAuth:n.authenticated,claudeCode:s.found&&s.authenticated,geminiCli:o.found&&o.authenticated,codexCli:i.found&&i.authenticated})}}function sl(){let t=R().hubspotUploadMode||"api",n=eo(),s=n.found?to():{authenticated:!1,username:""};return{github:{...n,...s},hubspot:Ji(t,!0)}}function so(){let e=R(),t=e.hubspotUploadMode||"api",n=Zn(),s=Qn(),o=Ji(t,!0),i=eo(),r=i.found?to():{authenticated:!1,username:""},a={authenticated:Ze(),expiresAt:Xt()?.expiresAt},l=st("claude-code")?wn():{...xn,name:"Claude Code"},c=st("gemini-cli")?Cn():{...xn,name:"Gemini CLI"},d=st("codex-cli")?kn():{...xn,name:"OpenAI Codex CLI"},u=ji(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:Li({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 Zt,Za,xn,Qt=N(()=>{"use strict";y();qt();ee();_t();Zt=process.platform==="win32"?"where":"which",Za=4e3;xn={name:"",found:!1,version:"",path:"",authenticated:!1,authDetail:"Disabled"}});import{readFileSync as Cg}from"fs";import{basename as kg}from"path";async function il(e){let t=ol.get(e);if(t&&t.expiresAt-Date.now()>_g)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 ol.set(e,o),o}async function Tn(e){let{accessToken:t}=await il(e);return{Authorization:`Bearer ${t}`}}function oo(e){return e.replace(/^\/+/,"").split("/").filter(Boolean).map(encodeURIComponent).join("/")}function $g(e){return e.startsWith("pat-eu1-")?"eu1":e.startsWith("pat-na1-")?"na1":e.startsWith("CiRldTE")?"eu1":"na1"}function Eg(e){return new Promise(t=>setTimeout(t,e))}async function ts(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 ns(e,t,n=Tg){for(let s=0;s<=n;s++){let o=await fetch(e,t);if(o.status===429||o.status>=500&&s<n){let i=Ag*Math.pow(2,s);await Eg(i);continue}return o}return fetch(e,t)}async function io(e){let t=await il(e),n=`${$t}/account-info/v3/details`,s=await ns(n,{headers:await Tn(e)});if(!s.ok){let a=await ts(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:$g(e)}}async function rl(e,t,n){let s=Cg(n),o=kg(n),i=new FormData,r=new Blob([s]);i.append("file",r,o);let a=`${$t}/cms/v3/source-code/published/content/${oo(t)}`,l=await ns(a,{method:"PUT",headers:await Tn(e),body:i});if(!l.ok){let c=await ts(l,t);return{success:!1,path:t,error:c}}return{success:!0,path:t}}async function Bi(e,t){let n=`${$t}/cms/v3/source-code/published/content/${oo(t)}`,s=await ns(n,{method:"DELETE",headers:await Tn(e)});if(!s.ok&&s.status!==404){let o=await ts(s,t);throw new Error(`Failed to delete ${t}: ${o.message}`)}}async function al(e,t){let n=`${$t}/cms/v3/source-code/published/content/${oo(t)}`,s=await ns(n,{method:"GET",headers:await Tn(e)});if(!s.ok){let i=await ts(s,t);throw new Error(`Failed to download ${t}: ${i.message}`)}let o=await s.arrayBuffer();return Buffer.from(o)}async function ro(e,t){let n=`${$t}/cms/v3/source-code/published/metadata/${oo(t)}`,s=await ns(n,{method:"GET",headers:await Tn(e)});if(s.status===404)return null;if(!s.ok){let o=await ts(s,t);throw new Error(`Failed to get metadata for ${t}: ${o.message}`)}return await s.json()}async function ll(e){let t=await Tn(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,Tg,Ag,_g,ol,en=N(()=>{"use strict";y();$t="https://api.hubapi.com",Tg=3,Ag=1e3,_g=300*1e3,ol=new Map});import*as ae from"@clack/prompts";function Hi(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 yt(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 Hi(t),t}async function Me(e){let t=await ae.confirm({message:I.accent(e.message),initialValue:e.initialValue??!0});return Hi(t),t}async function Et(e){let t=await ae.select({message:I.accent(e.message),options:e.options});return Hi(t),t}async function De(){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();gt()});import{readdirSync as Ui,statSync as Mg}from"fs";import{join as he,basename as Gi,extname as Ig}from"path";function cl(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 dl(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=Ui(s);for(let i of o){let r=he(s,i);if(!Mg(r).isFile())continue;let l=Ig(i);if(![".tsx",".jsx"].includes(l))continue;let c=Gi(i,l);if(c.startsWith("ui")||c==="index")continue;let d=P(r),u=Pg(c,d);t.push({name:c,path:r,description:u})}}catch{}return t}function Pg(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 ul(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 ml(e){let t=[],n=he(e,"src/hooks");if(x(n))try{let o=Ui(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=Ui(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 pl(e){let t,n=!1;if(e.startsWith("http")||e.startsWith("git@")){if(!cl(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=Gi(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=dl(t),o=x(he(t,"tailwind.config.ts"))||x(he(t,"tailwind.config.js")),{varCount:i,fonts:r}=ul(t),a=ml(t);return{sourceDir:t,wasCloned:n,components:s,hasTailwind:o,cssVarCount:i,fonts:r,interactions:a}}async function lo(){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@")){cl(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=Gi(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 De();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 De();s.start("Analyzing project structure...");let o=dl(t),i=x(he(t,"tailwind.config.ts"))||x(he(t,"tailwind.config.js")),{varCount:r,fonts:a}=ul(t),l=ml(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 yt(`${c}
|
|
5
5
|
|
|
6
6
|
CSS: ${d}
|
|
7
7
|
JS: ${m}
|
|
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
|
|
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 co=N(()=>{"use strict";y();qt();oe();Qe();gt()});var gl={};Ge(gl,{addEmailTemplateToTheme:()=>An,createThemeScaffold:()=>os});import{mkdirSync as Mt,writeFileSync as ss}from"fs";import{join as We}from"path";function os(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"}};ss(We(e,"theme.json"),JSON.stringify(n,null,2)+`
|
|
9
|
+
`),ss(We(e,"fields.json"),`[]
|
|
10
10
|
`);let s=`<!--
|
|
11
11
|
templateType: page
|
|
12
12
|
isAvailableForNewContent: false
|
|
@@ -22,7 +22,7 @@ var Zp=Object.defineProperty;var N=(e,t)=>()=>(e&&(t=e(e=0)),t);var Ge=(e,t)=>{f
|
|
|
22
22
|
%}
|
|
23
23
|
{% end_dnd_area %}
|
|
24
24
|
{% endblock body %}
|
|
25
|
-
`;
|
|
25
|
+
`;ss(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 Zp=Object.defineProperty;var N=(e,t)=>()=>(e&&(t=e(e=0)),t);var Ge=(e,t)=>{f
|
|
|
45
45
|
{{ standard_footer_includes }}
|
|
46
46
|
</body>
|
|
47
47
|
</html>
|
|
48
|
-
`;Mt(We(e,"templates","layouts"),{recursive:!0}),
|
|
48
|
+
`;Mt(We(e,"templates","layouts"),{recursive:!0}),ss(We(e,"templates","layouts","base.html"),o)}function An(e,t){let n=`<!--
|
|
49
49
|
templateType: email
|
|
50
50
|
isAvailableForNewContent: true
|
|
51
51
|
label: ${t} Email Template
|
|
@@ -84,8 +84,8 @@ var Zp=Object.defineProperty;var N=(e,t)=>()=>(e&&(t=e(e=0)),t);var Ge=(e,t)=>{f
|
|
|
84
84
|
{{ standard_footer_includes }}
|
|
85
85
|
</body>
|
|
86
86
|
</html>
|
|
87
|
-
`;Mt(We(e,"templates"),{recursive:!0}),
|
|
88
|
-
## `,o+s.length);return i>=0?t.slice(o,i).trim():t.slice(o).trim()}function
|
|
87
|
+
`;Mt(We(e,"templates"),{recursive:!0}),ss(We(e,"templates","email.html"),n)}var is=N(()=>{"use strict";y()});var hl={};Ge(hl,{fetchTheme:()=>rs});import{mkdirSync as fl,writeFileSync as Ng}from"fs";import{join as Rg,dirname as Og}from"path";async function Wi(e,t){let n=await ro(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 Wi(e,a));else{let l=i;l.folder?s.push(...await Wi(e,l.path||a)):s.push(l.path||a)}}return s}async function Fg(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 rs(e,t,n,s={}){let o=s.concurrency??5,i=await Wi(e,t);if(i.length===0)throw new Error(`Theme "${t}" not found on HubSpot or is empty`);fl(n,{recursive:!0}),await Fg(i,o,async r=>{let a=r.startsWith(t+"/")?r.slice(t.length+1):r,l=Rg(n,a);fl(Og(l),{recursive:!0});let c=await al(e,r);Ng(l,c),s.onFile?.(a)})}var uo=N(()=>{"use strict";y();en()});function Jt(e){let t=yl.get(e);if(t!==void 0)return t;try{t=P(hn(e))}catch{t=""}return yl.set(e,t),t}function ye(){return Jt("conversion-guide.md")||"Conversion guide not found. Using built-in rules."}function ls(){return Jt("design-guide.md")}function Ki(){return Jt("content-guide.md")}function Je(){return Jt("hubspot-rules.md")}function Vi(){return Jt("humanify-guide.md")}function bl(){return Jt("email-rules.md")}function Sl(){return Jt("blog-rules.md")}function zi(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 vl(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:
|
|
@@ -105,7 +105,7 @@ Follow the conversion guide below EXACTLY. Key rules:
|
|
|
105
105
|
${Je()}
|
|
106
106
|
|
|
107
107
|
## Conversion Guide
|
|
108
|
-
${e}`}function
|
|
108
|
+
${e}`}function xl(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 wl(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 Cl(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 kl(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
|
-
`)}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
|
|
183
|
-
`),t=!0)}catch{}}return t}function
|
|
184
|
-
{{ dnd_area_stylesheet }}`);r!==i&&(
|
|
185
|
-
`),"utf-8")}function
|
|
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 {
|
|
180
|
+
Return ONLY the template HTML content, no markdown fences.`}var yl,Ke=N(()=>{"use strict";y();oe();yl=new Map});import{appendFileSync as Bg,mkdirSync as Hg,readdirSync as Ug,unlinkSync as Gg}from"fs";import{join as Zi}from"path";import{homedir as Wg}from"os";function Vg(){if(!qi)try{Hg(go,{recursive:!0}),qi=!0}catch{}}function zg(){if(!Xi){Xi=!0;try{let e=Date.now()-Kg*864e5;for(let t of Ug(go)){if(!t.startsWith("vibespot-")||!t.endsWith(".log"))continue;let n=t.slice(9,19),s=new Date(n).getTime();if(s&&s<e)try{Gg(Zi(go,t))}catch{}}}catch{}}}function Yg(){let t=new Date().toISOString().slice(0,10);return Zi(go,`vibespot-${t}.log`)}function qg(){return new Date().toISOString().slice(11,23)}function Yi(e,t){if(Vg(),!!qi){Xi||zg();try{Bg(Yg(),`${qg()} ${e} ${t}
|
|
181
|
+
`)}catch{}}}var go,Kg,qi,Xi,E,le=N(()=>{"use strict";y();go=Zi(Wg(),".vibespot","logs"),Kg=7,qi=!1,Xi=!1;E={info(e,t,n){let s=n?`[${e}] ${t} ${JSON.stringify(n)}`:`[${e}] ${t}`;console.log(s),Yi("INFO",s)},warn(e,t,n){let s=n?`[${e}] ${t} ${JSON.stringify(n)}`:`[${e}] ${t}`;console.warn(s),Yi("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),Yi("ERROR",o)}}});function Zg(e){let t=(e||"").toLowerCase();return Xg.find(n=>t.includes(n.match))}function cs(e,t){let n=Zg(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 _n(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 Al(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 Xg,tn=N(()=>{"use strict";y();Xg=[{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 Qg}from"async_hooks";function ef(){return{inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheCreationTokens:0,costUsd:0,calls:0,unpricedCalls:0}}function tf(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 Qi(e){let t=ef();return{result:await _l.run(t,e),cost:tf(t)}}function $l(e,t){if(!t)return;let n=_l.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=cs(e,t);s?n.costUsd+=s.total:n.unpricedCalls+=1}var _l,er=N(()=>{"use strict";y();tn();_l=new Qg});import{randomUUID as Bt}from"crypto";import{AsyncLocalStorage as nf}from"async_hooks";function Ml(){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||sf).replace(/\/+$/,"");return{publicKey:t,secretKey:n,baseUrl:o}}function tr(){return Ml()!==null}function ho(e){if(typeof e=="string")return e.length>En?e.slice(0,En)+`\u2026[+${e.length-En} chars]`:e;try{let t=JSON.stringify(e);if(t&&t.length>En)return t.slice(0,En)+`\u2026[+${t.length-En} chars]`}catch{return"[unserializable]"}return e}async function tt(e,t){if(!tr())return t();let n=Bt();nn.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:ho(e.input)}:{},...e.metadata?{metadata:e.metadata}:{},...e.tags?{tags:e.tags}:{}}});try{return await fo.run({traceId:n,sessionId:e.sessionId},t)}finally{await Il()}}async function te(e,t,n){let s=fo.getStore();if(!tr()||!s?.traceId)return t();let o=Bt(),i=s.spanId,r=new Date,a,l;try{return await fo.run({...s,spanId:o},t)}catch(c){throw a="ERROR",l=c?.message,c}finally{nn.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:ho(n.input)}:{},...n?.metadata?{metadata:n.metadata}:{},...a?{level:a}:{},...l?{statusMessage:l}:{}}})}}async function of(e){if(tr())try{let t=fo.getStore(),n=t?.traceId,s=n?t?.spanId:void 0,o=!1;n||(n=Bt(),o=!0,nn.push({id:Bt(),type:"trace-create",timestamp:new Date().toISOString(),body:{id:n,name:e.name,timestamp:new Date().toISOString()}}));let i=e.usage?Al(e.usage):void 0,r=e.usage?cs(e.model,e.usage):void 0;nn.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:ho(e.input)}:{},...e.output!==void 0?{output:ho(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 Il()}catch(t){E.warn("langfuse",`recordGeneration failed: ${t.message}`)}}function St(e){let{engine:t,model:n,name:s,usage:o,startTime:i,endTime:r}=e,a=r.getTime()-i.getTime(),l=o?cs(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}),El.size>0){let c={engine:t,model:n,name:s,usage:o,cost:l,startTime:i,endTime:r,durationMs:a};for(let d of El)try{d(c)}catch{}}$l(n,o),of({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 Il(){let e=Ml();if(!e||nn.length===0)return;let t=nn;nn=[];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 sf,En,fo,nn,El,Be=N(()=>{"use strict";y();ee();le();tn();er();sf="https://cloud.langfuse.com",En=24e3,fo=new nf,nn=[],El=new Set});import{join as me}from"path";import{readdirSync as it,rmSync as yf}from"fs";function Co(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 ko(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 To(e){let t=[];return Dl(e)&&t.push("textarea \u2192 text"),jl(e)&&t.push("name \u2192 item_name"),Ll(e)&&t.push("now() \u2192 local_dt"),Jl(e)&&t.push("Removed HubDB templates"),Bl(e)&&t.push("Fixed link field defaults"),Hl(e)&&t.push("Fixed rgba/invalid color values \u2192 hex"),bf(e)&&t.push("Stripped CDN @import statements"),Gl(e)&&t.push('dnd_area \u2192 "main" in email templates'),Wl(e)&&t.push("Added {{ dnd_area_stylesheet }} to email templates"),t}function Fl(e,t){return t.message.includes("textarea")?Dl(e):t.message.includes("reserved field name")?jl(e):t.message.includes("now()")?Ll(e):t.message.includes("HubDB")?Jl(e):t.message.includes("invalid default value")||t.message.includes("deserialization")?Bl(e):t.message.includes("invalid format")&&t.message.includes("color")?Hl(e):t.message.includes("dnd")||t.message.includes("Dnd area")?Gl(e):t.message.includes("dnd_area_stylesheet")?Wl(e):!1}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))continue;let i=P(o);i.includes('"textarea"')&&(i=i.replace(/"textarea"/g,'"text"'),B(o,i),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))continue;let i=P(o);/"name":\s*"name"/g.test(i)&&(i=i.replace(/"name":\s*"name"/g,'"name": "item_name"'),B(o,i),t=!0)}return t}function Ll(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"),B(o,i),t=!0)}return t}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);(i.includes("hubdb_table")||i.includes("hubdb_table_rows"))&&(yf(o),t=!0)}return t}function Bl(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));Kl(i)&&(B(o,JSON.stringify(i,null,2)+`
|
|
182
|
+
`),t=!0)}catch{}}return t}function bf(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&&(B(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&&(B(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&&(B(i,a),t=!0)}return t}function Hl(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));Ul(i)&&(B(o,JSON.stringify(i,null,2)+`
|
|
183
|
+
`),t=!0)}catch{}}return t}function Ul(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"&&!Sf(i)){let r=vf(i);r&&(o.color=r.hex,r.opacity!==void 0&&(o.opacity=r.opacity),t=!0)}}Array.isArray(s.children)&&Ul(s.children)&&(t=!0)}return t}function Sf(e){return/^#[0-9a-fA-F]{6}$/.test(e)}function vf(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 Gl(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&&(B(o,r),t=!0)}return t}function Wl(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&&(B(o,r),t=!0)}return t}function Kl(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)&&Kl(s.children)&&(t=!0)}return t}var Ao=N(()=>{"use strict";y();oe()});import{readdirSync as xf}from"fs";import{join as wf,relative as Cf}from"path";function Vl(e){let t=[];for(let n of xf(e,{withFileTypes:!0})){if(kf.has(n.name)||n.name.startsWith(".")&&n.name!==".gitkeep")continue;let s=wf(e,n.name);n.isDirectory()?t.push(...Vl(s)):n.isFile()&&t.push(s)}return t}async function Tf(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 _o(e,t,n,s={}){let o=s.concurrency??5,i=Vl(t),r=i.length,a=0,l=0,c=[];return await Tf(i,o,async d=>{let u=Cf(t,d).replace(/\\/g,"/"),m=`${n}/${u}`;s.onFileStart?.(u);let g=await rl(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 kf,nr=N(()=>{"use strict";y();en();en();kf=new Set([".git","node_modules",".vibespot",".DS_Store"])});var nc=N(()=>{"use strict";y()});import{existsSync as It,writeFileSync as Ef,mkdirSync as Mf}from"fs";import{join as vt}from"path";function oc(e){return/^[0-9a-f]{4,40}$/i.test(e)}function ic(e){return Number.isInteger(e)&&e>0&&e<1e3}function rt(){return $o!==null||($o=Z(["--version"]).success),$o}function Eo(e){if(!rt())return!1;if(It(vt(e,".git")))return sc(e),!0;let t=Z(["init"],{cwd:e});return t.success?(If(e),sc(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 sc(e){let t=vt(e,".vibespot");It(t)||Mf(t,{recursive:!0})}function If(e){let t=vt(e,".gitignore");Ef(t,[".vibespot/","node_modules/",""].join(`
|
|
185
|
+
`),"utf-8")}function sn(e,t){if(!rt()||!It(vt(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 or(e,t,n,s){if(!rt()||!It(vt(e,".git")))return null;for(let u of s){let m=vt(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 rc(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 ac(e,t=50){if(!rt())return[];if(!It(vt(e,".git")))return[];if(!ic(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()?[]:rc(n.stdout)}function lc(e,t,n=50){if(!rt())return[];if(!It(vt(e,".git")))return[];if(!ic(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()?[]:rc(o.stdout)}function cc(e,t){if(!rt())return{success:!1,error:"Git not available"};if(!It(vt(e,".git")))return{success:!1,error:"Not a git repo"};if(!oc(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 dc(e,t,n,s){if(!rt())return{success:!1,error:"Git not available"};if(!It(vt(e,".git")))return{success:!1,error:"Not a git repo"};if(!oc(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 $o,In=N(()=>{"use strict";y();qt();$o=null});import{readFileSync as Pf,existsSync as mc,writeFileSync as Nf,mkdirSync as Rf,rmSync as Of}from"fs";import{join as Mo}from"path";function on(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(),Df()}function pc(e){let t=C();t&&(t.assets||(t.assets=[]),t.assets.push(e),t.updatedAt=Date.now(),L())}function gc(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 uc(e){return e.toLowerCase().replace(/[\s\-_]+/g,"")}function Ff(e,t){let n=uc(e),s=uc(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=>Ff(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 fc(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=Mo(t.themePath,"modules",`${e}.module`);mc(n)&&Of(n,{recursive:!0,force:!0})}t.updatedAt=Date.now(),at()}}function hc(e){let t=C();t&&(t.moduleOrder=t.moduleOrder.filter(n=>n!==e),t.updatedAt=Date.now(),at())}function yc(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);vc(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 Df(){let e=C();if(e)try{let t=Mo(e.themePath,".vibespot");Rf(t,{recursive:!0});let n={sessionId:e.id,themeName:e.themeName,messages:e.messages,updatedAt:Date.now()};Nf(Mo(t,"chat.json"),JSON.stringify(n,null,2),"utf-8")}catch{}}function bc(e){let t=Mo(e,".vibespot","chat.json");if(!mc(t))return[];try{let n=JSON.parse(Pf(t,"utf-8"));return Array.isArray(n.messages)?n.messages:[]}catch{return[]}}function Sc(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&&ms(e.pages[0].templateId),t.updatedAt=Date.now()}}function vc(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&&vc(i.children,s.slice(1).join("."),n))}var us=N(()=>{"use strict";y();ps();Ut();le()});import{existsSync as Io,rmSync as Po}from"fs";import{join as Pn}from"path";function No(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 ms(e){let t=C();if(!t)return!1;let n=t.templates.find(s=>s.id===e);return n?(t.activeTemplateId=e,on(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,on(l),s.updatedAt=Date.now(),l}function xc(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,on(l),n.updatedAt=Date.now(),l}function wc(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 Cc(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 kc(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=Pn(n.themePath,"templates"),r=`${o.id}.html`,a=Pn(i,r);if(Io(a)&&Po(a,{force:!0}),o.pageType==="blog_post"){let l=Pn(i,`${o.id}-listing.html`);Io(l)&&Po(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=Pn(n.themePath,"modules");for(let l of r){let c=Pn(a,`${l}.module`);Io(c)&&Po(c,{recursive:!0,force:!0})}}}if(n.activeTemplateId===e&&(n.templates.length>0?ms(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=Pn(n.themePath,".vibespot","plan.md");Io(r)&&Po(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();ps();us()});import{readFileSync as xt,readdirSync as cr,existsSync as Ie,writeFileSync as gs,mkdirSync as Ro,rmSync as ir,renameSync as rr,cpSync as jf}from"fs";import{join as pe,dirname as Tc}from"path";import{homedir as Lf}from"os";function Oo(){if(Nn)return Nn;try{return Ie(ar)?(Nn=JSON.parse(xt(ar,"utf-8")),Nn):lr()}catch{return lr()}}function Fo(e){Nn=e;try{Ro(de,{recursive:!0}),gs(ar,JSON.stringify(e),"utf-8")}catch{}}function lr(){if(!Ie(de))return[];let e=[];for(let t of cr(de).filter(n=>n.endsWith(".json")&&n!=="_index.json"))try{let n=JSON.parse(xt(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 Nn=e,Fo(e),e}function Ac(e){let t=Oo(),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),Fo(t)}function Jf(e){let t=Oo().filter(n=>n.id!==e);Fo(t)}function Bf(e){let t=Oo().filter(n=>n.themeName!==e);Fo(t)}function C(){return Ue}function _c(){return`vibe-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`}function Rn(e,t,n={}){let s={id:_c(),themePath:e,themeName:t,isImported:!!n.isImported,templates:[],activeTemplateId:"",messages:[],modules:[],sharedCss:"",sharedJs:"",template:"",moduleOrder:[],createdAt:Date.now(),updatedAt:Date.now()};return Ue=s,Eo(e),s}function L(){if(!Ue)return;Ro(de,{recursive:!0});let e=pe(de,`${Ue.id}.json`);gs(e,JSON.stringify(Ue,null,2),"utf-8"),Ac(Ue)}function Do(e){let t=pe(de,e+".json");if(!Ie(t))return null;try{let n=JSON.parse(xt(t,"utf-8"));if(n.templates||(n.templates=[]),n.activeTemplateId||(n.activeTemplateId=""),No(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 On(){return Ie(de)?Oo():[]}function $c(e,t=!1){let n=pe(de,e+".json"),s="";if(t)try{let o=JSON.parse(xt(n,"utf-8"));s=o.themeName||"",o.themePath&&Ie(o.themePath)&&ir(o.themePath,{recursive:!0,force:!0})}catch{}else try{s=JSON.parse(xt(n,"utf-8")).themeName||""}catch{}try{Ie(n)&&ir(n)}catch{}if(s&&Ie(de)){for(let o of cr(de).filter(i=>i.endsWith(".json")&&i!=="_index.json"))try{JSON.parse(xt(pe(de,o),"utf-8")).themeName===s&&ir(pe(de,o))}catch{}Bf(s)}else Jf(e);Ue?.id===e&&(Ue=null)}function Ec(e,t){let n=pe(de,e+".json");if(!Ie(n))return{ok:!1,error:"Session not found"};let s;try{s=JSON.parse(xt(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(Tc(i),t);if(Ie(i)){if(Ie(r))return{ok:!1,error:"A project with that name already exists"};try{rr(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{rr(a,l)}catch{}let c=pe(r,"js",`${o}-animations.js`),d=pe(r,"js",`${t}-animations.js`);if(Ie(c))try{rr(c,d)}catch{}let u=pe(r,"theme.json");if(Ie(u))try{let m=JSON.parse(xt(u,"utf-8"));m.label=t,m.name=t,gs(u,JSON.stringify(m,null,2),"utf-8")}catch{}}if(Ie(de))for(let a of cr(de).filter(l=>l.endsWith(".json")&&l!=="_index.json"))try{let l=JSON.parse(xt(pe(de,a),"utf-8"));l.themeName===o&&(l.themeName=t,l.themePath=r,l.updatedAt=Date.now(),gs(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()),lr(),{ok:!0}}function Mc(e){let t=pe(de,e+".json");if(!Ie(t))return{ok:!1,error:"Session not found"};let n;try{n=JSON.parse(xt(t,"utf-8"))}catch{return{ok:!1,error:"Failed to read session"}}let s=n.themeName.replace(/-copy(-\d+)?$/,""),o=Tc(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{jf(n.themePath,a,{recursive:!0})}catch(d){return{ok:!1,error:`Failed to copy files: ${d instanceof Error?d.message:String(d)}`}}else Ro(a,{recursive:!0});let l=_c(),c={...JSON.parse(JSON.stringify(n)),id:l,themeName:i,themePath:a,createdAt:Date.now(),updatedAt:Date.now(),messages:[]};return Ro(de,{recursive:!0}),gs(pe(de,`${l}.json`),JSON.stringify(c,null,2),"utf-8"),Ac(c),{ok:!0,newName:i,newSessionId:l}}var de,ar,Nn,Ue,ps=N(()=>{"use strict";y();In();Ut();de=pe(Lf(),".vibespot","sessions"),ar=pe(de,"_index.json"),Nn=null;Ue=null});import{readFileSync as Hf,readdirSync as Nc,statSync as dr}from"fs";import{createHash as Uf}from"crypto";import{join as be,relative as Gf}from"path";function Jo(e){let t=[];if(!x(e))return fh(e,[{severity:"error",rule:"theme.path.missing",message:`Theme directory not found: ${e}`}]);let n=Fn(e),s=uh(e),o=ph(e),i=gh(e),r=Yf(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 fs(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 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+`
|
|
190
|
+
`}function Bo(e,t){let n=be(e,"css");if(x(n))try{for(let r of Nc(n))if(r.endsWith("-theme.css"))return null}catch{}let s=Fn(e),o=fs(s);if(!o)return null;let i=be(n,`${t}-theme.css`);return B(i,o),i}function hs(e){return be(e,Wf)}function Vf(e,t=new Date().toISOString()){return{version:1,createdAt:t,files:Fc(e)}}function ur(e,t){let n=Vf(e,t),s=hs(e);return B(s,JSON.stringify(n,null,2)+`
|
|
191
|
+
`),s}function Rc(e){let t=hs(e);return x(t)?null:ur(e)}function zf(e){let t=hs(e);if(!x(t))return null;try{let n=JSON.parse(P(t));return yh(n)?n:null}catch{return null}}function Yf(e){let t=hs(e),n=zf(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=Fc(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:Lo(d.text),afterLines:Lo(u.text)}):r.push({file:d.path,status:"deleted",beforeSha256:d.sha256,beforeSize:d.size,beforeLines:Lo(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:Lo(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=dh(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(oh.source,"g");for(;(g=h.exec(m))!==null;){let f=g[1],b=new RegExp(ih.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 j=Ic(M[0]);o.set(j,v)}}}for(let f of[qf,Xf,Zf]){let b=new RegExp(f.source,"g"),S;for(;(S=b.exec(m))!==null;){let v=Ic(S[0]);v&&s.set(v,(s.get(v)??0)+1)}}jo(m,Qf,i,ah),jo(m,eh,r,f=>f.trim()),rh(m,a),jo(m,nh,l,f=>f.trim()),jo(m,sh,c,f=>f.trim())}let d=[...s.entries()].filter(([u])=>!ch(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 jo(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 rh(e,t){let n=new RegExp(th.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 ah(e){return e.split(",")[0].trim().replace(/^["']|["']$/g,"")}function Ic(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 ch(e){return lh.has(e)}function dh(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 uh(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=dr(d)}catch{continue}if(!u.isFile())continue;let m;try{m=P(d)}catch{continue}let g=mr(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:bh(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 mr(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 ph(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)&&Oc(r,o,t,0)}return t}function Oc(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&&!mh.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)&&Oc(i.children,t,n,s+1)}}function gh(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)&&Pc(a,e,r,t);let l=be(n,i,"module.js");if(x(l))try{P(l).trim().length>0&&t.push({file:pr(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=dr(r)}catch{continue}a.isFile()&&Pc(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 Pc(e,t,n,s){let o;try{o=P(e)}catch{return}let i=pr(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 fh(e,t){let n={hasSnapshot:!1,snapshotPath:hs(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 Fc(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=dr(i)}catch{continue}if(r.isDirectory()){n(i);continue}if(!r.isFile())continue;let a=pr(e,i),l=Hf(i),c={path:a,sha256:Uf("sha256").update(l).digest("hex"),size:l.length};hh(a)&&(c.text=l.toString("utf8")),t.push(c)}}return n(e),t.sort((s,o)=>s.path.localeCompare(o.path))}function hh(e){let t=e.lastIndexOf(".");return t<0?!1:Kf.has(e.slice(t).toLowerCase())}function yh(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 Lo(e){if(e!==void 0)return e.length===0?0:e.split(/\r\n|\r|\n/).length}function Gt(e){try{return Nc(e)}catch{return[]}}function pr(e,t){return Gf(e,t).split("\\").join("/")}function bh(e){return[...new Set(e)]}var Wf,Kf,qf,Xf,Zf,Qf,eh,th,nh,sh,oh,ih,lh,mh,Ho=N(()=>{"use strict";y();oe();Wf=".vibespot/import-snapshot.json",Kf=new Set([".css",".html",".htm",".js",".json",".md",".txt",".svg",".yml",".yaml"]);qf=/#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})\b/g,Xf=/\brgba?\([^)]+\)/g,Zf=/\bhsla?\([^)]+\)/g,Qf=/font-family\s*:\s*([^;}\n]+)/g,eh=/font-size\s*:\s*([^;}\n]+)/g,th=/(?:padding|margin|gap)(?:-(?:top|right|bottom|left))?\s*:\s*([^;}\n]+)/g,nh=/border-radius\s*:\s*([^;}\n]+)/g,sh=/box-shadow\s*:\s*([^;}\n]+)/g,oh=/:root\s*\{([\s\S]*?)\}/g,ih=/(--[\w-]+)\s*:\s*([^;}\n]+)/g;lh=new Set(["#000000","#ffffff","transparent","currentcolor","inherit","initial"]);mh=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 gr,readdirSync as bs,existsSync as xe,writeFileSync as Ye,mkdirSync as ys,rmSync as Dc}from"fs";import{join as U}from"path";function we(e){try{return gr(e,"utf-8")}catch{return""}}function Lc(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 Sh(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=mr(n);return{id:s,label:a,pageType:i,contentMode:r,moduleNames:c,templateContent:n,filename:t}}function vh(e,t,n,s,o){if(!xe(e))return[];let i=[],r=bs(e).filter(a=>a.endsWith(".html")&&a!=="home.html");for(let a of r){let l=U(e,a),c=Sh(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 Uo(e){let t=C();if(!t)return;let n=bc(e);n.length>0&&t.messages.length===0&&(t.messages=n),Eo(e),Rc(e);let s=U(e,"modules");if(!xe(s))return;let o=bs(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=bs(i).filter(v=>v.endsWith("-theme.css"));S.length>0&&(a=we(U(i,S[0])),t.sharedCss=a)}if(xe(r)){let S=bs(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=Fn(e),v=fs(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=vh(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}on(b[0])}else t.templates||(t.templates=[]),t.activeTemplateId||(t.activeTemplateId=""),No(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");ys(s,{recursive:!0});for(let l of n.values())ys(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");ys(l,{recursive:!0}),Ye(U(l,`${e.themeName}-theme.css`),e.sharedCss,"utf-8")}if(e.sharedJs){let l=U(t,"js");ys(l,{recursive:!0}),Ye(U(l,`${e.themeName}-animations.js`),e.sharedJs,"utf-8")}let o=U(t,"templates");ys(o,{recursive:!0});let i=U(o,"home.html");(e.templates.length>0||e.modules.length>0)&&xe(i)&&Dc(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=kh(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||Ch(l),d=jc(c,l.label,l.pageType),u=`${l.id}.html`;Ye(U(o,u),d,"utf-8"),a.add(u),l.pageType==="blog_post"&&(Th(o,l),a.add(`${l.id}-listing.html`))}else if(e.modules.length>0){let l=e.template||Ah(),c=jc(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 bs(o))l.startsWith("lp-")&&l.endsWith(".html")&&!a.has(l)&&Dc(U(o,l),{force:!0})}catch{}xh(),wh()}function Jc(){let e=C();e&&(e.modules=[],e.moduleOrder=[],e.sharedCss="",e.sharedJs="",e.template="",Uo(e.themePath),e.updatedAt=Date.now(),at())}function Bc(){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))}on(t),e.updatedAt=Date.now()}function xh(){let e=C();if(!e)return;let t=U(e.themePath,"templates","layouts","base.html");if(xe(t))try{let n=gr(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 }}`),Ye(t,n,"utf-8")}catch{}}function
|
|
197
|
+
{{ standard_footer_includes }}`),Ye(t,n,"utf-8")}catch{}}function wh(){let e=C();if(!e)return;let t=U(e.themePath,"theme.json");if(xe(t))try{let n=JSON.parse(gr(t,"utf-8"));n.label=e.themeName,n.name=e.themeName,Ye(t,JSON.stringify(n,null,2),"utf-8")}catch{}}function jc(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 Ch(e){if(e.modules.length===0)return"";let n=C().themeName,o=Lc(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 kh(e){let n=Lc(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 Th(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
|
-
`;Ye(U(e,`${t.id}-listing.html`),n,"utf-8")}function
|
|
305
|
+
`;Ye(U(e,`${t.id}-listing.html`),n,"utf-8")}function Ah(){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 fr=N(()=>{"use strict";y();ps();us();Ut();In();Ho()});var Hc=N(()=>{"use strict";y();nc();ps();us();fr();Ut()});var Ce=N(()=>{"use strict";y();Hc()});function rn(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]=rn(n.children):t[n.name]=n.default??"";return t}function jn(e,t){let n=e;return n=Oh(n),n=Kc(n,t),n=Vc(n,t),n=zc(n,t),n=Dh(n),n}function br(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 Oh(e){return e=e.replace(_h,""),e=e.replace($h,""),e=e.replace(Eh,""),Uc.lastIndex=0,e=e.replace(Uc,(t,n)=>`/theme-assets/${n}`),Gc.lastIndex=0,e=e.replace(Gc,""),e=e.replace(Mh,""),e=e.replace(Ih,""),e=e.replace(Ph,""),e=e.replace(Nh,""),e=e.replace(Rh,""),e}function Kc(e,t){let n=e,s=0;for(;s<30;){s++;let o=Fh(n);if(!o)break;let{varName:i,iterExpr:r,body:a,start:l,end:c}=o,d=jh(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=Kc(a,h);return f=Vc(f,h),f=zc(f,h),f}).join("")),n=n.slice(0,l)+u+n.slice(c)}return n}function Fh(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 Vc(e,t){let n=e,s=0;for(;hr.test(n)&&s<50;)s++,n=n.replace(hr,(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(Dn(i,t))return d[0];for(let u=1;u<d.length;u+=2){let m=d[u],g=d[u+1]||"";if(Dn(m,t))return g}return c}return Dn(i,t)?l:c}),hr.lastIndex=0;return n}function zc(e,t){return e.replace(/\{\{[-\s]*(.*?)[-\s]*\}\}/g,(n,s)=>{let i=s.trim().split("|"),r=i[0].trim(),a=Lh(t,r);for(let c=1;c<i.length;c++)a=qc(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 Dh(e){return e=e.replace(/\{%.*?%\}/gs,""),e=e.replace(/\{\{.*?\}\}/gs,""),e}function jh(e,t){let n=e.match(/^range\(\s*(.+?)\s*,\s*(.+?)\s*\)$/);if(n){let o=Wc(n[1],t),i=Wc(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=Wt(t,s[1].trim());return typeof o=="string"?o.split(s[2]):[]}return Wt(t,e)}function Wc(e,t){let s=e.trim().split("|"),o=s[0].trim();if(!isNaN(Number(o)))return Number(o);let i=Wt(t,o);for(let r=1;r<s.length;r++)i=qc(i,s[r].trim());return Number(i)||0}function Wt(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 Lh(e,t){let n=t.match(/^(.+?)\s*([*/])\s*([\d.]+)$/);if(n){let s=Wt(e,n[1].trim());if(s==null||s==="")return"";let o=Number(s);if(Number.isNaN(o))return"";let i=Number(n[3]);return n[2]==="/"?i===0?"":o/i:o*i}return Wt(e,t)}function Dn(e,t){let n=e.trim();if(n.startsWith("not "))return!Dn(n.slice(4),t);if(n.includes(" and "))return n.split(" and ").every(i=>Dn(i,t));if(n.includes(" or "))return n.split(" or ").some(i=>Dn(i,t));let s=n.match(/^(.+?)\s*(==|!=|>=|<=|>|<)\s*(.+)$/);if(s){let i=Wt(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=Wt(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=Wt(t,n);return Yc(o)}function Yc(e){return!(e==null||e===""||e===0||e===!1||Array.isArray(e)&&e.length===0)}function qc(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 Yc(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));case"convert_rgb":{let r=yr(e);return r?Bh(r):""}default:return e}}function yr(e){if(e==null)return null;if(typeof e=="string"){let t=e.match(/#?([0-9a-fA-F]{6}|[0-9a-fA-F]{3})(?![0-9a-fA-F])/);return t?Jh(t[1]):null}if(typeof e=="object"){let t=e;if(typeof t.color=="string")return yr(t.color);if(typeof t.hex=="string")return yr(t.hex)}return null}function Jh(e){let t=e.toLowerCase();return t.length===3?t.split("").map(n=>n+n).join(""):t}function Bh(e){let t=parseInt(e.slice(0,2),16),n=parseInt(e.slice(2,4),16),s=parseInt(e.slice(4,6),16);return`${t}, ${n}, ${s}`}var _h,$h,Eh,Uc,Gc,Mh,Ih,Ph,Nh,Rh,hr,Sr=N(()=>{"use strict";y();_h=/\{%[-\s]*require_(css|js)\b.*?%\}/gs,$h=/\{%[-\s]*end_require_(css|js)\s*%\}/gs,Eh=/\{\{[-\s]*require_(css|js)\(.*?\)\s*\}\}/gs,Uc=/\{\{[-\s]*get_asset_url\(["'](?:[^"'\/]+\/)?assets\/(.*?)["']\)\s*\}\}/gs,Gc=/\{\{[-\s]*get_asset_url\(.*?\)\s*\}\}/gs,Mh=/\{%[-\s]*(end_)?(dnd_area|dnd_section|dnd_column|dnd_row|dnd_module)\b.*?%\}/gs,Ih=/\{%[-\s]*module\b.*?%\}/gs,Ph=/\{%[-\s]*(extends|block|endblock|set)\b.*?%\}/gs,Nh=/\{#.*?#\}/gs,Rh=/\{\{[-\s]*content\.\w+.*?\}\}/gs,hr=/\{%[-\s]*if\s+(.*?)\s*-?%\}((?:(?!\{%[-\s]*if\s)[\s\S])*?)\{%[-\s]*endif\s*-?%\}/g});var Go={};Ge(Go,{buildModulePreviewHtml:()=>wr,buildPreviewHtml:()=>xr});function Hh(e){if(Ln()==="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 Uh(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 vr(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 xr(){let e=C();if(!e)return Xc();let t=ve(),n=e.moduleOrder||[];if(t.length===0&&n.length===0)return Xc();if(Hh(t))return Gh(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:rn(u)}}catch{d={module:{}}}let m=vr(c.moduleHtml,u),g=jn(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=Uh(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 br({renderedModules:s,sharedCss:e.sharedCss,moduleCssArray:[l,...o],sharedJs:e.sharedJs,moduleJsArray:i})}function Xc(){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 wr(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:rn(o)}}catch{s={module:{}}}let i=vr(n.moduleHtml,o),r=jn(i,s);return br({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 Gh(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:rn(a)}}catch{r={module:{}}}let l=vr(i.moduleHtml,a),c=jn(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,7 +485,7 @@ document.addEventListener('click', function(e) {
|
|
|
485
485
|
});
|
|
486
486
|
</script>
|
|
487
487
|
</body>
|
|
488
|
-
</html>`}var
|
|
488
|
+
</html>`}var Ss=N(()=>{"use strict";y();Sr();Ce();vs()});function ct(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 xs(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 ct(c)}function Cr(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 Zc(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=ct(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=>Cr(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=ct(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=>Cr(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=xs(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=>Cr(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 Wo=N(()=>{"use strict";y();Ce();le()});function Bn(){let e=C();return e?{pageType:ke()?.pageType,brandAssets:e.brandAssets}:{}}function ed(e,t,n=!1,s,o){let r=[{type:"text",text:Kh(t,n)}];if(n){let l=`## HubSpot CMS Rules
|
|
489
489
|
${Je()}
|
|
490
490
|
|
|
491
491
|
## Conversion Guide Reference
|
|
@@ -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
|
+
${ls()}
|
|
516
516
|
|
|
517
517
|
## Content & Copywriting Guide
|
|
518
|
-
${
|
|
518
|
+
${Ki()}
|
|
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=Wh(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 Wh(e,t){let n=[];if(e){let s=zi(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=Vi();s&&n.push(`## Anti-AI Copy Rules (Humanify)
|
|
528
528
|
${s}`)}return n.join(`
|
|
529
529
|
|
|
530
|
-
`)}function
|
|
530
|
+
`)}function Kh(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 ws(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?zi(s):"",a=r?`
|
|
689
689
|
|
|
690
690
|
## Page Type Context
|
|
691
691
|
${r}`:"",l="";if(o?.styleguide&&(l+=`
|
|
@@ -694,7 +694,7 @@ ${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=Vi();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+`
|
|
@@ -728,51 +728,54 @@ 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
|
+
${ls()}
|
|
732
732
|
|
|
733
733
|
## Content & Copywriting Guide
|
|
734
|
-
${
|
|
734
|
+
${Ki()}
|
|
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 Jn(e,t){return e.length<=t?e:e.slice(0,t)+`
|
|
741
|
+
/* \u2026truncated ${e.length-t} chars to fit the context budget\u2026 */`}function Cs(){let e=C(),t=[],n=e.modules,s=n.length;if(s>0){t.push(`
|
|
741
742
|
|
|
742
743
|
## Page Narrative (module sequence)
|
|
743
744
|
`),t.push(`This template has ${s} module${s===1?"":"s"} in this order:
|
|
744
|
-
`);for(let
|
|
745
|
+
`);for(let d=0;d<s;d++)t.push(`${d+1}. ${n[d].moduleName}
|
|
745
746
|
`);t.push(`
|
|
746
747
|
When the user asks to modify this page, decide whether to MODIFY existing modules, ADD new ones at the right narrative position, REARRANGE the sequence, or REMOVE sections. Always include ALL modules you want to keep in your output.
|
|
747
748
|
`),t.push(`
|
|
748
749
|
## Current Module State
|
|
749
|
-
`);for(let
|
|
750
|
-
### ${
|
|
751
|
-
`)
|
|
750
|
+
`);let a=0,l=!1,c=Math.max(2e3,Math.floor(Qc/Math.max(s,1)));for(let d=0;d<s;d++){let u=n[d];if(l){t.push(`
|
|
751
|
+
### ${d+1}/${s}: ${u.moduleName}.module \u2014 (source omitted to fit context budget; ask to edit it specifically to load its source)
|
|
752
|
+
`);continue}let m=`
|
|
753
|
+
### ${d+1}/${s}: ${u.moduleName}.module
|
|
754
|
+
**fields.json:**
|
|
752
755
|
\`\`\`json
|
|
753
|
-
${
|
|
756
|
+
${Jn(u.fieldsJson,c)}
|
|
754
757
|
\`\`\`
|
|
755
|
-
|
|
758
|
+
**module.html:**
|
|
756
759
|
\`\`\`html
|
|
757
|
-
${
|
|
760
|
+
${Jn(u.moduleHtml,c)}
|
|
758
761
|
\`\`\`
|
|
759
|
-
|
|
762
|
+
**module.css:**
|
|
760
763
|
\`\`\`css
|
|
761
|
-
${
|
|
764
|
+
${Jn(u.moduleCss,c)}
|
|
762
765
|
\`\`\`
|
|
763
|
-
|
|
766
|
+
`+(u.moduleJs?`**module.js:**
|
|
764
767
|
\`\`\`js
|
|
765
|
-
${
|
|
768
|
+
${Jn(u.moduleJs,c)}
|
|
766
769
|
\`\`\`
|
|
767
|
-
|
|
770
|
+
`:"");a+=m.length,t.push(m),a>Qc&&(l=!0)}e.sharedCss&&t.push(`
|
|
768
771
|
### Shared CSS
|
|
769
772
|
\`\`\`css
|
|
770
|
-
${e.sharedCss}
|
|
773
|
+
${Jn(e.sharedCss,c)}
|
|
771
774
|
\`\`\`
|
|
772
775
|
`),e.sharedJs&&t.push(`
|
|
773
776
|
### Shared JS
|
|
774
777
|
\`\`\`js
|
|
775
|
-
${e.sharedJs}
|
|
778
|
+
${Jn(e.sharedJs,c)}
|
|
776
779
|
\`\`\`
|
|
777
780
|
`)}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
781
|
|
|
@@ -780,7 +783,7 @@ ${e.sharedJs}
|
|
|
780
783
|
`);for(let a of r)t.push(`- ${a.module.moduleName} (used in: ${a.usedIn.join(", ")})
|
|
781
784
|
`);t.push(`
|
|
782
785
|
The user can ask to reuse any of these modules by name.
|
|
783
|
-
`)}return t.join("")}function
|
|
786
|
+
`)}return t.join("")}function kr(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=Cs(),r="";if(n.assets?.length){let d=n.assets.filter(u=>u.type==="image"&&u.usage==="asset");d.length>0&&(r=`
|
|
784
787
|
|
|
785
788
|
## Available Theme Assets
|
|
786
789
|
These images are in the theme's assets/ folder. Reference them with get_asset_url("${n.themeName}/assets/filename"):
|
|
@@ -794,13 +797,13 @@ ${i}`),r&&(a+=r),a+="\n\n---\nRemember: respond with a ```vibespot-modules JSON
|
|
|
794
797
|
[Attached document: ${d.originalName}]
|
|
795
798
|
${d.extractedText}`),d.type==="image"&&d.usage==="asset"&&d.assetPath&&(a+=`
|
|
796
799
|
|
|
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
|
|
800
|
+
[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 Qc,td=N(()=>{"use strict";y();Ke();Ce();Qc=2e5});import{spawn as sd}from"child_process";import{mkdtempSync as Vh}from"fs";import{tmpdir as nd}from"os";import{join as zh}from"path";async function od(){return Tr||(Tr=(await import("@anthropic-ai/sdk")).default),Tr}function id(e){if(!e?.length)return"";let t=[];for(let n of e)n.type==="image"&&n.usage==="asset"&&n.assetPath&&t.push(`
|
|
798
801
|
[Uploaded image: ${n.originalName} \u2192 use get_asset_url("${n.assetPath}")]`),n.type==="document"&&n.extractedText&&t.push(`
|
|
799
802
|
|
|
800
803
|
---
|
|
801
804
|
[Attached document: ${n.originalName}]
|
|
802
|
-
${n.extractedText}`);return t.join("")}async function
|
|
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&&(
|
|
805
|
+
${n.extractedText}`);return t.join("")}async function rd(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(je[0]);let g=setInterval(()=>{u++,m(je[Math.min(u,je.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{}St({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>=Ar.length)throw d;let h=Ar[l];E.warn("ai-engine",`Rate limited (429), attempt ${l+1}/${Ar.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 ad(e,t,n){let s=ye(),i=C().modules.length>0,r=kr(e,n),a=Bn(),l=ed(s,t,i,a.pageType,a.brandAssets);return{messages:r,systemBlocks:l,conversionGuide:s,editMode:i}}async function _r(e,t,n,s,o,i,r,a,l){let c=await od(),d=new c({apiKey:t,...l?{baseURL:l}:{}}),{messages:u,systemBlocks:m}=ad(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 rd(d,m,u,s,o,i,r)}async function ld(e,t,n,s,o,i,r){let a=await Fi();if(!a)throw new Error("Claude OAuth session expired. Please re-authenticate in Settings.");let l=await od(),c=new l({authToken:a,defaultHeaders:Xn}),{messages:d,systemBlocks:u}=ad(e,t,r),m=[{type:"text",text:Sn},...u];E.info("anthropic-oauth","API call",{model:n,systemBlockCount:m.length,cachedBlocks:m.filter(g=>g.cache_control).length,messageCount:d.length}),await rd(c,m,d,n,s,o,i,"claude-oauth")}async function $r(e,t,n,s,o,i,r,a,l){let c=ye(),d=C().modules.length>0,u=kr(e,a),m=Bn(),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=ws(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(je[0]);let j=setInterval(()=>{w++,M(je[Math.min(w,je.length-1)])},6e3),J="",H,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(`
|
|
806
|
+
`);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&&(J+=z,o(z)),_e.usage&&(H=_e.usage)}catch{}}}}finally{clearInterval(j)}St({engine:"openai-api",model:s,name:"vibe-chat",input:{system:h,messages:g},output:J,usage:_n(H),startTime:S,endTime:new Date}),r&&r(J)}async function Er(e,t,n,s,o,i,r,a,l){let c=ye(),d=C(),u=d.modules.length>0,m=Cs(),g=Bn(),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
807
|
|
|
805
808
|
---
|
|
806
809
|
${m}`:e;if(r?.length)for(let F of r)F.type==="document"&&F.extractedText&&(f+=`
|
|
@@ -809,36 +812,37 @@ ${m}`:e;if(r?.length)for(let F of r)F.type==="document"&&F.extractedText&&(f+=`
|
|
|
809
812
|
[Attached document: ${F.originalName}]
|
|
810
813
|
${F.extractedText}`),F.type==="image"&&F.usage==="asset"&&F.assetPath&&(f+=`
|
|
811
814
|
|
|
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=
|
|
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)}
|
|
814
|
-
`))>=0;){let
|
|
815
|
+
[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=ws(c,n,u,g.pageType,g.brandAssets),M=new Date,j=await fetch(v,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({systemInstruction:{parts:[{text:w}]},contents:h,generationConfig:{maxOutputTokens:48e3}})});if(!j.ok){let F=await j.text();throw new Error(`Gemini API error (${j.status}): ${F}`)}let J=0,H=o||(()=>{});H(je[0]);let K=setInterval(()=>{J++,H(je[Math.min(J,je.length-1)])},6e3),X="",O,k=j.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(`
|
|
816
|
+
`);$=_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)}St({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 Yh(){if(ks)return ks;try{ks=Vh(zh(nd(),"vibespot-claude-"))}catch{ks=nd()}return ks}function qh(e){return/prompt is too long|exceed\w*\s+(the\s+)?(maximum\s+)?context|too many (input )?tokens|200000|context window/i.test(e)?"This request exceeded the model's 200k-token context window. vibeSpot isolates the Claude Code CLI from your MCP servers and project memory, so this usually means the page state itself is too large. Try: removing or splitting very large modules, starting a fresh theme, or switching to the Anthropic API engine in AI Settings (isolated per-request, no ambient context).":e}function Ir(e,t,n={},s){return new Promise((o,i)=>{let r={...process.env};delete r.CLAUDECODE;let a=sd("claude",e,{stdio:["pipe","pipe","pipe"],env:r,cwd:Yh()}),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 j=M.text;l+=j,n.onChunk&&n.onChunk(j)}else if(M.type==="tool_use"){let j=M;j.name&&n.onToolUse&&n.onToolUse(j.name,j.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(`
|
|
817
|
+
`))>=0;){let j=d.slice(0,M).trim();if(d=d.slice(M+1),!!j)try{h(JSON.parse(j))}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(()=>{if(w!==0||m&&m.is_error){let j=`${c}
|
|
818
|
+
${l}`,J=qh(j);i(J!==j?new Error(J):new Error(`claude exited with code ${w}.
|
|
815
819
|
`+(c?`Stderr: ${c.slice(0,500)}
|
|
816
|
-
`:"")+(l?`Output: ${l.slice(0,500)}`:"No output")))
|
|
820
|
+
`:"")+(l?`Output: ${l.slice(0,500)}`:"No output")))}else 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
821
|
`+(c?`Stderr: ${c.slice(0,500)}
|
|
818
|
-
`:"")+`Partial output (${l.length} chars): ${l.slice(0,500)}`)))},b);a.on("close",()=>clearTimeout(v))})}function
|
|
822
|
+
`:"")+`Partial output (${l.length} chars): ${l.slice(0,500)}`)))},b);a.on("close",()=>clearTimeout(v))})}function Pr(e,t,n,s,o){return new Promise((i,r)=>{let a={...process.env};delete a.CLAUDECODE;let l=sd(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
823
|
`+(d?`Stderr: ${d.slice(0,500)}
|
|
820
824
|
`:"")+(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
825
|
`+(d?`Stderr: ${d.slice(0,500)}
|
|
822
|
-
`:"")+`Partial output (${c.length} chars): ${c.slice(0,500)}`)))},h);l.on("close",()=>clearTimeout(b))})}async function
|
|
826
|
+
`:"")+`Partial output (${c.length} chars): ${c.slice(0,500)}`)))},h);l.on("close",()=>clearTimeout(b))})}async function cd(e,t,n,s,o,i){let r=ye(),a=R(),l=C().modules.length>0,c=Bn(),d=ws(r,t,l,c.pageType,c.brandAssets);d+=`
|
|
823
827
|
|
|
824
828
|
## User Request
|
|
825
|
-
`+e,d+=
|
|
829
|
+
`+e,d+=Cs(),d+=id(i),d+="\n\n---\nRemember: respond with a ```vibespot-modules JSON block containing ALL modules. No text-only responses.";let u=["--print",...Mr];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(je[0]);let h=setInterval(()=>{m++;let f=je[Math.min(m,je.length-1)];g(f)},6e3);try{let f=await Ir(u,d,{onChunk:b=>n(b),onToolUse:(b,S)=>{g(Xh(b,S))}});o&&o(f)}finally{clearInterval(h)}}function Xh(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 Nr(e,t,n,s,o,i,r){let a=ye(),l=C().modules.length>0,c=Bn(),d=ws(a,n,l,c.pageType,c.brandAssets);d+=`
|
|
826
830
|
|
|
827
831
|
## User Request
|
|
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(`
|
|
832
|
+
`+t,d+=Cs(),d+=id(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(je[0]);let f=setInterval(()=>{g++;let b=je[Math.min(g,je.length-1)];h(b)},6e3);try{let b=await Pr(u,m,d,S=>{s(S)});i&&i(b)}finally{clearInterval(f)}}var Tr,je,Ar,Mr,ks,Rr=N(()=>{"use strict";y();Ke();ee();_t();Ce();td();le();Be();tn();Tr=null;je=["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..."],Ar=[10,20,40,60,120];Mr=["--strict-mcp-config"],ks=null});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 Zh,mkdirSync as dd,existsSync as Or,readFileSync as Fr}from"fs";import{join as an,extname as Qh}from"path";import{randomUUID as ey}from"crypto";import ty from"busboy";function iy(e,t){if(md.has(t))return t;let n=e.slice(e.lastIndexOf(".")).toLowerCase();return oy[n]??t}function ry(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_").replace(/_{2,}/g,"_").replace(/^_+|_+$/g,"").toLowerCase()}function ay(e,t){if(!Or(an(e,t)))return t;let n=Qh(t),s=t.slice(0,-n.length||void 0),o=1;for(;Or(an(e,`${s}-${o}${n}`));)o++;return`${s}-${o}${n}`}async function ly(e){let t=(await import("pdf-parse")).default,n=Fr(e);return(await t(n)).text}async function cy(e){return(await(await import("mammoth")).extractRawText({path:e})).value}function dy(e){return Fr(e,"utf-8")}function pd(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=ty({headers:e.headers,limits:{fileSize:ny,files:10}});l.on("file",(c,d,u)=>{let{filename:m,mimeType:g}=u;r++;let h=iy(m,g);if(!md.has(h)){i.push(`Unsupported file type: ${m} (${g})`),d.resume();return}let f=ud.has(h),b=ry(m),S=ey(),v,w;f?(v=an(n.themePath,"assets"),dd(v,{recursive:!0}),w=ay(v,b)):(v=an(n.themePath,".vibespot","uploads"),dd(v,{recursive:!0}),w=`${S}-${b}`);let M=an(v,w),j=Zh(M),J=0,H=!1;d.on("data",K=>{J+=K.length}),d.on("limit",()=>{H=!0,i.push(`File too large (>10MB): ${m}`)}),d.pipe(j),a.push(new Promise(K=>{j.on("finish",()=>{if(!H){let X={id:S,filename:w,originalName:m,type:f?"image":"document",usage:f?"asset":"context",mimeType:h,size:J,addedAt:new Date().toISOString()};o.push(X),pc(X)}K()}),j.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=an(n.themePath,".vibespot","uploads",c.filename);try{c.mimeType==="application/pdf"?c.extractedText=await ly(d):c.mimeType==="application/vnd.openxmlformats-officedocument.wordprocessingml.document"?c.extractedText=await cy(d):c.extractedText=dy(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 Ko(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=an(t.themePath,"assets",s.filename);Or(i)&&(o.base64=Fr(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 ny,ud,sy,md,oy,Dr=N(()=>{"use strict";y();Xe();Ce();le();ny=10*1024*1024,ud=new Set(["image/png","image/jpeg","image/jpg","image/svg+xml","image/webp","image/gif"]),sy=new Set(["application/pdf","application/vnd.openxmlformats-officedocument.wordprocessingml.document","text/markdown","text/plain"]),md=new Set([...ud,...sy]),oy={".md":"text/markdown",".txt":"text/plain",".markdown":"text/markdown"}});var vd={};Ge(vd,{LANGDOCK_BASE_URLS:()=>Ts,callAgent:()=>Pe,callAgentAPI:()=>Sd,isAgenticCapable:()=>_s,isCLIEngine:()=>Un,resolveThinkingBudget:()=>Hn});async function Vo(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>=jr.length)throw s;let a=jr[n];E.warn("agent-adapter",`Rate limited (429), attempt ${n+1}/${jr.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 As(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 yd(){return Lr||(Lr=(await import("@anthropic-ai/sdk")).default),Lr}async function gd(e,t,n,s,o,i){let r=await yd(),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 Vo(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:As(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 Vo(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 uy(e,t,n){let s=await yd(),o=new s({authToken:e,defaultHeaders:Xn}),i=n.messages,r;if(n.systemBlocks?r=[{type:"text",text:Sn},...n.systemBlocks]:r=[{type:"text",text:Sn},{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 Vo(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:As(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 Vo(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 Jr(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"?Jr(o):o;t.properties=n}return t.items&&typeof t.items=="object"&&(t.items=Jr(t.items)),t}async function fd(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:Jr(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=_n(l.usage);if(n.structuredOutput)try{return{type:"structured",data:As(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 hd(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:As(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 my(e,t,n){switch(e){case"claude-code":{let s=["--print",...Mr];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 py(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
833
|
`);t.push(`
|
|
830
834
|
|
|
831
835
|
## ${s}
|
|
832
|
-
${o}`)}if(e.structuredOutput){let n=
|
|
836
|
+
${o}`)}if(e.structuredOutput){let n=bd(e.structuredOutput.schema);t.push(`
|
|
833
837
|
|
|
834
838
|
## Output Format \u2014 CRITICAL
|
|
835
839
|
Respond with a JSON code block. Wrap your JSON in \`\`\`json fences. No prose or explanation before or after the code block.
|
|
836
840
|
|
|
837
841
|
The JSON must match this structure:
|
|
838
|
-
${n}`)}return t.join("")}function
|
|
839
|
-
`)}function
|
|
842
|
+
${n}`)}return t.join("")}function bd(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}": ${bd(a,t+1)}${l}${d}`):i.push(`${n} "${r}": ${c}${l}${d}${u}`)}return i.push(`${n}}`),i.join(`
|
|
843
|
+
`)}function gy(e){let t=e.trim(),n=ct(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=ct(a);if(l&&typeof l=="object")return l;let c=xs(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=ct(a);if(l&&typeof l=="object")return l;let c=xs(a);if(c&&typeof c=="object")return c}let r=xs(t);return r&&typeof r=="object"?r:null}async function fy(e,t,n){let{bin:s,args:o}=my(e,t,n),i=py(n),r;if(e==="claude-code"){let l=[...o,"--output-format","stream-json","--include-partial-messages","--verbose"];r=await Ir(l,i,{onChunk:n.onChunk,onToolUse:(c,d)=>{if(!n.onStatus)return;let u=hy(c,d);n.onStatus(u)}})}else r=await Pr(s,o,i,n.onChunk);if(!n.structuredOutput)return{type:"text",text:r};let a=gy(r);return a?{type:"structured",data:As(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 hy(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 Sd(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 gd(t,n,s);case"claude-oauth":{let{getValidAccessToken:r}=await Promise.resolve().then(()=>(_t(),Di)),a=await r();if(!a)throw new Error("Claude OAuth session expired. Please re-authenticate in Settings.");return uy(a,n,s)}case"openai-api":return fd(t,n,s);case"gemini-api":return hd(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||Ts[a];return fd(t,n,s,`${c}/v1/chat/completions`)}case"google":{let c=l||Ts.google;return hd(t,n,s,`${c}/v1beta/models/${n}:generateContent`)}default:{let c=l||Ts.anthropic;return gd(t,n,s,void 0,void 0,c)}}}default:throw new Error(`Unsupported API engine: ${e}`)}})();return by(e,n,s,i,o,new Date),i}function by(e,t,n,s,o,i){St({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 yy.has(e)?Sd(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}),fy(e,n,s))}function Hn(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 _s(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 Un(e){return e==="claude-code"||e==="gemini-cli"||e==="codex-cli"}var Ts,Kk,jr,Lr,yy,dt=N(()=>{"use strict";y();Rr();Wo();ee();_t();le();tn();Be();Ts={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=Ts.anthropic,jr=[10,20,40,60,120];Lr=null;yy=new Set(["anthropic-api","claude-oauth","openai-api","gemini-api","langdock-api"])});var Br,xd=N(()=>{"use strict";y();Br={"intent-analyzer":{version:2,placeholders:["themeName","contextData"],template:`You are the Intent Analyzer for vibeSpot, a HubSpot CMS builder that generates pages, email templates, and blog templates.
|
|
840
844
|
|
|
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.
|
|
845
|
+
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. Think like a product strategist: read past the literal words to the outcome the user actually wants, then scope the smallest set of changes that delivers it.
|
|
842
846
|
|
|
843
847
|
## Theme: "{{themeName}}"
|
|
844
848
|
|
|
@@ -868,10 +872,22 @@ If ambiguous, default to "page". The content type affects downstream pipeline be
|
|
|
868
872
|
7. **style_change** \u2014 User wants design system changes that affect shared CSS/multiple modules (e.g., "change the color scheme to blue")
|
|
869
873
|
8. **question** \u2014 User is asking a question, not requesting changes (e.g., "what modules do I have?"). Provide the answer directly.
|
|
870
874
|
|
|
875
|
+
## Surface the brief (create / create_site)
|
|
876
|
+
|
|
877
|
+
When the intent is **create** or **create_site**, capture what you can infer about the brief so downstream stages design with intent instead of guessing. In \`themeContext\` (or the page \`purpose\` fields), note the inferred:
|
|
878
|
+
- **Audience** \u2014 who the page is for (e.g., "RevOps leaders at mid-market SaaS").
|
|
879
|
+
- **Primary goal / conversion** \u2014 the one action the page should drive (book demo, start trial, buy, subscribe, contact).
|
|
880
|
+
- **Tone** \u2014 how it should feel (authoritative, playful, premium, technical, warm).
|
|
881
|
+
Infer these from the user's words and the theme name; never invent specifics that contradict the request. A page with a clear audience + goal + tone converts far better than a generic one.
|
|
882
|
+
|
|
883
|
+
## Plan a conversion-complete page (create, single page)
|
|
884
|
+
|
|
885
|
+
A landing page that only has a hero and a CTA underperforms. For a fresh **create**, lean toward a complete narrative arc so the Module Planner has the right scaffold: an attention-grabbing **hero**, **value/benefits**, **social proof** (logos, testimonials, or stats), an **objection-handler or how-it-works**, and a focused **final CTA**. Do not pad with filler \u2014 match section count to the brief \u2014 but do not ship a skeleton when the user asked for a real page.
|
|
886
|
+
|
|
871
887
|
## Multi-Page Site Rules (create_site only)
|
|
872
888
|
|
|
873
889
|
When classifying as \`create_site\`:
|
|
874
|
-
- Populate the \`pages\` array with one entry per page. Each page needs: id (kebab-case), label (human-readable), pageType ("landing_page" or "website_page"), purpose (1-sentence), slug (URL path without leading /).
|
|
890
|
+
- Populate the \`pages\` array with one entry per page. Each page needs: id (kebab-case), label (human-readable), pageType ("landing_page" or "website_page"), purpose (1-sentence, include audience + goal where inferable), slug (URL path without leading /).
|
|
875
891
|
- Populate \`sharedModules\` with names of modules shared across all pages (typically ["site-header", "site-footer"]).
|
|
876
892
|
- Always include at least a header and footer in sharedModules.
|
|
877
893
|
- Page IDs should be descriptive: "wp-home", "wp-about", "wp-contact", etc.
|
|
@@ -881,8 +897,8 @@ When classifying as \`create_site\`:
|
|
|
881
897
|
|
|
882
898
|
## Key Rules
|
|
883
899
|
|
|
884
|
-
- For **modify**: list only the modules that actually need changes in \`affectedModules\`. Everything else goes in \`unchangedModules\`.
|
|
885
|
-
- For **add**: new modules go in \`newModules\` with a descriptive name, brief description, and position index (0-based).
|
|
900
|
+
- For **modify**: list only the modules that actually need changes in \`affectedModules\`. Everything else goes in \`unchangedModules\`. Be surgical \u2014 touching modules the user didn't ask about risks regressions and wastes generation.
|
|
901
|
+
- For **add**: new modules go in \`newModules\` with a descriptive name, brief description, and position index (0-based). Place the new module where it strengthens the page's flow, not just at the end, unless the user specifies.
|
|
886
902
|
- For **reuse**: if the user references a module from the library, put it in \`reuseModules\` with the source template name. Reused modules are copied as-is \u2014 their structure (fields, HTML, CSS) MUST NOT change.
|
|
887
903
|
- For **style_change**: set \`designSystemChanges: true\`. All modules become affected since they need the updated design system.
|
|
888
904
|
- For **question**: set \`intent: "question"\` and provide the answer in the \`answer\` field. The pipeline will short-circuit.
|
|
@@ -908,73 +924,75 @@ CRITICAL: When the user corrects a misclassification (e.g., "I was referencing t
|
|
|
908
924
|
If the user asks for multiple things (e.g., "make hero taller AND add testimonials"), capture ALL parts:
|
|
909
925
|
- Affected existing modules in \`affectedModules\`
|
|
910
926
|
- New modules in \`newModules\`
|
|
911
|
-
- Set the broadest applicable intent (prefer "modify" + newModules over splitting)
|
|
912
|
-
|
|
913
|
-
## Content Type Detection
|
|
914
|
-
|
|
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.
|
|
927
|
+
- Set the broadest applicable intent (prefer "modify" + newModules over splitting)`},"design-system":{version:2,placeholders:["themeName"],template:`You are the Design System Architect for vibeSpot, a HubSpot CMS page builder.
|
|
916
928
|
|
|
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.
|
|
929
|
+
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 \u2014 so the system has to be coherent, distinctive, and accessible, not a generic bootstrap clone.
|
|
918
930
|
|
|
919
931
|
## Theme: "{{themeName}}"
|
|
920
932
|
|
|
933
|
+
## Design Direction \u2014 decide FIRST
|
|
934
|
+
Before writing CSS, commit to a deliberate visual direction that fits the brand's audience, goal, and mood (premium SaaS, editorial media, warm local business, technical/developer, bold consumer, etc.). Then make every token serve that direction. A page reads as "designed" when its color, type, spacing, and depth all tell the same story \u2014 and as "templated" when they're arbitrary. Avoid the default purple-on-white startup look unless the brief calls for it. Aim for a memorable, modern aesthetic: confident color, real typographic hierarchy, generous whitespace, and subtle depth.
|
|
935
|
+
|
|
921
936
|
## Output Requirements
|
|
922
937
|
|
|
923
938
|
### cssVariables
|
|
924
939
|
A flat object mapping CSS custom property names to values. Every variable your CSS references MUST be defined here. Include ALL of these categories:
|
|
925
940
|
|
|
926
|
-
**Colors** (at minimum):
|
|
941
|
+
**Colors** (at minimum). Build a deliberate palette, not random hex. Ensure text-on-background pairs meet **WCAG AA contrast (\u22654.5:1 for body, \u22653:1 for large text)** \u2014 this is non-negotiable for readability:
|
|
927
942
|
- --{{themeName}}-color-bg: page background
|
|
928
943
|
- --{{themeName}}-color-surface: card/section background
|
|
929
944
|
- --{{themeName}}-color-dark: dark section background
|
|
930
945
|
- --{{themeName}}-color-dark-surface: card bg inside dark sections
|
|
931
946
|
- --{{themeName}}-color-text: primary text color
|
|
932
947
|
- --{{themeName}}-color-text-inverse: text on dark backgrounds
|
|
933
|
-
- --{{themeName}}-color-text-muted: secondary/muted text
|
|
948
|
+
- --{{themeName}}-color-text-muted: secondary/muted text (still AA against its background)
|
|
934
949
|
- --{{themeName}}-color-primary: primary brand color
|
|
935
950
|
- --{{themeName}}-color-primary-dark: darker variant for hover states
|
|
936
|
-
- --{{themeName}}-color-accent: accent/highlight color
|
|
951
|
+
- --{{themeName}}-color-accent: accent/highlight color (use sparingly, for emphasis)
|
|
937
952
|
- --{{themeName}}-color-accent-light: light tint for pill/badge backgrounds
|
|
938
953
|
- --{{themeName}}-color-border: default border color
|
|
939
954
|
- --{{themeName}}-color-border-hover: border on hover
|
|
940
955
|
|
|
941
|
-
**Typography
|
|
956
|
+
**Typography**. Use a consistent **modular scale** (e.g. ~1.25 ratio) so heading sizes feel related rather than arbitrary:
|
|
942
957
|
- --{{themeName}}-font-display: display/heading font stack (system fonts only)
|
|
943
958
|
- --{{themeName}}-font-body: body text font stack (system fonts only)
|
|
944
|
-
- --{{themeName}}-size-h1 through --{{themeName}}-size-h3: heading sizes using clamp()
|
|
959
|
+
- --{{themeName}}-size-h1 through --{{themeName}}-size-h3: heading sizes using clamp() for fluid scaling
|
|
945
960
|
- --{{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
|
|
961
|
+
- --{{themeName}}-leading-tight, --{{themeName}}-leading-snug, --{{themeName}}-leading-body: line heights (tight for display, ~1.6 for body readability)
|
|
962
|
+
- --{{themeName}}-tracking-tight, --{{themeName}}-tracking-wide: letter spacing (tighten large display, widen labels/eyebrows)
|
|
963
|
+
- --{{themeName}}-weight-normal, --{{themeName}}-weight-medium, --{{themeName}}-weight-bold: weight scale for hierarchy
|
|
948
964
|
|
|
949
|
-
**Spacing
|
|
965
|
+
**Spacing**. Use a consistent **8pt-based scale** (4 / 8 / 16 / 24 / 40 / 64 \u2026) so rhythm is predictable:
|
|
950
966
|
- --{{themeName}}-space-xs through --{{themeName}}-space-xl, --{{themeName}}-space-section
|
|
951
967
|
- --{{themeName}}-max-width: content max-width (1152-1280px)
|
|
952
968
|
|
|
953
|
-
**Effects
|
|
969
|
+
**Effects**. Use layered, soft shadows (not a single harsh drop) for real depth:
|
|
954
970
|
- --{{themeName}}-radius-sm, --{{themeName}}-radius-md, --{{themeName}}-radius-lg, --{{themeName}}-radius-full
|
|
955
|
-
- --{{themeName}}-shadow-card-hover, --{{themeName}}-shadow-button
|
|
971
|
+
- --{{themeName}}-shadow-card, --{{themeName}}-shadow-card-hover, --{{themeName}}-shadow-button
|
|
956
972
|
- --{{themeName}}-transition-fast, --{{themeName}}-transition-base, --{{themeName}}-transition-slow
|
|
973
|
+
- --{{themeName}}-ease: a refined easing curve (e.g. cubic-bezier(0.4, 0, 0.2, 1)) for tasteful motion
|
|
957
974
|
|
|
958
975
|
### sharedCss
|
|
959
976
|
Complete CSS file content. MUST include:
|
|
960
977
|
1. A \`:root {}\` block with ALL variables from cssVariables
|
|
961
|
-
2. Reset (box-sizing, margin, padding)
|
|
962
|
-
3. Body styles referencing your variables
|
|
963
|
-
4. Typography rules (h1-h6, p)
|
|
978
|
+
2. Reset (box-sizing, margin, padding) and \`scroll-behavior: smooth\` with \`@media (prefers-reduced-motion: reduce)\` disabling it
|
|
979
|
+
3. Body styles referencing your variables (incl. \`-webkit-font-smoothing: antialiased\` and \`text-rendering: optimizeLegibility\`)
|
|
980
|
+
4. Typography rules (h1-h6, p) using the modular scale, with sensible \`max-width\` on body copy (~65ch) for readability
|
|
964
981
|
5. Layout utilities (.{{themeName}}-container, .{{themeName}}-section, .{{themeName}}-section--dark)
|
|
965
982
|
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)
|
|
983
|
+
7. Card component (.{{themeName}}-card with hover lift using shadow + translateY)
|
|
984
|
+
8. Button component (.{{themeName}}-btn, .{{themeName}}-btn--primary, .{{themeName}}-btn--secondary) with comfortable padding and a clear hover AND \`:focus-visible\` state
|
|
968
985
|
CRITICAL: Re-declare color, text-decoration:none, and font-family on :hover/:focus \u2014 HubSpot overrides link hover styles
|
|
969
986
|
9. Pill/badge (.{{themeName}}-pill)
|
|
970
|
-
10. Decorative elements (at least one background treatment: grid pattern, noise, gradient orb)
|
|
971
|
-
11. Scroll animation CSS ([data-animate], [data-animate-stagger]) with 3s CSS-only fallback
|
|
972
|
-
12. Section label (.{{themeName}}-label) \u2014 uppercase, letter-spacing, accent color
|
|
973
|
-
13. Stat number styling
|
|
974
|
-
14.
|
|
987
|
+
10. Decorative elements (at least one tasteful background treatment: subtle grid pattern, soft noise/grain, gradient mesh/orb) \u2014 used to add depth, never to distract
|
|
988
|
+
11. Scroll animation CSS ([data-animate], [data-animate-stagger]) with a 3s CSS-only fallback AND a \`@media (prefers-reduced-motion: reduce)\` block that shows content immediately
|
|
989
|
+
12. Section label (.{{themeName}}-label) \u2014 uppercase, letter-spacing, accent color (the "eyebrow")
|
|
990
|
+
13. Stat number styling (large, tight tracking, display font)
|
|
991
|
+
14. Global \`:focus-visible\` outline using the accent color for keyboard accessibility
|
|
992
|
+
15. Responsive mobile styles (@media max-width: 767px) \u2014 verify type, spacing, and grids all collapse gracefully
|
|
975
993
|
|
|
976
994
|
### sharedJs (optional)
|
|
977
|
-
IntersectionObserver-based scroll animation JS. Wrap in IIFE.
|
|
995
|
+
IntersectionObserver-based scroll animation JS. Wrap in IIFE. Respect \`prefers-reduced-motion\` (skip animating when the user opts out). Keep it lightweight and dependency-free.
|
|
978
996
|
|
|
979
997
|
## CSS Rules \u2014 CRITICAL
|
|
980
998
|
- All classes MUST use prefix "{{themeName}}-"
|
|
@@ -983,13 +1001,10 @@ IntersectionObserver-based scroll animation JS. Wrap in IIFE.
|
|
|
983
1001
|
- Every var() reference in CSS must have a matching declaration in :root
|
|
984
1002
|
- No Tailwind, no Sass, no PostCSS
|
|
985
1003
|
- Use clamp() for fluid typography sizing
|
|
1004
|
+
- Prefer CSS custom properties everywhere over hardcoded values, so modules stay consistent
|
|
986
1005
|
|
|
987
1006
|
## Font Strategy
|
|
988
|
-
Use system font stacks that approximate the desired aesthetic. Pick TWO stacks:
|
|
989
|
-
- Display: for headings
|
|
990
|
-
- Body: for text
|
|
991
|
-
|
|
992
|
-
**Choose the pairing that best fits the content's mood** \u2014 don't default to the same one every time:
|
|
1007
|
+
Use system font stacks that approximate the desired aesthetic. Pick TWO stacks (Display for headings, Body for text) that fit the brand mood \u2014 and create real contrast between them. Don't default to the same pairing every time:
|
|
993
1008
|
| Style | Display Stack | Body Stack | Best for |
|
|
994
1009
|
|-------|--------------|------------|----------|
|
|
995
1010
|
| Editorial | Georgia, Cambria, "Times New Roman", serif | system-ui, -apple-system, "Segoe UI", sans-serif | Media, luxury, culture |
|
|
@@ -999,9 +1014,9 @@ Use system font stacks that approximate the desired aesthetic. Pick TWO stacks:
|
|
|
999
1014
|
| Geometric | Futura, "Century Gothic", "Trebuchet MS", sans-serif | system-ui, sans-serif | Architecture, design, fashion |
|
|
1000
1015
|
| Classic | "Book Antiqua", Palatino, "Palatino Linotype", serif | Georgia, "Times New Roman", serif | Law, finance, heritage |
|
|
1001
1016
|
| Friendly | "Comic Sans MS", Chalkboard, cursive | "Trebuchet MS", system-ui, sans-serif | Kids, casual, fun brands |
|
|
1002
|
-
| Contrast pair | Georgia, serif (display) | system-ui, sans-serif (body) | When you want serif/sans tension |`},"module-planner":{version:
|
|
1017
|
+
| Contrast pair | Georgia, serif (display) | system-ui, sans-serif (body) | When you want serif/sans tension |`},"module-planner":{version:2,placeholders:["themeName","cssSummary"],template:`You are the Module Planner for vibeSpot, a HubSpot CMS page builder.
|
|
1003
1018
|
|
|
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.
|
|
1019
|
+
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. The quality of the finished page is decided here: a vague brief produces generic filler, a sharp brief produces copy that converts.
|
|
1005
1020
|
|
|
1006
1021
|
The Design System has already been created. Your module plans MUST reference the existing CSS classes and variables.
|
|
1007
1022
|
|
|
@@ -1012,6 +1027,9 @@ Reference these in your layoutNotes:
|
|
|
1012
1027
|
|
|
1013
1028
|
{{cssSummary}}
|
|
1014
1029
|
|
|
1030
|
+
## Plan the page as a persuasive narrative
|
|
1031
|
+
Order modules so the page argues its case: grab attention (hero) \u2192 establish relevance/pain \u2192 present the solution and its benefits \u2192 prove it (social proof, stats, testimonials) \u2192 handle objections (how-it-works, FAQ, comparison) \u2192 drive one clear action (final CTA). Vary the section types \u2014 don't stack three near-identical card grids. Match the section count to the brief; a focused 5-section page beats a padded 9-section one.
|
|
1032
|
+
|
|
1015
1033
|
## Output Rules
|
|
1016
1034
|
|
|
1017
1035
|
### Module names \u2014 CRITICAL
|
|
@@ -1019,17 +1037,25 @@ Reference these in your layoutNotes:
|
|
|
1019
1037
|
- **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
1038
|
- The \`description\` and \`contentBrief\` fields can be any text \u2014 they describe the module to humans, while \`name\` is the canonical identifier.
|
|
1021
1039
|
|
|
1022
|
-
### Content
|
|
1023
|
-
|
|
1024
|
-
-
|
|
1025
|
-
-
|
|
1040
|
+
### Content briefs \u2014 make them specific and benefit-led
|
|
1041
|
+
A strong \`contentBrief\` tells the developer exactly what to say, not just what kind of section it is. For each module include:
|
|
1042
|
+
- **Headline direction** \u2014 a benefit- or outcome-led angle (what the reader gets), not a feature label. Suggest an actual headline, not "Hero headline here".
|
|
1043
|
+
- **Supporting copy** \u2014 the key message, proof points, and the specific words/numbers to feature (real-sounding stats, concrete outcomes).
|
|
1044
|
+
- **CTA** \u2014 the exact action and button label where relevant ("Start free trial", "Book a 15-min demo").
|
|
1045
|
+
- **Conversion intent** \u2014 what this section must accomplish (build trust, remove a specific objection, create urgency).
|
|
1046
|
+
Apply proven structure where it fits: Problem\u2013Agitate\u2013Solution for the opening, social proof near decision points, objection-handling before the final CTA. Never write lorem ipsum or placeholder-y copy direction \u2014 write as if the brand's marketer wrote the brief.
|
|
1047
|
+
|
|
1048
|
+
### Layout notes
|
|
1049
|
+
- Describe the visual layout using the available CSS classes above (e.g., "Use {{themeName}}-grid--3 for the card layout, {{themeName}}-section--dark for the background, {{themeName}}-label for the eyebrow").
|
|
1050
|
+
- Call out hierarchy and rhythm: what's the focal element, how much breathing room, where the eye should land first.
|
|
1051
|
+
- Note responsive intent (how it should stack on mobile) when it matters.
|
|
1026
1052
|
|
|
1027
1053
|
### Module order
|
|
1028
1054
|
- \`moduleOrder\`: list **all** modules' names in the order they should appear on the page, including:
|
|
1029
1055
|
- 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:
|
|
1056
|
+
- any "Existing Modules to Keep" the user listed (these are not in \`modules\`, but still belong in \`moduleOrder\`)`},"site-module-planner":{version:2,placeholders:["themeName","siteMap","sharedList","cssSummary","navHrefs","sharedModuleNamesCsv"],template:`You are the Site Module Planner for vibeSpot, a HubSpot CMS page builder.
|
|
1031
1057
|
|
|
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.
|
|
1058
|
+
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. Think of the site as one story told across several pages \u2014 each page has a distinct job, but the voice, design language, and navigation stay consistent throughout.
|
|
1033
1059
|
|
|
1034
1060
|
## Theme: "{{themeName}}"
|
|
1035
1061
|
|
|
@@ -1054,7 +1080,7 @@ Reference these in your layoutNotes:
|
|
|
1054
1080
|
{{navHrefs}}
|
|
1055
1081
|
- Active page link uses CSS class "{{themeName}}-nav__link--active"
|
|
1056
1082
|
- Sticky with backdrop-blur, transitions on scroll
|
|
1057
|
-
- Mobile: hamburger menu with slide-in nav
|
|
1083
|
+
- Mobile: hamburger menu with slide-in nav, fully keyboard-accessible
|
|
1058
1084
|
|
|
1059
1085
|
### site-footer
|
|
1060
1086
|
- Consistent across all pages
|
|
@@ -1064,10 +1090,16 @@ Reference these in your layoutNotes:
|
|
|
1064
1090
|
## Per-Page Module Rules
|
|
1065
1091
|
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
1092
|
|
|
1067
|
-
Each page should have distinct content appropriate to its purpose. Aim for:
|
|
1093
|
+
Each page should have distinct content appropriate to its purpose, and each page should still earn its conversion (every page needs a clear next step, usually pointing toward the primary site goal). Aim for:
|
|
1068
1094
|
- 4-8 unique modules per page (not counting shared modules)
|
|
1069
|
-
-
|
|
1070
|
-
-
|
|
1095
|
+
- A persuasive flow per page (attention \u2192 value \u2192 proof \u2192 action), not a flat list of sections
|
|
1096
|
+
- Specific, benefit-led content briefs (real headline/CTA direction, concrete proof points \u2014 never lorem ipsum)
|
|
1097
|
+
- Consistent use of design system classes across all pages so the site feels like one product
|
|
1098
|
+
|
|
1099
|
+
## Cross-page coherence
|
|
1100
|
+
- Reuse the same component vocabulary (cards, labels, buttons, grids) across pages so they feel related.
|
|
1101
|
+
- Avoid repeating the exact same section on multiple pages \u2014 differentiate by purpose (e.g., home = overview, about = story/team, contact = form + details).
|
|
1102
|
+
- Keep tone and visual density consistent page to page.
|
|
1071
1103
|
|
|
1072
1104
|
## Module Naming
|
|
1073
1105
|
- Use kebab-case identifiers (e.g., "hero", "team-grid", "contact-form")
|
|
@@ -1081,9 +1113,9 @@ Return a JSON object with:
|
|
|
1081
1113
|
- \`pageId\`: matching the page ID from the site map
|
|
1082
1114
|
- \`modules\`: array of module specs for that page only (excluding shared)
|
|
1083
1115
|
- \`moduleOrder\`: ordered list of per-page module names only (excluding shared)
|
|
1084
|
-
- \`narrative\`: brief description of the overall site story/flow`},"module-developer":{version:
|
|
1116
|
+
- \`narrative\`: brief description of the overall site story/flow`},"module-developer":{version:2,placeholders:["themeName"],template:`You are a Module Developer for vibeSpot, a HubSpot CMS page builder.
|
|
1085
1117
|
|
|
1086
|
-
Your job: generate ONE HubSpot CMS module. You receive a module specification and must produce the complete module code.
|
|
1118
|
+
Your job: generate ONE HubSpot CMS module. You receive a module specification and must produce the complete module code. Build it to a senior front-end standard: clean semantic markup, polished responsive CSS that uses the theme's design system, and real, compelling default copy \u2014 what you ship is what the user sees in the live preview, so make it look finished, not like a wireframe.
|
|
1087
1119
|
|
|
1088
1120
|
## Theme: "{{themeName}}"
|
|
1089
1121
|
|
|
@@ -1096,6 +1128,22 @@ You produce a single module with these fields:
|
|
|
1096
1128
|
- **moduleCss**: Vanilla CSS (no Tailwind, no Sass, no CDN imports)
|
|
1097
1129
|
- **moduleJs**: Optional vanilla JS wrapped in IIFE, or null
|
|
1098
1130
|
|
|
1131
|
+
## Content quality \u2014 write real copy, never lorem
|
|
1132
|
+
- Default field values must be specific, on-brief, benefit-led copy in the brand's voice \u2014 NEVER "Lorem ipsum", "Your headline here", "Section title", or placeholder filler. Write headlines that lead with the outcome, body copy that's concrete, CTAs that name the action ("Start free trial", "Book a demo").
|
|
1133
|
+
- Use real, plausible numbers in stats ("12,000+ teams", "3.2\xD7 faster") rather than "XX%".
|
|
1134
|
+
- Keep copy tight: punchy headlines, scannable body text, no waffle.
|
|
1135
|
+
|
|
1136
|
+
## Design quality \u2014 make it look designed
|
|
1137
|
+
- Build a clear visual hierarchy (one focal element per section), generous whitespace, and consistent rhythm using the theme's spacing scale.
|
|
1138
|
+
- Use hover AND \`:focus-visible\` states on interactive elements; add tasteful transitions via the theme's transition/ease variables. Keep motion subtle.
|
|
1139
|
+
- Ensure the layout is fully responsive \u2014 verify it stacks cleanly at mobile widths (max-width: 767px).
|
|
1140
|
+
- Lean on the shared design system classes/variables shown below for consistency; only add module-specific CSS for what the shared system doesn't cover.
|
|
1141
|
+
|
|
1142
|
+
## Accessibility
|
|
1143
|
+
- Use semantic HTML (\`section\`, \`header\`, \`nav\`, \`h1\`-\`h3\` in order, \`button\`/\`a\` correctly).
|
|
1144
|
+
- Every image needs meaningful \`alt\` text. Icons that are decorative get \`aria-hidden="true"\`.
|
|
1145
|
+
- Maintain readable contrast (the design system colors are AA-compliant \u2014 keep text on the intended backgrounds).
|
|
1146
|
+
|
|
1099
1147
|
## CSS Rules
|
|
1100
1148
|
- All CSS classes must use prefix "{{themeName}}-"
|
|
1101
1149
|
- Use BEM naming: {{themeName}}-moduleName__element--modifier
|
|
@@ -1114,6 +1162,9 @@ You produce a single module with these fields:
|
|
|
1114
1162
|
- Image fields: type "image", default { "src": "https://placehold.co/800x600/1a1a2e/ffffff?text=Replace+in+HubSpot", "alt": "Placeholder", "width": 800, "height": 600 }
|
|
1115
1163
|
- For repeater groups, use "occurrence": { "min": 0, "max": 100 }
|
|
1116
1164
|
|
|
1165
|
+
## Style fields MUST have complete defaults \u2014 CRITICAL
|
|
1166
|
+
Every style/color field you reference in CSS must ship a complete default value. If your CSS builds a color from a style field \u2014 e.g. \`rgba({{ module.styles.bg.color|convert_rgb }}, {{ module.styles.bg.opacity/100 }})\` \u2014 that field's default MUST include both a \`color\` hex AND \`opacity\`, or the rendered CSS becomes invalid (\`rgba(15, 17, 21, )\`) and the browser drops the declaration, leaving the section unstyled. Always give color fields a real default hex + opacity 100, and never reference a style field you didn't define with a default. Prefer the theme's CSS variables for anything that should match the design system.
|
|
1167
|
+
|
|
1117
1168
|
## Images & Assets
|
|
1118
1169
|
- Use get_asset_url("{{themeName}}/assets/filename.ext") for uploaded assets
|
|
1119
1170
|
- For placeholder images, use image fields with placehold.co defaults
|
|
@@ -1122,10 +1173,10 @@ You produce a single module with these fields:
|
|
|
1122
1173
|
## Navigation & Anchors
|
|
1123
1174
|
- Add id attribute on module root element: id="module-name-lowercased"
|
|
1124
1175
|
- For nav modules, use anchor links (#features, #pricing, etc.)
|
|
1125
|
-
- Include smooth scroll behavior in nav click handlers
|
|
1176
|
+
- Include smooth scroll behavior in nav click handlers, and respect prefers-reduced-motion
|
|
1126
1177
|
|
|
1127
1178
|
## metaJson Template
|
|
1128
|
-
{ "host_template_types": ["PAGE"], "is_available_for_new_content": true }`}}});function
|
|
1179
|
+
{ "host_template_types": ["PAGE"], "is_available_for_new_content": true }`}}});function vy(){if(wd!==void 0)return wd;if($s!==void 0)return $s;try{let e=JSON.parse(P(hn(Sy)));$s=e&&typeof e=="object"&&e.prompts?e:null}catch{$s=null}return $s}function xy(e){let t=new Set;for(let n of e.matchAll(Cd))t.add(n[1]);return[...t]}function wy(e){let t=Br[e],n=vy()?.prompts?.[e];if(n&&n.version===t.version&&typeof n.template=="string"){let s=new Set(t.placeholders);if(xy(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 Cy(e,t,n){let s=new Set(Br[e].placeholders);return t.replace(Cd,(o,i)=>s.has(i)?n[i]??"":o)}function Rt(e,t){return Cy(e,wy(e).template,t)}var Sy,Cd,$s,wd,Es=N(()=>{"use strict";y();oe();xd();Sy="prompts.bundle.json",Cd=/\{\{\s*([a-zA-Z][\w]*)\s*\}\}/g});function kd(e,t,n,s,o){let i=t.length>0?`Current template modules (in page order):
|
|
1129
1180
|
${t.map((d,u)=>`${u+1}. ${d}`).join(`
|
|
1130
1181
|
`)}`:"No modules yet (new page).",r=n.length>0?`
|
|
1131
1182
|
|
|
@@ -1142,10 +1193,10 @@ All pages:
|
|
|
1142
1193
|
${o.pages.map(d=>`- ${d.label} (${d.id}, ${d.moduleCount} modules)`).join(`
|
|
1143
1194
|
`)}
|
|
1144
1195
|
|
|
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
|
|
1196
|
+
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 Td,Ad=N(()=>{"use strict";y();Es();Td={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 _d(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=kd(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:Td,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:ky(m)}),m}function ky(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 $d=N(()=>{"use strict";y();dt();Ad();le();Be()});function zo(e,t){let n=[];n.push(Rt("design-system",{themeName:e})),n.push(`
|
|
1146
1197
|
|
|
1147
1198
|
## Design Guide
|
|
1148
|
-
${
|
|
1199
|
+
${Nd()}`),t?.styleguide&&n.push(`
|
|
1149
1200
|
|
|
1150
1201
|
## Brand Style Guide
|
|
1151
1202
|
${t.styleguide}`),t?.themeContext&&n.push(`
|
|
@@ -1161,11 +1212,11 @@ ${o.join(`
|
|
|
1161
1212
|
## No Brand Provided \u2014 Follow the Generation Recipe
|
|
1162
1213
|
No brand colors, fonts, or styleguide have been set. You MUST follow these rules to create a unique design:
|
|
1163
1214
|
|
|
1164
|
-
${
|
|
1215
|
+
${Pd()}`),n.join("")}function Hr(e,t){let n=zo(e),o=n.indexOf(`
|
|
1165
1216
|
|
|
1166
1217
|
## Design Guide
|
|
1167
1218
|
`);if(o===-1)return[{type:"text",text:n}];let i=n.slice(0,o),r=`## Design Guide
|
|
1168
|
-
${
|
|
1219
|
+
${Nd()}`,a=[{type:"text",text:i},{type:"text",text:r,cache_control:{type:"ephemeral"}}],l=[];t?.styleguide&&l.push(`## Brand Style Guide
|
|
1169
1220
|
${t.styleguide}`),t?.themeContext&&l.push(`## Product Context
|
|
1170
1221
|
${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
|
|
1171
1222
|
The following brand identity values MUST be used. Do NOT substitute or override them:
|
|
@@ -1173,13 +1224,13 @@ ${d.join(`
|
|
|
1173
1224
|
`)}`)}return!c&&!t?.styleguide&&l.push(`## No Brand Provided \u2014 Follow the Generation Recipe
|
|
1174
1225
|
No brand colors, fonts, or styleguide have been set. You MUST follow these rules to create a unique design:
|
|
1175
1226
|
|
|
1176
|
-
${
|
|
1227
|
+
${Pd()}`),l.length>0&&a.push({type:"text",text:l.join(`
|
|
1177
1228
|
|
|
1178
|
-
`)}),a}function
|
|
1179
|
-
`)}function
|
|
1229
|
+
`)}),a}function Ty(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(`
|
|
1230
|
+
`)}function Md(e,t,n,s){let o=[],i=Ty(t);return o.push(Rt("module-planner",{themeName:e,cssSummary:i})),(!s||s.includes("content"))&&o.push(`
|
|
1180
1231
|
|
|
1181
1232
|
## Content & Copywriting Guide
|
|
1182
|
-
${
|
|
1233
|
+
${Ay()}`),n?.brandvoice&&o.push(`
|
|
1183
1234
|
|
|
1184
1235
|
## Brand Voice
|
|
1185
1236
|
${n.brandvoice}`),n?.themeContext&&o.push(`
|
|
@@ -1188,7 +1239,7 @@ ${n.brandvoice}`),n?.themeContext&&o.push(`
|
|
|
1188
1239
|
${n.themeContext}`),n?.humanify!==!1&&s?.includes("humanify")&&o.push(`
|
|
1189
1240
|
|
|
1190
1241
|
## Anti-AI Copy Rules
|
|
1191
|
-
${
|
|
1242
|
+
${_y()}`),o.join("")}function Pd(){let e=ls(),t=Ed(e,"## 4. Color System","## 5."),n=Ed(e,"### Recommended Font Pairings","### Typography Scale"),s=[];return s.push(`### Step 1: Derive the aesthetic from the content
|
|
1192
1243
|
Read the user's request carefully. What industry? What audience? What mood?
|
|
1193
1244
|
Map it to ONE of these aesthetic directions \u2014 then commit fully:
|
|
1194
1245
|
|
|
@@ -1244,7 +1295,7 @@ Before finalizing, ask yourself:
|
|
|
1244
1295
|
|
|
1245
1296
|
If any answer is "no," go bolder. The user wants personality, not safety.`),s.join(`
|
|
1246
1297
|
|
|
1247
|
-
`)}function
|
|
1298
|
+
`)}function Ed(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 Nd(){return`### Design Philosophy
|
|
1248
1299
|
You are a senior UI designer. Every page must look professionally designed, not like AI output.
|
|
1249
1300
|
Avoid "AI slop": purple gradients on white, cookie-cutter card grids, no personality.
|
|
1250
1301
|
|
|
@@ -1351,7 +1402,7 @@ Include these in shared CSS:
|
|
|
1351
1402
|
| All animations same speed | Stagger with increasing delays |
|
|
1352
1403
|
| Skip hover/focus states | Every interactive element needs feedback |
|
|
1353
1404
|
| Use \`<br>\` tags for spacing | Use proper margin/padding |
|
|
1354
|
-
| Put everything in a shadowed card | Vary: full-bleed, contained, floating |`}function
|
|
1405
|
+
| Put everything in a shadowed card | Vary: full-bleed, contained, floating |`}function Ay(){return`### Mandatory Page Sections (generate all)
|
|
1355
1406
|
1. **Navigation Bar** \u2014 Logo, 4-5 nav links, CTA button, sticky on scroll
|
|
1356
1407
|
2. **Hero** \u2014 Badge/pill, primary headline, subheadline, primary + secondary CTA, trust signals, visual element
|
|
1357
1408
|
3. **Social Proof Bar** \u2014 Logo strip of 4-6 clients OR stats bar (compact, py-8)
|
|
@@ -1439,7 +1490,7 @@ Alternate backgrounds every 2-3 sections to create visual "chapters." Sprinkle t
|
|
|
1439
1490
|
- Invent plausible specifics: neighborhood names, "48 hours" not "quickly", "\u20AC49" not "affordable"
|
|
1440
1491
|
- Keep paragraphs to 2-3 sentences max
|
|
1441
1492
|
- Aim for 6th-grade reading level
|
|
1442
|
-
- Include section labels (UPPERCASE, letter-spacing 0.1em, accent color, 2-3 words) above every headline`}function
|
|
1493
|
+
- Include section labels (UPPERCASE, letter-spacing 0.1em, accent color, 2-3 words) above every headline`}function _y(){return`### Banned Punctuation
|
|
1443
1494
|
- **Em dashes (\u2014)**: NEVER use. Biggest AI tell. Replace with periods, commas, or parentheses.
|
|
1444
1495
|
- **Semicolons**: Feel academic, not conversational. Use periods instead.
|
|
1445
1496
|
- **Exclamation marks**: One per page maximum. Zero is ideal for B2B.
|
|
@@ -1469,12 +1520,12 @@ seamless, cutting-edge, groundbreaking, game-changer, revolutionary, transformat
|
|
|
1469
1520
|
- Use plain short words: use > utilize, start > commence, help > facilitate
|
|
1470
1521
|
- Vary sentence length aggressively: mix 3-word, 12-word, and 25-word sentences
|
|
1471
1522
|
- Front-load the benefit in the first 5 words
|
|
1472
|
-
- Write like you'd explain it in a bar \u2014 if you wouldn't say it holding a beer, rewrite it`}var
|
|
1523
|
+
- Write like you'd explain it in a bar \u2014 if you wouldn't say it holding a beer, rewrite it`}var Ur,Id,Rd=N(()=>{"use strict";y();Ke();Es();Ur={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"]};Id={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 Gr(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?"":`
|
|
1473
1524
|
|
|
1474
1525
|
## Brand Kit \u2014 MANDATORY Design Constraints
|
|
1475
1526
|
The following brand identity values MUST be used. Do NOT substitute or override them:
|
|
1476
1527
|
${t.join(`
|
|
1477
|
-
`)}`}function
|
|
1528
|
+
`)}`}function Yo(e,t){let n=[];n.push(`You are the Email Design Token Architect for vibeSpot, a HubSpot email template builder.
|
|
1478
1529
|
|
|
1479
1530
|
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.
|
|
1480
1531
|
|
|
@@ -1563,25 +1614,25 @@ Do NOT use: system-ui, -apple-system, Segoe UI, Inter, or any Google Fonts.
|
|
|
1563
1614
|
- No external font imports`),n.push(`
|
|
1564
1615
|
|
|
1565
1616
|
## Email Design Guide
|
|
1566
|
-
${
|
|
1617
|
+
${Fd()}`),t?.styleguide&&n.push(`
|
|
1567
1618
|
|
|
1568
1619
|
## Brand Style Guide
|
|
1569
1620
|
${t.styleguide}`),t?.themeContext&&n.push(`
|
|
1570
1621
|
|
|
1571
1622
|
## Product Context
|
|
1572
|
-
${t.themeContext}`);let s=
|
|
1623
|
+
${t.themeContext}`);let s=Gr(t?.brandKit);return s?n.push(s):t?.styleguide||n.push(`
|
|
1573
1624
|
|
|
1574
1625
|
## No Brand Provided \u2014 Be Creative
|
|
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
|
|
1626
|
+
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 Wr(e,t){let n=Yo(e),o=n.indexOf(`
|
|
1576
1627
|
|
|
1577
1628
|
## Email Design Guide
|
|
1578
1629
|
`);if(o===-1)return[{type:"text",text:n}];let i=n.slice(0,o),r=`## Email Design Guide
|
|
1579
|
-
${
|
|
1630
|
+
${Fd()}`,a=[{type:"text",text:i},{type:"text",text:r,cache_control:{type:"ephemeral"}}],l=[];t?.styleguide&&l.push(`## Brand Style Guide
|
|
1580
1631
|
${t.styleguide}`),t?.themeContext&&l.push(`## Product Context
|
|
1581
|
-
${t.themeContext}`);let c=
|
|
1632
|
+
${t.themeContext}`);let c=Gr(t?.brandKit);return c?l.push(c):t?.styleguide||l.push(`## No Brand Provided \u2014 Be Creative
|
|
1582
1633
|
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(`
|
|
1583
1634
|
|
|
1584
|
-
`)}),a}function
|
|
1635
|
+
`)}),a}function Od(e,t,n,s){let o=[],i=Object.entries(t).map(([a,l])=>` ${a}: ${l}`).join(`
|
|
1585
1636
|
`);o.push(`You are the Email Module Planner for vibeSpot, a HubSpot email template builder.
|
|
1586
1637
|
|
|
1587
1638
|
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.
|
|
@@ -1640,7 +1691,7 @@ List all module names in display order (top to bottom)
|
|
|
1640
1691
|
One sentence describing the email's purpose and flow`),(!s||s.includes("content"))&&o.push(`
|
|
1641
1692
|
|
|
1642
1693
|
## Email Content Guide
|
|
1643
|
-
${
|
|
1694
|
+
${$y()}`),n?.brandvoice&&o.push(`
|
|
1644
1695
|
|
|
1645
1696
|
## Brand Voice
|
|
1646
1697
|
${n.brandvoice}`),n?.themeContext&&o.push(`
|
|
@@ -1649,7 +1700,7 @@ ${n.brandvoice}`),n?.themeContext&&o.push(`
|
|
|
1649
1700
|
${n.themeContext}`),n?.humanify!==!1&&s?.includes("humanify")&&o.push(`
|
|
1650
1701
|
|
|
1651
1702
|
## Anti-AI Copy Rules
|
|
1652
|
-
${
|
|
1703
|
+
${Ey()}`);let r=Gr(n?.brandKit);return r&&o.push(r),o.join("")}function Fd(){return`### Email Design Philosophy
|
|
1653
1704
|
Design for the inbox, not the browser. Email templates must look clean and professional in Gmail, Outlook, Apple Mail, and Yahoo Mail simultaneously.
|
|
1654
1705
|
|
|
1655
1706
|
### Color Strategy
|
|
@@ -1682,7 +1733,7 @@ Design for the inbox, not the browser. Email templates must look clean and profe
|
|
|
1682
1733
|
- Hero images: 600px wide, 2:1 to 3:1 aspect ratio
|
|
1683
1734
|
- Always include alt text (images blocked by default in many clients)
|
|
1684
1735
|
- Use display:block to prevent gaps in Outlook
|
|
1685
|
-
- Product images: consistent sizing within a row`}function
|
|
1736
|
+
- Product images: consistent sizing within a row`}function $y(){return`### Email Types and Structure
|
|
1686
1737
|
|
|
1687
1738
|
**Welcome / Onboarding Email**
|
|
1688
1739
|
- Warm greeting with first-name personalization
|
|
@@ -1728,7 +1779,7 @@ Design for the inbox, not the browser. Email templates must look clean and profe
|
|
|
1728
1779
|
- One idea per paragraph, 2-3 sentences max
|
|
1729
1780
|
- Use "you" more than "we"
|
|
1730
1781
|
- Specific > vague: "saves 3 hours/week" beats "saves time"
|
|
1731
|
-
- CTA copy = verb + benefit: "Start Your Trial", "See the Results"`}function
|
|
1782
|
+
- CTA copy = verb + benefit: "Start Your Trial", "See the Results"`}function Ey(){return`### Email-Specific Anti-AI Rules
|
|
1732
1783
|
- No em dashes (\u2014) in email copy. Period.
|
|
1733
1784
|
- No "I hope this email finds you well"
|
|
1734
1785
|
- No "In today's fast-paced world"
|
|
@@ -1737,31 +1788,31 @@ Design for the inbox, not the browser. Email templates must look clean and profe
|
|
|
1737
1788
|
- One exclamation mark per email maximum
|
|
1738
1789
|
- Avoid tricolon structures ("Fast, reliable, secure")
|
|
1739
1790
|
- Write like a colleague, not a press release
|
|
1740
|
-
- Every sentence must earn its place \u2014 if removing it doesn't hurt, remove it`}var
|
|
1791
|
+
- Every sentence must earn its place \u2014 if removing it doesn't hurt, remove it`}var Kr,Dd=N(()=>{"use strict";y();Kr={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 jd(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?Yo(n.themeName,n.brandAssets):zo(n.themeName,n.brandAssets),d=l?a?Wr(n.themeName,n.brandAssets):Hr(n.themeName,n.brandAssets):void 0,u=`## User Request
|
|
1741
1792
|
${e}`;n.modules.length>0&&t.designSystemChanges&&(u+=`
|
|
1742
1793
|
|
|
1743
1794
|
## Current Shared CSS (update this)
|
|
1744
1795
|
\`\`\`css
|
|
1745
1796
|
${n.sharedCss}
|
|
1746
|
-
\`\`\``);let m=
|
|
1747
|
-
${Object.entries(S).map(([
|
|
1797
|
+
\`\`\``);let m=Hn(s),g=a?Kr:Ur,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 {
|
|
1798
|
+
${Object.entries(S).map(([j,J])=>` ${j.startsWith("--")?j:`--${j}`}: ${J};`).join(`
|
|
1748
1799
|
`)}
|
|
1749
1800
|
}
|
|
1750
1801
|
|
|
1751
1802
|
${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
|
|
1803
|
+
`)}),r({type:"design_system_ready",sharedCss:b,sharedJs:f.sharedJs||"",aesthetic:f.aesthetic||""}),{...f,sharedCss:b}}async function Ld(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?Yo(n.themeName,n.brandAssets):zo(n.themeName,n.brandAssets),d=l?a?Wr(n.themeName,n.brandAssets):Hr(n.themeName,n.brandAssets):void 0,u=`## User Request
|
|
1753
1804
|
${e}`;n.modules.length>0&&t.designSystemChanges&&(u+=`
|
|
1754
1805
|
|
|
1755
1806
|
## Current Shared CSS (update this)
|
|
1756
1807
|
\`\`\`css
|
|
1757
1808
|
${n.sharedCss}
|
|
1758
|
-
\`\`\``);let m=
|
|
1809
|
+
\`\`\``);let m=Hn(s),g=a?Kr:Ur,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
1810
|
${Object.entries(S).map(([$,F])=>` ${$.startsWith("--")?$:`--${$}`}: ${F};`).join(`
|
|
1760
1811
|
`)}
|
|
1761
1812
|
}
|
|
1762
1813
|
|
|
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
|
|
1764
|
-
`)}),r({type:"design_system_ready",sharedCss:b,sharedJs:f.sharedJs||"",aesthetic:f.aesthetic||""}),r({type:"agent_step",step:"designing",label:"Planning modules..."});let
|
|
1814
|
+
${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 j=Object.keys(S||{}).length,J=a?[`Email design tokens: ${f.aesthetic||"created"} | ${j} tokens`]:[`Design system: ${f.aesthetic||"created"} | ${j} variables, ${b.length} chars CSS`,...v];r({type:"agent_decision",step:"designing",decision:J.join(`
|
|
1815
|
+
`)}),r({type:"design_system_ready",sharedCss:b,sharedJs:f.sharedJs||"",aesthetic:f.aesthetic||""}),r({type:"agent_step",step:"designing",label:"Planning modules..."});let H=a?Od(n.themeName,S||{},n.brandAssets,t.guidesNeeded):Md(n.themeName,b,n.brandAssets,t.guidesNeeded),K=`## User Request
|
|
1765
1816
|
${e}`;if(t.newModules.length>0&&(K+=`
|
|
1766
1817
|
|
|
1767
1818
|
## Planned Modules
|
|
@@ -1776,8 +1827,8 @@ These already exist and are being regenerated. Your output's module names MUST m
|
|
|
1776
1827
|
## Existing Modules to Keep (do not re-plan)
|
|
1777
1828
|
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).
|
|
1778
1829
|
`+F.map(re=>`- \`${re.moduleName}\``).join(`
|
|
1779
|
-
`))}let X=await te("module-planner",()=>Pe(s,o,i,{systemPrompt:
|
|
1780
|
-
`)}function
|
|
1830
|
+
`))}let X=await te("module-planner",()=>Pe(s,o,i,{systemPrompt:H,messages:[{role:"user",content:K}],structuredOutput:{schema:Id,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 Jd=N(()=>{"use strict";y();dt();Rd();Dd();le();Be()});function My(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(`
|
|
1831
|
+
`)}function Bd(e,t,n,s,o){let i=My(s),r=t.map(d=>`- **${d.label}** (${d.pageType}, slug: "${d.slug}"): ${d.purpose}`).join(`
|
|
1781
1832
|
`),a=n.map(d=>`- **${d}**`).join(`
|
|
1782
1833
|
`),l=[],c=t.map(d=>` - "${d.label}" \u2192 href="/${d.slug}"`).join(`
|
|
1783
1834
|
`);return l.push(Rt("site-module-planner",{themeName:e,siteMap:r,sharedList:a,cssSummary:i,navHrefs:c,sharedModuleNamesCsv:n.join(", ")})),o?.brandvoice&&l.push(`
|
|
@@ -1786,12 +1837,12 @@ These stay as-is. Do NOT include them in your output. They will appear in the fi
|
|
|
1786
1837
|
${o.brandvoice}`),o?.themeContext&&l.push(`
|
|
1787
1838
|
|
|
1788
1839
|
## Product Context
|
|
1789
|
-
${o.themeContext}`),l.join("")}var
|
|
1840
|
+
${o.themeContext}`),l.join("")}var Hd,Ud=N(()=>{"use strict";y();Es();Hd={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 Wd(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=Bd(n.themeName,l,c,s,n.brandAssets),u=`## User Request
|
|
1790
1841
|
${e}
|
|
1791
1842
|
|
|
1792
1843
|
## Site Map
|
|
1793
1844
|
${l.map(v=>`- ${v.label} (${v.slug}): ${v.purpose}`).join(`
|
|
1794
|
-
`)}`,m=
|
|
1845
|
+
`)}`,m=Hn(o),g=await te("site-module-planner",()=>Pe(o,i,r,{systemPrompt:d,messages:[{role:"user",content:u}],structuredOutput:{schema:Hd,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"),Gd(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):[]}),Gd(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 Gd(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 Kd=N(()=>{"use strict";y();dt();Ud();le();Be()});function qo(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 Vr=N(()=>{"use strict";y()});function Ms(e,t,n,s){let o=[];return o.push(Rt("module-developer",{themeName:e})),t&&o.push(`
|
|
1795
1846
|
|
|
1796
1847
|
## Theme Shared CSS (use these custom properties)
|
|
1797
1848
|
\`\`\`css
|
|
@@ -1808,7 +1859,7 @@ ${ye()}`),s?.themeContext&&o.push(`
|
|
|
1808
1859
|
${s.themeContext}`),s?.humanify!==!1&&n?.includes("humanify")&&o.push(`
|
|
1809
1860
|
|
|
1810
1861
|
## Anti-AI Copy Rules
|
|
1811
|
-
${
|
|
1862
|
+
${Vd()}`),o.join("")}function Xo(e,t,n,s){let o=[],i=Ms(e,"",[],s?{...s,humanify:!1}:void 0);t&&(i+=`
|
|
1812
1863
|
|
|
1813
1864
|
## Theme Shared CSS (use these custom properties)
|
|
1814
1865
|
\`\`\`css
|
|
@@ -1819,9 +1870,9 @@ ${ye()}`),r.length>0&&o.push({type:"text",text:r.join(`
|
|
|
1819
1870
|
|
|
1820
1871
|
`),cache_control:{type:"ephemeral"}});let a=[];return s?.themeContext&&a.push(`## Product Context
|
|
1821
1872
|
${s.themeContext}`),s?.humanify!==!1&&n?.includes("humanify")&&a.push(`## Anti-AI Copy Rules
|
|
1822
|
-
${
|
|
1873
|
+
${Vd()}`),a.length>0&&o.push({type:"text",text:a.join(`
|
|
1823
1874
|
|
|
1824
|
-
`)}),o}function
|
|
1875
|
+
`)}),o}function Vd(){return`### Banned Punctuation
|
|
1825
1876
|
- **Em dashes (\u2014)**: NEVER use. Replace with periods, commas, or parentheses. Hyphens for compounds fine.
|
|
1826
1877
|
- **Semicolons**: Use periods instead in marketing copy.
|
|
1827
1878
|
- **Exclamation marks**: One per page max. Zero ideal for B2B.
|
|
@@ -1860,7 +1911,7 @@ Never end with: "The future of [X] is here", "Your journey starts here", "Join t
|
|
|
1860
1911
|
- Keep slightly imperfect (fragments OK, mild hedging like "honestly didn't think")
|
|
1861
1912
|
- Full names, specific roles (not "John D., CEO")
|
|
1862
1913
|
- Never start with "This product is..." \u2014 start with the person's situation
|
|
1863
|
-
- Vary length and voice across testimonials`}function
|
|
1914
|
+
- Vary length and voice across testimonials`}function zd(e,t,n){let s=[];return s.push(`## User Request
|
|
1864
1915
|
${e}`),s.push(`
|
|
1865
1916
|
|
|
1866
1917
|
## Module Specification
|
|
@@ -1887,7 +1938,7 @@ ${n.moduleCss}
|
|
|
1887
1938
|
**module.js:**
|
|
1888
1939
|
\`\`\`js
|
|
1889
1940
|
${n.moduleJs}
|
|
1890
|
-
\`\`\``)),s.join("")}var
|
|
1941
|
+
\`\`\``)),s.join("")}var Is,zr=N(()=>{"use strict";y();Ke();Es();Is={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 Yr(e,t){let n=[];if(n.push(`You are an Email Module Developer for vibeSpot, a HubSpot CMS builder.
|
|
1891
1942
|
|
|
1892
1943
|
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
1944
|
|
|
@@ -2045,17 +2096,17 @@ Modules that serve as email footers MUST include:
|
|
|
2045
2096
|
${t.themeContext}`),t?.humanify!==!1&&n.push(`
|
|
2046
2097
|
|
|
2047
2098
|
## Anti-AI Copy Rules
|
|
2048
|
-
${
|
|
2099
|
+
${qd()}`),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
2100
|
|
|
2050
2101
|
## Brand Kit \u2014 MANDATORY Design Constraints
|
|
2051
2102
|
The following brand identity values MUST be used. Do NOT substitute or override them:
|
|
2052
2103
|
${s.join(`
|
|
2053
|
-
`)}`)}return n.join("")}function
|
|
2104
|
+
`)}`)}return n.join("")}function Yd(e,t){let n=[],s=Yr(e,{...t,humanify:!1});n.push({type:"text",text:s});let o;try{o=bl()}catch{o=""}o&&n.push({type:"text",text:`## Email Template Rules Reference
|
|
2054
2105
|
${o}`,cache_control:{type:"ephemeral"}});let i=[];return t?.themeContext&&i.push(`## Product Context
|
|
2055
2106
|
${t.themeContext}`),t?.humanify!==!1&&i.push(`## Anti-AI Copy Rules
|
|
2056
|
-
${
|
|
2107
|
+
${qd()}`),i.length>0&&n.push({type:"text",text:i.join(`
|
|
2057
2108
|
|
|
2058
|
-
`)}),n}function
|
|
2109
|
+
`)}),n}function qd(){return`### Banned Punctuation
|
|
2059
2110
|
- **Em dashes (\u2014)**: NEVER use. Replace with periods, commas, or parentheses.
|
|
2060
2111
|
- **Semicolons**: Use periods instead.
|
|
2061
2112
|
- **Exclamation marks**: One per email max. Zero ideal for B2B.
|
|
@@ -2074,7 +2125,7 @@ Never start with: "In today's", "In an era", "Whether you're", "Imagine a world"
|
|
|
2074
2125
|
- Be concrete: "42 minutes" not "fast", "\u20AC29/month" not "affordable"
|
|
2075
2126
|
- Use plain words: use > utilize, start > commence, help > facilitate
|
|
2076
2127
|
- Front-load the benefit in the first 5 words
|
|
2077
|
-
- Email subject lines: specific, benefit-first, under 50 chars`}function
|
|
2128
|
+
- Email subject lines: specific, benefit-first, under 50 chars`}function Xd(e,t,n){let s=[];return s.push(`## User Request
|
|
2078
2129
|
${e}`),s.push(`
|
|
2079
2130
|
|
|
2080
2131
|
## Email Module Specification
|
|
@@ -2094,7 +2145,7 @@ ${n.fieldsJson}
|
|
|
2094
2145
|
**module.html:**
|
|
2095
2146
|
\`\`\`html
|
|
2096
2147
|
${n.moduleHtml}
|
|
2097
|
-
\`\`\``),s.join("")}var
|
|
2148
|
+
\`\`\``),s.join("")}var Zd,Qd=N(()=>{"use strict";y();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: ["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 qr(e,t,n,s){let o=[];o.push(`You are a Blog Module Developer for vibeSpot, a HubSpot CMS builder.
|
|
2098
2149
|
|
|
2099
2150
|
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
2151
|
|
|
@@ -2279,22 +2330,22 @@ The blog post body module wraps \`{{ content.post_body }}\` with reading-optimiz
|
|
|
2279
2330
|
${s.themeContext}`),s?.humanify!==!1&&o.push(`
|
|
2280
2331
|
|
|
2281
2332
|
## Anti-AI Copy Rules
|
|
2282
|
-
${
|
|
2333
|
+
${tu()}`);let i=[];if(n?.includes("conversion"))try{let r=ye();r&&i.push(`## Conversion Guide
|
|
2283
2334
|
${r}`)}catch{}if(n?.includes("hubspot_rules"))try{let r=Je();r&&i.push(`## HubSpot Rules
|
|
2284
2335
|
${r}`)}catch{}return i.length>0&&o.push(`
|
|
2285
2336
|
|
|
2286
2337
|
${i.join(`
|
|
2287
2338
|
|
|
2288
|
-
`)}`),o.join("")}function
|
|
2339
|
+
`)}`),o.join("")}function eu(e,t,n,s){let o=[],i=qr(e,t,void 0,{...s,humanify:!1});o.push({type:"text",text:i});let r;try{r=Sl()}catch{r=""}r&&o.push({type:"text",text:`## Blog Template Rules Reference
|
|
2289
2340
|
${r}`,cache_control:{type:"ephemeral"}});let a=[];if(n?.includes("conversion"))try{let c=ye();c&&a.push(`## Conversion Guide
|
|
2290
2341
|
${c}`)}catch{}if(n?.includes("hubspot_rules"))try{let c=Je();c&&a.push(`## HubSpot Rules
|
|
2291
2342
|
${c}`)}catch{}a.length>0&&o.push({type:"text",text:a.join(`
|
|
2292
2343
|
|
|
2293
2344
|
`),cache_control:{type:"ephemeral"}});let l=[];return s?.themeContext&&l.push(`## Product Context
|
|
2294
2345
|
${s.themeContext}`),s?.humanify!==!1&&l.push(`## Anti-AI Copy Rules
|
|
2295
|
-
${
|
|
2346
|
+
${tu()}`),l.length>0&&o.push({type:"text",text:l.join(`
|
|
2296
2347
|
|
|
2297
|
-
`)}),o}function
|
|
2348
|
+
`)}),o}function tu(){return`### Banned Punctuation
|
|
2298
2349
|
- **Em dashes (\u2014)**: NEVER use. Replace with periods, commas, or parentheses.
|
|
2299
2350
|
- **Semicolons**: Use periods instead.
|
|
2300
2351
|
- **Exclamation marks**: Maximum one per page. Zero ideal for B2B.
|
|
@@ -2313,7 +2364,7 @@ Never start with: "In today's", "In an era", "Whether you're", "Imagine a world"
|
|
|
2313
2364
|
- Be concrete: "42 minutes" not "fast", "\u20AC29/month" not "affordable"
|
|
2314
2365
|
- Use plain words: use > utilize, start > commence, help > facilitate
|
|
2315
2366
|
- Front-load the benefit in the first 5 words
|
|
2316
|
-
- Blog headlines: specific, benefit-first, no clickbait`}function
|
|
2367
|
+
- Blog headlines: specific, benefit-first, no clickbait`}function nu(e,t,n){let s=[];return s.push(`## User Request
|
|
2317
2368
|
${e}`),s.push(`
|
|
2318
2369
|
|
|
2319
2370
|
## Blog Module Specification
|
|
@@ -2338,17 +2389,17 @@ ${n.moduleHtml}
|
|
|
2338
2389
|
**module.css:**
|
|
2339
2390
|
\`\`\`css
|
|
2340
2391
|
${n.moduleCss}
|
|
2341
|
-
\`\`\``),s.join("")}var
|
|
2392
|
+
\`\`\``),s.join("")}var su,ou=N(()=>{"use strict";y();Ke();Ke();su={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 Ps(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?Yr(s,d):g?qr(s,n,c,d):Ms(s,n,c,d),S=f?m?Yd(s,d):g?eu(s,n,c,d):Xo(s,n,c,d):void 0,v=qo(a),w=t.length,M=m?Zd:g?su:Is,j=t.map((H,K)=>v(async()=>{l({type:"module_progress",module:H.name,status:"generating",current:K+1,total:w});let X="";for(let O=0;O<2;O++)try{O>0&&(E.warn("module-developer",`${H.name}: retrying after failure (attempt ${O+1})`),l({type:"module_progress",module:H.name,status:"retrying",current:K+1,total:w}));let k=await iu(e,H,b,o,i,r,0,S,m,M,g);return l({type:"module_progress",module:H.name,status:"complete",current:K+1,total:w,moduleFiles:k}),{moduleName:H.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: ${H.name} (attempt ${O+1})`,{error:X})}return l({type:"module_progress",module:H.name,status:"failed",current:K+1,total:w}),{moduleName:H.name,error:X}}));return(await Promise.allSettled(j)).map(H=>H.status==="fulfilled"?H.value:{moduleName:"unknown",error:H.reason instanceof Error?H.reason.message:String(H.reason)})}async function iu(e,t,n,s,o,i,r=0,a,l=!1,c=Is,d=!1){let u=l?Xd(e,t,t.existingCode):d?nu(e,t,t.existingCode):zd(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}`),iu(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 ru=N(()=>{"use strict";y();dt();Vr();zr();Qd();ou();le()});function ln(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=au(c.fieldsJson,c.moduleName,"fieldsJson",l,i),c.metaJson=au(c.metaJson,c.moduleName,"metaJson",l,i,r);let d={};c.fieldsJson=Py(c.fieldsJson,c.moduleName,l,d),c.moduleHtml=Ny(c.moduleHtml,d),c.fieldsJson=Ry(c.fieldsJson,c.moduleName,l),i?c=Wy(c,l):(c.moduleCss=Oy(c.moduleCss,c.moduleName,"moduleCss",l),c.moduleCss=Dy(c.moduleCss,c.moduleName,t,l),c.moduleHtml=jy(c.moduleHtml,c.moduleName,t,l),r&&(c=Ky(c,l))),c.moduleHtml=Jy(c.moduleHtml,c.moduleName,l),i||By(c,l),c.metaJson=Hy(c.metaJson,c.moduleName,l,i,r),o&&Gy(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 au(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):ct(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 Py(e,t,n,s){let o=e;for(let[i,r]of Iy)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 Ny(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 Ry(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 Oy(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 cu(e){return Fy.has(e)||e.startsWith("body-wrapper")||e.startsWith("dnd-")||e.startsWith("row-")||e.startsWith("hs-")||e.startsWith("hs_")}function Dy(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)&&!cu(c)&&r.add(c)}if(r.size<=3)return e;let l=e;for(let c of r){let d=new RegExp(`\\.${Ly(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 jy(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)&&!cu(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 Ly(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Jy(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
2393
|
`);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 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(`
|
|
2394
|
+
${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 lu(e){if(!e)return[];let t=[],n=/\b(rgba?|hsla?)\(([^()]*)\)/gi,s;for(;(s=n.exec(e))!==null;){let o=s[2];(o.trim()===""||o.split(",").some(i=>i.trim()===""))&&t.push(s[0].trim())}return t}function By(e,t){let n=ct(e.fieldsJson),s=Array.isArray(n)?rn(n):{},o=e.moduleHtml||"";try{o=jn(e.moduleHtml||"",{module:s})}catch{}let i=[...lu(o),...lu(e.moduleCss||"")];if(i.length===0)return;let r=i[0].length>60?i[0].slice(0,57)+"\u2026":i[0];t.push({module:e.moduleName,field:"moduleCss",message:`${i.length} invalid CSS color value${i.length===1?"":"s"} (e.g. \`${r}\`) \u2014 renders unstyled. A style field with no default is likely fed into rgba()/hsla().`,autoFixed:!1,code:"invalid-css"})}function Hy(e,t,n,s=!1,o=!1){let i=ct(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 du(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 Gy(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(Uy))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 Wy(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 Ky(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 Iy,Fy,Uy,Xr=N(()=>{"use strict";y();Wo();le();Sr();Iy=[["name","item_name"],["label","section_label"],["body","body_text"]];Fy=new Set(["visible","active","scroll-animate","hidden","open","closed","fade-in","fade-out","is-active","is-open","is-visible"]);Uy=/#[0-9a-fA-F]{6}\b/g});import{execSync as Vy}from"child_process";async function uu(e,t,n,s,o,i,r,a){let l=Date.now(),c=i;if(Un(n)){let k={"claude-code":"claude","gemini-cli":"gemini","codex-cli":"codex"}[n];if(k)try{Vy(`command -v ${k}`,{stdio:"ignore"})}catch{throw new Error(`CLI engine "${n}" requires "${k}" to be installed and on your PATH.`)}}let d=await _d(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 zy(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 Ld(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",()=>Ps(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=ln(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",()=>Ps(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=ln(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
2395
|
`);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=
|
|
2396
|
+
${$}`})}else r({type:"agent_decision",step:"quality_check",decision:"All modules passed quality checks"})}let w=qy(t,d,b,u,a),M=Xy(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 j=Date.now()-l,J=b.length,H=d.unchangedModules.length,K=v?v.flatMap(O=>O.issues):[],X=Zy(d,J,H,S,j,u,K);return S.length>0?r({type:"pipeline_partial",succeeded:b.map(O=>O.moduleName),failed:S,durationMs:j}):r({type:"pipeline_complete",modulesGenerated:J,modulesUnchanged:H,durationMs:j,assistantMessage:X}),{modules:w,moduleOrder:M,sharedCss:m,sharedJs:g,assistantMessage:X,contentType:d.contentType,stats:{modulesGenerated:J,modulesUnchanged:H,modulesFailed:S.length,durationMs:j}}}async function zy(e,t,n,s,o,i,r,a,l){let c=t.pages,d=t.sharedModules||["site-header","site-footer"],u=await jd(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 Wd(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
2397
|
`);for(let $ of f)($.name.includes("header")||$.name.includes("nav"))&&($.layoutNotes+=`
|
|
2347
2398
|
|
|
2348
2399
|
## Site Navigation
|
|
2349
2400
|
This is a multi-page site. Include navigation links to all pages:
|
|
2350
2401
|
${b}
|
|
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",()=>
|
|
2402
|
+
Use relative href paths. Add CSS class "${n.themeName}-nav__link--active" on the current page's link.`);let S=await te("module-development",()=>Ps(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,j=[];if(v.length>0){let $=ln(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",()=>Ps(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(Us=>Us.moduleName===ne.moduleName);$e>=0&&(v[$e]=ne.module)}$=ln(v,n.themeName,a,t.contentType,n.brandAssets?.brandKit)}}M=$.map(z=>z.module),j=$.flatMap(z=>z.issues);let re=du(M,c.map(z=>z.slug));j.push(...re);let _e=j.length;if(_e>0){let z=j.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 J=new Map(M.map($=>[$.moduleName,$])),H=h.sharedModules.map($=>J.get($.name)).filter($=>!!$),K=new Map(c.map($=>[$.id,$])),X=h.pages.map($=>{let F=$.modules.map(ne=>J.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:[...H,...F],moduleOrder:z}}),O=Date.now()-l,k=Yy(c,v.length,w,O,h.narrative,j);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:H,sharedCss:m,sharedJs:g||"",assistantMessage:k,stats:{pagesGenerated:c.length,modulesGenerated:v.length,modulesFailed:w.length,durationMs:O}}}}function Yy(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
2403
|
|
|
2353
2404
|
**Pages:** ${e.map(d=>d.label).join(", ")}`),o&&a.push(`
|
|
2354
2405
|
|
|
@@ -2357,14 +2408,14 @@ ${o}`),n.length>0&&a.push(`
|
|
|
2357
2408
|
**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
2409
|
|
|
2359
2410
|
${d.join(`
|
|
2360
|
-
`)}`)}return a.join("")}function
|
|
2411
|
+
`)}`)}return a.join("")}function qy(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 Xy(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 Zy(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
2412
|
|
|
2362
2413
|
${i.narrative}`),s.length>0&&l.push(`
|
|
2363
2414
|
|
|
2364
2415
|
**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
2416
|
|
|
2366
2417
|
${u.join(`
|
|
2367
|
-
`)}`)}return l.join("")}var
|
|
2418
|
+
`)}`)}return l.join("")}var mu=N(()=>{"use strict";y();dt();$d();Jd();Kd();ru();Xr();le();Be();dt()});var yu={};Ge(yu,{runFigmaConversion:()=>Qy});import{basename as fu}from"path";async function Qy(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}=eb(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}=nb(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=Ms(t,d,["hubspot_rules","conversion"],a),b=h?Xo(t,d,["hubspot_rules","conversion"],a):void 0,S=qo(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=ib(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:Is,name:"module_output"},maxTokens:16e3});if(ne.type!=="structured")throw new Error("No structured output returned");let $e=ne.data,Us={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:Us}),{moduleName:$.name,module:Us}}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)}),j=M.filter(T=>T.module).map(T=>T.module),J=M.filter(T=>T.error).map(T=>T.moduleName),K=ln(j,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 J.length>0?r({type:"pipeline_partial",succeeded:K.map(T=>T.moduleName),failed:J,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:J.length,durationMs:X}}}function Zo(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 eb(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?Zo(a.hex).l<.4:!1;a&&n.push(` --${s}-color-bg: ${a.hex}`);let c=r[0]||(l?o.find(k=>Zo(k.hex).l>.7):o.find(k=>Zo(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=Zo(a.hex).l;n.push(` --${s}-color-surface: ${l?pu(a.hex,.05):gu(a.hex,.03)}`),n.push(` --${s}-color-border: ${l?pu(a.hex,.15):gu(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 j=e.effects.filter(k=>k.type==="shadow"),J=e.effects.filter(k=>k.type==="radius");j[0]&&n.push(` --${s}-shadow: ${j[0].cssValue}`),J.sort((k,T)=>parseFloat(k.cssValue)-parseFloat(T.cssValue)),J[0]&&n.push(` --${s}-radius: ${J[0].cssValue}`),J[1]&&n.push(` --${s}-radius-lg: ${J[1].cssValue}`);let H=`:root {
|
|
2368
2419
|
${n.join(`;
|
|
2369
2420
|
`)};
|
|
2370
2421
|
}`,K=`
|
|
@@ -2451,7 +2502,7 @@ body {
|
|
|
2451
2502
|
h1 { font-size: 2rem; }
|
|
2452
2503
|
h2 { font-size: 1.5rem; }
|
|
2453
2504
|
h3 { font-size: 1.25rem; }
|
|
2454
|
-
}`;return{sharedCss:
|
|
2505
|
+
}`;return{sharedCss:H+`
|
|
2455
2506
|
`+K,sharedJs:`(function() {
|
|
2456
2507
|
var observer = new IntersectionObserver(function(entries) {
|
|
2457
2508
|
entries.forEach(function(entry) {
|
|
@@ -2462,11 +2513,11 @@ body {
|
|
|
2462
2513
|
});
|
|
2463
2514
|
}, { threshold: 0.1 });
|
|
2464
2515
|
document.querySelectorAll('[data-animate]').forEach(function(el) { observer.observe(el); });
|
|
2465
|
-
})();`}}function
|
|
2466
|
-
`)}function
|
|
2516
|
+
})();`}}function pu(e,t){return hu(e,t)}function gu(e,t){return hu(e,-t)}function hu(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 tb(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[^a-zA-Z0-9]+/g,"-").replace(/(^-|-$)/g,"").toLowerCase()}function nb(e,t,n){let s=new Set,o=[];for(let i of e){let r=tb(i.name);if(s.has(r)){let d=2;for(;s.has(`${r}-${d}`);)d++;r=`${r}-${d}`}s.add(r);let a=sb(i.textContent),l=ob(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 sb(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(`
|
|
2517
|
+
`)}function ob(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
2518
|
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
|
|
2519
|
+
Available image assets:`);for(let o of t){let i=fu(o.localPath);s.push(` - get_asset_url("${n}/assets/${i}") \u2014 ${o.name}`)}}return s.join(`
|
|
2520
|
+
`)}function ib(e,t,n,s,o){let i=[];if(i.push(`## Figma Design Translation
|
|
2470
2521
|
|
|
2471
2522
|
TRANSLATE this Figma section into a HubSpot CMS module. This is a CONVERSION, not creation.
|
|
2472
2523
|
- Use the EXACT text content from the design as field default values
|
|
@@ -2491,12 +2542,12 @@ The Figma design shows the DESKTOP layout. You MUST add responsive CSS:
|
|
|
2491
2542
|
### 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
2543
|
### 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
2544
|
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=
|
|
2545
|
+
### 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=fu(r.localPath);i.push(`- \`get_asset_url("${s}/assets/${a}")\` \u2014 ${r.name}`)}}else{i.push(`
|
|
2495
2546
|
### 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
2547
|
## Module Specification
|
|
2497
2548
|
- **Name**: ${t.name}
|
|
2498
2549
|
- **Description**: ${t.description}`),i.join(`
|
|
2499
|
-
`)}var
|
|
2550
|
+
`)}var bu=N(()=>{"use strict";y();dt();Vr();zr();Xr();le();Be()});var Su={};Ge(Su,{buildPlanModePrompt:()=>rb});function rb(e,t,n,s,o){let i=ab(o,!!t?.plan),r=[];return r.push(`You are vibeSpot's plan-mode assistant for the theme "${e}".
|
|
2500
2551
|
|
|
2501
2552
|
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
2553
|
|
|
@@ -2565,15 +2616,15 @@ Drive toward filling these gaps in priority order:
|
|
|
2565
2616
|
The theme already has a styleguide. Reference its colors, typography, and tokens in the plan rather than asking about them again.
|
|
2566
2617
|
|
|
2567
2618
|
\`\`\`
|
|
2568
|
-
${
|
|
2619
|
+
${Zr(t.styleguide,1500)}
|
|
2569
2620
|
\`\`\``),t?.brandvoice&&r.push(`## Available brand voice
|
|
2570
2621
|
|
|
2571
2622
|
\`\`\`
|
|
2572
|
-
${
|
|
2623
|
+
${Zr(t.brandvoice,1e3)}
|
|
2573
2624
|
\`\`\``),t?.themeContext&&r.push(`## Theme context
|
|
2574
2625
|
|
|
2575
2626
|
\`\`\`
|
|
2576
|
-
${
|
|
2627
|
+
${Zr(t.themeContext,1e3)}
|
|
2577
2628
|
\`\`\``),n.length>0&&r.push(`## Existing modules in this theme
|
|
2578
2629
|
|
|
2579
2630
|
These already exist on the page \u2014 you can keep, modify, or remove them in the plan, or reference them as reusable:
|
|
@@ -2594,13 +2645,13 @@ ${t.plan}
|
|
|
2594
2645
|
|
|
2595
2646
|
${i}`),r.join(`
|
|
2596
2647
|
|
|
2597
|
-
`)}function
|
|
2648
|
+
`)}function ab(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
2649
|
- Briefly acknowledge the template and that you'll work from this structure (1\u20132 sentences in chat).
|
|
2599
2650
|
- 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
2651
|
- 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
2652
|
- 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
|
|
2653
|
+
- 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)+`
|
|
2654
|
+
... [truncated]`}var vu=N(()=>{"use strict";y()});var ra={};Ge(ra,{applyPipelineResult:()=>cn,handleAgenticGenerate:()=>Qo,handleFigmaImport:()=>Rs,handleGenerate:()=>lb,handleGenerateStream:()=>Ns,handlePlanModeStream:()=>sa,isGenerating:()=>Kt,isPlanModeActive:()=>oa,resolveAgenticEngine:()=>Gn,setParseWarningCallback:()=>ta,shouldUseAgenticMode:()=>ia});import{execSync as Qr}from"child_process";function ta(e){ea=e}function Kt(){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),Zc(e,ea||void 0),L()}async function Ns(e,t,n,s){let o=C();if(!o)throw new Error("No active session");Ot=o.id;let r=s?.length?Ko(s):void 0;try{let a=R(),l=a.aiEngine||na();switch(l){case"anthropic-api":case"api":{let c=Fe("anthropic-api",a);if(!c)throw new Error("Anthropic API key not configured. Open Settings to add one.");await _r(e,c,o.themeName,a.anthropicApiModel||"claude-sonnet-4-6",t,n,wt,r);break}case"claude-oauth":{await ld(e,o.themeName,a.anthropicApiModel||"claude-sonnet-4-6",t,n,wt,r);break}case"openai-api":{let c=Fe("openai-api",a);if(!c)throw new Error("OpenAI API key not configured. Open Settings to add one.");await $r(e,c,o.themeName,a.openaiApiModel||"gpt-4o",t,n,wt,r);break}case"gemini-api":{let c=Fe("gemini-api",a);if(!c)throw new Error("Gemini API key not configured. Open Settings to add one.");await Er(e,c,o.themeName,t,n,wt,r);break}case"claude-code":await cd(e,o.themeName,t,n,wt,r);break;case"gemini-cli":await Nr("gemini",e,o.themeName,t,n,wt,r);break;case"codex-cli":await Nr("codex",e,o.themeName,t,n,wt,r);break;case"langdock-api":{let c=Fe("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 $r(e,c,o.themeName,g||"gpt-4.1",t,n,wt,r,`${m}/v1/chat/completions`);break;case"google":await Er(e,c,o.themeName,t,n,wt,r,`${m}/v1beta/models/${g||"gemini-2.5-flash"}:streamGenerateContent?alt=sse`,g);break;default:await _r(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,ea=null}}function na(){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 Qr("claude --version",{stdio:"pipe"}),"claude-code"}catch{}try{return Qr("gemini --version",{stdio:"pipe"}),"gemini-cli"}catch{}try{return Qr("codex --version",{stdio:"pipe"}),"codex-cli"}catch{}throw new Error("No AI engine available. Open Settings to configure one.")}async function lb(e){let t="";return await Ns(e,n=>{t+=n}),t}function xu(){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 Gn(e){let t=e.aiEngine||na();if(!_s(t))throw new Error("Agentic pipeline is not available for this engine.");if(Un(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=Fe(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 Qo(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}=Gn(i),c=i.agenticConcurrency||20,d=xu(),u=d.brandAssets?.plan,m=e;u&&u.trim()&&(m=`## Approved plan
|
|
2604
2655
|
|
|
2605
2656
|
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
2657
|
|
|
@@ -2610,39 +2661,39 @@ ${u}
|
|
|
2610
2661
|
|
|
2611
2662
|
## User message
|
|
2612
2663
|
|
|
2613
|
-
${e}`);let g=n?.length?
|
|
2664
|
+
${e}`);let g=n?.length?Ko(n):void 0;if(g?.length)for(let M of g)M.type==="document"&&M.extractedText&&(m+=`
|
|
2614
2665
|
|
|
2615
2666
|
---
|
|
2616
2667
|
[Attached document: ${M.originalName}]
|
|
2617
2668
|
${M.extractedText}`),M.type==="image"&&M.usage==="asset"&&M.assetPath&&(m+=`
|
|
2618
2669
|
|
|
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
|
|
2670
|
+
[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 Qi(()=>tt({name:"agent_pipeline",sessionId:d.themeName,input:e,metadata:{engine:r,model:l,concurrency:c},tags:["vibespot","agentic-pipeline"]},()=>uu(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 Rs(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(()=>(bu(),yu)),a=R(),{engine:l,apiKey:c,model:d}=Gn(a),u=a.agenticConcurrency||20,m=xu(),{result:g,cost:h}=await Qi(()=>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 cn(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"});Sc({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&&gc(t.cost),lt("assistant",e.assistantMessage,t),L()}async function sa(e,t,n){let s=C();if(!s)throw new Error("No active session");let o=R(),{engine:i,apiKey:r,model:a}=Gn(o),[{buildPlanModePrompt:l},{callAgent:c}]=await Promise.all([Promise.resolve().then(()=>(vu(),Su)),Promise.resolve().then(()=>(dt(),vd))]),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?Ko(n):void 0,S=e;if(b?.length)for(let w of b)w.type==="document"&&w.extractedText&&(S+=`
|
|
2620
2671
|
|
|
2621
2672
|
---
|
|
2622
2673
|
[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
|
|
2624
|
-
`}}function
|
|
2674
|
+
${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 oa(){return!!R().planMode}function ia(){let e=R(),t=e.aiEngine||na();return _s(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 ea,Ot,Wn=N(()=>{"use strict";y();ee();Ce();Wo();le();er();Rr();_t();Dr();mu();Be();ea=null;Ot=null});import{readFileSync as cb,readdirSync as db,existsSync as ub}from"fs";import{dirname as mb,join as ei}from"path";import{fileURLToPath as pb}from"url";function fb(e){let t=e.match(gb);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 hb(e){let t=fb(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()+`
|
|
2675
|
+
`}}function yb(){let e=[ei(wu,"../../assets/plan-templates"),ei(wu,"../assets/plan-templates"),ei(process.cwd(),"assets/plan-templates")];for(let t of e)if(ub(t))return t;return null}function Cu(){if(Vt)return Vt;let e=yb();if(!e)return Vt=[],Vt;let t=[],n=[];try{n=db(e)}catch{return Vt=[],Vt}for(let s of n)if(s.endsWith(".md"))try{let o=cb(ei(e,s),"utf-8"),i=hb(o);i&&t.push(i)}catch{}return t.sort((s,o)=>s.order!==o.order?s.order-o.order:s.label.localeCompare(o.label)),Vt=t,Vt}function ku(e){return Cu().find(t=>t.id===e)??null}function Tu(){return Cu().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 wu,gb,Vt,Au=N(()=>{"use strict";y();wu=mb(pb(import.meta.url)),gb=/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/;Vt=null});import{existsSync as _u,mkdirSync as bb,writeFileSync as Sb,rmSync as vb}from"fs";import{join as $u}from"path";function Eu(e){return $u(e,".vibespot",xb)}function ti(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=$u(t.themePath,".vibespot");_u(s)||bb(s,{recursive:!0}),Sb(Eu(t.themePath),e,"utf-8")}catch(s){E.warn("plan",`Failed to write plan.md: ${s instanceof Error?s.message:String(s)}`)}return L(),e}function aa(){let e=C();if(!e)return;e.brandAssets&&delete e.brandAssets.plan;let t=ke();t&&delete t.plan;try{let n=Eu(e.themePath);_u(n)&&vb(n)}catch(n){E.warn("plan",`Failed to remove plan.md: ${n instanceof Error?n.message:String(n)}`)}L()}function Mu(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}ti(o),p(t,200,{ok:!0,plan:o})})}function Iu(e,t){qe(e,t,()=>{aa(),Y({planMode:!1}),p(t,200,{ok:!0})})}function Pu(e,t){p(t,200,{templates:Tu()})}function Nu(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=ku(o);if(!i){p(t,404,{error:`Unknown plan template: ${o}`});return}ti(i.body),Y({planMode:!0}),p(t,200,{ok:!0,templateId:i.id,label:i.label,plan:i.body})})}var xb,Ru=N(()=>{"use strict";y();Xe();Ce();Ut();ee();le();Au();xb="plan.md"});function Ou(e){let t,n,s;for(la.lastIndex=0;(s=la.exec(e))!==null;)t=s[1].trim();let o;for(ca.lastIndex=0;(o=ca.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(la,"").replace(ca,"").replace(/\n{3,}/g,`
|
|
2625
2676
|
|
|
2626
|
-
`).trim(),plan:t,choices:n}}var
|
|
2677
|
+
`).trim(),plan:t,choices:n}}var la,ca,Fu=N(()=>{"use strict";y();la=/```vibespot-plan\s*\n([\s\S]*?)```/g,ca=/```vibespot-choices\s*\n([\s\S]*?)```/g});import{spawn as da}from"child_process";function Du(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
2678
|
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
|
|
2679
|
+
Process timed out`,t.completedAt=Date.now())},n||3e5)}function Os(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};zt.set(o,i);let r=da(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()),Du(r,i,s?.timeout),o}function dn(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};zt.set(s,o);let i=e.split(" "),r=da(i[0],i.slice(1),{cwd:n?.cwd,stdio:["ignore","pipe","pipe"],env:{...process.env,...n?.env},shell:!0});return Du(r,o,n?.timeout),s}function ni(e){return zt.get(e)}function wb(){let e=Date.now()-18e5;for(let[t,n]of zt)n.completedAt&&n.completedAt<e&&zt.delete(t)}function si(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};zt.set(s,o);let i=e.split(" "),r=da(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
2680
|
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
|
|
2681
|
+
Process timed out`,o.completedAt=Date.now(),o.listeners.clear())},l),s}function ju(e,t){let n=zt.get(e);if(!n||!("listeners"in n))return;let s=n;if(s.output)try{t(s.output)}catch{}s.listeners.add(t)}function Lu(e,t){let n=zt.get(e);!n||!("listeners"in n)||n.listeners.delete(t)}var zt,oi=N(()=>{"use strict";y();zt=new Map;setInterval(wb,600*1e3)});import{readFileSync as Cb,readdirSync as kb,existsSync as Tb}from"fs";import{dirname as Ab,join as ii}from"path";import{fileURLToPath as _b}from"url";function $b(){let e=[ii(Ju,"../../starters"),ii(Ju,"../starters"),ii(process.cwd(),"starters")];for(let t of e)if(Tb(t))return t;return null}function Bu(){if(Kn!==null)return Kn;let e=$b();if(!e)return Kn=[],Kn;let t=[];for(let n of kb(e).filter(s=>s.endsWith(".json")).sort())try{let s=JSON.parse(Cb(ii(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 Kn=t,Kn}function Hu(){return Bu().map(e=>({id:e.id,name:e.name,description:e.description,category:e.category,contentType:e.contentType,moduleCount:e.modules.length}))}function ua(e){return Bu().find(t=>t.id===e)||null}var Ju,Kn,Uu=N(()=>{"use strict";y();Ju=Ab(_b(import.meta.url)),Kn=null});var Ds={};Ge(Ds,{collectThemeFiles:()=>Wu,extractDesignContext:()=>Nb});import{existsSync as ri,readdirSync as ai,readFileSync as Eb}from"fs";import{join as Ct}from"path";import{spawn as Mb}from"child_process";async function Gu(){return ma||(ma=(await import("@anthropic-ai/sdk")).default),ma}function Fs(e){try{return Eb(e,"utf-8")}catch{return""}}function Wu(e){let t=[],n=0;function s(a,l){if(!l.trim())return!0;let c=`
|
|
2631
2682
|
### ${a}
|
|
2632
2683
|
\`\`\`
|
|
2633
2684
|
${l}
|
|
2634
2685
|
\`\`\`
|
|
2635
|
-
`;return n+c.length>
|
|
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=
|
|
2686
|
+
`;return n+c.length>Ib?!1:(t.push(c),n+=c.length,!0)}let o=Fs(Ct(e,"theme.json"));o&&s("theme.json",o);let i=Ct(e,"css");if(ri(i)){for(let a of ai(i).filter(l=>l.endsWith(".css")))if(!s(`css/${a}`,Fs(Ct(i,a))))break}let r=Ct(e,"modules");if(ri(r))for(let a of ai(r).filter(l=>l.endsWith(".module"))){let l=Ct(r,a),c=Fs(Ct(l,"module.css"));if(c&&!s(`modules/${a}/module.css`,c))break}if(ri(r))for(let a of ai(r).filter(l=>l.endsWith(".module"))){let l=Ct(r,a),c=Fs(Ct(l,"module.html"));if(c&&!s(`modules/${a}/module.html`,c))break}if(ri(r))for(let a of ai(r).filter(l=>l.endsWith(".module"))){let l=Ct(r,a),c=Fs(Ct(l,"fields.json"));if(c&&!s(`modules/${a}/fields.json`,c))break}return t.join("")}function Pb(){if(!li)try{li=P(hn("extraction-prompt.md"))}catch{li=""}return li}function pa(e,t,n){return new Promise((s,o)=>{let i={...process.env};delete i.CLAUDECODE;let r=Mb(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 Nb(e,t){t?.({status:"Collecting theme files..."});let n=Wu(e);if(!n.trim())throw new Error("No CSS, HTML, or fields.json files found in theme.");let s=Pb();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:
|
|
2687
|
+
${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=Fe("anthropic-api");if(!u)throw new Error("Anthropic API key not configured. Open Settings to add one.");let m=await Gu(),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(),Di)),h=await u();if(!h)throw new Error("Claude OAuth session expired. Please re-authenticate in Settings.");let f=await Gu(),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=Fe("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=_n(g.usage);break}case"gemini-api":{let u=Fe("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
2688
|
|
|
2638
2689
|
## User Request
|
|
2639
|
-
${o}`,m=["--print"];i.claudeCodeModel&&m.push("--model",i.claudeCodeModel),a=await
|
|
2690
|
+
${o}`,m=["--print"];i.claudeCodeModel&&m.push("--model",i.claudeCodeModel),a=await pa("claude",m,u);break}case"gemini-cli":{let u=`${s}
|
|
2640
2691
|
|
|
2641
2692
|
## User Request
|
|
2642
|
-
${o}`;a=await
|
|
2693
|
+
${o}`;a=await pa("gemini",[],u);break}case"codex-cli":{let u=`${s}
|
|
2643
2694
|
|
|
2644
2695
|
## User Request
|
|
2645
|
-
${o}`;a=await
|
|
2696
|
+
${o}`;a=await pa("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&&St({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 ma,Ib,li,js=N(()=>{"use strict";y();oe();ee();Be();tn();ma=null;Ib=8e4;li=""});var ga={};Ge(ga,{extractBrandvoice:()=>Rb});async function Rb(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
2697
|
|
|
2647
2698
|
Return a markdown document with these sections (skip any section where the content provides no signal):
|
|
2648
2699
|
|
|
@@ -2662,7 +2713,7 @@ Typical sentence length, structure, use of questions, imperatives, etc.
|
|
|
2662
2713
|
## Dos and Don'ts
|
|
2663
2714
|
3-4 practical rules for writing in this voice (e.g., "Do: Lead with benefits, not features", "Don't: Use jargon without context").
|
|
2664
2715
|
|
|
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
|
|
2716
|
+
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 fa=N(()=>{"use strict";y();dt();le()});var ci={};Ge(ci,{extractThemeContext:()=>Ob});async function Ob(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
2717
|
|
|
2667
2718
|
Return a markdown document with these sections (skip any section where the content provides no information):
|
|
2668
2719
|
|
|
@@ -2684,11 +2735,11 @@ Specific terms, product names, or branded language used consistently.
|
|
|
2684
2735
|
Keep it concise \u2014 this brief is used as context for AI-generated content on other pages in the same theme.${t?`
|
|
2685
2736
|
|
|
2686
2737
|
Existing product context (update if the new content adds info, keep what's still accurate):
|
|
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,`
|
|
2738
|
+
${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 di=N(()=>{"use strict";y();dt();le()});import{join as Ku}from"path";function Fb(e){let t=[];return e.brandAssets?.styleguide||t.push("styleguide"),e.brandAssets?.brandvoice||t.push("brandvoice"),e.brandAssets?.themeContext||t.push("themeContext"),t}function Db(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=Ku(e.themePath,".vibespot");Re(o),B(Ku(o,s),n)}async function Vu(e,t){let n=Fb(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"]},()=>jb(e,t,n,s))}async function jb(e,t,n,s){let o=Lb(t)?t:{...await Jb(e),...t??{}};n.includes("styleguide")&&await ha(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 ha(e,"brandvoice",s,()=>te("extract-brandvoice",()=>o.extractBrandvoice(e,r))),n.includes("themeContext")&&await ha(e,"themeContext",s,()=>te("extract-theme-context",()=>o.extractThemeContext(e,r))),s}async function ha(e,t,n,s){n.attempted.push(t);try{let o=await s();if(!o){n.skipped.push(t);return}Db(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 Lb(e){return!!e?.extractStyleguide&&!!e.extractBrandvoice&&!!e.extractThemeContext&&!!e.buildPreviewHtml}async function Jb(e){let{extractDesignContext:t}=await Promise.resolve().then(()=>(js(),Ds)),{buildPreviewHtml:n}=await Promise.resolve().then(()=>(Ss(),Go)),{resolveAgenticEngine:s}=await Promise.resolve().then(()=>(Wn(),ra)),{extractBrandvoice:o}=await Promise.resolve().then(()=>(fa(),ga)),{extractThemeContext:i}=await Promise.resolve().then(()=>(di(),ci)),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 zu=N(()=>{"use strict";y();oe();ee();le();Be()});import{existsSync as Vn,readdirSync as Yu,rmSync as Bb,writeFileSync as un,mkdirSync as ui}from"fs";import{join as Ne,basename as Hb}from"path";import{homedir as Ub}from"os";import{execFileSync as Xu}from"child_process";function pi(){if(mi&&Date.now()-mi.ts<Gb)return mi.data;let e=[];if(Vn(ut))try{for(let t of Yu(ut,{withFileTypes:!0}))if(t.isDirectory()){let n=Ne(ut,t.name,"theme.json");if(Vn(n)){let s=0,o=Ne(ut,t.name,"modules");if(Vn(o))try{s=Yu(o,{withFileTypes:!0}).filter(i=>i.isDirectory()).length}catch{}e.push({name:t.name,moduleCount:s})}}}catch{}return mi={data:e,ts:Date.now()},e}function Qu(e){let t=C(),n=so(),s=!1;try{Xu("hs",["--version"],{encoding:"utf-8",stdio:"pipe",...Zu}),s=!0}catch{}let o=On().sort((r,a)=>a.updatedAt-r.updatedAt),i=pi();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:Ln()})}function em(e,t){W(e,n=>{try{if(Kt()){p(t,409,{error:"Cannot switch projects while AI is generating.",generating:!0});return}let{name:s,starterId:o,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(ut,r);if(Re(ut),Vn(a)&&Bb(a,{recursive:!0,force:!0}),o&&typeof o=="string"&&!ua(o)){p(t,400,{error:`Starter template "${o}" not found`});return}os(a,r),Rn(a,r),o&&typeof o=="string"?(Wb(a,r,o),Te()):i==="email"&&(Pt("module_only","Email","email"),An(a,r)),L(),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 Wb(e,t,n){let s=ua(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&&An(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");ui(d,{recursive:!0});for(let u of s.modules){let m=Ne(d,`${u.moduleName}.module`);ui(m,{recursive:!0}),un(Ne(m,"fields.json"),u.fieldsJson,"utf-8"),un(Ne(m,"meta.json"),u.metaJson,"utf-8"),un(Ne(m,"module.html"),u.moduleHtml,"utf-8"),un(Ne(m,"module.css"),u.moduleCss,"utf-8"),u.moduleJs&&un(Ne(m,"module.js"),u.moduleJs,"utf-8")}if(s.sharedCss){let u=Ne(e,"css");ui(u,{recursive:!0}),un(Ne(u,`${t}-theme.css`),s.sharedCss,"utf-8")}if(s.sharedJs){let u=Ne(e,"js");ui(u,{recursive:!0}),un(Ne(u,`${t}-animations.js`),s.sharedJs,"utf-8")}}function tm(e){p(e,200,{starters:Hu()})}function nm(e,t){W(e,n=>{try{if(Kt()){p(t,409,{error:"Cannot switch projects while AI is generating.",generating:!0});return}let{name:s}=JSON.parse(n);if(!s||typeof s!="string"){p(t,400,{error:"Theme name is required"});return}let o=s.replace(/^\/+|\/+$/g,"");if(!o){p(t,400,{error:"Theme name is required"});return}let i=Le(),r=R(),a=o.includes("/")||o.includes("@")?o.replace(/[@/]/g,"_").replace(/_+/g,"_").replace(/^_|_$/g,""):o,l=Ne(ut,a);Re(ut),r.hubspotUploadMode==="cli"||!i?(async()=>{Xu("hs",["cms","fetch",o,l],{encoding:"utf-8",stdio:"pipe",...Zu});let c=await qu(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)})}):rs(i,o,l).then(async()=>{let c=await qu(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 qu(e,t){Rn(e,t,{isImported:!0}),Uo(e),L();let n=C(),s={attempted:[],extracted:[],skipped:[],errors:[]};return n&&(s=await Vu(n),L()),{moduleCount:n?.modules.length||0,brandEnrichment:s}}function sm(e,t){W(e,n=>{try{if(Kt()){p(t,409,{error:"Cannot switch projects while AI is generating.",generating:!0});return}let{path:s}=JSON.parse(n);if(!s||typeof s!="string"){p(t,400,{error:"Theme path is required"});return}let o=s;if(Vn(o)||(o=Ne(ut,s)),!Vn(o)){p(t,400,{error:`Theme folder not found: ${s}`});return}let i=Hb(o);Rn(o,i),Uo(o),L(),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 om(e,t){W(e,n=>{try{if(Kt()){p(t,409,{error:"Cannot switch projects while AI is generating.",generating:!0});return}let{sessionId:s}=JSON.parse(n);if(!s||typeof s!="string"){p(t,400,{error:"Session ID is required"});return}let o=Do(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 im(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 rm(e){let t=Le();if(!t){p(e,200,{themes:[],error:"No HubSpot account connected"});return}(async()=>{let n=await ll(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 ro(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=pi(),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 Zu,ut,mi,Gb,gi=N(()=>{"use strict";y();Xe();ee();is();uo();en();Ce();Ut();Wn();Qt();ee();oe();Uu();vs();zu();Zu=process.platform==="win32"?{shell:!0}:{},ut=Ne(Ub(),"vibespot-themes"),mi=null,Gb=5e3});import{existsSync as Kb,readFileSync as Vb,appendFileSync as zb}from"fs";import{join as am}from"path";import{homedir as lm}from"os";function Xb(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 ba(e,t={},n=pm){let s=new AbortController,o=setTimeout(()=>s.abort(),n);try{return await fetch(e,{...t,signal:s.signal})}finally{clearTimeout(o)}}async function Zb(e){let t=await ba("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 Qb(e){let t=await ba("https://api.openai.com/v1/models",{headers:{Authorization:`Bearer ${e}`}});return t.ok?(await t.json()).data.map(s=>s.id):[]}function dm(e,t){return e.filter(n=>t.test(n)).sort((n,s)=>n.localeCompare(s)).map(n=>({id:n,label:Xb(n)}))}async function eS(e){let t=await ba(`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 tS(e=!1){if(!e&&Date.now()-zn.ts<Yb&&Object.keys(zn.data).length>0)return zn.data;let t=R(),n={...ya},s=[],o=Fe("anthropic-api",t);o&&s.push(Zb(o).then(c=>{c.length&&(n["anthropic-api"]=c,n["claude-oauth"]=c)}).catch(()=>{}));let i=Fe("openai-api",t);i&&s.push(Qb(i).then(c=>{if(!c.length)return;let d=dm(c,mm);d.length&&(n["openai-api"]=d);let u=dm(c,qb);u.length&&(n["codex-cli"]=u)}).catch(()=>{}));let r=Fe("gemini-api",t);r&&s.push(eS(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,pm+500))]);let l=t.langdockProvider||"anthropic";return n["langdock-api"]=cm[l]||cm.anthropic,a&&(zn.data=n,zn.ts=Date.now()),n}function gm(e){let t=tl(),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:yn(),environment:t,config:s,models:ya,sessionCount:On().length,localThemeCount:pi().length})}function fm(e,t){let n=/[?&]refresh=1\b/.test(e.url||"");tS(n).then(s=>p(t,200,{models:s})).catch(()=>p(t,200,{models:ya}))}function hm(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=um[o];if(!i&&Date.now()-r.ts<nS&&Object.keys(r.data).length>0){p(t,200,{...r.data,group:o,cached:!0});return}let a;if(o==="ai"){let l=nl();a={tools:{claudeCode:l.claudeCode,geminiCli:l.geminiCli,codexCli:l.codexCli,claudeOAuth:l.claudeOAuth},availableEngines:l.availableEngines}}else if(o==="platform")a={tools:sl()};else{let l=so();a={tools:l.tools,availableEngines:l.availableEngines}}um[o]={data:a,ts:Date.now()},p(t,200,{...a,group:o,cached:!1})}function ym(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 bm(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 Sm(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=dn(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 vm(e,t){W(e,n=>{try{let s=JSON.parse(n||"{}"),o=R(),i=o.hubspotUploadMode||"api";if(s.personalAccessKey)if(i==="api"){io(s.personalAccessKey).then(r=>{qn(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(!ft().found){p(t,400,{error:"HubSpot CLI not installed",needsInstall:!0});return}let a=Os("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(!ft().found){p(t,400,{error:"HubSpot CLI not installed",needsInstall:!0});return}let a=ht();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 xm(e,t){W(e,n=>{try{let s=JSON.parse(n||"{}");if(!eo().found){p(t,400,{error:"GitHub CLI not installed",needsInstall:!0});return}let i=to();if(i.authenticated&&!s.force){p(t,200,{ok:!0,alreadyAuthenticated:!0,username:i.username});return}if(s.token){let a=Os("gh",["auth","login","--with-token"],"Authenticating with GitHub",{timeout:3e4,stdin:s.token});p(t,200,{ok:!0,jobId:a});return}let r=dn("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 wm(e,t){W(e,n=>{try{let{portalId:s,action:o}=JSON.parse(n);if((R().hubspotUploadMode||"api")==="api"){if(o==="remove"&&s){Pi(s),p(t,200,{ok:!0});return}if(s){Ni(s),p(t,200,{ok:!0});return}}else{if(!ft().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=Os("hs",["accounts","remove",l],`Removing HubSpot account ${l}`,{timeout:15e3});p(t,200,{ok:!0,jobId:c});return}if(l){let c=Os("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 Cm(e){let t=dn("gh auth logout --hostname github.com -y","Logging out of GitHub",{timeout:15e3});p(e,200,{ok:!0,jobId:t})}function km(e,t){W(e,n=>{try{let{cli:s,apiKey:o}=JSON.parse(n||"{}");switch(s){case"claude":{let i=dn("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=dn("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")?am(lm(),".zshrc"):am(lm(),".bashrc");try{(Kb(l)?Vb(l,"utf-8"):"").includes("OPENAI_API_KEY")||zb(l,`
|
|
2688
2739
|
# Added by vibeSpot
|
|
2689
2740
|
${a}
|
|
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(`
|
|
2741
|
+
`)}catch{}}}p(t,200,{ok:!0,message:"API key saved"})}else{let i=dn("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 Tm(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 Am(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}Ri(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 _m(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]||"",zn.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 $m(e,t){let n=e.replace("/api/settings/job/","");if(!n){p(t,400,{error:"Job ID required"});return}let s=ni(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 zn,Yb,ya,cm,mm,qb,pm,nS,um,Em=N(()=>{"use strict";y();Xe();ee();Ce();gi();Qt();en();oe();oi();zn={data:{},ts:0},Yb=600*1e3,ya={"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"}]},cm={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"}]},mm=/^(gpt-[45](\.\d+)?(-[a-z0-9-]+)?|o[1-4](-(mini|pro|nano)(-high)?)?|codex(-[a-z0-9-]+)?)$/,qb=mm;pm=2500;nS=60*1e3,um={ai:{data:{},ts:0},platform:{data:{},ts:0},all:{data:{},ts:0}}});function Mm(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}Oi(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 Im(e,t){let n=Ze(),s=Xt();p(t,200,{authenticated:n,expiresAt:s?.expiresAt||null})}function Pm(e,t){try{qs(),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 Nm=N(()=>{"use strict";y();Xe();ee();_t()});import{existsSync as sS,rmSync as oS}from"fs";import{join as iS}from"path";function Rm(e,t,n){if(e==="GET"){let s=C(),o=On().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);$c(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 Om(e,t){W(e,n=>{try{let{sessionId:s}=JSON.parse(n),o=Do(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 Fm(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=iS(ut,s);if(!sS(o)){p(t,404,{error:"Theme not found on disk"});return}oS(o,{recursive:!0,force:!0}),p(t,200,{ok:!0})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function Dm(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=Ec(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 jm(e,t){W(e,n=>{try{let{sessionId:s}=JSON.parse(n);if(!s){p(t,400,{error:"sessionId is required"});return}let o=Mc(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 Lm=N(()=>{"use strict";y();Xe();Ce();gi()});import{existsSync as fi,readFileSync as rS,readdirSync as aS,rmSync as Gm}from"fs";import{join as Oe,basename as lS,relative as cS,sep as dS}from"path";import uS from"jszip";function Wm(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 Km(e,t=[]){for(let n of aS(e,{withFileTypes:!0}))if(n.isDirectory()){if(mS.has(n.name))continue;Km(Oe(e,n.name),t)}else n.isFile()&&t.push(Oe(e,n.name));return t}async function Vm(e){let t=C();if(!t){p(e,404,{error:"No active session"});return}let n=t.themePath;if(!fi(n)){p(e,404,{error:"Theme directory not found"});return}let s=t.themeName||"theme",o=lS(n);try{let i=new uS;for(let a of Km(n)){let l=Oe(o,cS(n,a)).split(dS).join("/");i.file(l,rS(a))}let r=await i.generateAsync({type:"nodebuffer",compression:"DEFLATE",compressionOptions:{level:6}});e.writeHead(200,{"Content-Type":"application/zip","Content-Disposition":`attachment; filename="${s}.zip"`,"Content-Length":r.length}),e.end(r)}catch(i){E.error("download-zip","Failed to create zip archive",i),p(e,500,{error:"Failed to create zip archive"})}}function zm(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&&An(s.themePath,s.themeName),L(),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(!kc(i,!!r)){p(n,404,{error:"Template not found"});return}L(),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){W(e,n=>{try{let{templateId:s}=JSON.parse(n);if(!s){p(t,400,{error:"templateId is required"});return}if(!ms(s)){p(t,404,{error:"Template not found"});return}L();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 qm(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(!Cc(s,o.trim())){p(t,404,{error:"Template not found"});return}L(),p(t,200,{ok:!0,newLabel:o.trim()})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function Xm(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(!wc(s)){p(t,400,{error:"Reorder rejected (length mismatch or no session)"});return}L(),p(t,200,{ok:!0})}catch(s){p(t,500,{error:s instanceof Error?s.message:String(s)})}})}function Zm(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=xc(s,o);if(!i){p(t,404,{error:"Template not found"});return}L(),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 Qm(e){let t=Nt();p(e,200,{modules:t.map(n=>({moduleName:n.module.moduleName,usedIn:n.usedIn,fieldsJson:n.module.fieldsJson}))})}function ep(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()),L(),p(n,200,{ok:!0})}catch(i){p(n,500,{error:i instanceof Error?i.message:String(i)})}})}function tp(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(),L(),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=Oe(s.themePath,".vibespot");Re(c),B(Oe(c,l),r);let d=null;a==="styleguide"&&(d=Sa(s,r)),L(),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=Oe(s.themePath,".vibespot",a);fi(l)&&Gm(l),L(),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 sp(e,t){p(t,200,np)}function gS(e){let t=[],n=[],s=e.split(`
|
|
2742
|
+
`),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(pS);if(l)for(let c of l)t.includes(c.toLowerCase())||t.push(c.toLowerCase())}if(i){let l=Jm.exec(a);if(Jm.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 Sa(e,t){let{colors:n,fonts:s}=gS(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=np.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=Oe(e.themePath,".vibespot");return Re(i),B(Oe(i,"brand-kit.json"),JSON.stringify(o,null,2)),o}function op(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"&&fS.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=Oe(s.themePath,".vibespot");Re(a),B(Oe(a,"brand-kit.json"),JSON.stringify(r,null,2)),L(),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=Oe(s.themePath,".vibespot","brand-kit.json");fi(o)&&Gm(o),L(),p(n,200,{ok:!0});return}p(n,405,{error:"Method not allowed"})}function Bm(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=Oe(e.themePath,".vibespot");Re(o),B(Oe(o,s),n)}function Hm(e){return e==="themeContext"?"extract-theme-context":`extract-${e}`}async function Um(e,t,n){if(t==="styleguide"){let{extractDesignContext:m}=await Promise.resolve().then(()=>(js(),Ds));return m(n||e.themePath)}let{resolveAgenticEngine:s}=await Promise.resolve().then(()=>(Wn(),ra)),{loadConfig:o}=await Promise.resolve().then(()=>(ee(),Ya)),i=o(),{engine:r,apiKey:a,model:l}=s(i),{buildPreviewHtml:c}=await Promise.resolve().then(()=>(Ss(),Go)),d=c();if(!d||d.length<50)return null;if(t==="brandvoice"){let{extractBrandvoice:m}=await Promise.resolve().then(()=>(fa(),ga));return m(d,r,a,l)}let{extractThemeContext:u}=await Promise.resolve().then(()=>(di(),ci));return u(d,e.brandAssets?.themeContext,r,a,l)}function ip(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(Hm(g),()=>Um(n,g,r))))),u={};for(let g=0;g<c.length;g++){let h=d[g],f=h.status==="fulfilled"?h.value:null;f&&Bm(n,c[g],f),u[c[g]]=f}let m=null;u.styleguide&&(m=Sa(n,u.styleguide)),L(),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(Hm(i),()=>Um(n,i,r)));if(!a){p(t,200,{ok:!1,type:i,error:"No content to extract from"});return}Bm(n,i,a);let l=null;i==="styleguide"&&(l=Sa(n,a)),L(),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 rp(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=Oe(h(),"vibespot-themes",".references",g);Re(f);let{fetchTheme:b}=await Promise.resolve().then(()=>(uo(),hl));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(!fi(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(()=>(js(),Ds)),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=Oe(n.themePath,".vibespot");Re(d),B(Oe(d,"styleguide.md"),c),L(),p(t,200,{ok:!0,styleguide:c,source:a})}catch(o){p(t,500,{error:o instanceof Error?o.message:String(o)})}})()})}var mS,np,pS,Jm,fS,ap=N(()=>{"use strict";y();Xe();le();Be();ee();is();Ce();oe();mS=new Set([".git",".vibespot","node_modules"]);np=[{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"}];pS=/#[0-9a-fA-F]{6}\b/g,Jm=/font[- ]?famil(?:y|ies)\s*[:=]\s*([^\n]+)/gi;fS=/^#[0-9a-fA-F]{6}$/});import{join as hS}from"path";function lp(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 cp(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?fc(o.moduleName):hc(o.moduleName),L(),p(n,200,{ok:!0})});return}p(n,405,{error:"Method not allowed"})}function dp(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(),L(),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(),L(),Te(),p(t,200,{ok:!0})}catch(o){p(t,400,{error:String(o)})}})}function up(e,t){qe(e,t,n=>{Array.isArray(n.order)?(Ht(n.order),L(),p(t,200,{ok:!0})):p(t,400,{error:"order must be an array"})})}async function mp(e){let t=C();if(!t){p(e,404,{error:"No active session"});return}try{Te();let n=To(t.themePath),s=si(`hs cms upload "${t.themePath}" "${t.themeName}"`,"Uploading to HubSpot",{cwd:hS(t.themePath,".."),timeout:18e4});p(e,200,{ok:!0,jobId:s,fixes:n})}catch(n){p(e,500,{error:String(n)})}}function pp(e,t){W(e,n=>{try{let{moduleName:s,fieldPath:o,value:i}=JSON.parse(n);yc(s,o,i),L(),p(t,200,{ok:!0})}catch(s){p(t,400,{error:String(s)})}})}function gp(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=pl(s),i=o.components.map(a=>`- ${a.name}: ${a.description}`).join(`
|
|
2692
2743
|
`),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
2744
|
|
|
2694
2745
|
Source analysis found ${o.components.length} components:
|
|
@@ -2698,19 +2749,19 @@ Design system: ${o.hasTailwind?"Tailwind CSS":"Custom CSS"}, ${o.cssVarCount} CS
|
|
|
2698
2749
|
Fonts: ${o.fonts.length>0?o.fonts.join(", "):"System fonts"}
|
|
2699
2750
|
Interactions: ${o.interactions.join(", ")}
|
|
2700
2751
|
|
|
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)}
|
|
2752
|
+
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 fp(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?lc(n.themePath,o,50):ac(n.themePath,50);p(t,200,{available:!0,commits:i,filtered:!!o})}function hp(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=dc(s.themePath,i,o,a);if(!l.success){p(t,500,{error:l.error||"Rollback failed"});return}Bc()}else{let r=cc(s.themePath,o);if(!r.success){p(t,500,{error:r.error||"Rollback failed"});return}Jc()}L(),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 yp=N(()=>{"use strict";y();Xe();Ce();Ao();oi();co();In()});import{writeFileSync as yS,mkdirSync as Sp}from"fs";import{join as hi}from"path";import{randomUUID as bS}from"crypto";function vp(e){let t=e.match(SS);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 bi(e,t){let n=await fetch(`${vS}${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 xa(e,t){for(let n=0;;n++)try{return await e()}catch(s){if(!(s.status===429)||n>=bp.length)throw s;let r=bp[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 mn(e,t,n=0){if(t(e,n),e.children)for(let s of e.children)mn(s,t,n+1)}function xp(e,t){if(e.id===t)return e;if(e.children)for(let n of e.children){let s=xp(n,t);if(s)return s}return null}function xS(e,t){if(t){let s=xp(e,t);if(!s)return[];if(s.type==="FRAME"||s.type==="COMPONENT"||s.type==="COMPONENT_SET"){let o=(s.children||[]).filter(i=>va.has(i.type));return o.length>0?o:[s]}return s.children?s.children.filter(o=>va.has(o.type)):[]}let n=e.children?.[0];return n?.children?n.children.filter(s=>va.has(s.type)):[]}function yi(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 wS(e){let t=new Map;for(let n of e)mn(n,s=>{if(s.fills){for(let o of s.fills)if(o.type==="SOLID"&&o.color){let i=yi(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=yi(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 CS(e){let t=new Map;for(let n of e)mn(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 kS(e){let t=[],n=new Set;for(let s of e)mn(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 TS(e){let t=[],n=new Set;for(let s of e)mn(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 mn(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 _S(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 $S(e){if(e.fills){for(let t of e.fills)if(t.type==="SOLID"&&t.color)return yi(t.color)}if(e.backgroundColor)return yi(e.backgroundColor)}function ES(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(_S),backgroundColor:$S(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 MS(e){let t=[];for(let n of e)mn(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 wp(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());yS(t,s)}async function IS(e,t,n,s,o){if(t.length===0)return new Map;Sp(s,{recursive:!0});let r=t.map(c=>c.id).join(",");o&&o("Exporting frame screenshots...");let a=await xa(()=>bi(`/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=hi(s,`frame-${u}.png`);try{await wp(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[];Sp(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 xa(()=>bi(`/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()}-${bS().slice(0,6)}.png`,f=hi(s,h);try{await wp(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 Cp(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 xa(()=>bi(i,n),o);E.info("figma",`Fetched file: ${r.name}`);let a=xS(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:wS(a),typography:CS(a),spacing:kS(a),effects:TS(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=ES(a),d=hi(s,".vibespot","figma-frames"),u=await IS(e,a,n,d,o),m=c.map(b=>({...b,frameImagePath:u.get(b.nodeId)||""}));o&&o("Extracting image assets...");let g=MS(a),h=hi(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 kp(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 Tp(e){return await bi("/v1/me",e)}var SS,vS,bp,va,Ap=N(()=>{"use strict";y();le();SS=/figma\.com\/(?:design|file|proto)\/([a-zA-Z0-9]+)(?:\/([^?]*))?/;vS="https://api.figma.com",bp=[10,20,40,60,120];va=new Set(["FRAME","COMPONENT","COMPONENT_SET","SECTION"])});var Pp={};Ge(Pp,{getCachedExtraction:()=>Ip,handleFigmaExtractRoute:()=>Ca,handleFigmaGenerateRoute:()=>ka,handleFigmaTestTokenRoute:()=>wa});import{randomUUID as _p}from"crypto";import{existsSync as $p,mkdirSync as Ep,writeFileSync as NS,copyFileSync as RS}from"fs";import{join as Si,basename as OS}from"path";function Mp(){let e=Date.now();for(let[t,n]of Ls)n.expires<e&&Ls.delete(t)}function Ip(e){Mp();let t=Ls.get(e);return t?(Ls.delete(e),t.extraction):null}function wa(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 Tp(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 Ca(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=vp(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-${_p().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
2753
|
|
|
2703
|
-
`)};try{let c=await
|
|
2704
|
-
`)}function
|
|
2754
|
+
`)};try{let c=await Cp(i.fileKey,i.nodeId,o,a,m=>l({type:"progress",message:m})),d=_p();Mp(),Ls.set(d,{extraction:c,expires:Date.now()+FS});let u=kp(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 DS(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(`
|
|
2755
|
+
`)}function ka(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=Ip(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
2756
|
|
|
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(x(c))try{let d=JSON.parse(P(c));if(Array.isArray(d)){let u=
|
|
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}
|
|
2757
|
+
`)};try{l({type:"progress",message:"Generating styleguide from design tokens..."});let c=DS(r),d=Si(a.themePath,".vibespot");if($p(d)||Ep(d,{recursive:!0}),NS(Si(d,"styleguide.md"),c),a.brandAssets||(a.brandAssets={}),a.brandAssets.styleguide=c,L(),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(L(),i&&r.assets.length>0){let f=Si(a.themePath,"assets");Ep(f,{recursive:!0});let b=0;for(let S of r.assets)if($p(S.localPath)){let v=Si(f,OS(S.localPath));try{RS(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 Rs(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});cn(g,{steps:u,modules:m,stats:g.stats}),Te(),sn(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 Ls,FS,Ta=N(()=>{"use strict";y();Xe();ee();le();Ap();Ce();us();fr();In();Wn();Ut();Ls=new Map,FS=1800*1e3});import{readdirSync as $a,statSync as jS}from"fs";import{join as q,relative as LS}from"path";function Yn(e){let t=q(e,Ft);if(!x(t))return null;try{return JSON.parse(P(t))}catch{return null}}function xi(e,t){let n=q(e,Ft);B(n,JSON.stringify(t,null,2)+`
|
|
2758
|
+
`)}function Js(e){let t=[];if(!x(e))return t.push({severity:"error",rule:"theme.path.missing",message:`Theme directory not found: ${e}`}),Aa(e,t,null);let n=_a(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."}),Aa(e,t,Yn(e));HS(e,n,t),US(e,n,t),GS(e,t),KS(e,t),VS(e,t),zS(e,t);let s=Yn(e);return YS(s,t),Aa(e,t,s)}function Aa(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 HS(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 JS)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 BS)(!(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=Fp(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 US(e,t,n){let s=t.screenshot_path;if(typeof s!="string"||s.length===0)return;let o=Fp(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 GS(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=$a(n)}catch{return}for(let i of o){if(!i.endsWith(".module"))continue;s++;let r=q(n,i);WS(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 WS(e,t,n,s){let o=_a(q(t,"meta.json")),i=mt(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=mt(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=_a(r);Array.isArray(c)?Rp(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:mt(e,l),message:`${n}: module.html is missing`,fix:"Recreate the module so module.html is generated."})}function Rp(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)&&Rp(i.children,t,n,s)}}function KS(e,t){let n=[],s=q(e,"css");vi(s,".css").forEach(i=>{Np(i,n,e)});let o=q(e,"modules");if(x(o))for(let i of Bs(o)){if(!i.endsWith(".module"))continue;let r=q(o,i);["module.css","module.html"].forEach(a=>{let l=q(r,a);x(l)&&Np(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 Np(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:mt(n,e),match:o[0]});let i=s.match(/<link[^>]+href=['"]https?:\/\/[^'"]+['"][^>]*>/i);i&&t.push({file:mt(n,e),match:i[0]});let r=s.match(/<script[^>]+src=['"]https?:\/\/[^'"]+['"][^>]*>/i);r&&t.push({file:mt(n,e),match:r[0]})}function VS(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");vi(o,".css").forEach(a=>s.push(a));let i=q(e,"js");vi(i,".js").forEach(a=>s.push(a));let r=q(e,"modules");if(x(r))for(let a of Bs(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:mt(e,a),message:`${c.message}: ${d[0]}`,fix:"Replace portal-specific URLs with theme-relative paths or HubSpot tokens like get_asset_url."})}}}function zS(e,t){let n=q(e,"modules");if(x(n))for(let s of Bs(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:mt(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:mt(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 YS(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?Yt.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: ${Yt.join(", ")}.`}):t.push({severity:"warning",rule:"marketplace.json.category.missing",file:Ft,message:"marketplace.json has no category",fix:`Pick one of: ${Yt.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 wi(e){let t=[],n=[],s=q(e,"modules");if(x(s))for(let i of Bs(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=Dp(a),B(l,JSON.stringify(d,null,2)+`
|
|
2759
|
+
`),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=Op(d);u>0&&(B(c,JSON.stringify(d,null,2)+`
|
|
2760
|
+
`),t.push(`${i}: filled ${u} missing field label(s)`))}}catch{n.push(`${i}: fields.json could not be parsed`)}}let o=qS(e);for(let i of o)t.push(`${i}: stripped external CDN reference(s)`);return{applied:t,skipped:n}}function qS(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&&(B(c,u),t.push(mt(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&&(B(c,u),t.push(mt(e,c)))}vi(q(e,"css"),".css").forEach(r);let l=q(e,"modules");if(x(l))for(let c of Bs(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 Op(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=Dp(String(s.name)),t++),Array.isArray(s.children)&&(t+=Op(s.children))}return t}function _a(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 Fp(e,t){let n=t.replace(/^\.?\//,"");return q(e,n)}function mt(e,t){return LS(e,t).split("\\").join("/")}function Bs(e){try{return $a(e)}catch{return[]}}function vi(e,t){if(!x(e))return[];try{let n=[];for(let s of $a(e)){let o=q(e,s);jS(o).isFile()&&s.endsWith(t)&&n.push(o)}return n}catch{return[]}}function Dp(e){return e.replace(/[-_]+/g," ").split(" ").filter(Boolean).map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" ")}var Yt,JS,BS,Ft,Ea=N(()=>{"use strict";y();oe();Yt=["Business Services","Education","Events","Health & Wellness","Hospitality","Marketing & SEO","Non-profit","Portfolio","Real Estate","Restaurant & Food","Retail & E-commerce","SaaS & Technology","Travel","Other"],JS=["label","preview_path","screenshot_path","version","documentation_url","license","example_url"],BS=["enable_domain_stylesheets","is_available_for_new_content"],Ft="marketplace.json"});function Ma(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 jp(e,t){let n=Ma(t);if(!n)return;let s=Js(n);p(t,200,{report:s,categories:Yt})}function Lp(e,t){let n=Ma(t);if(!n)return;let s=wi(n),o=Js(n);p(t,200,{fix:s,report:o})}function Jp(e,t,n){let s=Ma(n);if(s){if(e==="GET"){p(n,200,{metadata:Yn(s),categories:Yt});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};xi(s,i),p(n,200,{ok:!0,metadata:i})});return}p(n,405,{error:"Method not allowed"})}}var Bp=N(()=>{"use strict";y();Xe();Ce();Ea()});function XS(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 Hp(e,t){let n=XS(t);if(!n)return;let s=Jo(n);p(t,200,{report:s})}function Up(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=fs(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(),L(),p(t,200,{applied:!0,written:"session.sharedCss",rootBlock:o});return}let i=Bo(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 Gp=N(()=>{"use strict";y();Xe();Ce();Ho()});import{createServer as ZS}from"http";import{readFileSync as Na,existsSync as Hs}from"fs";import{join as jt,extname as Kp}from"path";import{WebSocketServer as QS,WebSocket as ev}from"ws";function Ae(e){ki&&ki.readyState===ev.OPEN&&ki.send(JSON.stringify(e))}function Ci(e){Ti.push(e),Ae(e)}function Dt(){Ti=[]}function Ia(e,t){return n=>{if(n.type==="module_progress"&&n.moduleFiles){let{moduleFiles:s,...o}=n;Ci(o)}else Ci(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),Ci({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}]}),Ci({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 Pa(e){let t=e.cost;if(!t||t.calls===0)return;let n=C();Ae({type:"generation_cost",cost:t,projectTotal:n?.costTotal})}function Ln(){return zp}function Ai(e){let{port:t,uiDir:n}=e;zp=e.contentMode||"page";let s=ZS((i,r)=>tv(i,r,n)),o=new QS({server:s});return o.on("connection",i=>sv(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 tv(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/")){nv(o,s.pathname,e,t);return}if(s.pathname==="/preview"){let i=xr();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=wr(i);t.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),t.end(r||"<!-- module not found -->");return}if(s.pathname.startsWith("/theme-assets/")){ov(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";Wp(i,jt(n,"docs"),e,t);return}Wp(s.pathname,n,e,t)}function nv(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":lp(e,s);break;case"/api/modules":cp(e,n,s);break;case"/api/modules/reorder":up(n,s);break;case"/api/modules/code":dp(n,s);break;case"/api/upload":mp(s);break;case"/api/upload-files":e==="POST"?pd(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/field":pp(n,s);break;case"/api/import":gp(n,s);break;case"/api/setup":Qu(s);break;case"/api/setup/create":em(n,s);break;case"/api/setup/fetch":nm(n,s);break;case"/api/setup/open":sm(n,s);break;case"/api/setup/resume":om(n,s);break;case"/api/setup/apikey":im(n,s);break;case"/api/setup/remote-themes":e==="GET"?rm(s):p(s,405,{error:"Method not allowed"});break;case"/api/starters":e==="GET"?tm(s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/status":e==="GET"?gm(s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/models":e==="GET"?fm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/tools":e==="GET"?hm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/engine":e==="POST"?ym(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/apikey":e==="POST"?bm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/install":e==="POST"?Sm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/hs-auth":e==="POST"?vm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/gh-auth":e==="POST"?xm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/hs-switch":e==="POST"?wm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/gh-logout":e==="POST"?Cm(s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/cli-auth":e==="POST"?km(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/hs-mode":e==="POST"?Tm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/cli-toggle":e==="POST"?Am(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/claude-oauth/save":e==="POST"?Mm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/claude-oauth/status":e==="GET"?Im(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings/claude-oauth/logout":e==="POST"?Pm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/settings":e==="POST"?_m(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/changelog":e==="GET"?p(s,200,{changelog:Ga()}):p(s,405,{error:"Method not allowed"});break;case"/api/themes":Rm(e,n,s);break;case"/api/themes/switch":e==="POST"?Om(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/themes/delete-local":e==="POST"?Fm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/themes/rename":e==="POST"?Dm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/themes/duplicate":e==="POST"?jm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/history":e==="GET"?fp(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/rollback":e==="POST"?hp(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/dashboard":e==="GET"?Wm(s):p(s,405,{error:"Method not allowed"});break;case"/api/templates":zm(e,n,s);break;case"/api/templates/activate":e==="POST"?Ym(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/templates/rename":e==="POST"?qm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/templates/clone":e==="POST"?Zm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/templates/reorder":e==="POST"?Xm(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/module-library":e==="GET"?Qm(s):p(s,405,{error:"Method not allowed"});break;case"/api/brand-assets":tp(e,n,s);break;case"/api/brand-kit":op(e,n,s);break;case"/api/fonts":e==="GET"?sp(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/brand-assets/extract":e==="POST"?ip(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/brand-assets/import-reference":e==="POST"?rp(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/download-zip":e==="GET"?Vm(s):p(s,405,{error:"Method not allowed"});break;case"/api/figma/test-token":e==="POST"?wa(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/figma/extract":e==="POST"?Ca(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/figma/generate":e==="POST"?ka(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/edit":e==="POST"?Mu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/discard":e==="POST"?Iu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/templates":e==="GET"?Pu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/plan/template":e==="POST"?Nu(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/marketplace/check":e==="GET"?jp(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/marketplace/fix":e==="POST"?Lp(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/marketplace/listing":Jp(e,n,s);break;case"/api/inverse/analyze":e==="GET"?Hp(n,s):p(s,405,{error:"Method not allowed"});break;case"/api/inverse/apply-tokens":e==="POST"?Up(n,s):p(s,405,{error:"Method not allowed"});break;default:t.startsWith("/api/settings/job/")&&e==="GET"?$m(t,s):t.match(/^\/api\/templates\/[^/]+\/add-module$/)&&e==="POST"?ep(t,n,s):p(s,404,{error:"Not found"})}}function sv(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(oa()){lt("user",o),L();try{e.send(JSON.stringify({type:"stream_status",content:"Planning..."}));let a="",l=await sa(o,d=>{a+=d,e.send(JSON.stringify({type:"stream",content:d}))},i),c=Ou(l||a);c.plan&&(ti(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),L(),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),L();let r=ia();r.needsPrompt&&e.send(JSON.stringify({type:"agentic_prompt"}));try{if(r.useAgentic){Dt();let l=[],c=[],d=await Qo(o,Ia(l,c),i);cn(d,{steps:l,modules:c,stats:d.stats,cost:d.cost}),Pa(d)}else ta(l=>{Ae({type:"parse_warning",message:l})}),await Ns(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=or(a.themePath,l.id,o,d)}else c=sn(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(()=>(Ta(),Pp)),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(()=>(is(),gl)),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),Rn(S,i),L()}Ae({type:"figma_import_started",fileName:a.fileName}),Dt();let c=[],d=[],u=await Rs(a,i,Ia(c,d));cn(u,{steps:c,modules:d,stats:u.stats,cost:u.cost}),Pa(u),Te(),sn(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}=Gn(i),{buildPreviewHtml:c}=await Promise.resolve().then(()=>(Ss(),Go)),d=c();if(!d||d.length<50)return;let{extractThemeContext:u}=await Promise.resolve().then(()=>(di(),ci)),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");Hs(f)||g(f,{recursive:!0}),h(jt(f,"theme-context.md"),m),L(),e.send(JSON.stringify({type:"brand_asset_extracted",assetType:"themeContext"}))}if(!o.brandAssets?.styleguide)try{let{extractDesignContext:f}=await Promise.resolve().then(()=>(js(),Ds)),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");Hs(S)||g(S,{recursive:!0}),h(jt(S,"styleguide.md"),b),L(),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=To(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 _o(l,o.themePath,o.themeName,{onFileStart:d=>{e.send(JSON.stringify({type:"upload_output",chunk:`Uploading ${d}
|
|
2710
2761
|
`}))},onFileComplete:d=>{e.send(JSON.stringify({type:"upload_output",chunk:` \u2713 ${d}
|
|
2711
2762
|
`}))},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=Lt();e.send(JSON.stringify({type:"upload_complete",output:`Uploaded ${c.uploaded} files`,portalId:d?.portalId||"",dataCenter:d?.dataCenter||"na1",themeName:o.themeName,contentMode:
|
|
2713
|
-
`),errors:d}))}}else{let l=
|
|
2763
|
+
`}))},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:Ln()}))}else{let d=Co(c.errors);e.send(JSON.stringify({type:"upload_failed",output:c.errors.map(u=>`${u.file}: ${u.message}`).join(`
|
|
2764
|
+
`),errors:d}))}}else{let l=si(`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}))};ju(l,c);let d=setInterval(()=>{let u=ni(l);if(!(!u||u.status==="running"))if(clearInterval(d),Lu(l,c),u.status==="completed"){let m=ht(),g=m.portalId?es(m.portalId):"na1";e.send(JSON.stringify({type:"upload_complete",output:u.output,portalId:m.portalId||"",dataCenter:g,themeName:o.themeName,contentMode:Ln()}))}else{let m=ko(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
2765
|
|
|
2715
2766
|
IMPORTANT: Be verbose in your response. For each error:
|
|
2716
2767
|
1. State exactly which file has the problem and what the error is
|
|
@@ -2723,9 +2774,9 @@ CRITICAL: After fixing the reported errors, scan ALL other module files in the t
|
|
|
2723
2774
|
After fixing all errors, summarize the changes you made.
|
|
2724
2775
|
|
|
2725
2776
|
Upload log:
|
|
2726
|
-
${o}`;lt("user",i),
|
|
2777
|
+
${o}`;lt("user",i),L(),e.send(JSON.stringify({type:"upload_fix_started"}));try{await Ns(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=sn(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),L();try{Dt();let a=[],l=[],c=await Qo(r,Ia(a,l));cn(c,{steps:a,modules:l,stats:c.stats,cost:c.cost}),Pa(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=or(d.themePath,u.id,"Approved plan: implementation",g)}else m=sn(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":{aa(),Y({planMode:!1}),e.send(JSON.stringify({type:"plan_discarded"}));break}default:e.send(JSON.stringify({type:"error",message:`Unknown type: ${s.type}`}))}}),ki=e;let t=C();if(t){let n=R(),s={"claude-code":"Claude Code","anthropic-api":"Anthropic API","claude-oauth":"Claude (OAuth)","openai-api":"OpenAI API","gemini-cli":"Gemini CLI","gemini-api":"Gemini API","codex-cli":"Codex CLI",api:"Anthropic API"},o=Kt(),i=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&&Ti.length>0)for(let r of Ti)e.send(JSON.stringify(r))}else e.send(JSON.stringify({type:"needs_setup"}))}function ov(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(!Hs(s)){t.writeHead(404,{"Content-Type":"text/plain"}),t.end("Asset not found");return}let o=Kp(s),i=Vp[o]||"application/octet-stream",r=Na(s);t.writeHead(200,{"Content-Type":i,"Cache-Control":"no-cache"}),t.end(r)}function Wp(e,t,n,s){let i=jt(t,e==="/"?"/index.html":e);if(!Hs(i)){let c=jt(t,"index.html");if(Hs(c)){let d=Na(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=Kp(i),a=Vp[r]||"application/octet-stream",l=r===".html";try{let c=Na(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 Vp,ki,Ti,zp,vs=N(()=>{"use strict";y();Ce();In();Ss();Wn();Ru();Fu();ee();Qt();Ao();oi();nr();Xe();oe();Be();gi();Em();Nm();Lm();ap();yp();Dr();Ta();Bp();Gp();Vp={".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"},ki=null,Ti=[];zp="page"});y();y();import{Command as yv}from"commander";y();y();gt();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${yn()}`)}`),console.log()}y();Qt();_t();qt();ee();en();Qe();gt();async function ao(){await ge("Checking your environment");let e=Zn();e.found||(V("Node.js not found. Install it from https://nodejs.org"),process.exit(1)),no(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 yt(`You need a Personal Access Key to deploy themes.
|
|
2727
2778
|
Create one at: https://app.hubspot.com/l/personal-access-key
|
|
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
|
|
2779
|
+
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 De();w.start("Validating key...");try{let M=await io(v);qn(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=ft();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 De();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=ft(),w.stop(`HubSpot CLI v${b.version} installed`)}let S=ht();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 De();w.start("Waiting for HubSpot authentication..."),Ka("hs init")||(w.stop("Authentication failed"),process.exit(1)),S=ht(),w.stop(`Connected to portal${S.portalName?`: ${S.portalName}`:""} (ID: ${S.portalId})`)}o=S.portalId,i=S.portalName}let r=wn(),a=Cn(),l=kn(),c=Qa(),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 yt(`You need an AI coding assistant to power the conversion.
|
|
2729
2780
|
|
|
2730
2781
|
${I.bold("Option 1:")} Install Claude Code ${I.muted("(recommended)")}
|
|
2731
2782
|
https://claude.ai/code
|
|
@@ -2738,7 +2789,7 @@ ${I.bold("Option 3:")} Install OpenAI Codex
|
|
|
2738
2789
|
|
|
2739
2790
|
${I.bold("Option 4:")} Set an Anthropic API key
|
|
2740
2791
|
export ANTHROPIC_API_KEY=sk-ant-...
|
|
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}}
|
|
2792
|
+
(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}}co();y();qt();oe();Qe();gt();ee();is();uo();import{join as as}from"path";async function mo(){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=as(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=as(s,t);let l=await De();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 rs(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=as(s,t);let l=await De();l.start("Creating theme...");try{os(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=as(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
2793
|
`,i.indexOf("theme-overrides.css"))):i.lastIndexOf("require_css");if(l>0){let c=i.lastIndexOf(`
|
|
2743
2794
|
`,l);i=i.slice(0,c)+`
|
|
2744
2795
|
{% if template_css %}
|
|
@@ -2751,17 +2802,17 @@ ${I.bold("Option 4:")} Set an Anthropic API key
|
|
|
2751
2802
|
{% endif %}`,m=i.indexOf("}}",l)+2+i.slice(i.indexOf("}}",l)+2).indexOf(`
|
|
2752
2803
|
`)+1;i=i.slice(0,i.indexOf(`
|
|
2753
2804
|
`,i.indexOf("}}",l)+2))+u+i.slice(i.indexOf(`
|
|
2754
|
-
`,i.indexOf("}}",l)+2)),r=!0}}if(r){let l=await
|
|
2805
|
+
`,i.indexOf("}}",l)+2)),r=!0}}if(r){let l=await De();l.start("Patching base.html..."),B(o,i),l.stop("base.html patched with template_css/template_js support")}let a=as(n,".hsignore");if(x(a)){let l=P(a);l.includes("docs/")||(B(a,l+`
|
|
2755
2806
|
docs/
|
|
2756
|
-
`),G("Added docs/ to .hsignore"))}else
|
|
2807
|
+
`),G("Added docs/ to .hsignore"))}else B(a,`docs/
|
|
2757
2808
|
*.md
|
|
2758
2809
|
node_modules/
|
|
2759
2810
|
.git
|
|
2760
|
-
`),G("Created .hsignore");return await fe("Theme ready!"),{themePath:n,themeName:t}}y();import{join as nt}from"path";import{readdirSync as
|
|
2811
|
+
`),G("Created .hsignore");return await fe("Theme ready!"),{themePath:n,themeName:t}}y();import{join as nt}from"path";import{readdirSync as ds,rmSync as Nl}from"fs";y();Ke();oe();import{spawn as Dg}from"child_process";import{join as Q,basename as jg}from"path";import{readdirSync as bt,statSync as Tl,writeFileSync as Lg}from"fs";var Jg=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"]),po=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 j=["--print","--max-turns","50","--allowedTools","Read,Glob,Grep,Write,Edit,Bash"];this.model&&j.push("--model",this.model);let J=Dg("claude",j,{cwd:s,stdio:["pipe","pipe","pipe"],env:M,shell:!0});J.stdout.on("data",H=>{m+=H.toString()}),J.stderr.on("data",H=>{g+=H.toString()}),J.on("error",H=>w(new Error(`Claude Code failed to start: ${H.message}`))),J.on("close",H=>{H!==0?w(new Error(`Claude Code exited with code ${H}.
|
|
2761
2812
|
`+(g?`Stderr: ${g.slice(0,500)}
|
|
2762
|
-
`:"")+(m?`Output: ${m.slice(0,500)}`:"No output"))):v()}),
|
|
2813
|
+
`:"")+(m?`Output: ${m.slice(0,500)}`:"No output"))):v()}),J.stdin.on("error",()=>{}),J.stdin.write(u),J.stdin.end(),setTimeout(()=>{J.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
2814
|
... (truncated, full guide follows)`,"","=== CLAUDE CODE STDOUT ===",m||"(empty)","","=== CLAUDE CODE STDERR ===",g||"(empty)",""].join(`
|
|
2764
|
-
`);
|
|
2815
|
+
`);Lg(f,w,"utf-8"),o("status",`Log written to ${jg(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
2816
|
|
|
2766
2817
|
This usually means the model described the conversion instead of using Write tool to create files.
|
|
2767
2818
|
|
|
@@ -2823,13 +2874,13 @@ HUBSPOT CMS RULES:
|
|
|
2823
2874
|
${Je()}
|
|
2824
2875
|
|
|
2825
2876
|
CONVERSION GUIDE:
|
|
2826
|
-
${s}`}scanGeneratedFiles(t){let n={sharedCss:"",sharedJs:"",template:"",modules:[]},s=Q(t,"css");if(x(s)){for(let a of
|
|
2877
|
+
${s}`}scanGeneratedFiles(t){let n={sharedCss:"",sharedJs:"",template:"",modules:[]},s=Q(t,"css");if(x(s)){for(let a of bt(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 bt(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 bt(i))if(a.startsWith("lp-")&&a.endsWith(".html")){n.template=P(Q(i,a));break}if(!n.template){for(let a of bt(i))if(a.endsWith(".html")&&!Jg.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 bt(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 bt(r)){if(!a.endsWith(".module"))continue;let l=Q(r,a);if(!Tl(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(bt(n).filter(s=>s.endsWith(".module"))):new Set}listDir(t){return x(t)?new Set(bt(t)):new Set}detectExpectedModules(t,n){let s=Q(t,"templates");if(!x(s))return 0;for(let o of bt(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 bt(t)){let o=Q(t,s);try{Tl(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();tn();import rf from"@anthropic-ai/sdk";import{join as ce,basename as af}from"path";import{readdirSync as Pl}from"fs";var yo=class{client;model="claude-sonnet-4-6";constructor(t){this.client=new rf({apiKey:t||process.env.ANTHROPIC_API_KEY})}async convert(t){let{sourceDir:n,themePath:s,conversionGuide:o,onProgress:i}=t,r=vl(o),a=af(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,wl(c,d,l)),m=ce(s,"css",`${l}-theme.css`);B(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,Cl(g,h,l)),b=ce(s,"js",`${l}-animations.js`);B(b,f),i("js-done",`Created js/${l}-animations.js`),i("modules","Building modules...");let S=this.findComponents(n),v=[];for(let J=0;J<S.length;J++){let H=S[J],K=H.name.replace(/Section$/,"").replace(/([A-Z])/g," $1").trim();i("module",`Building ${K}.module (${J+1}/${S.length})...`);let X=P(H.path),O=await this.complete(r,xl(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($),B(ce($,"fields.json"),T.fieldsJson),B(ce($,"meta.json"),T.metaJson),B(ce($,"module.html"),T.moduleHtml),B(ce($,"module.css"),T.moduleCss),T.moduleJs&&B(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(J=>J.moduleName),M=await this.complete(r,kl(w,a,l)),j=ce(s,"templates",`lp-${l}.html`);return B(j,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 St({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 Pl(n).filter(s=>s.endsWith(".ts")||s.endsWith(".tsx")).map(s=>`// ${s}
|
|
2827
2878
|
${P(ce(n,s))}`).join(`
|
|
2828
2879
|
|
|
2829
2880
|
`)}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
2881
|
${i}`)}return s.join(`
|
|
2831
2882
|
|
|
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
|
|
2883
|
+
`)}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 Pl(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 lf}from"child_process";import{join as Ve}from"path";import{readdirSync as bo,statSync as cf}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 Gemini CLI (this may take a few minutes)..."),await new Promise((a,l)=>{let c=lf("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
2884
|
|
|
2834
2885
|
INSTRUCTIONS:
|
|
2835
2886
|
1. Analyze all .tsx/.jsx components in the React source
|
|
@@ -2844,7 +2895,7 @@ CONVERSION GUIDE:
|
|
|
2844
2895
|
${s}
|
|
2845
2896
|
|
|
2846
2897
|
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=Ve(t,"css");if(x(s)){for(let a of
|
|
2898
|
+
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 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(Ve(s,a));break}}let o=Ve(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(Ve(o,a));break}}let i=Ve(t,"templates");if(x(i)){for(let a of bo(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 bo(r)){if(!a.endsWith(".module"))continue;let l=Ve(r,a);if(!cf(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 df}from"child_process";import{join as ze}from"path";import{readdirSync as vo,statSync as uf}from"fs";var xo=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=df("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
2899
|
|
|
2849
2900
|
INSTRUCTIONS:
|
|
2850
2901
|
1. Analyze all .tsx/.jsx components in the React source
|
|
@@ -2859,15 +2910,15 @@ CONVERSION GUIDE:
|
|
|
2859
2910
|
${s}
|
|
2860
2911
|
|
|
2861
2912
|
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=ze(t,"css");if(x(s)){for(let a of
|
|
2863
|
-
HubSpot-native modules. This takes 2-5 minutes.`,"AI Conversion");let t=
|
|
2864
|
-
${d}/${l.length} checks passed`),await
|
|
2913
|
+
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 vo(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 vo(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 vo(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 vo(r)){if(!a.endsWith(".module"))continue;let l=ze(r,a);if(!uf(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 mf(e,t){switch(e){case"claude-code":return new po(t);case"gemini-cli":return new So;case"codex-cli":return new xo;case"api":return new yo}}async function wo(e){await ge("Converting React to HubSpot Modules"),await yt(`AI will now analyze your React code and create
|
|
2914
|
+
HubSpot-native modules. This takes 2-5 minutes.`,"AI Conversion");let t=mf(e.aiEngine,e.model),n=ye(),s=await De();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=pf(e.themePath);for(let h of a)G(`Auto-fixed: ${h}`);let l=gf(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(`
|
|
2915
|
+
${d}/${l.length} checks passed`),await yt(c.join(`
|
|
2865
2916
|
`),"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
2917
|
`+u.map(f=>` - ${f.label}`).join(`
|
|
2867
2918
|
`)),!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
2919
|
`+m.map(h=>` - ${h.label}`).join(`
|
|
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}`):
|
|
2870
|
-
`,l=!0)}catch{t.push(`${r}: fields.json has invalid JSON \u2014 manual fix needed`)}l&&
|
|
2920
|
+
`));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}`):Nl(g)),await fe("Files ready for upload!"),i}function pf(e){let t=[];ff(e),hf(e);let n=nt(e,"modules");if(x(n))for(let o of ds(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;Rl(d)&&(u=!0,t.push(`${r}: fixed choice field format`)),Ol(d)&&(u=!0,t.push(`${r}: fixed link field default value`)),u&&(a=JSON.stringify(d,null,2)+`
|
|
2921
|
+
`,l=!0)}catch{t.push(`${r}: fields.json has invalid JSON \u2014 manual fix needed`)}l&&B(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"),B(c,d),t.push(`${r}: now() \u2192 local_dt`))}}let s=nt(e,"templates");if(x(s))for(let o of ds(s)){if(!o.endsWith(".html"))continue;let i=nt(s,o),r=P(i);(r.includes("hubdb_table")||r.includes("hubdb_table_rows"))&&(Nl(i),t.push(`Removed ${o} (HubDB requires CMS Hub Pro/Enterprise)`))}return t}function Rl(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)&&Rl(s.children)&&(t=!0)}return t}function Ol(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)&&Ol(s.children)&&(t=!0)}return t}function gf(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 ds(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 ff(e){let t=nt(e,"templates");if(x(t))for(let n of ds(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
2922
|
templateType: page`),r||(c+=`
|
|
2872
2923
|
isAvailableForNewContent: true`),/label\s*:/i.test(c)||(c+=`
|
|
2873
2924
|
label: ${a}`),o=c+o.slice(l)}else o=`<!--
|
|
@@ -2875,11 +2926,11 @@ ${d}/${l.length} checks passed`),await ht(c.join(`
|
|
|
2875
2926
|
isAvailableForNewContent: true
|
|
2876
2927
|
label: ${a}
|
|
2877
2928
|
-->
|
|
2878
|
-
`+o;
|
|
2879
|
-
`)}catch{}}}y();
|
|
2880
|
-
`);c=
|
|
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?
|
|
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
|
|
2929
|
+
`+o;B(s,o),G(`Template "${n}" \u2014 annotations verified`)}}function hf(e){let t=nt(e,"modules");if(x(t))for(let n of ds(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&&B(s,JSON.stringify(o,null,2)+`
|
|
2930
|
+
`)}catch{}}}y();qt();Qe();Ao();ee();nr();import{join as zl,basename as Af}from"path";function _f(e){return(e.match(/^Uploaded file /gm)||[]).length}async function Mn(e){await ge("Uploading to HubSpot");let t=Af(e)||e,n=R(),s=Le(),o=n.hubspotUploadMode!=="cli"&&!!s,i=await De(),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 _o(s,e,t,{onFileComplete:()=>{c++}});d=m.success,d?c=m.uploaded:l=Co(m.errors)}else{let m=ie(`hs cms upload "${e}" "${t}"`,{cwd:zl(e,"..")}),g=[m.stdout,m.stderr].filter(Boolean).join(`
|
|
2931
|
+
`);c=_f(g),d=m.success,d||(l=ko(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.
|
|
2932
|
+
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?Fl(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.
|
|
2933
|
+
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 Bi(s,`${t}/modules`)}catch{}else ie(`hs cms delete "${t}/modules"`,{cwd:zl(e,"..")});i.stop("Cleaned up modules, retrying...")}}}return V("Upload failed after multiple attempts."),!1}y();Qe();gt();Qt();oe();import{execFileSync as sr}from"child_process";import{rmSync as $f}from"fs";import{basename as Yl}from"path";async function ql(e){let{portalId:t,sourceDir:n,themePath:s,wasCloned:o}=e;await ge("You're all set!");let r=es(t)==="eu1"?"app-eu1.hubspot.com":"app.hubspot.com";if(await yt(`Your React page has been converted and uploaded to HubSpot.
|
|
2883
2934
|
The theme and modules are now in your account, but you still
|
|
2884
2935
|
need to ${I.bold("create a new landing page")} that uses them.
|
|
2885
2936
|
|
|
@@ -2891,15 +2942,15 @@ Next steps:
|
|
|
2891
2942
|
${I.bold("4.")} Your converted modules will appear \u2014 drag them onto the page
|
|
2892
2943
|
${I.bold("5.")} Click each section to edit text, images, and colors
|
|
2893
2944
|
${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"?
|
|
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}Ee(),await ge("Marketplace check");let s=`${n.errorCount} error${
|
|
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`)}`)}}
|
|
2901
|
-
`));let n=
|
|
2902
|
-
`));try{process.platform==="darwin"?
|
|
2903
|
-
Saving session...`)),
|
|
2904
|
-
`)),r(),setTimeout(()=>process.exit(0),500)})})}catch(s){console.error(
|
|
2945
|
+
${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"?sr("open",[c],{stdio:"ignore"}):d==="win32"?sr("cmd",["/c","start","",c],{stdio:"ignore"}):sr("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 (${Yl(n)})`}),x(s)&&l.push({path:s,label:`Theme directory (${Yl(s)})`}),l.length>0&&await Me({message:"Clean up local working directories?"}))for(let d of l)try{$f(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 Xl(){Ee();let e=await ao(),t=await lo();Y({lastSourcePath:t.sourceDir});let n=await mo();Y({lastThemePath:n.themePath}),await wo({aiEngine:e.aiEngine,model:e.model,sourceDir:t.sourceDir,themePath:n.themePath}),await Mn(n.themePath),await ql({portalId:e.portalId,sourceDir:t.sourceDir,themePath:n.themePath,wasCloned:t.wasCloned})}y();async function Zl(){Ee(),await ao()}y();co();ee();Qe();async function Ql(){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 lo(),n=await mo();await wo({aiEngine:e.aiEngine,sourceDir:t.sourceDir,themePath:n.themePath})}y();ee();Qe();async function ec(){Ee();let e=R();if(e.lastThemePath)if(await Me({message:`Upload from ${e.lastThemePath}?`}))await Mn(e.lastThemePath);else{let n=await Se({message:"Path to your HubSpot theme directory:",placeholder:"./my-theme"});await Mn(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 Mn(t)}}y();Qt();ee();Qe();gt();async function tc(){Ee(),await ge("Environment Diagnostics");let e=0,t=Zn();t.found?no(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=ft();if(!s.found)se("HubSpot CLI \u2014 not installed (only needed for deployment)"),D(" Install: npm install -g @hubspot/cli");else if(!el(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=ht();m.authenticated?G(`HubSpot portal${m.portalName?`: ${m.portalName}`:""} (ID: ${m.portalId})`):(se("HubSpot \u2014 not authenticated"),D(" Run: hs init"))}let o=wn();o.found?G(`Claude Code ${o.version} at ${o.path}`):D(I.muted("Claude Code \u2014 not installed"));let i=Cn();i.found?G(`Gemini CLI ${i.version} at ${i.path}`):D(I.muted("Gemini CLI \u2014 not installed"));let r=kn();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();vs();Ce();import{dirname as iv,join as _i}from"path";import{existsSync as rv}from"fs";import{fileURLToPath as av}from"url";import{execFileSync as Ra}from"child_process";import $i from"chalk";var Yp=iv(av(import.meta.url)),lv=4200;async function qp(){let e=$i.hex("#e8613a"),t=$i.dim;console.log(""),console.log(e(" v vibeSpot")),console.log(t(` Starting...
|
|
2946
|
+
`));let n=cv();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)||lv;try{let{port:o,close:i}=await Ai({port:s,uiDir:n}),r=`http://localhost:${o}`;if(console.log(e(` v ${r}`)),console.log(t(` Press Ctrl+C to stop
|
|
2947
|
+
`)),!process.env.VIBESPOT_NO_OPEN)try{process.platform==="darwin"?Ra("open",[r],{stdio:"ignore"}):process.platform==="win32"?Ra("cmd",["/c","start","",r],{stdio:"ignore"}):Ra("xdg-open",[r],{stdio:"ignore"})}catch{}await new Promise(a=>{process.on("SIGINT",()=>{console.log(t(`
|
|
2948
|
+
Saving session...`)),L(),i(),console.log(t(` Goodbye!
|
|
2949
|
+
`)),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 cv(){let e=[_i(Yp,"../../ui"),_i(Yp,"../ui"),_i(process.cwd(),"ui")];for(let t of e)if(rv(_i(t,"index.html")))return t;return null}y();import{resolve as Xp}from"path";import{existsSync as Oa}from"fs";gt();Qe();ee();Ea();async function Zp(e={}){let t=await eg(e.path);if(e.fix){let o=wi(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)+`
|
|
2950
|
+
`),n.passed||process.exit(1);return}Ee(),await ge("Marketplace check");let s=`${n.errorCount} error${Da(n.errorCount)}, ${n.warningCount} warning${Da(n.warningCount)}, ${n.infoCount} note${Da(n.infoCount)}`;n.passed?G(`Theme passes Marketplace checks (${s}).`):V(`Theme is not yet ready: ${s}.`),Fa("Errors",n.findings.filter(o=>o.severity==="error")),Fa("Warnings",n.findings.filter(o=>o.severity==="warning")),Fa("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 Qp(e={}){let t=await eg(e.path);Ee(),await ge("Marketplace listing details");let n=Yn(t)??{},s=await Et({message:"Category",options:Yt.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};xi(t,d),G("Saved marketplace.json"),await fe(`Run ${I.accent("vibespot marketplace check")} to confirm the theme is ready to submit.`)}async function eg(e){if(e){let o=Xp(e);if(!Oa(o))throw new Error(`Theme not found: ${o}`);return o}let t=R();if(t.lastThemePath&&Oa(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=Xp(n);if(!Oa(s))throw new Error(`Theme not found: ${s}`);return s}function Fa(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 Da(e){return e===1?"":"s"}y();import{resolve as tg}from"path";import{existsSync as ja}from"fs";import{basename as dv}from"path";gt();Qe();ee();Ho();async function ng(e={}){let t=await uv(e.path),n=dv(t);if(e.applyTokens){let i=Bo(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=ur(t);e.json||G(`Wrote imported theme snapshot to ${i}`)}let s=Jo(t);e.json&&(process.stdout.write(JSON.stringify(s,null,2)+`
|
|
2951
|
+
`),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`)}`)}}La("Errors",s.findings.filter(i=>i.severity==="error")),La("Warnings",s.findings.filter(i=>i.severity==="warning")),La("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 uv(e){if(e){let o=tg(e);if(!ja(o))throw new Error(`Theme not found: ${o}`);return o}let t=R();if(t.lastThemePath&&ja(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=tg(n);if(!ja(s))throw new Error(`Theme not found: ${s}`);return s}function La(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();vs();Ce();import{dirname as mv,join as Ei}from"path";import{existsSync as pv}from"fs";import{fileURLToPath as gv}from"url";import{execFileSync as Ja}from"child_process";import Mi from"chalk";var sg=mv(gv(import.meta.url)),fv=4200;async function og(){let e=Mi.hex("#e8613a"),t=Mi.dim;console.log(""),console.log(e(" v vibeSpot \u2014 Email Mode")),console.log(t(` Starting...
|
|
2952
|
+
`));let n=hv();n||(console.error(Mi.red(" Could not find UI assets. Is the package installed correctly?")),process.exit(1));try{let{port:s,close:o}=await Ai({port:fv,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
|
|
2953
|
+
`));try{process.platform==="darwin"?Ja("open",[i],{stdio:"ignore"}):process.platform==="win32"?Ja("cmd",["/c","start","",i],{stdio:"ignore"}):Ja("xdg-open",[i],{stdio:"ignore"})}catch{}await new Promise(r=>{process.on("SIGINT",()=>{console.log(t(`
|
|
2954
|
+
Saving session...`)),L(),o(),console.log(t(` Goodbye!
|
|
2955
|
+
`)),r(),setTimeout(()=>process.exit(0),500)})})}catch(s){console.error(Mi.red(` Failed to start: ${s instanceof Error?s.message:String(s)}`)),process.exit(1)}}function hv(){let e=[Ei(sg,"../../ui"),Ei(sg,"../ui"),Ei(process.cwd(),"ui")];for(let t of e)if(pv(Ei(t,"index.html")))return t;return null}oe();function ig(){let e=new yv;e.name("vibespot").description("AI-powered HubSpot CMS landing page builder").version(yn()).action(qp),e.command("wizard").description("Classic CLI wizard \u2014 step-by-step conversion flow").action(Xl),e.command("init").description("Check and install required tools").action(Zl),e.command("convert").description("Convert a React project to HubSpot modules").action(Ql),e.command("upload").description("Upload theme to HubSpot").action(ec),e.command("doctor").description("Diagnose environment issues").action(tc);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=>Zp(n)),t.command("edit").description("Edit Marketplace listing metadata (marketplace.json)").option("-p, --path <path>","Path to the theme directory").action(n=>Qp(n)),e.command("email").description("Launch email template generation mode").action(og),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=>ng(n)),e}var bv=ig();bv.parseAsync(process.argv).catch(e=>{console.error(e),process.exit(1)});
|
|
2905
2956
|
//# sourceMappingURL=index.js.map
|